# All files / src/semantics/map-function declaration.js

100% Statements 39/39
100% Branches 27/27
100% Functions 6/6
100% Lines 39/39

    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
    23x
    23x
    23x

    23x
    5x

    1x

    4x

    23x
    227x

    23x
    227x
    227x
    227x
    227x
    227x
    227x
    227x
    17x
    210x
    2x

    208x

    227x

    227x

    23x
    204x
    204x

    204x

    204x
    204x
    5x
    5x
    5x

    23x
    30x
    30x
    23x
    23x

    23x

    7x

     // @flow
    import Syntax from "../../Syntax";
    import curry from "curry";
    import {
      CLOSURE_TYPE,
      TYPE_ARRAY,
      TYPE_CONST,
      TYPE_INDEX,
      LOCAL_INDEX,
      GLOBAL_INDEX,
    } from "../metadata";

    const getTypeSize = typeString => {
      switch (typeString) {
        case "i64":
        case "f64":
          return 8;
        case "i32":
        case "f32":
        default:
          return 4;
      }
    };

    const isClosureType = (types, type): boolean => {
      return types[type] != null && !!types[type].meta[CLOSURE_TYPE];
    };
    const parse = (isConst, { types, scope }, declaration) => {
      const index = Object.keys(scope).length;
      const typeString = declaration.type;
      const modifier = declaration.type.slice(-2);
      const isArray = modifier === "[]";
      const isClosure = isClosureType(types, typeString);
      const type = (() => {
        if (isArray) {
          return "i32";
        } else if (isClosure) {
          return "i64";
        }
        return declaration.type;
      })();
      const meta = {
        [TYPE_ARRAY]: isArray ? typeString.slice(0, -2) : null,
        [CLOSURE_TYPE]: isClosure || null,
        [TYPE_CONST]: isConst || null,
        [TYPE_INDEX]: isClosure ? Object.keys(types).indexOf(typeString) : null,
      };

      return [type, meta, index];
    };

    export const parseDeclaration = curry((isConst, options, declaration) => {
      const { locals: scope, closures } = options;
      const [type, meta, index] = parse(
        isConst,
        { ...options, scope },
        declaration
      );
      scope[declaration.value] = {
        ...declaration,
        type,
        meta: { ...meta, [LOCAL_INDEX]: index },
        Type: Syntax.Declaration,
      };

      const { variables } = closures;
      if (variables[declaration.value] != null && declaration.params[0]) {
        const { offsets } = closures;
        offsets[declaration.value] = closures.envSize;
        closures.envSize += getTypeSize(declaration.type);
      }
    });

    export const parseGlobalDeclaration = curry((isConst, options, node) => {
      const { globals: scope } = options;
      if (node.type !== "Table" && node.type !== "Memory") {
        const [type, meta, index] = parse(isConst, { ...options, scope }, node);
        scope[node.value] = {
          ...node,
          meta: { ...meta, [GLOBAL_INDEX]: index },
          type,
          Type: Syntax.Declaration,
        };

        return scope[node.value];
      }
      return { ...node, meta: { [GLOBAL_INDEX]: -1 } };
    });