@@ -242,6 +242,8 @@ class Semantic {
242242 // widen the outer to finitize addresses
243243 val outer = if addr.outer.isInstanceOf [Addr ] then addr.copy(outer = Cold ) else addr
244244 val addr2 = Addr (klass, outer)
245+ if ! heap.contains(addr2) then
246+ heap(addr2) = Objekt (klass, Map .empty, Map (klass -> outer))
245247 addr2.call(ctor, superType = NoType , source)
246248
247249 case Fun (body, thisV, klass) =>
@@ -295,28 +297,17 @@ class Semantic {
295297 assert(name.isTermName, " type trees should not reach here" )
296298 cases(expr.tpe, thisV, klass, expr)
297299
298- case NewExpr (New (tpt), ctor, argss) =>
299- def typeRefOf (tp : Type ): TypeRef = tp.dealias.typeConstructor match {
300- case tref : TypeRef => tref
301- case hklambda : HKTypeLambda => typeRefOf(hklambda.resType)
302- }
303-
300+ case NewExpr (tref, New (tpt), ctor, argss) =>
304301 // check args
305302 val args = argss.flatten
306303 val ress = args.map { arg =>
307304 eval(arg, thisV, klass).ensureHot(" May use initialized value as arguments" , arg)
308305 }
309306 val errors = ress.flatMap(_.errors)
310307
311- val tref = typeRefOf(tpt.tpe)
312308 val cls = tref.classSymbol.asClass
313- if (tref.prefix == NoPrefix ) then
314- val enclosing = cls.owner.lexicallyEnclosingClass.asClass
315- val outer = resolveThis(enclosing, thisV, klass)
316- Result (outer, errors).instantiate(cls, ctor, expr)
317- else
318- val res = cases(tref.prefix, thisV, klass, tpt)
319- (res ++ errors).instantiate(cls, ctor, expr)
309+ val res = outerValue(tref, thisV, klass, tpt)
310+ (res ++ errors).instantiate(cls, ctor, expr)
320311
321312 case Call (ref, argss) =>
322313 // check args
@@ -504,8 +495,85 @@ class Semantic {
504495 case _ => ???
505496 }
506497
507- /** Initialize an abstract object */
508- def init (klass : Symbol , thisV : Addr ): Result = ???
498+ /** Compute the outer value that correspond to `tref.prefix` */
499+ def outerValue (tref : TypeRef , thisV : Value , klass : ClassSymbol , source : Tree )(using Context ): Result =
500+ val cls = tref.classSymbol.asClass
501+ if (tref.prefix == NoPrefix ) then
502+ val enclosing = cls.owner.lexicallyEnclosingClass.asClass
503+ val outerV = resolveThis(enclosing, thisV, klass)
504+ Result (outerV, noErrors)
505+ else
506+ cases(tref.prefix, thisV, klass, source)
507+
508+ /** Initialize part of an abstract object in `klass` of the inheritance chain */
509+ def init (klass : ClassSymbol , thisV : Addr )(using Context ): Result =
510+ val errorBuffer = new mutable.ArrayBuffer [Error ]
511+
512+ val tpl = klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
513+
514+ // init param fields
515+ var obj = heap(thisV)
516+ klass.paramAccessors.foreach { acc =>
517+ if (! acc.is(Flags .Method )) {
518+ traceIndented(acc.show + " initialized" , printer)
519+ obj = obj.copy(fields = obj.fields.updated(acc, Hot ))
520+ }
521+ }
522+ heap(thisV) = obj
523+
524+ def superCall (tref : TypeRef , ctor : Symbol , source : Tree ): Unit =
525+ // update outer for super class
526+ val cls = tref.classSymbol.asClass
527+ val res = outerValue(tref, thisV, klass, source)
528+ errorBuffer ++= res.errors
529+ val obj = heap(thisV)
530+ val obj2 = obj.copy(outers = obj.outers.updated(cls, res.value))
531+ heap(thisV) = obj2
532+
533+ // follow constructor
534+ val res2 = thisV.call(ctor, superType = NoType , source)
535+ errorBuffer ++= res2.errors
536+
537+ // parents
538+ tpl.parents.foreach {
539+ case tree @ Block (stats, NewExpr (tref, New (tpt), ctor, argss)) =>
540+ eval(stats, thisV, klass).foreach { res => errorBuffer ++= res.errors }
541+ argss.flatten.foreach { arg =>
542+ val res = eval(arg, thisV, klass)
543+ res.ensureHot(" Argument must be an initialized value" , arg)
544+ errorBuffer ++ res.errors
545+ }
546+ superCall(tref, ctor, tree)
547+
548+ case tree @ NewExpr (tref, New (tpt), ctor, argss) =>
549+ argss.flatten.foreach { arg =>
550+ val res = eval(arg, thisV, klass)
551+ res.ensureHot(" Argument must be an initialized value" , arg)
552+ errorBuffer ++ res.errors
553+ }
554+ superCall(tref, ctor, tree)
555+
556+ case ref : RefTree =>
557+ val tref = ref.tpe.asInstanceOf [TypeRef ]
558+ superCall(tref, tref.classSymbol.primaryConstructor, ref)
559+ }
560+
561+ // class body
562+ tpl.body.foreach {
563+ case vdef : ValDef =>
564+ val res = eval(vdef.rhs, thisV, klass)
565+ errorBuffer ++ res.errors
566+ val obj = heap(thisV)
567+ val obj2 = obj.copy(fields = obj.fields.updated(vdef.symbol, res.value))
568+ heap(thisV) = obj2
569+
570+ case _ : MemberDef =>
571+
572+ case tree =>
573+ eval(tree, thisV, klass)
574+ }
575+
576+ Result (thisV, errorBuffer.toList)
509577
510578// ----- Utility methods and extractors --------------------------------
511579
@@ -525,10 +593,16 @@ class Semantic {
525593 }
526594
527595 object NewExpr {
528- def unapply (tree : Tree )(using Context ): Option [(New , Symbol , List [List [Tree ]])] =
596+ private def typeRefOf (tp : Type )(using Context ): TypeRef = tp.dealias.typeConstructor match {
597+ case tref : TypeRef => tref
598+ case hklambda : HKTypeLambda => typeRefOf(hklambda.resType)
599+ }
600+
601+ def unapply (tree : Tree )(using Context ): Option [(TypeRef , New , Symbol , List [List [Tree ]])] =
529602 tree match
530603 case Call (fn @ Select (newTree : New , init), argss) if init == nme.CONSTRUCTOR =>
531- Some ((newTree, fn.symbol, argss))
604+ val tref = typeRefOf(newTree.tpe)
605+ Some ((tref, newTree, fn.symbol, argss))
532606 case _ => None
533607 }
534608}
0 commit comments