koka-lang / koka

Koka language compiler and interpreter
http://koka-lang.org
Other
3.31k stars 167 forks source link

mutal recursion #596

Open backtracking opened 3 weeks ago

backtracking commented 3 weeks ago

In an attempt to figure out of mutual recursion us supported, with the following input file,

fun foo()
  bar()
fun bar()
  foo()
fun main()
  ()

I get the following error with Koka 3.1.2:

$ koka --console=raw -v0 -e test.koka
test(1, 1): internal error: Backend.C.FromCore.genFunDefSig: not a function: (test/bar,test/foo)
CallStack (from HasCallStack):
  error, called at src/Backend/C/FromCore.hs:326:42 in koka-3.1.2-2NpoSf9Uv2JEsgjfT7jQ0Q:Backend.C.FromCore

Failed to compile test.koka
4y8 commented 3 weeks ago

The core generated by koka --console=raw -v0 -e --showcore test.koka is:

pub fun bar : forall<a,b> (x : a) -> div b
  = forall<a,b> test/foo;
pub fun foo : forall<a,b> (x : a) -> div b
  = forall<a,b> test/bar;
pub fun main : () -> ()
  = fn(){
    std/core/types/Unit;
  };

While the function genFunSig (which raises the issue) expects a Lam, the body of both functions are variables. https://github.com/koka-lang/koka/blob/70f5609320e7917f83f0c884211731b21d1813fa/src/Backend/C/FromCore.hs#L341-L348 There seem to be an eta-contraction between initial core and core which causes the problem as the initial core is:

pub fun bar : forall<a> () -> div a
  = forall<a> forall<b> fn<div>(){
    test/foo();
  };
pub fun foo : forall<a> () -> div a
  = forall<a> forall<b> fn<div>(){
    test/bar();
  };
pub fun main : () -> ()
  = fn(){
    std/core/types/Unit;
  };

It seems to be caused by the following optimisation, deleting this snippet allows the program to compile. The bug could be fixed by eta-expanding function definitions when they aren't lambdas. https://github.com/koka-lang/koka/blob/70f5609320e7917f83f0c884211731b21d1813fa/src/Core/Simplify.hs#L457-L467

daanx commented 2 weeks ago

That was such a strange bug! weird we never ran into it before but it should be fixed now.

daanx commented 2 weeks ago

btw. Koka support mutual recursion and does a topological sort. For polymorphic recursion one needs to add explicit type signatures.