All files / src/core memory.js

100% Statements 24/24
100% Branches 14/14
100% Functions 7/7
100% Lines 24/24
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          23x 23x     23x 8x 8x       90x   90x 90x 96x 96x     96x         11x             11x     85x   90x 255x 255x 255x   255x         441x                     255x 255x             247x     8x            
/**
 * Handles access to memory and Memory type declaration
 *
 * @flow
 */
import Syntax from 'walt-syntax';
import { GLOBAL_INDEX } from '../semantics/metadata';
import type { SemanticPlugin } from '../flow/types';
 
const isMemoryIdentifier = (context, id) => {
  const memory = context.memories[0];
  return memory && memory.value === id.value;
};
 
export default function memoryPlugin(): SemanticPlugin {
  return {
    semantics({ stmt }) {
      return {
        [Syntax.ImmutableDeclaration]: next => args => {
          const [decl, context] = args;
          const { scopes, memories } = context;
 
          // Short circuit since memory is a special type of declaration
          if (
            !scopes.length < 2 &&
            decl.type === 'Memory' &&
            !memories.length
          ) {
            memories.push({
              ...decl,
              meta: {
                ...decl.meta,
                [GLOBAL_INDEX]: -1,
              },
            });
            return memories[0];
          }
 
          return next(args);
        },
        [Syntax.FunctionCall]: next => (args, transform) => {
          const [node, context] = args;
          const [subscript, ...rest] = node.params;
          const [id = {}, field = {}] = subscript.params;
 
          const callMap = {
            dataSize: transform([stmt`i32.load(0);`, context]),
            grow: {
              ...id,
              value: 'grow_memory',
              params: rest.map(p => transform([p, context])),
              Type: Syntax.NativeMethod,
            },
            size: {
              ...id,
              value: 'current_memory',
              params: [],
              Type: Syntax.NativeMethod,
            },
          };
 
          const mapped = callMap[field.value];
          if (
            !(
              subscript.Type === Syntax.Access &&
              isMemoryIdentifier(context, id) &&
              mapped
            )
          ) {
            return next(args);
          }
 
          return mapped;
        },
      };
    },
  };
}