Skip to content

Commit

Permalink
make effect elaborator respect predicated mappings
Browse files Browse the repository at this point in the history
  • Loading branch information
tpolecat committed Aug 29, 2024
1 parent d3d94ef commit f80c024
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 20 deletions.
15 changes: 7 additions & 8 deletions modules/core/src/main/scala/compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1243,7 +1243,8 @@ object QueryCompiler {
* multiple effect handlers.
*
* This phase transforms the input query by assigning subtrees to effect
* handlers as specified by the supplied `emapping`.
* handlers as specified by the supplied `effects`, which takes a `Context` and
* fieldName, retuning an `EffectHandler` (if any).
*
* The mapping has `Type` and field name pairs as keys and effect handlers
* as values. When the traversal of the input query visits a `Select` node
Expand All @@ -1254,21 +1255,18 @@ object QueryCompiler {
* and evaluating the subquery against its result.
* 2. the subquery which will be evaluated by the effect handler.
*/
class EffectElaborator[F[_]] private (emapping: Map[(Type, String), EffectHandler[F]]) extends Phase {
class EffectElaborator[F[_]] private (effects: (Context, String) => Option[EffectHandler[F]]) extends Phase {
override def transform(query: Query): Elab[Query] =
query match {
case s@Select(fieldName, resultName, child) =>
for {
c <- Elab.context
obj <- Elab.liftR(c.tpe.underlyingObject.toResultOrError(s"Type ${c.tpe} is not an object or interface type"))
childCtx = c.forFieldOrAttribute(fieldName, resultName)
_ <- Elab.push(childCtx, child)
ec <- transform(child)
_ <- Elab.pop
schema <- Elab.schema
ref = schema.uncheckedRef(obj)
} yield
emapping.get((ref, fieldName)) match {
effects(c, fieldName) match {
case Some(handler) =>
Select(fieldName, resultName, Effect(handler, s.copy(child = ec)))
case None =>
Expand All @@ -1282,8 +1280,9 @@ object QueryCompiler {
object EffectElaborator {
case class EffectMapping[F[_]](tpe: TypeRef, fieldName: String, handler: EffectHandler[F])

def apply[F[_]](mappings: Seq[EffectMapping[F]]): EffectElaborator[F] =
new EffectElaborator(mappings.map(m => ((m.tpe, m.fieldName), m.handler)).toMap)
def apply[F[_]](effects: (Context, String) => Option[EffectHandler[F]]): EffectElaborator[F] =
new EffectElaborator(effects)

}

/**
Expand Down
17 changes: 5 additions & 12 deletions modules/core/src/main/scala/mapping.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1188,19 +1188,12 @@ abstract class Mapping[F[_]] {
ComponentElaborator(componentMappings)
}

lazy val effectElaborator = {
val effectMappings =
typeMappings.mappings.flatMap {
case om: ObjectMapping =>
om.fieldMappings.collect {
case EffectField(fieldName, handler, _, _) =>
EffectElaborator.EffectMapping(schema.uncheckedRef(om.tpe), fieldName, handler)
}
case _ => Seq.empty
lazy val effectElaborator: EffectElaborator[F] =
EffectElaborator { (ctx, fieldName) =>
typeMappings.fieldMapping(ctx, fieldName).collect {
case e: EffectField => e.handler
}

EffectElaborator(effectMappings)
}
}

def compilerPhases: List[QueryCompiler.Phase] = List(selectElaborator, componentElaborator, effectElaborator)

Expand Down

0 comments on commit f80c024

Please sign in to comment.