@@ -194,6 +194,7 @@ class Semantic {
194
194
class PromotionInfo {
195
195
var isCurrentObjectPromoted : Boolean = false
196
196
val values = mutable.Set .empty[Value ]
197
+ override def toString (): String = values.toString()
197
198
}
198
199
/** Values that have been safely promoted */
199
200
opaque type Promoted = PromotionInfo
@@ -405,6 +406,7 @@ class Semantic {
405
406
given Trace = trace1
406
407
val cls = target.owner.enclosingClass.asClass
407
408
val ddef = target.defTree.asInstanceOf [DefDef ]
409
+ // try early promotion here; if returns error, returns cold
408
410
val env2 = Env (ddef, args.map(_.value).widenArgs)
409
411
if target.isPrimaryConstructor then
410
412
given Env = env2
@@ -683,8 +685,26 @@ class Semantic {
683
685
}
684
686
685
687
/** Evaluate a list of expressions */
686
- def eval (exprs : List [Tree ], thisV : Addr , klass : ClassSymbol ): Contextual [List [Result ]] =
687
- exprs.map { expr => eval(expr, thisV, klass) }
688
+ def eval (exprs : List [Tree ], thisV : Addr , klass : ClassSymbol ): Contextual [(List [Result ], Env )] = exprs match {
689
+ case Nil => (Nil , env)
690
+ case h :: t => h match {
691
+ case v : ValDef => {
692
+ val res = eval(h, thisV, klass)
693
+ val newEnv = Env (Map (v.symbol -> res.value))
694
+ withEnv(env.union(newEnv)) {
695
+ val (res2, env2) = eval(t, thisV, klass)
696
+ (res :: res2, env2)
697
+ }
698
+ }
699
+ case _ => {
700
+ val res = eval(h, thisV, klass)
701
+ withEnv(env) {
702
+ val (res2, env2) = eval(t, thisV, klass)
703
+ (res :: res2, env2)
704
+ }
705
+ }
706
+ }
707
+ }
688
708
689
709
/** Evaluate arguments of methods */
690
710
def evalArgs (args : List [Arg ], thisV : Addr , klass : ClassSymbol ): Contextual [(List [Error ], List [ArgInfo ])] =
@@ -788,11 +808,13 @@ class Semantic {
788
808
Result (value, Nil )
789
809
790
810
case Block (stats, expr) =>
791
- val ress = eval(stats, thisV, klass)
792
- eval(expr, thisV, klass) ++ ress.flatMap(_.errors)
811
+ val (ress, env2) = eval(stats, thisV, klass)
812
+ withEnv(env2) {
813
+ eval(expr, thisV, klass) ++ ress.flatMap(_.errors)
814
+ }
793
815
794
816
case If (cond, thenp, elsep) =>
795
- val ress = eval(cond :: thenp :: elsep :: Nil , thisV, klass)
817
+ val ( ress, env2) = eval(cond :: thenp :: elsep :: Nil , thisV, klass)
796
818
val value = ress.map(_.value).join
797
819
val errors = ress.flatMap(_.errors)
798
820
Result (value, errors)
@@ -803,7 +825,7 @@ class Semantic {
803
825
804
826
case Match (selector, cases) =>
805
827
val res1 = eval(selector, thisV, klass).ensureHot(" The value to be matched needs to be fully initialized" , selector)
806
- val ress = eval(cases.map(_.body), thisV, klass)
828
+ val ( ress, env) = eval(cases.map(_.body), thisV, klass)
807
829
val value = ress.map(_.value).join
808
830
val errors = res1.errors ++ ress.flatMap(_.errors)
809
831
Result (value, errors)
@@ -812,15 +834,15 @@ class Semantic {
812
834
eval(expr, thisV, klass).ensureHot(" return expression may only be initialized value" , expr)
813
835
814
836
case WhileDo (cond, body) =>
815
- val ress = eval(cond :: body :: Nil , thisV, klass)
837
+ val ( ress, env2) = eval(cond :: body :: Nil , thisV, klass)
816
838
Result (Hot , ress.flatMap(_.errors))
817
839
818
840
case Labeled (_, expr) =>
819
841
eval(expr, thisV, klass)
820
842
821
843
case Try (block, cases, finalizer) =>
822
844
val res1 = eval(block, thisV, klass)
823
- val ress = eval(cases.map(_.body), thisV, klass)
845
+ val ( ress, env2) = eval(cases.map(_.body), thisV, klass)
824
846
val errors = ress.flatMap(_.errors)
825
847
val resValue = ress.map(_.value).join
826
848
if finalizer.isEmpty then
@@ -836,7 +858,7 @@ class Semantic {
836
858
Result (Hot , ress.flatMap(_.errors))
837
859
838
860
case Inlined (call, bindings, expansion) =>
839
- val ress = eval(bindings, thisV, klass)
861
+ val ( ress, env2) = eval(bindings, thisV, klass)
840
862
eval(expansion, thisV, klass) ++ ress.flatMap(_.errors)
841
863
842
864
case Thicket (List ()) =>
@@ -846,7 +868,8 @@ class Semantic {
846
868
case vdef : ValDef =>
847
869
// local val definition
848
870
// TODO: support explicit @cold annotation for local definitions
849
- eval(vdef.rhs, thisV, klass).ensureHot(" Local definitions may only hold initialized values" , vdef)
871
+ eval(vdef.rhs, thisV, klass)
872
+ // .ensureHot("Local definitions may only hold initialized values", vdef)
850
873
851
874
case ddef : DefDef =>
852
875
// local method
@@ -891,7 +914,7 @@ class Semantic {
891
914
// It's always safe to approximate them with `Cold`.
892
915
Result (Cold , Nil )
893
916
else
894
- default( )
917
+ Result (env.getOrElse(sym, Hot ), Nil )
895
918
896
919
case tmref : TermRef =>
897
920
cases(tmref.prefix, thisV, klass, source).select(tmref.symbol, source)
@@ -987,7 +1010,7 @@ class Semantic {
987
1010
// parents
988
1011
def initParent (parent : Tree , tasks : Tasks )(using Env ) = parent match {
989
1012
case tree @ Block (stats, NewExpr (tref, New (tpt), ctor, argss)) => // can happen
990
- eval(stats, thisV, klass).foreach { res => errorBuffer ++= res.errors }
1013
+ eval(stats, thisV, klass)._1. foreach { res => errorBuffer ++= res.errors }
991
1014
val (errors, args) = evalArgs(argss.flatten, thisV, klass)
992
1015
errorBuffer ++= errors
993
1016
superCall(tref, ctor, args, tree, tasks)
0 commit comments