All files / src/semantics index.js

100% Statements 30/30
100% Branches 0/0
100% Functions 3/3
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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130                            23x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x               23x                                   23x 90x                                                   90x         1352x       90x                         90x   90x 90x                                    
/**
 * Semantic Analysis
 *
 * The semantic analyzer below accepts a Walt AST and maps it, returning a new
 * transformed AST which contains all necessary data to generate the final
 * WebAssembly binary.
 *
 * The transformations may or may not create new nodes or attach metadata to
 * existing nodes.
 *
 * Metadata is information necessary to generate a valid binary, like type info.
 */
 
// @flow
import { combineParsers } from '../plugin';
import { map } from 'walt-parser-tools/map-node';
import { enter as enterScope } from 'walt-parser-tools/scope';
import { AST_METADATA } from './metadata';
import core from '../core';
import base from '../base';
import _types from '../core/types';
import unary from '../core/unary';
import _function from '../core/function';
import _imports from '../core/imports';
import booleans from '../core/bool';
import array from '../core/array';
import memory from '../core/memory';
import _statics from '../core/statics';
import functionPointer from '../core/function-pointer';
import struct from '../core/struct';
import native from '../core/native';
import defaultArguments from '../syntax-sugar/default-arguments';
import sizeof from '../syntax-sugar/sizeof';
import { GLOBAL_INDEX } from './metadata.js';
import type {
  NodeType,
  Context,
  SemanticOptions,
  SemanticsFactory,
} from '../flow/types';
 
export const builtinSemantics = [
  base,
  core,
  _imports,
  _types,
  unary,
  _function,
  booleans,
  array,
  memory,
  _statics,
  functionPointer,
  struct,
  native,
  sizeof,
  defaultArguments,
];
 
const getBuiltInParsers = (): SemanticsFactory[] => {
  return [
    base().semantics,
    core().semantics,
    _imports().semantics,
    _types().semantics,
    unary().semantics,
    _function().semantics,
    booleans().semantics,
    array().semantics,
    memory().semantics,
    _statics().semantics,
    functionPointer().semantics,
    struct().semantics,
    native().semantics,
    sizeof().semantics,
    defaultArguments().semantics,
  ];
};
 
// Return AST with full transformations applied
function semantics(
  ast: NodeType,
  extraSemantics: SemanticsFactory[],
  options: SemanticOptions
): NodeType {
  // Generate all the plugin instances with proper options
  const plugins = [...getBuiltInParsers(), ...extraSemantics];
 
  // Here each semantics parser will receive a reference to the parser & fragment
  // this allows a semantic parser to utilize the same grammar rules as the rest
  // of the program.
  const combined = combineParsers(plugins.map(p => p(options)));
 
  // The context is what we use to transfer state from one parser to another.
  // Global state like type information and scope chains for example.
  const context: Context = {
    functions: {},
    types: {},
    userTypes: {},
    table: {},
    hoist: [],
    statics: {},
    path: [],
    scopes: enterScope([], GLOBAL_INDEX),
    memories: [],
    tables: [],
  };
  // Parse the current ast
  const parsed = map(combined)([ast, context]);
 
  const { functions, scopes, types, userTypes, statics, hoist } = context;
  return {
    ...parsed,
    meta: {
      ...parsed.meta,
      // Attach information collected to the AST
      [AST_METADATA]: {
        functions,
        globals: scopes[0],
        types,
        userTypes,
        statics,
      },
    },
    params: [...parsed.params, ...hoist],
  };
}
 
export default semantics;