diff --git a/src/mol-script/builder.ts b/src/mol-script/builder.ts
index a79cd164338174b6851c94a9997059a0d04f7561..a4ea6a0931a4b677250f9851997b046aebf848e5 100644
--- a/src/mol-script/builder.ts
+++ b/src/mol-script/builder.ts
@@ -5,7 +5,7 @@
  */
 
 import Expression from './expression'
-import Symbol from './symbol'
+import { Symbol } from './symbol'
 import SymbolTable from './symbol-table'
 
 namespace Builder {
diff --git a/src/mol-script/compiler.ts b/src/mol-script/compiler.ts
index fb62178c72fcd952fad80211949f6ab938536099..ffdb7387a55360f6e84d745919c9945a4deafc0a 100644
--- a/src/mol-script/compiler.ts
+++ b/src/mol-script/compiler.ts
@@ -1,93 +1,92 @@
-/**
- * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
+// /**
+//  * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
+//  *
+//  * @author David Sehnal <david.sehnal@gmail.com>
+//  */
 
-import Expression from './expression'
-import Environment from './runtime/environment'
-import RuntimeExpression from './runtime/expression'
-import SymbolRuntime, { RuntimeArguments } from './runtime/symbol'
+// import Expression from './expression'
+// import Environment from './runtime/environment'
+// import RuntimeExpression from './runtime/expression'
+// import SymbolRuntime, { RuntimeArguments } from './runtime/symbol'
 
-export type CompiledExpression<C, T> = (ctx: C) => T
+// export type CompiledExpression<T> = () => T
 
-type Compiler<C> = <T>(expression: Expression) => CompiledExpression<C, T>
-function Compiler<C>(envProvider: (ctx?: C) => Environment): Compiler<C> {
-    const env = envProvider(void 0);
-    return expression => wrap(envProvider, compile(env, expression).runtime);
-}
+// type Compiler = <T>(expression: Expression) => CompiledExpression<T>
+// function Compiler<C>(env: Environment): Compiler {
+//     return expression => compile(env, expression).runtime;
+// }
 
-type CompileResult = { isConst: boolean, runtime: RuntimeExpression }
+// type CompileResult = { isConst: boolean, runtime: RuntimeExpression }
 
-namespace CompileResult {
-    export function Const(value: any): CompileResult { return { isConst: true, runtime: RuntimeExpression.constant(value) } }
-    export function Dynamic(runtime: RuntimeExpression): CompileResult { return { isConst: false, runtime } }
-}
+// namespace CompileResult {
+//     export function Const(value: any): CompileResult { return { isConst: true, runtime: RuntimeExpression.constant(value) } }
+//     export function Dynamic(runtime: RuntimeExpression): CompileResult { return { isConst: false, runtime } }
+// }
 
-function wrap<C, T>(envProvider: (ctx?: C) => Environment, runtime: RuntimeExpression<C, T>) {
-    return (ctx: C) => runtime(envProvider(ctx));
-}
+// function wrap<T>(envProvider: (ctx?: C) => Environment, runtime: RuntimeExpression<T>) {
+//     return (ctx: C) => runtime(envProvider(ctx));
+// }
 
-function noRuntimeFor(symbol: string) {
-    throw new Error(`Could not find runtime for symbol '${symbol}'.`);
-}
+// function noRuntimeFor(symbol: string) {
+//     throw new Error(`Could not find runtime for symbol '${symbol}'.`);
+// }
 
-function applySymbolStatic(runtime: SymbolRuntime, args: RuntimeArguments) {
-    return CompileResult.Dynamic(env => runtime(env, args))
-}
+// function applySymbolStatic(runtime: SymbolRuntime, args: RuntimeArguments) {
+//     return CompileResult.Dynamic(env => runtime(env, args))
+// }
 
-function applySymbolDynamic(head: RuntimeExpression, args: RuntimeArguments) {
-    return CompileResult.Dynamic(env => {
-        const value = head(env);
-        const symbol = env.symbolTable[value];
-        if (!symbol) noRuntimeFor(value);
-        return symbol.runtime(env, args);
-    })
-}
+// function applySymbolDynamic(head: RuntimeExpression, args: RuntimeArguments) {
+//     return CompileResult.Dynamic(env => {
+//         const value = head(env);
+//         const symbol = env.runtimeTable[value];
+//         if (!symbol) noRuntimeFor(value);
+//         return symbol.runtime(env, args);
+//     })
+// }
 
-function apply(env: Environment, head: CompileResult, args: RuntimeArguments, constArgs: boolean): CompileResult {
-    if (head.isConst) {
-        const value = head.runtime(env);
-        const symbol = env.symbolTable[value];
-        if (!symbol) throw new Error(`Could not find runtime for symbol '${value}'.`);
-        if (symbol.attributes.isStatic && constArgs) return CompileResult.Const(symbol.runtime(env, args));
-        return applySymbolStatic(symbol.runtime, args);
-    }
-    return applySymbolDynamic(head.runtime, args);
-}
+// function apply(env: Environment, head: CompileResult, args: RuntimeArguments, constArgs: boolean): CompileResult {
+//     if (head.isConst) {
+//         const value = head.runtime(env);
+//         const symbol = env.runtimeTable[value];
+//         if (!symbol) throw new Error(`Could not find runtime for symbol '${value}'.`);
+//         if (symbol.attributes.isStatic && constArgs) return CompileResult.Const(symbol.runtime(env, args));
+//         return applySymbolStatic(symbol.runtime, args);
+//     }
+//     return applySymbolDynamic(head.runtime, args);
+// }
 
-function compile(env: Environment, expression: Expression): CompileResult {
-    if (Expression.isLiteral(expression)) {
-        return CompileResult.Const(expression);
-    }
+// function compile(env: Environment, expression: Expression): CompileResult {
+//     if (Expression.isLiteral(expression)) {
+//         return CompileResult.Const(expression);
+//     }
 
-    if (Expression.isSymbol(expression)) {
-        // TOTO: this needs to look up in the symbol table.
-        return 0 as any;
-    }
+//     if (Expression.isSymbol(expression)) {
+//         // TOTO: this needs to look up in the symbol table.
+//         return 0 as any;
+//     }
 
-    const head = compile(env, expression.head);
-    if (!expression.args) {
-        return apply(env, head, [], true);
-    } else if (Expression.isArgumentsArray(expression.args)) {
-        const args = [];
-        let constArgs = false;
-        for (const arg of expression.args) {
-            const compiled = compile(env, arg);
-            constArgs = constArgs && compiled.isConst;
-            args.push(compiled.runtime);
-        }
-        return apply(env, head, args as any, constArgs);
-    } else {
-        const args = Object.create(null);
-        let constArgs = false;
-        for (const key of Object.keys(expression.args)) {
-            const compiled = compile(env, expression.args[key]);
-            constArgs = constArgs && compiled.isConst;
-            args[key] = compiled.runtime;
-        }
-        return apply(env, head, args, constArgs);
-    }
-}
+//     const head = compile(env, expression.head);
+//     if (!expression.args) {
+//         return apply(env, head, [], true);
+//     } else if (Expression.isArgumentsArray(expression.args)) {
+//         const args = [];
+//         let constArgs = false;
+//         for (const arg of expression.args) {
+//             const compiled = compile(env, arg);
+//             constArgs = constArgs && compiled.isConst;
+//             args.push(compiled.runtime);
+//         }
+//         return apply(env, head, args as any, constArgs);
+//     } else {
+//         const args = Object.create(null);
+//         let constArgs = false;
+//         for (const key of Object.keys(expression.args)) {
+//             const compiled = compile(env, expression.args[key]);
+//             constArgs = constArgs && compiled.isConst;
+//             args[key] = compiled.runtime;
+//         }
+//         return apply(env, head, args, constArgs);
+//     }
+// }
 
-export default Compiler
\ No newline at end of file
+// export default Compiler
\ No newline at end of file
diff --git a/src/mol-script/helpers.ts b/src/mol-script/helpers.ts
index 09ced0a60a313962856c2f911a47ab3d645f4486..9b384a2f87b847b6b8dc9f2f17c4429595a0acda 100644
--- a/src/mol-script/helpers.ts
+++ b/src/mol-script/helpers.ts
@@ -5,7 +5,7 @@
  */
 
 import Type from './type'
-import Symbol, { Arguments, isSymbol } from './symbol'
+import { Symbol, Arguments, isSymbol } from './symbol'
 
 export function symbol<A extends Arguments, T extends Type<S>, S>(args: A, type: T, description?: string) {
     return Symbol('', args, type, description);
diff --git a/src/mol-script/runtime/environment.ts b/src/mol-script/runtime/environment.ts
index d13d5738b8c7e528a361052eea01d5572aca65e1..4092a6786d412d61939ee783089132fe1ef37b27 100644
--- a/src/mol-script/runtime/environment.ts
+++ b/src/mol-script/runtime/environment.ts
@@ -4,13 +4,34 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { SymbolRuntimeTable } from './symbol'
+import { Symbol } from '../symbol'
+import { SymbolRuntime } from './symbol'
 import { Macro } from './macro';
+import Expression from '../expression';
 
-interface Environment<T = any> {
-    readonly symbolTable: SymbolRuntimeTable,
-    readonly context: T,
-    readonly macros: Macro.Table
+class Environment {
+    readonly runtimeTable: SymbolRuntime.Table;
+    readonly macroTable: Macro.Table = new Map<string, Macro>();
+
+    addMacro(name: string, expression: Expression, argNames: ReadonlyArray<string>): Macro {
+        const argIndex: Macro['argIndex'] = {};
+        for (let i = 0; i < argNames.length; i++) argIndex[argNames[i]] = i;
+        const macro: Macro = { expression, argIndex, argNames };
+        this.macroTable.set(name, macro);
+        return macro;
+    }
+
+    removeMacro(name: string) {
+        this.macroTable.delete(name);
+    }
+
+    addSymbolRuntime(symbol: Symbol, runtime: SymbolRuntime) {
+        this.runtimeTable.set(symbol.id, runtime);
+    }
+
+    removeSymbolRuntime(symbol: Symbol) {
+        this.runtimeTable.delete(symbol.id);
+    }
 }
 
 export default Environment
\ No newline at end of file
diff --git a/src/mol-script/runtime/expression.ts b/src/mol-script/runtime/expression.ts
index 2d8f7d8adc81a5d4d3a3d9ade5571479800de39f..c6d38827a8f35ec611c015a96cf054b295e0a009 100644
--- a/src/mol-script/runtime/expression.ts
+++ b/src/mol-script/runtime/expression.ts
@@ -6,18 +6,18 @@
 
 import Environment from './environment'
 
-type RuntimeExpression<C = any, T = any> = (env: Environment<C>) => T
+type RuntimeExpression<T = any> = (env: Environment) => T
 
 export interface ExpressionInfo {
     isConst?: boolean
 }
 
 namespace RuntimeExpression {
-    export function constant<C, T>(c: T): RuntimeExpression<C, T> {
+    export function constant<T>(c: T): RuntimeExpression<T> {
         return env => c;
     }
 
-    export function func<C, T>(f: (env: Environment<C>) => T): RuntimeExpression<C, T> {
+    export function func<T>(f: (env: Environment) => T): RuntimeExpression<T> {
         return env => f(env);
     }
 }
diff --git a/src/mol-script/runtime/symbol.ts b/src/mol-script/runtime/symbol.ts
index 81a3590e1a1adafb25036afc2924ec4329e8e73a..c0f0451cf7c4c4817508845903da9b54ea445431 100644
--- a/src/mol-script/runtime/symbol.ts
+++ b/src/mol-script/runtime/symbol.ts
@@ -6,27 +6,27 @@
 
 import Environment from './environment'
 import RuntimeExpression from './expression'
+import Expression from '../expression';
 
-export type RuntimeArguments = ArrayLike<RuntimeExpression> | { [name: string]: RuntimeExpression | undefined }
-
-type SymbolRuntime = (env: Environment, args: RuntimeArguments) => any
+type SymbolRuntime = SymbolRuntime.Dynamic | SymbolRuntime.Static
 
 namespace SymbolRuntime {
-    export interface Info {
-        readonly runtime: SymbolRuntime,
+    export interface Static {
+        kind: 'static',
+        readonly runtime: (env: Environment, args: Arguments) => any,
         readonly attributes: Attributes
     }
 
+    export interface Dynamic {
+        kind: 'dynamic',
+        readonly compile: (env: Environment, args: Expression.Arguments) => RuntimeExpression
+    }
+
     export interface Attributes { isStatic: boolean }
-}
 
-function SymbolRuntime(attributes: Partial<SymbolRuntime.Attributes> = {}) {
-    const { isStatic = false } = attributes;
-    return (runtime: SymbolRuntime): SymbolRuntime.Info => {
-        return ({ runtime, attributes: { isStatic } });
-    };
-}
+    export type Table = Map<string, SymbolRuntime>
 
-export type SymbolRuntimeTable = { readonly [id: string]: SymbolRuntime.Info }
+    export type Arguments = ArrayLike<RuntimeExpression> | { [name: string]: RuntimeExpression | undefined }
+}
 
-export default SymbolRuntime
\ No newline at end of file
+export { SymbolRuntime }
\ No newline at end of file
diff --git a/src/mol-script/script/mol-script/symbols.ts b/src/mol-script/script/mol-script/symbols.ts
index 66d41365f7e432dfa7a53961b41ad6ab274c2061..9c9cec57be92226f187ae70b43a5c030fdd5fcff 100644
--- a/src/mol-script/script/mol-script/symbols.ts
+++ b/src/mol-script/script/mol-script/symbols.ts
@@ -4,7 +4,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import Symbol, { Arguments, Argument } from '../../symbol'
+import { Symbol, Arguments, Argument } from '../../symbol'
 import B from '../../builder'
 import * as M from './macro'
 import MolScript from '../../symbol-table'
diff --git a/src/mol-script/symbol-table.ts b/src/mol-script/symbol-table.ts
index 7a12afc440f87184f9ada233c45cd32e2acf55b2..cfdb112a32415a4f47b45811cdbc223b993a43dd 100644
--- a/src/mol-script/symbol-table.ts
+++ b/src/mol-script/symbol-table.ts
@@ -7,7 +7,7 @@
 import core from './symbol-table/core'
 import structureQuery from './symbol-table/structure-query'
 import { normalizeTable, symbolList } from './helpers'
-import Symbol from './symbol'
+import { Symbol } from './symbol'
 
 const table = { core, structureQuery };
 
diff --git a/src/mol-script/symbol-table/core.ts b/src/mol-script/symbol-table/core.ts
index 6c20d0c00887fd5be338aa2a485cad9c7f9e1a59..c0bcac64f6d638ca0ace61f197974e1034a9d48e 100644
--- a/src/mol-script/symbol-table/core.ts
+++ b/src/mol-script/symbol-table/core.ts
@@ -5,7 +5,7 @@
  */
 
 import Type from '../type'
-import Symbol, { Arguments, Argument } from '../symbol'
+import { Symbol, Arguments, Argument } from '../symbol'
 import { symbol, normalizeTable, symbolList } from '../helpers'
 
 export namespace Types {
diff --git a/src/mol-script/symbol.ts b/src/mol-script/symbol.ts
index d79b6764b64a2045c4aae8d8bf8616f1405ef794..d6c2dbe33a2e8826c9c4a087797893af0cf3ccb2 100644
--- a/src/mol-script/symbol.ts
+++ b/src/mol-script/symbol.ts
@@ -50,7 +50,7 @@ export namespace Arguments {
 
 export type ExpressionArguments<T> = { [P in keyof T]?: Expression } | { [index: number]: Expression }
 
-interface Symbol<A extends Arguments = Arguments, T extends Type = Type> {
+export interface Symbol<A extends Arguments = Arguments, T extends Type = Type> {
     (args?: ExpressionArguments<A['@type']>): Expression,
     info: {
         namespace: string,
@@ -62,7 +62,7 @@ interface Symbol<A extends Arguments = Arguments, T extends Type = Type> {
     id: string,
 }
 
-function Symbol<A extends Arguments, T extends Type>(name: string, args: A, type: T, description?: string) {
+export function Symbol<A extends Arguments, T extends Type>(name: string, args: A, type: T, description?: string) {
     const symbol: Symbol<A, T> = function(args: ExpressionArguments<A['@type']>) {
         return Expression.Apply(Expression.Symbol(symbol.id), args as any);
     } as any;
@@ -80,5 +80,3 @@ export function isSymbol(x: any): x is Symbol {
 
 export type SymbolMap = { [id: string]: Symbol | undefined }
 
-export default Symbol
-