adding deepEqual. validating vars in eval

This commit is contained in:
Dustin Swan 2026-02-11 22:38:08 -07:00
parent c294d7fd6a
commit e12809efba
No known key found for this signature in database
GPG key ID: 30D46587E2100467
4 changed files with 41 additions and 21 deletions

View file

@ -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]));
}