@@ -129,50 +129,57 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
129129    Thicket (field, getter)
130130  }
131131
132-   /**  Replace a local lazy val inside a method, 
133-     * with a LazyHolder from 
134-     * dotty.runtime(eg dotty.runtime.LazyInt) 
135-     */  
132+   /**  Desugar a local `lazy val x: Int = <RHS>` into: 
133+    * 
134+    *  ``` 
135+    *  val x$lzy = new scala.runtime.LazyInt() 
136+    * 
137+    *  def x$lzycompute(): Int = x$lzy.synchronized { 
138+    *    if (x$lzy.initialized()) x$lzy.value() 
139+    *    else x$lzy.initialize(<RHS>) 
140+    *      // TODO: Implement Unit-typed lazy val optimization described below 
141+    *      // for a Unit-typed lazy val, this becomes `{ rhs ; x$lzy.initialize() }` 
142+    *      // to avoid passing around BoxedUnit 
143+    *  } 
144+    * 
145+    *  def x(): Int = if (x$lzy.initialized()) x$lzy.value() else x$lzycompute() 
146+    *  ``` 
147+    */  
136148  def  transformLocalDef (x : ValOrDefDef )(implicit  ctx : Context ):  Thicket  =  {
137-       val  valueInitter  =  x.rhs
138-       val  xname  =  x.name.asTermName
139-       val  holderName  =  LazyLocalName .fresh(xname)
140-       val  initName  =  LazyLocalInitName .fresh(xname)
141-       val  tpe  =  x.tpe.widen.resultType.widen
142- 
143-       val  holderType  = 
144-         if  (tpe isRef defn.IntClass ) " LazyInt" 
145-         else  if  (tpe isRef defn.LongClass ) " LazyLong" 
146-         else  if  (tpe isRef defn.BooleanClass ) " LazyBoolean" 
147-         else  if  (tpe isRef defn.FloatClass ) " LazyFloat" 
148-         else  if  (tpe isRef defn.DoubleClass ) " LazyDouble" 
149-         else  if  (tpe isRef defn.ByteClass ) " LazyByte" 
150-         else  if  (tpe isRef defn.CharClass ) " LazyChar" 
151-         else  if  (tpe isRef defn.ShortClass ) " LazyShort" 
152-         else  " LazyRef" 
153- 
154- 
155-       val  holderImpl  =  ctx.requiredClass(" dotty.runtime."   +  holderType)
156- 
157-       val  holderSymbol  =  ctx.newSymbol(x.symbol.owner, holderName, containerFlags, holderImpl.typeRef, coord =  x.pos)
158-       val  initSymbol  =  ctx.newSymbol(x.symbol.owner, initName, initFlags, MethodType (Nil , tpe), coord =  x.pos)
159-       val  result  =  ref(holderSymbol).select(lazyNme.value).withPos(x.pos)
160-       val  flag  =  ref(holderSymbol).select(lazyNme.initialized)
161-       val  initer  =  valueInitter.changeOwnerAfter(x.symbol, initSymbol, this )
162-       val  initBody  = 
163-         adaptToType(
164-           ref(holderSymbol).select(defn.Object_synchronized ).appliedTo(
165-             adaptToType(mkNonThreadSafeDef(result, flag, initer, nullables =  Nil ), defn.ObjectType )),
166-           tpe)
167-       val  initTree  =  DefDef (initSymbol, initBody)
168-       val  holderTree  =  ValDef (holderSymbol, New (holderImpl.typeRef, List ()))
169-       val  methodBody  =  tpd.If (flag.ensureApplied,
170-         result.ensureApplied,
171-         ref(initSymbol).ensureApplied).ensureConforms(tpe)
172- 
173-       val  methodTree  =  DefDef (x.symbol.asTerm, methodBody)
174-       ctx.debuglog(s " found a lazy val  ${x.show}, \n rewrote with  ${holderTree.show}" )
175-       Thicket (holderTree, initTree, methodTree)
149+     val  xname  =  x.name.asTermName
150+     val  tpe  =  x.tpe.widen.resultType.widen
151+ 
152+     //  val x$lzy = new scala.runtime.LazyInt()
153+     val  holderName  =  LazyLocalName .fresh(xname)
154+     val  holderImpl  =  defn.LazyHolder ()(ctx)(tpe.typeSymbol)
155+     val  holderSymbol  =  ctx.newSymbol(x.symbol.owner, holderName, containerFlags, holderImpl.typeRef, coord =  x.pos)
156+     val  holderTree  =  ValDef (holderSymbol, New (holderImpl.typeRef, Nil ))
157+ 
158+     val  holderRef  =  ref(holderSymbol)
159+     val  getValue  =  holderRef.select(lazyNme.value).ensureApplied.withPos(x.pos)
160+     val  initialized  =  holderRef.select(lazyNme.initialized).ensureApplied
161+ 
162+     //  def x$lzycompute(): Int = x$lzy.synchronized {
163+     //    if (x$lzy.initialized()) x$lzy.value()
164+     //    else x$lzy.initialize(<RHS>)
165+     //  }
166+     val  initName  =  LazyLocalInitName .fresh(xname)
167+     val  initSymbol  =  ctx.newSymbol(x.symbol.owner, initName, initFlags, MethodType (Nil , tpe), coord =  x.pos)
168+     val  rhs  =  x.rhs.changeOwnerAfter(x.symbol, initSymbol, this )
169+     val  initialize  =  holderRef.select(lazyNme.initialize).appliedTo(rhs)
170+     val  initBody  = 
171+       adaptToType(
172+         holderRef.select(defn.Object_synchronized ).appliedTo(
173+           adaptToType(If (initialized, getValue, initialize), defn.ObjectType )),
174+         tpe)
175+     val  initTree  =  DefDef (initSymbol, initBody)
176+ 
177+     //  def x(): Int = if (x$lzy.initialized()) x$lzy.value() else x$lzycompute()
178+     val  accessorBody  =  If (initialized, getValue, ref(initSymbol).ensureApplied).ensureConforms(tpe)
179+     val  accessor  =  DefDef (x.symbol.asTerm, accessorBody)
180+ 
181+     ctx.debuglog(s " found a lazy val  ${x.show}, \n rewrote with  ${holderTree.show}" )
182+     Thicket (holderTree, initTree, accessor)
176183  }
177184
178185
@@ -458,6 +465,7 @@ object LazyVals {
458465    val  result :  TermName       =  " result"  .toTermName
459466    val  value :  TermName        =  " value"  .toTermName
460467    val  initialized :  TermName  =  " initialized"  .toTermName
468+     val  initialize :  TermName   =  " initialize"  .toTermName
461469    val  retry :  TermName        =  " retry"  .toTermName
462470  }
463471}
0 commit comments