bitwise operators and boolean operators
This commit is contained in:
@@ -96,6 +96,38 @@ func TestIntegerArithmetic(t *testing.T) {
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "5 | 2",
|
||||
expectedConstants: []interface{}{5, 2},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpConstant, 1),
|
||||
code.Make(code.OpBitwiseOR),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
input: "5 ^ 2",
|
||||
expectedConstants: []interface{}{5, 2},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpConstant, 1),
|
||||
code.Make(code.OpBitwiseXOR),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
input: "5 & 2",
|
||||
expectedConstants: []interface{}{5, 2},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpConstant, 1),
|
||||
code.Make(code.OpBitwiseAND),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
runCompilerTests(t, tests)
|
||||
@@ -207,12 +239,32 @@ func TestBooleanExpressions(t *testing.T) {
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "true && false",
|
||||
expectedConstants: []interface{}{},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpTrue),
|
||||
code.Make(code.OpFalse),
|
||||
code.Make(code.OpAnd),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "true || false",
|
||||
expectedConstants: []interface{}{},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpTrue),
|
||||
code.Make(code.OpFalse),
|
||||
code.Make(code.OpOr),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "!true",
|
||||
expectedConstants: []interface{}{},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpTrue),
|
||||
code.Make(code.OpBang),
|
||||
code.Make(code.OpNot),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
@@ -228,20 +280,20 @@ func TestConditionals(t *testing.T) {
|
||||
if (true) { 10 }; 3333;
|
||||
`,
|
||||
constants: []interface{}{10, 3333},
|
||||
instructions: "0000 LoadTrue\n0001 JumpIfFalse 10\n0004 LoadConstant 0\n0007 Jump 11\n0010 LoadNull\n0011 Pop\n0012 LoadConstant 1\n0015 Pop\n",
|
||||
instructions: "0000 OpTrue\n0001 OpJumpNotTruthy 10\n0004 OpConstant 0\n0007 OpJump 11\n0010 OpNull\n0011 OpPop\n0012 OpConstant 1\n0015 OpPop\n",
|
||||
}, {
|
||||
input: `
|
||||
if (true) { 10 } else { 20 }; 3333;
|
||||
`,
|
||||
constants: []interface{}{10, 20, 3333},
|
||||
instructions: "0000 LoadTrue\n0001 JumpIfFalse 10\n0004 LoadConstant 0\n0007 Jump 13\n0010 LoadConstant 1\n0013 Pop\n0014 LoadConstant 2\n0017 Pop\n",
|
||||
instructions: "0000 OpTrue\n0001 OpJumpNotTruthy 10\n0004 OpConstant 0\n0007 OpJump 13\n0010 OpConstant 1\n0013 OpPop\n0014 OpConstant 2\n0017 OpPop\n",
|
||||
},
|
||||
{
|
||||
input: `
|
||||
let x = 0; if (true) { x = 1; }; if (false) { x = 2; }
|
||||
x := 0; if (true) { x = 1; }; if (false) { x = 2; }
|
||||
`,
|
||||
constants: []interface{}{0, 1, 2},
|
||||
instructions: "0000 LoadConstant 0\n0003 BindGlobal 0\n0006 Pop\n0007 LoadTrue\n0008 JumpIfFalse 20\n0011 LoadConstant 1\n0014 AssignGlobal 0\n0017 Jump 21\n0020 LoadNull\n0021 Pop\n0022 LoadFalse\n0023 JumpIfFalse 35\n0026 LoadConstant 2\n0029 AssignGlobal 0\n0032 Jump 36\n0035 LoadNull\n0036 Pop\n",
|
||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpTrue\n0008 OpJumpNotTruthy 20\n0011 OpConstant 1\n0014 OpAssignGlobal 0\n0017 OpJump 21\n0020 OpNull\n0021 OpPop\n0022 OpFalse\n0023 OpJumpNotTruthy 35\n0026 OpConstant 2\n0029 OpAssignGlobal 0\n0032 OpJump 36\n0035 OpNull\n0036 OpPop\n",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -255,7 +307,8 @@ func TestGlobalBindExpressions(t *testing.T) {
|
||||
one := 1;
|
||||
two := 2;
|
||||
`,
|
||||
instructions: "0000 LoadConstant 0\n0003 BindGlobal 0\n0006 Pop\n0007 LoadConstant 1\n0010 BindGlobal 1\n0013 Pop\n",
|
||||
constants: []interface{}{1, 2},
|
||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpConstant 1\n0010 OpSetGlobal 1\n0013 OpPop\n",
|
||||
},
|
||||
{
|
||||
input: `
|
||||
@@ -263,7 +316,7 @@ func TestGlobalBindExpressions(t *testing.T) {
|
||||
one;
|
||||
`,
|
||||
constants: []interface{}{1},
|
||||
instructions: "0000 LoadConstant 0\n0003 BindGlobal 0\n0006 Pop\n0007 LoadGlobal 0\n0010 Pop\n",
|
||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpGetGlobal 0\n0010 OpPop\n",
|
||||
},
|
||||
{
|
||||
input: `
|
||||
@@ -272,7 +325,7 @@ func TestGlobalBindExpressions(t *testing.T) {
|
||||
two;
|
||||
`,
|
||||
constants: []interface{}{1},
|
||||
instructions: "0000 LoadConstant 0\n0003 BindGlobal 0\n0006 Pop\n0007 LoadGlobal 0\n0010 BindGlobal 1\n0013 Pop\n0014 LoadGlobal 1\n0017 Pop\n",
|
||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpGetGlobal 0\n0010 OpSetGlobal 1\n0013 OpPop\n0014 OpGetGlobal 1\n0017 OpPop\n",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -490,31 +543,20 @@ func TestFunctionsWithoutReturn(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClosures(t *testing.T) {
|
||||
tests := []compilerTestCase{
|
||||
tests := []compilerTestCase2{
|
||||
{
|
||||
input: `fn(a) {
|
||||
return fn(b) {
|
||||
return a + b
|
||||
}
|
||||
}
|
||||
`,
|
||||
expectedConstants: []interface{}{
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpGetFree, 0),
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpAdd),
|
||||
code.Make(code.OpReturn),
|
||||
},
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpClosure, 0, 1),
|
||||
code.Make(code.OpReturn),
|
||||
},
|
||||
},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpClosure, 1, 0),
|
||||
code.Make(code.OpPop),
|
||||
input: `
|
||||
fn(a) {
|
||||
return fn(b) {
|
||||
return a + b
|
||||
}
|
||||
}
|
||||
`,
|
||||
constants: []interface{}{
|
||||
Instructions("0000 OpGetFree 0\n0002 OpGetLocal 0\n0004 OpAdd\n0005 OpReturn\n"),
|
||||
Instructions("0000 OpGetLocal 0\n0002 OpClosure 0 1\n0006 OpReturn\n"),
|
||||
},
|
||||
instructions: "0000 OpClosure 1 0\n0004 OpPop\n",
|
||||
},
|
||||
{
|
||||
input: `
|
||||
@@ -526,93 +568,45 @@ func TestClosures(t *testing.T) {
|
||||
}
|
||||
};
|
||||
`,
|
||||
expectedConstants: []interface{}{
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpGetFree, 0),
|
||||
code.Make(code.OpGetFree, 1),
|
||||
code.Make(code.OpAdd),
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpAdd),
|
||||
code.Make(code.OpReturn),
|
||||
},
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpGetFree, 0),
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpClosure, 0, 2),
|
||||
code.Make(code.OpReturn),
|
||||
},
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpClosure, 1, 1),
|
||||
code.Make(code.OpReturn),
|
||||
},
|
||||
},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpClosure, 2, 0),
|
||||
code.Make(code.OpPop),
|
||||
constants: []interface{}{
|
||||
Instructions("0000 OpGetFree 0\n0002 OpGetFree 1\n0004 OpAdd\n0005 OpGetLocal 0\n0007 OpAdd\n0008 OpReturn\n"),
|
||||
Instructions("0000 OpGetFree 0\n0002 OpGetLocal 0\n0004 OpClosure 0 2\n0008 OpReturn\n"),
|
||||
Instructions("0000 OpGetLocal 0\n0002 OpClosure 1 1\n0006 OpReturn\n"),
|
||||
},
|
||||
instructions: "0000 OpClosure 2 0\n0004 OpPop\n",
|
||||
},
|
||||
{
|
||||
input: `
|
||||
let global = 55;
|
||||
global := 55;
|
||||
|
||||
fn() {
|
||||
let a = 66;
|
||||
a := 66;
|
||||
|
||||
return fn() {
|
||||
let b = 77;
|
||||
b := 77;
|
||||
|
||||
return fn() {
|
||||
let c = 88;
|
||||
c := 88;
|
||||
|
||||
return global + a + b + c;
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
expectedConstants: []interface{}{
|
||||
constants: []interface{}{
|
||||
55,
|
||||
66,
|
||||
77,
|
||||
88,
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpConstant, 3),
|
||||
code.Make(code.OpSetLocal, 0),
|
||||
code.Make(code.OpGetGlobal, 0),
|
||||
code.Make(code.OpGetFree, 0),
|
||||
code.Make(code.OpAdd),
|
||||
code.Make(code.OpGetFree, 1),
|
||||
code.Make(code.OpAdd),
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpAdd),
|
||||
code.Make(code.OpReturn),
|
||||
},
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpConstant, 2),
|
||||
code.Make(code.OpSetLocal, 0),
|
||||
code.Make(code.OpGetFree, 0),
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpClosure, 4, 2),
|
||||
code.Make(code.OpReturn),
|
||||
},
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpConstant, 1),
|
||||
code.Make(code.OpSetLocal, 0),
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpClosure, 5, 1),
|
||||
code.Make(code.OpReturn),
|
||||
},
|
||||
},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpSetGlobal, 0),
|
||||
code.Make(code.OpClosure, 6, 0),
|
||||
code.Make(code.OpPop),
|
||||
Instructions("0000 OpConstant 3\n0003 OpSetLocal 0\n0005 OpPop\n0006 OpGetGlobal 0\n0009 OpGetFree 0\n0011 OpAdd\n0012 OpGetFree 1\n0014 OpAdd\n0015 OpGetLocal 0\n0017 OpAdd\n0018 OpReturn\n"),
|
||||
Instructions("0000 OpConstant 2\n0003 OpSetLocal 0\n0005 OpPop\n0006 OpGetFree 0\n0008 OpGetLocal 0\n0010 OpClosure 4 2\n0014 OpReturn\n"),
|
||||
Instructions("0000 OpConstant 1\n0003 OpSetLocal 0\n0005 OpPop\n0006 OpGetLocal 0\n0008 OpClosure 5 1\n0012 OpReturn\n"),
|
||||
},
|
||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpClosure 6 0\n0011 OpPop\n",
|
||||
},
|
||||
}
|
||||
|
||||
runCompilerTests(t, tests)
|
||||
runCompilerTests2(t, tests)
|
||||
}
|
||||
|
||||
func TestCompilerScopes(t *testing.T) {
|
||||
@@ -667,9 +661,9 @@ func TestFunctionCalls(t *testing.T) {
|
||||
input: `fn() { return 24 }();`,
|
||||
constants: []interface{}{
|
||||
24,
|
||||
Instructions("0000 LoadConstant 0\n0003 Return\n"),
|
||||
Instructions("0000 OpConstant 0\n0003 OpReturn\n"),
|
||||
},
|
||||
instructions: "0000 MakeClosure 1 0\n0004 Call 0\n0006 Pop\n",
|
||||
instructions: "0000 OpClosure 1 0\n0004 OpCall 0\n0006 OpPop\n",
|
||||
},
|
||||
{
|
||||
input: `
|
||||
@@ -678,9 +672,9 @@ func TestFunctionCalls(t *testing.T) {
|
||||
`,
|
||||
constants: []interface{}{
|
||||
24,
|
||||
Instructions("0000 SetSelf 0\n0002 LoadConstant 0\n0005 Return\n"),
|
||||
Instructions("0000 OpConstant 0\n0003 OpReturn\n"),
|
||||
},
|
||||
instructions: "0000 LoadGlobal 0\n0003 MakeClosure 1 1\n0007 BindGlobal 0\n0010 Pop\n0011 LoadGlobal 0\n0014 Call 0\n0016 Pop\n",
|
||||
instructions: "0000 OpClosure 1 0\n0004 OpSetGlobal 0\n0007 OpPop\n0008 OpGetGlobal 0\n0011 OpCall 0\n0013 OpPop\n",
|
||||
},
|
||||
{
|
||||
input: `
|
||||
@@ -688,10 +682,10 @@ func TestFunctionCalls(t *testing.T) {
|
||||
oneArg(24);
|
||||
`,
|
||||
constants: []interface{}{
|
||||
Instructions("0000 SetSelf 0\n0002 LoadLocal 0\n0004 Return\n"),
|
||||
Instructions("0000 OpGetLocal 0\n0002 OpReturn\n"),
|
||||
24,
|
||||
},
|
||||
instructions: "0000 LoadGlobal 0\n0003 MakeClosure 0 1\n0007 BindGlobal 0\n0010 Pop\n0011 LoadGlobal 0\n0014 LoadConstant 1\n0017 Call 1\n0019 Pop\n",
|
||||
instructions: "0000 OpClosure 0 0\n0004 OpSetGlobal 0\n0007 OpPop\n0008 OpGetGlobal 0\n0011 OpConstant 1\n0014 OpCall 1\n0016 OpPop\n",
|
||||
},
|
||||
{
|
||||
input: `
|
||||
@@ -699,12 +693,12 @@ func TestFunctionCalls(t *testing.T) {
|
||||
manyArg(24, 25, 26);
|
||||
`,
|
||||
constants: []interface{}{
|
||||
Instructions("0000 SetSelf 0\n0002 LoadLocal 0\n0004 Pop\n0005 LoadLocal 1\n0007 Pop\n0008 LoadLocal 2\n0010 Return\n"),
|
||||
Instructions("0000 OpGetLocal 0\n0002 OpPop\n0003 OpGetLocal 1\n0005 OpPop\n0006 OpGetLocal 2\n0008 OpReturn\n"),
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
},
|
||||
instructions: "0000 LoadGlobal 0\n0003 MakeClosure 0 1\n0007 BindGlobal 0\n0010 Pop\n0011 LoadGlobal 0\n0014 LoadConstant 1\n0017 LoadConstant 2\n0020 LoadConstant 3\n0023 Call 3\n0025 Pop\n",
|
||||
instructions: "0000 OpClosure 0 0\n0004 OpSetGlobal 0\n0007 OpPop\n0008 OpGetGlobal 0\n0011 OpConstant 1\n0014 OpConstant 2\n0017 OpConstant 3\n0020 OpCall 3\n0022 OpPop\n",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -715,11 +709,11 @@ func TestAssignmentExpressions(t *testing.T) {
|
||||
tests := []compilerTestCase2{
|
||||
{
|
||||
input: `
|
||||
let x = 1
|
||||
x := 1
|
||||
x = 2
|
||||
`,
|
||||
constants: []interface{}{1, 2},
|
||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpConstant 1\n0009 OpAssignGlobal 0\n0012 OpPop\n",
|
||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpConstant 1\n0010 OpAssignGlobal 0\n0013 OpPop\n",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -730,7 +724,7 @@ func TestAssignmentStatementScopes(t *testing.T) {
|
||||
tests := []compilerTestCase{
|
||||
{
|
||||
input: `
|
||||
let num = 0;
|
||||
num := 0;
|
||||
fn() { num = 55; }
|
||||
`,
|
||||
expectedConstants: []interface{}{
|
||||
@@ -746,13 +740,14 @@ func TestAssignmentStatementScopes(t *testing.T) {
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpSetGlobal, 0),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpClosure, 2, 0),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `
|
||||
fn() { let num = 0; num = 55; }
|
||||
fn() { num := 0; num = 55; }
|
||||
`,
|
||||
expectedConstants: []interface{}{
|
||||
0,
|
||||
@@ -760,6 +755,7 @@ func TestAssignmentStatementScopes(t *testing.T) {
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpSetLocal, 0),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpConstant, 1),
|
||||
code.Make(code.OpAssignLocal, 0),
|
||||
code.Make(code.OpNull),
|
||||
@@ -780,7 +776,7 @@ func TestLetStatementScopes(t *testing.T) {
|
||||
tests := []compilerTestCase{
|
||||
{
|
||||
input: `
|
||||
let num = 55;
|
||||
num := 55;
|
||||
fn() { return num }
|
||||
`,
|
||||
expectedConstants: []interface{}{
|
||||
@@ -793,6 +789,7 @@ func TestLetStatementScopes(t *testing.T) {
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpSetGlobal, 0),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpClosure, 1, 0),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
@@ -800,7 +797,7 @@ func TestLetStatementScopes(t *testing.T) {
|
||||
{
|
||||
input: `
|
||||
fn() {
|
||||
let num = 55;
|
||||
num := 55;
|
||||
return num
|
||||
}
|
||||
`,
|
||||
@@ -809,6 +806,7 @@ func TestLetStatementScopes(t *testing.T) {
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpSetLocal, 0),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpReturn),
|
||||
},
|
||||
@@ -821,8 +819,8 @@ func TestLetStatementScopes(t *testing.T) {
|
||||
{
|
||||
input: `
|
||||
fn() {
|
||||
let a = 55;
|
||||
let b = 77;
|
||||
a := 55;
|
||||
b := 77;
|
||||
return a + b
|
||||
}
|
||||
`,
|
||||
@@ -832,8 +830,10 @@ func TestLetStatementScopes(t *testing.T) {
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpSetLocal, 0),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpConstant, 1),
|
||||
code.Make(code.OpSetLocal, 1),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpGetLocal, 1),
|
||||
code.Make(code.OpAdd),
|
||||
@@ -847,8 +847,8 @@ func TestLetStatementScopes(t *testing.T) {
|
||||
},
|
||||
{
|
||||
input: `
|
||||
let a = 0;
|
||||
let a = a + 1;
|
||||
a := 0;
|
||||
a := a + 1;
|
||||
`,
|
||||
expectedConstants: []interface{}{
|
||||
0,
|
||||
@@ -857,10 +857,12 @@ func TestLetStatementScopes(t *testing.T) {
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpSetGlobal, 0),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpGetGlobal, 0),
|
||||
code.Make(code.OpConstant, 1),
|
||||
code.Make(code.OpAdd),
|
||||
code.Make(code.OpSetGlobal, 0),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -912,7 +914,7 @@ func TestRecursiveFunctions(t *testing.T) {
|
||||
tests := []compilerTestCase{
|
||||
{
|
||||
input: `
|
||||
let countDown = fn(x) { return countDown(x - 1); };
|
||||
countDown := fn(x) { return countDown(x - 1); };
|
||||
countDown(1);
|
||||
`,
|
||||
expectedConstants: []interface{}{
|
||||
@@ -930,6 +932,7 @@ func TestRecursiveFunctions(t *testing.T) {
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpClosure, 1, 0),
|
||||
code.Make(code.OpSetGlobal, 0),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpGetGlobal, 0),
|
||||
code.Make(code.OpConstant, 2),
|
||||
code.Make(code.OpCall, 1),
|
||||
@@ -938,8 +941,8 @@ func TestRecursiveFunctions(t *testing.T) {
|
||||
},
|
||||
{
|
||||
input: `
|
||||
let wrapper = fn() {
|
||||
let countDown = fn(x) { return countDown(x - 1); };
|
||||
wrapper := fn() {
|
||||
countDown := fn(x) { return countDown(x - 1); };
|
||||
return countDown(1);
|
||||
};
|
||||
wrapper();
|
||||
@@ -958,6 +961,7 @@ func TestRecursiveFunctions(t *testing.T) {
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpClosure, 1, 0),
|
||||
code.Make(code.OpSetLocal, 0),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpGetLocal, 0),
|
||||
code.Make(code.OpConstant, 2),
|
||||
code.Make(code.OpCall, 1),
|
||||
@@ -967,6 +971,7 @@ func TestRecursiveFunctions(t *testing.T) {
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpClosure, 3, 0),
|
||||
code.Make(code.OpSetGlobal, 0),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpGetGlobal, 0),
|
||||
code.Make(code.OpCall, 0),
|
||||
code.Make(code.OpPop),
|
||||
|
||||
Reference in New Issue
Block a user