From 1f127e2d3c43581402423ac50da9c0fd6f365ae3 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sun, 21 Sep 2025 01:20:24 +0800 Subject: [PATCH 01/55] Add `Term.Resolved` and `DefinitionSymbol` --- .../main/scala/hkmc2/semantics/Symbol.scala | 40 +++++++++++++++++-- .../src/main/scala/hkmc2/semantics/Term.scala | 12 ++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 9290b61a16..708d4fa17d 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -293,11 +293,28 @@ sealed trait ClassLikeSymbol extends IdentifiedSymbol: def subst(using sub: SymbolSubst): ClassLikeSymbol +/** + * A symbol that the entity it represents has a definition. + * + * This is different from `MemberSymbol` because `BlockMemberSymbol` extends `MemberSymbol`, and its + * definition is ambiguous in the sense that a `BlockMemberSymbol` corresponds to multiple + * overloaded definitions. In contrast, a `DefinitionSymbol` corresponds to only one specific + * definition. + */ +sealed trait DefinitionSymbol[Defn <: Definition] extends Symbol: + def defn: Opt[Defn] + def subst(using sub: SymbolSubst): DefinitionSymbol[Defn] + /** This is the symbol associated to specific definitions. * One overloaded `BlockMemberSymbol` may correspond to multiple `InnerSymbol`s * A `Ref(_: InnerSymbol)` represents a `this`-like reference to the current object. */ // TODO prevent from appearing in Ref sealed trait InnerSymbol(using State) extends Symbol: + // Ideally, InnerSymbol should extend DefinitionSymbol, but that requires us to specify the type + // parameter to all occurrences of InnerSymbol. So, we use a self-type annotation instead to + // ensure that any implementation of InnerSymbol is also a DefinitionSymbol. + self: DefinitionSymbol[?] => + val privatesScope: Scope = Scope.empty // * Scope for private members of this symbol val thisProxy: TempSymbol = TempSymbol(N, s"this$$$nme") def subst(using SymbolSubst): InnerSymbol @@ -306,7 +323,12 @@ trait IdentifiedSymbol extends Symbol: val id: Tree.Ident class ClassSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using State) - extends MemberSymbol[ClassDef] with ClassLikeSymbol with CtorSymbol with InnerSymbol with NamedSymbol: + extends MemberSymbol[ClassDef] + with ClassLikeSymbol + with CtorSymbol + with DefinitionSymbol[ClassDef] + with InnerSymbol + with NamedSymbol: def name: Str = nme def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of classe here @@ -317,7 +339,12 @@ class ClassSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using State) override def subst(using sub: SymbolSubst): ClassSymbol = sub.mapClsSym(this) class ModuleOrObjectSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using State) - extends MemberSymbol[ModuleOrObjectDef] with ClassLikeSymbol with CtorSymbol with InnerSymbol with NamedSymbol: + extends MemberSymbol[ModuleOrObjectDef] + with ClassLikeSymbol + with CtorSymbol + with DefinitionSymbol[ModuleOrObjectDef] + with InnerSymbol + with NamedSymbol: def name: Str = nme def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of module here @@ -335,7 +362,10 @@ class TypeAliasSymbol(val id: Tree.Ident)(using State) extends MemberSymbol[Type def subst(using sub: SymbolSubst): TypeAliasSymbol = sub.mapTypeAliasSym(this) class PatternSymbol(val id: Tree.Ident, val params: Opt[Tree.Tup], val body: Tree)(using State) - extends MemberSymbol[PatternDef] with CtorSymbol with InnerSymbol: + extends MemberSymbol[PatternDef] + with CtorSymbol + with DefinitionSymbol[PatternDef] + with InnerSymbol: def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of pattern here override def toString: Str = s"pattern:${id.name}" @@ -343,7 +373,9 @@ class PatternSymbol(val id: Tree.Ident, val params: Opt[Tree.Tup], val body: Tre override def subst(using sub: SymbolSubst): PatternSymbol = sub.mapPatSym(this) class TopLevelSymbol(blockNme: Str)(using State) - extends MemberSymbol[ModuleOrObjectDef] with InnerSymbol: + extends MemberSymbol[ModuleOrObjectDef] + with DefinitionSymbol[ModuleOrObjectDef] + with InnerSymbol: def nme = blockNme def toLoc: Option[Loc] = N override def toString: Str = s"globalThis:$blockNme${State.dbgUid(uid)}" diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index 2315464b38..8881099df7 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -53,6 +53,7 @@ sealed trait ResolvableImpl: def duplicate: this.type = this.match + case t: Term.Resolved => t.copy()(t.typ) case t: Term.Ref => t.copy()(t.tree, t.refNum, t.typ) case t: Term.App => t.copy()(t.tree, t.typ, t.resSym) case t: Term.TyApp => t.copy()(t.typ) @@ -71,6 +72,7 @@ sealed trait ResolvableImpl: def withTyp(typ: Type): this.type = this.match + case t: Term.Resolved => t.copy()(S(typ)) case t: Term.Ref => t.copy()(t.tree, t.refNum, S(typ)) case t: Term.App => t.copy()(t.tree, S(typ), t.resSym) case t: Term.TyApp => t.copy()(S(typ)) @@ -188,6 +190,9 @@ enum Term extends Statement: case UnitVal() case Missing // Placeholder terms that were not elaborated due to the "lightweight" elaboration mode `Mode.Light` case Lit(lit: Literal) + /** A term that wraps another term, indicating that the symbol of the inner term is resolved. */ + case Resolved(t: Term, sym: DefinitionSymbol[?]) + (val typ: Opt[Type]) extends Term, ResolvableImpl case Ref(sym: Symbol) (val tree: Tree.Ident, val refNum: Int, val typ: Opt[Type]) extends Term, ResolvableImpl case App(lhs: Term, rhs: Term) @@ -257,6 +262,7 @@ enum Term extends Statement: case r: Resolvable => r.expanded case t => t match + case res: Resolved => S(res.sym) case ref: Ref => ref.symbol case sel: Sel => sel.sym case sel: SynthSel => sel.sym @@ -268,6 +274,7 @@ enum Term extends Statement: case r: Resolvable => r.expanded case t => t match + case res: Resolved => res.typ case ref: Ref => ref.typ case app: App => app.typ case app: TyApp => app.typ @@ -296,6 +303,7 @@ enum Term extends Statement: case Lit(Tree.DecLit(value)) => Lit(Tree.DecLit(value)) case Lit(Tree.BoolLit(value)) => Lit(Tree.BoolLit(value)) case Lit(Tree.UnitLit(value)) => Lit(Tree.UnitLit(value)) + case term @ Resolved(t, sym) => Resolved(t.mkClone, sym)(term.typ) case term @ Ref(sym) => Ref(sym)(Tree.Ident(term.tree.name), term.refNum, term.typ) case term @ Sel(prefix, nme) => Sel(prefix.mkClone, Tree.Ident(nme.name))(term.sym, term.typ) case term @ App(lhs, rhs) => App(lhs.mkClone, rhs.mkClone)(term.tree, term.typ, term.resSym) @@ -420,6 +428,7 @@ sealed trait Statement extends AutoLocated, ProductWithExtraInfo: case _ => subTerms def subTerms: Ls[Term] = this match case Error | Missing | _: Lit | _: Ref | _: UnitVal => Nil + case Resolved(t, sym) => t :: Nil case App(lhs, rhs) => lhs :: rhs :: Nil case RcdField(lhs, rhs) => lhs :: rhs :: Nil case RcdSpread(bod) => bod :: Nil @@ -493,6 +502,8 @@ sealed trait Statement extends AutoLocated, ProductWithExtraInfo: def showDbg: Str = this match case r: Ref => showPlain + case r: Resolved => + s"${r.showPlain}‹${r.sym}›" case trm: Term => // s"$showPlain‹${trm.symbol.getOrElse("")}›" s"$showPlain${trm.symbol.fold("")("‹"+_+"›")}" @@ -506,6 +517,7 @@ sealed trait Statement extends AutoLocated, ProductWithExtraInfo: def showPlain: Str = this match case Term.UnitVal() => "()" case Lit(lit) => lit.idStr + case Resolved(t, sym) => t.showPlain case r @ Ref(symbol) => symbol.toString + symbol.getState.dbgRefNum(r.refNum) case App(lhs, rhs) => s"${lhs.showDbg}${rhs.showAsParams}" case RcdField(lhs, rhs) => s"${lhs.showDbg}: ${rhs.showDbg}" From 113fbe69812323cfd0988619e37ff8d02b2a6913 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sun, 28 Sep 2025 00:49:15 +0800 Subject: [PATCH 02/55] Support lowering of `Term.Resolved` --- .../src/main/scala/hkmc2/codegen/Block.scala | 19 ++- .../hkmc2/codegen/BlockTransformer.scala | 4 +- .../scala/hkmc2/codegen/BlockTraverser.scala | 2 +- .../scala/hkmc2/codegen/HandlerLowering.scala | 14 +- .../scala/hkmc2/codegen/LambdaRewriter.scala | 2 +- .../src/main/scala/hkmc2/codegen/Lifter.scala | 44 ++--- .../main/scala/hkmc2/codegen/Lowering.scala | 151 +++++++++-------- .../main/scala/hkmc2/codegen/Printer.scala | 2 +- .../hkmc2/codegen/StackSafeTransform.scala | 4 +- .../scala/hkmc2/codegen/UsedVarAnalyzer.scala | 12 +- .../scala/hkmc2/codegen/js/JSBuilder.scala | 17 +- .../scala/hkmc2/codegen/llir/Builder.scala | 32 ++-- .../scala/hkmc2/semantics/Elaborator.scala | 26 +++ .../main/scala/hkmc2/semantics/Resolver.scala | 97 +++++++---- .../main/scala/hkmc2/semantics/Symbol.scala | 36 ++-- .../src/main/scala/hkmc2/semantics/Term.scala | 3 + hkmc2/shared/src/test/mlscript/HkScratch.mls | 159 +++++++++++++++++- .../OverloadedModulesInSignatures.mls | 52 +++--- .../src/test/mlscript/backlog/NewWith.mls | 4 +- .../basics/CompanionModules_Classes.mls | 22 ++- .../src/test/mlscript/basics/DataClass.mls | 2 +- .../test/mlscript/basics/ModuleMethods.mls | 4 +- .../src/test/mlscript/basics/MutRcd.mls | 96 +++++++++++ .../src/test/mlscript/codegen/BasicTerms.mls | 4 +- .../test/mlscript/codegen/FieldSymbols.mls | 30 +++- .../test/mlscript/codegen/PlainClasses.mls | 2 +- .../test/mlscript/ctx/MissingDefinitions2.mls | 2 +- hkmc2/shared/src/test/mlscript/ctx/Summon.mls | 11 +- .../test/mlscript/ctx/SymbolResolution.mls | 118 +++++++++---- .../src/test/mlscript/ctx/TypeResolution.mls | 62 +++++-- .../src/test/mlscript/decls/Prelude.mls | 6 +- .../test/mlscript/handlers/GeneratorStack.mls | 27 +++ .../mlscript/lifter/ClassWithCompanion.mls | 136 ++++++++++++++- hkmc2/shared/src/test/mlscript/llir/Split.mls | 4 +- hkmc2/shared/src/test/mlscript/llir/Tuple.mls | 2 +- .../src/test/mlscript/llir/nofib/scc.mls | 4 +- hkmc2/shared/src/test/mlscript/nofib/scc.mls | 2 +- .../src/test/mlscript/parser/Handler.mls | 6 +- .../mlscript/ucs/future/SymbolicClass.mls | 2 +- .../test/scala/hkmc2/JSBackendDiffMaker.scala | 2 +- 40 files changed, 914 insertions(+), 310 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala index 6422f95961..f09a4873b4 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala @@ -492,7 +492,7 @@ sealed abstract class Result extends AutoLocated: case Instantiate(mut, cls, args) => cls :: args.map(_.value) case Select(qual, name) => qual :: name :: Nil case DynSelect(qual, fld, arrayIdx) => qual :: fld :: Nil - case Value.Ref(l) => Nil + case Value.Ref(l, disamb) => Nil case Value.This(sym) => Nil case Value.Lit(lit) => lit :: Nil case Value.Lam(params, body) => params :: Nil @@ -512,7 +512,7 @@ sealed abstract class Result extends AutoLocated: case Call(fun, args) => fun.freeVars ++ args.flatMap(_.value.freeVars).toSet case Instantiate(mut, cls, args) => cls.freeVars ++ args.flatMap(_.value.freeVars).toSet case Select(qual, name) => qual.freeVars - case Value.Ref(l) => Set(l) + case Value.Ref(l, disamb) => Set(l) case Value.This(sym) => Set.empty case Value.Lit(lit) => Set.empty case Value.Lam(params, body) => body.freeVars -- params.paramSyms @@ -525,11 +525,11 @@ sealed abstract class Result extends AutoLocated: case Call(fun, args) => fun.freeVarsLLIR ++ args.flatMap(_.value.freeVarsLLIR).toSet case Instantiate(mut, cls, args) => cls.freeVarsLLIR ++ args.flatMap(_.value.freeVarsLLIR).toSet case Select(qual, name) => qual.freeVarsLLIR - case Value.Ref(l: (BuiltinSymbol | TopLevelSymbol | ClassSymbol | TermSymbol)) => Set.empty - case Value.Ref(l: MemberSymbol[?]) => l.defn match + case Value.Ref(l: (BuiltinSymbol | TopLevelSymbol | ClassSymbol | TermSymbol), disamb) => Set.empty + case Value.Ref(l: MemberSymbol[?], disamb) => l.defn match case Some(d: ClassLikeDef) => Set.empty case _ => Set(l) - case Value.Ref(l) => Set(l) + case Value.Ref(l, disamb) => Set(l) case Value.This(sym) => Set.empty case Value.Lit(lit) => Set.empty case Value.Lam(params, body) => body.freeVarsLLIR -- params.paramSyms @@ -561,13 +561,18 @@ case class Select(qual: Path, name: Tree.Ident)(val symbol: Opt[FieldSymbol]) ex case class DynSelect(qual: Path, fld: Path, arrayIdx: Bool) extends Path enum Value extends Path: - case Ref(l: Local) + case Ref(l: Local, disamb: Opt[DefinitionSymbol[?]]) case This(sym: InnerSymbol) // TODO rm – just use Ref case Lit(lit: Literal) case Lam(params: ParamList, body: Block) case Arr(mut: Bool, elems: Ls[Arg]) case Rcd(mut: Bool, elems: Ls[RcdArg]) +object Value: + object Ref: + def apply(l: DefinitionSymbol[?]): Ref = Ref(l, S(l)) + def apply(l: TempSymbol | VarSymbol | BuiltinSymbol): Ref = Ref(l, N) + case class Arg(spread: Opt[Bool], value: Path) // * `IndxdArg(S(idx), value)` represents a key-value pair in a record `(idx): value` @@ -597,6 +602,6 @@ extension (k: Block => Block) def blockBuilder: Block => Block = identity extension (l: Local) - def asPath: Path = Value.Ref(l) + def asPath: Path = Value.Ref(l, N) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala index 3bc4d03145..c455553650 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala @@ -118,9 +118,9 @@ class BlockTransformer(subst: SymbolSubst): case v: Value => applyValue(v) def applyValue(v: Value): Value = v match - case Value.Ref(l) => + case Value.Ref(l, disamb) => val l2 = l.subst - if (l2 is l) then v else Value.Ref(l2) + if (l2 is l) then v else Value.Ref(l2, disamb) case Value.This(sym) => val sym2 = sym.subst if (sym2 is sym) then v else Value.This(sym2) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala index 2ca465b88e..2144f158ec 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala @@ -65,7 +65,7 @@ class BlockTraverser: case v: Value => applyValue(v) def applyValue(v: Value): Unit = v match - case Value.Ref(l) => l.traverse + case Value.Ref(l, disamb) => l.traverse case Value.This(sym) => sym.traverse case Value.Lit(lit) => () case v @ Value.Lam(params, body) => applyLam(v) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala index f740e6b9c9..6910db87e4 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala @@ -123,7 +123,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, def apply(res: Local, uid: StateId, rest: Block) = Assign(res, PureCall(Value.Ref(resumptionSymbol), List(Value.Lit(Tree.IntLit(uid)))), rest) def unapply(blk: Block) = blk match - case Assign(res, PureCall(Value.Ref(`resumptionSymbol`), List(Value.Lit(Tree.IntLit(uid)))), rest) => + case Assign(res, PureCall(Value.Ref(`resumptionSymbol`, _), List(Value.Lit(Tree.IntLit(uid)))), rest) => Some(res, uid, rest) case _ => None @@ -132,7 +132,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, def apply(res: Local, uid: StateId) = Assign(res, PureCall(Value.Ref(returnContSymbol), List(Value.Lit(Tree.IntLit(uid)))), End("")) def unapply(blk: Block) = blk match - case Assign(res, PureCall(Value.Ref(`returnContSymbol`), List(Value.Lit(Tree.IntLit(uid)))), _) => + case Assign(res, PureCall(Value.Ref(`returnContSymbol`, _), List(Value.Lit(Tree.IntLit(uid)))), _) => Some(res, uid) case _ => None @@ -148,7 +148,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, def unapply(blk: Block) = blk match case Assign( res, - PureCall(Value.Ref(`callSymbol`), List(Value.Lit(Tree.IntLit(uid)))), + PureCall(Value.Ref(`callSymbol`, _), List(Value.Lit(Tree.IntLit(uid)))), Assign(_, c, rest)) => Some(res, uid, c, rest) case _ => None @@ -158,7 +158,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, def apply(uid: StateId) = Return(PureCall(Value.Ref(transitionSymbol), List(Value.Lit(Tree.IntLit(uid)))), false) def unapply(blk: Block) = blk match - case Return(PureCall(Value.Ref(`transitionSymbol`), List(Value.Lit(Tree.IntLit(uid)))), false) => + case Return(PureCall(Value.Ref(`transitionSymbol`, _), List(Value.Lit(Tree.IntLit(uid)))), false) => S(uid) case _ => N @@ -166,7 +166,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, private val fnEndSymbol = freshTmp("fnEnd") def apply() = Return(PureCall(Value.Ref(fnEndSymbol), Nil), false) def unapply(blk: Block) = blk match - case Return(PureCall(Value.Ref(`fnEndSymbol`), Nil), false) => true + case Return(PureCall(Value.Ref(`fnEndSymbol`, _), Nil), false) => true case _ => false private class FreshId: @@ -397,7 +397,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, ResultPlaceholder(res, freshId(), c2, k(Value.Ref(res))) case r => super.applyResult2(r)(k) override def applyPath(p: Path): Path = p match - case Value.Ref(`getLocalsSym`) => handlerCtx.debugInfo.prevLocalsFn.get + case Value.Ref(`getLocalsSym`, _) => handlerCtx.debugInfo.prevLocalsFn.get case _ => super.applyPath(p) override def applyLam(lam: Value.Lam): Value.Lam = // This should normally be unreachable due to prior desugaring of lambda @@ -501,7 +501,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, val body = blockBuilder .define(clsDefn) - .assign(h.lhs, Instantiate(mut = true, Value.Ref(clsDefn.sym), Nil)) + .assign(h.lhs, Instantiate(mut = true, Value.Ref(clsDefn.sym, S(h.cls)), Nil)) .rest(handlerBody) val defn = FunDefn( diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/LambdaRewriter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/LambdaRewriter.scala index c113108229..0ffac8584f 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/LambdaRewriter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/LambdaRewriter.scala @@ -28,7 +28,7 @@ object LambdaRewriter: case lam: Value.Lam => val sym = BlockMemberSymbol("lambda", Nil, nameIsMeaningful = false) lambdasList ::= (sym -> super.applyLam(lam)) - Value.Ref(sym) + Value.Ref(sym, N) case _ => super.applyValue(v) val blk = lambdaRewriter.applyBlock(b) (blk, lambdasList) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index fd9e7527fa..bee77267fb 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -100,16 +100,16 @@ object Lifter: object RefOfBms: def unapply(p: Path) = p match - case Value.Ref(l: BlockMemberSymbol) => S(l) + case Value.Ref(l: BlockMemberSymbol, disamb) => S((l, disamb)) case s @ Select(_, _) => s.symbol match - case Some(value: BlockMemberSymbol) => S(value) + case Some(value: BlockMemberSymbol) => S(value, N) case _ => N case _ => N object InstSel: def unapply(p: Path) = p match - case Value.Ref(l: BlockMemberSymbol) => S(l) - case s @ Select(Value.Ref(l: BlockMemberSymbol), Tree.Ident("class")) => S(l) + case Value.Ref(l: BlockMemberSymbol, _) => S(l) + case s @ Select(Value.Ref(l: BlockMemberSymbol, _), Tree.Ident("class")) => S(l) case _ => N def modOrObj(d: Defn) = d match @@ -435,7 +435,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): case _ => () override def applyResult(r: Result): Unit = r match - case Call(Value.Ref(_: BlockMemberSymbol), args) => + case Call(Value.Ref(_: BlockMemberSymbol, _), args) => args.foreach(applyArg) case Instantiate(mut, InstSel(_), args) => args.foreach(applyArg) @@ -459,9 +459,9 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): parentPath match case None => () case Some(path) if isHandlerClsPath(path) => () - case Some(Select(RefOfBms(s), Tree.Ident("class"))) => + case Some(Select(RefOfBms(s, _), Tree.Ident("class"))) => if clsSyms.contains(s) then extendsGraph += (s -> defn.sym) - case Some(RefOfBms(s)) => + case Some(RefOfBms(s, _)) => if clsSyms.contains(s) then extendsGraph += (s -> defn.sym) case _ if !ignored.contains(defn.sym) => raise(WarningReport( @@ -482,7 +482,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): mod.foreach(applyClsLikeBody) override def applyValue(v: Value): Unit = v match - case RefOfBms(l) if clsSyms.contains(l) && !modOrObj(ctx.defns(l)) => + case RefOfBms(l, _) if clsSyms.contains(l) && !modOrObj(ctx.defns(l)) => raise(WarningReport( msg"Cannot yet lift class `${l.nme}` as it is used as a first-class class." -> N :: Nil, N, Diagnostic.Source.Compilation @@ -593,7 +593,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): override def applyResult(r: Result): Result = r match // if possible, directly rewrite the call using the efficient version - case c @ Call(RefOfBms(l), args) => ctx.bmsReqdInfo.get(l) match + case c @ Call(RefOfBms(l, _), args) => ctx.bmsReqdInfo.get(l) match case Some(info) if !ctx.isModOrObj(l) => val extraArgs = ctx.defns.get(l) match // If it's a class, we need to add the isMut parameter. @@ -611,20 +611,22 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): Call(info.singleCallBms.asPath, extraArgs ++ newArgs)(true, false) case _ => super.applyResult(r) // if possible, directly create the bms and replace the result with it - case RefOfBms(l) if ctx.bmsReqdInfo.contains(l) && !ctx.isModOrObj(l) => + case RefOfBms(l, _) if ctx.bmsReqdInfo.contains(l) && !ctx.isModOrObj(l) => createCall(l, ctx) case _ => super.applyResult(r) // otherwise, there's no choice but to create the call earlier override def applyPath(p: Path): Path = p match - case RefOfBms(l) if ctx.bmsReqdInfo.contains(l) && !ctx.isModOrObj(l) => + case RefOfBms(l, disamb) if ctx.bmsReqdInfo.contains(l) && !ctx.isModOrObj(l) => val newSym = syms.get(l) match case None => val newSym = FlowSymbol(l.nme + "$this") syms.addOne(l -> newSym) newSym case Some(value) => value - Value.Ref(newSym) + Value.Ref(newSym, disamb) + // TODO: ^ + // TODO: Ref Refactorization case _ => super.applyPath(p) (walker.applyBlock(b), syms.toList) end rewriteBms @@ -699,11 +701,11 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): override def applyPath(p: Path): Path = p match // These two cases rewrites `this.whatever` when referencing an outer class's fields. - case Value.Ref(l: InnerSymbol) => + case Value.Ref(l: InnerSymbol, _) => ctx.resolveIsymPath(l) match case Some(value) if !iSymInScope(l) => value.read case _ => super.applyPath(p) - case Value.Ref(t: TermSymbol) if t.owner.isDefined => + case Value.Ref(t: TermSymbol, _) if t.owner.isDefined => ctx.resolveIsymPath(t.owner.get) match case Some(value) if !iSymInScope(t.owner.get) => if (t.k is syntax.LetBind) && !t.owner.forall(_.isInstanceOf[semantics.TopLevelSymbol]) then @@ -716,9 +718,11 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): case _ => super.applyPath(p) // Rewrites this.className.class to reference the top-level definition - case s @ Select(RefOfBms(l), Tree.Ident("class")) if !ctx.ignored(l) && ctx.isRelevant(l) => + case s @ Select(RefOfBms(l, disamb), Tree.Ident("class")) if !ctx.ignored(l) && ctx.isRelevant(l) => // this class will be lifted, rewrite the ref to strip it of `Select` - Select(Value.Ref(l), Tree.Ident("class"))(s.symbol) + Select(Value.Ref(l, disamb), Tree.Ident("class"))(s.symbol) + // TODO: ^ + // TODO: Ref Refactorization // For objects inside classes: When an object is nested inside a class, its defn will be // replaced by a symbol, to which the object instance is assigned. This rewrites references @@ -730,13 +734,13 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): // This is to rewrite references to classes that are not lifted (when their BlockMemberSymbol // reference is passed as function parameters). - case RefOfBms(l) if ctx.ignored(l) && ctx.isRelevant(l) => ctx.getIgnoredBmsPath(l) match + case RefOfBms(l, _) if ctx.ignored(l) && ctx.isRelevant(l) => ctx.getIgnoredBmsPath(l) match case Some(value) => value.read case None => super.applyPath(p) // This rewrites naked references to locals. If a function is in a capture, then we select that value // from the capture; otherwise, we see if that local is passed directly as a parameter to this defn. - case Value.Ref(l) => ctx.getLocalCaptureSym(l) match + case Value.Ref(l, _) => ctx.getLocalCaptureSym(l) match case Some(captureSym) => Select(ctx.getLocalClosPath(l).get.read, captureSym.id)(N) case None => ctx.getLocalPath(l) match @@ -1099,8 +1103,8 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): case d => d def rewriteExtends(p: Path): Path = p match - case RefOfBms(b) if !ctx.ignored(b) && ctx.isRelevant(b) => b.asPath - case Select(RefOfBms(b), Tree.Ident("class")) if !ctx.ignored(b) && ctx.isRelevant(b) => + case RefOfBms(b, _) if !ctx.ignored(b) && ctx.isRelevant(b) => b.asPath + case Select(RefOfBms(b, _), Tree.Ident("class")) if !ctx.ignored(b) && ctx.isRelevant(b) => Select(b.asPath, Tree.Ident("class"))(N) case _ => return p diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index 6c2d72198c..3c8b45aea5 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -44,7 +44,7 @@ class Subst(initMap: Map[Local, Value]): Subst(map + kv) */ def apply(v: Value): Value = v match - case Value.Ref(l) => map.getOrElse(l, v) + case Value.Ref(l, _) => map.getOrElse(l, v) case _ => v object Subst: val empty = Subst(Map.empty) @@ -289,6 +289,77 @@ class Lowering()(using Config, TL, Raise, State, Ctx): subTerm_nonTail(arg): ar => k(Arg(spread = S(true), ar) :: Nil) + def ref(ref: st.Ref, disamb: Opt[DefinitionSymbol[?]], inStmtPos: Bool)(k: Result => Block)(using Subst): Block = + def warnStmt = if inStmtPos then + raise: + WarningReport(msg"Pure expression in statement position" -> ref.toLoc :: Nil, S(ref)) + + val st.Ref(sym) = ref + sym match + case ctx.builtins.source.bms | ctx.builtins.js.bms | ctx.builtins.debug.bms | ctx.builtins.annotations.bms => + return fail: + ErrorReport( + msg"Module '${sym.nme}' is virtual (i.e., \"compiler fiction\"); cannot be used directly" -> ref.toLoc :: + Nil, S(ref), source = Diagnostic.Source.Compilation) + case sym if sym.asCls.exists(ctx.builtins.virtualClasses) => + return fail: + ErrorReport( + msg"Symbol '${sym.nme}' is virtual (i.e., \"compiler fiction\"); cannot be used as a term" -> ref.toLoc :: + Nil, S(ref), source = Diagnostic.Source.Compilation) + case _ => () + + sym match + case sym: BuiltinSymbol => + warnStmt + if sym.binary then + val t1 = new Tree.Ident("arg1") + val t2 = new Tree.Ident("arg2") + val p1 = Param(FldFlags.empty, VarSymbol(t1), N, Modulefulness.none) + val p2 = Param(FldFlags.empty, VarSymbol(t2), N, Modulefulness.none) + val ps = PlainParamList(p1 :: p2 :: Nil) + val bod = st.App(ref, st.Tup(List(st.Ref(p1.sym)(t1, 666, N).resolve, st.Ref(p2.sym)(t2, 666, N).resolve)) + (Tree.Tup(Nil // FIXME should not be required (using dummy value) + )))( + Tree.App(Tree.Empty(), Tree.Empty()), // FIXME should not be required (using dummy value) + N, + FlowSymbol(sym.nme) + ).resolve + val (paramLists, bodyBlock) = setupFunctionDef(ps :: Nil, bod, S(sym.nme)) + tl.log(s"Ref builtin $sym") + assert(paramLists.length === 1) + return k(Value.Lam(paramLists.head, bodyBlock).withLocOf(ref)) + if sym.unary then + val t1 = new Tree.Ident("arg") + val p1 = Param(FldFlags.empty, VarSymbol(t1), N, Modulefulness.none) + val ps = PlainParamList(p1 :: Nil) + val bod = st.App(ref, st.Tup(List(st.Ref(p1.sym)(t1, 666, N).resolve)) + (Tree.Tup(Nil // FIXME should not be required (using dummy value) + )))( + Tree.App(Tree.Empty(), Tree.Empty()), // FIXME should not be required (using dummy value) + N, + FlowSymbol(sym.nme) + ).resolve + val (paramLists, bodyBlock) = setupFunctionDef(ps :: Nil, bod, S(sym.nme)) + tl.log(s"Ref builtin $sym") + assert(paramLists.length === 1) + return k(Value.Lam(paramLists.head, bodyBlock).withLocOf(ref)) + case bs: BlockMemberSymbol => + disamb.flatMap(_.defn) orElse bs.defn match + case S(d) if d.hasDeclareModifier.isDefined => + return term(Sel(State.globalThisSymbol.ref().resolve, ref.tree)(S(bs), N).withLocOf(ref).resolve)(k) + case S(td: TermDefinition) if td.k is syntax.Fun => + // * Local functions with no parameter lists are getters + // * and are lowered to functions with an empty parameter list + // * (non-local functions are compiled into getter methods selected on some prefix) + if td.params.isEmpty then + val l = new TempSymbol(S(ref)) + return Assign(l, Call(Value.Ref(bs, disamb).withLocOf(ref), Nil)(true, true), k(Value.Ref(l, disamb))) + case S(_) => () + case N => () // TODO panic here; can only lower refs to elab'd symbols + case _ => () + warnStmt + k(subst(Value.Ref(sym, disamb).withLocOf(ref))) + @tailrec final def term(t: st, inStmtPos: Bool = false)(k: Result => Block)(using Subst): Block = tl.log(s"Lowering.term ${t.showDbg.truncate(100, "[...]")}${ @@ -317,71 +388,10 @@ class Lowering()(using Config, TL, Raise, State, Ctx): case st.CtxTup(fs) => // * This case is currently triggered for code such as `f(using 42)` args(fs)(args => k(Value.Arr(mut = false, args))) - case ref @ st.Ref(sym) => - sym match - case ctx.builtins.source.bms | ctx.builtins.js.bms | ctx.builtins.debug.bms | ctx.builtins.annotations.bms => - return fail: - ErrorReport( - msg"Module '${sym.nme}' is virtual (i.e., \"compiler fiction\"); cannot be used directly" -> t.toLoc :: - Nil, S(t), source = Diagnostic.Source.Compilation) - case sym if sym.asCls.exists(ctx.builtins.virtualClasses) => - return fail: - ErrorReport( - msg"Symbol '${sym.nme}' is virtual (i.e., \"compiler fiction\"); cannot be used as a term" -> t.toLoc :: - Nil, S(t), source = Diagnostic.Source.Compilation) - case _ => () - - sym match - case sym: BuiltinSymbol => - warnStmt - if sym.binary then - val t1 = new Tree.Ident("arg1") - val t2 = new Tree.Ident("arg2") - val p1 = Param(FldFlags.empty, VarSymbol(t1), N, Modulefulness.none) - val p2 = Param(FldFlags.empty, VarSymbol(t2), N, Modulefulness.none) - val ps = PlainParamList(p1 :: p2 :: Nil) - val bod = st.App(t, st.Tup(List(st.Ref(p1.sym)(t1, 666, N).resolve, st.Ref(p2.sym)(t2, 666, N).resolve)) - (Tree.Tup(Nil // FIXME should not be required (using dummy value) - )))( - Tree.App(Tree.Empty(), Tree.Empty()), // FIXME should not be required (using dummy value) - N, - FlowSymbol(sym.nme) - ).resolve - val (paramLists, bodyBlock) = setupFunctionDef(ps :: Nil, bod, S(sym.nme)) - tl.log(s"Ref builtin $sym") - assert(paramLists.length === 1) - return k(Value.Lam(paramLists.head, bodyBlock).withLocOf(ref)) - if sym.unary then - val t1 = new Tree.Ident("arg") - val p1 = Param(FldFlags.empty, VarSymbol(t1), N, Modulefulness.none) - val ps = PlainParamList(p1 :: Nil) - val bod = st.App(t, st.Tup(List(st.Ref(p1.sym)(t1, 666, N).resolve)) - (Tree.Tup(Nil // FIXME should not be required (using dummy value) - )))( - Tree.App(Tree.Empty(), Tree.Empty()), // FIXME should not be required (using dummy value) - N, - FlowSymbol(sym.nme) - ).resolve - val (paramLists, bodyBlock) = setupFunctionDef(ps :: Nil, bod, S(sym.nme)) - tl.log(s"Ref builtin $sym") - assert(paramLists.length === 1) - return k(Value.Lam(paramLists.head, bodyBlock).withLocOf(ref)) - case bs: BlockMemberSymbol => - bs.defn match - case S(d) if d.hasDeclareModifier.isDefined => - return term(Sel(State.globalThisSymbol.ref().resolve, ref.tree)(S(bs), N).withLocOf(ref).resolve)(k) - case S(td: TermDefinition) if td.k is syntax.Fun => - // * Local functions with no parameter lists are getters - // * and are lowered to functions with an empty parameter list - // * (non-local functions are compiled into getter methods selected on some prefix) - if td.params.isEmpty then - val l = new TempSymbol(S(t)) - return Assign(l, Call(Value.Ref(bs).withLocOf(ref), Nil)(true, true), k(Value.Ref(l))) - case S(_) => () - case N => () // TODO panic here; can only lower refs to elab'd symbols - case _ => () - warnStmt - k(subst(Value.Ref(sym).withLocOf(ref))) + case t @ st.Ref(sym) => + ref(t, N, inStmtPos)(k) + case st.Resolved(t @ st.Ref(bsym), sym) => + ref(t, S(sym), inStmtPos)(k) case st.App(ref @ Ref(sym: BuiltinSymbol), arg) => arg match case st.Tup(Nil) => @@ -424,6 +434,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): case _: sem.BuiltinSymbol => true case sym: sem.BlockMemberSymbol => sym.trmImplTree.fold(sym.clsTree.isDefined)(_.k is syntax.Fun) + case sym: sem.TermSymbol => sym.k is syntax.Fun // Do not perform safety check on `MatchResult` and `MatchFailure`. case sym => (sym is State.matchResultClsSymbol) || (sym is State.matchFailureClsSymbol) @@ -448,7 +459,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): msg"Debugging functions are not enabled" -> t.toLoc :: Nil, source = Diagnostic.Source.Compilation) - conclude(Value.Ref(ctx.builtins.debug.getLocals).withLocOf(f)) + conclude(Value.Ref(ctx.builtins.debug.getLocals, N).withLocOf(f)) // * Due to whacky JS semantics, we need to make sure that selections leading to a call // * are preserved in the call and not moved to a temporary variable. case sel @ Sel(prefix, nme) => @@ -694,7 +705,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): val pctor = parentConstructor(cls, as) val clsDef = ClsLikeDefn(N, isym, sym, syntax.Cls, N, Nil, S(sr), mtds, privateFlds, publicFlds, pctor, ctor, N) - val inner = new New(sym.ref().resolve, Nil, N) + val inner = new New(sym.ref().resolved(isym), Nil, N) Define(clsDef, term_nonTail(if mut then Mut(inner) else inner)(k)) case Try(sub, finallyDo) => @@ -807,8 +818,10 @@ class Lowering()(using Config, TL, Raise, State, Ctx): case Ref(sym) if Elaborator.binaryOps.contains(sym.nme) => // builtin symbols val l = new TempSymbol(N) setupTerm("Builtin", Value.Lit(Tree.StrLit(sym.nme)) :: Nil)(k) + case Resolved(Ref(sym), disamb) => + k(Value.Ref(sym, S(disamb))) case Ref(sym) => - k(Value.Ref(sym)) + k(Value.Ref(sym, N)) case SynthSel(Ref(sym: ModuleOrObjectSymbol), name) => // Local cross-stage references setupSymbol(sym): r1 => val l1, l2 = new TempSymbol(N) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala index 17869af002..dd634b6296 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala @@ -91,7 +91,7 @@ object Printer: else doc def mkDocument(value: Value)(using Raise, Scope): Document = value match - case Value.Ref(l) => getVar(l) + case Value.Ref(l, _) => getVar(l) case Value.This(sym) => doc"this" case Value.Lit(lit) => doc"${lit.idStr}" case Value.Lam(params, body) => diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala index 6e1f313e79..e33670d43a 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala @@ -50,7 +50,7 @@ class StackSafeTransform(depthLimit: Int, paths: HandlerPaths)(using State): // Rewrites anything that can contain a Call to increase the stack depth def transform(b: Block, curDepth: => Symbol, isTopLevel: Bool = false): Block = def usesStack(r: Result) = r match - case Call(Value.Ref(_: BuiltinSymbol), _) => false + case Call(Value.Ref(_: BuiltinSymbol, _), _) => false case _: Call | _: Instantiate => true case _ => false @@ -114,7 +114,7 @@ class StackSafeTransform(depthLimit: Int, paths: HandlerPaths)(using State): new BlockTraverserShallow: applyBlock(b) override def applyResult(r: Result): Unit = r match - case Call(Value.Ref(_: BuiltinSymbol), _) => () + case Call(Value.Ref(_: BuiltinSymbol, _), _) => () case _: Call | _: Instantiate => trivial = false case _ => () trivial diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/UsedVarAnalyzer.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/UsedVarAnalyzer.scala index bcad5f6ae7..03a2b3775a 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/UsedVarAnalyzer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/UsedVarAnalyzer.scala @@ -141,10 +141,10 @@ class UsedVarAnalyzer(b: Block, handlerPaths: Opt[HandlerPaths])(using State): case _ => super.applyBlock(b) override def applyValue(v: Value): Unit = v match - case Value.Ref(_: BuiltinSymbol) => super.applyValue(v) - case RefOfBms(l) => + case Value.Ref(_: BuiltinSymbol, _) => super.applyValue(v) + case RefOfBms(l, _) => accessed = accessed.addRefdDefn(l) - case Value.Ref(l) => + case Value.Ref(l, _) => accessed = accessed.addAccess(l) case _ => super.applyValue(v) @@ -364,7 +364,7 @@ class UsedVarAnalyzer(b: Block, handlerPaths: Opt[HandlerPaths])(using State): hasMutator += l override def applyResult(r: Result): Unit = r match - case Call(RefOfBms(l), args) => + case Call(RefOfBms(l, _), args) => args.map(super.applyArg(_)) handleCalledBms(l) case Instantiate(mut, InstSel(l), args) => @@ -373,7 +373,7 @@ class UsedVarAnalyzer(b: Block, handlerPaths: Opt[HandlerPaths])(using State): case _ => super.applyResult(r) override def applyPath(p: Path): Unit = p match - case RefOfBms(l) => + case RefOfBms(l, _) => defnSyms.get(l) match case None => super.applyPath(p) case Some(defn) => @@ -403,7 +403,7 @@ class UsedVarAnalyzer(b: Block, handlerPaths: Opt[HandlerPaths])(using State): reqCapture += l hasMutator += l - case Value.Ref(l) => + case Value.Ref(l, _) => if hasMutator.contains(l) then reqCapture += (l) case _ => super.applyPath(p) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala index cf99b29bfc..4ffa0c211c 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala @@ -108,22 +108,25 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: case Value.This(sym) => scope.findThis_!(sym) case Value.Lit(Tree.StrLit(value)) => makeStringLiteral(value) case Value.Lit(lit) => lit.idStr - case Value.Ref(l: BuiltinSymbol) => + case Value.Ref(l: BuiltinSymbol, _) => if l.nullary then l.nme else errExpr(msg"Illegal reference to builtin symbol '${l.nme}'") - case Value.Ref(l) => getVar(l, r.toLoc) - - case Call(Value.Ref(l: BuiltinSymbol), lhs :: rhs :: Nil) if !l.functionLike => + case Value.Ref(l, disamb) => l match + case l: BlockMemberSymbol if l.hasLiftedClass && disamb.flatMap(d => d.asMod orElse d.asCls).isDefined => + doc"${getVar(l, l.toLoc)}.class" + case _ => + getVar(l, r.toLoc) + case Call(Value.Ref(l: BuiltinSymbol, _), lhs :: rhs :: Nil) if !l.functionLike => if l.binary then val res = doc"${operand(lhs)} ${l.nme} ${operand(rhs)}" if needsParens(l.nme) then doc"(${res})" else res else errExpr(msg"Cannot call non-binary builtin symbol '${l.nme}'") - case Call(Value.Ref(l: BuiltinSymbol), rhs :: Nil) if !l.functionLike => + case Call(Value.Ref(l: BuiltinSymbol, _), rhs :: Nil) if !l.functionLike => if l.unary then val res = doc"${l.nme} ${operand(rhs)}" if needsParens(l.nme) then doc"(${res})" else res else errExpr(msg"Cannot call non-unary builtin symbol '${l.nme}'") - case Call(Value.Ref(l: BuiltinSymbol), args) => + case Call(Value.Ref(l: BuiltinSymbol, _), args) => if l.functionLike then val argsDoc = args.map(argument).mkDocument(", ") doc"${l.nme}(${argsDoc})" @@ -335,7 +338,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: else v ownr match case S(owner) => - doc" # ${result(Value.Ref(owner))}.${sym.nme}$extraPath = $rhs" + doc" # ${result(Value.Ref(owner, N))}.${sym.nme}$extraPath = $rhs" case N => doc" # ${getVar(sym, sym.toLoc)}$extraPath = $rhs" } :/: ctorHead :: " " :: braced(ctorAux) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala index d9cc6f37a7..8581517d11 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala @@ -222,8 +222,8 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): given Ctx = ctx.setClass(isym) val funcs = methods.map(bMethodDef) def parentFromPath(p: Path): Set[Local] = p match - case Value.Ref(l) => Set(fromMemToClass(l)) - case Select(Value.Ref(l), Tree.Ident("class")) => Set(fromMemToClass(l)) + case Value.Ref(l, _) => Set(fromMemToClass(l)) + case Select(Value.Ref(l, _), Tree.Ident("class")) => Set(fromMemToClass(l)) case _ => bErrStop(msg"Unsupported parent path ${p.toString()}") ClassInfo( uid.make, @@ -277,12 +277,12 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): private def bValue(v: Value)(k: TrivialExpr => Ctx ?=> Node)(using ctx: Ctx)(using Raise, Scope) : Node = trace[Node](s"bValue { $v } begin", x => s"bValue end: ${x.show}"): v match - case Value.Ref(l: TermSymbol) if l.owner.nonEmpty => + case Value.Ref(l: TermSymbol, _) if l.owner.nonEmpty => k(l |> sr) - case Value.Ref(sym) if sym.nme.isCapitalized => + case Value.Ref(sym, _) if sym.nme.isCapitalized => val v: Local = newTemp Node.LetExpr(v, Expr.CtorApp(fromMemToClass(sym), Ls()), k(v |> sr)) - case Value.Ref(l) => + case Value.Ref(l, _) => ctx.fn_ctx.get(l) match case Some(f) => val tempSymbols = (0 until f.paramsSize).map(x => newNamed("arg")) @@ -329,9 +329,9 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): private def bPath(p: Path)(k: TrivialExpr => Ctx ?=> Node)(using ctx: Ctx)(using Raise, Scope) : Node = trace[Node](s"bPath { $p } begin", x => s"bPath end: ${x.show}"): p match - case s @ Select(Value.Ref(sym), Tree.Ident("Unit")) if sym is ctx.builtinSym.runtimeSym.get => + case s @ Select(Value.Ref(sym, _), Tree.Ident("Unit")) if sym is ctx.builtinSym.runtimeSym.get => bPath(Value.Lit(Tree.UnitLit(false)))(k) - case s @ Select(Value.Ref(cls: ClassSymbol), name) if ctx.method_class.contains(cls) => + case s @ Select(Value.Ref(cls: ClassSymbol, _), name) if ctx.method_class.contains(cls) => s.symbol match case None => ctx.flow_ctx.get(p) match @@ -373,12 +373,12 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): private def bResult(r: Result)(k: TrivialExpr => Ctx ?=> Node)(using ctx: Ctx)(using Raise, Scope) : Node = trace[Node](s"bResult begin", x => s"bResult end: ${x.show}"): r match - case Call(Value.Ref(sym: BuiltinSymbol), args) => + case Call(Value.Ref(sym: BuiltinSymbol, _), args) => bArgs(args): case args: Ls[TrivialExpr] => val v: Local = newTemp Node.LetExpr(v, Expr.BasicOp(sym, args), k(v |> sr)) - case Call(Value.Ref(sym: MemberSymbol[?]), args) if sym.defn.exists(defn => defn match + case Call(Value.Ref(sym: MemberSymbol[?], _), args) if sym.defn.exists(defn => defn match case cls: ClassLikeDef => true case _ => false ) => @@ -387,7 +387,7 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case args: Ls[TrivialExpr] => val v: Local = newTemp Node.LetExpr(v, Expr.CtorApp(fromMemToClass(sym), args), k(v |> sr)) - case Call(s @ Value.Ref(sym), args) => + case Call(s @ Value.Ref(sym, _), args) => val v: Local = newTemp ctx.fn_ctx.get(sym) match case Some(f) => @@ -400,22 +400,22 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): bArgs(args): case args: Ls[TrivialExpr] => Node.LetMethodCall(Ls(v), builtinCallable, builtinApply(args.length), f :: args, k(v |> sr)) - case Call(Select(Value.Ref(_: TopLevelSymbol), Tree.Ident("builtin")), args) => + case Call(Select(Value.Ref(_: TopLevelSymbol, _), Tree.Ident("builtin")), args) => bArgs(args): case args: Ls[TrivialExpr] => val v: Local = newTemp Node.LetCall(Ls(v), builtin, args, k(v |> sr)) - case Call(Select(Select(Value.Ref(_: TopLevelSymbol), Tree.Ident("console")), Tree.Ident("log")), args) => + case Call(Select(Select(Value.Ref(_: TopLevelSymbol, _), Tree.Ident("console")), Tree.Ident("log")), args) => bArgs(args): case args: Ls[TrivialExpr] => val v: Local = newTemp Node.LetCall(Ls(v), builtin, Expr.Literal(Tree.StrLit("println")) :: args, k(v |> sr)) - case Call(Select(Select(Value.Ref(_: TopLevelSymbol), Tree.Ident("Math")), Tree.Ident(mathPrimitive)), args) => + case Call(Select(Select(Value.Ref(_: TopLevelSymbol, _), Tree.Ident("Math")), Tree.Ident(mathPrimitive)), args) => bArgs(args): case args: Ls[TrivialExpr] => val v: Local = newTemp Node.LetCall(Ls(v), builtin, Expr.Literal(Tree.StrLit(mathPrimitive)) :: args, k(v |> sr)) - case Call(s @ Select(r @ Value.Ref(sym), Tree.Ident(fld)), args) if s.symbol.isDefined => + case Call(s @ Select(r @ Value.Ref(sym, _), Tree.Ident(fld)), args) if s.symbol.isDefined => bPath(r): case r => bArgs(args): @@ -426,7 +426,7 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case Call(_, _) => bErrStop(msg"Unsupported kind of Call ${r.toString()}") case Instantiate( false, - Select(Value.Ref(sym), Tree.Ident("class")), args) => + Value.Ref(sym, S(_: (ClassSymbol | ModuleOrObjectSymbol))), args) => bArgs(args): case args: Ls[TrivialExpr] => val v: Local = newTemp @@ -474,7 +474,7 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): summon[Ctx].def_acc += jpdef Node.Case(e, casesList, defaultCase) case Return(res, implct) => bResult(res)(x => Node.Result(Ls(x))) - case Throw(Instantiate(false, Select(Value.Ref(_), ident), + case Throw(Instantiate(false, Select(Value.Ref(_, _), ident), Ls(Arg(N, Value.Lit(Tree.StrLit(e)))))) if ident.name === "Error" => Node.Panic(e) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index c7c5e8d4ef..792b5e4bff 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -1093,6 +1093,8 @@ extends Importer: Fun, mtdSym, tsym, PlainParamList(Param(FldFlags.empty, valueSym, N, Modulefulness.none) :: Nil) :: Nil, N, N, S(valueSym.ref(Ident("value"))), FlowSymbol(s"‹result of non-local return›"), TermDefFlags.empty, Modulefulness.none, Nil, N) tsym.defn = S(td) + mtdSym.defn = S(td) + mtdSym.tdefn = S(td) val htd = HandlerTermDefinition(resumeSym, td) Term.Handle(nonLocalRetHandler, state.nonLocalRetHandlerTrm, Nil, clsSym, htd :: Nil, b) val r = FlowSymbol(s"‹result of ${sym}›") @@ -1111,6 +1113,7 @@ extends Importer: TermDefFlags.empty.copy(isMethod = isMethod), mfn, annotations, N) tsym.defn = S(tdf) sym.defn = S(tdf) + sym.tdefn = S(tdf) tdf go(sts, Nil, tdf :: acc) @@ -1197,6 +1200,7 @@ extends Importer: assert(p.fldSym.isEmpty) p.fldSym = S(fsym) fsym.defn = S(fdef) + fsym.tdefn = S(fdef) tsym.defn = S(fdef) fdef :: Nil else @@ -1319,6 +1323,28 @@ extends Importer: val (bod, c) = mkBody ClassDef(owner, Cls, clsSym, sym, tps, pss, newOf(td), ObjBody(bod), annotations, comp) clsSym.defn = S(cd) + if pss.nonEmpty then + val ctsym = TermSymbol(Fun, S(clsSym), clsSym.id) + val ctdef = + TermDefinition( + Fun, + sym, + ctsym, + pss, + S(tps.map(tp => Param(FldFlags.empty, tp.sym, N, Modulefulness.none))), + S(clsSym.ref()), + N, + FlowSymbol(s"‹constructor›"), + TermDefFlags.empty, + Modulefulness.none, + annotations.collect: + case a @ Annot.Modifier(Keyword.`declare`) => a + , + S(clsSym), + ) + ctsym.defn = S(ctdef) + sym.tdefn = S(ctdef) + log(s"Constructor: ${ctdef}") cd sym.defn = S(defn) go(sts, Nil, defn :: acc) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 63e0fe0a2a..ef3731ac85 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -129,6 +129,7 @@ object Resolver: case Module(reason: Opt[Message]) case NonModule(reason: Opt[Message]) case Class(reason: Opt[Message]) + case Selectable(reason: Opt[Message]) case Any def message: Ls[Message -> Opt[Loc]] = this match @@ -266,7 +267,7 @@ class Resolver(tl: TraceLogger) traverseDefn(tdf) case t: Term => - traverse(t, expect = NonModule(N)) + traverse(t, expect = Any) ictx // Default Case. e.g., import statements, let bindings. @@ -277,7 +278,9 @@ class Resolver(tl: TraceLogger) traverseStmts(rest)(using newICtx) - def expand2DotClass(t: Resolvable, expect: Expect.Module | Expect.Class) = t.resolvedSym match + def expand2DotClass(t: Resolvable, expect: Expect.Module | Expect.Class) = + log(s"Expanding ${t} to ${t}.class because it is expected to be a ${expect}.") + t.resolvedSym match case S(bsym: BlockMemberSymbol) if bsym.hasLiftedClass => val sym = expect match case _: Expect.Module => bsym.asMod @@ -293,7 +296,7 @@ class Resolver(tl: TraceLogger) * check the modulefulness of the term. */ def traverse(t: Term, expect: Expect)(using ictx: ICtx): Unit = - trace(s"Traversing term: $t"): + trace(s"Traversing term: $t (expect = ${expect})"): t match case blk: Term.Blk => @@ -505,15 +508,17 @@ class Resolver(tl: TraceLogger) // Resolve the sub-resolvable-terms of the term. val (defn, newICtx1) = t match + case _: Term.Resolved => lastWords(s"Term ${t} is already resolved.") + // Note: the arguments of the App are traversed later because the // definition is required. case Term.App(lhs: Resolvable, args) => val result = args match case t @ Term.CtxTup(_) => - resolve(lhs, prefer = prefer, inAppPrefix = true, inCtxPrefix = true, inTyPrefix = inTyPrefix) + resolve(lhs, prefer = Any, inAppPrefix = true, inCtxPrefix = true, inTyPrefix = inTyPrefix) case _ => - resolve(lhs, prefer = prefer, inAppPrefix = true, inCtxPrefix = inCtxPrefix, inTyPrefix = inTyPrefix) - resolveSymbol(t, prefer = prefer) + resolve(lhs, prefer = Any, inAppPrefix = true, inCtxPrefix = inCtxPrefix, inTyPrefix = inTyPrefix) + resolveSymbol(t, prefer = prefer, sign = false) resolveType(t, prefer = prefer) result case Term.App(lhs, _) => @@ -522,8 +527,8 @@ class Resolver(tl: TraceLogger) case Term.TyApp(lhs: Resolvable, targs) => resolve(lhs, prefer = prefer, inAppPrefix = inAppPrefix, inCtxPrefix = inCtxPrefix, inTyPrefix = true) - targs.foreach(traverse(_, expect = Any)) - resolveSymbol(t, prefer = prefer) + targs.foreach(traverseSign(_, expect = Any)) + resolveSymbol(t, prefer = prefer, sign = false) resolveType(t, prefer = prefer) (t.callableDefn, ictx) case Term.TyApp(lhs, targs) => @@ -532,25 +537,25 @@ class Resolver(tl: TraceLogger) (t.callableDefn, ictx) case AnySel(pre: Resolvable, id) => - resolve(pre, prefer = prefer, inAppPrefix = false, inCtxPrefix = false, inTyPrefix = false) - resolveSymbol(t, prefer = prefer) + resolve(pre, prefer = Selectable(N), inAppPrefix = false, inCtxPrefix = false, inTyPrefix = false) + resolveSymbol(t, prefer = prefer, sign = false) resolveType(t, prefer = prefer) (t.callableDefn, ictx) case AnySel(pre, id) => - traverse(pre, expect = Any) + traverse(pre, expect = Selectable(N)) (t.callableDefn, ictx) case Term.Ref(_: BlockMemberSymbol) => - resolveSymbol(t, prefer = prefer) + resolveSymbol(t, prefer = prefer, sign = false) resolveType(t, prefer = prefer) (t.callableDefn, ictx) case Term.Ref(_) => - resolveSymbol(t, prefer = prefer) + resolveSymbol(t, prefer = prefer, sign = false) resolveType(t, prefer = prefer) (N, ictx) t.expandedResolvableIn: t => - log(s"Resolving resolvable term ${t} with sym = ${t.resolvedSym}, typ = ${t.resolvedTyp}: ${defn}") + log(s"Resolving resolvable term ${t} with sym = ${t.resolvedSym}, typ = ${t.resolvedTyp}: ${t.resolvedSym.map(_.asInstanceOf[MemberSymbol[?]].defn)}") // Fill the context with possibly the type arguments information. val newICtx2 = newICtx1.givenIn: @@ -737,7 +742,7 @@ class Resolver(tl: TraceLogger) t.expand(S(expansion)) expansion match // * expansion may change the semantics, thus symbol is also changed case r: Resolvable => - resolveSymbol(r, prefer = prefer) + resolveSymbol(r, prefer = prefer, sign = false) resolveType(r, prefer = prefer) case _ => () @@ -749,6 +754,19 @@ class Resolver(tl: TraceLogger) t.dontResolve (N, ictx) + def disambSym(expect: Expect, sign: Bool)(bms: BlockMemberSymbol): Opt[DefinitionSymbol[?]] = + expect match + // If it is expecting a class or module specifically, cast the symbol. + case _: Module => bms.asMod + case _: Class => bms.asCls + case _: Selectable => bms.asModOrObj + // If it is expecting a generic symbol, use asPrinciple for the "default interpretation". + case _: (Any.type | NonModule) if sign => + bms.asTpe + case _: (Any.type | NonModule) => + bms.asPrincipal + + /** * Resolve the symbol for a resolvable term, which was not resolved by * the elaborator due to unready definitions. After the symbol @@ -767,7 +785,7 @@ class Resolver(tl: TraceLogger) * This also expands the LHS `Foo` of a selection to `Foo.class` if * the selection is selecting a static member from a lifted module. */ - def resolveSymbol(t: Resolvable, prefer: Expect)(using ictx: ICtx): Unit = + def resolveSymbol(t: Resolvable, prefer: Expect, sign: Bool)(using ictx: ICtx): Unit = trace[Unit]( s"Resolving symbol for term: ${t} (prefer = ${prefer})", _ => s"-> (sym = ${t.resolvedSym}, typ = ${t.resolvedTyp})" @@ -789,8 +807,16 @@ class Resolver(tl: TraceLogger) // not try to resolve it again in the resolver. case _ if t.symbol.exists(_.isInstanceOf[ErrorSymbol]) => () + case t @ Term.Ref(bsym: BlockMemberSymbol) => + log(s"Resolving symbol for reference ${t} (bsym = ${bsym}, defn = ${bsym.defn})") + val sym = disambSym(prefer, sign = sign)(bsym) + sym.foreach: sym => + t.expand(S(Term.Resolved(t.duplicate, sym)(N))) + resolveType(t, prefer = prefer) + log(s"Resolved symbol for ${t}: ${sym}") + case t @ AnySel(lhs: Resolvable, id) => lhs.expandedResolvableIn: lhs => - log(s"Resolving symbol for ${t}, defn = ${lhs.defn}") + log(s"Resolving symbol for selection ${t}, defn = ${lhs.defn}") lhs.singletonDefn.foreach: mdef => val fsym = mdef.body.members.get(id.name) fsym match @@ -821,21 +847,28 @@ class Resolver(tl: TraceLogger) def resolveType(t: Resolvable, prefer: Expect)(using ictx: ICtx): Unit = t.expandedResolvableIn: t => trace[Unit]( s"Resolving the type for term: ${t} (prefer = ${prefer}, sym = ${t.resolvedSym})", - _ => s"-> typ = ${t.resolvedTyp})" + _ => s"-> typ = ${t.resolvedTyp}" ): def disambSym(bms: BlockMemberSymbol): Opt[FieldSymbol] = prefer match case _: Module => bms.asMod case _: Class => bms.asCls - case _: NonModule => + case _: Selectable => bms.asModOrObj + case _: (Any.type | NonModule) => val trmSym = bms.defn match case S(defn: TermDefinition) => S(defn.tsym) case _ => N trmSym orElse bms.asPrincipal - case _: Any => bms.defn match - case S(defn: TermDefinition) => S(defn.tsym) - case S(defn: ClassDef) => S(defn.sym) - case S(defn: ModuleOrObjectDef) => S(defn.sym) - case _ => N + // TODO: @Harry check trmSym if needed + // case _: Any => + // val trmSym = bms.defn match + // case S(defn: TermDefinition) => S(defn.tsym) + // case _ => N + // trmSym orElse bms.asPrincipal + // bms.defn match + // case S(defn: TermDefinition) => S(defn.tsym) + // // case S(defn: ClassDef) => S(defn.sym) + // // case S(defn: ModuleOrObjectDef) => S(defn.sym) + // case _ => N t match case t @ Apps(base: Resolvable, ass) => @@ -845,7 +878,7 @@ class Resolver(tl: TraceLogger) log(s"Disambiguate ${bms} into ${disambBms} (defn = ${disambBms.map(_.defn)})") disambBms match case S(disambBms) => disambBms.defn - case N => bms.defn + case N => bms.asPrincipal.flatMap(_.defn) case S(bls: BlockLocalSymbol) => bls.decl case S(fs: FieldSymbol) => fs.defn case _ => N @@ -947,14 +980,18 @@ class Resolver(tl: TraceLogger) raise(ErrorReport(msg"Expected a type, got ${t.describe}" -> t.toLoc :: Nil)) return - val typ = resolveSign(t, expect = expect) + // * Resolve the symbol and type of the term. - t match + val typ = t match case t: Resolvable => - resolveSymbol(t, prefer = expect) + resolveSymbol(t, prefer = expect, sign = true) + val typ = resolveSign(t, expect = expect) t.expandedResolvableIn(_.withTyp(typ)) - case _ => () + typ + case _ => + val typ = resolveSign(t, expect = expect) + typ // * Check if the term satisfies the expectation. // * Check the arity of type params/args. @@ -979,7 +1016,7 @@ class Resolver(tl: TraceLogger) * Given a symbol-resolved term that represents a type, resolve the * type that it represents. */ - def resolveSign(t: Term, expect: Expect): Type = + def resolveSign(t: Term, expect: Expect): Type = def raiseError(sym: Opt[Symbol] = N) = val defnMsg = sym match case S(sym: FieldSymbol) => sym.defn match diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 708d4fa17d..c41fd2416f 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -53,7 +53,6 @@ abstract class Symbol(using State) extends Located: case _ => false - // * Not defining `asTrm` since `TermDef` curretly doesn't have a symbol def hasTrmDef: Bool = this match case trm: TermSymbol => true case mem: BlockMemberSymbol => mem.trmTree.nonEmpty @@ -70,12 +69,15 @@ abstract class Symbol(using State) extends Located: def asMod: Opt[ModuleOrObjectSymbol] = asModOrObj.filter(_.tree.k is Mod) def asObj: Opt[ModuleOrObjectSymbol] = asModOrObj.filter(_.tree.k is Obj) def asClsOrMod: Opt[ClassSymbol | ModuleOrObjectSymbol] = asCls orElse asModOrObj - /* + + // * This is a hack for that `TermDef` currently doesn't have a symbol. + // * So, the symbol is from the `TermDefinition`. def asTrm: Opt[TermSymbol] = this match case trm: TermSymbol => S(trm) - case mem: BlockMemberSymbol => mem.trmTree.flatMap(_.symbol.asTrm) + case mem: BlockMemberSymbol => mem.tdefn match + case S(defn: TermDefinition) => S(defn.tsym) + case N => N case _ => N - */ def asPat: Opt[PatternSymbol] = this match case pat: PatternSymbol => S(pat) case mem: BlockMemberSymbol => mem.patTree.flatMap(_.symbol.asPat) @@ -88,8 +90,9 @@ abstract class Symbol(using State) extends Located: def asClsLike: Opt[ClassSymbol | ModuleOrObjectSymbol | PatternSymbol] = (asCls: Opt[ClassSymbol | ModuleOrObjectSymbol | PatternSymbol]) orElse asModOrObj orElse asPat def asTpe: Opt[TypeSymbol] = asCls - .orElse[TypeSymbol](asModOrObj) + .orElse[TypeSymbol](asObj) .orElse[TypeSymbol](asAls) + .orElse[TypeSymbol](asMod) def asNonModTpe: Opt[TypeSymbol] = asCls .orElse[TypeSymbol](asObj) .orElse[TypeSymbol](asAls) @@ -100,11 +103,13 @@ abstract class Symbol(using State) extends Located: case S(defn: TypeLikeDef) => S(defn.bsym) case S(defn: TermDefinition) => S(defn.sym) case N => N - + /** Get the symbol corresponding to the "representative" of a set of overloaded definitions, * or the sole definition, if it is not overloaded. * We should consider the ordering terms > classes/objects/types > modules, for this purpose. */ - def asPrincipal = + def asPrincipal: Opt[TermSymbol | ClassSymbol | ModuleOrObjectSymbol | TypeAliasSymbol | PatternSymbol] = + val asTrm: Opt[TermSymbol | ClassSymbol | ModuleOrObjectSymbol | TypeAliasSymbol | PatternSymbol] = this.asTrm + asTrm orElse asCls orElse asObj orElse asAls orElse @@ -197,6 +202,12 @@ class BuiltinSymbol class BlockMemberSymbol(val nme: Str, val trees: Ls[TypeOrTermDef], val nameIsMeaningful: Bool = true)(using State) extends MemberSymbol[Definition]: + // * This is a hack for that `TermDef` currently doesn't have a symbol. + // * So, the symbol is from the `TermDefinition`. + // * To prevent the `TermDefinition` from being overridden by other definitions, + // * we use a special field here. + var tdefn: Opt[TermDefinition] = N + def toLoc: Option[Loc] = Loc(trees) def describe: Str = @@ -240,11 +251,14 @@ sealed abstract class MemberSymbol[Defn <: Definition](using State) extends Symb class TermSymbol(val k: TermDefKind, val owner: Opt[InnerSymbol], val id: Tree.Ident)(using State) - extends MemberSymbol[Definition] with LocalSymbol with NamedSymbol: + extends MemberSymbol[TermDefinition] + with DefinitionSymbol[TermDefinition] + with LocalSymbol + with NamedSymbol: def nme: Str = id.name def name: Str = nme def toLoc: Option[Loc] = id.toLoc - override def toString: Str = s"${owner.getOrElse("")}.${id.name}" + override def toString: Str = s"term:${owner.map(o => s"${o}.").getOrElse("")}${id.name}${State.dbgUid(uid)}" def subst(using sub: SymbolSubst): TermSymbol = sub.mapTermSym(this) @@ -354,7 +368,9 @@ class ModuleOrObjectSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using Sta override def subst(using sub: SymbolSubst): ModuleOrObjectSymbol = sub.mapModuleSym(this) -class TypeAliasSymbol(val id: Tree.Ident)(using State) extends MemberSymbol[TypeDef]: +class TypeAliasSymbol(val id: Tree.Ident)(using State) + extends MemberSymbol[TypeDef] + with DefinitionSymbol[TypeDef]: def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of type alias here override def toString: Str = s"type:${id.name}${State.dbgUid(uid)}" diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index 8881099df7..68680244ed 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -121,6 +121,9 @@ sealed trait ResolvableImpl: def resolve: this.type = expand(N) def dontResolve: this.type = this // TODO rm + def resolved(sym: DefinitionSymbol[?]): Term.Resolved = + Term.Resolved(this, sym)(typ = resolvedTyp) + def hasExpansion = expansion.isDefined def defn: Opt[Definition] = resolvedSym match diff --git a/hkmc2/shared/src/test/mlscript/HkScratch.mls b/hkmc2/shared/src/test/mlscript/HkScratch.mls index ef38e8b363..8b04dc96e7 100644 --- a/hkmc2/shared/src/test/mlscript/HkScratch.mls +++ b/hkmc2/shared/src/test/mlscript/HkScratch.mls @@ -1,12 +1,153 @@ :js -// :de -// :sjs -// :pt -// :elt - -:global -// :d -// :todo - +:dl +:lot +Object +//│ Lowering.term member:Object – symbol class:Object +//│ Expanding term Ref(member:Object) +//│ ~> Resolved(Ref(member:Object),class:Object) +//│ Lowering.term globalThis:globalThis.Object‹member:Object› – symbol member:Object +//│ Expanding term Sel(Ref(globalThis:globalThis),Ident(Object)) +//│ ~> Sel(Ref(globalThis:globalThis),Ident(Object)) +//│ Lowering.term globalThis:globalThis – symbol globalThis:globalThis +//│ Expanding term Ref(globalThis:globalThis) +//│ ~> Ref(globalThis:globalThis) +//│ Lowered: +//│ Program: +//│ imports = Nil +//│ main = Assign: +//│ lhs = $selRes +//│ rhs = Select{member:Object}: +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = N +//│ name = Ident of "Object" +//│ rest = Match: \ +//│ scrut = Ref: +//│ l = $selRes +//│ disamb = N +//│ arms = Ls of +//│ Tuple2: +//│ _1 = Lit of UnitLit of false +//│ _2 = Throw of Instantiate: +//│ mut = false +//│ cls = Select: +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = S of globalThis:globalThis +//│ name = Ident of "Error" +//│ args = Ls of +//│ Arg: +//│ spread = N +//│ value = Lit of StrLit of "Access to required field 'Object' yielded 'undefined'" +//│ dflt = N +//│ rest = Assign: \ +//│ lhs = $block$res +//│ rhs = Ref: +//│ l = $selRes +//│ disamb = N +//│ rest = Return: \ +//│ res = Lit of UnitLit of false +//│ implct = true +//│ avoidNames Assign($selRes,Select(Ref(globalThis:globalThis,None),Ident(Object)),Match(Ref($selRes,None),List((L... +//│ | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... +//│ | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... +//│ | | avoidNames Assign($block$res,Ref($selRes,None),Return(Lit(UnitLit(false)),true))... +//│ | | | avoidNames Return(Lit(UnitLit(false)),true)... +//│ = class Object +:dl +:lot +Object.freeze +//│ Lowering.term member:Object.freeze +//│ Expanding term Sel(Ref(member:Object),Ident(freeze)) +//│ ~> Sel(Ref(member:Object),Ident(freeze)) +//│ Lowering.term member:Object – symbol member:Object +//│ Expanding term Ref(member:Object) +//│ ~> Ref(member:Object) +//│ Lowering.term globalThis:globalThis.Object‹member:Object› – symbol member:Object +//│ Expanding term Sel(Ref(globalThis:globalThis),Ident(Object)) +//│ ~> Sel(Ref(globalThis:globalThis),Ident(Object)) +//│ Lowering.term globalThis:globalThis – symbol globalThis:globalThis +//│ Expanding term Ref(globalThis:globalThis) +//│ ~> Ref(globalThis:globalThis) +//│ Lowered: +//│ Program: +//│ imports = Nil +//│ main = Assign: +//│ lhs = $selRes +//│ rhs = Select{member:Object}: +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = N +//│ name = Ident of "Object" +//│ rest = Match: \ +//│ scrut = Ref: +//│ l = $selRes +//│ disamb = N +//│ arms = Ls of +//│ Tuple2: +//│ _1 = Lit of UnitLit of false +//│ _2 = Throw of Instantiate: +//│ mut = false +//│ cls = Select: +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = S of globalThis:globalThis +//│ name = Ident of "Error" +//│ args = Ls of +//│ Arg: +//│ spread = N +//│ value = Lit of StrLit of "Access to required field 'Object' yielded 'undefined'" +//│ dflt = N +//│ rest = Assign: \ +//│ lhs = $selRes +//│ rhs = Select: +//│ qual = Ref: +//│ l = $selRes +//│ disamb = N +//│ name = Ident of "freeze" +//│ rest = Assign: \ +//│ lhs = $discarded +//│ rhs = Select: +//│ qual = Ref: +//│ l = $selRes +//│ disamb = N +//│ name = Ident of "freeze$__checkNotMethod" +//│ rest = Match: \ +//│ scrut = Ref: +//│ l = $selRes +//│ disamb = N +//│ arms = Ls of +//│ Tuple2: +//│ _1 = Lit of UnitLit of false +//│ _2 = Throw of Instantiate: +//│ mut = false +//│ cls = Select: +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = S of globalThis:globalThis +//│ name = Ident of "Error" +//│ args = Ls of +//│ Arg: +//│ spread = N +//│ value = Lit of StrLit of "Access to required field 'freeze' yielded 'undefined'" +//│ dflt = N +//│ rest = Assign: \ +//│ lhs = $block$res +//│ rhs = Ref: +//│ l = $selRes +//│ disamb = N +//│ rest = Return: \ +//│ res = Lit of UnitLit of false +//│ implct = true +//│ avoidNames Assign($selRes,Select(Ref(globalThis:globalThis,None),Ident(Object)),Match(Ref($selRes,None),List((L... +//│ | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... +//│ | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... +//│ | | avoidNames Assign($selRes,Select(Ref($selRes,None),Ident(freeze)),Assign($discarded,Select(Ref($selRes,None),Id... +//│ | | | avoidNames Assign($discarded,Select(Ref($selRes,None),Ident(freeze$__checkNotMethod)),Match(Ref($selRes,None),L... +//│ | | | | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... +//│ | | | | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... +//│ | | | | | avoidNames Assign($block$res,Ref($selRes,None),Return(Lit(UnitLit(false)),true))... +//│ | | | | | | avoidNames Return(Lit(UnitLit(false)),true)... +//│ = fun freeze diff --git a/hkmc2/shared/src/test/mlscript/OverloadedModulesInSignatures.mls b/hkmc2/shared/src/test/mlscript/OverloadedModulesInSignatures.mls index 065d7fa522..69abb2d790 100644 --- a/hkmc2/shared/src/test/mlscript/OverloadedModulesInSignatures.mls +++ b/hkmc2/shared/src/test/mlscript/OverloadedModulesInSignatures.mls @@ -30,7 +30,9 @@ f //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Ref{sym=member:f,typ=class:ClsMod} of member:f +//│ res = Resolved{sym=term:f,typ=class:ClsMod}: +//│ t = Ref{sym=member:f} of member:f +//│ sym = term:f //│ = 42 fun f: module ClsMod = ClsMod @@ -40,7 +42,9 @@ f //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Ref{sym=member:f,typ=module:ClsMod} of member:f +//│ res = Resolved{sym=term:f,typ=module:ClsMod}: +//│ t = Ref{sym=member:f} of member:f +//│ sym = term:f //│ = class ClsMod { whoami: "module" } fun f: TypMod = 42 @@ -50,7 +54,9 @@ f //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Ref{sym=member:f,typ=type:TypMod} of member:f +//│ res = Resolved{sym=term:f,typ=type:TypMod}: +//│ t = Ref{sym=member:f} of member:f +//│ sym = term:f //│ = 42 fun f: module TypMod = TypMod @@ -60,38 +66,33 @@ f //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Ref{sym=member:f,typ=module:TypMod} of member:f +//│ res = Resolved{sym=term:f,typ=module:TypMod}: +//│ t = Ref{sym=member:f} of member:f +//│ sym = term:f //│ = class TypMod { whoami: "module" } :e fun f: TrmMod = 42 -//│ ╔══[ERROR] Expected a non-module type; found reference denoting module 'TrmMod'. -//│ ║ l.67: fun f: TrmMod = 42 +//│ ╔══[ERROR] Expected a non-module type; found reference of type TrmMod denoting module 'TrmMod'. +//│ ║ l.75: fun f: TrmMod = 42 //│ ║ ^^^^^^ //│ ╙── Function must be marked as returning a 'module' in order to have a module return type. -// * FIXME: Should compile to term (function) `TrmMod` rather than module `TrmMod` -// * FIXME: Should module-check as the term module (or probably we will remove module-checks before that) :sjs -:fixme fun f = TrmMod -//│ ╔══[ERROR] Unexpected moduleful reference of type TrmMod. -//│ ║ l.77: fun f = TrmMod -//│ ║ ^^^^^^ -//│ ╙── Function must be marked as returning a 'module' in order to return a module. //│ JS (unsanitized): -//│ let f5; f5 = function f() { return TrmMod1 }; +//│ let f5; f5 = function f() { let tmp4; tmp4 = TrmMod1(); return tmp4 }; :fixme :expect 42 f -//│ ═══[RUNTIME ERROR] Expected: '42', got: 'class TrmMod { whoami: "module" }' -//│ = class TrmMod { whoami: "module" } +//│ ═══[RUNTIME ERROR] TypeError: Class constructor TrmMod cannot be invoked without 'new' +//│ ═══[RUNTIME ERROR] Expected: '42', got: 'undefined' :sjs fun f: module TrmMod = TrmMod //│ JS (unsanitized): -//│ let f6; f6 = function f() { return TrmMod1 }; +//│ let f6; f6 = function f() { return TrmMod1.class }; fun assertModule(module m: ClsMod): module ClsMod = m @@ -101,8 +102,9 @@ assertModule(ClsMod).whoami assertModule(TypMod).whoami //│ = "module" +:fixme assertModule(TrmMod).whoami -//│ = "module" +//│ ═══[RUNTIME ERROR] TypeError: Class constructor TrmMod cannot be invoked without 'new' fun assertNonModule(m) = m @@ -122,11 +124,7 @@ assertNonModule(TypMod).whoami :breakme :fixme assertNonModule(TrmMod).whoami -//│ ╔══[ERROR] Unexpected moduleful reference of type TrmMod. -//│ ║ l.124: assertNonModule(TrmMod).whoami -//│ ║ ^^^^^^ -//│ ╙── Module argument passed to a non-module parameter. -//│ = "module" +//│ ═══[RUNTIME ERROR] TypeError: Class constructor TrmMod cannot be invoked without 'new' type Foo[A] = Int @@ -135,10 +133,10 @@ module Foo :e fun f(x: Foo): Foo = x //│ ╔══[ERROR] Expected 1 type arguments, got none -//│ ║ l.136: fun f(x: Foo): Foo = x +//│ ║ l.134: fun f(x: Foo): Foo = x //│ ╙── ^^^ //│ ╔══[ERROR] Expected 1 type arguments, got none -//│ ║ l.136: fun f(x: Foo): Foo = x +//│ ║ l.134: fun f(x: Foo): Foo = x //│ ╙── ^^^ fun f(x: Foo[Int]): Foo[Int] = x @@ -148,10 +146,10 @@ fun f(module x: Foo): module Foo = x :e fun f(module x: Foo[Int]): module Foo[Int] = x //│ ╔══[ERROR] Expected no type arguments, got 1 -//│ ║ l.149: fun f(module x: Foo[Int]): module Foo[Int] = x +//│ ║ l.147: fun f(module x: Foo[Int]): module Foo[Int] = x //│ ╙── ^^^^^^^^ //│ ╔══[ERROR] Expected no type arguments, got 1 -//│ ║ l.149: fun f(module x: Foo[Int]): module Foo[Int] = x +//│ ║ l.147: fun f(module x: Foo[Int]): module Foo[Int] = x //│ ╙── ^^^^^^^^ diff --git a/hkmc2/shared/src/test/mlscript/backlog/NewWith.mls b/hkmc2/shared/src/test/mlscript/backlog/NewWith.mls index 27b024ac01..963dbf98f9 100644 --- a/hkmc2/shared/src/test/mlscript/backlog/NewWith.mls +++ b/hkmc2/shared/src/test/mlscript/backlog/NewWith.mls @@ -77,7 +77,7 @@ new Foo(123) with { fun foo = 27 } :e :re new (Foo(123)) with { fun foo = 27 } -//│ ╔══[ERROR] Expected a statically known class; found application. +//│ ╔══[ERROR] Expected a statically known class; found application of type Foo. //│ ║ l.79: new (Foo(123)) with { fun foo = 27 } //│ ║ ^^^^^^^^ //│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation. @@ -93,7 +93,7 @@ new! (Foo(123)) with { fun foo = 27 } :e :re new {Foo(123)} with { fun foo = 27 } -//│ ╔══[ERROR] Expected a statically known class; found application. +//│ ╔══[ERROR] Expected a statically known class; found application of type Foo. //│ ║ l.95: new {Foo(123)} with { fun foo = 27 } //│ ║ ^^^^^^^^ //│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation. diff --git a/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls b/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls index fcf2a4134e..fbfc6f3500 100644 --- a/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls +++ b/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls @@ -10,8 +10,10 @@ C() //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = App: -//│ lhs = Ref{sym=member:C,typ=module:C} of member:C +//│ res = App{typ=class:C}: +//│ lhs = Resolved{sym=term:class:C.C}: +//│ t = Ref{sym=member:C} of member:C +//│ sym = term:class:C.C //│ rhs = Tup of Nil //│ = C() @@ -21,9 +23,9 @@ new C //│ Blk: //│ stats = Nil //│ res = New: -//│ cls = SynthSel{sym=class:C,typ=class:C}: -//│ prefix = Ref{sym=member:C} of member:C -//│ nme = Ident of "class" +//│ cls = Resolved{sym=class:C}: +//│ t = Ref{sym=member:C} of member:C +//│ sym = class:C //│ args = Nil //│ rft = N //│ = C() @@ -37,9 +39,9 @@ C.empty //│ Blk: //│ stats = Nil //│ res = Sel{sym=member:empty}: -//│ prefix = SynthSel{sym=module:C,typ=module:C}: -//│ prefix = Ref{sym=member:C,typ=module:C} of member:C -//│ nme = Ident of "class" +//│ prefix = Resolved{sym=module:C,typ=module:C}: +//│ t = Ref{sym=member:C} of member:C +//│ sym = module:C //│ nme = Ident of "empty" //│ = 1 @@ -60,7 +62,9 @@ C.empty //│ Blk: //│ stats = Nil //│ res = Sel{sym=member:empty}: -//│ prefix = Ref{sym=member:C,typ=module:C} of member:C +//│ prefix = Resolved{sym=module:C,typ=module:C}: +//│ t = Ref{sym=member:C} of member:C +//│ sym = module:C //│ nme = Ident of "empty" //│ = 1 diff --git a/hkmc2/shared/src/test/mlscript/basics/DataClass.mls b/hkmc2/shared/src/test/mlscript/basics/DataClass.mls index ac2c22fc22..f442475c8c 100644 --- a/hkmc2/shared/src/test/mlscript/basics/DataClass.mls +++ b/hkmc2/shared/src/test/mlscript/basics/DataClass.mls @@ -11,7 +11,7 @@ Foo(1).x :todo data Foo(x: Int) //│ ╔══[WARNING] This annotation has no effect. -//│ ╟── Such annotations are not supported on application terms. +//│ ╟── Such annotations are not supported on application of type Foo terms. //│ ║ l.12: data Foo(x: Int) //│ ╙── ^^^^^^^^^^^ //│ ╔══[COMPILATION ERROR] Symbol 'Int' is virtual (i.e., "compiler fiction"); cannot be used as a term diff --git a/hkmc2/shared/src/test/mlscript/basics/ModuleMethods.mls b/hkmc2/shared/src/test/mlscript/basics/ModuleMethods.mls index b259aa3ad8..3a248ea2b1 100644 --- a/hkmc2/shared/src/test/mlscript/basics/ModuleMethods.mls +++ b/hkmc2/shared/src/test/mlscript/basics/ModuleMethods.mls @@ -7,7 +7,7 @@ module MM[T] :e fun f(m: M) -//│ ╔══[ERROR] Expected a non-module type; found reference denoting module 'M'. +//│ ╔══[ERROR] Expected a non-module type; found reference of type M denoting module 'M'. //│ ║ l.9: fun f(m: M) //│ ║ ^ //│ ╙── Non-module parameter must have a non-module type. @@ -67,7 +67,7 @@ fun f() = M :e fun f(): M = M -//│ ╔══[ERROR] Expected a non-module type; found reference denoting module 'M'. +//│ ╔══[ERROR] Expected a non-module type; found reference of type M denoting module 'M'. //│ ║ l.69: fun f(): M = M //│ ║ ^ //│ ╙── Function must be marked as returning a 'module' in order to have a module return type. diff --git a/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls b/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls index 0c8a48f3a4..55b3c1951e 100644 --- a/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls +++ b/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls @@ -84,6 +84,102 @@ let r = mut x: 1 //│ r = {x: 1} +:dl +:lot +Object.freeze +//│ Lowering.term member:Object.freeze +//│ Expanding term Sel(Ref(member:Object),Ident(freeze)) +//│ ~> Sel(Ref(member:Object),Ident(freeze)) +//│ Lowering.term member:Object – symbol member:Object +//│ Expanding term Ref(member:Object) +//│ ~> Ref(member:Object) +//│ Lowering.term globalThis:globalThis.Object‹member:Object› – symbol member:Object +//│ Expanding term Sel(Ref(globalThis:globalThis),Ident(Object)) +//│ ~> Sel(Ref(globalThis:globalThis),Ident(Object)) +//│ Lowering.term globalThis:globalThis – symbol globalThis:globalThis +//│ Expanding term Ref(globalThis:globalThis) +//│ ~> Ref(globalThis:globalThis) +//│ Lowered: +//│ Program: +//│ imports = Nil +//│ main = Assign: +//│ lhs = $selRes +//│ rhs = Select{member:Object}: +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = N +//│ name = Ident of "Object" +//│ rest = Match: \ +//│ scrut = Ref: +//│ l = $selRes +//│ disamb = N +//│ arms = Ls of +//│ Tuple2: +//│ _1 = Lit of UnitLit of false +//│ _2 = Throw of Instantiate: +//│ mut = false +//│ cls = Select: +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = S of globalThis:globalThis +//│ name = Ident of "Error" +//│ args = Ls of +//│ Arg: +//│ spread = N +//│ value = Lit of StrLit of "Access to required field 'Object' yielded 'undefined'" +//│ dflt = N +//│ rest = Assign: \ +//│ lhs = $selRes +//│ rhs = Select: +//│ qual = Ref: +//│ l = $selRes +//│ disamb = N +//│ name = Ident of "freeze" +//│ rest = Assign: \ +//│ lhs = $discarded +//│ rhs = Select: +//│ qual = Ref: +//│ l = $selRes +//│ disamb = N +//│ name = Ident of "freeze$__checkNotMethod" +//│ rest = Match: \ +//│ scrut = Ref: +//│ l = $selRes +//│ disamb = N +//│ arms = Ls of +//│ Tuple2: +//│ _1 = Lit of UnitLit of false +//│ _2 = Throw of Instantiate: +//│ mut = false +//│ cls = Select: +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = S of globalThis:globalThis +//│ name = Ident of "Error" +//│ args = Ls of +//│ Arg: +//│ spread = N +//│ value = Lit of StrLit of "Access to required field 'freeze' yielded 'undefined'" +//│ dflt = N +//│ rest = Assign: \ +//│ lhs = $block$res +//│ rhs = Ref: +//│ l = $selRes +//│ disamb = N +//│ rest = Return: \ +//│ res = Lit of UnitLit of false +//│ implct = true +//│ avoidNames Assign($selRes,Select(Ref(globalThis:globalThis,None),Ident(Object)),Match(Ref($selRes,None),List((L... +//│ | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... +//│ | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... +//│ | | avoidNames Assign($selRes,Select(Ref($selRes,None),Ident(freeze)),Assign($discarded,Select(Ref($selRes,None),Id... +//│ | | | avoidNames Assign($discarded,Select(Ref($selRes,None),Ident(freeze$__checkNotMethod)),Match(Ref($selRes,None),L... +//│ | | | | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... +//│ | | | | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... +//│ | | | | | avoidNames Assign($block$res,Ref($selRes,None),Return(Lit(UnitLit(false)),true))... +//│ | | | | | | avoidNames Return(Lit(UnitLit(false)),true)... +//│ = fun freeze + Object.freeze(r) //│ = {x: 1} diff --git a/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls b/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls index ad80485e1d..82ab883e71 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls @@ -50,7 +50,9 @@ print("Hi") //│ lhs = $tmp //│ rhs = Call: //│ fun = Select{member:print}: -//│ qual = Ref of member:Predef +//│ qual = Ref: +//│ l = member:Predef +//│ disamb = S of module:Predef //│ name = Ident of "print" //│ args = Ls of //│ Arg: diff --git a/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls b/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls index 702afdc8d7..69a9cb3621 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls @@ -104,29 +104,41 @@ case //│ modulefulness = Modulefulness of N //│ restParam = N //│ body = Match: -//│ scrut = Ref of caseScrut +//│ scrut = Ref: +//│ l = caseScrut +//│ disamb = N //│ arms = Ls of //│ Tuple2: //│ _1 = Cls: //│ cls = class:Foo //│ path = Select{class:Foo}: -//│ qual = Ref of member:Foo +//│ qual = Ref: +//│ l = member:Foo +//│ disamb = S of term:class:Foo.Foo //│ name = Ident of "class" //│ _2 = Assign: //│ lhs = $param0 -//│ rhs = Select{class:Foo.x}: -//│ qual = Ref of caseScrut +//│ rhs = Select{term:class:Foo.x}: +//│ qual = Ref: +//│ l = caseScrut +//│ disamb = N //│ name = Ident of "x" //│ rest = Assign: \ //│ lhs = a -//│ rhs = Ref of $param0 +//│ rhs = Ref: +//│ l = $param0 +//│ disamb = N //│ rest = Return: \ -//│ res = Ref of a +//│ res = Ref: +//│ l = a +//│ disamb = N //│ implct = false //│ dflt = S of Throw of Instantiate: //│ mut = false //│ cls = Select: -//│ qual = Ref of globalThis:globalThis +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = S of globalThis:globalThis //│ name = Ident of "Error" //│ args = Ls of //│ Arg: @@ -135,7 +147,9 @@ case //│ rest = End of "" //│ rest = Assign: \ //│ lhs = $block$res -//│ rhs = Ref of member:lambda +//│ rhs = Ref: +//│ l = member:lambda +//│ disamb = N //│ rest = Return: \ //│ res = Lit of UnitLit of false //│ implct = true diff --git a/hkmc2/shared/src/test/mlscript/codegen/PlainClasses.mls b/hkmc2/shared/src/test/mlscript/codegen/PlainClasses.mls index 5754645200..f7da3e9a97 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/PlainClasses.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/PlainClasses.mls @@ -46,7 +46,7 @@ Foo :re Foo() //│ JS (unsanitized): -//│ Foo1() +//│ runtime.safeCall(Foo1()) //│ ═══[RUNTIME ERROR] TypeError: Class constructor Foo cannot be invoked without 'new' diff --git a/hkmc2/shared/src/test/mlscript/ctx/MissingDefinitions2.mls b/hkmc2/shared/src/test/mlscript/ctx/MissingDefinitions2.mls index 468e4a22cd..2572b03c45 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/MissingDefinitions2.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/MissingDefinitions2.mls @@ -74,7 +74,7 @@ test(1, 2) //│ ║ l.55: fun (++) test: (Int, Int) -> Int //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^ //│ JS (unsanitized): -//│ let tmp2; tmp2 = test(); runtime.safeCall(tmp2(1, 1)) +//│ let tmp2; tmp2 = test(); tmp2(1, 1) //│ ═══[RUNTIME ERROR] ReferenceError: test is not defined diff --git a/hkmc2/shared/src/test/mlscript/ctx/Summon.mls b/hkmc2/shared/src/test/mlscript/ctx/Summon.mls index 926ef2ce0c..318e6302a2 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/Summon.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/Summon.mls @@ -62,7 +62,6 @@ fun f(using Int) = use[Num] data class Some[T](value: T) - :expect 42 fun f[T](using Some[T]) = use[Some[T]].value using Some[Int] = Some(42) @@ -73,10 +72,10 @@ f :re use{[Some[Int]].value} //│ ╔══[ERROR] Illegal juxtaposition right-hand side (selection). -//│ ║ l.74: use{[Some[Int]].value} +//│ ║ l.73: use{[Some[Int]].value} //│ ╙── ^^^^^^^^^^^ //│ ╔══[ERROR] Cannot query instance of type ‹unspecified› (type parameter T) for call: -//│ ║ l.74: use{[Some[Int]].value} +//│ ║ l.73: use{[Some[Int]].value} //│ ║ ^^^ //│ ╟── Required by contextual parameter declaration: //│ ║ l.92: fun use[T](using instance: T) = instance @@ -88,7 +87,7 @@ use{[Some[Int]].value} :re use([Some[Int]].value) //│ ╔══[ERROR] Cannot query instance of type ‹unspecified› (type parameter T) for call: -//│ ║ l.89: use([Some[Int]].value) +//│ ║ l.88: use([Some[Int]].value) //│ ║ ^^^ //│ ╟── Required by contextual parameter declaration: //│ ║ l.92: fun use[T](using instance: T) = instance @@ -107,10 +106,10 @@ f[Int] :re f //│ ╔══[ERROR] Cannot query instance of type ‹unspecified› (type parameter T) for call: -//│ ║ l.108: f +//│ ║ l.107: f //│ ║ ^ //│ ╟── Required by contextual parameter declaration: -//│ ║ l.101: fun f[T](using T) = use[T] +//│ ║ l.100: fun f[T](using T) = use[T] //│ ║ ^ //│ ╙── Illegal query for an unspecified type variable T. //│ ═══[RUNTIME ERROR] Error: Function 'f' expected 1 argument but got 0 diff --git a/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls b/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls index 4fcca7c686..ec538dcc34 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls @@ -25,7 +25,9 @@ M.foo //│ Blk: //│ stats = Nil //│ res = Sel{sym=member:foo,typ=module:M}: -//│ prefix = Ref{sym=member:M,typ=module:M} of member:M +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M //│ nme = Ident of "foo" M.bar @@ -33,7 +35,9 @@ M.bar //│ Blk: //│ stats = Nil //│ res = Sel{sym=member:bar,typ=module:M}: -//│ prefix = Ref{sym=member:M,typ=module:M} of member:M +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M //│ nme = Ident of "bar" M.baz @@ -41,7 +45,9 @@ M.baz //│ Blk: //│ stats = Nil //│ res = Sel{sym=member:baz}: -//│ prefix = Ref{sym=member:M,typ=module:M} of member:M +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M //│ nme = Ident of "baz" M.baz() @@ -50,7 +56,9 @@ M.baz() //│ stats = Nil //│ res = App{typ=module:M}: //│ lhs = Sel{sym=member:baz}: -//│ prefix = Ref{sym=member:M,typ=module:M} of member:M +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M //│ nme = Ident of "baz" //│ rhs = Tup of Nil @@ -62,7 +70,9 @@ M.foo.bar.baz() //│ lhs = Sel{sym=member:baz}: //│ prefix = Sel{sym=member:bar,typ=module:M}: //│ prefix = Sel{sym=member:foo,typ=module:M}: -//│ prefix = Ref{sym=member:M,typ=module:M} of member:M +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M //│ nme = Ident of "foo" //│ nme = Ident of "bar" //│ nme = Ident of "baz" @@ -74,7 +84,9 @@ M.that.that //│ stats = Nil //│ res = Sel{sym=member:that,typ=module:M}: //│ prefix = Sel{sym=member:that,typ=module:N}: -//│ prefix = Ref{sym=member:M,typ=module:M} of member:M +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M //│ nme = Ident of "that" //│ nme = Ident of "that" @@ -88,7 +100,9 @@ M.that.that.that.that.that.that //│ prefix = Sel{sym=member:that,typ=module:N}: //│ prefix = Sel{sym=member:that,typ=module:M}: //│ prefix = Sel{sym=member:that,typ=module:N}: -//│ prefix = Ref{sym=member:M,typ=module:M} of member:M +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M //│ nme = Ident of "that" //│ nme = Ident of "that" //│ nme = Ident of "that" @@ -101,7 +115,9 @@ R.foo //│ Blk: //│ stats = Nil //│ res = Sel{sym=member:foo}: -//│ prefix = Ref{sym=member:R,typ=module:R} of member:R +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R //│ nme = Ident of "foo" R.foo() @@ -110,7 +126,9 @@ R.foo() //│ stats = Nil //│ res = App: //│ lhs = Sel{sym=member:foo}: -//│ prefix = Ref{sym=member:R,typ=module:R} of member:R +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R //│ nme = Ident of "foo" //│ rhs = Tup of Nil @@ -121,7 +139,9 @@ R.foo()() //│ res = App{typ=module:N}: //│ lhs = App: //│ lhs = Sel{sym=member:foo}: -//│ prefix = Ref{sym=member:R,typ=module:R} of member:R +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R //│ nme = Ident of "foo" //│ rhs = Tup of Nil //│ rhs = Tup of Nil @@ -134,7 +154,9 @@ R.foo()()() //│ lhs = App{typ=module:N}: //│ lhs = App: //│ lhs = Sel{sym=member:foo}: -//│ prefix = Ref{sym=member:R,typ=module:R} of member:R +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R //│ nme = Ident of "foo" //│ rhs = Tup of Nil //│ rhs = Tup of Nil @@ -152,22 +174,30 @@ R.bar //│ lhs = App: //│ lhs = App: //│ lhs = Sel{sym=member:bar}: -//│ prefix = Ref{sym=member:R,typ=module:R} of member:R +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R //│ nme = Ident of "bar" //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Int),typ=class:Int} of member:instance$Ident(Int) +//│ term = Resolved{sym=term:instance$Ident(Int),typ=class:Int}: +//│ t = Ref{sym=member:instance$Ident(Int)} of member:instance$Ident(Int) +//│ sym = term:instance$Ident(Int) //│ asc = N //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Num),typ=class:Num} of member:instance$Ident(Num) +//│ term = Resolved{sym=term:instance$Ident(Num),typ=class:Num}: +//│ t = Ref{sym=member:instance$Ident(Num)} of member:instance$Ident(Num) +//│ sym = term:instance$Ident(Num) //│ asc = N //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Str),typ=class:Str} of member:instance$Ident(Str) +//│ term = Resolved{sym=term:instance$Ident(Str),typ=class:Str}: +//│ t = Ref{sym=member:instance$Ident(Str)} of member:instance$Ident(Str) +//│ sym = term:instance$Ident(Str) //│ asc = N // the symbol of this Ref should be M because of the implicit application @@ -178,21 +208,29 @@ foo //│ res = App{typ=module:M}: //│ lhs = App: //│ lhs = App: -//│ lhs = Ref{sym=member:foo} of member:foo +//│ lhs = Resolved{sym=term:foo}: +//│ t = Ref{sym=member:foo} of member:foo +//│ sym = term:foo //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Int),typ=class:Int} of member:instance$Ident(Int) +//│ term = Resolved{sym=term:instance$Ident(Int),typ=class:Int}: +//│ t = Ref{sym=member:instance$Ident(Int)} of member:instance$Ident(Int) +//│ sym = term:instance$Ident(Int) //│ asc = N //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Num),typ=class:Num} of member:instance$Ident(Num) +//│ term = Resolved{sym=term:instance$Ident(Num),typ=class:Num}: +//│ t = Ref{sym=member:instance$Ident(Num)} of member:instance$Ident(Num) +//│ sym = term:instance$Ident(Num) //│ asc = N //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Str),typ=class:Str} of member:instance$Ident(Str) +//│ term = Resolved{sym=term:instance$Ident(Str),typ=class:Str}: +//│ t = Ref{sym=member:instance$Ident(Str)} of member:instance$Ident(Str) +//│ sym = term:instance$Ident(Str) //│ asc = N // the symbol of this TyApp should be M because of the implicit application @@ -206,24 +244,34 @@ R.bar[Int] //│ lhs = App: //│ lhs = TyApp{sym=member:bar}: //│ lhs = Sel{sym=member:bar}: -//│ prefix = Ref{sym=member:R,typ=module:R} of member:R +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R //│ nme = Ident of "bar" //│ targs = Ls of -//│ Ref{sym=member:Int} of member:Int +//│ Resolved{sym=class:Int}: +//│ t = Ref{sym=member:Int} of member:Int +//│ sym = class:Int //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Int),typ=class:Int} of member:instance$Ident(Int) +//│ term = Resolved{sym=term:instance$Ident(Int),typ=class:Int}: +//│ t = Ref{sym=member:instance$Ident(Int)} of member:instance$Ident(Int) +//│ sym = term:instance$Ident(Int) //│ asc = N //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Num),typ=class:Num} of member:instance$Ident(Num) +//│ term = Resolved{sym=term:instance$Ident(Num),typ=class:Num}: +//│ t = Ref{sym=member:instance$Ident(Num)} of member:instance$Ident(Num) +//│ sym = term:instance$Ident(Num) //│ asc = N //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Str),typ=class:Str} of member:instance$Ident(Str) +//│ term = Resolved{sym=term:instance$Ident(Str),typ=class:Str}: +//│ t = Ref{sym=member:instance$Ident(Str)} of member:instance$Ident(Str) +//│ sym = term:instance$Ident(Str) //│ asc = N // the symbol of this TyApp should be M because of the implicit application @@ -235,22 +283,32 @@ foo[Int] //│ res = App{typ=module:M}: //│ lhs = App: //│ lhs = App: -//│ lhs = TyApp{sym=member:foo}: -//│ lhs = Ref{sym=member:foo} of member:foo +//│ lhs = TyApp{sym=term:foo}: +//│ lhs = Resolved{sym=term:foo}: +//│ t = Ref{sym=member:foo} of member:foo +//│ sym = term:foo //│ targs = Ls of -//│ Ref{sym=member:Int} of member:Int +//│ Resolved{sym=class:Int}: +//│ t = Ref{sym=member:Int} of member:Int +//│ sym = class:Int //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Int),typ=class:Int} of member:instance$Ident(Int) +//│ term = Resolved{sym=term:instance$Ident(Int),typ=class:Int}: +//│ t = Ref{sym=member:instance$Ident(Int)} of member:instance$Ident(Int) +//│ sym = term:instance$Ident(Int) //│ asc = N //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Num),typ=class:Num} of member:instance$Ident(Num) +//│ term = Resolved{sym=term:instance$Ident(Num),typ=class:Num}: +//│ t = Ref{sym=member:instance$Ident(Num)} of member:instance$Ident(Num) +//│ sym = term:instance$Ident(Num) //│ asc = N //│ rhs = Tup of Ls of //│ Fld: //│ flags = () -//│ term = Ref{sym=member:instance$Ident(Str),typ=class:Str} of member:instance$Ident(Str) +//│ term = Resolved{sym=term:instance$Ident(Str),typ=class:Str}: +//│ t = Ref{sym=member:instance$Ident(Str)} of member:instance$Ident(Str) +//│ sym = term:instance$Ident(Str) //│ asc = N diff --git a/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls b/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls index fbba32ad5b..f3d4df51a2 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls @@ -9,7 +9,9 @@ new Foo //│ Blk: //│ stats = Nil //│ res = New: -//│ cls = Ref{sym=member:Foo} of member:Foo +//│ cls = Resolved{sym=class:Foo}: +//│ t = Ref{sym=member:Foo} of member:Foo +//│ sym = class:Foo //│ args = Nil //│ rft = N @@ -20,7 +22,9 @@ new! Foo //│ Blk: //│ stats = Nil //│ res = DynNew: -//│ cls = Ref{sym=member:Foo} of member:Foo +//│ cls = Resolved{sym=class:Foo}: +//│ t = Ref{sym=member:Foo} of member:Foo +//│ sym = class:Foo //│ args = Nil val foo: Foo = new Foo @@ -30,7 +34,9 @@ foo //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Ref{sym=member:foo,typ=class:Foo} of member:foo +//│ res = Resolved{sym=term:foo,typ=class:Foo}: +//│ t = Ref{sym=member:foo} of member:foo +//│ sym = term:foo :rt foo.foo @@ -51,7 +57,9 @@ new Foo2 //│ Blk: //│ stats = Nil //│ res = New: -//│ cls = Ref{sym=member:Foo2} of member:Foo2 +//│ cls = Resolved{sym=class:Foo2}: +//│ t = Ref{sym=member:Foo2} of member:Foo2 +//│ sym = class:Foo2 //│ args = Nil //│ rft = N @@ -62,7 +70,9 @@ new! Foo2 //│ Blk: //│ stats = Nil //│ res = DynNew: -//│ cls = Ref{sym=member:Foo2} of member:Foo2 +//│ cls = Resolved{sym=class:Foo2}: +//│ t = Ref{sym=member:Foo2} of member:Foo2 +//│ sym = class:Foo2 //│ args = Nil val foo: Foo2[Str, Int] = new Foo2 @@ -72,7 +82,9 @@ foo //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Ref{sym=member:foo,typ=class:Foo2[class:Str, class:Int]} of member:foo +//│ res = Resolved{sym=term:foo,typ=class:Foo2[class:Str, class:Int]}: +//│ t = Ref{sym=member:foo} of member:foo +//│ sym = term:foo :rt foo.foo @@ -91,7 +103,7 @@ fun f(x: Foo) = x //│ TermDefinition: //│ k = Fun //│ sym = member:f -//│ tsym = .f +//│ tsym = term:f //│ params = Ls of //│ ParamList: //│ flags = () @@ -99,7 +111,9 @@ fun f(x: Foo) = x //│ Param: //│ flags = () //│ sym = x -//│ sign = S of Ref{sym=member:Foo} of member:Foo +//│ sign = S of Resolved{sym=class:Foo}: +//│ t = Ref{sym=member:Foo} of member:Foo +//│ sym = class:Foo //│ modulefulness = Modulefulness of N //│ restParam = N //│ tparams = N @@ -120,14 +134,18 @@ M //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Ref{sym=member:M,typ=module:M} of member:M +//│ res = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M :rt O //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Ref{sym=member:O,typ=object:O} of member:O +//│ res = Resolved{sym=object:O,typ=object:O}: +//│ t = Ref{sym=member:O} of member:O +//│ sym = object:O val m: module M = M val o: O = O @@ -137,14 +155,18 @@ m //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Ref{sym=member:m,typ=module:M} of member:m +//│ res = Resolved{sym=term:m,typ=module:M}: +//│ t = Ref{sym=member:m} of member:m +//│ sym = term:m :rt o //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Ref{sym=member:o,typ=object:O} of member:o +//│ res = Resolved{sym=term:o,typ=object:O}: +//│ t = Ref{sym=member:o} of member:o +//│ sym = term:o :rt fun f(module m: M): module M = m @@ -154,7 +176,7 @@ fun f(module m: M): module M = m //│ TermDefinition: //│ k = Fun //│ sym = member:f -//│ tsym = .f +//│ tsym = term:f //│ params = Ls of //│ ParamList: //│ flags = () @@ -162,11 +184,15 @@ fun f(module m: M): module M = m //│ Param: //│ flags = () //│ sym = m -//│ sign = S of Ref{sym=member:M} of member:M +//│ sign = S of Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M //│ modulefulness = Modulefulness of S of module:M //│ restParam = N //│ tparams = N -//│ sign = S of Ref{sym=member:M} of member:M +//│ sign = S of Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M //│ body = S of Ref{sym=m,typ=module:M} of m //│ resSym = ‹result of member:f› //│ flags = () @@ -183,7 +209,7 @@ fun f(o: O) = o //│ TermDefinition: //│ k = Fun //│ sym = member:f -//│ tsym = .f +//│ tsym = term:f //│ params = Ls of //│ ParamList: //│ flags = () @@ -191,7 +217,9 @@ fun f(o: O) = o //│ Param: //│ flags = () //│ sym = o -//│ sign = S of Ref{sym=member:O} of member:O +//│ sign = S of Resolved{sym=object:O,typ=object:O}: +//│ t = Ref{sym=member:O} of member:O +//│ sym = object:O //│ modulefulness = Modulefulness of N //│ restParam = N //│ tparams = N diff --git a/hkmc2/shared/src/test/mlscript/decls/Prelude.mls b/hkmc2/shared/src/test/mlscript/decls/Prelude.mls index 8f08751ff0..c4952dca12 100644 --- a/hkmc2/shared/src/test/mlscript/decls/Prelude.mls +++ b/hkmc2/shared/src/test/mlscript/decls/Prelude.mls @@ -17,9 +17,9 @@ declare class Set declare class Map declare class WeakSet declare class WeakMap -declare class Error -declare class TypeError -declare class RangeError +declare class Error(info) +declare class TypeError(info) +declare class RangeError(info) declare class Date declare class ArrayBuffer diff --git a/hkmc2/shared/src/test/mlscript/handlers/GeneratorStack.mls b/hkmc2/shared/src/test/mlscript/handlers/GeneratorStack.mls index 915a0e177f..8dcd0dcff8 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/GeneratorStack.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/GeneratorStack.mls @@ -4,6 +4,33 @@ import "../../mlscript-compile/Stack.mls" open Stack +:rt +val x: Stack[Int] +//│ Resolved tree: +//│ Blk: +//│ stats = Ls of +//│ TermDefinition: +//│ k = ImmutVal +//│ sym = member:x +//│ tsym = term:x +//│ params = Nil +//│ tparams = N +//│ sign = S of TyApp{sym=type:Stack}: +//│ lhs = Resolved{sym=type:Stack}: +//│ t = Ref{sym=member:Stack} of member:Stack +//│ sym = type:Stack +//│ targs = Ls of +//│ Resolved{sym=class:Int}: +//│ t = Ref{sym=member:Int} of member:Int +//│ sym = class:Int +//│ body = N +//│ resSym = ‹result of member:x› +//│ flags = () +//│ modulefulness = Modulefulness of N +//│ annotations = Nil +//│ companion = N +//│ res = Lit of UnitLit of false + class Generator with fun produce(result: Stack[Int]): () diff --git a/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls b/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls index 4a38ce4a73..f3b488285d 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls @@ -1,17 +1,147 @@ -:lift :js :w +:lot fun foo(x) = class C(y) with fun get = [x, y] module C with val empty = C(123) C.empty -//│ ═══[WARNING] Modules are not yet lifted. +//│ Lowered: +//│ Program: +//│ imports = Nil +//│ main = Define: +//│ defn = FunDefn: +//│ owner = N +//│ sym = member:foo +//│ params = Ls of +//│ ParamList: +//│ flags = () +//│ params = Ls of +//│ Param: +//│ flags = () +//│ sym = x +//│ sign = N +//│ modulefulness = Modulefulness of N +//│ restParam = N +//│ body = Define: +//│ defn = ClsLikeDefn: +//│ owner = N +//│ isym = class:C +//│ sym = member:C +//│ k = Cls +//│ paramsOpt = S of ParamList: +//│ flags = () +//│ params = Ls of +//│ Param: +//│ flags = () +//│ sym = y +//│ sign = N +//│ modulefulness = Modulefulness of N +//│ restParam = N +//│ auxParams = Nil +//│ parentPath = N +//│ methods = Ls of +//│ FunDefn: +//│ owner = S of class:C +//│ sym = member:get +//│ params = Nil +//│ body = Return: +//│ res = Arr: +//│ mut = false +//│ elems = Ls of +//│ Arg: +//│ spread = N +//│ value = Ref: +//│ l = x +//│ disamb = N +//│ Arg: +//│ spread = N +//│ value = Ref: +//│ l = term:class:C.y +//│ disamb = N +//│ implct = false +//│ privateFields = Ls of +//│ term:class:C.y +//│ publicFields = Nil +//│ preCtor = End of "" +//│ ctor = Assign: +//│ lhs = term:class:C.y +//│ rhs = Ref: +//│ l = y +//│ disamb = N +//│ rest = End of "" +//│ companion = S of ClsLikeBody: +//│ isym = module:C +//│ methods = Nil +//│ privateFields = Nil +//│ publicFields = Ls of +//│ Tuple2: +//│ _1 = member:empty +//│ _2 = term:module:C.empty +//│ ctor = Begin: +//│ sub = End of "" +//│ rest = Assign: \ +//│ lhs = $tmp +//│ rhs = Call: +//│ fun = Ref: +//│ l = member:C +//│ disamb = S of term:class:C.C +//│ args = Ls of +//│ Arg: +//│ spread = N +//│ value = Lit of IntLit of 123 +//│ rest = Define: \ +//│ defn = ValDefn: +//│ tsym = term:module:C.empty +//│ sym = member:empty +//│ rhs = Ref: +//│ l = $tmp +//│ disamb = N +//│ rest = End of "" +//│ rest = Assign: \ +//│ lhs = $selRes +//│ rhs = Select{member:empty}: +//│ qual = Ref: +//│ l = member:C +//│ disamb = S of module:C +//│ name = Ident of "empty" +//│ rest = Match: \ +//│ scrut = Ref: +//│ l = $selRes +//│ disamb = N +//│ arms = Ls of +//│ Tuple2: +//│ _1 = Lit of UnitLit of false +//│ _2 = Throw of Instantiate: +//│ mut = false +//│ cls = Select: +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = S of globalThis:globalThis +//│ name = Ident of "Error" +//│ args = Ls of +//│ Arg: +//│ spread = N +//│ value = Lit of StrLit of "Access to required field 'empty' yielded 'undefined'" +//│ dflt = N +//│ rest = Return: \ +//│ res = Ref: +//│ l = $selRes +//│ disamb = N +//│ implct = false +//│ rest = Assign: \ +//│ lhs = $block$res +//│ rhs = Lit of UnitLit of false +//│ rest = End of "" +//│ FAILURE: Unexpected lack of warnings +:sjs foo(10).get +//│ JS (unsanitized): +//│ let tmp; tmp = foo(10); tmp.get //│ = [10, 123] :w @@ -21,7 +151,7 @@ fun foo(x) = module C with val empty = new C C.empty -//│ ═══[WARNING] Modules are not yet lifted. +//│ FAILURE: Unexpected lack of warnings foo(10).get //│ = 10 diff --git a/hkmc2/shared/src/test/mlscript/llir/Split.mls b/hkmc2/shared/src/test/mlscript/llir/Split.mls index 2e2d5cf54b..c39dbafff0 100644 --- a/hkmc2/shared/src/test/mlscript/llir/Split.mls +++ b/hkmc2/shared/src/test/mlscript/llir/Split.mls @@ -22,7 +22,7 @@ fun fold(acc, it) = if done(it) then acc else fold(n + acc, it) fun map_sum(f, n) = let it = map(f, dec(n)) in fold(0, it) map_sum(x => x, 200) -//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref($scrut)), Arg(None,Lit(IntLit(0))))) +//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime,None),Ident(Tuple)),Ident(get)),List(Arg(None,Ref($scrut,None)), Arg(None,Lit(IntLit(0))))) //│ Stopped due to an error during the Llir generation :intl @@ -50,5 +50,5 @@ fun fold(acc, iter) = if iter is if it is Done then acc else fold(f(n) + acc, Map(f, it)) fun map_sum(f, n) = let it = map(f, dec(n)) in fold(0, it) map_sum(x => x, 200) -//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref($scrut)), Arg(None,Lit(IntLit(0))))) +//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime,None),Ident(Tuple)),Ident(get)),List(Arg(None,Ref($scrut,None)), Arg(None,Lit(IntLit(0))))) //│ Stopped due to an error during the Llir generation diff --git a/hkmc2/shared/src/test/mlscript/llir/Tuple.mls b/hkmc2/shared/src/test/mlscript/llir/Tuple.mls index 6e80c9547e..9c5838e9bc 100644 --- a/hkmc2/shared/src/test/mlscript/llir/Tuple.mls +++ b/hkmc2/shared/src/test/mlscript/llir/Tuple.mls @@ -10,5 +10,5 @@ fun mkTup(x, y) = [x, y] fun fst(t) = if t is [x, y] then x mkTup(1, 2) //│ = [1, 2] -//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(t)), Arg(None,Lit(IntLit(0))))) +//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime,None),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(t,None)), Arg(None,Lit(IntLit(0))))) //│ Stopped due to an error during the Llir generation diff --git a/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls b/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls index b1c0deab22..422b1b5b83 100644 --- a/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls +++ b/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls @@ -3,7 +3,7 @@ :import NofibPrelude.mls //│ Imported 104 member(s) -//│ Error: hkmc2.ErrorReport: Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(t1)), Arg(None,Lit(IntLit(0))))) +//│ Error: hkmc2.ErrorReport: Unsupported kind of Call Call(Select(Select(Ref($runtime,None),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(t1,None)), Arg(None,Lit(IntLit(0))))) //│ Stopped due to an error during the Llir generation @@ -13,7 +13,7 @@ fun dfs(r, vsns, xs) = if vsns is [vs, ns] and x :: xs and inList(x, vs) then dfs(r, [vs, ns], xs) dfs(r, [x :: vs, Nil], r(x)) is [vs', ns'] then dfs(r, [vs', (x :: ns') +: ns], xs) -//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(vsns)), Arg(None,Lit(IntLit(0))))) +//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime,None),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(vsns,None)), Arg(None,Lit(IntLit(0))))) //│ Stopped due to an error during the Llir generation fun stronglyConnComp(es, vs) = diff --git a/hkmc2/shared/src/test/mlscript/nofib/scc.mls b/hkmc2/shared/src/test/mlscript/nofib/scc.mls index ce3fc5f146..c54e2c4c33 100644 --- a/hkmc2/shared/src/test/mlscript/nofib/scc.mls +++ b/hkmc2/shared/src/test/mlscript/nofib/scc.mls @@ -12,7 +12,7 @@ fun dfs(r, vsns, xs) = if vsns is [vs, ns] and x :: xs and inList(x, vs) then dfs(r, [vs, ns], xs) dfs(r, [x :: vs, Nil], r(x)) is [vs', ns'] then dfs(r, [vs', (x :: ns') +: ns], xs) -//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(vsns)), Arg(None,Lit(IntLit(0))))) +//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime,None),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(vsns,None)), Arg(None,Lit(IntLit(0))))) //│ Stopped due to an error during the Llir generation fun stronglyConnComp(es, vs) = diff --git a/hkmc2/shared/src/test/mlscript/parser/Handler.mls b/hkmc2/shared/src/test/mlscript/parser/Handler.mls index fcca72c7ae..03269443b5 100644 --- a/hkmc2/shared/src/test/mlscript/parser/Handler.mls +++ b/hkmc2/shared/src/test/mlscript/parser/Handler.mls @@ -50,7 +50,7 @@ handle h = Eff with fun f()(r) = r(0) in foo(h) -//│ Elab: { handle h = Ref(member:Eff)() List(HandlerTermDefinition(r,TermDefinition(Fun,member:f,class:Handler$h$.f,List(ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(0)),None))))),‹result of member:f›,‹method ›,Modulefulness(None),List(),None))) in App(Ref(member:foo),Tup(List(Fld(‹›,Ref(h),None)))) } +//│ Elab: { handle h = Ref(member:Eff)() List(HandlerTermDefinition(r,TermDefinition(Fun,member:f,term:class:Handler$h$.f,List(ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(0)),None))))),‹result of member:f›,‹method ›,Modulefulness(None),List(),None))) in App(Ref(member:foo),Tup(List(Fld(‹›,Ref(h),None)))) } :e ( @@ -74,7 +74,7 @@ handle h = Mod.Eff(3) with fun f()(r) = r(0) fun g(a)()()(r) = r(1) foo(h) -//│ Elab: { handle h = Sel(Ref(member:Mod),Ident(Eff))(Lit(IntLit(3))) List(HandlerTermDefinition(r,TermDefinition(Fun,member:f,class:Handler$h$.f,List(ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(0)),None))))),‹result of member:f›,‹method ›,Modulefulness(None),List(),None)), HandlerTermDefinition(r,TermDefinition(Fun,member:g,class:Handler$h$.g,List(ParamList(‹›,List(Param(‹›,a,None,Modulefulness(None))),None), ParamList(‹›,List(),None), ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(1)),None))))),‹result of member:g›,‹method ›,Modulefulness(None),List(),None))) in App(Ref(member:foo),Tup(List(Fld(‹›,Ref(h),None)))) } +//│ Elab: { handle h = Sel(Ref(member:Mod),Ident(Eff))(Lit(IntLit(3))) List(HandlerTermDefinition(r,TermDefinition(Fun,member:f,term:class:Handler$h$.f,List(ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(0)),None))))),‹result of member:f›,‹method ›,Modulefulness(None),List(),None)), HandlerTermDefinition(r,TermDefinition(Fun,member:g,term:class:Handler$h$.g,List(ParamList(‹›,List(Param(‹›,a,None,Modulefulness(None))),None), ParamList(‹›,List(),None), ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(1)),None))))),‹result of member:g›,‹method ›,Modulefulness(None),List(),None))) in App(Ref(member:foo),Tup(List(Fld(‹›,Ref(h),None)))) } :e handle h = Eff with @@ -128,4 +128,4 @@ foo(h) //│ ╔══[WARNING] Terms in handler block do nothing //│ ║ l.126: 12345 //│ ╙── ^^^^^ -//│ Elab: { handle h = Ref(member:Eff)() List(HandlerTermDefinition(r,TermDefinition(Fun,member:f,class:Handler$h$.f,List(ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(0)),None))))),‹result of member:f›,‹method ›,Modulefulness(None),List(),None)), HandlerTermDefinition(r,TermDefinition(Fun,member:g,class:Handler$h$.g,List(ParamList(‹›,List(Param(‹›,a,None,Modulefulness(None))),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(1)),None))))),‹result of member:g›,‹method ›,Modulefulness(None),List(),None))) in App(Ref(member:foo),Tup(List(Fld(‹›,Ref(h),None)))) } +//│ Elab: { handle h = Ref(member:Eff)() List(HandlerTermDefinition(r,TermDefinition(Fun,member:f,term:class:Handler$h$.f,List(ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(0)),None))))),‹result of member:f›,‹method ›,Modulefulness(None),List(),None)), HandlerTermDefinition(r,TermDefinition(Fun,member:g,term:class:Handler$h$.g,List(ParamList(‹›,List(Param(‹›,a,None,Modulefulness(None))),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(1)),None))))),‹result of member:g›,‹method ›,Modulefulness(None),List(),None))) in App(Ref(member:foo),Tup(List(Fld(‹›,Ref(h),None)))) } diff --git a/hkmc2/shared/src/test/mlscript/ucs/future/SymbolicClass.mls b/hkmc2/shared/src/test/mlscript/ucs/future/SymbolicClass.mls index 13eabfbf6d..3883902479 100644 --- a/hkmc2/shared/src/test/mlscript/ucs/future/SymbolicClass.mls +++ b/hkmc2/shared/src/test/mlscript/ucs/future/SymbolicClass.mls @@ -42,7 +42,7 @@ new 1 :: 2 :re :sjs new (1 :: 2) -//│ ╔══[ERROR] Expected a statically known class; found application. +//│ ╔══[ERROR] Expected a statically known class; found application of type Cons. //│ ║ l.44: new (1 :: 2) //│ ║ ^^^^^^ //│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation. diff --git a/hkmc2DiffTests/src/test/scala/hkmc2/JSBackendDiffMaker.scala b/hkmc2DiffTests/src/test/scala/hkmc2/JSBackendDiffMaker.scala index 1adcd726b3..ad2e68dbbf 100644 --- a/hkmc2DiffTests/src/test/scala/hkmc2/JSBackendDiffMaker.scala +++ b/hkmc2DiffTests/src/test/scala/hkmc2/JSBackendDiffMaker.scala @@ -188,7 +188,7 @@ abstract class JSBackendDiffMaker extends MLsDiffMaker: Return( Call( Value.Ref(Elaborator.State.runtimeSymbol).selSN("printRaw"), - Arg(N, Value.Ref(sym)) :: Nil)(true, false), + Arg(N, Value.Ref(sym, N)) :: Nil)(true, false), implct = true) val je = nestedScp.givenIn: jsb.block(le, endSemi = false) From cf8c1c7480bbe5df8990de3d1f8a40da3100f6a1 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sun, 28 Sep 2025 00:49:51 +0800 Subject: [PATCH 03/55] Defer `.class` expansion until lower --- .../scala/hkmc2/codegen/js/JSBuilder.scala | 5 +- .../main/scala/hkmc2/semantics/Resolver.scala | 37 +- .../src/test/mlscript/codegen/ImportMLs.mls | 2 +- .../test/mlscript/codegen/NestedClasses.mls | 28 +- .../src/test/mlscript/handlers/Effects.mls | 14 +- .../ups/examples/DoubleTripleList.mls | 422 +++++++++--------- 6 files changed, 268 insertions(+), 240 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala index 4ffa0c211c..6fd2f9f3b1 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala @@ -112,7 +112,10 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: if l.nullary then l.nme else errExpr(msg"Illegal reference to builtin symbol '${l.nme}'") case Value.Ref(l, disamb) => l match - case l: BlockMemberSymbol if l.hasLiftedClass && disamb.flatMap(d => d.asMod orElse d.asCls).isDefined => + case l: BlockMemberSymbol if { + l.hasLiftedClass && + disamb.flatMap(d => d.asMod orElse d.asCls).exists(_ isnt ctx.builtins.Array) + } => doc"${getVar(l, l.toLoc)}.class" case _ => getVar(l, r.toLoc) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index ef3731ac85..048467a21e 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -276,20 +276,6 @@ class Resolver(tl: TraceLogger) ictx traverseStmts(rest)(using newICtx) - - - def expand2DotClass(t: Resolvable, expect: Expect.Module | Expect.Class) = - log(s"Expanding ${t} to ${t}.class because it is expected to be a ${expect}.") - t.resolvedSym match - case S(bsym: BlockMemberSymbol) if bsym.hasLiftedClass => - val sym = expect match - case _: Expect.Module => bsym.asMod - case _: Expect.Class => bsym.asCls - sym.foreach: sym => - if sym isnt ctx.builtins.Array then - t.expand(S(Term.SynthSel(t.duplicate, new Tree.Ident("class"))(S(sym), S(Type.Ref(sym, Nil))))) - case _ => - () /** * Traverse a term: traverse the sub-terms, resolve the term, and @@ -332,11 +318,6 @@ class Resolver(tl: TraceLogger) case t: Resolvable => resolve(t, prefer = expect, inAppPrefix = false, inTyPrefix = false, inCtxPrefix = false) - t.expanded match - case t: Resolvable => expect match - case expect: Expect.Class => expand2DotClass(t, expect = expect) - case _ => - case _ => case _ => t.subTerms.foreach(traverse(_, expect = NonModule(N))) @@ -825,7 +806,6 @@ class Resolver(tl: TraceLogger) lastWords(s"${mdef}: field symbol found ${fldSym} but no block member symbol") log(s"Resolving symbol for ${t}, defn = ${lhs.defn}") t.expand(S(t.withSym(bsym))) - expand2DotClass(lhs, expect = Expect.Module(N)) log(s"Resolved symbol for ${t}: ${bsym}") case N => t.expand(S(t.withSym(ErrorSymbol(id.name, Tree.Dummy)))) @@ -853,22 +833,7 @@ class Resolver(tl: TraceLogger) case _: Module => bms.asMod case _: Class => bms.asCls case _: Selectable => bms.asModOrObj - case _: (Any.type | NonModule) => - val trmSym = bms.defn match - case S(defn: TermDefinition) => S(defn.tsym) - case _ => N - trmSym orElse bms.asPrincipal - // TODO: @Harry check trmSym if needed - // case _: Any => - // val trmSym = bms.defn match - // case S(defn: TermDefinition) => S(defn.tsym) - // case _ => N - // trmSym orElse bms.asPrincipal - // bms.defn match - // case S(defn: TermDefinition) => S(defn.tsym) - // // case S(defn: ClassDef) => S(defn.sym) - // // case S(defn: ModuleOrObjectDef) => S(defn.sym) - // case _ => N + case _: (Any.type | NonModule) => bms.asPrincipal t match case t @ Apps(base: Resolvable, ass) => diff --git a/hkmc2/shared/src/test/mlscript/codegen/ImportMLs.mls b/hkmc2/shared/src/test/mlscript/codegen/ImportMLs.mls index 07b13f5dfb..e4bbe9ea1e 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/ImportMLs.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/ImportMLs.mls @@ -39,7 +39,7 @@ Some(1) :sjs (new Some(1)) isDefined() //│ JS (unsanitized): -//│ let tmp3; tmp3 = globalThis.Object.freeze(new Option.Some.class(1)); Option.isDefined(tmp3) +//│ let tmp3; tmp3 = globalThis.Object.freeze(new Option.Some(1)); Option.isDefined(tmp3) //│ = true new Some(1) isDefined() diff --git a/hkmc2/shared/src/test/mlscript/codegen/NestedClasses.mls b/hkmc2/shared/src/test/mlscript/codegen/NestedClasses.mls index 5eb21ee8f4..015b97a5b1 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/NestedClasses.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/NestedClasses.mls @@ -32,13 +32,39 @@ object D extends Foo.C(123) with print(id(this).x) //│ > 123 //│ > 123 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot define property class, object is not extensible +//│ at Function.defineProperty () +//│ at new D (REPL32:1:737) +//│ at (REPL32:1:275) +//│ at REPL32:1:851 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) :e object D extends Foo.C(123) with print(this.x) //│ ╔══[ERROR] Object 'D' does not contain member 'x' -//│ ║ l.38: print(this.x) +//│ ║ l.51: print(this.x) //│ ╙── ^^^^^^ //│ > 123 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot define property class, object is not extensible +//│ at Function.defineProperty () +//│ at new D2 (REPL35:1:570) +//│ at (REPL35:1:276) +//│ at REPL35:1:685 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) diff --git a/hkmc2/shared/src/test/mlscript/handlers/Effects.mls b/hkmc2/shared/src/test/mlscript/handlers/Effects.mls index f023883baf..8d7fc35dd5 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/Effects.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/Effects.mls @@ -241,7 +241,19 @@ module A with handle h = A.Effect(3) with fun perform()(k) = 0 h.perform() -//│ = 0 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: h.perform is not a function +//│ at handleBlock$ (REPL56:1:2244) +//│ at REPL56:1:2457 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) fun f(perform) = handle h = Effect with diff --git a/hkmc2/shared/src/test/mlscript/ups/examples/DoubleTripleList.mls b/hkmc2/shared/src/test/mlscript/ups/examples/DoubleTripleList.mls index e8610ea98a..16c87cd321 100644 --- a/hkmc2/shared/src/test/mlscript/ups/examples/DoubleTripleList.mls +++ b/hkmc2/shared/src/test/mlscript/ups/examples/DoubleTripleList.mls @@ -99,14 +99,38 @@ fun withLog(f) = result let testList = 1 :: 2 :: Nil -//│ testList = Cons(1, Cons(2, Nil)) +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at REPL86:1:57 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ testList = undefined withLog of () => testList.head testList.tail () -//│ > access the `head` of [1, 2] -//│ > access the `tail` of [1, 2] +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'head') +//│ at lambda (REPL90:1:179) +//│ at withLog (REPL83:1:192) +//│ at REPL90:1:671 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) fun list(...elements) = elements Iter.rightFolded of Nil, (::) @@ -114,58 +138,64 @@ fun isDoubleTripleList__compiled(xs) = withLog of () => xs is @compile DoubleTripleList isDoubleTripleList__compiled of list(1, 2, 3) -//│ > access the `head` of [1, 2, 3] -//│ > access the `tail` of [1, 2, 3] -//│ > access the `head` of [2, 3] -//│ > access the `tail` of [2, 3] -//│ > access the `head` of [3] -//│ > access the `tail` of [3] -//│ = true +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL99:1:41 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) isDoubleTripleList__compiled of list(1, 2, 3, 4) -//│ > access the `head` of [1, 2, 3, 4] -//│ > access the `tail` of [1, 2, 3, 4] -//│ > access the `head` of [2, 3, 4] -//│ > access the `tail` of [2, 3, 4] -//│ > access the `head` of [3, 4] -//│ > access the `tail` of [3, 4] -//│ > access the `head` of [4] -//│ > access the `tail` of [4] -//│ = true +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL102:1:41 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) isDoubleTripleList__compiled of list(1, 2, 3, 4, 5) -//│ > access the `head` of [1, 2, 3, 4, 5] -//│ > access the `tail` of [1, 2, 3, 4, 5] -//│ > access the `head` of [2, 3, 4, 5] -//│ > access the `tail` of [2, 3, 4, 5] -//│ > access the `head` of [3, 4, 5] -//│ > access the `tail` of [3, 4, 5] -//│ > access the `head` of [4, 5] -//│ > access the `tail` of [4, 5] -//│ > access the `head` of [5] -//│ > access the `tail` of [5] -//│ = false +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL105:1:43 isDoubleTripleList__compiled of list(1, 2, 3, 4, 5, 6, 7, 8, 9) -//│ > access the `head` of [1, 2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [1, 2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `head` of [2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `head` of [3, 4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [3, 4, 5, 6, 7, 8, 9] -//│ > access the `head` of [4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [4, 5, 6, 7, 8, 9] -//│ > access the `head` of [5, 6, 7, 8, 9] -//│ > access the `tail` of [5, 6, 7, 8, 9] -//│ > access the `head` of [6, 7, 8, 9] -//│ > access the `tail` of [6, 7, 8, 9] -//│ > access the `head` of [7, 8, 9] -//│ > access the `tail` of [7, 8, 9] -//│ > access the `head` of [8, 9] -//│ > access the `tail` of [8, 9] -//│ > access the `head` of [9] -//│ > access the `tail` of [9] -//│ = true +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) isDoubleTripleList__compiled of Nil //│ = true @@ -178,70 +208,50 @@ fun isDoubleTripleList__naive(xs) = // It does not backtracking because the `DoubleList` is tested first. isDoubleTripleList__naive of list(1, 2, 3, 4) -//│ > access the `head` of [1, 2, 3, 4] -//│ > access the `tail` of [1, 2, 3, 4] -//│ > access the `head` of [2, 3, 4] -//│ > access the `tail` of [2, 3, 4] -//│ > access the `head` of [3, 4] -//│ > access the `tail` of [3, 4] -//│ > access the `head` of [4] -//│ > access the `tail` of [4] -//│ = true +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL117:1:43 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) // It does backtracking when `DoubleList` does not match. isDoubleTripleList__naive of list(1, 2, 3) -//│ > access the `head` of [1, 2, 3] -//│ > access the `tail` of [1, 2, 3] -//│ > access the `head` of [2, 3] -//│ > access the `tail` of [2, 3] -//│ > access the `head` of [3] -//│ > access the `tail` of [3] -//│ > access the `head` of [1, 2, 3] -//│ > access the `tail` of [1, 2, 3] -//│ > access the `head` of [2, 3] -//│ > access the `tail` of [2, 3] -//│ > access the `head` of [3] -//│ > access the `tail` of [3] -//│ = true +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL120:1:43 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) isDoubleTripleList__naive of list(1, 2, 3, 4, 5, 6, 7, 8, 9) -//│ > access the `head` of [1, 2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [1, 2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `head` of [2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `head` of [3, 4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [3, 4, 5, 6, 7, 8, 9] -//│ > access the `head` of [4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [4, 5, 6, 7, 8, 9] -//│ > access the `head` of [5, 6, 7, 8, 9] -//│ > access the `tail` of [5, 6, 7, 8, 9] -//│ > access the `head` of [6, 7, 8, 9] -//│ > access the `tail` of [6, 7, 8, 9] -//│ > access the `head` of [7, 8, 9] -//│ > access the `tail` of [7, 8, 9] -//│ > access the `head` of [8, 9] -//│ > access the `tail` of [8, 9] -//│ > access the `head` of [9] -//│ > access the `tail` of [9] -//│ > access the `head` of [1, 2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [1, 2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `head` of [2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [2, 3, 4, 5, 6, 7, 8, 9] -//│ > access the `head` of [3, 4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [3, 4, 5, 6, 7, 8, 9] -//│ > access the `head` of [4, 5, 6, 7, 8, 9] -//│ > access the `tail` of [4, 5, 6, 7, 8, 9] -//│ > access the `head` of [5, 6, 7, 8, 9] -//│ > access the `tail` of [5, 6, 7, 8, 9] -//│ > access the `head` of [6, 7, 8, 9] -//│ > access the `tail` of [6, 7, 8, 9] -//│ > access the `head` of [7, 8, 9] -//│ > access the `tail` of [7, 8, 9] -//│ > access the `head` of [8, 9] -//│ > access the `tail` of [8, 9] -//│ > access the `head` of [9] -//│ > access the `tail` of [9] -//│ = true +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) pattern DoubleAndTripleList = DoubleList & TripleList @@ -249,112 +259,124 @@ fun isDoubleAndTriple__naive(xs) = withLog of () => xs is DoubleAndTripleList isDoubleAndTriple__naive of list(8, 9) -//│ > access the `head` of [8, 9] -//│ > access the `tail` of [8, 9] -//│ > access the `head` of [9] -//│ > access the `tail` of [9] -//│ > access the `head` of [8, 9] -//│ > access the `tail` of [8, 9] -//│ > access the `head` of [9] -//│ > access the `tail` of [9] -//│ = false +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL132:1:43 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) isDoubleAndTriple__naive of list(1, 2, 3) -//│ > access the `head` of [1, 2, 3] -//│ > access the `tail` of [1, 2, 3] -//│ > access the `head` of [2, 3] -//│ > access the `tail` of [2, 3] -//│ > access the `head` of [3] -//│ > access the `tail` of [3] -//│ = false +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL135:1:43 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) isDoubleAndTriple__naive of list(4, 3, 2, 1) -//│ > access the `head` of [4, 3, 2, 1] -//│ > access the `tail` of [4, 3, 2, 1] -//│ > access the `head` of [3, 2, 1] -//│ > access the `tail` of [3, 2, 1] -//│ > access the `head` of [2, 1] -//│ > access the `tail` of [2, 1] -//│ > access the `head` of [1] -//│ > access the `tail` of [1] -//│ > access the `head` of [4, 3, 2, 1] -//│ > access the `tail` of [4, 3, 2, 1] -//│ > access the `head` of [3, 2, 1] -//│ > access the `tail` of [3, 2, 1] -//│ > access the `head` of [2, 1] -//│ > access the `tail` of [2, 1] -//│ > access the `head` of [1] -//│ > access the `tail` of [1] -//│ = false +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL138:1:43 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) isDoubleAndTriple__naive of list(1, 2, 3, 4, 5, 6) -//│ > access the `head` of [1, 2, 3, 4, 5, 6] -//│ > access the `tail` of [1, 2, 3, 4, 5, 6] -//│ > access the `head` of [2, 3, 4, 5, 6] -//│ > access the `tail` of [2, 3, 4, 5, 6] -//│ > access the `head` of [3, 4, 5, 6] -//│ > access the `tail` of [3, 4, 5, 6] -//│ > access the `head` of [4, 5, 6] -//│ > access the `tail` of [4, 5, 6] -//│ > access the `head` of [5, 6] -//│ > access the `tail` of [5, 6] -//│ > access the `head` of [6] -//│ > access the `tail` of [6] -//│ > access the `head` of [1, 2, 3, 4, 5, 6] -//│ > access the `tail` of [1, 2, 3, 4, 5, 6] -//│ > access the `head` of [2, 3, 4, 5, 6] -//│ > access the `tail` of [2, 3, 4, 5, 6] -//│ > access the `head` of [3, 4, 5, 6] -//│ > access the `tail` of [3, 4, 5, 6] -//│ > access the `head` of [4, 5, 6] -//│ > access the `tail` of [4, 5, 6] -//│ > access the `head` of [5, 6] -//│ > access the `tail` of [5, 6] -//│ > access the `head` of [6] -//│ > access the `tail` of [6] -//│ = true +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) fun isDoubleAndTriple__compiled(xs) = withLog of () => xs is @compile DoubleAndTripleList isDoubleAndTriple__compiled of list(8, 9) -//│ > access the `head` of [8, 9] -//│ > access the `tail` of [8, 9] -//│ > access the `head` of [9] -//│ > access the `tail` of [9] -//│ = false +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL147:1:43 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) isDoubleAndTriple__compiled of list(1, 2, 3) -//│ > access the `head` of [1, 2, 3] -//│ > access the `tail` of [1, 2, 3] -//│ > access the `head` of [2, 3] -//│ > access the `tail` of [2, 3] -//│ > access the `head` of [3] -//│ > access the `tail` of [3] -//│ = false +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL150:1:43 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) isDoubleAndTriple__compiled of list(4, 3, 2, 1) -//│ > access the `head` of [4, 3, 2, 1] -//│ > access the `tail` of [4, 3, 2, 1] -//│ > access the `head` of [3, 2, 1] -//│ > access the `tail` of [3, 2, 1] -//│ > access the `head` of [2, 1] -//│ > access the `tail` of [2, 1] -//│ > access the `head` of [1] -//│ > access the `tail` of [1] -//│ = false +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) +//│ at REPL153:1:43 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) isDoubleAndTriple__compiled of list(1, 2, 3, 4, 5, 6) -//│ > access the `head` of [1, 2, 3, 4, 5, 6] -//│ > access the `tail` of [1, 2, 3, 4, 5, 6] -//│ > access the `head` of [2, 3, 4, 5, 6] -//│ > access the `tail` of [2, 3, 4, 5, 6] -//│ > access the `head` of [3, 4, 5, 6] -//│ > access the `tail` of [3, 4, 5, 6] -//│ > access the `head` of [4, 5, 6] -//│ > access the `tail` of [4, 5, 6] -//│ > access the `head` of [5, 6] -//│ > access the `tail` of [5, 6] -//│ > access the `head` of [6] -//│ > access the `tail` of [6] -//│ = true +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head +//│ at Function.defineProperty () +//│ at makeObservableCons (REPL79:1:1038) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) +//│ at list (REPL93:1:184) From 0f161418b8bdd71b53e94fac30af8c2eb1460183 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Thu, 9 Oct 2025 19:31:22 +0800 Subject: [PATCH 04/55] WIP: Test Cases Use wrapping term for Sel resoultion. --- hkmc2/shared/src/test/mlscript/HkScratch.mls | 184 ++++--------------- 1 file changed, 34 insertions(+), 150 deletions(-) diff --git a/hkmc2/shared/src/test/mlscript/HkScratch.mls b/hkmc2/shared/src/test/mlscript/HkScratch.mls index 8b04dc96e7..4090f0bae0 100644 --- a/hkmc2/shared/src/test/mlscript/HkScratch.mls +++ b/hkmc2/shared/src/test/mlscript/HkScratch.mls @@ -1,153 +1,37 @@ :js -:dl -:lot -Object -//│ Lowering.term member:Object – symbol class:Object -//│ Expanding term Ref(member:Object) -//│ ~> Resolved(Ref(member:Object),class:Object) -//│ Lowering.term globalThis:globalThis.Object‹member:Object› – symbol member:Object -//│ Expanding term Sel(Ref(globalThis:globalThis),Ident(Object)) -//│ ~> Sel(Ref(globalThis:globalThis),Ident(Object)) -//│ Lowering.term globalThis:globalThis – symbol globalThis:globalThis -//│ Expanding term Ref(globalThis:globalThis) -//│ ~> Ref(globalThis:globalThis) -//│ Lowered: -//│ Program: -//│ imports = Nil -//│ main = Assign: -//│ lhs = $selRes -//│ rhs = Select{member:Object}: -//│ qual = Ref: -//│ l = globalThis:globalThis -//│ disamb = N -//│ name = Ident of "Object" -//│ rest = Match: \ -//│ scrut = Ref: -//│ l = $selRes -//│ disamb = N -//│ arms = Ls of -//│ Tuple2: -//│ _1 = Lit of UnitLit of false -//│ _2 = Throw of Instantiate: -//│ mut = false -//│ cls = Select: -//│ qual = Ref: -//│ l = globalThis:globalThis -//│ disamb = S of globalThis:globalThis -//│ name = Ident of "Error" -//│ args = Ls of -//│ Arg: -//│ spread = N -//│ value = Lit of StrLit of "Access to required field 'Object' yielded 'undefined'" -//│ dflt = N -//│ rest = Assign: \ -//│ lhs = $block$res -//│ rhs = Ref: -//│ l = $selRes -//│ disamb = N -//│ rest = Return: \ -//│ res = Lit of UnitLit of false -//│ implct = true -//│ avoidNames Assign($selRes,Select(Ref(globalThis:globalThis,None),Ident(Object)),Match(Ref($selRes,None),List((L... -//│ | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... -//│ | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... -//│ | | avoidNames Assign($block$res,Ref($selRes,None),Return(Lit(UnitLit(false)),true))... -//│ | | | avoidNames Return(Lit(UnitLit(false)),true)... -//│ = class Object +data class Foo(x) +module Foo with + fun foo = 42 -:dl -:lot -Object.freeze -//│ Lowering.term member:Object.freeze -//│ Expanding term Sel(Ref(member:Object),Ident(freeze)) -//│ ~> Sel(Ref(member:Object),Ident(freeze)) -//│ Lowering.term member:Object – symbol member:Object -//│ Expanding term Ref(member:Object) -//│ ~> Ref(member:Object) -//│ Lowering.term globalThis:globalThis.Object‹member:Object› – symbol member:Object -//│ Expanding term Sel(Ref(globalThis:globalThis),Ident(Object)) -//│ ~> Sel(Ref(globalThis:globalThis),Ident(Object)) -//│ Lowering.term globalThis:globalThis – symbol globalThis:globalThis -//│ Expanding term Ref(globalThis:globalThis) -//│ ~> Ref(globalThis:globalThis) -//│ Lowered: -//│ Program: -//│ imports = Nil -//│ main = Assign: -//│ lhs = $selRes -//│ rhs = Select{member:Object}: -//│ qual = Ref: -//│ l = globalThis:globalThis -//│ disamb = N -//│ name = Ident of "Object" -//│ rest = Match: \ -//│ scrut = Ref: -//│ l = $selRes -//│ disamb = N -//│ arms = Ls of -//│ Tuple2: -//│ _1 = Lit of UnitLit of false -//│ _2 = Throw of Instantiate: -//│ mut = false -//│ cls = Select: -//│ qual = Ref: -//│ l = globalThis:globalThis -//│ disamb = S of globalThis:globalThis -//│ name = Ident of "Error" -//│ args = Ls of -//│ Arg: -//│ spread = N -//│ value = Lit of StrLit of "Access to required field 'Object' yielded 'undefined'" -//│ dflt = N -//│ rest = Assign: \ -//│ lhs = $selRes -//│ rhs = Select: -//│ qual = Ref: -//│ l = $selRes -//│ disamb = N -//│ name = Ident of "freeze" -//│ rest = Assign: \ -//│ lhs = $discarded -//│ rhs = Select: -//│ qual = Ref: -//│ l = $selRes -//│ disamb = N -//│ name = Ident of "freeze$__checkNotMethod" -//│ rest = Match: \ -//│ scrut = Ref: -//│ l = $selRes -//│ disamb = N -//│ arms = Ls of -//│ Tuple2: -//│ _1 = Lit of UnitLit of false -//│ _2 = Throw of Instantiate: -//│ mut = false -//│ cls = Select: -//│ qual = Ref: -//│ l = globalThis:globalThis -//│ disamb = S of globalThis:globalThis -//│ name = Ident of "Error" -//│ args = Ls of -//│ Arg: -//│ spread = N -//│ value = Lit of StrLit of "Access to required field 'freeze' yielded 'undefined'" -//│ dflt = N -//│ rest = Assign: \ -//│ lhs = $block$res -//│ rhs = Ref: -//│ l = $selRes -//│ disamb = N -//│ rest = Return: \ -//│ res = Lit of UnitLit of false -//│ implct = true -//│ avoidNames Assign($selRes,Select(Ref(globalThis:globalThis,None),Ident(Object)),Match(Ref($selRes,None),List((L... -//│ | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... -//│ | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... -//│ | | avoidNames Assign($selRes,Select(Ref($selRes,None),Ident(freeze)),Assign($discarded,Select(Ref($selRes,None),Id... -//│ | | | avoidNames Assign($discarded,Select(Ref($selRes,None),Ident(freeze$__checkNotMethod)),Match(Ref($selRes,None),L... -//│ | | | | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... -//│ | | | | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... -//│ | | | | | avoidNames Assign($block$res,Ref($selRes,None),Return(Lit(UnitLit(false)),true))... -//│ | | | | | | avoidNames Return(Lit(UnitLit(false)),true)... -//│ = fun freeze +Foo.foo +//│ = 42 + +Foo(42) +//│ = Foo(42) + + +module M with + data class Foo(x) + module Foo with + fun foo = 42 + +:js +M.Foo.foo +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] Error: Access to required field 'foo' yielded 'undefined' +//│ at REPL22:1:271 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:613:22) + + +M.Foo(42) +//│ = Foo(42) From df23015ba0cd58f540e55fbd127eb593a473fcde Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Thu, 9 Oct 2025 23:22:42 +0800 Subject: [PATCH 05/55] Use `Term.Resolved` for Sel resoultion --- .../src/main/scala/hkmc2/codegen/Block.scala | 18 +- .../hkmc2/codegen/BlockTransformer.scala | 2 +- .../src/main/scala/hkmc2/codegen/Lifter.scala | 17 +- .../main/scala/hkmc2/codegen/Lowering.scala | 68 +-- .../scala/hkmc2/codegen/js/JSBuilder.scala | 11 +- .../main/scala/hkmc2/semantics/Resolver.scala | 13 +- .../main/scala/hkmc2/semantics/Symbol.scala | 5 + .../src/main/scala/hkmc2/semantics/Term.scala | 17 +- hkmc2/shared/src/test/mlscript/HkScratch.mls | 41 +- .../basics/CompanionModules_Classes.mls | 24 +- .../src/test/mlscript/basics/MutRcd.mls | 6 +- .../src/test/mlscript/codegen/BasicTerms.mls | 4 +- .../test/mlscript/codegen/FieldSymbols.mls | 8 +- .../src/test/mlscript/codegen/ImportMLs.mls | 2 +- .../test/mlscript/codegen/NestedClasses.mls | 28 +- .../test/mlscript/ctx/SymbolResolution.mls | 178 ++++---- .../src/test/mlscript/handlers/Effects.mls | 14 +- .../mlscript/lifter/ClassWithCompanion.mls | 150 +------ .../ups/examples/DoubleTripleList.mls | 422 +++++++++--------- 19 files changed, 456 insertions(+), 572 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala index f09a4873b4..2a3b4bd999 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala @@ -550,23 +550,31 @@ case class Call(fun: Path, args: Ls[Arg])(val isMlsFun: Bool, val mayRaiseEffect case class Instantiate(mut: Bool, cls: Path, args: Ls[Arg]) extends Result sealed abstract class Path extends TrivialResult: - def selN(id: Tree.Ident): Path = Select(this, id)(N) - def sel(id: Tree.Ident, sym: FieldSymbol): Path = Select(this, id)(S(sym)) + def selN(id: Tree.Ident): Path = Select(this, id)(N, N) + def sel(id: Tree.Ident, sym: FieldSymbol): Path = Select(this, id)(S(sym), N) def selSN(id: Str): Path = selN(new Tree.Ident(id)) def asArg = Arg(spread = N, this) -case class Select(qual: Path, name: Tree.Ident)(val symbol: Opt[FieldSymbol]) extends Path with ProductWithExtraInfo: - def extraInfo: Str = symbol.mkString +case class Select(qual: Path, name: Tree.Ident)(val symbol: Opt[FieldSymbol], val disamb: Opt[DefinitionSymbol[?]]) extends Path with ProductWithExtraInfo: + def extraInfo: Str = + (symbol.map(s => s"sym=${s}") :: disamb.map(s => s"disamb=${s}") :: Nil) + .collect: + case S(info) => info + .mkString(",") case class DynSelect(qual: Path, fld: Path, arrayIdx: Bool) extends Path -enum Value extends Path: +enum Value extends Path with ProductWithExtraInfo: case Ref(l: Local, disamb: Opt[DefinitionSymbol[?]]) case This(sym: InnerSymbol) // TODO rm – just use Ref case Lit(lit: Literal) case Lam(params: ParamList, body: Block) case Arr(mut: Bool, elems: Ls[Arg]) case Rcd(mut: Bool, elems: Ls[RcdArg]) + + override def extraInfo: Str = this match + case Ref(l, disamb) => disamb.map(s => s"disamb=${s}").mkString + case _ => "" object Value: object Ref: diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala index c455553650..576a0024a4 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala @@ -114,7 +114,7 @@ class BlockTransformer(subst: SymbolSubst): case p @ Select(qual, name) => val qual2 = applyPath(qual) val sym2 = p.symbol.mapConserve(_.subst) - if (qual2 is qual) && (sym2 is p.symbol) then p else Select(qual2, name)(sym2) + if (qual2 is qual) && (sym2 is p.symbol) then p else Select(qual2, name)(sym2, p.disamb) case v: Value => applyValue(v) def applyValue(v: Value): Value = v match diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index bee77267fb..4bb28ce3dd 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -229,7 +229,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): def read = this match case Sym(l) => l.asPath - case PubField(isym, sym) => Select(isym.asPath, Tree.Ident(sym.nme))(S(sym)) + case PubField(isym, sym) => Select(isym.asPath, Tree.Ident(sym.nme))(S(sym), N) def asArg = read.asArg @@ -714,13 +714,13 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): msg"Uses of private fields cannot yet be lifted." -> N :: Nil, N, Diagnostic.Source.Compilation )) - Select(value.read, t.id)(N) + Select(value.read, t.id)(N, N) case _ => super.applyPath(p) // Rewrites this.className.class to reference the top-level definition case s @ Select(RefOfBms(l, disamb), Tree.Ident("class")) if !ctx.ignored(l) && ctx.isRelevant(l) => // this class will be lifted, rewrite the ref to strip it of `Select` - Select(Value.Ref(l, disamb), Tree.Ident("class"))(s.symbol) + Select(Value.Ref(l, disamb), Tree.Ident("class"))(s.symbol, N) // TODO: ^ // TODO: Ref Refactorization @@ -729,7 +729,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): // from the objects BlockMemberSymbol to that new symbol. case s @ Select(qual, ident) => s.symbol.flatMap(ctx.getLocalPath) match - case Some(LocalPath.Sym(value: MemberSymbol[?])) => Select(qual, Tree.Ident(value.nme))(S(value)) + case Some(LocalPath.Sym(value: MemberSymbol[?])) => Select(qual, Tree.Ident(value.nme))(S(value), N) case _ => super.applyPath(p) // This is to rewrite references to classes that are not lifted (when their BlockMemberSymbol @@ -742,7 +742,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): // from the capture; otherwise, we see if that local is passed directly as a parameter to this defn. case Value.Ref(l, _) => ctx.getLocalCaptureSym(l) match case Some(captureSym) => - Select(ctx.getLocalClosPath(l).get.read, captureSym.id)(N) + Select(ctx.getLocalClosPath(l).get.read, captureSym.id)(N, N) case None => ctx.getLocalPath(l) match case Some(value) => value.read case None => super.applyPath(p) @@ -942,7 +942,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): var curSym = TempSymbol(None, "tmp") def instInner(isMut: Bool) = if c.paramsOpt.isDefined - then Instantiate(mut = isMut, Select(c.sym.asPath, Tree.Ident("class"))(N), paramArgs) + then Instantiate(mut = isMut, Select(c.sym.asPath, Tree.Ident("class"))(N, N), paramArgs) else Instantiate(mut = isMut, c.sym.asPath, paramArgs) val initSym = curSym @@ -1105,7 +1105,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): def rewriteExtends(p: Path): Path = p match case RefOfBms(b, _) if !ctx.ignored(b) && ctx.isRelevant(b) => b.asPath case Select(RefOfBms(b, _), Tree.Ident("class")) if !ctx.ignored(b) && ctx.isRelevant(b) => - Select(b.asPath, Tree.Ident("class"))(N) + Select(b.asPath, Tree.Ident("class"))(N, N) case _ => return p // if this class extends something, rewrite @@ -1196,7 +1196,8 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): .withCompanionMap(analyzer.companionMap) val walker1 = new BlockTransformerShallow(SymbolSubst()): - override def applyBlock(b: Block): Block = b match + override def applyBlock(b: Block): Block = + b match case Define(d, rest) => val (unliftable, modules, objects) = createMetadata(d, ctx) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index 3c8b45aea5..61d8bc94df 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -67,10 +67,10 @@ class Lowering()(using Config, TL, Raise, State, Ctx): val lift: Bool = config.liftDefns.isDefined private lazy val unreachableFn = - Select(Value.Ref(State.runtimeSymbol), Tree.Ident("unreachable"))(N) + Select(Value.Ref(State.runtimeSymbol), Tree.Ident("unreachable"))(N, N) def unit: Path = - Select(Value.Ref(State.runtimeSymbol), Tree.Ident("Unit"))(S(State.unitSymbol)) + Select(Value.Ref(State.runtimeSymbol), Tree.Ident("Unit"))(S(State.unitSymbol), N) def fail(err: ErrorReport): Block = @@ -442,9 +442,9 @@ class Lowering()(using Config, TL, Raise, State, Ctx): // * We have to instantiate `f` again because, if `f` is a Sel, the `term` // * function is not called again with f. See below `Sel` and `SelProj` cases. f.instantiated match - case t if t.resolvedSym.isDefined && (t.resolvedSym.get is ctx.builtins.js.try_catch) => + case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.js.try_catch) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("try_catch"))) - case t if t.resolvedSym.isDefined && (t.resolvedSym.get is ctx.builtins.debug.printStack) => + case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.debug.printStack) => if !config.effectHandlers.exists(_.debug) then return fail: ErrorReport( @@ -452,7 +452,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): t.toLoc :: Nil, source = Diagnostic.Source.Compilation) conclude(Value.Ref(State.runtimeSymbol).selSN("raisePrintStackEffect").withLocOf(f)) - case t if t.resolvedSym.isDefined && (t.resolvedSym.get is ctx.builtins.debug.getLocals) => + case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.debug.getLocals) => if !config.effectHandlers.exists(_.debug) then return fail: ErrorReport( @@ -464,10 +464,16 @@ class Lowering()(using Config, TL, Raise, State, Ctx): // * are preserved in the call and not moved to a temporary variable. case sel @ Sel(prefix, nme) => subTerm(prefix): p => - conclude(Select(p, nme)(sel.sym).withLocOf(sel)) + conclude(Select(p, nme)(sel.sym, N).withLocOf(sel)) + case Resolved(sel @ Sel(prefix, nme), sym) => + subTerm(prefix): p => + conclude(Select(p, nme)(sel.sym, S(sym)).withLocOf(sel)) case sel @ SelProj(prefix, _, nme) => subTerm(prefix): p => - conclude(Select(p, nme)(sel.sym).withLocOf(sel)) + conclude(Select(p, nme)(sel.sym, N).withLocOf(sel)) + case Resolved(sel @ SelProj(prefix, _, nme), sym) => + subTerm(prefix): p => + conclude(Select(p, nme)(sel.sym, S(sym)).withLocOf(sel)) case _ => subTerm(f)(conclude) case h @ Handle(lhs, rhs, as, cls, defs, bod) => if !lowerHandlers then @@ -603,7 +609,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): Case.Cls(ctorSym, st) -> go(tail, topLevel = false) case (param, arg) :: args => val (cse, blk) = mkArgs(args) - (cse, Assign(arg, Select(sr, new Tree.Ident(param.id.name).withLocOf(arg))(S(param)), blk)) + (cse, Assign(arg, Select(sr, new Tree.Ident(param.id.name).withLocOf(arg))(S(param), N), blk)) mkMatch(mkArgs(clsParams.iterator.zip(args).toList)) ctor.symbol.flatMap(_.asClsOrMod) match case S(cls: ClassSymbol) if ctx.builtins.virtualClasses contains cls => @@ -630,7 +636,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): case ((fieldName, fieldSymbol), blk) => mkMatch( Case.Field(fieldName, safe = true), // we know we have an object, no need to check again - Assign(fieldSymbol, Select(sr, fieldName)(N), blk) + Assign(fieldSymbol, Select(sr, fieldName)(N, N), blk) ) ) case Split.Else(els) => @@ -642,7 +648,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): else End() ) case Split.End => - Throw(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Error"))(N), + Throw(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Error"))(N, N), Value.Lit(syntax.Tree.StrLit("match error")).asArg :: Nil)) // TODO add failed-match scrutinee info val normalize = ucs.Normalization() @@ -663,13 +669,19 @@ class Lowering()(using Config, TL, Raise, State, Ctx): ) case sel @ Sel(prefix, nme) => - setupSelection(prefix, nme, sel.sym)(k) - + setupSelection(prefix, nme, sel.sym, N)(k) + case Resolved(sel @ Sel(prefix, nme), sym) => + setupSelection(prefix, nme, sel.sym, S(sym))(k) + case sel @ SynthSel(prefix, nme) => // * Not using `setupSelection` as these selections are not meant to be sanity-checked subTerm(prefix): p => - k(Select(p, nme)(sel.sym)) - + k(Select(p, nme)(sel.sym, N)) + case Resolved(sel @ SynthSel(prefix, nme), sym) => + // * Not using `setupSelection` as these selections are not meant to be sanity-checked + subTerm(prefix): p => + k(Select(p, nme)(sel.sym, S(sym))) + case DynSel(prefix, fld, ai) => subTerm(prefix): p => subTerm_nonTail(fld): f => @@ -720,19 +732,19 @@ class Lowering()(using Config, TL, Raise, State, Ctx): // * BbML-specific cases: t.Cls#field and mutable operations case sp @ SelProj(prefix, _, proj) => - setupSelection(prefix, proj, sp.sym)(k) + setupSelection(prefix, proj, sp.sym, N)(k) case Region(reg, body) => - Assign(reg, Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Region"))(N), Nil), + Assign(reg, Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Region"))(N, N), Nil), term_nonTail(body)(k)) case RegRef(reg, value) => plainArgs(reg :: value :: Nil): args => - k(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Ref"))(N), args)) + k(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Ref"))(N, N), args)) case Drop(ref) => subTerm(ref): _ => k(unit) case Deref(ref) => subTerm(ref): r => - k(Select(r, Tree.Ident("value"))(N)) + k(Select(r, Tree.Ident("value"))(N, N)) case SetRef(lhs, rhs) => subTerm(lhs): ref => subTerm_nonTail(rhs): value => @@ -1019,10 +1031,10 @@ class Lowering()(using Config, TL, Raise, State, Ctx): ) - def setupSelection(prefix: Term, nme: Tree.Ident, sym: Opt[FieldSymbol])(k: Result => Block)(using Subst): Block = + def setupSelection(prefix: Term, nme: Tree.Ident, sym: Opt[FieldSymbol], disamb: Opt[DefinitionSymbol[?]])(k: Result => Block)(using Subst): Block = subTerm(prefix): p => - val selRes = TempSymbol(N, "selRes") - k(Select(p, nme)(sym)) + val selRes = TempSymbol(N, "selRes") // TODO @LP: why is it here? + k(Select(p, nme)(sym, disamb)) final def setupFunctionOrByNameDef(paramLists: List[ParamList], bodyTerm: Term, name: Option[Str]) (using Subst): (List[ParamList], Block) = @@ -1046,23 +1058,23 @@ trait LoweringSelSanityChecks(using Config, TL, Raise, State) extends Lowering: private val instrument: Bool = config.sanityChecks.isDefined - - override def setupSelection(prefix: st, nme: Tree.Ident, sym: Opt[FieldSymbol])(k: Result => Block)(using Subst): Block = - if !instrument then return super.setupSelection(prefix, nme, sym)(k) + + override def setupSelection(prefix: st, nme: Tree.Ident, sym: Opt[FieldSymbol], disamb: Opt[DefinitionSymbol[?]])(k: Result => Block)(using Subst): Block = + if !instrument then return super.setupSelection(prefix, nme, sym, disamb)(k) subTerm(prefix): p => val selRes = TempSymbol(N, "selRes") // * We are careful to access `x.f` before `x.f$__checkNotMethod` in case `x` is, eg, `undefined` and // * the access should throw an error like `TypeError: Cannot read property 'f' of undefined`. val b0 = blockBuilder - .assign(selRes, Select(p, nme)(sym)) + .assign(selRes, Select(p, nme)(sym, disamb)) (if sym.isDefined then // * If the symbol is known, the elaborator will have already checked the access [invariant:1] b0 else b0 - .assign(TempSymbol(N, "discarded"), Select(p, Tree.Ident(nme.name+"$__checkNotMethod"))(N))) + .assign(TempSymbol(N, "discarded"), Select(p, Tree.Ident(nme.name+"$__checkNotMethod"))(N, N))) .ifthen(selRes.asPath, Case.Lit(syntax.Tree.UnitLit(false)), - Throw(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Error"))(N), + Throw(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Error"))(N, N), Value.Lit(syntax.Tree.StrLit(s"Access to required field '${nme.name}' yielded 'undefined'")).asArg :: Nil)) ) .rest(k(selRes.asPath)) @@ -1074,7 +1086,7 @@ trait LoweringTraceLog(instrument: Bool)(using TL, Raise, State) private def selFromGlobalThis(path: Str*): Path = path.foldLeft[Path](Value.Ref(State.globalThisSymbol)): - (qual, name) => Select(qual, Tree.Ident(name))(N) + (qual, name) => Select(qual, Tree.Ident(name))(N, N) private def assignStmts(stmts: (Local, Result)*)(rest: Block) = stmts.foldRight(rest): diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala index 6fd2f9f3b1..60b48bd3f8 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala @@ -113,6 +113,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: else errExpr(msg"Illegal reference to builtin symbol '${l.nme}'") case Value.Ref(l, disamb) => l match case l: BlockMemberSymbol if { + // TODO @Harry: refactor(ize) duplicated logic l.hasLiftedClass && disamb.flatMap(d => d.asMod orElse d.asCls).exists(_ isnt ctx.builtins.Array) } => @@ -152,7 +153,13 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: case Value.Lam(ps, bod) => scope.nest givenIn: val (params, bodyDoc) = setupFunction(none, ps, bod) doc"($params) => ${ braced(bodyDoc) }" - case Select(qual, id) => + case s @ Select(qual, id) => + val dotClass = s.symbol match + case S(bms: BlockMemberSymbol) if { + bms.hasLiftedClass && + s.disamb.flatMap(d => d.asMod orElse d.asCls).exists(_ isnt ctx.builtins.Array) + } => doc".class" + case _ => doc"" val name = id.name doc"${result(qual)}${ if isValidFieldName(name) @@ -160,7 +167,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: else name.toIntOption match case S(index) => doc"[$index]" case N => doc"[${makeStringLiteral(name)}]" - }" + }${dotClass}" case DynSelect(qual, fld, ai) => if ai then doc"${result(qual)}.at(${result(fld)})" diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 048467a21e..4a161a266e 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -801,12 +801,15 @@ class Resolver(tl: TraceLogger) lhs.singletonDefn.foreach: mdef => val fsym = mdef.body.members.get(id.name) fsym match - case S(fldSym) => - val bsym = fldSym.asBlkMember.getOrElse: - lastWords(s"${mdef}: field symbol found ${fldSym} but no block member symbol") + case S(bms: BlockMemberSymbol) => log(s"Resolving symbol for ${t}, defn = ${lhs.defn}") - t.expand(S(t.withSym(bsym))) - log(s"Resolved symbol for ${t}: ${bsym}") + disambSym(prefer, sign)(bms) match + case S(ds) => + t.expand(S(Term.Resolved(t.withSym(bms), ds)(N))) + case N => + log(s"! Unable to disambiguate ${bms}") + t.expand(S(t.withSym(bms))) + log(s"Resolved symbol for ${t}: ${bms}") case N => t.expand(S(t.withSym(ErrorSymbol(id.name, Tree.Dummy)))) raise: diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index c41fd2416f..4114b03f52 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -103,6 +103,7 @@ abstract class Symbol(using State) extends Located: case S(defn: TypeLikeDef) => S(defn.bsym) case S(defn: TermDefinition) => S(defn.sym) case N => N + case _ => N /** Get the symbol corresponding to the "representative" of a set of overloaded definitions, * or the sole definition, if it is not overloaded. @@ -316,8 +317,12 @@ sealed trait ClassLikeSymbol extends IdentifiedSymbol: * definition. */ sealed trait DefinitionSymbol[Defn <: Definition] extends Symbol: + this: MemberSymbol[Defn] => + def defn: Opt[Defn] def subst(using sub: SymbolSubst): DefinitionSymbol[Defn] + + def asMemSym: MemberSymbol[Defn] = this /** This is the symbol associated to specific definitions. * One overloaded `BlockMemberSymbol` may correspond to multiple `InnerSymbol`s diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index 68680244ed..49bac02c89 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -671,11 +671,18 @@ final case class HandlerTermDefinition( case class ObjBody(blk: Term.Blk): - lazy val members: Map[Str, FieldSymbol] = blk.stats.collect: - case td: TermDefinition => td.sym.nme -> td.sym - case td: ClassLikeDef => td.sym.nme -> td.sym - case td: TypeDef => td.sym.nme -> td.sym - .toMap + lazy val members: Map[Str, BlockMemberSymbol] = + blk.stats.collect: + case td: TermDefinition => td.sym + case td: ClassLikeDef => td.bsym + case td: TypeDef => td.bsym + .groupBy(_.nme) + .map: (nme, syms) => + if syms.distinct.length > 1 then + lastWords: + s"Duplicate members named '${nme}' with different block-member symbols: ${syms.mkString(", ")}." + nme -> syms.head + .toMap lazy val (methods, nonMethods) = blk.stats.partitionMap: case td: TermDefinition if td.k is syntax.Fun => L(td) diff --git a/hkmc2/shared/src/test/mlscript/HkScratch.mls b/hkmc2/shared/src/test/mlscript/HkScratch.mls index 4090f0bae0..947fed5df4 100644 --- a/hkmc2/shared/src/test/mlscript/HkScratch.mls +++ b/hkmc2/shared/src/test/mlscript/HkScratch.mls @@ -1,27 +1,21 @@ :js - -data class Foo(x) -module Foo with - fun foo = 42 - -Foo.foo -//│ = 42 - -Foo(42) -//│ = Foo(42) - - -module M with - data class Foo(x) - module Foo with - fun foo = 42 - -:js -M.Foo.foo +:lift + +fun f = + class C() + module C with + val empty = C() + C.empty +//│ FAILURE: Unexpected warning +//│ FAILURE LOCATION: applyDefn (Lifter.scala:395) +//│ ═══[WARNING] Modules are not yet lifted. + +f //│ FAILURE: Unexpected runtime error //│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] Error: Access to required field 'foo' yielded 'undefined' -//│ at REPL22:1:271 +//│ ═══[RUNTIME ERROR] Error: Access to required field 'empty' yielded 'undefined' +//│ at f (REPL10:1:589) +//│ at REPL13:1:39 //│ at ContextifyScript.runInThisContext (node:vm:137:12) //│ at REPLServer.defaultEval (node:repl:593:22) //│ at bound (node:domain:433:15) @@ -30,8 +24,3 @@ M.Foo.foo //│ at REPLServer.emit (node:events:518:28) //│ at REPLServer.emit (node:domain:489:12) //│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) -//│ at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:613:22) - - -M.Foo(42) -//│ = Foo(42) diff --git a/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls b/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls index fbfc6f3500..d09619ecee 100644 --- a/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls +++ b/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls @@ -38,11 +38,13 @@ C.empty //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Sel{sym=member:empty}: -//│ prefix = Resolved{sym=module:C,typ=module:C}: -//│ t = Ref{sym=member:C} of member:C -//│ sym = module:C -//│ nme = Ident of "empty" +//│ res = Resolved{sym=term:module:C.empty}: +//│ t = Sel{sym=member:empty}: +//│ prefix = Resolved{sym=module:C,typ=module:C}: +//│ t = Ref{sym=member:C} of member:C +//│ sym = module:C +//│ nme = Ident of "empty" +//│ sym = term:module:C.empty //│ = 1 :breakme // TODO: should be an error, down the line, when we resolve all selections statically @@ -61,11 +63,13 @@ C.empty //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Sel{sym=member:empty}: -//│ prefix = Resolved{sym=module:C,typ=module:C}: -//│ t = Ref{sym=member:C} of member:C -//│ sym = module:C -//│ nme = Ident of "empty" +//│ res = Resolved{sym=term:module:C.empty}: +//│ t = Sel{sym=member:empty}: +//│ prefix = Resolved{sym=module:C,typ=module:C}: +//│ t = Ref{sym=member:C} of member:C +//│ sym = module:C +//│ nme = Ident of "empty" +//│ sym = term:module:C.empty //│ = 1 diff --git a/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls b/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls index 55b3c1951e..9a38bf0244 100644 --- a/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls +++ b/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls @@ -104,7 +104,7 @@ Object.freeze //│ imports = Nil //│ main = Assign: //│ lhs = $selRes -//│ rhs = Select{member:Object}: +//│ rhs = Select{sym=member:Object}: //│ qual = Ref: //│ l = globalThis:globalThis //│ disamb = N @@ -119,7 +119,7 @@ Object.freeze //│ _2 = Throw of Instantiate: //│ mut = false //│ cls = Select: -//│ qual = Ref: +//│ qual = Ref{disamb=globalThis:globalThis}: //│ l = globalThis:globalThis //│ disamb = S of globalThis:globalThis //│ name = Ident of "Error" @@ -152,7 +152,7 @@ Object.freeze //│ _2 = Throw of Instantiate: //│ mut = false //│ cls = Select: -//│ qual = Ref: +//│ qual = Ref{disamb=globalThis:globalThis}: //│ l = globalThis:globalThis //│ disamb = S of globalThis:globalThis //│ name = Ident of "Error" diff --git a/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls b/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls index 82ab883e71..ebe71999cc 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls @@ -49,8 +49,8 @@ print("Hi") //│ main = Assign: //│ lhs = $tmp //│ rhs = Call: -//│ fun = Select{member:print}: -//│ qual = Ref: +//│ fun = Select{sym=member:print,disamb=term:module:Predef.print}: +//│ qual = Ref{disamb=module:Predef}: //│ l = member:Predef //│ disamb = S of module:Predef //│ name = Ident of "print" diff --git a/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls b/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls index 69a9cb3621..75fc0f01e2 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls @@ -111,14 +111,14 @@ case //│ Tuple2: //│ _1 = Cls: //│ cls = class:Foo -//│ path = Select{class:Foo}: -//│ qual = Ref: +//│ path = Select{sym=class:Foo}: +//│ qual = Ref{disamb=term:class:Foo.Foo}: //│ l = member:Foo //│ disamb = S of term:class:Foo.Foo //│ name = Ident of "class" //│ _2 = Assign: //│ lhs = $param0 -//│ rhs = Select{term:class:Foo.x}: +//│ rhs = Select{sym=term:class:Foo.x}: //│ qual = Ref: //│ l = caseScrut //│ disamb = N @@ -136,7 +136,7 @@ case //│ dflt = S of Throw of Instantiate: //│ mut = false //│ cls = Select: -//│ qual = Ref: +//│ qual = Ref{disamb=globalThis:globalThis}: //│ l = globalThis:globalThis //│ disamb = S of globalThis:globalThis //│ name = Ident of "Error" diff --git a/hkmc2/shared/src/test/mlscript/codegen/ImportMLs.mls b/hkmc2/shared/src/test/mlscript/codegen/ImportMLs.mls index e4bbe9ea1e..07b13f5dfb 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/ImportMLs.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/ImportMLs.mls @@ -39,7 +39,7 @@ Some(1) :sjs (new Some(1)) isDefined() //│ JS (unsanitized): -//│ let tmp3; tmp3 = globalThis.Object.freeze(new Option.Some(1)); Option.isDefined(tmp3) +//│ let tmp3; tmp3 = globalThis.Object.freeze(new Option.Some.class(1)); Option.isDefined(tmp3) //│ = true new Some(1) isDefined() diff --git a/hkmc2/shared/src/test/mlscript/codegen/NestedClasses.mls b/hkmc2/shared/src/test/mlscript/codegen/NestedClasses.mls index 015b97a5b1..5eb21ee8f4 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/NestedClasses.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/NestedClasses.mls @@ -32,39 +32,13 @@ object D extends Foo.C(123) with print(id(this).x) //│ > 123 //│ > 123 -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot define property class, object is not extensible -//│ at Function.defineProperty () -//│ at new D (REPL32:1:737) -//│ at (REPL32:1:275) -//│ at REPL32:1:851 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) :e object D extends Foo.C(123) with print(this.x) //│ ╔══[ERROR] Object 'D' does not contain member 'x' -//│ ║ l.51: print(this.x) +//│ ║ l.38: print(this.x) //│ ╙── ^^^^^^ //│ > 123 -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot define property class, object is not extensible -//│ at Function.defineProperty () -//│ at new D2 (REPL35:1:570) -//│ at (REPL35:1:276) -//│ at REPL35:1:685 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) diff --git a/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls b/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls index ec538dcc34..59d45edb93 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls @@ -24,42 +24,50 @@ M.foo //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Sel{sym=member:foo,typ=module:M}: -//│ prefix = Resolved{sym=module:M,typ=module:M}: -//│ t = Ref{sym=member:M} of member:M -//│ sym = module:M -//│ nme = Ident of "foo" +//│ res = Resolved{sym=term:module:M.foo,typ=module:M}: +//│ t = Sel{sym=member:foo}: +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M +//│ nme = Ident of "foo" +//│ sym = term:module:M.foo M.bar //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Sel{sym=member:bar,typ=module:M}: -//│ prefix = Resolved{sym=module:M,typ=module:M}: -//│ t = Ref{sym=member:M} of member:M -//│ sym = module:M -//│ nme = Ident of "bar" +//│ res = Resolved{sym=term:module:M.bar,typ=module:M}: +//│ t = Sel{sym=member:bar}: +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M +//│ nme = Ident of "bar" +//│ sym = term:module:M.bar M.baz //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Sel{sym=member:baz}: -//│ prefix = Resolved{sym=module:M,typ=module:M}: -//│ t = Ref{sym=member:M} of member:M -//│ sym = module:M -//│ nme = Ident of "baz" +//│ res = Resolved{sym=term:module:M.baz}: +//│ t = Sel{sym=member:baz}: +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M +//│ nme = Ident of "baz" +//│ sym = term:module:M.baz M.baz() //│ Resolved tree: //│ Blk: //│ stats = Nil //│ res = App{typ=module:M}: -//│ lhs = Sel{sym=member:baz}: -//│ prefix = Resolved{sym=module:M,typ=module:M}: -//│ t = Ref{sym=member:M} of member:M -//│ sym = module:M -//│ nme = Ident of "baz" +//│ lhs = Resolved{sym=term:module:M.baz}: +//│ t = Sel{sym=member:baz}: +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M +//│ nme = Ident of "baz" +//│ sym = term:module:M.baz //│ rhs = Tup of Nil M.foo.bar.baz() @@ -67,69 +75,79 @@ M.foo.bar.baz() //│ Blk: //│ stats = Nil //│ res = App{typ=module:M}: -//│ lhs = Sel{sym=member:baz}: -//│ prefix = Sel{sym=member:bar,typ=module:M}: -//│ prefix = Sel{sym=member:foo,typ=module:M}: -//│ prefix = Resolved{sym=module:M,typ=module:M}: -//│ t = Ref{sym=member:M} of member:M -//│ sym = module:M -//│ nme = Ident of "foo" -//│ nme = Ident of "bar" -//│ nme = Ident of "baz" +//│ lhs = Resolved{sym=term:module:M.baz}: +//│ t = Sel{sym=member:baz}: +//│ prefix = Sel{sym=member:bar,typ=module:M}: +//│ prefix = Sel{sym=member:foo,typ=module:M}: +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M +//│ nme = Ident of "foo" +//│ nme = Ident of "bar" +//│ nme = Ident of "baz" +//│ sym = term:module:M.baz //│ rhs = Tup of Nil M.that.that //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Sel{sym=member:that,typ=module:M}: -//│ prefix = Sel{sym=member:that,typ=module:N}: -//│ prefix = Resolved{sym=module:M,typ=module:M}: -//│ t = Ref{sym=member:M} of member:M -//│ sym = module:M +//│ res = Resolved{sym=term:module:N.that,typ=module:M}: +//│ t = Sel{sym=member:that}: +//│ prefix = Sel{sym=member:that,typ=module:N}: +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M +//│ nme = Ident of "that" //│ nme = Ident of "that" -//│ nme = Ident of "that" +//│ sym = term:module:N.that M.that.that.that.that.that.that //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Sel{sym=member:that,typ=module:M}: -//│ prefix = Sel{sym=member:that,typ=module:N}: -//│ prefix = Sel{sym=member:that,typ=module:M}: -//│ prefix = Sel{sym=member:that,typ=module:N}: -//│ prefix = Sel{sym=member:that,typ=module:M}: -//│ prefix = Sel{sym=member:that,typ=module:N}: -//│ prefix = Resolved{sym=module:M,typ=module:M}: -//│ t = Ref{sym=member:M} of member:M -//│ sym = module:M +//│ res = Resolved{sym=term:module:N.that,typ=module:M}: +//│ t = Sel{sym=member:that}: +//│ prefix = Sel{sym=member:that,typ=module:N}: +//│ prefix = Sel{sym=member:that,typ=module:M}: +//│ prefix = Sel{sym=member:that,typ=module:N}: +//│ prefix = Sel{sym=member:that,typ=module:M}: +//│ prefix = Sel{sym=member:that,typ=module:N}: +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M +//│ nme = Ident of "that" //│ nme = Ident of "that" //│ nme = Ident of "that" //│ nme = Ident of "that" //│ nme = Ident of "that" //│ nme = Ident of "that" -//│ nme = Ident of "that" +//│ sym = term:module:N.that R.foo //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Sel{sym=member:foo}: -//│ prefix = Resolved{sym=module:R,typ=module:R}: -//│ t = Ref{sym=member:R} of member:R -//│ sym = module:R -//│ nme = Ident of "foo" +//│ res = Resolved{sym=term:module:R.foo}: +//│ t = Sel{sym=member:foo}: +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R +//│ nme = Ident of "foo" +//│ sym = term:module:R.foo R.foo() //│ Resolved tree: //│ Blk: //│ stats = Nil //│ res = App: -//│ lhs = Sel{sym=member:foo}: -//│ prefix = Resolved{sym=module:R,typ=module:R}: -//│ t = Ref{sym=member:R} of member:R -//│ sym = module:R -//│ nme = Ident of "foo" +//│ lhs = Resolved{sym=term:module:R.foo}: +//│ t = Sel{sym=member:foo}: +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R +//│ nme = Ident of "foo" +//│ sym = term:module:R.foo //│ rhs = Tup of Nil R.foo()() @@ -138,11 +156,13 @@ R.foo()() //│ stats = Nil //│ res = App{typ=module:N}: //│ lhs = App: -//│ lhs = Sel{sym=member:foo}: -//│ prefix = Resolved{sym=module:R,typ=module:R}: -//│ t = Ref{sym=member:R} of member:R -//│ sym = module:R -//│ nme = Ident of "foo" +//│ lhs = Resolved{sym=term:module:R.foo}: +//│ t = Sel{sym=member:foo}: +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R +//│ nme = Ident of "foo" +//│ sym = term:module:R.foo //│ rhs = Tup of Nil //│ rhs = Tup of Nil @@ -153,11 +173,13 @@ R.foo()()() //│ res = App: //│ lhs = App{typ=module:N}: //│ lhs = App: -//│ lhs = Sel{sym=member:foo}: -//│ prefix = Resolved{sym=module:R,typ=module:R}: -//│ t = Ref{sym=member:R} of member:R -//│ sym = module:R -//│ nme = Ident of "foo" +//│ lhs = Resolved{sym=term:module:R.foo}: +//│ t = Sel{sym=member:foo}: +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R +//│ nme = Ident of "foo" +//│ sym = term:module:R.foo //│ rhs = Tup of Nil //│ rhs = Tup of Nil //│ rhs = Tup of Nil @@ -173,11 +195,13 @@ R.bar //│ res = App{typ=module:M}: //│ lhs = App: //│ lhs = App: -//│ lhs = Sel{sym=member:bar}: -//│ prefix = Resolved{sym=module:R,typ=module:R}: -//│ t = Ref{sym=member:R} of member:R -//│ sym = module:R -//│ nme = Ident of "bar" +//│ lhs = Resolved{sym=term:module:R.bar}: +//│ t = Sel{sym=member:bar}: +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R +//│ nme = Ident of "bar" +//│ sym = term:module:R.bar //│ rhs = Tup of Ls of //│ Fld: //│ flags = () @@ -242,12 +266,14 @@ R.bar[Int] //│ res = App{typ=module:M}: //│ lhs = App: //│ lhs = App: -//│ lhs = TyApp{sym=member:bar}: -//│ lhs = Sel{sym=member:bar}: -//│ prefix = Resolved{sym=module:R,typ=module:R}: -//│ t = Ref{sym=member:R} of member:R -//│ sym = module:R -//│ nme = Ident of "bar" +//│ lhs = TyApp{sym=term:module:R.bar}: +//│ lhs = Resolved{sym=term:module:R.bar}: +//│ t = Sel{sym=member:bar}: +//│ prefix = Resolved{sym=module:R,typ=module:R}: +//│ t = Ref{sym=member:R} of member:R +//│ sym = module:R +//│ nme = Ident of "bar" +//│ sym = term:module:R.bar //│ targs = Ls of //│ Resolved{sym=class:Int}: //│ t = Ref{sym=member:Int} of member:Int diff --git a/hkmc2/shared/src/test/mlscript/handlers/Effects.mls b/hkmc2/shared/src/test/mlscript/handlers/Effects.mls index 8d7fc35dd5..f023883baf 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/Effects.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/Effects.mls @@ -241,19 +241,7 @@ module A with handle h = A.Effect(3) with fun perform()(k) = 0 h.perform() -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: h.perform is not a function -//│ at handleBlock$ (REPL56:1:2244) -//│ at REPL56:1:2457 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ = 0 fun f(perform) = handle h = Effect with diff --git a/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls b/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls index f3b488285d..915114f78a 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls @@ -1,148 +1,30 @@ +:lift :js :w -:lot fun foo(x) = class C(y) with fun get = [x, y] module C with val empty = C(123) C.empty -//│ Lowered: -//│ Program: -//│ imports = Nil -//│ main = Define: -//│ defn = FunDefn: -//│ owner = N -//│ sym = member:foo -//│ params = Ls of -//│ ParamList: -//│ flags = () -//│ params = Ls of -//│ Param: -//│ flags = () -//│ sym = x -//│ sign = N -//│ modulefulness = Modulefulness of N -//│ restParam = N -//│ body = Define: -//│ defn = ClsLikeDefn: -//│ owner = N -//│ isym = class:C -//│ sym = member:C -//│ k = Cls -//│ paramsOpt = S of ParamList: -//│ flags = () -//│ params = Ls of -//│ Param: -//│ flags = () -//│ sym = y -//│ sign = N -//│ modulefulness = Modulefulness of N -//│ restParam = N -//│ auxParams = Nil -//│ parentPath = N -//│ methods = Ls of -//│ FunDefn: -//│ owner = S of class:C -//│ sym = member:get -//│ params = Nil -//│ body = Return: -//│ res = Arr: -//│ mut = false -//│ elems = Ls of -//│ Arg: -//│ spread = N -//│ value = Ref: -//│ l = x -//│ disamb = N -//│ Arg: -//│ spread = N -//│ value = Ref: -//│ l = term:class:C.y -//│ disamb = N -//│ implct = false -//│ privateFields = Ls of -//│ term:class:C.y -//│ publicFields = Nil -//│ preCtor = End of "" -//│ ctor = Assign: -//│ lhs = term:class:C.y -//│ rhs = Ref: -//│ l = y -//│ disamb = N -//│ rest = End of "" -//│ companion = S of ClsLikeBody: -//│ isym = module:C -//│ methods = Nil -//│ privateFields = Nil -//│ publicFields = Ls of -//│ Tuple2: -//│ _1 = member:empty -//│ _2 = term:module:C.empty -//│ ctor = Begin: -//│ sub = End of "" -//│ rest = Assign: \ -//│ lhs = $tmp -//│ rhs = Call: -//│ fun = Ref: -//│ l = member:C -//│ disamb = S of term:class:C.C -//│ args = Ls of -//│ Arg: -//│ spread = N -//│ value = Lit of IntLit of 123 -//│ rest = Define: \ -//│ defn = ValDefn: -//│ tsym = term:module:C.empty -//│ sym = member:empty -//│ rhs = Ref: -//│ l = $tmp -//│ disamb = N -//│ rest = End of "" -//│ rest = Assign: \ -//│ lhs = $selRes -//│ rhs = Select{member:empty}: -//│ qual = Ref: -//│ l = member:C -//│ disamb = S of module:C -//│ name = Ident of "empty" -//│ rest = Match: \ -//│ scrut = Ref: -//│ l = $selRes -//│ disamb = N -//│ arms = Ls of -//│ Tuple2: -//│ _1 = Lit of UnitLit of false -//│ _2 = Throw of Instantiate: -//│ mut = false -//│ cls = Select: -//│ qual = Ref: -//│ l = globalThis:globalThis -//│ disamb = S of globalThis:globalThis -//│ name = Ident of "Error" -//│ args = Ls of -//│ Arg: -//│ spread = N -//│ value = Lit of StrLit of "Access to required field 'empty' yielded 'undefined'" -//│ dflt = N -//│ rest = Return: \ -//│ res = Ref: -//│ l = $selRes -//│ disamb = N -//│ implct = false -//│ rest = Assign: \ -//│ lhs = $block$res -//│ rhs = Lit of UnitLit of false -//│ rest = End of "" -//│ FAILURE: Unexpected lack of warnings +//│ ═══[WARNING] Modules are not yet lifted. -:sjs foo(10).get -//│ JS (unsanitized): -//│ let tmp; tmp = foo(10); tmp.get -//│ = [10, 123] +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] Error: Access to required field 'empty' yielded 'undefined' +//│ at foo (REPL10:1:755) +//│ at REPL13:1:58 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) :w fun foo(x) = @@ -151,7 +33,7 @@ fun foo(x) = module C with val empty = new C C.empty -//│ FAILURE: Unexpected lack of warnings +//│ ═══[WARNING] Modules are not yet lifted. foo(10).get //│ = 10 diff --git a/hkmc2/shared/src/test/mlscript/ups/examples/DoubleTripleList.mls b/hkmc2/shared/src/test/mlscript/ups/examples/DoubleTripleList.mls index 16c87cd321..e8610ea98a 100644 --- a/hkmc2/shared/src/test/mlscript/ups/examples/DoubleTripleList.mls +++ b/hkmc2/shared/src/test/mlscript/ups/examples/DoubleTripleList.mls @@ -99,38 +99,14 @@ fun withLog(f) = result let testList = 1 :: 2 :: Nil -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at REPL86:1:57 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ testList = undefined +//│ testList = Cons(1, Cons(2, Nil)) withLog of () => testList.head testList.tail () -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'head') -//│ at lambda (REPL90:1:179) -//│ at withLog (REPL83:1:192) -//│ at REPL90:1:671 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) +//│ > access the `head` of [1, 2] +//│ > access the `tail` of [1, 2] fun list(...elements) = elements Iter.rightFolded of Nil, (::) @@ -138,64 +114,58 @@ fun isDoubleTripleList__compiled(xs) = withLog of () => xs is @compile DoubleTripleList isDoubleTripleList__compiled of list(1, 2, 3) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL99:1:41 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) +//│ > access the `head` of [1, 2, 3] +//│ > access the `tail` of [1, 2, 3] +//│ > access the `head` of [2, 3] +//│ > access the `tail` of [2, 3] +//│ > access the `head` of [3] +//│ > access the `tail` of [3] +//│ = true isDoubleTripleList__compiled of list(1, 2, 3, 4) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL102:1:41 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ > access the `head` of [1, 2, 3, 4] +//│ > access the `tail` of [1, 2, 3, 4] +//│ > access the `head` of [2, 3, 4] +//│ > access the `tail` of [2, 3, 4] +//│ > access the `head` of [3, 4] +//│ > access the `tail` of [3, 4] +//│ > access the `head` of [4] +//│ > access the `tail` of [4] +//│ = true isDoubleTripleList__compiled of list(1, 2, 3, 4, 5) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL105:1:43 +//│ > access the `head` of [1, 2, 3, 4, 5] +//│ > access the `tail` of [1, 2, 3, 4, 5] +//│ > access the `head` of [2, 3, 4, 5] +//│ > access the `tail` of [2, 3, 4, 5] +//│ > access the `head` of [3, 4, 5] +//│ > access the `tail` of [3, 4, 5] +//│ > access the `head` of [4, 5] +//│ > access the `tail` of [4, 5] +//│ > access the `head` of [5] +//│ > access the `tail` of [5] +//│ = false isDoubleTripleList__compiled of list(1, 2, 3, 4, 5, 6, 7, 8, 9) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ > access the `head` of [1, 2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [1, 2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `head` of [2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `head` of [3, 4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [3, 4, 5, 6, 7, 8, 9] +//│ > access the `head` of [4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [4, 5, 6, 7, 8, 9] +//│ > access the `head` of [5, 6, 7, 8, 9] +//│ > access the `tail` of [5, 6, 7, 8, 9] +//│ > access the `head` of [6, 7, 8, 9] +//│ > access the `tail` of [6, 7, 8, 9] +//│ > access the `head` of [7, 8, 9] +//│ > access the `tail` of [7, 8, 9] +//│ > access the `head` of [8, 9] +//│ > access the `tail` of [8, 9] +//│ > access the `head` of [9] +//│ > access the `tail` of [9] +//│ = true isDoubleTripleList__compiled of Nil //│ = true @@ -208,50 +178,70 @@ fun isDoubleTripleList__naive(xs) = // It does not backtracking because the `DoubleList` is tested first. isDoubleTripleList__naive of list(1, 2, 3, 4) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL117:1:43 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ > access the `head` of [1, 2, 3, 4] +//│ > access the `tail` of [1, 2, 3, 4] +//│ > access the `head` of [2, 3, 4] +//│ > access the `tail` of [2, 3, 4] +//│ > access the `head` of [3, 4] +//│ > access the `tail` of [3, 4] +//│ > access the `head` of [4] +//│ > access the `tail` of [4] +//│ = true // It does backtracking when `DoubleList` does not match. isDoubleTripleList__naive of list(1, 2, 3) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL120:1:43 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) +//│ > access the `head` of [1, 2, 3] +//│ > access the `tail` of [1, 2, 3] +//│ > access the `head` of [2, 3] +//│ > access the `tail` of [2, 3] +//│ > access the `head` of [3] +//│ > access the `tail` of [3] +//│ > access the `head` of [1, 2, 3] +//│ > access the `tail` of [1, 2, 3] +//│ > access the `head` of [2, 3] +//│ > access the `tail` of [2, 3] +//│ > access the `head` of [3] +//│ > access the `tail` of [3] +//│ = true isDoubleTripleList__naive of list(1, 2, 3, 4, 5, 6, 7, 8, 9) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) +//│ > access the `head` of [1, 2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [1, 2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `head` of [2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `head` of [3, 4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [3, 4, 5, 6, 7, 8, 9] +//│ > access the `head` of [4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [4, 5, 6, 7, 8, 9] +//│ > access the `head` of [5, 6, 7, 8, 9] +//│ > access the `tail` of [5, 6, 7, 8, 9] +//│ > access the `head` of [6, 7, 8, 9] +//│ > access the `tail` of [6, 7, 8, 9] +//│ > access the `head` of [7, 8, 9] +//│ > access the `tail` of [7, 8, 9] +//│ > access the `head` of [8, 9] +//│ > access the `tail` of [8, 9] +//│ > access the `head` of [9] +//│ > access the `tail` of [9] +//│ > access the `head` of [1, 2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [1, 2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `head` of [2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [2, 3, 4, 5, 6, 7, 8, 9] +//│ > access the `head` of [3, 4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [3, 4, 5, 6, 7, 8, 9] +//│ > access the `head` of [4, 5, 6, 7, 8, 9] +//│ > access the `tail` of [4, 5, 6, 7, 8, 9] +//│ > access the `head` of [5, 6, 7, 8, 9] +//│ > access the `tail` of [5, 6, 7, 8, 9] +//│ > access the `head` of [6, 7, 8, 9] +//│ > access the `tail` of [6, 7, 8, 9] +//│ > access the `head` of [7, 8, 9] +//│ > access the `tail` of [7, 8, 9] +//│ > access the `head` of [8, 9] +//│ > access the `tail` of [8, 9] +//│ > access the `head` of [9] +//│ > access the `tail` of [9] +//│ = true pattern DoubleAndTripleList = DoubleList & TripleList @@ -259,124 +249,112 @@ fun isDoubleAndTriple__naive(xs) = withLog of () => xs is DoubleAndTripleList isDoubleAndTriple__naive of list(8, 9) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL132:1:43 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) +//│ > access the `head` of [8, 9] +//│ > access the `tail` of [8, 9] +//│ > access the `head` of [9] +//│ > access the `tail` of [9] +//│ > access the `head` of [8, 9] +//│ > access the `tail` of [8, 9] +//│ > access the `head` of [9] +//│ > access the `tail` of [9] +//│ = false isDoubleAndTriple__naive of list(1, 2, 3) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL135:1:43 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) +//│ > access the `head` of [1, 2, 3] +//│ > access the `tail` of [1, 2, 3] +//│ > access the `head` of [2, 3] +//│ > access the `tail` of [2, 3] +//│ > access the `head` of [3] +//│ > access the `tail` of [3] +//│ = false isDoubleAndTriple__naive of list(4, 3, 2, 1) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL138:1:43 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ > access the `head` of [4, 3, 2, 1] +//│ > access the `tail` of [4, 3, 2, 1] +//│ > access the `head` of [3, 2, 1] +//│ > access the `tail` of [3, 2, 1] +//│ > access the `head` of [2, 1] +//│ > access the `tail` of [2, 1] +//│ > access the `head` of [1] +//│ > access the `tail` of [1] +//│ > access the `head` of [4, 3, 2, 1] +//│ > access the `tail` of [4, 3, 2, 1] +//│ > access the `head` of [3, 2, 1] +//│ > access the `tail` of [3, 2, 1] +//│ > access the `head` of [2, 1] +//│ > access the `tail` of [2, 1] +//│ > access the `head` of [1] +//│ > access the `tail` of [1] +//│ = false isDoubleAndTriple__naive of list(1, 2, 3, 4, 5, 6) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) +//│ > access the `head` of [1, 2, 3, 4, 5, 6] +//│ > access the `tail` of [1, 2, 3, 4, 5, 6] +//│ > access the `head` of [2, 3, 4, 5, 6] +//│ > access the `tail` of [2, 3, 4, 5, 6] +//│ > access the `head` of [3, 4, 5, 6] +//│ > access the `tail` of [3, 4, 5, 6] +//│ > access the `head` of [4, 5, 6] +//│ > access the `tail` of [4, 5, 6] +//│ > access the `head` of [5, 6] +//│ > access the `tail` of [5, 6] +//│ > access the `head` of [6] +//│ > access the `tail` of [6] +//│ > access the `head` of [1, 2, 3, 4, 5, 6] +//│ > access the `tail` of [1, 2, 3, 4, 5, 6] +//│ > access the `head` of [2, 3, 4, 5, 6] +//│ > access the `tail` of [2, 3, 4, 5, 6] +//│ > access the `head` of [3, 4, 5, 6] +//│ > access the `tail` of [3, 4, 5, 6] +//│ > access the `head` of [4, 5, 6] +//│ > access the `tail` of [4, 5, 6] +//│ > access the `head` of [5, 6] +//│ > access the `tail` of [5, 6] +//│ > access the `head` of [6] +//│ > access the `tail` of [6] +//│ = true fun isDoubleAndTriple__compiled(xs) = withLog of () => xs is @compile DoubleAndTripleList isDoubleAndTriple__compiled of list(8, 9) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL147:1:43 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) +//│ > access the `head` of [8, 9] +//│ > access the `tail` of [8, 9] +//│ > access the `head` of [9] +//│ > access the `tail` of [9] +//│ = false isDoubleAndTriple__compiled of list(1, 2, 3) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL150:1:43 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) +//│ > access the `head` of [1, 2, 3] +//│ > access the `tail` of [1, 2, 3] +//│ > access the `head` of [2, 3] +//│ > access the `tail` of [2, 3] +//│ > access the `head` of [3] +//│ > access the `tail` of [3] +//│ = false isDoubleAndTriple__compiled of list(4, 3, 2, 1) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) -//│ at REPL153:1:43 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ > access the `head` of [4, 3, 2, 1] +//│ > access the `tail` of [4, 3, 2, 1] +//│ > access the `head` of [3, 2, 1] +//│ > access the `tail` of [3, 2, 1] +//│ > access the `head` of [2, 1] +//│ > access the `tail` of [2, 1] +//│ > access the `head` of [1] +//│ > access the `tail` of [1] +//│ = false isDoubleAndTriple__compiled of list(1, 2, 3, 4, 5, 6) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: head -//│ at Function.defineProperty () -//│ at makeObservableCons (REPL79:1:1038) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:578:33) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at go (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:577:16) -//│ at Iter.rightFolded (file:///home/flandia/mlscript/hkmc2/shared/src/test/mlscript-compile/Iter.mjs:583:12) -//│ at list (REPL93:1:184) +//│ > access the `head` of [1, 2, 3, 4, 5, 6] +//│ > access the `tail` of [1, 2, 3, 4, 5, 6] +//│ > access the `head` of [2, 3, 4, 5, 6] +//│ > access the `tail` of [2, 3, 4, 5, 6] +//│ > access the `head` of [3, 4, 5, 6] +//│ > access the `tail` of [3, 4, 5, 6] +//│ > access the `head` of [4, 5, 6] +//│ > access the `tail` of [4, 5, 6] +//│ > access the `head` of [5, 6] +//│ > access the `tail` of [5, 6] +//│ > access the `head` of [6] +//│ > access the `tail` of [6] +//│ = true From 860681523c2a9341540f03bde2843c372b84b4f6 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Tue, 14 Oct 2025 21:56:23 +0800 Subject: [PATCH 06/55] Some refactor_ization_ WIP --- .../src/main/scala/hkmc2/codegen/Block.scala | 11 +++-- .../hkmc2/codegen/BlockTransformer.scala | 4 +- .../scala/hkmc2/codegen/BlockTraverser.scala | 2 +- .../scala/hkmc2/codegen/HandlerLowering.scala | 10 ++--- .../src/main/scala/hkmc2/codegen/Lifter.scala | 23 +++++----- .../main/scala/hkmc2/codegen/Lowering.scala | 45 +++++++++++-------- .../hkmc2/codegen/StackSafeTransform.scala | 2 +- .../scala/hkmc2/codegen/js/JSBuilder.scala | 8 ++-- .../scala/hkmc2/codegen/llir/Builder.scala | 16 +++---- .../scala/hkmc2/codegen/wasm/text/Wasm.scala | 4 +- .../hkmc2/codegen/wasm/text/WatBuilder.scala | 6 +-- .../main/scala/hkmc2/semantics/Resolver.scala | 2 + .../main/scala/hkmc2/semantics/Symbol.scala | 8 ++++ .../src/main/scala/hkmc2/semantics/Term.scala | 1 + .../hkmc2/semantics/ucs/Normalization.scala | 22 ++++----- .../hkmc2/semantics/ucs/TermSynthesizer.scala | 12 +++-- 16 files changed, 102 insertions(+), 74 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala index 6d2c006e34..c57209506c 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala @@ -558,14 +558,17 @@ case class Record(mut: Bool, elems: Ls[RcdArg]) extends Result sealed abstract class Path extends TrivialResult: - def selN(id: Tree.Ident): Path = Select(this, id)(N, N) - def sel(id: Tree.Ident, sym: FieldSymbol): Path = Select(this, id)(S(sym), N) + def selN(id: Tree.Ident): Path = Select(this, id)(N) + def sel(id: Tree.Ident, sym: DefinitionSymbol[?]): Path = Select(this, id)(S(sym)) def selSN(id: Str): Path = selN(new Tree.Ident(id)) def asArg = Arg(spread = N, this) -case class Select(qual: Path, name: Tree.Ident)(val symbol: Opt[FieldSymbol], val disamb: Opt[DefinitionSymbol[?]]) extends Path with ProductWithExtraInfo: +/** + * @param symbol The symbol, representing the definition that this selection refers to, if known. + */ +case class Select(qual: Path, name: Tree.Ident)(val symbol_SelectSymbol: Opt[DefinitionSymbol[?]]) extends Path with ProductWithExtraInfo: def extraInfo: Str = - (symbol.map(s => s"sym=${s}") :: disamb.map(s => s"disamb=${s}") :: Nil) + (symbol_SelectSymbol.map(s => s"sym=${s}") :: Nil) .collect: case S(info) => info .mkString(",") diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala index a756c1e9b6..eca199d4aa 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala @@ -139,8 +139,8 @@ class BlockTransformer(subst: SymbolSubst): k(if (qual2 is qual) && (fld2 is fld) then p else DynSelect(qual2, fld2, arrayIdx)) case p @ Select(qual, name) => applyPath(qual): qual2 => - val sym2 = p.symbol.mapConserve(_.subst) - k(if (qual2 is qual) && (sym2 is p.symbol) then p else Select(qual2, name)(sym2, p.disamb)) + val sym2 = p.symbol_SelectSymbol.mapConserve(_.subst) + k(if (qual2 is qual) && (sym2 is p.symbol_SelectSymbol) then p else Select(qual2, name)(sym2)) case v: Value => applyValue(v)(k) def applyValue(v: Value)(k: Value => Block) = v match diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala index dbb80ba72c..0f14338457 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala @@ -65,7 +65,7 @@ class BlockTraverser: case DynSelect(qual, fld, arrayIdx) => applyPath(qual); applyPath(fld) case p @ Select(qual, name) => - applyPath(qual); p.symbol.foreach(_.traverse) + applyPath(qual); p.symbol_SelectSymbol.foreach(_.traverse) case v: Value => applyValue(v) def applyValue(v: Value): Unit = v match diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala index 729b2867be..725abffcc3 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala @@ -591,7 +591,9 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, f.owner match case None => S(Call(f.sym.asPath, params)(true, true)) case Some(owner) => - S(Call(Select(owner.asPath, Tree.Ident(f.sym.nme))(S(f.sym), N), params)(true, true)) + S(Call(Select(owner.asPath, Tree.Ident(f.sym.nme))(S(f.innerSym.asInstanceOf)), params)(true, true)) + // TODO: ^^^^^^^^ + // TODO: @Harry check again on asInstanceOf case _ => None // TODO: more than one plist FunDefn(f.owner, f.sym, f.params, translateBlock(f.body, @@ -719,8 +721,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, // Create the DoUnwind function doUnwindMap += R(clsSym) -> Select(clsSym.asPath, Tree.Ident("doUnwind"))( - N /* this refers to the method defined in Runtime.FunctionContFrame */, - N + N /* this refers to the method defined in Runtime.FunctionContFrame */ ) val newPcSym = VarSymbol(Tree.Ident("newPc")) val resSym = VarSymbol(Tree.Ident("res")) @@ -792,8 +793,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, override def applyBlock(b: Block): Block = b match case ReturnCont(res, uid) => Return(Call( Select(clsSym.asPath, Tree.Ident("doUnwind"))( - N /* this refers to the method defined in Runtime.FunctionContFrame */, - N + N /* this refers to the method defined in Runtime.FunctionContFrame */ ), res.asPath.asArg :: Value.Lit(Tree.IntLit(uid)).asArg :: Nil)(true, false), false diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index 6ecc8722a7..eabdd75ea3 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -103,7 +103,7 @@ object Lifter: object RefOfBms: def unapply(p: Path) = p match case Value.Ref(l: BlockMemberSymbol, disamb) => S((l, disamb)) - case s @ Select(_, _) => s.symbol match + case s @ Select(_, _) => s.symbol_SelectSymbol match case Some(value: BlockMemberSymbol) => S(value, N) case _ => N case _ => N @@ -234,7 +234,8 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): def read = this match case Sym(l) => l.asPath - case PubField(isym, sym) => Select(isym.asPath, Tree.Ident(sym.nme))(S(sym), N) + case PubField(isym, sym) => Select(isym.asPath, Tree.Ident(sym.nme))(isym.asDefnSym_TODO) + // TODO: isym.asInstanceOf def asArg = read.asArg @@ -798,13 +799,13 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): msg"Uses of private fields cannot yet be lifted." -> N :: Nil, N, Diagnostic.Source.Compilation )) - k(Select(value.read, t.id)(N, N)) + k(Select(value.read, t.id)(N)) case _ => super.applyPath(p)(k) // Rewrites this.className.class to reference the top-level definition case s @ Select(RefOfBms(l, disamb), Tree.Ident("class")) if !ctx.ignored(l) && ctx.isRelevant(l) => // this class will be lifted, rewrite the ref to strip it of `Select` - k(Select(Value.Ref(l, disamb), Tree.Ident("class"))(s.symbol, N)) + k(Select(Value.Ref(l, disamb), Tree.Ident("class"))(s.symbol_SelectSymbol)) // TODO: ^ // TODO: Ref Refactorization @@ -812,9 +813,9 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): // replaced by a symbol, to which the object instance is assigned. This rewrites references // from the objects BlockMemberSymbol to that new symbol. case s @ Select(qual, ident) => - s.symbol.flatMap(ctx.getLocalPath) match - case Some(LocalPath.Sym(value: MemberSymbol[?])) => - k(Select(qual, Tree.Ident(value.nme))(S(value), N)) + s.symbol_SelectSymbol.flatMap(ctx.getLocalPath) match + case Some(LocalPath.Sym(value: DefinitionSymbol[?])) => + k(Select(qual, Tree.Ident(value.nme))(S(value))) case _ => super.applyPath(p)(k) // This is to rewrite references to classes that are not lifted (when their BlockMemberSymbol @@ -827,7 +828,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): // from the capture; otherwise, we see if that local is passed directly as a parameter to this defn. case Value.Ref(l, _) => ctx.getLocalCaptureSym(l) match case Some(captureSym) => - k(Select(ctx.getLocalClosPath(l).get.read, captureSym.id)(N, N)) + k(Select(ctx.getLocalClosPath(l).get.read, captureSym.id)(N)) case None => ctx.getLocalPath(l) match case Some(value) => k(value.read) case None => super.applyPath(p)(k) @@ -1027,8 +1028,9 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): val isMutSym = VarSymbol(Tree.Ident("isMut")) var curSym = TempSymbol(None, "tmp") + // TODO: This special case Select(..., "class") is redundant after this PR. def instInner(isMut: Bool) = if c.paramsOpt.isDefined - then Instantiate(mut = isMut, Select(c.sym.asPath, Tree.Ident("class"))(N, N), paramArgs) + then Instantiate(mut = isMut, Select(c.sym.asPath, Tree.Ident("class"))(N), paramArgs) else Instantiate(mut = isMut, c.sym.asPath, paramArgs) val initSym = curSym @@ -1188,10 +1190,11 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): case c: ClsLikeDefn => c.copy(owner = N) case d => d + // TODO: The special case Select(..., "class") is redundant after the PR. def rewriteExtends(p: Path): Path = p match case RefOfBms(b, _) if !ctx.ignored(b) && ctx.isRelevant(b) => b.asPath case Select(RefOfBms(b, _), Tree.Ident("class")) if !ctx.ignored(b) && ctx.isRelevant(b) => - Select(b.asPath, Tree.Ident("class"))(N, N) + Select(b.asPath, Tree.Ident("class"))(N) case _ => return p // if this class extends something, rewrite diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index 25d134be69..7695ab33be 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -68,10 +68,10 @@ class Lowering()(using Config, TL, Raise, State, Ctx): val lift: Bool = config.liftDefns.isDefined private lazy val unreachableFn = - Select(Value.Ref(State.runtimeSymbol), Tree.Ident("unreachable"))(N, N) + Select(Value.Ref(State.runtimeSymbol), Tree.Ident("unreachable"))(N) def unit: Path = - Select(Value.Ref(State.runtimeSymbol), Tree.Ident("Unit"))(S(State.unitSymbol), N) + Select(Value.Ref(State.runtimeSymbol), Tree.Ident("Unit"))(S(State.unitSymbol)) def fail(err: ErrorReport): Block = @@ -482,16 +482,20 @@ class Lowering()(using Config, TL, Raise, State, Ctx): // * are preserved in the call and not moved to a temporary variable. case sel @ Sel(prefix, nme) => subTerm(prefix): p => - conclude(Select(p, nme)(sel.sym, N).withLocOf(sel)) + conclude(Select(p, nme)(sel.sym.flatMap(_.asDefnSym_TODO)).withLocOf(sel)) case Resolved(sel @ Sel(prefix, nme), sym) => subTerm(prefix): p => - conclude(Select(p, nme)(sel.sym, S(sym)).withLocOf(sel)) + // conclude(Select(p, nme)(sel.sym, S(sym)).withLocOf(sel)) + // TODO @Harry: Check this logic. + conclude(Select(p, nme)(S(sym)).withLocOf(sel)) case sel @ SelProj(prefix, _, nme) => subTerm(prefix): p => - conclude(Select(p, nme)(sel.sym, N).withLocOf(sel)) + conclude(Select(p, nme)(sel.sym.flatMap(_.asDefnSym_TODO)).withLocOf(sel)) case Resolved(sel @ SelProj(prefix, _, nme), sym) => subTerm(prefix): p => - conclude(Select(p, nme)(sel.sym, S(sym)).withLocOf(sel)) + // conclude(Select(p, nme)(sel.sym, S(sym)).withLocOf(sel)) + // TODO @Harry: Check this logic. + conclude(Select(p, nme)(S(sym)).withLocOf(sel)) case _ => subTerm(f)(conclude) case h @ Handle(lhs, rhs, as, cls, defs, bod) => if !lowerHandlers then @@ -630,7 +634,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): Case.Cls(ctorSym, st) -> go(tail, topLevel = false) case (param, arg) :: args => val (cse, blk) = mkArgs(args) - (cse, Assign(arg, Select(sr, new Tree.Ident(param.id.name).withLocOf(arg))(S(param), N), blk)) + (cse, Assign(arg, Select(sr, new Tree.Ident(param.id.name).withLocOf(arg))(S(param)), blk)) mkMatch(mkArgs(clsParams.iterator.zip(args).toList)) ctor.symbol.flatMap(_.asClsOrMod) match case S(cls: ClassSymbol) if ctx.builtins.virtualClasses contains cls => @@ -657,7 +661,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): case ((fieldName, fieldSymbol), blk) => mkMatch( Case.Field(fieldName, safe = true), // we know we have an object, no need to check again - Assign(fieldSymbol, Select(sr, fieldName)(N, N), blk) + Assign(fieldSymbol, Select(sr, fieldName)(N), blk) ) ) case Split.Else(els) => @@ -669,7 +673,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): else End() ) case Split.End => - Throw(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Error"))(N, N), + Throw(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Error"))(N), Value.Lit(syntax.Tree.StrLit("match error")).asArg :: Nil)) // TODO add failed-match scrutinee info val normalize = ucs.Normalization() @@ -697,11 +701,13 @@ class Lowering()(using Config, TL, Raise, State, Ctx): case sel @ SynthSel(prefix, nme) => // * Not using `setupSelection` as these selections are not meant to be sanity-checked subTerm(prefix): p => - k(Select(p, nme)(sel.sym, N)) + k(Select(p, nme)(sel.sym.flatMap(_.asDefnSym_TODO))) case Resolved(sel @ SynthSel(prefix, nme), sym) => // * Not using `setupSelection` as these selections are not meant to be sanity-checked subTerm(prefix): p => - k(Select(p, nme)(sel.sym, S(sym))) + // k(Select(p, nme)(sel.sym, S(sym))) + // TODO @Harry: Check this logic. + k(Select(p, nme)(S(sym))) case DynSel(prefix, fld, ai) => subTerm(prefix): p => @@ -755,17 +761,17 @@ class Lowering()(using Config, TL, Raise, State, Ctx): case sp @ SelProj(prefix, _, proj) => setupSelection(prefix, proj, sp.sym, N)(k) case Region(reg, body) => - Assign(reg, Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Region"))(N, N), Nil), + Assign(reg, Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Region"))(N), Nil), term_nonTail(body)(k)) case RegRef(reg, value) => plainArgs(reg :: value :: Nil): args => - k(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Ref"))(N, N), args)) + k(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Ref"))(N), args)) case Drop(ref) => subTerm(ref): _ => k(unit) case Deref(ref) => subTerm(ref): r => - k(Select(r, Tree.Ident("value"))(N, N)) + k(Select(r, Tree.Ident("value"))(N)) case SetRef(lhs, rhs) => subTerm(lhs): ref => subTerm_nonTail(rhs): value => @@ -1079,7 +1085,8 @@ class Lowering()(using Config, TL, Raise, State, Ctx): def setupSelection(prefix: Term, nme: Tree.Ident, sym: Opt[FieldSymbol], disamb: Opt[DefinitionSymbol[?]])(k: Result => Block)(using Subst): Block = subTerm(prefix): p => val selRes = TempSymbol(N, "selRes") // TODO @LP: why is it here? - k(Select(p, nme)(sym, disamb)) + // k(Select(p, nme)(sym, disamb)) + k(Select(p, nme)(disamb.orElse(sym.flatMap(_.asDefnSym_TODO)))) final def setupFunctionOrByNameDef(paramLists: List[ParamList], bodyTerm: Term, name: Option[Str]) (using Subst): (List[ParamList], Block) = @@ -1111,15 +1118,15 @@ trait LoweringSelSanityChecks(using Config, TL, Raise, State) // * We are careful to access `x.f` before `x.f$__checkNotMethod` in case `x` is, eg, `undefined` and // * the access should throw an error like `TypeError: Cannot read property 'f' of undefined`. val b0 = blockBuilder - .assign(selRes, Select(p, nme)(sym, disamb)) + .assign(selRes, Select(p, nme)(disamb.orElse(sym.flatMap(_.asDefnSym_TODO)))) (if sym.isDefined then // * If the symbol is known, the elaborator will have already checked the access [invariant:1] b0 else b0 - .assign(TempSymbol(N, "discarded"), Select(p, Tree.Ident(nme.name+"$__checkNotMethod"))(N, N))) + .assign(TempSymbol(N, "discarded"), Select(p, Tree.Ident(nme.name+"$__checkNotMethod"))(N))) .ifthen(selRes.asPath, Case.Lit(syntax.Tree.UnitLit(false)), - Throw(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Error"))(N, N), + Throw(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Error"))(N), Value.Lit(syntax.Tree.StrLit(s"Access to required field '${nme.name}' yielded 'undefined'")).asArg :: Nil)) ) .rest(k(selRes.asPath)) @@ -1131,7 +1138,7 @@ trait LoweringTraceLog(instrument: Bool)(using TL, Raise, State) private def selFromGlobalThis(path: Str*): Path = path.foldLeft[Path](Value.Ref(State.globalThisSymbol)): - (qual, name) => Select(qual, Tree.Ident(name))(N, N) + (qual, name) => Select(qual, Tree.Ident(name))(N) private def assignStmts(stmts: (Local, Result)*)(rest: Block) = stmts.foldRight(rest): diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala index ae6ff19770..aadcc2a7aa 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala @@ -13,7 +13,7 @@ class StackSafeTransform(depthLimit: Int, paths: HandlerPaths, doUnwindMap: Map[ private val STACK_DEPTH_IDENT: Tree.Ident = Tree.Ident("stackDepth") val doUnwindFns = doUnwindMap.values.collect: - case s: Select if s.symbol.isDefined => s.symbol.get + case s: Select if s.symbol_SelectSymbol.isDefined => s.symbol_SelectSymbol.get case Value.Ref(sym, _) => sym .toSet diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala index 01c32d47d9..9e76fa2f1b 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala @@ -154,10 +154,10 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: val (params, bodyDoc) = setupFunction(none, ps, bod) doc"($params) => ${ braced(bodyDoc) }" case s @ Select(qual, id) => - val dotClass = s.symbol match - case S(bms: BlockMemberSymbol) if { - bms.hasLiftedClass && - s.disamb.flatMap(d => d.asMod orElse d.asCls).exists(_ isnt ctx.builtins.Array) + val dotClass = s.symbol_SelectSymbol match + case S(ds) if { + (ds.hasLiftedClass) && + (ds.asMod orElse ds.asCls).exists(_ isnt ctx.builtins.Array) } => doc".class" case _ => doc"" val name = id.name diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala index 9f501c7b77..6fe7821058 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala @@ -297,7 +297,7 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case Value.Lit(lit) => k(Expr.Literal(lit)) - private def getClassOfField(p: FieldSymbol)(using ctx: Ctx)(using Raise, Scope): Local = + private def getClassOfField(p: DefinitionSymbol[?])(using ctx: Ctx)(using Raise, Scope): Local = trace[Local](s"bClassOfField { $p } begin", x => s"bClassOfField end: $x"): p match case ts: TermSymbol => ts.owner.get @@ -325,7 +325,7 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case s @ Select(Value.Ref(sym, _), Tree.Ident("Unit")) if sym is ctx.builtinSym.runtimeSym.get => bPath(Value.Lit(Tree.UnitLit(false)))(k) case s @ Select(Value.Ref(cls: ClassSymbol, _), name) if ctx.method_class.contains(cls) => - s.symbol match + s.symbol_SelectSymbol match case None => ctx.flow_ctx.get(p) match case Some(cls) => @@ -337,8 +337,8 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case s @ DynSelect(qual, fld, arrayIdx) => bErrStop(msg"Unsupported dynamic selection") case s @ Select(qual, name) => - log(s"bPath Select: $qual.$name with ${s.symbol}") - s.symbol match + log(s"bPath Select: $qual.$name with ${s.symbol_SelectSymbol}") + s.symbol_SelectSymbol match case None => ctx.flow_ctx.get(qual) match case Some(cls) => @@ -356,7 +356,7 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): bPath(qual): case q: Expr.Ref => val v: Local = newTemp - val cls = getClassOfField(s.symbol.get) + val cls = getClassOfField(s.symbol_SelectSymbol.get) val field = name.name Node.LetExpr(v, Expr.Select(q.sym, cls, field), k(v |> sr)) case q: Expr.Literal => @@ -408,14 +408,14 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case args: Ls[TrivialExpr] => val v: Local = newTemp Node.LetCall(Ls(v), builtin, Expr.Literal(Tree.StrLit(mathPrimitive)) :: args, k(v |> sr)) - case Call(s @ Select(r @ Value.Ref(sym, _), Tree.Ident(fld)), args) if s.symbol.isDefined => + case Call(s @ Select(r @ Value.Ref(sym, _), Tree.Ident(fld)), args) if s.symbol_SelectSymbol.isDefined => bPath(r): case r => bArgs(args): case args: Ls[TrivialExpr] => val v: Local = newTemp - log(s"Method Call Select: $r.$fld with ${s.symbol}") - Node.LetMethodCall(Ls(v), getClassOfField(s.symbol.get), s.symbol.get, r :: args, k(v |> sr)) + log(s"Method Call Select: $r.$fld with ${s.symbol_SelectSymbol}") + Node.LetMethodCall(Ls(v), getClassOfField(s.symbol_SelectSymbol.get), s.symbol_SelectSymbol.get, r :: args, k(v |> sr)) case Call(_, _) => bErrStop(msg"Unsupported kind of Call ${r.toString()}") case Instantiate( false, diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/Wasm.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/Wasm.scala index c94100de54..cad44a8592 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/Wasm.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/Wasm.scala @@ -5,7 +5,7 @@ package text import mlscript.utils.*, shorthands.* import document.* -import semantics.FieldSymbol +import semantics.DefinitionSymbol import scala.collection.Map @@ -124,7 +124,7 @@ case class Field( })" /** A type representing a structure type. */ -case class StructType(fields: Map[FieldSymbol, NumIdx -> Field]) extends ToWat: +case class StructType(fields: Map[DefinitionSymbol[?], NumIdx -> Field]) extends ToWat: def fieldSeq: Seq[Field] = fields.values.toSeq.sortBy(_._1.index).map(_._2) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala index 3e06822220..af61c37c65 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala @@ -115,7 +115,7 @@ class WatBuilder(using TraceLogger, State) extends CodeBuilder: ) case r => result(r) - def fieldSelect(thisSym: BlockMemberSymbol, sym: FieldSymbol)(using Ctx, Raise): FieldIdx = + def fieldSelect(thisSym: BlockMemberSymbol, sym: DefinitionSymbol[?])(using Ctx, Raise): FieldIdx = val structInfo = ctx.getTypeInfo_!(thisSym) val symToField = structInfo.compType match case ty: StructType => ty.fields @@ -231,7 +231,7 @@ class WatBuilder(using TraceLogger, State) extends CodeBuilder: case sel @ Select(qual, id) => val qualRes = result(qual) - val selSym = sel.symbol getOrElse: + val selSym = sel.symbol_SelectSymbol getOrElse: lastWords(s"Symbol for Select(...) expression must be resolved") val selTrmSym = selSym match case termSym: TermSymbol => termSym @@ -260,7 +260,7 @@ class WatBuilder(using TraceLogger, State) extends CodeBuilder: ), extraInfo = S(s"Block IR of `cls` expression: ${cls.toString}") ) - val ctorClsSym = ctorClsPath.symbol match + val ctorClsSym = ctorClsPath.symbol_SelectSymbol match case S(sym) => sym case N => return errExpr( Ls( diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 76a57365c7..1655469034 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -14,6 +14,8 @@ import typing.Type import Message.MessageContext import scala.annotation.tailrec +import hkmc2.semantics.ucs.FlatPattern +import hkmc2.syntax.Keyword.__ object Resolver: diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 4114b03f52..71bff006be 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -116,6 +116,10 @@ abstract class Symbol(using State) extends Located: asAls orElse asPat orElse asMod + + def asDefnSym_TODO: Opt[DefinitionSymbol[?]] = this match + case defn: DefinitionSymbol[?] => S(defn) + case _ => N override def equals(x: Any): Bool = x match case that: Symbol => uid === that.uid @@ -323,6 +327,10 @@ sealed trait DefinitionSymbol[Defn <: Definition] extends Symbol: def subst(using sub: SymbolSubst): DefinitionSymbol[Defn] def asMemSym: MemberSymbol[Defn] = this + + def hasLiftedClass: Bool = + this.asBlkMember.exists(_.hasLiftedClass) || + this.asCls.flatMap(_.defn).exists(_.paramsOpt.isDefined) /** This is the symbol associated to specific definitions. * One overloaded `BlockMemberSymbol` may correspond to multiple `InnerSymbol`s diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index b67f9c4caf..88d3acbfe3 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -250,6 +250,7 @@ enum Term extends Statement: * elaboration. */ lazy val symbol: Opt[Symbol] = this match + case res: Resolved => S(res.sym) case Ref(sym) => S(sym) case sel: Sel => sel.sym case sel: SynthSel => sel.sym diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala index 3547b3fc7b..26b01d8cbf 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala @@ -42,17 +42,17 @@ class Normalization(using tl: TL)(using Raise, Ctx, State) extends TermSynthesiz extension (lhs: FlatPattern.ClassLike) /** Generate a term that really resolves to the class at runtime. */ def selectClass: FlatPattern.ClassLike = - val constructor = lhs.constructor.symbol match - case S(cls: ClassSymbol) => lhs.constructor - case S(mem: BlockMemberSymbol) => - // If the class is declaration-only, we do not need to select the - // class. - if !mem.hasLiftedClass || mem.defn.exists(_.hasDeclareModifier.isDefined) then - lhs.constructor - else - Term.SynthSel(lhs.constructor, Tree.Ident("class"))(mem.clsTree.orElse(mem.modOrObjTree).map(_.symbol), N).resolve - case _ => lhs.constructor - lhs.copy(constructor)(lhs.tree, lhs.output) + // val constructor = lhs.constructor.symbol match + // case S(cls: ClassSymbol) => lhs.constructor + // case S(mem: BlockMemberSymbol) => + // // If the class is declaration-only, we do not need to select the + // // class. + // if !mem.hasLiftedClass || mem.defn.exists(_.hasDeclareModifier.isDefined) then + // lhs.constructor + // else + // Term.SynthSel(lhs.constructor, Tree.Ident("class"))(mem.clsTree.orElse(mem.modOrObjTree).map(_.symbol), N).resolve + // case _ => lhs.constructor + lhs.copy(lhs.constructor)(lhs.tree, lhs.output) extension (lhs: FlatPattern) /** Checks if two patterns are the same. */ diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala index c2d013cda5..eefa942a15 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala @@ -38,19 +38,23 @@ trait TermSynthesizer(using Ctx, State): /** Make a term that looks like `runtime.MatchResult` with its symbol. */ protected lazy val matchResultClass = - sel(runtimeRef, "MatchResult", State.matchResultClsSymbol) + Term.Resolved + (sel(runtimeRef, "MatchResult", State.matchResultClsSymbol), State.matchResultClsSymbol) + (N) /** Make a pattern that looks like `runtime.MatchResult.class`. */ protected def matchResultPattern(parameters: Opt[Ls[BlockLocalSymbol]]): FlatPattern.ClassLike = - FlatPattern.ClassLike(sel(matchResultClass, "class", State.matchResultClsSymbol), parameters) + FlatPattern.ClassLike(matchResultClass, parameters) /** Make a term that looks like `runtime.MatchFailure` with its symbol. */ protected lazy val matchFailureClass = - sel(runtimeRef, "MatchFailure", State.matchFailureClsSymbol) + Term.Resolved + (sel(runtimeRef, "MatchFailure", State.matchFailureClsSymbol), State.matchFailureClsSymbol) + (N) /** Make a pattern that looks like `runtime.MatchFailure.class`. */ protected def matchFailurePattern(parameters: Opt[Ls[BlockLocalSymbol]]): FlatPattern.ClassLike = - FlatPattern.ClassLike(sel(matchFailureClass, "class", State.matchFailureClsSymbol), parameters) + FlatPattern.ClassLike(matchFailureClass, parameters) protected lazy val tupleSlice = sel(sel(runtimeRef, "Tuple"), "slice") protected lazy val tupleLazySlice = sel(sel(runtimeRef, "Tuple"), "lazySlice") From 019c3aeb03cde1824573ce9c45b1757be67dacb4 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Thu, 30 Oct 2025 14:56:54 +0800 Subject: [PATCH 07/55] wrapup 1 --- .../scala/hkmc2/codegen/js/JSBuilder.scala | 7 +- .../scala/hkmc2/semantics/Elaborator.scala | 40 ++++- .../main/scala/hkmc2/semantics/Pattern.scala | 14 ++ .../main/scala/hkmc2/semantics/Resolver.scala | 52 +++++- .../main/scala/hkmc2/semantics/Symbol.scala | 7 +- .../src/main/scala/hkmc2/semantics/Term.scala | 1 + .../hkmc2/semantics/ucs/TermSynthesizer.scala | 10 +- .../scala/hkmc2/semantics/ups/Compiler.scala | 11 +- .../src/test/mlscript/basics/MutRcd.mls | 2 +- .../src/test/mlscript/codegen/BasicTerms.mls | 2 +- .../src/test/mlscript/codegen/CaseOfCase.mls | 4 +- .../test/mlscript/codegen/CaseShorthand.mls | 2 +- .../test/mlscript/codegen/ClassMatching.mls | 6 +- .../test/mlscript/codegen/FieldSymbols.mls | 8 +- .../test/mlscript/codegen/MergeMatchArms.mls | 58 +++---- .../src/test/mlscript/codegen/OptMatch.mls | 4 +- .../src/test/mlscript/handlers/Effects.mls | 74 ++++++++- .../mlscript/handlers/EffectsInClasses.mls | 14 +- .../mlscript/handlers/EffectsInMethods.mls | 106 +++++++++++- .../mlscript/handlers/HandlersInMethods.mls | 63 ++++++- .../test/mlscript/handlers/UserThreads.mls | 12 ++ .../mlscript/handlers/UserThreadsSafe.mls | 108 ++++++++++-- .../src/test/mlscript/lifter/ClassInFun.mls | 73 +++++++-- .../src/test/mlscript/lifter/DefnsInClass.mls | 21 ++- .../test/mlscript/lifter/ModulesObjects.mls | 48 +++++- .../shared/src/test/mlscript/llir/Classes.mls | 26 +-- hkmc2/shared/src/test/mlscript/llir/Lazy.mls | 72 +------- .../src/test/mlscript/llir/LazyCycle.mls | 154 +----------------- .../shared/src/test/mlscript/llir/Method.mls | 17 +- .../src/test/mlscript/llir/nofib/scc.mls | 2 +- hkmc2/shared/src/test/mlscript/nofib/scc.mls | 3 +- .../mlscript/ucs/hygiene/HygienicBindings.mls | 16 +- .../ucs/normalization/OverlapOfPrimitives.mls | 2 +- .../ucs/patterns/ConjunctionPattern.mls | 2 +- .../mlscript/ups/parametric/EtaConversion.mls | 8 +- .../shared/src/test/mlscript/wasm/Basics.mls | 16 +- 36 files changed, 673 insertions(+), 392 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala index 9e76fa2f1b..962ac76f98 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala @@ -113,9 +113,9 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: else errExpr(msg"Illegal reference to builtin symbol '${l.nme}'") case Value.Ref(l, disamb) => l match case l: BlockMemberSymbol if { - // TODO @Harry: refactor(ize) duplicated logic + // println(disamb.flatMap(d => d.asModOrObj orElse d.asCls)) l.hasLiftedClass && - disamb.flatMap(d => d.asMod orElse d.asCls).exists(_ isnt ctx.builtins.Array) + disamb.flatMap(s => s.asCls orElse s.asMod).exists(_ isnt ctx.builtins.Array) } => doc"${getVar(l, l.toLoc)}.class" case _ => @@ -157,7 +157,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: val dotClass = s.symbol_SelectSymbol match case S(ds) if { (ds.hasLiftedClass) && - (ds.asMod orElse ds.asCls).exists(_ isnt ctx.builtins.Array) + (ds.asModOrObj orElse ds.asCls).exists(_ isnt ctx.builtins.Array) } => doc".class" case _ => doc"" val name = id.name @@ -469,6 +469,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: case Elaborator.ctx.builtins.BigInt => doc"typeof $sd === 'bigint'" case Elaborator.ctx.builtins.Symbol.module => doc"typeof $sd === 'symbol'" case Elaborator.ctx.builtins.TypedArray => doc"globalThis.ArrayBuffer.isView($sd) && !($sd instanceof globalThis.DataView)" + case _: ModuleOrObjectSymbol => doc"$sd === ${result(pth)}" case _ => doc"$sd instanceof ${result(pth)}" case Case.Tup(len, inf) => doc"$runtimeVar.Tuple.isArrayLike($sd) && $sd.length ${if inf then ">=" else "==="} ${len}" case Case.Field(name = n, safe = false) => diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index 5d032c43b3..dccb2391e6 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -243,10 +243,11 @@ object Elaborator: val nonLocalRet = val id = new Ident("ret") BlockMemberSymbol(id.name, Nil, true) - val matchResultClsSymbol = + val (matchResultClsSymbol, matchResultTrmSymbol) = val id = new Ident("MatchResult") val td = TypeDef(syntax.Cls, App(id, Tup(Ident("output") :: Ident("bindings") :: Nil)), N) val cs = ClassSymbol(td, id) + val ts = TermSymbol(syntax.Fun, N, id) val flag = FldFlags.empty.copy(isVal = true) val ps = PlainParamList( Param(flag, VarSymbol(Ident("output")), N, Modulefulness(N)(false)) :: @@ -254,16 +255,47 @@ object Elaborator: Nil) cs.defn = S(ClassDef.Parameterized(N, syntax.Cls, cs, BlockMemberSymbol(cs.name, Nil), Nil, ps, Nil, N, ObjBody(Blk(Nil, Term.Lit(UnitLit(false)))), N, Nil)) - cs - val matchFailureClsSymbol = + ts.defn = S: + TermDefinition( + syntax.Fun, + BlockMemberSymbol(id.name, td :: Nil), + ts, + ps :: Nil, + N, + N, + N, + FlowSymbol("MatchResult-constructor"), + TermDefFlags.empty, + Modulefulness(N)(false), + Nil, + N, + ) + cs -> ts + val (matchFailureClsSymbol, matchFailureTrmSymbol) = val id = new Ident("MatchFailure") val td = DummyTypeDef(syntax.Cls) val cs = ClassSymbol(td, id) + val ts = TermSymbol(syntax.Fun, N, id) val flag = FldFlags.empty.copy(isVal = true) val ps = PlainParamList(Param(flag, VarSymbol(Ident("errors")), N, Modulefulness(N)(false)) :: Nil) cs.defn = S(ClassDef.Parameterized(N, syntax.Cls, cs, BlockMemberSymbol(cs.name, td :: Nil), Nil, ps, Nil, N, ObjBody(Blk(Nil, Term.Lit(UnitLit(false)))), N, Nil)) - cs + ts.defn = S: + TermDefinition( + syntax.Fun, + BlockMemberSymbol(id.name, td :: Nil), + ts, + ps :: Nil, + N, + N, + N, + FlowSymbol("MatchFailure-constructor"), + TermDefFlags.empty, + Modulefulness(N)(false), + Nil, + N, + ) + cs -> ts val builtinOpsMap = val baseBuiltins = builtins.map: op => op -> BuiltinSymbol(op, diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Pattern.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Pattern.scala index 1c40d35d57..e18fbe84b5 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Pattern.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Pattern.scala @@ -265,6 +265,20 @@ enum Pattern extends AutoLocated: case Alias(pattern, alias) => pattern :: alias :: Nil case Transform(pattern, transform) => pattern :: transform :: Nil + def subPatterns: Ls[Pattern] = this match + case Constructor(_, patternArguments, arguments) => + patternArguments ::: arguments.fold(Nil)(_.toList) + case Composition(_, left, right) => left :: right :: Nil + case Negation(pattern) => pattern :: Nil + case _: (Wildcard | Literal | Range) => Nil + case Concatenation(left, right) => left :: right :: Nil + case Tuple(leading, spread, trailing) => + leading ::: spread.toList ::: trailing + case Record(fields) => fields.map(_._2) + case Chain(first, second) => first :: second :: Nil + case Alias(pattern, _) => pattern :: Nil + case Transform(pattern, _) => pattern :: Nil + def subTerms: Ls[Term] = this match case Constructor(target, patternArguments, arguments) => target :: patternArguments.flatMap(_.subTerms) ::: arguments.fold(Nil)(_.flatMap(_.subTerms)) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 1655469034..3ddc9b704f 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -132,6 +132,7 @@ object Resolver: case NonModule(reason: Opt[Message]) case Class(reason: Opt[Message]) case Selectable(reason: Opt[Message]) + case PatternConstructor(reason: Opt[Message]) case Any def message: Ls[Message -> Opt[Loc]] = this match @@ -296,7 +297,13 @@ class Resolver(tl: TraceLogger) def split(s: Split): Unit = s match case Split.Cons(head, tail) => traverse(head.scrutinee, expect = NonModule(N)) - head.pattern.subTerms.foreach(traverse(_, expect = NonModule(N))) + head.pattern match + case FlatPattern.ClassLike(constructor = t) => + head.pattern.subTerms.foreach: + case `t` => traverse(t, expect = PatternConstructor(N)) + case other => traverse(other, expect = NonModule(N)) + case _ => + head.pattern.subTerms.foreach(traverse(_, expect = NonModule(N))) split(head.continuation) split(tail) case Split.Let(sym, term, tail) => @@ -417,6 +424,35 @@ class Resolver(tl: TraceLogger) traverseBlock(cld.body.blk)(using withCtxParams) + def traversePattern(p: Pattern): Unit = p match + case _: (Pattern.Wildcard | Pattern.Literal | Pattern.Range) => () + case Pattern.Constructor(target, patternArguments, arguments) => + traverse(target, expect = PatternConstructor(N)) + patternArguments.foreach(traversePattern(_)) + arguments.foreach(_.foreach(traversePattern(_))) + case Pattern.Composition(_, left, right) => + traversePattern(left) + traversePattern(right) + case Pattern.Negation(pattern) => + traversePattern(pattern) + case Pattern.Concatenation(left, right) => + traversePattern(left) + traversePattern(right) + case Pattern.Tuple(leading, spread, trailing) => + leading.foreach(traversePattern(_)) + spread.foreach(traversePattern(_)) + trailing.foreach(traversePattern(_)) + case Pattern.Record(fields) => + fields.map((id, p) => traversePattern(p)) + case Pattern.Chain(first, second) => + traversePattern(first) + traversePattern(second) + case Pattern.Alias(pattern, _) => + traversePattern(pattern) + case Pattern.Transform(pattern, transform) => + traversePattern(pattern) + traverse(transform, expect = NonModule(N)) + defn match // Case: instance definition. Add the instance to the context. @@ -442,10 +478,10 @@ class Resolver(tl: TraceLogger) case defn: ClassLikeDef => log(s"Resolving ${defn.kind.desc} definition $defn") - // For pattern definitions, we need to traverse through the pattern body. defn match case defn: PatternDef => - defn.pattern.subTerms.foreach(traverse(_, expect = NonModule(N))) + // For pattern definitions, we need to traverse through the pattern body. + traversePattern(defn.pattern) case _: ClassLikeDef => () traverseClassLikeDef(defn) @@ -748,6 +784,14 @@ class Resolver(tl: TraceLogger) bms.asTpe case _: (Any.type | NonModule) => bms.asPrincipal + case _: PatternConstructor => + bms.asCls orElse + bms.asObj orElse + bms.asAls orElse + bms.asPat orElse + bms.asMod orElse + bms.asTrm + /** @@ -809,7 +853,7 @@ class Resolver(tl: TraceLogger) case S(ds) => t.expand(S(Term.Resolved(t.withSym(bms), ds)(N))) case N => - log(s"! Unable to disambiguate ${bms}") + log(s"Unable to disambiguate ${bms}") t.expand(S(t.withSym(bms))) log(s"Resolved symbol for ${t}: ${bms}") case N => diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 71bff006be..615968489a 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -238,8 +238,13 @@ class BlockMemberSymbol(val nme: Str, val trees: Ls[TypeOrTermDef], val nameIsMe def isParameterizedMethod: Bool = trmTree.exists(_.isParameterizedMethod) + /** + * Indicate if this BMS stores a `.class` for its overload in its code generation. + * + * During lowering, + */ lazy val hasLiftedClass: Bool = - objTree.isDefined || trmTree.isDefined || clsTree.exists(_.paramLists.nonEmpty) + trmTree.isDefined || clsTree.exists(_.paramLists.nonEmpty) override def toString: Str = s"member:$nme${State.dbgUid(uid)}" diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index 88d3acbfe3..e2cea3d874 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -406,6 +406,7 @@ sealed trait Statement extends AutoLocated, ProductWithExtraInfo: case Annotated(annotation, target) => "annotation" case Ret(res) => "return" case Try(body, finallyDo) => "try expression" + case Resolved(t, sym) => t.describe case s => TODO(s) this match case self: Resolvable => self.resolvedTyp match diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala index eefa942a15..41c2adbd87 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala @@ -26,6 +26,8 @@ trait TermSynthesizer(using Ctx, State): protected final def app(l: Term, r: Term, label: Str): Term.App = app(l, r, FlowSymbol(label)) protected final def app(l: Term, r: Term, s: FlowSymbol): Term.App = (Term.App(l, r)(App(Dummy, Dummy), N, s): Term.App).resolve + protected final def `new`(cls: Term, args: Ls[Term], label: Str): Term.New = + Term.New(cls, args, N) protected final def rcd(fields: RcdField*): Term.Rcd = Term.Rcd(false, fields.toList) protected final def splitLet(sym: BlockLocalSymbol, term: Term)(inner: Split): Split = @@ -101,16 +103,16 @@ trait TermSynthesizer(using Ctx, State): Split.Let(s, cond, Branch(s.safeRef, inner) ~: Split.End) protected final def makeMatchResult(output: Term) = - app(matchResultClass, tup(fld(output), fld(rcd())), "result of `MatchResult`") + `new`(matchResultClass, tup(fld(output), fld(rcd())) :: Nil, "result of `MatchResult`") protected final def makeMatchResult(output: Term, bindings: Term) = - app(matchResultClass, tup(fld(output), fld(bindings)), "result of `MatchResult`") + `new`(matchResultClass, tup(fld(output), fld(bindings)) :: Nil, "result of `MatchResult`") protected final def makeMatchResult(output: Term, fields: Ls[RcdField | RcdSpread]) = - app(matchResultClass, tup(fld(output), fld(Term.Rcd(false, fields))), "result of `MatchResult`") + `new`(matchResultClass, tup(fld(output), fld(Term.Rcd(false, fields))) :: Nil, "result of `MatchResult`") protected final def makeMatchFailure(errors: Term = Term.Lit(UnitLit(true))) = - app(matchFailureClass, tup(fld(errors)), "result of `MatchFailure`") + `new`(matchFailureClass, tup(fld(errors)) :: Nil, "result of `MatchFailure`") /** Make a `Branch` that calls `Pattern` symbols' `unapply` functions. */ def makeLocalPatternBranch( diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Compiler.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Compiler.scala index 8e6eb3c525..96b3661996 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Compiler.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Compiler.scala @@ -408,14 +408,14 @@ object Compiler: def findSymbol(elem: Ctx.Elem): Opt[Term] = elem.symbol.flatMap(_.asClsLike).collectFirst: // Check the element's symbol. - case `symbol` => S(elem.ref(new Ident(symbol.nme)).withLoc(loc)) + case `symbol` => S(Term.Resolved(elem.ref(new Ident(symbol.nme)).withLoc(loc), symbol)(N)) // Look up the symbol in module members. case module: ModuleOrObjectSymbol => val moduleRef = module.defn.get.bsym.ref() module.tree.definedSymbols.iterator.map(_.mapSecond(_.asClsLike)).collectFirst: case (key, S(`symbol`)) => val memberSymbol = symbol.defn.get.bsym - SynthSel(moduleRef, Ident(key))(S(memberSymbol), N) + Term.Resolved(SynthSel(moduleRef, Ident(key))(S(memberSymbol), N), symbol)(N) .flatten @tailrec def go(ctx: Ctx): Opt[Term] = ctx.env.values.iterator.map(findSymbol).firstSome match @@ -423,12 +423,7 @@ object Compiler: case N => ctx.parent match case N => N case S(parent) => go(parent) - go(ctx).map: term => - // If the `symbol` is a virtual class, then do not select `class`. - symbol match - case s: ClassSymbol if !(ctx.builtins.virtualClasses contains s) => - SynthSel(term, Ident("class"))(S(s), N).resolve - case _: (ClassSymbol | ModuleOrObjectSymbol | PatternSymbol) => term + go(ctx) import Pattern.* diff --git a/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls b/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls index 9a38bf0244..95d0d1ecc3 100644 --- a/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls +++ b/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls @@ -104,7 +104,7 @@ Object.freeze //│ imports = Nil //│ main = Assign: //│ lhs = $selRes -//│ rhs = Select{sym=member:Object}: +//│ rhs = Select: //│ qual = Ref: //│ l = globalThis:globalThis //│ disamb = N diff --git a/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls b/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls index ebe71999cc..a2ed080be2 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls @@ -49,7 +49,7 @@ print("Hi") //│ main = Assign: //│ lhs = $tmp //│ rhs = Call: -//│ fun = Select{sym=member:print,disamb=term:module:Predef.print}: +//│ fun = Select{sym=term:module:Predef.print}: //│ qual = Ref{disamb=module:Predef}: //│ l = member:Predef //│ disamb = S of module:Predef diff --git a/hkmc2/shared/src/test/mlscript/codegen/CaseOfCase.mls b/hkmc2/shared/src/test/mlscript/codegen/CaseOfCase.mls index d8a18fff1b..c6afcea9e6 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/CaseOfCase.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/CaseOfCase.mls @@ -23,7 +23,7 @@ fun test(x) = //│ v = param0; //│ tmp = v + 1; //│ tmp1 = Some1(tmp); -//│ } else if (x instanceof None1.class) { +//│ } else if (x === None1) { //│ tmp1 = None1; //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) @@ -33,7 +33,7 @@ fun test(x) = //│ param01 = scrut.value; //│ v1 = param01; //│ return Predef.print(v1) -//│ } else if (scrut instanceof None1.class) { +//│ } else if (scrut === None1) { //│ return Predef.print("none") //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ }; diff --git a/hkmc2/shared/src/test/mlscript/codegen/CaseShorthand.mls b/hkmc2/shared/src/test/mlscript/codegen/CaseShorthand.mls index 510dbe3eeb..c7dd5566e0 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/CaseShorthand.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/CaseShorthand.mls @@ -83,7 +83,7 @@ val isDefined = case //│ lambda12 = (undefined, function (caseScrut) { //│ if (caseScrut instanceof Some1.class) { //│ return true -//│ } else if (caseScrut instanceof None1.class) { +//│ } else if (caseScrut === None1) { //│ return false //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) diff --git a/hkmc2/shared/src/test/mlscript/codegen/ClassMatching.mls b/hkmc2/shared/src/test/mlscript/codegen/ClassMatching.mls index 0fe73cf074..1b2bf67697 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/ClassMatching.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/ClassMatching.mls @@ -130,7 +130,7 @@ fun f(x) = if x is //│ } else { //│ return Predef.print("oops") //│ } -//│ } else if (x3 instanceof None1.class) { return "ok" } else { return Predef.print("oops") } +//│ } else if (x3 === None1) { return "ok" } else { return Predef.print("oops") } //│ }; f(Some(0)) @@ -194,9 +194,7 @@ fun f(x) = print of if x is //│ } else { //│ tmp8 = "oops"; //│ } -//│ } else if (x3 instanceof None1.class) { -//│ tmp8 = "ok"; -//│ } else { tmp8 = "oops"; } +//│ } else if (x3 === None1) { tmp8 = "ok"; } else { tmp8 = "oops"; } //│ return Predef.print(tmp8) //│ }; diff --git a/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls b/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls index 75fc0f01e2..2736df02d3 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls @@ -111,11 +111,9 @@ case //│ Tuple2: //│ _1 = Cls: //│ cls = class:Foo -//│ path = Select{sym=class:Foo}: -//│ qual = Ref{disamb=term:class:Foo.Foo}: -//│ l = member:Foo -//│ disamb = S of term:class:Foo.Foo -//│ name = Ident of "class" +//│ path = Ref{disamb=class:Foo}: +//│ l = member:Foo +//│ disamb = S of class:Foo //│ _2 = Assign: //│ lhs = $param0 //│ rhs = Select{sym=term:class:Foo.x}: diff --git a/hkmc2/shared/src/test/mlscript/codegen/MergeMatchArms.mls b/hkmc2/shared/src/test/mlscript/codegen/MergeMatchArms.mls index bb1dc3e77b..40e6bda17b 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/MergeMatchArms.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/MergeMatchArms.mls @@ -19,13 +19,13 @@ if a is C then 3 D then 4 //│ JS (unsanitized): -//│ if (a instanceof A1.class) { +//│ if (a === A1) { //│ 1 -//│ } else if (a instanceof B1.class) { +//│ } else if (a === B1) { //│ 2 -//│ } else if (a instanceof C1.class) { +//│ } else if (a === C1) { //│ 3 -//│ } else if (a instanceof D1.class) { +//│ } else if (a === D1) { //│ 4 //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ = 1 @@ -40,11 +40,11 @@ if a is B then 2 C then 3 //│ JS (unsanitized): -//│ if (a instanceof A1.class) { +//│ if (a === A1) { //│ 1 -//│ } else if (a instanceof B1.class) { +//│ } else if (a === B1) { //│ 2 -//│ } else if (a instanceof C1.class) { +//│ } else if (a === C1) { //│ 3 //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ = 1 @@ -58,17 +58,17 @@ if a is B then 2 C then 3 //│ JS (unsanitized): -//│ if (a instanceof A1.class) { -//│ if (b instanceof A1.class) { +//│ if (a === A1) { +//│ if (b === A1) { //│ 1 -//│ } else if (b instanceof B1.class) { +//│ } else if (b === B1) { //│ 2 //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) //│ } -//│ } else if (a instanceof B1.class) { +//│ } else if (a === B1) { //│ 2 -//│ } else if (a instanceof C1.class) { +//│ } else if (a === C1) { //│ 3 //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ = 2 @@ -94,23 +94,23 @@ print(x) //│ JS (unsanitized): //│ let x, tmp, tmp1, tmp2, tmp3; //│ tmp = 3; -//│ if (a instanceof A1.class) { +//│ if (a === A1) { //│ tmp1 = 1; -//│ } else if (a instanceof B1.class) { +//│ } else if (a === B1) { //│ tmp1 = 2; -//│ } else if (a instanceof C1.class) { +//│ } else if (a === C1) { //│ tmp1 = 3; -//│ } else if (a instanceof D1.class) { -//│ if (a instanceof A1.class) { +//│ } else if (a === D1) { +//│ if (a === A1) { //│ tmp2 = 1 + tmp; -//│ } else if (a instanceof B1.class) { +//│ } else if (a === B1) { //│ tmp2 = 2 + tmp; //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) //│ } //│ tmp3 = tmp2; //│ tmp1 = Predef.print("done"); -//│ } else if (a instanceof E1.class) { +//│ } else if (a === E1) { //│ tmp3 = 5; //│ tmp1 = Predef.print("done"); //│ } else { @@ -132,9 +132,9 @@ if a is //│ JS (unsanitized): //│ let tmp4; //│ tmp4 = 2; -//│ if (a instanceof A1.class) { +//│ if (a === A1) { //│ 1 -//│ } else if (a instanceof B1.class) { +//│ } else if (a === B1) { //│ 2 + tmp4 //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ = 1 @@ -153,11 +153,11 @@ if a is B then 2 + tmp //│ JS (unsanitized): //│ let tmp5; -//│ if (a instanceof A1.class) { +//│ if (a === A1) { //│ 1 //│ } else { //│ tmp5 = printAndId(3); -//│ if (a instanceof B1.class) { +//│ if (a === B1) { //│ 2 + tmp5 //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ } @@ -176,13 +176,13 @@ if a is print(x) //│ JS (unsanitized): //│ let x1, tmp6; -//│ if (a instanceof A1.class) { +//│ if (a === A1) { //│ 1 -//│ } else if (a instanceof B1.class) { +//│ } else if (a === B1) { //│ tmp6 = 2; //│ x1 = tmp6; //│ Predef.print(x1) -//│ } else if (a instanceof C1.class) { +//│ } else if (a === C1) { //│ tmp6 = 3; //│ x1 = tmp6; //│ Predef.print(x1) @@ -205,12 +205,12 @@ if a is print(x + 2) //│ JS (unsanitized): //│ let x2, tmp7, tmp8, tmp9, tmp10, tmp11; -//│ if (a instanceof B1.class) { +//│ if (a === B1) { //│ 1 //│ } else { -//│ if (a instanceof A1.class) { +//│ if (a === A1) { //│ tmp7 = 2; -//│ } else if (a instanceof C1.class) { +//│ } else if (a === C1) { //│ tmp7 = 3; //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) diff --git a/hkmc2/shared/src/test/mlscript/codegen/OptMatch.mls b/hkmc2/shared/src/test/mlscript/codegen/OptMatch.mls index 3e710ba474..08e8143455 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/OptMatch.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/OptMatch.mls @@ -14,7 +14,7 @@ fun isDefined(x) = if x is //│ isDefined = function isDefined(x) { //│ if (x instanceof Some1.class) { //│ return true -//│ } else if (x instanceof None1.class) { +//│ } else if (x === None1) { //│ return false //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ }; @@ -37,7 +37,7 @@ val isDefined = case //│ if (caseScrut instanceof Some1.class) { //│ param0 = caseScrut.value; //│ return true -//│ } else if (caseScrut instanceof None1.class) { +//│ } else if (caseScrut === None1) { //│ return false //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) diff --git a/hkmc2/shared/src/test/mlscript/handlers/Effects.mls b/hkmc2/shared/src/test/mlscript/handlers/Effects.mls index 41f5579d45..9d4c1fbc08 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/Effects.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/Effects.mls @@ -230,11 +230,57 @@ module A with data class Effect(x) with fun test() = x fun perform(arg) +//│ FAILURE: Unexpected exception +//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) +//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) +//│ at: scala.collection.immutable.List.map(List.scala:247) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) +//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) +//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) +//│ at: hkmc2.codegen.HandlerLowering.firstPass(HandlerLowering.scala:536) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateBlock(HandlerLowering.scala:477) handle h = A.Effect(3) with fun perform()(k) = 0 h.perform() -//│ = 0 +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: lookup_! (Scope.scala:112) +//│ FAILURE INFO: Tuple2: +//│ _1 = Tuple2: +//│ _1 = member:A +//│ _2 = class hkmc2.semantics.BlockMemberSymbol +//│ _2 = Scope: +//│ parent = N +//│ curThis = S of S of globalThis:globalThis +//│ bindings = HashMap(class:Cont$func$lambda$ -> Cont$func$lambda$, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$6, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$3, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$3, $runtime -> runtime, class:Handler$h$ -> Handler$h$, $definitionMetadata -> definitionMetadata, $prettyPrint -> prettyPrint, $block$res -> block$res14, $Term -> Term, $tmp -> tmp11, class:Handler$h$ -> Handler$h$3, $block$res -> block$res2, $tmp -> tmp, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$, class:Cont$func$foo$ -> Cont$func$foo$1, member:handleBlock$ -> handleBlock$11, $block$res -> block$res5, $tmp -> tmp3, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$5, class:Handler$h$ -> Handler$h$12, member:handleBlock$ -> handleBlock$, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$4, member:handleBlock$ -> handleBlock$3, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$2, class:Handler$h$ -> Handler$h$11, $block$res -> block$res15, $tmp -> tmp12, $selRes -> selRes, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$2, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$10, $res -> res, class:Cont$func$bar$ -> Cont$func$bar$, member:handleBlock$ -> handleBlock$12, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$1, member:foo -> foo2, class:Handler$h$ -> Handler$h$2, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$11, class:Handler$h$ -> Handler$h$9, member:foo -> foo1, $block$res -> block$res4, $tmp -> tmp2, member:foo -> foo, $block$res -> block$res8, member:handleBlock$ -> handleBlock$2, member:bar -> bar, class:Cont$func$foobar$ -> Cont$func$foobar$, member:foobar -> foobar, member:foo -> foo3, class:Handler$h$ -> Handler$h$5, class:Handler$h$ -> Handler$h$8, $block$res -> block$res12, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, $tmp -> tmp9, member:handleBlock$ -> handleBlock$10, $block$res -> block$res7, class:Handler$h$ -> Handler$h$1, $block$res -> block$res11, $tmp -> tmp5, result -> result, $tmp -> tmp8, class:Handler$h$ -> Handler$h$6, class:Handler$h$ -> Handler$h$7, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$9, $block$res -> block$res, member:handleBlock$ -> handleBlock$8, $block$res -> block$res3, $tmp -> tmp1, class:Handler$h$ -> Handler$h$10, member:Predef -> Predef, class:Cont$func$foo$ -> Cont$func$foo$, class:Handler$h$ -> Handler$h$4, member:Effect -> Effect1, class:Effect -> Effect, member:handleBlock$ -> handleBlock$1, $block$res -> block$res9, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$7, $tmp -> tmp6, $block$res -> block$res10, member:handleBlock$ -> handleBlock$5, $tmp -> tmp7, $block$res -> block$res1, $block$res -> block$res6, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $tmp -> tmp4, member:handleBlock$ -> handleBlock$6, $block$res -> block$res13, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$5, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$4, member:handleBlock$ -> handleBlock$9, member:handleBlock$ -> handleBlock$7, member:handleBlock$ -> handleBlock$4, $tmp -> tmp10, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$8) +//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'A' +//│ ║ l.246: handle h = A.Effect(3) with +//│ ║ ^ +//│ ╟── which references the symbol introduced here +//│ ║ l.229: module A with +//│ ║ ^^^^^^ +//│ ║ l.230: data class Effect(x) with +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.231: fun test() = x +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ║ l.232: fun perform(arg) +//│ ╙── ^^^^^^^^^^^^^^^^^^^^ +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] ReferenceError: A is not defined +//│ at REPL53:1:46 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:613:22) fun f(perform) = handle h = Effect with @@ -368,7 +414,18 @@ fun foo(h) = handle h = Eff with fun perform()(k) = k(()) foo(h) -//│ = 123 +//│ FAILURE: Unexpected exception +//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) +//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) +//│ at: scala.collection.immutable.List.map(List.scala:247) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) +//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) +//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) +//│ at: hkmc2.codegen.BlockTransformer.applySubBlock(BlockTransformer.scala:16) +//│ at: hkmc2.codegen.BlockTransformer.applyBlock$$anonfun$3$$anonfun$1(BlockTransformer.scala:38) :expect 123 fun foo(h) = @@ -394,7 +451,18 @@ fun foo(h) = handle h = Eff with fun perform()(k) = k(()) foo(h) -//│ = 123 +//│ FAILURE: Unexpected exception +//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) +//│ at: hkmc2.codegen.HandlerLowering.translateBody$$anonfun$1(HandlerLowering.scala:616) +//│ at: scala.collection.immutable.List.map(List.scala:247) +//│ at: hkmc2.codegen.HandlerLowering.translateBody(HandlerLowering.scala:616) +//│ at: hkmc2.codegen.HandlerLowering.$anonfun$13(HandlerLowering.scala:628) +//│ at: scala.Option.map(Option.scala:242) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:628) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) +//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) +//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) // Access superclass fields handle h1 = Object with diff --git a/hkmc2/shared/src/test/mlscript/handlers/EffectsInClasses.mls b/hkmc2/shared/src/test/mlscript/handlers/EffectsInClasses.mls index fbef803763..01d6e39abf 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/EffectsInClasses.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/EffectsInClasses.mls @@ -158,5 +158,15 @@ module A with let obj = new Object with fun foo() = print("Hello") foo() -//│ > Hello -//│ obj = $anon +//│ FAILURE: Unexpected exception +//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) +//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) +//│ at: scala.collection.immutable.List.map(List.scala:247) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) +//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) +//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) +//│ at: hkmc2.codegen.BlockTransformer.applySubBlock(BlockTransformer.scala:16) +//│ at: hkmc2.codegen.BlockTransformer.applyBlock$$anonfun$3$$anonfun$2(BlockTransformer.scala:43) diff --git a/hkmc2/shared/src/test/mlscript/handlers/EffectsInMethods.mls b/hkmc2/shared/src/test/mlscript/handlers/EffectsInMethods.mls index 8d9b6c4188..f35e5d53ee 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/EffectsInMethods.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/EffectsInMethods.mls @@ -10,17 +10,111 @@ class Test with fun p(h, x) = h.perform("A", x) + h.perform("B", x + 1) let t = new Test -//│ t = Test +//│ FAILURE: Unexpected exception +//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) +//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) +//│ at: scala.collection.immutable.List.map(List.scala:247) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) +//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) +//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) +//│ at: hkmc2.codegen.HandlerLowering.firstPass(HandlerLowering.scala:536) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateBlock(HandlerLowering.scala:477) handle h = Effect with fun perform(arg, x)(k) = print(arg) k(x * 2) [t.p(h, 2), t.p(h, 3)] -//│ > A -//│ > B -//│ > A -//│ > B -//│ = [10, 14] +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: lookup_! (Scope.scala:112) +//│ FAILURE INFO: Tuple2: +//│ _1 = Tuple2: +//│ _1 = t +//│ _2 = class hkmc2.semantics.VarSymbol +//│ _2 = Scope: +//│ parent = S of Scope: +//│ parent = S of Scope: +//│ parent = S of Scope: +//│ parent = S of Scope: +//│ parent = S of Scope: +//│ parent = N +//│ curThis = S of S of globalThis:globalThis +//│ bindings = HashMap(class:Cont$handler$h$perform$ -> Cont$handler$h$perform$, member:Predef -> Predef, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:Effect -> Effect1, $prettyPrint -> prettyPrint, class:Effect -> Effect, $Term -> Term, $block$res -> block$res1, $block$res -> block$res2, $tmp -> tmp, member:handleBlock$ -> handleBlock$, $block$res -> block$res, class:Handler$h$ -> Handler$h$) +//│ curThis = S of N +//│ bindings = HashMap($args -> args) +//│ curThis = N +//│ bindings = HashMap($tmp -> tmp1, member:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, $tmp -> tmp2, member:doUnwind -> doUnwind, member:Handler$h$ -> Handler$h$1, h -> h) +//│ curThis = S of S of class:Cont$handleBlock$h$ +//│ bindings = HashMap(pc -> pc) +//│ curThis = N +//│ bindings = HashMap($args -> args1, value$ -> value$) +//│ curThis = N +//│ bindings = HashMap($contLoop -> contLoop) +//│ ╔══[COMPILATION ERROR] No definition found in scope for member 't' +//│ ║ l.30: [t.p(h, 2), t.p(h, 3)] +//│ ║ ^ +//│ ╟── which references the symbol introduced here +//│ ║ l.12: let t = new Test +//│ ╙── ^ +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: lookup_! (Scope.scala:112) +//│ FAILURE INFO: Tuple2: +//│ _1 = Tuple2: +//│ _1 = t +//│ _2 = class hkmc2.semantics.VarSymbol +//│ _2 = Scope: +//│ parent = S of Scope: +//│ parent = S of Scope: +//│ parent = N +//│ curThis = S of S of globalThis:globalThis +//│ bindings = HashMap(class:Cont$handler$h$perform$ -> Cont$handler$h$perform$, member:Predef -> Predef, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:Effect -> Effect1, $prettyPrint -> prettyPrint, class:Effect -> Effect, $Term -> Term, $block$res -> block$res1, $block$res -> block$res2, $tmp -> tmp, member:handleBlock$ -> handleBlock$, $block$res -> block$res, class:Handler$h$ -> Handler$h$) +//│ curThis = S of N +//│ bindings = HashMap($args -> args) +//│ curThis = N +//│ bindings = HashMap($tmp -> tmp1, member:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, $tmp -> tmp2, member:doUnwind -> doUnwind, member:Handler$h$ -> Handler$h$1, h -> h) +//│ ╔══[COMPILATION ERROR] No definition found in scope for member 't' +//│ ║ l.30: [t.p(h, 2), t.p(h, 3)] +//│ ║ ^ +//│ ╟── which references the symbol introduced here +//│ ║ l.12: let t = new Test +//│ ╙── ^ +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: lookup_! (Scope.scala:112) +//│ FAILURE INFO: Tuple2: +//│ _1 = Tuple2: +//│ _1 = t +//│ _2 = class hkmc2.semantics.VarSymbol +//│ _2 = Scope: +//│ parent = S of Scope: +//│ parent = S of Scope: +//│ parent = N +//│ curThis = S of S of globalThis:globalThis +//│ bindings = HashMap(class:Cont$handler$h$perform$ -> Cont$handler$h$perform$, member:Predef -> Predef, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:Effect -> Effect1, $prettyPrint -> prettyPrint, class:Effect -> Effect, $Term -> Term, $block$res -> block$res1, $block$res -> block$res2, $tmp -> tmp, member:handleBlock$ -> handleBlock$, $block$res -> block$res, class:Handler$h$ -> Handler$h$) +//│ curThis = S of N +//│ bindings = HashMap($args -> args) +//│ curThis = N +//│ bindings = HashMap($tmp -> tmp1, member:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, $tmp -> tmp2, member:doUnwind -> doUnwind, member:Handler$h$ -> Handler$h$1, h -> h) +//│ ╔══[COMPILATION ERROR] No definition found in scope for member 't' +//│ ║ l.30: [t.p(h, 2), t.p(h, 3)] +//│ ║ ^ +//│ ╟── which references the symbol introduced here +//│ ║ l.12: let t = new Test +//│ ╙── ^ +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] ReferenceError: t is not defined +//│ at handleBlock$ (REPL13:1:4084) +//│ at REPL13:1:4411 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) diff --git a/hkmc2/shared/src/test/mlscript/handlers/HandlersInMethods.mls b/hkmc2/shared/src/test/mlscript/handlers/HandlersInMethods.mls index ad9f06f16e..b738c368cf 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/HandlersInMethods.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/HandlersInMethods.mls @@ -14,13 +14,64 @@ class Test with k(x * 2) h.perform("A", x) + h.perform("B", x + 1) let t = new Test -//│ t = Test +//│ FAILURE: Unexpected exception +//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) +//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) +//│ at: scala.collection.immutable.List.map(List.scala:247) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) +//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) +//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) +//│ at: hkmc2.codegen.HandlerLowering.firstPass(HandlerLowering.scala:536) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateBlock(HandlerLowering.scala:477) [t.p(2), t.p(3)] -//│ > A -//│ > B -//│ > A -//│ > B -//│ = [10, 14] +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: lookup_! (Scope.scala:112) +//│ FAILURE INFO: Tuple2: +//│ _1 = Tuple2: +//│ _1 = t +//│ _2 = class hkmc2.semantics.VarSymbol +//│ _2 = Scope: +//│ parent = N +//│ curThis = S of S of globalThis:globalThis +//│ bindings = HashMap(member:Predef -> Predef, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:Effect -> Effect1, $prettyPrint -> prettyPrint, class:Effect -> Effect, $Term -> Term, $block$res -> block$res1, $block$res -> block$res2, $tmp -> tmp, $tmp -> tmp1, $block$res -> block$res) +//│ ╔══[COMPILATION ERROR] No definition found in scope for member 't' +//│ ║ l.30: [t.p(2), t.p(3)] +//│ ║ ^ +//│ ╟── which references the symbol introduced here +//│ ║ l.16: let t = new Test +//│ ╙── ^ +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: lookup_! (Scope.scala:112) +//│ FAILURE INFO: Tuple2: +//│ _1 = Tuple2: +//│ _1 = t +//│ _2 = class hkmc2.semantics.VarSymbol +//│ _2 = Scope: +//│ parent = N +//│ curThis = S of S of globalThis:globalThis +//│ bindings = HashMap(member:Predef -> Predef, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:Effect -> Effect1, $prettyPrint -> prettyPrint, class:Effect -> Effect, $Term -> Term, $block$res -> block$res1, $block$res -> block$res2, $tmp -> tmp, $tmp -> tmp1, $block$res -> block$res) +//│ ╔══[COMPILATION ERROR] No definition found in scope for member 't' +//│ ║ l.30: [t.p(2), t.p(3)] +//│ ║ ^ +//│ ╟── which references the symbol introduced here +//│ ║ l.16: let t = new Test +//│ ╙── ^ +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] ReferenceError: t is not defined +//│ at REPL13:1:44 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:613:22) diff --git a/hkmc2/shared/src/test/mlscript/handlers/UserThreads.mls b/hkmc2/shared/src/test/mlscript/handlers/UserThreads.mls index 0aef56f838..3cfe6c58d3 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/UserThreads.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/UserThreads.mls @@ -15,6 +15,18 @@ class Lock(locked) with set locked = true fun unlock() = set locked = false +//│ FAILURE: Unexpected exception +//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) +//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) +//│ at: scala.collection.immutable.List.map(List.scala:247) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) +//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) +//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) +//│ at: hkmc2.codegen.HandlerLowering.firstPass(HandlerLowering.scala:536) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateBlock(HandlerLowering.scala:477) fun f(h, x) = print("f " + x) diff --git a/hkmc2/shared/src/test/mlscript/handlers/UserThreadsSafe.mls b/hkmc2/shared/src/test/mlscript/handlers/UserThreadsSafe.mls index c240949e57..9817594861 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/UserThreadsSafe.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/UserThreadsSafe.mls @@ -10,6 +10,18 @@ class ThreadEffect with tasks.pop()() fun fork(thread: () -> ()): () fun yld(): () +//│ FAILURE: Unexpected exception +//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) +//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) +//│ at: scala.collection.immutable.List.map(List.scala:247) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) +//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) +//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) +//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) +//│ at: hkmc2.codegen.HandlerLowering.firstPass(HandlerLowering.scala:536) +//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateBlock(HandlerLowering.scala:477) fun f(h, x)() = @@ -39,14 +51,46 @@ handle h = ThreadEffect with this.drain() in main(h) -//│ > main start -//│ > main end -//│ > f 2 -//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$ -//│ at f (UserThreadsSafe.mls:17:3) -//│ at drain (UserThreadsSafe.mls:10:7) -//│ at fork (UserThreadsSafe.mls:35:5) -//│ at fork (UserThreadsSafe.mls:35:5) +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: lookup_! (Scope.scala:112) +//│ FAILURE INFO: Tuple2: +//│ _1 = Tuple2: +//│ _1 = member:ThreadEffect +//│ _2 = class hkmc2.semantics.BlockMemberSymbol +//│ _2 = Scope: +//│ parent = S of Scope: +//│ parent = S of Scope: +//│ parent = S of Scope: +//│ parent = N +//│ curThis = S of S of globalThis:globalThis +//│ bindings = HashMap(member:getLocals -> getLocals2, member:Predef -> Predef, member:getLocals -> getLocals, class:Handler$h$ -> Handler$h$, $runtime -> runtime, member:getLocals -> getLocals1, member:main -> main, member:getLocals -> getLocals3, $definitionMetadata -> definitionMetadata, member:handleBlock$ -> handleBlock$, $prettyPrint -> prettyPrint, class:Cont$handler$h$yld$ -> Cont$handler$h$yld$, $Term -> Term, class:Cont$func$main$ -> Cont$func$main$, member:f -> f, class:Cont$func$f$ -> Cont$func$f$, class:Cont$handler$h$fork$ -> Cont$handler$h$fork$, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $block$res -> block$res2, $block$res -> block$res3, $block$res -> block$res1, $block$res -> block$res, $tmp -> tmp) +//│ curThis = S of N +//│ bindings = HashMap($args -> args) +//│ curThis = N +//│ bindings = HashMap(h -> h, member:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, member:Handler$h$ -> Handler$h$1, member:doUnwind -> doUnwind, member:getLocals -> getLocals4, $res -> res) +//│ curThis = S of S of class:Handler$h$ +//│ bindings = HashMap() +//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'ThreadEffect' +//│ ║ l.44: handle h = ThreadEffect with +//│ ║ ^^^^^^^^^^^^ +//│ ╟── which references the symbol introduced here +//│ ║ l.5: class ThreadEffect with +//│ ║ ^^^^^^^^^^^^^^^^^ +//│ ║ l.6: // task queue +//│ ║ ^^^^^^^^^^^^^^^ +//│ ║ l.7: val tasks = mut [] +//│ ║ ^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.8: fun drain() = +//│ ║ ^^^^^^^^^^^^^^^ +//│ ║ l.9: while tasks.length != 0 do +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.10: tasks.pop()() +//│ ║ ^^^^^^^^^^^^^^^^^^^ +//│ ║ l.11: fun fork(thread: () -> ()): () +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.12: fun yld(): () +//│ ╙── ^^^^^^^^^^^^^^^ +//│ ═══[RUNTIME ERROR] ReferenceError: ThreadEffect is not defined // FIFO @@ -61,13 +105,45 @@ handle h = ThreadEffect with this.drain() in main(h) -//│ > main start -//│ > main end -//│ > f 0 -//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$1 -//│ at f (UserThreadsSafe.mls:17:3) -//│ at drain (UserThreadsSafe.mls:10:7) -//│ at fork (UserThreadsSafe.mls:57:5) -//│ at fork (UserThreadsSafe.mls:57:5) +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: lookup_! (Scope.scala:112) +//│ FAILURE INFO: Tuple2: +//│ _1 = Tuple2: +//│ _1 = member:ThreadEffect +//│ _2 = class hkmc2.semantics.BlockMemberSymbol +//│ _2 = Scope: +//│ parent = S of Scope: +//│ parent = S of Scope: +//│ parent = S of Scope: +//│ parent = N +//│ curThis = S of S of globalThis:globalThis +//│ bindings = HashMap(class:Handler$h$ -> Handler$h$, $runtime -> runtime, member:main -> main, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, $definitionMetadata -> definitionMetadata, $prettyPrint -> prettyPrint, $Term -> Term, member:f -> f, class:Cont$handler$h$fork$ -> Cont$handler$h$fork$, $block$res -> block$res2, $block$res -> block$res3, class:Handler$h$ -> Handler$h$1, $block$res -> block$res1, $block$res -> block$res, $tmp -> tmp, member:getLocals -> getLocals2, member:Predef -> Predef, member:getLocals -> getLocals, class:Cont$handler$h$fork$ -> Cont$handler$h$fork$1, member:getLocals -> getLocals1, member:getLocals -> getLocals3, member:handleBlock$ -> handleBlock$, class:Cont$handler$h$yld$ -> Cont$handler$h$yld$, class:Cont$func$main$ -> Cont$func$main$, $block$res -> block$res4, class:Cont$func$f$ -> Cont$func$f$, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $tmp -> tmp1, member:getLocals -> getLocals4, member:handleBlock$ -> handleBlock$1, class:Cont$handler$h$yld$ -> Cont$handler$h$yld$1) +//│ curThis = S of N +//│ bindings = HashMap($args -> args) +//│ curThis = N +//│ bindings = HashMap(member:getLocals -> getLocals5, $res -> res, h -> h, member:Cont$handleBlock$h$ -> Cont$handleBlock$h$2, member:Handler$h$ -> Handler$h$2, member:doUnwind -> doUnwind) +//│ curThis = S of S of class:Handler$h$ +//│ bindings = HashMap() +//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'ThreadEffect' +//│ ║ l.98: handle h = ThreadEffect with +//│ ║ ^^^^^^^^^^^^ +//│ ╟── which references the symbol introduced here +//│ ║ l.5: class ThreadEffect with +//│ ║ ^^^^^^^^^^^^^^^^^ +//│ ║ l.6: // task queue +//│ ║ ^^^^^^^^^^^^^^^ +//│ ║ l.7: val tasks = mut [] +//│ ║ ^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.8: fun drain() = +//│ ║ ^^^^^^^^^^^^^^^ +//│ ║ l.9: while tasks.length != 0 do +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.10: tasks.pop()() +//│ ║ ^^^^^^^^^^^^^^^^^^^ +//│ ║ l.11: fun fork(thread: () -> ()): () +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.12: fun yld(): () +//│ ╙── ^^^^^^^^^^^^^^^ +//│ ═══[RUNTIME ERROR] ReferenceError: ThreadEffect is not defined diff --git a/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls b/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls index 6d604a7de6..d1dc9ec444 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls @@ -19,7 +19,9 @@ fun f(x) = fun get() = x Test() f(1).get() -//│ = 1 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) +//│ ═══[RUNTIME ERROR] Expected: '1', got: '()' :expect 1 fun f(used1, unused1) = @@ -32,7 +34,9 @@ fun f(used1, unused1) = fun get() = used1 Test(unused1) f(1, 2).get() -//│ = 1 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) +//│ ═══[RUNTIME ERROR] Expected: '1', got: '()' :expect 1 fun f(used1, unused1) = @@ -45,7 +49,9 @@ fun f(used1, unused1) = fun get() = used1 new Test(unused1) f(1, 2).get() -//│ = 1 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) +//│ ═══[RUNTIME ERROR] Expected: '1', got: '()' :expect 1 fun f(used1, unused1) = @@ -67,7 +73,22 @@ fun f(x) = A().f() x f(1) -//│ = 2 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot set properties of undefined (setting 'x$capture$0') +//│ at A.f (REPL25:1:949) +//│ at f (REPL25:1:1572) +//│ at REPL25:1:1641 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) +//│ ═══[RUNTIME ERROR] Expected: '2', got: 'undefined' // only w should be in a capture :expect 10111 @@ -132,9 +153,9 @@ f().foo() //│ foo() { //│ let tmp6, tmp7; //│ this.z = 100; -//│ tmp6 = this.x + this.y; -//│ tmp7 = tmp6 + this.z; -//│ return tmp7 + this.f$capture.w$capture$0 +//│ tmp6 = this.x.class + this.y.class; +//│ tmp7 = tmp6 + this.z.class; +//│ return tmp7 + this.f$capture.class.w$capture$0 //│ } //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "Good", []]; @@ -168,7 +189,7 @@ f().foo() //│ get f$capture() { return this.#f$capture; } //│ set f$capture(value) { this.#f$capture = value; } //│ foo() { -//│ this.f$capture.w$capture$0 = 10000; +//│ this.f$capture.class.w$capture$0 = 10000; //│ return runtime.Unit //│ } //│ toString() { return runtime.render(this); } @@ -197,7 +218,22 @@ f().foo() //│ }; //│ tmp5 = f5(); //│ runtime.safeCall(tmp5.foo()) -//│ = 10111 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot set properties of undefined (setting 'w$capture$0') +//│ at Bad.foo (REPL28:1:2553) +//│ at f (REPL28:1:3237) +//│ at REPL28:1:3332 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) +//│ ═══[RUNTIME ERROR] Expected: '10111', got: 'undefined' :expect 2 fun f(x) = @@ -213,9 +249,24 @@ a.foo() let b = a.newA() b.foo() a.getX() -//│ = 2 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'x$capture$0') +//│ at A2.foo (REPL31:1:1268) +//│ at REPL31:1:2105 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) +//│ ═══[RUNTIME ERROR] Expected: '2', got: 'undefined' //│ a = A() -//│ b = A() +//│ b = undefined // handler diff --git a/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls b/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls index b679dffcae..b7b047f79d 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls @@ -38,7 +38,7 @@ data class A(x) with //│ get A$instance() { return this.#A$instance; } //│ set A$instance(value) { this.#A$instance = value; } //│ getB() { -//│ return this.A$instance.x + this.y +//│ return this.A$instance.class.x + this.y //│ } //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "B", ["y"]]; @@ -55,7 +55,7 @@ data class A(x) with //│ } //│ getA() { //│ let tmp; -//│ tmp = B$(false, this, 2); +//│ tmp = this.B(2); //│ return runtime.safeCall(tmp.getB()) //│ } //│ toString() { return runtime.render(this); } @@ -64,7 +64,22 @@ data class A(x) with :expect 3 A(1).getA() -//│ = 3 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: this.B is not a function +//│ at A.getA (REPL10:1:1494) +//│ at REPL13:1:81 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) +//│ ═══[RUNTIME ERROR] Expected: '3', got: 'undefined' :sjs class A with diff --git a/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls b/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls index b27cccd164..a38e934f72 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls @@ -164,7 +164,22 @@ data class A(x) with :expect 2 A(2).getA() -//│ = 2 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'getB') +//│ at A.getA (REPL50:1:966) +//│ at REPL53:1:82 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) +//│ ═══[RUNTIME ERROR] Expected: '2', got: 'undefined' // Classes and functions in modules // @@ -193,7 +208,22 @@ object M with fun get = x val hi = A() M.hi.get -//│ = 2 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: this.A is not a function +//│ at new M12 (REPL62:1:1145) +//│ at (REPL62:1:1049) +//│ at REPL62:1:1298 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) +//│ ═══[RUNTIME ERROR] Expected: '2', got: 'undefined' :expect 2 object M with @@ -273,7 +303,19 @@ module M with fun newB = B() 0 is A M.A(2).newB.newA_B(3).newB.get -//│ = 3 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] TypeError: this.B is not a function +//│ at get newB (REPL74:1:1737) +//│ at REPL74:1:2121 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) module M with class A diff --git a/hkmc2/shared/src/test/mlscript/llir/Classes.mls b/hkmc2/shared/src/test/mlscript/llir/Classes.mls index 2bfb5b2433..0de40b6897 100644 --- a/hkmc2/shared/src/test/mlscript/llir/Classes.mls +++ b/hkmc2/shared/src/test/mlscript/llir/Classes.mls @@ -24,26 +24,8 @@ fun main() = let d = Derived() d.Base#get() * d.Derived#get() main() -//│ LLIR: -//│ class Base() { -//│ def get() = -//│ 1 -//│ } -//│ class Derived() extends Base { -//│ def get1() = -//│ 2 -//│ } -//│ def main() = -//│ let x = Derived() in -//│ let x1 = Base.get(x) in -//│ let x2 = Derived.get(x) in -//│ let x3 = *(x1,x2) in -//│ x3 -//│ def entry() = -//│ let* (x4) = main() in -//│ x4 -//│ entry = entry -//│ -//│ Interpreted: -//│ 4 +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: bErrStop (Builder.scala:22) +//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Ref(d,None),Ident(get)),List()) +//│ Stopped due to an error during the Llir generation diff --git a/hkmc2/shared/src/test/mlscript/llir/Lazy.mls b/hkmc2/shared/src/test/mlscript/llir/Lazy.mls index 23cb1ccaa2..64322e0574 100644 --- a/hkmc2/shared/src/test/mlscript/llir/Lazy.mls +++ b/hkmc2/shared/src/test/mlscript/llir/Lazy.mls @@ -11,6 +11,10 @@ type LazyList[out T] = Lazy[LzList[T]] abstract class LzList[out T]: LzCons[T] | LzNil data class LzCons[out T](head: T, tail: LazyList[T]) extends LzList[T] object LzNil extends LzList +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: bErrStop (Builder.scala:22) +//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Ref(x,None),Ident(get)),List()) +//│ Stopped due to an error during the Llir generation :sllir :scpp @@ -23,67 +27,7 @@ fun main() = let y1 = force(x) // force again, but should not execute side_effect again () main() -//│ LLIR: -//│ class Lambda_lambda() extends Callable { -//│ def apply0() = -//│ let* (x) = side_effect() in -//│ x -//│ } -//│ def side_effect() = -//│ let* (x1) = $_builtin$_("println","executed") in -//│ 1 -//│ def main() = -//│ let x2 = Lambda_lambda() in -//│ let* (x3) = lazy(x2) in -//│ let* (x4) = force(x3) in -//│ let* (x5) = force(x3) in -//│ undefined -//│ def entry() = -//│ let* (x6) = main() in -//│ x6 -//│ entry = entry -//│ -//│ Cpp: -//│ #include "mlsprelude.h" -//│ struct _mls_Lambda_lambda; -//│ _mlsValue _mls_side_effect(); -//│ _mlsValue _mls_main(); -//│ _mlsValue _mls_entry(); -//│ struct _mls_Lambda_lambda: public _mls_Callable { -//│ -//│ constexpr static inline const char *typeName = "Lambda_lambda"; -//│ constexpr static inline uint32_t typeTag = nextTypeTag(); -//│ virtual void print() const override { std::printf("%s", typeName); } -//│ virtual void destroy() override { operator delete (this, std::align_val_t(_mlsAlignment)); } -//│ static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Lambda_lambda; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; return _mlsValue(_mlsVal); } -//│ virtual _mlsValue _mls_apply0(); -//│ }; -//│ _mlsValue _mls_side_effect() { -//│ _mlsValue _mls_retval; -//│ auto _mls_x1 = _mls_builtin_println(_mlsValue::create<_mls_Str>("executed")); -//│ _mls_retval = _mlsValue::fromIntLit(1); -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_main() { -//│ _mlsValue _mls_retval; -//│ auto _mls_x2 = _mlsValue::create<_mls_Lambda_lambda>(); -//│ auto _mls_x3 = _mls_lazy(_mls_x2); -//│ auto _mls_x4 = _mls_force(_mls_x3); -//│ auto _mls_x5 = _mls_force(_mls_x3); -//│ _mls_retval = _mlsValue::create<_mls_Unit>(); -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_entry() { -//│ _mlsValue _mls_retval; -//│ auto _mls_x6 = _mls_main(); -//│ _mls_retval = _mls_x6; -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_Lambda_lambda::_mls_apply0() { -//│ _mlsValue _mls_retval; -//│ auto _mls_x = _mls_side_effect(); -//│ _mls_retval = _mls_x; -//│ return _mls_retval; -//│ } -//│ _mlsValue _mlsMain() { return _mls_entry(); } -//│ int main() { return _mlsLargeStack(_mlsMainWrapper); } +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: bErrStop (Builder.scala:22) +//│ ═══[COMPILATION ERROR] Name not found: member:lazy +//│ Stopped due to an error during the Llir generation diff --git a/hkmc2/shared/src/test/mlscript/llir/LazyCycle.mls b/hkmc2/shared/src/test/mlscript/llir/LazyCycle.mls index 7a28a12aac..0cec5fff06 100644 --- a/hkmc2/shared/src/test/mlscript/llir/LazyCycle.mls +++ b/hkmc2/shared/src/test/mlscript/llir/LazyCycle.mls @@ -11,6 +11,10 @@ type LazyList[out T] = Lazy[LzList[T]] abstract class LzList[out T]: LzCons[T] | LzNil data class LzCons[out T](head: T, tail: LazyList[T]) extends LzList[T] object LzNil extends LzList +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: bErrStop (Builder.scala:22) +//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Ref(x,None),Ident(get)),List()) +//│ Stopped due to an error during the Llir generation :sllir :showWholeCpp @@ -18,149 +22,7 @@ fun llist(x) = fun f(x) = lazy(() => LzCons(x, f(x + 1))) f(x) llist(1) -//│ LLIR: -//│ class Lambda_lambda(lam_arg0,lam_arg1) extends Callable { -//│ def apply0() = -//│ let x = +(lam_arg0,1) in -//│ let x1 = Callable.apply1(lam_arg1,x) in -//│ let x2 = LzCons(lam_arg0,x1) in -//│ x2 -//│ } -//│ class Lambda_f() extends Callable { -//│ def apply1(x3) = -//│ let x4 = Lambda_lambda(x3,$_this$_) in -//│ let* (x5) = lazy(x4) in -//│ x5 -//│ } -//│ def llist(x6) = -//│ let x7 = Lambda_f() in -//│ let x8 = Callable.apply1(x7,x6) in -//│ x8 -//│ def entry() = -//│ let* (x9) = llist(1) in -//│ x9 -//│ entry = entry -//│ -//│ WholeProgramCpp: -//│ #include "mlsprelude.h" -//│ struct _mls_Lambda_f; -//│ struct _mls_Lambda_lambda; -//│ struct _mls_Lazy; -//│ struct _mls_LzList; -//│ struct _mls_LzCons; -//│ struct _mls_LzNil; -//│ _mlsValue _mls_entry2(); -//│ _mlsValue _mls_entry(); -//│ _mlsValue _mls_llist(_mlsValue); -//│ _mlsValue _mls_force(_mlsValue); -//│ _mlsValue _mls_lazy(_mlsValue); -//│ _mlsValue _mls_j(); -//│ _mlsValue _mls_entry1(); -//│ struct _mls_Lambda_f: public _mls_Callable { -//│ -//│ constexpr static inline const char *typeName = "Lambda_f"; -//│ constexpr static inline uint32_t typeTag = nextTypeTag(); -//│ virtual void print() const override { std::printf("%s", typeName); } -//│ virtual void destroy() override { operator delete (this, std::align_val_t(_mlsAlignment)); } -//│ static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Lambda_f; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; return _mlsValue(_mlsVal); } -//│ virtual _mlsValue _mls_apply1(_mlsValue); -//│ }; -//│ struct _mls_Lambda_lambda: public _mls_Callable { -//│ _mlsValue _mls_lam_arg0; -//│ _mlsValue _mls_lam_arg1; -//│ constexpr static inline const char *typeName = "Lambda_lambda"; -//│ constexpr static inline uint32_t typeTag = nextTypeTag(); -//│ virtual void print() const override { std::printf("%s", typeName); std::printf("("); this->_mls_lam_arg0.print(); std::printf(", "); this->_mls_lam_arg1.print(); std::printf(")"); } -//│ virtual void destroy() override { _mlsValue::destroy(this->_mls_lam_arg0); _mlsValue::destroy(this->_mls_lam_arg1); operator delete (this, std::align_val_t(_mlsAlignment)); } -//│ static _mlsValue create(_mlsValue _mls_lam_arg0, _mlsValue _mls_lam_arg1) { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Lambda_lambda; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; _mlsVal->_mls_lam_arg0 = _mls_lam_arg0; _mlsVal->_mls_lam_arg1 = _mls_lam_arg1; return _mlsValue(_mlsVal); } -//│ virtual _mlsValue _mls_apply0(); -//│ }; -//│ struct _mls_LzList: public _mlsObject { -//│ -//│ constexpr static inline const char *typeName = "LzList"; -//│ constexpr static inline uint32_t typeTag = nextTypeTag(); -//│ virtual void print() const override { std::printf("%s", typeName); } -//│ virtual void destroy() override { operator delete (this, std::align_val_t(_mlsAlignment)); } -//│ static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_LzList; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; return _mlsValue(_mlsVal); } -//│ -//│ }; -//│ struct _mls_LzCons: public _mls_LzList { -//│ _mlsValue _mls_head; -//│ _mlsValue _mls_tail; -//│ constexpr static inline const char *typeName = "LzCons"; -//│ constexpr static inline uint32_t typeTag = nextTypeTag(); -//│ virtual void print() const override { std::printf("%s", typeName); std::printf("("); this->_mls_head.print(); std::printf(", "); this->_mls_tail.print(); std::printf(")"); } -//│ virtual void destroy() override { _mlsValue::destroy(this->_mls_head); _mlsValue::destroy(this->_mls_tail); operator delete (this, std::align_val_t(_mlsAlignment)); } -//│ static _mlsValue create(_mlsValue _mls_head, _mlsValue _mls_tail) { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_LzCons; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; _mlsVal->_mls_head = _mls_head; _mlsVal->_mls_tail = _mls_tail; return _mlsValue(_mlsVal); } -//│ -//│ }; -//│ struct _mls_LzNil: public _mls_LzList { -//│ -//│ constexpr static inline const char *typeName = "LzNil"; -//│ constexpr static inline uint32_t typeTag = nextTypeTag(); -//│ virtual void print() const override { std::printf("%s", typeName); } -//│ virtual void destroy() override { operator delete (this, std::align_val_t(_mlsAlignment)); } -//│ static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_LzNil; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; return _mlsValue(_mlsVal); } -//│ -//│ }; -//│ _mlsValue _mls_j() { -//│ _mlsValue _mls_retval; -//│ _mls_retval = _mlsValue::create<_mls_Unit>(); -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_entry() { -//│ _mlsValue _mls_retval; -//│ _mls_retval = _mlsValue::create<_mls_Unit>(); -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_lazy(_mlsValue _mls_x7) { -//│ _mlsValue _mls_retval; -//│ auto _mls_x6 = _mlsValue::create<_mls_Lazy>(_mls_x7); -//│ _mls_retval = _mls_x6; -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_llist(_mlsValue _mls_x12) { -//│ _mlsValue _mls_retval; -//│ auto _mls_x11 = _mlsValue::create<_mls_Lambda_f>(); -//│ auto _mls_x13 = _mlsMethodCall<_mls_Callable>(_mls_x11)->_mls_apply1(_mls_x12); -//│ _mls_retval = _mls_x13; -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_entry1() { -//│ _mlsValue _mls_retval; -//│ auto _mls_x8 = _mls_llist(_mlsValue::fromIntLit(1)); -//│ _mls_retval = _mls_x8; -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_entry2() { -//│ _mlsValue _mls_retval; -//│ _mls_retval = _mlsValue::create<_mls_Unit>(); -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_force(_mlsValue _mls_x9) { -//│ _mlsValue _mls_retval; -//│ if (_mlsValue::isValueOf<_mls_Lazy>(_mls_x9)) { -//│ auto _mls_x10 = _mlsMethodCall<_mls_Lazy>(_mls_x9)->_mls_get(); -//│ _mls_retval = _mls_x10; -//│ } else { -//│ throw std::runtime_error("match error"); -//│ } -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_Lambda_f::_mls_apply1(_mlsValue _mls_x1) { -//│ _mlsValue _mls_retval; -//│ auto _mls_x = _mlsValue::create<_mls_Lambda_lambda>(_mls_x1, _mlsValue(this, _mlsValue::inc_ref_tag{})); -//│ auto _mls_x2 = _mls_lazy(_mls_x); -//│ _mls_retval = _mls_x2; -//│ return _mls_retval; -//│ } -//│ _mlsValue _mls_Lambda_lambda::_mls_apply0() { -//│ _mlsValue _mls_retval; -//│ auto _mls_x3 = (_mls_lam_arg0 + _mlsValue::fromIntLit(1)); -//│ auto _mls_x4 = _mlsMethodCall<_mls_Callable>(_mls_lam_arg1)->_mls_apply1(_mls_x3); -//│ auto _mls_x5 = _mlsValue::create<_mls_LzCons>(_mls_lam_arg0, _mls_x4); -//│ _mls_retval = _mls_x5; -//│ return _mls_retval; -//│ } -//│ _mlsValue _mlsMain() { return _mls_entry1(); } -//│ int main() { return _mlsLargeStack(_mlsMainWrapper); } +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: bErrStop (Builder.scala:22) +//│ ═══[COMPILATION ERROR] Name not found: member:lazy +//│ Stopped due to an error during the Llir generation diff --git a/hkmc2/shared/src/test/mlscript/llir/Method.mls b/hkmc2/shared/src/test/mlscript/llir/Method.mls index f7277d456c..4f569cbd0a 100644 --- a/hkmc2/shared/src/test/mlscript/llir/Method.mls +++ b/hkmc2/shared/src/test/mlscript/llir/Method.mls @@ -10,17 +10,8 @@ fun main() = a.A#f() main() //│ = 1 -//│ LLIR: -//│ class A(m) { -//│ def f() = -//│ m -//│ } -//│ def main() = -//│ let x = A(1) in -//│ let x1 = A.f(x) in -//│ x1 -//│ def entry() = -//│ let* (x2) = main() in -//│ x2 -//│ entry = entry +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: bErrStop (Builder.scala:22) +//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Ref(a,None),Ident(f)),List()) +//│ Stopped due to an error during the Llir generation diff --git a/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls b/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls index 422b1b5b83..dfac8db569 100644 --- a/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls +++ b/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls @@ -3,7 +3,7 @@ :import NofibPrelude.mls //│ Imported 104 member(s) -//│ Error: hkmc2.ErrorReport: Unsupported kind of Call Call(Select(Select(Ref($runtime,None),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(t1,None)), Arg(None,Lit(IntLit(0))))) +//│ Error: hkmc2.ErrorReport: Unsupported kind of Call Call(Select(Ref(x,None),Ident(get)),List()) //│ Stopped due to an error during the Llir generation diff --git a/hkmc2/shared/src/test/mlscript/nofib/scc.mls b/hkmc2/shared/src/test/mlscript/nofib/scc.mls index c54e2c4c33..ec1b4f49ae 100644 --- a/hkmc2/shared/src/test/mlscript/nofib/scc.mls +++ b/hkmc2/shared/src/test/mlscript/nofib/scc.mls @@ -3,7 +3,8 @@ :silent :import NofibPrelude.mls -//│ /!!!\ Uncaught error: scala.NotImplementedError: AssignField not supported (of class String) +//│ Error: hkmc2.ErrorReport: Unsupported selection by users +//│ Stopped due to an error during the Llir generation fun dfs(r, vsns, xs) = if vsns is [vs, ns] and diff --git a/hkmc2/shared/src/test/mlscript/ucs/hygiene/HygienicBindings.mls b/hkmc2/shared/src/test/mlscript/ucs/hygiene/HygienicBindings.mls index 7de8d4ff67..e3b652f8a8 100644 --- a/hkmc2/shared/src/test/mlscript/ucs/hygiene/HygienicBindings.mls +++ b/hkmc2/shared/src/test/mlscript/ucs/hygiene/HygienicBindings.mls @@ -40,16 +40,16 @@ fun h1(a) = a is None then 0 //│ Normalized: //│ > if -//│ > a is Option.Some.class(param0) and +//│ > a is Option.Some(param0) and //│ > let x = $param0 -//│ > x is Left.class(param0) and +//│ > x is Left(param0) and //│ > let y = $param0 //│ > else y //│ > let y = $param0 -//│ > y is Right.class(param0) and +//│ > y is Right(param0) and //│ > let z = $param0 //│ > else z -//│ > a is Option.None.class then 0 +//│ > a is Option.None then 0 h1(Some(Left(42))) //│ = 42 @@ -72,18 +72,18 @@ fun h2(a) = a is None then 0 //│ Normalized: //│ > if -//│ > a is Option.Some.class(param0) and +//│ > a is Option.Some(param0) and //│ > let x = $param0 //│ > let x' = x -//│ > x' is Left.class(param0) and +//│ > x' is Left(param0) and //│ > let y = $param0 //│ > else y //│ > let y = $param0 //│ > let y' = y -//│ > y' is Right.class(param0) and +//│ > y' is Right(param0) and //│ > let z = $param0 //│ > else z -//│ > a is Option.None.class then 0 +//│ > a is Option.None then 0 // :w fun h3(x, y, f, p) = diff --git a/hkmc2/shared/src/test/mlscript/ucs/normalization/OverlapOfPrimitives.mls b/hkmc2/shared/src/test/mlscript/ucs/normalization/OverlapOfPrimitives.mls index 26ad26d50c..6b42b6676e 100644 --- a/hkmc2/shared/src/test/mlscript/ucs/normalization/OverlapOfPrimitives.mls +++ b/hkmc2/shared/src/test/mlscript/ucs/normalization/OverlapOfPrimitives.mls @@ -151,7 +151,7 @@ fun f(arg) = if arg is Object then String(arg) //│ Normalized: //│ > if -//│ > arg is Foo.class then "just Foo" +//│ > arg is Foo then "just Foo" //│ > arg is Object then member:String(arg) fun f(arg) = if arg is diff --git a/hkmc2/shared/src/test/mlscript/ucs/patterns/ConjunctionPattern.mls b/hkmc2/shared/src/test/mlscript/ucs/patterns/ConjunctionPattern.mls index 003be9bb5b..21c1a39976 100644 --- a/hkmc2/shared/src/test/mlscript/ucs/patterns/ConjunctionPattern.mls +++ b/hkmc2/shared/src/test/mlscript/ucs/patterns/ConjunctionPattern.mls @@ -28,7 +28,7 @@ fun foo(v) = A & B then 1 else 0 //│ JS (unsanitized): -//│ let foo; foo = function foo(v) { if (v instanceof A1.class) { return 0 } else { return 0 } }; +//│ let foo; foo = function foo(v) { if (v === A1) { return 0 } else { return 0 } }; fun range(i, j) = if i > j then Nil diff --git a/hkmc2/shared/src/test/mlscript/ups/parametric/EtaConversion.mls b/hkmc2/shared/src/test/mlscript/ups/parametric/EtaConversion.mls index 6fc7d7c04b..bde9cbbdeb 100644 --- a/hkmc2/shared/src/test/mlscript/ups/parametric/EtaConversion.mls +++ b/hkmc2/shared/src/test/mlscript/ups/parametric/EtaConversion.mls @@ -11,9 +11,9 @@ pattern Zero = 0 //│ Normalized: //│ > if //│ > let $scrut = 0 -//│ > let $param0 = member:Zero +//│ > let $param0 = member:Zero‹pattern:Zero› //│ > let $matchResult = (member:Nullable.)unapply($param0, $scrut) -//│ > $matchResult is $runtime.MatchResult.class then true +//│ > $matchResult is ($runtime.)MatchResult‹class:MatchResult› then true //│ > else false //│ = true @@ -23,9 +23,9 @@ import "../../../mlscript-compile/Char.mls" fun foo(x) = x is Nullable(pattern Char.Letter) //│ Normalized: //│ > if -//│ > let $param0 = (member:Char.)Letter‹member:Letter› +//│ > let $param0 = (member:Char.)Letter‹pattern:Letter› //│ > let $matchResult = (member:Nullable.)unapply($param0, x) -//│ > $matchResult is $runtime.MatchResult.class then true +//│ > $matchResult is ($runtime.)MatchResult‹class:MatchResult› then true //│ > else false foo of null diff --git a/hkmc2/shared/src/test/mlscript/wasm/Basics.mls b/hkmc2/shared/src/test/mlscript/wasm/Basics.mls index 67a067e99d..d5ba0b66a0 100644 --- a/hkmc2/shared/src/test/mlscript/wasm/Basics.mls +++ b/hkmc2/shared/src/test/mlscript/wasm/Basics.mls @@ -3,14 +3,6 @@ :wasm false -//│ Wat: -//│ (module -//│ (type (func (result (ref null any)))) -//│ (func $entry (type 0) (result (ref null any)) -//│ (ref.i31 -//│ (i32.const 0))) -//│ (export "entry" (func $entry)) -//│ (elem declare func $entry)) //│ Wasm result: //│ FAILURE: Unexpected runtime error //│ FAILURE LOCATION: mkQuery (WasmDiffMaker.scala:128) @@ -100,8 +92,8 @@ x fun foo() = 42 foo //│ ╔══[COMPILATION ERROR] Returning function instances is not supported -//│ ║ l.102: foo -//│ ╙── ^^^ +//│ ║ l.93: foo +//│ ╙── ^^^ fun foo() = 42 @@ -211,7 +203,7 @@ new Foo(0) //│ FAILURE LOCATION: errExpr (WatBuilder.scala:262) //│ FAILURE INFO: Block IR of `cls` expression: Ref(member:Foo,Some(class:Foo)) //│ ╔══[COMPILATION ERROR] WatBuilder::result for Instantiate(...) where `cls` is not a Select(...) path not implemented yet -//│ ║ l.210: new Foo(0) +//│ ║ l.201: new Foo(0) //│ ╙── ^^^ //│ FAILURE: Unexpected exception //│ /!!!\ Uncaught error: java.lang.UnsupportedOperationException: UnreachableType is a compiler-internal type and cannot be converted to WAT @@ -234,7 +226,7 @@ class Foo(val a) //│ FAILURE LOCATION: errExpr (WatBuilder.scala:262) //│ FAILURE INFO: Block IR of `cls` expression: Ref(member:Foo,Some(class:Foo)) //│ ╔══[COMPILATION ERROR] WatBuilder::result for Instantiate(...) where `cls` is not a Select(...) path not implemented yet -//│ ║ l.233: (new Foo(42)).Foo#a +//│ ║ l.224: (new Foo(42)).Foo#a //│ ╙── ^^^ //│ Wat: //│ (module From 99bdb5f2834b74a2b81bd11d8d952b1b8171f89f Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Thu, 30 Oct 2025 15:09:26 +0800 Subject: [PATCH 08/55] Apply Mark's Patch --- .../src/main/scala/hkmc2/codegen/Lifter.scala | 13 ++-- .../src/test/mlscript/lifter/ClassInFun.mls | 73 +++---------------- .../mlscript/lifter/ClassWithCompanion.mls | 14 +--- .../src/test/mlscript/lifter/DefnsInClass.mls | 4 +- .../test/mlscript/lifter/ModulesObjects.mls | 10 +-- 5 files changed, 27 insertions(+), 87 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index eabdd75ea3..ec8761824d 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -234,7 +234,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): def read = this match case Sym(l) => l.asPath - case PubField(isym, sym) => Select(isym.asPath, Tree.Ident(sym.nme))(isym.asDefnSym_TODO) + case PubField(isym, sym) => Select(isym.asPath, Tree.Ident(sym.nme))(N) // TODO: isym.asInstanceOf def asArg = read.asArg @@ -242,8 +242,11 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): def assign(value: Result, rest: Block) = this match case Sym(l) => Assign(l, value, rest) case PubField(isym, sym) => AssignField(isym.asPath, Tree.Ident(sym.nme), value, rest)(S(sym)) - - + + def readDisamb(d: Opt[DefinitionSymbol[?]]) = this match + case Sym(l) => Value.Ref(l, d) + case PubField(isym, sym) => Select(isym.asPath, Tree.Ident(sym.nme))(d) + def isHandlerClsPath(p: Path) = handlerPaths match case None => false case Some(paths) => paths.isHandlerClsPath(p) @@ -820,8 +823,8 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): // This is to rewrite references to classes that are not lifted (when their BlockMemberSymbol // reference is passed as function parameters). - case RefOfBms(l, _) if ctx.ignored(l) && ctx.isRelevant(l) => ctx.getIgnoredBmsPath(l) match - case Some(value) => k(value.read) + case RefOfBms(l, disamb) if ctx.ignored(l) && ctx.isRelevant(l) => ctx.getIgnoredBmsPath(l) match + case Some(value) => k(value.readDisamb(disamb)) case None => super.applyPath(p)(k) // This rewrites naked references to locals. If a function is in a capture, then we select that value diff --git a/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls b/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls index d1dc9ec444..6d604a7de6 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls @@ -19,9 +19,7 @@ fun f(x) = fun get() = x Test() f(1).get() -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) -//│ ═══[RUNTIME ERROR] Expected: '1', got: '()' +//│ = 1 :expect 1 fun f(used1, unused1) = @@ -34,9 +32,7 @@ fun f(used1, unused1) = fun get() = used1 Test(unused1) f(1, 2).get() -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) -//│ ═══[RUNTIME ERROR] Expected: '1', got: '()' +//│ = 1 :expect 1 fun f(used1, unused1) = @@ -49,9 +45,7 @@ fun f(used1, unused1) = fun get() = used1 new Test(unused1) f(1, 2).get() -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) -//│ ═══[RUNTIME ERROR] Expected: '1', got: '()' +//│ = 1 :expect 1 fun f(used1, unused1) = @@ -73,22 +67,7 @@ fun f(x) = A().f() x f(1) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot set properties of undefined (setting 'x$capture$0') -//│ at A.f (REPL25:1:949) -//│ at f (REPL25:1:1572) -//│ at REPL25:1:1641 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) -//│ ═══[RUNTIME ERROR] Expected: '2', got: 'undefined' +//│ = 2 // only w should be in a capture :expect 10111 @@ -153,9 +132,9 @@ f().foo() //│ foo() { //│ let tmp6, tmp7; //│ this.z = 100; -//│ tmp6 = this.x.class + this.y.class; -//│ tmp7 = tmp6 + this.z.class; -//│ return tmp7 + this.f$capture.class.w$capture$0 +//│ tmp6 = this.x + this.y; +//│ tmp7 = tmp6 + this.z; +//│ return tmp7 + this.f$capture.w$capture$0 //│ } //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "Good", []]; @@ -189,7 +168,7 @@ f().foo() //│ get f$capture() { return this.#f$capture; } //│ set f$capture(value) { this.#f$capture = value; } //│ foo() { -//│ this.f$capture.class.w$capture$0 = 10000; +//│ this.f$capture.w$capture$0 = 10000; //│ return runtime.Unit //│ } //│ toString() { return runtime.render(this); } @@ -218,22 +197,7 @@ f().foo() //│ }; //│ tmp5 = f5(); //│ runtime.safeCall(tmp5.foo()) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot set properties of undefined (setting 'w$capture$0') -//│ at Bad.foo (REPL28:1:2553) -//│ at f (REPL28:1:3237) -//│ at REPL28:1:3332 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) -//│ ═══[RUNTIME ERROR] Expected: '10111', got: 'undefined' +//│ = 10111 :expect 2 fun f(x) = @@ -249,24 +213,9 @@ a.foo() let b = a.newA() b.foo() a.getX() -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'x$capture$0') -//│ at A2.foo (REPL31:1:1268) -//│ at REPL31:1:2105 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) -//│ ═══[RUNTIME ERROR] Expected: '2', got: 'undefined' +//│ = 2 //│ a = A() -//│ b = undefined +//│ b = A() // handler diff --git a/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls b/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls index 915114f78a..4a38ce4a73 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls @@ -12,19 +12,7 @@ fun foo(x) = //│ ═══[WARNING] Modules are not yet lifted. foo(10).get -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] Error: Access to required field 'empty' yielded 'undefined' -//│ at foo (REPL10:1:755) -//│ at REPL13:1:58 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ = [10, 123] :w fun foo(x) = diff --git a/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls b/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls index b7b047f79d..4b4d372276 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls @@ -38,7 +38,7 @@ data class A(x) with //│ get A$instance() { return this.#A$instance; } //│ set A$instance(value) { this.#A$instance = value; } //│ getB() { -//│ return this.A$instance.class.x + this.y +//│ return this.A$instance.x + this.y //│ } //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "B", ["y"]]; @@ -67,7 +67,7 @@ A(1).getA() //│ FAILURE: Unexpected runtime error //│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) //│ ═══[RUNTIME ERROR] TypeError: this.B is not a function -//│ at A.getA (REPL10:1:1494) +//│ at A.getA (REPL10:1:1488) //│ at REPL13:1:81 //│ at ContextifyScript.runInThisContext (node:vm:137:12) //│ at REPLServer.defaultEval (node:repl:593:22) diff --git a/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls b/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls index a38e934f72..02e8219fe7 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls @@ -211,9 +211,9 @@ M.hi.get //│ FAILURE: Unexpected runtime error //│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) //│ ═══[RUNTIME ERROR] TypeError: this.A is not a function -//│ at new M12 (REPL62:1:1145) -//│ at (REPL62:1:1049) -//│ at REPL62:1:1298 +//│ at new M12 (REPL62:1:1139) +//│ at (REPL62:1:1043) +//│ at REPL62:1:1292 //│ at ContextifyScript.runInThisContext (node:vm:137:12) //│ at REPLServer.defaultEval (node:repl:593:22) //│ at bound (node:domain:433:15) @@ -306,8 +306,8 @@ M.A(2).newB.newA_B(3).newB.get //│ FAILURE: Unexpected runtime error //│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) //│ ═══[RUNTIME ERROR] TypeError: this.B is not a function -//│ at get newB (REPL74:1:1737) -//│ at REPL74:1:2121 +//│ at get newB (REPL74:1:1731) +//│ at REPL74:1:2115 //│ at ContextifyScript.runInThisContext (node:vm:137:12) //│ at REPLServer.defaultEval (node:repl:593:22) //│ at bound (node:domain:433:15) From 55ba010783097bff6f5b088ff2f7a3a3fa7b2b8d Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Fri, 31 Oct 2025 12:35:20 +0800 Subject: [PATCH 09/55] Resolve symbols for inner SynthSel --- .../main/scala/hkmc2/semantics/Resolver.scala | 70 ++++++++++++++----- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 3ddc9b704f..aab3e180e6 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -521,7 +521,7 @@ class Resolver(tl: TraceLogger) */ def resolve(t: Resolvable, prefer: Expect, inAppPrefix: Bool, inCtxPrefix: Bool, inTyPrefix: Bool)(using ICtx): (Opt[CallableDefinition], ICtx) = trace[(Opt[CallableDefinition], ICtx)]( - s"Resolving resolvable term: ${t}, (inPrefix = ${inTyPrefix})", + s"Resolving resolvable term: ${t}, (prefer = ${prefer}, inAppPrefix = ${inAppPrefix}, inCtxPrefix = ${inCtxPrefix}, inTyPrefix = ${inTyPrefix})", _ => s"~> ${t.expanded} (sym = ${t.resolvedSym}, typ = ${t.resolvedTyp})" ): // Resolve the sub-resolvable-terms of the term. @@ -574,7 +574,7 @@ class Resolver(tl: TraceLogger) (N, ictx) t.expandedResolvableIn: t => - log(s"Resolving resolvable term ${t} with sym = ${t.resolvedSym}, typ = ${t.resolvedTyp}: ${t.resolvedSym.map(_.asInstanceOf[MemberSymbol[?]].defn)}") + log(s"Resolving resolvable term ${t} with sym = ${t.resolvedSym}, typ = ${t.resolvedTyp}") // Fill the context with possibly the type arguments information. val newICtx2 = newICtx1.givenIn: @@ -844,25 +844,57 @@ class Resolver(tl: TraceLogger) case t @ AnySel(lhs: Resolvable, id) => lhs.expandedResolvableIn: lhs => log(s"Resolving symbol for selection ${t}, defn = ${lhs.defn}") - lhs.singletonDefn.foreach: mdef => - val fsym = mdef.body.members.get(id.name) + + // Signleton Definitions + lhs.singletonDefn.foreach: defn => + val fsym = defn.body.members.get(id.name) fsym match - case S(bms: BlockMemberSymbol) => - log(s"Resolving symbol for ${t}, defn = ${lhs.defn}") - disambSym(prefer, sign)(bms) match - case S(ds) => - t.expand(S(Term.Resolved(t.withSym(bms), ds)(N))) + case S(bms: BlockMemberSymbol) => + log(s"Resolving symbol for ${t}, defn = ${lhs.defn}") + disambSym(prefer, sign)(bms) match + case S(ds) => + t.expand(S(Term.Resolved(t.withSym(bms), ds)(N))) + case N => + log(s"Unable to disambiguate ${bms}") + t.expand(S(t.withSym(bms))) + log(s"Resolved symbol for ${t}: ${bms}") + case N => + t.expand(S(t.withSym(ErrorSymbol(id.name, Tree.Dummy)))) + raise: + ErrorReport( + msg"${defn.kind.desc.capitalize} '${defn.sym.nme}' " + + msg"does not contain member '${id.name}'" -> t.toLoc :: Nil, + extraInfo = S(defn)) + + // Class-Like Definitions + lhs.defn.foreach: + case defn: ClassLikeDef => + // A reference to a member within the class is elaborated into a SynthSel, e.g., + // class C with + // fun f = 42 + // f + // The `f` in the body is elaborated into SynthSel(class:Foo, 'f'). + val fsym = defn.body.members.get(id.name) + fsym match + case S(bms: BlockMemberSymbol) => + log(s"Resolving symbol for ${t}, defn = ${lhs.defn}") + disambSym(prefer, sign)(bms) match + case S(ds) => + t.expand(S(Term.Resolved(t.withSym(bms), ds)(N))) + case N => + log(s"Unable to disambiguate ${bms}") + t.expand(S(t.withSym(bms))) + log(s"Resolved symbol for ${t}: ${bms}") case N => - log(s"Unable to disambiguate ${bms}") - t.expand(S(t.withSym(bms))) - log(s"Resolved symbol for ${t}: ${bms}") - case N => - t.expand(S(t.withSym(ErrorSymbol(id.name, Tree.Dummy)))) - raise: - ErrorReport( - msg"${mdef.kind.desc.capitalize} '${mdef.sym.nme}' " + - msg"does not contain member '${id.name}'" -> t.toLoc :: Nil, - extraInfo = S(mdef)) + // TODO @Harry: Appropriately resolve all selections on classes. + // t.expand(S(t.withSym(ErrorSymbol(id.name, Tree.Dummy)))) + // raise: + // ErrorReport( + // msg"${defn.kind.desc.capitalize} '${defn.sym.nme}' " + + // msg"does not contain member '${id.name}'" -> t.toLoc :: Nil, + // extraInfo = S(defn))' + case defn => + log(s"Unsupported selection from definition: ${defn}") case _ => /** From cd3ac616c5dd02a50a09b87c3db247ac032d7a75 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Fri, 31 Oct 2025 12:39:11 +0800 Subject: [PATCH 10/55] Fix Effect Handler --- .../scala/hkmc2/codegen/HandlerLowering.scala | 2 +- .../src/test/mlscript/handlers/Effects.mls | 74 +----------- .../mlscript/handlers/EffectsInClasses.mls | 14 +-- .../mlscript/handlers/EffectsInMethods.mls | 106 +---------------- .../mlscript/handlers/HandlersInMethods.mls | 63 +--------- .../test/mlscript/handlers/UserThreads.mls | 12 -- .../mlscript/handlers/UserThreadsSafe.mls | 108 +++--------------- 7 files changed, 34 insertions(+), 345 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala index 725abffcc3..342f7a8ed5 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala @@ -591,7 +591,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, f.owner match case None => S(Call(f.sym.asPath, params)(true, true)) case Some(owner) => - S(Call(Select(owner.asPath, Tree.Ident(f.sym.nme))(S(f.innerSym.asInstanceOf)), params)(true, true)) + S(Call(Select(owner.asPath, Tree.Ident(f.sym.nme))(f.innerSym.asInstanceOf), params)(true, true)) // TODO: ^^^^^^^^ // TODO: @Harry check again on asInstanceOf case _ => None // TODO: more than one plist diff --git a/hkmc2/shared/src/test/mlscript/handlers/Effects.mls b/hkmc2/shared/src/test/mlscript/handlers/Effects.mls index 9d4c1fbc08..41f5579d45 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/Effects.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/Effects.mls @@ -230,57 +230,11 @@ module A with data class Effect(x) with fun test() = x fun perform(arg) -//│ FAILURE: Unexpected exception -//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) -//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) -//│ at: scala.collection.immutable.List.map(List.scala:247) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) -//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) -//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) -//│ at: hkmc2.codegen.HandlerLowering.firstPass(HandlerLowering.scala:536) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateBlock(HandlerLowering.scala:477) handle h = A.Effect(3) with fun perform()(k) = 0 h.perform() -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: lookup_! (Scope.scala:112) -//│ FAILURE INFO: Tuple2: -//│ _1 = Tuple2: -//│ _1 = member:A -//│ _2 = class hkmc2.semantics.BlockMemberSymbol -//│ _2 = Scope: -//│ parent = N -//│ curThis = S of S of globalThis:globalThis -//│ bindings = HashMap(class:Cont$func$lambda$ -> Cont$func$lambda$, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$6, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$3, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$3, $runtime -> runtime, class:Handler$h$ -> Handler$h$, $definitionMetadata -> definitionMetadata, $prettyPrint -> prettyPrint, $block$res -> block$res14, $Term -> Term, $tmp -> tmp11, class:Handler$h$ -> Handler$h$3, $block$res -> block$res2, $tmp -> tmp, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$, class:Cont$func$foo$ -> Cont$func$foo$1, member:handleBlock$ -> handleBlock$11, $block$res -> block$res5, $tmp -> tmp3, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$5, class:Handler$h$ -> Handler$h$12, member:handleBlock$ -> handleBlock$, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$4, member:handleBlock$ -> handleBlock$3, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$2, class:Handler$h$ -> Handler$h$11, $block$res -> block$res15, $tmp -> tmp12, $selRes -> selRes, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$2, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$10, $res -> res, class:Cont$func$bar$ -> Cont$func$bar$, member:handleBlock$ -> handleBlock$12, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$1, member:foo -> foo2, class:Handler$h$ -> Handler$h$2, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$11, class:Handler$h$ -> Handler$h$9, member:foo -> foo1, $block$res -> block$res4, $tmp -> tmp2, member:foo -> foo, $block$res -> block$res8, member:handleBlock$ -> handleBlock$2, member:bar -> bar, class:Cont$func$foobar$ -> Cont$func$foobar$, member:foobar -> foobar, member:foo -> foo3, class:Handler$h$ -> Handler$h$5, class:Handler$h$ -> Handler$h$8, $block$res -> block$res12, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, $tmp -> tmp9, member:handleBlock$ -> handleBlock$10, $block$res -> block$res7, class:Handler$h$ -> Handler$h$1, $block$res -> block$res11, $tmp -> tmp5, result -> result, $tmp -> tmp8, class:Handler$h$ -> Handler$h$6, class:Handler$h$ -> Handler$h$7, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$9, $block$res -> block$res, member:handleBlock$ -> handleBlock$8, $block$res -> block$res3, $tmp -> tmp1, class:Handler$h$ -> Handler$h$10, member:Predef -> Predef, class:Cont$func$foo$ -> Cont$func$foo$, class:Handler$h$ -> Handler$h$4, member:Effect -> Effect1, class:Effect -> Effect, member:handleBlock$ -> handleBlock$1, $block$res -> block$res9, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$7, $tmp -> tmp6, $block$res -> block$res10, member:handleBlock$ -> handleBlock$5, $tmp -> tmp7, $block$res -> block$res1, $block$res -> block$res6, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $tmp -> tmp4, member:handleBlock$ -> handleBlock$6, $block$res -> block$res13, class:Cont$handler$h$perform$ -> Cont$handler$h$perform$5, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$4, member:handleBlock$ -> handleBlock$9, member:handleBlock$ -> handleBlock$7, member:handleBlock$ -> handleBlock$4, $tmp -> tmp10, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$8) -//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'A' -//│ ║ l.246: handle h = A.Effect(3) with -//│ ║ ^ -//│ ╟── which references the symbol introduced here -//│ ║ l.229: module A with -//│ ║ ^^^^^^ -//│ ║ l.230: data class Effect(x) with -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.231: fun test() = x -//│ ║ ^^^^^^^^^^^^^^^^^^ -//│ ║ l.232: fun perform(arg) -//│ ╙── ^^^^^^^^^^^^^^^^^^^^ -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] ReferenceError: A is not defined -//│ at REPL53:1:46 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) -//│ at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:613:22) +//│ = 0 fun f(perform) = handle h = Effect with @@ -414,18 +368,7 @@ fun foo(h) = handle h = Eff with fun perform()(k) = k(()) foo(h) -//│ FAILURE: Unexpected exception -//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) -//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) -//│ at: scala.collection.immutable.List.map(List.scala:247) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) -//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) -//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) -//│ at: hkmc2.codegen.BlockTransformer.applySubBlock(BlockTransformer.scala:16) -//│ at: hkmc2.codegen.BlockTransformer.applyBlock$$anonfun$3$$anonfun$1(BlockTransformer.scala:38) +//│ = 123 :expect 123 fun foo(h) = @@ -451,18 +394,7 @@ fun foo(h) = handle h = Eff with fun perform()(k) = k(()) foo(h) -//│ FAILURE: Unexpected exception -//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) -//│ at: hkmc2.codegen.HandlerLowering.translateBody$$anonfun$1(HandlerLowering.scala:616) -//│ at: scala.collection.immutable.List.map(List.scala:247) -//│ at: hkmc2.codegen.HandlerLowering.translateBody(HandlerLowering.scala:616) -//│ at: hkmc2.codegen.HandlerLowering.$anonfun$13(HandlerLowering.scala:628) -//│ at: scala.Option.map(Option.scala:242) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:628) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) -//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) -//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) +//│ = 123 // Access superclass fields handle h1 = Object with diff --git a/hkmc2/shared/src/test/mlscript/handlers/EffectsInClasses.mls b/hkmc2/shared/src/test/mlscript/handlers/EffectsInClasses.mls index 01d6e39abf..fbef803763 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/EffectsInClasses.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/EffectsInClasses.mls @@ -158,15 +158,5 @@ module A with let obj = new Object with fun foo() = print("Hello") foo() -//│ FAILURE: Unexpected exception -//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) -//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) -//│ at: scala.collection.immutable.List.map(List.scala:247) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) -//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) -//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) -//│ at: hkmc2.codegen.BlockTransformer.applySubBlock(BlockTransformer.scala:16) -//│ at: hkmc2.codegen.BlockTransformer.applyBlock$$anonfun$3$$anonfun$2(BlockTransformer.scala:43) +//│ > Hello +//│ obj = $anon diff --git a/hkmc2/shared/src/test/mlscript/handlers/EffectsInMethods.mls b/hkmc2/shared/src/test/mlscript/handlers/EffectsInMethods.mls index f35e5d53ee..8d9b6c4188 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/EffectsInMethods.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/EffectsInMethods.mls @@ -10,111 +10,17 @@ class Test with fun p(h, x) = h.perform("A", x) + h.perform("B", x + 1) let t = new Test -//│ FAILURE: Unexpected exception -//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) -//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) -//│ at: scala.collection.immutable.List.map(List.scala:247) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) -//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) -//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) -//│ at: hkmc2.codegen.HandlerLowering.firstPass(HandlerLowering.scala:536) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateBlock(HandlerLowering.scala:477) +//│ t = Test handle h = Effect with fun perform(arg, x)(k) = print(arg) k(x * 2) [t.p(h, 2), t.p(h, 3)] -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: lookup_! (Scope.scala:112) -//│ FAILURE INFO: Tuple2: -//│ _1 = Tuple2: -//│ _1 = t -//│ _2 = class hkmc2.semantics.VarSymbol -//│ _2 = Scope: -//│ parent = S of Scope: -//│ parent = S of Scope: -//│ parent = S of Scope: -//│ parent = S of Scope: -//│ parent = S of Scope: -//│ parent = N -//│ curThis = S of S of globalThis:globalThis -//│ bindings = HashMap(class:Cont$handler$h$perform$ -> Cont$handler$h$perform$, member:Predef -> Predef, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:Effect -> Effect1, $prettyPrint -> prettyPrint, class:Effect -> Effect, $Term -> Term, $block$res -> block$res1, $block$res -> block$res2, $tmp -> tmp, member:handleBlock$ -> handleBlock$, $block$res -> block$res, class:Handler$h$ -> Handler$h$) -//│ curThis = S of N -//│ bindings = HashMap($args -> args) -//│ curThis = N -//│ bindings = HashMap($tmp -> tmp1, member:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, $tmp -> tmp2, member:doUnwind -> doUnwind, member:Handler$h$ -> Handler$h$1, h -> h) -//│ curThis = S of S of class:Cont$handleBlock$h$ -//│ bindings = HashMap(pc -> pc) -//│ curThis = N -//│ bindings = HashMap($args -> args1, value$ -> value$) -//│ curThis = N -//│ bindings = HashMap($contLoop -> contLoop) -//│ ╔══[COMPILATION ERROR] No definition found in scope for member 't' -//│ ║ l.30: [t.p(h, 2), t.p(h, 3)] -//│ ║ ^ -//│ ╟── which references the symbol introduced here -//│ ║ l.12: let t = new Test -//│ ╙── ^ -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: lookup_! (Scope.scala:112) -//│ FAILURE INFO: Tuple2: -//│ _1 = Tuple2: -//│ _1 = t -//│ _2 = class hkmc2.semantics.VarSymbol -//│ _2 = Scope: -//│ parent = S of Scope: -//│ parent = S of Scope: -//│ parent = N -//│ curThis = S of S of globalThis:globalThis -//│ bindings = HashMap(class:Cont$handler$h$perform$ -> Cont$handler$h$perform$, member:Predef -> Predef, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:Effect -> Effect1, $prettyPrint -> prettyPrint, class:Effect -> Effect, $Term -> Term, $block$res -> block$res1, $block$res -> block$res2, $tmp -> tmp, member:handleBlock$ -> handleBlock$, $block$res -> block$res, class:Handler$h$ -> Handler$h$) -//│ curThis = S of N -//│ bindings = HashMap($args -> args) -//│ curThis = N -//│ bindings = HashMap($tmp -> tmp1, member:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, $tmp -> tmp2, member:doUnwind -> doUnwind, member:Handler$h$ -> Handler$h$1, h -> h) -//│ ╔══[COMPILATION ERROR] No definition found in scope for member 't' -//│ ║ l.30: [t.p(h, 2), t.p(h, 3)] -//│ ║ ^ -//│ ╟── which references the symbol introduced here -//│ ║ l.12: let t = new Test -//│ ╙── ^ -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: lookup_! (Scope.scala:112) -//│ FAILURE INFO: Tuple2: -//│ _1 = Tuple2: -//│ _1 = t -//│ _2 = class hkmc2.semantics.VarSymbol -//│ _2 = Scope: -//│ parent = S of Scope: -//│ parent = S of Scope: -//│ parent = N -//│ curThis = S of S of globalThis:globalThis -//│ bindings = HashMap(class:Cont$handler$h$perform$ -> Cont$handler$h$perform$, member:Predef -> Predef, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:Effect -> Effect1, $prettyPrint -> prettyPrint, class:Effect -> Effect, $Term -> Term, $block$res -> block$res1, $block$res -> block$res2, $tmp -> tmp, member:handleBlock$ -> handleBlock$, $block$res -> block$res, class:Handler$h$ -> Handler$h$) -//│ curThis = S of N -//│ bindings = HashMap($args -> args) -//│ curThis = N -//│ bindings = HashMap($tmp -> tmp1, member:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, $tmp -> tmp2, member:doUnwind -> doUnwind, member:Handler$h$ -> Handler$h$1, h -> h) -//│ ╔══[COMPILATION ERROR] No definition found in scope for member 't' -//│ ║ l.30: [t.p(h, 2), t.p(h, 3)] -//│ ║ ^ -//│ ╟── which references the symbol introduced here -//│ ║ l.12: let t = new Test -//│ ╙── ^ -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] ReferenceError: t is not defined -//│ at handleBlock$ (REPL13:1:4084) -//│ at REPL13:1:4411 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ > A +//│ > B +//│ > A +//│ > B +//│ = [10, 14] diff --git a/hkmc2/shared/src/test/mlscript/handlers/HandlersInMethods.mls b/hkmc2/shared/src/test/mlscript/handlers/HandlersInMethods.mls index b738c368cf..ad9f06f16e 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/HandlersInMethods.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/HandlersInMethods.mls @@ -14,64 +14,13 @@ class Test with k(x * 2) h.perform("A", x) + h.perform("B", x + 1) let t = new Test -//│ FAILURE: Unexpected exception -//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) -//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) -//│ at: scala.collection.immutable.List.map(List.scala:247) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) -//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) -//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) -//│ at: hkmc2.codegen.HandlerLowering.firstPass(HandlerLowering.scala:536) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateBlock(HandlerLowering.scala:477) +//│ t = Test [t.p(2), t.p(3)] -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: lookup_! (Scope.scala:112) -//│ FAILURE INFO: Tuple2: -//│ _1 = Tuple2: -//│ _1 = t -//│ _2 = class hkmc2.semantics.VarSymbol -//│ _2 = Scope: -//│ parent = N -//│ curThis = S of S of globalThis:globalThis -//│ bindings = HashMap(member:Predef -> Predef, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:Effect -> Effect1, $prettyPrint -> prettyPrint, class:Effect -> Effect, $Term -> Term, $block$res -> block$res1, $block$res -> block$res2, $tmp -> tmp, $tmp -> tmp1, $block$res -> block$res) -//│ ╔══[COMPILATION ERROR] No definition found in scope for member 't' -//│ ║ l.30: [t.p(2), t.p(3)] -//│ ║ ^ -//│ ╟── which references the symbol introduced here -//│ ║ l.16: let t = new Test -//│ ╙── ^ -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: lookup_! (Scope.scala:112) -//│ FAILURE INFO: Tuple2: -//│ _1 = Tuple2: -//│ _1 = t -//│ _2 = class hkmc2.semantics.VarSymbol -//│ _2 = Scope: -//│ parent = N -//│ curThis = S of S of globalThis:globalThis -//│ bindings = HashMap(member:Predef -> Predef, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:Effect -> Effect1, $prettyPrint -> prettyPrint, class:Effect -> Effect, $Term -> Term, $block$res -> block$res1, $block$res -> block$res2, $tmp -> tmp, $tmp -> tmp1, $block$res -> block$res) -//│ ╔══[COMPILATION ERROR] No definition found in scope for member 't' -//│ ║ l.30: [t.p(2), t.p(3)] -//│ ║ ^ -//│ ╟── which references the symbol introduced here -//│ ║ l.16: let t = new Test -//│ ╙── ^ -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] ReferenceError: t is not defined -//│ at REPL13:1:44 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) -//│ at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:613:22) +//│ > A +//│ > B +//│ > A +//│ > B +//│ = [10, 14] diff --git a/hkmc2/shared/src/test/mlscript/handlers/UserThreads.mls b/hkmc2/shared/src/test/mlscript/handlers/UserThreads.mls index 3cfe6c58d3..0aef56f838 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/UserThreads.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/UserThreads.mls @@ -15,18 +15,6 @@ class Lock(locked) with set locked = true fun unlock() = set locked = false -//│ FAILURE: Unexpected exception -//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) -//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) -//│ at: scala.collection.immutable.List.map(List.scala:247) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) -//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) -//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) -//│ at: hkmc2.codegen.HandlerLowering.firstPass(HandlerLowering.scala:536) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateBlock(HandlerLowering.scala:477) fun f(h, x) = print("f " + x) diff --git a/hkmc2/shared/src/test/mlscript/handlers/UserThreadsSafe.mls b/hkmc2/shared/src/test/mlscript/handlers/UserThreadsSafe.mls index 9817594861..c240949e57 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/UserThreadsSafe.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/UserThreadsSafe.mls @@ -10,18 +10,6 @@ class ThreadEffect with tasks.pop()() fun fork(thread: () -> ()): () fun yld(): () -//│ FAILURE: Unexpected exception -//│ /!!!\ Uncaught error: java.lang.ClassCastException: Cannot cast to scala.Nothing -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateFun(HandlerLowering.scala:594) -//│ at: hkmc2.codegen.HandlerLowering.$anonfun$12(HandlerLowering.scala:626) -//│ at: scala.collection.immutable.List.map(List.scala:247) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateCls(HandlerLowering.scala:626) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyDefn(HandlerLowering.scala:534) -//│ at: hkmc2.codegen.BlockTransformer.applyBlock(BlockTransformer.scala:75) -//│ at: hkmc2.codegen.BlockTransformerShallow.applyBlock(BlockTransformer.scala:288) -//│ at: hkmc2.codegen.HandlerLowering$$anon$2.applyBlock(HandlerLowering.scala:509) -//│ at: hkmc2.codegen.HandlerLowering.firstPass(HandlerLowering.scala:536) -//│ at: hkmc2.codegen.HandlerLowering.hkmc2$codegen$HandlerLowering$$translateBlock(HandlerLowering.scala:477) fun f(h, x)() = @@ -51,46 +39,14 @@ handle h = ThreadEffect with this.drain() in main(h) -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: lookup_! (Scope.scala:112) -//│ FAILURE INFO: Tuple2: -//│ _1 = Tuple2: -//│ _1 = member:ThreadEffect -//│ _2 = class hkmc2.semantics.BlockMemberSymbol -//│ _2 = Scope: -//│ parent = S of Scope: -//│ parent = S of Scope: -//│ parent = S of Scope: -//│ parent = N -//│ curThis = S of S of globalThis:globalThis -//│ bindings = HashMap(member:getLocals -> getLocals2, member:Predef -> Predef, member:getLocals -> getLocals, class:Handler$h$ -> Handler$h$, $runtime -> runtime, member:getLocals -> getLocals1, member:main -> main, member:getLocals -> getLocals3, $definitionMetadata -> definitionMetadata, member:handleBlock$ -> handleBlock$, $prettyPrint -> prettyPrint, class:Cont$handler$h$yld$ -> Cont$handler$h$yld$, $Term -> Term, class:Cont$func$main$ -> Cont$func$main$, member:f -> f, class:Cont$func$f$ -> Cont$func$f$, class:Cont$handler$h$fork$ -> Cont$handler$h$fork$, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $block$res -> block$res2, $block$res -> block$res3, $block$res -> block$res1, $block$res -> block$res, $tmp -> tmp) -//│ curThis = S of N -//│ bindings = HashMap($args -> args) -//│ curThis = N -//│ bindings = HashMap(h -> h, member:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, member:Handler$h$ -> Handler$h$1, member:doUnwind -> doUnwind, member:getLocals -> getLocals4, $res -> res) -//│ curThis = S of S of class:Handler$h$ -//│ bindings = HashMap() -//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'ThreadEffect' -//│ ║ l.44: handle h = ThreadEffect with -//│ ║ ^^^^^^^^^^^^ -//│ ╟── which references the symbol introduced here -//│ ║ l.5: class ThreadEffect with -//│ ║ ^^^^^^^^^^^^^^^^^ -//│ ║ l.6: // task queue -//│ ║ ^^^^^^^^^^^^^^^ -//│ ║ l.7: val tasks = mut [] -//│ ║ ^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.8: fun drain() = -//│ ║ ^^^^^^^^^^^^^^^ -//│ ║ l.9: while tasks.length != 0 do -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.10: tasks.pop()() -//│ ║ ^^^^^^^^^^^^^^^^^^^ -//│ ║ l.11: fun fork(thread: () -> ()): () -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.12: fun yld(): () -//│ ╙── ^^^^^^^^^^^^^^^ -//│ ═══[RUNTIME ERROR] ReferenceError: ThreadEffect is not defined +//│ > main start +//│ > main end +//│ > f 2 +//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$ +//│ at f (UserThreadsSafe.mls:17:3) +//│ at drain (UserThreadsSafe.mls:10:7) +//│ at fork (UserThreadsSafe.mls:35:5) +//│ at fork (UserThreadsSafe.mls:35:5) // FIFO @@ -105,45 +61,13 @@ handle h = ThreadEffect with this.drain() in main(h) -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: lookup_! (Scope.scala:112) -//│ FAILURE INFO: Tuple2: -//│ _1 = Tuple2: -//│ _1 = member:ThreadEffect -//│ _2 = class hkmc2.semantics.BlockMemberSymbol -//│ _2 = Scope: -//│ parent = S of Scope: -//│ parent = S of Scope: -//│ parent = S of Scope: -//│ parent = N -//│ curThis = S of S of globalThis:globalThis -//│ bindings = HashMap(class:Handler$h$ -> Handler$h$, $runtime -> runtime, member:main -> main, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$1, $definitionMetadata -> definitionMetadata, $prettyPrint -> prettyPrint, $Term -> Term, member:f -> f, class:Cont$handler$h$fork$ -> Cont$handler$h$fork$, $block$res -> block$res2, $block$res -> block$res3, class:Handler$h$ -> Handler$h$1, $block$res -> block$res1, $block$res -> block$res, $tmp -> tmp, member:getLocals -> getLocals2, member:Predef -> Predef, member:getLocals -> getLocals, class:Cont$handler$h$fork$ -> Cont$handler$h$fork$1, member:getLocals -> getLocals1, member:getLocals -> getLocals3, member:handleBlock$ -> handleBlock$, class:Cont$handler$h$yld$ -> Cont$handler$h$yld$, class:Cont$func$main$ -> Cont$func$main$, $block$res -> block$res4, class:Cont$func$f$ -> Cont$func$f$, class:Cont$handleBlock$h$ -> Cont$handleBlock$h$, $tmp -> tmp1, member:getLocals -> getLocals4, member:handleBlock$ -> handleBlock$1, class:Cont$handler$h$yld$ -> Cont$handler$h$yld$1) -//│ curThis = S of N -//│ bindings = HashMap($args -> args) -//│ curThis = N -//│ bindings = HashMap(member:getLocals -> getLocals5, $res -> res, h -> h, member:Cont$handleBlock$h$ -> Cont$handleBlock$h$2, member:Handler$h$ -> Handler$h$2, member:doUnwind -> doUnwind) -//│ curThis = S of S of class:Handler$h$ -//│ bindings = HashMap() -//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'ThreadEffect' -//│ ║ l.98: handle h = ThreadEffect with -//│ ║ ^^^^^^^^^^^^ -//│ ╟── which references the symbol introduced here -//│ ║ l.5: class ThreadEffect with -//│ ║ ^^^^^^^^^^^^^^^^^ -//│ ║ l.6: // task queue -//│ ║ ^^^^^^^^^^^^^^^ -//│ ║ l.7: val tasks = mut [] -//│ ║ ^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.8: fun drain() = -//│ ║ ^^^^^^^^^^^^^^^ -//│ ║ l.9: while tasks.length != 0 do -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.10: tasks.pop()() -//│ ║ ^^^^^^^^^^^^^^^^^^^ -//│ ║ l.11: fun fork(thread: () -> ()): () -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.12: fun yld(): () -//│ ╙── ^^^^^^^^^^^^^^^ -//│ ═══[RUNTIME ERROR] ReferenceError: ThreadEffect is not defined +//│ > main start +//│ > main end +//│ > f 0 +//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$1 +//│ at f (UserThreadsSafe.mls:17:3) +//│ at drain (UserThreadsSafe.mls:10:7) +//│ at fork (UserThreadsSafe.mls:57:5) +//│ at fork (UserThreadsSafe.mls:57:5) From 66a700bbe10d6d2a809f6712d42655fd20555cfd Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Fri, 31 Oct 2025 14:10:31 +0800 Subject: [PATCH 11/55] Fix LLIR --- .../main/scala/hkmc2/codegen/Lowering.scala | 2 + .../scala/hkmc2/semantics/Elaborator.scala | 4 +- .../main/scala/hkmc2/semantics/Resolver.scala | 29 ++-- .../src/main/scala/hkmc2/semantics/Term.scala | 8 +- .../mlscript/basics/BadMemberProjections.mls | 18 +- .../mlscript/basics/MemberProjections.mls | 18 +- .../src/test/mlscript/bbml/bbErrors.mls | 13 +- .../shared/src/test/mlscript/llir/Classes.mls | 26 ++- hkmc2/shared/src/test/mlscript/llir/Lazy.mls | 72 +++++++- .../src/test/mlscript/llir/LazyCycle.mls | 154 +++++++++++++++++- .../shared/src/test/mlscript/llir/Method.mls | 17 +- 11 files changed, 307 insertions(+), 54 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index 7695ab33be..52e5d66adb 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -760,6 +760,8 @@ class Lowering()(using Config, TL, Raise, State, Ctx): // * BbML-specific cases: t.Cls#field and mutable operations case sp @ SelProj(prefix, _, proj) => setupSelection(prefix, proj, sp.sym, N)(k) + case Resolved(sp @ SelProj(prefix, _, proj), sym) => + setupSelection(prefix, proj, sp.sym, S(sym))(k) case Region(reg, body) => Assign(reg, Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Region"))(N), Nil), term_nonTail(body)(k)) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index dccb2391e6..7eca8260d8 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -554,7 +554,7 @@ extends Importer: case _ => raise(ErrorReport(msg"Identifier `${idn.name}` does not name a known class symbol." -> idn.toLoc :: Nil)) N - Term.SelProj(subterm(pre), c, idp)(f) + Term.SelProj(subterm(pre), c, idp)(f, N) case App(Ident("#"), Tup(Sel(pre, Ident(name)) :: App(Ident(proj), args) :: Nil)) => subterm(App(App(Ident("#"), Tup(Sel(pre, Ident(name)) :: Ident(proj) :: Nil)), args)) case App(Ident("!"), Tup(rhs :: Nil)) => @@ -635,7 +635,7 @@ extends Importer: ) val rs = FlowSymbol.app() Term.Lam(ps, - Term.App(Term.SelProj(self.ref(), c, nme)(f), args.ref())( + Term.App(Term.SelProj(self.ref(), c, nme)(f, N), args.ref())( App(nme, Tup(Nil)) // FIXME , N, rs) ) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index aab3e180e6..7dbb9b9bc2 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -555,13 +555,17 @@ class Resolver(tl: TraceLogger) targs.foreach(traverse(_, expect = Any)) (t.callableDefn, ictx) - case AnySel(pre: Resolvable, id) => + case AnySel(pre: Resolvable, id, cls) => resolve(pre, prefer = Selectable(N), inAppPrefix = false, inCtxPrefix = false, inTyPrefix = false) + cls.foreach: + case cls: Resolvable => resolve(cls, prefer = Class(N), inAppPrefix = false, inCtxPrefix = false, inTyPrefix = false) + case cls => traverse(cls, expect = Class(N)) resolveSymbol(t, prefer = prefer, sign = false) resolveType(t, prefer = prefer) (t.callableDefn, ictx) - case AnySel(pre, id) => + case AnySel(pre, id, cls) => traverse(pre, expect = Selectable(N)) + cls.foreach(traverse(_, expect = Class(N))) (t.callableDefn, ictx) case Term.Ref(_: BlockMemberSymbol) => @@ -842,10 +846,14 @@ class Resolver(tl: TraceLogger) resolveType(t, prefer = prefer) log(s"Resolved symbol for ${t}: ${sym}") - case t @ AnySel(lhs: Resolvable, id) => lhs.expandedResolvableIn: lhs => + case t @ AnySel(lhs: Resolvable, id, cls) => lhs.expandedResolvableIn: lhs => log(s"Resolving symbol for selection ${t}, defn = ${lhs.defn}") - // Signleton Definitions + val clsDefn = cls.flatMap: sym => + sym.resolvedSym.flatMap(_.asCls).map: clsSym => + clsSym.defn.getOrElse(die) + + // Singleton Definitions lhs.singletonDefn.foreach: defn => val fsym = defn.body.members.get(id.name) fsym match @@ -867,7 +875,7 @@ class Resolver(tl: TraceLogger) extraInfo = S(defn)) // Class-Like Definitions - lhs.defn.foreach: + (clsDefn orElse lhs.defn).foreach: case defn: ClassLikeDef => // A reference to a member within the class is elaborated into a SynthSel, e.g., // class C with @@ -1007,8 +1015,8 @@ class Resolver(tl: TraceLogger) case Term.App(Term.Ref(_: BuiltinSymbol), Term.Tup(Fld(term = Term.Lit(_)) :: Nil)) => // Selection. The prefix should be a term, rather than a type, that - // can be selected from. - case AnySel(base, _) => + // can be selected from. This should not be a selection projection. + case AnySel(base, _, N) => base.subTerms.foreach(traverse(_, expect = Any)) // Type Application. Traverse the type constructor and arguments, @@ -1132,9 +1140,10 @@ class Resolver(tl: TraceLogger) end Resolver object AnySel: - def unapply(t: (Term.Sel | Term.SynthSel)): S[(Term, Tree.Ident)] = t match - case Term.Sel(lhs, id) => S((lhs, id)) - case Term.SynthSel(lhs, id) => S((lhs, id)) + def unapply(t: (Term.Sel | Term.SynthSel | Term.SelProj)): S[(Term, Tree.Ident, Opt[Term])] = t match + case Term.Sel(lhs, id) => S((lhs, id, N)) + case Term.SynthSel(lhs, id) => S((lhs, id, N)) + case Term.SelProj(lhs, cls, proj) => S((lhs, proj, S(cls))) object ModuleChecker: diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index e2cea3d874..da7aefba8f 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -59,6 +59,7 @@ sealed trait ResolvableImpl: case t: Term.TyApp => t.copy()(t.typ) case t: Term.Sel => t.copy()(t.sym, t.typ) case t: Term.SynthSel => t.copy()(t.sym, t.typ) + case t: Term.SelProj => t.copy()(t.sym, t.typ) .withLocOf(this) .asInstanceOf @@ -66,6 +67,7 @@ sealed trait ResolvableImpl: this.match case t: Term.Sel => t.copy()(S(sym), t.typ) case t: Term.SynthSel => t.copy()(S(sym), t.typ) + case t: Term.SelProj => t.copy()(S(sym), t.typ) case _ => lastWords(s"Cannot attach a symbol to a non-selection term: ${this.show}") .withLocOf(this) .asInstanceOf @@ -78,6 +80,7 @@ sealed trait ResolvableImpl: case t: Term.TyApp => t.copy()(S(typ)) case t: Term.Sel => t.copy()(t.sym, S(typ)) case t: Term.SynthSel => t.copy()(t.sym, S(typ)) + case t: Term.SelProj => t.copy()(t.sym, S(typ)) .withLocOf(this) .asInstanceOf @@ -206,6 +209,8 @@ enum Term extends Statement: (val sym: Opt[FieldSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl case SynthSel(prefix: Term, nme: Tree.Ident) (val sym: Opt[FieldSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl + case SelProj(prefix: Term, cls: Term, proj: Tree.Ident) + (val sym: Opt[FieldSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl case DynSel(prefix: Term, fld: Term, arrayIdx: Bool) case Tup(fields: Ls[Elem])(val tree: Tree.Tup) case Mut(underlying: Tup | Rcd | New | DynNew) @@ -221,7 +226,6 @@ enum Term extends Statement: case Unquoted(body: Term) case New(cls: Term, args: Ls[Term], rft: Opt[ClassSymbol -> ObjBody]) case DynNew(cls: Term, args: Ls[Term]) - case SelProj(prefix: Term, cls: Term, proj: Tree.Ident)(val sym: Opt[FieldSymbol]) case Asc(term: Term, ty: Term) case CompType(lhs: Term, rhs: Term, pol: Bool) case Neg(rhs: Term) @@ -330,7 +334,7 @@ enum Term extends Statement: New(cls.mkClone, args.map(_.mkClone), rft.map { case (cs, ob) => cs -> ObjBody(ob.blk.mkBlkClone) }) case DynNew(cls, args) => DynNew(cls.mkClone, args.map(_.mkClone)) case term @ SelProj(prefix, cls, proj) => - SelProj(prefix.mkClone, cls.mkClone, Tree.Ident(proj.name))(term.sym) + SelProj(prefix.mkClone, cls.mkClone, Tree.Ident(proj.name))(term.sym, term.typ) case Asc(term, ty) => Asc(term.mkClone, ty.mkClone) case CompType(lhs, rhs, pol) => CompType(lhs.mkClone, rhs.mkClone, pol) case Neg(rhs) => Neg(rhs.mkClone) diff --git a/hkmc2/shared/src/test/mlscript/basics/BadMemberProjections.mls b/hkmc2/shared/src/test/mlscript/basics/BadMemberProjections.mls index 917d9f6a02..3873c91b9a 100644 --- a/hkmc2/shared/src/test/mlscript/basics/BadMemberProjections.mls +++ b/hkmc2/shared/src/test/mlscript/basics/BadMemberProjections.mls @@ -9,6 +9,9 @@ //│ ║ ^ //│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection; //│ ╙── add a space before ‹identifier› to make it an operator application. +//│ ╔══[ERROR] Expected a statically known class; found integer literal. +//│ ║ l.6: 1::x +//│ ╙── ^ //│ JS (unsanitized): //│ let lambda; //│ lambda = (undefined, function (self, ...args) { return runtime.safeCall(self.x(...args)) }); @@ -20,10 +23,13 @@ :re 1::x() //│ ╔══[ERROR] Integer literal is not a known class. -//│ ║ l.21: 1::x() +//│ ║ l.24: 1::x() //│ ║ ^ //│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection; //│ ╙── add a space before ‹identifier› to make it an operator application. +//│ ╔══[ERROR] Expected a statically known class; found integer literal. +//│ ║ l.24: 1::x() +//│ ╙── ^ //│ JS: //│ lambda1 = (undefined, function (...args1) { //│ runtime.checkArgs("", 1, false, args1.length); @@ -50,19 +56,25 @@ let x = 1 :e "A"::x //│ ╔══[ERROR] String literal is not a known class. -//│ ║ l.51: "A"::x +//│ ║ l.57: "A"::x //│ ║ ^^^ //│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection; //│ ╙── add a space before ‹identifier› to make it an operator application. +//│ ╔══[ERROR] Expected a statically known class; found string literal. +//│ ║ l.57: "A"::x +//│ ╙── ^^^ //│ = fun :e "A" ::x //│ ╔══[ERROR] String literal is not a known class. -//│ ║ l.60: "A" ::x +//│ ║ l.69: "A" ::x //│ ║ ^^^ //│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection; //│ ╙── add a space before ‹identifier› to make it an operator application. +//│ ╔══[ERROR] Expected a statically known class; found string literal. +//│ ║ l.69: "A" ::x +//│ ╙── ^^^ //│ = fun diff --git a/hkmc2/shared/src/test/mlscript/basics/MemberProjections.mls b/hkmc2/shared/src/test/mlscript/basics/MemberProjections.mls index 8a945a7d69..c22fcf695c 100644 --- a/hkmc2/shared/src/test/mlscript/basics/MemberProjections.mls +++ b/hkmc2/shared/src/test/mlscript/basics/MemberProjections.mls @@ -81,13 +81,14 @@ foo.Foo#m() //│ ╔══[ERROR] Identifier `Foo` does not name a known class symbol. //│ ║ l.77: foo.Foo#m() //│ ╙── ^^^^ +//│ ═══[ERROR] Expected a statically known class; found ‹error›. //│ = 124 :e :re foo.M.Foo::m() //│ ╔══[ERROR] Selection is not a known class. -//│ ║ l.88: foo.M.Foo::m() +//│ ║ l.89: foo.M.Foo::m() //│ ║ ^^^ //│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection; //│ ╙── add a space before ‹identifier› to make it an operator application. @@ -97,36 +98,39 @@ foo.M.Foo::m() :re foo.M.Foo#m() //│ ╔══[ERROR] Name not found: Foo -//│ ║ l.98: foo.M.Foo#m() +//│ ║ l.99: foo.M.Foo#m() //│ ╙── ^^^^ //│ ╔══[ERROR] Identifier `Foo` does not name a known class symbol. -//│ ║ l.98: foo.M.Foo#m() +//│ ║ l.99: foo.M.Foo#m() //│ ╙── ^^^^ +//│ ═══[ERROR] Expected a statically known class; found ‹error›. //│ ═══[RUNTIME ERROR] Error: Access to required field 'M' yielded 'undefined' :e Foo::m //│ ╔══[ERROR] Name not found: Foo -//│ ║ l.108: Foo::m +//│ ║ l.110: Foo::m //│ ╙── ^^^ //│ ╔══[ERROR] Identifier is not a known class. -//│ ║ l.108: Foo::m +//│ ║ l.110: Foo::m //│ ║ ^^^ //│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection; //│ ╙── add a space before ‹identifier› to make it an operator application. +//│ ═══[ERROR] Expected a statically known class; found ‹error›. //│ = fun :e :sjs Foo::n(foo, 2) //│ ╔══[ERROR] Name not found: Foo -//│ ║ l.121: Foo::n(foo, 2) +//│ ║ l.124: Foo::n(foo, 2) //│ ╙── ^^^ //│ ╔══[ERROR] Identifier is not a known class. -//│ ║ l.121: Foo::n(foo, 2) +//│ ║ l.124: Foo::n(foo, 2) //│ ║ ^^^ //│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection; //│ ╙── add a space before ‹identifier› to make it an operator application. +//│ ═══[ERROR] Expected a statically known class; found ‹error›. //│ JS (unsanitized): //│ let lambda9; //│ lambda9 = (undefined, function (self, ...args) { diff --git a/hkmc2/shared/src/test/mlscript/bbml/bbErrors.mls b/hkmc2/shared/src/test/mlscript/bbml/bbErrors.mls index 1721148967..1988eb6c99 100644 --- a/hkmc2/shared/src/test/mlscript/bbml/bbErrors.mls +++ b/hkmc2/shared/src/test/mlscript/bbml/bbErrors.mls @@ -27,6 +27,7 @@ //│ ╔══[ERROR] Identifier `Foo` does not name a known class symbol. //│ ║ l.23: (1).Foo#a() //│ ╙── ^^^^ +//│ ═══[ERROR] Expected a statically known class; found ‹error›. //│ ═══[ERROR] Not a valid class: ‹error› //│ Type: ⊥ @@ -34,20 +35,20 @@ fun Oops() = 1 Oops().Oops#a() //│ ╔══[ERROR] Identifier `Oops` does not name a known class symbol. -//│ ║ l.35: Oops().Oops#a() +//│ ║ l.36: Oops().Oops#a() //│ ╙── ^^^^^ //│ ╔══[ERROR] Not a valid class: reference -//│ ║ l.35: Oops().Oops#a() +//│ ║ l.36: Oops().Oops#a() //│ ╙── ^^^^^ //│ Type: ⊥ data class Oops2() (new Oops2()).Oops2#a() //│ ╔══[ERROR] Class 'Oops2' does not contain member 'a'. -//│ ║ l.45: (new Oops2()).Oops2#a() +//│ ║ l.46: (new Oops2()).Oops2#a() //│ ╙── ^ //│ ╔══[ERROR] a is not a valid member in class Oops2 -//│ ║ l.45: (new Oops2()).Oops2#a() +//│ ║ l.46: (new Oops2()).Oops2#a() //│ ╙── ^^^^^^^^^^^^^^^^^^^^ //│ Type: ⊥ @@ -56,7 +57,7 @@ data class Oops2() fun inc(x) = x + 1 inc("oops") //│ ╔══[ERROR] Type error in string literal with expected type 'x -//│ ║ l.57: inc("oops") +//│ ║ l.58: inc("oops") //│ ║ ^^^^^^ //│ ╟── because: cannot constrain Str <: 'x //│ ╟── because: cannot constrain Str <: 'x @@ -66,7 +67,7 @@ inc("oops") fun inc(x) = x + 1 inc as Int //│ ╔══[ERROR] Type error in reference with expected type Int -//│ ║ l.67: inc as Int +//│ ║ l.68: inc as Int //│ ║ ^^^ //│ ╙── because: cannot constrain ('x) ->{⊥} (Int) <: Int //│ Type: Int diff --git a/hkmc2/shared/src/test/mlscript/llir/Classes.mls b/hkmc2/shared/src/test/mlscript/llir/Classes.mls index 0de40b6897..2bfb5b2433 100644 --- a/hkmc2/shared/src/test/mlscript/llir/Classes.mls +++ b/hkmc2/shared/src/test/mlscript/llir/Classes.mls @@ -24,8 +24,26 @@ fun main() = let d = Derived() d.Base#get() * d.Derived#get() main() -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: bErrStop (Builder.scala:22) -//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Ref(d,None),Ident(get)),List()) -//│ Stopped due to an error during the Llir generation +//│ LLIR: +//│ class Base() { +//│ def get() = +//│ 1 +//│ } +//│ class Derived() extends Base { +//│ def get1() = +//│ 2 +//│ } +//│ def main() = +//│ let x = Derived() in +//│ let x1 = Base.get(x) in +//│ let x2 = Derived.get(x) in +//│ let x3 = *(x1,x2) in +//│ x3 +//│ def entry() = +//│ let* (x4) = main() in +//│ x4 +//│ entry = entry +//│ +//│ Interpreted: +//│ 4 diff --git a/hkmc2/shared/src/test/mlscript/llir/Lazy.mls b/hkmc2/shared/src/test/mlscript/llir/Lazy.mls index 64322e0574..23cb1ccaa2 100644 --- a/hkmc2/shared/src/test/mlscript/llir/Lazy.mls +++ b/hkmc2/shared/src/test/mlscript/llir/Lazy.mls @@ -11,10 +11,6 @@ type LazyList[out T] = Lazy[LzList[T]] abstract class LzList[out T]: LzCons[T] | LzNil data class LzCons[out T](head: T, tail: LazyList[T]) extends LzList[T] object LzNil extends LzList -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: bErrStop (Builder.scala:22) -//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Ref(x,None),Ident(get)),List()) -//│ Stopped due to an error during the Llir generation :sllir :scpp @@ -27,7 +23,67 @@ fun main() = let y1 = force(x) // force again, but should not execute side_effect again () main() -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: bErrStop (Builder.scala:22) -//│ ═══[COMPILATION ERROR] Name not found: member:lazy -//│ Stopped due to an error during the Llir generation +//│ LLIR: +//│ class Lambda_lambda() extends Callable { +//│ def apply0() = +//│ let* (x) = side_effect() in +//│ x +//│ } +//│ def side_effect() = +//│ let* (x1) = $_builtin$_("println","executed") in +//│ 1 +//│ def main() = +//│ let x2 = Lambda_lambda() in +//│ let* (x3) = lazy(x2) in +//│ let* (x4) = force(x3) in +//│ let* (x5) = force(x3) in +//│ undefined +//│ def entry() = +//│ let* (x6) = main() in +//│ x6 +//│ entry = entry +//│ +//│ Cpp: +//│ #include "mlsprelude.h" +//│ struct _mls_Lambda_lambda; +//│ _mlsValue _mls_side_effect(); +//│ _mlsValue _mls_main(); +//│ _mlsValue _mls_entry(); +//│ struct _mls_Lambda_lambda: public _mls_Callable { +//│ +//│ constexpr static inline const char *typeName = "Lambda_lambda"; +//│ constexpr static inline uint32_t typeTag = nextTypeTag(); +//│ virtual void print() const override { std::printf("%s", typeName); } +//│ virtual void destroy() override { operator delete (this, std::align_val_t(_mlsAlignment)); } +//│ static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Lambda_lambda; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; return _mlsValue(_mlsVal); } +//│ virtual _mlsValue _mls_apply0(); +//│ }; +//│ _mlsValue _mls_side_effect() { +//│ _mlsValue _mls_retval; +//│ auto _mls_x1 = _mls_builtin_println(_mlsValue::create<_mls_Str>("executed")); +//│ _mls_retval = _mlsValue::fromIntLit(1); +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_main() { +//│ _mlsValue _mls_retval; +//│ auto _mls_x2 = _mlsValue::create<_mls_Lambda_lambda>(); +//│ auto _mls_x3 = _mls_lazy(_mls_x2); +//│ auto _mls_x4 = _mls_force(_mls_x3); +//│ auto _mls_x5 = _mls_force(_mls_x3); +//│ _mls_retval = _mlsValue::create<_mls_Unit>(); +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_entry() { +//│ _mlsValue _mls_retval; +//│ auto _mls_x6 = _mls_main(); +//│ _mls_retval = _mls_x6; +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_Lambda_lambda::_mls_apply0() { +//│ _mlsValue _mls_retval; +//│ auto _mls_x = _mls_side_effect(); +//│ _mls_retval = _mls_x; +//│ return _mls_retval; +//│ } +//│ _mlsValue _mlsMain() { return _mls_entry(); } +//│ int main() { return _mlsLargeStack(_mlsMainWrapper); } diff --git a/hkmc2/shared/src/test/mlscript/llir/LazyCycle.mls b/hkmc2/shared/src/test/mlscript/llir/LazyCycle.mls index 0cec5fff06..7a28a12aac 100644 --- a/hkmc2/shared/src/test/mlscript/llir/LazyCycle.mls +++ b/hkmc2/shared/src/test/mlscript/llir/LazyCycle.mls @@ -11,10 +11,6 @@ type LazyList[out T] = Lazy[LzList[T]] abstract class LzList[out T]: LzCons[T] | LzNil data class LzCons[out T](head: T, tail: LazyList[T]) extends LzList[T] object LzNil extends LzList -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: bErrStop (Builder.scala:22) -//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Ref(x,None),Ident(get)),List()) -//│ Stopped due to an error during the Llir generation :sllir :showWholeCpp @@ -22,7 +18,149 @@ fun llist(x) = fun f(x) = lazy(() => LzCons(x, f(x + 1))) f(x) llist(1) -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: bErrStop (Builder.scala:22) -//│ ═══[COMPILATION ERROR] Name not found: member:lazy -//│ Stopped due to an error during the Llir generation +//│ LLIR: +//│ class Lambda_lambda(lam_arg0,lam_arg1) extends Callable { +//│ def apply0() = +//│ let x = +(lam_arg0,1) in +//│ let x1 = Callable.apply1(lam_arg1,x) in +//│ let x2 = LzCons(lam_arg0,x1) in +//│ x2 +//│ } +//│ class Lambda_f() extends Callable { +//│ def apply1(x3) = +//│ let x4 = Lambda_lambda(x3,$_this$_) in +//│ let* (x5) = lazy(x4) in +//│ x5 +//│ } +//│ def llist(x6) = +//│ let x7 = Lambda_f() in +//│ let x8 = Callable.apply1(x7,x6) in +//│ x8 +//│ def entry() = +//│ let* (x9) = llist(1) in +//│ x9 +//│ entry = entry +//│ +//│ WholeProgramCpp: +//│ #include "mlsprelude.h" +//│ struct _mls_Lambda_f; +//│ struct _mls_Lambda_lambda; +//│ struct _mls_Lazy; +//│ struct _mls_LzList; +//│ struct _mls_LzCons; +//│ struct _mls_LzNil; +//│ _mlsValue _mls_entry2(); +//│ _mlsValue _mls_entry(); +//│ _mlsValue _mls_llist(_mlsValue); +//│ _mlsValue _mls_force(_mlsValue); +//│ _mlsValue _mls_lazy(_mlsValue); +//│ _mlsValue _mls_j(); +//│ _mlsValue _mls_entry1(); +//│ struct _mls_Lambda_f: public _mls_Callable { +//│ +//│ constexpr static inline const char *typeName = "Lambda_f"; +//│ constexpr static inline uint32_t typeTag = nextTypeTag(); +//│ virtual void print() const override { std::printf("%s", typeName); } +//│ virtual void destroy() override { operator delete (this, std::align_val_t(_mlsAlignment)); } +//│ static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Lambda_f; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; return _mlsValue(_mlsVal); } +//│ virtual _mlsValue _mls_apply1(_mlsValue); +//│ }; +//│ struct _mls_Lambda_lambda: public _mls_Callable { +//│ _mlsValue _mls_lam_arg0; +//│ _mlsValue _mls_lam_arg1; +//│ constexpr static inline const char *typeName = "Lambda_lambda"; +//│ constexpr static inline uint32_t typeTag = nextTypeTag(); +//│ virtual void print() const override { std::printf("%s", typeName); std::printf("("); this->_mls_lam_arg0.print(); std::printf(", "); this->_mls_lam_arg1.print(); std::printf(")"); } +//│ virtual void destroy() override { _mlsValue::destroy(this->_mls_lam_arg0); _mlsValue::destroy(this->_mls_lam_arg1); operator delete (this, std::align_val_t(_mlsAlignment)); } +//│ static _mlsValue create(_mlsValue _mls_lam_arg0, _mlsValue _mls_lam_arg1) { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Lambda_lambda; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; _mlsVal->_mls_lam_arg0 = _mls_lam_arg0; _mlsVal->_mls_lam_arg1 = _mls_lam_arg1; return _mlsValue(_mlsVal); } +//│ virtual _mlsValue _mls_apply0(); +//│ }; +//│ struct _mls_LzList: public _mlsObject { +//│ +//│ constexpr static inline const char *typeName = "LzList"; +//│ constexpr static inline uint32_t typeTag = nextTypeTag(); +//│ virtual void print() const override { std::printf("%s", typeName); } +//│ virtual void destroy() override { operator delete (this, std::align_val_t(_mlsAlignment)); } +//│ static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_LzList; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; return _mlsValue(_mlsVal); } +//│ +//│ }; +//│ struct _mls_LzCons: public _mls_LzList { +//│ _mlsValue _mls_head; +//│ _mlsValue _mls_tail; +//│ constexpr static inline const char *typeName = "LzCons"; +//│ constexpr static inline uint32_t typeTag = nextTypeTag(); +//│ virtual void print() const override { std::printf("%s", typeName); std::printf("("); this->_mls_head.print(); std::printf(", "); this->_mls_tail.print(); std::printf(")"); } +//│ virtual void destroy() override { _mlsValue::destroy(this->_mls_head); _mlsValue::destroy(this->_mls_tail); operator delete (this, std::align_val_t(_mlsAlignment)); } +//│ static _mlsValue create(_mlsValue _mls_head, _mlsValue _mls_tail) { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_LzCons; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; _mlsVal->_mls_head = _mls_head; _mlsVal->_mls_tail = _mls_tail; return _mlsValue(_mlsVal); } +//│ +//│ }; +//│ struct _mls_LzNil: public _mls_LzList { +//│ +//│ constexpr static inline const char *typeName = "LzNil"; +//│ constexpr static inline uint32_t typeTag = nextTypeTag(); +//│ virtual void print() const override { std::printf("%s", typeName); } +//│ virtual void destroy() override { operator delete (this, std::align_val_t(_mlsAlignment)); } +//│ static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_LzNil; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; return _mlsValue(_mlsVal); } +//│ +//│ }; +//│ _mlsValue _mls_j() { +//│ _mlsValue _mls_retval; +//│ _mls_retval = _mlsValue::create<_mls_Unit>(); +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_entry() { +//│ _mlsValue _mls_retval; +//│ _mls_retval = _mlsValue::create<_mls_Unit>(); +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_lazy(_mlsValue _mls_x7) { +//│ _mlsValue _mls_retval; +//│ auto _mls_x6 = _mlsValue::create<_mls_Lazy>(_mls_x7); +//│ _mls_retval = _mls_x6; +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_llist(_mlsValue _mls_x12) { +//│ _mlsValue _mls_retval; +//│ auto _mls_x11 = _mlsValue::create<_mls_Lambda_f>(); +//│ auto _mls_x13 = _mlsMethodCall<_mls_Callable>(_mls_x11)->_mls_apply1(_mls_x12); +//│ _mls_retval = _mls_x13; +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_entry1() { +//│ _mlsValue _mls_retval; +//│ auto _mls_x8 = _mls_llist(_mlsValue::fromIntLit(1)); +//│ _mls_retval = _mls_x8; +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_entry2() { +//│ _mlsValue _mls_retval; +//│ _mls_retval = _mlsValue::create<_mls_Unit>(); +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_force(_mlsValue _mls_x9) { +//│ _mlsValue _mls_retval; +//│ if (_mlsValue::isValueOf<_mls_Lazy>(_mls_x9)) { +//│ auto _mls_x10 = _mlsMethodCall<_mls_Lazy>(_mls_x9)->_mls_get(); +//│ _mls_retval = _mls_x10; +//│ } else { +//│ throw std::runtime_error("match error"); +//│ } +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_Lambda_f::_mls_apply1(_mlsValue _mls_x1) { +//│ _mlsValue _mls_retval; +//│ auto _mls_x = _mlsValue::create<_mls_Lambda_lambda>(_mls_x1, _mlsValue(this, _mlsValue::inc_ref_tag{})); +//│ auto _mls_x2 = _mls_lazy(_mls_x); +//│ _mls_retval = _mls_x2; +//│ return _mls_retval; +//│ } +//│ _mlsValue _mls_Lambda_lambda::_mls_apply0() { +//│ _mlsValue _mls_retval; +//│ auto _mls_x3 = (_mls_lam_arg0 + _mlsValue::fromIntLit(1)); +//│ auto _mls_x4 = _mlsMethodCall<_mls_Callable>(_mls_lam_arg1)->_mls_apply1(_mls_x3); +//│ auto _mls_x5 = _mlsValue::create<_mls_LzCons>(_mls_lam_arg0, _mls_x4); +//│ _mls_retval = _mls_x5; +//│ return _mls_retval; +//│ } +//│ _mlsValue _mlsMain() { return _mls_entry1(); } +//│ int main() { return _mlsLargeStack(_mlsMainWrapper); } diff --git a/hkmc2/shared/src/test/mlscript/llir/Method.mls b/hkmc2/shared/src/test/mlscript/llir/Method.mls index 4f569cbd0a..f7277d456c 100644 --- a/hkmc2/shared/src/test/mlscript/llir/Method.mls +++ b/hkmc2/shared/src/test/mlscript/llir/Method.mls @@ -10,8 +10,17 @@ fun main() = a.A#f() main() //│ = 1 -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: bErrStop (Builder.scala:22) -//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Ref(a,None),Ident(f)),List()) -//│ Stopped due to an error during the Llir generation +//│ LLIR: +//│ class A(m) { +//│ def f() = +//│ m +//│ } +//│ def main() = +//│ let x = A(1) in +//│ let x1 = A.f(x) in +//│ x1 +//│ def entry() = +//│ let* (x2) = main() in +//│ x2 +//│ entry = entry From b4235ebc4630287ad8d3c8fedfacded9296a385d Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Fri, 31 Oct 2025 14:12:48 +0800 Subject: [PATCH 12/55] Recover errors that were already there --- hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls | 2 +- hkmc2/shared/src/test/mlscript/nofib/scc.mls | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls b/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls index dfac8db569..422b1b5b83 100644 --- a/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls +++ b/hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls @@ -3,7 +3,7 @@ :import NofibPrelude.mls //│ Imported 104 member(s) -//│ Error: hkmc2.ErrorReport: Unsupported kind of Call Call(Select(Ref(x,None),Ident(get)),List()) +//│ Error: hkmc2.ErrorReport: Unsupported kind of Call Call(Select(Select(Ref($runtime,None),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(t1,None)), Arg(None,Lit(IntLit(0))))) //│ Stopped due to an error during the Llir generation diff --git a/hkmc2/shared/src/test/mlscript/nofib/scc.mls b/hkmc2/shared/src/test/mlscript/nofib/scc.mls index ec1b4f49ae..c54e2c4c33 100644 --- a/hkmc2/shared/src/test/mlscript/nofib/scc.mls +++ b/hkmc2/shared/src/test/mlscript/nofib/scc.mls @@ -3,8 +3,7 @@ :silent :import NofibPrelude.mls -//│ Error: hkmc2.ErrorReport: Unsupported selection by users -//│ Stopped due to an error during the Llir generation +//│ /!!!\ Uncaught error: scala.NotImplementedError: AssignField not supported (of class String) fun dfs(r, vsns, xs) = if vsns is [vs, ns] and From 18ff415b89ca7f993eebe48d0bbb905ad2ac96d3 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Fri, 31 Oct 2025 14:15:41 +0800 Subject: [PATCH 13/55] Fix WASM --- .../hkmc2/codegen/wasm/text/WatBuilder.scala | 9 +- .../shared/src/test/mlscript/wasm/Basics.mls | 148 ++---------------- 2 files changed, 22 insertions(+), 135 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala index af61c37c65..ad5d8658f9 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala @@ -252,15 +252,16 @@ class WatBuilder(using TraceLogger, State) extends CodeBuilder: ) case Instantiate(_, cls, as) => - val ctorClsPath = cls match - case sel: Select => sel + val ctorClsSymOpt = cls match + case ref: Value.Ref => ref.disamb + case sel: Select => sel.symbol_SelectSymbol case cls => return errExpr( Ls( - msg"WatBuilder::result for Instantiate(...) where `cls` is not a Select(...) path not implemented yet " -> cls.toLoc + msg"WatBuilder::result for Instantiate(...) where `cls` is not a Ref(...) or Select(...) path not implemented yet " -> cls.toLoc ), extraInfo = S(s"Block IR of `cls` expression: ${cls.toString}") ) - val ctorClsSym = ctorClsPath.symbol_SelectSymbol match + val ctorClsSym = ctorClsSymOpt match case S(sym) => sym case N => return errExpr( Ls( diff --git a/hkmc2/shared/src/test/mlscript/wasm/Basics.mls b/hkmc2/shared/src/test/mlscript/wasm/Basics.mls index d5ba0b66a0..b653656173 100644 --- a/hkmc2/shared/src/test/mlscript/wasm/Basics.mls +++ b/hkmc2/shared/src/test/mlscript/wasm/Basics.mls @@ -4,114 +4,42 @@ false //│ Wasm result: -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (WasmDiffMaker.scala:128) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'binaryenPrintFuncRes') -//│ at REPL7:1:33 -//│ at REPL7:2:4 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ = 0 true //│ Wasm result: -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (WasmDiffMaker.scala:128) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'binaryenPrintFuncRes') -//│ at REPL8:1:33 -//│ at REPL8:2:4 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ = 1 2 //│ Wasm result: -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (WasmDiffMaker.scala:128) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'binaryenPrintFuncRes') -//│ at REPL9:1:33 -//│ at REPL9:2:4 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ = 2 1 + 1 //│ Wasm result: -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (WasmDiffMaker.scala:128) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'binaryenPrintFuncRes') -//│ at REPL10:1:33 -//│ at REPL10:2:4 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ = 2 let x = 0 x //│ Wasm result: -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (WasmDiffMaker.scala:128) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'binaryenPrintFuncRes') -//│ at REPL11:1:33 -//│ at REPL11:2:4 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ = 0 :ge fun foo() = 42 foo //│ ╔══[COMPILATION ERROR] Returning function instances is not supported -//│ ║ l.93: foo +//│ ║ l.33: foo //│ ╙── ^^^ fun foo() = 42 foo() //│ Wasm result: -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (WasmDiffMaker.scala:128) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'binaryenPrintFuncRes') -//│ at REPL12:1:33 -//│ at REPL12:2:4 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ = 42 :wat @@ -164,70 +92,24 @@ foo() + foo() //│ (export "entry" (func $entry)) //│ (elem declare func $entry)) //│ Wasm result: -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (WasmDiffMaker.scala:128) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'binaryenPrintFuncRes') -//│ at REPL13:1:33 -//│ at REPL13:2:4 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ = 84 fun foo(x) = x + 1 foo(41) //│ Wasm result: -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (WasmDiffMaker.scala:128) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'binaryenPrintFuncRes') -//│ at REPL14:1:33 -//│ at REPL14:2:4 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) - +//│ = 42 +:lot class Foo(val x) new Foo(0) -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: errExpr (WatBuilder.scala:262) -//│ FAILURE INFO: Block IR of `cls` expression: Ref(member:Foo,Some(class:Foo)) -//│ ╔══[COMPILATION ERROR] WatBuilder::result for Instantiate(...) where `cls` is not a Select(...) path not implemented yet -//│ ║ l.201: new Foo(0) -//│ ╙── ^^^ -//│ FAILURE: Unexpected exception -//│ /!!!\ Uncaught error: java.lang.UnsupportedOperationException: UnreachableType is a compiler-internal type and cannot be converted to WAT -//│ at: hkmc2.codegen.wasm.text.UnreachableType$.toWat(Wasm.scala:50) -//│ at: hkmc2.codegen.wasm.text.Type.asValType_$bang$$anonfun$1(Wasm.scala:36) -//│ at: scala.Option.getOrElse(Option.scala:201) -//│ at: hkmc2.codegen.wasm.text.Type.asValType_$bang(Wasm.scala:36) -//│ at: hkmc2.codegen.wasm.text.WatBuilder.returningTerm$$anonfun$6(WatBuilder.scala:537) -//│ at: scala.collection.immutable.List.map(List.scala:247) -//│ at: scala.collection.immutable.List.map(List.scala:79) -//│ at: hkmc2.codegen.wasm.text.WatBuilder.returningTerm(WatBuilder.scala:537) -//│ at: hkmc2.codegen.wasm.text.WatBuilder.block(WatBuilder.scala:634) -//│ at: hkmc2.codegen.wasm.text.WatBuilder.program(WatBuilder.scala:599) +//│ Wasm result: +//│ = {} :wat class Foo(val a) (new Foo(42)).Foo#a -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: errExpr (WatBuilder.scala:262) -//│ FAILURE INFO: Block IR of `cls` expression: Ref(member:Foo,Some(class:Foo)) -//│ ╔══[COMPILATION ERROR] WatBuilder::result for Instantiate(...) where `cls` is not a Select(...) path not implemented yet -//│ ║ l.224: (new Foo(42)).Foo#a -//│ ╙── ^^^ //│ Wat: //│ (module //│ (type $Foo (struct (field $a (mut (ref null any))))) @@ -255,9 +137,13 @@ class Foo(val a) //│ (nop) //│ (block (result (ref null any)) //│ (local.set $tmp -//│ (unreachable)) +//│ (call $Foo +//│ (ref.i31 +//│ (i32.const 42)))) //│ (struct.get $Foo 0 //│ (ref.cast (ref $Foo) //│ (local.get $tmp)))))) //│ (export "entry" (func $entry)) //│ (elem declare func $entry)) +//│ Wasm result: +//│ = 42 From 1e5db6bd7d5ab413f0c7cc0177e59c76793a80b9 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Fri, 31 Oct 2025 22:00:46 +0800 Subject: [PATCH 14/55] Fix duplicate symbol error --- .../scala/hkmc2/semantics/Elaborator.scala | 9 ++++- .../src/main/scala/hkmc2/semantics/Term.scala | 37 +++++++++++++------ .../test/mlscript/codegen/ParamClasses.mls | 15 +++++--- .../mlscript/codegen/ThisCallVariations.mls | 8 ++++ 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index 53c318e865..62f4a598ff 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -1243,7 +1243,7 @@ extends Importer: p.modulefulness, Nil, N, - ) + ).withLocOf(p) assert(p.fldSym.isEmpty) p.fldSym = S(fsym) fsym.defn = S(fdef) @@ -1268,7 +1268,12 @@ extends Importer: val (blk, c) = fn(using ctxWithFields) val blkWithFields: Blk = blk.copy(stats = fields ::: blk.stats) - (blkWithFields, c) + ObjBody.extractMembers(blkWithFields) match + case R(_) => + (blkWithFields, c) + case L(errs) => + errs.foreach(raise) + (blk, c) def mkBody(using Ctx) = withFields: body match diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index e5ace0b8f0..8fa0e0fe79 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -9,6 +9,7 @@ import syntax.* import Elaborator.State import hkmc2.typing.Type import hkmc2.semantics.Elaborator.{Ctx, ctx} +import hkmc2.Message.MessageContext final case class QuantVar(sym: VarSymbol, ub: Opt[Term], lb: Opt[Term]) @@ -670,20 +671,34 @@ final case class HandlerTermDefinition( td: TermDefinition ) +object ObjBody: + + def extractMembers(blk: Term.Blk): Ls[ErrorReport] \/ Map[Str, BlockMemberSymbol] = + val (errs, mems) = blk.stats.collect: + case td: TermDefinition => td.sym -> td + case td: ClassLikeDef => td.bsym -> td + case td: TypeDef => td.bsym -> td + .groupBy(_._1.nme) + .partitionMap: (nme, syms) => + if syms.map(_._1).distinct.tail.nonEmpty then L: + (msg"Found duplicate members with the same name '${nme}'." -> N) :: + syms.map(_._2).map(msg"Defined at: " -> _.toLoc) + else R: + nme -> syms.head._1 + + if errs.nonEmpty then + L(errs.map(ErrorReport(_)).toList) + else + R(mems.toMap) + case class ObjBody(blk: Term.Blk): lazy val members: Map[Str, BlockMemberSymbol] = - blk.stats.collect: - case td: TermDefinition => td.sym - case td: ClassLikeDef => td.bsym - case td: TypeDef => td.bsym - .groupBy(_.nme) - .map: (nme, syms) => - if syms.distinct.length > 1 then - lastWords: - s"Duplicate members named '${nme}' with different block-member symbols: ${syms.mkString(", ")}." - nme -> syms.head - .toMap + ObjBody.extractMembers(blk) match + case L(errs) => lastWords: + errs.map(_.mainMsg).mkString("\n") + case R(mems) => + mems lazy val (methods, nonMethods) = blk.stats.partitionMap: case td: TermDefinition if td.k is syntax.Fun => L(td) diff --git a/hkmc2/shared/src/test/mlscript/codegen/ParamClasses.mls b/hkmc2/shared/src/test/mlscript/codegen/ParamClasses.mls index 29994014fb..c0c6ddde10 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/ParamClasses.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/ParamClasses.mls @@ -233,9 +233,15 @@ Foo(10, 20, 30, 40, 50) //│ = Foo(_, 20, _, 40, _) -:todo // * This should be an error :e class Foo(val z, val z) +//│ ╔══[ERROR] Found duplicate members with the same name 'z'. +//│ ╟── Defined at: +//│ ║ l.237: class Foo(val z, val z) +//│ ║ ^ +//│ ╟── Defined at: +//│ ║ l.237: class Foo(val z, val z) +//│ ╙── ^ //│ JS (unsanitized): //│ let Foo9; //│ Foo9 = function Foo(z, z1) { @@ -245,10 +251,7 @@ class Foo(val z, val z) //│ static { //│ Foo9.class = this //│ } -//│ constructor(z, z1) { -//│ this.z = z; -//│ this.z = z1; -//│ } +//│ constructor(z, z1) {} //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "Foo", ["z", "z"]]; //│ }); @@ -256,6 +259,6 @@ class Foo(val z, val z) Foo(1, 2) //│ JS (unsanitized): //│ Foo9(1, 2) -//│ = Foo(2, 2) +//│ = Foo(undefined, undefined) diff --git a/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls b/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls index 3f48d6c062..ac387b68e1 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls @@ -53,9 +53,17 @@ id(Example) .!. oops(2) //│ = [2, 1] +:e data class Example2(val a) with val a = 1 fun f(inc) = Example2(a + inc) +//│ ╔══[ERROR] Found duplicate members with the same name 'a'. +//│ ╟── Defined at: +//│ ║ l.57: data class Example2(val a) with +//│ ║ ^ +//│ ╟── Defined at: +//│ ║ l.58: val a = 1 +//│ ╙── ^ let oops2 = Example2(0).("f") //│ oops2 = fun f From a2fbf484f059a717e378ca726088f5693f573873 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Fri, 31 Oct 2025 22:21:24 +0800 Subject: [PATCH 15/55] Enhance type resolution --- .../main/scala/hkmc2/semantics/Resolver.scala | 7 +- .../test/mlscript/codegen/ClassInClass.mls | 2 +- .../test/mlscript/codegen/SanityChecks.mls | 18 +++- .../src/test/mlscript/ctx/TypeResolution.mls | 94 +++++++++++++++++-- .../src/test/mlscript/lifter/ClassInFun.mls | 2 +- .../src/test/mlscript/lifter/DefnsInClass.mls | 4 +- .../test/mlscript/lifter/ModulesObjects.mls | 6 +- .../src/test/mlscript/objbuf/Basics.mls | 30 ------ 8 files changed, 116 insertions(+), 47 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 7dbb9b9bc2..10a3c8131a 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -875,7 +875,7 @@ class Resolver(tl: TraceLogger) extraInfo = S(defn)) // Class-Like Definitions - (clsDefn orElse lhs.defn).foreach: + (clsDefn orElse lhs.typDefn).foreach: case defn: ClassLikeDef => // A reference to a member within the class is elaborated into a SynthSel, e.g., // class C with @@ -947,6 +947,11 @@ class Resolver(tl: TraceLogger) case S(defn: ModuleOrObjectDef) if ass.isEmpty => val ty = Type.Ref(defn.sym, Nil) t.expand(S(t.withTyp(ty))) + case S(defn: ClassDef) => base match + case Term.Ref(inner: InnerSymbol) => + val ty = Type.Ref(defn.sym, Nil) + t.expand(S(t.withTyp(ty))) + case _ => case _ => case _ => end resolveType diff --git a/hkmc2/shared/src/test/mlscript/codegen/ClassInClass.mls b/hkmc2/shared/src/test/mlscript/codegen/ClassInClass.mls index e81205fe02..195b55a49a 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/ClassInClass.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/ClassInClass.mls @@ -64,7 +64,7 @@ data class Outer(a, b) with //│ o2(c, d) { //│ let tmp; //│ tmp = this.Inner(c); -//│ return runtime.safeCall(tmp.i1(d)) +//│ return tmp.i1(d) //│ } //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "Outer", ["a", "b"]]; diff --git a/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls b/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls index efd52746db..0fc31ee9db 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls @@ -97,10 +97,14 @@ f(2) :expect NaN :ssjs +:e :noSanityCheck data class Cls(x, y) with fun f(z, p) = x + y + z + p Cls(1, 2).f(3) +//│ ╔══[ERROR] Expected 2 arguments, got 1 +//│ ║ l.104: Cls(1, 2).f(3) +//│ ╙── ^^^ //│ JS: //│ Cls1 = function Cls(x, y) { //│ return globalThis.Object.freeze(new Cls.class(x, y)); @@ -123,15 +127,19 @@ Cls(1, 2).f(3) //│ static [definitionMetadata] = ["class", "Cls", ["x", "y"]]; //│ }); //│ tmp1 = Cls1(1, 2); -//│ block$res7 = runtime.safeCall(tmp1.f(3)); +//│ block$res7 = tmp1.f(3); //│ undefined //│ = NaN :ssjs +:e :re data class Cls(x, y) with fun f(z, p) = x + y + z + p Cls(1, 2).f(3) +//│ ╔══[ERROR] Expected 2 arguments, got 1 +//│ ║ l.139: Cls(1, 2).f(3) +//│ ╙── ^^^ //│ JS: //│ Cls3 = function Cls(...args) { //│ return globalThis.Object.freeze(new Cls.class(...args)); @@ -158,16 +166,20 @@ Cls(1, 2).f(3) //│ static [definitionMetadata] = ["class", "Cls", ["x", "y"]]; //│ }); //│ tmp2 = runtime.checkCall(Cls3(1, 2)); -//│ block$res8 = runtime.safeCall(tmp2.f(3)); +//│ block$res8 = runtime.checkCall(tmp2.f(3)); //│ undefined //│ ═══[RUNTIME ERROR] Error: Function 'f' expected 2 arguments but got 1 :ssjs +:e :re data class Cls(x, y) with fun f(z, p)(q, s) = x + y + z + p + q + s Cls(1, 2).f(3, 4)(5) +//│ ╔══[ERROR] Expected 2 arguments, got 1 +//│ ║ l.179: Cls(1, 2).f(3, 4)(5) +//│ ╙── ^^^ //│ JS: //│ Cls5 = function Cls(...args) { //│ return globalThis.Object.freeze(new Cls.class(...args)); @@ -346,7 +358,7 @@ M.A(1).g(0) :ssjs M.A(1).f(0) //│ JS: -//│ tmp11 = runtime.checkCall(M1.A(1)); block$res19 = runtime.safeCall(tmp11.f(0)); undefined +//│ tmp11 = runtime.checkCall(M1.A(1)); block$res19 = runtime.checkCall(tmp11.f(0)); undefined //│ = 1 diff --git a/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls b/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls index f3d4df51a2..6fef83e19d 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls @@ -43,9 +43,11 @@ foo.foo //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Sel: -//│ prefix = Ref{sym=member:foo,typ=class:Foo} of member:foo -//│ nme = Ident of "foo" +//│ res = Resolved{sym=term:class:Foo.foo,typ=class:Foo}: +//│ t = Sel{sym=member:foo}: +//│ prefix = Ref{sym=member:foo,typ=class:Foo} of member:foo +//│ nme = Ident of "foo" +//│ sym = term:class:Foo.foo class Foo2[A, B] with val foo: Foo2[Int, Str] = new Foo2 @@ -91,9 +93,11 @@ foo.foo //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = Sel: -//│ prefix = Ref{sym=member:foo,typ=class:Foo2[class:Str, class:Int]} of member:foo -//│ nme = Ident of "foo" +//│ res = Resolved{sym=term:class:Foo2.foo,typ=class:Foo2[class:Int, class:Str]}: +//│ t = Sel{sym=member:foo}: +//│ prefix = Ref{sym=member:foo,typ=class:Foo2[class:Str, class:Int]} of member:foo +//│ nme = Ident of "foo" +//│ sym = term:class:Foo2.foo :rt fun f(x: Foo) = x @@ -231,3 +235,81 @@ fun f(o: O) = o //│ annotations = Nil //│ companion = N //│ res = Lit of UnitLit of false + +// The implicit `this` should be resolved correctly... +:rt +class Foo with + val foo = 42 + foo +//│ Resolved tree: +//│ Blk: +//│ stats = Ls of +//│ Plain: +//│ owner = N +//│ kind = Cls +//│ sym = class:Foo +//│ bsym = member:Foo +//│ tparams = Nil +//│ ext = N +//│ body = ObjBody of Blk: +//│ stats = Ls of +//│ TermDefinition: +//│ k = ImmutVal +//│ sym = member:foo +//│ tsym = term:class:Foo.foo +//│ params = Nil +//│ tparams = N +//│ sign = N +//│ body = S of Lit of IntLit of 42 +//│ resSym = ‹result of member:foo› +//│ flags = (method) +//│ modulefulness = Modulefulness of N +//│ annotations = Nil +//│ companion = N +//│ res = Resolved{sym=term:class:Foo.foo}: +//│ t = SynthSel{sym=member:foo}: +//│ prefix = Ref{sym=class:Foo,typ=class:Foo} of class:Foo +//│ nme = Ident of "foo" +//│ sym = term:class:Foo.foo +//│ companion = N +//│ annotations = Nil +//│ res = Lit of UnitLit of false + +// ... as well as an explicit `this`. +:rt +class Foo with + val foo = 42 + this.foo +//│ Resolved tree: +//│ Blk: +//│ stats = Ls of +//│ Plain: +//│ owner = N +//│ kind = Cls +//│ sym = class:Foo +//│ bsym = member:Foo +//│ tparams = Nil +//│ ext = N +//│ body = ObjBody of Blk: +//│ stats = Ls of +//│ TermDefinition: +//│ k = ImmutVal +//│ sym = member:foo +//│ tsym = term:class:Foo.foo +//│ params = Nil +//│ tparams = N +//│ sign = N +//│ body = S of Lit of IntLit of 42 +//│ resSym = ‹result of member:foo› +//│ flags = (method) +//│ modulefulness = Modulefulness of N +//│ annotations = Nil +//│ companion = N +//│ res = Resolved{sym=term:class:Foo.foo}: +//│ t = Sel{sym=member:foo}: +//│ prefix = Ref{sym=class:Foo,typ=class:Foo} of class:Foo +//│ nme = Ident of "foo" +//│ sym = term:class:Foo.foo +//│ companion = N +//│ annotations = Nil +//│ res = Lit of UnitLit of false diff --git a/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls b/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls index 6d604a7de6..ec726f6ed4 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls @@ -192,7 +192,7 @@ f().foo() //│ z = 10; //│ capture.w$capture$0 = 1000; //│ tmp6 = Bad$(false, capture); -//│ tmp7 = runtime.safeCall(tmp6.foo()); +//│ tmp7 = tmp6.foo(); //│ return Good$(false, x, y, z, capture) //│ }; //│ tmp5 = f5(); diff --git a/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls b/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls index 4b4d372276..ced6f447b4 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls @@ -56,7 +56,7 @@ data class A(x) with //│ getA() { //│ let tmp; //│ tmp = this.B(2); -//│ return runtime.safeCall(tmp.getB()) +//│ return tmp.getB() //│ } //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "A", ["x"]]; @@ -68,7 +68,7 @@ A(1).getA() //│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) //│ ═══[RUNTIME ERROR] TypeError: this.B is not a function //│ at A.getA (REPL10:1:1488) -//│ at REPL13:1:81 +//│ at REPL13:1:82 //│ at ContextifyScript.runInThisContext (node:vm:137:12) //│ at REPLServer.defaultEval (node:repl:593:22) //│ at bound (node:domain:433:15) diff --git a/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls b/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls index 02e8219fe7..c5e092b9d1 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls @@ -168,7 +168,7 @@ A(2).getA() //│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) //│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'getB') //│ at A.getA (REPL50:1:966) -//│ at REPL53:1:82 +//│ at REPL53:1:83 //│ at ContextifyScript.runInThisContext (node:vm:137:12) //│ at REPLServer.defaultEval (node:repl:593:22) //│ at bound (node:domain:433:15) @@ -306,8 +306,8 @@ M.A(2).newB.newA_B(3).newB.get //│ FAILURE: Unexpected runtime error //│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) //│ ═══[RUNTIME ERROR] TypeError: this.B is not a function -//│ at get newB (REPL74:1:1731) -//│ at REPL74:1:2115 +//│ at get newB (REPL74:1:1717) +//│ at REPL74:1:2101 //│ at ContextifyScript.runInThisContext (node:vm:137:12) //│ at REPLServer.defaultEval (node:repl:593:22) //│ at bound (node:domain:433:15) diff --git a/hkmc2/shared/src/test/mlscript/objbuf/Basics.mls b/hkmc2/shared/src/test/mlscript/objbuf/Basics.mls index 5d6ef745ce..0e561fc34e 100644 --- a/hkmc2/shared/src/test/mlscript/objbuf/Basics.mls +++ b/hkmc2/shared/src/test/mlscript/objbuf/Basics.mls @@ -58,19 +58,9 @@ let obj2 = buf.mkNew(A)(5) //│ obj2 = 2 A.f(buf, obj1)(1) -//│ FAILURE: Unexpected type error -//│ FAILURE LOCATION: newDefn (Resolver.scala:652) -//│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.60: A.f(buf, obj1)(1) -//│ ╙── ^^^^^^^^^^^ //│ = 4 A.f(buf, obj2)(1) -//│ FAILURE: Unexpected type error -//│ FAILURE LOCATION: newDefn (Resolver.scala:652) -//│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.63: A.f(buf, obj2)(1) -//│ ╙── ^^^^^^^^^^^ //│ = 6 buf.del(A, obj1) @@ -80,19 +70,9 @@ let obj3 = buf.mkNew(A)(10) // UAF A.f(buf, obj1)(1) -//│ FAILURE: Unexpected type error -//│ FAILURE LOCATION: newDefn (Resolver.scala:652) -//│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.72: A.f(buf, obj1)(1) -//│ ╙── ^^^^^^^^^^^ //│ = 11 A.f(buf, obj3)(1) -//│ FAILURE: Unexpected type error -//│ FAILURE LOCATION: newDefn (Resolver.scala:652) -//│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.75: A.f(buf, obj3)(1) -//│ ╙── ^^^^^^^^^^^ //│ = 11 @@ -111,22 +91,12 @@ let obj2 = buf.mkNew(A)(3) //│ obj2 = 4 A.f(buf, obj2)(1) -//│ FAILURE: Unexpected type error -//│ FAILURE LOCATION: newDefn (Resolver.scala:652) -//│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.93: A.f(buf, obj2)(1) -//│ ╙── ^^^^^^^^^^^ //│ = 4 buf.del(Oops, obj1) :expect 4 A.f(buf, obj2)(1) -//│ FAILURE: Unexpected type error -//│ FAILURE LOCATION: newDefn (Resolver.scala:652) -//│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.99: A.f(buf, obj2)(1) -//│ ╙── ^^^^^^^^^^^ //│ = 4 From b4c9cd17d16c54eb85d6bbc2a1bfe29ec5b411f7 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Fri, 31 Oct 2025 23:35:15 +0800 Subject: [PATCH 16/55] Cleanup asDefnSym_TODO --- .../main/scala/hkmc2/codegen/Lowering.scala | 38 ++++++++----------- .../scala/hkmc2/semantics/Elaborator.scala | 4 +- .../main/scala/hkmc2/semantics/Resolver.scala | 31 ++++++++++++--- .../src/main/scala/hkmc2/semantics/Term.scala | 13 ++++++- .../hkmc2/semantics/ucs/TermSynthesizer.scala | 2 +- .../basics/CompanionModules_Classes.mls | 2 +- .../src/test/mlscript/basics/MutRcd.mls | 26 ++++++++----- .../test/mlscript/codegen/SanityChecks.mls | 8 ++-- .../src/test/mlscript/ctx/TypeResolution.mls | 6 +-- .../test/mlscript/lifter/ModulesObjects.mls | 12 +++--- 10 files changed, 86 insertions(+), 56 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index dfa16a7739..0b7f763c8a 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -505,19 +505,15 @@ class Lowering()(using Config, TL, Raise, State, Ctx): // * are preserved in the call and not moved to a temporary variable. case sel @ Sel(prefix, nme) => subTerm(prefix): p => - conclude(Select(p, nme)(sel.sym.flatMap(_.asDefnSym_TODO)).withLocOf(sel)) + conclude(Select(p, nme)(N).withLocOf(sel)) case Resolved(sel @ Sel(prefix, nme), sym) => subTerm(prefix): p => - // conclude(Select(p, nme)(sel.sym, S(sym)).withLocOf(sel)) - // TODO @Harry: Check this logic. conclude(Select(p, nme)(S(sym)).withLocOf(sel)) case sel @ SelProj(prefix, _, nme) => subTerm(prefix): p => - conclude(Select(p, nme)(sel.sym.flatMap(_.asDefnSym_TODO)).withLocOf(sel)) + conclude(Select(p, nme)(N).withLocOf(sel)) case Resolved(sel @ SelProj(prefix, _, nme), sym) => subTerm(prefix): p => - // conclude(Select(p, nme)(sel.sym, S(sym)).withLocOf(sel)) - // TODO @Harry: Check this logic. conclude(Select(p, nme)(S(sym)).withLocOf(sel)) case _ => subTerm(f)(conclude) case h @ Handle(lhs, rhs, as, cls, defs, bod) => @@ -717,19 +713,17 @@ class Lowering()(using Config, TL, Raise, State, Ctx): ) case sel @ Sel(prefix, nme) => - setupSelection(prefix, nme, sel.sym, N)(k) + setupSelection(prefix, nme, N)(k) case Resolved(sel @ Sel(prefix, nme), sym) => - setupSelection(prefix, nme, sel.sym, S(sym))(k) + setupSelection(prefix, nme, S(sym))(k) case sel @ SynthSel(prefix, nme) => // * Not using `setupSelection` as these selections are not meant to be sanity-checked subTerm(prefix): p => - k(Select(p, nme)(sel.sym.flatMap(_.asDefnSym_TODO))) + k(Select(p, nme)(N)) case Resolved(sel @ SynthSel(prefix, nme), sym) => // * Not using `setupSelection` as these selections are not meant to be sanity-checked subTerm(prefix): p => - // k(Select(p, nme)(sel.sym, S(sym))) - // TODO @Harry: Check this logic. k(Select(p, nme)(S(sym))) case DynSel(prefix, fld, ai) => @@ -767,7 +761,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): val pctor = parentConstructor(cls, as) val clsDef = ClsLikeDefn(N, isym, sym, syntax.Cls, N, Nil, S(sr), mtds, privateFlds, publicFlds, pctor, ctor, N, N) - val inner = new New(sym.ref().resolved(isym), Nil, N) + val inner = new New(sym.ref().resolved(isym), Nil, N)(N) Define(clsDef, term_nonTail(if mut then Mut(inner) else inner)(k)) case Try(sub, finallyDo) => @@ -782,9 +776,9 @@ class Lowering()(using Config, TL, Raise, State, Ctx): // * BbML-specific cases: t.Cls#field and mutable operations case sp @ SelProj(prefix, _, proj) => - setupSelection(prefix, proj, sp.sym, N)(k) + setupSelection(prefix, proj, N)(k) case Resolved(sp @ SelProj(prefix, _, proj), sym) => - setupSelection(prefix, proj, sp.sym, S(sym))(k) + setupSelection(prefix, proj, S(sym))(k) case Region(reg, body) => Assign(reg, Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Region"))(N), Nil), term_nonTail(body)(k)) @@ -1109,11 +1103,9 @@ class Lowering()(using Config, TL, Raise, State, Ctx): ) - def setupSelection(prefix: Term, nme: Tree.Ident, sym: Opt[FieldSymbol], disamb: Opt[DefinitionSymbol[?]])(k: Result => Block)(using Subst): Block = + def setupSelection(prefix: Term, nme: Tree.Ident, disamb: Opt[DefinitionSymbol[?]])(k: Result => Block)(using Subst): Block = subTerm(prefix): p => - val selRes = TempSymbol(N, "selRes") // TODO @LP: why is it here? - // k(Select(p, nme)(sym, disamb)) - k(Select(p, nme)(disamb.orElse(sym.flatMap(_.asDefnSym_TODO)))) + k(Select(p, nme)(disamb)) final def setupFunctionOrByNameDef(paramLists: List[ParamList], bodyTerm: Term, name: Option[Str]) (using Subst): (List[ParamList], Block) = @@ -1138,16 +1130,16 @@ trait LoweringSelSanityChecks(using Config, TL, Raise, State) private val instrument: Bool = config.sanityChecks.isDefined - override def setupSelection(prefix: st, nme: Tree.Ident, sym: Opt[FieldSymbol], disamb: Opt[DefinitionSymbol[?]])(k: Result => Block)(using Subst): Block = - if !instrument then return super.setupSelection(prefix, nme, sym, disamb)(k) + override def setupSelection(prefix: st, nme: Tree.Ident, disamb: Opt[DefinitionSymbol[?]])(k: Result => Block)(using Subst): Block = + if !instrument then return super.setupSelection(prefix, nme, disamb)(k) subTerm(prefix): p => val selRes = TempSymbol(N, "selRes") // * We are careful to access `x.f` before `x.f$__checkNotMethod` in case `x` is, eg, `undefined` and // * the access should throw an error like `TypeError: Cannot read property 'f' of undefined`. val b0 = blockBuilder - .assign(selRes, Select(p, nme)(disamb.orElse(sym.flatMap(_.asDefnSym_TODO)))) - (if sym.isDefined then - // * If the symbol is known, the elaborator will have already checked the access [invariant:1] + .assign(selRes, Select(p, nme)(disamb)) + (if disamb.isDefined then + // * If the symbol is known, the resolver will have already checked the access [invariant:1] b0 else b0 .assign(TempSymbol(N, "discarded"), Select(p, Tree.Ident(nme.name+"$__checkNotMethod"))(N))) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index 62f4a598ff..f6b89968da 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -674,11 +674,11 @@ extends Importer: subterm(c2), // * Note: we'll catch bad `new` targets during type checking args.map(subterm(_)), bodo - ).withLocOf(tree) + )(N).withLocOf(tree) if mut then Term.Mut(inner) else inner case N => Term.New(State.globalThisSymbol.ref().sel(Ident("Object"), S(ctx.builtins.Object)), - Nil, bodo).withLocOf(tree) + Nil, bodo)(N).withLocOf(tree) // case _ => // raise(ErrorReport(msg"Illegal new expression." -> tree.toLoc :: Nil)) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 10a3c8131a..8428b822f1 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -319,11 +319,6 @@ class Resolver(tl: TraceLogger) args.foreach(traverse(_, expect = NonModule(N))) defs.foreach(d => traverseDefn(d.td)) traverse(body, expect = NonModule(N)) - - case Term.New(cls, args, rft) => - traverse(cls, expect = Class(S("The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation."))) - args.foreach(traverse(_, expect = NonModule(N))) - rft.foreach((sym, bdy) => traverseBlock(bdy.blk)) case t: Resolvable => resolve(t, prefer = expect, inAppPrefix = false, inTyPrefix = false, inCtxPrefix = false) @@ -568,6 +563,13 @@ class Resolver(tl: TraceLogger) cls.foreach(traverse(_, expect = Class(N))) (t.callableDefn, ictx) + case Term.New(cls, args, rft) => + // Term.New has only a type, but does not have a symbol. + traverse(cls, expect = Class(S("The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation."))) + args.foreach(traverse(_, expect = NonModule(N))) + resolveType(t, prefer = prefer) + (t.callableDefn, ictx) + case Term.Ref(_: BlockMemberSymbol) => resolveSymbol(t, prefer = prefer, sign = false) resolveType(t, prefer = prefer) @@ -903,6 +905,17 @@ class Resolver(tl: TraceLogger) // extraInfo = S(defn))' case defn => log(s"Unsupported selection from definition: ${defn}") + + case t @ Term.New(cls, _, N) => + // cls is already resolved, so the symbol should be present; + // otherwise, there is already an error raised. + cls.resolvedSym match + case S(clsSym: ClassSymbol) => + t.expand(S(Term.Resolved(t.duplicate, clsSym)(N))) + case S(sym) => + lastWords(s"Expected a class symbol; found ${sym} for term ${t}.") + case N => + case _ => /** @@ -925,6 +938,14 @@ class Resolver(tl: TraceLogger) case _: (Any.type | NonModule) => bms.asPrincipal t match + case Term.New(cls, _, N) => cls.resolvedSym match + case S(clsSym: ClassSymbol) => + val ty = Type.Ref(clsSym, Nil) + t.expand(S(t.withTyp(ty))) + case _ => + // cls is already resolved, so the symbol should be present; + // otherwise, there is already an error raised. + () case t @ Apps(base: Resolvable, ass) => val decl = base.resolvedSym match case S(bms: BlockMemberSymbol) => diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index 8fa0e0fe79..1e0d5ecca8 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -62,6 +62,7 @@ sealed trait ResolvableImpl: case t: Term.Sel => t.copy()(t.sym, t.typ) case t: Term.SynthSel => t.copy()(t.sym, t.typ) case t: Term.SelProj => t.copy()(t.sym, t.typ) + case t: Term.New => t.copy()(t.typ) .withLocOf(this) .asInstanceOf @@ -83,6 +84,7 @@ sealed trait ResolvableImpl: case t: Term.Sel => t.copy()(t.sym, S(typ)) case t: Term.SynthSel => t.copy()(t.sym, S(typ)) case t: Term.SelProj => t.copy()(t.sym, S(typ)) + case t: Term.New => t.copy()(S(typ)) .withLocOf(this) .asInstanceOf @@ -227,6 +229,7 @@ enum Term extends Statement: case Quoted(body: Term) case Unquoted(body: Term) case New(cls: Term, args: Ls[Term], rft: Opt[ClassSymbol -> ObjBody]) + (val typ: Opt[Type]) extends Term, ResolvableImpl case DynNew(cls: Term, args: Ls[Term]) case Asc(term: Term, ty: Term) case CompType(lhs: Term, rhs: Term, pol: Bool) @@ -284,6 +287,7 @@ enum Term extends Statement: case app: TyApp => app.typ case sel: Sel => sel.typ case sel: SynthSel => sel.typ + case nu: New => nu.typ case _ => N def sel(id: Tree.Ident, sym: Opt[FieldSymbol]): Sel = @@ -332,8 +336,8 @@ enum Term extends Statement: case Rcd(mut, stats) => Rcd(mut, stats.map(_.mkClone)) case Quoted(body) => Quoted(body.mkClone) case Unquoted(body) => Unquoted(body.mkClone) - case New(cls, args, rft) => - New(cls.mkClone, args.map(_.mkClone), rft.map { case (cs, ob) => cs -> ObjBody(ob.blk.mkBlkClone) }) + case term @ New(cls, args, rft) => + New(cls.mkClone, args.map(_.mkClone), rft.map { case (cs, ob) => cs -> ObjBody(ob.blk.mkBlkClone) })(term.typ) case DynNew(cls, args) => DynNew(cls.mkClone, args.map(_.mkClone)) case term @ SelProj(prefix, cls, proj) => SelProj(prefix.mkClone, cls.mkClone, Tree.Ident(proj.name))(term.sym, term.typ) @@ -989,6 +993,11 @@ object Apps: case t => S(t, Nil) +object ResolvedOpt: + def unapply(t: Term): S[(Term, Opt[Symbol])] = t match + case r: Resolved => S((r.t, S(r.sym))) + case _ => S((t, N)) + trait BlkImpl: this: Blk => def mkBlkClone(using State): Blk = Blk(stats.map(_.mkClone), res.mkClone) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala index 41c2adbd87..680b911e76 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala @@ -27,7 +27,7 @@ trait TermSynthesizer(using Ctx, State): protected final def app(l: Term, r: Term, s: FlowSymbol): Term.App = (Term.App(l, r)(App(Dummy, Dummy), N, s): Term.App).resolve protected final def `new`(cls: Term, args: Ls[Term], label: Str): Term.New = - Term.New(cls, args, N) + Term.New(cls, args, N)(N) protected final def rcd(fields: RcdField*): Term.Rcd = Term.Rcd(false, fields.toList) protected final def splitLet(sym: BlockLocalSymbol, term: Term)(inner: Split): Split = diff --git a/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls b/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls index b62d6f07e1..ced354b8b2 100644 --- a/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls +++ b/hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls @@ -22,7 +22,7 @@ new C //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = New: +//│ res = New{typ=class:C}: //│ cls = Resolved{sym=class:C}: //│ t = Ref{sym=member:C} of member:C //│ sym = class:C diff --git a/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls b/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls index 95d0d1ecc3..1c34653831 100644 --- a/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls +++ b/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls @@ -109,6 +109,13 @@ Object.freeze //│ l = globalThis:globalThis //│ disamb = N //│ name = Ident of "Object" +//│ rest = Assign: \ +//│ lhs = $discarded +//│ rhs = Select: +//│ qual = Ref: +//│ l = globalThis:globalThis +//│ disamb = N +//│ name = Ident of "Object$__checkNotMethod" //│ rest = Match: \ //│ scrut = Ref: //│ l = $selRes @@ -169,15 +176,16 @@ Object.freeze //│ rest = Return: \ //│ res = Lit of UnitLit of false //│ implct = true -//│ avoidNames Assign($selRes,Select(Ref(globalThis:globalThis,None),Ident(Object)),Match(Ref($selRes,None),List((L... -//│ | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... -//│ | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... -//│ | | avoidNames Assign($selRes,Select(Ref($selRes,None),Ident(freeze)),Assign($discarded,Select(Ref($selRes,None),Id... -//│ | | | avoidNames Assign($discarded,Select(Ref($selRes,None),Ident(freeze$__checkNotMethod)),Match(Ref($selRes,None),L... -//│ | | | | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... -//│ | | | | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... -//│ | | | | | avoidNames Assign($block$res,Ref($selRes,None),Return(Lit(UnitLit(false)),true))... -//│ | | | | | | avoidNames Return(Lit(UnitLit(false)),true)... +//│ avoidNames Assign($selRes,Select(Ref(globalThis:globalThis,None),Ident(Object)),Assign($discarded,Select(Ref(gl... +//│ | avoidNames Assign($discarded,Select(Ref(globalThis:globalThis,None),Ident(Object$__checkNotMethod)),Match(Ref($... +//│ | | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... +//│ | | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... +//│ | | | avoidNames Assign($selRes,Select(Ref($selRes,None),Ident(freeze)),Assign($discarded,Select(Ref($selRes,None),Id... +//│ | | | | avoidNames Assign($discarded,Select(Ref($selRes,None),Ident(freeze$__checkNotMethod)),Match(Ref($selRes,None),L... +//│ | | | | | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... +//│ | | | | | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... +//│ | | | | | | avoidNames Assign($block$res,Ref($selRes,None),Return(Lit(UnitLit(false)),true))... +//│ | | | | | | | avoidNames Return(Lit(UnitLit(false)),true)... //│ = fun freeze Object.freeze(r) diff --git a/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls b/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls index 0fc31ee9db..e9447e397e 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls @@ -223,6 +223,7 @@ Cls(1, 2).f(3, 4)(5) console.log(1) //│ JS: //│ selRes = globalThis.console; +//│ discarded = globalThis.console$__checkNotMethod; //│ if (selRes === undefined) { //│ throw globalThis.Object.freeze(new globalThis.Error("Access to required field 'console' yielded 'undefined'")) //│ } @@ -236,7 +237,7 @@ console.log(1) globalThis.x //│ JS: //│ selRes1 = globalThis.x; -//│ discarded = globalThis.x$__checkNotMethod; +//│ discarded1 = globalThis.x$__checkNotMethod; //│ if (selRes1 === undefined) { //│ throw globalThis.Object.freeze(new globalThis.Error("Access to required field 'x' yielded 'undefined'")) //│ } @@ -296,7 +297,7 @@ if M.A(1).y is //│ }); //│ tmp5 = runtime.checkCall(M1.A(1)); //│ selRes2 = tmp5.y; -//│ discarded1 = tmp5.y$__checkNotMethod; +//│ discarded2 = tmp5.y$__checkNotMethod; //│ if (selRes2 === undefined) { //│ throw globalThis.Object.freeze(new globalThis.Error("Access to required field 'y' yielded 'undefined'")) //│ } @@ -314,12 +315,13 @@ M.A(1).y console.log() //│ JS: //│ selRes3 = globalThis.console; +//│ discarded3 = globalThis.console$__checkNotMethod; //│ if (selRes3 === undefined) { //│ throw globalThis.Object.freeze(new globalThis.Error("Access to required field 'console' yielded 'undefined'")) //│ } //│ tmp6 = runtime.checkCall(M1.A(1)); //│ selRes4 = tmp6.y; -//│ discarded2 = tmp6.y$__checkNotMethod; +//│ discarded4 = tmp6.y$__checkNotMethod; //│ if (selRes4 === undefined) { //│ throw globalThis.Object.freeze(new globalThis.Error("Access to required field 'y' yielded 'undefined'")) //│ } diff --git a/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls b/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls index 6fef83e19d..bfd51abc7c 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls @@ -2,13 +2,12 @@ class Foo with val foo: Foo = new Foo -// * TODO: new-expression should also be resolvable for its type :rt new Foo //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = New: +//│ res = New{typ=class:Foo}: //│ cls = Resolved{sym=class:Foo}: //│ t = Ref{sym=member:Foo} of member:Foo //│ sym = class:Foo @@ -52,13 +51,12 @@ foo.foo class Foo2[A, B] with val foo: Foo2[Int, Str] = new Foo2 -// * TODO: new-expression should also be resolvable for its type :rt new Foo2 //│ Resolved tree: //│ Blk: //│ stats = Nil -//│ res = New: +//│ res = New{typ=class:Foo2}: //│ cls = Resolved{sym=class:Foo2}: //│ t = Ref{sym=member:Foo2} of member:Foo2 //│ sym = class:Foo2 diff --git a/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls b/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls index c5e092b9d1..1e249418bc 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls @@ -54,7 +54,7 @@ foo(10) //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "M"]; //│ }); -//│ foo1 = function foo(y) { let tmp; tmp = M$(false, y); return runtime.safeCall(tmp.foo()) }; +//│ foo1 = function foo(y) { let tmp; tmp = M$(false, y); return tmp.foo() }; //│ foo1(10) @@ -211,9 +211,9 @@ M.hi.get //│ FAILURE: Unexpected runtime error //│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) //│ ═══[RUNTIME ERROR] TypeError: this.A is not a function -//│ at new M12 (REPL62:1:1139) -//│ at (REPL62:1:1043) -//│ at REPL62:1:1292 +//│ at new M12 (REPL62:1:1151) +//│ at (REPL62:1:1055) +//│ at REPL62:1:1304 //│ at ContextifyScript.runInThisContext (node:vm:137:12) //│ at REPLServer.defaultEval (node:repl:593:22) //│ at bound (node:domain:433:15) @@ -306,8 +306,8 @@ M.A(2).newB.newA_B(3).newB.get //│ FAILURE: Unexpected runtime error //│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) //│ ═══[RUNTIME ERROR] TypeError: this.B is not a function -//│ at get newB (REPL74:1:1717) -//│ at REPL74:1:2101 +//│ at get newB (REPL74:1:1732) +//│ at REPL74:1:2116 //│ at ContextifyScript.runInThisContext (node:vm:137:12) //│ at REPLServer.defaultEval (node:repl:593:22) //│ at bound (node:domain:433:15) From 37dc34a25dca3657b336471a6d74b8abe71eac61 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Fri, 31 Oct 2025 23:42:53 +0800 Subject: [PATCH 17/55] Fix instanceof for objects --- .../scala/hkmc2/codegen/js/JSBuilder.scala | 2 +- hkmc2/shared/src/test/mlscript/HkScratch.mls | 21 ++++++- .../src/test/mlscript/codegen/CaseOfCase.mls | 4 +- .../test/mlscript/codegen/CaseShorthand.mls | 2 +- .../test/mlscript/codegen/ClassMatching.mls | 6 +- .../test/mlscript/codegen/MergeMatchArms.mls | 58 +++++++++---------- .../src/test/mlscript/codegen/OptMatch.mls | 4 +- .../shared/src/test/mlscript/nofib/boyer2.mls | 49 +++++++++++++++- .../ucs/patterns/ConjunctionPattern.mls | 2 +- 9 files changed, 107 insertions(+), 41 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala index c360dec7a6..dddd7f26fe 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala @@ -469,7 +469,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: case Elaborator.ctx.builtins.BigInt => doc"typeof $sd === 'bigint'" case Elaborator.ctx.builtins.Symbol.module => doc"typeof $sd === 'symbol'" case Elaborator.ctx.builtins.TypedArray => doc"globalThis.ArrayBuffer.isView($sd) && !($sd instanceof globalThis.DataView)" - case _: ModuleOrObjectSymbol => doc"$sd === ${result(pth)}" + case _: ModuleOrObjectSymbol => doc"$sd instanceof ${result(pth)}.class" case _ => doc"$sd instanceof ${result(pth)}" case Case.Tup(len, inf) => doc"$runtimeVar.Tuple.isArrayLike($sd) && $sd.length ${if inf then ">=" else "==="} ${len}" case Case.Field(name = n, safe = false) => diff --git a/hkmc2/shared/src/test/mlscript/HkScratch.mls b/hkmc2/shared/src/test/mlscript/HkScratch.mls index ef38e8b363..43d31f0aca 100644 --- a/hkmc2/shared/src/test/mlscript/HkScratch.mls +++ b/hkmc2/shared/src/test/mlscript/HkScratch.mls @@ -9,4 +9,23 @@ // :todo - +:sjs +object Foo +Foo is Foo +//│ JS (unsanitized): +//│ let Foo1, scrut; +//│ globalThis.Object.freeze(class Foo { +//│ static { +//│ Foo1 = globalThis.Object.freeze(new this) +//│ } +//│ constructor() { +//│ Object.defineProperty(this, "class", { +//│ value: Foo +//│ }) +//│ } +//│ toString() { return runtime.render(this); } +//│ static [definitionMetadata] = ["object", "Foo"]; +//│ }); +//│ scrut = Foo1; +//│ if (scrut instanceof Foo1.class) { true } else { false } +//│ = true diff --git a/hkmc2/shared/src/test/mlscript/codegen/CaseOfCase.mls b/hkmc2/shared/src/test/mlscript/codegen/CaseOfCase.mls index c6afcea9e6..d8a18fff1b 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/CaseOfCase.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/CaseOfCase.mls @@ -23,7 +23,7 @@ fun test(x) = //│ v = param0; //│ tmp = v + 1; //│ tmp1 = Some1(tmp); -//│ } else if (x === None1) { +//│ } else if (x instanceof None1.class) { //│ tmp1 = None1; //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) @@ -33,7 +33,7 @@ fun test(x) = //│ param01 = scrut.value; //│ v1 = param01; //│ return Predef.print(v1) -//│ } else if (scrut === None1) { +//│ } else if (scrut instanceof None1.class) { //│ return Predef.print("none") //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ }; diff --git a/hkmc2/shared/src/test/mlscript/codegen/CaseShorthand.mls b/hkmc2/shared/src/test/mlscript/codegen/CaseShorthand.mls index c7dd5566e0..510dbe3eeb 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/CaseShorthand.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/CaseShorthand.mls @@ -83,7 +83,7 @@ val isDefined = case //│ lambda12 = (undefined, function (caseScrut) { //│ if (caseScrut instanceof Some1.class) { //│ return true -//│ } else if (caseScrut === None1) { +//│ } else if (caseScrut instanceof None1.class) { //│ return false //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) diff --git a/hkmc2/shared/src/test/mlscript/codegen/ClassMatching.mls b/hkmc2/shared/src/test/mlscript/codegen/ClassMatching.mls index 1b2bf67697..0fe73cf074 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/ClassMatching.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/ClassMatching.mls @@ -130,7 +130,7 @@ fun f(x) = if x is //│ } else { //│ return Predef.print("oops") //│ } -//│ } else if (x3 === None1) { return "ok" } else { return Predef.print("oops") } +//│ } else if (x3 instanceof None1.class) { return "ok" } else { return Predef.print("oops") } //│ }; f(Some(0)) @@ -194,7 +194,9 @@ fun f(x) = print of if x is //│ } else { //│ tmp8 = "oops"; //│ } -//│ } else if (x3 === None1) { tmp8 = "ok"; } else { tmp8 = "oops"; } +//│ } else if (x3 instanceof None1.class) { +//│ tmp8 = "ok"; +//│ } else { tmp8 = "oops"; } //│ return Predef.print(tmp8) //│ }; diff --git a/hkmc2/shared/src/test/mlscript/codegen/MergeMatchArms.mls b/hkmc2/shared/src/test/mlscript/codegen/MergeMatchArms.mls index 40e6bda17b..bb1dc3e77b 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/MergeMatchArms.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/MergeMatchArms.mls @@ -19,13 +19,13 @@ if a is C then 3 D then 4 //│ JS (unsanitized): -//│ if (a === A1) { +//│ if (a instanceof A1.class) { //│ 1 -//│ } else if (a === B1) { +//│ } else if (a instanceof B1.class) { //│ 2 -//│ } else if (a === C1) { +//│ } else if (a instanceof C1.class) { //│ 3 -//│ } else if (a === D1) { +//│ } else if (a instanceof D1.class) { //│ 4 //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ = 1 @@ -40,11 +40,11 @@ if a is B then 2 C then 3 //│ JS (unsanitized): -//│ if (a === A1) { +//│ if (a instanceof A1.class) { //│ 1 -//│ } else if (a === B1) { +//│ } else if (a instanceof B1.class) { //│ 2 -//│ } else if (a === C1) { +//│ } else if (a instanceof C1.class) { //│ 3 //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ = 1 @@ -58,17 +58,17 @@ if a is B then 2 C then 3 //│ JS (unsanitized): -//│ if (a === A1) { -//│ if (b === A1) { +//│ if (a instanceof A1.class) { +//│ if (b instanceof A1.class) { //│ 1 -//│ } else if (b === B1) { +//│ } else if (b instanceof B1.class) { //│ 2 //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) //│ } -//│ } else if (a === B1) { +//│ } else if (a instanceof B1.class) { //│ 2 -//│ } else if (a === C1) { +//│ } else if (a instanceof C1.class) { //│ 3 //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ = 2 @@ -94,23 +94,23 @@ print(x) //│ JS (unsanitized): //│ let x, tmp, tmp1, tmp2, tmp3; //│ tmp = 3; -//│ if (a === A1) { +//│ if (a instanceof A1.class) { //│ tmp1 = 1; -//│ } else if (a === B1) { +//│ } else if (a instanceof B1.class) { //│ tmp1 = 2; -//│ } else if (a === C1) { +//│ } else if (a instanceof C1.class) { //│ tmp1 = 3; -//│ } else if (a === D1) { -//│ if (a === A1) { +//│ } else if (a instanceof D1.class) { +//│ if (a instanceof A1.class) { //│ tmp2 = 1 + tmp; -//│ } else if (a === B1) { +//│ } else if (a instanceof B1.class) { //│ tmp2 = 2 + tmp; //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) //│ } //│ tmp3 = tmp2; //│ tmp1 = Predef.print("done"); -//│ } else if (a === E1) { +//│ } else if (a instanceof E1.class) { //│ tmp3 = 5; //│ tmp1 = Predef.print("done"); //│ } else { @@ -132,9 +132,9 @@ if a is //│ JS (unsanitized): //│ let tmp4; //│ tmp4 = 2; -//│ if (a === A1) { +//│ if (a instanceof A1.class) { //│ 1 -//│ } else if (a === B1) { +//│ } else if (a instanceof B1.class) { //│ 2 + tmp4 //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ = 1 @@ -153,11 +153,11 @@ if a is B then 2 + tmp //│ JS (unsanitized): //│ let tmp5; -//│ if (a === A1) { +//│ if (a instanceof A1.class) { //│ 1 //│ } else { //│ tmp5 = printAndId(3); -//│ if (a === B1) { +//│ if (a instanceof B1.class) { //│ 2 + tmp5 //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ } @@ -176,13 +176,13 @@ if a is print(x) //│ JS (unsanitized): //│ let x1, tmp6; -//│ if (a === A1) { +//│ if (a instanceof A1.class) { //│ 1 -//│ } else if (a === B1) { +//│ } else if (a instanceof B1.class) { //│ tmp6 = 2; //│ x1 = tmp6; //│ Predef.print(x1) -//│ } else if (a === C1) { +//│ } else if (a instanceof C1.class) { //│ tmp6 = 3; //│ x1 = tmp6; //│ Predef.print(x1) @@ -205,12 +205,12 @@ if a is print(x + 2) //│ JS (unsanitized): //│ let x2, tmp7, tmp8, tmp9, tmp10, tmp11; -//│ if (a === B1) { +//│ if (a instanceof B1.class) { //│ 1 //│ } else { -//│ if (a === A1) { +//│ if (a instanceof A1.class) { //│ tmp7 = 2; -//│ } else if (a === C1) { +//│ } else if (a instanceof C1.class) { //│ tmp7 = 3; //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) diff --git a/hkmc2/shared/src/test/mlscript/codegen/OptMatch.mls b/hkmc2/shared/src/test/mlscript/codegen/OptMatch.mls index 08e8143455..3e710ba474 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/OptMatch.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/OptMatch.mls @@ -14,7 +14,7 @@ fun isDefined(x) = if x is //│ isDefined = function isDefined(x) { //│ if (x instanceof Some1.class) { //│ return true -//│ } else if (x === None1) { +//│ } else if (x instanceof None1.class) { //│ return false //│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ }; @@ -37,7 +37,7 @@ val isDefined = case //│ if (caseScrut instanceof Some1.class) { //│ param0 = caseScrut.value; //│ return true -//│ } else if (caseScrut === None1) { +//│ } else if (caseScrut instanceof None1.class) { //│ return false //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) diff --git a/hkmc2/shared/src/test/mlscript/nofib/boyer2.mls b/hkmc2/shared/src/test/mlscript/nofib/boyer2.mls index e4a9ece8f6..8cb3463807 100644 --- a/hkmc2/shared/src/test/mlscript/nofib/boyer2.mls +++ b/hkmc2/shared/src/test/mlscript/nofib/boyer2.mls @@ -425,10 +425,40 @@ let rules = nofibStringToList("(equal (flatten (cdr (gopher x) ) )(if (listp x)(cdr (flatten x) )(Conss (zero)(Nill) ) ) )") :: nofibStringToList("(equal (quotient (times y x)y)(if (zerop y)(zero)(fix x) ) )") :: nofibStringToList("(equal (get j (set i val mem) )(if (eqp j i)val(get j mem) ) )") :: Nil -//│ rules = [["(","e","q","u","a","l"," ","(","c","o","m","p","i","l","e"," ","f","o","r","m",")","(","r","e","v","e","r","s","e"," ","(","c","o","d","e","g","e","n"," ","(","o","p","t","i","m","i","z","e"," ","f","o","r","m",")"," ","(","N","i","l","l",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","p"," ","x"," ","y",")","(","e","q","u","a","l"," ","(","f","i","x"," ","x",")","(","f","i","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","r","e","a","t","e","r","p"," ","x"," ","y",")","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","e","q","p"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","r","e","a","t","e","r","e","q","p"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","b","o","o","l","e","a","n"," ","x",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","t",")"," ",")","(","e","q","u","a","l"," ","x"," ","(","f",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","i","f","f"," ","x"," ","y",")","(","a","n","d"," ","(","i","m","p","l","i","e","s"," ","x"," ","y",")","(","i","m","p","l","i","e","s"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","v","e","n","1"," ","x",")","(","i","f"," ","(","z","e","r","o","p"," ","x",")","(","t",")","(","o","d","d"," ","(","1","-"," ","x",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","c","o","u","n","t","p","s","-"," ","l"," ","p","r","e","d",")","(","c","o","u","n","t","p","s","-","l","o","o","p"," ","l"," ","p","r","e","d"," ","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","a","c","t","-"," ","i",")","(","f","a","c","t","-","l","o","o","p"," ","i"," ","1",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e","-"," ","x",")","(","r","e","v","e","r","s","e","-","l","o","o","p"," ","x"," ","(","N","i","l","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","v","i","d","e","s"," ","x"," ","y",")","(","z","e","r","o","p"," ","(","r","e","m","a","i","n","d","e","r"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","s","s","u","m","e","-","t","r","u","e"," ","v","a","r"," ","a","l","i","s","t",")","(","C","o","n","s","s"," ","(","C","o","n","s","s"," ","v","a","r"," ","(","t",")"," ",")","a","l","i","s","t",")"," ",")"],["(","e","q","u","a","l"," ","(","a","s","s","u","m","e","-","f","a","l","s","e"," ","v","a","r"," ","a","l","i","s","t",")","(","C","o","n","s","s"," ","(","C","o","n","s","s"," ","v","a","r"," ","(","f",")"," ",")","a","l","i","s","t",")"," ",")"],["(","e","q","u","a","l"," ","(","t","a","u","t","o","l","o","g","y","-","c","h","e","c","k","e","r"," ","x",")","(","t","a","u","t","o","l","o","g","y","p"," ","(","n","o","r","m","a","l","i","z","e"," ","x",")","(","N","i","l","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","a","l","s","i","f","y"," ","x",")","(","f","a","l","s","i","f","y","1"," ","(","n","o","r","m","a","l","i","z","e"," ","x",")","(","N","i","l","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","r","i","m","e"," ","x",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","x",")",")","(","n","o","t"," ","(","e","q","u","a","l"," ","x"," ","(","a","d","d","1"," ","(","z","e","r","o",")"," ",")"," ",")"," ",")","(","p","r","i","m","e","1"," ","x"," ","(","1","-"," ","x",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","n","d"," ","p"," ","q",")","(","i","f"," ","p"," ","(","i","f"," ","q"," ","(","t",")"," ","(","f",")"," ",")"," ","(","f",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","o","r"," ","p"," ","q",")","(","i","f"," ","p"," ","(","t",")"," ","(","i","f"," ","q"," ","(","t",")"," ","(","f",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","n","o","t"," ","p",")","(","i","f"," ","p"," ","(","f",")"," ","(","t",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","i","m","p","l","i","e","s"," ","p"," ","q",")","(","i","f"," ","p"," ","(","i","f"," ","q"," ","(","t",")"," ","(","f",")"," ",")"," ","(","t",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","i","x"," ","x",")","(","i","f"," ","(","n","u","m","b","e","r","p"," ","x",")"," ","x"," ","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","i","f"," ","(","i","f"," ","a"," ","b"," ","c",")"," ","d"," ","e",")","(","i","f"," ","a"," ","(","i","f"," ","b"," ","d"," ","e",")"," ","(","i","f"," ","c"," ","d"," ","e",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","z","e","r","o","p"," ","x",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")","(","n","o","t"," ","(","n","u","m","b","e","r","p"," ","x",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","l","u","s"," ","(","p","l","u","s"," ","x"," ","y",")"," ","z"," ",")","(","p","l","u","s"," ","x"," ","(","p","l","u","s"," ","y"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","p","l","u","s"," ","a"," ","b",")"," ","(","z","e","r","o"," ",")"," ",")","(","a","n","d"," ","(","z","e","r","o","p"," ","a",")"," ","(","z","e","r","o","p"," ","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","x",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","p","l","u","s"," ","a"," ","b",")"," ","(","p","l","u","s"," ","a"," ","c",")"," ",")","(","e","q","u","a","l"," ","(","f","i","x"," ","b",")"," ","(","f","i","x"," ","c",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","z","e","r","o",")"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","y",")"," ",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","x"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","y",")"," ",")","(","a","n","d"," ","(","n","u","m","b","e","r","p"," ","x",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")","(","z","e","r","o","p"," ","y",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ",")"," ","a",")","(","p","l","u","s"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","x",")"," ","a",")","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","y",")"," ","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","(","p","l","u","s","-","f","r","i","n","g","e"," ","x",")"," ",")"," ","a",")","(","f","i","x"," ","(","m","e","a","n","i","n","g"," ","x"," ","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","p","p","e","n","d"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ","z",")","(","a","p","p","e","n","d"," ","x"," ","(","a","p","p","e","n","d"," ","y"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","a","p","p","e","n","d"," ","(","r","e","v","e","r","s","e"," ","b",")"," ","(","r","e","v","e","r","s","e"," ","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","(","p","l","u","s"," ","y"," ","z",")"," ",")","(","p","l","u","s"," ","(","t","i","m","e","s"," ","x"," ","y",")","(","t","i","m","e","s"," ","x"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ","z",")","(","t","i","m","e","s"," ","x"," ","(","t","i","m","e","s"," ","y"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ","(","z","e","r","o",")"," ",")","(","o","r"," ","(","z","e","r","o","p"," ","x",")","(","z","e","r","o","p"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","x","e","c"," ","(","a","p","p","e","n","d"," ","x"," ","y",")","p","d","s"," ","e","n","v","r","n",")","(","e","x","e","c"," ","y"," ","(","e","x","e","c"," ","x"," ","p","d","s"," ","e","n","v","r","n",")","e","n","v","r","n",")"," ",")"],["(","e","q","u","a","l"," ","(","m","c","-","f","l","a","t","t","e","n"," ","x"," ","y",")","(","a","p","p","e","n","d"," ","(","f","l","a","t","t","e","n"," ","x",")","y",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","m","b","e","r"," ","x"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","o","r"," ","(","m","e","m","b","e","r"," ","x"," ","a",")","(","m","e","m","b","e","r"," ","x"," ","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","m","b","e","r"," ","x"," ","(","r","e","v","e","r","s","e"," ","y",")"," ",")","(","m","e","m","b","e","r"," ","x"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","n","g","t","h"," ","(","r","e","v","e","r","s","e"," ","x",")"," ",")","(","l","e","n","g","t","h"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","m","b","e","r"," ","a"," ","(","i","n","t","e","r","s","e","c","t"," ","b"," ","c",")"," ",")","(","a","n","d"," ","(","m","e","m","b","e","r"," ","a"," ","b",")","(","m","e","m","b","e","r"," ","a"," ","c",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","n","t","h"," ","(","z","e","r","o",")","i",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","e","x","p"," ","i"," ","(","p","l","u","s"," ","j"," ","k",")"," ",")","(","t","i","m","e","s"," ","(","e","x","p"," ","i"," ","j",")","(","e","x","p"," ","i"," ","k",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","x","p"," ","i"," ","(","t","i","m","e","s"," ","j"," ","k",")"," ",")","(","e","x","p"," ","(","e","x","p"," ","i"," ","j",")","k",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e","-","l","o","o","p"," ","x"," ","y",")","(","a","p","p","e","n","d"," ","(","r","e","v","e","r","s","e"," ","x",")","y",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e","-","l","o","o","p"," ","x"," ","(","N","i","l","l",")"," ",")","(","r","e","v","e","r","s","e"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","c","o","u","n","t","-","l","i","s","t"," ","z"," ","(","s","o","r","t","-","l","p"," ","x"," ","y",")"," ",")","(","p","l","u","s"," ","(","c","o","u","n","t","-","l","i","s","t"," ","z"," ","x",")","(","c","o","u","n","t","-","l","i","s","t"," ","z"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","a","p","p","e","n","d"," ","a"," ","b",")","(","a","p","p","e","n","d"," ","a"," ","c",")"," ",")","(","e","q","u","a","l"," ","b"," ","c",")"," ",")"],["(","e","q","u","a","l"," ","(","p","l","u","s"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","y",")","(","t","i","m","e","s"," ","y"," ","(","q","u","o","t","i","e","n","t"," ","x"," ","y",")"," ",")"," ",")","(","f","i","x"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","b","i","g","-","p","l","u","s","1"," ","l"," ","i"," ","b","a","s","e",")","b","a","s","e",")","(","p","l","u","s"," ","(","p","o","w","e","r","-","e","v","a","l"," ","l"," ","b","a","s","e",")","i",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","b","i","g","-","p","l","u","s"," ","x"," ","y"," ","i"," ","b","a","s","e",")","b","a","s","e",")","(","p","l","u","s"," ","i"," ","(","p","l","u","s"," ","(","p","o","w","e","r","-","e","v","a","l"," ","x"," ","b","a","s","e",")","(","p","o","w","e","r","-","e","v","a","l"," ","y"," ","b","a","s","e",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","y"," ","1",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","y",")","y",")","(","n","o","t"," ","(","z","e","r","o","p"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","x",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","q","u","o","t","i","e","n","t"," ","i"," ","j",")","i",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","i",")"," ",")","(","o","r"," ","(","z","e","r","o","p"," ","j",")","(","n","o","t"," ","(","e","q","u","a","l"," ","j"," ","1",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","y",")","x",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","y",")"," ",")","(","n","o","t"," ","(","z","e","r","o","p"," ","x",")"," ",")","(","n","o","t"," ","(","l","e","s","s","p"," ","x"," ","y",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","p","o","w","e","r","-","r","e","p"," ","i"," ","b","a","s","e",")","b","a","s","e",")","(","f","i","x"," ","i",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","b","i","g","-","p","l","u","s"," ","(","p","o","w","e","r","-","r","e","p"," ","i"," ","b","a","s","e",")","(","p","o","w","e","r","-","r","e","p"," ","j"," ","b","a","s","e",")","(","z","e","r","o",")","b","a","s","e",")","b","a","s","e",")","(","p","l","u","s"," ","i"," ","j",")"," ",")"],["(","e","q","u","a","l"," ","(","g","c","d"," ","x"," ","y",")","(","g","c","d"," ","y"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","n","t","h"," ","(","a","p","p","e","n","d"," ","a"," ","b",")","i",")","(","a","p","p","e","n","d"," ","(","n","t","h"," ","a"," ","i",")","(","n","t","h"," ","b"," ","(","d","i","f","f","e","r","e","n","c","e"," ","i"," ","(","l","e","n","g","t","h"," ","a",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","x"," ","y",")","x",")","(","f","i","x"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","y"," ","x",")","x",")","(","f","i","x"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","x"," ","y",")","(","p","l","u","s"," ","x"," ","z",")"," ",")","(","d","i","f","f","e","r","e","n","c","e"," ","y"," ","z",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","(","d","i","f","f","e","r","e","n","c","e"," ","c"," ","w",")"," ",")","(","d","i","f","f","e","r","e","n","c","e"," ","(","t","i","m","e","s"," ","c"," ","x",")","(","t","i","m","e","s"," ","w"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","(","t","i","m","e","s"," ","x"," ","z",")","z",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","b"," ","(","p","l","u","s"," ","a"," ","c",")"," ",")","a",")","(","p","l","u","s"," ","b"," ","c",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","a","d","d","1"," ","(","p","l","u","s"," ","y"," ","z",")","z",")","(","a","d","d","1"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","p","l","u","s"," ","x"," ","y",")","(","p","l","u","s"," ","x"," ","z"," ",")"," ",")","(","l","e","s","s","p"," ","y"," ","z",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","t","i","m","e","s"," ","x"," ","z",")","(","t","i","m","e","s"," ","y"," ","z",")"," ",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","z",")"," ",")","(","l","e","s","s","p"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","y"," ","(","p","l","u","s"," ","x"," ","y",")"," ",")","(","n","o","t"," ","(","z","e","r","o","p"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","c","d"," ","(","t","i","m","e","s"," ","x"," ","z",")","(","t","i","m","e","s"," ","y"," ","z",")"," ",")","(","t","i","m","e","s"," ","z"," ","(","g","c","d"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","v","a","l","u","e"," ","(","n","o","r","m","a","l","i","z","e"," ","x",")","a",")","(","v","a","l","u","e"," ","x"," ","a",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","f","l","a","t","t","e","n"," ","x",")","(","C","o","n","s","s"," ","y"," ","(","N","i","l","l",")"," ",")"," ",")","(","a","n","d"," ","(","n","l","i","s","t","p"," ","x",")","(","e","q","u","a","l"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","i","s","t","p"," ","(","g","o","p","h","e","r"," ","x",")"," ",")","(","l","i","s","t","p"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","s","a","m","e","f","r","i","n","g","e"," ","x"," ","y",")","(","e","q","u","a","l"," ","(","f","l","a","t","t","e","n"," ","x",")","(","f","l","a","t","t","e","n"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"," ","x"," ","y",")","(","z","e","r","o",")"," ",")","(","a","n","d"," ","(","o","r"," ","(","z","e","r","o","p"," ","y",")","(","e","q","u","a","l"," ","y"," ","1",")"," ",")","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"," ","x"," ","y",")","1",")","(","e","q","u","a","l"," ","x"," ","1",")"," ",")"],["(","e","q","u","a","l"," ","(","n","u","m","b","e","r","p"," ","(","g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"," ","x"," ","y",")"," ",")","(","n","o","t"," ","(","a","n","d"," ","(","o","r"," ","(","z","e","r","o","p"," ","y",")","(","e","q","u","a","l"," ","y"," ","1",")"," ",")","(","n","o","t"," ","(","n","u","m","b","e","r","p"," ","x",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s","-","l","i","s","t"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ",")","(","t","i","m","e","s"," ","(","t","i","m","e","s","-","l","i","s","t"," ","x",")","(","t","i","m","e","s","-","l","i","s","t"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","r","i","m","e","-","l","i","s","t"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ",")","(","a","n","d"," ","(","p","r","i","m","e","-","l","i","s","t"," ","x",")","(","p","r","i","m","e","-","l","i","s","t"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","z"," ","(","t","i","m","e","s"," ","w"," ","z",")"," ",")","(","a","n","d"," ","(","n","u","m","b","e","r","p"," ","z",")","(","o","r"," ","(","e","q","u","a","l"," ","z"," ","(","z","e","r","o",")"," ",")","(","e","q","u","a","l"," ","w"," ","1",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","r","e","a","t","e","r","e","q","p","r"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","x"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")","(","a","n","d"," ","(","n","u","m","b","e","r","p"," ","x",")","(","e","q","u","a","l"," ","y"," ","1",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","(","t","i","m","e","s"," ","y"," ","x",")","y",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","a"," ","b",")","1",")","(","a","n","d"," ","(","n","o","t"," ","(","e","q","u","a","l"," ","a"," ","(","z","e","r","o",")"," ",")"," ",")","(","n","o","t"," ","(","e","q","u","a","l"," ","b"," ","(","z","e","r","o",")"," ",")"," ",")","(","n","u","m","b","e","r","p"," ","a",")","(","n","u","m","b","e","r","p"," ","b",")","(","e","q","u","a","l"," ","(","1","-"," ","a",")","(","z","e","r","o",")"," ",")","(","e","q","u","a","l"," ","(","1","-"," ","b",")","(","z","e","r","o",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","l","e","n","g","t","h"," ","(","d","e","l","e","t","e"," ","x"," ","l",")"," ",")","(","l","e","n","g","t","h"," ","l",")"," ",")","(","m","e","m","b","e","r"," ","x"," ","l",")"," ",")"],["(","e","q","u","a","l"," ","(","s","o","r","t","2"," ","(","d","e","l","e","t","e"," ","x"," ","l",")"," ",")","(","d","e","l","e","t","e"," ","x"," ","(","s","o","r","t","2"," ","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","s","o","r","t"," ","x",")","(","s","o","r","t","2"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","n","g","t","h","(","C","o","n","s","s"," ","x","1","(","C","o","n","s","s"," ","x","2","(","C","o","n","s","s"," ","x","3","(","C","o","n","s","s"," ","x","4","(","C","o","n","s","s"," ","x","5","(","C","o","n","s","s"," ","x","6"," ","x","7",")"," ",")"," ",")"," ",")"," ",")"," ",")"," ",")","(","p","l","u","s"," ","6"," ","(","l","e","n","g","t","h"," ","x","7",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","a","d","d","1"," ","(","a","d","d","1"," ","x",")"," ",")","2",")","(","f","i","x"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","q","u","o","t","i","e","n","t"," ","(","p","l","u","s"," ","x"," ","(","p","l","u","s"," ","x"," ","y",")"," ",")","2",")","(","p","l","u","s"," ","x"," ","(","q","u","o","t","i","e","n","t"," ","y"," ","2",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","s","i","g","m","a"," ","(","z","e","r","o",")","i",")","(","q","u","o","t","i","e","n","t"," ","(","t","i","m","e","s"," ","i"," ","(","a","d","d","1"," ","i",")"," ",")","2",")"," ",")"],["(","e","q","u","a","l"," ","(","p","l","u","s"," ","x"," ","(","a","d","d","1"," ","y",")"," ",")","(","i","f"," ","(","n","u","m","b","e","r","p"," ","y",")","(","a","d","d","1"," ","(","p","l","u","s"," ","x"," ","y",")"," ",")","(","a","d","d","1"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","y",")","(","d","i","f","f","e","r","e","n","c","e"," ","z"," ","y",")"," ",")","(","i","f"," ","(","l","e","s","s","p"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","z",")"," ",")","(","i","f"," ","(","l","e","s","s","p"," ","z"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")","(","e","q","u","a","l"," ","(","f","i","x"," ","x",")","(","f","i","x"," ","z",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","(","d","e","l","e","t","e"," ","x"," ","y",")"," ",")","a",")","(","i","f"," ","(","m","e","m","b","e","r"," ","x"," ","y",")","(","d","i","f","f","e","r","e","n","c","e"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","y",")","a",")","(","m","e","a","n","i","n","g"," ","x"," ","a",")"," ",")","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","y",")","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","(","a","d","d","1"," ","y",")"," ",")","(","i","f"," ","(","n","u","m","b","e","r","p"," ","y",")","(","p","l","u","s"," ","x"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ",")","(","f","i","x"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","n","t","h"," ","(","N","i","l","l",")","i",")","(","i","f"," ","(","z","e","r","o","p"," ","i",")","(","N","i","l","l",")","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","a","s","t"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","i","f"," ","(","l","i","s","t","p"," ","b",")","(","l","a","s","t"," ","b",")","(","i","f"," ","(","l","i","s","t","p"," ","a",")","(","C","o","n","s","s"," ","(","c","a","r"," ","(","l","a","s","t"," ","a",")"," ",")","b",")","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","x"," ","y",")","z",")","(","i","f"," ","(","l","e","s","s","p"," ","x"," ","y",")","(","e","q","u","a","l"," ","t"," ","z",")","(","e","q","u","a","l"," ","f"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","s","s","i","g","n","m","e","n","t"," ","x"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","i","f"," ","(","a","s","s","i","g","n","e","d","p"," ","x"," ","a",")","(","a","s","s","i","g","n","m","e","n","t"," ","x"," ","a",")","(","a","s","s","i","g","n","m","e","n","t"," ","x"," ","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","c","a","r"," ","(","g","o","p","h","e","r"," ","x",")"," ",")","(","i","f"," ","(","l","i","s","t","p"," ","x",")","(","c","a","r"," ","(","f","l","a","t","t","e","n"," ","x",")"," ",")","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","l","a","t","t","e","n"," ","(","c","d","r"," ","(","g","o","p","h","e","r"," ","x",")"," ",")"," ",")","(","i","f"," ","(","l","i","s","t","p"," ","x",")","(","c","d","r"," ","(","f","l","a","t","t","e","n"," ","x",")"," ",")","(","C","o","n","s","s"," ","(","z","e","r","o",")","(","N","i","l","l",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","q","u","o","t","i","e","n","t"," ","(","t","i","m","e","s"," ","y"," ","x",")","y",")","(","i","f"," ","(","z","e","r","o","p"," ","y",")","(","z","e","r","o",")","(","f","i","x"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","e","t"," ","j"," ","(","s","e","t"," ","i"," ","v","a","l"," ","m","e","m",")"," ",")","(","i","f"," ","(","e","q","p"," ","j"," ","i",")","v","a","l","(","g","e","t"," ","j"," ","m","e","m",")"," ",")"," ",")"]] +//│ FAILURE: Unexpected exception +//│ /!!!\ Uncaught error: java.lang.StackOverflowError :silent let lemmas = addlemmalst(makelemmas(rules), Empty) +//│ FAILURE: Unexpected compilation error +//│ FAILURE LOCATION: lookup_! (Scope.scala:112) +//│ FAILURE INFO: Tuple2: +//│ _1 = Tuple2: +//│ _1 = rules +//│ _2 = class hkmc2.semantics.VarSymbol +//│ _2 = Scope: +//│ parent = N +//│ curThis = S of S of globalThis:globalThis +//│ bindings = HashMap($block$res -> block$res19, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:assoc -> assoc, $prettyPrint -> prettyPrint, $Term -> Term, $block$res -> block$res20, $block$res -> block$res21, member:LUT -> LUT1, class:LUT -> LUT, $block$res -> block$res22, member:Empty -> Empty1, object:Empty -> Empty, $block$res -> block$res23, member:Node -> Node1, class:Node -> Node, $block$res -> block$res24, member:addtoLUT -> addtoLUT, member:Lisplist -> Lisplist1, class:Lisplist -> Lisplist, $block$res -> block$res2, $block$res -> block$res, member:Conss -> Conss1, member:Atom -> Atom1, $block$res -> block$res25, member:Nill -> Nill1, object:Nill -> Nill, class:Atom -> Atom, class:Conss -> Conss, member:enumFrom -> enumFrom, member:LzList -> LzList1, member:leave_lz -> leave_lz, member:sum -> sum, member:nub_lz -> nub_lz, member:LzNil -> LzNil1, member:getLUT -> getLUT, member:intDiv -> intDiv, member:Nil -> Nil1, member:ltList -> ltList, $block$res -> block$res3, member:divMod -> divMod, member:lispListEq -> lispListEq, member:scanl -> scanl, member:zip_lz_lz -> zip_lz_lz, member:nofibListToString -> nofibListToString, member:orList -> orList, member:lazy -> lazy, member:atIndex -> atIndex, member:_internal_cons_to_str -> _internal_cons_to_str, member:force -> force, member:stringOfFloat -> stringOfFloat, member:unionBy -> unionBy, member:splitAt -> splitAt, member:nubBy_lz -> nubBy_lz, member:union -> union, member:zip -> zip, member:compose -> compose, member:fromSome -> fromSome, member:take_lz_lz -> take_lz_lz, member:stringConcat -> stringConcat, member:map -> map, member:all -> all, member:head -> head, member:zipWith_lz_lz -> zipWith_lz_lz, member:unzip -> unzip, $block$res -> block$res4, member:null_ -> null_, member:concat -> concat, member:break_ -> break_, member:lispmember -> lispmember, member:zip_lz_nl -> zip_lz_nl, member:truep -> truep, member:min -> min, $block$res -> block$res26, member:eqTup2 -> eqTup2, member:filter_lz -> filter_lz, member:intQuot -> intQuot, member:zipWith -> zipWith, member:scanr -> scanr, member:makelemmas -> makelemmas, member:replicate -> replicate, member:append_nl_lz -> append_nl_lz, member:tail -> tail, member:cos -> cos, member:int_of_char -> int_of_char, member:LzCons -> LzCons1, member:map_lz -> map_lz, member:until -> until, member:ltTup2 -> ltTup2, member:Cons -> Cons1, member:Lazy -> Lazy1, member:zipWith_lz_nl -> zipWith_lz_nl, member:snd -> snd, member:reverse -> reverse, $block$res -> block$res27, member:filter -> filter, member:append_lz_lz -> append_lz_lz, member:quotRem -> quotRem, member:maximum -> maximum, member:addlemma -> addlemma, member:take_lz -> take_lz, member:replicate_lz -> replicate_lz, member:zip3 -> zip3, member:leaveWhile -> leaveWhile, member:enumFromTo -> enumFromTo, member:max -> max, member:foldl -> foldl, member:enumFromThenTo -> enumFromThenTo, $block$res -> block$res5, member:sqrt -> sqrt, member:flatMap -> flatMap, member:intRem -> intRem, member:take -> take, member:listEqBy -> listEqBy, member:flip -> flip, member:Some -> Some1, member:falsep -> falsep, member:inList -> inList, member:nofibStringToList -> nofibStringToList, member:Option -> Option1, member:intMod -> intMod, member:None -> None1, member:head_lz -> head_lz, member:notElem -> notElem, member:round -> round, member:iterate -> iterate, $block$res -> block$res28, member:transpose -> transpose, member:while_ -> while_, member:repeat -> repeat, member:power -> power, member:foldr -> foldr, member:List -> List1, member:stringOfInt -> stringOfInt, member:tan -> tan, $block$res -> block$res6, member:listNeq -> listNeq, member:abs -> abs, member:listEq -> listEq, member:foldr1 -> foldr1, member:fst -> fst, member:splitAt_lz -> splitAt_lz, member:nubBy -> nubBy, member:addlemmalst -> addlemmalst, member:sin -> sin, member:tv -> tv, member:stringListConcat -> stringListConcat, member:listLen -> listLen, member:foldl1 -> foldl1, member:list -> list, member:leave -> leave, member:deleteBy -> deleteBy, member:append -> append, $block$res -> block$res7, class:Option -> Option, member:atom -> atom, class:Some -> Some, $block$res -> block$res29, member:applysubstlst -> applysubstlst, member:applysubst -> applysubst, $block$res -> block$res8, member:car -> car, object:None -> None, $block$res -> block$res9, member:cdr -> cdr, class:Lazy -> Lazy, lemmas -> lemmas, $block$res -> block$res37, $tmp -> tmp2, $block$res -> block$res10, member:cadr -> cadr, $block$res -> block$res11, member:caddr -> caddr, $block$res -> block$res30, $block$res -> block$res12, class:List -> List, member:cadddr -> cadddr, member:onewayunify1 -> onewayunify1, class:Cons -> Cons, member:onewayunify1lst -> onewayunify1lst, $block$res -> block$res13, member:tautologyp -> tautologyp, object:Nil -> Nil, $block$res -> block$res31, $block$res -> block$res14, member:onewayunify -> onewayunify, class:LzList -> LzList, $block$res -> block$res32, member:rewritewithlemmas -> rewritewithlemmas, member:rewriteargs -> rewriteargs, class:LzCons -> LzCons, member:rewrite -> rewrite, object:LzNil -> LzNil, member:sublist -> sublist, $block$res -> block$res15, $block$res -> block$res33, statement -> statement, member:mkLispList -> mkLispList, $block$res -> block$res34, $tmp -> tmp, $tmp -> tmp1, member:subterm -> subterm, $block$res -> block$res1, $block$res -> block$res16, member:restOfToken -> restOfToken, $block$res -> block$res35, member:report -> report, $block$res -> block$res36, $block$res -> block$res17, member:getToken -> getToken, member:Predef -> Predef, $block$res -> block$res18, member:strToToken -> strToToken) +//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'rules' +//│ ║ l.432: let lemmas = addlemmalst(makelemmas(rules), Empty) +//│ ║ ^^^^^ +//│ ╟── which references the symbol introduced here +//│ ║ l.321: let rules = +//│ ╙── ^^^^^ +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] ReferenceError: rules is not defined +//│ at REPL118:1:60 +//│ at ContextifyScript.runInThisContext (node:vm:137:12) +//│ at REPLServer.defaultEval (node:repl:593:22) +//│ at bound (node:domain:433:15) +//│ at REPLServer.runBound [as eval] (node:domain:444:12) +//│ at REPLServer.onLine (node:repl:922:10) +//│ at REPLServer.emit (node:events:518:28) +//│ at REPLServer.emit (node:domain:489:12) +//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:613:22) fun tautp(term) = tautologyp([rewrite(term, lemmas), Nill, Nill]) @@ -440,7 +470,22 @@ fun testBoyer2_nofib(n) = report(testresult(n)) :expect "The term is a tautology" testBoyer2_nofib(3) -//│ = "The term is a tautology" +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) +//│ ═══[RUNTIME ERROR] Error: match error +//│ at getLUT (REPL84:1:2367) +//│ at rewrite (REPL105:1:3439) +//│ at rewriteargs (REPL105:1:2106) +//│ at rewrite (REPL105:1:3147) +//│ at rewriteargs (REPL105:1:2106) +//│ at rewrite (REPL105:1:3147) +//│ at tautp (REPL120:1:170) +//│ at testresult (REPL126:1:227) +//│ at testBoyer2_nofib (REPL129:1:205) +//│ at REPL132:1:39 +//│ FAILURE: Unexpected runtime error +//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) +//│ ═══[RUNTIME ERROR] Expected: '"The term is a tautology"', got: 'undefined' diff --git a/hkmc2/shared/src/test/mlscript/ucs/patterns/ConjunctionPattern.mls b/hkmc2/shared/src/test/mlscript/ucs/patterns/ConjunctionPattern.mls index 21c1a39976..003be9bb5b 100644 --- a/hkmc2/shared/src/test/mlscript/ucs/patterns/ConjunctionPattern.mls +++ b/hkmc2/shared/src/test/mlscript/ucs/patterns/ConjunctionPattern.mls @@ -28,7 +28,7 @@ fun foo(v) = A & B then 1 else 0 //│ JS (unsanitized): -//│ let foo; foo = function foo(v) { if (v === A1) { return 0 } else { return 0 } }; +//│ let foo; foo = function foo(v) { if (v instanceof A1.class) { return 0 } else { return 0 } }; fun range(i, j) = if i > j then Nil From d1c43f1f804baa8a98379562a109de07f6ac0630 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 00:02:08 +0800 Subject: [PATCH 18/55] Cleanup hasLiftedClass --- .../scala/hkmc2/codegen/js/JSBuilder.scala | 22 +++++---- .../main/scala/hkmc2/semantics/Symbol.scala | 11 ----- .../shared/src/test/mlscript/nofib/boyer2.mls | 49 +------------------ 3 files changed, 14 insertions(+), 68 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala index dddd7f26fe..705cb5688e 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala @@ -112,11 +112,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: if l.nullary then l.nme else errExpr(msg"Illegal reference to builtin symbol '${l.nme}'") case Value.Ref(l, disamb) => l match - case l: BlockMemberSymbol if { - // println(disamb.flatMap(d => d.asModOrObj orElse d.asCls)) - l.hasLiftedClass && - disamb.flatMap(s => s.asCls orElse s.asMod).exists(_ isnt ctx.builtins.Array) - } => + case l: BlockMemberSymbol if disamb.exists(_.shouldBeLifted) => doc"${getVar(l, l.toLoc)}.class" case _ => getVar(l, r.toLoc) @@ -155,10 +151,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: doc"($params) => ${ braced(bodyDoc) }" case s @ Select(qual, id) => val dotClass = s.symbol_SelectSymbol match - case S(ds) if { - (ds.hasLiftedClass) && - (ds.asModOrObj orElse ds.asCls).exists(_ isnt ctx.builtins.Array) - } => doc".class" + case S(ds) if ds.shouldBeLifted => doc".class" case _ => doc"" val name = id.name doc"${result(qual)}${ @@ -716,7 +709,16 @@ object JSBuilder: then c.toString else f"\\u${c.toInt}%04X" }.mkString - + + extension (dsym: DefinitionSymbol[?]) + def shouldBeLifted: Bool = + val bsym = dsym.asBlkMember + ( + (dsym.asTrm orElse bsym.flatMap(_.asTrm)).isDefined || + (dsym.asCls orElse bsym.flatMap(_.asCls)).flatMap(_.defn).exists(_.paramsOpt.isDefined) + ) && + (dsym.asModOrObj orElse dsym.asCls).isDefined + end JSBuilder diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 615968489a..ef32ae57fc 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -238,14 +238,6 @@ class BlockMemberSymbol(val nme: Str, val trees: Ls[TypeOrTermDef], val nameIsMe def isParameterizedMethod: Bool = trmTree.exists(_.isParameterizedMethod) - /** - * Indicate if this BMS stores a `.class` for its overload in its code generation. - * - * During lowering, - */ - lazy val hasLiftedClass: Bool = - trmTree.isDefined || clsTree.exists(_.paramLists.nonEmpty) - override def toString: Str = s"member:$nme${State.dbgUid(uid)}" @@ -333,9 +325,6 @@ sealed trait DefinitionSymbol[Defn <: Definition] extends Symbol: def asMemSym: MemberSymbol[Defn] = this - def hasLiftedClass: Bool = - this.asBlkMember.exists(_.hasLiftedClass) || - this.asCls.flatMap(_.defn).exists(_.paramsOpt.isDefined) /** This is the symbol associated to specific definitions. * One overloaded `BlockMemberSymbol` may correspond to multiple `InnerSymbol`s diff --git a/hkmc2/shared/src/test/mlscript/nofib/boyer2.mls b/hkmc2/shared/src/test/mlscript/nofib/boyer2.mls index 8cb3463807..e4a9ece8f6 100644 --- a/hkmc2/shared/src/test/mlscript/nofib/boyer2.mls +++ b/hkmc2/shared/src/test/mlscript/nofib/boyer2.mls @@ -425,40 +425,10 @@ let rules = nofibStringToList("(equal (flatten (cdr (gopher x) ) )(if (listp x)(cdr (flatten x) )(Conss (zero)(Nill) ) ) )") :: nofibStringToList("(equal (quotient (times y x)y)(if (zerop y)(zero)(fix x) ) )") :: nofibStringToList("(equal (get j (set i val mem) )(if (eqp j i)val(get j mem) ) )") :: Nil -//│ FAILURE: Unexpected exception -//│ /!!!\ Uncaught error: java.lang.StackOverflowError +//│ rules = [["(","e","q","u","a","l"," ","(","c","o","m","p","i","l","e"," ","f","o","r","m",")","(","r","e","v","e","r","s","e"," ","(","c","o","d","e","g","e","n"," ","(","o","p","t","i","m","i","z","e"," ","f","o","r","m",")"," ","(","N","i","l","l",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","p"," ","x"," ","y",")","(","e","q","u","a","l"," ","(","f","i","x"," ","x",")","(","f","i","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","r","e","a","t","e","r","p"," ","x"," ","y",")","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","e","q","p"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","r","e","a","t","e","r","e","q","p"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","b","o","o","l","e","a","n"," ","x",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","t",")"," ",")","(","e","q","u","a","l"," ","x"," ","(","f",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","i","f","f"," ","x"," ","y",")","(","a","n","d"," ","(","i","m","p","l","i","e","s"," ","x"," ","y",")","(","i","m","p","l","i","e","s"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","v","e","n","1"," ","x",")","(","i","f"," ","(","z","e","r","o","p"," ","x",")","(","t",")","(","o","d","d"," ","(","1","-"," ","x",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","c","o","u","n","t","p","s","-"," ","l"," ","p","r","e","d",")","(","c","o","u","n","t","p","s","-","l","o","o","p"," ","l"," ","p","r","e","d"," ","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","a","c","t","-"," ","i",")","(","f","a","c","t","-","l","o","o","p"," ","i"," ","1",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e","-"," ","x",")","(","r","e","v","e","r","s","e","-","l","o","o","p"," ","x"," ","(","N","i","l","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","v","i","d","e","s"," ","x"," ","y",")","(","z","e","r","o","p"," ","(","r","e","m","a","i","n","d","e","r"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","s","s","u","m","e","-","t","r","u","e"," ","v","a","r"," ","a","l","i","s","t",")","(","C","o","n","s","s"," ","(","C","o","n","s","s"," ","v","a","r"," ","(","t",")"," ",")","a","l","i","s","t",")"," ",")"],["(","e","q","u","a","l"," ","(","a","s","s","u","m","e","-","f","a","l","s","e"," ","v","a","r"," ","a","l","i","s","t",")","(","C","o","n","s","s"," ","(","C","o","n","s","s"," ","v","a","r"," ","(","f",")"," ",")","a","l","i","s","t",")"," ",")"],["(","e","q","u","a","l"," ","(","t","a","u","t","o","l","o","g","y","-","c","h","e","c","k","e","r"," ","x",")","(","t","a","u","t","o","l","o","g","y","p"," ","(","n","o","r","m","a","l","i","z","e"," ","x",")","(","N","i","l","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","a","l","s","i","f","y"," ","x",")","(","f","a","l","s","i","f","y","1"," ","(","n","o","r","m","a","l","i","z","e"," ","x",")","(","N","i","l","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","r","i","m","e"," ","x",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","x",")",")","(","n","o","t"," ","(","e","q","u","a","l"," ","x"," ","(","a","d","d","1"," ","(","z","e","r","o",")"," ",")"," ",")"," ",")","(","p","r","i","m","e","1"," ","x"," ","(","1","-"," ","x",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","n","d"," ","p"," ","q",")","(","i","f"," ","p"," ","(","i","f"," ","q"," ","(","t",")"," ","(","f",")"," ",")"," ","(","f",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","o","r"," ","p"," ","q",")","(","i","f"," ","p"," ","(","t",")"," ","(","i","f"," ","q"," ","(","t",")"," ","(","f",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","n","o","t"," ","p",")","(","i","f"," ","p"," ","(","f",")"," ","(","t",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","i","m","p","l","i","e","s"," ","p"," ","q",")","(","i","f"," ","p"," ","(","i","f"," ","q"," ","(","t",")"," ","(","f",")"," ",")"," ","(","t",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","i","x"," ","x",")","(","i","f"," ","(","n","u","m","b","e","r","p"," ","x",")"," ","x"," ","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","i","f"," ","(","i","f"," ","a"," ","b"," ","c",")"," ","d"," ","e",")","(","i","f"," ","a"," ","(","i","f"," ","b"," ","d"," ","e",")"," ","(","i","f"," ","c"," ","d"," ","e",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","z","e","r","o","p"," ","x",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")","(","n","o","t"," ","(","n","u","m","b","e","r","p"," ","x",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","l","u","s"," ","(","p","l","u","s"," ","x"," ","y",")"," ","z"," ",")","(","p","l","u","s"," ","x"," ","(","p","l","u","s"," ","y"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","p","l","u","s"," ","a"," ","b",")"," ","(","z","e","r","o"," ",")"," ",")","(","a","n","d"," ","(","z","e","r","o","p"," ","a",")"," ","(","z","e","r","o","p"," ","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","x",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","p","l","u","s"," ","a"," ","b",")"," ","(","p","l","u","s"," ","a"," ","c",")"," ",")","(","e","q","u","a","l"," ","(","f","i","x"," ","b",")"," ","(","f","i","x"," ","c",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","z","e","r","o",")"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","y",")"," ",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","x"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","y",")"," ",")","(","a","n","d"," ","(","n","u","m","b","e","r","p"," ","x",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")","(","z","e","r","o","p"," ","y",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ",")"," ","a",")","(","p","l","u","s"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","x",")"," ","a",")","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","y",")"," ","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","(","p","l","u","s","-","f","r","i","n","g","e"," ","x",")"," ",")"," ","a",")","(","f","i","x"," ","(","m","e","a","n","i","n","g"," ","x"," ","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","p","p","e","n","d"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ","z",")","(","a","p","p","e","n","d"," ","x"," ","(","a","p","p","e","n","d"," ","y"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","a","p","p","e","n","d"," ","(","r","e","v","e","r","s","e"," ","b",")"," ","(","r","e","v","e","r","s","e"," ","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","(","p","l","u","s"," ","y"," ","z",")"," ",")","(","p","l","u","s"," ","(","t","i","m","e","s"," ","x"," ","y",")","(","t","i","m","e","s"," ","x"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ","z",")","(","t","i","m","e","s"," ","x"," ","(","t","i","m","e","s"," ","y"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ","(","z","e","r","o",")"," ",")","(","o","r"," ","(","z","e","r","o","p"," ","x",")","(","z","e","r","o","p"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","x","e","c"," ","(","a","p","p","e","n","d"," ","x"," ","y",")","p","d","s"," ","e","n","v","r","n",")","(","e","x","e","c"," ","y"," ","(","e","x","e","c"," ","x"," ","p","d","s"," ","e","n","v","r","n",")","e","n","v","r","n",")"," ",")"],["(","e","q","u","a","l"," ","(","m","c","-","f","l","a","t","t","e","n"," ","x"," ","y",")","(","a","p","p","e","n","d"," ","(","f","l","a","t","t","e","n"," ","x",")","y",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","m","b","e","r"," ","x"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","o","r"," ","(","m","e","m","b","e","r"," ","x"," ","a",")","(","m","e","m","b","e","r"," ","x"," ","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","m","b","e","r"," ","x"," ","(","r","e","v","e","r","s","e"," ","y",")"," ",")","(","m","e","m","b","e","r"," ","x"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","n","g","t","h"," ","(","r","e","v","e","r","s","e"," ","x",")"," ",")","(","l","e","n","g","t","h"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","m","b","e","r"," ","a"," ","(","i","n","t","e","r","s","e","c","t"," ","b"," ","c",")"," ",")","(","a","n","d"," ","(","m","e","m","b","e","r"," ","a"," ","b",")","(","m","e","m","b","e","r"," ","a"," ","c",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","n","t","h"," ","(","z","e","r","o",")","i",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","e","x","p"," ","i"," ","(","p","l","u","s"," ","j"," ","k",")"," ",")","(","t","i","m","e","s"," ","(","e","x","p"," ","i"," ","j",")","(","e","x","p"," ","i"," ","k",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","x","p"," ","i"," ","(","t","i","m","e","s"," ","j"," ","k",")"," ",")","(","e","x","p"," ","(","e","x","p"," ","i"," ","j",")","k",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e","-","l","o","o","p"," ","x"," ","y",")","(","a","p","p","e","n","d"," ","(","r","e","v","e","r","s","e"," ","x",")","y",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e","-","l","o","o","p"," ","x"," ","(","N","i","l","l",")"," ",")","(","r","e","v","e","r","s","e"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","c","o","u","n","t","-","l","i","s","t"," ","z"," ","(","s","o","r","t","-","l","p"," ","x"," ","y",")"," ",")","(","p","l","u","s"," ","(","c","o","u","n","t","-","l","i","s","t"," ","z"," ","x",")","(","c","o","u","n","t","-","l","i","s","t"," ","z"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","a","p","p","e","n","d"," ","a"," ","b",")","(","a","p","p","e","n","d"," ","a"," ","c",")"," ",")","(","e","q","u","a","l"," ","b"," ","c",")"," ",")"],["(","e","q","u","a","l"," ","(","p","l","u","s"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","y",")","(","t","i","m","e","s"," ","y"," ","(","q","u","o","t","i","e","n","t"," ","x"," ","y",")"," ",")"," ",")","(","f","i","x"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","b","i","g","-","p","l","u","s","1"," ","l"," ","i"," ","b","a","s","e",")","b","a","s","e",")","(","p","l","u","s"," ","(","p","o","w","e","r","-","e","v","a","l"," ","l"," ","b","a","s","e",")","i",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","b","i","g","-","p","l","u","s"," ","x"," ","y"," ","i"," ","b","a","s","e",")","b","a","s","e",")","(","p","l","u","s"," ","i"," ","(","p","l","u","s"," ","(","p","o","w","e","r","-","e","v","a","l"," ","x"," ","b","a","s","e",")","(","p","o","w","e","r","-","e","v","a","l"," ","y"," ","b","a","s","e",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","y"," ","1",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","y",")","y",")","(","n","o","t"," ","(","z","e","r","o","p"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","x",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","q","u","o","t","i","e","n","t"," ","i"," ","j",")","i",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","i",")"," ",")","(","o","r"," ","(","z","e","r","o","p"," ","j",")","(","n","o","t"," ","(","e","q","u","a","l"," ","j"," ","1",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","y",")","x",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","y",")"," ",")","(","n","o","t"," ","(","z","e","r","o","p"," ","x",")"," ",")","(","n","o","t"," ","(","l","e","s","s","p"," ","x"," ","y",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","p","o","w","e","r","-","r","e","p"," ","i"," ","b","a","s","e",")","b","a","s","e",")","(","f","i","x"," ","i",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","b","i","g","-","p","l","u","s"," ","(","p","o","w","e","r","-","r","e","p"," ","i"," ","b","a","s","e",")","(","p","o","w","e","r","-","r","e","p"," ","j"," ","b","a","s","e",")","(","z","e","r","o",")","b","a","s","e",")","b","a","s","e",")","(","p","l","u","s"," ","i"," ","j",")"," ",")"],["(","e","q","u","a","l"," ","(","g","c","d"," ","x"," ","y",")","(","g","c","d"," ","y"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","n","t","h"," ","(","a","p","p","e","n","d"," ","a"," ","b",")","i",")","(","a","p","p","e","n","d"," ","(","n","t","h"," ","a"," ","i",")","(","n","t","h"," ","b"," ","(","d","i","f","f","e","r","e","n","c","e"," ","i"," ","(","l","e","n","g","t","h"," ","a",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","x"," ","y",")","x",")","(","f","i","x"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","y"," ","x",")","x",")","(","f","i","x"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","x"," ","y",")","(","p","l","u","s"," ","x"," ","z",")"," ",")","(","d","i","f","f","e","r","e","n","c","e"," ","y"," ","z",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","(","d","i","f","f","e","r","e","n","c","e"," ","c"," ","w",")"," ",")","(","d","i","f","f","e","r","e","n","c","e"," ","(","t","i","m","e","s"," ","c"," ","x",")","(","t","i","m","e","s"," ","w"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","(","t","i","m","e","s"," ","x"," ","z",")","z",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","b"," ","(","p","l","u","s"," ","a"," ","c",")"," ",")","a",")","(","p","l","u","s"," ","b"," ","c",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","a","d","d","1"," ","(","p","l","u","s"," ","y"," ","z",")","z",")","(","a","d","d","1"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","p","l","u","s"," ","x"," ","y",")","(","p","l","u","s"," ","x"," ","z"," ",")"," ",")","(","l","e","s","s","p"," ","y"," ","z",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","t","i","m","e","s"," ","x"," ","z",")","(","t","i","m","e","s"," ","y"," ","z",")"," ",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","z",")"," ",")","(","l","e","s","s","p"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","y"," ","(","p","l","u","s"," ","x"," ","y",")"," ",")","(","n","o","t"," ","(","z","e","r","o","p"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","c","d"," ","(","t","i","m","e","s"," ","x"," ","z",")","(","t","i","m","e","s"," ","y"," ","z",")"," ",")","(","t","i","m","e","s"," ","z"," ","(","g","c","d"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","v","a","l","u","e"," ","(","n","o","r","m","a","l","i","z","e"," ","x",")","a",")","(","v","a","l","u","e"," ","x"," ","a",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","f","l","a","t","t","e","n"," ","x",")","(","C","o","n","s","s"," ","y"," ","(","N","i","l","l",")"," ",")"," ",")","(","a","n","d"," ","(","n","l","i","s","t","p"," ","x",")","(","e","q","u","a","l"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","i","s","t","p"," ","(","g","o","p","h","e","r"," ","x",")"," ",")","(","l","i","s","t","p"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","s","a","m","e","f","r","i","n","g","e"," ","x"," ","y",")","(","e","q","u","a","l"," ","(","f","l","a","t","t","e","n"," ","x",")","(","f","l","a","t","t","e","n"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"," ","x"," ","y",")","(","z","e","r","o",")"," ",")","(","a","n","d"," ","(","o","r"," ","(","z","e","r","o","p"," ","y",")","(","e","q","u","a","l"," ","y"," ","1",")"," ",")","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"," ","x"," ","y",")","1",")","(","e","q","u","a","l"," ","x"," ","1",")"," ",")"],["(","e","q","u","a","l"," ","(","n","u","m","b","e","r","p"," ","(","g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"," ","x"," ","y",")"," ",")","(","n","o","t"," ","(","a","n","d"," ","(","o","r"," ","(","z","e","r","o","p"," ","y",")","(","e","q","u","a","l"," ","y"," ","1",")"," ",")","(","n","o","t"," ","(","n","u","m","b","e","r","p"," ","x",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s","-","l","i","s","t"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ",")","(","t","i","m","e","s"," ","(","t","i","m","e","s","-","l","i","s","t"," ","x",")","(","t","i","m","e","s","-","l","i","s","t"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","r","i","m","e","-","l","i","s","t"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ",")","(","a","n","d"," ","(","p","r","i","m","e","-","l","i","s","t"," ","x",")","(","p","r","i","m","e","-","l","i","s","t"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","z"," ","(","t","i","m","e","s"," ","w"," ","z",")"," ",")","(","a","n","d"," ","(","n","u","m","b","e","r","p"," ","z",")","(","o","r"," ","(","e","q","u","a","l"," ","z"," ","(","z","e","r","o",")"," ",")","(","e","q","u","a","l"," ","w"," ","1",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","r","e","a","t","e","r","e","q","p","r"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","x"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")","(","a","n","d"," ","(","n","u","m","b","e","r","p"," ","x",")","(","e","q","u","a","l"," ","y"," ","1",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","(","t","i","m","e","s"," ","y"," ","x",")","y",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","a"," ","b",")","1",")","(","a","n","d"," ","(","n","o","t"," ","(","e","q","u","a","l"," ","a"," ","(","z","e","r","o",")"," ",")"," ",")","(","n","o","t"," ","(","e","q","u","a","l"," ","b"," ","(","z","e","r","o",")"," ",")"," ",")","(","n","u","m","b","e","r","p"," ","a",")","(","n","u","m","b","e","r","p"," ","b",")","(","e","q","u","a","l"," ","(","1","-"," ","a",")","(","z","e","r","o",")"," ",")","(","e","q","u","a","l"," ","(","1","-"," ","b",")","(","z","e","r","o",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","l","e","n","g","t","h"," ","(","d","e","l","e","t","e"," ","x"," ","l",")"," ",")","(","l","e","n","g","t","h"," ","l",")"," ",")","(","m","e","m","b","e","r"," ","x"," ","l",")"," ",")"],["(","e","q","u","a","l"," ","(","s","o","r","t","2"," ","(","d","e","l","e","t","e"," ","x"," ","l",")"," ",")","(","d","e","l","e","t","e"," ","x"," ","(","s","o","r","t","2"," ","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","s","o","r","t"," ","x",")","(","s","o","r","t","2"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","n","g","t","h","(","C","o","n","s","s"," ","x","1","(","C","o","n","s","s"," ","x","2","(","C","o","n","s","s"," ","x","3","(","C","o","n","s","s"," ","x","4","(","C","o","n","s","s"," ","x","5","(","C","o","n","s","s"," ","x","6"," ","x","7",")"," ",")"," ",")"," ",")"," ",")"," ",")"," ",")","(","p","l","u","s"," ","6"," ","(","l","e","n","g","t","h"," ","x","7",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","a","d","d","1"," ","(","a","d","d","1"," ","x",")"," ",")","2",")","(","f","i","x"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","q","u","o","t","i","e","n","t"," ","(","p","l","u","s"," ","x"," ","(","p","l","u","s"," ","x"," ","y",")"," ",")","2",")","(","p","l","u","s"," ","x"," ","(","q","u","o","t","i","e","n","t"," ","y"," ","2",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","s","i","g","m","a"," ","(","z","e","r","o",")","i",")","(","q","u","o","t","i","e","n","t"," ","(","t","i","m","e","s"," ","i"," ","(","a","d","d","1"," ","i",")"," ",")","2",")"," ",")"],["(","e","q","u","a","l"," ","(","p","l","u","s"," ","x"," ","(","a","d","d","1"," ","y",")"," ",")","(","i","f"," ","(","n","u","m","b","e","r","p"," ","y",")","(","a","d","d","1"," ","(","p","l","u","s"," ","x"," ","y",")"," ",")","(","a","d","d","1"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","y",")","(","d","i","f","f","e","r","e","n","c","e"," ","z"," ","y",")"," ",")","(","i","f"," ","(","l","e","s","s","p"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","z",")"," ",")","(","i","f"," ","(","l","e","s","s","p"," ","z"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")","(","e","q","u","a","l"," ","(","f","i","x"," ","x",")","(","f","i","x"," ","z",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","(","d","e","l","e","t","e"," ","x"," ","y",")"," ",")","a",")","(","i","f"," ","(","m","e","m","b","e","r"," ","x"," ","y",")","(","d","i","f","f","e","r","e","n","c","e"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","y",")","a",")","(","m","e","a","n","i","n","g"," ","x"," ","a",")"," ",")","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","y",")","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","(","a","d","d","1"," ","y",")"," ",")","(","i","f"," ","(","n","u","m","b","e","r","p"," ","y",")","(","p","l","u","s"," ","x"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ",")","(","f","i","x"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","n","t","h"," ","(","N","i","l","l",")","i",")","(","i","f"," ","(","z","e","r","o","p"," ","i",")","(","N","i","l","l",")","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","a","s","t"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","i","f"," ","(","l","i","s","t","p"," ","b",")","(","l","a","s","t"," ","b",")","(","i","f"," ","(","l","i","s","t","p"," ","a",")","(","C","o","n","s","s"," ","(","c","a","r"," ","(","l","a","s","t"," ","a",")"," ",")","b",")","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","x"," ","y",")","z",")","(","i","f"," ","(","l","e","s","s","p"," ","x"," ","y",")","(","e","q","u","a","l"," ","t"," ","z",")","(","e","q","u","a","l"," ","f"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","s","s","i","g","n","m","e","n","t"," ","x"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","i","f"," ","(","a","s","s","i","g","n","e","d","p"," ","x"," ","a",")","(","a","s","s","i","g","n","m","e","n","t"," ","x"," ","a",")","(","a","s","s","i","g","n","m","e","n","t"," ","x"," ","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","c","a","r"," ","(","g","o","p","h","e","r"," ","x",")"," ",")","(","i","f"," ","(","l","i","s","t","p"," ","x",")","(","c","a","r"," ","(","f","l","a","t","t","e","n"," ","x",")"," ",")","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","l","a","t","t","e","n"," ","(","c","d","r"," ","(","g","o","p","h","e","r"," ","x",")"," ",")"," ",")","(","i","f"," ","(","l","i","s","t","p"," ","x",")","(","c","d","r"," ","(","f","l","a","t","t","e","n"," ","x",")"," ",")","(","C","o","n","s","s"," ","(","z","e","r","o",")","(","N","i","l","l",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","q","u","o","t","i","e","n","t"," ","(","t","i","m","e","s"," ","y"," ","x",")","y",")","(","i","f"," ","(","z","e","r","o","p"," ","y",")","(","z","e","r","o",")","(","f","i","x"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","e","t"," ","j"," ","(","s","e","t"," ","i"," ","v","a","l"," ","m","e","m",")"," ",")","(","i","f"," ","(","e","q","p"," ","j"," ","i",")","v","a","l","(","g","e","t"," ","j"," ","m","e","m",")"," ",")"," ",")"]] :silent let lemmas = addlemmalst(makelemmas(rules), Empty) -//│ FAILURE: Unexpected compilation error -//│ FAILURE LOCATION: lookup_! (Scope.scala:112) -//│ FAILURE INFO: Tuple2: -//│ _1 = Tuple2: -//│ _1 = rules -//│ _2 = class hkmc2.semantics.VarSymbol -//│ _2 = Scope: -//│ parent = N -//│ curThis = S of S of globalThis:globalThis -//│ bindings = HashMap($block$res -> block$res19, $runtime -> runtime, $definitionMetadata -> definitionMetadata, member:assoc -> assoc, $prettyPrint -> prettyPrint, $Term -> Term, $block$res -> block$res20, $block$res -> block$res21, member:LUT -> LUT1, class:LUT -> LUT, $block$res -> block$res22, member:Empty -> Empty1, object:Empty -> Empty, $block$res -> block$res23, member:Node -> Node1, class:Node -> Node, $block$res -> block$res24, member:addtoLUT -> addtoLUT, member:Lisplist -> Lisplist1, class:Lisplist -> Lisplist, $block$res -> block$res2, $block$res -> block$res, member:Conss -> Conss1, member:Atom -> Atom1, $block$res -> block$res25, member:Nill -> Nill1, object:Nill -> Nill, class:Atom -> Atom, class:Conss -> Conss, member:enumFrom -> enumFrom, member:LzList -> LzList1, member:leave_lz -> leave_lz, member:sum -> sum, member:nub_lz -> nub_lz, member:LzNil -> LzNil1, member:getLUT -> getLUT, member:intDiv -> intDiv, member:Nil -> Nil1, member:ltList -> ltList, $block$res -> block$res3, member:divMod -> divMod, member:lispListEq -> lispListEq, member:scanl -> scanl, member:zip_lz_lz -> zip_lz_lz, member:nofibListToString -> nofibListToString, member:orList -> orList, member:lazy -> lazy, member:atIndex -> atIndex, member:_internal_cons_to_str -> _internal_cons_to_str, member:force -> force, member:stringOfFloat -> stringOfFloat, member:unionBy -> unionBy, member:splitAt -> splitAt, member:nubBy_lz -> nubBy_lz, member:union -> union, member:zip -> zip, member:compose -> compose, member:fromSome -> fromSome, member:take_lz_lz -> take_lz_lz, member:stringConcat -> stringConcat, member:map -> map, member:all -> all, member:head -> head, member:zipWith_lz_lz -> zipWith_lz_lz, member:unzip -> unzip, $block$res -> block$res4, member:null_ -> null_, member:concat -> concat, member:break_ -> break_, member:lispmember -> lispmember, member:zip_lz_nl -> zip_lz_nl, member:truep -> truep, member:min -> min, $block$res -> block$res26, member:eqTup2 -> eqTup2, member:filter_lz -> filter_lz, member:intQuot -> intQuot, member:zipWith -> zipWith, member:scanr -> scanr, member:makelemmas -> makelemmas, member:replicate -> replicate, member:append_nl_lz -> append_nl_lz, member:tail -> tail, member:cos -> cos, member:int_of_char -> int_of_char, member:LzCons -> LzCons1, member:map_lz -> map_lz, member:until -> until, member:ltTup2 -> ltTup2, member:Cons -> Cons1, member:Lazy -> Lazy1, member:zipWith_lz_nl -> zipWith_lz_nl, member:snd -> snd, member:reverse -> reverse, $block$res -> block$res27, member:filter -> filter, member:append_lz_lz -> append_lz_lz, member:quotRem -> quotRem, member:maximum -> maximum, member:addlemma -> addlemma, member:take_lz -> take_lz, member:replicate_lz -> replicate_lz, member:zip3 -> zip3, member:leaveWhile -> leaveWhile, member:enumFromTo -> enumFromTo, member:max -> max, member:foldl -> foldl, member:enumFromThenTo -> enumFromThenTo, $block$res -> block$res5, member:sqrt -> sqrt, member:flatMap -> flatMap, member:intRem -> intRem, member:take -> take, member:listEqBy -> listEqBy, member:flip -> flip, member:Some -> Some1, member:falsep -> falsep, member:inList -> inList, member:nofibStringToList -> nofibStringToList, member:Option -> Option1, member:intMod -> intMod, member:None -> None1, member:head_lz -> head_lz, member:notElem -> notElem, member:round -> round, member:iterate -> iterate, $block$res -> block$res28, member:transpose -> transpose, member:while_ -> while_, member:repeat -> repeat, member:power -> power, member:foldr -> foldr, member:List -> List1, member:stringOfInt -> stringOfInt, member:tan -> tan, $block$res -> block$res6, member:listNeq -> listNeq, member:abs -> abs, member:listEq -> listEq, member:foldr1 -> foldr1, member:fst -> fst, member:splitAt_lz -> splitAt_lz, member:nubBy -> nubBy, member:addlemmalst -> addlemmalst, member:sin -> sin, member:tv -> tv, member:stringListConcat -> stringListConcat, member:listLen -> listLen, member:foldl1 -> foldl1, member:list -> list, member:leave -> leave, member:deleteBy -> deleteBy, member:append -> append, $block$res -> block$res7, class:Option -> Option, member:atom -> atom, class:Some -> Some, $block$res -> block$res29, member:applysubstlst -> applysubstlst, member:applysubst -> applysubst, $block$res -> block$res8, member:car -> car, object:None -> None, $block$res -> block$res9, member:cdr -> cdr, class:Lazy -> Lazy, lemmas -> lemmas, $block$res -> block$res37, $tmp -> tmp2, $block$res -> block$res10, member:cadr -> cadr, $block$res -> block$res11, member:caddr -> caddr, $block$res -> block$res30, $block$res -> block$res12, class:List -> List, member:cadddr -> cadddr, member:onewayunify1 -> onewayunify1, class:Cons -> Cons, member:onewayunify1lst -> onewayunify1lst, $block$res -> block$res13, member:tautologyp -> tautologyp, object:Nil -> Nil, $block$res -> block$res31, $block$res -> block$res14, member:onewayunify -> onewayunify, class:LzList -> LzList, $block$res -> block$res32, member:rewritewithlemmas -> rewritewithlemmas, member:rewriteargs -> rewriteargs, class:LzCons -> LzCons, member:rewrite -> rewrite, object:LzNil -> LzNil, member:sublist -> sublist, $block$res -> block$res15, $block$res -> block$res33, statement -> statement, member:mkLispList -> mkLispList, $block$res -> block$res34, $tmp -> tmp, $tmp -> tmp1, member:subterm -> subterm, $block$res -> block$res1, $block$res -> block$res16, member:restOfToken -> restOfToken, $block$res -> block$res35, member:report -> report, $block$res -> block$res36, $block$res -> block$res17, member:getToken -> getToken, member:Predef -> Predef, $block$res -> block$res18, member:strToToken -> strToToken) -//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'rules' -//│ ║ l.432: let lemmas = addlemmalst(makelemmas(rules), Empty) -//│ ║ ^^^^^ -//│ ╟── which references the symbol introduced here -//│ ║ l.321: let rules = -//│ ╙── ^^^^^ -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] ReferenceError: rules is not defined -//│ at REPL118:1:60 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) -//│ at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:613:22) fun tautp(term) = tautologyp([rewrite(term, lemmas), Nill, Nill]) @@ -470,22 +440,7 @@ fun testBoyer2_nofib(n) = report(testresult(n)) :expect "The term is a tautology" testBoyer2_nofib(3) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] Error: match error -//│ at getLUT (REPL84:1:2367) -//│ at rewrite (REPL105:1:3439) -//│ at rewriteargs (REPL105:1:2106) -//│ at rewrite (REPL105:1:3147) -//│ at rewriteargs (REPL105:1:2106) -//│ at rewrite (REPL105:1:3147) -//│ at tautp (REPL120:1:170) -//│ at testresult (REPL126:1:227) -//│ at testBoyer2_nofib (REPL129:1:205) -//│ at REPL132:1:39 -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) -//│ ═══[RUNTIME ERROR] Expected: '"The term is a tautology"', got: 'undefined' +//│ = "The term is a tautology" From ef12ca6ae44fa14ca0f3c6c209defb8708751c6a Mon Sep 17 00:00:00 2001 From: CAG2Mark Date: Sat, 1 Nov 2025 00:03:14 +0800 Subject: [PATCH 19/55] Fix lifter bugs --- .../src/main/scala/hkmc2/codegen/Lifter.scala | 31 +++++++----- .../src/test/mlscript/backlog/Lifter.mls | 10 ++-- .../src/test/mlscript/lifter/DefnsInClass.mls | 19 +------- .../test/mlscript/lifter/ModulesObjects.mls | 48 ++----------------- .../src/test/mlscript/objbuf/Basics.mls | 14 +++--- 5 files changed, 37 insertions(+), 85 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index e92a9789e9..807b6eb8a5 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -101,10 +101,10 @@ object Lifter: case s: LocalVarSymbol => s object RefOfBms: - def unapply(p: Path) = p match + def unapply(p: Path): Opt[(BlockMemberSymbol, Opt[DefinitionSymbol[?]])] = p match case Value.Ref(l: BlockMemberSymbol, disamb) => S((l, disamb)) case s @ Select(_, _) => s.symbol_SelectSymbol match - case Some(value: BlockMemberSymbol) => S(value, N) + case Some(value) => value.asBlkMember.map((_, S(value))) case _ => N case _ => N @@ -175,7 +175,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): val isymPaths: Map[InnerSymbol, LocalPath] = Map.empty, val replacedDefns: Map[BlockMemberSymbol, Defn] = Map.empty, val firstClsFns: Set[BlockMemberSymbol] = Set.empty, - val companionMap: Map[InnerSymbol, InnerSymbol] = Map.empty + val companionMap: Map[InnerSymbol, InnerSymbol] = Map.empty, ): // gets the function to which a local belongs def lookup(l: Local) = usedLocals.lookup(l) @@ -558,11 +558,9 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): val clsCaptures: List[InnerSymbol] = ctx.prevClsDefns.map(_.isym) val refBms = inScopeRefs.intersect(ctx.ignoredDefns).toList.sortBy(_.uid) - val modLocal = d match - case c: ClsLikeDefn if modOrObj(c) && !ctx.ignored(c.sym) => parentCls match - case None => S(VarSymbol(Tree.Ident(c.sym.nme + "$"))) - case Some(value) => S(TermSymbol(syntax.ImmutVal, S(value.isym), Tree.Ident(c.sym.nme + "$"))) - case _ => N + val isModLocal = d match + case c: ClsLikeDefn if modOrObj(c) && !ctx.ignored(c.sym) => true + case _ => false if ctx.ignored(d.sym) || (includedCaptures.isEmpty && includedLocals.isEmpty && clsCaptures.isEmpty && refBms.isEmpty) then @@ -574,7 +572,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): case _ => Map.empty else val fakeCtorBms = d match - case c: ClsLikeDefn if !modLocal.isDefined => S(BlockMemberSymbol(d.sym.nme + "$ctor", Nil)) + case c: ClsLikeDefn if !isModLocal => S(BlockMemberSymbol(d.sym.nme + "$ctor", Nil)) case _ => N val singleCallBms = BlockMemberSymbol(d.sym.nme + "$", Nil) @@ -769,15 +767,16 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): case _ => super.applyBlock(rewritten) // rewrite object definitions, assigning to the given symbol in modObjLocals - case Define(d: Defn, rest: Block) => ctx.modObjLocals.get(d.sym) match + case Define(d: ClsLikeDefn, rest: Block) => ctx.modObjLocals.get(d.sym) match case Some(sym) if !ctx.ignored(d.sym) => ctx.getBmsReqdInfo(d.sym) match case Some(_) => // has args blockBuilder .assign(sym, Instantiate(mut = false, d.sym.asPath, getCallArgs(d.sym, ctx))) .rest(applyBlock(rest)) case None => // has no args + // Objects with no parameters are instantiated statically blockBuilder - .assign(sym, Instantiate(mut = false, d.sym.asPath, Nil)) + .assign(sym, d.sym.asPath) .rest(applyBlock(rest)) case _ => ctx.replacedDefns.get(d.sym) match case Some(value) => Define(value, applyBlock(rest)) @@ -1119,10 +1118,12 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): // ctorIncluded: ditto, but lifted val (ctorIgnored, ctorIncluded) = allCtorDefns.partition(d => ctxx.ignored(d.sym)) + // Symbols containing refernces to nested classes and nested objects are here + // Deals with references to lifted objects defined within the class val nestedClsPaths: Map[Local, LocalPath] = ctorIncluded.map: case c: ClsLikeDefn if modOrObj(c) => ctxx.modObjLocals.get(c.sym) match - case Some(sym) => S(c.sym -> LocalPath.Sym(sym)) + case Some(sym) => S(c.isym -> LocalPath.Sym(sym)) case _ => S(c.sym -> LocalPath.Sym(c.sym)) case _ => None .collect: @@ -1299,7 +1300,11 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): case Some(bms) => val nestedIn = analyzer.defnsMap(bms) nestedIn match - case cls: ClsLikeDefn => S(c.sym -> TermSymbol(syntax.ImmutVal, S(cls.isym), Tree.Ident(c.sym.nme + "$"))) + // These will be the names of the objects/modules after being lifted + // We should use the nested object/module's **original name** if nested inside a class, + // so they can be accesed directly by name from te outside. + // For example, if a class C has an object M, (new C).M as a dynamic selection works + case cls: ClsLikeDefn => S(c.sym -> TermSymbol(syntax.ImmutVal, S(cls.isym), Tree.Ident(c.sym.nme))) case _ => S(c.sym -> VarSymbol(Tree.Ident(c.sym.nme + "$"))) case _ => N .collect: diff --git a/hkmc2/shared/src/test/mlscript/backlog/Lifter.mls b/hkmc2/shared/src/test/mlscript/backlog/Lifter.mls index d3afd69e69..495a749c0e 100644 --- a/hkmc2/shared/src/test/mlscript/backlog/Lifter.mls +++ b/hkmc2/shared/src/test/mlscript/backlog/Lifter.mls @@ -40,9 +40,13 @@ f(2) data class A(x) with data class B(y) with fun getB() = x + y - fun getA() = this.B(2).getB() + fun getA() = + // NOTE: The Term.Resolved PR made it so `this.B` gets resolved correctly. + // Explicitly binding `t = this` reproduces the previous error + let t = this + t.B(2).getB() A(1).getA() -//│ ═══[RUNTIME ERROR] TypeError: this.B is not a function +//│ ═══[RUNTIME ERROR] TypeError: t.B is not a function //│ ═══[RUNTIME ERROR] Expected: '3', got: 'undefined' // This is due to the order of classes after lifting @@ -195,7 +199,7 @@ fun foo(x) = (new Bar).self2 foo(2) //│ ╔══[ERROR] Expected a statically known class; found reference of type Foo. -//│ ║ l.194: class Bar extends Foo +//│ ║ l.198: class Bar extends Foo //│ ║ ^^^ //│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation. //│ ═══[COMPILATION ERROR] No definition found in scope for member 'Foo$' diff --git a/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls b/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls index 4b4d372276..b679dffcae 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls @@ -55,7 +55,7 @@ data class A(x) with //│ } //│ getA() { //│ let tmp; -//│ tmp = this.B(2); +//│ tmp = B$(false, this, 2); //│ return runtime.safeCall(tmp.getB()) //│ } //│ toString() { return runtime.render(this); } @@ -64,22 +64,7 @@ data class A(x) with :expect 3 A(1).getA() -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: this.B is not a function -//│ at A.getA (REPL10:1:1488) -//│ at REPL13:1:81 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) -//│ ═══[RUNTIME ERROR] Expected: '3', got: 'undefined' +//│ = 3 :sjs class A with diff --git a/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls b/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls index 02e8219fe7..b27cccd164 100644 --- a/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls +++ b/hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls @@ -164,22 +164,7 @@ data class A(x) with :expect 2 A(2).getA() -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'getB') -//│ at A.getA (REPL50:1:966) -//│ at REPL53:1:82 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) -//│ ═══[RUNTIME ERROR] Expected: '2', got: 'undefined' +//│ = 2 // Classes and functions in modules // @@ -208,22 +193,7 @@ object M with fun get = x val hi = A() M.hi.get -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: this.A is not a function -//│ at new M12 (REPL62:1:1139) -//│ at (REPL62:1:1043) -//│ at REPL62:1:1292 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: processTerm (JSBackendDiffMaker.scala:203) -//│ ═══[RUNTIME ERROR] Expected: '2', got: 'undefined' +//│ = 2 :expect 2 object M with @@ -303,19 +273,7 @@ module M with fun newB = B() 0 is A M.A(2).newB.newA_B(3).newB.get -//│ FAILURE: Unexpected runtime error -//│ FAILURE LOCATION: mkQuery (JSBackendDiffMaker.scala:154) -//│ ═══[RUNTIME ERROR] TypeError: this.B is not a function -//│ at get newB (REPL74:1:1731) -//│ at REPL74:1:2115 -//│ at ContextifyScript.runInThisContext (node:vm:137:12) -//│ at REPLServer.defaultEval (node:repl:593:22) -//│ at bound (node:domain:433:15) -//│ at REPLServer.runBound [as eval] (node:domain:444:12) -//│ at REPLServer.onLine (node:repl:922:10) -//│ at REPLServer.emit (node:events:518:28) -//│ at REPLServer.emit (node:domain:489:12) -//│ at [_onLine] [as _onLine] (node:internal/readline/interface:419:12) +//│ = 3 module M with class A diff --git a/hkmc2/shared/src/test/mlscript/objbuf/Basics.mls b/hkmc2/shared/src/test/mlscript/objbuf/Basics.mls index 5d6ef745ce..427b71fa48 100644 --- a/hkmc2/shared/src/test/mlscript/objbuf/Basics.mls +++ b/hkmc2/shared/src/test/mlscript/objbuf/Basics.mls @@ -69,7 +69,7 @@ A.f(buf, obj2)(1) //│ FAILURE: Unexpected type error //│ FAILURE LOCATION: newDefn (Resolver.scala:652) //│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.63: A.f(buf, obj2)(1) +//│ ║ l.68: A.f(buf, obj2)(1) //│ ╙── ^^^^^^^^^^^ //│ = 6 @@ -83,7 +83,7 @@ A.f(buf, obj1)(1) //│ FAILURE: Unexpected type error //│ FAILURE LOCATION: newDefn (Resolver.scala:652) //│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.72: A.f(buf, obj1)(1) +//│ ║ l.82: A.f(buf, obj1)(1) //│ ╙── ^^^^^^^^^^^ //│ = 11 @@ -91,7 +91,7 @@ A.f(buf, obj3)(1) //│ FAILURE: Unexpected type error //│ FAILURE LOCATION: newDefn (Resolver.scala:652) //│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.75: A.f(buf, obj3)(1) +//│ ║ l.90: A.f(buf, obj3)(1) //│ ╙── ^^^^^^^^^^^ //│ = 11 @@ -114,8 +114,8 @@ A.f(buf, obj2)(1) //│ FAILURE: Unexpected type error //│ FAILURE LOCATION: newDefn (Resolver.scala:652) //│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.93: A.f(buf, obj2)(1) -//│ ╙── ^^^^^^^^^^^ +//│ ║ l.113: A.f(buf, obj2)(1) +//│ ╙── ^^^^^^^^^^^ //│ = 4 buf.del(Oops, obj1) @@ -125,8 +125,8 @@ A.f(buf, obj2)(1) //│ FAILURE: Unexpected type error //│ FAILURE LOCATION: newDefn (Resolver.scala:652) //│ ╔══[ERROR] Expected 1 arguments, got 2 -//│ ║ l.99: A.f(buf, obj2)(1) -//│ ╙── ^^^^^^^^^^^ +//│ ║ l.124: A.f(buf, obj2)(1) +//│ ╙── ^^^^^^^^^^^ //│ = 4 From 5de57fec01e5dbe9cc7e0b1f4d370fd7ce49f61f Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 00:04:29 +0800 Subject: [PATCH 20/55] Cleanup symbol_SelectSymbol --- .../src/main/scala/hkmc2/codegen/Block.scala | 4 ++-- .../scala/hkmc2/codegen/BlockTransformer.scala | 4 ++-- .../main/scala/hkmc2/codegen/BlockTraverser.scala | 2 +- .../scala/hkmc2/codegen/BufferableTransform.scala | 2 +- .../src/main/scala/hkmc2/codegen/Lifter.scala | 6 +++--- .../scala/hkmc2/codegen/StackSafeTransform.scala | 2 +- .../main/scala/hkmc2/codegen/js/JSBuilder.scala | 2 +- .../main/scala/hkmc2/codegen/llir/Builder.scala | 14 +++++++------- .../scala/hkmc2/codegen/wasm/text/WatBuilder.scala | 4 ++-- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala index eec57a7e93..9abaf90f54 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala @@ -567,9 +567,9 @@ sealed abstract class Path extends TrivialResult: /** * @param symbol The symbol, representing the definition that this selection refers to, if known. */ -case class Select(qual: Path, name: Tree.Ident)(val symbol_SelectSymbol: Opt[DefinitionSymbol[?]]) extends Path with ProductWithExtraInfo: +case class Select(qual: Path, name: Tree.Ident)(val symbol: Opt[DefinitionSymbol[?]]) extends Path with ProductWithExtraInfo: def extraInfo: Str = - (symbol_SelectSymbol.map(s => s"sym=${s}") :: Nil) + (symbol.map(s => s"sym=${s}") :: Nil) .collect: case S(info) => info .mkString(",") diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala index 3f53cacced..a5d94dfaa6 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala @@ -139,8 +139,8 @@ class BlockTransformer(subst: SymbolSubst): k(if (qual2 is qual) && (fld2 is fld) then p else DynSelect(qual2, fld2, arrayIdx)) case p @ Select(qual, name) => applyPath(qual): qual2 => - val sym2 = p.symbol_SelectSymbol.mapConserve(_.subst) - k(if (qual2 is qual) && (sym2 is p.symbol_SelectSymbol) then p else Select(qual2, name)(sym2)) + val sym2 = p.symbol.mapConserve(_.subst) + k(if (qual2 is qual) && (sym2 is p.symbol) then p else Select(qual2, name)(sym2)) case v: Value => applyValue(v)(k) def applyValue(v: Value)(k: Value => Block) = v match diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala index ee5e3e40e5..8f68ac00ba 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala @@ -65,7 +65,7 @@ class BlockTraverser: case DynSelect(qual, fld, arrayIdx) => applyPath(qual); applyPath(fld) case p @ Select(qual, name) => - applyPath(qual); p.symbol_SelectSymbol.foreach(_.traverse) + applyPath(qual); p.symbol.foreach(_.traverse) case v: Value => applyValue(v) def applyValue(v: Value): Unit = v match diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/BufferableTransform.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/BufferableTransform.scala index abf7cceac1..95a229f6d7 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/BufferableTransform.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/BufferableTransform.scala @@ -53,7 +53,7 @@ class BufferableTransform()(using Ctx, State, Raise): case _ => super.applyBlock(b) override def applyPath(p: Path)(k: Path => Block): Block = p match case sel: Select => - sel.symbol_SelectSymbol.fold(super.applyPath(p)(k)): sym => + sel.symbol.fold(super.applyPath(p)(k)): sym => fieldMap.get(sym).orElse(pubFieldMap.get(sym).flatMap(fieldMap.get(_))).fold(super.applyPath(p)(k)): off => getOffset(off): res => k(res) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index e92a9789e9..402a511c55 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -103,7 +103,7 @@ object Lifter: object RefOfBms: def unapply(p: Path) = p match case Value.Ref(l: BlockMemberSymbol, disamb) => S((l, disamb)) - case s @ Select(_, _) => s.symbol_SelectSymbol match + case s @ Select(_, _) => s.symbol match case Some(value: BlockMemberSymbol) => S(value, N) case _ => N case _ => N @@ -809,7 +809,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): // Rewrites this.className.class to reference the top-level definition case s @ Select(RefOfBms(l, disamb), Tree.Ident("class")) if !ctx.ignored(l) && ctx.isRelevant(l) => // this class will be lifted, rewrite the ref to strip it of `Select` - k(Select(Value.Ref(l, disamb), Tree.Ident("class"))(s.symbol_SelectSymbol)) + k(Select(Value.Ref(l, disamb), Tree.Ident("class"))(s.symbol)) // TODO: ^ // TODO: Ref Refactorization @@ -817,7 +817,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): // replaced by a symbol, to which the object instance is assigned. This rewrites references // from the objects BlockMemberSymbol to that new symbol. case s @ Select(qual, ident) => - s.symbol_SelectSymbol.flatMap(ctx.getLocalPath) match + s.symbol.flatMap(ctx.getLocalPath) match case Some(LocalPath.Sym(value: DefinitionSymbol[?])) => k(Select(qual, Tree.Ident(value.nme))(S(value))) case _ => super.applyPath(p)(k) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala index 820e27e403..df9f4130eb 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala @@ -13,7 +13,7 @@ class StackSafeTransform(depthLimit: Int, paths: HandlerPaths, doUnwindMap: Map[ private val STACK_DEPTH_IDENT: Tree.Ident = Tree.Ident("stackDepth") val doUnwindFns = doUnwindMap.values.collect: - case s: Select if s.symbol_SelectSymbol.isDefined => s.symbol_SelectSymbol.get + case s: Select if s.symbol.isDefined => s.symbol.get case Value.Ref(sym, _) => sym .toSet diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala index 705cb5688e..47fbd2f841 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala @@ -150,7 +150,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder: val (params, bodyDoc) = setupFunction(none, ps, bod) doc"($params) => ${ braced(bodyDoc) }" case s @ Select(qual, id) => - val dotClass = s.symbol_SelectSymbol match + val dotClass = s.symbol match case S(ds) if ds.shouldBeLifted => doc".class" case _ => doc"" val name = id.name diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala index df85c8d25c..6bc4ca8661 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala @@ -325,7 +325,7 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case s @ Select(Value.Ref(sym, _), Tree.Ident("Unit")) if sym is ctx.builtinSym.runtimeSym.get => bPath(Value.Lit(Tree.UnitLit(false)))(k) case s @ Select(Value.Ref(cls: ClassSymbol, _), name) if ctx.method_class.contains(cls) => - s.symbol_SelectSymbol match + s.symbol match case None => ctx.flow_ctx.get(p) match case Some(cls) => @@ -337,8 +337,8 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case s @ DynSelect(qual, fld, arrayIdx) => bErrStop(msg"Unsupported dynamic selection") case s @ Select(qual, name) => - log(s"bPath Select: $qual.$name with ${s.symbol_SelectSymbol}") - s.symbol_SelectSymbol match + log(s"bPath Select: $qual.$name with ${s.symbol}") + s.symbol match case None => ctx.flow_ctx.get(qual) match case Some(cls) => @@ -356,7 +356,7 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): bPath(qual): case q: Expr.Ref => val v: Local = newTemp - val cls = getClassOfField(s.symbol_SelectSymbol.get) + val cls = getClassOfField(s.symbol.get) val field = name.name Node.LetExpr(v, Expr.Select(q.sym, cls, field), k(v |> sr)) case q: Expr.Literal => @@ -408,14 +408,14 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case args: Ls[TrivialExpr] => val v: Local = newTemp Node.LetCall(Ls(v), builtin, Expr.Literal(Tree.StrLit(mathPrimitive)) :: args, k(v |> sr)) - case Call(s @ Select(r @ Value.Ref(sym, _), Tree.Ident(fld)), args) if s.symbol_SelectSymbol.isDefined => + case Call(s @ Select(r @ Value.Ref(sym, _), Tree.Ident(fld)), args) if s.symbol.isDefined => bPath(r): case r => bArgs(args): case args: Ls[TrivialExpr] => val v: Local = newTemp - log(s"Method Call Select: $r.$fld with ${s.symbol_SelectSymbol}") - Node.LetMethodCall(Ls(v), getClassOfField(s.symbol_SelectSymbol.get), s.symbol_SelectSymbol.get, r :: args, k(v |> sr)) + log(s"Method Call Select: $r.$fld with ${s.symbol}") + Node.LetMethodCall(Ls(v), getClassOfField(s.symbol.get), s.symbol.get, r :: args, k(v |> sr)) case Call(_, _) => bErrStop(msg"Unsupported kind of Call ${r.toString()}") case Instantiate( false, diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala index ad5d8658f9..8abdef10f8 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala @@ -231,7 +231,7 @@ class WatBuilder(using TraceLogger, State) extends CodeBuilder: case sel @ Select(qual, id) => val qualRes = result(qual) - val selSym = sel.symbol_SelectSymbol getOrElse: + val selSym = sel.symbol getOrElse: lastWords(s"Symbol for Select(...) expression must be resolved") val selTrmSym = selSym match case termSym: TermSymbol => termSym @@ -254,7 +254,7 @@ class WatBuilder(using TraceLogger, State) extends CodeBuilder: case Instantiate(_, cls, as) => val ctorClsSymOpt = cls match case ref: Value.Ref => ref.disamb - case sel: Select => sel.symbol_SelectSymbol + case sel: Select => sel.symbol case cls => return errExpr( Ls( msg"WatBuilder::result for Instantiate(...) where `cls` is not a Ref(...) or Select(...) path not implemented yet " -> cls.toLoc From f58deae728d95defe853e80d1e56a41d00a5135d Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 00:09:30 +0800 Subject: [PATCH 21/55] Cleanup add docs --- hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala index 9abaf90f54..669da4e281 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala @@ -565,7 +565,7 @@ sealed abstract class Path extends TrivialResult: def asArg = Arg(spread = N, this) /** - * @param symbol The symbol, representing the definition that this selection refers to, if known. + * @param symbol The symbol representing the definition that the selection refers to, if known. */ case class Select(qual: Path, name: Tree.Ident)(val symbol: Opt[DefinitionSymbol[?]]) extends Path with ProductWithExtraInfo: def extraInfo: Str = @@ -577,6 +577,10 @@ case class Select(qual: Path, name: Tree.Ident)(val symbol: Opt[DefinitionSymbol case class DynSelect(qual: Path, fld: Path, arrayIdx: Bool) extends Path enum Value extends Path with ProductWithExtraInfo: + /** + * @param disamb The symbol disambiguating the definition that the reference refers to. This + * exists if and only if l is a BlockMemberSymbol. + */ case Ref(l: Local, disamb: Opt[DefinitionSymbol[?]]) case This(sym: InnerSymbol) // TODO rm – just use Ref case Lit(lit: Literal) @@ -587,7 +591,10 @@ enum Value extends Path with ProductWithExtraInfo: object Value: object Ref: + // * Some helper constructors that allow omitting the disambiguation symbol. + // * If the ref itself is a DefinitionSymbol, then disambiguating it results in itself. def apply(l: DefinitionSymbol[?]): Ref = Ref(l, S(l)) + // * If the ref is a symbol that does not refer to a definition, then there is no disambiguation. def apply(l: TempSymbol | VarSymbol | BuiltinSymbol): Ref = Ref(l, N) case class Arg(spread: Opt[Bool], value: Path) From df75b33a6199044d8154a1ff492c1b91d634b88c Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 00:16:01 +0800 Subject: [PATCH 22/55] Cleanup HandlerLowering --- .../shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala index 7bbe16404d..e3173ddc52 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala @@ -591,9 +591,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, f.owner match case None => S(Call(f.sym.asPath, params)(true, true)) case Some(owner) => - S(Call(Select(owner.asPath, Tree.Ident(f.sym.nme))(f.innerSym.asInstanceOf), params)(true, true)) - // TODO: ^^^^^^^^ - // TODO: @Harry check again on asInstanceOf + S(Call(Select(owner.asPath, Tree.Ident(f.sym.nme))(N), params)(true, true)) case _ => None // TODO: more than one plist FunDefn(f.owner, f.sym, f.params, translateBlock(f.body, From 46830c6b5fdd61112463214ccea221958c7e9447 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 14:50:46 +0800 Subject: [PATCH 23/55] Cleanup lifter --- hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index e61278b8e4..5850657891 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -235,7 +235,6 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): def read = this match case Sym(l) => l.asPath case PubField(isym, sym) => Select(isym.asPath, Tree.Ident(sym.nme))(N) - // TODO: isym.asInstanceOf def asArg = read.asArg @@ -675,8 +674,6 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): syms.addOne(l -> value) value k(Value.Ref(newSym, disamb)) - // ^^^^^^ - // TODO: Ref Refactorization case _ => super.applyPath(p)(k) (walker.applyBlock(b), syms.toList) end rewriteBms @@ -804,13 +801,6 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): )) k(Select(value.read, t.id)(N)) case _ => super.applyPath(p)(k) - - // Rewrites this.className.class to reference the top-level definition - case s @ Select(RefOfBms(l, disamb), Tree.Ident("class")) if !ctx.ignored(l) && ctx.isRelevant(l) => - // this class will be lifted, rewrite the ref to strip it of `Select` - k(Select(Value.Ref(l, disamb), Tree.Ident("class"))(s.symbol)) - // TODO: ^ - // TODO: Ref Refactorization // For objects inside classes: When an object is nested inside a class, its defn will be // replaced by a symbol, to which the object instance is assigned. This rewrites references From 04640c139cc556a5d471dc1633e809c062d6ff8e Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 14:54:19 +0800 Subject: [PATCH 24/55] Cleanup Normalization --- .../hkmc2/semantics/ucs/Normalization.scala | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala index 26b01d8cbf..cacbf97d96 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala @@ -38,21 +38,6 @@ class Normalization(using tl: TL)(using Raise, Ctx, State) extends TermSynthesiz case Split.Cons(head, tail) => Split.Cons(head, tail ++ those) case Split.Let(name, term, tail) => Split.Let(name, term, tail ++ those) case Split.Else(_) /* impossible */ | Split.End => those) - - extension (lhs: FlatPattern.ClassLike) - /** Generate a term that really resolves to the class at runtime. */ - def selectClass: FlatPattern.ClassLike = - // val constructor = lhs.constructor.symbol match - // case S(cls: ClassSymbol) => lhs.constructor - // case S(mem: BlockMemberSymbol) => - // // If the class is declaration-only, we do not need to select the - // // class. - // if !mem.hasLiftedClass || mem.defn.exists(_.hasDeclareModifier.isDefined) then - // lhs.constructor - // else - // Term.SynthSel(lhs.constructor, Tree.Ident("class"))(mem.clsTree.orElse(mem.modOrObjTree).map(_.symbol), N).resolve - // case _ => lhs.constructor - lhs.copy(lhs.constructor)(lhs.tree, lhs.output) extension (lhs: FlatPattern) /** Checks if two patterns are the same. */ @@ -173,7 +158,7 @@ class Normalization(using tl: TL)(using Raise, Ctx, State) extends TermSynthesiz val whenTrue = aliasOutputSymbols(scrutinee, pattern.output, normalize(specialize(consequent ++ alternative, +, scrutinee, pattern))) val whenFalse = normalizeImpl(specialize(alternative, -, scrutinee, pattern).clearFallback) - Branch(scrutinee, pattern.selectClass, whenTrue) ~: whenFalse + Branch(scrutinee, pattern, whenTrue) ~: whenFalse else // If any errors were raised, we skip the branch. log("BROKEN"); normalizeImpl(alternative) case S(S(mod: ModuleOrObjectSymbol)) => @@ -182,7 +167,7 @@ class Normalization(using tl: TL)(using Raise, Ctx, State) extends TermSynthesiz val whenTrue = aliasOutputSymbols(scrutinee, pattern.output, normalize(specialize(consequent ++ alternative, +, scrutinee, pattern))) val whenFalse = normalizeImpl(specialize(alternative, -, scrutinee, pattern).clearFallback) - Branch(scrutinee, pattern.selectClass, whenTrue) ~: whenFalse + Branch(scrutinee, pattern, whenTrue) ~: whenFalse else // If any errors were raised, we skip the branch. log("BROKEN"); normalizeImpl(alternative) case S(S(pat: PatternSymbol)) => mode match From efc0587056c941b23f654325a0ee1ff660bcb125 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 14:56:25 +0800 Subject: [PATCH 25/55] Cleanup Pattern --- .../src/main/scala/hkmc2/semantics/Pattern.scala | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Pattern.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Pattern.scala index e18fbe84b5..1c40d35d57 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Pattern.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Pattern.scala @@ -265,20 +265,6 @@ enum Pattern extends AutoLocated: case Alias(pattern, alias) => pattern :: alias :: Nil case Transform(pattern, transform) => pattern :: transform :: Nil - def subPatterns: Ls[Pattern] = this match - case Constructor(_, patternArguments, arguments) => - patternArguments ::: arguments.fold(Nil)(_.toList) - case Composition(_, left, right) => left :: right :: Nil - case Negation(pattern) => pattern :: Nil - case _: (Wildcard | Literal | Range) => Nil - case Concatenation(left, right) => left :: right :: Nil - case Tuple(leading, spread, trailing) => - leading ::: spread.toList ::: trailing - case Record(fields) => fields.map(_._2) - case Chain(first, second) => first :: second :: Nil - case Alias(pattern, _) => pattern :: Nil - case Transform(pattern, _) => pattern :: Nil - def subTerms: Ls[Term] = this match case Constructor(target, patternArguments, arguments) => target :: patternArguments.flatMap(_.subTerms) ::: arguments.fold(Nil)(_.flatMap(_.subTerms)) From 0137185bd3fd95538f5b53c80f3f063ca2f9b6ff Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 15:07:49 +0800 Subject: [PATCH 26/55] Cleanup Term --- .../src/main/scala/hkmc2/semantics/Elaborator.scala | 6 +++--- .../shared/src/main/scala/hkmc2/semantics/Resolver.scala | 8 ++++---- hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala | 8 ++------ hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala | 3 +++ .../main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala | 8 ++------ .../src/main/scala/hkmc2/semantics/ups/Compiler.scala | 4 ++-- 6 files changed, 16 insertions(+), 21 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index f6b89968da..b3781563f8 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -194,19 +194,19 @@ object Elaborator: object Ctx: abstract class Elem: def nme: Str - def ref(id: Ident)(using Elaborator.State): Term + def ref(id: Ident)(using Elaborator.State): Resolvable def symbol: Opt[Symbol] def isImport: Bool final case class RefElem(sym: Symbol) extends Elem: val nme = sym.nme - def ref(id: Ident)(using Elaborator.State): Term = + def ref(id: Ident)(using Elaborator.State): Resolvable = // * Note: due to symbolic ops, we may have `id.name =/= nme`; // * e.g., we can have `id.name = "|>"` and `nme = "pipe"`. Term.Ref(sym)(id, 666, N) // FIXME: 666 is a temporary placeholder def symbol = S(sym) def isImport: Bool = false final case class SelElem(base: Elem, nme: Str, symOpt: Opt[FieldSymbol], isImport: Bool) extends Elem: - def ref(id: Ident)(using Elaborator.State): Term = + def ref(id: Ident)(using Elaborator.State): Resolvable = // * Same remark as in RefElem#ref Term.SynthSel(base.ref(Ident(base.nme)), new Ident(nme).withLocOf(id))(symOpt, N) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 8428b822f1..c9a06b9edd 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -844,7 +844,7 @@ class Resolver(tl: TraceLogger) log(s"Resolving symbol for reference ${t} (bsym = ${bsym}, defn = ${bsym.defn})") val sym = disambSym(prefer, sign = sign)(bsym) sym.foreach: sym => - t.expand(S(Term.Resolved(t.duplicate, sym)(N))) + t.expand(S((t.duplicate.resolved(sym)))) resolveType(t, prefer = prefer) log(s"Resolved symbol for ${t}: ${sym}") @@ -863,7 +863,7 @@ class Resolver(tl: TraceLogger) log(s"Resolving symbol for ${t}, defn = ${lhs.defn}") disambSym(prefer, sign)(bms) match case S(ds) => - t.expand(S(Term.Resolved(t.withSym(bms), ds)(N))) + t.expand(S(t.withSym(bms).resolved(ds))) case N => log(s"Unable to disambiguate ${bms}") t.expand(S(t.withSym(bms))) @@ -890,7 +890,7 @@ class Resolver(tl: TraceLogger) log(s"Resolving symbol for ${t}, defn = ${lhs.defn}") disambSym(prefer, sign)(bms) match case S(ds) => - t.expand(S(Term.Resolved(t.withSym(bms), ds)(N))) + t.expand(S(t.withSym(bms).resolved(ds))) case N => log(s"Unable to disambiguate ${bms}") t.expand(S(t.withSym(bms))) @@ -911,7 +911,7 @@ class Resolver(tl: TraceLogger) // otherwise, there is already an error raised. cls.resolvedSym match case S(clsSym: ClassSymbol) => - t.expand(S(Term.Resolved(t.duplicate, clsSym)(N))) + t.expand(S(t.duplicate.resolved(clsSym))) case S(sym) => lastWords(s"Expected a class symbol; found ${sym} for term ${t}.") case N => diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index ef32ae57fc..61e91b6fb5 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -117,17 +117,13 @@ abstract class Symbol(using State) extends Located: asPat orElse asMod - def asDefnSym_TODO: Opt[DefinitionSymbol[?]] = this match - case defn: DefinitionSymbol[?] => S(defn) - case _ => N - override def equals(x: Any): Bool = x match case that: Symbol => uid === that.uid case _ => false override def hashCode: Int = uid.hashCode - + def subst(using SymbolSubst): Symbol - + end Symbol diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index 1e0d5ecca8..a7d5008497 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -128,6 +128,9 @@ sealed trait ResolvableImpl: def resolve: this.type = expand(N) def dontResolve: this.type = this // TODO rm + /** + * A helper function to create a resolved term for this term. + */ def resolved(sym: DefinitionSymbol[?]): Term.Resolved = Term.Resolved(this, sym)(typ = resolvedTyp) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala index 680b911e76..581ce1f810 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala @@ -40,9 +40,7 @@ trait TermSynthesizer(using Ctx, State): /** Make a term that looks like `runtime.MatchResult` with its symbol. */ protected lazy val matchResultClass = - Term.Resolved - (sel(runtimeRef, "MatchResult", State.matchResultClsSymbol), State.matchResultClsSymbol) - (N) + sel(runtimeRef, "MatchResult", State.matchResultClsSymbol).resolved(State.matchResultClsSymbol) /** Make a pattern that looks like `runtime.MatchResult.class`. */ protected def matchResultPattern(parameters: Opt[Ls[BlockLocalSymbol]]): FlatPattern.ClassLike = @@ -50,9 +48,7 @@ trait TermSynthesizer(using Ctx, State): /** Make a term that looks like `runtime.MatchFailure` with its symbol. */ protected lazy val matchFailureClass = - Term.Resolved - (sel(runtimeRef, "MatchFailure", State.matchFailureClsSymbol), State.matchFailureClsSymbol) - (N) + sel(runtimeRef, "MatchFailure", State.matchFailureClsSymbol).resolved(State.matchFailureClsSymbol) /** Make a pattern that looks like `runtime.MatchFailure.class`. */ protected def matchFailurePattern(parameters: Opt[Ls[BlockLocalSymbol]]): FlatPattern.ClassLike = diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Compiler.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Compiler.scala index 96b3661996..9cd2ec6cc7 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Compiler.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Compiler.scala @@ -408,14 +408,14 @@ object Compiler: def findSymbol(elem: Ctx.Elem): Opt[Term] = elem.symbol.flatMap(_.asClsLike).collectFirst: // Check the element's symbol. - case `symbol` => S(Term.Resolved(elem.ref(new Ident(symbol.nme)).withLoc(loc), symbol)(N)) + case `symbol` => S(elem.ref(new Ident(symbol.nme)).withLoc(loc).resolved(symbol)) // Look up the symbol in module members. case module: ModuleOrObjectSymbol => val moduleRef = module.defn.get.bsym.ref() module.tree.definedSymbols.iterator.map(_.mapSecond(_.asClsLike)).collectFirst: case (key, S(`symbol`)) => val memberSymbol = symbol.defn.get.bsym - Term.Resolved(SynthSel(moduleRef, Ident(key))(S(memberSymbol), N), symbol)(N) + SynthSel(moduleRef, Ident(key))(S(memberSymbol), N).resolved(symbol) .flatten @tailrec def go(ctx: Ctx): Opt[Term] = ctx.env.values.iterator.map(findSymbol).firstSome match From 959781477486a927f5635467bb44e60b13dc71b4 Mon Sep 17 00:00:00 2001 From: Flandia Date: Sat, 1 Nov 2025 15:09:50 +0800 Subject: [PATCH 27/55] Apply suggestion from @LPTK Co-authored-by: Lionel Parreaux --- hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index a7d5008497..73d17c2249 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -688,7 +688,7 @@ object ObjBody: .groupBy(_._1.nme) .partitionMap: (nme, syms) => if syms.map(_._1).distinct.tail.nonEmpty then L: - (msg"Found duplicate members with the same name '${nme}'." -> N) :: + (msg"Duplicate definition of member named '${nme}'." -> N) :: syms.map(_._2).map(msg"Defined at: " -> _.toLoc) else R: nme -> syms.head._1 From 0997535b78ab632ff6c232c1a23b11412cb05727 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 15:11:37 +0800 Subject: [PATCH 28/55] Cleanup HkScratch --- hkmc2/shared/src/test/mlscript/HkScratch.mls | 21 +------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/hkmc2/shared/src/test/mlscript/HkScratch.mls b/hkmc2/shared/src/test/mlscript/HkScratch.mls index 43d31f0aca..ef38e8b363 100644 --- a/hkmc2/shared/src/test/mlscript/HkScratch.mls +++ b/hkmc2/shared/src/test/mlscript/HkScratch.mls @@ -9,23 +9,4 @@ // :todo -:sjs -object Foo -Foo is Foo -//│ JS (unsanitized): -//│ let Foo1, scrut; -//│ globalThis.Object.freeze(class Foo { -//│ static { -//│ Foo1 = globalThis.Object.freeze(new this) -//│ } -//│ constructor() { -//│ Object.defineProperty(this, "class", { -//│ value: Foo -//│ }) -//│ } -//│ toString() { return runtime.render(this); } -//│ static [definitionMetadata] = ["object", "Foo"]; -//│ }); -//│ scrut = Foo1; -//│ if (scrut instanceof Foo1.class) { true } else { false } -//│ = true + From 82c087967510f8aabb798119de57538502c51a5d Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 15:13:16 +0800 Subject: [PATCH 29/55] Cleanup some tests 1 --- hkmc2/shared/src/test/mlscript/codegen/ParamClasses.mls | 2 +- .../shared/src/test/mlscript/codegen/ThisCallVariations.mls | 2 +- hkmc2/shared/src/test/mlscript/wasm/Basics.mls | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/hkmc2/shared/src/test/mlscript/codegen/ParamClasses.mls b/hkmc2/shared/src/test/mlscript/codegen/ParamClasses.mls index c0c6ddde10..30be3cf8a8 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/ParamClasses.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/ParamClasses.mls @@ -235,7 +235,7 @@ Foo(10, 20, 30, 40, 50) :e class Foo(val z, val z) -//│ ╔══[ERROR] Found duplicate members with the same name 'z'. +//│ ╔══[ERROR] Duplicate definition of member named 'z'. //│ ╟── Defined at: //│ ║ l.237: class Foo(val z, val z) //│ ║ ^ diff --git a/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls b/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls index ac387b68e1..61163ccdab 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls @@ -57,7 +57,7 @@ id(Example) .!. oops(2) data class Example2(val a) with val a = 1 fun f(inc) = Example2(a + inc) -//│ ╔══[ERROR] Found duplicate members with the same name 'a'. +//│ ╔══[ERROR] Duplicate definition of member named 'a'. //│ ╟── Defined at: //│ ║ l.57: data class Example2(val a) with //│ ║ ^ diff --git a/hkmc2/shared/src/test/mlscript/wasm/Basics.mls b/hkmc2/shared/src/test/mlscript/wasm/Basics.mls index b653656173..7c8e6ad2dc 100644 --- a/hkmc2/shared/src/test/mlscript/wasm/Basics.mls +++ b/hkmc2/shared/src/test/mlscript/wasm/Basics.mls @@ -2,6 +2,7 @@ :global :wasm + false //│ Wasm result: //│ = 0 @@ -32,7 +33,7 @@ x fun foo() = 42 foo //│ ╔══[COMPILATION ERROR] Returning function instances is not supported -//│ ║ l.33: foo +//│ ║ l.34: foo //│ ╙── ^^^ @@ -100,7 +101,7 @@ foo(41) //│ Wasm result: //│ = 42 -:lot + class Foo(val x) new Foo(0) //│ Wasm result: From 571d9dd4902d8d3b96c86798c8fb88069909dd39 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 16:06:34 +0800 Subject: [PATCH 30/55] Cleanup some tests 2 --- .../src/test/mlscript/basics/MutRcd.mls | 104 ------------------ hkmc2/shared/src/test/mlscript/ctx/Summon.mls | 11 +- .../test/mlscript/handlers/GeneratorStack.mls | 27 ----- 3 files changed, 6 insertions(+), 136 deletions(-) diff --git a/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls b/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls index 1c34653831..0c8a48f3a4 100644 --- a/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls +++ b/hkmc2/shared/src/test/mlscript/basics/MutRcd.mls @@ -84,110 +84,6 @@ let r = mut x: 1 //│ r = {x: 1} -:dl -:lot -Object.freeze -//│ Lowering.term member:Object.freeze -//│ Expanding term Sel(Ref(member:Object),Ident(freeze)) -//│ ~> Sel(Ref(member:Object),Ident(freeze)) -//│ Lowering.term member:Object – symbol member:Object -//│ Expanding term Ref(member:Object) -//│ ~> Ref(member:Object) -//│ Lowering.term globalThis:globalThis.Object‹member:Object› – symbol member:Object -//│ Expanding term Sel(Ref(globalThis:globalThis),Ident(Object)) -//│ ~> Sel(Ref(globalThis:globalThis),Ident(Object)) -//│ Lowering.term globalThis:globalThis – symbol globalThis:globalThis -//│ Expanding term Ref(globalThis:globalThis) -//│ ~> Ref(globalThis:globalThis) -//│ Lowered: -//│ Program: -//│ imports = Nil -//│ main = Assign: -//│ lhs = $selRes -//│ rhs = Select: -//│ qual = Ref: -//│ l = globalThis:globalThis -//│ disamb = N -//│ name = Ident of "Object" -//│ rest = Assign: \ -//│ lhs = $discarded -//│ rhs = Select: -//│ qual = Ref: -//│ l = globalThis:globalThis -//│ disamb = N -//│ name = Ident of "Object$__checkNotMethod" -//│ rest = Match: \ -//│ scrut = Ref: -//│ l = $selRes -//│ disamb = N -//│ arms = Ls of -//│ Tuple2: -//│ _1 = Lit of UnitLit of false -//│ _2 = Throw of Instantiate: -//│ mut = false -//│ cls = Select: -//│ qual = Ref{disamb=globalThis:globalThis}: -//│ l = globalThis:globalThis -//│ disamb = S of globalThis:globalThis -//│ name = Ident of "Error" -//│ args = Ls of -//│ Arg: -//│ spread = N -//│ value = Lit of StrLit of "Access to required field 'Object' yielded 'undefined'" -//│ dflt = N -//│ rest = Assign: \ -//│ lhs = $selRes -//│ rhs = Select: -//│ qual = Ref: -//│ l = $selRes -//│ disamb = N -//│ name = Ident of "freeze" -//│ rest = Assign: \ -//│ lhs = $discarded -//│ rhs = Select: -//│ qual = Ref: -//│ l = $selRes -//│ disamb = N -//│ name = Ident of "freeze$__checkNotMethod" -//│ rest = Match: \ -//│ scrut = Ref: -//│ l = $selRes -//│ disamb = N -//│ arms = Ls of -//│ Tuple2: -//│ _1 = Lit of UnitLit of false -//│ _2 = Throw of Instantiate: -//│ mut = false -//│ cls = Select: -//│ qual = Ref{disamb=globalThis:globalThis}: -//│ l = globalThis:globalThis -//│ disamb = S of globalThis:globalThis -//│ name = Ident of "Error" -//│ args = Ls of -//│ Arg: -//│ spread = N -//│ value = Lit of StrLit of "Access to required field 'freeze' yielded 'undefined'" -//│ dflt = N -//│ rest = Assign: \ -//│ lhs = $block$res -//│ rhs = Ref: -//│ l = $selRes -//│ disamb = N -//│ rest = Return: \ -//│ res = Lit of UnitLit of false -//│ implct = true -//│ avoidNames Assign($selRes,Select(Ref(globalThis:globalThis,None),Ident(Object)),Assign($discarded,Select(Ref(gl... -//│ | avoidNames Assign($discarded,Select(Ref(globalThis:globalThis,None),Ident(Object$__checkNotMethod)),Match(Ref($... -//│ | | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... -//│ | | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... -//│ | | | avoidNames Assign($selRes,Select(Ref($selRes,None),Ident(freeze)),Assign($discarded,Select(Ref($selRes,None),Id... -//│ | | | | avoidNames Assign($discarded,Select(Ref($selRes,None),Ident(freeze$__checkNotMethod)),Match(Ref($selRes,None),L... -//│ | | | | | avoidNames Match(Ref($selRes,None),List((Lit(UnitLit(false)),Throw(Instantiate(false,Select(Ref(globalThis:glob... -//│ | | | | | | avoidNames Throw(Instantiate(false,Select(Ref(globalThis:globalThis,Some(globalThis:globalThis)),Ident(Error)),... -//│ | | | | | | avoidNames Assign($block$res,Ref($selRes,None),Return(Lit(UnitLit(false)),true))... -//│ | | | | | | | avoidNames Return(Lit(UnitLit(false)),true)... -//│ = fun freeze - Object.freeze(r) //│ = {x: 1} diff --git a/hkmc2/shared/src/test/mlscript/ctx/Summon.mls b/hkmc2/shared/src/test/mlscript/ctx/Summon.mls index 318e6302a2..926ef2ce0c 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/Summon.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/Summon.mls @@ -62,6 +62,7 @@ fun f(using Int) = use[Num] data class Some[T](value: T) + :expect 42 fun f[T](using Some[T]) = use[Some[T]].value using Some[Int] = Some(42) @@ -72,10 +73,10 @@ f :re use{[Some[Int]].value} //│ ╔══[ERROR] Illegal juxtaposition right-hand side (selection). -//│ ║ l.73: use{[Some[Int]].value} +//│ ║ l.74: use{[Some[Int]].value} //│ ╙── ^^^^^^^^^^^ //│ ╔══[ERROR] Cannot query instance of type ‹unspecified› (type parameter T) for call: -//│ ║ l.73: use{[Some[Int]].value} +//│ ║ l.74: use{[Some[Int]].value} //│ ║ ^^^ //│ ╟── Required by contextual parameter declaration: //│ ║ l.92: fun use[T](using instance: T) = instance @@ -87,7 +88,7 @@ use{[Some[Int]].value} :re use([Some[Int]].value) //│ ╔══[ERROR] Cannot query instance of type ‹unspecified› (type parameter T) for call: -//│ ║ l.88: use([Some[Int]].value) +//│ ║ l.89: use([Some[Int]].value) //│ ║ ^^^ //│ ╟── Required by contextual parameter declaration: //│ ║ l.92: fun use[T](using instance: T) = instance @@ -106,10 +107,10 @@ f[Int] :re f //│ ╔══[ERROR] Cannot query instance of type ‹unspecified› (type parameter T) for call: -//│ ║ l.107: f +//│ ║ l.108: f //│ ║ ^ //│ ╟── Required by contextual parameter declaration: -//│ ║ l.100: fun f[T](using T) = use[T] +//│ ║ l.101: fun f[T](using T) = use[T] //│ ║ ^ //│ ╙── Illegal query for an unspecified type variable T. //│ ═══[RUNTIME ERROR] Error: Function 'f' expected 1 argument but got 0 diff --git a/hkmc2/shared/src/test/mlscript/handlers/GeneratorStack.mls b/hkmc2/shared/src/test/mlscript/handlers/GeneratorStack.mls index 8dcd0dcff8..915a0e177f 100644 --- a/hkmc2/shared/src/test/mlscript/handlers/GeneratorStack.mls +++ b/hkmc2/shared/src/test/mlscript/handlers/GeneratorStack.mls @@ -4,33 +4,6 @@ import "../../mlscript-compile/Stack.mls" open Stack -:rt -val x: Stack[Int] -//│ Resolved tree: -//│ Blk: -//│ stats = Ls of -//│ TermDefinition: -//│ k = ImmutVal -//│ sym = member:x -//│ tsym = term:x -//│ params = Nil -//│ tparams = N -//│ sign = S of TyApp{sym=type:Stack}: -//│ lhs = Resolved{sym=type:Stack}: -//│ t = Ref{sym=member:Stack} of member:Stack -//│ sym = type:Stack -//│ targs = Ls of -//│ Resolved{sym=class:Int}: -//│ t = Ref{sym=member:Int} of member:Int -//│ sym = class:Int -//│ body = N -//│ resSym = ‹result of member:x› -//│ flags = () -//│ modulefulness = Modulefulness of N -//│ annotations = Nil -//│ companion = N -//│ res = Lit of UnitLit of false - class Generator with fun produce(result: Stack[Int]): () From 79a7a88fa3fec2bda1d74a275c6598d6cb0aa44e Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 16:07:56 +0800 Subject: [PATCH 31/55] Cleanup Resolver --- hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index c9a06b9edd..ed631e28ef 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -12,10 +12,10 @@ import Elaborator.State import Resolvable.* import typing.Type +import semantics.ucs.FlatPattern + import Message.MessageContext import scala.annotation.tailrec -import hkmc2.semantics.ucs.FlatPattern -import hkmc2.syntax.Keyword.__ object Resolver: From 6ff7a4f3ded56d48ca66e269e5dc4187e4122917 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 16:12:02 +0800 Subject: [PATCH 32/55] Correct location of TermDefinition --- .../src/main/scala/hkmc2/semantics/Elaborator.scala | 2 +- .../shared/src/test/mlscript/basics/ModuleMethods.mls | 4 ++-- .../src/test/mlscript/codegen/ThisCallVariations.mls | 2 +- hkmc2/shared/src/test/mlscript/parser/Handler.mls | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index b3781563f8..5f96d1a356 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -1157,7 +1157,7 @@ extends Importer: val tsym = TermSymbol(k, owner, id) // TODO? val tdf = TermDefinition(k, sym, tsym, pss, tps, s, body, r, - TermDefFlags.empty.copy(isMethod = isMethod), mfn, annotations, N) + TermDefFlags.empty.copy(isMethod = isMethod), mfn, annotations, N).withLocOf(td) tsym.defn = S(tdf) sym.defn = S(tdf) sym.tdefn = S(tdf) diff --git a/hkmc2/shared/src/test/mlscript/basics/ModuleMethods.mls b/hkmc2/shared/src/test/mlscript/basics/ModuleMethods.mls index 3a248ea2b1..9df8d9038b 100644 --- a/hkmc2/shared/src/test/mlscript/basics/ModuleMethods.mls +++ b/hkmc2/shared/src/test/mlscript/basics/ModuleMethods.mls @@ -173,7 +173,7 @@ class C with val bar: module M = M //│ ╔══[ERROR] Function returning modules should not be a class member. //│ ║ l.172: fun foo: module M = M -//│ ╙── ^^^^^ +//│ ╙── ^^^^^^^^^^^^^^^^^^^^^ //│ ╔══[ERROR] Value returning modules should not be a class member. //│ ║ l.173: val bar: module M = M -//│ ╙── ^^^^^ +//│ ╙── ^^^^^^^^^^^^^^^^^^^^^ diff --git a/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls b/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls index 61163ccdab..99166a71c4 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls @@ -63,7 +63,7 @@ data class Example2(val a) with //│ ║ ^ //│ ╟── Defined at: //│ ║ l.58: val a = 1 -//│ ╙── ^ +//│ ╙── ^^^^^^^^^ let oops2 = Example2(0).("f") //│ oops2 = fun f diff --git a/hkmc2/shared/src/test/mlscript/parser/Handler.mls b/hkmc2/shared/src/test/mlscript/parser/Handler.mls index 03269443b5..624ea76716 100644 --- a/hkmc2/shared/src/test/mlscript/parser/Handler.mls +++ b/hkmc2/shared/src/test/mlscript/parser/Handler.mls @@ -86,7 +86,7 @@ handle h = Eff with foo(h) //│ ╔══[ERROR] Only function definitions are allowed in handler blocks //│ ║ l.83: val x = 24 -//│ ╙── ^^ +//│ ╙── ^^^^^^^^^^ //│ ╔══[ERROR] Only function definitions are allowed in handler blocks //│ ║ l.85: fun x() = x //│ ╙── ^ @@ -104,16 +104,16 @@ handle h = Eff with foo(h) //│ ╔══[ERROR] Handler function is missing resumption parameter //│ ║ l.99: fun f = r(0) -//│ ╙── ^^^^ +//│ ╙── ^^^^^^^^^^^^ //│ ╔══[ERROR] Handler function is missing resumption parameter //│ ║ l.100: fun g() = r(0) -//│ ╙── ^^^^ +//│ ╙── ^^^^^^^^^^^^^^ //│ ╔══[ERROR] Handler function is missing resumption parameter //│ ║ l.101: fun h()() = r(1) -//│ ╙── ^^^^ +//│ ╙── ^^^^^^^^^^^^^^^^ //│ ╔══[ERROR] Handler function is missing resumption parameter //│ ║ l.102: fun h2()(a, b) = r(1) -//│ ╙── ^^^^ +//│ ╙── ^^^^^^^^^^^^^^^^^^^^^ //│ ╔══[ERROR] Name not found: h //│ ║ l.103: foo(h) //│ ╙── ^ From 383da7fb9ac72dd468867f54d6ba7fd877dcdfc4 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 16:17:30 +0800 Subject: [PATCH 33/55] Cleanup Resolver --- .../shared/src/main/scala/hkmc2/semantics/Resolver.scala | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index ed631e28ef..3805a8e55d 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -897,12 +897,9 @@ class Resolver(tl: TraceLogger) log(s"Resolved symbol for ${t}: ${bms}") case N => // TODO @Harry: Appropriately resolve all selections on classes. - // t.expand(S(t.withSym(ErrorSymbol(id.name, Tree.Dummy)))) - // raise: - // ErrorReport( - // msg"${defn.kind.desc.capitalize} '${defn.sym.nme}' " + - // msg"does not contain member '${id.name}'" -> t.toLoc :: Nil, - // extraInfo = S(defn))' + // The type annotations in the current code bases are largely incomplete, + // so many selections on classes cannot be resolved properly. + // We will refactor this later... case defn => log(s"Unsupported selection from definition: ${defn}") From dd08cce9a84d87eea88406ec0efaa2bef67d5a48 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 1 Nov 2025 16:18:44 +0800 Subject: [PATCH 34/55] Cleanup Elaborator --- hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index 5f96d1a356..f6039a1a8d 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -1396,7 +1396,6 @@ extends Importer: ) ctsym.defn = S(ctdef) sym.tdefn = S(ctdef) - log(s"Constructor: ${ctdef}") cd sym.defn = S(defn) go(sts, Nil, defn :: acc) From ce4f4a6e9f7bc6cd433f211d9aaa7ce277b760c4 Mon Sep 17 00:00:00 2001 From: Flandia Date: Sat, 8 Nov 2025 14:56:08 +0800 Subject: [PATCH 35/55] Apply @LPTK's suggestion Co-authored-by: Lionel Parreaux --- hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index 0b7f763c8a..f864ff7d4e 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -318,7 +318,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): raise: WarningReport(msg"Pure expression in statement position" -> ref.toLoc :: Nil, S(ref)) - val st.Ref(sym) = ref + val sym = ref.symbol sym match case ctx.builtins.source.bms | ctx.builtins.js.bms | ctx.builtins.wasm.bms | ctx.builtins.debug.bms | ctx.builtins.annotations.bms => return fail: From 7d92a231f34adb376f6afd4e4b04d49743b99021 Mon Sep 17 00:00:00 2001 From: Flandia Date: Sat, 8 Nov 2025 15:27:55 +0800 Subject: [PATCH 36/55] Apply @LPTK's suggestion Co-authored-by: Lionel Parreaux --- hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index 5850657891..100e6464a4 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -1292,7 +1292,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): nestedIn match // These will be the names of the objects/modules after being lifted // We should use the nested object/module's **original name** if nested inside a class, - // so they can be accesed directly by name from te outside. + // so they can be accesed directly by name from the outside. // For example, if a class C has an object M, (new C).M as a dynamic selection works case cls: ClsLikeDefn => S(c.sym -> TermSymbol(syntax.ImmutVal, S(cls.isym), Tree.Ident(c.sym.nme))) case _ => S(c.sym -> VarSymbol(Tree.Ident(c.sym.nme + "$"))) From 146ee2b1df7c30726e3b73545a3325d56e664e90 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 14:55:52 +0800 Subject: [PATCH 37/55] Clarify test comment --- hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls b/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls index bfd51abc7c..887bd29387 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls @@ -234,7 +234,7 @@ fun f(o: O) = o //│ companion = N //│ res = Lit of UnitLit of false -// The implicit `this` should be resolved correctly... +// The implicit `this` (class:Foo) in the SynthSel(class:Foo, "foo") should be resolved correctly. :rt class Foo with val foo = 42 @@ -273,7 +273,7 @@ class Foo with //│ annotations = Nil //│ res = Lit of UnitLit of false -// ... as well as an explicit `this`. +// The explicit `this` (class:Foo) in the Sel(class:Foo, "foo") should be resolved correctly. :rt class Foo with val foo = 42 From 63ec9eeccef65619649edc42f05f894b735f6d5c Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 14:59:37 +0800 Subject: [PATCH 38/55] Refactor out `t.resolvedSym.flatMap(_.asBlkMember)` --- .../main/scala/hkmc2/codegen/Lowering.scala | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index f864ff7d4e..b76cf01490 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -468,24 +468,26 @@ class Lowering()(using Config, TL, Raise, State, Ctx): case sym => (sym is State.matchResultClsSymbol) || (sym is State.matchFailureClsSymbol) def conclude(fr: Path) = lowerCall(fr, isMlsFun, arg, t.toLoc)(k) + + lazy val resolvedBms = t.resolvedSym.flatMap(_.asBlkMember) // * We have to instantiate `f` again because, if `f` is a Sel, the `term` // * function is not called again with f. See below `Sel` and `SelProj` cases. f.instantiated match - case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.js.bitand) => + case t if resolvedBms.exists(_ is ctx.builtins.js.bitand) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("bitand"))) - case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.js.bitnot) => + case t if resolvedBms.exists(_ is ctx.builtins.js.bitnot) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("bitnot"))) - case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.js.bitor) => + case t if resolvedBms.exists(_ is ctx.builtins.js.bitor) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("bitor"))) - case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.js.shl) => + case t if resolvedBms.exists(_ is ctx.builtins.js.shl) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("shl"))) - case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.js.try_catch) => + case t if resolvedBms.exists(_ is ctx.builtins.js.try_catch) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("try_catch"))) - case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.wasm.plus_impl) => + case t if resolvedBms.exists(_ is ctx.builtins.wasm.plus_impl) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("plus_impl"))) - case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.Int31) => + case t if resolvedBms.exists(_ is ctx.builtins.Int31) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("Int31"))) - case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.debug.printStack) => + case t if resolvedBms.exists(_ is ctx.builtins.debug.printStack) => if !config.effectHandlers.exists(_.debug) then return fail: ErrorReport( @@ -493,7 +495,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): t.toLoc :: Nil, source = Diagnostic.Source.Compilation) conclude(Value.Ref(State.runtimeSymbol).selSN("raisePrintStackEffect").withLocOf(f)) - case t if t.resolvedSym.flatMap(_.asBlkMember).exists(_ is ctx.builtins.debug.getLocals) => + case t if resolvedBms.exists(_ is ctx.builtins.debug.getLocals) => if !config.effectHandlers.exists(_.debug) then return fail: ErrorReport( From c327e4537c6b52f9b2be84741fa7a09f34c656fa Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 15:03:19 +0800 Subject: [PATCH 39/55] Deobfuscate Harry's top-quality code --- hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala index 669da4e281..4e530d68cd 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala @@ -568,11 +568,7 @@ sealed abstract class Path extends TrivialResult: * @param symbol The symbol representing the definition that the selection refers to, if known. */ case class Select(qual: Path, name: Tree.Ident)(val symbol: Opt[DefinitionSymbol[?]]) extends Path with ProductWithExtraInfo: - def extraInfo: Str = - (symbol.map(s => s"sym=${s}") :: Nil) - .collect: - case S(info) => info - .mkString(",") + def extraInfo: Str = symbol.map(s => s"sym=${s}").mkString case class DynSelect(qual: Path, fld: Path, arrayIdx: Bool) extends Path From ba1f714a480c10e4570b8a509b793038b211d217 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 15:10:04 +0800 Subject: [PATCH 40/55] Refactor out `t.resolvedSym.flatMap(_.asBlkMember)` --- .../main/scala/hkmc2/codegen/Lowering.scala | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index b76cf01490..d888e57e6e 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -469,25 +469,27 @@ class Lowering()(using Config, TL, Raise, State, Ctx): (sym is State.matchFailureClsSymbol) def conclude(fr: Path) = lowerCall(fr, isMlsFun, arg, t.toLoc)(k) - lazy val resolvedBms = t.resolvedSym.flatMap(_.asBlkMember) + val instantiated = f.instantiated + val instantiatedResolvedBms = instantiated.resolvedSym.flatMap(_.asBlkMember) + // * We have to instantiate `f` again because, if `f` is a Sel, the `term` // * function is not called again with f. See below `Sel` and `SelProj` cases. - f.instantiated match - case t if resolvedBms.exists(_ is ctx.builtins.js.bitand) => + instantiated match + case t if instantiatedResolvedBms.exists(_ is ctx.builtins.js.bitand) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("bitand"))) - case t if resolvedBms.exists(_ is ctx.builtins.js.bitnot) => + case t if instantiatedResolvedBms.exists(_ is ctx.builtins.js.bitnot) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("bitnot"))) - case t if resolvedBms.exists(_ is ctx.builtins.js.bitor) => + case t if instantiatedResolvedBms.exists(_ is ctx.builtins.js.bitor) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("bitor"))) - case t if resolvedBms.exists(_ is ctx.builtins.js.shl) => + case t if instantiatedResolvedBms.exists(_ is ctx.builtins.js.shl) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("shl"))) - case t if resolvedBms.exists(_ is ctx.builtins.js.try_catch) => + case t if instantiatedResolvedBms.exists(_ is ctx.builtins.js.try_catch) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("try_catch"))) - case t if resolvedBms.exists(_ is ctx.builtins.wasm.plus_impl) => + case t if instantiatedResolvedBms.exists(_ is ctx.builtins.wasm.plus_impl) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("plus_impl"))) - case t if resolvedBms.exists(_ is ctx.builtins.Int31) => + case t if instantiatedResolvedBms.exists(_ is ctx.builtins.Int31) => conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident("Int31"))) - case t if resolvedBms.exists(_ is ctx.builtins.debug.printStack) => + case t if instantiatedResolvedBms.exists(_ is ctx.builtins.debug.printStack) => if !config.effectHandlers.exists(_.debug) then return fail: ErrorReport( @@ -495,7 +497,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): t.toLoc :: Nil, source = Diagnostic.Source.Compilation) conclude(Value.Ref(State.runtimeSymbol).selSN("raisePrintStackEffect").withLocOf(f)) - case t if resolvedBms.exists(_ is ctx.builtins.debug.getLocals) => + case t if instantiatedResolvedBms.exists(_ is ctx.builtins.debug.getLocals) => if !config.effectHandlers.exists(_.debug) then return fail: ErrorReport( From 4fe9cf65df88f481348e0ed3b2870a7e38dd8fe4 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 15:16:43 +0800 Subject: [PATCH 41/55] Preserve empty lines in Lifter --- hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index 100e6464a4..ef92c8e871 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -241,11 +241,12 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): def assign(value: Result, rest: Block) = this match case Sym(l) => Assign(l, value, rest) case PubField(isym, sym) => AssignField(isym.asPath, Tree.Ident(sym.nme), value, rest)(S(sym)) - + def readDisamb(d: Opt[DefinitionSymbol[?]]) = this match case Sym(l) => Value.Ref(l, d) case PubField(isym, sym) => Select(isym.asPath, Tree.Ident(sym.nme))(d) + def isHandlerClsPath(p: Path) = handlerPaths match case None => false case Some(paths) => paths.isHandlerClsPath(p) From 6c50dde49035cd8d43982c75bb7cc083eb203239 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 15:27:25 +0800 Subject: [PATCH 42/55] Refine symbol typing and clean redundancy --- .../src/main/scala/hkmc2/codegen/Block.scala | 6 +++--- .../scala/hkmc2/codegen/HandlerLowering.scala | 2 +- .../src/main/scala/hkmc2/codegen/Lifter.scala | 13 ++++--------- .../scala/hkmc2/codegen/llir/Builder.scala | 18 +++++++++--------- .../main/scala/hkmc2/codegen/llir/Llir.scala | 4 ++-- .../src/main/scala/hkmc2/semantics/Term.scala | 2 +- 6 files changed, 20 insertions(+), 25 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala index 4e530d68cd..4e63263cd5 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala @@ -399,7 +399,7 @@ object ValDefn: // * a lone module is represented as an empty class with a `companion` module. final case class ClsLikeDefn( owner: Opt[InnerSymbol], - isym: MemberSymbol[? <: ClassLikeDef] & InnerSymbol, + isym: DefinitionSymbol[? <: ClassLikeDef] & InnerSymbol, sym: BlockMemberSymbol, k: syntax.ClsLikeKind, paramsOpt: Opt[ParamList], @@ -414,12 +414,12 @@ final case class ClsLikeDefn( bufferable: Option[Bool], ) extends Defn: require(k isnt syntax.Mod) - val innerSym = S(isym) + val innerSym = S(isym.asMemSym) // * This is only supposed to be for companion module definitions (notably, not for `object`) final case class ClsLikeBody( - isym: MemberSymbol[? <: ModuleOrObjectDef] & InnerSymbol, + isym: DefinitionSymbol[? <: ModuleOrObjectDef] & InnerSymbol, methods: Ls[FunDefn], privateFields: Ls[TermSymbol], publicFields: Ls[BlockMemberSymbol -> TermSymbol], diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala index e3173ddc52..3393ec5b6c 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala @@ -33,7 +33,7 @@ object HandlerLowering: private case class LinkState(res: Local, cls: Path, uid: Path) - type FnOrCls = Either[BlockMemberSymbol, MemberSymbol[? <: ClassLikeDef] & InnerSymbol] + type FnOrCls = Either[BlockMemberSymbol, DefinitionSymbol[? <: ClassLikeDef] & InnerSymbol] // isTopLevel: // whether the current block is the top level block, as we do not emit code for continuation class on the top level diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index ef92c8e871..db70913ea2 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -230,7 +230,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): enum LocalPath: case Sym(l: Local) - case PubField(isym: MemberSymbol[? <: ClassLikeDef] & InnerSymbol, sym: BlockMemberSymbol) + case PubField(isym: DefinitionSymbol[? <: ClassLikeDef] & InnerSymbol, sym: BlockMemberSymbol) def read = this match case Sym(l) => l.asPath @@ -1022,10 +1022,8 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): val isMutSym = VarSymbol(Tree.Ident("isMut")) var curSym = TempSymbol(None, "tmp") - // TODO: This special case Select(..., "class") is redundant after this PR. - def instInner(isMut: Bool) = if c.paramsOpt.isDefined - then Instantiate(mut = isMut, Select(c.sym.asPath, Tree.Ident("class"))(N), paramArgs) - else Instantiate(mut = isMut, c.sym.asPath, paramArgs) + def instInner(isMut: Bool) = + Instantiate(mut = isMut, Value.Ref(c.sym, S(c.isym)), paramArgs) val initSym = curSym @@ -1186,13 +1184,10 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): case c: ClsLikeDefn => c.copy(owner = N) case d => d - // TODO: The special case Select(..., "class") is redundant after the PR. def rewriteExtends(p: Path): Path = p match case RefOfBms(b, _) if !ctx.ignored(b) && ctx.isRelevant(b) => b.asPath - case Select(RefOfBms(b, _), Tree.Ident("class")) if !ctx.ignored(b) && ctx.isRelevant(b) => - Select(b.asPath, Tree.Ident("class"))(N) case _ => return p - + // if this class extends something, rewrite val newPar = c.parentPath.map(rewriteExtends) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala index 6bc4ca8661..f287cedb41 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala @@ -31,7 +31,7 @@ final case class BuiltinSymbols( var builtinSym: Opt[Local] = None, fieldSym: MutMap[Int, VarSymbol] = MutMap.empty, applySym: MutMap[Int, BlockMemberSymbol] = MutMap.empty, - tupleSym: MutMap[Int, MemberSymbol[? <: ClassLikeDef]] = MutMap.empty, + tupleSym: MutMap[Int, DefinitionSymbol[? <: ClassLikeDef]] = MutMap.empty, runtimeSym: Opt[TempSymbol] = None, ): def hiddenClasses = callableSym.toSet @@ -41,28 +41,28 @@ final case class Ctx( class_acc: ListBuffer[ClassInfo], symbol_ctx: Map[Local, Local] = Map.empty, fn_ctx: Map[Local, FuncInfo] = Map.empty, // is a known function - class_ctx: Map[MemberSymbol[? <: ClassLikeDef], ClassInfo] = Map.empty, - class_sym_ctx: Map[BlockMemberSymbol, MemberSymbol[? <: ClassLikeDef]] = Map.empty, + class_ctx: Map[DefinitionSymbol[? <: ClassLikeDef], ClassInfo] = Map.empty, + class_sym_ctx: Map[BlockMemberSymbol, DefinitionSymbol[? <: ClassLikeDef]] = Map.empty, flow_ctx: Map[Path, Local] = Map.empty, isTopLevel: Bool = true, - method_class: Opt[MemberSymbol[? <: ClassLikeDef]] = None, + method_class: Opt[DefinitionSymbol[? <: ClassLikeDef]] = None, builtinSym: BuiltinSymbols = BuiltinSymbols() ): def addFuncName(n: Local, paramsSize: Int) = copy(fn_ctx = fn_ctx + (n -> FuncInfo(paramsSize))) def findFuncName(n: Local)(using Raise) = fn_ctx.get(n) match case None => bErrStop(msg"Function name not found: ${n.toString()}") case Some(value) => value - def addClassInfo(n: MemberSymbol[? <: ClassLikeDef], bsym: BlockMemberSymbol, m: ClassInfo) = + def addClassInfo(n: DefinitionSymbol[? <: ClassLikeDef], bsym: BlockMemberSymbol, m: ClassInfo) = copy(class_ctx = class_ctx + (n -> m), class_sym_ctx = class_sym_ctx + (bsym -> n)) def addName(n: Local, m: Local) = copy(symbol_ctx = symbol_ctx + (n -> m)) def findName(n: Local)(using Raise) = symbol_ctx.get(n) match case None => bErrStop(msg"Name not found: ${n.toString}") case Some(value) => value - def findClassInfo(n: MemberSymbol[? <: ClassLikeDef])(using Raise) = class_ctx.get(n) match + def findClassInfo(n: DefinitionSymbol[? <: ClassLikeDef])(using Raise) = class_ctx.get(n) match case None => bErrStop(msg"Class not found: ${n.toString}") case Some(value) => value def addKnownClass(n: Path, m: Local) = copy(flow_ctx = flow_ctx + (n -> m)) - def setClass(c: MemberSymbol[? <: ClassLikeDef]) = copy(method_class = Some(c)) + def setClass(c: DefinitionSymbol[? <: ClassLikeDef]) = copy(method_class = Some(c)) def nonTopLevel = copy(isTopLevel = false) object Ctx: @@ -308,8 +308,8 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case Some(value) => bErrStop(msg"Member symbol without class definition ${value.toString}") case None => bErrStop(msg"Member symbol without definition ${ms.toString}") - private def fromMemToClass(m: Symbol)(using ctx: Ctx)(using Raise, Scope): MemberSymbol[? <: ClassLikeDef] = - trace[MemberSymbol[? <: ClassLikeDef]](s"bFromMemToClass $m", x => s"bFromMemToClass end: $x"): + private def fromMemToClass(m: Symbol)(using ctx: Ctx)(using Raise, Scope): DefinitionSymbol[? <: ClassLikeDef] = + trace[DefinitionSymbol[? <: ClassLikeDef]](s"bFromMemToClass $m", x => s"bFromMemToClass end: $x"): m match case ms: MemberSymbol[?] => ms.defn match diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Llir.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Llir.scala index 6c41a73333..69a5dd7b66 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Llir.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Llir.scala @@ -38,7 +38,7 @@ implicit object ClassInfoOrdering extends Ordering[ClassInfo] { case class ClassInfo( id: Int, - symbol: MemberSymbol[? <: ClassLikeDef], + symbol: DefinitionSymbol[? <: ClassLikeDef], fields: Ls[VarSymbol], parents: Ls[Local], methods: Map[Local, Func], @@ -82,7 +82,7 @@ sealed trait TrivialExpr: enum Expr: case Ref(sym: Local) extends Expr, TrivialExpr case Literal(lit: hkmc2.syntax.Literal) extends Expr, TrivialExpr - case CtorApp(cls: MemberSymbol[? <: ClassLikeDef], args: Ls[TrivialExpr]) + case CtorApp(cls: DefinitionSymbol[? <: ClassLikeDef], args: Ls[TrivialExpr]) case Select(name: Local, cls: Local, field: Str) case BasicOp(name: BuiltinSymbol, args: Ls[TrivialExpr]) case AssignField(assignee: Local, cls: Local, field: Str, value: TrivialExpr) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index 73d17c2249..3373b7375f 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -744,7 +744,7 @@ sealed abstract class TypeLikeDef extends Definition: sealed abstract class ClassLikeDef extends TypeLikeDef: val owner: Opt[InnerSymbol] val kind: ClsLikeKind - val sym: MemberSymbol[? <: ClassLikeDef] & InnerSymbol + val sym: DefinitionSymbol[? <: ClassLikeDef] & InnerSymbol val bsym: BlockMemberSymbol val tparams: Ls[TyParam] val paramsOpt: Opt[ParamList] From 31fb16cd005521df91c57608a930315203d09d8a Mon Sep 17 00:00:00 2001 From: Flandia Date: Sat, 8 Nov 2025 15:36:02 +0800 Subject: [PATCH 43/55] Apply @LPTK's suggestion Co-authored-by: Lionel Parreaux --- hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index 3373b7375f..16da8a590d 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -203,7 +203,8 @@ enum Term extends Statement: case UnitVal() case Missing // Placeholder terms that were not elaborated due to the "lightweight" elaboration mode `Mode.Light` case Lit(lit: Literal) - /** A term that wraps another term, indicating that the symbol of the inner term is resolved. */ + /** A term that wraps another term, indicating that the symbol of the inner term is resolved. + * This is mainly used to disambiguate overloaded definitions. */ case Resolved(t: Term, sym: DefinitionSymbol[?]) (val typ: Opt[Type]) extends Term, ResolvableImpl case Ref(sym: Symbol) From a8bb754a53fdcebb2df2e622123ccc70c011823c Mon Sep 17 00:00:00 2001 From: Flandia Date: Sat, 8 Nov 2025 15:37:20 +0800 Subject: [PATCH 44/55] Apply @LPTK's suggestion Co-authored-by: Lionel Parreaux --- hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 61e91b6fb5..5b977cc5f2 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -306,7 +306,7 @@ sealed trait ClassLikeSymbol extends IdentifiedSymbol: /** - * A symbol that the entity it represents has a definition. + * A symbol for entities with a definition. * * This is different from `MemberSymbol` because `BlockMemberSymbol` extends `MemberSymbol`, and its * definition is ambiguous in the sense that a `BlockMemberSymbol` corresponds to multiple From e026034236d9f46f6bf08fa9f01d9d4417c0fa4d Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 15:29:45 +0800 Subject: [PATCH 45/55] Fix @LPTK's suggestion --- hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index d888e57e6e..253c219f41 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -318,7 +318,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): raise: WarningReport(msg"Pure expression in statement position" -> ref.toLoc :: Nil, S(ref)) - val sym = ref.symbol + val sym = ref.sym sym match case ctx.builtins.source.bms | ctx.builtins.js.bms | ctx.builtins.wasm.bms | ctx.builtins.debug.bms | ctx.builtins.annotations.bms => return fail: From ae1a97be5725691435ac1413cd4c0dd291529a4e Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 15:34:25 +0800 Subject: [PATCH 46/55] Fix sanity check test cases --- .../test/mlscript/codegen/SanityChecks.mls | 122 ++++++++---------- 1 file changed, 54 insertions(+), 68 deletions(-) diff --git a/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls b/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls index e9447e397e..d5ef1fbb25 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls @@ -1,5 +1,6 @@ :js +// * In this test, we use `id` to wrap functions so that compile-time arity checks get bypassed. :ssjs @@ -20,36 +21,29 @@ f(2, 3) :expect NaN :ssjs :noSanityCheck -:e fun f2(x, y) = x + y -f2(2) -//│ ╔══[ERROR] Expected 2 arguments, got 1 -//│ ║ l.25: f2(2) -//│ ╙── ^^^ +id(f2)(2) //│ JS: -//│ f2 = function f2(x, y) { return x + y }; block$res2 = f2(2); undefined +//│ f2 = function f2(x, y) { +//│ return x + y +//│ }; +//│ tmp = Predef.id(f2); +//│ block$res2 = runtime.safeCall(tmp(2)); +//│ undefined //│ = NaN :ssjs :re -:e -f(2) -//│ ╔══[ERROR] Expected 2 arguments, got 1 -//│ ║ l.36: f(2) -//│ ╙── ^^^ +id(f)(2) //│ JS: -//│ block$res3 = runtime.checkCall(f(2)); undefined +//│ tmp1 = runtime.checkCall(Predef.id(f)); block$res3 = runtime.safeCall(tmp1(2)); undefined //│ ═══[RUNTIME ERROR] Error: Function 'f' expected 2 arguments but got 1 :ssjs :re -:e fun f(x)(y, z) = x + y + z -f(3)(4) -//│ ╔══[ERROR] Expected 2 arguments, got 1 -//│ ║ l.49: f(3)(4) -//│ ╙── ^^^ +id(f)(3)(4) //│ JS: //│ f1 = function f(...args) { //│ runtime.checkArgs("f", 1, true, args.length); @@ -58,13 +52,14 @@ f(3)(4) //│ runtime.checkArgs("", 2, true, args1.length); //│ let y = args1[0]; //│ let z = args1[1]; -//│ let tmp1; -//│ tmp1 = x + y; -//│ return tmp1 + z +//│ let tmp4; +//│ tmp4 = x + y; +//│ return tmp4 + z //│ } //│ }; -//│ tmp = runtime.checkCall(f1(3)); -//│ block$res4 = runtime.safeCall(tmp(4)); +//│ tmp2 = runtime.checkCall(Predef.id(f1)); +//│ tmp3 = runtime.safeCall(tmp2(3)); +//│ block$res4 = runtime.safeCall(tmp3(4)); //│ undefined //│ ═══[RUNTIME ERROR] Error: Function expected 2 arguments but got 1 @@ -97,14 +92,10 @@ f(2) :expect NaN :ssjs -:e :noSanityCheck data class Cls(x, y) with fun f(z, p) = x + y + z + p -Cls(1, 2).f(3) -//│ ╔══[ERROR] Expected 2 arguments, got 1 -//│ ║ l.104: Cls(1, 2).f(3) -//│ ╙── ^^^ +id(Cls(1, 2)).f(3) //│ JS: //│ Cls1 = function Cls(x, y) { //│ return globalThis.Object.freeze(new Cls.class(x, y)); @@ -118,28 +109,25 @@ Cls(1, 2).f(3) //│ this.y = y; //│ } //│ f(z, p) { -//│ let tmp2, tmp3; -//│ tmp2 = this.x + this.y; -//│ tmp3 = tmp2 + z; -//│ return tmp3 + p +//│ let tmp6, tmp7; +//│ tmp6 = this.x + this.y; +//│ tmp7 = tmp6 + z; +//│ return tmp7 + p //│ } //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "Cls", ["x", "y"]]; //│ }); -//│ tmp1 = Cls1(1, 2); -//│ block$res7 = tmp1.f(3); +//│ tmp4 = Cls1(1, 2); +//│ tmp5 = Predef.id(tmp4); +//│ block$res7 = runtime.safeCall(tmp5.f(3)); //│ undefined //│ = NaN :ssjs -:e :re data class Cls(x, y) with fun f(z, p) = x + y + z + p -Cls(1, 2).f(3) -//│ ╔══[ERROR] Expected 2 arguments, got 1 -//│ ║ l.139: Cls(1, 2).f(3) -//│ ╙── ^^^ +id(Cls(1, 2)).f(3) //│ JS: //│ Cls3 = function Cls(...args) { //│ return globalThis.Object.freeze(new Cls.class(...args)); @@ -157,29 +145,26 @@ Cls(1, 2).f(3) //│ runtime.checkArgs("f", 2, true, args.length); //│ let z = args[0]; //│ let p = args[1]; -//│ let tmp3, tmp4; -//│ tmp3 = this.x + this.y; -//│ tmp4 = tmp3 + z; -//│ return tmp4 + p +//│ let tmp8, tmp9; +//│ tmp8 = this.x + this.y; +//│ tmp9 = tmp8 + z; +//│ return tmp9 + p //│ } //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "Cls", ["x", "y"]]; //│ }); -//│ tmp2 = runtime.checkCall(Cls3(1, 2)); -//│ block$res8 = runtime.checkCall(tmp2.f(3)); +//│ tmp6 = runtime.checkCall(Cls3(1, 2)); +//│ tmp7 = runtime.checkCall(Predef.id(tmp6)); +//│ block$res8 = runtime.safeCall(tmp7.f(3)); //│ undefined //│ ═══[RUNTIME ERROR] Error: Function 'f' expected 2 arguments but got 1 :ssjs -:e :re data class Cls(x, y) with fun f(z, p)(q, s) = x + y + z + p + q + s -Cls(1, 2).f(3, 4)(5) -//│ ╔══[ERROR] Expected 2 arguments, got 1 -//│ ║ l.179: Cls(1, 2).f(3, 4)(5) -//│ ╙── ^^^ +id(Cls(1, 2)).f(3, 4)(5) //│ JS: //│ Cls5 = function Cls(...args) { //│ return globalThis.Object.freeze(new Cls.class(...args)); @@ -201,20 +186,21 @@ Cls(1, 2).f(3, 4)(5) //│ runtime.checkArgs("", 2, true, args1.length); //│ let q = args1[0]; //│ let s = args1[1]; -//│ let tmp5, tmp6, tmp7, tmp8; -//│ tmp5 = this.x + this.y; -//│ tmp6 = tmp5 + z; -//│ tmp7 = tmp6 + p; -//│ tmp8 = tmp7 + q; -//│ return tmp8 + s +//│ let tmp11, tmp12, tmp13, tmp14; +//│ tmp11 = this.x + this.y; +//│ tmp12 = tmp11 + z; +//│ tmp13 = tmp12 + p; +//│ tmp14 = tmp13 + q; +//│ return tmp14 + s //│ } //│ } //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "Cls", ["x", "y"]]; //│ }); -//│ tmp3 = runtime.checkCall(Cls5(1, 2)); -//│ tmp4 = tmp3.f(3, 4); -//│ block$res9 = runtime.safeCall(tmp4(5)); +//│ tmp8 = runtime.checkCall(Cls5(1, 2)); +//│ tmp9 = runtime.checkCall(Predef.id(tmp8)); +//│ tmp10 = tmp9.f(3, 4); +//│ block$res9 = runtime.safeCall(tmp10(5)); //│ undefined //│ ═══[RUNTIME ERROR] Error: Function expected 2 arguments but got 1 @@ -295,9 +281,9 @@ if M.A(1).y is //│ toString() { return runtime.render(this); } //│ static [definitionMetadata] = ["class", "M"]; //│ }); -//│ tmp5 = runtime.checkCall(M1.A(1)); -//│ selRes2 = tmp5.y; -//│ discarded2 = tmp5.y$__checkNotMethod; +//│ tmp11 = runtime.checkCall(M1.A(1)); +//│ selRes2 = tmp11.y; +//│ discarded2 = tmp11.y$__checkNotMethod; //│ if (selRes2 === undefined) { //│ throw globalThis.Object.freeze(new globalThis.Error("Access to required field 'y' yielded 'undefined'")) //│ } @@ -319,9 +305,9 @@ M.A(1).y //│ if (selRes3 === undefined) { //│ throw globalThis.Object.freeze(new globalThis.Error("Access to required field 'console' yielded 'undefined'")) //│ } -//│ tmp6 = runtime.checkCall(M1.A(1)); -//│ selRes4 = tmp6.y; -//│ discarded4 = tmp6.y$__checkNotMethod; +//│ tmp12 = runtime.checkCall(M1.A(1)); +//│ selRes4 = tmp12.y; +//│ discarded4 = tmp12.y$__checkNotMethod; //│ if (selRes4 === undefined) { //│ throw globalThis.Object.freeze(new globalThis.Error("Access to required field 'y' yielded 'undefined'")) //│ } @@ -336,7 +322,7 @@ M.A(1).y M.A(1).y console.log() //│ JS: -//│ tmp7 = M1.A(1); block$res15 = runtime.safeCall(globalThis.console.log(tmp7.y)); undefined +//│ tmp13 = M1.A(1); block$res15 = runtime.safeCall(globalThis.console.log(tmp13.y)); undefined //│ > undefined :noSanityCheck @@ -352,15 +338,15 @@ M.A(2).y > 1 :ssjs M.A(1).g(0) //│ JS: -//│ tmp10 = runtime.checkCall(M1.A(1)); block$res18 = runtime.safeCall(tmp10.g(0)); undefined -//│ ═══[RUNTIME ERROR] TypeError: tmp10.g is not a function +//│ tmp16 = runtime.checkCall(M1.A(1)); block$res18 = runtime.safeCall(tmp16.g(0)); undefined +//│ ═══[RUNTIME ERROR] TypeError: tmp16.g is not a function :ssjs M.A(1).f(0) //│ JS: -//│ tmp11 = runtime.checkCall(M1.A(1)); block$res19 = runtime.checkCall(tmp11.f(0)); undefined +//│ tmp17 = runtime.checkCall(M1.A(1)); block$res19 = runtime.checkCall(tmp17.f(0)); undefined //│ = 1 From 51a77b8a8f2272cfb10bec9cc3c875c2a66b7d55 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 15:36:41 +0800 Subject: [PATCH 47/55] Remove unused definition --- hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala | 5 ----- 1 file changed, 5 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index 16da8a590d..961abca790 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -997,11 +997,6 @@ object Apps: case t => S(t, Nil) -object ResolvedOpt: - def unapply(t: Term): S[(Term, Opt[Symbol])] = t match - case r: Resolved => S((r.t, S(r.sym))) - case _ => S((t, N)) - trait BlkImpl: this: Blk => def mkBlkClone(using State): Blk = Blk(stats.map(_.mkClone), res.mkClone) From 55ca3fd1d1336266a9f95f34ecc5d485be8ad326 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 16:14:40 +0800 Subject: [PATCH 48/55] Store `TermSymbol` directly in `BlockMemberSymbol` rather than `TermDefinition` --- .../scala/hkmc2/semantics/Elaborator.scala | 39 ++----------------- .../main/scala/hkmc2/semantics/Symbol.scala | 9 +---- 2 files changed, 6 insertions(+), 42 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index f6039a1a8d..5470af11a2 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -257,21 +257,6 @@ object Elaborator: Nil) cs.defn = S(ClassDef.Parameterized(N, syntax.Cls, cs, BlockMemberSymbol(cs.name, Nil), Nil, ps, Nil, N, ObjBody(Blk(Nil, Term.Lit(UnitLit(false)))), N, Nil)) - ts.defn = S: - TermDefinition( - syntax.Fun, - BlockMemberSymbol(id.name, td :: Nil), - ts, - ps :: Nil, - N, - N, - N, - FlowSymbol("MatchResult-constructor"), - TermDefFlags.empty, - Modulefulness(N)(false), - Nil, - N, - ) cs -> ts val (matchFailureClsSymbol, matchFailureTrmSymbol) = val id = new Ident("MatchFailure") @@ -282,21 +267,6 @@ object Elaborator: val ps = PlainParamList(Param(flag, VarSymbol(Ident("errors")), N, Modulefulness(N)(false)) :: Nil) cs.defn = S(ClassDef.Parameterized(N, syntax.Cls, cs, BlockMemberSymbol(cs.name, td :: Nil), Nil, ps, Nil, N, ObjBody(Blk(Nil, Term.Lit(UnitLit(false)))), N, Nil)) - ts.defn = S: - TermDefinition( - syntax.Fun, - BlockMemberSymbol(id.name, td :: Nil), - ts, - ps :: Nil, - N, - N, - N, - FlowSymbol("MatchFailure-constructor"), - TermDefFlags.empty, - Modulefulness(N)(false), - Nil, - N, - ) cs -> ts val builtinOpsMap = val baseBuiltins = builtins.map: op => @@ -1140,8 +1110,7 @@ extends Importer: Fun, mtdSym, tsym, PlainParamList(Param(FldFlags.empty, valueSym, N, Modulefulness.none) :: Nil) :: Nil, N, N, S(valueSym.ref(Ident("value"))), FlowSymbol(s"‹result of non-local return›"), TermDefFlags.empty, Modulefulness.none, Nil, N) tsym.defn = S(td) - mtdSym.defn = S(td) - mtdSym.tdefn = S(td) + mtdSym.tsym = S(tsym) val htd = HandlerTermDefinition(resumeSym, td) Term.Handle(nonLocalRetHandler, state.nonLocalRetHandlerTrm, Nil, clsSym, htd :: Nil, b) val r = FlowSymbol(s"‹result of ${sym}›") @@ -1160,7 +1129,7 @@ extends Importer: TermDefFlags.empty.copy(isMethod = isMethod), mfn, annotations, N).withLocOf(td) tsym.defn = S(tdf) sym.defn = S(tdf) - sym.tdefn = S(tdf) + sym.tsym = S(tsym) tdf go(sts, Nil, tdf :: acc) @@ -1247,7 +1216,7 @@ extends Importer: assert(p.fldSym.isEmpty) p.fldSym = S(fsym) fsym.defn = S(fdef) - fsym.tdefn = S(fdef) + fsym.tsym = S(tsym) tsym.defn = S(fdef) fdef :: Nil else @@ -1395,7 +1364,7 @@ extends Importer: S(clsSym), ) ctsym.defn = S(ctdef) - sym.tdefn = S(ctdef) + sym.tsym = S(ctsym) cd sym.defn = S(defn) go(sts, Nil, defn :: acc) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 5b977cc5f2..05fd4b09c9 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -74,9 +74,7 @@ abstract class Symbol(using State) extends Located: // * So, the symbol is from the `TermDefinition`. def asTrm: Opt[TermSymbol] = this match case trm: TermSymbol => S(trm) - case mem: BlockMemberSymbol => mem.tdefn match - case S(defn: TermDefinition) => S(defn.tsym) - case N => N + case mem: BlockMemberSymbol => mem.tsym case _ => N def asPat: Opt[PatternSymbol] = this match case pat: PatternSymbol => S(pat) @@ -204,10 +202,7 @@ class BlockMemberSymbol(val nme: Str, val trees: Ls[TypeOrTermDef], val nameIsMe extends MemberSymbol[Definition]: // * This is a hack for that `TermDef` currently doesn't have a symbol. - // * So, the symbol is from the `TermDefinition`. - // * To prevent the `TermDefinition` from being overridden by other definitions, - // * we use a special field here. - var tdefn: Opt[TermDefinition] = N + var tsym: Opt[TermSymbol] = N def toLoc: Option[Loc] = Loc(trees) From d81d0e64aab9b305fdbefd7e88885cbcabf0c702 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 16:14:51 +0800 Subject: [PATCH 49/55] =?UTF-8?q?Fix=20"Worst=20part=20of=20the=20PR=20?= =?UTF-8?q?=F0=9F=91=8E=E2=80=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index 253c219f41..a54d543674 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -1133,7 +1133,7 @@ trait LoweringSelSanityChecks(using Config, TL, Raise, State) extends Lowering: private val instrument: Bool = config.sanityChecks.isDefined - + override def setupSelection(prefix: st, nme: Tree.Ident, disamb: Opt[DefinitionSymbol[?]])(k: Result => Block)(using Subst): Block = if !instrument then return super.setupSelection(prefix, nme, disamb)(k) subTerm(prefix): p => From f527f3d11e275cee73dade701f11c49f61d386be Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Sat, 8 Nov 2025 16:27:04 +0800 Subject: [PATCH 50/55] Refine TODO comments in resolver --- hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 3805a8e55d..65adaf4c8b 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -897,9 +897,8 @@ class Resolver(tl: TraceLogger) log(s"Resolved symbol for ${t}: ${bms}") case N => // TODO @Harry: Appropriately resolve all selections on classes. - // The type annotations in the current code bases are largely incomplete, - // so many selections on classes cannot be resolved properly. - // We will refactor this later... + // - MLscript programs selecting JS members without properly defining them. + // - Inherited members. case defn => log(s"Unsupported selection from definition: ${defn}") From 58de90d8d01e389cf25ddeab666d95908e8f4268 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Wed, 12 Nov 2025 02:16:40 +0800 Subject: [PATCH 51/55] Prelinminarily remove `defn` from BMS --- .../src/main/scala/hkmc2/codegen/Block.scala | 7 +- .../main/scala/hkmc2/codegen/Lowering.scala | 2 +- .../scala/hkmc2/codegen/llir/Builder.scala | 29 +++-- .../scala/hkmc2/semantics/Elaborator.scala | 7 +- .../main/scala/hkmc2/semantics/Resolver.scala | 22 ++-- .../main/scala/hkmc2/semantics/Symbol.scala | 29 ++++- .../src/main/scala/hkmc2/semantics/Term.scala | 121 ++++++++++-------- .../hkmc2/semantics/ucs/Normalization.scala | 12 +- .../src/test/mlscript-compile/Predef.mjs | 4 +- .../src/test/mlscript-compile/Runtime.mjs | 20 +-- .../test/mlscript/basics/BadTypeClasses.mls | 4 +- .../src/test/mlscript/codegen/Throw.mls | 6 +- .../test/mlscript/ctx/SymbolResolution.mls | 62 +++++---- .../src/test/mlscript/ctx/TypeResolution.mls | 8 +- .../src/test/mlscript/decls/Prelude.mls | 33 ++++- 15 files changed, 233 insertions(+), 133 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala index 586f9e318d..2d4c7d40c7 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala @@ -532,8 +532,13 @@ sealed abstract class Result extends AutoLocated: case Record(mut, args) => args.flatMap(arg => arg.idx.fold(Set.empty)(_.freeVarsLLIR) ++ arg.value.freeVarsLLIR).toSet case Value.Ref(l: (BuiltinSymbol | TopLevelSymbol | ClassSymbol | TermSymbol), disamb) => Set.empty - case Value.Ref(l: MemberSymbol[?], disamb) => l.defn match + case Value.Ref(l: BlockMemberSymbol, S(disamb)) => disamb.defn match case Some(d: ClassLikeDef) => Set.empty + case Some(d: TermDefinition) if d.companionClass.isDefined => Set.empty + case _ => Set(l) + case Value.Ref(l: DefinitionSymbol[?], N) => l.defn match + case Some(d: ClassLikeDef) => Set.empty + case Some(d: TermDefinition) if d.companionClass.isDefined => Set.empty case _ => Set(l) case Value.Ref(l, disamb) => Set(l) case Value.This(sym) => Set.empty diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index 21a12f6f1e..739e9765f4 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -383,7 +383,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): assert(paramLists.length === 1) return k(Lambda(paramLists.head, bodyBlock).withLocOf(ref)) case bs: BlockMemberSymbol => - disamb.flatMap(_.defn) orElse bs.defn match + disamb.flatMap(_.defn) match case S(_) if bs.asCls.exists(_ is ctx.builtins.Int31) => return term(Sel(State.runtimeSymbol.ref().resolve, ref.tree)(S(bs), N).withLocOf(ref).resolve)(k) case S(d) if d.hasDeclareModifier.isDefined => diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala index c6528761dc..1b71932de8 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala @@ -222,8 +222,7 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): given Ctx = ctx.setClass(isym) val funcs = methods.map(bMethodDef) def parentFromPath(p: Path): Ls[Local] = p match - case Value.Ref(l, _) => fromMemToClass(l) :: Nil - case Select(Value.Ref(l, _), Tree.Ident("class")) => fromMemToClass(l) :: Nil + case Value.Ref(l, disamb) => fromMemToClass(l.orElseDisamb(disamb)) :: Nil case _ => bErrStop(msg"Unsupported parent path ${p.toString()}") ClassInfo( uid.make, @@ -279,9 +278,9 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): v match case Value.Ref(l: TermSymbol, _) if l.owner.nonEmpty => k(l |> sr) - case Value.Ref(sym, _) if sym.nme.isCapitalized => + case Value.Ref(sym, disamb) if sym.nme.isCapitalized => val v: Local = newTemp - Node.LetExpr(v, Expr.CtorApp(fromMemToClass(sym), Ls()), k(v |> sr)) + Node.LetExpr(v, Expr.CtorApp(fromMemToClass(sym.orElseDisamb(disamb)), Ls()), k(v |> sr)) case Value.Ref(l, _) => ctx.fn_ctx.get(l) match case Some(f) => @@ -311,8 +310,11 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): private def fromMemToClass(m: Symbol)(using ctx: Ctx)(using Raise, Scope): DefinitionSymbol[? <: ClassLikeDef] = trace[DefinitionSymbol[? <: ClassLikeDef]](s"bFromMemToClass $m", x => s"bFromMemToClass end: $x"): m match - case ms: MemberSymbol[?] => + case ms: DefinitionSymbol[?] => ms.defn match + case Some(d: TermDefinition) => + val companion = d.companionClass.getOrElse(bErrStop(msg"Term definition without companion ${d.toString}")) + fromMemToClass(companion) case Some(d: ClassLikeDef) => d.sym.asClsLike.getOrElse(bErrStop(msg"Class definition without symbol")) case Some(value) => bErrStop(msg"Member symbol without class definition ${value.toString}") case None => bErrStop(msg"Member symbol without definition ${ms.toString}") @@ -371,11 +373,20 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case args: Ls[TrivialExpr] => val v: Local = newTemp Node.LetExpr(v, Expr.BasicOp(sym, args), k(v |> sr)) - case Call(Value.Ref(sym: MemberSymbol[?], _), args) if sym.defn.exists(defn => defn match + case Call(Value.Ref(sym, S(disamb)), args) if disamb.defn.exists(defn => defn match case cls: ClassLikeDef => true + case trm: TermDefinition => trm.companionClass.isDefined + case _ => false + ) => + bArgs(args): + case args: Ls[TrivialExpr] => + val v: Local = newTemp + Node.LetExpr(v, Expr.CtorApp(fromMemToClass(disamb), args), k(v |> sr)) + case Call(Value.Ref(sym: DefinitionSymbol[?], _), args) if sym.defn.exists(defn => defn match + case cls: ClassLikeDef => true + case trm: TermDefinition => trm.companionClass.isDefined case _ => false ) => - log(s"xxx $sym is ${sym.getClass()}") bArgs(args): case args: Ls[TrivialExpr] => val v: Local = newTemp @@ -419,11 +430,11 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): case Call(_, _) => bErrStop(msg"Unsupported kind of Call ${r.toString()}") case Instantiate( false, - Value.Ref(sym, S(_: (ClassSymbol | ModuleOrObjectSymbol))), args) => + Value.Ref(sym, S(disamb: (ClassSymbol | ModuleOrObjectSymbol))), args) => bArgs(args): case args: Ls[TrivialExpr] => val v: Local = newTemp - Node.LetExpr(v, Expr.CtorApp(fromMemToClass(sym), args), k(v |> sr)) + Node.LetExpr(v, Expr.CtorApp(fromMemToClass(disamb), args), k(v |> sr)) case Instantiate(_, cls, args) => bErrStop(msg"Unsupported kind of Instantiate") case lam @ Lambda(params, body) => bLam(lam, N, N)(k) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index 965b545fa0..0146889e40 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -1126,7 +1126,6 @@ extends Importer with ucs.SplitElaborator: val tdf = TermDefinition(k, sym, tsym, pss, tps, s, body, r, TermDefFlags.empty.copy(isMethod = isMethod), mfn, annotations, N).withLocOf(td) tsym.defn = S(tdf) - sym.defn = S(tdf) sym.tsym = S(tsym) tdf @@ -1213,7 +1212,6 @@ extends Importer with ucs.SplitElaborator: ).withLocOf(p) assert(p.fldSym.isEmpty) p.fldSym = S(fsym) - fsym.defn = S(fdef) fsym.tsym = S(tsym) tsym.defn = S(fdef) fdef :: Nil @@ -1364,7 +1362,6 @@ extends Importer with ucs.SplitElaborator: ctsym.defn = S(ctdef) sym.tsym = S(ctsym) cd - sym.defn = S(defn) go(sts, Nil, defn :: acc) case Annotated(annotation, target) :: sts => go(target :: sts, annotations ++ annot(annotation), acc) @@ -1600,7 +1597,9 @@ extends Importer with ucs.SplitElaborator: case p @ Pun(false, _) :: Nil => record(p) case p @ InfixApp(_: Ident, Keywrd(Keyword.`:`), _) :: Nil => record(p) case lhs :: Nil => arrow(lhs, rhs) - case _ :: _ | Nil => ??? // TODO: When is this case reached? + // TODO: When is this case reached? + // * Answer: pattern p = () => Unit + case _ :: _ | Nil => ??? case p as q => q match // `p as id` is elaborated into alias if `id` is not a constructor. case id: Ident => ident(id) match diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 7ae97c8692..1517c96964 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -139,6 +139,8 @@ object Resolver: case Expect.Module(msg) => msg.toList.map(_ -> N) case Expect.NonModule(msg) => msg.toList.map(_ -> N) case Expect.Class(msg) => msg.toList.map(_ -> N) + case Expect.Selectable(msg) => msg.toList.map(_ -> N) + case Expect.PatternConstructor(msg) => msg.toList.map(_ -> N) case Expect.Any => Nil def `module` = isInstanceOf[Module] @@ -146,10 +148,12 @@ object Resolver: def nonModule = isInstanceOf[NonModule] override def toString: Str = this match - case _: Module => "Module" - case _: NonModule => "NonModule" - case _: Class => "Class" - case _: Any => "Any" + case _: Expect.Module => "Module" + case _: Expect.NonModule => "NonModule" + case _: Expect.Class => "Class" + case _: Expect.Selectable => "Selectable" + case _: Expect.PatternConstructor => "PatternConstructor" + case Expect.Any => "Any" object Expect: def fromModulefulness(mf: Modulefulness): Expect = @@ -784,7 +788,7 @@ class Resolver(tl: TraceLogger) // If it is expecting a class or module specifically, cast the symbol. case _: Module => bms.asMod case _: Class => bms.asCls - case _: Selectable => bms.asModOrObj + case _: Selectable => bms.asModOrObj orElse bms.asTrm // If it is expecting a generic symbol, use asPrinciple for the "default interpretation". case _: (Any.type | NonModule) if sign => bms.asTpe @@ -841,7 +845,7 @@ class Resolver(tl: TraceLogger) case _ if t.symbol.exists(_.isInstanceOf[ErrorSymbol]) => () case t @ Term.Ref(bsym: BlockMemberSymbol) => - log(s"Resolving symbol for reference ${t} (bsym = ${bsym}, defn = ${bsym.defn})") + log(s"Resolving symbol for reference ${t} (bsym = ${bsym})") val sym = disambSym(prefer, sign = sign)(bsym) sym.foreach: sym => t.expand(S((t.duplicate.resolved(sym)))) @@ -930,7 +934,7 @@ class Resolver(tl: TraceLogger) def disambSym(bms: BlockMemberSymbol): Opt[FieldSymbol] = prefer match case _: Module => bms.asMod case _: Class => bms.asCls - case _: Selectable => bms.asModOrObj + case _: Selectable => bms.asModOrObj orElse bms.asTrm case _: (Any.type | NonModule) => bms.asPrincipal t match @@ -946,7 +950,7 @@ class Resolver(tl: TraceLogger) val decl = base.resolvedSym match case S(bms: BlockMemberSymbol) => val disambBms = disambSym(bms) - log(s"Disambiguate ${bms} into ${disambBms} (defn = ${disambBms.map(_.defn)})") + log(s"Disambiguate ${bms} (${bms.asTrm}) into ${disambBms} (defn = ${disambBms.map(_.defn)}), preferring ${prefer}") disambBms match case S(disambBms) => disambBms.defn case N => bms.asPrincipal.flatMap(_.defn) @@ -1096,7 +1100,7 @@ class Resolver(tl: TraceLogger) def resolveSign(t: Term, expect: Expect): Type = def raiseError(sym: Opt[Symbol] = N) = val defnMsg = sym match - case S(sym: FieldSymbol) => sym.defn match + case S(sym: DefinitionSymbol[?]) => sym.defn match case S(defn: TermDefinition) => s" denoting ${defn.k.desc} '${defn.sym.nme}'" case S(defn: ClassLikeDef) => s" denoting ${defn.kind.desc} '${defn.sym.nme}'" case _ => "" diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 05fd4b09c9..c0fdb0945b 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -115,6 +115,16 @@ abstract class Symbol(using State) extends Located: asPat orElse asMod + def orElseDisamb(disamb: Opt[DefinitionSymbol[?]]): Symbol = (this, disamb) match + case (bms: BlockMemberSymbol, S(disamb)) => + disamb + case (bms: BlockMemberSymbol, N) => + lastWords(s"Cannot disambiguate overloaded member symbol ${bms.nme}: no disambiguation provided") + case (sym, N) => + sym + case (sym, S(_)) => + lastWords(s"Cannot disambiguate non-BlockMember symbol ${sym.nme}: disambiguation provided") + override def equals(x: Any): Bool = x match case that: Symbol => uid === that.uid case _ => false @@ -201,6 +211,9 @@ class BuiltinSymbol class BlockMemberSymbol(val nme: Str, val trees: Ls[TypeOrTermDef], val nameIsMeaningful: Bool = true)(using State) extends MemberSymbol[Definition]: + def defn: Option[Definition] = ??? + def defn_=(d: Option[Definition]): Unit = ??? + // * This is a hack for that `TermDef` currently doesn't have a symbol. var tsym: Opt[TermSymbol] = N @@ -239,7 +252,10 @@ end BlockMemberSymbol sealed abstract class MemberSymbol[Defn <: Definition](using State) extends Symbol: def nme: Str - var defn: Opt[Defn] = N + + def defn: Opt[Defn] + def defn_=(d: Opt[Defn]): Unit + def subst(using SymbolSubst): MemberSymbol[Defn] @@ -250,6 +266,9 @@ class TermSymbol(val k: TermDefKind, val owner: Opt[InnerSymbol], val id: Tree.I with NamedSymbol: def nme: Str = id.name def name: Str = nme + + var defn: Opt[TermDefinition] = N + def toLoc: Option[Loc] = id.toLoc override def toString: Str = s"term:${owner.map(o => s"${o}.").getOrElse("")}${id.name}${State.dbgUid(uid)}" @@ -287,6 +306,7 @@ type FieldSymbol = MemberSymbol[?] * same error from throwing multiple times. */ case class ErrorSymbol(val nme: Str, tree: Tree)(using State) extends MemberSymbol[Nothing]: + var defn: Opt[Nothing] = N override def toLoc: Option[Loc] = tree.toLoc @@ -341,6 +361,9 @@ class ClassSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using State) with DefinitionSymbol[ClassDef] with InnerSymbol with NamedSymbol: + + var defn: Opt[ClassDef] = N + def name: Str = nme def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of classe here @@ -357,6 +380,7 @@ class ModuleOrObjectSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using Sta with DefinitionSymbol[ModuleOrObjectDef] with InnerSymbol with NamedSymbol: + var defn: Opt[ModuleOrObjectDef] = N def name: Str = nme def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of module here @@ -369,6 +393,7 @@ class ModuleOrObjectSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using Sta class TypeAliasSymbol(val id: Tree.Ident)(using State) extends MemberSymbol[TypeDef] with DefinitionSymbol[TypeDef]: + var defn: Opt[TypeDef] = N def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of type alias here override def toString: Str = s"type:${id.name}${State.dbgUid(uid)}" @@ -380,6 +405,7 @@ class PatternSymbol(val id: Tree.Ident, val params: Opt[Tree.Tup], val body: Tre with CtorSymbol with DefinitionSymbol[PatternDef] with InnerSymbol: + var defn: Opt[PatternDef] = N def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of pattern here override def toString: Str = s"pattern:${id.name}" @@ -390,6 +416,7 @@ class TopLevelSymbol(blockNme: Str)(using State) extends MemberSymbol[ModuleOrObjectDef] with DefinitionSymbol[ModuleOrObjectDef] with InnerSymbol: + var defn: Opt[ModuleOrObjectDef] = N def nme = blockNme def toLoc: Option[Loc] = N override def toString: Str = s"globalThis:$blockNme${State.dbgUid(uid)}" diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index ab462b5e46..d0360835ee 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -137,6 +137,7 @@ sealed trait ResolvableImpl: def hasExpansion = expansion.isDefined def defn: Opt[Definition] = resolvedSym match + case S(sym: BlockMemberSymbol) => N case S(sym: MemberSymbol[?]) => sym.defn case _ => N @@ -311,61 +312,67 @@ enum Term extends Statement: App(this, Tup(args.toList.map(PlainFld(_)))(Tree.DummyTup)) (Tree.App(Tree.Dummy, Tree.Dummy), N, FlowSymbol("")) - override def mkClone(using State): Term = this match - case Error => Error - case UnitVal() => UnitVal() - case Missing => Missing - case Lit(Tree.StrLit(value)) => Lit(Tree.StrLit(value)) - case Lit(Tree.IntLit(value)) => Lit(Tree.IntLit(value)) - case Lit(Tree.DecLit(value)) => Lit(Tree.DecLit(value)) - case Lit(Tree.BoolLit(value)) => Lit(Tree.BoolLit(value)) - case Lit(Tree.UnitLit(value)) => Lit(Tree.UnitLit(value)) - case term @ Resolved(t, sym) => Resolved(t.mkClone, sym)(term.typ) - case term @ Ref(sym) => Ref(sym)(Tree.Ident(term.tree.name), term.refNum, term.typ) - case term @ Sel(prefix, nme) => Sel(prefix.mkClone, Tree.Ident(nme.name))(term.sym, term.typ) - case term @ App(lhs, rhs) => App(lhs.mkClone, rhs.mkClone)(term.tree, term.typ, term.resSym) - case term @ TyApp(lhs, targs) => TyApp(lhs.mkClone, targs.map(_.mkClone))(term.typ) - case term @ SynthSel(prefix, nme) => SynthSel(prefix.mkClone, Tree.Ident(nme.name))(term.sym, term.typ) - case DynSel(prefix, fld, arrayIdx) => DynSel(prefix.mkClone, fld.mkClone, arrayIdx) - case term @ Tup(fields) => Tup(fields.map { - case f: Fld => f.copy(term = f.term.mkClone, asc = f.asc.map(_.mkClone)) - case s: Spd => s.copy(term = s.term.mkClone) - })(term.tree) - case Mut(underlying) => Mut(underlying.mkClone.asInstanceOf[Tup | Rcd | New | DynNew]) - case term @ CtxTup(fields) => CtxTup(fields.map { - case f: Fld => f.copy(term = f.term.mkClone, asc = f.asc.map(_.mkClone)) - case s: Spd => s.copy(term = s.term.mkClone) - })(term.tree) - case IfLike(kw, split) => IfLike(kw, split) - case SynthIf(split) => SynthIf(split.mkClone) - case Lam(params, body) => Lam(params, body.mkClone) - case FunTy(lhs, rhs, eff) => FunTy(lhs.mkClone, rhs.mkClone, eff.map(_.mkClone)) - case Forall(tvs, outer, body) => Forall(tvs, outer, body.mkClone) - case WildcardTy(in, out) => WildcardTy(in.map(_.mkClone), out.map(_.mkClone)) - case blk: Blk => blk.mkBlkClone - case Rcd(mut, stats) => Rcd(mut, stats.map(_.mkClone)) - case Quoted(body) => Quoted(body.mkClone) - case Unquoted(body) => Unquoted(body.mkClone) - case term @ New(cls, args, rft) => - New(cls.mkClone, args.map(_.mkClone), rft.map { case (cs, ob) => cs -> ObjBody(ob.blk.mkBlkClone) })(term.typ) - case DynNew(cls, args) => DynNew(cls.mkClone, args.map(_.mkClone)) - case term @ SelProj(prefix, cls, proj) => - SelProj(prefix.mkClone, cls.mkClone, Tree.Ident(proj.name))(term.sym, term.typ) - case Asc(term, ty) => Asc(term.mkClone, ty.mkClone) - case CompType(lhs, rhs, pol) => CompType(lhs.mkClone, rhs.mkClone, pol) - case Neg(rhs) => Neg(rhs.mkClone) - case Region(name, body) => Region(name, body.mkClone) - case RegRef(reg, value) => RegRef(reg.mkClone, value.mkClone) - case Assgn(lhs, rhs) => Assgn(lhs.mkClone, rhs.mkClone) - case Drop(trm) => Drop(trm.mkClone) - case Deref(ref) => Deref(ref.mkClone) - case SetRef(ref, value) => SetRef(ref.mkClone, value.mkClone) - case Ret(result) => Ret(result.mkClone) - case Throw(result) => Throw(result.mkClone) - case Try(body, finallyDo) => Try(body.mkClone, finallyDo.mkClone) - case Annotated(annot, target) => Annotated(annot, target.mkClone) - case Handle(lhs, rhs, args, derivedClsSym, defs, body) => - Handle(lhs, rhs.mkClone, args.map(_.mkClone), derivedClsSym, defs, body.mkClone) + override def mkClone(using State): Term = + val that = this match + case Error => Error + case UnitVal() => UnitVal() + case Missing => Missing + case Lit(Tree.StrLit(value)) => Lit(Tree.StrLit(value)) + case Lit(Tree.IntLit(value)) => Lit(Tree.IntLit(value)) + case Lit(Tree.DecLit(value)) => Lit(Tree.DecLit(value)) + case Lit(Tree.BoolLit(value)) => Lit(Tree.BoolLit(value)) + case Lit(Tree.UnitLit(value)) => Lit(Tree.UnitLit(value)) + case term @ Resolved(t, sym) => Resolved(t.mkClone, sym)(term.typ) + case term @ Ref(sym) => Ref(sym)(Tree.Ident(term.tree.name), term.refNum, term.typ) + case term @ Sel(prefix, nme) => Sel(prefix.mkClone, Tree.Ident(nme.name))(term.sym, term.typ) + case term @ App(lhs, rhs) => App(lhs.mkClone, rhs.mkClone)(term.tree, term.typ, term.resSym) + case term @ TyApp(lhs, targs) => TyApp(lhs.mkClone, targs.map(_.mkClone))(term.typ) + case term @ SynthSel(prefix, nme) => SynthSel(prefix.mkClone, Tree.Ident(nme.name))(term.sym, term.typ) + case DynSel(prefix, fld, arrayIdx) => DynSel(prefix.mkClone, fld.mkClone, arrayIdx) + case term @ Tup(fields) => Tup(fields.map { + case f: Fld => f.copy(term = f.term.mkClone, asc = f.asc.map(_.mkClone)) + case s: Spd => s.copy(term = s.term.mkClone) + })(term.tree) + case Mut(underlying) => Mut(underlying.mkClone.asInstanceOf[Tup | Rcd | New | DynNew]) + case term @ CtxTup(fields) => CtxTup(fields.map { + case f: Fld => f.copy(term = f.term.mkClone, asc = f.asc.map(_.mkClone)) + case s: Spd => s.copy(term = s.term.mkClone) + })(term.tree) + case IfLike(kw, split) => IfLike(kw, split) + case SynthIf(split) => SynthIf(split.mkClone) + case Lam(params, body) => Lam(params, body.mkClone) + case FunTy(lhs, rhs, eff) => FunTy(lhs.mkClone, rhs.mkClone, eff.map(_.mkClone)) + case Forall(tvs, outer, body) => Forall(tvs, outer, body.mkClone) + case WildcardTy(in, out) => WildcardTy(in.map(_.mkClone), out.map(_.mkClone)) + case blk: Blk => blk.mkBlkClone + case Rcd(mut, stats) => Rcd(mut, stats.map(_.mkClone)) + case Quoted(body) => Quoted(body.mkClone) + case Unquoted(body) => Unquoted(body.mkClone) + case term @ New(cls, args, rft) => + New(cls.mkClone, args.map(_.mkClone), rft.map { case (cs, ob) => cs -> ObjBody(ob.blk.mkBlkClone) })(term.typ) + case DynNew(cls, args) => DynNew(cls.mkClone, args.map(_.mkClone)) + case term @ SelProj(prefix, cls, proj) => + SelProj(prefix.mkClone, cls.mkClone, Tree.Ident(proj.name))(term.sym, term.typ) + case Asc(term, ty) => Asc(term.mkClone, ty.mkClone) + case CompType(lhs, rhs, pol) => CompType(lhs.mkClone, rhs.mkClone, pol) + case Neg(rhs) => Neg(rhs.mkClone) + case Region(name, body) => Region(name, body.mkClone) + case RegRef(reg, value) => RegRef(reg.mkClone, value.mkClone) + case Assgn(lhs, rhs) => Assgn(lhs.mkClone, rhs.mkClone) + case Drop(trm) => Drop(trm.mkClone) + case Deref(ref) => Deref(ref.mkClone) + case SetRef(ref, value) => SetRef(ref.mkClone, value.mkClone) + case Ret(result) => Ret(result.mkClone) + case Throw(result) => Throw(result.mkClone) + case Try(body, finallyDo) => Try(body.mkClone, finallyDo.mkClone) + case Annotated(annot, target) => Annotated(annot, target.mkClone) + case Handle(lhs, rhs, args, derivedClsSym, defs, body) => + Handle(lhs, rhs.mkClone, args.map(_.mkClone), derivedClsSym, defs, body.mkClone) + (this, that) match + case (self: Resolvable, that: Resolvable) if self.expansion.isDefined => + that.expand(self.expansion.get.map(_.mkClone)) + case _ => + that end Term @@ -683,6 +690,10 @@ final case class TermDefinition( def extraAnnotations: Ls[Annot] = annotations.filter: case Annot.Modifier(Keyword.`declare` | Keyword.`abstract`) => false case _ => true + + def companionClass: Opt[ClassSymbol] = companion match + case S(sym: ClassSymbol) if sym.defn.isDefined => S(sym) + case _ => N final case class HandlerTermDefinition( resumeSym: VarSymbol, diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala index 36e3ca01b2..f330177289 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala @@ -262,14 +262,6 @@ class Normalization(lowering: Lowering)(using tl: TL)(using Raise, Ctx, State) e val (cse, blk) = mkArgs(args) (cse, Assign(arg, Select(sr, new Tree.Ident(param.id.name).withLocOf(arg))(S(param)), blk)) mkMatch(mkArgs(clsParams.iterator.zip(args).toList)) - // Select the constructor's `.class` field. - lazy val ctorTerm = ctor.symbol match - // case S(mem: BlockMemberSymbol) => - // // If the class is declaration-only, we do not need to - // // select the class. - // if !mem.hasLiftedClass || mem.defn.exists(_.hasDeclareModifier.isDefined) then ctor - // else Term.SynthSel(ctor, Tree.Ident("class"))(mem.clsTree.orElse(mem.modOrObjTree).map(_.symbol), N).resolve - case _ => ctor symbol match case cls: ClassSymbol if ctx.builtins.virtualClasses contains cls => // [invariant:0] Some classes (e.g., `Int`) from `Prelude` do @@ -280,9 +272,9 @@ class Normalization(lowering: Lowering)(using tl: TL)(using Raise, Ctx, State) e // and use it `Predef.unreachable` here. k(cls, Nil)(unreachableFn) case cls: ClassSymbol => - subTerm_nonTail(ctorTerm)(k(cls, cls.tree.clsParams)) + subTerm_nonTail(ctor)(k(cls, cls.tree.clsParams)) case mod: ModuleOrObjectSymbol => - subTerm_nonTail(ctorTerm)(k(mod, Nil)) + subTerm_nonTail(ctor)(k(mod, Nil)) case FlatPattern.Tuple(len, inf) => mkMatch(Case.Tup(len, inf) -> lowerSplit(tail, cont, topLevel = false)) case FlatPattern.Record(entries) => val objectSym = ctx.builtins.Object diff --git a/hkmc2/shared/src/test/mlscript-compile/Predef.mjs b/hkmc2/shared/src/test/mlscript-compile/Predef.mjs index a4ce900a78..1c4f30daa5 100644 --- a/hkmc2/shared/src/test/mlscript-compile/Predef.mjs +++ b/hkmc2/shared/src/test/mlscript-compile/Predef.mjs @@ -114,10 +114,10 @@ globalThis.Object.freeze(class Predef { static notImplemented(msg) { let tmp; tmp = "Not implemented: " + msg; - throw globalThis.Error(tmp) + throw runtime.safeCall(globalThis.Error(tmp)) } static get notImplementedError() { - throw globalThis.Error("Not implemented"); + throw runtime.safeCall(globalThis.Error("Not implemented")); } static tuple(...xs) { return xs diff --git a/hkmc2/shared/src/test/mlscript-compile/Runtime.mjs b/hkmc2/shared/src/test/mlscript-compile/Runtime.mjs index d5cc8a4258..f411500de9 100644 --- a/hkmc2/shared/src/test/mlscript-compile/Runtime.mjs +++ b/hkmc2/shared/src/test/mlscript-compile/Runtime.mjs @@ -143,14 +143,14 @@ globalThis.Object.freeze(class Runtime { let scrut, scrut1, tmp, tmp1, tmp2; scrut = i >= xs.length; if (scrut === true) { - throw globalThis.RangeError("Tuple.get: index out of bounds") + throw runtime.safeCall(globalThis.RangeError("Tuple.get: index out of bounds")) } else { tmp = runtime.Unit; } tmp1 = - xs.length; scrut1 = i < tmp1; if (scrut1 === true) { - throw globalThis.RangeError("Tuple.get: negative index out of bounds") + throw runtime.safeCall(globalThis.RangeError("Tuple.get: negative index out of bounds")) } else { tmp2 = runtime.Unit; } @@ -176,7 +176,7 @@ globalThis.Object.freeze(class Runtime { let scrut; scrut = i >= string.length; if (scrut === true) { - throw globalThis.RangeError("Str.get: index out of bounds") + throw runtime.safeCall(globalThis.RangeError("Str.get: index out of bounds")) } else { return runtime.safeCall(string.at(i)) } @@ -424,7 +424,7 @@ globalThis.Object.freeze(class Runtime { }); } static get unreachable() { - throw globalThis.Error("unreachable"); + throw runtime.safeCall(globalThis.Error("unreachable")); } static checkArgs(functionName, expected, isUB, got) { let scrut, name, scrut1, scrut2, tmp, lambda, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12; @@ -465,7 +465,7 @@ globalThis.Object.freeze(class Runtime { tmp10 = tmp8 + tmp9; tmp11 = tmp10 + " but got "; tmp12 = tmp11 + got; - throw globalThis.Error(tmp12) + throw runtime.safeCall(globalThis.Error(tmp12)) } else { return runtime.Unit } @@ -479,7 +479,7 @@ globalThis.Object.freeze(class Runtime { } static checkCall(x) { if (x === undefined) { - throw globalThis.Error("MLscript call unexpectedly returned `undefined`, the forbidden value.") + throw runtime.safeCall(globalThis.Error("MLscript call unexpectedly returned `undefined`, the forbidden value.")) } else { return x } @@ -490,7 +490,7 @@ globalThis.Object.freeze(class Runtime { tmp1 = tmp + "' of class '"; tmp2 = tmp1 + clsName; tmp3 = tmp2 + "' was accessed without being called."; - throw globalThis.Error(tmp3) + throw runtime.safeCall(globalThis.Error(tmp3)) } static try(f) { let res; @@ -657,7 +657,7 @@ globalThis.Object.freeze(class Runtime { reps = tmp2; scrut1 = reps > 10; if (scrut1 === true) { - throw globalThis.Error("10 repeated continuation frame (loop?)") + throw runtime.safeCall(globalThis.Error("10 repeated continuation frame (loop?)")) } else { tmp3 = runtime.Unit; } @@ -702,7 +702,7 @@ globalThis.Object.freeze(class Runtime { reps = tmp1; scrut1 = reps > 10; if (scrut1 === true) { - throw globalThis.Error("10 repeated continuation frame (loop?)") + throw runtime.safeCall(globalThis.Error("10 repeated continuation frame (loop?)")) } else { tmp2 = runtime.Unit; } @@ -912,7 +912,7 @@ globalThis.Object.freeze(class Runtime { let scrut, tmp, tmp1; scrut = contTrace.resumed; if (scrut === true) { - throw globalThis.Error("Multiple resumption") + throw runtime.safeCall(globalThis.Error("Multiple resumption")) } else { tmp = runtime.Unit; } diff --git a/hkmc2/shared/src/test/mlscript/basics/BadTypeClasses.mls b/hkmc2/shared/src/test/mlscript/basics/BadTypeClasses.mls index 5f2d5281d1..f1a37c14b9 100644 --- a/hkmc2/shared/src/test/mlscript/basics/BadTypeClasses.mls +++ b/hkmc2/shared/src/test/mlscript/basics/BadTypeClasses.mls @@ -28,11 +28,11 @@ val someInt = 42 :e using someInt = 42 -//│ ╔══[ERROR] Expected a non-module type; found reference denoting value 'someInt'. +//│ ╔══[ERROR] Expected a non-module type; found reference. //│ ║ l.30: using someInt = 42 //│ ║ ^^^^^^^ //│ ╙── Implicit instance must be marked as returning a 'module' in order to have a module return type. -//│ ╔══[ERROR] Expected a type, got reference denoting value 'someInt' +//│ ╔══[ERROR] Expected a type, got reference //│ ║ l.30: using someInt = 42 //│ ╙── ^^^^^^^ diff --git a/hkmc2/shared/src/test/mlscript/codegen/Throw.mls b/hkmc2/shared/src/test/mlscript/codegen/Throw.mls index 4ef0cd898a..56ae1bfd85 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/Throw.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/Throw.mls @@ -31,7 +31,7 @@ fun f(x) = return y f(1) //│ JS (unsanitized): -//│ let f2; f2 = function f(x) { throw globalThis.Error("e") }; f2(1) +//│ let f2; f2 = function f(x) { throw runtime.safeCall(globalThis.Error("e")) }; f2(1) //│ ═══[RUNTIME ERROR] Error: e @@ -43,7 +43,9 @@ f(false) //│ JS (unsanitized): //│ let f3; //│ f3 = function f(x) { -//│ if (x === true) { throw globalThis.Error("x") } else { throw globalThis.Error("y") } +//│ if (x === true) { +//│ throw runtime.safeCall(globalThis.Error("x")) +//│ } else { throw runtime.safeCall(globalThis.Error("y")) } //│ }; //│ f3(false) //│ ═══[RUNTIME ERROR] Error: y diff --git a/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls b/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls index 59d45edb93..4d1064c62c 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls @@ -77,13 +77,17 @@ M.foo.bar.baz() //│ res = App{typ=module:M}: //│ lhs = Resolved{sym=term:module:M.baz}: //│ t = Sel{sym=member:baz}: -//│ prefix = Sel{sym=member:bar,typ=module:M}: -//│ prefix = Sel{sym=member:foo,typ=module:M}: -//│ prefix = Resolved{sym=module:M,typ=module:M}: -//│ t = Ref{sym=member:M} of member:M -//│ sym = module:M -//│ nme = Ident of "foo" -//│ nme = Ident of "bar" +//│ prefix = Resolved{sym=term:module:M.bar,typ=module:M}: +//│ t = Sel{sym=member:bar}: +//│ prefix = Resolved{sym=term:module:M.foo,typ=module:M}: +//│ t = Sel{sym=member:foo}: +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M +//│ nme = Ident of "foo" +//│ sym = term:module:M.foo +//│ nme = Ident of "bar" +//│ sym = term:module:M.bar //│ nme = Ident of "baz" //│ sym = term:module:M.baz //│ rhs = Tup of Nil @@ -94,11 +98,13 @@ M.that.that //│ stats = Nil //│ res = Resolved{sym=term:module:N.that,typ=module:M}: //│ t = Sel{sym=member:that}: -//│ prefix = Sel{sym=member:that,typ=module:N}: -//│ prefix = Resolved{sym=module:M,typ=module:M}: -//│ t = Ref{sym=member:M} of member:M -//│ sym = module:M -//│ nme = Ident of "that" +//│ prefix = Resolved{sym=term:module:M.that,typ=module:N}: +//│ t = Sel{sym=member:that}: +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M +//│ nme = Ident of "that" +//│ sym = term:module:M.that //│ nme = Ident of "that" //│ sym = term:module:N.that @@ -108,19 +114,29 @@ M.that.that.that.that.that.that //│ stats = Nil //│ res = Resolved{sym=term:module:N.that,typ=module:M}: //│ t = Sel{sym=member:that}: -//│ prefix = Sel{sym=member:that,typ=module:N}: -//│ prefix = Sel{sym=member:that,typ=module:M}: -//│ prefix = Sel{sym=member:that,typ=module:N}: -//│ prefix = Sel{sym=member:that,typ=module:M}: -//│ prefix = Sel{sym=member:that,typ=module:N}: -//│ prefix = Resolved{sym=module:M,typ=module:M}: -//│ t = Ref{sym=member:M} of member:M -//│ sym = module:M -//│ nme = Ident of "that" +//│ prefix = Resolved{sym=term:module:M.that,typ=module:N}: +//│ t = Sel{sym=member:that}: +//│ prefix = Resolved{sym=term:module:N.that,typ=module:M}: +//│ t = Sel{sym=member:that}: +//│ prefix = Resolved{sym=term:module:M.that,typ=module:N}: +//│ t = Sel{sym=member:that}: +//│ prefix = Resolved{sym=term:module:N.that,typ=module:M}: +//│ t = Sel{sym=member:that}: +//│ prefix = Resolved{sym=term:module:M.that,typ=module:N}: +//│ t = Sel{sym=member:that}: +//│ prefix = Resolved{sym=module:M,typ=module:M}: +//│ t = Ref{sym=member:M} of member:M +//│ sym = module:M +//│ nme = Ident of "that" +//│ sym = term:module:M.that +//│ nme = Ident of "that" +//│ sym = term:module:N.that +//│ nme = Ident of "that" +//│ sym = term:module:M.that //│ nme = Ident of "that" -//│ nme = Ident of "that" +//│ sym = term:module:N.that //│ nme = Ident of "that" -//│ nme = Ident of "that" +//│ sym = term:module:M.that //│ nme = Ident of "that" //│ sym = term:module:N.that diff --git a/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls b/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls index 887bd29387..6af8dd1cfe 100644 --- a/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls +++ b/hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls @@ -44,7 +44,9 @@ foo.foo //│ stats = Nil //│ res = Resolved{sym=term:class:Foo.foo,typ=class:Foo}: //│ t = Sel{sym=member:foo}: -//│ prefix = Ref{sym=member:foo,typ=class:Foo} of member:foo +//│ prefix = Resolved{sym=term:foo,typ=class:Foo}: +//│ t = Ref{sym=member:foo} of member:foo +//│ sym = term:foo //│ nme = Ident of "foo" //│ sym = term:class:Foo.foo @@ -93,7 +95,9 @@ foo.foo //│ stats = Nil //│ res = Resolved{sym=term:class:Foo2.foo,typ=class:Foo2[class:Int, class:Str]}: //│ t = Sel{sym=member:foo}: -//│ prefix = Ref{sym=member:foo,typ=class:Foo2[class:Str, class:Int]} of member:foo +//│ prefix = Resolved{sym=term:foo,typ=class:Foo2[class:Str, class:Int]}: +//│ t = Ref{sym=member:foo} of member:foo +//│ sym = term:foo //│ nme = Ident of "foo" //│ sym = term:class:Foo2.foo diff --git a/hkmc2/shared/src/test/mlscript/decls/Prelude.mls b/hkmc2/shared/src/test/mlscript/decls/Prelude.mls index 5b36a10887..920084fde2 100644 --- a/hkmc2/shared/src/test/mlscript/decls/Prelude.mls +++ b/hkmc2/shared/src/test/mlscript/decls/Prelude.mls @@ -7,35 +7,64 @@ declare type Nothing declare type untyped declare class Object +declare val Object declare class JSON +declare val JSON declare class Number +declare val Number declare class BigInt +declare val BigInt declare class Function +declare val Function declare class String +declare val String declare class RegExp +declare val RegExp declare class Set +declare val Set declare class Map +declare val Map declare class WeakSet +declare val WeakSet declare class WeakMap +declare val WeakMap declare class Error(info) +declare val Error declare class TypeError(info) +declare val TypeError declare class RangeError(info) +declare val RangeError declare class Date +declare val Date declare class ArrayBuffer +declare val ArrayBuffer declare class TypedArray +declare val TypedArray declare class Int8Array +declare val Int8Array declare class Uint8Array +declare val Uint8Array declare class Uint8ClampedArray +declare val Uint8ClampedArray declare class Int16Array +declare val Int16Array declare class Uint16Array +declare val Uint16Array declare class Int32Array +declare val Int32Array declare class Uint32Array +declare val Uint32Array declare class Float16Array +declare val Float16Array declare class Float32Array +declare val Float32Array declare class Float64Array +declare val Float64Array declare class BigInt64Array +declare val BigInt64Array declare class BigUint64Array +declare val BigUint64Array // MLscript-specific types declare class Bool @@ -120,8 +149,8 @@ declare val fs declare val Infinity // Wasm support -declare class Promise with - fun resolve +declare class Promise +declare val Promise declare object WebAssembly with declare class Memory declare object Module with From 2c45f4140d7ca382d15a5c84420476bf7ded39c7 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Thu, 13 Nov 2025 16:10:58 +0800 Subject: [PATCH 52/55] Move `defn` definition to `DefinitionSymbol` --- .../src/main/scala/hkmc2/codegen/Block.scala | 4 +- .../scala/hkmc2/codegen/Instrumentation.scala | 2 +- .../main/scala/hkmc2/codegen/Printer.scala | 4 +- .../scala/hkmc2/codegen/llir/Builder.scala | 2 +- .../scala/hkmc2/semantics/Elaborator.scala | 10 ++-- .../main/scala/hkmc2/semantics/Resolver.scala | 6 +-- .../main/scala/hkmc2/semantics/Symbol.scala | 49 +++++++------------ .../src/main/scala/hkmc2/semantics/Term.scala | 14 +++--- .../hkmc2/semantics/ucs/TermSynthesizer.scala | 4 +- .../src/main/scala/hkmc2/syntax/Tree.scala | 2 +- 10 files changed, 41 insertions(+), 56 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala index 2d4c7d40c7..f74f4ab183 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala @@ -280,7 +280,7 @@ case class TryBlock(sub: Block, finallyDo: Block, rest: Block) extends Block wit case class Assign(lhs: Local, rhs: Result, rest: Block) extends Block with ProductWithTail // case class Assign(lhs: Path, rhs: Result, rest: Block) extends Block with ProductWithTail -case class AssignField(lhs: Path, nme: Tree.Ident, rhs: Result, rest: Block)(val symbol: Opt[FieldSymbol]) extends Block with ProductWithTail +case class AssignField(lhs: Path, nme: Tree.Ident, rhs: Result, rest: Block)(val symbol: Opt[MemberSymbol]) extends Block with ProductWithTail case class AssignDynField(lhs: Path, fld: Path, arrayIdx: Bool, rhs: Result, rest: Block) extends Block with ProductWithTail @@ -300,7 +300,7 @@ case class HandleBlock( sealed abstract class Defn: - val innerSym: Opt[MemberSymbol[?]] + val innerSym: Opt[MemberSymbol] val sym: BlockMemberSymbol def isOwned: Bool = owner.isDefined def owner: Opt[InnerSymbol] diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Instrumentation.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Instrumentation.scala index 3232ad7b09..b65d7427d6 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Instrumentation.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Instrumentation.scala @@ -9,7 +9,7 @@ class Instrumentation(using Raise) extends BlockTransformer(new SymbolSubst()): override def applyDefn(d: Defn)(k: Defn => Block): Block = d match case defn: ClsLikeDefn => - if defn.sym.defn.exists(_.hasStagedModifier.isDefined) && defn.companion.isDefined + if defn.isym.defn.exists(_.hasStagedModifier.isDefined) && defn.companion.isDefined then raise(WarningReport(msg"`staged` keyword doesn't do anything currently." -> defn.sym.toLoc :: Nil)) super.applyDefn(defn)(k) case b => super.applyDefn(b)(k) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala index 049fc2affc..521b5d5f7d 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala @@ -66,7 +66,7 @@ object Printer: doc"fun ${sym.nme}${docParams} { #{ # ${docBody} #} # }" case ValDefn(tsym, sym, rhs) => doc"val ${tsym.nme} = ${mkDocument(rhs)}" - case ClsLikeDefn(own, _, sym, k, paramsOpt, auxParams, parentSym, methods, + case ClsLikeDefn(own, isym, sym, k, paramsOpt, auxParams, parentSym, methods, privateFields, publicFields, preCtor, ctor, mod, bufferable) => def optFldBody(t: semantics.TermDefinition) = @@ -82,7 +82,7 @@ object Printer: val docPubFlds = if publicFields.isEmpty then doc"" else doc" # ${pubFields}" val docBody = if publicFields.isEmpty && privateFields.isEmpty then doc"" else doc" { #{ ${docPrivFlds}${docPubFlds} #} # }" val docCtorParams = if clsParams.isEmpty then doc"" else doc"(${ctorParams.mkDocument(", ")})" - val docStaged = if sym.defn.forall(_.hasStagedModifier.isEmpty) then doc"" else doc"staged " + val docStaged = if isym.defn.forall(_.hasStagedModifier.isEmpty) then doc"" else doc"staged " doc"${docStaged}class ${own.fold("")(_.toString+"::")}${sym.nme}${docCtorParams}${docBody}" def mkDocument(arg: Arg)(using Raise, Scope): Document = diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala index 1b71932de8..50478b1560 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala @@ -300,7 +300,7 @@ final class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt): trace[Local](s"bClassOfField { $p } begin", x => s"bClassOfField end: $x"): p match case ts: TermSymbol => ts.owner.get - case ms: MemberSymbol[?] => + case ms: MemberSymbol => ms.defn match case Some(d: ClassLikeDef) => d.owner.get case Some(d: TermDefinition) => d.owner.get diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index 0146889e40..db1c67bf01 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -82,7 +82,7 @@ object Elaborator: // * but they should be allowed to shadow previous imports. env.get(kv._1).forall(_.isImport)) - def withMembers(members: Iterable[Str -> MemberSymbol[?]]): Ctx = + def withMembers(members: Iterable[Str -> MemberSymbol]): Ctx = copy(env = env ++ members.map: case (nme, sym) => val elem = outer.inner match @@ -205,7 +205,7 @@ object Elaborator: Term.Ref(sym)(id, 666, N) // FIXME: 666 is a temporary placeholder def symbol = S(sym) def isImport: Bool = false - final case class SelElem(base: Elem, nme: Str, symOpt: Opt[FieldSymbol], isImport: Bool) extends Elem: + final case class SelElem(base: Elem, nme: Str, symOpt: Opt[MemberSymbol], isImport: Bool) extends Elem: def ref(id: Ident)(using Elaborator.State): Resolvable = // * Same remark as in RefElem#ref Term.SynthSel(base.ref(Ident(base.nme)), @@ -308,7 +308,7 @@ extends Importer with ucs.SplitElaborator: def mkLetBinding(kw: Tree.Keywrd[?], sym: LocalSymbol, rhs: Term, annotations: Ls[Annot]): Ls[Statement] = LetDecl(sym, annotations).mkLocWith(kw, sym) :: DefineVar(sym, rhs) :: Nil - def resolveField(srcTree: Tree, base: Opt[Symbol], nme: Ident): Opt[FieldSymbol] = + def resolveField(srcTree: Tree, base: Opt[Symbol], nme: Ident): Opt[MemberSymbol] = base match case S(psym: BlockMemberSymbol) => psym.modOrObjTree match @@ -519,7 +519,7 @@ extends Importer with ucs.SplitElaborator: val f = c.symbol.flatMap(_.asCls) match case S(cls: ClassSymbol) => cls.tree.allSymbols.get(idp.name) match - case S(fld: FieldSymbol) => S(fld) + case S(fld: MemberSymbol) => S(fld) case _ => raise(ErrorReport(msg"Class '${cls.nme}' does not contain member '${idp.name}'." -> idp.toLoc :: Nil)) N @@ -586,7 +586,7 @@ extends Importer with ucs.SplitElaborator: val f = c.symbol.flatMap(_.asCls) match case S(cls: ClassSymbol) => cls.tree.allSymbols.get(nme.name) match - case S(fld: FieldSymbol) => S(fld) + case S(fld: MemberSymbol) => S(fld) case _ => raise(ErrorReport(msg"Class '${cls.nme}' does not contain member '${nme.name}'." -> nme.toLoc :: Nil)) N diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala index 1517c96964..47338ce962 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala @@ -931,7 +931,7 @@ class Resolver(tl: TraceLogger) s"Resolving the type for term: ${t} (prefer = ${prefer}, sym = ${t.resolvedSym})", _ => s"-> typ = ${t.resolvedTyp}" ): - def disambSym(bms: BlockMemberSymbol): Opt[FieldSymbol] = prefer match + def disambSym(bms: BlockMemberSymbol): Opt[DefinitionSymbol[?]] = prefer match case _: Module => bms.asMod case _: Class => bms.asCls case _: Selectable => bms.asModOrObj orElse bms.asTrm @@ -955,7 +955,7 @@ class Resolver(tl: TraceLogger) case S(disambBms) => disambBms.defn case N => bms.asPrincipal.flatMap(_.defn) case S(bls: BlockLocalSymbol) => bls.decl - case S(fs: FieldSymbol) => fs.defn + case S(ds: DefinitionSymbol[?]) => ds.defn case _ => N log(s"Declaration: ${decl}") decl match @@ -1206,7 +1206,7 @@ object ModuleChecker: def checkSym(sym: Symbol): Bool = sym match case sym: BuiltinSymbol => false case sym: BlockLocalSymbol => sym.decl.exists(checkDecl) - case sym: FieldSymbol => prefer match + case sym: MemberSymbol => prefer match case Expect.Module(_) => sym.existsModuleful case _ => !sym.existsNonModuleful diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index c0fdb0945b..596da69ee7 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -97,7 +97,7 @@ abstract class Symbol(using State) extends Located: def asBlkMember: Opt[BlockMemberSymbol] = this match case mem: BlockMemberSymbol => S(mem) - case mem: MemberSymbol[?] => mem.defn match + case mem: DefinitionSymbol[?] => mem.defn match case S(defn: TypeLikeDef) => S(defn.bsym) case S(defn: TermDefinition) => S(defn.sym) case N => N @@ -209,10 +209,7 @@ class BuiltinSymbol * `nameIsMeaningful` is `true` when the name comes from the user's source code; * it is false when the name is a default given by the compiler, such as "lambda" when lifting lambdas. */ class BlockMemberSymbol(val nme: Str, val trees: Ls[TypeOrTermDef], val nameIsMeaningful: Bool = true)(using State) - extends MemberSymbol[Definition]: - - def defn: Option[Definition] = ??? - def defn_=(d: Option[Definition]): Unit = ??? + extends MemberSymbol: // * This is a hack for that `TermDef` currently doesn't have a symbol. var tsym: Opt[TermSymbol] = N @@ -250,25 +247,20 @@ class BlockMemberSymbol(val nme: Str, val trees: Ls[TypeOrTermDef], val nameIsMe end BlockMemberSymbol -sealed abstract class MemberSymbol[Defn <: Definition](using State) extends Symbol: +sealed abstract class MemberSymbol(using State) extends Symbol: def nme: Str - def defn: Opt[Defn] - def defn_=(d: Opt[Defn]): Unit - - def subst(using SymbolSubst): MemberSymbol[Defn] + def subst(using SymbolSubst): MemberSymbol class TermSymbol(val k: TermDefKind, val owner: Opt[InnerSymbol], val id: Tree.Ident)(using State) - extends MemberSymbol[TermDefinition] + extends MemberSymbol with DefinitionSymbol[TermDefinition] with LocalSymbol with NamedSymbol: def nme: Str = id.name def name: Str = nme - var defn: Opt[TermDefinition] = N - def toLoc: Option[Loc] = id.toLoc override def toString: Str = s"term:${owner.map(o => s"${o}.").getOrElse("")}${id.name}${State.dbgUid(uid)}" @@ -298,24 +290,22 @@ type BaseTypeSymbol = ClassSymbol | ModuleOrObjectSymbol type TypeSymbol = BaseTypeSymbol | TypeAliasSymbol -type FieldSymbol = MemberSymbol[?] - /** * ErrorSymbol is a placeholder symbol denoting error (during symbol * resolution in the elaborator / resolver). This helps prevent the * same error from throwing multiple times. */ -case class ErrorSymbol(val nme: Str, tree: Tree)(using State) extends MemberSymbol[Nothing]: +case class ErrorSymbol(val nme: Str, tree: Tree)(using State) extends MemberSymbol: var defn: Opt[Nothing] = N override def toLoc: Option[Loc] = tree.toLoc - override def subst(using sub: SymbolSubst): MemberSymbol[Nothing] = sub.mapErrorSym(this) + override def subst(using sub: SymbolSubst): ErrorSymbol = sub.mapErrorSym(this) override def toString = s"error:$nme" sealed trait ClassLikeSymbol extends IdentifiedSymbol: - self: MemberSymbol[? <: ClassDef | ModuleOrObjectDef] => + self: MemberSymbol & DefinitionSymbol[? <: ClassDef | ModuleOrObjectDef] => val tree: Tree.TypeDef def subst(using sub: SymbolSubst): ClassLikeSymbol @@ -329,12 +319,13 @@ sealed trait ClassLikeSymbol extends IdentifiedSymbol: * definition. */ sealed trait DefinitionSymbol[Defn <: Definition] extends Symbol: - this: MemberSymbol[Defn] => + this: MemberSymbol => + + var defn: Opt[Defn] = N - def defn: Opt[Defn] def subst(using sub: SymbolSubst): DefinitionSymbol[Defn] - def asMemSym: MemberSymbol[Defn] = this + def asMemSym: MemberSymbol = this /** This is the symbol associated to specific definitions. @@ -355,15 +346,13 @@ trait IdentifiedSymbol extends Symbol: val id: Tree.Ident class ClassSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using State) - extends MemberSymbol[ClassDef] + extends MemberSymbol with ClassLikeSymbol with CtorSymbol with DefinitionSymbol[ClassDef] with InnerSymbol with NamedSymbol: - var defn: Opt[ClassDef] = N - def name: Str = nme def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of classe here @@ -374,13 +363,12 @@ class ClassSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using State) override def subst(using sub: SymbolSubst): ClassSymbol = sub.mapClsSym(this) class ModuleOrObjectSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using State) - extends MemberSymbol[ModuleOrObjectDef] + extends MemberSymbol with ClassLikeSymbol with CtorSymbol with DefinitionSymbol[ModuleOrObjectDef] with InnerSymbol with NamedSymbol: - var defn: Opt[ModuleOrObjectDef] = N def name: Str = nme def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of module here @@ -391,9 +379,8 @@ class ModuleOrObjectSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using Sta override def subst(using sub: SymbolSubst): ModuleOrObjectSymbol = sub.mapModuleSym(this) class TypeAliasSymbol(val id: Tree.Ident)(using State) - extends MemberSymbol[TypeDef] + extends MemberSymbol with DefinitionSymbol[TypeDef]: - var defn: Opt[TypeDef] = N def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of type alias here override def toString: Str = s"type:${id.name}${State.dbgUid(uid)}" @@ -401,11 +388,10 @@ class TypeAliasSymbol(val id: Tree.Ident)(using State) def subst(using sub: SymbolSubst): TypeAliasSymbol = sub.mapTypeAliasSym(this) class PatternSymbol(val id: Tree.Ident, val params: Opt[Tree.Tup], val body: Tree)(using State) - extends MemberSymbol[PatternDef] + extends MemberSymbol with CtorSymbol with DefinitionSymbol[PatternDef] with InnerSymbol: - var defn: Opt[PatternDef] = N def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of pattern here override def toString: Str = s"pattern:${id.name}" @@ -413,10 +399,9 @@ class PatternSymbol(val id: Tree.Ident, val params: Opt[Tree.Tup], val body: Tre override def subst(using sub: SymbolSubst): PatternSymbol = sub.mapPatSym(this) class TopLevelSymbol(blockNme: Str)(using State) - extends MemberSymbol[ModuleOrObjectDef] + extends MemberSymbol with DefinitionSymbol[ModuleOrObjectDef] with InnerSymbol: - var defn: Opt[ModuleOrObjectDef] = N def nme = blockNme def toLoc: Option[Loc] = N override def toString: Str = s"globalThis:$blockNme${State.dbgUid(uid)}" diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index d0360835ee..89dc0480fb 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -66,7 +66,7 @@ sealed trait ResolvableImpl: .withLocOf(this) .asInstanceOf - def withSym(sym: FieldSymbol): this.type = + def withSym(sym: MemberSymbol): this.type = this.match case t: Term.Sel => t.copy()(S(sym), t.typ) case t: Term.SynthSel => t.copy()(S(sym), t.typ) @@ -138,7 +138,7 @@ sealed trait ResolvableImpl: def defn: Opt[Definition] = resolvedSym match case S(sym: BlockMemberSymbol) => N - case S(sym: MemberSymbol[?]) => sym.defn + case S(sym: DefinitionSymbol[?]) => sym.defn case _ => N def typDefn = resolvedTyp match @@ -215,11 +215,11 @@ enum Term extends Statement: case TyApp(lhs: Term, targs: Ls[Term]) (val typ: Opt[Type]) extends Term, ResolvableImpl case Sel(prefix: Term, nme: Tree.Ident) - (val sym: Opt[FieldSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl + (val sym: Opt[MemberSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl case SynthSel(prefix: Term, nme: Tree.Ident) - (val sym: Opt[FieldSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl + (val sym: Opt[MemberSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl case SelProj(prefix: Term, cls: Term, proj: Tree.Ident) - (val sym: Opt[FieldSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl + (val sym: Opt[MemberSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl case DynSel(prefix: Term, fld: Term, arrayIdx: Bool) case Tup(fields: Ls[Elem])(val tree: Tree.Tup) case Mut(underlying: Tup | Rcd | New | DynNew) @@ -300,7 +300,7 @@ enum Term extends Statement: case nu: New => nu.typ case _ => N - def sel(id: Tree.Ident, sym: Opt[FieldSymbol]): Sel = + def sel(id: Tree.Ident, sym: Opt[MemberSymbol]): Sel = Sel(this, id)(sym, N) def selNoSym(nme: Str, synth: Bool = false): Sel | SynthSel = val id = new Tree.Ident(nme) @@ -980,7 +980,7 @@ object Param: final case class Param(flags: FldFlags, sym: VarSymbol, sign: Opt[Term], modulefulness: Modulefulness) extends Declaration, AutoLocated: - var fldSym: Opt[FieldSymbol] = N + var fldSym: Opt[MemberSymbol] = N def subTerms: Ls[Term] = sign.toList override protected def children: List[Located] = sym :: sign.toList def showDbg: Str = flags.show + sym + sign.fold("")(": " + _.showDbg) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala index 4199993d23..239e8eb172 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala @@ -12,10 +12,10 @@ import syntax.Tree, Tree.*, Elaborator.{Ctx, State, ctx} trait TermSynthesizer(using State): protected final def sel(p: Term, k: Ident): Term.SynthSel = (Term.SynthSel(p, k)(N, N): Term.SynthSel).resolve - protected final def sel(p: Term, k: Ident, s: FieldSymbol): Term.SynthSel = + protected final def sel(p: Term, k: Ident, s: MemberSymbol): Term.SynthSel = (Term.SynthSel(p, k)(S(s), N): Term.SynthSel).resolve protected final def sel(p: Term, k: Str): Term.SynthSel = sel(p, Ident(k): Ident) - protected final def sel(p: Term, k: Str, s: FieldSymbol): Term.SynthSel = sel(p, Ident(k): Ident, s) + protected final def sel(p: Term, k: Str, s: MemberSymbol): Term.SynthSel = sel(p, Ident(k): Ident, s) protected final def int(i: Int) = Term.Lit(IntLit(BigInt(i))) protected final def str(s: Str) = Term.Lit(StrLit(s)) protected final def `null` = Term.Lit(UnitLit(true)) diff --git a/hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala b/hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala index c723a548ef..2f23305bd9 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala @@ -537,7 +537,7 @@ trait TypeDefImpl(using State) extends TypeOrTermDef: import semantics.* - lazy val symbol: MemberSymbol[? <: TypeLikeDef] = k match + lazy val symbol: DefinitionSymbol[? <: TypeLikeDef] = k match case Cls => ClassSymbol(this, name.getOrElse(Ident("‹error›"))) case Mod | Obj => ModuleOrObjectSymbol(this, name.getOrElse(Ident("‹error›"))) case Als => TypeAliasSymbol(name.getOrElse(Ident("‹error›"))) From ebb3af6534ee546a491d7ec1b7f454156f86999c Mon Sep 17 00:00:00 2001 From: Flandia Date: Thu, 13 Nov 2025 16:24:54 +0800 Subject: [PATCH 53/55] Apply @LPTK's top-quality suggestion Co-authored-by: Lionel Parreaux --- hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index db1c67bf01..cdafc57c6b 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -1597,9 +1597,7 @@ extends Importer with ucs.SplitElaborator: case p @ Pun(false, _) :: Nil => record(p) case p @ InfixApp(_: Ident, Keywrd(Keyword.`:`), _) :: Nil => record(p) case lhs :: Nil => arrow(lhs, rhs) - // TODO: When is this case reached? - // * Answer: pattern p = () => Unit - case _ :: _ | Nil => ??? + case _ :: _ | Nil => ??? // TODO: this case reached by, eg, `pattern p = () => Unit` case p as q => q match // `p as id` is elaborated into alias if `id` is not a constructor. case id: Ident => ident(id) match From 4bd0874dc3363f5b1e0e833dc3756ea1457cf0df Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Thu, 13 Nov 2025 16:25:10 +0800 Subject: [PATCH 54/55] Revert regression --- .../src/test/mlscript-compile/Predef.mjs | 4 ++-- .../src/test/mlscript-compile/Runtime.mjs | 20 +++++++++---------- .../src/test/mlscript/codegen/Throw.mls | 6 ++---- .../src/test/mlscript/decls/Prelude.mls | 3 --- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/hkmc2/shared/src/test/mlscript-compile/Predef.mjs b/hkmc2/shared/src/test/mlscript-compile/Predef.mjs index 1c4f30daa5..a4ce900a78 100644 --- a/hkmc2/shared/src/test/mlscript-compile/Predef.mjs +++ b/hkmc2/shared/src/test/mlscript-compile/Predef.mjs @@ -114,10 +114,10 @@ globalThis.Object.freeze(class Predef { static notImplemented(msg) { let tmp; tmp = "Not implemented: " + msg; - throw runtime.safeCall(globalThis.Error(tmp)) + throw globalThis.Error(tmp) } static get notImplementedError() { - throw runtime.safeCall(globalThis.Error("Not implemented")); + throw globalThis.Error("Not implemented"); } static tuple(...xs) { return xs diff --git a/hkmc2/shared/src/test/mlscript-compile/Runtime.mjs b/hkmc2/shared/src/test/mlscript-compile/Runtime.mjs index f411500de9..d5cc8a4258 100644 --- a/hkmc2/shared/src/test/mlscript-compile/Runtime.mjs +++ b/hkmc2/shared/src/test/mlscript-compile/Runtime.mjs @@ -143,14 +143,14 @@ globalThis.Object.freeze(class Runtime { let scrut, scrut1, tmp, tmp1, tmp2; scrut = i >= xs.length; if (scrut === true) { - throw runtime.safeCall(globalThis.RangeError("Tuple.get: index out of bounds")) + throw globalThis.RangeError("Tuple.get: index out of bounds") } else { tmp = runtime.Unit; } tmp1 = - xs.length; scrut1 = i < tmp1; if (scrut1 === true) { - throw runtime.safeCall(globalThis.RangeError("Tuple.get: negative index out of bounds")) + throw globalThis.RangeError("Tuple.get: negative index out of bounds") } else { tmp2 = runtime.Unit; } @@ -176,7 +176,7 @@ globalThis.Object.freeze(class Runtime { let scrut; scrut = i >= string.length; if (scrut === true) { - throw runtime.safeCall(globalThis.RangeError("Str.get: index out of bounds")) + throw globalThis.RangeError("Str.get: index out of bounds") } else { return runtime.safeCall(string.at(i)) } @@ -424,7 +424,7 @@ globalThis.Object.freeze(class Runtime { }); } static get unreachable() { - throw runtime.safeCall(globalThis.Error("unreachable")); + throw globalThis.Error("unreachable"); } static checkArgs(functionName, expected, isUB, got) { let scrut, name, scrut1, scrut2, tmp, lambda, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12; @@ -465,7 +465,7 @@ globalThis.Object.freeze(class Runtime { tmp10 = tmp8 + tmp9; tmp11 = tmp10 + " but got "; tmp12 = tmp11 + got; - throw runtime.safeCall(globalThis.Error(tmp12)) + throw globalThis.Error(tmp12) } else { return runtime.Unit } @@ -479,7 +479,7 @@ globalThis.Object.freeze(class Runtime { } static checkCall(x) { if (x === undefined) { - throw runtime.safeCall(globalThis.Error("MLscript call unexpectedly returned `undefined`, the forbidden value.")) + throw globalThis.Error("MLscript call unexpectedly returned `undefined`, the forbidden value.") } else { return x } @@ -490,7 +490,7 @@ globalThis.Object.freeze(class Runtime { tmp1 = tmp + "' of class '"; tmp2 = tmp1 + clsName; tmp3 = tmp2 + "' was accessed without being called."; - throw runtime.safeCall(globalThis.Error(tmp3)) + throw globalThis.Error(tmp3) } static try(f) { let res; @@ -657,7 +657,7 @@ globalThis.Object.freeze(class Runtime { reps = tmp2; scrut1 = reps > 10; if (scrut1 === true) { - throw runtime.safeCall(globalThis.Error("10 repeated continuation frame (loop?)")) + throw globalThis.Error("10 repeated continuation frame (loop?)") } else { tmp3 = runtime.Unit; } @@ -702,7 +702,7 @@ globalThis.Object.freeze(class Runtime { reps = tmp1; scrut1 = reps > 10; if (scrut1 === true) { - throw runtime.safeCall(globalThis.Error("10 repeated continuation frame (loop?)")) + throw globalThis.Error("10 repeated continuation frame (loop?)") } else { tmp2 = runtime.Unit; } @@ -912,7 +912,7 @@ globalThis.Object.freeze(class Runtime { let scrut, tmp, tmp1; scrut = contTrace.resumed; if (scrut === true) { - throw runtime.safeCall(globalThis.Error("Multiple resumption")) + throw globalThis.Error("Multiple resumption") } else { tmp = runtime.Unit; } diff --git a/hkmc2/shared/src/test/mlscript/codegen/Throw.mls b/hkmc2/shared/src/test/mlscript/codegen/Throw.mls index 56ae1bfd85..4ef0cd898a 100644 --- a/hkmc2/shared/src/test/mlscript/codegen/Throw.mls +++ b/hkmc2/shared/src/test/mlscript/codegen/Throw.mls @@ -31,7 +31,7 @@ fun f(x) = return y f(1) //│ JS (unsanitized): -//│ let f2; f2 = function f(x) { throw runtime.safeCall(globalThis.Error("e")) }; f2(1) +//│ let f2; f2 = function f(x) { throw globalThis.Error("e") }; f2(1) //│ ═══[RUNTIME ERROR] Error: e @@ -43,9 +43,7 @@ f(false) //│ JS (unsanitized): //│ let f3; //│ f3 = function f(x) { -//│ if (x === true) { -//│ throw runtime.safeCall(globalThis.Error("x")) -//│ } else { throw runtime.safeCall(globalThis.Error("y")) } +//│ if (x === true) { throw globalThis.Error("x") } else { throw globalThis.Error("y") } //│ }; //│ f3(false) //│ ═══[RUNTIME ERROR] Error: y diff --git a/hkmc2/shared/src/test/mlscript/decls/Prelude.mls b/hkmc2/shared/src/test/mlscript/decls/Prelude.mls index 920084fde2..b540e2c5ca 100644 --- a/hkmc2/shared/src/test/mlscript/decls/Prelude.mls +++ b/hkmc2/shared/src/test/mlscript/decls/Prelude.mls @@ -29,11 +29,8 @@ declare val WeakSet declare class WeakMap declare val WeakMap declare class Error(info) -declare val Error declare class TypeError(info) -declare val TypeError declare class RangeError(info) -declare val RangeError declare class Date declare val Date From 859ff43ec41109bdb8667cdcd41d572ac159f4d0 Mon Sep 17 00:00:00 2001 From: Flandia Yingman Date: Thu, 13 Nov 2025 16:26:16 +0800 Subject: [PATCH 55/55] Remove something that I forgot to remove --- hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 596da69ee7..1f9113e758 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -296,8 +296,6 @@ type TypeSymbol = BaseTypeSymbol | TypeAliasSymbol * same error from throwing multiple times. */ case class ErrorSymbol(val nme: Str, tree: Tree)(using State) extends MemberSymbol: - var defn: Opt[Nothing] = N - override def toLoc: Option[Loc] = tree.toLoc override def subst(using sub: SymbolSubst): ErrorSymbol = sub.mapErrorSym(this)