# All files / src/parser type.js

100% Statements 27/27
100% Branches 8/8
100% Functions 1/1
100% Lines 27/27

    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
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    26x

    26x
    26x

    45x
    45x

    45x
    45x

    45x

    45x
    5x
    5x

    5x
    5x

    5x

    5x

    40x

    31x

    31x

    31x
    31x

    31x

    31x

    9x
    1x
    1x
    1x

    8x

     // @flow
    import Syntax from "../Syntax";
    import type Context from "./context";
    import expression from "./expression";
    import generateError from "../utils/generate-error";
    import type { NodeType } from "../flow/types";

    export default function typeParser(ctx: Context): NodeType {
      const node: NodeType = ctx.startNode();
      ctx.eat(["type"]);

      const value = ctx.expect(null, Syntax.Identifier).value;
      ctx.expect(["="]);

      const maybeGeneric = ctx.token.value;
      // Generic Type
      if (ctx.eat(null, Syntax.Identifier)) {
        ctx.expect(["<"]);
        const idNode = ctx.makeNode(
          { ...ctx.token, type: null },
          Syntax.Identifier
        );
        ctx.expect(null, Syntax.Identifier);
        ctx.expect([">"]);

        const genericTypeNode = ctx.endNode(
          { ...node, value, params: [{ ...idNode, value: maybeGeneric }, idNode] },
          Syntax.GenericType
        );
        return genericTypeNode;
      }

      // Regular function type definition
      if (ctx.eat(["("])) {
        // Arguments are optional
        const argsExpression = expression(ctx);
        const args =
          argsExpression != null
            ? {
                ...argsExpression,
                value: "FUNCTION_ARGUMENTS",
                Type: Syntax.FunctionArguments,
                params: [argsExpression],
              }
            : {
                ...node,
                value: "FUNCTION_ARGUMENTS",
                Type: Syntax.FunctionArguments,
                params: [],
              };

        ctx.expect([")"]);
        ctx.expect(["=>"]);
        // Result is not optional
        const result = {
          ...expression(ctx),
          value: "FUNCTION_RESULT",
          Type: Syntax.FunctionResult,
        };
        return ctx.endNode(
          {
            ...node,
            value,
            type: result.type,
            params: [args, result],
          },
          Syntax.Typedef
        );
      }

      // Sanity check definition
      if (ctx.token.value !== "{") {
        const start = node.range[0];
        const end = ctx.token.end;
        throw new SyntaxError(
          generateError(
            "Invalid type syntax",
            "A function type must be of form (<type>, ...) <type>",
            { start, end },
            "",
            ""
          )
        );
      }

      // Struct type definition
      return ctx.endNode(
        {
          ...node,
          value,
          params: [expression(ctx)],
          type: "i32",
        },
        Syntax.Struct
      );
    }