From bf6607d3685751493aa3397636873d1aff274b6c Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Sun, 26 Oct 2025 08:53:51 -0700 Subject: [PATCH] put builtin global functions into a higher scope --- src/vm.ts | 13 ++++++------- tests/native.test.ts | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/vm.ts b/src/vm.ts index f451e1e..30ee039 100644 --- a/src/vm.ts +++ b/src/vm.ts @@ -19,19 +19,18 @@ export class VM { labels: Map = new Map() nativeFunctions: Map = new Map() - constructor(bytecode: Bytecode, nativeFunctions?: Record, valueFunctions?: Record) { + constructor(bytecode: Bytecode, globalFunctions?: Record) { this.instructions = bytecode.instructions this.constants = bytecode.constants this.labels = bytecode.labels || new Map() this.scope = new Scope() - if (nativeFunctions) - for (const name of Object.keys(nativeFunctions)) - this.registerFunction(name, nativeFunctions[name]!) + if (globalFunctions) { + for (const name of Object.keys(globalFunctions)) + this.registerFunction(name, globalFunctions[name]!) - if (valueFunctions) - for (const name of Object.keys(valueFunctions)) - this.registerValueFunction(name, valueFunctions[name]!) + this.scope = new Scope(this.scope) + } } async call(name: string, ...args: any) { diff --git a/tests/native.test.ts b/tests/native.test.ts index 159fc15..53a30d2 100644 --- a/tests/native.test.ts +++ b/tests/native.test.ts @@ -1741,3 +1741,23 @@ test("vm.call() with native function - variadic parameters", async () => { const result = await vm.call('sum', 1, 2, 3, 4, 5) expect(result).toEqual({ type: 'number', value: 15 }) }) + +test("builtin global functions are placed into a higher level scope", async () => { + const bytecode = toBytecode(` + PUSH 1 + STORE x + HALT + `) + + const vm = new VM(bytecode, { + sum: (...nums: number[]) => nums.reduce((acc, n) => acc + n, 0), + greet: (name: string, greeting = 'Hello') => `${greeting}, ${name}!` + }) + await vm.run() + + const locals = Array.from(vm.scope.locals.entries()).map(([name,]) => name) + const globals = Array.from(vm.scope.parent!.locals.entries()).map(([name,]) => name) + + expect(globals).toEqual(['sum', 'greet']) + expect(locals).toEqual(['x']) +}) \ No newline at end of file