From e323bc847badcf92f8945c2243a5622e8e4ad2ec Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Mon, 4 Jun 2018 11:41:44 +0200 Subject: [PATCH] Working on mol-script --- src/mol-script/builder.ts | 2 +- src/mol-script/compiler.ts | 157 ++++++++++---------- src/mol-script/helpers.ts | 2 +- src/mol-script/runtime/environment.ts | 31 +++- src/mol-script/runtime/expression.ts | 6 +- src/mol-script/runtime/symbol.ts | 28 ++-- src/mol-script/script/mol-script/symbols.ts | 2 +- src/mol-script/symbol-table.ts | 2 +- src/mol-script/symbol-table/core.ts | 2 +- src/mol-script/symbol.ts | 6 +- 10 files changed, 128 insertions(+), 110 deletions(-) diff --git a/src/mol-script/builder.ts b/src/mol-script/builder.ts index a79cd1643..a4ea6a093 100644 --- a/src/mol-script/builder.ts +++ b/src/mol-script/builder.ts @@ -5,7 +5,7 @@ */ import Expression from './expression' -import Symbol from './symbol' +import { Symbol } from './symbol' import SymbolTable from './symbol-table' namespace Builder { diff --git a/src/mol-script/compiler.ts b/src/mol-script/compiler.ts index fb62178c7..ffdb7387a 100644 --- a/src/mol-script/compiler.ts +++ b/src/mol-script/compiler.ts @@ -1,93 +1,92 @@ -/** - * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author David Sehnal <david.sehnal@gmail.com> - */ +// /** +// * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info. +// * +// * @author David Sehnal <david.sehnal@gmail.com> +// */ -import Expression from './expression' -import Environment from './runtime/environment' -import RuntimeExpression from './runtime/expression' -import SymbolRuntime, { RuntimeArguments } from './runtime/symbol' +// import Expression from './expression' +// import Environment from './runtime/environment' +// import RuntimeExpression from './runtime/expression' +// import SymbolRuntime, { RuntimeArguments } from './runtime/symbol' -export type CompiledExpression<C, T> = (ctx: C) => T +// export type CompiledExpression<T> = () => T -type Compiler<C> = <T>(expression: Expression) => CompiledExpression<C, T> -function Compiler<C>(envProvider: (ctx?: C) => Environment): Compiler<C> { - const env = envProvider(void 0); - return expression => wrap(envProvider, compile(env, expression).runtime); -} +// type Compiler = <T>(expression: Expression) => CompiledExpression<T> +// function Compiler<C>(env: Environment): Compiler { +// return expression => compile(env, expression).runtime; +// } -type CompileResult = { isConst: boolean, runtime: RuntimeExpression } +// type CompileResult = { isConst: boolean, runtime: RuntimeExpression } -namespace CompileResult { - export function Const(value: any): CompileResult { return { isConst: true, runtime: RuntimeExpression.constant(value) } } - export function Dynamic(runtime: RuntimeExpression): CompileResult { return { isConst: false, runtime } } -} +// namespace CompileResult { +// export function Const(value: any): CompileResult { return { isConst: true, runtime: RuntimeExpression.constant(value) } } +// export function Dynamic(runtime: RuntimeExpression): CompileResult { return { isConst: false, runtime } } +// } -function wrap<C, T>(envProvider: (ctx?: C) => Environment, runtime: RuntimeExpression<C, T>) { - return (ctx: C) => runtime(envProvider(ctx)); -} +// function wrap<T>(envProvider: (ctx?: C) => Environment, runtime: RuntimeExpression<T>) { +// return (ctx: C) => runtime(envProvider(ctx)); +// } -function noRuntimeFor(symbol: string) { - throw new Error(`Could not find runtime for symbol '${symbol}'.`); -} +// function noRuntimeFor(symbol: string) { +// throw new Error(`Could not find runtime for symbol '${symbol}'.`); +// } -function applySymbolStatic(runtime: SymbolRuntime, args: RuntimeArguments) { - return CompileResult.Dynamic(env => runtime(env, args)) -} +// function applySymbolStatic(runtime: SymbolRuntime, args: RuntimeArguments) { +// return CompileResult.Dynamic(env => runtime(env, args)) +// } -function applySymbolDynamic(head: RuntimeExpression, args: RuntimeArguments) { - return CompileResult.Dynamic(env => { - const value = head(env); - const symbol = env.symbolTable[value]; - if (!symbol) noRuntimeFor(value); - return symbol.runtime(env, args); - }) -} +// function applySymbolDynamic(head: RuntimeExpression, args: RuntimeArguments) { +// return CompileResult.Dynamic(env => { +// const value = head(env); +// const symbol = env.runtimeTable[value]; +// if (!symbol) noRuntimeFor(value); +// return symbol.runtime(env, args); +// }) +// } -function apply(env: Environment, head: CompileResult, args: RuntimeArguments, constArgs: boolean): CompileResult { - if (head.isConst) { - const value = head.runtime(env); - const symbol = env.symbolTable[value]; - if (!symbol) throw new Error(`Could not find runtime for symbol '${value}'.`); - if (symbol.attributes.isStatic && constArgs) return CompileResult.Const(symbol.runtime(env, args)); - return applySymbolStatic(symbol.runtime, args); - } - return applySymbolDynamic(head.runtime, args); -} +// function apply(env: Environment, head: CompileResult, args: RuntimeArguments, constArgs: boolean): CompileResult { +// if (head.isConst) { +// const value = head.runtime(env); +// const symbol = env.runtimeTable[value]; +// if (!symbol) throw new Error(`Could not find runtime for symbol '${value}'.`); +// if (symbol.attributes.isStatic && constArgs) return CompileResult.Const(symbol.runtime(env, args)); +// return applySymbolStatic(symbol.runtime, args); +// } +// return applySymbolDynamic(head.runtime, args); +// } -function compile(env: Environment, expression: Expression): CompileResult { - if (Expression.isLiteral(expression)) { - return CompileResult.Const(expression); - } +// function compile(env: Environment, expression: Expression): CompileResult { +// if (Expression.isLiteral(expression)) { +// return CompileResult.Const(expression); +// } - if (Expression.isSymbol(expression)) { - // TOTO: this needs to look up in the symbol table. - return 0 as any; - } +// if (Expression.isSymbol(expression)) { +// // TOTO: this needs to look up in the symbol table. +// return 0 as any; +// } - const head = compile(env, expression.head); - if (!expression.args) { - return apply(env, head, [], true); - } else if (Expression.isArgumentsArray(expression.args)) { - const args = []; - let constArgs = false; - for (const arg of expression.args) { - const compiled = compile(env, arg); - constArgs = constArgs && compiled.isConst; - args.push(compiled.runtime); - } - return apply(env, head, args as any, constArgs); - } else { - const args = Object.create(null); - let constArgs = false; - for (const key of Object.keys(expression.args)) { - const compiled = compile(env, expression.args[key]); - constArgs = constArgs && compiled.isConst; - args[key] = compiled.runtime; - } - return apply(env, head, args, constArgs); - } -} +// const head = compile(env, expression.head); +// if (!expression.args) { +// return apply(env, head, [], true); +// } else if (Expression.isArgumentsArray(expression.args)) { +// const args = []; +// let constArgs = false; +// for (const arg of expression.args) { +// const compiled = compile(env, arg); +// constArgs = constArgs && compiled.isConst; +// args.push(compiled.runtime); +// } +// return apply(env, head, args as any, constArgs); +// } else { +// const args = Object.create(null); +// let constArgs = false; +// for (const key of Object.keys(expression.args)) { +// const compiled = compile(env, expression.args[key]); +// constArgs = constArgs && compiled.isConst; +// args[key] = compiled.runtime; +// } +// return apply(env, head, args, constArgs); +// } +// } -export default Compiler \ No newline at end of file +// export default Compiler \ No newline at end of file diff --git a/src/mol-script/helpers.ts b/src/mol-script/helpers.ts index 09ced0a60..9b384a2f8 100644 --- a/src/mol-script/helpers.ts +++ b/src/mol-script/helpers.ts @@ -5,7 +5,7 @@ */ import Type from './type' -import Symbol, { Arguments, isSymbol } from './symbol' +import { Symbol, Arguments, isSymbol } from './symbol' export function symbol<A extends Arguments, T extends Type<S>, S>(args: A, type: T, description?: string) { return Symbol('', args, type, description); diff --git a/src/mol-script/runtime/environment.ts b/src/mol-script/runtime/environment.ts index d13d5738b..4092a6786 100644 --- a/src/mol-script/runtime/environment.ts +++ b/src/mol-script/runtime/environment.ts @@ -4,13 +4,34 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { SymbolRuntimeTable } from './symbol' +import { Symbol } from '../symbol' +import { SymbolRuntime } from './symbol' import { Macro } from './macro'; +import Expression from '../expression'; -interface Environment<T = any> { - readonly symbolTable: SymbolRuntimeTable, - readonly context: T, - readonly macros: Macro.Table +class Environment { + readonly runtimeTable: SymbolRuntime.Table; + readonly macroTable: Macro.Table = new Map<string, Macro>(); + + addMacro(name: string, expression: Expression, argNames: ReadonlyArray<string>): Macro { + const argIndex: Macro['argIndex'] = {}; + for (let i = 0; i < argNames.length; i++) argIndex[argNames[i]] = i; + const macro: Macro = { expression, argIndex, argNames }; + this.macroTable.set(name, macro); + return macro; + } + + removeMacro(name: string) { + this.macroTable.delete(name); + } + + addSymbolRuntime(symbol: Symbol, runtime: SymbolRuntime) { + this.runtimeTable.set(symbol.id, runtime); + } + + removeSymbolRuntime(symbol: Symbol) { + this.runtimeTable.delete(symbol.id); + } } export default Environment \ No newline at end of file diff --git a/src/mol-script/runtime/expression.ts b/src/mol-script/runtime/expression.ts index 2d8f7d8ad..c6d38827a 100644 --- a/src/mol-script/runtime/expression.ts +++ b/src/mol-script/runtime/expression.ts @@ -6,18 +6,18 @@ import Environment from './environment' -type RuntimeExpression<C = any, T = any> = (env: Environment<C>) => T +type RuntimeExpression<T = any> = (env: Environment) => T export interface ExpressionInfo { isConst?: boolean } namespace RuntimeExpression { - export function constant<C, T>(c: T): RuntimeExpression<C, T> { + export function constant<T>(c: T): RuntimeExpression<T> { return env => c; } - export function func<C, T>(f: (env: Environment<C>) => T): RuntimeExpression<C, T> { + export function func<T>(f: (env: Environment) => T): RuntimeExpression<T> { return env => f(env); } } diff --git a/src/mol-script/runtime/symbol.ts b/src/mol-script/runtime/symbol.ts index 81a3590e1..c0f0451cf 100644 --- a/src/mol-script/runtime/symbol.ts +++ b/src/mol-script/runtime/symbol.ts @@ -6,27 +6,27 @@ import Environment from './environment' import RuntimeExpression from './expression' +import Expression from '../expression'; -export type RuntimeArguments = ArrayLike<RuntimeExpression> | { [name: string]: RuntimeExpression | undefined } - -type SymbolRuntime = (env: Environment, args: RuntimeArguments) => any +type SymbolRuntime = SymbolRuntime.Dynamic | SymbolRuntime.Static namespace SymbolRuntime { - export interface Info { - readonly runtime: SymbolRuntime, + export interface Static { + kind: 'static', + readonly runtime: (env: Environment, args: Arguments) => any, readonly attributes: Attributes } + export interface Dynamic { + kind: 'dynamic', + readonly compile: (env: Environment, args: Expression.Arguments) => RuntimeExpression + } + export interface Attributes { isStatic: boolean } -} -function SymbolRuntime(attributes: Partial<SymbolRuntime.Attributes> = {}) { - const { isStatic = false } = attributes; - return (runtime: SymbolRuntime): SymbolRuntime.Info => { - return ({ runtime, attributes: { isStatic } }); - }; -} + export type Table = Map<string, SymbolRuntime> -export type SymbolRuntimeTable = { readonly [id: string]: SymbolRuntime.Info } + export type Arguments = ArrayLike<RuntimeExpression> | { [name: string]: RuntimeExpression | undefined } +} -export default SymbolRuntime \ No newline at end of file +export { SymbolRuntime } \ No newline at end of file diff --git a/src/mol-script/script/mol-script/symbols.ts b/src/mol-script/script/mol-script/symbols.ts index 66d41365f..9c9cec57b 100644 --- a/src/mol-script/script/mol-script/symbols.ts +++ b/src/mol-script/script/mol-script/symbols.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Symbol, { Arguments, Argument } from '../../symbol' +import { Symbol, Arguments, Argument } from '../../symbol' import B from '../../builder' import * as M from './macro' import MolScript from '../../symbol-table' diff --git a/src/mol-script/symbol-table.ts b/src/mol-script/symbol-table.ts index 7a12afc44..cfdb112a3 100644 --- a/src/mol-script/symbol-table.ts +++ b/src/mol-script/symbol-table.ts @@ -7,7 +7,7 @@ import core from './symbol-table/core' import structureQuery from './symbol-table/structure-query' import { normalizeTable, symbolList } from './helpers' -import Symbol from './symbol' +import { Symbol } from './symbol' const table = { core, structureQuery }; diff --git a/src/mol-script/symbol-table/core.ts b/src/mol-script/symbol-table/core.ts index 6c20d0c00..c0bcac64f 100644 --- a/src/mol-script/symbol-table/core.ts +++ b/src/mol-script/symbol-table/core.ts @@ -5,7 +5,7 @@ */ import Type from '../type' -import Symbol, { Arguments, Argument } from '../symbol' +import { Symbol, Arguments, Argument } from '../symbol' import { symbol, normalizeTable, symbolList } from '../helpers' export namespace Types { diff --git a/src/mol-script/symbol.ts b/src/mol-script/symbol.ts index d79b6764b..d6c2dbe33 100644 --- a/src/mol-script/symbol.ts +++ b/src/mol-script/symbol.ts @@ -50,7 +50,7 @@ export namespace Arguments { export type ExpressionArguments<T> = { [P in keyof T]?: Expression } | { [index: number]: Expression } -interface Symbol<A extends Arguments = Arguments, T extends Type = Type> { +export interface Symbol<A extends Arguments = Arguments, T extends Type = Type> { (args?: ExpressionArguments<A['@type']>): Expression, info: { namespace: string, @@ -62,7 +62,7 @@ interface Symbol<A extends Arguments = Arguments, T extends Type = Type> { id: string, } -function Symbol<A extends Arguments, T extends Type>(name: string, args: A, type: T, description?: string) { +export function Symbol<A extends Arguments, T extends Type>(name: string, args: A, type: T, description?: string) { const symbol: Symbol<A, T> = function(args: ExpressionArguments<A['@type']>) { return Expression.Apply(Expression.Symbol(symbol.id), args as any); } as any; @@ -80,5 +80,3 @@ export function isSymbol(x: any): x is Symbol { export type SymbolMap = { [id: string]: Symbol | undefined } -export default Symbol - -- GitLab