diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index b266166745de..6f76861875a8 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -829,6 +829,24 @@ object desugar { Thicket(aliasType :: companions.toList) } + /** Transforms + * + * type $T >: Low <: Hi + * + * to + * + * @patternBindHole type $T >: Low <: Hi + * + * if the type is a type splice. + */ + def quotedPatternTypeDef(tree: TypeDef)(implicit ctx: Context): TypeDef = { + assert(ctx.mode.is(Mode.QuotedPattern)) + if (tree.name.startsWith("$") /* && !tree.isBackQuoted*/) { // TODO add backquoted TypeDef + val mods = tree.mods.withAddedAnnotation(New(ref(defn.InternalQuoted_patternBindHoleAnnot.typeRef)).withSpan(tree.span)) + tree.withMods(mods) + } else tree + } + /** The normalized name of `mdef`. This means * 1. Check that the name does not redefine a Scala core class. * If it does redefine, issue an error and return a mangled name instead of the original one. @@ -995,6 +1013,7 @@ object desugar { case tree: TypeDef => if (tree.isClassDef) classDef(tree) else if (tree.mods.is(Opaque, butNot = Synthetic)) opaqueAlias(tree) + else if (ctx.mode.is(Mode.QuotedPattern)) quotedPatternTypeDef(tree) else tree case tree: DefDef => if (tree.name.isConstructorName) tree // was already handled by enclosing classDef diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 28f11a24de21..5da7d6212bc1 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -1181,7 +1181,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** An extractor for typed splices */ object Splice { def apply(tree: Tree)(implicit ctx: Context): Tree = { - val baseType = tree.tpe.baseType(defn.QuotedExprClass) + val baseType = tree.tpe.baseType(defn.QuotedExprClass).orElse(tree.tpe.baseType(defn.QuotedTypeClass)) val argType = if (baseType != NoType) baseType.argTypesHi.head else { @@ -1318,6 +1318,17 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } } + /** Creates the tuple type tree repesentation of the type trees in `ts` */ + def tupleTypeTree(elems: List[Tree])(implicit ctx: Context): Tree = { + val arity = elems.length + if (arity <= Definitions.MaxTupleArity && defn.TupleType(arity) != null) AppliedTypeTree(TypeTree(defn.TupleType(arity)), elems) + else nestedPairsType(elems) + } + + /** Creates the nested pairs type tree repesentation of the type trees in `ts` */ + def nestedPairsType(ts: List[Tree])(implicit ctx: Context): Tree = + ts.foldRight[Tree](TypeTree(defn.UnitType))((x, acc) => AppliedTypeTree(TypeTree(defn.PairType), x :: acc :: Nil)) + /** Replaces all positions in `tree` with zero-extent positions */ private def focusPositions(tree: Tree)(implicit ctx: Context): Tree = { val transformer = new tpd.TreeMap { diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 15bf66caa6bd..60bc8633b644 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -723,6 +723,7 @@ class Definitions { lazy val InternalQuoted_patternHoleR: TermRef = InternalQuotedModule.requiredMethodRef("patternHole") def InternalQuoted_patternHole(implicit ctx: Context): Symbol = InternalQuoted_patternHoleR.symbol lazy val InternalQuoted_patternBindHoleAnnot: ClassSymbol = InternalQuotedModule.requiredClass("patternBindHole") + lazy val InternalQuoted_patternTypeHole: Symbol = InternalQuotedModule.requiredType("patternTypeHole") lazy val InternalQuotedMatcherModuleRef: TermRef = ctx.requiredModuleRef("scala.internal.quoted.Matcher") def InternalQuotedMatcherModule(implicit ctx: Context): Symbol = InternalQuotedMatcherModuleRef.symbol diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 1cf5220e9dee..26afc7031a18 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -584,6 +584,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { else keywordStr("'{") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}") case Splice(tree) => keywordStr("${") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}") + case TypSplice(tree) => + keywordStr("${") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}") case tree: Applications.IntegratedTypeArgs => toText(tree.app) ~ Str("(with integrated type args)").provided(ctx.settings.YprintDebug.value) case Thicket(trees) => diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index 1da497b19109..10154e9ea0af 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -150,7 +150,9 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( /** Is a reference to a class but not `this.type` */ def isClassRef = sym.isClass && !tp.isInstanceOf[ThisType] - if (sym.exists && !sym.isStaticOwner && !isClassRef && !levelOK(sym)) + if (sym.exists && !sym.isStaticOwner && !isClassRef && !levelOK(sym) && + !sym.hasAnnotation(defn.InternalQuoted_patternBindHoleAnnot) // FIXME this is a workaround + ) tryHeal(sym, tp, pos) else None diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 90523de12f6a..c149ef29bbd2 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1943,11 +1943,27 @@ class Typer extends Namer val exprPt = pt.baseType(defn.QuotedExprClass) val quotedPt = if (exprPt.exists) exprPt.argTypesHi.head else defn.AnyType val quoted1 = typedExpr(quoted, quotedPt)(quoteContext.addMode(Mode.QuotedPattern)) - val (shape, splices) = splitQuotePattern(quoted1) + val (typeBindings, shape, splices) = splitQuotePattern(quoted1) +// val typeBindings = splices.collect { +// case t if t.tpe.derivesFrom(defn.QuotedTypeClass) => +// t.tpe.widen.argTypesHi.head.typeSymbol +// } +// val inQuoteTypeBinding = typeBindings.map { sym => +// ctx.newSymbol(sym.owner, (sym.name + "$$$").toTypeName, // TODO remove $$$, just there for debugging +// EmptyFlags, sym.info, coord = sym.coord) +// } +// val shape2 = +// seq(inQuoteTypeBinding.map(TypeDef), shape.subst(typeBindings, inQuoteTypeBinding)) + + val patType = defn.tupleType(splices.tpes.map(_.widen)) + + val typeBindingsTuple = tpd.tupleTypeTree(typeBindings) + val splicePat = typed(untpd.Tuple(splices.map(untpd.TypedSplice(_))).withSpan(quoted.span), patType) + UnApply( - fun = ref(defn.InternalQuotedMatcher_unapplyR).appliedToType(patType), + fun = ref(defn.InternalQuotedMatcher_unapplyR).appliedToTypeTrees(typeBindingsTuple :: TypeTree(patType) :: Nil), implicits = ref(defn.InternalQuoted_exprQuoteR).appliedToType(shape.tpe).appliedTo(shape) :: implicitArgTree(defn.TastyReflectionType, tree.span) :: Nil, @@ -1959,8 +1975,24 @@ class Typer extends Namer } } - def splitQuotePattern(quoted: Tree)(implicit ctx: Context): (Tree, List[Tree]) = { + def splitQuotePattern(quoted: Tree)(implicit ctx: Context): (List[Bind], Tree, List[Tree]) = { val ctx0 = ctx + + val typeBindings: collection.mutable.Map[Symbol, Bind] = collection.mutable.Map.empty + def getBinding(sym: Symbol): Bind = + typeBindings.getOrElseUpdate(sym, { + val bindingBounds = TypeBounds.apply(defn.NothingType, defn.AnyType) // TODO recover bounds + val bsym = ctx.newPatternBoundSymbol((sym.name + "$").toTypeName, bindingBounds, quoted.span) + Bind(bsym, untpd.Ident(nme.WILDCARD).withType(bindingBounds)).withSpan(quoted.span) + }) + def replaceTypeBindings = new TypeMap { + def apply(tp: Type): Type = tp match { + case tp: TypeRef if tp.typeSymbol.hasAnnotation(defn.InternalQuoted_patternBindHoleAnnot) => + getBinding(tp.typeSymbol).symbol.typeRef + case _ => mapOver(tp) + } + } + object splitter extends tpd.TreeMap { val patBuf = new mutable.ListBuffer[Tree] override def transform(tree: Tree)(implicit ctx: Context) = tree match { @@ -1993,17 +2025,29 @@ class Typer extends Namer patBuf += Bind(sym, untpd.Ident(nme.WILDCARD).withType(bindingExprTpe)).withSpan(ddef.span) } super.transform(tree) + case tdef: TypeDef if tdef.symbol.hasAnnotation(defn.InternalQuoted_patternBindHoleAnnot) => + val bindingType = getBinding(tdef.symbol).symbol.typeRef + val bindingTypeTpe = AppliedType(defn.QuotedTypeType, bindingType :: Nil) + assert(tdef.name.startsWith("$")) + val bindName = tdef.name.toString.stripPrefix("$").toTermName + val sym = ctx0.newPatternBoundSymbol(bindName, bindingTypeTpe, tdef.span) + patBuf += Bind(sym, untpd.Ident(nme.WILDCARD).withType(bindingTypeTpe)).withSpan(tdef.span) + super.transform(tree) case _ => super.transform(tree) } } val result = splitter.transform(quoted) - (result, splitter.patBuf.toList) + val patterns = splitter.patBuf.toList + (typeBindings.toList.map(_._2), result, patterns) } /** A hole the shape pattern of a quoted.Matcher.unapply, representing a splice */ - def patternHole(splice: Tree)(implicit ctx: Context): Tree = - ref(defn.InternalQuoted_patternHoleR).appliedToType(splice.tpe).withSpan(splice.span) + def patternHole(splice: Tree)(implicit ctx: Context): Tree = { + val Splice(pat) = splice + if (pat.tpe.derivesFrom(defn.QuotedTypeClass)) AppliedTypeTree(ref(defn.InternalQuoted_patternTypeHole), TypeTree(splice.tpe) :: Nil).withSpan(splice.span) + else ref(defn.InternalQuoted_patternHoleR).appliedToType(splice.tpe).withSpan(splice.span) + } /** Translate `${ t: Expr[T] }` into expression `t.splice` while tracking the quotation level in the context */ def typedSplice(tree: untpd.Splice, pt: Type)(implicit ctx: Context): Tree = track("typedSplice") { @@ -2042,9 +2086,48 @@ class Typer extends Namer /** Translate ${ t: Type[T] }` into type `t.splice` while tracking the quotation level in the context */ def typedTypSplice(tree: untpd.TypSplice, pt: Type)(implicit ctx: Context): Tree = track("typedTypSplice") { + // TODO factor out comon code with typedSplice ctx.compilationUnit.needsStaging = true checkSpliceOutsideQuote(tree) - typedSelect(untpd.Select(tree.expr, tpnme.splice), pt)(spliceContext).withSpan(tree.span) + tree.expr match { + case untpd.Quote(innerExpr) => + ctx.warning("Canceled quote directly inside a splice. ${ '{ XYZ } } is equivalent to XYZ.", tree.sourcePos) + typed(innerExpr, pt) + case expr => + if (ctx.mode.is(Mode.QuotedPattern) && level == 1) { + if (isFullyDefined(pt, ForceDegree.all)) { + // TODO is this error still relevant here? probably not + ctx.error(i"Type must be fully defined.\nConsider annotating the splice using a type ascription:\n ($tree: XYZ).", tree.expr.sourcePos) + tree.withType(UnspecifiedErrorType) + } else { + expr match { + case Ident(name) => typedIdent(untpd.Ident(("$" + name).toTypeName), pt) + } + +// println() +// println(expr) +// println() +// println() +// val bindingBounds = TypeBounds.apply(defn.NothingType, defn.AnyType) +// def getName(tree: untpd.Tree): TypeName = tree match { +// case tree: RefTree => ("$" + tree.name).toTypeName +// case tree: Typed => getName(tree.expr) +// } +// val sym = ctx.newPatternBoundSymbol(getName(expr), bindingBounds, expr.span) +// val bind = Bind(sym, untpd.Ident(nme.WILDCARD).withType(bindingBounds)).withSpan(expr.span) +// +// def spliceOwner(ctx: Context): Symbol = +// if (ctx.mode.is(Mode.QuotedPattern)) spliceOwner(ctx.outer) else ctx.owner +// val pat = typedPattern(tree.expr, defn.QuotedTypeType.appliedTo(sym.typeRef))( +// spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx))) +// Splice(Typed(pat, AppliedTypeTree(TypeTree(defn.QuotedTypeType), bind :: Nil))) + + } + + } else { + typedSelect(untpd.Select(tree.expr, tpnme.splice), pt)(spliceContext).withSpan(tree.span) + } + } } private def checkSpliceOutsideQuote(tree: untpd.Tree)(implicit ctx: Context): Unit = { diff --git a/library/src-2.x/scala/internal/quoted/Matcher.scala b/library/src-2.x/scala/internal/quoted/Matcher.scala index 1e80a2a69fdf..0da396539b1b 100644 --- a/library/src-2.x/scala/internal/quoted/Matcher.scala +++ b/library/src-2.x/scala/internal/quoted/Matcher.scala @@ -5,7 +5,7 @@ import scala.tasty.Reflection object Matcher { - def unapply[Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], reflection: Reflection): Option[Tup] = + def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], reflection: Reflection): Option[Tup] = throw new Exception("running on non bootstrapped library") } diff --git a/library/src-3.x/scala/internal/Quoted.scala b/library/src-3.x/scala/internal/Quoted.scala index 0b649d196da7..1ecbab627e50 100644 --- a/library/src-3.x/scala/internal/Quoted.scala +++ b/library/src-3.x/scala/internal/Quoted.scala @@ -24,4 +24,5 @@ object Quoted { /** A splice of a name in a quoted pattern is desugared by wrapping getting this annotation */ class patternBindHole extends Annotation + type patternTypeHole[T] = T } diff --git a/library/src-3.x/scala/internal/quoted/Matcher.scala b/library/src-3.x/scala/internal/quoted/Matcher.scala index 34854b093128..e09f0f81f27d 100644 --- a/library/src-3.x/scala/internal/quoted/Matcher.scala +++ b/library/src-3.x/scala/internal/quoted/Matcher.scala @@ -8,7 +8,7 @@ import scala.tasty._ object Matcher { - private final val debug = false + private final val debug = true /** Pattern matches an the scrutineeExpr aquainsnt the patternExpr and returns a tuple * with the matched holes if successful. @@ -30,7 +30,7 @@ object Matcher { * @param reflection instance of the reflection API (implicitly provided by the macro) * @return None if it did not match, `Some(tup)` if it matched where `tup` contains `Expr[Ti]`` */ - def unapply[Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], reflection: Reflection): Option[Tup] = { + def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], reflection: Reflection): Option[Tup] = { import reflection.{Bind => BindPattern, _} // TODO improve performance @@ -81,14 +81,12 @@ object Matcher { // Match a scala.internal.Quoted.patternHole typed as a repeated argument and return the scrutinee tree case (IsTerm(scrutinee @ Typed(s, tpt1)), Typed(TypeApply(patternHole, tpt :: Nil), tpt2)) if patternHole.symbol == kernel.Definitions_InternalQuoted_patternHole && - s.tpe <:< tpt.tpe && tpt2.tpe.derivesFrom(definitions.RepeatedParamClass) => Some(Tuple1(scrutinee.seal)) // Match a scala.internal.Quoted.patternHole and return the scrutinee tree case (IsTerm(scrutinee), TypeApply(patternHole, tpt :: Nil)) - if patternHole.symbol == kernel.Definitions_InternalQuoted_patternHole && - scrutinee.tpe <:< tpt.tpe => + if patternHole.symbol == kernel.Definitions_InternalQuoted_patternHole => Some(Tuple1(scrutinee.seal)) // @@ -117,7 +115,17 @@ object Matcher { foldMatchings(treeMatches(fn1, fn2), treesMatch(args1, args2)) case (Block(stats1, expr1), Block(stats2, expr2)) => - foldMatchings(treesMatch(stats1, stats2), treeMatches(expr1, expr2)) + def rec(scrutinees: List[Tree], patterns: List[Tree], acc: Option[Tuple]): Option[Tuple] = (scrutinees, patterns) match { + case (x :: xs, y :: ys) => + if (y.symbol.annots.exists(_.symbol.owner.name == "patternBindHole")) { + println(y.show) + rec(x :: xs, ys, acc) + } else rec(xs, ys, foldMatchings(acc, treeMatches(x, y))) + case (Nil, Nil) => + foldMatchings(acc, treeMatches(expr1, expr2)) + case _ => None + } + rec(stats1, stats2, Some(())) case (If(cond1, thenp1, elsep1), If(cond2, thenp2, elsep2)) => foldMatchings(treeMatches(cond1, cond2), treeMatches(thenp1, thenp2), treeMatches(elsep1, elsep2)) @@ -219,7 +227,8 @@ object Matcher { | |${pattern.showExtractors} | - | + |with environment + |${env} | | |""".stripMargin) diff --git a/tests/pos/quotedPatterns.scala b/tests/pos/quotedPatterns.scala index 1309c8067845..9704c0fcbf8e 100644 --- a/tests/pos/quotedPatterns.scala +++ b/tests/pos/quotedPatterns.scala @@ -1,35 +1,41 @@ object Test { val x = '{1 + 2} - - def f(x: Int) = x - def g(x: Int, y: Int) = x * y +// +// def f(x: Int) = x +// def g(x: Int, y: Int) = x * y def res given tasty.Reflection: quoted.Expr[Int] = x match { - case '{1 + 2} => '{0} - case '{f($y)} => y - case '{g($y, $z)} => '{$y * $z} - case '{ ((a: Int) => 3)($y) } => y - case '{ 1 + ($y: Int)} => y - case '{ val a = 1 + ($y: Int); 3 } => y - case '{ val $y: Int = $z; println(`$y`); 1 } => - val a: quoted.matching.Bind[Int] = y - z - case '{ (($y: Int) => 1 + `$y` + ($z: Int))(2) } => - val a: quoted.matching.Bind[Int] = y - z - case '{ def $ff: Int = $z; `$ff` } => - val a: quoted.matching.Bind[Int] = ff - z - case '{ def $ff(i: Int): Int = $z; 2 } => - val a: quoted.matching.Bind[Int => Int] = ff - z - case '{ def $ff(i: Int)(j: Int): Int = $z; 2 } => - val a: quoted.matching.Bind[Int => Int => Int] = ff - z - case '{ def $ff[T](i: T): Int = $z; 2 } => - val a: quoted.matching.Bind[[T] => T => Int] = ff - z +// case '{1 + 2} => '{0} +// case '{f($y)} => y +// case '{g($y, $z)} => '{$y * $z} +// case '{ ((a: Int) => 3)($y) } => y +// case '{ 1 + ($y: Int)} => y +// case '{ val a = 1 + ($y: Int); 3 } => y +// case '{ val $y: Int = $z; println(`$y`); 1 } => +// val a: quoted.matching.Bind[Int] = y +// z +// case '{ (($y: Int) => 1 + `$y` + ($z: Int))(2) } => +// val a: quoted.matching.Bind[Int] = y +// z +// case '{ def $ff: Int = $z; `$ff` } => +// val a: quoted.matching.Bind[Int] = ff +// z +// case '{ def $ff(i: Int): Int = $z; 2 } => +// val a: quoted.matching.Bind[Int => Int] = ff +// z +// case '{ def $ff(i: Int)(j: Int): Int = $z; 2 } => +// val a: quoted.matching.Bind[Int => Int => Int] = ff +// z +// case '{ def $ff[T](i: T): Int = $z; 2 } => +// val a: quoted.matching.Bind[[T] => T => Int] = ff +// z +// case '{ poly[$t]($x); 2 } => ??? +// case '{ val x: $t = $a; val y: `$t` = x; 1 } => ??? + case '{ type $t; val x: $t = $a; val y: $t = x; 1 } => ??? +// case '{ type $t; val x: $t = $a; val y: $t = x; 1 } => ??? case _ => '{1} } + + def poly[T](x: T): Unit = () } \ No newline at end of file diff --git a/tests/run-macros/quote-matcher-runtime.check b/tests/run-macros/quote-matcher-runtime.check index 54ac86017e9f..e69de29bb2d1 100644 --- a/tests/run-macros/quote-matcher-runtime.check +++ b/tests/run-macros/quote-matcher-runtime.check @@ -1,664 +0,0 @@ -Scrutinee: 1 -Pattern: 1 -Result: Some(List()) - -Scrutinee: 1 -Pattern: 2 -Result: None - -Scrutinee: (1: scala.Int) -Pattern: 1 -Result: None - -Scrutinee: (1: scala.Int) -Pattern: (1: scala.Int) -Result: Some(List()) - -Scrutinee: 1 -Pattern: (1: scala.Int) -Result: None - -Scrutinee: 3 -Pattern: scala.internal.Quoted.patternHole[scala.Int] -Result: Some(List(Expr(3))) - -Scrutinee: x -Pattern: scala.internal.Quoted.patternHole[scala.Int] -Result: Some(List(Expr(x))) - -Scrutinee: 5 -Pattern: scala.internal.Quoted.patternHole[scala.Any] -Result: Some(List(Expr(5))) - -Scrutinee: 6.+(x) -Pattern: scala.internal.Quoted.patternHole[scala.Int] -Result: Some(List(Expr(6.+(x)))) - -Scrutinee: 6.+(x) -Pattern: 6.+(scala.internal.Quoted.patternHole[scala.Int]) -Result: Some(List(Expr(x))) - -Scrutinee: 6.+(x) -Pattern: scala.internal.Quoted.patternHole[scala.Int].+(x) -Result: Some(List(Expr(6))) - -Scrutinee: 6.+(x) -Pattern: scala.internal.Quoted.patternHole[scala.Int].+(scala.internal.Quoted.patternHole[scala.Int]) -Result: Some(List(Expr(6), Expr(x))) - -Scrutinee: 6.+(x).+(y) -Pattern: 6.+(scala.internal.Quoted.patternHole[scala.Int]).+(y) -Result: Some(List(Expr(x))) - -Scrutinee: 4 -Pattern: scala.internal.Quoted.patternHole[scala.Predef.String] -Result: None - -Scrutinee: 6.+(x) -Pattern: 7.+(scala.internal.Quoted.patternHole[scala.Int]) -Result: None - -Scrutinee: 6.+(x) -Pattern: scala.internal.Quoted.patternHole[scala.Int].+(4) -Result: None - -Scrutinee: g[scala.Int] -Pattern: scala.internal.Quoted.patternHole[scala.Predef.String] -Result: None - -Scrutinee: h[scala.Int](7) -Pattern: h[scala.Predef.String](scala.internal.Quoted.patternHole[scala.Predef.String]) -Result: None - -Scrutinee: h[scala.Int](6) -Pattern: h[scala.Int](7) -Result: None - -Scrutinee: z = 4 -Pattern: z = 5 -Result: None - -Scrutinee: z = 4 -Pattern: z2 = 4 -Result: None - -Scrutinee: f(4) -Pattern: scala.internal.Quoted.patternHole[scala.Int] -Result: Some(List(Expr(f(4)))) - -Scrutinee: f(5) -Pattern: f(scala.internal.Quoted.patternHole[scala.Int]) -Result: Some(List(Expr(5))) - -Scrutinee: g[scala.Int] -Pattern: scala.internal.Quoted.patternHole[scala.Int] -Result: Some(List(Expr(g[scala.Int]))) - -Scrutinee: h[scala.Int](7) -Pattern: scala.internal.Quoted.patternHole[scala.Int] -Result: Some(List(Expr(h[scala.Int](7)))) - -Scrutinee: h[scala.Int](8) -Pattern: h[scala.Int](scala.internal.Quoted.patternHole[scala.Int]) -Result: Some(List(Expr(8))) - -Scrutinee: Test.this -Pattern: Test.this -Result: Some(List()) - -Scrutinee: Test.this -Pattern: scala.internal.Quoted.patternHole[this.type] -Result: Some(List(Expr(Test.this))) - -Scrutinee: new Foo(1) -Pattern: new Foo(1) -Result: Some(List()) - -Scrutinee: new Foo(1) -Pattern: scala.internal.Quoted.patternHole[Foo] -Result: Some(List(Expr(new Foo(1)))) - -Scrutinee: new Foo(1) -Pattern: new Foo(scala.internal.Quoted.patternHole[scala.Int]) -Result: Some(List(Expr(1))) - -Scrutinee: if (b) x else y -Pattern: if (b) x else y -Result: Some(List()) - -Scrutinee: if (b) x else y -Pattern: scala.internal.Quoted.patternHole[scala.Int] -Result: Some(List(Expr(if (b) x else y))) - -Scrutinee: if (b) x else y -Pattern: if (scala.internal.Quoted.patternHole[scala.Boolean]) scala.internal.Quoted.patternHole[scala.Int] else scala.internal.Quoted.patternHole[scala.Int] -Result: Some(List(Expr(b), Expr(x), Expr(y))) - -Scrutinee: while (b) { - x - () -} -Pattern: while (b) { - x - () -} -Result: Some(List()) - -Scrutinee: while (b) { - x - () -} -Pattern: scala.internal.Quoted.patternHole[scala.Unit] -Result: Some(List(Expr(while (b) { - x - () -}))) - -Scrutinee: while (b) { - x - () -} -Pattern: while (scala.internal.Quoted.patternHole[scala.Boolean]) { - scala.internal.Quoted.patternHole[scala.Int] - () -} -Result: Some(List(Expr(b), Expr(x))) - -Scrutinee: z = 4 -Pattern: z = 4 -Result: Some(List()) - -Scrutinee: z = 4 -Pattern: scala.internal.Quoted.patternHole[scala.Unit] -Result: Some(List(Expr(z = 4))) - -Scrutinee: z = 4 -Pattern: z = scala.internal.Quoted.patternHole[scala.Int] -Result: Some(List(Expr(4))) - -Scrutinee: 1 -Pattern: 1 -Result: Some(List()) - -Scrutinee: 1 -Pattern: 1 -Result: Some(List()) - -Scrutinee: fs() -Pattern: fs() -Result: Some(List()) - -Scrutinee: fs() -Pattern: fs((scala.internal.Quoted.patternHole[scala.Seq[scala.Int]]: scala.[scala.Int])) -Result: Some(List(Expr((: scala.[scala.Int])))) - -Scrutinee: fs((1, 2, 3: scala.[scala.Int])) -Pattern: fs((1, 2, 3: scala.[scala.Int])) -Result: Some(List()) - -Scrutinee: fs((1, 2, 3: scala.[scala.Int])) -Pattern: fs((scala.internal.Quoted.patternHole[scala.Int], scala.internal.Quoted.patternHole[scala.Int], 3: scala.[scala.Int])) -Result: Some(List(Expr(1), Expr(2))) - -Scrutinee: fs((1, 2, 3: scala.[scala.Int])) -Pattern: fs((scala.internal.Quoted.patternHole[scala.Seq[scala.Int]]: scala.[scala.Int])) -Result: Some(List(Expr((1, 2, 3: scala.[scala.Int])))) - -Scrutinee: f2(1, 2) -Pattern: f2(1, 2) -Result: Some(List()) - -Scrutinee: f2(a = 1, b = 2) -Pattern: f2(a = 1, b = 2) -Result: Some(List()) - -Scrutinee: f2(a = 1, b = 2) -Pattern: f2(a = scala.internal.Quoted.patternHole[scala.Int], b = scala.internal.Quoted.patternHole[scala.Int]) -Result: Some(List(Expr(1), Expr(2))) - -Scrutinee: super.toString() -Pattern: super.toString() -Result: Some(List()) - -Scrutinee: (() => "abc") -Pattern: scala.internal.Quoted.patternHole[scala.Function0[scala.Predef.String]] -Result: Some(List(Expr((() => "abc")))) - -Scrutinee: (() => "abc").apply() -Pattern: scala.internal.Quoted.patternHole[scala.Function0[scala.Predef.String]].apply() -Result: Some(List(Expr((() => "abc")))) - -Scrutinee: ((x: scala.Int) => "abc") -Pattern: scala.internal.Quoted.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.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.patternBindHole) => scala.internal.Quoted.patternHole[scala.Predef.String]) -Result: Some(List(Bind(x), Expr("abc"))) - -Scrutinee: scala.StringContext.apply(("abc", "xyz": scala.[scala.Predef.String])) -Pattern: scala.StringContext.apply(("abc", "xyz": scala.[scala.Predef.String])) -Result: Some(List()) - -Scrutinee: scala.StringContext.apply(("abc", "xyz": scala.[scala.Predef.String])) -Pattern: scala.StringContext.apply((scala.internal.Quoted.patternHole[java.lang.String], scala.internal.Quoted.patternHole[java.lang.String]: scala.[scala.Predef.String])) -Result: Some(List(Expr("abc"), Expr("xyz"))) - -Scrutinee: scala.StringContext.apply(("abc", "xyz": scala.[scala.Predef.String])) -Pattern: scala.StringContext.apply((scala.internal.Quoted.patternHole[scala.Seq[scala.Predef.String]]: scala.[scala.Predef.String])) -Result: Some(List(Expr(("abc", "xyz": scala.[scala.Predef.String])))) - -Scrutinee: { - val a: scala.Int = 45 - () -} -Pattern: { - val a: scala.Int = 45 - () -} -Result: Some(List()) - -Scrutinee: { - val a: scala.Int = 45 - () -} -Pattern: { - @scala.internal.Quoted.patternBindHole val a: scala.Int = scala.internal.Quoted.patternHole[scala.Int] - () -} -Result: Some(List(Bind(a), Expr(45))) - -Scrutinee: { - val a: scala.Int = 45 - () -} -Pattern: { - lazy val a: scala.Int = 45 - () -} -Result: None - -Scrutinee: { - val a: scala.Int = 45 - () -} -Pattern: { - var a: scala.Int = 45 - () -} -Result: None - -Scrutinee: { - val a: scala.Int = 45 - () -} -Pattern: { - @scala.internal.Quoted.patternBindHole var a: scala.Int = scala.internal.Quoted.patternHole[scala.Int] - () -} -Result: None - -Scrutinee: { - lazy val a: scala.Int = 45 - () -} -Pattern: { - val a: scala.Int = 45 - () -} -Result: None - -Scrutinee: { - lazy val a: scala.Int = 45 - () -} -Pattern: { - lazy val a: scala.Int = 45 - () -} -Result: Some(List()) - -Scrutinee: { - lazy val a: scala.Int = 45 - () -} -Pattern: { - var a: scala.Int = 45 - () -} -Result: None - -Scrutinee: { - lazy val a: scala.Int = 45 - () -} -Pattern: { - @scala.internal.Quoted.patternBindHole val a: scala.Int = scala.internal.Quoted.patternHole[scala.Int] - () -} -Result: None - -Scrutinee: { - lazy val a: scala.Int = 45 - () -} -Pattern: { - @scala.internal.Quoted.patternBindHole var a: scala.Int = scala.internal.Quoted.patternHole[scala.Int] - () -} -Result: None - -Scrutinee: { - var a: scala.Int = 45 - () -} -Pattern: { - val a: scala.Int = 45 - () -} -Result: None - -Scrutinee: { - var a: scala.Int = 45 - () -} -Pattern: { - lazy val a: scala.Int = 45 - () -} -Result: None - -Scrutinee: { - var a: scala.Int = 45 - () -} -Pattern: { - var a: scala.Int = 45 - () -} -Result: Some(List()) - -Scrutinee: { - var a: scala.Int = 45 - () -} -Pattern: { - @scala.internal.Quoted.patternBindHole val a: scala.Int = scala.internal.Quoted.patternHole[scala.Int] - () -} -Result: None - -Scrutinee: { - var a: scala.Int = 45 - () -} -Pattern: { - @scala.internal.Quoted.patternBindHole lazy val a: scala.Int = scala.internal.Quoted.patternHole[scala.Int] - () -} -Result: None - -Scrutinee: { - scala.Predef.println() - scala.Predef.println() -} -Pattern: { - scala.Predef.println() - scala.Predef.println() -} -Result: Some(List()) - -Scrutinee: { - scala.Predef.println() - scala.Predef.println() -} -Pattern: { - scala.Predef.println() - scala.Predef.println() -} -Result: Some(List()) - -Scrutinee: { - scala.Predef.println() - scala.Predef.println() -} -Pattern: { - scala.Predef.println() - scala.Predef.println() -} -Result: Some(List()) - -Scrutinee: { - scala.Predef.println() - scala.Predef.println() -} -Pattern: { - scala.Predef.println() - scala.Predef.println() -} -Result: Some(List()) - -Scrutinee: { - scala.Predef.println() - scala.Predef.println() -} -Pattern: { - scala.Predef.println() - scala.Predef.println() -} -Result: Some(List()) - -Scrutinee: { - def a: scala.Int = 45 - () -} -Pattern: { - def a: scala.Int = 45 - () -} -Result: Some(List()) - -Scrutinee: { - def a: scala.Int = 45 - () -} -Pattern: { - @scala.internal.Quoted.patternBindHole def a: scala.Int = scala.internal.Quoted.patternHole[scala.Int] - () -} -Result: Some(List(Bind(a), Expr(45))) - -Scrutinee: { - def a(x: scala.Int): scala.Int = 45 - () -} -Pattern: { - def a(x: scala.Int): scala.Int = 45 - () -} -Result: Some(List()) - -Scrutinee: { - def a(x: scala.Int): scala.Int = 45 - () -} -Pattern: { - def a(x: scala.Int, y: scala.Int): scala.Int = 45 - () -} -Result: None - -Scrutinee: { - def a(x: scala.Int): scala.Int = 45 - () -} -Pattern: { - def a(x: scala.Int)(y: scala.Int): scala.Int = 45 - () -} -Result: None - -Scrutinee: { - def a(x: scala.Int, y: scala.Int): scala.Int = 45 - () -} -Pattern: { - def a(x: scala.Int): scala.Int = 45 - () -} -Result: None - -Scrutinee: { - def a(x: scala.Int)(y: scala.Int): scala.Int = 45 - () -} -Pattern: { - def a(x: scala.Int): scala.Int = 45 - () -} -Result: None - -Scrutinee: { - def a(x: scala.Predef.String): scala.Int = 45 - () -} -Pattern: { - def a(x: scala.Predef.String): scala.Int = 45 - () -} -Result: Some(List()) - -Scrutinee: { - def a(x: scala.Int): scala.Int = 45 - () -} -Pattern: { - def a(x: scala.Int @scala.internal.Quoted.patternBindHole): scala.Int = 45 - () -} -Result: Some(List(Bind(x))) - -Scrutinee: { - def a(x: scala.Int): scala.Int = 45 - () -} -Pattern: { - def a(x: scala.Int @scala.internal.Quoted.patternBindHole): scala.Int = 45 - () -} -Result: Some(List(Bind(x))) - -Scrutinee: { - def a(x: scala.Int): scala.Int = x - () -} -Pattern: { - def b(y: scala.Int): scala.Int = y - () -} -Result: Some(List()) - -Scrutinee: { - def a: scala.Int = a - () -} -Pattern: { - def b: scala.Int = b - () -} -Result: Some(List()) - -Scrutinee: { - lazy val a: scala.Int = a - () -} -Pattern: { - lazy val b: scala.Int = b - () -} -Result: Some(List()) - -Scrutinee: 1 match { - case _ => - 2 -} -Pattern: 1 match { - case _ => - 2 -} -Result: Some(List()) - -Scrutinee: 1 match { - case _ => - 2 -} -Pattern: scala.internal.Quoted.patternHole[scala.Int] match { - case _ => - scala.internal.Quoted.patternHole[scala.Int] -} -Result: Some(List(Expr(1), Expr(2))) - -Scrutinee: scala.Predef.??? match { - case scala.None => - 2 -} -Pattern: scala.Predef.??? match { - case scala.None => - 2 -} -Result: Some(List()) - -Scrutinee: scala.Predef.??? match { - case scala.Some(1) => - 2 -} -Pattern: scala.Predef.??? match { - case scala.Some(1) => - 2 -} -Result: Some(List()) - -Scrutinee: try 1 catch { - case _ => - 2 -} -Pattern: try 1 catch { - case _ => - 2 -} -Result: Some(List()) - -Scrutinee: try 1 finally { - 2 - () -} -Pattern: try 1 finally { - 2 - () -} -Result: Some(List()) - -Scrutinee: try 1 catch { - case _ => - 2 -} -Pattern: try scala.internal.Quoted.patternHole[scala.Int] catch { - case _ => - scala.internal.Quoted.patternHole[scala.Int] -} -Result: Some(List(Expr(1), Expr(2))) - -Scrutinee: try 1 finally { - 2 - () -} -Pattern: try scala.internal.Quoted.patternHole[scala.Int] finally { - scala.internal.Quoted.patternHole[scala.Int] - () -} -Result: Some(List(Expr(1), Expr(2))) - diff --git a/tests/run-macros/quote-matcher-runtime/quoted_1.scala b/tests/run-macros/quote-matcher-runtime/quoted_1.scala index 8e2ef4d8a071..75b9e87bceca 100644 --- a/tests/run-macros/quote-matcher-runtime/quoted_1.scala +++ b/tests/run-macros/quote-matcher-runtime/quoted_1.scala @@ -10,7 +10,7 @@ object Macros { private def impl[A, B](a: Expr[A], b: Expr[B])(implicit reflect: Reflection): Expr[Unit] = { import reflect.{Bind => _, _} - val res = scala.internal.quoted.Matcher.unapply[Tuple](a)(b, reflect).map { tup => + val res = scala.internal.quoted.Matcher.unapply[Tuple, Tuple](a)(b, reflect).map { tup => tup.toArray.toList.map { case r: Expr[_] => s"Expr(${r.unseal.show})" diff --git a/tests/run-macros/quote-matcher-runtime/quoted_2.scala b/tests/run-macros/quote-matcher-runtime/quoted_2.scala index ca424f94de4a..af0bc3da675f 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.Matcher._ -import scala.internal.Quoted.{patternHole, patternBindHole} +import scala.internal.Quoted._ object Test { @@ -19,116 +19,118 @@ object Test { def h[A](a: A): A = a def fs(a: Int*): Int = 72 - matches(1, 1) - matches(1, 2) - matches(1: Int, 1) - matches(1: Int, 1: Int) - matches(1, 1: Int) - matches(3, patternHole[Int]) - matches(x, patternHole[Int]) - matches(5, patternHole[Any]) - matches(6 + x, patternHole[Int]) - matches(6 + x, 6 + patternHole[Int]) - matches(6 + x, patternHole[Int] + x) - matches(6 + x, patternHole[Int] + patternHole[Int]) - matches(6 + x + y, 6 + patternHole[Int] + y) - matches(4, patternHole[String]) - matches(6 + x, 7 + patternHole[Int]) - matches(6 + x, patternHole[Int] + 4) - matches(g[Int], patternHole[String]) - matches(h[Int](7), h[String](patternHole[String])) - matches(h[Int](6), h[Int](7)) - matches({z = 4}, {z = 5}) - matches({z = 4}, {z2 = 4}) - matches(f(4), patternHole[Int]) - matches(f(5), f(patternHole[Int])) - matches(g[Int], patternHole[Int]) - matches(h[Int](7), patternHole[Int]) - matches(h[Int](8), h[Int](patternHole[Int])) - matches(this, this) - matches(this, patternHole[this.type]) - matches(new Foo(1), new Foo(1)) - matches(new Foo(1), patternHole[Foo]) - matches(new Foo(1), new Foo(patternHole[Int])) - matches(if (b) x else y, if (b) x else y) - matches(if (b) x else y, patternHole[Int]) - matches(if (b) x else y, if (patternHole[Boolean]) patternHole[Int] else patternHole[Int]) - matches(while (b) x, while (b) x) - matches(while (b) x, patternHole[Unit]) - matches(while (b) x, while (patternHole[Boolean]) patternHole[Int]) - matches({z = 4}, {z = 4}) - matches({z = 4}, patternHole[Unit]) - matches({z = 4}, {z = patternHole[Int]}) - // matches({z = 4}, {varHole = 4}) - matches(1, {1}) - matches({1}, 1) - // Should these match? - // matches({(); 1}, 1) - // matches(1, {(); 1}) - matches(fs(), fs()) - matches(fs(), fs(patternHole[Seq[Int]]: _*)) - matches(fs(1, 2, 3), fs(1, 2, 3)) - matches(fs(1, 2, 3), fs(patternHole[Int], patternHole[Int], 3)) - matches(fs(1, 2, 3), fs(patternHole[Seq[Int]]: _*)) - matches(f2(1, 2), f2(1, 2)) - matches(f2(a = 1, b = 2), f2(a = 1, b = 2)) - matches(f2(a = 1, b = 2), f2(a = patternHole[Int], b = patternHole[Int])) - // Should these match? - // matches(f2(a = 1, b = 2), f2(1, 2)) - // matches(f2(b = 2, a = 1), f2(1, 2)) - matches(super.toString, super.toString) - matches(() => "abc", patternHole[() => String]) - matches((() => "abc")(), (patternHole[() => String]).apply()) - matches((x: Int) => "abc", patternHole[Int=> String]) - matches(((x: Int) => "abc")(4), (patternHole[Int => String]).apply(4)) - matches((x: Int) => "abc", (x: Int @patternBindHole) => patternHole[String]) - matches(StringContext("abc", "xyz"), StringContext("abc", "xyz")) - matches(StringContext("abc", "xyz"), StringContext(patternHole, patternHole)) - matches(StringContext("abc", "xyz"), StringContext(patternHole[Seq[String]]: _*)) - matches({ val a: Int = 45 }, { val a: Int = 45 }) - matches({ val a: Int = 45 }, { @patternBindHole val a: Int = patternHole }) - matches({ val a: Int = 45 }, { lazy val a: Int = 45 }) - matches({ val a: Int = 45 }, { var a: Int = 45 }) - matches({ val a: Int = 45 }, { @patternBindHole var a: Int = patternHole }) - matches({ lazy val a: Int = 45 }, { val a: Int = 45 }) - matches({ lazy val a: Int = 45 }, { lazy val a: Int = 45 }) - matches({ lazy val a: Int = 45 }, { var a: Int = 45 }) - matches({ lazy val a: Int = 45 }, { @patternBindHole val a: Int = patternHole }) - matches({ lazy val a: Int = 45 }, { @patternBindHole var a: Int = patternHole }) - matches({ var a: Int = 45 }, { val a: Int = 45 }) - matches({ var a: Int = 45 }, { lazy val a: Int = 45 }) - matches({ var a: Int = 45 }, { var a: Int = 45 }) - matches({ var a: Int = 45 }, { @patternBindHole val a: Int = patternHole }) - matches({ var a: Int = 45 }, { @patternBindHole lazy val a: Int = patternHole }) - matches({ println(); println() }, { println(); println() }) - matches({ { println() }; println() }, { println(); println() }) - matches({ println(); { println() } }, { println(); println() }) - matches({ println(); println() }, { println(); { println() } }) - matches({ println(); println() }, { { println() }; println() }) - matches({ def a: Int = 45 }, { def a: Int = 45 }) - matches({ def a: Int = 45 }, { @patternBindHole def a: Int = patternHole[Int] }) - matches({ def a(x: Int): Int = 45 }, { def a(x: Int): Int = 45 }) - matches({ def a(x: Int): Int = 45 }, { def a(x: Int, y: Int): Int = 45 }) - matches({ def a(x: Int): Int = 45 }, { def a(x: Int)(y: Int): Int = 45 }) - matches({ def a(x: Int, y: Int): Int = 45 }, { def a(x: Int): Int = 45 }) - matches({ def a(x: Int)(y: Int): Int = 45 }, { def a(x: Int): Int = 45 }) - matches({ def a(x: String): Int = 45 }, { def a(x: String): Int = 45 }) - matches({ def a(x: Int): Int = 45 }, { def a(x: Int @patternBindHole): Int = 45 }) - matches({ def a(x: Int): Int = 45 }, { def a(x: Int @patternBindHole): Int = 45 }) - matches({ def a(x: Int): Int = x }, { def b(y: Int): Int = y }) - matches({ def a: Int = a }, { def b: Int = b }) - matches({ lazy val a: Int = a }, { lazy val b: Int = b }) - matches(1 match { case _ => 2 }, 1 match { case _ => 2 }) - matches(1 match { case _ => 2 }, patternHole[Int] match { case _ => patternHole[Int] }) - matches(??? match { case None => 2 }, ??? match { case None => 2 }) - matches(??? match { case Some(1) => 2 }, ??? match { case Some(1) => 2 }) - // matches(??? match { case Some(1) => 2 }, ??? match { case Some(patternMatchHole()) => 2 }) - // matches(??? match { case Some(n) => 2 }, ??? match { case Some(patternMatchBindHole(n)) => 2 }) - // matches(??? match { case Some(n @ Some(m)) => 2 }, ??? match { case Some(patterMatchBindHole(n @ Some(patternMatchBindHole(m)))) => 2 }) - matches(try 1 catch { case _ => 2 }, try 1 catch { case _ => 2 }) - matches(try 1 finally 2, try 1 finally 2) - matches(try 1 catch { case _ => 2 }, try patternHole[Int] catch { case _ => patternHole[Int] }) - matches(try 1 finally 2, try patternHole[Int] finally patternHole[Int]) +// matches(1, 1) +// matches(1, 2) +// matches(1: Int, 1) +// matches(1: Int, 1: Int) +// matches(1, 1: Int) +// matches(3, patternHole[Int]) +// matches(x, patternHole[Int]) +// matches(5, patternHole[Any]) +// matches(6 + x, patternHole[Int]) +// matches(6 + x, 6 + patternHole[Int]) +// matches(6 + x, patternHole[Int] + x) +// matches(6 + x, patternHole[Int] + patternHole[Int]) +// matches(6 + x + y, 6 + patternHole[Int] + y) +// matches(4, patternHole[String]) +// matches(6 + x, 7 + patternHole[Int]) +// matches(6 + x, patternHole[Int] + 4) +// matches(g[Int], patternHole[String]) +// matches(h[Int](7), h[String](patternHole[String])) +// matches(h[Int](6), h[Int](7)) +// matches({z = 4}, {z = 5}) +// matches({z = 4}, {z2 = 4}) +// matches(f(4), patternHole[Int]) +// matches(f(5), f(patternHole[Int])) +// matches(g[Int], patternHole[Int]) +// matches(h[Int](7), patternHole[Int]) +// matches(h[Int](8), h[Int](patternHole[Int])) +// matches(this, this) +// matches(this, patternHole[this.type]) +// matches(new Foo(1), new Foo(1)) +// matches(new Foo(1), patternHole[Foo]) +// matches(new Foo(1), new Foo(patternHole[Int])) +// matches(if (b) x else y, if (b) x else y) +// matches(if (b) x else y, patternHole[Int]) +// matches(if (b) x else y, if (patternHole[Boolean]) patternHole[Int] else patternHole[Int]) +// matches(while (b) x, while (b) x) +// matches(while (b) x, patternHole[Unit]) +// matches(while (b) x, while (patternHole[Boolean]) patternHole[Int]) +// matches({z = 4}, {z = 4}) +// matches({z = 4}, patternHole[Unit]) +// matches({z = 4}, {z = patternHole[Int]}) +// // matches({z = 4}, {varHole = 4}) +// matches(1, {1}) +// matches({1}, 1) +// // Should these match? +// // matches({(); 1}, 1) +// // matches(1, {(); 1}) +// matches(fs(), fs()) +// matches(fs(), fs(patternHole[Seq[Int]]: _*)) +// matches(fs(1, 2, 3), fs(1, 2, 3)) +// matches(fs(1, 2, 3), fs(patternHole[Int], patternHole[Int], 3)) +// matches(fs(1, 2, 3), fs(patternHole[Seq[Int]]: _*)) +// matches(f2(1, 2), f2(1, 2)) +// matches(f2(a = 1, b = 2), f2(a = 1, b = 2)) +// matches(f2(a = 1, b = 2), f2(a = patternHole[Int], b = patternHole[Int])) +// // Should these match? +// // matches(f2(a = 1, b = 2), f2(1, 2)) +// // matches(f2(b = 2, a = 1), f2(1, 2)) +// matches(super.toString, super.toString) +// matches(() => "abc", patternHole[() => String]) +// matches((() => "abc")(), (patternHole[() => String]).apply()) +// matches((x: Int) => "abc", patternHole[Int=> String]) +// matches(((x: Int) => "abc")(4), (patternHole[Int => String]).apply(4)) +// matches((x: Int) => "abc", (x: Int @patternBindHole) => patternHole[String]) +// matches(StringContext("abc", "xyz"), StringContext("abc", "xyz")) +// matches(StringContext("abc", "xyz"), StringContext(patternHole, patternHole)) +// matches(StringContext("abc", "xyz"), StringContext(patternHole[Seq[String]]: _*)) +// matches({ val a: Int = 45 }, { val a: Int = 45 }) +// matches({ val a: Int = 45 }, { @patternBindHole val a: Int = patternHole }) +// matches({ val a: Int = 45 }, { lazy val a: Int = 45 }) +// matches({ val a: Int = 45 }, { var a: Int = 45 }) +// matches({ val a: Int = 45 }, { @patternBindHole var a: Int = patternHole }) +// matches({ lazy val a: Int = 45 }, { val a: Int = 45 }) +// matches({ lazy val a: Int = 45 }, { lazy val a: Int = 45 }) +// matches({ lazy val a: Int = 45 }, { var a: Int = 45 }) +// matches({ lazy val a: Int = 45 }, { @patternBindHole val a: Int = patternHole }) +// matches({ lazy val a: Int = 45 }, { @patternBindHole var a: Int = patternHole }) +// matches({ var a: Int = 45 }, { val a: Int = 45 }) +// matches({ var a: Int = 45 }, { lazy val a: Int = 45 }) +// matches({ var a: Int = 45 }, { var a: Int = 45 }) +// matches({ var a: Int = 45 }, { @patternBindHole val a: Int = patternHole }) +// matches({ var a: Int = 45 }, { @patternBindHole lazy val a: Int = patternHole }) +// matches({ println(); println() }, { println(); println() }) +// matches({ { println() }; println() }, { println(); println() }) +// matches({ println(); { println() } }, { println(); println() }) +// matches({ println(); println() }, { println(); { println() } }) +// matches({ println(); println() }, { { println() }; println() }) +// matches({ def a: Int = 45 }, { def a: Int = 45 }) +// matches({ def a: Int = 45 }, { @patternBindHole def a: Int = patternHole[Int] }) +// matches({ def a(x: Int): Int = 45 }, { def a(x: Int): Int = 45 }) +// matches({ def a(x: Int): Int = 45 }, { def a(x: Int, y: Int): Int = 45 }) +// matches({ def a(x: Int): Int = 45 }, { def a(x: Int)(y: Int): Int = 45 }) +// matches({ def a(x: Int, y: Int): Int = 45 }, { def a(x: Int): Int = 45 }) +// matches({ def a(x: Int)(y: Int): Int = 45 }, { def a(x: Int): Int = 45 }) +// matches({ def a(x: String): Int = 45 }, { def a(x: String): Int = 45 }) +// matches({ def a(x: Int): Int = 45 }, { def a(x: Int @patternBindHole): Int = 45 }) +// matches({ def a(x: Int): Int = 45 }, { def a(x: Int @patternBindHole): Int = 45 }) +// matches({ def a(x: Int): Int = x }, { def b(y: Int): Int = y }) +// matches({ def a: Int = a }, { def b: Int = b }) +// matches({ lazy val a: Int = a }, { lazy val b: Int = b }) +// matches(1 match { case _ => 2 }, 1 match { case _ => 2 }) +// matches(1 match { case _ => 2 }, patternHole[Int] match { case _ => patternHole[Int] }) +// matches(??? match { case None => 2 }, ??? match { case None => 2 }) +// matches(??? match { case Some(1) => 2 }, ??? match { case Some(1) => 2 }) +// // matches(??? match { case Some(1) => 2 }, ??? match { case Some(patternMatchHole()) => 2 }) +// // matches(??? match { case Some(n) => 2 }, ??? match { case Some(patternMatchBindHole(n)) => 2 }) +// // matches(??? match { case Some(n @ Some(m)) => 2 }, ??? match { case Some(patterMatchBindHole(n @ Some(patternMatchBindHole(m)))) => 2 }) +// matches(try 1 catch { case _ => 2 }, try 1 catch { case _ => 2 }) +// matches(try 1 finally 2, try 1 finally 2) +// matches(try 1 catch { case _ => 2 }, try patternHole[Int] catch { case _ => patternHole[Int] }) +// matches(try 1 finally 2, try patternHole[Int] finally patternHole[Int]) + + matches({ val a: Int = 3; a }, { @patternBindHole type $t; val x: patternTypeHole[$t] = patternHole[$t]; x }) } } diff --git a/tests/run-with-compiler/quote-matcher-type-bind/Macro_1.scala b/tests/run-with-compiler/quote-matcher-type-bind/Macro_1.scala new file mode 100644 index 000000000000..7aaceed7463c --- /dev/null +++ b/tests/run-with-compiler/quote-matcher-type-bind/Macro_1.scala @@ -0,0 +1,100 @@ +import scala.quoted._ +import scala.quoted.matching._ + +import scala.tasty.Reflection + +import scala.internal.quoted.Matcher._ +import scala.internal.Quoted._ + +object Macros { + + inline def swapFandG(x: => Unit): Unit = ${impl('x)} + + private def impl(x: Expr[Unit])(implicit reflect: Reflection): Expr[Unit] = { + + type TT // type binding + object DSLf { + def unapply(x: Expr[_])(implicit reflect: Reflection): Option[Tuple2[Type[_], Expr[Any]]] = + scala.internal.quoted.Matcher.unapply[Tuple2[Type[_], Expr[Any]]](x)('{type t; DSL.f[Hole[t]](patternHole[t]) }, reflect) + } // case '{ DSL.f[$t]($x) } => + + x match { + // case '{ DSL.f[$t]($x) } => + // case scala.internal.quoted.Matcher.unapply[Tuple2[Type[tt @ _], Expr[tt]]](Tuple2(t, TypedExpr(x)(`t`, reflect))(/*implicits*/ '{ DSL.f[Hole[Nothing, Any]](hole[Any])] }, reflect) => + case DSLf((t: Type[tt], x: Expr[t2])) => + + implicit val tt = t + '{ DSL.g[$t]($x) } + + // case '{ DSL.f[$t]($x) } => + // case DSLg(t, x) => + // '{ DSL.f[$t]($x) } +??? + case _ => + x + } + } + +} + + +object TypedExpr { + def unapply[T](arg: Expr[_])(implicit t: Type[T], reflect: Reflection): Option[Expr[T]] = { + import reflect._ + if (arg.unseal.tpe <:< t.unseal.tpe) Some(arg.asInstanceOf[Expr[T]]) + else None + } +} + + +// +// DSL in which the user write the code +// + +object DSL { + def f[T](x: T): Unit = println("f: " + x.toString) + def g[T](x: T): Unit = println("g: " + x.toString) +} + +// +// Helper to abstract call to scala.internal.quoted.Matcher.unapply and setup an object with the unapply +// + +class ExprMatch[Tup <: Tuple](pattern: Expr[_]) { + def unapply(x: Expr[_])(implicit reflect: Reflection): Option[Tup] = + scala.internal.quoted.Matcher.unapply[Tup](x)(pattern, reflect) +} + + +//class a { +// +// def foo(x: Any) = +// +// new Foo { type T = Int; type Tup = (Int, List[Int]); val contents: Tup = (3, 5 :: Nil) } match { +// case Bar(x, ls) => +// val l2 = x :: ls +// l2 +// } +// new Foo { val contents = ??? } match { +// case Bar(x, ls) => +// val l2 = x :: ls +// l2 +// } +//} +// +// +// +//trait Foo { +// type T +// type Tup <: Tuple +// val contents: Tup +//} +// +//object Foo { +// def unaplly[F <: Foo](arg: F): Option[arg.Tup] = Some(arg.contents) +//} +// +//object Bar { +// def unapply(arg: Foo { type Tup = (T, List[T]) }): Option[arg.Tup] = +// Foo.unaplly[Foo { type Tup = (T, List[T]) }](arg) +//} \ No newline at end of file diff --git a/tests/run-with-compiler/quote-matcher-type-bind/Test_2.scala b/tests/run-with-compiler/quote-matcher-type-bind/Test_2.scala new file mode 100644 index 000000000000..43ed9608bebc --- /dev/null +++ b/tests/run-with-compiler/quote-matcher-type-bind/Test_2.scala @@ -0,0 +1,11 @@ +import Macros._ + + +object Test { + + def main(args: Array[String]): Unit = { + swapFandG(DSL.f(5)) + // swapFandG(DSL.g("abc")) + } + +}