Skip to content

Commit 86bcafa

Browse files
author
Oron Port
committed
used Scala 3.6.x Selectable.Fields for DFStruct/DFTuple with workaround for scala/scala3#22036
1 parent 68f5017 commit 86bcafa

File tree

3 files changed

+27
-46
lines changed

3 files changed

+27
-46
lines changed

core/src/main/scala/dfhdl/core/DFStruct.scala

-42
Original file line numberDiff line numberDiff line change
@@ -217,47 +217,5 @@ object DFStruct:
217217
sf.check(dfType, value.dfType)
218218
value.asValTP[DFStruct[F], RP]
219219
end Compare
220-
221-
trait Refiner[T <: FieldsOrTuple, A, I, P]:
222-
type Out <: DFVal[DFStruct[T], Modifier[A, Any, I, P]]
223-
object Refiner:
224-
transparent inline given [T <: FieldsOrTuple, A, I, P]: Refiner[T, A, I, P] = ${
225-
refineMacro[T, A, I, P]
226-
}
227-
def refineMacro[T <: FieldsOrTuple, A, I, P](using
228-
Quotes,
229-
Type[T],
230-
Type[A],
231-
Type[I],
232-
Type[P]
233-
): Expr[Refiner[T, A, I, P]] =
234-
import quotes.reflect.*
235-
val dfValTpe = TypeRepr.of[DFVal[DFStruct[T], Modifier[A, Any, I, P]]]
236-
val tTpe = TypeRepr.of[T]
237-
val fields: List[(String, TypeRepr)] = tTpe.asTypeOf[Any] match
238-
case '[NonEmptyTuple] =>
239-
tTpe.getTupleArgs.zipWithIndex.map((f, i) =>
240-
f.asTypeOf[Any] match
241-
case '[DFValOf[t]] =>
242-
(s"_${i + 1}", TypeRepr.of[DFVal[t, Modifier[A, Any, I, P]]])
243-
)
244-
case _ =>
245-
val clsSym = tTpe.classSymbol.get
246-
clsSym.caseFields.map(m =>
247-
tTpe.memberType(m).asTypeOf[Any] match
248-
case '[DFValOf[t]] =>
249-
(m.name.toString, TypeRepr.of[DFVal[t, Modifier[A, Any, I, P]]])
250-
)
251-
252-
val refined = fields.foldLeft(dfValTpe) { case (r, (n, t)) =>
253-
Refinement(r, n, t)
254-
}
255-
val refinedType = refined.asTypeOf[DFVal[DFStruct[T], Modifier[A, Any, I, P]]]
256-
'{
257-
new Refiner[T, A, I, P]:
258-
type Out = refinedType.Underlying
259-
}
260-
end refineMacro
261-
end Refiner
262220
end Val
263221
end DFStruct

core/src/main/scala/dfhdl/core/DFVal.scala

+18-4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ final class DFVal[+T <: DFTypeAny, +M <: ModifierAny](val irValue: ir.DFVal | DF
1818
extends AnyVal
1919
with DFMember[ir.DFVal]
2020
with Selectable:
21+
type Fields = DFVal.Fields[T @uncheckedVariance, M @uncheckedVariance]
2122

2223
def selectDynamic(name: String)(using DFC): Any = trydf {
2324
val ir.DFStruct(structName, fieldMap) = this.asIR.dfType: @unchecked
@@ -269,6 +270,23 @@ sealed protected trait DFValLP:
269270
from => from.asValTP[T, NOTCONST]
270271
end DFValLP
271272
object DFVal extends DFValLP:
273+
protected type FieldWithModifier[V, M <: ModifierAny] = V match
274+
case DFVal[t, _] =>
275+
M match
276+
case Modifier[a, Any, i, p] => DFVal[t, Modifier[a, Any, i, p]]
277+
protected type FieldsWithModifier[V <: NamedTuple.AnyNamedTuple, M <: ModifierAny] =
278+
NamedTuple.Map[V, [t] =>> FieldWithModifier[t, M]]
279+
protected[core] type Fields[T <: DFTypeAny, M <: ModifierAny] = T match
280+
case DFType[t, Args1[a]] =>
281+
t match
282+
case ir.DFStruct =>
283+
// TODO: NamedTuple.From should suffice when https://github.com/scala/scala3/issues/22036 is fixed
284+
a match
285+
case DFStruct.Fields => FieldsWithModifier[NamedTuple.From[a], M]
286+
case NonEmptyTuple => FieldsWithModifier[TupleToNamedTuple[a], M]
287+
case _ => Any
288+
case _ => Any
289+
272290
// constructing a front-end DFVal value class object. if it's a global value, then
273291
// we need to save the DFC, instead of the actual member IR object
274292
inline def apply[T <: DFTypeAny, M <: ModifierAny, IR <: ir.DFVal | DFError](
@@ -321,10 +339,6 @@ object DFVal extends DFValLP:
321339
given [T <: DFTypeAny, M <: ModifierAny]: CanEqual[DFEncoding, DFVal[T, M]] =
322340
CanEqual.derived
323341

324-
given __refined_dfVal[T <: FieldsOrTuple, A, I, P](using
325-
r: DFStruct.Val.Refiner[T, A, I, P]
326-
): Conversion[DFVal[DFStruct[T], Modifier[A, Any, I, P]], r.Out] = _.asInstanceOf[r.Out]
327-
328342
trait ConstCheck[P]
329343
given [P](using
330344
AssertGiven[

internals/src/main/scala/dfhdl/internals/helpers.scala

+9
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,15 @@ object ValueOfTuple:
173173
end ValueOfTuple
174174

175175
type <:![T <: UB, UB] = T & UB
176+
/*
177+
TODO: not required when https://github.com/scala/scala3/issues/22036 is fixed
178+
*/
179+
import compiletime.ops.string.+ as ++
180+
protected type TupleNamesRecur[X <: Tuple, N <: Int, I <: Int] <: Tuple = I match
181+
case 0 => X
182+
case S[i] => ("_" ++ ToString[N - i]) *: TupleNamesRecur[X, N, i]
183+
protected type TupleNames[N <: Int] = TupleNamesRecur[EmptyTuple, N, N]
184+
type TupleToNamedTuple[T <: Tuple] = NamedTuple.NamedTuple[TupleNames[Tuple.Size[T]], T]
176185

177186
//evidence of class T which has no arguments and no type arguments
178187
trait ClassEv[T]:

0 commit comments

Comments
 (0)