|
|
|
|
@ -19,8 +19,8 @@ export const _rt = {
|
|
|
|
|
max: (a: number) => (b: number) => Math.max(a, b),
|
|
|
|
|
min: (a: number) => (b: number) => Math.min(a, b),
|
|
|
|
|
|
|
|
|
|
eq: (a: any) => (b: any) => ({ _tag: a === b ? 'True' : 'False' }),
|
|
|
|
|
neq: (a: any) => (b: any) => ({ _tag: a !== b ? 'True' : 'False' }),
|
|
|
|
|
eq: (a: any) => (b: any) => ({ _tag: deepEqual(a, b) ? 'True' : 'False' }),
|
|
|
|
|
neq: (a: any) => (b: any) => ({ _tag: deepEqual(a, b) ? 'False' : 'True' }),
|
|
|
|
|
gt: (a: any) => (b: any) => ({ _tag: a > b ? 'True' : 'False' }),
|
|
|
|
|
lt: (a: any) => (b: any) => ({ _tag: a < b ? 'True' : 'False' }),
|
|
|
|
|
gte: (a: any) => (b: any) => ({ _tag: a >= b ? 'True' : 'False' }),
|
|
|
|
|
@ -142,7 +142,6 @@ export const _rt = {
|
|
|
|
|
return printed;
|
|
|
|
|
},
|
|
|
|
|
rebind: (name: string, pathOrValue: any, maybeValue?: any) => {
|
|
|
|
|
console.log("rebind", store, name, pathOrValue, maybeValue);
|
|
|
|
|
if (maybeValue === undefined) {
|
|
|
|
|
store[name] = pathOrValue;
|
|
|
|
|
} else {
|
|
|
|
|
@ -202,13 +201,17 @@ export const _rt = {
|
|
|
|
|
const parser = new Parser(tokens, wrapped);
|
|
|
|
|
const defs = parser.parse();
|
|
|
|
|
const ast = defs[0].body;
|
|
|
|
|
|
|
|
|
|
// validate free vars
|
|
|
|
|
// const free = freeVars(ast);
|
|
|
|
|
// const allowed = new Set([
|
|
|
|
|
// ...Object.keys(store),
|
|
|
|
|
// ...Object.keys(_rt),
|
|
|
|
|
// 'True'
|
|
|
|
|
// ])
|
|
|
|
|
const free = freeVars(ast);
|
|
|
|
|
const allowed = new Set([
|
|
|
|
|
...Object.keys(store),
|
|
|
|
|
...Object.keys(_rt)
|
|
|
|
|
]);
|
|
|
|
|
const unknown = [...free].filter(v => !allowed.has(v));
|
|
|
|
|
if (unknown.length > 0) {
|
|
|
|
|
return { _tag: 'Err', _0: `Unknown: ${unknown.join(', ')}` };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const compiled = compile(defs[0].body);
|
|
|
|
|
const fn = new Function('_rt', 'store', `return ${compiled}`);
|
|
|
|
|
@ -314,3 +317,17 @@ export function syncToAst(name: string) {
|
|
|
|
|
saveDefinitions();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function deepEqual(a: any, b: any): boolean {
|
|
|
|
|
if (a === b) return true;
|
|
|
|
|
if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') return false;
|
|
|
|
|
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
|
|
|
if (Array.isArray(a)) {
|
|
|
|
|
if (a.length !== b.length) return false;
|
|
|
|
|
return a.every((v, i) => deepEqual(v, b[i]));
|
|
|
|
|
}
|
|
|
|
|
const keysA = Object.keys(a);
|
|
|
|
|
const keysB = Object.keys(b);
|
|
|
|
|
if (keysA.length !== keysB.length) return false;
|
|
|
|
|
return keysA.every(k => deepEqual(a[k], b[k]));
|
|
|
|
|
}
|
|
|
|
|
|