koka
koka copied to clipboard
Tail recursive effects (using `fun`) with 3 or 4 arguments (but not 1 or 2) crash across multiple backends
The problem
This program
pub module three-fun
effect oper {
fun oper3(arg0 : (), arg1 : (), arg2 : ()) : ()
}
fun main() {
with fun oper3(_,_,_) -> ()
with fun oper3(x,y,z) -> oper3(x,y,z)
println(oper3((),(),()))
}
and this program
pub module four-fun
effect oper {
fun oper4(arg0 : (), arg1 : (), arg2 : (), arg3 : ()) : ()
}
fun main() {
with fun oper4(_,_,_,_) -> ()
with fun oper4(x,y,z,w) -> oper4(x,y,z,w)
println(oper4((),(),(),()))
}
both crash when run with either the C or JS backend. The JS versions run out of stack space.
Working programs
None of the following variants crash.
pub module three-fun-manual
effect oper {
ctl oper3(arg0 : (), arg1 : (), arg2 : ()) : ()
}
fun main() {
with ctl oper3(_,_,_) ->
val f = fn() {()}
resume(f())
with ctl oper3(x,y,z) ->
val f = fn() {oper3(x,y,z)}
resume(f())
println(oper3((),(),()))
}
pub module three-ctl
effect oper {
ctl oper3(arg0 : (), arg1 : (), arg2 : ()) : ()
}
fun main() {
with ctl oper3(_,_,_) -> resume(())
with ctl oper3(x,y,z) -> resume(oper3(x,y,z))
println(oper3((),(),()))
}
pub module zero-fun
effect oper {
fun oper0() : ()
}
fun main() {
with fun oper0() -> ()
with fun oper0() -> oper0()
println(oper0())
}
pub module one-fun
effect oper {
fun oper1(arg0 : ()) : ()
}
fun main() {
with fun oper1(_) -> ()
with fun oper1(x) -> oper1(x)
println(oper1(()))
}
pub module two-fun
effect oper {
fun oper2(arg0 : (), arg1 : ()) : ()
}
fun main() {
with fun oper2(_,_) -> ()
with fun oper2(x,y) -> oper2(x,y)
println(oper2((),()))
}
Workarounds
Don't use 3 or 4 argument fun
effects, instead, tuple your arguments to use 1 or 2 argument fun
effects or ctl
effects.