call()

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;
  }