assert and test changes
Some checks failed
Build / build (push) Successful in 1m18s
Test / build (push) Failing after 11m19s

This commit is contained in:
Chuck Smith
2024-03-19 08:15:11 -04:00
parent 0b1ed43ae5
commit 60d27f09d7
7 changed files with 164 additions and 142 deletions

View File

@@ -91,9 +91,7 @@ func (c *Compiler) Compile(node ast.Node) error {
return err return err
} }
if !c.lastInstructionIs(code.OpNoop) {
c.emit(code.OpPop) c.emit(code.OpPop)
}
case *ast.InfixExpression: case *ast.InfixExpression:
if node.Operator == "<" || node.Operator == "<=" { if node.Operator == "<" || node.Operator == "<=" {
@@ -182,9 +180,6 @@ func (c *Compiler) Compile(node ast.Node) error {
} }
case *ast.IfExpression: case *ast.IfExpression:
if c.lastInstructionIs(code.OpPop) {
c.removeLastPop()
}
c.l++ c.l++
err := c.Compile(node.Condition) err := c.Compile(node.Condition)
c.l-- c.l--
@@ -240,6 +235,14 @@ func (c *Compiler) Compile(node ast.Node) error {
} }
c.l-- c.l--
if c.lastInstructionIs(code.OpPop) {
c.removeLastPop()
} else {
if !c.lastInstructionIs(code.OpReturn) {
c.emit(code.OpNull)
}
}
case *ast.AssignmentStatement: case *ast.AssignmentStatement:
symbol, ok := c.symbolTable.Resolve(node.Name.Value) symbol, ok := c.symbolTable.Resolve(node.Name.Value)
if !ok { if !ok {
@@ -366,8 +369,13 @@ func (c *Compiler) Compile(node ast.Node) error {
if c.lastInstructionIs(code.OpPop) { if c.lastInstructionIs(code.OpPop) {
c.replaceLastPopWithReturn() c.replaceLastPopWithReturn()
} }
// If the function doesn't end with a return statement add one with a
// `return null;` and also handle the edge-case of empty functions.
if !c.lastInstructionIs(code.OpReturn) { if !c.lastInstructionIs(code.OpReturn) {
if !c.lastInstructionIs(code.OpNull) {
c.emit(code.OpNull) c.emit(code.OpNull)
}
c.emit(code.OpReturn) c.emit(code.OpReturn)
} }

View File

@@ -231,15 +231,15 @@ func TestConditionals(t *testing.T) {
code.Make(code.OpJumpNotTruthy, 10), code.Make(code.OpJumpNotTruthy, 10),
// 0004 // 0004
code.Make(code.OpConstant, 0), code.Make(code.OpConstant, 0),
// 0007 // 0008
code.Make(code.OpJump, 13), code.Make(code.OpJump, 13),
// 0010 // 0011
code.Make(code.OpConstant, 1), code.Make(code.OpConstant, 1),
// 0013 // 0013
code.Make(code.OpPop), code.Make(code.OpPop),
// 0014 // 0014
code.Make(code.OpConstant, 2), code.Make(code.OpConstant, 2),
// 0017 // 0018
code.Make(code.OpPop), code.Make(code.OpPop),
}, },
}, },
@@ -256,28 +256,34 @@ func TestConditionals(t *testing.T) {
// 0006 // 0006
code.Make(code.OpTrue), code.Make(code.OpTrue),
// 0007 // 0007
code.Make(code.OpJumpNotTruthy, 19), code.Make(code.OpJumpNotTruthy, 20),
// 0010 // 0010
code.Make(code.OpConstant, 1), code.Make(code.OpConstant, 1),
// 0013 // 0013
code.Make(code.OpAssignGlobal, 0), code.Make(code.OpAssignGlobal, 0),
// 0016 // 0016
code.Make(code.OpJump, 20),
// 0019
code.Make(code.OpNull), code.Make(code.OpNull),
// 0017
code.Make(code.OpJump, 21),
// 0020 // 0020
code.Make(code.OpFalse),
// 0021
code.Make(code.OpJumpNotTruthy, 33),
// 0024
code.Make(code.OpConstant, 2),
// 0027
code.Make(code.OpAssignGlobal, 0),
// 0030
code.Make(code.OpJump, 34),
// 0033
code.Make(code.OpNull), code.Make(code.OpNull),
// 0034 // 0021
code.Make(code.OpPop),
// 0022
code.Make(code.OpFalse),
// 0023
code.Make(code.OpJumpNotTruthy, 36),
// 0025
code.Make(code.OpConstant, 2),
// 0029
code.Make(code.OpAssignGlobal, 0),
// 0032
code.Make(code.OpNull),
// 0033
code.Make(code.OpJump, 37),
// 0036
code.Make(code.OpNull),
// 0037
code.Make(code.OpPop), code.Make(code.OpPop),
}, },
}, },
@@ -487,7 +493,7 @@ func TestIndexExpressions(t *testing.T) {
func TestFunctions(t *testing.T) { func TestFunctions(t *testing.T) {
tests := []compilerTestCase{ tests := []compilerTestCase{
{ {
input: "fn() { return 5 + 10 }", input: `fn() { return 5 + 10 }`,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
5, 5,
10, 10,
@@ -504,24 +510,7 @@ func TestFunctions(t *testing.T) {
}, },
}, },
{ {
input: `fn() { 5 + 10 }`, input: `fn() { 1; return 2 }`,
expectedConstants: []interface{}{
5,
10,
[]code.Instructions{
code.Make(code.OpConstant, 0),
code.Make(code.OpConstant, 1),
code.Make(code.OpAdd),
code.Make(code.OpReturn),
},
},
expectedInstructions: []code.Instructions{
code.Make(code.OpClosure, 2, 0),
code.Make(code.OpPop),
},
},
{
input: `fn() { 1; 2 }`,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
1, 1,
2, 2,
@@ -566,8 +555,8 @@ func TestClosures(t *testing.T) {
tests := []compilerTestCase{ tests := []compilerTestCase{
{ {
input: `fn(a) { input: `fn(a) {
fn(b) { return fn(b) {
a + b return a + b
} }
} }
`, `,
@@ -592,9 +581,9 @@ func TestClosures(t *testing.T) {
{ {
input: ` input: `
fn(a) { fn(a) {
fn(b) { return fn(b) {
fn(c) { return fn(c) {
a + b + c return a + b + c
} }
} }
}; };
@@ -632,13 +621,13 @@ func TestClosures(t *testing.T) {
fn() { fn() {
let a = 66; let a = 66;
fn() { return fn() {
let b = 77; let b = 77;
fn() { return fn() {
let c = 88; let c = 88;
global + a + b + c; return global + a + b + c;
} }
} }
} }
@@ -737,7 +726,7 @@ func TestCompilerScopes(t *testing.T) {
func TestFunctionCalls(t *testing.T) { func TestFunctionCalls(t *testing.T) {
tests := []compilerTestCase{ tests := []compilerTestCase{
{ {
input: `fn() { 24 }();`, input: `fn() { return 24 }();`,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
24, 24,
[]code.Instructions{ []code.Instructions{
@@ -753,7 +742,7 @@ func TestFunctionCalls(t *testing.T) {
}, },
{ {
input: ` input: `
let noArg = fn() { 24 }; let noArg = fn() { return 24 };
noArg(); noArg();
`, `,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
@@ -773,7 +762,7 @@ func TestFunctionCalls(t *testing.T) {
}, },
{ {
input: ` input: `
let oneArg = fn(a) { a }; let oneArg = fn(a) { return a };
oneArg(24); oneArg(24);
`, `,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
@@ -794,7 +783,7 @@ func TestFunctionCalls(t *testing.T) {
}, },
{ {
input: ` input: `
let manyArg = fn(a, b, c) { a; b; c }; let manyArg = fn(a, b, c) { a; b; return c };
manyArg(24, 25, 26); manyArg(24, 25, 26);
`, `,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
@@ -881,7 +870,7 @@ func TestLetStatementScopes(t *testing.T) {
{ {
input: ` input: `
let num = 55; let num = 55;
fn() { num } fn() { return num }
`, `,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
55, 55,
@@ -901,7 +890,7 @@ func TestLetStatementScopes(t *testing.T) {
input: ` input: `
fn() { fn() {
let num = 55; let num = 55;
num return num
} }
`, `,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
@@ -923,7 +912,7 @@ func TestLetStatementScopes(t *testing.T) {
fn() { fn() {
let a = 55; let a = 55;
let b = 77; let b = 77;
a + b return a + b
} }
`, `,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
@@ -977,11 +966,11 @@ func TestBuiltins(t *testing.T) {
`, `,
expectedConstants: []interface{}{1}, expectedConstants: []interface{}{1},
expectedInstructions: []code.Instructions{ expectedInstructions: []code.Instructions{
code.Make(code.OpGetBuiltin, 4), code.Make(code.OpGetBuiltin, 5),
code.Make(code.OpArray, 0), code.Make(code.OpArray, 0),
code.Make(code.OpCall, 1), code.Make(code.OpCall, 1),
code.Make(code.OpPop), code.Make(code.OpPop),
code.Make(code.OpGetBuiltin, 7), code.Make(code.OpGetBuiltin, 8),
code.Make(code.OpArray, 0), code.Make(code.OpArray, 0),
code.Make(code.OpConstant, 0), code.Make(code.OpConstant, 0),
code.Make(code.OpCall, 2), code.Make(code.OpCall, 2),
@@ -989,10 +978,10 @@ func TestBuiltins(t *testing.T) {
}, },
}, },
{ {
input: `fn() { len([]) }`, input: `fn() { return len([]) }`,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
[]code.Instructions{ []code.Instructions{
code.Make(code.OpGetBuiltin, 4), code.Make(code.OpGetBuiltin, 5),
code.Make(code.OpArray, 0), code.Make(code.OpArray, 0),
code.Make(code.OpCall, 1), code.Make(code.OpCall, 1),
code.Make(code.OpReturn), code.Make(code.OpReturn),
@@ -1012,7 +1001,7 @@ func TestRecursiveFunctions(t *testing.T) {
tests := []compilerTestCase{ tests := []compilerTestCase{
{ {
input: ` input: `
let countDown = fn(x) { countDown(x - 1); }; let countDown = fn(x) { return countDown(x - 1); };
countDown(1); countDown(1);
`, `,
expectedConstants: []interface{}{ expectedConstants: []interface{}{
@@ -1039,8 +1028,8 @@ func TestRecursiveFunctions(t *testing.T) {
{ {
input: ` input: `
let wrapper = fn() { let wrapper = fn() {
let countDown = fn(x) { countDown(x - 1); }; let countDown = fn(x) { return countDown(x - 1); };
countDown(1); return countDown(1);
}; };
wrapper(); wrapper();
`, `,
@@ -1088,15 +1077,15 @@ func TestIteration(t *testing.T) {
// 0000 // 0000
code.Make(code.OpTrue), code.Make(code.OpTrue),
// 0001 // 0001
code.Make(code.OpJumpNotTruthy, 11), code.Make(code.OpJumpNotTruthy, 10),
// 0004 // 0004
code.Make(code.OpConstant, 0), code.Make(code.OpConstant, 0),
// 0007 // 0007
code.Make(code.OpPop),
// 0008
code.Make(code.OpJump, 0), code.Make(code.OpJump, 0),
// 0011 // 0010
code.Make(code.OpNoop), code.Make(code.OpNoop),
// 0011
code.Make(code.OpPop),
}, },
}, },
} }

View File

@@ -40,4 +40,4 @@ let map = fn(arr, f) {
}; };
let numbers = [1, 1 + 1, 4 - 1, 2 * 2, 2 + 3, 12 / 2]; let numbers = [1, 1 + 1, 4 - 1, 2 * 2, 2 + 3, 12 / 2];
//map(numbers, fibonacci); map(numbers, fibonacci);

View File

@@ -5,4 +5,4 @@ let fact = fn(n) {
return n * fact(n - 1) return n * fact(n - 1)
} }
print(fact(5) assert(fact(5) == 120, "fact(5) != 120")

View File

@@ -20,6 +20,7 @@ var Builtins = map[string]*Builtin{
"push": {Name: "push", Fn: Push}, "push": {Name: "push", Fn: Push},
"pop": {Name: "pop", Fn: Pop}, "pop": {Name: "pop", Fn: Pop},
"exit": {Name: "exit", Fn: Exit}, "exit": {Name: "exit", Fn: Exit},
"assert": {Name: "assert", Fn: Assert},
} }
// BuiltinsIndex ... // BuiltinsIndex ...
@@ -213,3 +214,26 @@ func Exit(args ...Object) Object {
} }
return nil return nil
} }
// Assert ...
func Assert(args ...Object) Object {
if len(args) != 2 {
return newError("wrong number of arguments. got=%d, want=2",
len(args))
}
if args[0].Type() != BOOLEAN_OBJ {
return newError("argument #1 to `assert` must be BOOLEAN, got %s",
args[0].Type())
}
if args[1].Type() != STRING_OBJ {
return newError("argument #2 to `assert` must be STRING, got %s",
args[0].Type())
}
if !args[0].(*Boolean).Value {
fmt.Printf("Assertion Error: %s", args[1].(*String).Value)
os.Exit(1)
}
return nil
}

View File

@@ -119,11 +119,7 @@ func (vm *VM) Run() error {
} }
case code.OpPop: case code.OpPop:
// This makes things like this work:
// >> let x = 1; if (x == 1) { x = 2 }
if vm.sp > 0 {
vm.pop() vm.pop()
}
case code.OpTrue: case code.OpTrue:
err := vm.push(True) err := vm.push(True)

View File

@@ -259,7 +259,12 @@ func TestConditionals(t *testing.T) {
{"if (1 > 2) { 10 } else { 20 }", 20}, {"if (1 > 2) { 10 } else { 20 }", 20},
{"if (1 > 2) { 10 }", Null}, {"if (1 > 2) { 10 }", Null},
{"if (false) { 10 }", Null}, {"if (false) { 10 }", Null},
//{"if ((if (false) { 10 })) { 10 } else { 20 }", 20}, {"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}, {"let x = 0; if (true) { x = 1; }; if (false) { x = 2; }; x", 1},
} }
@@ -346,24 +351,24 @@ func TestCallingFunctionsWithoutArguments(t *testing.T) {
tests := []vmTestCase{ tests := []vmTestCase{
{ {
input: ` input: `
let fivePlusTen = fn() { 5 + 10; }; let fivePlusTen = fn() { return 5 + 10; };
fivePlusTen(); fivePlusTen();
`, `,
expected: 15, expected: 15,
}, },
{ {
input: ` input: `
let one = fn() { 1; }; let one = fn() { return 1; };
let two = fn() { 2; }; let two = fn() { return 2; };
one() + two() one() + two()
`, `,
expected: 3, expected: 3,
}, },
{ {
input: ` input: `
let a = fn() { 1 }; let a = fn() { return 1 };
let b = fn() { a() + 1 }; let b = fn() { return a() + 1 };
let c = fn() { b() + 1 }; let c = fn() { return b() + 1 };
c(); c();
`, `,
expected: 3, expected: 3,
@@ -421,8 +426,8 @@ func TestFirstClassFunctions(t *testing.T) {
tests := []vmTestCase{ tests := []vmTestCase{
{ {
input: ` input: `
let returnsOne = fn() { 1; }; let returnsOne = fn() { return 1; };
let returnsOneReturner = fn() { returnsOne; }; let returnsOneReturner = fn() { return returnsOne; };
returnsOneReturner()(); returnsOneReturner()();
`, `,
expected: 1, expected: 1,
@@ -430,7 +435,7 @@ func TestFirstClassFunctions(t *testing.T) {
{ {
input: ` input: `
let returnsOneReturner = fn() { let returnsOneReturner = fn() {
let returnsOne = fn() { 1; }; let returnsOne = fn() { return 1; };
returnsOne; returnsOne;
}; };
returnsOneReturner()(); returnsOneReturner()();
@@ -444,32 +449,32 @@ func TestFirstClassFunctions(t *testing.T) {
func TestCallingFunctionsWithBindings(t *testing.T) { func TestCallingFunctionsWithBindings(t *testing.T) {
tests := []vmTestCase{ tests := []vmTestCase{
//{
// input: `
//let one = fn() { let one = 1; one };
//one();
//`,
// expected: 1,
//},
{ {
input: ` input: `
let oneAndTwo = fn() { let one = 1; let two = 2; one + two; }; let one = fn() { let one = 1; return one };
one();
`,
expected: 1,
},
{
input: `
let oneAndTwo = fn() { let one = 1; let two = 2; return one + two; };
oneAndTwo(); oneAndTwo();
`, `,
expected: 3, expected: 3,
}, },
{ {
input: ` input: `
let oneAndTwo = fn() { let one = 1; let two = 2; one + two; }; let oneAndTwo = fn() { let one = 1; let two = 2; return one + two; };
let threeAndFour = fn() { let three = 3; let four = 4; three + four; }; let threeAndFour = fn() { let three = 3; let four = 4; return three + four; };
oneAndTwo() + threeAndFour(); oneAndTwo() + threeAndFour();
`, `,
expected: 10, expected: 10,
}, },
{ {
input: ` input: `
let firstFoobar = fn() { let foobar = 50; foobar; }; let firstFoobar = fn() { let foobar = 50; return foobar; };
let secondFoobar = fn() { let foobar = 100; foobar; }; let secondFoobar = fn() { let foobar = 100; return foobar; };
firstFoobar() + secondFoobar(); firstFoobar() + secondFoobar();
`, `,
expected: 150, expected: 150,
@@ -479,11 +484,11 @@ func TestCallingFunctionsWithBindings(t *testing.T) {
let globalSeed = 50; let globalSeed = 50;
let minusOne = fn() { let minusOne = fn() {
let num = 1; let num = 1;
globalSeed - num; return globalSeed - num;
} }
let minusTwo = fn() { let minusTwo = fn() {
let num = 2; let num = 2;
globalSeed - num; return globalSeed - num;
} }
minusOne() + minusTwo(); minusOne() + minusTwo();
`, `,
@@ -498,14 +503,14 @@ func TestCallingFunctionsWithArgumentsAndBindings(t *testing.T) {
tests := []vmTestCase{ tests := []vmTestCase{
{ {
input: ` input: `
let identity = fn(a) { a; }; let identity = fn(a) { return a; };
identity(4); identity(4);
`, `,
expected: 4, expected: 4,
}, },
{ {
input: ` input: `
let sum = fn(a, b) { a + b; }; let sum = fn(a, b) { return a + b; };
sum(1, 2); sum(1, 2);
`, `,
expected: 3, expected: 3,
@@ -514,7 +519,7 @@ func TestCallingFunctionsWithArgumentsAndBindings(t *testing.T) {
input: ` input: `
let sum = fn(a, b) { let sum = fn(a, b) {
let c = a + b; let c = a + b;
c; return c;
}; };
sum(1, 2); sum(1, 2);
`, `,
@@ -524,7 +529,7 @@ func TestCallingFunctionsWithArgumentsAndBindings(t *testing.T) {
input: ` input: `
let sum = fn(a, b) { let sum = fn(a, b) {
let c = a + b; let c = a + b;
c; return c;
}; };
sum(1, 2) + sum(3, 4);`, sum(1, 2) + sum(3, 4);`,
expected: 10, expected: 10,
@@ -533,10 +538,10 @@ func TestCallingFunctionsWithArgumentsAndBindings(t *testing.T) {
input: ` input: `
let sum = fn(a, b) { let sum = fn(a, b) {
let c = a + b; let c = a + b;
c; return c;
}; };
let outer = fn() { let outer = fn() {
sum(1, 2) + sum(3, 4); return sum(1, 2) + sum(3, 4);
}; };
outer(); outer();
`, `,
@@ -548,11 +553,11 @@ func TestCallingFunctionsWithArgumentsAndBindings(t *testing.T) {
let sum = fn(a, b) { let sum = fn(a, b) {
let c = a + b; let c = a + b;
c + globalNum; return c + globalNum;
}; };
let outer = fn() { let outer = fn() {
sum(1, 2) + sum(3, 4) + globalNum; return sum(1, 2) + sum(3, 4) + globalNum;
}; };
outer() + globalNum; outer() + globalNum;
@@ -567,15 +572,15 @@ func TestCallingFunctionsWithArgumentsAndBindings(t *testing.T) {
func TestCallingFunctionsWithWrongArguments(t *testing.T) { func TestCallingFunctionsWithWrongArguments(t *testing.T) {
tests := []vmTestCase{ tests := []vmTestCase{
{ {
input: `fn() { 1; }(1);`, input: `fn() { return 1; }(1);`,
expected: `wrong number of arguments: want=0, got=1`, expected: `wrong number of arguments: want=0, got=1`,
}, },
{ {
input: `fn(a) { a; }();`, input: `fn(a) { return a; }();`,
expected: `wrong number of arguments: want=1, got=0`, expected: `wrong number of arguments: want=1, got=0`,
}, },
{ {
input: `fn(a, b) { a + b; }(1);`, input: `fn(a, b) { return a + b; }(1);`,
expected: `wrong number of arguments: want=2, got=1`, expected: `wrong number of arguments: want=2, got=1`,
}, },
} }
@@ -658,7 +663,7 @@ func TestClosures(t *testing.T) {
{ {
input: ` input: `
let newClosure = fn(a) { let newClosure = fn(a) {
fn() { a; }; fn() { return a; };
}; };
let closure = newClosure(99); let closure = newClosure(99);
closure(); closure();
@@ -668,7 +673,7 @@ func TestClosures(t *testing.T) {
{ {
input: ` input: `
let newAdder = fn(a, b) { let newAdder = fn(a, b) {
fn(c) { a + b + c }; fn(c) { return a + b + c };
}; };
let adder = newAdder(1, 2); let adder = newAdder(1, 2);
adder(8); adder(8);
@@ -679,7 +684,7 @@ func TestClosures(t *testing.T) {
input: ` input: `
let newAdder = fn(a, b) { let newAdder = fn(a, b) {
let c = a + b; let c = a + b;
fn(d) { c + d }; fn(d) { return c + d };
}; };
let adder = newAdder(1, 2); let adder = newAdder(1, 2);
adder(8); adder(8);
@@ -690,9 +695,9 @@ func TestClosures(t *testing.T) {
input: ` input: `
let newAdderOuter = fn(a, b) { let newAdderOuter = fn(a, b) {
let c = a + b; let c = a + b;
fn(d) { return fn(d) {
let e = d + c; let e = d + c;
fn(f) { e + f; }; return fn(f) { return e + f; };
}; };
}; };
let newAdderInner = newAdderOuter(1, 2) let newAdderInner = newAdderOuter(1, 2)
@@ -705,8 +710,8 @@ func TestClosures(t *testing.T) {
input: ` input: `
let a = 1; let a = 1;
let newAdderOuter = fn(b) { let newAdderOuter = fn(b) {
fn(c) { return fn(c) {
fn(d) { a + b + c + d }; return fn(d) { return a + b + c + d };
}; };
}; };
let newAdderInner = newAdderOuter(2) let newAdderInner = newAdderOuter(2)
@@ -718,9 +723,9 @@ func TestClosures(t *testing.T) {
{ {
input: ` input: `
let newClosure = fn(a, b) { let newClosure = fn(a, b) {
let one = fn() { a; }; let one = fn() { return a; };
let two = fn() { b; }; let two = fn() { return b; };
fn() { one() + two(); }; return fn() { return one() + two(); };
}; };
let closure = newClosure(9, 90); let closure = newClosure(9, 90);
closure(); closure();
@@ -740,7 +745,7 @@ func TestRecursiveFunctions(t *testing.T) {
if (x == 0) { if (x == 0) {
return 0; return 0;
} else { } else {
countDown(x - 1); return countDown(x - 1);
} }
}; };
countDown(1); countDown(1);
@@ -753,11 +758,11 @@ func TestRecursiveFunctions(t *testing.T) {
if (x == 0) { if (x == 0) {
return 0; return 0;
} else { } else {
countDown(x - 1); return countDown(x - 1);
} }
}; };
let wrapper = fn() { let wrapper = fn() {
countDown(1); return countDown(1);
}; };
wrapper(); wrapper();
`, `,
@@ -770,10 +775,10 @@ func TestRecursiveFunctions(t *testing.T) {
if (x == 0) { if (x == 0) {
return 0; return 0;
} else { } else {
countDown(x - 1); return countDown(x - 1);
} }
}; };
countDown(1); return countDown(1);
}; };
wrapper(); wrapper();
`, `,
@@ -795,7 +800,7 @@ func TestRecursiveFibonacci(t *testing.T) {
if (x == 1) { if (x == 1) {
return 1; return 1;
} else { } else {
fibonacci(x - 1) + fibonacci(x - 2); return fibonacci(x - 1) + fibonacci(x - 2);
} }
} }
}; };