Skip to content

Commit

Permalink
Fix elaboration of local by-name functions (getters)
Browse files Browse the repository at this point in the history
  • Loading branch information
LPTK committed Jan 11, 2025
1 parent 4aedfaa commit 6d029bb
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 1 deletion.
12 changes: 11 additions & 1 deletion hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,17 @@ extends Importer:
val s = st.map(term(_)(using newCtx))
val b = rhs.map(term(_)(using newCtx))
val r = FlowSymbol(s"‹result of ${sym}")
val tdf = TermDefinition(owner, k, sym, pss, s, b, r,
val real_pss =
// * Local functions (i.e. those without owner) with no parameter lists
// * are elaborated into functions with a single empty parameter list.
// * This is because JS does not support local "getter" functions.
owner match
case S(_) => pss
case N => pss match
case Nil if k is Fun =>
ParamList(ParamListFlags.empty, Nil, N) :: Nil
case _ => pss
val tdf = TermDefinition(owner, k, sym, real_pss, s, b, r,
TermDefFlags.empty.copy(isModMember = isModMember), annotations)
sym.defn = S(tdf)

Expand Down
11 changes: 11 additions & 0 deletions hkmc2/shared/src/test/mlscript/basics/LocalVal.mls
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
:js


fun foo() =
val x = 1
x + 1

foo()
//│ = 2


102 changes: 102 additions & 0 deletions hkmc2/shared/src/test/mlscript/bbml/bbGetters.mls
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
:js
:noSanityCheck // * For some reason, these cause problems

// * For the `log` function
:import ../codegen/PredefJS.mls
//│ Imported 2 member(s)

:global
:bbml
//│ Type: ⊤


:sjs
fun test1() =
fun sayHi = log("Hi")
sayHi, sayHi, sayHi
//│ JS (unsanitized):
//│ function test1() {
//│ let tmp, tmp1;
//│ function sayHi() {
//│ return globalThis.log("Hi") ?? null;
//│ }
//│ tmp = sayHi();
//│ tmp1 = sayHi();
//│ return sayHi();
//│ }
//│ null
//│ Type: ⊤

test1()
//│ > Hi
//│ > Hi
//│ > Hi
//│ Type: ⊤


:sjs
fun test2() =
fun funny = case
0 then 0
n then funny(n - 1) + 1
funny
//│ JS (unsanitized):
//│ function test2() {
//│ function funny() {
//│ return (caseScrut) => {
//│ let n, tmp, tmp1, tmp2;
//│ if (caseScrut === 0) {
//│ return 0;
//│ } else {
//│ n = caseScrut;
//│ tmp = funny();
//│ tmp1 = n - 1;
//│ tmp2 = tmp(tmp1) ?? null;
//│ return tmp2 + 1;
//│ }
//│ };
//│ }
//│ return funny();
//│ }
//│ null
//│ Type: ⊤

test2()(5)
//│ = 5
//│ Type: Int


// * Notice the mistake here; we should warn that the first case in statement position is useless!
:sjs
fun test2() =
fun funny =
case 0 then 0
case n then funny(n - 1) + 1
funny
//│ JS (unsanitized):
//│ function test2() {
//│ function funny() {
//│ return (caseScrut) => {
//│ let n, tmp, tmp1, tmp2;
//│ n = caseScrut;
//│ tmp = funny();
//│ tmp1 = n - 1;
//│ tmp2 = tmp(tmp1) ?? null;
//│ return tmp2 + 1;
//│ };
//│ }
//│ return funny();
//│ }
//│ null
//│ Type: ⊤


:todo
fun test3 =
log("Hi")
//│ ╔══[ERROR] Function definition shape not yet supported for test3
//│ ║ l.96: log("Hi")
//│ ╙── ^^^^^^^^^
//│ Type: ⊤


0 comments on commit 6d029bb

Please sign in to comment.