Skip to content

Commit 305d3b0

Browse files
committed
generalise lift synthesis, which makes the boilerplate in the generation a lot lower
1 parent c1664f2 commit 305d3b0

2 files changed

Lines changed: 31 additions & 23 deletions

File tree

parsley/shared/src/main/scala-3/parsley/Main.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ object Pos {
1414
}
1515
}
1616

17-
case class Foo[A](arg1: A, arg2: Int = 6)//(@isPosition val y: Pos)
17+
case class Foo[A](arg1: A, arg2: Int = 6)(@isPosition val y: Pos)
1818

1919
def foo[B] = bridge[Foo[B]]
2020

parsley/shared/src/main/scala-3/parsley/experimental/generic/ParserBridge.scala

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,29 +54,19 @@ private class BridgeImpl(using Quotes) {
5454
case (pos, _) => pos
5555
}
5656
val con = constructor[T](cls, bridgePrimaryArgs, tyArgs, categorisedArgs, existsUniquePosition.map(_.tyRepr))
57-
// TODO: look for unique position
57+
val body = synthesiseLift[S](existsUniquePosition, bridgePrimaryArgs.map(_._2), con, _)
5858
// TODO: ensure validation if Err is encountered (report separately, but then abort if failed (Option))
5959
bridgePrimaryArgs.map(_._2.asType) match {
60-
case List('[t1]) =>
61-
'{new Bridge1[t1, S] {
62-
def apply(p1: Parsley[t1]): Parsley[S] = ${
63-
existsUniquePosition match {
64-
case Some(impl@PosImpl(_, given Type[posTy])) =>
65-
'{lift.lift2(${con.asExprOf[(posTy, t1) => T]}, ${impl.parser}, p1)}
66-
case None => '{p1.map(${con.asExprOf[t1 => T]})}
67-
}
68-
}
69-
}}
70-
case List('[t1], '[t2]) =>
71-
'{new Bridge2[t1, t2, S] {
72-
def apply(p1: Parsley[t1], p2: Parsley[t2]): Parsley[S] = ${
73-
existsUniquePosition match {
74-
case Some(impl@PosImpl(_, given Type[posTy])) =>
75-
'{lift.lift3(${con.asExprOf[(posTy, t1, t2) => T]}, ${impl.parser}, p1, p2)}
76-
case None => '{lift.lift2(${con.asExprOf[(t1, t2) => T]}, p1, p2)}
77-
}
78-
}
79-
}}
60+
case List('[t1]) => '{
61+
new Bridge1[t1, S] {
62+
def apply(p1: Parsley[t1]): Parsley[S] = ${body(List('p1.asTerm))}
63+
}
64+
}
65+
case List('[t1], '[t2]) => '{
66+
new Bridge2[t1, t2, S] {
67+
def apply(p1: Parsley[t1], p2: Parsley[t2]): Parsley[S] = ${body(List('p1.asTerm, 'p2.asTerm))}
68+
}
69+
}
8070
// TODO: 19 more of these
8171
case _ => '{???}
8272
}
@@ -146,7 +136,6 @@ private class BridgeImpl(using Quotes) {
146136
val tys: List[TypeTree] = clsTyArgs.map(tyRep => TypeTree.of(using tyRep.asType))
147137
val objTy = New(Applied(TypeTree.ref(cls), tys))
148138
val con = objTy.select(cls.primaryConstructor).appliedToTypes(clsTyArgs)
149-
//val conBridged = con.appliedToArgs(params) // TODO: this doesn't work when positions can be in the first set
150139
val kaboom: Term = '{???}.asTerm
151140
// at this point, we have applied the constructor to the bridge args (except for positions)
152141
// we now need to apply the other default arguments
@@ -181,6 +170,25 @@ private class BridgeImpl(using Quotes) {
181170
saturated
182171
}
183172

173+
private def synthesiseLift[R: Type](existsUniquePosition: Option[PosImpl[?]], argTys: List[TypeRepr], con: Term, args: List[Term]): Expr[Parsley[R]] = {
174+
val tys = argTys :+ TypeRepr.of[R]
175+
val arity = argTys.size + existsUniquePosition.size
176+
TypeRepr.of[parsley.lift$].typeSymbol.methodMember(s"lift$arity").headOption.map('{parsley.lift}.asTerm.select(_)) match {
177+
case Some(lift) => existsUniquePosition match {
178+
case Some(impl@PosImpl(_, given Type[posTy])) =>
179+
val posTyRepr = TypeRepr.of[posTy]
180+
lift.appliedToTypes(posTyRepr :: tys)
181+
.appliedToArgs(con :: impl.parser.asTerm :: args)
182+
.asExprOf[Parsley[R]]
183+
case None =>
184+
lift.appliedToTypes(tys)
185+
.appliedToArgs(con :: args)
186+
.asExprOf[Parsley[R]]
187+
}
188+
case None => report.errorAndAbort(s"No `lift` available for arity $arity")
189+
}
190+
}
191+
184192
private object Bridgeable {
185193
def unapply(ty: TypeRepr): Option[(Symbol, List[Symbol], List[Symbol], List[List[Symbol]])] = {
186194
val clsDef = ty.classSymbol

0 commit comments

Comments
 (0)