closures and they can recurse!!!
Some checks failed
Build / build (push) Failing after 1m35s
Test / build (push) Has been cancelled

This commit is contained in:
Chuck Smith
2024-03-14 20:08:40 -04:00
parent 78b560e457
commit cc78fee3c8
10 changed files with 640 additions and 39 deletions

View File

@@ -27,6 +27,19 @@ func runVmTests(t *testing.T, tests []vmTestCase) {
t.Fatalf("compiler error: %s", err)
}
//for i, constant := range comp.Bytecode().Constants {
// fmt.Printf("CONSTANT %d %p (%T):\n", i, constant, constant)
//
// switch constant := constant.(type) {
// case *object.CompiledFunction:
// fmt.Printf(" Instructions:\n%s", constant.Instructions)
// case *object.Integer:
// fmt.Printf(" Value: %d\n", constant.Value)
// }
//
// fmt.Printf("\n")
//}
vm := New(comp.Bytecode())
err = vm.Run()
if err != nil {
@@ -611,3 +624,134 @@ func TestBuiltinFunctions(t *testing.T) {
runVmTests(t, tests)
}
func TestClosures(t *testing.T) {
tests := []vmTestCase{
{
input: `
let newClosure = fn(a) {
fn() { a; };
};
let closure = newClosure(99);
closure();
`,
expected: 99,
},
{
input: `
let newAdder = fn(a, b) {
fn(c) { a + b + c };
};
let adder = newAdder(1, 2);
adder(8);
`,
expected: 11,
},
{
input: `
let newAdder = fn(a, b) {
let c = a + b;
fn(d) { c + d };
};
let adder = newAdder(1, 2);
adder(8);
`,
expected: 11,
},
{
input: `
let newAdderOuter = fn(a, b) {
let c = a + b;
fn(d) {
let e = d + c;
fn(f) { e + f; };
};
};
let newAdderInner = newAdderOuter(1, 2)
let adder = newAdderInner(3);
adder(8);
`,
expected: 14,
},
{
input: `
let a = 1;
let newAdderOuter = fn(b) {
fn(c) {
fn(d) { a + b + c + d };
};
};
let newAdderInner = newAdderOuter(2)
let adder = newAdderInner(3);
adder(8);
`,
expected: 14,
},
{
input: `
let newClosure = fn(a, b) {
let one = fn() { a; };
let two = fn() { b; };
fn() { one() + two(); };
};
let closure = newClosure(9, 90);
closure();
`,
expected: 99,
},
}
runVmTests(t, tests)
}
func TestRecursiveFunctions(t *testing.T) {
tests := []vmTestCase{
{
input: `
let countDown = fn(x) {
if (x == 0) {
return 0;
} else {
countDown(x - 1);
}
};
countDown(1);
`,
expected: 0,
},
{
input: `
let countDown = fn(x) {
if (x == 0) {
return 0;
} else {
countDown(x - 1);
}
};
let wrapper = fn() {
countDown(1);
};
wrapper();
`,
expected: 0,
},
{
input: `
let wrapper = fn() {
let countDown = fn(x) {
if (x == 0) {
return 0;
} else {
countDown(x - 1);
}
};
countDown(1);
};
wrapper();
`,
expected: 0,
},
}
runVmTests(t, tests)
}