in packages/sqrl/src/ast/SqrlAstTransformer.ts [99:194]
call(ast: CallAst) {
const { instance } = this.state;
const hasFunction = instance.has(ast.func);
sqrlInvariant(ast, hasFunction, "Function not found: " + ast.func);
const props = instance.getProps(ast.func);
const isPrivate = ast.func.startsWith("_");
if (isPrivate && ast.hasOwnProperty("location")) {
// Given `ast` will have a location if it was user specified
sqrlInvariant(
ast,
this.state.allowPrivate,
"Function names cannot start with an underscore"
);
}
if (props.transformAst) {
// If a transformAst is defined do the argument count check before transform
this.assertArgs(ast);
const originalFunc = ast.func;
const transformed = props.transformAst(this.state, ast);
if (transformed.type !== "call") {
return this.transform(transformed);
}
invariant(
transformed.func !== originalFunc,
"transformed func must have a different name: %s",
transformed.func
);
return this.transform(transformed);
}
// If we need state / when context arguments add them automatically
if (props.stateArg) {
const astArgs: Ast[] = [...ast.args];
if (props.whenCauseArg) {
// Remove any state arguments before checking the whenCause
if (astArgs.length > 0 && astArgs[0].type === "state") {
astArgs.shift();
}
if (astArgs.length === 0 || astArgs[0].type !== "whenCause") {
astArgs.unshift({
type: "whenCause",
});
}
}
if (astArgs.length === 0 || astArgs[0].type !== "state") {
astArgs.unshift({
type: "state",
});
}
ast = Object.assign({}, ast, {
args: astArgs,
});
}
this.assertArgs(ast);
if (ast.args) {
const args = ast.args.map((arg, idx) => {
invariantCb(
arg,
() =>
`Cannot transform ast type:: arg ${idx} is undefined:: ${
ast.type
} ${JSON.stringify(props)} ${JSON.stringify(
SqrlAst.removeLocation(ast)
)}`
);
return this.transform(arg);
});
if (props.pure) {
const allConstant = args.every((arg) => arg.type === "constant");
if (allConstant) {
return {
type: "constant",
value: this.state.instance.pureFunction[ast.func](
...args.map((arg) => arg.value)
),
};
}
}
ast = Object.assign({}, ast, {
args,
});
}
return ast;
}