diff --git a/CLAUDE.md b/CLAUDE.md index 31440d8..0098761 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -137,37 +137,55 @@ Array format features: - Function params as string arrays: `["MAKE_FUNCTION", ["x", "y=10"], ".body"]` - See `tests/programmatic.test.ts` and `examples/programmatic.ts` for examples -### Native Function Registration +### Native Function Registration and Global Values **Option 1**: Pass to `run()` or `VM` constructor (convenience) ```typescript const result = await run(bytecode, { add: (a: number, b: number) => a + b, - greet: (name: string) => `Hello, ${name}!` + greet: (name: string) => `Hello, ${name}!`, + pi: 3.14159, + config: { debug: true, port: 8080 } }) // Or with VM constructor -const vm = new VM(bytecode, { add, greet }) +const vm = new VM(bytecode, { add, greet, pi, config }) ``` -**Option 2**: Register with `vm.registerFunction()` (manual) +**Option 2**: Set values with `vm.set()` (manual) ```typescript const vm = new VM(bytecode) -vm.registerFunction('add', (a: number, b: number) => a + b) + +// Set functions (auto-wrapped to native functions) +vm.set('add', (a: number, b: number) => a + b) + +// Set any other values (auto-converted to ReefVM Values) +vm.set('pi', 3.14159) +vm.set('config', { debug: true, port: 8080 }) + await vm.run() ``` -**Option 3**: Register Value-based functions (for direct Value access) +**Option 3**: Set Value-based functions with `vm.setValueFunction()` (advanced) + +For functions that work directly with ReefVM Value types: + ```typescript -vm.registerValueFunction('customOp', (a: Value, b: Value): Value => { +const vm = new VM(bytecode) + +// Set Value-based function (no wrapping, works directly with Values) +vm.setValueFunction('customOp', (a: Value, b: Value): Value => { return toValue(toNumber(a) + toNumber(b)) }) + +await vm.run() ``` Auto-wrapping handles: -- Value ↔ native type conversion (`fromValue`/`toValue`) +- Functions: wrapped as native functions with Value ↔ native type conversion - Sync and async functions - Arrays, objects, primitives, null, RegExp +- All values converted via `toValue()` ### Calling Functions from TypeScript diff --git a/GUIDE.md b/GUIDE.md index 99b8073..a8e5683 100644 --- a/GUIDE.md +++ b/GUIDE.md @@ -662,18 +662,18 @@ const vm = new VM(bytecode, { add, greet }) **Method 2**: Register after construction ```typescript const vm = new VM(bytecode) -vm.registerFunction('add', (a: number, b: number) => a + b) +vm.set('add', (a: number, b: number) => a + b) await vm.run() ``` **Method 3**: Value-based functions (for full control) ```typescript -vm.registerValueFunction('customOp', (a: Value, b: Value): Value => { +vm.setValueFunction('customOp', (a: Value, b: Value): Value => { return { type: 'number', value: toNumber(a) + toNumber(b) } }) ``` -**Auto-wrapping**: `registerFunction` automatically converts between native TypeScript types and ReefVM Value types. Both sync and async functions work. +**Auto-wrapping**: `vm.set()` automatically converts between native TypeScript types and ReefVM Value types. Both sync and async functions work. **Usage in bytecode**: ``` @@ -702,12 +702,12 @@ CALL ; → "Hi, Alice!" ```typescript // Basic @named - collects all named args -vm.registerFunction('greet', (atNamed: any = {}) => { +vm.set('greet', (atNamed: any = {}) => { return `Hello, ${atNamed.name || 'World'}!` }) // Mixed positional and @named -vm.registerFunction('configure', (name: string, atOptions: any = {}) => { +vm.set('configure', (name: string, atOptions: any = {}) => { return { name, debug: atOptions.debug || false, diff --git a/SPEC.md b/SPEC.md index acc01d1..1aa2118 100644 --- a/SPEC.md +++ b/SPEC.md @@ -622,7 +622,7 @@ const vm = new VM(bytecode, { }) // Or after construction: -vm.registerFunction('multiply', (a: number, b: number) => a * b) +vm.set('multiply', (a: number, b: number) => a * b) ``` **Usage in Bytecode**: @@ -637,9 +637,9 @@ CALL ; Call it like any other function **Native Function Types**: -1. **Auto-wrapped functions** (via `registerFunction`): Accept and return native TypeScript types (number, string, boolean, array, object, etc.). The VM automatically converts between Value types and native types. +1. **Auto-wrapped functions** (via `vm.set()`): Accept and return native TypeScript types (number, string, boolean, array, object, etc.). The VM automatically converts between Value types and native types. -2. **Value-based functions** (via `registerValueFunction`): Accept and return `Value` types directly for full control over type handling. +2. **Value-based functions** (via `vm.setValueFunction()`): Accept and return `Value` types directly for full control over type handling. **Auto-Wrapping Behavior**: - Parameters: `Value` → native type (number, string, boolean, array, object, null, RegExp) @@ -655,27 +655,27 @@ CALL ; Call it like any other function **Examples**: ```typescript // Auto-wrapped native types -vm.registerFunction('add', (a: number, b: number) => a + b) -vm.registerFunction('greet', (name: string) => `Hello, ${name}!`) -vm.registerFunction('range', (n: number) => Array.from({ length: n }, (_, i) => i)) +vm.set('add', (a: number, b: number) => a + b) +vm.set('greet', (name: string) => `Hello, ${name}!`) +vm.set('range', (n: number) => Array.from({ length: n }, (_, i) => i)) // With defaults -vm.registerFunction('greet', (name: string, greeting = 'Hello') => { +vm.set('greet', (name: string, greeting = 'Hello') => { return `${greeting}, ${name}!` }) // Variadic functions -vm.registerFunction('sum', (...nums: number[]) => { +vm.set('sum', (...nums: number[]) => { return nums.reduce((acc, n) => acc + n, 0) }) // Value-based for custom logic -vm.registerValueFunction('customOp', (a: Value, b: Value): Value => { +vm.setValueFunction('customOp', (a: Value, b: Value): Value => { return { type: 'number', value: toNumber(a) + toNumber(b) } }) // Async functions -vm.registerFunction('fetchData', async (url: string) => { +vm.set('fetchData', async (url: string) => { const response = await fetch(url) return response.json() }) @@ -912,10 +912,10 @@ const vm = new VM(bytecode, { }) // Or register after construction -vm.registerFunction('multiply', (a: number, b: number) => a * b) +vm.set('multiply', (a: number, b: number) => a * b) // Or use Value-based functions -vm.registerValueFunction('customOp', (a: Value, b: Value): Value => { +vm.setValueFunction('customOp', (a: Value, b: Value): Value => { return { type: 'number', value: toNumber(a) + toNumber(b) } }) diff --git a/examples/native.ts b/examples/native.ts index 70d3e0d..f1c9b5b 100644 --- a/examples/native.ts +++ b/examples/native.ts @@ -9,7 +9,7 @@ const bytecode = toBytecode(` const vm = new VM(bytecode) -vm.registerFunction('print', (...args: Value[]): Value => { +vm.set('print', (...args: Value[]): Value => { console.log(...args.map(toString)) return toNull() }) diff --git a/src/index.ts b/src/index.ts index ce72660..40b5dfd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,9 @@ import type { Bytecode } from "./bytecode" -import type { Value, TypeScriptFunction } from "./value" +import type { Value } from "./value" import { VM } from "./vm" -export async function run(bytecode: Bytecode, functions?: Record): Promise { - const vm = new VM(bytecode, functions) +export async function run(bytecode: Bytecode, globals?: Record): Promise { + const vm = new VM(bytecode, globals) return await vm.run() } diff --git a/src/vm.ts b/src/vm.ts index 7b8cd24..5d8b9d0 100644 --- a/src/vm.ts +++ b/src/vm.ts @@ -19,15 +19,15 @@ export class VM { labels: Map = new Map() nativeFunctions: Map = new Map() - constructor(bytecode: Bytecode, globalFunctions?: Record) { + constructor(bytecode: Bytecode, globals?: Record) { this.instructions = bytecode.instructions this.constants = bytecode.constants this.labels = bytecode.labels || new Map() this.scope = new Scope() - if (globalFunctions) { - for (const name of Object.keys(globalFunctions)) - this.registerFunction(name, globalFunctions[name]!) + if (globals) { + for (const name of Object.keys(globals ?? {})) + this.set(name, globals[name]) this.scope = new Scope(this.scope) } @@ -48,12 +48,18 @@ export class VM { } } - registerFunction(name: string, fn: TypeScriptFunction) { - const wrapped = isWrapped(fn) ? fn as NativeFunction : wrapNative(this, fn) - this.scope.set(name, { type: 'native', fn: wrapped, value: '' }) + set(name: string, value: any) { + if (typeof value === 'function') + this.setFunction(name, value) + else + this.scope.set(name, toValue(value)) } - registerValueFunction(name: string, fn: NativeFunction) { + setFunction(name: string, fn: TypeScriptFunction) { + this.scope.set(name, { type: 'native', fn: wrapNative(this, fn), value: '' }) + } + + setValueFunction(name: string, fn: NativeFunction) { this.scope.set(name, { type: 'native', fn, value: '' }) } diff --git a/tests/functions-parameter.test.ts b/tests/functions-parameter.test.ts index 05077dd..bde5575 100644 --- a/tests/functions-parameter.test.ts +++ b/tests/functions-parameter.test.ts @@ -104,7 +104,7 @@ describe("functions parameter", () => { expect(result).toEqual({ type: 'number', value: 200 }) }) - test("can combine with manual registerFunction", async () => { + test("can combine with manual vm.set", async () => { const bytecode = toBytecode(` LOAD add PUSH 5 @@ -127,7 +127,7 @@ describe("functions parameter", () => { }) // Register another function manually - vm.registerFunction('subtract', (a: number, b: number) => a - b) + vm.set('subtract', (a: number, b: number) => a - b) const result = await vm.run() expect(result).toEqual({ type: 'number', value: 6 }) @@ -224,7 +224,7 @@ describe("functions parameter", () => { }) // Override with manual registration - vm.registerFunction('getValue', () => 200) + vm.set('getValue', () => 200) const result = await vm.run() expect(result).toEqual({ type: 'number', value: 200 }) diff --git a/tests/native.test.ts b/tests/native.test.ts index 6fb4550..67a8d0f 100644 --- a/tests/native.test.ts +++ b/tests/native.test.ts @@ -16,7 +16,7 @@ test("LOAD - basic function call", async () => { const vm = new VM(bytecode) // Register a Value-based function - vm.registerValueFunction('add', (a, b) => { + vm.setValueFunction('add', (a, b) => { return toValue(toNumber(a) + toNumber(b)) }) @@ -36,7 +36,7 @@ test("LOAD - function with string manipulation", async () => { const vm = new VM(bytecode) - vm.registerValueFunction('concat', (a, b) => { + vm.setValueFunction('concat', (a, b) => { const aStr = a.type === 'string' ? a.value : toString(a) const bStr = b.type === 'string' ? b.value : toString(b) return toValue(aStr + ' ' + bStr) @@ -57,7 +57,7 @@ test("LOAD - async function", async () => { const vm = new VM(bytecode) - vm.registerValueFunction('asyncDouble', async (a) => { + vm.setValueFunction('asyncDouble', async (a) => { // Simulate async operation await new Promise(resolve => setTimeout(resolve, 1)) return toValue(toNumber(a) * 2) @@ -77,7 +77,7 @@ test("LOAD - function with no arguments", async () => { const vm = new VM(bytecode) - vm.registerValueFunction('getAnswer', () => { + vm.setValueFunction('getAnswer', () => { return toValue(42) }) @@ -98,7 +98,7 @@ test("LOAD - function with multiple arguments", async () => { const vm = new VM(bytecode) - vm.registerValueFunction('sum', (...args) => { + vm.setValueFunction('sum', (...args) => { const total = args.reduce((acc, val) => acc + toNumber(val), 0) return toValue(total) }) @@ -118,7 +118,7 @@ test("LOAD - function returns array", async () => { const vm = new VM(bytecode) - vm.registerValueFunction('makeRange', (n) => { + vm.setValueFunction('makeRange', (n) => { const count = toNumber(n) const arr = [] for (let i = 0; i < count; i++) { @@ -165,7 +165,7 @@ test("LOAD - using result in subsequent operations", async () => { const vm = new VM(bytecode) - vm.registerValueFunction('triple', (n) => { + vm.setValueFunction('triple', (n) => { return toValue(toNumber(n) * 3) }) @@ -186,7 +186,7 @@ test("Native function wrapping - basic sync function with native types", async ( const vm = new VM(bytecode) // Register with native TypeScript types - auto-wraps! - vm.registerFunction('add', (a: number, b: number) => { + vm.set('add', (a: number, b: number) => { return a + b }) @@ -206,7 +206,7 @@ test("Native function wrapping - async function with native types", async () => const vm = new VM(bytecode) // Async native function - vm.registerFunction('asyncDouble', async (n: number) => { + vm.set('asyncDouble', async (n: number) => { await new Promise(resolve => setTimeout(resolve, 1)) return n * 2 }) @@ -228,7 +228,7 @@ test("Native function wrapping - string manipulation", async () => { const vm = new VM(bytecode) // Native string function - vm.registerFunction('concat', (a: string, b: string) => { + vm.set('concat', (a: string, b: string) => { return a + ' ' + b }) @@ -248,7 +248,7 @@ test("Native function wrapping - with default parameters", async () => { const vm = new VM(bytecode) // Function with default parameter (like NOSE commands) - vm.registerFunction('ls', (path: string, link = false) => { + vm.set('ls', (path: string, link = false) => { return link ? `listing ${path} with links` : `listing ${path}` }) @@ -268,7 +268,7 @@ test("Native function wrapping - returns array", async () => { const vm = new VM(bytecode) // Return native array - auto-converts to Value array - vm.registerFunction('makeRange', (n: number) => { + vm.set('makeRange', (n: number) => { return Array.from({ length: n }, (_, i) => i) }) @@ -297,7 +297,7 @@ test("Native function wrapping - returns object (becomes dict)", async () => { const vm = new VM(bytecode) // Return plain object - auto-converts to dict - vm.registerFunction('makeUser', (name: string, age: number) => { + vm.set('makeUser', (name: string, age: number) => { return { name, age } }) @@ -326,11 +326,11 @@ test("Native function wrapping - mixed with manual Value functions", async () => const vm = new VM(bytecode) - // Native function (auto-wrapped by registerFunction) - vm.registerFunction('nativeAdd', (n: number) => n + 10) + // Native function (auto-wrapped by set) + vm.set('nativeAdd', (n: number) => n + 10) - // Manual Value function (use registerValueFunction) - vm.registerValueFunction('manualDouble', (v) => { + // Manual Value function (use setValueFunction) + vm.setValueFunction('manualDouble', (v) => { return toValue(toNumber(v) * 2) }) @@ -349,7 +349,7 @@ test("Named arguments - basic named arg", async () => { `) const vm = new VM(bytecode) - vm.registerFunction('greet', (name: string) => `Hello, ${name}!`) + vm.set('greet', (name: string) => `Hello, ${name}!`) const result = await vm.run() expect(result).toEqual({ type: 'string', value: 'Hello, Alice!' }) @@ -367,7 +367,7 @@ test("Named arguments - mixed positional and named", async () => { `) const vm = new VM(bytecode) - vm.registerFunction('makeUser', (name: string, age: number) => { + vm.set('makeUser', (name: string, age: number) => { return { name, age } }) @@ -393,7 +393,7 @@ test("Named arguments - named takes priority over positional", async () => { `) const vm = new VM(bytecode) - vm.registerFunction('add', (a: number, b: number) => a + b) + vm.set('add', (a: number, b: number) => a + b) const result = await vm.run() // Named args should be: a=5, b=10 @@ -412,7 +412,7 @@ test("Named arguments - with defaults", async () => { `) const vm = new VM(bytecode) - vm.registerFunction('greet', (name: string, greeting = 'Hello') => { + vm.set('greet', (name: string, greeting = 'Hello') => { return `${greeting}, ${name}!` }) @@ -433,7 +433,7 @@ test("Named arguments - override defaults with named args", async () => { `) const vm = new VM(bytecode) - vm.registerFunction('greet', (name: string, greeting = 'Hello') => { + vm.set('greet', (name: string, greeting = 'Hello') => { return `${greeting}, ${name}!` }) @@ -455,7 +455,7 @@ test("Named arguments - with variadic function", async () => { `) const vm = new VM(bytecode) - vm.registerFunction('sum', (multiplier: number, ...nums: number[]) => { + vm.set('sum', (multiplier: number, ...nums: number[]) => { const total = nums.reduce((acc, n) => acc + n, 0) return total * multiplier }) @@ -466,7 +466,7 @@ test("Named arguments - with variadic function", async () => { test("Named arguments - works with both wrapped and non-wrapped functions", async () => { const bytecode = toBytecode(` - ; Test wrapped function (registerFunction) + ; Test wrapped function (vm.set) LOAD wrappedAdd PUSH "a" PUSH 5 @@ -477,7 +477,7 @@ test("Named arguments - works with both wrapped and non-wrapped functions", asyn CALL STORE result1 - ; Test non-wrapped function (registerValueFunction) + ; Test non-wrapped function (vm.setValueFunction) LOAD valueAdd PUSH "a" PUSH 3 @@ -497,10 +497,10 @@ test("Named arguments - works with both wrapped and non-wrapped functions", asyn const vm = new VM(bytecode) // Wrapped function - auto-converts types - vm.registerFunction('wrappedAdd', (a: number, b: number) => a + b) + vm.set('wrappedAdd', (a: number, b: number) => a + b) // Non-wrapped function - works directly with Values - vm.registerValueFunction('valueAdd', (a, b) => { + vm.setValueFunction('valueAdd', (a, b) => { return toValue(toNumber(a) + toNumber(b)) }) @@ -523,7 +523,7 @@ test("@named pattern - basic atNamed parameter", async () => { `) const vm = new VM(bytecode) - vm.registerFunction('greet', (atNamed: any = {}) => { + vm.set('greet', (atNamed: any = {}) => { const name = atNamed.name || 'Unknown' const greeting = atNamed.greeting || 'Hello' const extra = atNamed.extra || '' @@ -548,7 +548,7 @@ test('@named pattern - atNamed parameters with varadic args', async () => { `) const vm = new VM(bytecode) - vm.registerFunction('cmd', (atNamed: any = {}, ...rest: string[]) => { + vm.set('cmd', (atNamed: any = {}, ...rest: string[]) => { return { rest, namedArg: atNamed['named'] } }) @@ -573,7 +573,7 @@ test("@named pattern - mixed positional and atOptions", async () => { `) const vm = new VM(bytecode) - vm.registerFunction('configure', (name: string, atOptions: any = {}) => { + vm.set('configure', (name: string, atOptions: any = {}) => { return { name, debug: atOptions.debug || false, @@ -600,7 +600,7 @@ test("@named pattern - with default empty object", async () => { `) const vm = new VM(bytecode) - vm.registerFunction('build', (name: string, atConfig: any = {}) => { + vm.set('build', (name: string, atConfig: any = {}) => { return `Building ${name} with ${Object.keys(atConfig).length} options` }) @@ -625,7 +625,7 @@ test("@named pattern - collects only unmatched named args", async () => { `) const vm = new VM(bytecode) - vm.registerFunction('process', (file: string, mode: string, atOptions: any = {}) => { + vm.set('process', (file: string, mode: string, atOptions: any = {}) => { // file and mode are matched, extra1 and extra2 go to atOptions return { file, @@ -675,7 +675,7 @@ test("Native function receives Reef function as callback - basic map", async () const vm = new VM(bytecode) // Native function that takes an array and a callback - vm.registerFunction('map', async (array: any[], callback: Function) => { + vm.set('map', async (array: any[], callback: Function) => { const results = [] for (const item of array) { results.push(await callback(item)) @@ -732,7 +732,7 @@ test("Native function receives Reef function - iterator pattern with each", asyn const vm = new VM(bytecode) // Native 'each' function (like Ruby's each) - vm.registerFunction('each', async (array: any[], callback: Function) => { + vm.set('each', async (array: any[], callback: Function) => { for (const item of array) { await callback(item) } @@ -773,7 +773,7 @@ test("Native function receives Reef function - filter pattern", async () => { const vm = new VM(bytecode) // Native filter function - vm.registerFunction('filter', async (array: any[], predicate: Function) => { + vm.set('filter', async (array: any[], predicate: Function) => { const results = [] for (const item of array) { if (await predicate(item)) { @@ -824,7 +824,7 @@ test("Native function receives Reef function - closure capturing", async () => { const vm = new VM(bytecode) - vm.registerFunction('map', async (array: any[], callback: Function) => { + vm.set('map', async (array: any[], callback: Function) => { const results = [] for (const item of array) { results.push(await callback(item)) @@ -873,7 +873,7 @@ test("Native function receives Reef function - multiple arguments", async () => const vm = new VM(bytecode) // Native reduce function (accumulator, array, callback) - vm.registerFunction('reduce', async (array: any[], initial: any, callback: Function) => { + vm.set('reduce', async (array: any[], initial: any, callback: Function) => { let acc = initial for (const item of array) { acc = await callback(acc, item) @@ -913,7 +913,7 @@ test("Native function receives Reef function - returns non-primitive", async () const vm = new VM(bytecode) - vm.registerFunction('map', async (array: any[], callback: Function) => { + vm.set('map', async (array: any[], callback: Function) => { const results = [] for (const item of array) { results.push(await callback(item)) @@ -965,7 +965,7 @@ test("Native function calls Reef function - basic", async () => { const vm = new VM(bytecode) - vm.registerFunction('process', async function (n: number) { + vm.setFunction('process', async function (n: number) { return await this.call('double', n) }) @@ -1006,7 +1006,7 @@ test("Native function calls multiple Reef functions", async () => { const vm = new VM(bytecode) - vm.registerFunction('orchestrate', async function (n: number) { + vm.setFunction('orchestrate', async function (n: number) { const doubled = await this.call('double', n) const tripled = await this.call('triple', n) @@ -1064,7 +1064,7 @@ test("Native function conditionally calls Reef functions", async () => { const vm = new VM(bytecode) - vm.registerFunction('validate', async function (n: number) { + vm.setFunction('validate', async function (n: number) { const isPositive = await this.call('is_positive', n) if (isPositive) { @@ -1105,7 +1105,7 @@ test("Native function calls Reef function with closure", async () => { const vm = new VM(bytecode) - vm.registerFunction('transform', async function (n: number) { + vm.setFunction('transform', async function (n: number) { return await this.call('multiply_by_ten', n) }) @@ -1143,7 +1143,7 @@ test("Native function uses Reef function as filter predicate", async () => { const vm = new VM(bytecode) - vm.registerFunction('filter_evens', async function (array: any[]) { + vm.setFunction('filter_evens', async function (array: any[]) { const results = [] for (const item of array) { if (await this.call('is_even', item)) { @@ -1199,7 +1199,7 @@ test("Reef calls native calls Reef - roundtrip", async () => { const vm = new VM(bytecode) - vm.registerFunction('native_helper', async function (n: number) { + vm.setFunction('native_helper', async function (n: number) { const squared = await this.call('square', n) return squared + 1 // Add 1 to the squared result }) @@ -1232,7 +1232,7 @@ test("Native function calls Reef function with multiple arguments", async () => const vm = new VM(bytecode) - vm.registerFunction('calculate', async function () { + vm.setFunction('calculate', async function () { return await this.call('add_three', 10, 20, 30) }) @@ -1266,7 +1266,7 @@ test("Native function calls Reef function that returns complex type", async () = const vm = new VM(bytecode) - vm.registerFunction('create_user', async function () { + vm.setFunction('create_user', async function () { return await this.call('make_user', "Alice", 30) }) @@ -1289,7 +1289,7 @@ test("Native function calls non-existent Reef function - throws error", async () const vm = new VM(bytecode) - vm.registerFunction('bad_caller', async function () { + vm.setFunction('bad_caller', async function () { return await this.call('nonexistent', 42) }) @@ -1299,7 +1299,7 @@ test("Native function calls non-existent Reef function - throws error", async () test("Native function calls Reef function with named arguments", async () => { const bytecode = toBytecode(` ; Reef function with default parameters - MAKE_FUNCTION (name greeting='Hello') .greet_body + MAKE_FUNCTION (name greeting='Hello') .greet_body STORE greet JUMP .skip_greet .greet_body: @@ -1387,7 +1387,7 @@ test("Native function receives Reef closure with default params - calls with nam const vm = new VM(bytecode) // Native function that calls the Reef closure with named arguments - vm.registerFunction('map', async (array: any[], callback: Function) => { + vm.set('map', async (array: any[], callback: Function) => { const results = [] for (const item of array) { // Call with named argument to override the default @@ -1457,7 +1457,7 @@ test("Native function receives Reef closure with variadic parameters", async () const vm = new VM(bytecode) // Native function that calls the variadic Reef closure with multiple args - vm.registerFunction('process', async (callback: Function) => { + vm.set('process', async (callback: Function) => { // Call with varying number of arguments const result1 = await callback(1, 2, 3) const result2 = await callback(10, 20) @@ -1508,7 +1508,7 @@ test("Native function receives Reef closure with @named parameter", async () => const vm = new VM(bytecode) // Native function that calls Reef closure with named arguments - vm.registerFunction('format_messages', async (messages: any[], formatter: Function) => { + vm.set('format_messages', async (messages: any[], formatter: Function) => { const results = [] for (const msg of messages) { // Call with named arguments @@ -1553,7 +1553,7 @@ test("Native function receives Reef closure - calls with only named arguments", const vm = new VM(bytecode) // Native function that calls Reef closure with ONLY named arguments - vm.registerFunction('compute', async (callback: Function) => { + vm.set('compute', async (callback: Function) => { // First call with all named args const result1 = await callback({ x: 10, y: 20, z: 30 }) @@ -1619,7 +1619,7 @@ test("Native function receives Reef closure with mixed positional and variadic", const vm = new VM(bytecode) // Native function that calls Reef closure with mixed args - vm.registerFunction('process_numbers', async (calculator: Function) => { + vm.set('process_numbers', async (calculator: Function) => { // Call with fixed multiplier and variadic numbers const result1 = await calculator(10, 1, 2, 3) // 10 * (1+2+3) = 60 const result2 = await calculator(5, 4, 6) // 5 * (4+6) = 50 diff --git a/tests/regex.test.ts b/tests/regex.test.ts index 72927d0..2e2caa2 100644 --- a/tests/regex.test.ts +++ b/tests/regex.test.ts @@ -399,7 +399,7 @@ describe("RegExp", () => { const vm = new VM(bytecode) // Register a native function that takes a string and regex - vm.registerFunction('match', (str: string, pattern: RegExp) => { + vm.set('match', (str: string, pattern: RegExp) => { return pattern.test(str) }) @@ -422,7 +422,7 @@ describe("RegExp", () => { const vm = new VM(bytecode) - vm.registerFunction('replace', (str: string, pattern: RegExp, replacement: string) => { + vm.set('replace', (str: string, pattern: RegExp, replacement: string) => { return str.replace(pattern, replacement) }) @@ -444,7 +444,7 @@ describe("RegExp", () => { const vm = new VM(bytecode) - vm.registerFunction('extractNumbers', (str: string, pattern: RegExp) => { + vm.set('extractNumbers', (str: string, pattern: RegExp) => { return str.match(pattern) || [] })