Skip to content

Commit af1ed69

Browse files
committed
Weave context parameters throughout the codebase
1 parent 4ea5fe5 commit af1ed69

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+2065
-1619
lines changed

Base/src/docs/_docs/getting-started.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ Together the scaffolding of the string context extension method becomes
230230
```scala
231231
type Result
232232
import scala.quoted.{Expr, Quotes}
233-
import name.rayrobdod.stringContextParserCombinator.Interpolator._
233+
import name.rayrobdod.stringContextParserCombinator.Interpolator.quotedInterpolators._
234234

235235
extension (inline sc:StringContext)
236236
inline def prefix(inline args:Any*):Result =
@@ -256,7 +256,7 @@ This can be done with the map operator, such as `.map(Expr(_))`, or equivalently
256256
```
257257

258258
`ofType` changes from requiring an implicit `scala.reflect.ClassTag` and returning an unwrapped value,
259-
to requiring an implicit `scala.quoted.Type` and returning an `Expr` that builds a value.
259+
to requiring an implicit `TypeCreator` and returning an `Expr` that builds a value.
260260
Since the `ofType` result is in an `Expr`, the mapping applied to this value must be changed from a `Any => String` to a `Expr[Any] => Expr[String]`, essentially wrapping the mapping in a Quote.
261261

262262
```diff
@@ -285,7 +285,7 @@ Taken together, the macro-level reimplementation of the standard string interpol
285285

286286
```scala
287287
import scala.quoted.{Expr, Quotes}
288-
import name.rayrobdod.stringContextParserCombinator.Interpolator._
288+
import name.rayrobdod.stringContextParserCombinator.Interpolator.quotedInterpolators._
289289

290290
extension (inline sc:StringContext)
291291
inline def s2(inline args:Any*):String =

Base/src/main/scala-2.12/AssembleUnapply.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ object AssembleUnapply {
2929
value:c.Expr[UnexprA],
3030
valueType:c.TypeTag[UnexprA],
3131
conditionFn:c.Expr[UnexprA] => c.Expr[Boolean],
32-
extracted:UnapplyExpr.Part[c.Expr, c.TypeTag, c.Expr[UnexprA], _],
32+
extracted:UnapplyExpr.Part[c.type, c.Expr, c.TypeTag, c.Expr[UnexprA], _],
3333
):c.Expr[Any] = {
3434
import c.universe.Quasiquote
3535

@@ -38,7 +38,7 @@ object AssembleUnapply {
3838

3939
val condition = conditionFn(valueIdent)
4040
val extractedType = extracted.typ
41-
val extractedValue = extracted.value(valueIdent)
41+
val extractedValue = extracted.value(valueIdent, c)
4242

4343
c.Expr(
4444
q"""
@@ -58,7 +58,7 @@ object AssembleUnapply {
5858
value:c.Expr[UnexprA],
5959
valueType:c.TypeTag[UnexprA],
6060
conditionFn:c.Expr[UnexprA] => c.Expr[Boolean],
61-
extracteds:List[UnapplyExpr.Part[c.Expr, c.TypeTag, c.Expr[UnexprA], _]],
61+
extracteds:List[UnapplyExpr.Part[c.type, c.Expr, c.TypeTag, c.Expr[UnexprA], _]],
6262
):c.Expr[Any] = {
6363
import c.universe.Quasiquote
6464

@@ -67,7 +67,7 @@ object AssembleUnapply {
6767

6868
val condition = conditionFn(valueIdent)
6969
val extractedTypes = extracteds.map(_.typ.tpe)
70-
val extractedValues = extracteds.map(_.value(valueIdent).tree)
70+
val extractedValues = extracteds.map(_.value(valueIdent, c).tree)
7171

7272
val extractedTuple = {
7373
c.universe.Apply(

Base/src/main/scala-2.13/AssembleUnapply.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ object AssembleUnapply {
2929
value:c.Expr[UnexprA],
3030
valueType:c.TypeTag[UnexprA],
3131
conditionFn:c.Expr[UnexprA] => c.Expr[Boolean],
32-
extracted:UnapplyExpr.Part[c.Expr, c.TypeTag, c.Expr[UnexprA], _],
32+
extracted:UnapplyExpr.Part[c.type, c.Expr, c.TypeTag, c.Expr[UnexprA], _],
3333
):c.Expr[Any] = {
3434
import c.universe.Quasiquote
3535

@@ -38,7 +38,7 @@ object AssembleUnapply {
3838

3939
val condition = conditionFn(valueIdent)
4040
val extractedType = extracted.typ
41-
val extractedValue = extracted.value(valueIdent)
41+
val extractedValue = extracted.value(valueIdent, c)
4242

4343
c.Expr(
4444
q"""
@@ -53,7 +53,7 @@ object AssembleUnapply {
5353
value:c.Expr[UnexprA],
5454
valueType:c.TypeTag[UnexprA],
5555
conditionFn:c.Expr[UnexprA] => c.Expr[Boolean],
56-
extracteds:List[UnapplyExpr.Part[c.Expr, c.TypeTag, c.Expr[UnexprA], _]],
56+
extracteds:List[UnapplyExpr.Part[c.type, c.Expr, c.TypeTag, c.Expr[UnexprA], _]],
5757
):c.Expr[Any] = {
5858
import c.universe.Quasiquote
5959

@@ -62,7 +62,7 @@ object AssembleUnapply {
6262

6363
val condition = conditionFn(valueIdent)
6464
val extractedTypes = extracteds.map(_.typ.tpe)
65-
val extractedValues = extracteds.map(_.value(valueIdent).tree)
65+
val extractedValues = extracteds.map(_.value(valueIdent, c).tree)
6666

6767
val extractedTuple = {
6868
c.universe.Apply(

Base/src/main/scala-2/VersionSpecificUnapplyExpr.scala

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import scala.reflect.macros.blackbox.Context
44

55
private[stringContextParserCombinator]
66
trait VersionSpecificUnapplyExprs {
7-
def forContext(c:Context): UnapplyExprs[c.Expr, c.TypeTag] = {
7+
def forContext(c:Context): UnapplyExprs[c.type, c.Expr, c.TypeTag] = {
88
def selectApply[Z](lhs:c.Expr[_], op:String, rhs:c.Expr[_])(implicit typZ:c.TypeTag[Z]):c.Expr[Z] = {
99
c.Expr[Z](
1010
c.universe.Apply(
@@ -17,32 +17,17 @@ trait VersionSpecificUnapplyExprs {
1717
)
1818
}
1919

20-
val exprTrue = c.Expr[Boolean](c.universe.Liftable.liftBoolean(true))
21-
val exprFalse = c.Expr[Boolean](c.universe.Liftable.liftBoolean(false))
22-
23-
val andBooleanExprs:Function2[c.Expr[Boolean], () => c.Expr[Boolean], c.Expr[Boolean]] = {(left, rightFn) =>
24-
val B = c.universe.Unliftable.unliftBoolean
25-
val right = rightFn()
26-
(left.tree, right.tree) match {
27-
case (B(true), _) => right
28-
case (B(false), _) => c.Expr[Boolean](c.universe.Liftable.liftBoolean(false))
29-
case (_, B(true)) => left
30-
case (_, B(false)) => c.Expr[Boolean](c.universe.Liftable.liftBoolean(false))
31-
case (_, _) => selectApply(left, "$amp$amp", right)
32-
}
33-
}
34-
35-
new UnapplyExprs.Common[c.Expr, c.TypeTag](exprTrue, exprFalse, andBooleanExprs) {
36-
override def ofType[Z](implicit typ:c.TypeTag[Z]):UnapplyExpr[c.Expr, c.TypeTag, c.Expr[Z]] = {
37-
UnapplyExpr[c.Expr, c.TypeTag, c.Expr[Z]](
38-
{(_:c.Expr[Z]) => exprTrue},
39-
UnapplyExpr.Part(typ, {(value:c.Expr[Z]) => value}) :: Nil
20+
new UnapplyExprs.Common[c.type, c.Expr, c.TypeTag]()(using typeclass.Exprs.forContext[c.type]) {
21+
override def ofType[Z](implicit typ:c.TypeTag[Z]):UnapplyExpr[c.type, c.Expr, c.TypeTag, c.Expr[Z]] = {
22+
UnapplyExpr[c.type, c.Expr, c.TypeTag, c.Expr[Z]](
23+
{(_:c.Expr[Z], ctx: c.type) => typeclass.Exprs.forContext[c.type].constTrue(ctx)},
24+
UnapplyExpr.Part(typ, {(value:c.Expr[Z], _: c.type) => value}) :: Nil
4025
)
4126
}
4227

43-
override def isEqualTo[A](other:c.Expr[A])(implicit typ:c.TypeTag[A]):UnapplyExpr[c.Expr, c.TypeTag, c.Expr[A]] = {
44-
UnapplyExpr[c.Expr, c.TypeTag, c.Expr[A]](
45-
{(value:c.Expr[A]) => selectApply[Boolean](value, "$eq$eq", other)},
28+
override def isEqualTo[A](other:c.Expr[A])(implicit typ:c.TypeTag[A]):UnapplyExpr[c.type, c.Expr, c.TypeTag, c.Expr[A]] = {
29+
UnapplyExpr[c.type, c.Expr, c.TypeTag, c.Expr[A]](
30+
{(value:c.Expr[A], _: c.type) => selectApply[Boolean](value, "$eq$eq", other)},
4631
Nil
4732
)
4833
}

Base/src/main/scala-2/internal/Lifted.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ object Lifted {
1010
lift:LiftFunction[c.type, Lifter, Z],
1111
description:ExpectingDescription
1212
)(implicit lifterTypeTag:c.TypeTag[Lifter[_]]
13-
):Interpolator[c.Expr[_], Z] = {
14-
new Interpolator[c.Expr[_], Z] {
15-
override def interpolate[ExprZ <: c.Expr[_], Pos](input:Input[ExprZ, Pos])(implicit ev1:Ordering[Pos]):Result[ExprZ, Pos, Z] = {
13+
):Interpolator[c.type, c.Expr[_], Z] = {
14+
new Interpolator[c.type, c.Expr[_], Z] {
15+
override def interpolate[ExprZ <: c.Expr[_], Pos](input:Input[ExprZ, Pos])(implicit ctx: c.type, ev1:Ordering[Pos]):Result[ExprZ, Pos, Z] = {
1616
input.consume(
1717
_ => None,
1818
liftee => {

Base/src/main/scala-2/internal/OfType.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ import scala.reflect.macros.blackbox.Context
77
private[stringContextParserCombinator]
88
final class OfType[Ctx <: Context with Singleton, A](
99
tpetag:Ctx#TypeTag[A]
10-
) extends Parser[Ctx#Expr, Ctx#TypeTag, Ctx#Expr[A]] {
10+
) extends Parser[Ctx, Ctx#Expr, Ctx#TypeTag, Ctx#Expr[A]] {
1111
private val expecting = ExpectingDescription(s"OfType(${tpetag.tpe})")
1212

13-
def interpolate[ExprZ <: Ctx#Expr[_], Pos](input:Input[ExprZ, Pos])(implicit ev1:Ordering[Pos]):Result[ExprZ, Pos, Ctx#Expr[A]] = {
13+
def interpolate[ExprZ <: Ctx#Expr[_], Pos](input:Input[ExprZ, Pos])(implicit ctx: Ctx, ev1:Ordering[Pos]):Result[ExprZ, Pos, Ctx#Expr[A]] = {
1414
input.consume(
1515
_ => None,
1616
arg => Some(arg).filter(x => x.actualType <:< tpetag.tpe).map(_.asInstanceOf[Ctx#Expr[A]]),
1717
this.expecting
1818
)
1919
}
2020

21-
override def extractor[Pos](input:Input[Unit, Pos])(implicit ev1:Ordering[Pos], exprs:UnapplyExprs[Ctx#Expr, Ctx#TypeTag]):Result[Unit, Pos, UnapplyExpr[Ctx#Expr, Ctx#TypeTag, Ctx#Expr[A]]] = {
21+
override def extractor[Pos](input:Input[Unit, Pos])(implicit ctx: Ctx, ev1:Ordering[Pos], exprs:UnapplyExprs[Ctx, Ctx#Expr, Ctx#TypeTag]):Result[Unit, Pos, UnapplyExpr[Ctx, Ctx#Expr, Ctx#TypeTag, Ctx#Expr[A]]] = {
2222
input.consume(
2323
_ => None,
2424
(_:Unit) => Some(exprs.ofType(tpetag)),

Base/src/main/scala-2/package.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ package object stringContextParserCombinator {
1212
type Id[+A] = A
1313
/** An identity function for lifting into the identity context */
1414
type IdToExpr[A] = =:=[A, A]
15+
implicit val given_IdCtx: IdCtx = new IdCtx()
1516

1617
private[stringContextParserCombinator]
1718
val Name = new Unapply.Fixed[Universe#Name, String] {
@@ -82,4 +83,6 @@ package object stringContextParserCombinator {
8283
package stringContextParserCombinator {
8384
/** Support for Interpolator.contextInterpolators.lifted; represents a macro-level function that combines a CC[A] and an A. */
8485
trait LiftFunction[U <: Context with Singleton, -CC[_], +Z] {def apply[A](lifter:U#Expr[CC[A]], elem:U#Expr[A]):Z}
86+
/** A context avaliable for the identity context. Essentially a `Unit`, but with an implicit value */
87+
final class IdCtx()
8588
}

Base/src/main/scala-2/typeclass/ToExprMapping.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@ import scala.reflect.ClassTag
88
* Associates an Expr type with the implicit types required to lift a value into an Expr.
99
* Support for [[Interpolator.mapToExpr]].
1010
*/
11-
trait ToExprMapping[Expr[+_], ToExpr[_], Type[_]] {
12-
def apply[A](value:A, fn:ToExpr[A], tpe: Type[A]):Expr[A]
11+
trait ToExprMapping[Ctx, Expr[+_], ToExpr[_], Type[_]] {
12+
def apply[A](ctx:Ctx, value:A, fn:ToExpr[A], tpe: Type[A]):Expr[A]
1313
}
1414

1515
/** Predefined implicit implementations of ToExprMapping */
1616
object ToExprMapping {
17-
def forContext(c:Context):ToExprMapping[c.Expr, c.universe.Liftable, c.TypeTag] = {
18-
new ToExprMapping[c.Expr, c.universe.Liftable, c.TypeTag] {
19-
def apply[A](value:A, fn:c.universe.Liftable[A], tpe: c.TypeTag[A]):c.Expr[A] = {
17+
def forContext(c:Context):ToExprMapping[c.type, c.Expr, c.universe.Liftable, c.TypeTag] = {
18+
new ToExprMapping[c.type, c.Expr, c.universe.Liftable, c.TypeTag] {
19+
def apply[A](ctx:c.type, value:A, fn:c.universe.Liftable[A], tpe: c.TypeTag[A]):c.Expr[A] = {
2020
c.Expr[A](fn(value))(tpe)
2121
}
2222
}
2323
}
2424

25-
def forId:ToExprMapping[Id, IdToExpr, ClassTag] = {
26-
new ToExprMapping[Id, IdToExpr, ClassTag] {
27-
def apply[A](value:A, fn: IdToExpr[A], tpe: ClassTag[A]):Id[A] = {
25+
def forId:ToExprMapping[IdCtx, Id, IdToExpr, ClassTag] = {
26+
new ToExprMapping[IdCtx, Id, IdToExpr, ClassTag] {
27+
def apply[A](ctx:IdCtx, value:A, fn: IdToExpr[A], tpe: ClassTag[A]):Id[A] = {
2828
value
2929
}
3030
}

Base/src/main/scala-3/InterpolatorImpl.scala

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,23 @@ object InterpolatorImpl {
1616
}
1717
}
1818

19-
def unapplyExprToExpr[UnexprA](expr: UnapplyExpr[quoted.Expr, quoted.Type, quoted.Expr[UnexprA]])(using Type[UnexprA], Quotes): Expr[SCUnapply[UnexprA]] = {
20-
val conditionFn:quoted.Expr[UnexprA] => quoted.Expr[Boolean] = expr.condition
19+
def unapplyExprToExpr[UnexprA](expr: UnapplyExpr[Quotes, Expr, TypeCreator, Expr[UnexprA]])(using TypeCreator[UnexprA], Quotes): Expr[SCUnapply[UnexprA]] = {
20+
val conditionFn: Expr[UnexprA] => Quotes ?=> Expr[Boolean] = (in: Expr[UnexprA]) => (quotes:Quotes) ?=> expr.condition(in, quotes)
21+
given Type[UnexprA] = TypeCreator[UnexprA].createType
2122

2223
expr.parts match {
2324
case Nil =>
2425
'{((a:UnexprA) => ${conditionFn('a)}):Unapply.Zero[UnexprA]}
25-
case (part: UnapplyExpr.Part[quoted.Expr, quoted.Type, quoted.Expr[UnexprA], z]) :: Nil =>
26-
@nowarn("msg=unused local definition") given quoted.Type[z] = part.typ
27-
'{((a:UnexprA) => Option.when[z](${conditionFn('a)})(${part.value('a)})):Unapply.Fixed[UnexprA, z]}
26+
case (part: UnapplyExpr.Part[Quotes, Expr, TypeCreator, Expr[UnexprA], z]) :: Nil =>
27+
@nowarn("msg=unused local definition") given Type[z] = part.typ.createType
28+
'{((a:UnexprA) => Option.when[z](${conditionFn('a)})(${part.value('a, summon)})):Unapply.Fixed[UnexprA, z]}
2829
case _ =>
2930
import quotes.reflect._
3031
val unexpraTypeTree = TypeTree.of[UnexprA]
3132

3233
val tupleTypeConstructorSymbol = defn.TupleClass(expr.parts.size)
3334
val tupleTypeConstructorTree = TypeIdent(tupleTypeConstructorSymbol)
34-
val tupleTypeTree = Applied(tupleTypeConstructorTree, expr.parts.map(part => TypeTree.of(using part.typ)))
35+
val tupleTypeTree = Applied(tupleTypeConstructorTree, expr.parts.map(part => TypeTree.of(using part.typ.createType)))
3536
val optionTupleTypeTree = Applied(TypeIdent(defn.OptionClass), List(tupleTypeTree))
3637

3738
val tupleModule = tupleTypeConstructorSymbol.companionModule
@@ -60,8 +61,8 @@ object InterpolatorImpl {
6061
val optionModule = defn.OptionClass.companionModule
6162

6263
val partsTuple = {
63-
val typeArgs = expr.parts.map(part => TypeTree.of(using part.typ))
64-
val valueArgs = expr.parts.map(part => part.value(param).asTerm)
64+
val typeArgs = expr.parts.map(part => TypeTree.of(using part.typ.createType))
65+
val valueArgs = expr.parts.map(part => part.value(param, summon).asTerm)
6566

6667
tupleConstructorTree
6768
.select(tupleModule.methodMember("apply")(0))
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package name.rayrobdod.stringContextParserCombinator
2+
3+
import scala.quoted.*
4+
import scala.annotation.nowarn
5+
6+
/**
7+
* A factory for types.
8+
*/
9+
abstract class TypeCreator[A <: AnyKind] {
10+
def createType(using Quotes): Type[A]
11+
12+
final def show(using Quotes): String = Type.show[A](using this.createType)
13+
}
14+
15+
object TypeCreator {
16+
def apply[A <: AnyKind](using tt: TypeCreator[A]): TypeCreator[A] = tt
17+
18+
@nowarn("id=E197")
19+
inline given derived[A <: AnyKind]: TypeCreator[A] = {
20+
final class typeCreator extends TypeCreator[A] {
21+
def createType(using Quotes) = Type.of[A]
22+
}
23+
new typeCreator
24+
}
25+
}

0 commit comments

Comments
 (0)