All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dotty.tools.dotc.transform.TransformByNameApply.scala Maven / Gradle / Ivy

The newest version!
package dotty.tools
package dotc
package transform

import MegaPhase._
import core._
import Symbols._
import SymDenotations._
import Contexts._
import Types._
import Flags._
import Decorators._
import DenotTransformers._
import core.StdNames.nme
import ast.Trees._
import reporting.trace

/** Abstract base class of ByNameClosures and ElimByName, factoring out the
 *  common functionality to transform arguments of by-name parameters.
 */
abstract class TransformByNameApply extends MiniPhase { thisPhase: DenotTransformer =>
  import ast.tpd._

  /** The info of the tree's symbol before it is potentially transformed in this phase */
  private def originalDenotation(tree: Tree)(implicit ctx: Context) =
    tree.symbol.denot(ctx.withPhase(thisPhase))

  /** If denotation had an ExprType before, it now gets a function type */
  protected def exprBecomesFunction(symd: SymDenotation)(implicit ctx: Context): Boolean =
    symd.is(Param) || symd.is(ParamAccessor, butNot = Method)

  protected def isByNameRef(tree: Tree)(implicit ctx: Context): Boolean = {
    val origDenot = originalDenotation(tree)
    origDenot.info.isInstanceOf[ExprType] && exprBecomesFunction(origDenot)
  }

  def mkByNameClosure(arg: Tree, argType: Type)(implicit ctx: Context): Tree = unsupported(i"mkClosure($arg)")

  override def transformApply(tree: Apply)(implicit ctx: Context): Tree =
    trace(s"transforming ${tree.show} at phase ${ctx.phase}", show = true) {

    def transformArg(arg: Tree, formal: Type): Tree = formal.dealias match {
      case formalExpr: ExprType =>
        var argType = arg.tpe.widenIfUnstable
        if (defn.isBottomType(argType)) argType = formal.widenExpr
        def wrap(arg: Tree) =
          ref(defn.cbnArg).appliedToType(argType).appliedTo(arg).withSpan(arg.span)
        arg match {
          case Apply(Select(qual, nme.apply), Nil)
          if qual.tpe.derivesFrom(defn.FunctionClass(0)) && isPureExpr(qual) =>
            wrap(qual)
          case _ =>
            if (isByNameRef(arg) || arg.symbol == defn.cbnArg) arg
            else wrap(mkByNameClosure(arg, argType))
        }
      case _ =>
        arg
    }

    val mt @ MethodType(_) = tree.fun.tpe.widen
    val args1 = tree.args.zipWithConserve(mt.paramInfos)(transformArg)
    cpy.Apply(tree)(tree.fun, args1)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy