Skip to content

Commit 6c7f170

Browse files
committed
Initial implementation of object initialization
1 parent a8c70d5 commit 6c7f170

File tree

1 file changed

+92
-18
lines changed

1 file changed

+92
-18
lines changed

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 92 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)