61890b15cb
* wip * move print and JSON functions to modules * builtin functions are not replacable now * builtin functions are added for default nil symbol table * importables: builtin modules and source modules * refactoring runtime tests * fix tests * update documentation * cleanup * clean up cli * fix REPL prints
111 lines
1.6 KiB
Go
111 lines
1.6 KiB
Go
package runtime_test
|
|
|
|
import "testing"
|
|
|
|
func TestTailCall(t *testing.T) {
|
|
expect(t, `
|
|
fac := func(n, a) {
|
|
if n == 1 {
|
|
return a
|
|
}
|
|
return fac(n-1, n*a)
|
|
}
|
|
out = fac(5, 1)`, nil, 120)
|
|
|
|
expect(t, `
|
|
fac := func(n, a) {
|
|
if n == 1 {
|
|
return a
|
|
}
|
|
x := {foo: fac} // indirection for test
|
|
return x.foo(n-1, n*a)
|
|
}
|
|
out = fac(5, 1)`, nil, 120)
|
|
|
|
expect(t, `
|
|
fib := func(x, s) {
|
|
if x == 0 {
|
|
return 0 + s
|
|
} else if x == 1 {
|
|
return 1 + s
|
|
}
|
|
return fib(x-1, fib(x-2, s))
|
|
}
|
|
out = fib(15, 0)`, nil, 610)
|
|
|
|
expect(t, `
|
|
fib := func(n, a, b) {
|
|
if n == 0 {
|
|
return a
|
|
} else if n == 1 {
|
|
return b
|
|
}
|
|
return fib(n-1, b, a + b)
|
|
}
|
|
out = fib(15, 0, 1)`, nil, 610)
|
|
|
|
// global variable and no return value
|
|
expect(t, `
|
|
out = 0
|
|
foo := func(a) {
|
|
if a == 0 {
|
|
return
|
|
}
|
|
out += a
|
|
foo(a-1)
|
|
}
|
|
foo(10)`, nil, 55)
|
|
|
|
expect(t, `
|
|
f1 := func() {
|
|
f2 := 0 // TODO: this might be fixed in the future
|
|
f2 = func(n, s) {
|
|
if n == 0 { return s }
|
|
return f2(n-1, n + s)
|
|
}
|
|
return f2(5, 0)
|
|
}
|
|
out = f1()`, nil, 15)
|
|
|
|
// tail-call replacing loop
|
|
// without tail-call optimization, this code will cause stack overflow
|
|
expect(t, `
|
|
iter := func(n, max) {
|
|
if n == max {
|
|
return n
|
|
}
|
|
|
|
return iter(n+1, max)
|
|
}
|
|
out = iter(0, 9999)
|
|
`, nil, 9999)
|
|
expect(t, `
|
|
c := 0
|
|
iter := func(n, max) {
|
|
if n == max {
|
|
return
|
|
}
|
|
|
|
c++
|
|
iter(n+1, max)
|
|
}
|
|
iter(0, 9999)
|
|
out = c
|
|
`, nil, 9999)
|
|
}
|
|
|
|
// tail call with free vars
|
|
func TestTailCallFreeVars(t *testing.T) {
|
|
expect(t, `
|
|
func() {
|
|
a := 10
|
|
f2 := 0
|
|
f2 = func(n, s) {
|
|
if n == 0 {
|
|
return s + a
|
|
}
|
|
return f2(n-1, n+s)
|
|
}
|
|
out = f2(5, 0)
|
|
}()`, nil, 25)
|
|
}
|