diff --git a/package-lock.json b/package-lock.json index 0b0df7edaf6edb49db5b2861d5b6c4b2f321a620..4f137e24d0fb3957776c524681a389410b1a1b40 100644 Binary files a/package-lock.json and b/package-lock.json differ diff --git a/package.json b/package.json index eb8afa253cb97c9f7bc8d02c890cd85ed88ee76b..40e7655c3b9d40d5d2ccc189c6a249d80c157895 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 fbc466845b97f16694d61f36f8afffd2462e7219..c01698f91a40bda96ebad2fd4955b18e9a1546a7 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 7541c8ac2bb2b35476830dd45d163b6c4098da3b..188aac0e74467e0fe384765424ed0ee118fa1c09 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 4283b6b73029bf88d6c793253fb6871f6657ed60..f7629182ea113880e2e9064578a5077b1b82b042 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 213b47a7af669e630ed9416806e15a0fdf8f3e43..8c7efa07de3d50d5890519d21fe76e2c3a5c668e 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 6f47d15d9cef2872174dc4376b35eff27dc749dd..3dec8616fedebe9973a69385ca78da09092d2020 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 b4164f6133e2e580cbbb3d1a7f437391566742e3..fa0a801d9b45ffca5da52bebfb4b7d0cb93d95b5 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 c928809b91c619afc49d8142ab44ca05ecf985a2..de9b536655c7689782e4b84b11edad833aa69fc3 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 9a50889cbac701e5c7738ee4eb278049d8231a3c..90465ec4df5420823eb3e82f0e0ed80a52b31833 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 54882d11a24416b72b889d962410aea0ee0e80cb..7592071c8960339bb7d96eb643efb6631bb9b10c 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 c6d38827a8f35ec611c015a96cf054b295e0a009..f12841edf8abf4c883931fa29a9e1677586dfb10 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 4d5128886ff764a749d37c9e7ba52144ea4f2918..d6ef5f71d25d6a9feec022ac5aa92bca7b445902 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 0000000000000000000000000000000000000000..63598bb4c420865970b6e460213f5a5091fa3912 --- /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 0000000000000000000000000000000000000000..d5c4217d74a0c2dd107a7b509a8b9f3a4b320f0a --- /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 5a53a4ba8e9f680ad24ce0bbb87b2e305813075f..b707833307edc6c52c47cbfa85ca617395e24bee 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 7df280f8b7cc74bfd2fae937da928dbc8552f4f0..1f689f1d3697c9f3a447d9fcdfe1f606312bd8c9 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 a2c9c5a7c90fd759cd1fd93bc84ec783228ff8fc..436e06bc6e3a8df01afeac0899743777f0a2e968 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 b313de302d4d3008b10b3bd51047fd04223c0914..f9452036a6811b567c7310bffe24da90082f1974 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 dbbf1c5f843acac78b0f53bbf25fdf2409c3a1d9..70b7028af1c6175845a7ae0b2b18f509ff6237f3 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 3b488f5f59bd9bc46e52b174c75213dfaa6ebae5..104c6c1949383142a133d76c5a259a6c71dcfd01 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 8da5b2ddc8d0c13c4d3d346f02177527b308f51b..48fb8c0dc68e8ec29fb848888ed98531fc1cdf85 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" ],