# 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
    26x
    26x
    26x
    26x

    26x
    172x
    172x

    172x
    172x

    26x
    172x
    172x
    148x

    148x
    148x
    142x

    6x

    6x

    24x

    175x
    3x

    172x
    172x
    172x
    172x
    172x
    172x
    172x
    812x
    812x
    420x

    172x

    172x

     // @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
      );
    }