Skip to content

Add QuotePattern AST #17935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
15 changes: 15 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,21 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
if tree.symbol.isTypeSplice then Some(tree.qualifier) else None
}

extension (tree: tpd.Quote)
/** Type of the quoted expression as seen from outside the quote */
def bodyType(using Context): Type =
val quoteType = tree.tpe // `Quotes ?=> Expr[T]` or `Quotes ?=> Type[T]`
val exprType = quoteType.argInfos.last // `Expr[T]` or `Type[T]`
exprType.argInfos.head // T
end extension

extension (tree: tpd.QuotePattern)
/** Type of the quoted pattern */
def bodyType(using Context): Type =
val quoteType = tree.tpe // `Expr[T]` or `Type[T]`
quoteType.argInfos.head // T
end extension

/** Extractor for not-null assertions.
* A not-null assertion for reference `x` has the form `x.$asInstanceOf$[x.type & T]`.
*/
Expand Down
11 changes: 0 additions & 11 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -704,12 +704,6 @@ object Trees {
/** Is this a type quote `'[tpe]' */
def isTypeQuote = body.isType

/** Type of the quoted expression as seen from outside the quote */
def bodyType(using Context): Type =
val quoteType = typeOpt // `Quotes ?=> Expr[T]` or `Quotes ?=> Type[T]`
val exprType = quoteType.argInfos.last // `Expr[T]` or `Type[T]`
exprType.argInfos.head // T

/** Set the type of the body of the quote */
def withBodyType(tpe: Type)(using Context): Quote[Type] =
val exprType = // `Expr[T]` or `Type[T]`
Expand Down Expand Up @@ -752,11 +746,6 @@ object Trees {
case class QuotePattern[+T <: Untyped] private[ast] (bindings: List[Tree[T]], body: Tree[T], quotes: Tree[T])(implicit @constructorOnly src: SourceFile)
extends PatternTree[T] {
type ThisTree[+T <: Untyped] = QuotePattern[T]

/** Type of the quoted pattern */
def bodyType(using Context): Type =
val quoteType = typeOpt // `Expr[T]` or `Type[T]`
quoteType.argInfos.head // T
}

/** A tree representing a pattern splice `${ pattern }`, `$ident` or `$ident(args*)` in a quote pattern.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
keywordStr("macro ") ~ toTextGlobal(call)
case tree @ Quote(body, tags) =>
val tagsText = (keywordStr("<") ~ toTextGlobal(tags, ", ") ~ keywordStr(">")).provided(tree.tags.nonEmpty)
val exprTypeText = (keywordStr("[") ~ toTextGlobal(tree.bodyType) ~ keywordStr("]")).provided(printDebug && tree.typeOpt.exists)
val exprTypeText = (keywordStr("[") ~ toTextGlobal(tpd.bodyType(tree.asInstanceOf[tpd.Quote])) ~ keywordStr("]")).provided(printDebug && tree.typeOpt.exists)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when I pretty-print an untyped Quote node?

Copy link
Contributor Author

@nicolasstucki nicolasstucki Jun 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The provided condition makes sure that the type exists. If it does not, the text and tpd.bodyType is not evaluated as it is a by-name prefix.

The other solution to this would be to create bodyTypeOpt. But this is the only use case for it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I missed the provided, ok.

val open = if (body.isTerm) keywordStr("{") else keywordStr("[")
val close = if (body.isTerm) keywordStr("}") else keywordStr("]")
keywordStr("'") ~ tagsText ~ exprTypeText ~ open ~ toTextGlobal(body) ~ close
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/ReTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking

override def typedQuote(tree: untpd.Quote, pt: Type)(using Context): Tree =
assertTyped(tree)
val body1 = typed(tree.body, tree.bodyType)(using quoteContext)
val body1 = typed(tree.body, promote(tree).bodyType)(using quoteContext)
for tag <- tree.tags do assertTyped(tag)
untpd.cpy.Quote(tree)(body1, tree.tags).withType(tree.typeOpt)

Expand All @@ -115,7 +115,7 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking
assertTyped(tree)
val bindings1 = tree.bindings.map(typed(_))
val bodyCtx = quoteContext.retractMode(Mode.Pattern).addMode(Mode.QuotedPattern)
val body1 = typed(tree.body, tree.bodyType)(using bodyCtx)
val body1 = typed(tree.body, promote(tree).bodyType)(using bodyCtx)
val quotes1 = typed(tree.quotes, defn.QuotesClass.typeRef)
untpd.cpy.QuotePattern(tree)(bindings1, body1, quotes1).withType(tree.typeOpt)

Expand Down
1 change: 1 addition & 0 deletions compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ object QuotesImpl {
}

class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler, QuoteMatching:
import tpd.*

private val xCheckMacro: Boolean = ctx.settings.XcheckMacros.value

Expand Down