diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Instrumentation.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Instrumentation.scala index 5cced783bf..c84834dcbf 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Instrumentation.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Instrumentation.scala @@ -5,12 +5,12 @@ import utils.* import hkmc2.Message.MessageContext import scala.collection.mutable.HashMap -import scala.util.chaining._ +import scala.util.chaining.* import mlscript.utils.*, shorthands.* import semantics.* -import semantics.Elaborator.State +import semantics.Elaborator.{State, Ctx, ctx} import syntax.{Literal, Tree} @@ -18,7 +18,10 @@ import syntax.{Literal, Tree} // this avoids having to rebuild the same shapes everytime they are needed // transform Block to Block IR so that it can be instrumented in mlscript -class InstrumentationImpl(using State, Raise): +class Instrumentation(using State, Raise, Ctx) extends BlockTransformer(new SymbolSubst()): + // recover `defn` for when `sym.defn` is `None`, when the definition was generated by other compiler passes + val defnMap = HashMap[Symbol, ClsLikeDefn]() + type ArgWrappable = Path | Symbol type Context = HashMap[Path, Path] // TODO: there could be a fresh scope per function body, instead of a single one for the entire program @@ -91,22 +94,38 @@ class InstrumentationImpl(using State, Raise): // transformation helpers - def transformSymbol(sym: Symbol, symName: Str = "sym")(k: Path => Block): Block = + // if sym is ClassSymbol, we may need pOpt to link to the path pointing to the value of the symbol + def transformSymbol(sym: Symbol, pOpt: Option[Path] = N, symName: Str = "sym")(k: Path => Block): Block = sym match - case clsSym: ClassSymbol => - clsSym.defn match - case S(defn) => - val name = scope.allocateOrGetName(sym) - transformParamsOpt(defn.paramsOpt): paramsOpt => - blockCtor("ClassSymbol", Ls(toValue(name), paramsOpt), symName)(k) - case N => - raise(ErrorReport(msg"Unable to infer parameters from ClassSymbol in staged module, which are necessary to reconstruct class instances." -> sym.toLoc :: Nil)) - End() - case t: TermSymbol if t.defn.exists(_.sym.asCls.isDefined) => - transformSymbol(t.defn.get.sym.asCls.get, symName)(k) + case t: TermSymbol if t.defn.exists(_.sym.asClsOrMod.isDefined) => + transformSymbol(t.defn.get.sym.asClsOrMod.get, pOpt, symName)(k) + // retain names to built-in functions or function definitions + case t: TermSymbol if t.defn.exists(_.k == syntax.Fun) => + blockCtor("Symbol", Ls(toValue(sym.nme)), symName)(k) case _: BuiltinSymbol => - // retain names to built-in functions blockCtor("Symbol", Ls(toValue(sym.nme)), symName)(k) + case clsSym: ClassSymbol if ctx.builtins.virtualClasses(clsSym) => + blockCtor("VirtualClassSymbol", Ls(toValue(sym.nme)), symName)(k) + case baseSym: BaseTypeSymbol => + val name = scope.allocateOrGetName(sym) + val (owner, bsym, paramsOpt, auxParams) = (baseSym.defn, defnMap.get(baseSym)) match + case (S(defn), _) => (defn.owner, defn.bsym, defn.paramsOpt, defn.auxParams) + case (_, S(defn: ClsLikeDefn)) => (defn.owner, defn.sym, defn.paramsOpt, defn.auxParams) + case _ => + raise(ErrorReport(msg"Unable to infer parameters from symbol in staged module, which are necessary to reconstruct class instances: ${sym.toString()}" -> sym.toLoc :: Nil)) + return End() + + val path: ArgWrappable = pOpt.getOrElse(owner match + case S(owner) => owner.asPath.selSN(sym.nme) + case N => bsym) + baseSym match + case _: ClassSymbol => + transformParamsOpt(paramsOpt): paramsOpt => + auxParams.map(ps => transformParamList(ps)).collectApply: auxParams => + tuple(auxParams): auxParams => + blockCtor("ClassSymbol", Ls(toValue(name), path, paramsOpt, auxParams), symName)(k) + case _: ModuleOrObjectSymbol => + blockCtor("ModuleSymbol", Ls(toValue(name), path), symName)(k) case _ => val name = scope.allocateOrGetName(sym) blockCtor("Symbol", Ls(toValue(name)), symName)(k) @@ -156,7 +175,7 @@ class InstrumentationImpl(using State, Raise): blockCtor("ValueLit", Ls(l), "lit")(k) case s @ Select(p, Tree.Ident(name)) => transformPath(p): x => - val sym = s.symbol.map(transformSymbol(_)) + val sym = s.symbol.map(transformSymbol(_, S(s))) .getOrElse(blockCtor("Symbol", Ls(toValue(name)))) sym: sym => blockCtor("Select", Ls(x, sym), "sel")(k) @@ -290,13 +309,13 @@ class InstrumentationImpl(using State, Raise): transformSymbol(labelSymbol): labelSymbol => blockCtor("Break", Ls(labelSymbol))(k(_, ctx)) case _ => - raise(ErrorReport(msg"Other Blocks not supprted in staged module: ${b.toString()}" -> N :: Nil)) + raise(ErrorReport(msg"Other Blocks not supported in staged module: ${b.toString()}" -> N :: Nil)) End() def transformFunDefn(f: FunDefn)(using Context)(k: Path => Block): Block = transformBlock(f.body): body => if f.params.length != 1 then - raise(WarningReport(msg"Multiple parameter lists are not supported in shape propagation yet." -> f.sym.toLoc :: Nil)) + raise(ErrorReport(msg":ftc must be enabled to desugar functions with multiple parameter lists." -> f.sym.toLoc :: Nil)) // maintain parameter names in instrumented code f.params.map( _.params.map(p => blockCtor("Symbol", Ls(toValue(p.sym.nme)))).collectApply @@ -306,7 +325,7 @@ class InstrumentationImpl(using State, Raise): tuple(tups): tup => blockCtor("FunDefn", Ls(sym, tup, body, toValue(true)))(k) - def applyFunDefn(f: FunDefn): (FunDefn, Block => Block) = + def applyFunDefnInner(f: FunDefn): (FunDefn, Block => Block) = val genSymName = f.sym.nme + "_instr" val genSym = BlockMemberSymbol(genSymName, Nil, false) val sym = f.owner.get.asPath.selSN(genSymName) @@ -321,10 +340,6 @@ class InstrumentationImpl(using State, Raise): val newFun = f.copy(sym = genSym, dSym = dSym, params = Ls(PlainParamList(Nil)), body = newBody)(false) (newFun, debug) -// TODO: rename as InstrumentationTransformer? -class Instrumentation(using State, Raise) extends BlockTransformer(new SymbolSubst()): - val impl = new InstrumentationImpl - override def applyBlock(b: Block): Block = super.applyBlock(b) match // find modules with staged annotation @@ -332,10 +347,10 @@ class Instrumentation(using State, Raise) extends BlockTransformer(new SymbolSub val sym = c.sym.subst val companion = c.companion.get val (stagedMethods, debugPrintCode) = companion.methods - .map(impl.applyFunDefn) + .map(applyFunDefnInner) .unzip val ctor = FunDefn.withFreshSymbol(S(companion.isym), BlockMemberSymbol("ctor$", Nil), Ls(PlainParamList(Nil)), companion.ctor)(false) - val (stagedCtor, ctorPrint) = impl.applyFunDefn(ctor) + val (stagedCtor, ctorPrint) = applyFunDefnInner(ctor) val unit = State.runtimeSymbol.asPath.selSN("Unit") val debugBlock = (ctorPrint :: debugPrintCode).foldRight((Return(unit, true): Block))(_(_)) @@ -346,7 +361,7 @@ class Instrumentation(using State, Raise) extends BlockTransformer(new SymbolSub override def applyBlock(b: Block): Block = super.applyBlock(b) match case Define(c: ClsLikeDefn, rest) if c.companion.isEmpty => val (stagedMethods, debugPrintCode) = c.methods - .map(impl.applyFunDefn) + .map(applyFunDefnInner) .unzip val newModule = c.copy(methods = c.methods ++ stagedMethods) Define(newModule, rest) @@ -356,3 +371,16 @@ class Instrumentation(using State, Raise) extends BlockTransformer(new SymbolSub val newModule = c.copy(sym = sym, companion = S(newCompanion)) Define(newModule, rest) case b => b + + def mkDefnMap(b: Block): Unit = + val transformer = new BlockTransformer(new SymbolSubst()): + override def applyDefn(defn: Defn)(k: Defn => Block) = defn match + case c: ClsLikeDefn => + defnMap.addOne(c.isym, c) + super.applyDefn(defn)(k) + case _ => super.applyDefn(defn)(k) + transformer.applyBlock(b) + + def applyBlockFinal(b: Block) = + mkDefnMap(b) + applyBlock(b) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index 395c2fab97..9d83f84b80 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -1088,7 +1088,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): if config.funcToCls then Lifter(FirstClassFunctionTransformer().transform(merged)).transform else merged - val staged = Instrumentation(using summon).applyBlock(funcToCls) + val staged = Instrumentation(using summon).applyBlockFinal(funcToCls) val res = if config.tailRecOpt then TailRecOpt().transform(staged) diff --git a/hkmc2/shared/src/test/mlscript-compile/Block.mls b/hkmc2/shared/src/test/mlscript-compile/Block.mls index 7186b9de89..55854af63c 100644 --- a/hkmc2/shared/src/test/mlscript-compile/Block.mls +++ b/hkmc2/shared/src/test/mlscript-compile/Block.mls @@ -17,9 +17,11 @@ type Literal = null | undefined | Str | Int | Num | Bool type ParamList = Array[Symbol] class Symbol(val name: Str) -type Ident = Symbol -// this is so that we're able to retrieve information about the class from the symbol -class ClassSymbol(val name: Str, val paramsOpt: Opt[ParamList]) extends Symbol(name) +class VirtualClassSymbol(val name: Str) extends Symbol(name) +class ClassSymbol(val name: Str, val value, val paramsOpt: Option[ParamList], val auxParams: Array[ParamList]) extends Symbol(name) +class ModuleSymbol(val name: Str, val value) extends Symbol(name) + +// Classes defined in Block.scala class Arg(val value: Path) @@ -37,7 +39,7 @@ class Result with class Path extends Result with constructor - Select(val qual: Path, val name: Ident) + Select(val qual: Path, val name: Symbol) DynSelect(val qual: Path, val fld: Path, val arrayIdx: Bool) // is arrayIdx used? ValueRef(val l: Symbol) ValueLit(val lit: Literal) @@ -82,22 +84,12 @@ fun showLiteral(l: Literal) = else l.toString() fun showSymbol(s: Symbol) = - // console.log("printing " + s) - if s is - ClassSymbol(name, args) then - "ClassSymbol(" + "\"" + name + "\"" + - if args - is Some(args) then ":[" + args.map(showSymbol).join(", ") + "]" - is None then "" - + ")" - _ then "Symbol(" + "\"" + s.name + "\"" + ")" - -fun showIdent(i: Ident) = showSymbol(i) + s.toString() fun showPath(p: Path): Str = if p is Select(qual, name) then - "Select(" + showPath(qual) + ", " + showIdent(name) + ")" + "Select(" + showPath(qual) + ", " + showSymbol(name) + ")" DynSelect(qual, fld, arrayIdx) then "DynSelect(" + showPath(qual) + ", " + showPath(fld) + ", " + showBool(arrayIdx) + ")" ValueRef(l) then diff --git a/hkmc2/shared/src/test/mlscript/block-staging/Functions.mls b/hkmc2/shared/src/test/mlscript/block-staging/Functions.mls index 4425ef8a3e..304094d79b 100644 --- a/hkmc2/shared/src/test/mlscript/block-staging/Functions.mls +++ b/hkmc2/shared/src/test/mlscript/block-staging/Functions.mls @@ -30,7 +30,7 @@ staged module Expressions with //│ > FunDefn(Symbol("tup1"), ([]), Return(Tuple([Lit(1), Lit(2)]), false), true) //│ > FunDefn(Symbol("tup2"), ([]), Return(Tuple([Lit(1), Ref(Symbol("x1"))]), false), true) //│ > FunDefn(Symbol("dynsel"), ([]), Scoped([Symbol("tmp")], Assign(Symbol("tmp"), Tuple([Lit(1)]), Return(DynSelect(Ref(Symbol("tmp")), Lit(0), false), false))), true) -//│ > FunDefn(Symbol("match1"), ([]), Scoped([Symbol("scrut")], Assign(Symbol("scrut"), Lit(9), Match(Ref(Symbol("scrut")), [Cls(ClassSymbol("Bool"), Select(Ref(Symbol("runtime")), Symbol("unreachable"))) -> Return(Lit(1), false), Lit(8) -> Return(Lit(2), false), Cls(ClassSymbol("Int"), Select(Ref(Symbol("runtime")), Symbol("unreachable"))) -> Return(Lit(3), false)], Return(Lit(0), false), End))), true) +//│ > FunDefn(Symbol("match1"), ([]), Scoped([Symbol("scrut")], Assign(Symbol("scrut"), Lit(9), Match(Ref(Symbol("scrut")), [Cls(VirtualClassSymbol("Bool"), Select(Ref(Symbol("runtime")), Symbol("unreachable"))) -> Return(Lit(1), false), Lit(8) -> Return(Lit(2), false), Cls(VirtualClassSymbol("Int"), Select(Ref(Symbol("runtime")), Symbol("unreachable"))) -> Return(Lit(3), false)], Return(Lit(0), false), End))), true) //│ > FunDefn(Symbol("match2"), ([]), Scoped([Symbol("a"), Symbol("element1$"), Symbol("element0$")], Match(Ref(Symbol("x1")), [Tup(0) -> Return(Lit(1), false), Tup(2) -> Assign(Symbol("element0$"), Call(Select(Select(Ref(Symbol("runtime")), Symbol("Tuple")), Symbol("get")), [Ref(Symbol("x1")), Lit(0)]), Assign(Symbol("element1$"), Call(Select(Select(Ref(Symbol("runtime")), Symbol("Tuple")), Symbol("get")), [Ref(Symbol("x1")), Lit(1)]), Match(Ref(Symbol("element0$")), [Lit(1) -> Match(Ref(Symbol("element1$")), [Lit(2) -> Return(Lit(2), false)], Assign(Symbol("a"), Ref(Symbol("element0$")), Return(Lit(3), false)), End)], Assign(Symbol("a"), Ref(Symbol("element0$")), Return(Lit(3), false)), End)))], Return(Lit(0), false), End)), true) //│ x = [1, 2, 3] @@ -42,11 +42,11 @@ staged module ClassInstrumentation with fun inst2() = new NoArg fun app1() = Outside(1) fun app2() = Inside(1, 2) -//│ > FunDefn(Symbol("ctor$"), ([]), Define(ClsLikeDefn(ClassSymbol("Inside":[Symbol("a1"), Symbol("b")]), [], TODO), Define(ClsLikeDefn(ClassSymbol("NoArg"), [], TODO), End)), true) -//│ > FunDefn(Symbol("inst1"), ([]), Return(Instantiate(Ref(ClassSymbol("Outside":[Symbol("a")])), [Lit(1)]), false), true) -//│ > FunDefn(Symbol("inst2"), ([]), Return(Instantiate(Select(Ref(Symbol("ClassInstrumentation")), ClassSymbol("NoArg")), []), false), true) -//│ > FunDefn(Symbol("app1"), ([]), Return(Call(Ref(ClassSymbol("Outside":[Symbol("a")])), [Lit(1)]), false), true) -//│ > FunDefn(Symbol("app2"), ([]), Return(Call(Select(Ref(Symbol("ClassInstrumentation")), ClassSymbol("Inside":[Symbol("a1"), Symbol("b")])), [Lit(1), Lit(2)]), false), true) +//│ > FunDefn(Symbol("ctor$"), ([]), Define(ClsLikeDefn(ClassSymbol("Inside", fun Inside { class: class Inside }, Some([Symbol("a1"), Symbol("b")]), []), [], TODO), Define(ClsLikeDefn(ClassSymbol("NoArg", class NoArg, None, []), [], TODO), End)), true) +//│ > FunDefn(Symbol("inst1"), ([]), Return(Instantiate(Ref(ClassSymbol("Outside", fun Outside { class: class Outside }, Some([Symbol("a")]), [])), [Lit(1)]), false), true) +//│ > FunDefn(Symbol("inst2"), ([]), Return(Instantiate(Select(Ref(ModuleSymbol("ClassInstrumentation", class ClassInstrumentation { Inside: fun Inside { class: class Inside }, NoArg: class NoArg })), ClassSymbol("NoArg", class NoArg, None, [])), []), false), true) +//│ > FunDefn(Symbol("app1"), ([]), Return(Call(Ref(ClassSymbol("Outside", fun Outside { class: class Outside }, Some([Symbol("a")]), [])), [Lit(1)]), false), true) +//│ > FunDefn(Symbol("app2"), ([]), Return(Call(Select(Ref(ModuleSymbol("ClassInstrumentation", class ClassInstrumentation { Inside: fun Inside { class: class Inside }, NoArg: class NoArg })), ClassSymbol("Inside", fun Inside { class: class Inside }, Some([Symbol("a1"), Symbol("b")]), [])), [Lit(1), Lit(2)]), false), true) module Nonstaged with fun f() = 1 @@ -60,20 +60,17 @@ staged module CallSubst with Nonstaged.f() Staged.f() //│ > FunDefn(Symbol("ctor$"), ([]), End, true) -//│ > FunDefn(Symbol("call"), ([]), Assign(Symbol("$_no$_symbol$_"), Call(Ref(Symbol("+")), [Lit(1), Lit(1)]), Assign(Symbol("$_no$_symbol$_"), Call(Select(Ref(Symbol("Nonstaged")), Symbol("f")), []), Return(Call(Select(Ref(Symbol("Staged")), Symbol("f_gen")), []), false))), true) +//│ > FunDefn(Symbol("call"), ([]), Assign(Symbol("$_no$_symbol$_"), Call(Ref(Symbol("+")), [Lit(1), Lit(1)]), Assign(Symbol("$_no$_symbol$_"), Call(Select(Ref(ModuleSymbol("Nonstaged", class Nonstaged)), Symbol("f")), []), Return(Call(Select(Ref(ModuleSymbol("Staged", class Staged)), Symbol("f_gen")), []), false))), true) -:w +:ftc staged module Arguments with fun f(x) = x = 1 x fun g(x)(y, z)() = z -//│ ╔══[WARNING] Multiple parameter lists are not supported in shape propagation yet. -//│ ║ l.70: fun g(x)(y, z)() = z -//│ ╙── ^^^^^^^^^^^^^^^^^^^^ //│ > FunDefn(Symbol("ctor$"), ([]), End, true) //│ > FunDefn(Symbol("f"), ([Symbol("x")]), Assign(Symbol("x"), Lit(1), Return(Ref(Symbol("x")), false)), true) -//│ > FunDefn(Symbol("g"), ([Symbol("x")],[Symbol("y"), Symbol("z")],[]), Return(Ref(Symbol("z")), false), true) +//│ > FunDefn(Symbol("g"), ([Symbol("x")]), Scoped([Symbol("tmp")], Assign(Symbol("tmp"), Instantiate(Ref(ClassSymbol("Function$", class Function$, None, [])), []), Return(Ref(Symbol("tmp")), false))), true) staged module OtherBlocks with fun scope() = @@ -87,17 +84,18 @@ staged module OtherBlocks with 3 then 0 else 0 //│ > FunDefn(Symbol("ctor$"), ([]), End, true) -//│ > FunDefn(Symbol("scope"), ([]), Scoped([Symbol("a")], Assign(Symbol("a"), Lit(1), Return(Call(Select(Select(Ref(Symbol("OtherBlocks")), Symbol("scope")), Symbol("locally")), [Ref(Symbol("a"))]), false))), true) +//│ > FunDefn(Symbol("scope"), ([]), Scoped([Symbol("a")], Assign(Symbol("a"), Lit(1), Return(Call(Select(Select(Ref(ModuleSymbol("OtherBlocks", class OtherBlocks)), Symbol("scope")), Symbol("locally")), [Ref(Symbol("a"))]), false))), true) //│ > FunDefn(Symbol("breakAndLabel"), ([]), Scoped([Symbol("scrut")], Assign(Symbol("scrut"), Lit(1), Match(Ref(Symbol("scrut")), [Lit(2) -> Return(Lit(0), false), Lit(3) -> Return(Lit(0), false)], Return(Lit(0), false), End))), true) staged module ClassDefs with class A -//│ > FunDefn(Symbol("ctor$"), ([]), Define(ClsLikeDefn(ClassSymbol("A"), [], TODO), End), true) +//│ > FunDefn(Symbol("ctor$"), ([]), Define(ClsLikeDefn(ClassSymbol("A", class A, None, []), [], TODO), End), true) staged module ClassFunctions with - class A with - fun f() = 1 -//│ > FunDefn(Symbol("ctor$"), ([]), Define(ClsLikeDefn(ClassSymbol("A"), [FunDefn(Symbol("f"), ([]), Return(Lit(1), false), true)], TODO), End), true) + class InnerClass() with + fun f() = 1 + Arguments.f(1) + fun g() = f() // TODO +//│ > FunDefn(Symbol("ctor$"), ([]), Define(ClsLikeDefn(ClassSymbol("InnerClass", fun InnerClass { class: class InnerClass }, Some([]), []), [FunDefn(Symbol("f"), ([]), Scoped([Symbol("tmp")], Assign(Symbol("tmp"), Call(Select(Ref(ModuleSymbol("Arguments", class Arguments)), Symbol("f_gen")), [Lit(1)]), Return(Call(Ref(Symbol("+")), [Lit(1), Ref(Symbol("tmp"))]), false))), true),FunDefn(Symbol("g"), ([]), Return(Call(Select(Ref(ClassSymbol("InnerClass", fun InnerClass { class: class InnerClass }, Some([]), [])), Symbol("f")), []), false), true)], TODO), End), true) // name collision class A() @@ -113,17 +111,26 @@ module A with //│ > FunDefn(Symbol("ctor$"), ([]), End, true) //│ > FunDefn(Symbol("f"), ([]), Return(Lit(1), false), true) +// TODO: force enable :ftc to desugar Label and Break +staged module M with + fun f() = if 1 is + 0 then 2 + 1 then 2 + else 2 +//│ > FunDefn(Symbol("ctor$"), ([]), End, true) +//│ > FunDefn(Symbol("f"), ([]), Scoped([Symbol("scrut")], Assign(Symbol("scrut"), Lit(1), Match(Ref(Symbol("scrut")), [Lit(0) -> Return(Lit(2), false), Lit(1) -> Return(Lit(2), false)], Return(Lit(2), false), End))), true) + :e class C(val a) staged module A with let x = C(1) fun f() = set x.a = 0 fun g() = {1 : 2} -//│ ═══[COMPILATION ERROR] Other Blocks not supprted in staged module: AssignField(Ref(term:A/x,None),Ident(a),Lit(IntLit(0)),Return(Select(Ref(tmp:runtime,None),Ident(Unit)),false)) +//│ ═══[COMPILATION ERROR] Other Blocks not supported in staged module: AssignField(Ref(term:A/x,None),Ident(a),Lit(IntLit(0)),Return(Select(Ref(tmp:runtime,None),Ident(Unit)),false)) //│ ╔══[COMPILATION ERROR] Other Results not supported in staged module: Record(false,List(RcdArg(Some(Lit(IntLit(1))),Lit(IntLit(2))))) -//│ ║ l.121: fun g() = {1 : 2} +//│ ║ l.128: fun g() = {1 : 2} //│ ╙── ^ -//│ > FunDefn(Symbol("ctor$"), ([]), Assign(Symbol("x"), Call(Ref(ClassSymbol("C":[Symbol("a")])), [Lit(1)]), End), true) +//│ > FunDefn(Symbol("ctor$"), ([]), Assign(Symbol("x"), Call(Ref(ClassSymbol("C", fun C { class: class C }, Some([Symbol("a")]), [])), [Lit(1)]), End), true) //│ ═══[RUNTIME ERROR] Error: MLscript call unexpectedly returned `undefined`, the forbidden value. :todo diff --git a/hkmc2/shared/src/test/mlscript/block-staging/StageSymbols.mls b/hkmc2/shared/src/test/mlscript/block-staging/StageSymbols.mls new file mode 100644 index 0000000000..6630944b28 --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/block-staging/StageSymbols.mls @@ -0,0 +1,57 @@ +:js +:staging + +staged module M with + class C with + fun f() = 1 + fun g() = f() +//│ > FunDefn(Symbol("ctor$"), ([]), Define(ClsLikeDefn(ClassSymbol("C", class C, None, []), [FunDefn(Symbol("f"), ([]), Return(Lit(1), false), true),FunDefn(Symbol("g"), ([]), Return(Call(Select(Ref(ClassSymbol("C", class C, None, [])), Symbol("f")), []), false), true)], TODO), End), true) + +staged module A with + fun f() = 1 +module B with + fun f() = 1 +class C(val a, b)(c)(d) +staged module D with + class E + fun f() = + A.f() + B.f() + fun matching() = + 1 is Int + 1 is C +//│ > FunDefn(Symbol("ctor$"), ([]), End, true) +//│ > FunDefn(Symbol("f"), ([]), Return(Lit(1), false), true) +//│ > FunDefn(Symbol("ctor$"), ([]), Define(ClsLikeDefn(ClassSymbol("E", class E, None, []), [], TODO), End), true) +//│ > FunDefn(Symbol("f"), ([]), Assign(Symbol("$_no$_symbol$_"), Call(Select(Ref(ModuleSymbol("A", class A)), Symbol("f_gen")), []), Return(Call(Select(Ref(ModuleSymbol("B", class B)), Symbol("f")), []), false)), true) +//│ > FunDefn(Symbol("matching"), ([]), Scoped([Symbol("tmp"), Symbol("scrut"), Symbol("scrut1")], Assign(Symbol("scrut"), Lit(1), Match(Ref(Symbol("scrut")), [Cls(VirtualClassSymbol("Int"), Select(Ref(Symbol("runtime")), Symbol("unreachable"))) -> Assign(Symbol("tmp"), Lit(true), End)], Assign(Symbol("tmp"), Lit(false), End), Assign(Symbol("scrut1"), Lit(1), Match(Ref(Symbol("scrut1")), [Cls(ClassSymbol("C", fun C { class: class C }, Some([Symbol("a"), Symbol("b")]), [[Symbol("c")], [Symbol("d")]]), Ref(ClassSymbol("C", fun C { class: class C }, Some([Symbol("a"), Symbol("b")]), [[Symbol("c")], [Symbol("d")]]))) -> Return(Lit(true), false)], Return(Lit(false), false), End))))), true) + +module A with + module B with + class C(a) +staged module M with + class E + fun f() = + D.E + A.B.C + A.B.C(1) + E +//│ > FunDefn(Symbol("ctor$"), ([]), Define(ClsLikeDefn(ClassSymbol("E", class E, None, []), [], TODO), End), true) +//│ > FunDefn(Symbol("f"), ([]), Assign(Symbol("$_no$_symbol$_"), Call(Select(Select(Ref(ModuleSymbol("A", class A { B: class B { C: fun C { class: class C } } })), ModuleSymbol("B", class B { C: fun C { class: class C } })), ClassSymbol("C", fun C { class: class C }, Some([Symbol("a")]), [])), [Lit(1)]), Return(Select(Ref(ModuleSymbol("M", class M2 { E: class E })), ClassSymbol("E", class E, None, [])), false)), true) + +:e +staged module M with + fun g()() = 1 +//│ ╔══[COMPILATION ERROR] :ftc must be enabled to desugar functions with multiple parameter lists. +//│ ║ l.44: fun g()() = 1 +//│ ╙── ^^^^^^^^^^^^^ +//│ > FunDefn(Symbol("ctor$"), ([]), End, true) +//│ > FunDefn(Symbol("g"), ([],[]), Return(Lit(1), false), true) + +:ftc +staged module M with + fun f() = x => x + fun g()() = 1 +//│ > FunDefn(Symbol("ctor$"), ([]), End, true) +//│ > FunDefn(Symbol("f"), ([]), Scoped([Symbol("tmp")], Assign(Symbol("tmp"), Instantiate(Ref(ClassSymbol("Function$", class Function$, None, [])), []), Return(Ref(Symbol("tmp")), false))), true) +//│ > FunDefn(Symbol("g"), ([]), Scoped([Symbol("tmp1")], Assign(Symbol("tmp1"), Instantiate(Ref(ClassSymbol("Function$1", class Function$, None, [])), []), Return(Ref(Symbol("tmp1")), false))), true)