import { test, expect } from "bun:test" import { VM } from "#vm" import { OpCode } from "#opcode" test("MAKE_FUNCTION - creates function with captured scope", async () => { const vm = new VM({ instructions: [ { op: OpCode.MAKE_FUNCTION, operand: 0 } ], constants: [ { type: 'function_def', params: [], defaults: {}, body: 999, variadic: false, kwargs: false } ] }) const result = await vm.run() expect(result.type).toBe('function') if (result.type === 'function') { expect(result.body).toBe(999) expect(result.params).toEqual([]) } }) test("CALL and RETURN - basic function call", async () => { // Function that returns 42 const vm = new VM({ instructions: [ // 0: Create and call the function { op: OpCode.MAKE_FUNCTION, operand: 0 }, { op: OpCode.CALL, operand: 0 }, // call with 0 args { op: OpCode.HALT }, // 3: Function body (starts here, address = 3) { op: OpCode.PUSH, operand: 1 }, // push 42 { op: OpCode.RETURN } ], constants: [ { type: 'function_def', params: [], defaults: {}, body: 3, // function body starts at instruction 3 variadic: false, kwargs: false }, { type: 'number', value: 42 } ] }) const result = await vm.run() expect(result).toEqual({ type: 'number', value: 42 }) }) test("CALL and RETURN - function with one parameter", async () => { // Function that returns its parameter const vm = new VM({ instructions: [ // 0: Push argument and call function { op: OpCode.MAKE_FUNCTION, operand: 0 }, { op: OpCode.PUSH, operand: 1 }, // argument: 100 { op: OpCode.CALL, operand: 1 }, // call with 1 arg { op: OpCode.HALT }, // 4: Function body { op: OpCode.LOAD, operand: 'x' }, // load parameter x { op: OpCode.RETURN } ], constants: [ { type: 'function_def', params: ['x'], defaults: {}, body: 4, variadic: false, kwargs: false }, { type: 'number', value: 100 } ] }) const result = await vm.run() expect(result).toEqual({ type: 'number', value: 100 }) }) test("CALL and RETURN - function with two parameters", async () => { // Function that adds two parameters const vm = new VM({ instructions: [ // 0: Push arguments and call function { op: OpCode.MAKE_FUNCTION, operand: 0 }, { op: OpCode.PUSH, operand: 1 }, // arg1: 10 { op: OpCode.PUSH, operand: 2 }, // arg2: 20 { op: OpCode.CALL, operand: 2 }, // call with 2 args { op: OpCode.HALT }, // 5: Function body { op: OpCode.LOAD, operand: 'a' }, { op: OpCode.LOAD, operand: 'b' }, { op: OpCode.ADD }, { op: OpCode.RETURN } ], constants: [ { type: 'function_def', params: ['a', 'b'], defaults: {}, body: 5, variadic: false, kwargs: false }, { type: 'number', value: 10 }, { type: 'number', value: 20 } ] }) const result = await vm.run() expect(result).toEqual({ type: 'number', value: 30 }) })