@@ -22,6 +22,8 @@ case class Program(
2222
2323sealed abstract class Block extends Product with AutoLocated :
2424
25+ def ~ (that : Block ): Block = Begin (this , that)
26+
2527 protected def children : Ls [Located ] = ??? // Maybe extending AutoLocated is unnecessary
2628
2729 lazy val definedVars : Set [Local ] = this match
@@ -91,12 +93,37 @@ sealed abstract class Block extends Product with AutoLocated:
9193 case TryBlock (sub, finallyDo, rest) => sub.freeVars ++ finallyDo.freeVars ++ rest.freeVars
9294 case Assign (lhs, rhs, rest) => Set (lhs) ++ rhs.freeVars ++ rest.freeVars
9395 case AssignField (lhs, nme, rhs, rest) => lhs.freeVars ++ rhs.freeVars ++ rest.freeVars
96+ case AssignDynField (lhs, fld, arrayIdx, rhs, rest) => lhs.freeVars ++ fld.freeVars ++ rhs.freeVars ++ rest.freeVars
9497 case Define (defn, rest) => defn.freeVars ++ rest.freeVars
9598 case HandleBlock (lhs, res, par, args, cls, hdr, bod, rst) =>
9699 (bod.freeVars - lhs) ++ rst.freeVars ++ hdr.flatMap(_.freeVars)
97100 case HandleBlockReturn (res) => res.freeVars
98101 case End (msg) => Set .empty
99102
103+ // TODO: freeVarsLLIR skips `fun` and `cls` in `Call` and `Instantiate` respectively, which is needed in some
104+ // other places. However, adding them breaks some LLIR tests. Supposedly, once the IR uses the new symbol system,
105+ // this should no longer happen. This version should be removed once that is resolved.
106+ lazy val freeVarsLLIR : Set [Local ] = this match
107+ case Match (scrut, arms, dflt, rest) =>
108+ scrut.freeVarsLLIR ++ dflt.toList.flatMap(_.freeVarsLLIR) ++ rest.freeVarsLLIR
109+ ++ arms.flatMap:
110+ (pat, arm) => arm.freeVarsLLIR -- pat.freeVars
111+ case Return (res, implct) => res.freeVarsLLIR
112+ case Throw (exc) => exc.freeVarsLLIR
113+ case Label (label, body, rest) => (body.freeVarsLLIR - label) ++ rest.freeVarsLLIR
114+ case Break (label) => Set (label)
115+ case Continue (label) => Set (label)
116+ case Begin (sub, rest) => sub.freeVarsLLIR ++ rest.freeVarsLLIR
117+ case TryBlock (sub, finallyDo, rest) => sub.freeVarsLLIR ++ finallyDo.freeVarsLLIR ++ rest.freeVarsLLIR
118+ case Assign (lhs, rhs, rest) => Set (lhs) ++ rhs.freeVarsLLIR ++ rest.freeVarsLLIR
119+ case AssignField (lhs, nme, rhs, rest) => lhs.freeVarsLLIR ++ rhs.freeVarsLLIR ++ rest.freeVarsLLIR
120+ case AssignDynField (lhs, fld, arrayIdx, rhs, rest) => lhs.freeVarsLLIR ++ fld.freeVarsLLIR ++ rhs.freeVarsLLIR ++ rest.freeVarsLLIR
121+ case Define (defn, rest) => defn.freeVarsLLIR ++ rest.freeVarsLLIR
122+ case HandleBlock (lhs, res, par, args, cls, hdr, bod, rst) =>
123+ (bod.freeVarsLLIR - lhs) ++ rst.freeVarsLLIR ++ hdr.flatMap(_.freeVars)
124+ case HandleBlockReturn (res) => res.freeVarsLLIR
125+ case End (msg) => Set .empty
126+
100127 lazy val subBlocks : Ls [Block ] = this match
101128 case Match (p, arms, dflt, rest) => p.subBlocks ++ arms.map(_._2) ++ dflt.toList :+ rest
102129 case Begin (sub, rest) => sub :: rest :: Nil
@@ -122,15 +149,19 @@ sealed abstract class Block extends Product with AutoLocated:
122149 // Note that this returns the definitions in reverse order, with the bottommost definiton appearing
123150 // last. This is so that using defns.foldLeft later to add the definitions to the front of a block,
124151 // we don't need to reverse the list again to preserve the order of the definitions.
125- def floatOutDefns =
152+ def floatOutDefns (
153+ ignore : Defn => Bool = _ => false ,
154+ preserve : Defn => Bool = _ => false
155+ ) =
126156 var defns : List [Defn ] = Nil
127157 val transformer = new BlockTransformerShallow (SymbolSubst ()):
128158 override def applyBlock (b : Block ): Block = b match
129- case Define (defn, rest) => defn match
159+ case Define (defn, rest) if ! ignore(defn) => defn match
130160 case v : ValDefn => super .applyBlock(b)
131161 case _ =>
132162 defns ::= defn
133- applyBlock(rest)
163+ if preserve(defn) then super .applyBlock(b)
164+ else applyBlock(rest)
134165 case _ => super .applyBlock(b)
135166
136167 (transformer.applyBlock(this ), defns)
@@ -281,10 +312,20 @@ sealed abstract class Defn:
281312 lazy val freeVars : Set [Local ] = this match
282313 case FunDefn (own, sym, params, body) => body.freeVars -- params.flatMap(_.paramSyms) - sym
283314 case ValDefn (owner, k, sym, rhs) => rhs.freeVars
284- case ClsLikeDefn (own, isym, sym, k, paramsOpt, parentSym, methods, privateFields, publicFields, preCtor, ctor) =>
315+ case ClsLikeDefn (own, isym, sym, k, paramsOpt, auxParams, parentSym,
316+ methods, privateFields, publicFields, preCtor, ctor) =>
285317 preCtor.freeVars
286318 ++ ctor.freeVars ++ methods.flatMap(_.freeVars)
287- -- privateFields -- publicFields.map(_.sym)
319+ -- privateFields -- publicFields.map(_.sym) -- auxParams.flatMap(_.paramSyms)
320+
321+ lazy val freeVarsLLIR : Set [Local ] = this match
322+ case FunDefn (own, sym, params, body) => body.freeVarsLLIR -- params.flatMap(_.paramSyms) - sym
323+ case ValDefn (owner, k, sym, rhs) => rhs.freeVarsLLIR
324+ case ClsLikeDefn (own, isym, sym, k, paramsOpt, auxParams, parentSym,
325+ methods, privateFields, publicFields, preCtor, ctor) =>
326+ preCtor.freeVarsLLIR
327+ ++ ctor.freeVarsLLIR ++ methods.flatMap(_.freeVarsLLIR)
328+ -- privateFields -- publicFields.map(_.sym) -- auxParams.flatMap(_.paramSyms)
288329
289330final case class FunDefn (
290331 owner : Opt [InnerSymbol ],
@@ -304,10 +345,11 @@ final case class ValDefn(
304345
305346final case class ClsLikeDefn (
306347 owner : Opt [InnerSymbol ],
307- isym : MemberSymbol [? <: ClassLikeDef ],
348+ isym : MemberSymbol [? <: ClassLikeDef ] & InnerSymbol ,
308349 sym : BlockMemberSymbol ,
309350 k : syntax.ClsLikeKind ,
310351 paramsOpt : Opt [ParamList ],
352+ auxParams : List [ParamList ],
311353 parentPath : Opt [Path ],
312354 methods : Ls [FunDefn ],
313355 privateFields : Ls [TermSymbol ],
@@ -325,6 +367,7 @@ final case class Handler(
325367 params : Ls [ParamList ],
326368 body : Block ,
327369):
370+ lazy val freeVarsLLIR : Set [Local ] = body.freeVarsLLIR -- params.flatMap(_.paramSyms) - sym - resumeSym
328371 lazy val freeVars : Set [Local ] = body.freeVars -- params.flatMap(_.paramSyms) - sym - resumeSym
329372
330373/* Represents either unreachable code (for functions that must return a result)
@@ -340,6 +383,13 @@ enum Case:
340383 case Lit (_) => Set .empty
341384 case Cls (_, path) => path.freeVars
342385 case Tup (_, _) => Set .empty
386+
387+ lazy val freeVarsLLIR : Set [Local ] = this match
388+ case Lit (_) => Set .empty
389+ case Cls (_, path) => path.freeVarsLLIR
390+ case Tup (_, _) => Set .empty
391+
392+ sealed trait TrivialResult extends Result
343393
344394sealed abstract class Result :
345395
@@ -353,14 +403,26 @@ sealed abstract class Result:
353403 case _ => Nil
354404
355405 lazy val freeVars : Set [Local ] = this match
356- case Call (fun, args) => args.flatMap(_.value.freeVars).toSet
357- case Instantiate (cls, args) => args.flatMap(_.freeVars).toSet
406+ case Call (fun, args) => fun.freeVars ++ args.flatMap(_.value.freeVars).toSet
407+ case Instantiate (cls, args) => cls.freeVars ++ args.flatMap(_.freeVars).toSet
358408 case Select (qual, name) => qual.freeVars
359409 case Value .Ref (l) => Set (l)
360410 case Value .This (sym) => Set .empty
361411 case Value .Lit (lit) => Set .empty
362412 case Value .Lam (params, body) => body.freeVars -- params.paramSyms
363413 case Value .Arr (elems) => elems.flatMap(_.value.freeVars).toSet
414+ case DynSelect (qual, fld, arrayIdx) => qual.freeVars ++ fld.freeVars
415+
416+ lazy val freeVarsLLIR : Set [Local ] = this match
417+ case Call (fun, args) => args.flatMap(_.value.freeVarsLLIR).toSet
418+ case Instantiate (cls, args) => args.flatMap(_.freeVarsLLIR).toSet
419+ case Select (qual, name) => qual.freeVarsLLIR
420+ case Value .Ref (l) => Set (l)
421+ case Value .This (sym) => Set .empty
422+ case Value .Lit (lit) => Set .empty
423+ case Value .Lam (params, body) => body.freeVarsLLIR -- params.paramSyms
424+ case Value .Arr (elems) => elems.flatMap(_.value.freeVarsLLIR).toSet
425+ case DynSelect (qual, fld, arrayIdx) => qual.freeVarsLLIR ++ fld.freeVarsLLIR
364426
365427// type Local = LocalSymbol
366428type Local = Symbol
@@ -373,8 +435,9 @@ case class Call(fun: Path, args: Ls[Arg])(val isMlsFun: Bool, val mayRaiseEffect
373435
374436case class Instantiate (cls : Path , args : Ls [Path ]) extends Result
375437
376- sealed abstract class Path extends Result :
438+ sealed abstract class Path extends TrivialResult :
377439 def selN (id : Tree .Ident ): Path = Select (this , id)(N )
440+ def sel (id : Tree .Ident , sym : FieldSymbol ): Path = Select (this , id)(S (sym))
378441 def selSN (id : Str ): Path = selN(new Tree .Ident (id))
379442 def asArg = Arg (false , this )
380443
@@ -389,9 +452,15 @@ enum Value extends Path:
389452 case Lit (lit : Literal )
390453 case Lam (params : ParamList , body : Block )
391454 case Arr (elems : Ls [Arg ])
455+ case Rcd (elems : Ls [RcdArg ])
392456
393457case class Arg (spread : Bool , value : Path )
394458
459+ // * `IndxdArg(S(idx), value)` represents a key-value pair in a record `(idx): value`
460+ // * `IndxdArg(N, value)` represents a spread element in a record `...value`
461+ case class RcdArg (idx : Opt [Path ], value : Path ):
462+ def spread : Bool = idx.isEmpty
463+
395464extension (k : Block => Block )
396465
397466 def chain (other : Block => Block ): Block => Block = b => k(other(b))
0 commit comments