Skip to content
Snippets Groups Projects
Commit e323bc84 authored by David Sehnal's avatar David Sehnal
Browse files

Working on mol-script

parent d1fe97f7
No related branches found
No related tags found
No related merge requests found
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
import Expression from './expression' import Expression from './expression'
import Symbol from './symbol' import { Symbol } from './symbol'
import SymbolTable from './symbol-table' import SymbolTable from './symbol-table'
namespace Builder { namespace Builder {
......
/** // /**
* Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info. // * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
* // *
* @author David Sehnal <david.sehnal@gmail.com> // * @author David Sehnal <david.sehnal@gmail.com>
*/ // */
import Expression from './expression' // import Expression from './expression'
import Environment from './runtime/environment' // import Environment from './runtime/environment'
import RuntimeExpression from './runtime/expression' // import RuntimeExpression from './runtime/expression'
import SymbolRuntime, { RuntimeArguments } from './runtime/symbol' // 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> // type Compiler = <T>(expression: Expression) => CompiledExpression<T>
function Compiler<C>(envProvider: (ctx?: C) => Environment): Compiler<C> { // function Compiler<C>(env: Environment): Compiler {
const env = envProvider(void 0); // return expression => compile(env, expression).runtime;
return expression => wrap(envProvider, compile(env, expression).runtime); // }
}
type CompileResult = { isConst: boolean, runtime: RuntimeExpression } // type CompileResult = { isConst: boolean, runtime: RuntimeExpression }
namespace CompileResult { // namespace CompileResult {
export function Const(value: any): CompileResult { return { isConst: true, runtime: RuntimeExpression.constant(value) } } // export function Const(value: any): CompileResult { return { isConst: true, runtime: RuntimeExpression.constant(value) } }
export function Dynamic(runtime: RuntimeExpression): CompileResult { return { isConst: false, runtime } } // export function Dynamic(runtime: RuntimeExpression): CompileResult { return { isConst: false, runtime } }
} // }
function wrap<C, T>(envProvider: (ctx?: C) => Environment, runtime: RuntimeExpression<C, T>) { // function wrap<T>(envProvider: (ctx?: C) => Environment, runtime: RuntimeExpression<T>) {
return (ctx: C) => runtime(envProvider(ctx)); // return (ctx: C) => runtime(envProvider(ctx));
} // }
function noRuntimeFor(symbol: string) { // function noRuntimeFor(symbol: string) {
throw new Error(`Could not find runtime for symbol '${symbol}'.`); // throw new Error(`Could not find runtime for symbol '${symbol}'.`);
} // }
function applySymbolStatic(runtime: SymbolRuntime, args: RuntimeArguments) { // function applySymbolStatic(runtime: SymbolRuntime, args: RuntimeArguments) {
return CompileResult.Dynamic(env => runtime(env, args)) // return CompileResult.Dynamic(env => runtime(env, args))
} // }
function applySymbolDynamic(head: RuntimeExpression, args: RuntimeArguments) { // function applySymbolDynamic(head: RuntimeExpression, args: RuntimeArguments) {
return CompileResult.Dynamic(env => { // return CompileResult.Dynamic(env => {
const value = head(env); // const value = head(env);
const symbol = env.symbolTable[value]; // const symbol = env.runtimeTable[value];
if (!symbol) noRuntimeFor(value); // if (!symbol) noRuntimeFor(value);
return symbol.runtime(env, args); // return symbol.runtime(env, args);
}) // })
} // }
function apply(env: Environment, head: CompileResult, args: RuntimeArguments, constArgs: boolean): CompileResult { // function apply(env: Environment, head: CompileResult, args: RuntimeArguments, constArgs: boolean): CompileResult {
if (head.isConst) { // if (head.isConst) {
const value = head.runtime(env); // const value = head.runtime(env);
const symbol = env.symbolTable[value]; // const symbol = env.runtimeTable[value];
if (!symbol) throw new Error(`Could not find runtime for symbol '${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)); // if (symbol.attributes.isStatic && constArgs) return CompileResult.Const(symbol.runtime(env, args));
return applySymbolStatic(symbol.runtime, args); // return applySymbolStatic(symbol.runtime, args);
} // }
return applySymbolDynamic(head.runtime, args); // return applySymbolDynamic(head.runtime, args);
} // }
function compile(env: Environment, expression: Expression): CompileResult { // function compile(env: Environment, expression: Expression): CompileResult {
if (Expression.isLiteral(expression)) { // if (Expression.isLiteral(expression)) {
return CompileResult.Const(expression); // return CompileResult.Const(expression);
} // }
if (Expression.isSymbol(expression)) { // if (Expression.isSymbol(expression)) {
// TOTO: this needs to look up in the symbol table. // // TOTO: this needs to look up in the symbol table.
return 0 as any; // return 0 as any;
} // }
const head = compile(env, expression.head); // const head = compile(env, expression.head);
if (!expression.args) { // if (!expression.args) {
return apply(env, head, [], true); // return apply(env, head, [], true);
} else if (Expression.isArgumentsArray(expression.args)) { // } else if (Expression.isArgumentsArray(expression.args)) {
const args = []; // const args = [];
let constArgs = false; // let constArgs = false;
for (const arg of expression.args) { // for (const arg of expression.args) {
const compiled = compile(env, arg); // const compiled = compile(env, arg);
constArgs = constArgs && compiled.isConst; // constArgs = constArgs && compiled.isConst;
args.push(compiled.runtime); // args.push(compiled.runtime);
} // }
return apply(env, head, args as any, constArgs); // return apply(env, head, args as any, constArgs);
} else { // } else {
const args = Object.create(null); // const args = Object.create(null);
let constArgs = false; // let constArgs = false;
for (const key of Object.keys(expression.args)) { // for (const key of Object.keys(expression.args)) {
const compiled = compile(env, expression.args[key]); // const compiled = compile(env, expression.args[key]);
constArgs = constArgs && compiled.isConst; // constArgs = constArgs && compiled.isConst;
args[key] = compiled.runtime; // args[key] = compiled.runtime;
} // }
return apply(env, head, args, constArgs); // return apply(env, head, args, constArgs);
} // }
} // }
export default Compiler // export default Compiler
\ No newline at end of file \ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
import Type from './type' 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) { export function symbol<A extends Arguments, T extends Type<S>, S>(args: A, type: T, description?: string) {
return Symbol('', args, type, description); return Symbol('', args, type, description);
......
...@@ -4,13 +4,34 @@ ...@@ -4,13 +4,34 @@
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
*/ */
import { SymbolRuntimeTable } from './symbol' import { Symbol } from '../symbol'
import { SymbolRuntime } from './symbol'
import { Macro } from './macro'; import { Macro } from './macro';
import Expression from '../expression';
interface Environment<T = any> { class Environment {
readonly symbolTable: SymbolRuntimeTable, readonly runtimeTable: SymbolRuntime.Table;
readonly context: T, readonly macroTable: Macro.Table = new Map<string, Macro>();
readonly macros: Macro.Table
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 export default Environment
\ No newline at end of file
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
import Environment from './environment' import Environment from './environment'
type RuntimeExpression<C = any, T = any> = (env: Environment<C>) => T type RuntimeExpression<T = any> = (env: Environment) => T
export interface ExpressionInfo { export interface ExpressionInfo {
isConst?: boolean isConst?: boolean
} }
namespace RuntimeExpression { namespace RuntimeExpression {
export function constant<C, T>(c: T): RuntimeExpression<C, T> { export function constant<T>(c: T): RuntimeExpression<T> {
return env => c; 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); return env => f(env);
} }
} }
......
...@@ -6,27 +6,27 @@ ...@@ -6,27 +6,27 @@
import Environment from './environment' import Environment from './environment'
import RuntimeExpression from './expression' import RuntimeExpression from './expression'
import Expression from '../expression';
export type RuntimeArguments = ArrayLike<RuntimeExpression> | { [name: string]: RuntimeExpression | undefined } type SymbolRuntime = SymbolRuntime.Dynamic | SymbolRuntime.Static
type SymbolRuntime = (env: Environment, args: RuntimeArguments) => any
namespace SymbolRuntime { namespace SymbolRuntime {
export interface Info { export interface Static {
readonly runtime: SymbolRuntime, kind: 'static',
readonly runtime: (env: Environment, args: Arguments) => any,
readonly attributes: Attributes readonly attributes: Attributes
} }
export interface Dynamic {
kind: 'dynamic',
readonly compile: (env: Environment, args: Expression.Arguments) => RuntimeExpression
}
export interface Attributes { isStatic: boolean } export interface Attributes { isStatic: boolean }
}
function SymbolRuntime(attributes: Partial<SymbolRuntime.Attributes> = {}) { export type Table = Map<string, SymbolRuntime>
const { isStatic = false } = attributes;
return (runtime: SymbolRuntime): SymbolRuntime.Info => {
return ({ runtime, attributes: { isStatic } });
};
}
export type SymbolRuntimeTable = { readonly [id: string]: SymbolRuntime.Info } export type Arguments = ArrayLike<RuntimeExpression> | { [name: string]: RuntimeExpression | undefined }
}
export default SymbolRuntime export { SymbolRuntime }
\ No newline at end of file \ No newline at end of file
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
*/ */
import Symbol, { Arguments, Argument } from '../../symbol' import { Symbol, Arguments, Argument } from '../../symbol'
import B from '../../builder' import B from '../../builder'
import * as M from './macro' import * as M from './macro'
import MolScript from '../../symbol-table' import MolScript from '../../symbol-table'
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import core from './symbol-table/core' import core from './symbol-table/core'
import structureQuery from './symbol-table/structure-query' import structureQuery from './symbol-table/structure-query'
import { normalizeTable, symbolList } from './helpers' import { normalizeTable, symbolList } from './helpers'
import Symbol from './symbol' import { Symbol } from './symbol'
const table = { core, structureQuery }; const table = { core, structureQuery };
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
import Type from '../type' import Type from '../type'
import Symbol, { Arguments, Argument } from '../symbol' import { Symbol, Arguments, Argument } from '../symbol'
import { symbol, normalizeTable, symbolList } from '../helpers' import { symbol, normalizeTable, symbolList } from '../helpers'
export namespace Types { export namespace Types {
......
...@@ -50,7 +50,7 @@ export namespace Arguments { ...@@ -50,7 +50,7 @@ export namespace Arguments {
export type ExpressionArguments<T> = { [P in keyof T]?: Expression } | { [index: number]: Expression } 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, (args?: ExpressionArguments<A['@type']>): Expression,
info: { info: {
namespace: string, namespace: string,
...@@ -62,7 +62,7 @@ interface Symbol<A extends Arguments = Arguments, T extends Type = Type> { ...@@ -62,7 +62,7 @@ interface Symbol<A extends Arguments = Arguments, T extends Type = Type> {
id: string, 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']>) { const symbol: Symbol<A, T> = function(args: ExpressionArguments<A['@type']>) {
return Expression.Apply(Expression.Symbol(symbol.id), args as any); return Expression.Apply(Expression.Symbol(symbol.id), args as any);
} as any; } as any;
...@@ -80,5 +80,3 @@ export function isSymbol(x: any): x is Symbol { ...@@ -80,5 +80,3 @@ export function isSymbol(x: any): x is Symbol {
export type SymbolMap = { [id: string]: Symbol | undefined } export type SymbolMap = { [id: string]: Symbol | undefined }
export default Symbol
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment