function defaultArguments () {
  return {
    grammar: grammar$1,
    semantics() {
      return {
        [Syntax.FunctionDeclaration]: next => args => {
          const [node, context] = args;
          const [argumentsNode] = node.params;

          const defaultArguments = [];

          walkNode({
            Assignment: defaultArg => {
              const [, value] = defaultArg.params;
              defaultArguments.push(value);
            }
          })(argumentsNode);

          // Attach any default arguments found to the function node directly,
          // proceed with the rest of the parsers
          return next([_extends({}, node, {
            meta: _extends({}, node.meta, { DEFAULT_ARGUMENTS: defaultArguments })
          }), context]);
        },
        // There isn't a need to parse out the Assignment expressions as they are
        // not actually compiled/generated into the final binary
        // [Syntax.Assignment]: next => (args, transform) => {
        //   const [node, context] = args;
        //   // Not inside arguments
        //   const currentScope = current(context.scopes);

        //   // Arguments have not been set for scope yet and the current scope is
        //   // not global
        //   if (currentScope.arguments == null && context.scopes.length > 1) {
        //     return next(args);
        //   }

        //   // Assignment has higher precedence than ":" Pair expressions so the
        //   // children of this node will be [Pair(id:type), Constant(value)]
        //   // remove the constant return the pair.
        //   //
        //   // A helpful visual of a valid default argument syntax:
        //   //
        //   //      function fn(x : i32, y : i32, z : i32 = 0) { ... }
        //   const [pair] = node.params;

        //   // Short circuit the parsers since it does not make sense to process
        //   // assignment anymore. Instead parse the Pair, which is the argument.
        //   return transform([pair, context]);
        // },
        [Syntax.FunctionCall]: next => args => {
          const [call, context] = args;
          const { functions } = context;
          const [id, ...fnArgs] = call.params;

          const target = functions[id.value];

          // Most likely a built-in function
          if (!target) {
            return next(args);
          }

          const expectedArguments = target.meta.FUNCTION_METADATA.argumentsCount;
          const count = fnArgs.length;
          const difference = expectedArguments - count;
          if (difference > 0) {
            return next([_extends({}, call, {
              params: [...call.params, ...target.meta.DEFAULT_ARGUMENTS.slice(difference - 1)]
            }), context]);
          }

          return next(args);
        }
      };
    }
  };
}
Default Arguments syntax sugar plugin.

Converts FUNCTION CALLS with missing arguments to default values