Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mutal recursion #596

Open
backtracking opened this issue Oct 22, 2024 · 3 comments
Open

mutal recursion #596

backtracking opened this issue Oct 22, 2024 · 3 comments

Comments

@backtracking
Copy link

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
Copy link

4y8 commented Oct 23, 2024

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.

genFunSig :: Bool -> Visibility -> Name -> Expr -> Doc
genFunSig inlineC vis name defExpr
= let tryFun expr = case expr of
TypeApp e _ -> tryFun e
TypeLam _ e -> tryFun e
Lam params eff body -> genLamSig inlineC vis name params body
_ -> error ("Backend.C.FromCore.genFunDefSig: not a function: " ++ show (name,defExpr))
in tryFun defExpr

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.

koka/src/Core/Simplify.hs

Lines 457 to 467 in 70f5609

-- direct application of arguments to a lambda: fun(x1...xn) { f(x1,...,xn) } -> f
bottomUp (Lam pars eff (App f@(Var _ info) args)) | notExternal && length pars == length args && argsMatchPars
= f
where
argsMatchPars = and (zipWith argMatchPar pars args)
argMatchPar par (Var name _) = par == name
argMatchPar _ _ = False
notExternal = case info of
InfoExternal{} -> False
_ -> True

@daanx
Copy link
Member

daanx commented Oct 28, 2024

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

@daanx
Copy link
Member

daanx commented Oct 28, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants