Skip to content

Encode quote pattern matches directly on QuoteContext #10246

New issue

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

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

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,8 @@ class Definitions {

@tu lazy val QuoteContextClass: ClassSymbol = requiredClass("scala.quoted.QuoteContext")
@tu lazy val QuoteContextInternalClass: ClassSymbol = requiredClass("scala.internal.quoted.QuoteContextInternal")
@tu lazy val QuoteContextInternalClass_ExprMatch: Symbol = QuoteContextInternalClass.requiredMethod("ExprMatch")
@tu lazy val QuoteContextInternalClass_TypeMatch: Symbol = QuoteContextInternalClass.requiredMethod("TypeMatch")

@tu lazy val LiftableModule: Symbol = requiredModule("scala.quoted.Liftable")
@tu lazy val LiftableModule_BooleanLiftable: Symbol = LiftableModule.requiredMethod("BooleanLiftable")
Expand All @@ -821,14 +823,6 @@ class Definitions {
@tu lazy val InternalQuotedPatterns_patternTypeAnnot: ClassSymbol = InternalQuotedPatterns.requiredClass("patternType")
@tu lazy val InternalQuotedPatterns_fromAboveAnnot: ClassSymbol = InternalQuotedPatterns.requiredClass("fromAbove")

@tu lazy val InternalQuotedExprModule: Symbol = requiredModule("scala.internal.quoted.Expr")
@tu lazy val InternalQuotedExpr_unapply: Symbol = InternalQuotedExprModule.requiredMethod(nme.unapply)
@tu lazy val InternalQuotedExpr_null: Symbol = InternalQuotedExprModule.requiredMethod(nme.null_)
@tu lazy val InternalQuotedExpr_unit: Symbol = InternalQuotedExprModule.requiredMethod(nme.Unit)

@tu lazy val InternalQuotedTypeModule: Symbol = requiredModule("scala.internal.quoted.Type")
@tu lazy val InternalQuotedType_unapply: Symbol = InternalQuotedTypeModule.requiredMethod(nme.unapply)

@tu lazy val QuotedTypeClass: ClassSymbol = requiredClass("scala.quoted.Type")
@tu lazy val QuotedType_splice: Symbol = QuotedTypeClass.requiredType(tpnme.Underlying)

Expand Down
18 changes: 13 additions & 5 deletions compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2639,11 +2639,19 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, scala.intern
val tree = PickledQuotes.unpickleTypeTree(pickledQuote)(using reflect.rootContext)
new scala.internal.quoted.Type(tree, hash).asInstanceOf[scala.quoted.Type[T]]

def exprMatch(scrutinee: scala.quoted.Expr[Any], pattern: scala.quoted.Expr[Any]): Option[Tuple] =
treeMatch(scrutinee.unseal(using this), pattern.unseal(using this))

def typeMatch(scrutinee: scala.quoted.Type[?], pattern: scala.quoted.Type[?]): Option[Tuple] =
treeMatch(reflect.TypeTree.of(using scrutinee), reflect.TypeTree.of(using pattern))
object ExprMatch extends ExprMatchModule:
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutinee: scala.quoted.Expr[Any])(using pattern: scala.quoted.Expr[Any]): Option[Tup] =
val scrutineeTree = scrutinee.unseal(using QuoteContextImpl.this)
val patternTree = pattern.unseal(using QuoteContextImpl.this)
treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]]
end ExprMatch

object TypeMatch extends TypeMatchModule:
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutinee: scala.quoted.Type[?])(using pattern: scala.quoted.Type[?]): Option[Tup] =
val scrutineeTree = reflect.TypeTree.of(using scrutinee)
val patternTree = reflect.TypeTree.of(using pattern)
treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]]
end TypeMatch

private def treeMatch(scrutinee: reflect.Tree, pattern: reflect.Tree): Option[Tuple] = {
import reflect._
Expand Down
9 changes: 6 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala
Original file line number Diff line number Diff line change
Expand Up @@ -458,14 +458,17 @@ trait QuotesAndSplices {
if splices.isEmpty then ref(defn.EmptyTupleModule.termRef)
else typed(untpd.Tuple(splices.map(x => untpd.TypedSplice(replaceBindingsInTree.transform(x)))).withSpan(quoted.span), patType)

val unapplySym = if (tree.quoted.isTerm) defn.InternalQuotedExpr_unapply else defn.InternalQuotedType_unapply
val quoteClass = if (tree.quoted.isTerm) defn.QuotedExprClass else defn.QuotedTypeClass
val quotedPattern =
if (tree.quoted.isTerm) ref(defn.InternalQuoted_exprQuote.termRef).appliedToType(defn.AnyType).appliedTo(shape).select(nme.apply).appliedTo(qctx)
else ref(defn.QuotedTypeModule_apply.termRef).appliedToTypeTree(shape).select(nme.apply).appliedTo(qctx)

val matchModule = if tree.quoted.isTerm then defn.QuoteContextInternalClass_ExprMatch else defn.QuoteContextInternalClass_TypeMatch
val unapplyFun = qctx.asInstance(defn.QuoteContextInternalClass.typeRef).select(matchModule).select(nme.unapply)

UnApply(
fun = ref(unapplySym.termRef).appliedToTypeTrees(typeBindingsTuple :: TypeTree(patType) :: Nil),
implicits = quotedPattern :: qctx :: Nil,
fun = unapplyFun.appliedToTypeTrees(typeBindingsTuple :: TypeTree(patType) :: Nil),
implicits = quotedPattern :: Nil,
patterns = splicePat :: Nil,
proto = quoteClass.typeRef.appliedTo(replaceBindings(quoted1.tpe) & quotedPt))
}
Expand Down
30 changes: 0 additions & 30 deletions library/src-bootstrapped/scala/internal/quoted/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,3 @@ final class Expr[Tree](val tree: Tree, val scopeId: Int) extends scala.quoted.Ex
override def hashCode: Int = tree.hashCode
override def toString: String = "'{ ... }"
}

object Expr {

/** Pattern matches an the scrutineeExpr against the patternExpr and returns a tuple
* with the matched holes if successful.
*
* Examples:
* - `Matcher.unapply('{ f(0, myInt) })('{ f(0, myInt) }, _)`
* will return `Some(())` (where `()` is a tuple of arity 0)
* - `Matcher.unapply('{ f(0, myInt) })('{ f(patternHole[Int], patternHole[Int]) }, _)`
* will return `Some(Tuple2('{0}, '{ myInt }))`
* - `Matcher.unapply('{ f(0, "abc") })('{ f(0, patternHole[Int]) }, _)`
* will return `None` due to the missmatch of types in the hole
*
* Holes:
* - scala.internal.Quoted.patternHole[T]: hole that matches an expression `x` of type `Expr[U]`
* if `U <:< T` and returns `x` as part of the match.
*
* @param scrutineeExpr `Expr[Any]` on which we are pattern matching
* @param patternExpr `Expr[Any]` containing the pattern tree
* @param hasTypeSplices `Boolean` notify if the pattern has type splices
* @param qctx the current QuoteContext
* @return None if it did not match, `Some(tup)` if it matched where `tup` contains `Expr[Ti]``
*/
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: scala.quoted.Expr[Any])
(using patternExpr: scala.quoted.Expr[Any], qctx: QuoteContext): Option[Tup] = {
qctx.asInstanceOf[QuoteContextInternal].exprMatch(scrutineeExpr, patternExpr).asInstanceOf[Option[Tup]]
}

}
18 changes: 0 additions & 18 deletions library/src-bootstrapped/scala/internal/quoted/Type.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,3 @@ final class Type[Tree](val typeTree: Tree, val scopeId: Int) extends scala.quote
override def hashCode: Int = typeTree.hashCode
override def toString: String = "'[ ... ]"
}

object Type {

/** Pattern matches an the scrutineeType against the patternType and returns a tuple
* with the matched holes if successful.
*
* @param scrutineeType `Type[_]` on which we are pattern matching
* @param patternType `Type[_]` containing the pattern tree
* @param hasTypeSplices `Boolean` notify if the pattern has type splices
* @param qctx the current QuoteContext
* @return None if it did not match, `Some(tup)` if it matched where `tup` contains `Type[Ti]``
*/
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeType: scala.quoted.Type[_])
(using patternType: scala.quoted.Type[_], qctx: QuoteContext): Option[Tup] = {
qctx.asInstanceOf[QuoteContextInternal].typeMatch(scrutineeType, patternType).asInstanceOf[Option[Tup]]
}

}
115 changes: 100 additions & 15 deletions library/src-bootstrapped/scala/quoted/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ abstract class Expr[+T] private[scala] {
* ```
*/
final def matches(that: Expr[Any])(using qctx: QuoteContext): Boolean =
!scala.internal.quoted.Expr.unapply[EmptyTuple, EmptyTuple](this)(using that, qctx).isEmpty
val ExprMatch = qctx.asInstanceOf[scala.internal.quoted.QuoteContextInternal].ExprMatch
ExprMatch.unapply[EmptyTuple, EmptyTuple](this)(using that).nonEmpty
Copy link
Contributor

Choose a reason for hiding this comment

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

From the usage, it seems to me ExprMatch and TypeMatch does not make it simpler. Do we have places where they are used as extractors?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the only place in the library where it is needed. But I plan to move this implementation out of the library and then I might not even need to have this call and could call the tree pattern matcher directly.

This is another method that should only be called from code generated by the compiler.


/** Checked cast to a `quoted.Expr[U]` */
def cast[U](using tp: scala.quoted.Type[U])(using qctx: QuoteContext): scala.quoted.Expr[U] = asExprOf[U]
Expand Down Expand Up @@ -121,57 +122,141 @@ object Expr {
* `'{ ($e1, $e2, ...) }` typed as an `Expr[Tuple]`
*/
def ofTupleFromSeq(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] = {
seq match {
case Seq() =>
'{ Tuple() }
case Seq('{ $x1: t1 }) =>
'{ Tuple1($x1) }
case Seq('{ $x1: t1 }, '{ $x2: t2 }) =>
'{ Tuple2($x1, $x2) }
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }) =>
'{ Tuple3($x1, $x2, $x3) }
seq.size match {
case 0 => '{ Tuple() }
case 1 => ofTupleFromSeq1(seq)
case 2 => ofTupleFromSeq2(seq)
case 3 => ofTupleFromSeq3(seq)
case 4 => ofTupleFromSeq4(seq)
case 5 => ofTupleFromSeq5(seq)
case 6 => ofTupleFromSeq6(seq)
case 7 => ofTupleFromSeq7(seq)
case 8 => ofTupleFromSeq8(seq)
case 9 => ofTupleFromSeq9(seq)
case 10 => ofTupleFromSeq10(seq)
case 11 => ofTupleFromSeq11(seq)
case 12 => ofTupleFromSeq12(seq)
case 13 => ofTupleFromSeq13(seq)
case 14 => ofTupleFromSeq14(seq)
case 15 => ofTupleFromSeq15(seq)
case 16 => ofTupleFromSeq16(seq)
case 17 => ofTupleFromSeq17(seq)
case 18 => ofTupleFromSeq18(seq)
case 19 => ofTupleFromSeq19(seq)
case 20 => ofTupleFromSeq20(seq)
case 21 => ofTupleFromSeq21(seq)
case 22 => ofTupleFromSeq22(seq)
case _ => '{ Tuple.fromIArray(IArray(${Varargs(seq)}: _*)) }
}
}

private def ofTupleFromSeq1(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }) => '{ Tuple1($x1) }

private def ofTupleFromSeq2(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }) => '{ Tuple2($x1, $x2) }

private def ofTupleFromSeq3(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }) => '{ Tuple3($x1, $x2, $x3) }

private def ofTupleFromSeq4(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }) =>
'{ Tuple4($x1, $x2, $x3, $x4) }
'{ Tuple4($x1, $x2, $x3, $x4) }

private def ofTupleFromSeq5(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }) =>
'{ Tuple5($x1, $x2, $x3, $x4, $x5) }

private def ofTupleFromSeq6(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }) =>
'{ Tuple6($x1, $x2, $x3, $x4, $x5, $x6) }

private def ofTupleFromSeq7(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }) =>
'{ Tuple7($x1, $x2, $x3, $x4, $x5, $x6, $x7) }

private def ofTupleFromSeq8(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }) =>
'{ Tuple8($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8) }

private def ofTupleFromSeq9(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }) =>
'{ Tuple9($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9) }

private def ofTupleFromSeq10(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }) =>
'{ Tuple10($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10) }

private def ofTupleFromSeq11(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }) =>
'{ Tuple11($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11) }

private def ofTupleFromSeq12(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }) =>
'{ Tuple12($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12) }

private def ofTupleFromSeq13(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }, '{ $x13: t13 }) =>
'{ Tuple13($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13) }

private def ofTupleFromSeq14(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }, '{ $x13: t13 }, '{ $x14: t14 }) =>
'{ Tuple14($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14) }

private def ofTupleFromSeq15(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }, '{ $x13: t13 }, '{ $x14: t14 }, '{ $x15: t15 }) =>
'{ Tuple15($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15) }

private def ofTupleFromSeq16(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }, '{ $x13: t13 }, '{ $x14: t14 }, '{ $x15: t15 }, '{ $x16: t16 }) =>
'{ Tuple16($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16) }

private def ofTupleFromSeq17(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }, '{ $x13: t13 }, '{ $x14: t14 }, '{ $x15: t15 }, '{ $x16: t16 }, '{ $x17: t17 }) =>
'{ Tuple17($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17) }

private def ofTupleFromSeq18(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }, '{ $x13: t13 }, '{ $x14: t14 }, '{ $x15: t15 }, '{ $x16: t16 }, '{ $x17: t17 }, '{ $x18: t18 }) =>
'{ Tuple18($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18) }

private def ofTupleFromSeq19(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }, '{ $x13: t13 }, '{ $x14: t14 }, '{ $x15: t15 }, '{ $x16: t16 }, '{ $x17: t17 }, '{ $x18: t18 }, '{ $x19: t19 }) =>
'{ Tuple19($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19) }

private def ofTupleFromSeq20(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }, '{ $x13: t13 }, '{ $x14: t14 }, '{ $x15: t15 }, '{ $x16: t16 }, '{ $x17: t17 }, '{ $x18: t18 }, '{ $x19: t19 }, '{ $x20: t20 }) =>
'{ Tuple20($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, $x20) }

private def ofTupleFromSeq21(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }, '{ $x13: t13 }, '{ $x14: t14 }, '{ $x15: t15 }, '{ $x16: t16 }, '{ $x17: t17 }, '{ $x18: t18 }, '{ $x19: t19 }, '{ $x20: t20 }, '{ $x21: t21 }) =>
'{ Tuple21($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, $x20, $x21) }

private def ofTupleFromSeq22(seq: Seq[Expr[Any]])(using qctx: QuoteContext): Expr[Tuple] =
seq match
case Seq('{ $x1: t1 }, '{ $x2: t2 }, '{ $x3: t3 }, '{ $x4: t4 }, '{ $x5: t5 }, '{ $x6: t6 }, '{ $x7: t7 }, '{ $x8: t8 }, '{ $x9: t9 }, '{ $x10: t10 }, '{ $x11: t11 }, '{ $x12: t12 }, '{ $x13: t13 }, '{ $x14: t14 }, '{ $x15: t15 }, '{ $x16: t16 }, '{ $x17: t17 }, '{ $x18: t18 }, '{ $x19: t19 }, '{ $x20: t20 }, '{ $x21: t21 }, '{ $x22: t22 }) =>
'{ Tuple22($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, $x20, $x21, $x22) }
case _ =>
'{ Tuple.fromIArray(IArray(${Varargs(seq)}: _*)) }
}
}


/** Given a tuple of the form `(Expr[A1], ..., Expr[An])`, outputs a tuple `Expr[(A1, ..., An)]`. */
def ofTuple[T <: Tuple: Tuple.IsMappedBy[Expr]: Type](tup: T)(using qctx: QuoteContext): Expr[Tuple.InverseMap[T, Expr]] = {
Expand Down
Loading