# All files / src/core types.js

100% Statements 34/34
100% Branches 4/4
100% Functions 8/8
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
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    9823x
    23x
    23x
    23x

    23x
    4x
    4x
    4x
    4x

    4x

    4x
    4x

    87x

    87x
    87x
    87x
    87x
    87x

    87x

    137x
    137x

    3x

    134x

    37x
    37x
    37x

    1x
    1x

    48x

    37x

    37x
    37x

    87x

     import curry from 'curry';
    import Syntax from '../Syntax';
    import mapNode from '../utils/map-node';
    import walkNode from '../utils/walk-node';

    const mapGeneric = curry((options, node, _) => {
      const { types } = options;
      const [generic, T] = node.params;
      const realType = types[T.value];
      const [args, result] = realType.params;
      // Patch the node to be a real type which we can reference later
      const patch = {
        ...realType,
        range: generic.range,
        value: node.value,
        meta: { ...realType.meta, CLOSURE_TYPE: generic.value === 'Lambda' },
        params: [
          {
            ...args,
            params: [
              {
                ...args,
                params: [],
                type: 'i32',
                value: 'i32',
                Type: Syntax.Type,
              },
              ...args.params,
            ],
          },
          result,
        ],
      };
      types[patch.value] = patch;
      return patch;
    });

    export default function typePlugin() {
      return {
        semantics() {
          return {
            Typedef: _ => ([node]) => node,
            Program: next => args => {
              const [ast, context] = args;
              const { types } = context;
              // Types have to be pre-parsed before the rest of the program
              const astWithTypes = mapNode({
                [Syntax.Export]: (node, transform) => {
                  const [maybeType] = node.params;
                  if (
                    maybeType != null &&
                    [Syntax.Typedef, Syntax.Struct].includes(maybeType.Type)
                  ) {
                    return transform({
                      ...maybeType,
                      meta: {
                        ...maybeType.meta,
                        EXPORTED: true,
                      },
                    });
                  }
                  return node;
                },
                [Syntax.Typedef]: (node, _) => {
                  let argumentsCount = 0;
                  const defaultArgs = [];
                  walkNode({
                    Assignment(assignment) {
                      const defaultValue = assignment.params[1];
                      defaultArgs.push(defaultValue);
                    },
                    Type() {
                      argumentsCount += 1;
                    },
                  })(node);
                  const parsed = {
                    ...node,
                    meta: {
                      ...node.meta,
                      FUNCTION_METADATA: {
                        argumentsCount,
                      },
                      DEFAULT_ARGUMENTS: defaultArgs,
                    },
                  };
                  types[node.value] = parsed;
                  return parsed;
                },
                [Syntax.GenericType]: mapGeneric({ types }),
              })(ast);

              return next([astWithTypes, context]);
            },
          };
        },
      };
    }