koka icon indicating copy to clipboard operation
koka copied to clipboard

Tail recursive effects (using `fun`) with 3 or 4 arguments (but not 1 or 2) crash across multiple backends

Open jasigal opened this issue 2 years ago • 0 comments

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.

jasigal avatar Jun 16 '22 17:06 jasigal