diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index c2517145c935..2f36384a51ab 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -933,7 +933,7 @@ object desugar { def quotedPatternTypeDef(tree: TypeDef)(implicit ctx: Context): TypeDef = { assert(ctx.mode.is(Mode.QuotedPattern)) if (tree.name.startsWith("$") && !tree.isBackquoted) { - val patternBindHoleAnnot = New(ref(defn.InternalQuoted_patternTypeAnnot.typeRef)).withSpan(tree.span) + val patternBindHoleAnnot = New(ref(defn.InternalQuotedMatcher_patternTypeAnnot.typeRef)).withSpan(tree.span) val mods = tree.mods.withAddedAnnotation(patternBindHoleAnnot) tree.withMods(mods) } diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 3b4a52f176c7..904e54cb3c43 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -103,7 +103,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } case class Throw(expr: Tree)(implicit @constructorOnly src: SourceFile) extends TermTree case class Quote(quoted: Tree)(implicit @constructorOnly src: SourceFile) extends TermTree - case class Splice(expr: Tree)(implicit @constructorOnly src: SourceFile) extends TermTree + case class Splice(expr: Tree)(implicit @constructorOnly src: SourceFile) extends TermTree { + def isInBraces: Boolean = span.end != expr.span.end + } case class TypSplice(expr: Tree)(implicit @constructorOnly src: SourceFile) extends TypTree case class ForYield(enums: List[Tree], expr: Tree)(implicit @constructorOnly src: SourceFile) extends TermTree case class ForDo(enums: List[Tree], body: Tree)(implicit @constructorOnly src: SourceFile) extends TermTree diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 65a53c19dece..040273d1eeb4 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -694,11 +694,14 @@ class Definitions { @tu lazy val InternalQuoted_exprSplice : Symbol = InternalQuotedModule.requiredMethod("exprSplice") @tu lazy val InternalQuoted_exprNestedSplice : Symbol = InternalQuotedModule.requiredMethod("exprNestedSplice") @tu lazy val InternalQuoted_typeQuote : Symbol = InternalQuotedModule.requiredMethod("typeQuote") - @tu lazy val InternalQuoted_patternHole: Symbol = InternalQuotedModule.requiredMethod("patternHole") - @tu lazy val InternalQuoted_patternTypeAnnot: ClassSymbol = InternalQuotedModule.requiredClass("patternType") @tu lazy val InternalQuoted_QuoteTypeTagAnnot: ClassSymbol = InternalQuotedModule.requiredClass("quoteTypeTag") - @tu lazy val InternalQuoted_fromAboveAnnot: ClassSymbol = InternalQuotedModule.requiredClass("fromAbove") + @tu lazy val InternalQuotedMatcher: Symbol = ctx.requiredModule("scala.internal.quoted.Matcher") + @tu lazy val InternalQuotedMatcher_patternHole: Symbol = InternalQuotedMatcher.requiredMethod("patternHole") + @tu lazy val InternalQuotedMatcher_patternHigherOrderHole: Symbol = InternalQuotedMatcher.requiredMethod("patternHigherOrderHole") + @tu lazy val InternalQuotedMatcher_higherOrderHole: Symbol = InternalQuotedMatcher.requiredMethod("higherOrderHole") + @tu lazy val InternalQuotedMatcher_patternTypeAnnot: ClassSymbol = InternalQuotedMatcher.requiredClass("patternType") + @tu lazy val InternalQuotedMatcher_fromAboveAnnot: ClassSymbol = InternalQuotedMatcher.requiredClass("fromAbove") @tu lazy val InternalQuotedExprModule: Symbol = ctx.requiredModule("scala.internal.quoted.Expr") @tu lazy val InternalQuotedExpr_unapply: Symbol = InternalQuotedExprModule.requiredMethod(nme.unapply) diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index 546b7aea7bef..1590456cc833 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -1982,9 +1982,10 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def Definitions_TupleClass(arity: Int): Symbol = defn.TupleType(arity).classSymbol.asClass def Definitions_isTupleClass(sym: Symbol): Boolean = defn.isTupleClass(sym) - def Definitions_InternalQuoted_patternHole: Symbol = defn.InternalQuoted_patternHole - def Definitions_InternalQuoted_patternTypeAnnot: Symbol = defn.InternalQuoted_patternTypeAnnot - def Definitions_InternalQuoted_fromAboveAnnot: Symbol = defn.InternalQuoted_fromAboveAnnot + def Definitions_InternalQuotedMatcher_patternHole: Symbol = defn.InternalQuotedMatcher_patternHole + def Definitions_InternalQuotedMatcher_higherOrderHole: Symbol = defn.InternalQuotedMatcher_higherOrderHole + def Definitions_InternalQuotedMatcher_patternTypeAnnot: Symbol = defn.InternalQuotedMatcher_patternTypeAnnot + def Definitions_InternalQuotedMatcher_fromAboveAnnot: Symbol = defn.InternalQuotedMatcher_fromAboveAnnot // Types diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index 67db036ee4ff..4619bd980533 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -119,14 +119,27 @@ trait QuotesAndSplices { def typedAppliedSplice(tree: untpd.Apply, pt: Type)(using Context): Tree = { assert(ctx.mode.is(Mode.QuotedPattern)) val untpd.Apply(splice: untpd.Splice, args) = tree - if (isFullyDefined(pt, ForceDegree.flipBottom)) then + if !isFullyDefined(pt, ForceDegree.flipBottom) then + ctx.error(i"Type must be fully defined.", splice.sourcePos) + tree.withType(UnspecifiedErrorType) + else if splice.isInBraces then // ${x}(...) match an application val typedArgs = args.map(arg => typedExpr(arg)) val argTypes = typedArgs.map(_.tpe.widenTermRefExpr) val splice1 = typedSplice(splice, defn.FunctionOf(argTypes, pt)) Apply(splice1.select(nme.apply), typedArgs).withType(pt).withSpan(tree.span) - else - ctx.error(i"Type must be fully defined.", splice.sourcePos) - tree.withType(UnspecifiedErrorType) + else // $x(...) higher-order quasipattern + val typedArgs = args.map { + case arg: untpd.Ident => + typedExpr(arg) + case arg => + ctx.error("Open patttern exprected an identifier", arg.sourcePos) + EmptyTree + } + if args.isEmpty then + ctx.error("Missing arguments for open pattern", tree.sourcePos) + val argTypes = typedArgs.map(_.tpe.widenTermRefExpr) + val typedPat = typedSplice(splice, defn.FunctionOf(argTypes, pt)) + ref(defn.InternalQuotedMatcher_patternHigherOrderHole).appliedToType(pt).appliedTo(typedPat, SeqLiteral(typedArgs, TypeTree(defn.AnyType))) } /** Translate ${ t: Type[T] }` into type `t.splice` while tracking the quotation level in the context */ @@ -154,7 +167,7 @@ trait QuotesAndSplices { case pt: TypeBounds => pt case _ => TypeBounds.empty val typeSym = ctx.newSymbol(spliceOwner(ctx), name, EmptyFlags, typeSymInfo, NoSymbol, tree.expr.span) - typeSym.addAnnotation(Annotation(New(ref(defn.InternalQuoted_patternTypeAnnot.typeRef)).withSpan(tree.expr.span))) + typeSym.addAnnotation(Annotation(New(ref(defn.InternalQuotedMatcher_patternTypeAnnot.typeRef)).withSpan(tree.expr.span))) val pat = typedPattern(tree.expr, defn.QuotedTypeClass.typeRef.appliedTo(typeSym.typeRef))( using spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx))) pat.select(tpnme.splice) @@ -224,8 +237,16 @@ trait QuotesAndSplices { val exprTpt = AppliedTypeTree(TypeTree(defn.QuotedExprClass.typeRef), tpt1 :: Nil) val newSplice = ref(defn.InternalQuoted_exprSplice).appliedToType(tpt1.tpe).appliedTo(Typed(pat, exprTpt)) transform(newSplice) + case Apply(TypeApply(fn, targs), Apply(sp, pat :: Nil) :: args :: Nil) if fn.symbol == defn.InternalQuotedMatcher_patternHigherOrderHole => + try ref(defn.InternalQuotedMatcher_higherOrderHole.termRef).appliedToTypeTrees(targs).appliedTo(args).withSpan(tree.span) + finally { + val patType = pat.tpe.widen + val patType1 = patType.translateFromRepeated(toArray = false) + val pat1 = if (patType eq patType1) pat else pat.withType(patType1) + patBuf += pat1 + } case Apply(fn, pat :: Nil) if fn.symbol == defn.InternalQuoted_exprSplice => - try ref(defn.InternalQuoted_patternHole.termRef).appliedToType(tree.tpe).withSpan(tree.span) + try ref(defn.InternalQuotedMatcher_patternHole.termRef).appliedToType(tree.tpe).withSpan(tree.span) finally { val patType = pat.tpe.widen val patType1 = patType.translateFromRepeated(toArray = false) @@ -241,7 +262,7 @@ trait QuotesAndSplices { else tree case tdef: TypeDef => - if tdef.symbol.hasAnnotation(defn.InternalQuoted_patternTypeAnnot) then + if tdef.symbol.hasAnnotation(defn.InternalQuotedMatcher_patternTypeAnnot) then transformTypeBindingTypeDef(tdef, typePatBuf) else if tdef.symbol.isClass then val kind = if tdef.symbol.is(Module) then "objects" else "classes" @@ -276,7 +297,7 @@ trait QuotesAndSplices { private def transformTypeBindingTypeDef(tdef: TypeDef, buff: mutable.Builder[Tree, List[Tree]])(using Context): Tree = { if (variance == -1) - tdef.symbol.addAnnotation(Annotation(New(ref(defn.InternalQuoted_fromAboveAnnot.typeRef)).withSpan(tdef.span))) + tdef.symbol.addAnnotation(Annotation(New(ref(defn.InternalQuotedMatcher_fromAboveAnnot.typeRef)).withSpan(tdef.span))) val bindingType = getBinding(tdef.symbol).symbol.typeRef val bindingTypeTpe = AppliedType(defn.QuotedTypeClass.typeRef, bindingType :: Nil) val bindName = tdef.name.toString.stripPrefix("$").toTermName diff --git a/docs/docs/reference/metaprogramming/macros.md b/docs/docs/reference/metaprogramming/macros.md index a9f638d025d4..f76a0fb42062 100644 --- a/docs/docs/reference/metaprogramming/macros.md +++ b/docs/docs/reference/metaprogramming/macros.md @@ -744,5 +744,51 @@ trait Show[-T] { } ``` +#### Open code patterns + +Quote pattern matching also provides higher-order patterns to match open terms. If a quoted term contains a definition, +then the rest of the quote can refer to this definition. +``` +'{ + val x: Int = 4 + x * x +} +``` + +To match such a term we need to match the definition and the rest of the code, but we need to expicilty state that the rest of the code may refer to this definition. +```scala +case '{ val y: Int = $x; $body(y): Int } => +``` +Here `$x` will match any closed expression while `$body(y)` will match expression that is closed under `y`. Then +the subxpression of type `Expr[Int]` is bound to `body` as an `Expr[Int => Int]`. The extra argument represents the references to `y`. Usually this expression is used in compination with `Expr.betaReduce` to replace the extra argument. + +```scala +inline def eval(inline e: Int): Int = ${ evalExpr('e) } + +private def evalExpr(using QuoteContext)(e: Expr[Int]): Expr[Int] = { + e match { + case '{ val y: Int = $x; $body(y): Int } => + // body: Expr[Int => Int] where the argument represents references to y + evalExpr(Expr.betaReduce(body)(evalExpr(x))) + case '{ ($x: Int) * ($y: Int) } => + (x, y) match + case (Const(a), Const(b)) => Expr(a * b) + case _ => e + case _ => e + } +} +``` + +```scala +eval { // expands to the code: (16: Int) + val x: Int = 4 + x * x +} +``` + +We can also close over several bindings using `$b(a1, a2, ..., an)`. +To match an actual application we can use braces on the function part `${b}(a1, a2, ..., an)`. + + ### More details [More details](./macros-spec.md) diff --git a/library/src-bootstrapped/scala/internal/quoted/CompileTime.scala b/library/src-bootstrapped/scala/internal/quoted/CompileTime.scala index 2f6e8402afb2..4891d3cbf8c8 100644 --- a/library/src-bootstrapped/scala/internal/quoted/CompileTime.scala +++ b/library/src-bootstrapped/scala/internal/quoted/CompileTime.scala @@ -24,23 +24,6 @@ object CompileTime { @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.typeQuote`") def typeQuote[T <: AnyKind]: QuoteContext ?=> Type[T] = ??? - /** A splice in a quoted pattern is desugared by the compiler into a call to this method */ - @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.patternHole`") - def patternHole[T]: T = ??? - - // TODO remove - /** A splice of a name in a quoted pattern is desugared by wrapping getting this annotation */ - @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.patternBindHole`") - class patternBindHole extends Annotation - - /** A splice of a name in a quoted pattern is that marks the definition of a type splice */ - @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.patternType`") - class patternType extends Annotation - - /** A type pattern that must be aproximated from above */ - @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.fromAbove`") - class fromAbove extends Annotation - /** Artifact of pickled type splices * * During quote reification a quote `'{ ... F[$t] ... }` will be transformed into diff --git a/library/src/scala/internal/quoted/Matcher.scala b/library/src/scala/internal/quoted/Matcher.scala index eeb371db2b33..4f9ecad58973 100644 --- a/library/src/scala/internal/quoted/Matcher.scala +++ b/library/src/scala/internal/quoted/Matcher.scala @@ -1,6 +1,7 @@ package scala.internal.quoted import scala.annotation.internal.sharable +import scala.annotation.{Annotation, compileTimeOnly} import scala.quoted._ @@ -94,7 +95,32 @@ import scala.quoted._ * * ``` */ -private[quoted] object Matcher { +object Matcher { + + /** A splice in a quoted pattern is desugared by the compiler into a call to this method */ + @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.patternHole`") + def patternHole[T]: T = ??? + + @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.patternHigherOrderHole`") + /** A higher order splice in a quoted pattern is desugared by the compiler into a call to this method */ + def patternHigherOrderHole[U](pat: Any, args: Any*): U = ??? + + @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.higherOrderHole`") + /** A higher order splice in a quoted pattern is desugared by the compiler into a call to this method */ + def higherOrderHole[U](args: Any*): U = ??? + + // TODO remove + /** A splice of a name in a quoted pattern is desugared by wrapping getting this annotation */ + @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.patternBindHole`") + class patternBindHole extends Annotation + + /** A splice of a name in a quoted pattern is that marks the definition of a type splice */ + @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.patternType`") + class patternType extends Annotation + + /** A type pattern that must be aproximated from above */ + @compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.fromAbove`") + class fromAbove extends Annotation class QuoteMatcher[QCtx <: QuoteContext & Singleton](using val qctx: QCtx) { // TODO improve performance @@ -164,13 +190,13 @@ private[quoted] object Matcher { private def hasFromAboveAnnotation(sym: Symbol) = sym.annots.exists(isFromAboveAnnotation) private def isPatternTypeAnnotation(tree: Tree): Boolean = tree match { - case New(tpt) => tpt.symbol == internal.Definitions_InternalQuoted_patternTypeAnnot - case annot => annot.symbol.owner == internal.Definitions_InternalQuoted_patternTypeAnnot + case New(tpt) => tpt.symbol == internal.Definitions_InternalQuotedMatcher_patternTypeAnnot + case annot => annot.symbol.owner == internal.Definitions_InternalQuotedMatcher_patternTypeAnnot } private def isFromAboveAnnotation(tree: Tree): Boolean = tree match { - case New(tpt) => tpt.symbol == internal.Definitions_InternalQuoted_fromAboveAnnot - case annot => annot.symbol.owner == internal.Definitions_InternalQuoted_fromAboveAnnot + case New(tpt) => tpt.symbol == internal.Definitions_InternalQuotedMatcher_fromAboveAnnot + case annot => annot.symbol.owner == internal.Definitions_InternalQuotedMatcher_fromAboveAnnot } /** Check that all trees match with `mtch` and concatenate the results with &&& */ @@ -226,7 +252,7 @@ private[quoted] object Matcher { /* Term hole */ // Match a scala.internal.Quoted.patternHole typed as a repeated argument and return the scrutinee tree case (scrutinee @ Typed(s, tpt1), Typed(TypeApply(patternHole, tpt :: Nil), tpt2)) - if patternHole.symbol == internal.Definitions_InternalQuoted_patternHole && + if patternHole.symbol == internal.Definitions_InternalQuotedMatcher_patternHole && s.tpe <:< tpt.tpe && tpt2.tpe.derivesFrom(defn.RepeatedParamClass) => matched(scrutinee.seal) @@ -234,15 +260,15 @@ private[quoted] object Matcher { /* Term hole */ // Match a scala.internal.Quoted.patternHole and return the scrutinee tree case (ClosedPatternTerm(scrutinee), TypeApply(patternHole, tpt :: Nil)) - if patternHole.symbol == internal.Definitions_InternalQuoted_patternHole && + if patternHole.symbol == internal.Definitions_InternalQuotedMatcher_patternHole && scrutinee.tpe <:< tpt.tpe => matched(scrutinee.seal) /* Higher order term hole */ // Matches an open term and wraps it into a lambda that provides the free variables - // TODO do not encode with `hole`. Maybe use `higherOrderHole[(T1, ..., Tn) => R]((x1: T1, ..., xn: Tn)): R` - case (scrutinee, pattern @ Apply(Select(TypeApply(patternHole, List(Inferred())), "apply"), args0 @ IdentArgs(args))) - if patternHole.symbol == internal.Definitions_InternalQuoted_patternHole => + case (scrutinee, pattern @ Apply(TypeApply(Ident("higherOrderHole"), List(Inferred())), Repeated(args, _) :: Nil)) + if pattern.symbol == internal.Definitions_InternalQuotedMatcher_higherOrderHole => + def bodyFn(lambdaArgs: List[Tree]): Tree = { val argsMap = args.map(_.symbol).zip(lambdaArgs.asInstanceOf[List[Term]]).toMap new TreeMap { @@ -252,8 +278,11 @@ private[quoted] object Matcher { case tree => super.transformTerm(tree) }.transformTree(scrutinee) } - val names = args.map(_.name) - val argTypes = args0.map(x => x.tpe.widenTermRefExpr) + val names = args.map { + case Block(List(DefDef("$anonfun", _, _, _, Some(Apply(Ident(name), _)))), _) => name + case arg => arg.symbol.name + } + val argTypes = args.map(x => x.tpe.widenTermRefExpr) val resType = pattern.tpe val res = Lambda(MethodType(names)(_ => argTypes, _ => resType), bodyFn) matched(res.seal) diff --git a/library/src/scala/tasty/reflect/CompilerInterface.scala b/library/src/scala/tasty/reflect/CompilerInterface.scala index e6d953579fb1..3ad8f946d588 100644 --- a/library/src/scala/tasty/reflect/CompilerInterface.scala +++ b/library/src/scala/tasty/reflect/CompilerInterface.scala @@ -1511,14 +1511,17 @@ trait CompilerInterface { def Definitions_TupleClass(arity: Int): Symbol def Definitions_isTupleClass(sym: Symbol): Boolean - /** Symbol of scala.internal.Quoted.patternHole */ - def Definitions_InternalQuoted_patternHole: Symbol + /** Symbol of scala.internal.CompileTime.patternHole */ + def Definitions_InternalQuotedMatcher_patternHole: Symbol - /** Symbol of scala.internal.Quoted.patternType */ - def Definitions_InternalQuoted_patternTypeAnnot: Symbol + /** Symbol of scala.internal.CompileTime.higherOrderHole */ + def Definitions_InternalQuotedMatcher_higherOrderHole: Symbol - /** Symbol of scala.internal.Quoted.fromAbove */ - def Definitions_InternalQuoted_fromAboveAnnot: Symbol + /** Symbol of scala.internal.CompileTime.patternType */ + def Definitions_InternalQuotedMatcher_patternTypeAnnot: Symbol + + /** Symbol of scala.internal.CompileTime.fromAbove */ + def Definitions_InternalQuotedMatcher_fromAboveAnnot: Symbol def Definitions_UnitType: Type def Definitions_ByteType: Type diff --git a/tests/neg/quote-open-patterns-stages.scala b/tests/neg/quote-open-patterns-stages.scala new file mode 100644 index 000000000000..5d14851bbbbd --- /dev/null +++ b/tests/neg/quote-open-patterns-stages.scala @@ -0,0 +1,5 @@ +import scala.quoted._ + +def f(using QuoteContext)(x: Expr[Any]) = x match { + case '{ identity($y(x)) } => // error: access to value x from wrong staging level +} diff --git a/tests/neg/quote-open-patterns-typer.scala b/tests/neg/quote-open-patterns-typer.scala new file mode 100644 index 000000000000..4c0dc8b62a1d --- /dev/null +++ b/tests/neg/quote-open-patterns-typer.scala @@ -0,0 +1,6 @@ +import scala.quoted._ + +def f(using QuoteContext)(x: Expr[Any]) = x match { + case '{ val a: Int = 3; $y(identity(a)) } => // error: Exprected an identifier + case '{ identity($y()) } => // error: Missing arguments for open pattern +} diff --git a/tests/pos/quoted-splice-pattern-applied.scala b/tests/pos/quoted-splice-pattern-applied.scala index 5014d7f82d2f..d861ddbc0ce5 100644 --- a/tests/pos/quoted-splice-pattern-applied.scala +++ b/tests/pos/quoted-splice-pattern-applied.scala @@ -1,12 +1,12 @@ import scala.quoted._ def f(x: Expr[Int])(using QuoteContext) = x match { - case '{ $f($a: Int): Int } => + case '{ ${f}($a: Int): Int } => val f1: Expr[Int => Int] = f val a1: Expr[Int] = a - case '{ def a: Int = $f($b: Int); () } => + case '{ def a: Int = ${f}($b: Int); () } => val f1: Expr[Int => Int] = f val b1: Expr[Int] = b - case '{ val a: Int = 3; $f(a): Int } => + case '{ val a: Int = 3; ${f}(a): Int } => val f1: Expr[Int => Int] = f } diff --git a/tests/run-macros/quote-matcher-runtime.check b/tests/run-macros/quote-matcher-runtime.check index 4013b40ad123..269eaf7cd4ae 100644 --- a/tests/run-macros/quote-matcher-runtime.check +++ b/tests/run-macros/quote-matcher-runtime.check @@ -19,55 +19,55 @@ Pattern: (1: scala.Int) Result: Some(List()) Scrutinee: 3 -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Int] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Int] Result: Some(List(Expr(3))) Scrutinee: x -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Int] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Int] Result: Some(List(Expr(x))) Scrutinee: 5 -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Any] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Any] Result: Some(List(Expr(5))) Scrutinee: 6.+(x) -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Int] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Int] Result: Some(List(Expr(6.+(x)))) Scrutinee: 6.+(x) -Pattern: 6.+(scala.internal.quoted.CompileTime.patternHole[scala.Int]) +Pattern: 6.+(scala.internal.quoted.Matcher.patternHole[scala.Int]) Result: Some(List(Expr(x))) Scrutinee: 6.+(x) -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Int].+(x) +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Int].+(x) Result: Some(List(Expr(6))) Scrutinee: 6.+(x) -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Int].+(scala.internal.quoted.CompileTime.patternHole[scala.Int]) +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Int].+(scala.internal.quoted.Matcher.patternHole[scala.Int]) Result: Some(List(Expr(6), Expr(x))) Scrutinee: 6.+(x).+(y) -Pattern: 6.+(scala.internal.quoted.CompileTime.patternHole[scala.Int]).+(y) +Pattern: 6.+(scala.internal.quoted.Matcher.patternHole[scala.Int]).+(y) Result: Some(List(Expr(x))) Scrutinee: 4 -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Predef.String] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Predef.String] Result: None Scrutinee: 6.+(x) -Pattern: 7.+(scala.internal.quoted.CompileTime.patternHole[scala.Int]) +Pattern: 7.+(scala.internal.quoted.Matcher.patternHole[scala.Int]) Result: None Scrutinee: 6.+(x) -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Int].+(4) +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Int].+(4) Result: None Scrutinee: g[scala.Int] -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Predef.String] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Predef.String] Result: None Scrutinee: h[scala.Int](7) -Pattern: h[scala.Predef.String](scala.internal.quoted.CompileTime.patternHole[scala.Predef.String]) +Pattern: h[scala.Predef.String](scala.internal.quoted.Matcher.patternHole[scala.Predef.String]) Result: None Scrutinee: h[scala.Int](6) @@ -83,23 +83,23 @@ Pattern: z2 = 4 Result: None Scrutinee: f(4) -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Int] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Int] Result: Some(List(Expr(f(4)))) Scrutinee: f(5) -Pattern: f(scala.internal.quoted.CompileTime.patternHole[scala.Int]) +Pattern: f(scala.internal.quoted.Matcher.patternHole[scala.Int]) Result: Some(List(Expr(5))) Scrutinee: g[scala.Int] -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Int] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Int] Result: Some(List(Expr(g[scala.Int]))) Scrutinee: h[scala.Int](7) -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Int] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Int] Result: Some(List(Expr(h[scala.Int](7)))) Scrutinee: h[scala.Int](8) -Pattern: h[scala.Int](scala.internal.quoted.CompileTime.patternHole[scala.Int]) +Pattern: h[scala.Int](scala.internal.quoted.Matcher.patternHole[scala.Int]) Result: Some(List(Expr(8))) Scrutinee: Test.this @@ -107,7 +107,7 @@ Pattern: Test.this Result: Some(List()) Scrutinee: Test.this -Pattern: scala.internal.quoted.CompileTime.patternHole[this.type] +Pattern: scala.internal.quoted.Matcher.patternHole[this.type] Result: Some(List(Expr(Test.this))) Scrutinee: new Foo(1) @@ -115,11 +115,11 @@ Pattern: new Foo(1) Result: Some(List()) Scrutinee: new Foo(1) -Pattern: scala.internal.quoted.CompileTime.patternHole[Foo] +Pattern: scala.internal.quoted.Matcher.patternHole[Foo] Result: Some(List(Expr(new Foo(1)))) Scrutinee: new Foo(1) -Pattern: new Foo(scala.internal.quoted.CompileTime.patternHole[scala.Int]) +Pattern: new Foo(scala.internal.quoted.Matcher.patternHole[scala.Int]) Result: Some(List(Expr(1))) Scrutinee: if (b) x else y @@ -127,11 +127,11 @@ Pattern: if (b) x else y Result: Some(List()) Scrutinee: if (b) x else y -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Int] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Int] Result: Some(List(Expr(if (b) x else y))) Scrutinee: if (b) x else y -Pattern: if (scala.internal.quoted.CompileTime.patternHole[scala.Boolean]) scala.internal.quoted.CompileTime.patternHole[scala.Int] else scala.internal.quoted.CompileTime.patternHole[scala.Int] +Pattern: if (scala.internal.quoted.Matcher.patternHole[scala.Boolean]) scala.internal.quoted.Matcher.patternHole[scala.Int] else scala.internal.quoted.Matcher.patternHole[scala.Int] Result: Some(List(Expr(b), Expr(x), Expr(y))) Scrutinee: while (b) { @@ -148,7 +148,7 @@ Scrutinee: while (b) { x () } -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Unit] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Unit] Result: Some(List(Expr(while (b) { x () @@ -158,8 +158,8 @@ Scrutinee: while (b) { x () } -Pattern: while (scala.internal.quoted.CompileTime.patternHole[scala.Boolean]) { - scala.internal.quoted.CompileTime.patternHole[scala.Int] +Pattern: while (scala.internal.quoted.Matcher.patternHole[scala.Boolean]) { + scala.internal.quoted.Matcher.patternHole[scala.Int] () } Result: Some(List(Expr(b), Expr(x))) @@ -169,11 +169,11 @@ Pattern: z = 4 Result: Some(List()) Scrutinee: z = 4 -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Unit] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Unit] Result: Some(List(Expr(z = 4))) Scrutinee: z = 4 -Pattern: z = scala.internal.quoted.CompileTime.patternHole[scala.Int] +Pattern: z = scala.internal.quoted.Matcher.patternHole[scala.Int] Result: Some(List(Expr(4))) Scrutinee: 1 @@ -189,7 +189,7 @@ Pattern: fs() Result: Some(List()) Scrutinee: fs() -Pattern: fs(scala.internal.quoted.CompileTime.patternHole[scala.Seq[scala.Int]]: _*) +Pattern: fs(scala.internal.quoted.Matcher.patternHole[scala.Seq[scala.Int]]: _*) Result: Some(List(Expr())) Scrutinee: fs(1, 2, 3) @@ -197,11 +197,11 @@ Pattern: fs(1, 2, 3) Result: Some(List()) Scrutinee: fs(1, 2, 3) -Pattern: fs(scala.internal.quoted.CompileTime.patternHole[scala.Int], scala.internal.quoted.CompileTime.patternHole[scala.Int], 3) +Pattern: fs(scala.internal.quoted.Matcher.patternHole[scala.Int], scala.internal.quoted.Matcher.patternHole[scala.Int], 3) Result: Some(List(Expr(1), Expr(2))) Scrutinee: fs(1, 2, 3) -Pattern: fs(scala.internal.quoted.CompileTime.patternHole[scala.Seq[scala.Int]]: _*) +Pattern: fs(scala.internal.quoted.Matcher.patternHole[scala.Seq[scala.Int]]: _*) Result: Some(List(Expr(1, 2, 3))) Scrutinee: f2(1, 2) @@ -213,7 +213,7 @@ Pattern: f2(a = 1, b = 2) Result: Some(List()) Scrutinee: f2(a = 1, b = 2) -Pattern: f2(a = scala.internal.quoted.CompileTime.patternHole[scala.Int], b = scala.internal.quoted.CompileTime.patternHole[scala.Int]) +Pattern: f2(a = scala.internal.quoted.Matcher.patternHole[scala.Int], b = scala.internal.quoted.Matcher.patternHole[scala.Int]) Result: Some(List(Expr(1), Expr(2))) Scrutinee: super.toString() @@ -221,23 +221,23 @@ Pattern: super.toString() Result: Some(List()) Scrutinee: (() => "abc") -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Function0[scala.Predef.String]] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Function0[scala.Predef.String]] Result: Some(List(Expr((() => "abc")))) Scrutinee: (() => "abc").apply() -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Function0[scala.Predef.String]].apply() +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Function0[scala.Predef.String]].apply() Result: Some(List(Expr((() => "abc")))) Scrutinee: ((x: scala.Int) => "abc") -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Function1[scala.Int, scala.Predef.String]] +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Function1[scala.Int, scala.Predef.String]] Result: Some(List(Expr(((x: scala.Int) => "abc")))) Scrutinee: ((x: scala.Int) => "abc").apply(4) -Pattern: scala.internal.quoted.CompileTime.patternHole[scala.Function1[scala.Int, scala.Predef.String]].apply(4) +Pattern: scala.internal.quoted.Matcher.patternHole[scala.Function1[scala.Int, scala.Predef.String]].apply(4) Result: Some(List(Expr(((x: scala.Int) => "abc")))) Scrutinee: ((x: scala.Int) => "abc") -Pattern: ((x: scala.Int) => scala.internal.quoted.CompileTime.patternHole[scala.Predef.String]) +Pattern: ((x: scala.Int) => scala.internal.quoted.Matcher.patternHole[scala.Predef.String]) Result: Some(List(Expr("abc"))) Scrutinee: scala.StringContext.apply("abc", "xyz") @@ -245,11 +245,11 @@ Pattern: scala.StringContext.apply("abc", "xyz") Result: Some(List()) Scrutinee: scala.StringContext.apply("abc", "xyz") -Pattern: scala.StringContext.apply(scala.internal.quoted.CompileTime.patternHole[java.lang.String], scala.internal.quoted.CompileTime.patternHole[java.lang.String]) +Pattern: scala.StringContext.apply(scala.internal.quoted.Matcher.patternHole[java.lang.String], scala.internal.quoted.Matcher.patternHole[java.lang.String]) Result: Some(List(Expr("abc"), Expr("xyz"))) Scrutinee: scala.StringContext.apply("abc", "xyz") -Pattern: scala.StringContext.apply(scala.internal.quoted.CompileTime.patternHole[scala.Seq[scala.Predef.String]]: _*) +Pattern: scala.StringContext.apply(scala.internal.quoted.Matcher.patternHole[scala.Seq[scala.Predef.String]]: _*) Result: Some(List(Expr("abc", "xyz"))) Scrutinee: { @@ -267,7 +267,7 @@ Scrutinee: { () } Pattern: { - val a: scala.Int = scala.internal.quoted.CompileTime.patternHole[scala.Int] + val a: scala.Int = scala.internal.quoted.Matcher.patternHole[scala.Int] () } Result: Some(List(Expr(45))) @@ -297,7 +297,7 @@ Scrutinee: { () } Pattern: { - var a: scala.Int = scala.internal.quoted.CompileTime.patternHole[scala.Int] + var a: scala.Int = scala.internal.quoted.Matcher.patternHole[scala.Int] () } Result: None @@ -330,7 +330,7 @@ Scrutinee: { } Pattern: { val x: scala.Int = 45 - x.+(scala.internal.quoted.CompileTime.patternHole[scala.Int]) + x.+(scala.internal.quoted.Matcher.patternHole[scala.Int]) } Result: None @@ -369,7 +369,7 @@ Scrutinee: { () } Pattern: { - val a: scala.Int = scala.internal.quoted.CompileTime.patternHole[scala.Int] + val a: scala.Int = scala.internal.quoted.Matcher.patternHole[scala.Int] () } Result: None @@ -379,7 +379,7 @@ Scrutinee: { () } Pattern: { - var a: scala.Int = scala.internal.quoted.CompileTime.patternHole[scala.Int] + var a: scala.Int = scala.internal.quoted.Matcher.patternHole[scala.Int] () } Result: None @@ -419,7 +419,7 @@ Scrutinee: { () } Pattern: { - val a: scala.Int = scala.internal.quoted.CompileTime.patternHole[scala.Int] + val a: scala.Int = scala.internal.quoted.Matcher.patternHole[scala.Int] () } Result: None @@ -429,7 +429,7 @@ Scrutinee: { () } Pattern: { - lazy val a: scala.Int = scala.internal.quoted.CompileTime.patternHole[scala.Int] + lazy val a: scala.Int = scala.internal.quoted.Matcher.patternHole[scala.Int] () } Result: None @@ -499,7 +499,7 @@ Scrutinee: { () } Pattern: { - def a: scala.Int = scala.internal.quoted.CompileTime.patternHole[scala.Int] + def a: scala.Int = scala.internal.quoted.Matcher.patternHole[scala.Int] () } Result: Some(List(Expr(45))) @@ -619,8 +619,8 @@ Scrutinee: { a.+(a) } Pattern: { - def a: scala.Int = scala.internal.quoted.CompileTime.patternHole[scala.Int] - a.+(scala.internal.quoted.CompileTime.patternHole[scala.Int]) + def a: scala.Int = scala.internal.quoted.Matcher.patternHole[scala.Int] + a.+(scala.internal.quoted.Matcher.patternHole[scala.Int]) } Result: None @@ -636,22 +636,22 @@ Result: Some(List()) Scrutinee: scala.List.apply[scala.Int](1, 2, 3).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) Pattern: { - @scala.internal.quoted.CompileTime.patternType type T - scala.internal.quoted.CompileTime.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.quoted.CompileTime.patternHole[scala.Function1[scala.Int, T]]) + @scala.internal.quoted.Matcher.patternType type T + scala.internal.quoted.Matcher.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.quoted.Matcher.patternHole[scala.Function1[scala.Int, T]]) } Result: Some(List(Type(scala.Unit), Expr(scala.List.apply[scala.Int](1, 2, 3)), Expr(((x: scala.Int) => scala.Predef.println(x))))) Scrutinee: scala.List.apply[scala.Int](1, 2, 3).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) Pattern: { - @scala.internal.quoted.CompileTime.patternType type T = scala.Unit - scala.internal.quoted.CompileTime.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.quoted.CompileTime.patternHole[scala.Function1[scala.Int, T]]) + @scala.internal.quoted.Matcher.patternType type T = scala.Unit + scala.internal.quoted.Matcher.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.quoted.Matcher.patternHole[scala.Function1[scala.Int, T]]) } Result: Some(List(Type(scala.Unit), Expr(scala.List.apply[scala.Int](1, 2, 3)), Expr(((x: scala.Int) => scala.Predef.println(x))))) Scrutinee: scala.List.apply[scala.Int](1, 2, 3).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) Pattern: { - @scala.internal.quoted.CompileTime.patternType type T <: scala.Predef.String - scala.internal.quoted.CompileTime.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.quoted.CompileTime.patternHole[scala.Function1[scala.Int, T]]) + @scala.internal.quoted.Matcher.patternType type T <: scala.Predef.String + scala.internal.quoted.Matcher.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.quoted.Matcher.patternHole[scala.Function1[scala.Int, T]]) } Result: None @@ -661,9 +661,9 @@ Scrutinee: { () } Pattern: { - @scala.internal.quoted.CompileTime.patternType type T - val a: T = scala.internal.quoted.CompileTime.patternHole[T] - val b: T = scala.internal.quoted.CompileTime.patternHole[T] + @scala.internal.quoted.Matcher.patternType type T + val a: T = scala.internal.quoted.Matcher.patternHole[T] + val b: T = scala.internal.quoted.Matcher.patternHole[T] () } Result: Some(List(Type(scala.Int), Expr(4), Expr(4))) @@ -674,9 +674,9 @@ Scrutinee: { () } Pattern: { - @scala.internal.quoted.CompileTime.patternType type T - val a: T = scala.internal.quoted.CompileTime.patternHole[T] - val b: T = scala.internal.quoted.CompileTime.patternHole[T] + @scala.internal.quoted.Matcher.patternType type T + val a: T = scala.internal.quoted.Matcher.patternHole[T] + val b: T = scala.internal.quoted.Matcher.patternHole[T] () } Result: Some(List(Type(scala.Int), Expr(4), Expr(5))) @@ -687,9 +687,9 @@ Scrutinee: { () } Pattern: { - @scala.internal.quoted.CompileTime.patternType type T - val a: T = scala.internal.quoted.CompileTime.patternHole[T] - val b: T = scala.internal.quoted.CompileTime.patternHole[T] + @scala.internal.quoted.Matcher.patternType type T + val a: T = scala.internal.quoted.Matcher.patternHole[T] + val b: T = scala.internal.quoted.Matcher.patternHole[T] () } Result: Some(List(Type(scala.Int | java.lang.String), Expr(4), Expr("x"))) @@ -700,52 +700,52 @@ Scrutinee: { () } Pattern: { - @scala.internal.quoted.CompileTime.patternType type T <: scala.Int - val a: T = scala.internal.quoted.CompileTime.patternHole[T] - val b: T = scala.internal.quoted.CompileTime.patternHole[T] + @scala.internal.quoted.Matcher.patternType type T <: scala.Int + val a: T = scala.internal.quoted.Matcher.patternHole[T] + val b: T = scala.internal.quoted.Matcher.patternHole[T] () } Result: None Scrutinee: scala.List.apply[scala.Int](1, 2, 3).map[scala.Double](((x: scala.Int) => x.toDouble./(2))).map[java.lang.String](((y: scala.Double) => y.toString())) Pattern: { - @scala.internal.quoted.CompileTime.patternType type T - @scala.internal.quoted.CompileTime.patternType type U - @scala.internal.quoted.CompileTime.patternType type V + @scala.internal.quoted.Matcher.patternType type T + @scala.internal.quoted.Matcher.patternType type U + @scala.internal.quoted.Matcher.patternType type V - (scala.internal.quoted.CompileTime.patternHole[scala.List[T]].map[U](scala.internal.quoted.CompileTime.patternHole[scala.Function1[T, U]]).map[V](scala.internal.quoted.CompileTime.patternHole[scala.Function1[U, V]]): scala.collection.immutable.List[scala.Any]) + (scala.internal.quoted.Matcher.patternHole[scala.List[T]].map[U](scala.internal.quoted.Matcher.patternHole[scala.Function1[T, U]]).map[V](scala.internal.quoted.Matcher.patternHole[scala.Function1[U, V]]): scala.collection.immutable.List[scala.Any]) } Result: Some(List(Type(scala.Int), Type(scala.Double), Type(java.lang.String), Expr(scala.List.apply[scala.Int](1, 2, 3)), Expr(((x: scala.Int) => x.toDouble./(2))), Expr(((y: scala.Double) => y.toString())))) Scrutinee: ((x: scala.Int) => x) Pattern: { - @scala.internal.quoted.CompileTime.patternType type T + @scala.internal.quoted.Matcher.patternType type T - (scala.internal.quoted.CompileTime.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) + (scala.internal.quoted.Matcher.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) } Result: Some(List(Type(scala.Int), Expr(((x: scala.Int) => x)))) Scrutinee: ((x: scala.Int) => x.toString()) Pattern: { - @scala.internal.quoted.CompileTime.patternType type T + @scala.internal.quoted.Matcher.patternType type T - (scala.internal.quoted.CompileTime.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) + (scala.internal.quoted.Matcher.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) } Result: None Scrutinee: ((x: scala.Any) => scala.Predef.???) Pattern: { - @scala.internal.quoted.CompileTime.patternType type T + @scala.internal.quoted.Matcher.patternType type T - (scala.internal.quoted.CompileTime.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) + (scala.internal.quoted.Matcher.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) } Result: Some(List(Type(scala.Nothing), Expr(((x: scala.Any) => scala.Predef.???)))) Scrutinee: ((x: scala.Nothing) => (1: scala.Any)) Pattern: { - @scala.internal.quoted.CompileTime.patternType type T + @scala.internal.quoted.Matcher.patternType type T - (scala.internal.quoted.CompileTime.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) + (scala.internal.quoted.Matcher.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) } Result: None diff --git a/tests/run-macros/quote-matcher-runtime/quoted_2.scala b/tests/run-macros/quote-matcher-runtime/quoted_2.scala index 3f3263c6236b..2eeca0fc04e5 100644 --- a/tests/run-macros/quote-matcher-runtime/quoted_2.scala +++ b/tests/run-macros/quote-matcher-runtime/quoted_2.scala @@ -3,7 +3,7 @@ import Macros._ import scala.internal.quoted.Expr._ -import scala.internal.quoted.CompileTime._ +import scala.internal.quoted.Matcher._ object Test { diff --git a/tests/run-macros/quote-matcher-symantics-2/quoted_1.scala b/tests/run-macros/quote-matcher-symantics-2/quoted_1.scala index ae8ce7d4e7e8..239a33bd4a7c 100644 --- a/tests/run-macros/quote-matcher-symantics-2/quoted_1.scala +++ b/tests/run-macros/quote-matcher-symantics-2/quoted_1.scala @@ -20,7 +20,7 @@ object Macros { case '{ ($x: DSL) * ($y: DSL) } => sym.times(lift(x), lift(y)) - case '{ $f($x: DSL): DSL } => sym.app(liftFun(f), lift(x)) + case '{ ${f}($x: DSL): DSL } => sym.app(liftFun(f), lift(x)) case '{ val x: DSL = $value; $bodyFn(x): DSL } => UnsafeExpr.open(bodyFn) { (body1, close) => diff --git a/tests/run-macros/quote-matcher-symantics-3/quoted_1.scala b/tests/run-macros/quote-matcher-symantics-3/quoted_1.scala index 63be08612d1f..af240c4b16dc 100644 --- a/tests/run-macros/quote-matcher-symantics-3/quoted_1.scala +++ b/tests/run-macros/quote-matcher-symantics-3/quoted_1.scala @@ -39,7 +39,7 @@ object Macros { case '{ ($x: Int) <= ($y: Int) } => '{ $sym.leq(${lift(x)}, ${lift(y)}).asInstanceOf[R[T]] } - case '{ $f($arg: $t): $u } => + case '{ ${f}($arg: $t): $u } => '{ $sym.app[$t, $u](${lift(f)}, ${lift(arg)}).asInstanceOf[R[T]] } case '{ (if ($cond) $thenp else $elsep): $t } => diff --git a/tests/run-macros/quoted-pattern-open-expr-0.check b/tests/run-macros/quoted-pattern-open-expr-0.check new file mode 100644 index 000000000000..c916537133af --- /dev/null +++ b/tests/run-macros/quoted-pattern-open-expr-0.check @@ -0,0 +1,2 @@ +Matched open +((y: scala.Int) => y.*(y)) diff --git a/tests/run-macros/quoted-pattern-open-expr-0/Macro_1.scala b/tests/run-macros/quoted-pattern-open-expr-0/Macro_1.scala new file mode 100644 index 000000000000..f62dbda107c2 --- /dev/null +++ b/tests/run-macros/quoted-pattern-open-expr-0/Macro_1.scala @@ -0,0 +1,9 @@ +import scala.quoted._ + +inline def test(inline e: Int): String = ${testExpr('e)} + +private def testExpr(e: Expr[Int])(using QuoteContext): Expr[String] = { + e match { + case '{ val y: Int = 4; $body(y): Int } => Expr("Matched open\n" + body.show) + } +} diff --git a/tests/run-macros/quoted-pattern-open-expr-0/Test_2.scala b/tests/run-macros/quoted-pattern-open-expr-0/Test_2.scala new file mode 100644 index 000000000000..33e7cef92138 --- /dev/null +++ b/tests/run-macros/quoted-pattern-open-expr-0/Test_2.scala @@ -0,0 +1,6 @@ + +object Test { + def main(args: Array[String]): Unit = { + println(test { val x: Int = 4; x * x }) + } +} diff --git a/tests/run-macros/quoted-pattern-open-expr-simple-eval/Macro_1.scala b/tests/run-macros/quoted-pattern-open-expr-simple-eval/Macro_1.scala new file mode 100644 index 000000000000..ee9ae64eae1a --- /dev/null +++ b/tests/run-macros/quoted-pattern-open-expr-simple-eval/Macro_1.scala @@ -0,0 +1,15 @@ +import scala.quoted._ + +inline def eval(inline e: Int): Int = ${ evalExpr('e) } + +private def evalExpr(using QuoteContext)(e: Expr[Int]): Expr[Int] = { + e match { + case '{ val y: Int = $x; $body(y): Int } => + evalExpr(Expr.betaReduce(body)(evalExpr(x))) + case '{ ($x: Int) * ($y: Int) } => + (x, y) match + case (Const(a), Const(b)) => Expr(a * b) + case _ => e + case _ => e + } +} diff --git a/tests/run-macros/quoted-pattern-open-expr-simple-eval/Test_2.scala b/tests/run-macros/quoted-pattern-open-expr-simple-eval/Test_2.scala new file mode 100644 index 000000000000..8ad8b9bcb9c7 --- /dev/null +++ b/tests/run-macros/quoted-pattern-open-expr-simple-eval/Test_2.scala @@ -0,0 +1,9 @@ + +object Test { + def main(args: Array[String]): Unit = { + println(eval { + val x: Int = 4 + x * x + }) + } +}