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

    177x
    177x

    27x
    177x
    177x
    153x

    153x
    153x
    147x

    6x

    6x

    24x

    182x
    5x

    177x
    177x
    177x
    177x
    177x
    177x
    177x
    838x
    838x
    433x

    177x

    177x

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