# All files / src/core imports.js

100% Statements 29/29
100% Branches 8/8
100% Functions 6/6
100% Lines 29/29

    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
    98
    99
    100

    23x
    23x

    23x
    23x

    81x
    81x
    81x
    25x
    25x

    3x

    3x

    1x

    2x

    2x

    36x
    36x

    36x

    23x
    23x
    23x

    23x
    23x

    13x
    2x
    2x
    2x

    11x
    11x

    13x

     /**
     * Imports Plugin
     *
     * @flow
     */
    import Syntax from 'walt-syntax';
    import {
      current,
      add,
      index as scopeIndex,
      namespace,
    } from 'walt-parser-tools/scope';
    import { mapNode } from 'walt-parser-tools/map-node';
    import { FUNCTION_INDEX, TYPE_INDEX, TYPE_CONST } from '../semantics/metadata';
    import type { SemanticPlugin } from '../flow/types';

    export default function Imports(): SemanticPlugin {
      return {
        semantics: () => ({
          [Syntax.Import]: _next => args => {
            const [node, context] = args;
            return mapNode({
              [Syntax.BinaryExpression]: (as, transform) => {
                const [maybePair, asIdentifier] = as.params;
                // if the original import is not typed this isn't a valid import and is ignored
                if (maybePair.Type !== Syntax.Pair) {
                  // No transform happens here (the transform is what creates the global fn to reference)
                  return as;
                }
                // Continue transforming the import as before, the AS metadata will notify
                // the generator to ask for the original import.
                const [original, typeNode] = maybePair.params;

                return transform({
                  ...maybePair,
                  params: [
                    {
                      ...asIdentifier,
                      meta: {
                        ...original.meta,
                        // <new-value> AS <original-value>
                        AS: original.value,
                      },
                    },
                    typeNode,
                  ],
                });
              },
              [Syntax.Pair]: (pairNode, __) => {
                const { types, functions } = context;
                const [identifierNode, typeNode] = pairNode.params;

                if (types[typeNode.value] != null) {
                  // crate a new type

                  const functionIndex = Object.keys(functions).length;
                  const typeIndex = Object.keys(types).indexOf(typeNode.value);
                  const functionNode = {
                    ...identifierNode,
                    id: identifierNode.value,
                    type: types[typeNode.value].type,
                    meta: {
                      ...identifierNode.meta,
                      [FUNCTION_INDEX]: functionIndex,
                      [TYPE_INDEX]: typeIndex,
                      FUNCTION_METADATA:
                        types[typeNode.value].meta.FUNCTION_METADATA,
                      DEFAULT_ARGUMENTS:
                        types[typeNode.value].meta.DEFAULT_ARGUMENTS,
                    },
                  };
                  functions[identifierNode.value] = functionNode;
                  return {
                    ...pairNode,
                    params: [functionNode, types[typeNode.value]],
                  };
                }

                if (!['Table', 'Memory'].includes(typeNode.value)) {
                  const scope = current(context.scopes);
                  const index = scopeIndex(scope, identifierNode.value);
                  add(context.scopes, identifierNode.value, {
                    ...identifierNode,
                    meta: { [scope[namespace]]: index, [TYPE_CONST]: true },
                    type: typeNode.type,
                  });
                } else {
                  const bucket =
                    typeNode.value === 'Memory' ? 'memories' : 'tables';
                  context[bucket].push(identifierNode);
                }

                return pairNode;
              },
            })(node);
          },
        }),
      };
    }