-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add more combinators to Output - issue #466
- Loading branch information
Showing
5 changed files
with
348 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package besom.internal | ||
|
||
import scala.quoted.* | ||
|
||
object OutputUnzip: | ||
inline def unzip[A <: NonEmptyTuple](output: Output[A]): Tuple.Map[A, Output] = ${ unzipImpl[A]('output) } | ||
|
||
// essentially we're performing Output[(A, B, C)] => (Output[A], Output[B], Output[C]) transformation | ||
def unzipImpl[A <: NonEmptyTuple: Type](outputA: Expr[Output[A]])(using Quotes): Expr[Tuple.Map[A, Output]] = | ||
import quotes.reflect.* | ||
|
||
// tuple xxl is represented as a linked list of types via AppliedType, we extract types recursively | ||
def extractTypesFromTupleXXL(tup: TypeRepr): List[TypeRepr] = | ||
tup match | ||
// tuple cons element | ||
case AppliedType(tpe, types) if tpe =:= TypeRepr.of[scala.*:] => | ||
// for tuple cons, we expect exactly 2 types, type and tail consisting of another scala.*: | ||
types match | ||
case tpe :: tail :: Nil => tpe :: extractTypesFromTupleXXL(tail) | ||
case Nil => Nil | ||
case _ => | ||
report.errorAndAbort(s"Expected an AppliedType for scala.:* type (exactly 2 elems), got: ${types.map(_.show)}") | ||
// final element in the tuple | ||
case tpe if tpe =:= TypeRepr.of[EmptyTuple] => Nil | ||
case _ => report.errorAndAbort(s"Expected an AppliedType for scala.:* type, got: ${tup.show}") | ||
|
||
val tupleType = TypeRepr.of[A] | ||
val tupleTypes = tupleType match | ||
case AppliedType(tpe, types) if tpe =:= TypeRepr.of[scala.*:] => extractTypesFromTupleXXL(tupleType) | ||
case AppliedType(tpe, types) => types | ||
case _ => report.errorAndAbort(s"Expected a tuple type, got: ${tupleType.show}") | ||
|
||
val mapExprs = tupleTypes.zipWithIndex.map { (tpe, idx) => | ||
val idxExpr = Expr(idx) | ||
tpe.asType match | ||
case '[t] => | ||
// we use Tuple#toArray to avoid _23 problem (compiler generates accessors up to 22 elems) | ||
'{ $outputA.map[t](x => x.toArray($idxExpr).asInstanceOf[t]) } | ||
} | ||
|
||
val tupleOfOutputs = mapExprs.foldLeft[Expr[Tuple]](Expr.ofTuple(EmptyTuple)) { (acc, expr) => | ||
'{ $acc :* $expr } | ||
} | ||
|
||
'{ $tupleOfOutputs.asInstanceOf[Tuple.Map[A, Output]] } | ||
|
||
end unzipImpl | ||
|
||
end OutputUnzip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
fyi @pawelprazak