@@ -144,56 +144,6 @@ object Semantic:
144144
145145 def hasField (f : Symbol ) = fields.contains(f)
146146
147- /** The environment stores values for constructor parameters
148- *
149- * For performance and usability, we restrict parameters to be either `Cold`
150- * or `Hot`.
151- *
152- * Despite that we have environment for evaluating expressions in secondary
153- * constructors, we don't need to put environment as the cache key. The
154- * reason is that constructor parameters are determined by the value of
155- * `this` --- it suffices to make the value of `this` as part of the cache
156- * key.
157- *
158- * This crucially depends on the fact that in the initialization process
159- * there can be exactly one call to a specific constructor for a given
160- * receiver. However, once we relax the design to allow non-hot values to
161- * methods and functions, we have to put the environment as part of the cache
162- * key. The reason is that given the same receiver, a method or function may
163- * be called with different arguments -- they are not decided by the receiver
164- * anymore.
165- *
166- * TODO: remove Env as it is only used to pass value from `callConstructor` -> `eval` -> `init`.
167- * It goes through `eval` for caching (termination) purposes.
168- */
169- object Env :
170- opaque type Env = Map [Symbol , Value ]
171-
172- val empty : Env = Map .empty
173-
174- def apply (bindings : Map [Symbol , Value ]): Env = bindings
175-
176- def apply (ddef : DefDef , args : List [Value ])(using Context ): Env =
177- val params = ddef.termParamss.flatten.map(_.symbol)
178- assert(args.size == params.size, " arguments = " + args.size + " , params = " + params.size)
179- params.zip(args).toMap
180-
181- extension (env : Env )
182- def lookup (sym : Symbol )(using Context ): Value = env(sym)
183-
184- def getOrElse (sym : Symbol , default : Value )(using Context ): Value = env.getOrElse(sym, default)
185-
186- def union (other : Env ): Env = env ++ other
187-
188- def isHot : Boolean = env.values.forall(_ == Hot )
189- end Env
190-
191- type Env = Env .Env
192- inline def env (using env : Env ) = env
193- inline def withEnv [T ](env : Env )(op : Env ?=> T ): T = op(using env)
194-
195- import Env .*
196-
197147 object Promoted :
198148 class PromotionInfo :
199149 var isCurrentObjectPromoted : Boolean = false
@@ -399,7 +349,7 @@ object Semantic:
399349// ----- Checker State -----------------------------------
400350
401351 /** The state that threads through the interpreter */
402- type Contextual [T ] = (Env , Context , Trace , Promoted , Cache , Reporter ) ?=> T
352+ type Contextual [T ] = (Context , Trace , Promoted , Cache , Reporter ) ?=> T
403353
404354// ----- Error Handling -----------------------------------
405355
@@ -692,10 +642,8 @@ object Semantic:
692642 outer.instantiate(klass, klass.primaryConstructor, args)
693643 else
694644 reporter.reportAll(argErrors)
695- withEnv(if isLocal then env else Env .empty) {
696- extendTrace(ddef) {
697- eval(ddef.rhs, ref, cls, cacheResult = true )
698- }
645+ extendTrace(ddef) {
646+ eval(ddef.rhs, ref, cls, cacheResult = true )
699647 }
700648 else if ref.canIgnoreMethodCall(target) then
701649 Hot
@@ -726,15 +674,14 @@ object Semantic:
726674 }
727675
728676 def callConstructor (ctor : Symbol , args : List [ArgInfo ]): Contextual [Value ] = log(" call " + ctor.show + " , args = " + args.map(_.value.show), printer, (_ : Value ).show) {
729- // init "fake" param fields for the secondary constructor
730- def addParamsAsFields (env : Env , ref : Ref , ctorDef : DefDef ) = {
731- val paramSyms = ctorDef.termParamss.flatten.map(_.symbol)
732- paramSyms.map { acc =>
733- val value = env.lookup(acc)
734- ref.updateField(acc, value)
735- printer.println(acc.show + " initialized with " + value)
736- }
737- }
677+ // init "fake" param fields for parameters of primary and secondary constructors
678+ def addParamsAsFields (args : List [Value ], ref : Ref , ctorDef : DefDef ) =
679+ val params = ctorDef.termParamss.flatten.map(_.symbol)
680+ assert(args.size == params.size, " arguments = " + args.size + " , params = " + params.size)
681+ for (param, value) <- params.zip(args) do
682+ ref.updateField(param, value)
683+ printer.println(param.show + " initialized with " + value)
684+
738685 value match {
739686 case Hot | Cold | _ : RefSet | _ : Fun =>
740687 report.error(" unexpected constructor call, meth = " + ctor + " , value = " + value, trace.toVector.last)
@@ -744,13 +691,12 @@ object Semantic:
744691 if ctor.hasSource then
745692 val cls = ctor.owner.enclosingClass.asClass
746693 val ddef = ctor.defTree.asInstanceOf [DefDef ]
747- val env2 = Env (ddef, args.map(_.value).widenArgs)
694+ val args2 = args.map(_.value).widenArgs
695+ addParamsAsFields(args2, ref, ddef)
748696 if ctor.isPrimaryConstructor then
749- given Env = env2
750697 val tpl = cls.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
751698 extendTrace(cls.defTree) { init(tpl, ref, cls) }
752699 else
753- addParamsAsFields(env2, ref, ddef)
754700 val initCall = ddef.rhs match
755701 case Block (call :: _, _) => call
756702 case call => call
@@ -763,14 +709,13 @@ object Semantic:
763709 if ctor.hasSource then
764710 val cls = ctor.owner.enclosingClass.asClass
765711 val ddef = ctor.defTree.asInstanceOf [DefDef ]
766- val env2 = Env (ddef, args.map(_.value).widenArgs)
712+ val args2 = args.map(_.value).widenArgs
713+ addParamsAsFields(args2, ref, ddef)
767714 if ctor.isPrimaryConstructor then
768- given Env = env2
769715 val tpl = cls.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
770716 extendTrace(cls.defTree) { eval(tpl, ref, cls, cacheResult = true ) }
771717 ref
772718 else
773- addParamsAsFields(env2, ref, ddef)
774719 extendTrace(ddef) { eval(ddef.rhs, ref, cls, cacheResult = true ) }
775720 else if ref.canIgnoreMethodCall(ctor) then
776721 Hot
@@ -1057,16 +1002,18 @@ object Semantic:
10571002 val thisRef = task.value
10581003 val tpl = thisRef.klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
10591004
1060- val paramValues = tpl.constr.termParamss.flatten.map(param => param.symbol -> Hot ).toMap
1061-
10621005 @ tailrec
10631006 def iterate (): Unit = {
10641007 given Promoted = Promoted .empty
10651008 given Trace = Trace .empty.add(thisRef.klass.defTree)
1066- given Env = Env (paramValues)
10671009 given reporter : Reporter .BufferedReporter = new Reporter .BufferedReporter
10681010
10691011 thisRef.ensureFresh()
1012+
1013+ // set up constructor parameters
1014+ for param <- tpl.constr.termParamss.flatten do
1015+ thisRef.updateField(param.symbol, Hot )
1016+
10701017 log(" checking " + task) { eval(tpl, thisRef, thisRef.klass) }
10711018 reporter.errors.foreach(_.issue)
10721019
@@ -1433,7 +1380,7 @@ object Semantic:
14331380 /** Initialize part of an abstract object in `klass` of the inheritance chain */
14341381 def init (tpl : Template , thisV : Ref , klass : ClassSymbol ): Contextual [Value ] = log(" init " + klass.show, printer, (_ : Value ).show) {
14351382 val paramsMap = tpl.constr.termParamss.flatten.map { vdef =>
1436- vdef.name -> env.lookup (vdef.symbol)
1383+ vdef.name -> thisV.objekt.field (vdef.symbol)
14371384 }.toMap
14381385
14391386 // init param fields
@@ -1446,7 +1393,7 @@ object Semantic:
14461393 // Tasks is used to schedule super constructor calls.
14471394 // Super constructor calls are delayed until all outers are set.
14481395 type Tasks = mutable.ArrayBuffer [() => Unit ]
1449- def superCall (tref : TypeRef , ctor : Symbol , args : List [ArgInfo ], tasks : Tasks )( using Env ) : Unit =
1396+ def superCall (tref : TypeRef , ctor : Symbol , args : List [ArgInfo ], tasks : Tasks ): Unit =
14501397 val cls = tref.classSymbol.asClass
14511398 // update outer for super class
14521399 val res = outerValue(tref, thisV, klass)
@@ -1461,7 +1408,7 @@ object Semantic:
14611408 }
14621409
14631410 // parents
1464- def initParent (parent : Tree , tasks : Tasks )( using Env ) =
1411+ def initParent (parent : Tree , tasks : Tasks ) =
14651412 parent match
14661413 case tree @ Block (stats, NewExpr (tref, New (tpt), ctor, argss)) => // can happen
14671414 eval(stats, thisV, klass)
@@ -1479,8 +1426,6 @@ object Semantic:
14791426 // see spec 5.1 about "Template Evaluation".
14801427 // https://www.scala-lang.org/files/archive/spec/2.13/05-classes-and-objects.html
14811428 if ! klass.is(Flags .Trait ) then
1482- given Env = Env .empty
1483-
14841429 // outers are set first
14851430 val tasks = new mutable.ArrayBuffer [() => Unit ]
14861431
@@ -1526,18 +1471,16 @@ object Semantic:
15261471 // class body
15271472 if thisV.isThisRef || ! thisV.asInstanceOf [Warm ].isPopulatingParams then tpl.body.foreach {
15281473 case vdef : ValDef if ! vdef.symbol.is(Flags .Lazy ) && ! vdef.rhs.isEmpty =>
1529- given Env = Env .empty
15301474 val res = eval(vdef.rhs, thisV, klass)
15311475 thisV.updateField(vdef.symbol, res)
15321476 fieldsChanged = true
15331477
15341478 case _ : MemberDef =>
15351479
15361480 case tree =>
1537- if fieldsChanged && thisV.isThisRef then thisV.asInstanceOf [ThisRef ].tryPromoteCurrentObject()
1481+ if fieldsChanged && thisV.isThisRef then
1482+ thisV.asInstanceOf [ThisRef ].tryPromoteCurrentObject()
15381483 fieldsChanged = false
1539-
1540- given Env = Env .empty
15411484 eval(tree, thisV, klass)
15421485 }
15431486
0 commit comments