Eval complete
This commit is contained in:
@@ -120,7 +120,9 @@ func TestReturnStatements(t *testing.T) {
|
||||
{"return 10; 9;", 10},
|
||||
{"return 2 * 5; 9;", 10},
|
||||
{"9; return 2 * 5; 9;", 10},
|
||||
{`
|
||||
{"if (10 > 1) { return 10; }", 10},
|
||||
{
|
||||
`
|
||||
if (10 > 1) {
|
||||
if (10 > 1) {
|
||||
return 10;
|
||||
@@ -128,9 +130,28 @@ func TestReturnStatements(t *testing.T) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
`,
|
||||
`,
|
||||
10,
|
||||
},
|
||||
{
|
||||
`
|
||||
let f = fn(x) {
|
||||
return x;
|
||||
x + 10;
|
||||
};
|
||||
f(10);`,
|
||||
10,
|
||||
},
|
||||
{
|
||||
`
|
||||
let f = fn(x) {
|
||||
let result = x + 10;
|
||||
return result;
|
||||
return 10;
|
||||
};
|
||||
f(10);`,
|
||||
20,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -219,6 +240,60 @@ func TestLetStatements(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFunctionObject(t *testing.T) {
|
||||
input := "fn(x) { x + 2; };"
|
||||
|
||||
evaluated := testEval(input)
|
||||
fn, ok := evaluated.(*object.Function)
|
||||
if !ok {
|
||||
t.Fatalf("object is not Function. got=%T (%+v)", evaluated, evaluated)
|
||||
}
|
||||
|
||||
if len(fn.Parameters) != 1 {
|
||||
t.Fatalf("function has wrong parameters. Parameters=%+v", fn.Parameters)
|
||||
}
|
||||
|
||||
if fn.Parameters[0].String() != "x" {
|
||||
t.Fatalf("parameter is not 'x'. got=%q", fn.Parameters[0])
|
||||
}
|
||||
|
||||
expectedBody := "(x + 2)"
|
||||
|
||||
if fn.Body.String() != expectedBody {
|
||||
t.Fatalf("body is not %q. got=%q", expectedBody, fn.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestFunctionApplication(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
expected int64
|
||||
}{
|
||||
{"let identity = fn(x) { x; }; identity(5);", 5},
|
||||
{"let identity = fn(x) { return x; }; identity(5);", 5},
|
||||
{"let double = fn(x) { x * 2; }; double(5);", 10},
|
||||
{"let add = fn(x, y) { x + y; }; add(5, 5);", 10},
|
||||
{"let add = fn(x, y) { x + y; }; add(5 + 5, add(5, 5));", 20},
|
||||
{"fn(x) { x; }(5)", 5},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
testIntegerObject(t, testEval(tt.input), tt.expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClosures(t *testing.T) {
|
||||
input := `
|
||||
let newAdder = fn(x) {
|
||||
fn(y) { x + y };
|
||||
};
|
||||
|
||||
let addTwo = newAdder(2);
|
||||
addTwo(2);`
|
||||
|
||||
testIntegerObject(t, testEval(input), 4)
|
||||
}
|
||||
|
||||
func testEval(input string) object.Object {
|
||||
l := lexer.New(input)
|
||||
p := parser.New(l)
|
||||
|
||||
Reference in New Issue
Block a user