package vm_test import ( "testing" ) func TestFunction(t *testing.T) { // function with no "return" statement returns "invalid" value. expect(t, `f1 = func() {}; out = f1();`, undefined()) expect(t, `f1 = func() {}; f2 = func() { return f1(); }; f1(); out = f2();`, undefined()) expect(t, `f = func(x) { x; }; out = f(5);`, undefined()) expect(t, `f = func(x) { return x; }; out = f(5);`, 5) expect(t, `f = func(x) { return x * 2; }; out = f(5);`, 10) expect(t, `f = func(x, y) { return x + y; }; out = f(5, 5);`, 10) expect(t, `f = func(x, y) { return x + y; }; out = f(5 + 5, f(5, 5));`, 20) expect(t, `out = func(x) { return x; }(5)`, 5) expect(t, `x = 10; f = func(x) { return x; }; f(5); out = x;`, 10) expect(t, ` f2 = func(a) { f1 = func(a) { return a * 2; }; return f1(a) * 3; }; out = f2(10); `, 60) // closures expect(t, ` newAdder = func(x) { return func(y) { return x + y }; }; add2 = newAdder(2); out = add2(5); `, 7) // function as a argument expect(t, ` add = func(a, b) { return a + b }; sub = func(a, b) { return a - b }; applyFunc = func(a, b, f) { return f(a, b) }; out = applyFunc(applyFunc(2, 2, add), 3, sub); `, 1) expect(t, `f1 = func() { return 5 + 10; }; out = f1();`, 15) expect(t, `f1 = func() { return 1 }; f2 = func() { return 2 }; out = f1() + f2()`, 3) expect(t, `f1 = func() { return 1 }; f2 = func() { return f1() + 2 }; f3 = func() { return f2() + 3 }; out = f3()`, 6) expect(t, `f1 = func() { return 99; 100 }; out = f1();`, 99) expect(t, `f1 = func() { return 99; return 100 }; out = f1();`, 99) expect(t, `f1 = func() { return 33; }; f2 = func() { return f1 }; out = f2()();`, 33) expect(t, `one = func() { one = 1; return one }; out = one()`, 1) expect(t, `three = func() { one = 1; two = 2; return one + two }; out = three()`, 3) expect(t, `three = func() { one = 1; two = 2; return one + two }; seven = func() { three = 3; four = 4; return three + four }; out = three() + seven()`, 10) expect(t, `foo1 = func() { foo = 50; return foo}; foo2 = func() { foo = 100; return foo }; out = foo1() + foo2()`, 150) expect(t, ` g = 50; minusOne = func() { n = 1; return g - n; }; minusTwo = func() { n = 2; return g - n; }; out = minusOne() + minusTwo() `, 97) expect(t, ` f1 = func() { f2 = func() { return 1; } return f2 }; out = f1()() `, 1) expect(t, ` f1 = func(a) { return a; }; out = f1(4)`, 4) expect(t, ` f1 = func(a, b) { return a + b; }; out = f1(1, 2)`, 3) expect(t, ` sum = func(a, b) { c = a + b; return c; }; out = sum(1, 2);`, 3) expect(t, ` sum = func(a, b) { c = a + b; return c; }; out = sum(1, 2) + sum(3, 4);`, 10) expect(t, ` sum = func(a, b) { c = a + b return c }; outer = func() { return sum(1, 2) + sum(3, 4) }; out = outer();`, 10) expect(t, ` g = 10; sum = func(a, b) { c = a + b; return c + g; } outer = func() { return sum(1, 2) + sum(3, 4) + g; } out = outer() + g `, 50) expectError(t, `func() { return 1; }(1)`) expectError(t, `func(a) { return a; }()`) expectError(t, `func(a, b) { return a + b; }(1)`) expect(t, ` f1 = func(a) { return func() { return a; }; }; f2 = f1(99); out = f2() `, 99) expect(t, ` f1 = func(a, b) { return func(c) { return a + b + c }; }; f2 = f1(1, 2); out = f2(8); `, 11) expect(t, ` f1 = func(a, b) { c = a + b; return func(d) { return c + d }; }; f2 = f1(1, 2); out = f2(8); `, 11) expect(t, ` f1 = func(a, b) { c = a + b; return func(d) { e = d + c; return func(f) { return e + f }; } }; f2 = f1(1, 2); f3 = f2(3); out = f3(8); `, 14) expect(t, ` a = 1; f1 = func(b) { return func(c) { return func(d) { return a + b + c + d } }; }; f2 = f1(2); f3 = f2(3); out = f3(8); `, 14) expect(t, ` f1 = func(a, b) { one = func() { return a; }; two = func() { return b; }; return func() { return one() + two(); } }; f2 = f1(9, 90); out = f2(); `, 99) // fibonacci expect(t, ` fib = func(x) { if(x == 0) { return 0; } else { if(x == 1) { return 1; } else { return fib(x-1) + fib(x-2); } } }; out = fib(15); `, 610) }