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 @@
*/
import Expression from './expression'
import Symbol from './symbol'
import { Symbol } from './symbol'
import SymbolTable from './symbol-table'
namespace Builder {
......
/**
* 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
......@@ -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);
......
......@@ -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
......@@ -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);
}
}
......
......@@ -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
......@@ -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'
......
......@@ -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 };
......
......@@ -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 {
......
......@@ -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
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