3500c686b3
- 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
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)`, 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)
|
|
}
|