xgo/runtime/vm_tail_call_test.go
Daniel 3500c686b3
Improvements on compiler/VM error reporting (filename:line:col)
- add type infos to VM error messages
- add 'Name' to UserFunction objects 
- add 'expectErrorString' to VM tests
- replace vm.expectError() with vm.expectErrorString() to make it more explicit
- add source map info to VM error messages
- optimization in function calls
- add file/line/col info to compiler errors
- change stdlib module to be loaded from VM (instead of compiler) so they can be properly loaded after the source is compiled into binary
- VM can take builtin modules optionally
2019-02-20 16:26:11 -08: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)`, 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)`, 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)`, 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)`, 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)`, 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()`, 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)
`, 9999)
expect(t, `
c := 0
iter := func(n, max) {
if n == max {
return
}
c++
iter(n+1, max)
}
iter(0, 9999)
out = c
`, 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)
}()`, 25)
}