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

100% Statements 41/41
100% Branches 27/27
100% Functions 7/7
100% Lines 40/40

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

    27x
    5x

    1x

    4x

    27x
    321x

    27x
    321x
    321x
    321x
    321x
    321x
    321x
    321x
    17x
    304x
    2x

    302x

    321x

    321x

    27x
    276x
    276x

    276x

    276x

    276x
    276x
    5x
    5x
    5x

    27x
    52x
    52x
    45x
    45x

    45x

    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
      );

      const params = declaration.params.map(node => ({
        ...node,
        type: declaration.type,
      }));

      scope[declaration.value] = {
        ...declaration,
        params,
        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 } };
    });