Skip to content

Commit

Permalink
Cleaned up code
Browse files Browse the repository at this point in the history
  • Loading branch information
propensive committed Feb 27, 2024
1 parent b071452 commit ca7f1c3
Showing 1 changed file with 59 additions and 65 deletions.
124 changes: 59 additions & 65 deletions src/core/selectable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ trait Record[DataType](data: DataType, access: String => DataType => Any) extend
trait ValueAccessor[RecordType <: Record[DataType], DataType, LabelType <: Label, ValueType]:
def transform(data: DataType, params: List[String]): ValueType

trait RecordAccessor
[RecordType <: Record[DataType], DataType, LabelType <: Label, TypeConstructorType[_]]:
trait RecordAccessor[RecordType <: Record[DataType], DataType, LabelType <: Label, TypeConstructorType[_]]:
def transform(data: DataType, make: DataType => RecordType): TypeConstructorType[RecordType]

enum RecordField:
Expand All @@ -40,11 +39,10 @@ trait Schema[DataType, RecordType <: Record[DataType]]:
def make(data: DataType, transform: String => DataType => Any): RecordType
def access(name: String, value: DataType): DataType

def build
(value: Expr[DataType])
(using Quotes, Type[RecordType], Type[DataType])
def build(value: Expr[DataType])(using Quotes, Type[RecordType], Type[DataType])
(using thisType: Type[this.type])
: Expr[RecordType] =
: Expr[RecordType] =

import quotes.reflect.*

given Realm = realm"polyvinyl"
Expand All @@ -54,67 +52,63 @@ trait Schema[DataType, RecordType <: Record[DataType]]:
Ref(TypeRepr.of[thisType].typeSymbol.companionModule).asExprOf[Schema[DataType, RecordType]]

def refine
(value: Expr[DataType], fields: List[(String, RecordField)], refinedType: TypeRepr,
caseDefs: List[CaseDef] = List(CaseDef(Wildcard(), None, '{???}.asTerm)))
: (TypeRepr, List[CaseDef]) = fields match
case Nil =>
(refinedType, caseDefs)

case (name, RecordField.Value(typeName, params*)) :: tail =>
(ConstantType(StringConstant(typeName)).asType: @unchecked) match
case '[type typeName <: Label; typeName] =>
(Expr.summon[ValueAccessor[RecordType, DataType, typeName, ?]]: @unchecked) match
case None =>
fail(msg"""could not find a ValueAccessor instance for the field $name with type
$typeName""")

case Some('{$accessor: ValueAccessor[RecordType, DataType, typeName, valueType]}) =>

val rhs: Expr[DataType => Any] =
'{ (data: DataType) => $accessor.transform($target.access(${Expr(name)}, data),
${Expr(params.to(List))}) }

val caseDefs2 = CaseDef(Literal(StringConstant(name)), None, rhs.asTerm) :: caseDefs
val refinement = Refinement(refinedType, name, TypeRepr.of[valueType])

refine(value, tail, refinement, caseDefs2)

case (name, RecordField.Record(typeName, map)) :: tail =>
(ConstantType(StringConstant(typeName)).asType: @unchecked) match
case '[type typeName <: Label; typeName] =>
(Expr.summon[RecordAccessor[RecordType, DataType, typeName, ?]]: @unchecked) match
case None =>
fail(msg"""could not find a RecordAccessor instance for the field $name with type
$typeName""")
( value: Expr[DataType],
fields: List[(String, RecordField)],
refinedType: TypeRepr,
caseDefs: List[CaseDef] = List(CaseDef(Wildcard(), None, '{???}.asTerm)) )
: (TypeRepr, List[CaseDef]) =
fields match
case Nil =>
(refinedType, caseDefs)

case (name, RecordField.Value(typeName, params*)) :: tail =>
(ConstantType(StringConstant(typeName)).asType: @unchecked) match
case '[type typeName <: Label; typeName] =>
(Expr.summon[ValueAccessor[RecordType, DataType, typeName, ?]]: @unchecked) match
case None =>
fail(msg"could not find a ValueAccessor instance for the field $name with type $typeName")

case Some('{
type typeConstructor[_]
$accessor: RecordAccessor[RecordType, DataType, typeName, typeConstructor]
}) =>

val nested = '{$target.access(${Expr(name)}, $value)}
val recordTypeRepr = TypeRepr.of[RecordType]
val (nestedType, nestedCaseDefs) = refine(nested, map.to(List), recordTypeRepr)

val matchFn: Expr[String => DataType => Any] =
'{ (name: String) => ${Match('name.asTerm, nestedCaseDefs).asExprOf[DataType =>
Any]} }

val maker: Expr[DataType => RecordType] =
'{ field => $target.make(field, $matchFn) }

val rhs: Expr[DataType => Any] =
'{ data => $accessor.transform($target.access(${Expr(name)}, data), $maker) }

val caseDef = CaseDef(Literal(StringConstant(name)), None, rhs.asTerm)

(nestedType.asType: @unchecked) match
case '[nestedRecordType] =>
val typeRepr = TypeRepr.of[typeConstructor[nestedRecordType]]

refine(value, tail, Refinement(refinedType, name, typeRepr),
caseDef :: caseDefs)
case Some('{$accessor: ValueAccessor[RecordType, DataType, typeName, valueType]}) =>

val rhs: Expr[DataType => Any] =
'{
(data: DataType) =>
$accessor.transform($target.access(${Expr(name)}, data), ${Expr(params.to(List))})
}

val caseDefs2 = CaseDef(Literal(StringConstant(name)), None, rhs.asTerm) :: caseDefs
val refinement = Refinement(refinedType, name, TypeRepr.of[valueType])

refine(value, tail, refinement, caseDefs2)

case (name, RecordField.Record(typeName, map)) :: tail =>
(ConstantType(StringConstant(typeName)).asType: @unchecked) match
case '[type typeName <: Label; typeName] =>
(Expr.summon[RecordAccessor[RecordType, DataType, typeName, ?]]: @unchecked) match
case None =>
fail(msg"could not find a RecordAccessor instance for the field $name with type $typeName")

case Some('{ type typeConstructor[_]
$accessor: RecordAccessor[RecordType, DataType, typeName, typeConstructor] }) =>

val nested = '{$target.access(${Expr(name)}, $value)}
val recordTypeRepr = TypeRepr.of[RecordType]
val (nestedType, nestedCaseDefs) = refine(nested, map.to(List), recordTypeRepr)

val matchFn: Expr[String => DataType => Any] =
'{ (name: String) => ${Match('name.asTerm, nestedCaseDefs).asExprOf[DataType => Any]} }

val maker: Expr[DataType => RecordType] = '{ field => $target.make(field, $matchFn) }

val rhs: Expr[DataType => Any] =
'{ data => $accessor.transform($target.access(${Expr(name)}, data), $maker) }

val caseDef = CaseDef(Literal(StringConstant(name)), None, rhs.asTerm)

(nestedType.asType: @unchecked) match
case '[nestedRecordType] =>
val typeRepr = TypeRepr.of[typeConstructor[nestedRecordType]]
refine(value, tail, Refinement(refinedType, name, typeRepr), caseDef :: caseDefs)

val (refinedType, caseDefs) = refine(value, fields.to(List), TypeRepr.of[RecordType])

Expand Down

0 comments on commit ca7f1c3

Please sign in to comment.