Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
1f127e2
Add `Term.Resolved` and `DefinitionSymbol`
FlandiaYingman Sep 20, 2025
113fbe6
Support lowering of `Term.Resolved`
FlandiaYingman Sep 27, 2025
cf8c1c7
Defer `.class` expansion until lower
FlandiaYingman Sep 27, 2025
0f16141
WIP: Test Cases
FlandiaYingman Oct 9, 2025
df23015
Use `Term.Resolved` for Sel resoultion
FlandiaYingman Oct 9, 2025
b1545c0
Merge branch 'hkmc2' into resolved-term
FlandiaYingman Oct 9, 2025
5501876
Merge branch 'hkmc2' into resolved-term
FlandiaYingman Oct 11, 2025
85efd07
Merge branch 'hkmc2' into resolved-term
FlandiaYingman Oct 11, 2025
8606815
Some refactor_ization_ WIP
FlandiaYingman Oct 14, 2025
019c3ae
wrapup 1
FlandiaYingman Oct 30, 2025
99bdb5f
Apply Mark's Patch
FlandiaYingman Oct 30, 2025
55ba010
Resolve symbols for inner SynthSel
FlandiaYingman Oct 31, 2025
cd3ac61
Fix Effect Handler
FlandiaYingman Oct 31, 2025
66a700b
Fix LLIR
FlandiaYingman Oct 31, 2025
b4235eb
Recover errors that were already there
FlandiaYingman Oct 31, 2025
18ff415
Fix WASM
FlandiaYingman Oct 31, 2025
da6fcd7
Merge branch 'hkmc2' into resolved-term
FlandiaYingman Oct 31, 2025
1e5db6b
Fix duplicate symbol error
FlandiaYingman Oct 31, 2025
a2fbf48
Enhance type resolution
FlandiaYingman Oct 31, 2025
b4c9cd1
Cleanup asDefnSym_TODO
FlandiaYingman Oct 31, 2025
37dc34a
Fix instanceof for objects
FlandiaYingman Oct 31, 2025
d1c43f1
Cleanup hasLiftedClass
FlandiaYingman Oct 31, 2025
ef12ca6
Fix lifter bugs
CAG2Mark Oct 31, 2025
5de57fe
Cleanup symbol_SelectSymbol
FlandiaYingman Oct 31, 2025
f58deae
Cleanup add docs
FlandiaYingman Oct 31, 2025
df75b33
Cleanup HandlerLowering
FlandiaYingman Oct 31, 2025
09c39ab
Merge remote-tracking branch 'mark/top-quality-fixes-2' into resolved…
FlandiaYingman Oct 31, 2025
46830c6
Cleanup lifter
FlandiaYingman Nov 1, 2025
04640c1
Cleanup Normalization
FlandiaYingman Nov 1, 2025
efc0587
Cleanup Pattern
FlandiaYingman Nov 1, 2025
0137185
Cleanup Term
FlandiaYingman Nov 1, 2025
9597814
Apply suggestion from @LPTK
FlandiaYingman Nov 1, 2025
0997535
Cleanup HkScratch
FlandiaYingman Nov 1, 2025
82c0879
Cleanup some tests 1
FlandiaYingman Nov 1, 2025
571d9dd
Cleanup some tests 2
FlandiaYingman Nov 1, 2025
79a7a88
Cleanup Resolver
FlandiaYingman Nov 1, 2025
6ff7a4f
Correct location of TermDefinition
FlandiaYingman Nov 1, 2025
383da7f
Cleanup Resolver
FlandiaYingman Nov 1, 2025
dd08cce
Cleanup Elaborator
FlandiaYingman Nov 1, 2025
ce4f4a6
Apply @LPTK's suggestion
FlandiaYingman Nov 8, 2025
7d92a23
Apply @LPTK's suggestion
FlandiaYingman Nov 8, 2025
146ee2b
Clarify test comment
FlandiaYingman Nov 8, 2025
63ec9ee
Refactor out `t.resolvedSym.flatMap(_.asBlkMember)`
FlandiaYingman Nov 8, 2025
c327e45
Deobfuscate Harry's top-quality code
FlandiaYingman Nov 8, 2025
ba1f714
Refactor out `t.resolvedSym.flatMap(_.asBlkMember)`
FlandiaYingman Nov 8, 2025
4fe9cf6
Preserve empty lines in Lifter
FlandiaYingman Nov 8, 2025
6c50dde
Refine symbol typing and clean redundancy
FlandiaYingman Nov 8, 2025
31fb16c
Apply @LPTK's suggestion
FlandiaYingman Nov 8, 2025
a8bb754
Apply @LPTK's suggestion
FlandiaYingman Nov 8, 2025
e026034
Fix @LPTK's suggestion
FlandiaYingman Nov 8, 2025
ae1a97b
Fix sanity check test cases
FlandiaYingman Nov 8, 2025
51a77b8
Remove unused definition
FlandiaYingman Nov 8, 2025
55ca3fd
Store `TermSymbol` directly in `BlockMemberSymbol` rather than `TermD…
FlandiaYingman Nov 8, 2025
d81d0e6
Fix "Worst part of the PR 👎“
FlandiaYingman Nov 8, 2025
f527f3d
Refine TODO comments in resolver
FlandiaYingman Nov 8, 2025
a37f2f5
Merge branch 'hkmc2' into resolved-term
FlandiaYingman Nov 11, 2025
7aa3feb
Merge branch 'hkmc2' into resolved-term
FlandiaYingman Nov 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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(",")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"))
Expand Down Expand Up @@ -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
Expand Down
23 changes: 13 additions & 10 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -798,23 +799,23 @@ 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

// 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 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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
45 changes: 26 additions & 19 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 =>
Expand All @@ -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) =>
Expand All @@ -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()
Expand Down Expand Up @@ -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 =>
Expand Down Expand Up @@ -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 =>
Expand Down Expand Up @@ -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) =
Expand Down Expand Up @@ -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))
Expand All @@ -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):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading