Skip to content

Commit

Permalink
Remove alt compiler, simplify field compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
kubukoz committed Sep 24, 2023
1 parent 17ab109 commit 7725427
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 53 deletions.
2 changes: 1 addition & 1 deletion modules/ast/src/main/scala/playground/smithyql/AST.scala
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ object Struct {
)(
getValue: F[Identifier] => Identifier
): Option[F[InputNode[F]]] = value
.find(pair => getValue(pair.identifier).text == name)
.find(pair => getValue(pair.identifier).text === name)
.map(_.value)

}
Expand Down
76 changes: 24 additions & 52 deletions modules/core/src/main/scala/playground/QueryCompilerVisitor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import util.chaining._

import java.util.Base64
import java.util.UUID
import scala.collection.immutable.ListMap

object QueryCompilerVisitor {
val full: Schema ~> QueryCompiler =
Expand Down Expand Up @@ -222,7 +223,6 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
private trait FieldCompiler[A] {
def compiler: QueryCompiler[A]
def default: Option[A]
def label: String
}

private object FieldCompiler {
Expand All @@ -235,8 +235,6 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {

override val default: Option[A] = field.schema.getDefaultValue

override val label: String = field.label

}

}
Expand All @@ -247,9 +245,11 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
fieldsRaw: Vector[Field[S, _]],
make: IndexedSeq[Any] => S,
): QueryCompiler[S] = {
val fields = fieldsRaw.map(FieldCompiler.compile(_))
val fields = fieldsRaw
.map(f => f.label -> FieldCompiler.compile(f))
.to(ListMap)

val validFields = fields.map(_.label)
val validFields = fields
val deprecatedFields =
fieldsRaw.flatMap { f =>
f.hints.get(api.Deprecated).tupleLeft(f.label)
Expand All @@ -261,18 +261,13 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
val presentKeys = struct.value.fields.value.keys

// this is a list to keep the original type's ordering
val remainingValidFields =
validFields
.filterNot(
presentKeys.map(_.value.text).toSet
)
.toList
val remainingValidFields = validFields -- presentKeys.map(_.value.text).toSet

val extraFieldErrors: QueryCompiler.Result[Unit] = presentKeys
.filterNot(field => validFields.contains(field.value.text))
.map { unexpectedKey =>
CompilationError.error(
UnexpectedField(remainingValidFields),
UnexpectedField(remainingValidFields.keys.toList),
unexpectedKey.range,
)
}
Expand All @@ -294,14 +289,15 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
.combine(Ior.right(()))

def handleField[T](
field: FieldCompiler[T]
label: String,
field: FieldCompiler[T],
): QueryCompiler.Result[T] = {
val fieldByName =
struct
.value
.fields
.value
.byName(field.label)(_.value)
.byName(label)(_.value)

// Note: defaults get no special handling in dynamic schemas (in which a field with a default is considered optional).
// There's no real need to provide the default value in a dynamic client, as it can just omit the field in the request being sent.
Expand All @@ -313,58 +309,38 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
.flatMap {
_.toRightIor(
CompilationError.error(
MissingField(field.label),
MissingField(label),
struct.value.fields.range,
)
).toIorNec
}
}

val buildStruct = fields
.parTraverse(handleField(_))
.toVector
.parTraverse { case (label, instance) => handleField(label, instance) }

buildStruct.map(make) <& extraFieldErrors <& deprecatedFieldWarnings
}
}

// todo: get rid of these
private trait QueryCompilerAlt[U, A] {
def instance: QueryCompiler[A]
def alt: Alt[U, A]
def label = alt.label

def inject(
a: A
): U = alt.inject(a)

}

private object QueryCompilerAlt {

def fromAlt[U, A](
_alt: Alt[U, A]
): QueryCompilerAlt[U, A] =
new QueryCompilerAlt[U, A] {
override val alt: Alt[U, A] = _alt

override val instance: QueryCompiler[A] = alt
.schema
.compile(QueryCompilerVisitorInternal.this)

}

}

def union[U](
shapeId: ShapeId,
hints: Hints,
alternatives: Vector[Alt[U, _]],
dispatcher: Alt.Dispatcher[U],
): QueryCompiler[U] = {
def handleAlt[A](
alt: Alt[U, A]
): QueryCompiler[U] = alt
.schema
.compile(QueryCompilerVisitorInternal.this)
.map(alt.inject)

val alternativesCompiled = alternatives
.map(QueryCompilerAlt.fromAlt(_))
.groupBy(_.label)
.map(_.map(_.head))
.groupByNev(_.label)
.fmap(_.head)
.fmap(handleAlt(_))

val deprecatedAlternativeLabels =
alternatives.flatMap(alt => alt.hints.get(api.Deprecated).tupleLeft(alt.label)).toMap
Expand All @@ -379,10 +355,6 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
val definition = s.value.fields.value.head
val key = definition.identifier

def go[A](
alt: QueryCompilerAlt[U, A]
): QueryCompiler[U] = alt.instance.map(alt.inject)

val op =
alternativesCompiled
.get(key.value.text)
Expand All @@ -406,7 +378,7 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
.toBothLeft(())
.combine(Ior.right(()))

op.flatMap(go(_).compile(definition.value)) <& deprecationWarning
op.flatMap(_.compile(definition.value)) <& deprecationWarning

case s if s.value.fields.value.isEmpty =>
CompilationError
Expand Down

0 comments on commit 7725427

Please sign in to comment.