# All files / src/parser closure.js

100% Statements 23/23
78.26% Branches 18/23
100% Functions 4/4
100% Lines 21/21

    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
    83
    84
    85
    26x

    26x

    26x

    4x
    2x

    2x

    4x
    4x
    4x
    4x

    4x
    4x

    4x

    4x
    2x
    1x

    1x

    2x
    1x

    1x

    4x

     // @flow
    import Syntax from "../Syntax";
    import type Context from "./context";
    import type { NodeType, TokenType } from "../flow/types";

    export const makeResult = (node: NodeType | null) => ({
      range: [],
      ...node,
      meta: {},
      params: [],
      Type: Syntax.FunctionResult,
      value: "FUNCTION_RESULT",
    });

    export const makeArgs = (node: NodeType | null) => ({
      range: [],
      ...node,
      params: (() => {
        if (node == null) {
          return [];
        }
        return node.Type === Syntax.Sequence ? node.params : [node];
      })(),
      type: null,
      meta: {},
      value: "FUNCTION_ARGUMENTS",
      Type: Syntax.FunctionArguments,
    });

    export default function parselambda(
      ctx: Context,
      op: TokenType,
      operands: NodeType[]
    ): NodeType {
      const args = operands[0];
      const result = operands[1];
      const block = operands[2] || result || args;
      operands.splice(-3);

      let baseParams = [];
      const lambda = {
        ...op,
        type: "i32",
        range: [ctx.token.start, ctx.token.end],
        meta: {},
        Type: Syntax.Closure,
        params: [],
      };

      const [lhs, rhs] = args.params;
      // The reason why this is so tricky to parse is because there are too many
      // optional parts of a coluse definition, like arguments and return type
      if (args.Type === Syntax.Pair) {
        if (lhs != null && rhs != null) {
          baseParams =
            lhs.Type === Syntax.Pair
              ? [makeArgs(lhs), makeResult(rhs)]
              : [
                  makeArgs(lhs.Type === Syntax.Sequence ? lhs : args),
                  makeResult(rhs.Type === Syntax.Type ? rhs : null),
                ];
        } else {
          baseParams = [makeArgs(null), makeResult(lhs)];
        }
      } else if (args.Type === Syntax.Sequence) {
        baseParams = [
          makeArgs(args),
          makeResult(result.Type === Syntax.Type ? result : null),
        ];
      } else {
        baseParams = [makeArgs(null), makeResult(null)];
      }

      return {
        ...lambda,
        params: [
          {
            ...lambda,
            Type: Syntax.FunctionDeclaration,
            params: [...baseParams, block],
          },
        ],
      };
    }