xgo/runtime/vm_tail_call_test.go
Daniel 61890b15cb
module refactor (#148)
* 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
2019-03-18 08:15:26 -07:00

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)
}