Skip to content

Direct fn calls: Fix cyclic values, add a regression test #43

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

Draft
wants to merge 3 commits into
base: lamdera-next
Choose a base branch
from

Conversation

Janiczek
Copy link
Collaborator

Quick Summary: Cyclic functions were not correctly analyzed for makeArgLookup (finding the number of arguments of a function).

SSCCE

module Main exposing (main)

import Html exposing (Html)


main : Html msg
main =
    Html.div []
        [ Html.text (a1 1 1)
        , Html.text (a2 1 1)
        , Html.text (b1 3 4 5)
        , Html.text (b2 1 2 3 4 5)
        ]


a1 : Int -> Int -> String
a1 =
    a2


a2 : Int -> Int -> String
a2 m n =
    if n > 0 then
        a1 (m - 1) (n - 1)

    else
        "done"


b1 : Int -> Int -> Int -> String
b1 =
    b2 1 2


b2 : Int -> Int -> Int -> Int -> Int -> String
b2 x1 x2 x3 x4 x5 =
    if True then
        "done"

    else
        b1 3 4 5

Additional Details

Found by @pithub here

@Janiczek
Copy link
Collaborator Author

We could remove the possibility of error-ing on edge cases we didn't think about and return Nothing like Gren does. That would make them work in the old way (A2 etc.).

Personally I'd rather let people use this and report any forgotten cases, putting it on our radar to generate fast optimized JS for those as well.

A counterargument might be that Robin says there might be cases that can't be optimized in this way (though we don't know what they might be).

@Janiczek Janiczek marked this pull request as draft March 27, 2025 18:51
@Janiczek
Copy link
Collaborator Author

Janiczek commented Mar 27, 2025

The above code compiles but doesn't run - it generates some additional direct fn usages but not their definitions.

For any

partial : () -> () -> Result
partial =
  full 1

full : Int -> () -> () -> Result
full a b c =
  if True then
    "done"
  else
    partial b c

we need to additionally generate a partial$ = function (arg1,arg2) { return full$(1, arg1, arg2); } for the code as of 427d562 to work properly.

This should be done inside generateRealCycle: we can generate the direct fn name (with the $ at the end) with

    directFnName = JsName.fromGlobalDirectFn home name

and add this to the returned block:

    , JS.Var directFnName
        (JS.Function Nothing (error "TODO generated arg list")
          (Expr.codeToStmtList (Expr.generate mode argLookup (error "TODO `code` transformed into a direct fn call, combining our args and the ones from the generated arg list")))
        )

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

Successfully merging this pull request may close these issues.

1 participant