bind expression (:=) instead of let
Some checks failed
Build / build (push) Successful in 10m26s
Test / build (push) Failing after 16m44s

This commit is contained in:
Chuck Smith
2024-03-21 17:43:03 -04:00
parent 66d5453ecc
commit 6282075e66
36 changed files with 425 additions and 583 deletions

View File

@@ -261,12 +261,12 @@ func TestConditionals(t *testing.T) {
{"if (1 > 2) { 10 }", Null},
{"if (false) { 10 }", Null},
{"if ((if (false) { 10 })) { 10 } else { 20 }", 20},
{"if (true) { let a = 5; }", Null},
{"if (true) { 10; let a = 5; }", Null},
{"if (false) { 10 } else { let b = 5; }", Null},
{"if (false) { 10 } else { 10; let b = 5; }", Null},
{"if (true) { let a = 5; } else { 10 }", Null},
{"let x = 0; if (true) { x = 1; }; if (false) { x = 2; }; x", 1},
{"if (true) { a := 5; }", Null},
{"if (true) { 10; a := 5; }", Null},
{"if (false) { 10 } else { b := 5; }", Null},
{"if (false) { 10 } else { 10; b := 5; }", Null},
{"if (true) { a := 5; } else { 10 }", Null},
{"x := 0; if (true) { x = 1; }; if (false) { x = 2; }; x", 1},
{"if (1 < 2) { 10 } else if (1 == 2) { 20 }", 10},
{"if (1 > 2) { 10 } else if (1 == 2) { 20 } else { 30 }", 30},
}
@@ -274,11 +274,11 @@ func TestConditionals(t *testing.T) {
runVmTests(t, tests)
}
func TestGlobalLetStatements(t *testing.T) {
func TestGlobalBindExpressions(t *testing.T) {
tests := []vmTestCase{
{"let one = 1; one", 1},
{"let one = 1; let two = 2; one + two", 3},
{"let one = 1; let two = one + one; one + two", 3},
{"one := 1; one", 1},
{"one := 1; two := 2; one + two", 3},
{"one := 1; two := one + one; one + two", 3},
}
runVmTests(t, tests)
@@ -364,24 +364,24 @@ func TestCallingFunctionsWithoutArguments(t *testing.T) {
tests := []vmTestCase{
{
input: `
let fivePlusTen = fn() { return 5 + 10; };
fivePlusTen := fn() { return 5 + 10; };
fivePlusTen();
`,
expected: 15,
},
{
input: `
let one = fn() { return 1; };
let two = fn() { return 2; };
one := fn() { return 1; };
two := fn() { return 2; };
one() + two()
`,
expected: 3,
},
{
input: `
let a = fn() { return 1 };
let b = fn() { return a() + 1 };
let c = fn() { return b() + 1 };
a := fn() { return 1 };
b := fn() { return a() + 1 };
c:= fn() { return b() + 1 };
c();
`,
expected: 3,
@@ -395,14 +395,14 @@ func TestFunctionsWithReturnStatements(t *testing.T) {
tests := []vmTestCase{
{
input: `
let earlyExit = fn() { return 99; 100; };
earlyExit := fn() { return 99; 100; };
earlyExit();
`,
expected: 99,
},
{
input: `
let earlyExit = fn() { return 99; return 100; };
earlyExit := fn() { return 99; return 100; };
earlyExit();
`,
expected: 99,
@@ -416,15 +416,15 @@ func TestFunctionsWithoutReturnValue(t *testing.T) {
tests := []vmTestCase{
{
input: `
let noReturn = fn() { };
noReturn := fn() { };
noReturn();
`,
expected: Null,
},
{
input: `
let noReturn = fn() { };
let noReturnTwo = fn() { noReturn(); };
noReturn := fn() { };
noReturnTwo := fn() { noReturn(); };
noReturn();
noReturnTwo();
`,
@@ -439,16 +439,16 @@ func TestFirstClassFunctions(t *testing.T) {
tests := []vmTestCase{
{
input: `
let returnsOne = fn() { return 1; };
let returnsOneReturner = fn() { return returnsOne; };
returnsOne := fn() { return 1; };
returnsOneReturner := fn() { return returnsOne; };
returnsOneReturner()();
`,
expected: 1,
},
{
input: `
let returnsOneReturner = fn() {
let returnsOne = fn() { return 1; };
returnsOneReturner := fn() {
returnsOne := fn() { return 1; };
return returnsOne;
};
returnsOneReturner()();
@@ -464,43 +464,43 @@ func TestCallingFunctionsWithBindings(t *testing.T) {
tests := []vmTestCase{
//{
// input: `
// let one = fn() { let one = 1; return one };
// one := fn() { one := 1; return one };
// one();
// `,
// expected: 1,
//},
{
input: `
let oneAndTwo = fn() { let one = 1; let two = 2; return one + two; };
oneAndTwo := fn() { one := 1; two := 2; return one + two; };
oneAndTwo();
`,
expected: 3,
},
{
input: `
let oneAndTwo = fn() { let one = 1; let two = 2; return one + two; };
let threeAndFour = fn() { let three = 3; let four = 4; return three + four; };
oneAndTwo := fn() { one := 1; two := 2; return one + two; };
threeAndFour := fn() { three := 3; four := 4; return three + four; };
oneAndTwo() + threeAndFour();
`,
expected: 10,
},
{
input: `
let firstFoobar = fn() { let foobar = 50; return foobar; };
let secondFoobar = fn() { let foobar = 100; return foobar; };
firstFoobar := fn() { foobar := 50; return foobar; };
secondFoobar := fn() { foobar := 100; return foobar; };
firstFoobar() + secondFoobar();
`,
expected: 150,
},
{
input: `
let globalSeed = 50;
let minusOne = fn() {
let num = 1;
globalSeed := 50;
minusOne := fn() {
num := 1;
return globalSeed - num;
}
let minusTwo = fn() {
let num = 2;
minusTwo := fn() {
num := 2;
return globalSeed - num;
}
minusOne() + minusTwo();
@@ -516,22 +516,22 @@ func TestCallingFunctionsWithArgumentsAndBindings(t *testing.T) {
tests := []vmTestCase{
{
input: `
let identity = fn(a) { return a; };
identity := fn(a) { return a; };
identity(4);
`,
expected: 4,
},
{
input: `
let sum = fn(a, b) { return a + b; };
sum := fn(a, b) { return a + b; };
sum(1, 2);
`,
expected: 3,
},
{
input: `
let sum = fn(a, b) {
let c = a + b;
sum := fn(a, b) {
c := a + b;
return c;
};
sum(1, 2);
@@ -540,8 +540,8 @@ func TestCallingFunctionsWithArgumentsAndBindings(t *testing.T) {
},
{
input: `
let sum = fn(a, b) {
let c = a + b;
sum := fn(a, b) {
c := a + b;
return c;
};
sum(1, 2) + sum(3, 4);`,
@@ -549,11 +549,11 @@ func TestCallingFunctionsWithArgumentsAndBindings(t *testing.T) {
},
{
input: `
let sum = fn(a, b) {
let c = a + b;
sum := fn(a, b) {
c := a + b;
return c;
};
let outer = fn() {
outer := fn() {
return sum(1, 2) + sum(3, 4);
};
outer();
@@ -562,14 +562,14 @@ func TestCallingFunctionsWithArgumentsAndBindings(t *testing.T) {
},
{
input: `
let globalNum = 10;
globalNum := 10;
let sum = fn(a, b) {
let c = a + b;
sum := fn(a, b) {
c := a + b;
return c + globalNum;
};
let outer = fn() {
outer := fn() {
return sum(1, 2) + sum(3, 4) + globalNum;
};
@@ -697,72 +697,72 @@ func TestClosures(t *testing.T) {
tests := []vmTestCase{
{
input: `
let newClosure = fn(a) {
newClosure := fn(a) {
return fn() { return a; };
};
let closure = newClosure(99);
closure := newClosure(99);
closure();
`,
expected: 99,
},
{
input: `
let newAdder = fn(a, b) {
newAdder := fn(a, b) {
return fn(c) { return a + b + c };
};
let adder = newAdder(1, 2);
adder := newAdder(1, 2);
adder(8);
`,
expected: 11,
},
{
input: `
let newAdder = fn(a, b) {
let c = a + b;
newAdder := fn(a, b) {
c := a + b;
return fn(d) { return c + d };
};
let adder = newAdder(1, 2);
adder := newAdder(1, 2);
adder(8);
`,
expected: 11,
},
{
input: `
let newAdderOuter = fn(a, b) {
let c = a + b;
newAdderOuter := fn(a, b) {
c := a + b;
return fn(d) {
let e = d + c;
e := d + c;
return fn(f) { return e + f; };
};
};
let newAdderInner = newAdderOuter(1, 2)
let adder = newAdderInner(3);
newAdderInner := newAdderOuter(1, 2)
adder := newAdderInner(3);
adder(8);
`,
expected: 14,
},
{
input: `
let a = 1;
let newAdderOuter = fn(b) {
a := 1;
newAdderOuter := fn(b) {
return fn(c) {
return fn(d) { return a + b + c + d };
};
};
let newAdderInner = newAdderOuter(2)
let adder = newAdderInner(3);
newAdderInner := newAdderOuter(2)
adder := newAdderInner(3);
adder(8);
`,
expected: 14,
},
{
input: `
let newClosure = fn(a, b) {
let one = fn() { return a; };
let two = fn() { return b; };
newClosure := fn(a, b) {
one := fn() { return a; };
two := fn() { return b; };
return fn() { return one() + two(); };
};
let closure = newClosure(9, 90);
closure := newClosure(9, 90);
closure();
`,
expected: 99,
@@ -776,7 +776,7 @@ func TestRecursiveFunctions(t *testing.T) {
tests := []vmTestCase{
{
input: `
let countDown = fn(x) {
countDown := fn(x) {
if (x == 0) {
return 0;
} else {
@@ -789,14 +789,14 @@ func TestRecursiveFunctions(t *testing.T) {
},
{
input: `
let countDown = fn(x) {
countDown := fn(x) {
if (x == 0) {
return 0;
} else {
return countDown(x - 1);
}
};
let wrapper = fn() {
wrapper := fn() {
return countDown(1);
};
wrapper();
@@ -805,8 +805,8 @@ func TestRecursiveFunctions(t *testing.T) {
},
{
input: `
let wrapper = fn() {
let countDown = fn(x) {
wrapper := fn() {
countDown := fn(x) {
if (x == 0) {
return 0;
} else {
@@ -828,7 +828,7 @@ func TestRecursiveFibonacci(t *testing.T) {
tests := []vmTestCase{
{
input: `
let fibonacci = fn(x) {
fibonacci := fn(x) {
if (x == 0) {
return 0;
} else {
@@ -851,14 +851,14 @@ func TestRecursiveFibonacci(t *testing.T) {
func TestIterations(t *testing.T) {
tests := []vmTestCase{
{"while (false) { }", nil},
{"let n = 0; while (n < 10) { let n = n + 1 }; n", 10},
{"let n = 10; while (n > 0) { let n = n - 1 }; n", 0},
{"let n = 0; while (n < 10) { let n = n + 1 }", nil},
{"let n = 10; while (n > 0) { let n = n - 1 }", nil},
{"let n = 0; while (n < 10) { n = n + 1 }; n", 10},
{"let n = 10; while (n > 0) { n = n - 1 }; n", 0},
{"let n = 0; while (n < 10) { n = n + 1 }", nil},
{"let n = 10; while (n > 0) { n = n - 1 }", nil},
{"n := 0; while (n < 10) { n := n + 1 }; n", 10},
{"n := 10; while (n > 0) { n := n - 1 }; n", 0},
{"n := 0; while (n < 10) { n := n + 1 }", nil},
{"n := 10; while (n > 0) { n := n - 1 }", nil},
{"n := 0; while (n < 10) { n = n + 1 }; n", 10},
{"n := 10; while (n > 0) { n = n - 1 }; n", 0},
{"n := 0; while (n < 10) { n = n + 1 }", nil},
{"n := 10; while (n > 0) { n = n - 1 }", nil},
}
runVmTests(t, tests)
@@ -866,7 +866,7 @@ func TestIterations(t *testing.T) {
func TestIndexAssignmentStatements(t *testing.T) {
tests := []vmTestCase{
{"let xs = [1, 2, 3]; xs[1] = 4; xs[1];", 4},
{"xs := [1, 2, 3]; xs[1] = 4; xs[1];", 4},
}
runVmTests(t, tests)
@@ -874,20 +874,20 @@ func TestIndexAssignmentStatements(t *testing.T) {
func TestAssignmentExpressions(t *testing.T) {
tests := []vmTestCase{
{"let a = 0; a = 5;", nil},
{"let a = 0; a = 5; a;", 5},
{"let a = 0; a = 5 * 5;", nil},
{"let a = 0; a = 5 * 5; a;", 25},
{"let a = 0; a = 5; let b = 0; b = a;", nil},
{"let a = 0; a = 5; let b = 0; b = a; b;", 5},
{"let a = 0; a = 5; let b = 0; b = a; let c = 0; c = a + b + 5;", nil},
{"let a = 0; a = 5; let b = 0; b = a; let c = 0; c = a + b + 5; c;", 15},
{"let a = 5; let b = a; a = 0;", nil},
{"let a = 5; let b = a; a = 0; b;", 5},
{"let one = 0; one = 1", nil},
{"let one = 0; one = 1; one", 1},
{"let one = 0; one = 1; let two = 0; two = 2; one + two", 3},
{"let one = 0; one = 1; let two = 0; two = one + one; one + two", 3},
{"a := 0; a = 5;", nil},
{"a := 0; a = 5; a;", 5},
{"a := 0; a = 5 * 5;", nil},
{"a := 0; a = 5 * 5; a;", 25},
{"a := 0; a = 5; b := 0; b = a;", nil},
{"a := 0; a = 5; b := 0; b = a; b;", 5},
{"a := 0; a = 5; b := 0; b = a; c := 0; c = a + b + 5;", nil},
{"a := 0; a = 5; b := 0; b = a; c := 0; c = a + b + 5; c;", 15},
{"a := 5; b := a; a = 0;", nil},
{"a := 5; b := a; a = 0; b;", 5},
{"one := 0; one = 1", nil},
{"one := 0; one = 1; one", 1},
{"one := 0; one = 1; two := 0; two = 2; one + two", 3},
{"one := 0; one = 1; two := 0; two = one + one; one + two", 3},
}
runVmTests(t, tests)
@@ -897,7 +897,7 @@ func TestTailCalls(t *testing.T) {
tests := []vmTestCase{
{
input: `
let fact = fn(n, a) {
fact := fn(n, a) {
if (n == 0) {
return a
}
@@ -912,7 +912,7 @@ func TestTailCalls(t *testing.T) {
// without tail recursion optimization this will cause a stack overflow
{
input: `
let iter = fn(n, max) {
iter := fn(n, max) {
if (n == max) {
return n
}
@@ -971,14 +971,14 @@ func TestIntegration(t *testing.T) {
func BenchmarkFibonacci(b *testing.B) {
tests := map[string]string{
"iterative": `
let fib = fn(n) {
fib := fn(n) {
if (n < 3) {
return 1
}
let a = 1
let b = 1
let c = 0
let i = 0
a := 1
b := 1
c := 0
i := 0
while (i < n - 2) {
c = a + b
b = a
@@ -991,7 +991,7 @@ func BenchmarkFibonacci(b *testing.B) {
fib(35)
`,
"recursive": `
let fib = fn(x) {
fib := fn(x) {
if (x == 0) {
return 0
}
@@ -1004,7 +1004,7 @@ func BenchmarkFibonacci(b *testing.B) {
fib(35)
`,
"tail-recursive": `
let fib = fn(n, a, b) {
fib := fn(n, a, b) {
if (n == 0) {
return a
}