From abc545a99761e32e5f204d87a3646dbd496bba34 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Wed, 8 Aug 2018 14:34:00 +0200
Subject: [PATCH] wip mol-script, 1st compiled query

---
 package-lock.json                            | Bin 411997 -> 418525 bytes
 package.json                                 |   4 +-
 src/apps/structure-info/model.ts             |  11 +-
 src/mol-model/structure/query/context.ts     |   4 +-
 src/mol-model/structure/query/query.ts       |   4 +-
 src/mol-script/language/builder.ts           |   8 +-
 src/mol-script/language/symbol-table.ts      |   8 +-
 src/mol-script/language/symbol-table/core.ts |   9 +
 src/mol-script/language/symbol.ts            |   3 +-
 src/mol-script/language/type.ts              |   2 +-
 src/mol-script/runtime/environment.ts        |  60 +-
 src/mol-script/runtime/expression.ts         |  38 +-
 src/mol-script/runtime/macro.ts              | 132 ++---
 src/mol-script/runtime/query/compiler.ts     | 151 +++++
 src/mol-script/runtime/query/table.ts        |  65 +++
 src/mol-script/runtime/symbol.ts             |  48 +-
 src/mol-script/script/mol-script/examples.ts | 206 +++----
 src/mol-script/script/mol-script/macro.ts    |  68 +--
 src/mol-script/script/mol-script/parser.ts   | 356 ++++++------
 src/mol-script/script/mol-script/symbols.ts  | 546 +++++++++----------
 src/perf-tests/mol-script.ts                 |  53 +-
 tsconfig.json                                |   3 +-
 22 files changed, 1021 insertions(+), 758 deletions(-)
 create mode 100644 src/mol-script/runtime/query/compiler.ts
 create mode 100644 src/mol-script/runtime/query/table.ts

diff --git a/package-lock.json b/package-lock.json
index 0b0df7edaf6edb49db5b2861d5b6c4b2f321a620..4f137e24d0fb3957776c524681a389410b1a1b40 100644
GIT binary patch
delta 31690
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
UHjG&+K?iSY!8C}h<*MZZ0C*9XjsO4v

delta 30563
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
BwjTfh

diff --git a/package.json b/package.json
index eb8afa253..40e7655c3 100644
--- a/package.json
+++ b/package.json
@@ -83,8 +83,8 @@
     "file-loader": "^1.1.11",
     "glslify-import": "^3.1.0",
     "glslify-loader": "^1.0.2",
-    "graphql-code-generator": "^0.10.6",
-    "graphql-codegen-typescript-template": "^0.10.6",
+    "graphql-code-generator": "^0.10.7",
+    "graphql-codegen-typescript-template": "^0.10.7",
     "graphql-tag": "^2.9.2",
     "jest": "^23.4.2",
     "jest-raw-loader": "^1.0.1",
diff --git a/src/apps/structure-info/model.ts b/src/apps/structure-info/model.ts
index fbc466845..c01698f91 100644
--- a/src/apps/structure-info/model.ts
+++ b/src/apps/structure-info/model.ts
@@ -22,7 +22,7 @@ async function downloadFromPdb(pdb: string) {
     return parsed.blocks[0];
 }
 
-async function readPdbFile(path: string) {
+export async function readCifFile(path: string) {
     const parsed = await openCif(path);
     return parsed.blocks[0];
 }
@@ -197,9 +197,14 @@ export function printModelStats(models: ReadonlyArray<Model>) {
     console.log();
 }
 
-async function run(frame: CifFrame, args: Args) {
+export async function getModelsAndStructure(frame: CifFrame) {
     const models = await Model.create(Format.mmCIF(frame)).run();
     const structure = Structure.ofModel(models[0]);
+    return { models, structure };
+}
+
+async function run(frame: CifFrame, args: Args) {
+    const { models, structure } = await getModelsAndStructure(frame);
 
     if (args.models) printModelStats(models);
     if (args.seq) printSequence(models[0]);
@@ -218,7 +223,7 @@ async function runDL(pdb: string, args: Args) {
 }
 
 async function runFile(filename: string, args: Args) {
-    const mmcif = await readPdbFile(filename);
+    const mmcif = await readCifFile(filename);
     run(mmcif, args);
 }
 
diff --git a/src/mol-model/structure/query/context.ts b/src/mol-model/structure/query/context.ts
index 7541c8ac2..188aac0e7 100644
--- a/src/mol-model/structure/query/context.ts
+++ b/src/mol-model/structure/query/context.ts
@@ -58,5 +58,5 @@ export class QueryContext implements QueryContextView {
     }
 }
 
-export interface QueryPredicate { (ctx: QueryContextView): boolean }
-export interface QueryFn<T = any> { (ctx: QueryContextView): T }
\ No newline at end of file
+export interface QueryPredicate { (ctx: QueryContext): boolean }
+export interface QueryFn<T = any> { (ctx: QueryContext): T }
\ No newline at end of file
diff --git a/src/mol-model/structure/query/query.ts b/src/mol-model/structure/query/query.ts
index 4283b6b73..f7629182e 100644
--- a/src/mol-model/structure/query/query.ts
+++ b/src/mol-model/structure/query/query.ts
@@ -6,9 +6,9 @@
 
 import { Structure } from '../structure'
 import { StructureSelection } from './selection'
-import { QueryContext } from './context';
+import { QueryContext, QueryFn } from './context';
 
-interface StructureQuery { (ctx: QueryContext): StructureSelection }
+interface StructureQuery extends QueryFn<StructureSelection> { }
 namespace StructureQuery {
     export function run(query: StructureQuery, structure: Structure, timeoutMs = 0) {
         return query(new QueryContext(structure, timeoutMs));
diff --git a/src/mol-script/language/builder.ts b/src/mol-script/language/builder.ts
index 213b47a7a..8c7efa07d 100644
--- a/src/mol-script/language/builder.ts
+++ b/src/mol-script/language/builder.ts
@@ -6,9 +6,9 @@
 
 import Expression from './expression'
 import { MSymbol } from './symbol'
-import SymbolTable from './symbol-table'
+import { MolScriptSymbolTable as SymbolTable } from './symbol-table'
 
-namespace Builder {
+export namespace MolScriptBuilder {
     export const core = SymbolTable.core;
     export const struct = SymbolTable.structureQuery;
 
@@ -35,6 +35,4 @@ namespace Builder {
     export function acpSet(p: keyof typeof _acp) { return _aps([ acp(p) ]) };
     export function atpSet(p: keyof typeof _atp) { return _aps([ atp(p) ]) };
     export function ammpSet(p: keyof typeof _ammp) { return _aps([ ammp(p) ]) };
-}
-
-export default Builder
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/mol-script/language/symbol-table.ts b/src/mol-script/language/symbol-table.ts
index 6f47d15d9..3dec8616f 100644
--- a/src/mol-script/language/symbol-table.ts
+++ b/src/mol-script/language/symbol-table.ts
@@ -9,11 +9,11 @@ import structureQuery from './symbol-table/structure-query'
 import { normalizeTable, symbolList } from './helpers'
 import { MSymbol } from './symbol'
 
-const table = { core, structureQuery };
+const MolScriptSymbolTable = { core, structureQuery };
 
-normalizeTable(table);
+normalizeTable(MolScriptSymbolTable);
 
-export const SymbolList = symbolList(table);
+export const SymbolList = symbolList(MolScriptSymbolTable);
 
 export const SymbolMap = (function() {
     const map: { [id: string]: MSymbol | undefined } = Object.create(null);
@@ -21,4 +21,4 @@ export const SymbolMap = (function() {
     return map;
 })();
 
-export default table
\ No newline at end of file
+export { MolScriptSymbolTable }
\ No newline at end of file
diff --git a/src/mol-script/language/symbol-table/core.ts b/src/mol-script/language/symbol-table/core.ts
index b4164f613..fa0a801d9 100644
--- a/src/mol-script/language/symbol-table/core.ts
+++ b/src/mol-script/language/symbol-table/core.ts
@@ -41,6 +41,15 @@ function binRel<A extends Type, T extends Type>(src: A, target: T, description?:
     }), target, description);
 }
 
+export const TTargs = Arguments.Dictionary({
+    0: Argument(Type.Num),
+    1: Argument(Type.Num)
+})
+
+const XX = { test: Argument(Type.Str) };
+const t: Arguments.PropTypes<typeof XX> = 0 as any;
+t.test
+
 const type = {
     '@header': 'Types',
     bool: symbol(Arguments.Dictionary({ 0: Argument(Type.AnyValue) }), Type.Bool, 'Convert a value to boolean.'),
diff --git a/src/mol-script/language/symbol.ts b/src/mol-script/language/symbol.ts
index c928809b9..de9b53665 100644
--- a/src/mol-script/language/symbol.ts
+++ b/src/mol-script/language/symbol.ts
@@ -31,7 +31,8 @@ export namespace Arguments {
         map: { [P in keyof T]: Argument<T[P]> },
         '@type': T
     }
-    export function Dictionary<Map extends { [key: string]: Argument<any> }>(map: Map): Arguments<{ [P in keyof Map]: Map[P]['type']['@type'] }> {
+    export type PropTypes<Map extends { [key: string]: Argument<any>  }> = { [P in keyof Map]: Map[P]['type']['@type'] }
+    export function Dictionary<Map extends { [key: string]: Argument<any> }>(map: Map): Arguments<PropTypes<Map>> {
         return { kind: 'dictionary', map, '@type': 0 as any };
     }
 
diff --git a/src/mol-script/language/type.ts b/src/mol-script/language/type.ts
index 9a50889cb..90465ec4d 100644
--- a/src/mol-script/language/type.ts
+++ b/src/mol-script/language/type.ts
@@ -9,7 +9,7 @@ type Type<T = any> =
     | Type.Container<T> | Type.Union<T> | Type.OneOf<T>
 
 namespace Type {
-    export interface Any { kind: 'any',  '@type': any }
+    export interface Any { kind: 'any', '@type': any }
     export interface Variable<T> { kind: 'variable', name: string, type: Type, isConstraint: boolean, '@type': any }
     export interface AnyValue { kind: 'any-value', '@type': any }
     export interface Value<T> { kind: 'value', namespace: string, name: string, parent?: Value<any>, '@type': T }
diff --git a/src/mol-script/runtime/environment.ts b/src/mol-script/runtime/environment.ts
index 54882d11a..7592071c8 100644
--- a/src/mol-script/runtime/environment.ts
+++ b/src/mol-script/runtime/environment.ts
@@ -1,37 +1,37 @@
-/**
- * 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 { MSymbol } from '../language/symbol'
-import { SymbolRuntime } from './symbol'
-import { Macro } from './macro';
-import Expression from '../language/expression';
+// import { MSymbol } from '../language/symbol'
+// import { SymbolRuntime } from './symbol'
+// import { Macro } from './macro';
+// import Expression from '../language/expression';
 
-class Environment {
-    readonly runtimeTable: SymbolRuntime.Table;
-    readonly macroTable: Macro.Table = new Map<string, Macro>();
+// 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;
-    }
+//     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);
-    }
+//     removeMacro(name: string) {
+//         this.macroTable.delete(name);
+//     }
 
-    addSymbolRuntime(symbol: MSymbol, runtime: SymbolRuntime) {
-        this.runtimeTable.set(symbol.id, runtime);
-    }
+//     addSymbolRuntime(symbol: MSymbol, runtime: SymbolRuntime) {
+//         this.runtimeTable.set(symbol.id, runtime);
+//     }
 
-    removeSymbolRuntime(symbol: MSymbol) {
-        this.runtimeTable.delete(symbol.id);
-    }
-}
+//     removeSymbolRuntime(symbol: MSymbol) {
+//         this.runtimeTable.delete(symbol.id);
+//     }
+// }
 
-export default Environment
\ No newline at end of file
+// 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 c6d38827a..f12841edf 100644
--- a/src/mol-script/runtime/expression.ts
+++ b/src/mol-script/runtime/expression.ts
@@ -1,25 +1,25 @@
-/**
- * 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 Environment from './environment'
+// import Environment from './environment'
 
-type RuntimeExpression<T = any> = (env: Environment) => T
+// type RuntimeExpression<T = any> = (env: Environment) => T
 
-export interface ExpressionInfo {
-    isConst?: boolean
-}
+// export interface ExpressionInfo {
+//     isConst?: boolean
+// }
 
-namespace RuntimeExpression {
-    export function constant<T>(c: T): RuntimeExpression<T> {
-        return env => c;
-    }
+// namespace RuntimeExpression {
+//     export function constant<T>(c: T): RuntimeExpression<T> {
+//         return env => c;
+//     }
 
-    export function func<T>(f: (env: Environment) => T): RuntimeExpression<T> {
-        return env => f(env);
-    }
-}
+//     export function func<T>(f: (env: Environment) => T): RuntimeExpression<T> {
+//         return env => f(env);
+//     }
+// }
 
-export default RuntimeExpression
\ No newline at end of file
+// export default RuntimeExpression
\ No newline at end of file
diff --git a/src/mol-script/runtime/macro.ts b/src/mol-script/runtime/macro.ts
index 4d5128886..d6ef5f71d 100644
--- a/src/mol-script/runtime/macro.ts
+++ b/src/mol-script/runtime/macro.ts
@@ -1,81 +1,81 @@
-/**
- * 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 '../language/expression';
+// import Expression from '../language/expression';
 
-interface Macro {
-    readonly argNames: ReadonlyArray<string>,
-    readonly argIndex: { [name: string]: number },
-    readonly expression: Expression
-}
+// interface Macro {
+//     readonly argNames: ReadonlyArray<string>,
+//     readonly argIndex: { [name: string]: number },
+//     readonly expression: Expression
+// }
 
-namespace Macro {
-    export type Table = Map<string, Macro>
+// namespace Macro {
+//     export type Table = Map<string, Macro>
 
-    function subst(table: Table, expr: Expression, argIndex: { [name: string]: number }, args: ArrayLike<Expression>): Expression {
-        if (Expression.isLiteral(expr)) return expr;
-        if (Expression.isSymbol(expr)) {
-            const idx = argIndex[expr.name];
-            if (typeof idx !== 'undefined') return args[idx];
+//     function subst(table: Table, expr: Expression, argIndex: { [name: string]: number }, args: ArrayLike<Expression>): Expression {
+//         if (Expression.isLiteral(expr)) return expr;
+//         if (Expression.isSymbol(expr)) {
+//             const idx = argIndex[expr.name];
+//             if (typeof idx !== 'undefined') return args[idx];
 
-            if (table.has(expr.name)) {
-                const macro = table.get(expr.name)!;
-                if (macro.argNames.length === 0) return macro.expression;
-            }
+//             if (table.has(expr.name)) {
+//                 const macro = table.get(expr.name)!;
+//                 if (macro.argNames.length === 0) return macro.expression;
+//             }
 
-            return expr;
-        }
+//             return expr;
+//         }
 
-        const head = subst(table, expr.head, argIndex, args);
-        const headChanged = head === expr.head;
-        if (!expr.args) {
-            return headChanged ? Expression.Apply(head) : expr;
-        }
+//         const head = subst(table, expr.head, argIndex, args);
+//         const headChanged = head === expr.head;
+//         if (!expr.args) {
+//             return headChanged ? Expression.Apply(head) : expr;
+//         }
 
-        let argsChanged = false;
+//         let argsChanged = false;
 
-        if (Expression.isArgumentsArray(expr.args)) {
-            let newArgs: Expression[] = [];
-            for (let i = 0, _i = expr.args.length; i < _i; i++) {
-                const oldArg = expr.args[i];
-                const newArg = subst(table, oldArg, argIndex, args);
-                if (oldArg !== newArg) argsChanged = true;
-                newArgs[newArgs.length] = newArg;
-            }
-            if (!argsChanged) newArgs = expr.args;
+//         if (Expression.isArgumentsArray(expr.args)) {
+//             let newArgs: Expression[] = [];
+//             for (let i = 0, _i = expr.args.length; i < _i; i++) {
+//                 const oldArg = expr.args[i];
+//                 const newArg = subst(table, oldArg, argIndex, args);
+//                 if (oldArg !== newArg) argsChanged = true;
+//                 newArgs[newArgs.length] = newArg;
+//             }
+//             if (!argsChanged) newArgs = expr.args;
 
-            if (Expression.isSymbol(head) && table.has(head.name)) {
-                const macro = table.get(head.name)!;
-                if (macro.argNames.length === newArgs.length) {
-                    return subst(table, macro.expression, macro.argIndex, newArgs);
-                }
-            }
+//             if (Expression.isSymbol(head) && table.has(head.name)) {
+//                 const macro = table.get(head.name)!;
+//                 if (macro.argNames.length === newArgs.length) {
+//                     return subst(table, macro.expression, macro.argIndex, newArgs);
+//                 }
+//             }
 
-            if (!headChanged && !argsChanged) return expr;
-            return Expression.Apply(head, newArgs);
-        } else {
+//             if (!headChanged && !argsChanged) return expr;
+//             return Expression.Apply(head, newArgs);
+//         } else {
 
-            let newArgs: any = {}
-            for (const key of Object.keys(expr.args)) {
-                const oldArg = expr.args[key];
-                const newArg = subst(table, oldArg, argIndex, args);
-                if (oldArg !== newArg) argsChanged = true;
-                newArgs[key] = newArg;
-            }
-            if (!headChanged && !argsChanged) return expr;
-            if (!argsChanged) newArgs = expr.args;
+//             let newArgs: any = {}
+//             for (const key of Object.keys(expr.args)) {
+//                 const oldArg = expr.args[key];
+//                 const newArg = subst(table, oldArg, argIndex, args);
+//                 if (oldArg !== newArg) argsChanged = true;
+//                 newArgs[key] = newArg;
+//             }
+//             if (!headChanged && !argsChanged) return expr;
+//             if (!argsChanged) newArgs = expr.args;
 
-            return Expression.Apply(head, newArgs);
-        }
-    }
+//             return Expression.Apply(head, newArgs);
+//         }
+//     }
 
-    export function substitute(table: Table, macro: Macro, args: ArrayLike<Expression>) {
-        if (args.length === 0) return macro.expression;
-        return subst(table, macro.expression, macro.argIndex, args);
-    }
-}
+//     export function substitute(table: Table, macro: Macro, args: ArrayLike<Expression>) {
+//         if (args.length === 0) return macro.expression;
+//         return subst(table, macro.expression, macro.argIndex, args);
+//     }
+// }
 
-export { Macro }
\ No newline at end of file
+// export { Macro }
\ No newline at end of file
diff --git a/src/mol-script/runtime/query/compiler.ts b/src/mol-script/runtime/query/compiler.ts
new file mode 100644
index 000000000..63598bb4c
--- /dev/null
+++ b/src/mol-script/runtime/query/compiler.ts
@@ -0,0 +1,151 @@
+/**
+ * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+import Expression from '../../language/expression';
+import { QueryContext, QueryFn, Structure } from 'mol-model/structure';
+import { MSymbol } from '../../language/symbol';
+
+export class QueryRuntimeTable {
+    private map = new Map<string, QuerySymbolRuntime>();
+
+    addSymbol(runtime: QuerySymbolRuntime) {
+        this.map.set(runtime.symbol.id, runtime);
+    }
+
+    getRuntime(id: string) {
+        return this.map.get(id);
+    }
+}
+
+export const DefaultQueryRuntimeTable = new QueryRuntimeTable();
+
+export class QueryCompilerCtx {
+    constQueryContext: QueryContext = new QueryContext(Structure.Empty);
+
+    constructor(public table: QueryRuntimeTable) {
+
+    }
+}
+
+export type ConstQuerySymbolFn<S extends MSymbol = MSymbol> = (ctx: QueryContext, args: QueryRuntimeArguments<S>) => any
+export type QuerySymbolFn<S extends MSymbol = MSymbol> = (ctx: QueryContext, args: QueryRuntimeArguments<S>) => any
+
+
+export type QueryCompiledSymbolRuntime = { kind: 'const', value: any } | { kind: 'dynamic', runtime: QuerySymbolFn }
+
+export type CompiledQueryFn<T = any> = { isConst: boolean, fn: QueryFn }
+
+export namespace QueryCompiledSymbol {
+    export function Const(value: any): QueryCompiledSymbolRuntime  {
+        return { kind: 'const', value }
+    }
+
+    export function Dynamic(runtime: QuerySymbolFn): QueryCompiledSymbolRuntime {
+        return { kind: 'dynamic', runtime };
+    }
+}
+
+export namespace CompiledQueryFn {
+    export function Const(value: any): CompiledQueryFn  {
+        return { isConst: true, fn: ctx => value };
+    }
+
+    export function Dynamic(fn: QueryFn): CompiledQueryFn {
+        return { isConst: false, fn };
+    }
+}
+
+export interface QuerySymbolRuntime {
+    symbol: MSymbol,
+    compile(ctx: QueryCompilerCtx, args?: Expression.Arguments): CompiledQueryFn
+}
+
+export type QueryRuntimeArguments<S extends MSymbol> =
+    { length?: number } & { [P in keyof S['args']['@type']]: QueryFn<S['args']['@type'][P]> }
+
+export namespace QuerySymbolRuntime {
+    export function Const<S extends MSymbol<any>>(symbol: S, fn: ConstQuerySymbolFn<S>): QuerySymbolRuntime {
+        return new SymbolRuntimeImpl(symbol, fn, true);
+    }
+
+    export function Dynamic<S extends MSymbol<any>>(symbol: S, fn: QuerySymbolFn<S>): QuerySymbolRuntime {
+        return new SymbolRuntimeImpl(symbol, fn, false);
+    }
+}
+
+class SymbolRuntimeImpl<S extends MSymbol> implements QuerySymbolRuntime {
+    compile(ctx: QueryCompilerCtx, inputArgs?: Expression.Arguments): CompiledQueryFn {
+        let args: any, constArgs = false;
+        if (!inputArgs) {
+            args = void 0;
+            constArgs = true;
+        } else if (Expression.isArgumentsArray(inputArgs)) {
+            args = [];
+            constArgs = false;
+            for (const arg of inputArgs) {
+                const compiled = _compile(ctx, arg);
+                constArgs = constArgs && compiled.isConst;
+                args.push(compiled.fn);
+            }
+        } else {
+            args = Object.create(null);
+            constArgs = false;
+            for (const key of Object.keys(inputArgs)) {
+                const compiled = _compile(ctx, inputArgs[key]);
+                constArgs = constArgs && compiled.isConst;
+                args[key] = compiled.fn;
+            }
+        }
+
+        if (this.isConst) {
+            if (this.isConst && constArgs) {
+                return CompiledQueryFn.Const(this.fn(ctx.constQueryContext, args))
+            }
+
+            return CompiledQueryFn.Dynamic(createDynamicFn(this.fn, args));
+        }
+
+        return CompiledQueryFn.Dynamic(createDynamicFn(this.fn, args));
+    }
+
+    constructor(public symbol: S, private fn: QuerySymbolFn<S>, private isConst: boolean) {
+
+    }
+}
+
+function createDynamicFn<S extends MSymbol>(fn: QuerySymbolFn<S>, args: any): QueryFn {
+    return ctx => fn(ctx, args);
+}
+
+function _compile(ctx: QueryCompilerCtx, expression: Expression): CompiledQueryFn {
+    if (Expression.isLiteral(expression)) {
+        return CompiledQueryFn.Const(expression);
+    }
+
+    if (Expression.isSymbol(expression)) {
+        // TODO: is this ok in case of constants?
+        throw new Error('Cannot compile a symbol that is not applied.');
+    }
+
+    if (!Expression.isSymbol(expression.head)) {
+        throw new Error('Can only apply symbols.');
+    }
+
+    const compiler = ctx.table.getRuntime(expression.head.name);
+
+    if (!compiler) {
+        throw new Error(`Symbol '${expression.head.name}' is not implemented.`);
+    }
+
+    return compiler.compile(ctx, expression.args);
+}
+
+export function compile<T = any>(expression: Expression): QueryFn<T> {
+    const ctx = new QueryCompilerCtx(DefaultQueryRuntimeTable);
+    return _compile(ctx, expression).fn;
+}
+
+import './table'
\ No newline at end of file
diff --git a/src/mol-script/runtime/query/table.ts b/src/mol-script/runtime/query/table.ts
new file mode 100644
index 000000000..d5c4217d7
--- /dev/null
+++ b/src/mol-script/runtime/query/table.ts
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+import { MolScriptSymbolTable as MolScript } from '../../language/symbol-table';
+import { DefaultQueryRuntimeTable, QuerySymbolRuntime } from './compiler';
+
+import C = QuerySymbolRuntime.Const
+import D = QuerySymbolRuntime.Dynamic
+import { Queries, StructureProperties } from 'mol-model/structure';
+import { ElementSymbol } from 'mol-model/structure/model/types';
+
+const symbols = [
+    C(MolScript.core.math.add, (ctx, xs) => {
+        let ret = 0;
+        if (typeof xs.length === 'number') {
+            for (let i = 0, _i = xs.length; i < _i; i++) ret += xs[i](ctx);
+        } else {
+            for (const k of Object.keys(xs)) ret += xs[k](ctx);
+        }
+        return ret;
+    }),
+
+    // ============= RELATIONAL ================
+    C(MolScript.core.rel.eq, (ctx, v) => v[0](ctx) === v[1](ctx)),
+    C(MolScript.core.rel.neq, (ctx, v) => v[0](ctx) !== v[1](ctx)),
+    C(MolScript.core.rel.lt, (ctx, v) => v[0](ctx) < v[1](ctx)),
+    C(MolScript.core.rel.lte, (ctx, v) => v[0](ctx) <= v[1](ctx)),
+    C(MolScript.core.rel.gr, (ctx, v) => v[0](ctx) > v[1](ctx)),
+    C(MolScript.core.rel.gre, (ctx, v) => v[0](ctx) >= v[1](ctx)),
+
+    // ============= TYPES ================
+    C(MolScript.structureQuery.type.elementSymbol, (ctx, v) => ElementSymbol(v[0](ctx))),
+
+    // ============= GENERATORS ================
+    D(MolScript.structureQuery.generator.atomGroups, (ctx, xs) => Queries.generators.atoms({
+        entityTest: xs['entity-test'],
+        chainTest: xs['chain-test'],
+        residueTest: xs['residue-test'],
+        atomTest: xs['atom-test'],
+        groupBy: xs['group-by']
+    })(ctx)),
+
+    // ============= ATOM PROPERTIES ================
+    D(MolScript.structureQuery.atomProperty.macromolecular.label_comp_id, (ctx, _) => StructureProperties.residue.label_comp_id(ctx.element)),
+    D(MolScript.structureQuery.atomProperty.core.elementSymbol, (ctx, _) => StructureProperties.atom.type_symbol(ctx.element))
+
+    // Symbol(MolQL.core.rel.neq, staticAttr)((env, v) => v[0](env) !== v[1](env)),
+    // Symbol(MolQL.core.rel.lt, staticAttr)((env, v) => v[0](env) < v[1](env)),
+    // Symbol(MolQL.core.rel.lte, staticAttr)((env, v) => v[0](env) <= v[1](env)),
+    // Symbol(MolQL.core.rel.gr, staticAttr)((env, v) => v[0](env) > v[1](env)),
+    // Symbol(MolQL.core.rel.gre, staticAttr)((env, v) => v[0](env) >= v[1](env)),
+    // Symbol(MolQL.core.rel.inRange, staticAttr)((env, v) => {
+    //     const x = v[0](env);
+    //     return x >= v[1](env) && x <= v[2](env)
+    // }),
+];
+
+(function () {
+    for (const s of symbols) {
+        DefaultQueryRuntimeTable.addSymbol(s);
+    }
+})();
\ No newline at end of file
diff --git a/src/mol-script/runtime/symbol.ts b/src/mol-script/runtime/symbol.ts
index 5a53a4ba8..b70783330 100644
--- a/src/mol-script/runtime/symbol.ts
+++ b/src/mol-script/runtime/symbol.ts
@@ -1,32 +1,32 @@
-/**
- * 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 Environment from './environment'
-import RuntimeExpression from './expression'
-import Expression from '../language/expression';
+// import Environment from './environment'
+// import RuntimeExpression from './expression'
+// import Expression from '../language/expression';
 
-type SymbolRuntime = SymbolRuntime.Dynamic | SymbolRuntime.Static
+// type SymbolRuntime = SymbolRuntime.Dynamic | SymbolRuntime.Static
 
-namespace SymbolRuntime {
-    export interface Static {
-        kind: 'static',
-        readonly runtime: (env: Environment, args: Arguments) => any,
-        readonly attributes: Attributes
-    }
+// namespace SymbolRuntime {
+//     export interface Static {
+//         kind: 'static',
+//         readonly runtime: (ctx: any, args: Arguments) => any,
+//         readonly attributes: Attributes
+//     }
 
-    export interface Dynamic {
-        kind: 'dynamic',
-        readonly compile: (env: Environment, args: Expression.Arguments) => RuntimeExpression
-    }
+//     export interface Dynamic {
+//         kind: 'dynamic',
+//         readonly compile: (env: Environment, args: Expression.Arguments) => RuntimeExpression
+//     }
 
-    export interface Attributes { isStatic: boolean }
+//     export interface Attributes { isStatic: boolean }
 
-    export type Table = Map<string, SymbolRuntime>
+//     export type Table = Map<string, SymbolRuntime>
 
-    export type Arguments = ArrayLike<RuntimeExpression> | { [name: string]: RuntimeExpression | undefined }
-}
+//     export type Arguments = ArrayLike<RuntimeExpression> | { [name: string]: RuntimeExpression | undefined }
+// }
 
-export { SymbolRuntime }
\ No newline at end of file
+// export { SymbolRuntime }
\ No newline at end of file
diff --git a/src/mol-script/script/mol-script/examples.ts b/src/mol-script/script/mol-script/examples.ts
index 7df280f8b..1f689f1d3 100644
--- a/src/mol-script/script/mol-script/examples.ts
+++ b/src/mol-script/script/mol-script/examples.ts
@@ -1,104 +1,104 @@
-/**
- * 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>
+//  */
 
-export default [{
-    name: 'Residues connected to HEM',
-    value: `(sel.atom.is-connected-to
-  sel.atom.res
-  :target (sel.atom.res (= atom.label_comp_id HEM))
-  ;; default bond test allows only covalent bonds
-  :bond-test true
-  :disjunct true)`
-}, {
-    name: 'All C or N atoms in ALA residues',
-    value: `(sel.atom.atom-groups
-  :residue-test (= atom.auth_comp_id ALA)
-  :atom-test (set.has (set _C _N) atom.el))`
-}, {
-    name: 'Residues 130 to 180',
-    value: `(sel.atom.res (in-range atom.resno 130 180))`
-}, {
-    name: 'All residues within 5 ang from Fe atom',
-    value: `(sel.atom.include-surroundings
-  (sel.atom.atoms (= atom.el _Fe))
-  :radius 5
-  :as-whole-residues true)`
-}, {
-    name: 'Cluster LYS residues within 5 ang',
-    value: `(sel.atom.cluster
-  (sel.atom.res (= atom.label_comp_id LYS))
-  :max-distance 5)`
-}, {
-    name: 'Residues with max b-factor < 45',
-    value: `(sel.atom.pick sel.atom.res
-  :test (< (atom.set.max atom.B_iso_or_equiv) 45))`
-}, {
-  name: 'Atoms between 10 and 15 ang from Fe',
-  value: `(sel.atom.within sel.atom.atoms
-  :target (sel.atom.atoms (= atom.el _Fe))
-  :min-radius 10
-  :max-radius 15)`
-}, {
-  name: 'HEM and 2 layers of connected residues',
-  value: `(sel.atom.include-connected
-  (sel.atom.res (= atom.label_comp_id HEM))
-  ;; default bond test allows only covalent bonds
-  ;; another option is to use :bond-test true to allow any connection
-  :bond-test (bond.is metallic covalent)
-  :layer-count 2
-  :as-whole-residues true)`
-}, {
-  name: 'All rings',
-  value: `(sel.atom.rings)`
-}, {
-  name: 'CCCCN and CCNCN rings',
-  value: `(sel.atom.rings
-  (ringfp _C _N _C _N _C)
-  ;; the "rotation" of element symbols has no effect
-  ;; the following is the same as (ringfp _C _C _C _C _N)
-  (ringfp _C _C _C _N _C))`
-}, {
-  name: 'Sheets',
-  value: `(sel.atom.atom-groups
-  :residue-test (atom.sec-struct.is sheet)
-  :group-by (atom.key.sec-struct))`
-}, {
-  name: 'Helices formed by at least 30 residues',
-  value: `(sel.atom.pick
-  (sel.atom.atom-groups
-  :residue-test (atom.sec-struct.is helix)
-  :group-by atom.key.sec-struct)
-  :test (<= 30 (atom.set.count-query sel.atom.res)))`
-}, {
-  name: 'Modified residues',
-  value: `(sel.atom.res atom.is-modified)`
-}, {
-  name: 'Atoms participating in metallic coordination',
-  value: `(sel.atom.atoms
-  (> (atom.bond-count :flags (bond-flags metallic)) 0))`
-}, {
-  name: 'LYS and ALA residues that are between 2 and 5 ang apart',
-  value: `(sel.atom.dist-cluster
-  ;; upper triangular matrix are maximum distances of corresponding selections
-  ;; lower triangular matrix are minumum distances of corresponding selections
-  :matrix [
-    [0 5]
-    [2 0]
-  ]
-  :selections [
-    (sel.atom.res (= atom.resname LYS))
-    (sel.atom.res (= atom.resname ALA))
-  ])`
-}, {
-  name: 'Clusters of 3 LYS residues that are mutually no more than 5 ang apart',
-  value: `(sel.atom.dist-cluster
-  :matrix [[0 5 5] [0 0 5] [0 0 0]]
-  :selections [
-    (sel.atom.res (= atom.resname LYS))
-    (sel.atom.res (= atom.resname LYS))
-    (sel.atom.res (= atom.resname LYS))
-  ])`
-}]
\ No newline at end of file
+// export default [{
+//     name: 'Residues connected to HEM',
+//     value: `(sel.atom.is-connected-to
+//   sel.atom.res
+//   :target (sel.atom.res (= atom.label_comp_id HEM))
+//   ;; default bond test allows only covalent bonds
+//   :bond-test true
+//   :disjunct true)`
+// }, {
+//     name: 'All C or N atoms in ALA residues',
+//     value: `(sel.atom.atom-groups
+//   :residue-test (= atom.auth_comp_id ALA)
+//   :atom-test (set.has (set _C _N) atom.el))`
+// }, {
+//     name: 'Residues 130 to 180',
+//     value: `(sel.atom.res (in-range atom.resno 130 180))`
+// }, {
+//     name: 'All residues within 5 ang from Fe atom',
+//     value: `(sel.atom.include-surroundings
+//   (sel.atom.atoms (= atom.el _Fe))
+//   :radius 5
+//   :as-whole-residues true)`
+// }, {
+//     name: 'Cluster LYS residues within 5 ang',
+//     value: `(sel.atom.cluster
+//   (sel.atom.res (= atom.label_comp_id LYS))
+//   :max-distance 5)`
+// }, {
+//     name: 'Residues with max b-factor < 45',
+//     value: `(sel.atom.pick sel.atom.res
+//   :test (< (atom.set.max atom.B_iso_or_equiv) 45))`
+// }, {
+//   name: 'Atoms between 10 and 15 ang from Fe',
+//   value: `(sel.atom.within sel.atom.atoms
+//   :target (sel.atom.atoms (= atom.el _Fe))
+//   :min-radius 10
+//   :max-radius 15)`
+// }, {
+//   name: 'HEM and 2 layers of connected residues',
+//   value: `(sel.atom.include-connected
+//   (sel.atom.res (= atom.label_comp_id HEM))
+//   ;; default bond test allows only covalent bonds
+//   ;; another option is to use :bond-test true to allow any connection
+//   :bond-test (bond.is metallic covalent)
+//   :layer-count 2
+//   :as-whole-residues true)`
+// }, {
+//   name: 'All rings',
+//   value: `(sel.atom.rings)`
+// }, {
+//   name: 'CCCCN and CCNCN rings',
+//   value: `(sel.atom.rings
+//   (ringfp _C _N _C _N _C)
+//   ;; the "rotation" of element symbols has no effect
+//   ;; the following is the same as (ringfp _C _C _C _C _N)
+//   (ringfp _C _C _C _N _C))`
+// }, {
+//   name: 'Sheets',
+//   value: `(sel.atom.atom-groups
+//   :residue-test (atom.sec-struct.is sheet)
+//   :group-by (atom.key.sec-struct))`
+// }, {
+//   name: 'Helices formed by at least 30 residues',
+//   value: `(sel.atom.pick
+//   (sel.atom.atom-groups
+//   :residue-test (atom.sec-struct.is helix)
+//   :group-by atom.key.sec-struct)
+//   :test (<= 30 (atom.set.count-query sel.atom.res)))`
+// }, {
+//   name: 'Modified residues',
+//   value: `(sel.atom.res atom.is-modified)`
+// }, {
+//   name: 'Atoms participating in metallic coordination',
+//   value: `(sel.atom.atoms
+//   (> (atom.bond-count :flags (bond-flags metallic)) 0))`
+// }, {
+//   name: 'LYS and ALA residues that are between 2 and 5 ang apart',
+//   value: `(sel.atom.dist-cluster
+//   ;; upper triangular matrix are maximum distances of corresponding selections
+//   ;; lower triangular matrix are minumum distances of corresponding selections
+//   :matrix [
+//     [0 5]
+//     [2 0]
+//   ]
+//   :selections [
+//     (sel.atom.res (= atom.resname LYS))
+//     (sel.atom.res (= atom.resname ALA))
+//   ])`
+// }, {
+//   name: 'Clusters of 3 LYS residues that are mutually no more than 5 ang apart',
+//   value: `(sel.atom.dist-cluster
+//   :matrix [[0 5 5] [0 0 5] [0 0 0]]
+//   :selections [
+//     (sel.atom.res (= atom.resname LYS))
+//     (sel.atom.res (= atom.resname LYS))
+//     (sel.atom.res (= atom.resname LYS))
+//   ])`
+// }]
\ No newline at end of file
diff --git a/src/mol-script/script/mol-script/macro.ts b/src/mol-script/script/mol-script/macro.ts
index a2c9c5a7c..436e06bc6 100644
--- a/src/mol-script/script/mol-script/macro.ts
+++ b/src/mol-script/script/mol-script/macro.ts
@@ -1,39 +1,39 @@
-/**
- * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
+// /**
+//  * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
+//  *
+//  * @author David Sehnal <david.sehnal@gmail.com>
+//  * @author Alexander Rose <alexander.rose@weirdbyte.de>
+//  */
 
-import B from '../../language/builder'
+// import B from '../../language/builder'
 
-export function getPositionalArgs(args: any) {
-    return Object.keys(args)
-        .filter(k => !isNaN(k as any))
-        .map(k => +k)
-        .sort((a, b) => a - b)
-        .map(k => args[k]);
-}
+// export function getPositionalArgs(args: any) {
+//     return Object.keys(args)
+//         .filter(k => !isNaN(k as any))
+//         .map(k => +k)
+//         .sort((a, b) => a - b)
+//         .map(k => args[k]);
+// }
 
-export function tryGetArg(args: any, name: string | number, defaultValue?: any) {
-    return (args && args[name] !== void 0) ? args[name] : defaultValue;
-}
+// export function tryGetArg(args: any, name: string | number, defaultValue?: any) {
+//     return (args && args[name] !== void 0) ? args[name] : defaultValue;
+// }
 
-export function pickArgs(args: any, ...names: string[]) {
-    const ret = Object.create(null);
-    let count = 0;
-    for (let k of Object.keys(args)) {
-        if (names.indexOf(k) >= 0) {
-            ret[k] = args[k];
-            count++;
-        }
-    }
-    return count ? ret : void 0;
-}
+// export function pickArgs(args: any, ...names: string[]) {
+//     const ret = Object.create(null);
+//     let count = 0;
+//     for (let k of Object.keys(args)) {
+//         if (names.indexOf(k) >= 0) {
+//             ret[k] = args[k];
+//             count++;
+//         }
+//     }
+//     return count ? ret : void 0;
+// }
 
-export function aggregate(property: any, fn: any, initial?: any){
-    return B.struct.atomSet.reduce({
-        initial: initial !== void 0 ? initial : property,
-        value: fn([ B.struct.slot.elementSetReduce(), property ])
-    });
-}
\ No newline at end of file
+// export function aggregate(property: any, fn: any, initial?: any){
+//     return B.struct.atomSet.reduce({
+//         initial: initial !== void 0 ? initial : property,
+//         value: fn([ B.struct.slot.elementSetReduce(), property ])
+//     });
+// }
\ No newline at end of file
diff --git a/src/mol-script/script/mol-script/parser.ts b/src/mol-script/script/mol-script/parser.ts
index b313de302..f9452036a 100644
--- a/src/mol-script/script/mol-script/parser.ts
+++ b/src/mol-script/script/mol-script/parser.ts
@@ -1,178 +1,178 @@
-/**
- * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { MonadicParser as P } from 'mol-util/monadic-parser'
-import Expression from '../../language/expression'
-import B from '../../language/builder'
-
-export function parseMolScript(input: string) {
-    return Language.parse(input);
-}
-
-namespace Language {
-    type AST = ASTNode.Expression[]
-
-    namespace ASTNode {
-        export type Expression = Str | Symb | List | Comment
-
-        export interface Str {
-            kind: 'string',
-            value: string
-        }
-
-        export interface Symb {
-            kind: 'symbol',
-            value: string
-        }
-
-        export interface List {
-            kind: 'list',
-            bracket: '(' | '[' | '{',
-            nodes: Expression[]
-        }
-
-        export interface Comment {
-            kind: 'comment',
-            value: string
-        }
-
-        export function str(value: string): Str { return { kind: 'string', value }; }
-        export function symb(value: string): Symb { return { kind: 'symbol', value }; }
-        export function list(bracket: '(' | '[' | '{', nodes: Expression[]): List { return { kind: 'list', bracket, nodes }; }
-        export function comment(value: string): Comment { return { kind: 'comment', value } }
-    }
-
-    const ws = P.regexp(/[\n\r\s]*/);
-    const Expr: P<ASTNode.Expression> = P.lazy(() => (P.alt(Str, List, Symb, Comment).trim(ws)));
-    const Str = P.takeWhile(c => c !== '`').trim('`').map(ASTNode.str);
-    const Symb = P.regexp(/[^()\[\]{};`,\n\r\s]+/).map(ASTNode.symb);
-    const Comment = P.regexp(/\s*;+([^\n\r]*)\n/, 1).map(ASTNode.comment);
-    const Args = Expr.many();
-    const List1 = Args.wrap('(', ')').map(args => ASTNode.list('(', args));
-    const List2 = Args.wrap('[', ']').map(args => ASTNode.list('[', args));
-    const List3 = Args.wrap('{', '}').map(args => ASTNode.list('{', args));
-    const List = P.alt(List1, List2, List3);
-
-    const Expressions: P<AST> = Expr.many();
-
-    function getAST(input: string) { return Expressions.tryParse(input); }
-
-    function visitExpr(expr: ASTNode.Expression): Expression {
-        switch (expr.kind) {
-            case 'string': return expr.value;
-            case 'symbol': {
-                const value = expr.value;
-                if (value.length > 1) {
-                    const fst = value.charAt(0);
-                    switch (fst) {
-                        case '.': return B.atomName(value.substr(1));
-                        case '_': return B.struct.type.elementSymbol([value.substr(1)]);
-                    }
-                }
-                if (value === 'true') return true;
-                if (value === 'false') return false;
-                if (isNumber(value)) return +value;
-                return Expression.Symbol(value);
-            }
-            case 'list': {
-                switch (expr.bracket) {
-                    case '[': return B.core.type.list(withoutComments(expr.nodes).map(visitExpr));
-                    case '{': return B.core.type.set(withoutComments(expr.nodes).map(visitExpr));
-                    case '(': {
-                        const head = visitExpr(expr.nodes[0]);
-                        return Expression.Apply(head, getArgs(expr.nodes));
-                    }
-                }
-                return 0 as any;
-            }
-            default: {
-                throw new Error('should not happen');
-            }
-        }
-    }
-
-    function getArgs(nodes: ASTNode.Expression[]): Expression.Arguments | undefined {
-        if (nodes.length <= 1) return void 0;
-        if (!hasNamedArgs(nodes)) {
-            const args: Expression[] = [];
-            for (let i = 1, _i = nodes.length; i < _i; i++) {
-                const n = nodes[i];
-                if (n.kind === 'comment') continue;
-                args[args.length] = visitExpr(n);
-            }
-            return args;
-        }
-        const args: { [name: string]: Expression } = {};
-        let allNumeric = true;
-        let pos = 0;
-        for (let i = 1, _i = nodes.length; i < _i; i++) {
-            const n = nodes[i];
-            if (n.kind === 'comment') continue;
-            if (n.kind === 'symbol' && n.value.length > 1 && n.value.charAt(0) === ':') {
-                const name = n.value.substr(1);
-                ++i;
-                while (i < _i && nodes[i].kind === 'comment') { i++; }
-                if (i >= _i) throw new Error(`There must be a value foolowed a named arg ':${name}'.`);
-                args[name] = visitExpr(nodes[i]);
-                if (isNaN(+name)) allNumeric = false;
-            } else {
-                args[pos++] = visitExpr(n);
-            }
-        }
-        if (allNumeric) {
-            const keys = Object.keys(args).map(a => +a).sort((a, b) => a - b);
-            let isArray = true;
-            for (let i = 0, _i = keys.length; i < _i; i++) {
-                if (keys[i] !== i) {
-                    isArray = false;
-                    break;
-                }
-            }
-            if (isArray) {
-                const arrayArgs: Expression[] = [];
-                for (let i = 0, _i = keys.length; i < _i; i++) {
-                    arrayArgs[i] = args[i];
-                }
-                return arrayArgs;
-            }
-        }
-        return args;
-    }
-
-    function hasNamedArgs(nodes: ASTNode.Expression[]) {
-        for (let i = 1, _i = nodes.length; i < _i; i++) {
-            const n = nodes[i];
-            if (n.kind === 'symbol' && n.value.length > 1 && n.value.charAt(0) === ':') return true;
-        }
-        return false;
-    }
-
-    function withoutComments(nodes: ASTNode.Expression[]) {
-        let hasComment = false;
-        for (let i = 0, _i = nodes.length; i < _i; i++) {
-            if (nodes[i].kind === 'comment') {
-                hasComment = true;
-                break;
-            }
-        }
-        if (!hasComment) return nodes;
-        return nodes.filter(n => n.kind !== 'comment');
-    }
-
-    function isNumber(value: string) {
-        return /-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/.test(value);
-    }
-
-    export function parse(input: string): Expression[] {
-        const ast = getAST(input);
-        const ret: Expression[] = [];
-        for (const expr of ast) {
-            if (expr.kind === 'comment') continue;
-            ret[ret.length] = visitExpr(expr);
-        }
-        return ret;
-    }
-}
\ No newline at end of file
+// /**
+//  * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
+//  *
+//  * @author David Sehnal <david.sehnal@gmail.com>
+//  */
+
+// import { MonadicParser as P } from 'mol-util/monadic-parser'
+// import Expression from '../../language/expression'
+// import B from '../../language/builder'
+
+// export function parseMolScript(input: string) {
+//     return Language.parse(input);
+// }
+
+// namespace Language {
+//     type AST = ASTNode.Expression[]
+
+//     namespace ASTNode {
+//         export type Expression = Str | Symb | List | Comment
+
+//         export interface Str {
+//             kind: 'string',
+//             value: string
+//         }
+
+//         export interface Symb {
+//             kind: 'symbol',
+//             value: string
+//         }
+
+//         export interface List {
+//             kind: 'list',
+//             bracket: '(' | '[' | '{',
+//             nodes: Expression[]
+//         }
+
+//         export interface Comment {
+//             kind: 'comment',
+//             value: string
+//         }
+
+//         export function str(value: string): Str { return { kind: 'string', value }; }
+//         export function symb(value: string): Symb { return { kind: 'symbol', value }; }
+//         export function list(bracket: '(' | '[' | '{', nodes: Expression[]): List { return { kind: 'list', bracket, nodes }; }
+//         export function comment(value: string): Comment { return { kind: 'comment', value } }
+//     }
+
+//     const ws = P.regexp(/[\n\r\s]*/);
+//     const Expr: P<ASTNode.Expression> = P.lazy(() => (P.alt(Str, List, Symb, Comment).trim(ws)));
+//     const Str = P.takeWhile(c => c !== '`').trim('`').map(ASTNode.str);
+//     const Symb = P.regexp(/[^()\[\]{};`,\n\r\s]+/).map(ASTNode.symb);
+//     const Comment = P.regexp(/\s*;+([^\n\r]*)\n/, 1).map(ASTNode.comment);
+//     const Args = Expr.many();
+//     const List1 = Args.wrap('(', ')').map(args => ASTNode.list('(', args));
+//     const List2 = Args.wrap('[', ']').map(args => ASTNode.list('[', args));
+//     const List3 = Args.wrap('{', '}').map(args => ASTNode.list('{', args));
+//     const List = P.alt(List1, List2, List3);
+
+//     const Expressions: P<AST> = Expr.many();
+
+//     function getAST(input: string) { return Expressions.tryParse(input); }
+
+//     function visitExpr(expr: ASTNode.Expression): Expression {
+//         switch (expr.kind) {
+//             case 'string': return expr.value;
+//             case 'symbol': {
+//                 const value = expr.value;
+//                 if (value.length > 1) {
+//                     const fst = value.charAt(0);
+//                     switch (fst) {
+//                         case '.': return B.atomName(value.substr(1));
+//                         case '_': return B.struct.type.elementSymbol([value.substr(1)]);
+//                     }
+//                 }
+//                 if (value === 'true') return true;
+//                 if (value === 'false') return false;
+//                 if (isNumber(value)) return +value;
+//                 return Expression.Symbol(value);
+//             }
+//             case 'list': {
+//                 switch (expr.bracket) {
+//                     case '[': return B.core.type.list(withoutComments(expr.nodes).map(visitExpr));
+//                     case '{': return B.core.type.set(withoutComments(expr.nodes).map(visitExpr));
+//                     case '(': {
+//                         const head = visitExpr(expr.nodes[0]);
+//                         return Expression.Apply(head, getArgs(expr.nodes));
+//                     }
+//                 }
+//                 return 0 as any;
+//             }
+//             default: {
+//                 throw new Error('should not happen');
+//             }
+//         }
+//     }
+
+//     function getArgs(nodes: ASTNode.Expression[]): Expression.Arguments | undefined {
+//         if (nodes.length <= 1) return void 0;
+//         if (!hasNamedArgs(nodes)) {
+//             const args: Expression[] = [];
+//             for (let i = 1, _i = nodes.length; i < _i; i++) {
+//                 const n = nodes[i];
+//                 if (n.kind === 'comment') continue;
+//                 args[args.length] = visitExpr(n);
+//             }
+//             return args;
+//         }
+//         const args: { [name: string]: Expression } = {};
+//         let allNumeric = true;
+//         let pos = 0;
+//         for (let i = 1, _i = nodes.length; i < _i; i++) {
+//             const n = nodes[i];
+//             if (n.kind === 'comment') continue;
+//             if (n.kind === 'symbol' && n.value.length > 1 && n.value.charAt(0) === ':') {
+//                 const name = n.value.substr(1);
+//                 ++i;
+//                 while (i < _i && nodes[i].kind === 'comment') { i++; }
+//                 if (i >= _i) throw new Error(`There must be a value foolowed a named arg ':${name}'.`);
+//                 args[name] = visitExpr(nodes[i]);
+//                 if (isNaN(+name)) allNumeric = false;
+//             } else {
+//                 args[pos++] = visitExpr(n);
+//             }
+//         }
+//         if (allNumeric) {
+//             const keys = Object.keys(args).map(a => +a).sort((a, b) => a - b);
+//             let isArray = true;
+//             for (let i = 0, _i = keys.length; i < _i; i++) {
+//                 if (keys[i] !== i) {
+//                     isArray = false;
+//                     break;
+//                 }
+//             }
+//             if (isArray) {
+//                 const arrayArgs: Expression[] = [];
+//                 for (let i = 0, _i = keys.length; i < _i; i++) {
+//                     arrayArgs[i] = args[i];
+//                 }
+//                 return arrayArgs;
+//             }
+//         }
+//         return args;
+//     }
+
+//     function hasNamedArgs(nodes: ASTNode.Expression[]) {
+//         for (let i = 1, _i = nodes.length; i < _i; i++) {
+//             const n = nodes[i];
+//             if (n.kind === 'symbol' && n.value.length > 1 && n.value.charAt(0) === ':') return true;
+//         }
+//         return false;
+//     }
+
+//     function withoutComments(nodes: ASTNode.Expression[]) {
+//         let hasComment = false;
+//         for (let i = 0, _i = nodes.length; i < _i; i++) {
+//             if (nodes[i].kind === 'comment') {
+//                 hasComment = true;
+//                 break;
+//             }
+//         }
+//         if (!hasComment) return nodes;
+//         return nodes.filter(n => n.kind !== 'comment');
+//     }
+
+//     function isNumber(value: string) {
+//         return /-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/.test(value);
+//     }
+
+//     export function parse(input: string): Expression[] {
+//         const ast = getAST(input);
+//         const ret: Expression[] = [];
+//         for (const expr of ast) {
+//             if (expr.kind === 'comment') continue;
+//             ret[ret.length] = visitExpr(expr);
+//         }
+//         return ret;
+//     }
+// }
\ 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 dbbf1c5f8..70b7028af 100644
--- a/src/mol-script/script/mol-script/symbols.ts
+++ b/src/mol-script/script/mol-script/symbols.ts
@@ -1,300 +1,300 @@
-/**
- * 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 { MSymbol, Arguments, Argument } from '../../language/symbol'
-import B from '../../language/builder'
-import * as M from './macro'
-import MolScript from '../../language/symbol-table'
-import Type from '../../language/type'
-import * as Struct from '../../language/symbol-table/structure-query'
-import Expression from '../../language/expression'
-import { UniqueArray } from 'mol-data/generic'
+// import { MSymbol, Arguments, Argument } from '../../language/symbol'
+// import B from '../../language/builder'
+// import * as M from './macro'
+// import { MolScriptSymbolTable as MolScript } from '../../language/symbol-table'
+// import Type from '../../language/type'
+// import * as Struct from '../../language/symbol-table/structure-query'
+// import Expression from '../../language/expression'
+// import { UniqueArray } from 'mol-data/generic'
 
-export type MolScriptSymbol =
-    | { kind: 'alias', aliases: string[], symbol: MSymbol }
-    | { kind: 'macro', aliases: string[], symbol: MSymbol, translate: (args: any) => Expression }
+// export type MolScriptSymbol =
+//     | { kind: 'alias', aliases: string[], symbol: MSymbol }
+//     | { kind: 'macro', aliases: string[], symbol: MSymbol, translate: (args: any) => Expression }
 
-function Alias(symbol: MSymbol<any>, ...aliases: string[]): MolScriptSymbol { return { kind: 'alias', aliases, symbol }; }
-function Macro(symbol: MSymbol<any>, translate: (args: any) => Expression, ...aliases: string[]): MolScriptSymbol {
-    symbol.info.namespace = 'molscript-macro';
-    symbol.id = `molscript-macro.${symbol.info.name}`;
-    return { kind: 'macro', symbol, translate, aliases: [symbol.info.name, ...aliases] };
-}
+// function Alias(symbol: MSymbol<any>, ...aliases: string[]): MolScriptSymbol { return { kind: 'alias', aliases, symbol }; }
+// function Macro(symbol: MSymbol<any>, translate: (args: any) => Expression, ...aliases: string[]): MolScriptSymbol {
+//     symbol.info.namespace = 'molscript-macro';
+//     symbol.id = `molscript-macro.${symbol.info.name}`;
+//     return { kind: 'macro', symbol, translate, aliases: [symbol.info.name, ...aliases] };
+// }
 
-export function isMolScriptSymbol(x: any): x is MolScriptSymbol {
-    return x.kind === 'alias' || x.kind === 'macro';
-}
+// export function isMolScriptSymbol(x: any): x is MolScriptSymbol {
+//     return x.kind === 'alias' || x.kind === 'macro';
+// }
 
-export const SymbolTable = [
-    [
-        'Core symbols',
-        Alias(MolScript.core.type.bool, 'bool'),
-        Alias(MolScript.core.type.num, 'num'),
-        Alias(MolScript.core.type.str, 'str'),
-        Alias(MolScript.core.type.regex, 'regex'),
-        Alias(MolScript.core.type.list, 'list'),
-        Alias(MolScript.core.type.set, 'set'),
+// export const SymbolTable = [
+//     [
+//         'Core symbols',
+//         Alias(MolScript.core.type.bool, 'bool'),
+//         Alias(MolScript.core.type.num, 'num'),
+//         Alias(MolScript.core.type.str, 'str'),
+//         Alias(MolScript.core.type.regex, 'regex'),
+//         Alias(MolScript.core.type.list, 'list'),
+//         Alias(MolScript.core.type.set, 'set'),
 
-        Alias(MolScript.core.type.compositeKey, 'composite-key'),
-        Alias(MolScript.core.logic.not, 'not'),
-        Alias(MolScript.core.logic.and, 'and'),
-        Alias(MolScript.core.logic.or, 'or'),
-        Alias(MolScript.core.ctrl.if, 'if'),
-        Alias(MolScript.core.ctrl.fn, 'fn'),
-        Alias(MolScript.core.ctrl.eval, 'eval'),
-        Alias(MolScript.core.math.add, 'add', '+'),
-        Alias(MolScript.core.math.sub, 'sub', '-'),
-        Alias(MolScript.core.math.mult, 'mult', '*'),
-        Alias(MolScript.core.math.div, 'div', '/'),
-        Alias(MolScript.core.math.pow, 'pow', '**'),
-        Alias(MolScript.core.math.mod, 'mod'),
-        Alias(MolScript.core.math.min, 'min'),
-        Alias(MolScript.core.math.max, 'max'),
-        Alias(MolScript.core.math.floor, 'floor'),
-        Alias(MolScript.core.math.ceil, 'ceil'),
-        Alias(MolScript.core.math.roundInt, 'round'),
-        Alias(MolScript.core.math.abs, 'abs'),
-        Alias(MolScript.core.math.sqrt, 'sqrt'),
-        Alias(MolScript.core.math.sin, 'sin'),
-        Alias(MolScript.core.math.cos, 'cos'),
-        Alias(MolScript.core.math.tan, 'tan'),
-        Alias(MolScript.core.math.asin, 'asin'),
-        Alias(MolScript.core.math.acos, 'acos'),
-        Alias(MolScript.core.math.atan, 'atan'),
-        Alias(MolScript.core.math.sinh, 'sinh'),
-        Alias(MolScript.core.math.cosh, 'cosh'),
-        Alias(MolScript.core.math.tanh, 'tanh'),
-        Alias(MolScript.core.math.exp, 'exp'),
-        Alias(MolScript.core.math.log, 'log'),
-        Alias(MolScript.core.math.log10, 'log10'),
-        Alias(MolScript.core.math.atan2, 'atan2'),
-        Alias(MolScript.core.rel.eq, 'eq', '='),
-        Alias(MolScript.core.rel.neq, 'neq', '!='),
-        Alias(MolScript.core.rel.lt, 'lt', '<'),
-        Alias(MolScript.core.rel.lte, 'lte', '<='),
-        Alias(MolScript.core.rel.gr, 'gr', '>'),
-        Alias(MolScript.core.rel.gre, 'gre', '>='),
-        Alias(MolScript.core.rel.inRange, 'in-range'),
-        Alias(MolScript.core.str.concat, 'concat'),
-        Alias(MolScript.core.str.match, 'regex.match'),
-        Alias(MolScript.core.list.getAt, 'list.get'),
-        Alias(MolScript.core.set.has, 'set.has'),
-        Alias(MolScript.core.set.isSubset, 'set.subset'),
-    ],
-    [
-        'Structure',
-        [
-            'Types',
-            Alias(MolScript.structureQuery.type.entityType, 'ent-type'),
-            Alias(MolScript.structureQuery.type.authResidueId, 'auth-resid'),
-            Alias(MolScript.structureQuery.type.labelResidueId, 'label-resid'),
-            Alias(MolScript.structureQuery.type.ringFingerprint, 'ringfp'),
-            Alias(MolScript.structureQuery.type.bondFlags, 'bond-flags'),
-        ],
-        [
-            'Slots',
-            Alias(MolScript.structureQuery.slot.elementSetReduce, 'atom.set.reduce.value'),
-        ],
-        [
-            'Generators',
-            Alias(MolScript.structureQuery.generator.atomGroups, 'sel.atom.atom-groups'),
-            Alias(MolScript.structureQuery.generator.queryInSelection, 'sel.atom.query-in-selection'),
-            Alias(MolScript.structureQuery.generator.rings, 'sel.atom.rings'),
-            Alias(MolScript.structureQuery.generator.empty, 'sel.atom.empty'),
+//         Alias(MolScript.core.type.compositeKey, 'composite-key'),
+//         Alias(MolScript.core.logic.not, 'not'),
+//         Alias(MolScript.core.logic.and, 'and'),
+//         Alias(MolScript.core.logic.or, 'or'),
+//         Alias(MolScript.core.ctrl.if, 'if'),
+//         Alias(MolScript.core.ctrl.fn, 'fn'),
+//         Alias(MolScript.core.ctrl.eval, 'eval'),
+//         Alias(MolScript.core.math.add, 'add', '+'),
+//         Alias(MolScript.core.math.sub, 'sub', '-'),
+//         Alias(MolScript.core.math.mult, 'mult', '*'),
+//         Alias(MolScript.core.math.div, 'div', '/'),
+//         Alias(MolScript.core.math.pow, 'pow', '**'),
+//         Alias(MolScript.core.math.mod, 'mod'),
+//         Alias(MolScript.core.math.min, 'min'),
+//         Alias(MolScript.core.math.max, 'max'),
+//         Alias(MolScript.core.math.floor, 'floor'),
+//         Alias(MolScript.core.math.ceil, 'ceil'),
+//         Alias(MolScript.core.math.roundInt, 'round'),
+//         Alias(MolScript.core.math.abs, 'abs'),
+//         Alias(MolScript.core.math.sqrt, 'sqrt'),
+//         Alias(MolScript.core.math.sin, 'sin'),
+//         Alias(MolScript.core.math.cos, 'cos'),
+//         Alias(MolScript.core.math.tan, 'tan'),
+//         Alias(MolScript.core.math.asin, 'asin'),
+//         Alias(MolScript.core.math.acos, 'acos'),
+//         Alias(MolScript.core.math.atan, 'atan'),
+//         Alias(MolScript.core.math.sinh, 'sinh'),
+//         Alias(MolScript.core.math.cosh, 'cosh'),
+//         Alias(MolScript.core.math.tanh, 'tanh'),
+//         Alias(MolScript.core.math.exp, 'exp'),
+//         Alias(MolScript.core.math.log, 'log'),
+//         Alias(MolScript.core.math.log10, 'log10'),
+//         Alias(MolScript.core.math.atan2, 'atan2'),
+//         Alias(MolScript.core.rel.eq, 'eq', '='),
+//         Alias(MolScript.core.rel.neq, 'neq', '!='),
+//         Alias(MolScript.core.rel.lt, 'lt', '<'),
+//         Alias(MolScript.core.rel.lte, 'lte', '<='),
+//         Alias(MolScript.core.rel.gr, 'gr', '>'),
+//         Alias(MolScript.core.rel.gre, 'gre', '>='),
+//         Alias(MolScript.core.rel.inRange, 'in-range'),
+//         Alias(MolScript.core.str.concat, 'concat'),
+//         Alias(MolScript.core.str.match, 'regex.match'),
+//         Alias(MolScript.core.list.getAt, 'list.get'),
+//         Alias(MolScript.core.set.has, 'set.has'),
+//         Alias(MolScript.core.set.isSubset, 'set.subset'),
+//     ],
+//     [
+//         'Structure',
+//         [
+//             'Types',
+//             Alias(MolScript.structureQuery.type.entityType, 'ent-type'),
+//             Alias(MolScript.structureQuery.type.authResidueId, 'auth-resid'),
+//             Alias(MolScript.structureQuery.type.labelResidueId, 'label-resid'),
+//             Alias(MolScript.structureQuery.type.ringFingerprint, 'ringfp'),
+//             Alias(MolScript.structureQuery.type.bondFlags, 'bond-flags'),
+//         ],
+//         [
+//             'Slots',
+//             Alias(MolScript.structureQuery.slot.elementSetReduce, 'atom.set.reduce.value'),
+//         ],
+//         [
+//             'Generators',
+//             Alias(MolScript.structureQuery.generator.atomGroups, 'sel.atom.atom-groups'),
+//             Alias(MolScript.structureQuery.generator.queryInSelection, 'sel.atom.query-in-selection'),
+//             Alias(MolScript.structureQuery.generator.rings, 'sel.atom.rings'),
+//             Alias(MolScript.structureQuery.generator.empty, 'sel.atom.empty'),
 
-            Macro(MSymbol('sel.atom.atoms', Arguments.Dictionary({
-                0: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'Test applied to each atom.' })
-            }), Struct.Types.ElementSelection, 'A selection of singleton atom sets.'),
-            args => B.struct.generator.atomGroups({ 'atom-test':  M.tryGetArg(args, 0, true) })),
+//             Macro(MSymbol('sel.atom.atoms', Arguments.Dictionary({
+//                 0: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'Test applied to each atom.' })
+//             }), Struct.Types.ElementSelection, 'A selection of singleton atom sets.'),
+//             args => B.struct.generator.atomGroups({ 'atom-test':  M.tryGetArg(args, 0, true) })),
 
-            Macro(MSymbol('sel.atom.res', Arguments.Dictionary({
-                0: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'Test applied to the 1st atom of each residue.' })
-            }), Struct.Types.ElementSelection, 'A selection of atom sets grouped by residue.'),
-            args => B.struct.generator.atomGroups({
-                'residue-test':  M.tryGetArg(args, 0, true),
-                'group-by': B.ammp('residueKey')
-            })),
+//             Macro(MSymbol('sel.atom.res', Arguments.Dictionary({
+//                 0: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'Test applied to the 1st atom of each residue.' })
+//             }), Struct.Types.ElementSelection, 'A selection of atom sets grouped by residue.'),
+//             args => B.struct.generator.atomGroups({
+//                 'residue-test':  M.tryGetArg(args, 0, true),
+//                 'group-by': B.ammp('residueKey')
+//             })),
 
-            Macro(MSymbol('sel.atom.chains', Arguments.Dictionary({
-                0: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'Test applied to the 1st atom of each chain.' })
-            }), Struct.Types.ElementSelection, 'A selection of atom sets grouped by chain.'),
-            args => B.struct.generator.atomGroups({
-                'chain-test': M.tryGetArg(args, 0, true),
-                'group-by': B.ammp('chainKey')
-            })),
-        ],
-        [
-            'Modifiers',
-            Alias(MolScript.structureQuery.modifier.queryEach, 'sel.atom.query-each'),
-            Alias(MolScript.structureQuery.modifier.intersectBy, 'sel.atom.intersect-by'),
-            Alias(MolScript.structureQuery.modifier.exceptBy, 'sel.atom.except-by'),
-            Alias(MolScript.structureQuery.modifier.unionBy, 'sel.atom.union-by'),
-            Alias(MolScript.structureQuery.modifier.union, 'sel.atom.union'),
-            Alias(MolScript.structureQuery.modifier.cluster, 'sel.atom.cluster'),
-            Alias(MolScript.structureQuery.modifier.includeSurroundings, 'sel.atom.include-surroundings'),
-            Alias(MolScript.structureQuery.modifier.includeConnected, 'sel.atom.include-connected'),
-            Alias(MolScript.structureQuery.modifier.expandProperty, 'sel.atom.expand-property'),
+//             Macro(MSymbol('sel.atom.chains', Arguments.Dictionary({
+//                 0: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'Test applied to the 1st atom of each chain.' })
+//             }), Struct.Types.ElementSelection, 'A selection of atom sets grouped by chain.'),
+//             args => B.struct.generator.atomGroups({
+//                 'chain-test': M.tryGetArg(args, 0, true),
+//                 'group-by': B.ammp('chainKey')
+//             })),
+//         ],
+//         [
+//             'Modifiers',
+//             Alias(MolScript.structureQuery.modifier.queryEach, 'sel.atom.query-each'),
+//             Alias(MolScript.structureQuery.modifier.intersectBy, 'sel.atom.intersect-by'),
+//             Alias(MolScript.structureQuery.modifier.exceptBy, 'sel.atom.except-by'),
+//             Alias(MolScript.structureQuery.modifier.unionBy, 'sel.atom.union-by'),
+//             Alias(MolScript.structureQuery.modifier.union, 'sel.atom.union'),
+//             Alias(MolScript.structureQuery.modifier.cluster, 'sel.atom.cluster'),
+//             Alias(MolScript.structureQuery.modifier.includeSurroundings, 'sel.atom.include-surroundings'),
+//             Alias(MolScript.structureQuery.modifier.includeConnected, 'sel.atom.include-connected'),
+//             Alias(MolScript.structureQuery.modifier.expandProperty, 'sel.atom.expand-property'),
 
-            Macro(MSymbol('sel.atom.around', Arguments.Dictionary({
-                0: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'Test applied to the 1st atom of each chain.' })
-            }), Struct.Types.ElementSelection, 'A selection of singleton atom sets with centers within "radius" of the center of any atom in the given selection.'),
-            args => B.struct.modifier.exceptBy({
-                '0': B.struct.filter.within({
-                    '0': B.struct.generator.atomGroups(), target: M.tryGetArg(args, 0), 'max-radius': M.tryGetArg(args, 'radius')
-                }),
-                by: M.tryGetArg(args, 0)
-            }))
-        ],
-        [
-            'Filters',
-            Alias(MolScript.structureQuery.filter.pick, 'sel.atom.pick'),
-            Alias(MolScript.structureQuery.filter.withSameAtomProperties, 'sel.atom.with-same-atom-properties'),
-            Alias(MolScript.structureQuery.filter.intersectedBy, 'sel.atom.intersected-by'),
-            Alias(MolScript.structureQuery.filter.within, 'sel.atom.within'),
-            Alias(MolScript.structureQuery.filter.isConnectedTo, 'sel.atom.is-connected-to'),
-        ],
-        [
-            'Combinators',
-            Alias(MolScript.structureQuery.combinator.intersect, 'sel.atom.intersect'),
-            Alias(MolScript.structureQuery.combinator.merge, 'sel.atom.merge'),
-            Alias(MolScript.structureQuery.combinator.distanceCluster, 'sel.atom.dist-cluster'),
-        ],
-        [
-            'Atom Set Properties',
-            Alias(MolScript.structureQuery.atomSet.atomCount, 'atom.set.atom-count'),
-            Alias(MolScript.structureQuery.atomSet.countQuery, 'atom.set.count-query'),
-            Alias(MolScript.structureQuery.atomSet.reduce, 'atom.set.reduce'),
-            Alias(MolScript.structureQuery.atomSet.propertySet, 'atom.set.property'),
+//             Macro(MSymbol('sel.atom.around', Arguments.Dictionary({
+//                 0: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'Test applied to the 1st atom of each chain.' })
+//             }), Struct.Types.ElementSelection, 'A selection of singleton atom sets with centers within "radius" of the center of any atom in the given selection.'),
+//             args => B.struct.modifier.exceptBy({
+//                 '0': B.struct.filter.within({
+//                     '0': B.struct.generator.atomGroups(), target: M.tryGetArg(args, 0), 'max-radius': M.tryGetArg(args, 'radius')
+//                 }),
+//                 by: M.tryGetArg(args, 0)
+//             }))
+//         ],
+//         [
+//             'Filters',
+//             Alias(MolScript.structureQuery.filter.pick, 'sel.atom.pick'),
+//             Alias(MolScript.structureQuery.filter.withSameAtomProperties, 'sel.atom.with-same-atom-properties'),
+//             Alias(MolScript.structureQuery.filter.intersectedBy, 'sel.atom.intersected-by'),
+//             Alias(MolScript.structureQuery.filter.within, 'sel.atom.within'),
+//             Alias(MolScript.structureQuery.filter.isConnectedTo, 'sel.atom.is-connected-to'),
+//         ],
+//         [
+//             'Combinators',
+//             Alias(MolScript.structureQuery.combinator.intersect, 'sel.atom.intersect'),
+//             Alias(MolScript.structureQuery.combinator.merge, 'sel.atom.merge'),
+//             Alias(MolScript.structureQuery.combinator.distanceCluster, 'sel.atom.dist-cluster'),
+//         ],
+//         [
+//             'Atom Set Properties',
+//             Alias(MolScript.structureQuery.atomSet.atomCount, 'atom.set.atom-count'),
+//             Alias(MolScript.structureQuery.atomSet.countQuery, 'atom.set.count-query'),
+//             Alias(MolScript.structureQuery.atomSet.reduce, 'atom.set.reduce'),
+//             Alias(MolScript.structureQuery.atomSet.propertySet, 'atom.set.property'),
 
-            Macro(MSymbol('atom.set.max', Arguments.Dictionary({
-                0: Argument(Type.Num, { description: 'Numeric atom property.'})
-            }), Type.Num, 'Maximum of the given property in the current atom set.'),
-            args => M.aggregate(M.tryGetArg(args, 0), B.core.math.max)),
+//             Macro(MSymbol('atom.set.max', Arguments.Dictionary({
+//                 0: Argument(Type.Num, { description: 'Numeric atom property.'})
+//             }), Type.Num, 'Maximum of the given property in the current atom set.'),
+//             args => M.aggregate(M.tryGetArg(args, 0), B.core.math.max)),
 
-            Macro(MSymbol('atom.set.sum', Arguments.Dictionary({
-                0: Argument(Type.Num, { description: 'Numeric atom property.'})
-            }), Type.Num, 'Sum of the given property in the current atom set.'),
-            args => M.aggregate(M.tryGetArg(args, 0), B.core.math.add, 0)),
+//             Macro(MSymbol('atom.set.sum', Arguments.Dictionary({
+//                 0: Argument(Type.Num, { description: 'Numeric atom property.'})
+//             }), Type.Num, 'Sum of the given property in the current atom set.'),
+//             args => M.aggregate(M.tryGetArg(args, 0), B.core.math.add, 0)),
 
-            Macro(MSymbol('atom.set.avg', Arguments.Dictionary({
-                0: Argument(Type.Num, { description: 'Numeric atom property.'})
-            }), Type.Num, 'Average of the given property in the current atom set.'),
-            args => B.core.math.div([ M.aggregate(M.tryGetArg(args, 0), B.core.math.add, 0), B.struct.atomSet.atomCount() ])),
+//             Macro(MSymbol('atom.set.avg', Arguments.Dictionary({
+//                 0: Argument(Type.Num, { description: 'Numeric atom property.'})
+//             }), Type.Num, 'Average of the given property in the current atom set.'),
+//             args => B.core.math.div([ M.aggregate(M.tryGetArg(args, 0), B.core.math.add, 0), B.struct.atomSet.atomCount() ])),
 
-            Macro(MSymbol('atom.set.min', Arguments.Dictionary({
-                0: Argument(Type.Num, { description: 'Numeric atom property.'})
-            }), Type.Num, 'Minimum of the given property in the current atom set.'),
-            args => M.aggregate(M.tryGetArg(args, 0), B.core.math.min))
-        ],
-        [
-            'Atom Properties',
-            Alias(MolScript.structureQuery.atomProperty.core.elementSymbol, 'atom.el'),
-            Alias(MolScript.structureQuery.atomProperty.core.vdw, 'atom.vdw'),
-            Alias(MolScript.structureQuery.atomProperty.core.mass, 'atom.mass'),
-            Alias(MolScript.structureQuery.atomProperty.core.atomicNumber, 'atom.atomic-number'),
-            Alias(MolScript.structureQuery.atomProperty.core.x, 'atom.x'),
-            Alias(MolScript.structureQuery.atomProperty.core.y, 'atom.y'),
-            Alias(MolScript.structureQuery.atomProperty.core.z, 'atom.z'),
-            Alias(MolScript.structureQuery.atomProperty.core.atomKey, 'atom.key'),
-            Alias(MolScript.structureQuery.atomProperty.core.bondCount, 'atom.bond-count'),
+//             Macro(MSymbol('atom.set.min', Arguments.Dictionary({
+//                 0: Argument(Type.Num, { description: 'Numeric atom property.'})
+//             }), Type.Num, 'Minimum of the given property in the current atom set.'),
+//             args => M.aggregate(M.tryGetArg(args, 0), B.core.math.min))
+//         ],
+//         [
+//             'Atom Properties',
+//             Alias(MolScript.structureQuery.atomProperty.core.elementSymbol, 'atom.el'),
+//             Alias(MolScript.structureQuery.atomProperty.core.vdw, 'atom.vdw'),
+//             Alias(MolScript.structureQuery.atomProperty.core.mass, 'atom.mass'),
+//             Alias(MolScript.structureQuery.atomProperty.core.atomicNumber, 'atom.atomic-number'),
+//             Alias(MolScript.structureQuery.atomProperty.core.x, 'atom.x'),
+//             Alias(MolScript.structureQuery.atomProperty.core.y, 'atom.y'),
+//             Alias(MolScript.structureQuery.atomProperty.core.z, 'atom.z'),
+//             Alias(MolScript.structureQuery.atomProperty.core.atomKey, 'atom.key'),
+//             Alias(MolScript.structureQuery.atomProperty.core.bondCount, 'atom.bond-count'),
 
-            Alias(MolScript.structureQuery.atomProperty.topology.connectedComponentKey, 'atom.key.molecule'),
+//             Alias(MolScript.structureQuery.atomProperty.topology.connectedComponentKey, 'atom.key.molecule'),
 
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.authResidueId, 'atom.auth-resid'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.labelResidueId, 'atom.label-resid'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.residueKey, 'atom.key.res'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.chainKey, 'atom.key.chain'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.entityKey, 'atom.key.entity'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.isHet, 'atom.is-het'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.id, 'atom.id'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.label_atom_id, 'atom.label_atom_id'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.label_alt_id, 'atom.label_alt_id', 'atom.altloc'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.label_comp_id, 'atom.label_comp_id'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.label_asym_id, 'atom.label_asym_id'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.label_entity_id, 'atom.label_entity_id'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.label_seq_id, 'atom.label_seq_id'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.auth_atom_id, 'atom.auth_atom_id', 'atom.name'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.auth_comp_id, 'atom.auth_comp_id', 'atom.resname'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.auth_asym_id, 'atom.auth_asym_id', 'atom.chain'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.auth_seq_id, 'atom.auth_seq_id', 'atom.resno'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.pdbx_PDB_ins_code, 'atom.pdbx_PDB_ins_code', 'atom.inscode'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.pdbx_formal_charge, 'atom.pdbx_formal_charge'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.occupancy, 'atom.occupancy'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.B_iso_or_equiv, 'atom.B_iso_or_equiv', 'atom.bfactor'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.entityType, 'atom.entity-type'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.authResidueId, 'atom.auth-resid'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.labelResidueId, 'atom.label-resid'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.residueKey, 'atom.key.res'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.chainKey, 'atom.key.chain'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.entityKey, 'atom.key.entity'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.isHet, 'atom.is-het'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.id, 'atom.id'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.label_atom_id, 'atom.label_atom_id'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.label_alt_id, 'atom.label_alt_id', 'atom.altloc'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.label_comp_id, 'atom.label_comp_id'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.label_asym_id, 'atom.label_asym_id'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.label_entity_id, 'atom.label_entity_id'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.label_seq_id, 'atom.label_seq_id'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.auth_atom_id, 'atom.auth_atom_id', 'atom.name'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.auth_comp_id, 'atom.auth_comp_id', 'atom.resname'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.auth_asym_id, 'atom.auth_asym_id', 'atom.chain'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.auth_seq_id, 'atom.auth_seq_id', 'atom.resno'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.pdbx_PDB_ins_code, 'atom.pdbx_PDB_ins_code', 'atom.inscode'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.pdbx_formal_charge, 'atom.pdbx_formal_charge'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.occupancy, 'atom.occupancy'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.B_iso_or_equiv, 'atom.B_iso_or_equiv', 'atom.bfactor'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.entityType, 'atom.entity-type'),
 
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.secondaryStructureKey, 'atom.key.sec-struct'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.secondaryStructureKey, 'atom.key.sec-struct'),
 
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.isModified, 'atom.is-modified'),
-            Alias(MolScript.structureQuery.atomProperty.macromolecular.modifiedParentName, 'atom.modified-parent'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.isModified, 'atom.is-modified'),
+//             Alias(MolScript.structureQuery.atomProperty.macromolecular.modifiedParentName, 'atom.modified-parent'),
 
-            Macro(MSymbol('atom.sec-struct.is', Arguments.List(Struct.Types.SecondaryStructureFlag), Type.Bool,
-                `Test if the current atom is part of an secondary structure. Optionally specify allowed sec. struct. types: ${Type.oneOfValues(Struct.Types.SecondaryStructureFlag).join(', ')}`),
-            args => B.core.flags.hasAny([B.struct.atomProperty.macromolecular.secondaryStructureFlags(), B.struct.type.secondaryStructureFlags(args)])),
-        ],
-        [
-            'Bond Properties',
-            Alias(MolScript.structureQuery.bondProperty.order, 'bond.order'),
-            Macro(MSymbol('bond.is', Arguments.List(Struct.Types.BondFlag), Type.Bool,
-                `Test if the current bond has at least one (or all if partial = false) of the specified flags: ${Type.oneOfValues(Struct.Types.BondFlag).join(', ')}`),
-            args => B.core.flags.hasAny([B.struct.bondProperty.flags(), B.struct.type.bondFlags(M.getPositionalArgs(args))])),
-        ]
-    ]
-];
+//             Macro(MSymbol('atom.sec-struct.is', Arguments.List(Struct.Types.SecondaryStructureFlag), Type.Bool,
+//                 `Test if the current atom is part of an secondary structure. Optionally specify allowed sec. struct. types: ${Type.oneOfValues(Struct.Types.SecondaryStructureFlag).join(', ')}`),
+//             args => B.core.flags.hasAny([B.struct.atomProperty.macromolecular.secondaryStructureFlags(), B.struct.type.secondaryStructureFlags(args)])),
+//         ],
+//         [
+//             'Bond Properties',
+//             Alias(MolScript.structureQuery.bondProperty.order, 'bond.order'),
+//             Macro(MSymbol('bond.is', Arguments.List(Struct.Types.BondFlag), Type.Bool,
+//                 `Test if the current bond has at least one (or all if partial = false) of the specified flags: ${Type.oneOfValues(Struct.Types.BondFlag).join(', ')}`),
+//             args => B.core.flags.hasAny([B.struct.bondProperty.flags(), B.struct.type.bondFlags(M.getPositionalArgs(args))])),
+//         ]
+//     ]
+// ];
 
-const list: MolScriptSymbol[] = [];
+// const list: MolScriptSymbol[] = [];
 
-function makeList(xs: any[]) {
-    for (const x of xs) {
-        if (isMolScriptSymbol(x)) list.push(x);
-        else if (x instanceof Array) makeList(x);
-    }
-}
+// function makeList(xs: any[]) {
+//     for (const x of xs) {
+//         if (isMolScriptSymbol(x)) list.push(x);
+//         else if (x instanceof Array) makeList(x);
+//     }
+// }
 
-makeList(SymbolTable);
+// makeList(SymbolTable);
 
-const normalized = (function () {
-    const symbolList: [string, MolScriptSymbol][] = [];
-    const symbolMap: { [id: string]: MolScriptSymbol | undefined } = Object.create(null);
-    const namedArgs = UniqueArray.create<string, string>();
-    const constants = UniqueArray.create<string, string>();
+// const normalized = (function () {
+//     const symbolList: [string, MolScriptSymbol][] = [];
+//     const symbolMap: { [id: string]: MolScriptSymbol | undefined } = Object.create(null);
+//     const namedArgs = UniqueArray.create<string, string>();
+//     const constants = UniqueArray.create<string, string>();
 
-    for (const s of list) {
-        for (const a of s.aliases) {
-            symbolList.push([a, s]);
-            if (symbolMap[a]) throw new Error(`Alias '${a}' already in use.`);
-            symbolMap[a] = s;
-        }
-        const args = s.symbol.args;
-        if (args.kind !== 'dictionary') {
-            if (args.type.kind === 'oneof') {
-                Type.oneOfValues(args.type).forEach(v => UniqueArray.add(constants, v, v));
-            }
-            continue;
-        }
-        for (const a of Object.keys(args.map)) {
-            if (isNaN(a as any)) UniqueArray.add(namedArgs, a, a);
-            const arg = ((args.map as any)[a]) as Argument;
-            if (arg.type.kind === 'oneof') {
-                Type.oneOfValues(arg.type).forEach(v => UniqueArray.add(constants, v, v));
-            }
-        }
-    }
+//     for (const s of list) {
+//         for (const a of s.aliases) {
+//             symbolList.push([a, s]);
+//             if (symbolMap[a]) throw new Error(`Alias '${a}' already in use.`);
+//             symbolMap[a] = s;
+//         }
+//         const args = s.symbol.args;
+//         if (args.kind !== 'dictionary') {
+//             if (args.type.kind === 'oneof') {
+//                 Type.oneOfValues(args.type).forEach(v => UniqueArray.add(constants, v, v));
+//             }
+//             continue;
+//         }
+//         for (const a of Object.keys(args.map)) {
+//             if (isNaN(a as any)) UniqueArray.add(namedArgs, a, a);
+//             const arg = ((args.map as any)[a]) as Argument;
+//             if (arg.type.kind === 'oneof') {
+//                 Type.oneOfValues(arg.type).forEach(v => UniqueArray.add(constants, v, v));
+//             }
+//         }
+//     }
 
-    return { symbolList, symbolMap, namedArgs: namedArgs.array, constants: constants.array }
-})();
+//     return { symbolList, symbolMap, namedArgs: namedArgs.array, constants: constants.array }
+// })();
 
-export const MolScriptSymbols = list;
-export const Constants = normalized.constants;
-export const NamedArgs = normalized.namedArgs;
-export const SymbolMap = normalized.symbolMap;
-export const SymbolList = normalized.symbolList;
+// export const MolScriptSymbols = list;
+// export const Constants = normalized.constants;
+// export const NamedArgs = normalized.namedArgs;
+// export const SymbolMap = normalized.symbolMap;
+// export const SymbolList = normalized.symbolList;
 
-const sortedSymbols = SymbolList.map(s => s[0]).sort((a, b) => {
-    if (a.length === b.length) return (a < b) as any;
-    return a.length - b.length;
-});
-export default [...sortedSymbols, ...NamedArgs.map(a => ':' + a), ...Constants];
\ No newline at end of file
+// const sortedSymbols = SymbolList.map(s => s[0]).sort((a, b) => {
+//     if (a.length === b.length) return (a < b) as any;
+//     return a.length - b.length;
+// });
+// export default [...sortedSymbols, ...NamedArgs.map(a => ':' + a), ...Constants];
\ No newline at end of file
diff --git a/src/perf-tests/mol-script.ts b/src/perf-tests/mol-script.ts
index 3b488f5f5..104c6c194 100644
--- a/src/perf-tests/mol-script.ts
+++ b/src/perf-tests/mol-script.ts
@@ -1,12 +1,17 @@
-import Examples from 'mol-script/script/mol-script/examples'
-import { parseMolScript } from 'mol-script/script/mol-script/parser'
-import * as util from 'util'
-//import { compileAST } from 'mol-script/script/mol-script/compile';
-
-for (const e of Examples) {
-    const expr = parseMolScript(e.value)[0];
-    console.log(e.name, util.inspect(expr, true, 10, true));
-}
+import { MolScriptBuilder } from 'mol-script/language/builder';
+import { compile } from 'mol-script/runtime/query/compiler';
+import { QueryContext, Structure, StructureQuery } from 'mol-model/structure';
+import { readCifFile, getModelsAndStructure } from '../apps/structure-info/model';
+
+// import Examples from 'mol-script/script/mol-script/examples'
+// import { parseMolScript } from 'mol-script/script/mol-script/parser'
+// import * as util from 'util'
+// //import { compileAST } from 'mol-script/script/mol-script/compile';
+
+// for (const e of Examples) {
+//     const expr = parseMolScript(e.value)[0];
+//     console.log(e.name, util.inspect(expr, true, 10, true));
+// }
 // const exprs = parseMolScript(`(sel.atom.atom-groups
 //     :residue-test (= atom.auth_comp_id ALA)
 //     ;; ho ho ho
@@ -15,4 +20,32 @@ for (const e of Examples) {
 //     ((hi) (ho))`);
 
 // console.log(util.inspect(exprs, true, 10, true));
-// //console.log(expr);
\ No newline at end of file
+// //console.log(expr);
+
+const expr = MolScriptBuilder.core.math.add([1, 2, 3]);
+const compiled = compile<number>(expr);
+const result = compiled(new QueryContext(Structure.Empty));
+console.log(result);
+
+async function testQ() {
+    const frame = await readCifFile('e:/test/quick/1cbs_updated.cif');
+    const { structure } = await getModelsAndStructure(frame);
+
+    const expr = MolScriptBuilder.struct.generator.atomGroups({
+        'atom-test': MolScriptBuilder.core.rel.eq([
+            MolScriptBuilder.struct.atomProperty.core.elementSymbol(),
+            MolScriptBuilder.es('C')
+        ]),
+        'residue-test': MolScriptBuilder.core.rel.eq([
+            MolScriptBuilder.struct.atomProperty.macromolecular.label_comp_id(),
+            'REA'
+        ])
+    });
+
+    const compiled = compile<StructureQuery>(expr);
+    const result = compiled(new QueryContext(structure));
+
+    console.log(result);
+}
+
+testQ();
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index 8da5b2ddc..48fb8c0dc 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -8,7 +8,8 @@
         "noUnusedLocals": true,
         "strictNullChecks": true,
         "strictFunctionTypes": true,
-        "keyofStringsOnly": true,
+        //"keyofStringsOnly": true,
+        // temp fix for immutable package: has(key: string): key is keyof TProps; => has(key: string | number | Symbol): key is keyof TProps;
         //"downlevelIteration": true,
         "jsx": "react",
         "lib": [ "es6", "dom", "esnext.asynciterable", "es2016" ],
-- 
GitLab