@@ -93,11 +93,11 @@ class Objects(using Context @constructorOnly):
9393 * | UnknownValue // values whose source are unknown at compile time
9494 * vs ::= ValueSet(Set(ve)) // set of abstract values
9595 * Value ::= ve | vs | Package
96- * Ref ::= ObjectRef | InstanceRef | ArrayRef // values that represent a reference to some (global or instance) object
96+ * Ref ::= ObjectRef | InstanceRef | ArrayRef // values that represent a reference to some (global or instance) object
9797 * RefSet ::= Set(ref) // set of refs
9898 * Bottom ::= RefSet(Empty) // unreachable code
9999 * ThisValue ::= Ref | RefSet // possible values for 'this'
100- * EnvRef(meth , ownerObject) // represents environments for methods or functions
100+ * EnvRef(tree , ownerObject) // represents environments for methods or functions
101101 * EnvSet ::= Set(EnvRef)
102102 * InstanceBody ::= (valsMap: Map[Symbol, Value],
103103 outersMap: Map[ClassSymbol, Value],
@@ -409,9 +409,9 @@ class Objects(using Context @constructorOnly):
409409 *
410410 * For local variables in rhs of class field definitions, the `meth` is the primary constructor.
411411 */
412- case class EnvRef (meth : Symbol , owner : ClassSymbol )(using Trace ) extends Scope :
412+ case class EnvRef (tree : Tree , owner : ClassSymbol )(using Trace ) extends Scope :
413413 def show (using Context ) =
414- " meth : " + meth .show + " \n " +
414+ " tree : " + tree .show + " \n " +
415415 " owner: " + owner.show
416416
417417 def valValue (sym : Symbol )(using EnvMap .EnvMapMutableData ): Value = EnvMap .readVal(this , sym)
@@ -454,36 +454,49 @@ class Objects(using Context @constructorOnly):
454454
455455 val NoEnv = EnvSet (Set .empty)
456456
457- /** An empty environment can be used for non-method environments, e.g., field initializers.
458- *
459- * The owner for the local environment for field initializers is the primary constructor of the
460- * enclosing class.
461- */
462- def emptyEnv (meth : Symbol )(using Context , State .Data , EnvMap .EnvMapMutableData , Trace ): EnvRef =
463- _of(Map .empty, meth, Bottom , NoEnv )
464-
465457 def valValue (x : Symbol )(using env : EnvRef , ctx : Context , trace : Trace , envMap : EnvMap .EnvMapMutableData ): Value =
466458 if env.hasVal(x) then
467459 env.valValue(x)
468460 else
469461 report.warning(" [Internal error] Value not found " + x.show + " \n env = " + env.show + " . " + Trace .show, Trace .position)
470462 Bottom
471463
472- private [Env ] def _of (argMap : Map [Symbol , Value ], meth : Symbol , thisV : ThisValue , outerEnv : EnvSet )
464+ /** The method of creating an Env that evaluates `tree` */
465+ private [Env ] def _of (argMap : Map [Symbol , Value ], tree : Tree , thisV : ThisValue , outerEnv : EnvSet )
473466 (using State .Data , EnvMap .EnvMapMutableData , Trace ): EnvRef =
474- val env = EnvRef (meth , State .currentObject)
467+ val env = EnvRef (tree , State .currentObject)
475468 argMap.foreach(env.initVal(_, _))
476469 env.initThisV(thisV)
477470 env.initOuterEnvs(outerEnv)
478471 env
479472
473+ /**
474+ * Creates an environment that evaluates the body of a method or the body of a closure
475+ */
476+ def ofDefDef (ddef : DefDef , args : List [Value ], thisV : ThisValue , outerEnv : EnvSet )
477+ (using State .Data , EnvMap .EnvMapMutableData , Trace ): EnvRef =
478+ val params = ddef.termParamss.flatten.map(_.symbol)
479+ assert(args.size == params.size, " arguments = " + args.size + " , params = " + params.size)
480+ // assert(ddef.symbol.owner.is(Method) ^ (outerEnv == NoEnv), "ddef.owner = " + ddef.symbol.owner.show + ", outerEnv = " + outerEnv + ", " + ddef.source)
481+ _of(params.zip(args).toMap, ddef, thisV, outerEnv)
482+
483+
484+ /**
485+ * Creates an environment that evaluates a lazy val with `tree` as rhs
486+ * or evaluates a by-name parameter where `tree` is the argument tree
487+ */
488+ def ofByName (sym : Symbol , tree : Tree , thisV : ThisValue , outerEnv : EnvSet )
489+ (using State .Data , EnvMap .EnvMapMutableData , Trace ): EnvRef =
490+ assert((sym.is(Flags .Param ) && sym.info.isInstanceOf [ExprType ]) || sym.is(Flags .Lazy ));
491+ _of(Map .empty, tree, thisV, outerEnv)
492+
480493 /**
481494 * The main procedure for searching through the outer chain
482495 * @param target The symbol to search for if `bySymbol = true`; otherwise the method symbol of the target environment
483496 * @param scopeSet The set of scopes as starting point
484497 * @return The scopes that contains symbol `target` or whose method is `target`,
485498 * and the value for `C.this` where C is the enclosing class of the result scopes
486- */
499+ */
487500 private [Env ] def resolveEnvRecur (
488501 target : Symbol , envSet : EnvSet , bySymbol : Boolean = true )
489502 : Contextual [Option [EnvSet ]] = log(" Resolving environment, target = " + target + " , envSet = " + envSet, printer) {
@@ -493,7 +506,7 @@ class Objects(using Context @constructorOnly):
493506 if bySymbol then
494507 envSet.envs.filter(_.hasVal(target))
495508 else
496- envSet.envs.filter(_.meth == target)
509+ envSet.envs.filter(env => env.tree. isInstanceOf [ DefDef ] && env.tree. asInstanceOf [ DefDef ].symbol == target)
497510
498511 assert(filter.isEmpty || filter.size == envSet.envs.size, " Either all scopes or no scopes contain " + target)
499512 if (! filter.isEmpty) then
@@ -515,19 +528,6 @@ class Objects(using Context @constructorOnly):
515528 resolveEnvRecur(target, outerEnvsOfThis, bySymbol)
516529 }
517530
518-
519- def ofDefDef (ddef : DefDef , args : List [Value ], thisV : ThisValue , outerEnv : EnvSet )
520- (using State .Data , EnvMap .EnvMapMutableData , Trace ): EnvRef =
521- val params = ddef.termParamss.flatten.map(_.symbol)
522- assert(args.size == params.size, " arguments = " + args.size + " , params = " + params.size)
523- // assert(ddef.symbol.owner.is(Method) ^ (outerEnv == NoEnv), "ddef.owner = " + ddef.symbol.owner.show + ", outerEnv = " + outerEnv + ", " + ddef.source)
524- _of(params.zip(args).toMap, ddef.symbol, thisV, outerEnv)
525-
526- def ofByName (byNameParam : Symbol , thisV : ThisValue , outerEnv : EnvSet )
527- (using State .Data , EnvMap .EnvMapMutableData , Trace ): EnvRef =
528- assert(byNameParam.is(Flags .Param ) && byNameParam.info.isInstanceOf [ExprType ]);
529- _of(Map .empty, byNameParam, thisV, outerEnv)
530-
531531 def setLocalVal (x : Symbol , value : Value )(using scope : Scope , ctx : Context , heap : Heap .MutableData , envMap : EnvMap .EnvMapMutableData ): Unit =
532532 assert(! x.isOneOf(Flags .Param | Flags .Mutable ), " Only local immutable variable allowed" )
533533 scope match
@@ -1191,12 +1191,12 @@ class Objects(using Context @constructorOnly):
11911191
11921192 case ref : Ref =>
11931193 val target = if needResolve then resolve(ref.klass, field) else field
1194- if target.is(Flags .Lazy ) then
1195- given Scope = Env .emptyEnv(target.owner.asInstanceOf [ClassSymbol ].primaryConstructor)
1194+ if target.is(Flags .Lazy ) then // select a lazy field
11961195 if ref.hasVal(target) then
11971196 ref.valValue(target)
11981197 else if target.hasSource then
11991198 val rhs = target.defTree.asInstanceOf [ValDef ].rhs
1199+ given Scope = Env .ofByName(target, rhs, ref, Env .NoEnv )
12001200 val result = eval(rhs, ref, target.owner.asClass, cacheResult = true )
12011201 ref.initVal(target, result)
12021202 result
@@ -1358,8 +1358,8 @@ class Objects(using Context @constructorOnly):
13581358 def evalByNameParam (value : Value ): Contextual [Value ] = value match
13591359 case Fun (code, thisV, klass, scope) =>
13601360 val byNameEnv = scope match {
1361- case ref : Ref => Env .ofByName(sym, thisV, Env .NoEnv )
1362- case env : Env .EnvRef => Env .ofByName(sym, thisV, Env .EnvSet (Set (env)))
1361+ case ref : Ref => Env .ofByName(sym, code, thisV, Env .NoEnv ) // for by-name arguments of constructors
1362+ case env : Env .EnvRef => Env .ofByName(sym, code, thisV, Env .EnvSet (Set (env))) // for by-name arguments of methods/functions
13631363 }
13641364 given Scope = byNameEnv
13651365 eval(code, thisV, klass, cacheResult = true )
@@ -1389,7 +1389,7 @@ class Objects(using Context @constructorOnly):
13891389 else
13901390 if sym.is(Flags .Lazy ) then
13911391 val outerThis = envSet.joinThisV
1392- given Scope = Env .ofByName(sym, outerThis, envSet)
1392+ given Scope = Env .ofByName(sym, sym.defTree, outerThis, envSet)
13931393 val rhs = sym.defTree.asInstanceOf [ValDef ].rhs
13941394 eval(rhs, outerThis, sym.enclosingClass.asClass, cacheResult = true )
13951395 else
@@ -2144,7 +2144,7 @@ class Objects(using Context @constructorOnly):
21442144 thisV
21452145 else
21462146 // `target` must enclose `klass`
2147- assert(klass.enclosingClassNamed (target.name) != NoSymbol , target.show + " does not enclose " + klass.show)
2147+ assert(klass.ownersIterator.contains (target) , target.show + " does not enclose " + klass.show)
21482148 val outerThis = thisV match {
21492149 case ref : Ref => ref.outerValue(klass)
21502150 case refSet : RefSet => refSet.joinOuters(klass)
0 commit comments