Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion community-build/community-projects/scalatest
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class ScalaSettings extends Settings.SettingGroup {
val YemitTastyInClass: Setting[Boolean] = BooleanSetting("-Yemit-tasty-in-class", "Generate tasty in the .class file and add an empty *.hasTasty file.")
val YlogClasspath: Setting[Boolean] = BooleanSetting("-Ylog-classpath", "Output information about what classpath is being applied.")
val YdisableFlatCpCaching: Setting[Boolean] = BooleanSetting("-YdisableFlatCpCaching", "Do not cache flat classpath representation of classpath elements from jars across compiler instances.")
val Yscala3ImplicitScopes: Setting[Boolean] = BooleanSetting("-Yscala3ImplicitScopes", "Use Scala 3 implicit scopes rules under -language:Scala2")

val Yscala2Unpickler: Setting[String] = StringSetting("-Yscala2-unpickler", "", "Control where we may get Scala 2 symbols from. This is either \"always\", \"never\", or a classpath.", "always")
// TODO: Remove once we drop support for 2.12 standard library
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import dotty.tools.dotc.core.Types._
import dotty.tools.dotc.core.tasty.TreePickler.Hole
import dotty.tools.dotc.core.tasty.{PositionPickler, TastyPickler, TastyPrinter, TastyString}
import dotty.tools.dotc.core.tasty.TreeUnpickler.UnpickleMode
import dotty.tools.dotc.tastyreflect.ReflectionImpl

import scala.internal.quoted._
import scala.reflect.ClassTag
Expand Down Expand Up @@ -47,7 +48,7 @@ object PickledQuotes {
forceAndCleanArtefacts.transform(unpickled)
case expr: TastyTreeExpr[Tree] @unchecked => healOwner(expr.tree)
case expr: FunctionAppliedTo[_] =>
functionAppliedTo(quotedExprToTree(expr.f), expr.args.map(arg => quotedExprToTree(arg)).toList)
functionAppliedTo(quotedExprToTree(expr.f), expr.args.map(arg => quotedExprToTree(arg(new scala.quoted.QuoteContext(ReflectionImpl(ctx))))).toList)
}

/** Transform the expression into its fully spliced TypeTree */
Expand Down
5 changes: 3 additions & 2 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1273,14 +1273,15 @@ class TreeUnpickler(reader: TastyReader,
val args = until(end)(readTerm())
val splice = splices(idx)
def wrap(arg: Tree) =
if (arg.isTerm) new TastyTreeExpr(arg)
if (arg.isTerm) given (qctx: scala.quoted.QuoteContext) => new TastyTreeExpr(arg)
else new TreeType(arg)
val reifiedArgs = args.map(wrap)
val filled = if (isType) {
val quotedType = splice.asInstanceOf[Seq[Any] => quoted.Type[_]](reifiedArgs)
PickledQuotes.quotedTypeToTree(quotedType)
} else {
val quotedExpr = splice.asInstanceOf[Seq[Any] => quoted.Expr[_]](reifiedArgs)
val splice1 = splice.asInstanceOf[Seq[Any] => given scala.quoted.QuoteContext => quoted.Expr[_]]
val quotedExpr = splice1(reifiedArgs) given new scala.quoted.QuoteContext(tastyreflect.ReflectionImpl(ctx))
PickledQuotes.quotedExprToTree(quotedExpr)
}
// We need to make sure a hole is created with the source file of the surrounding context, even if
Expand Down
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@ import dotty.tools.dotc.core.Decorators._
import dotty.tools.dotc.tastyreflect.FromSymbol.{definitionFromSym, packageDefFromSym}
import dotty.tools.dotc.parsing.Parsers.Parser
import dotty.tools.dotc.typer.Implicits.{AmbiguousImplicits, DivergingImplicit, NoMatchingImplicits, SearchFailure, SearchFailureType}
import dotty.tools.dotc.util.SourceFile
import dotty.tools.dotc.util.{SourceFile, SourcePosition, Spans}

import scala.tasty.reflect.Kernel

class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.SourcePosition) extends Kernel {
class KernelImpl(val rootContext: core.Contexts.Context) extends Kernel {

private implicit def ctx: core.Contexts.Context = rootContext

def settings: Settings = rootContext.settings

def rootPosition: util.SourcePosition =
tastyreflect.MacroExpansion.position.getOrElse(SourcePosition(rootContext.source, Spans.NoSpan))

//
// CONTEXT
//
Expand Down
18 changes: 18 additions & 0 deletions compiler/src/dotty/tools/dotc/tastyreflect/MacroExpansion.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package dotty.tools.dotc.tastyreflect

import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core._
import dotty.tools.dotc.core.Contexts._
import dotty.tools.dotc.util.{Property, SourcePosition, Spans}

object MacroExpansion {

private val MacroExpansionPosition = new Property.Key[SourcePosition]

def position(implicit ctx: Context): Option[SourcePosition] =
ctx.property(MacroExpansionPosition)

def context(inlinedFrom: tpd.Tree)(implicit ctx: Context): Context =
ctx.fresh.setProperty(MacroExpansionPosition, SourcePosition(inlinedFrom.source, inlinedFrom.span)).withSource(inlinedFrom.source)

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@ package dotty.tools.dotc.tastyreflect

import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core._
import dotty.tools.dotc.util.{SourcePosition, Spans}
import dotty.tools.dotc.core.Contexts._

import scala.quoted.show.SyntaxHighlight

object ReflectionImpl {

def apply(rootContext: Contexts.Context): scala.tasty.Reflection =
apply(rootContext, SourcePosition(rootContext.source, Spans.NoSpan))

def apply(rootContext: Contexts.Context, rootPosition: SourcePosition): scala.tasty.Reflection =
new scala.tasty.Reflection(new KernelImpl(rootContext, rootPosition))
new scala.tasty.Reflection(new KernelImpl(rootContext))

def showTree(tree: tpd.Tree)(implicit ctx: Contexts.Context): String = {
val refl = new scala.tasty.Reflection(new KernelImpl(ctx, tree.sourcePos))
val refl = new scala.tasty.Reflection(new KernelImpl(MacroExpansion.context(tree)))
val reflCtx = ctx.asInstanceOf[refl.Context]
val reflTree = tree.asInstanceOf[refl.Tree]
val syntaxHighlight =
Expand Down
51 changes: 27 additions & 24 deletions compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ class ReifyQuotes extends MacroTransform {
*/
override protected def transformQuotation(body: Tree, quote: Tree)(implicit ctx: Context): Tree = {
val isType = quote.symbol eq defn.InternalQuoted_typeQuote
assert(!(body.symbol.isSplice && (body.isInstanceOf[GenericApply[_]] || body.isInstanceOf[Select])))
if (level > 0) {
val body1 = nested(isQuote = true).transform(body)(quoteContext)
super.transformQuotation(body1, quote)
Expand Down Expand Up @@ -209,35 +208,37 @@ class ReifyQuotes extends MacroTransform {
qctx
}

def liftedValue[T](value: T, name: TermName, qctx: Tree) =
ref(defn.LiftableModule).select(name).select("toExpr".toTermName).appliedTo(Literal(Constant(value))).select(nme.apply).appliedTo(qctx)

def pickleAsValue[T](value: T) = value match {
case null => ref(defn.QuotedExprModule).select("nullExpr".toTermName).appliedTo(qctx)
case _: Unit => ref(defn.QuotedExprModule).select("unitExpr".toTermName).appliedTo(qctx)
case _: Boolean => liftedValue(value, "Liftable_Boolean_delegate".toTermName, qctx)
case _: Byte => liftedValue(value, "Liftable_Byte_delegate".toTermName, qctx)
case _: Short => liftedValue(value, "Liftable_Short_delegate".toTermName, qctx)
case _: Int => liftedValue(value, "Liftable_Int_delegate".toTermName, qctx)
case _: Long => liftedValue(value, "Liftable_Long_delegate".toTermName, qctx)
case _: Float => liftedValue(value, "Liftable_Float_delegate".toTermName, qctx)
case _: Double => liftedValue(value, "Liftable_Double_delegate".toTermName, qctx)
case _: Char => liftedValue(value, "Liftable_Char_delegate".toTermName, qctx)
case _: String => liftedValue(value, "Liftable_String_delegate".toTermName, qctx)
def liftedValue[T](value: T, name: TermName) =
ref(defn.LiftableModule).select(name).select("toExpr".toTermName).appliedTo(Literal(Constant(value)))

def pickleAsValue[T](value: T) = {
value match {
case null => ref(defn.QuotedExprModule).select("nullExpr".toTermName)
case _: Unit => ref(defn.QuotedExprModule).select("unitExpr".toTermName)
case _: Boolean => liftedValue(value, "Liftable_Boolean_delegate".toTermName)
case _: Byte => liftedValue(value, "Liftable_Byte_delegate".toTermName)
case _: Short => liftedValue(value, "Liftable_Short_delegate".toTermName)
case _: Int => liftedValue(value, "Liftable_Int_delegate".toTermName)
case _: Long => liftedValue(value, "Liftable_Long_delegate".toTermName)
case _: Float => liftedValue(value, "Liftable_Float_delegate".toTermName)
case _: Double => liftedValue(value, "Liftable_Double_delegate".toTermName)
case _: Char => liftedValue(value, "Liftable_Char_delegate".toTermName)
case _: String => liftedValue(value, "Liftable_String_delegate".toTermName)
}
}

def pickleAsTasty() = {
val meth =
if (isType) ref(defn.Unpickler_unpickleType).appliedToType(originalTp)
else ref(defn.Unpickler_unpickleExpr).appliedToType(originalTp.widen)
def wildcardQuotedType = defn.QuotedTypeClass.typeRef.appliedTo(WildcardType)
val spliceResType =
if (isType) wildcardQuotedType
else defn.QuotedExprClass.typeRef.appliedTo(defn.AnyType) | wildcardQuotedType
meth.appliedTo(
liftList(PickledQuotes.pickleQuote(body).map(x => Literal(Constant(x))), defn.StringType),
liftList(splices, defn.FunctionType(1).appliedTo(defn.SeqType.appliedTo(defn.AnyType), spliceResType)))
if (isType) defn.QuotedTypeClass.typeRef.appliedTo(WildcardType)
else defn.FunctionType(1, isContextual = true).appliedTo(defn.QuoteContextClass.typeRef, defn.QuotedExprClass.typeRef.appliedTo(defn.AnyType)) | defn.QuotedTypeClass.typeRef.appliedTo(WildcardType)
val pickledQuoteStrings = liftList(PickledQuotes.pickleQuote(body).map(x => Literal(Constant(x))), defn.StringType)
val splicesList = liftList(splices, defn.FunctionType(1).appliedTo(defn.SeqType.appliedTo(defn.AnyType), spliceResType))
meth.appliedTo(pickledQuoteStrings, splicesList)
}

if (splices.nonEmpty) pickleAsTasty()
else if (isType) {
def tag(tagName: String) = ref(defn.QuotedTypeModule).select(tagName.toTermName).appliedTo(qctx)
Expand Down Expand Up @@ -316,7 +317,7 @@ class ReifyQuotes extends MacroTransform {
assert(tpw.isInstanceOf[ValueType])
val argTpe =
if (tree.isType) defn.QuotedTypeClass.typeRef.appliedTo(tpw)
else defn.QuotedExprClass.typeRef.appliedTo(tpw)
else defn.FunctionType(1, isContextual = true).appliedTo(defn.QuoteContextClass.typeRef, defn.QuotedExprClass.typeRef.appliedTo(tpw))
val selectArg = arg.select(nme.apply).appliedTo(Literal(Constant(i))).cast(argTpe)
val capturedArg = SyntheticValDef(UniqueName.fresh(tree.symbol.name.toTermName).toTermName, selectArg)
i += 1
Expand Down Expand Up @@ -357,7 +358,9 @@ class ReifyQuotes extends MacroTransform {
val tree2 = transform(tree)
capturers --= outer.localSymbols

seq(captured.result().valuesIterator.toList, tree2)
val captures = captured.result().valuesIterator.toList
if (captures.isEmpty) tree2
else Block(captures, tree2)
}

/** Returns true if this tree will be captured by `makeLambda`. Checks phase consistency and presence of capturer. */
Expand Down
Loading