# All files / src/parser maybe-function-declaration.js

100% Statements 33/33
100% Branches 12/12
100% Functions 4/4
100% Lines 33/33

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    27x
    27x
    27x
    27x

    27x
    208x
    208x

    208x
    208x

    27x
    208x
    208x
    174x

    174x
    174x
    164x

    10x

    10x

    34x

    211x
    3x

    208x
    208x
    208x
    208x
    208x
    208x
    208x
    1014x
    1014x
    530x

    208x

    208x

     // @flow
    import Syntax from "../Syntax";
    import statement from "./statement";
    import declaration from "./declaration";
    import expression from "./expression";
    import type { NodeType } from "../flow/types";
    import type Context from "./context";

    export const parseArguments = (ctx: Context): NodeType => {
      ctx.expect(["("]);
      const argumentsNode = ctx.makeNode(
        {
          params: [expression(ctx)],
          value: "FUNCTION_ARGUMENTS",
        },
        Syntax.FunctionArguments
      );
      ctx.expect([")"]);
      return argumentsNode;
    };

    export const parseFunctionResult = (ctx: Context): NodeType => {
      const baseNode: NodeType = ctx.startNode();
      if (ctx.eat([":"])) {
        return ctx.endNode(
          {
            ...baseNode,
            value: ctx.token.value,
            type: (() => {
              const value = ctx.token.value;
              if (ctx.eat(null, Syntax.Type)) {
                return value === "void" ? null : value;
              }

              // If we did not find a user-type we default to an i32
              ctx.expect(null, Syntax.Identifier);

              return "i32";
            })(),
          },
          Syntax.FunctionResult
        );
      }

      return ctx.endNode(
        {
          ...baseNode,
          value: "FUNCTION_RESULT",
        },
        Syntax.FunctionResult
      );
    };

    export default function maybeFunctionDeclaration(ctx: Context): NodeType {
      if (!ctx.eat(["function"])) {
        return declaration(ctx);
      }

      const node = ctx.startNode();
      const value = ctx.expect(null, Syntax.Identifier).value;
      const argumentsNode = parseArguments(ctx);
      const resultNode = parseFunctionResult(ctx);
      ctx.expect(["{"]);
      const statements = [];
      while (ctx.token && ctx.token.value !== "}") {
        const stmt = statement(ctx);
        if (stmt) {
          statements.push(stmt);
        }
      }
      ctx.expect(["}"]);

      return ctx.endNode(
        {
          ...node,
          value,
          params: [argumentsNode, resultNode, ...statements],
        },
        Syntax.FunctionDeclaration
      );
    }