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

Macro

parent 2aa188d3
No related branches found
No related tags found
No related merge requests found
......@@ -11,18 +11,18 @@ type Expression =
namespace Expression {
export type Literal = string | number | boolean
export type Symbol = { kind: 'symbol', name: string }
export type Symbol = { name: string }
export type Arguments = Expression[] | { [name: string]: Expression }
export interface Apply { readonly head: Expression, readonly args?: Arguments }
export function Symbol(name: string): Symbol { return { kind: 'symbol', name }; }
export function Symbol(name: string): Symbol { return { name }; }
export function Apply(head: Expression, args?: Arguments): Apply { return args ? { head, args } : { head }; }
export function isArgumentsArray(e: Arguments): e is Expression[] { return e instanceof Array; }
export function isArgumentsMap(e: Arguments): e is { [name: string]: Expression } { return !(e instanceof Array); }
export function isArgumentsArray(e?: Arguments): e is Expression[] { return !!e && Array.isArray(e); }
export function isArgumentsMap(e?: Arguments): e is { [name: string]: Expression } { return !!e && !Array.isArray(e); }
export function isLiteral(e: Expression): e is Expression.Literal { return !isApply(e); }
export function isApply(e: Expression): e is Expression.Apply { return !!e && !!(e as Expression.Apply).head && typeof e === 'object'; }
export function isSymbol(e: Expression): e is Expression.Symbol { return !!e && (e as any).kind === 'symbol' }
export function isSymbol(e: Expression): e is Expression.Symbol { return !!e && typeof (e as any).name === 'string' }
}
export default Expression
\ 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 { SymbolRuntimeTable } from './symbol'
import { Macro } from './macro';
interface Environment<T = any> {
readonly symbolTable: SymbolRuntimeTable,
readonly context: T
readonly context: T,
readonly macros: Macro.Table
}
export default Environment
\ 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>
......
/**
* 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';
interface Macro {
readonly argNames: ReadonlyArray<string>,
readonly argIndex: { [name: string]: number },
readonly expression: Expression
}
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];
if (table.has(expr.name)) {
const macro = table.get(expr.name)!;
if (macro.argNames.length === 0) return macro.expression;
}
return 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;
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 (!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;
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 { Macro }
\ 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>
......@@ -20,7 +20,7 @@ namespace SymbolRuntime {
export interface Attributes { isStatic: boolean }
}
function SymbolRuntime(symbol: Symbol, attributes: Partial<SymbolRuntime.Attributes> = {}) {
function SymbolRuntime(attributes: Partial<SymbolRuntime.Attributes> = {}) {
const { isStatic = false } = attributes;
return (runtime: SymbolRuntime): SymbolRuntime.Info => {
return ({ runtime, attributes: { isStatic } });
......
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