@@ -42,9 +42,45 @@ object Derive {
4242 def rec (remaining : List [AdtTypeNode ])(using Quotes ): Expr [F [T ]] =
4343 remaining match
4444 case Nil => macroCall[T ]
45+ case x0 :: x1 :: x2 :: x3 :: x4 :: x5 :: x6 :: x7 :: tail =>
46+ (x0.tpe.asType, x1.tpe.asType, x2.tpe.asType, x3.tpe.asType, x4.tpe.asType, x5.tpe.asType, x6.tpe.asType, x7.tpe.asType) match
47+ case (' [t0], ' [t1], ' [t2], ' [t3], ' [t4], ' [t5], ' [t6], ' [t7]) =>
48+ ' {
49+ given F [t0] = $ { macroCall[t0] }
50+ given F [t1] = $ { macroCall[t1] }
51+ given F [t2] = $ { macroCall[t2] }
52+ given F [t3] = $ { macroCall[t3] }
53+ given F [t4] = $ { macroCall[t4] }
54+ given F [t5] = $ { macroCall[t5] }
55+ given F [t6] = $ { macroCall[t6] }
56+ given F [t7] = $ { macroCall[t7] }
57+ $ { rec(tail) }
58+ }
59+ case x0 :: x1 :: x2 :: x3 :: tail =>
60+ (x0.tpe.asType, x1.tpe.asType, x2.tpe.asType, x3.tpe.asType) match
61+ case (' [t0], ' [t1], ' [t2], ' [t3]) =>
62+ ' {
63+ given F [t0] = $ { macroCall[t0] }
64+ given F [t1] = $ { macroCall[t1] }
65+ given F [t2] = $ { macroCall[t2] }
66+ given F [t3] = $ { macroCall[t3] }
67+ $ { rec(tail) }
68+ }
69+ case x0 :: x1 :: tail =>
70+ (x0.tpe.asType, x1.tpe.asType) match
71+ case (' [t0], ' [t1]) =>
72+ ' {
73+ given F [t0] = $ { macroCall[t0] }
74+ given F [t1] = $ { macroCall[t1] }
75+ $ { rec(tail) }
76+ }
4577 case x :: tail =>
4678 x.tpe.asType match
47- case ' [t] => ' { implicit val x : F [t] = $ { macroCall[t] }; $ { rec(tail) } }
79+ case ' [t] =>
80+ ' {
81+ given F [t] = $ { macroCall[t] }
82+ $ { rec(tail) }
83+ }
4884
4985 rec(subsWithoutImplicitTypeclassInstances[F ](rootNode))
5086 }
@@ -518,10 +554,6 @@ abstract private[derivation] class Deriver[F[_]: Type, T: Type, Q <: Quotes](usi
518554 using Quotes ): Expr [B ] =
519555 ' { val x : A = $initialValue; $ { inner(' x ) } }
520556
521- final def withVar [A : Type , B : Type ](initialValue : Expr [A ])(inner : Quotes ?=> Var { type V = A } => Expr [B ])(
522- using Quotes ): Expr [B ] =
523- ' { var x : A = $initialValue; $ { inner(Var .of(' x , newX => ' { x = $newX })) } }
524-
525557 sealed abstract class Val {
526558 type V
527559 def tpe : Type [V ]
@@ -572,49 +604,271 @@ abstract private[derivation] class Deriver[F[_]: Type, T: Type, Q <: Quotes](usi
572604 next : Quotes ?=> IArray [Val ] => Expr [B ])(using Quotes ): Expr [B ] =
573605 val result = new Array [Val ](array.size)
574606 def rec (ix : Int )(using Quotes ): Expr [B ] =
575- if (ix < array.size) {
576- val x = initialValue(array(ix))
577- x.tpe match
578- case ' [t] =>
579- withVal(x.as[t].get) { y =>
580- result(ix) = Val .of(y)
581- rec(ix + 1 )
582- }
583- } else next(IArray .unsafeFromArray(result))
607+ array.size - ix match
608+ case n if n >= 8 =>
609+ val v0 = initialValue(array(ix + 0 ))
610+ val v1 = initialValue(array(ix + 1 ))
611+ val v2 = initialValue(array(ix + 2 ))
612+ val v3 = initialValue(array(ix + 3 ))
613+ val v4 = initialValue(array(ix + 4 ))
614+ val v5 = initialValue(array(ix + 5 ))
615+ val v6 = initialValue(array(ix + 6 ))
616+ val v7 = initialValue(array(ix + 7 ))
617+ (v0.tpe, v1.tpe, v2.tpe, v3.tpe, v4.tpe, v5.tpe, v6.tpe, v7.tpe) match
618+ case (' [t0], ' [t1], ' [t2], ' [t3], ' [t4], ' [t5], ' [t6], ' [t7]) =>
619+ ' {
620+ val x0 : t0 = $ { v0.as[t0].get }
621+ val x1 : t1 = $ { v1.as[t1].get }
622+ val x2 : t2 = $ { v2.as[t2].get }
623+ val x3 : t3 = $ { v3.as[t3].get }
624+ val x4 : t4 = $ { v4.as[t4].get }
625+ val x5 : t5 = $ { v5.as[t5].get }
626+ val x6 : t6 = $ { v6.as[t6].get }
627+ val x7 : t7 = $ { v7.as[t7].get }
628+ $ {
629+ result(ix + 0 ) = Val .of(' x0 )
630+ result(ix + 1 ) = Val .of(' x1 )
631+ result(ix + 2 ) = Val .of(' x2 )
632+ result(ix + 3 ) = Val .of(' x3 )
633+ result(ix + 4 ) = Val .of(' x4 )
634+ result(ix + 5 ) = Val .of(' x5 )
635+ result(ix + 6 ) = Val .of(' x6 )
636+ result(ix + 7 ) = Val .of(' x7 )
637+ rec(ix + 8 )
638+ }
639+ }
640+
641+ case n if n >= 4 =>
642+ val v0 = initialValue(array(ix + 0 ))
643+ val v1 = initialValue(array(ix + 1 ))
644+ val v2 = initialValue(array(ix + 2 ))
645+ val v3 = initialValue(array(ix + 3 ))
646+ (v0.tpe, v1.tpe, v2.tpe, v3.tpe) match
647+ case (' [t0], ' [t1], ' [t2], ' [t3]) =>
648+ ' {
649+ val x0 : t0 = $ { v0.as[t0].get }
650+ val x1 : t1 = $ { v1.as[t1].get }
651+ val x2 : t2 = $ { v2.as[t2].get }
652+ val x3 : t3 = $ { v3.as[t3].get }
653+ $ {
654+ result(ix + 0 ) = Val .of(' x0 )
655+ result(ix + 1 ) = Val .of(' x1 )
656+ result(ix + 2 ) = Val .of(' x2 )
657+ result(ix + 3 ) = Val .of(' x3 )
658+ rec(ix + 4 )
659+ }
660+ }
661+
662+ case n if n >= 2 =>
663+ val v0 = initialValue(array(ix + 0 ))
664+ val v1 = initialValue(array(ix + 1 ))
665+ (v0.tpe, v1.tpe) match
666+ case (' [t0], ' [t1]) =>
667+ ' {
668+ val x0 : t0 = $ { v0.as[t0].get }
669+ val x1 : t1 = $ { v1.as[t1].get }
670+ $ {
671+ result(ix + 0 ) = Val .of(' x0 )
672+ result(ix + 1 ) = Val .of(' x1 )
673+ rec(ix + 2 )
674+ }
675+ }
676+
677+ case n if n >= 1 =>
678+ val v = initialValue(array(ix))
679+ v.tpe match
680+ case ' [t] =>
681+ ' {
682+ val x : t = $ { v.as[t].get }
683+ $ {
684+ result(ix) = Val .of(' x )
685+ rec(ix + 1 )
686+ }
687+ }
688+
689+ case _ => next(IArray .unsafeFromArray(result))
690+
584691 rec(0 )
585692
586693 final def withVars [A , B : Type ](array : IArray [A ])(initialValue : Quotes ?=> A => Val )(
587694 next : Quotes ?=> IArray [Var ] => Expr [B ])(using Quotes ): Expr [B ] =
588695 val result = new Array [Var ](array.size)
589696 def rec (ix : Int )(using Quotes ): Expr [B ] =
590- if (ix < array.size) {
591- val x = initialValue(array(ix))
592- x.tpe match
593- case ' [t] =>
594- withVar(x.as[t].get) { y =>
595- result(ix) = y
596- rec(ix + 1 )
597- }
598- } else next(IArray .unsafeFromArray(result))
697+ array.size - ix match
698+ case n if n >= 8 =>
699+ val v0 = initialValue(array(ix + 0 ))
700+ val v1 = initialValue(array(ix + 1 ))
701+ val v2 = initialValue(array(ix + 2 ))
702+ val v3 = initialValue(array(ix + 3 ))
703+ val v4 = initialValue(array(ix + 4 ))
704+ val v5 = initialValue(array(ix + 5 ))
705+ val v6 = initialValue(array(ix + 6 ))
706+ val v7 = initialValue(array(ix + 7 ))
707+ (v0.tpe, v1.tpe, v2.tpe, v3.tpe, v4.tpe, v5.tpe, v6.tpe, v7.tpe) match
708+ case (' [t0], ' [t1], ' [t2], ' [t3], ' [t4], ' [t5], ' [t6], ' [t7]) =>
709+ ' {
710+ var x0 : t0 = $ { v0.as[t0].get }
711+ var x1 : t1 = $ { v1.as[t1].get }
712+ var x2 : t2 = $ { v2.as[t2].get }
713+ var x3 : t3 = $ { v3.as[t3].get }
714+ var x4 : t4 = $ { v4.as[t4].get }
715+ var x5 : t5 = $ { v5.as[t5].get }
716+ var x6 : t6 = $ { v6.as[t6].get }
717+ var x7 : t7 = $ { v7.as[t7].get }
718+ $ {
719+ result(ix + 0 ) = Var .of(' x0 , newX => ' { x0 = $newX })
720+ result(ix + 1 ) = Var .of(' x1 , newX => ' { x1 = $newX })
721+ result(ix + 2 ) = Var .of(' x2 , newX => ' { x2 = $newX })
722+ result(ix + 3 ) = Var .of(' x3 , newX => ' { x3 = $newX })
723+ result(ix + 4 ) = Var .of(' x4 , newX => ' { x4 = $newX })
724+ result(ix + 5 ) = Var .of(' x5 , newX => ' { x5 = $newX })
725+ result(ix + 6 ) = Var .of(' x6 , newX => ' { x6 = $newX })
726+ result(ix + 7 ) = Var .of(' x7 , newX => ' { x7 = $newX })
727+ rec(ix + 8 )
728+ }
729+ }
730+
731+ case n if n >= 4 =>
732+ val v0 = initialValue(array(ix + 0 ))
733+ val v1 = initialValue(array(ix + 1 ))
734+ val v2 = initialValue(array(ix + 2 ))
735+ val v3 = initialValue(array(ix + 3 ))
736+ (v0.tpe, v1.tpe, v2.tpe, v3.tpe) match
737+ case (' [t0], ' [t1], ' [t2], ' [t3]) =>
738+ ' {
739+ var x0 : t0 = $ { v0.as[t0].get }
740+ var x1 : t1 = $ { v1.as[t1].get }
741+ var x2 : t2 = $ { v2.as[t2].get }
742+ var x3 : t3 = $ { v3.as[t3].get }
743+ $ {
744+ result(ix + 0 ) = Var .of(' x0 , newX => ' { x0 = $newX })
745+ result(ix + 1 ) = Var .of(' x1 , newX => ' { x1 = $newX })
746+ result(ix + 2 ) = Var .of(' x2 , newX => ' { x2 = $newX })
747+ result(ix + 3 ) = Var .of(' x3 , newX => ' { x3 = $newX })
748+ rec(ix + 4 )
749+ }
750+ }
751+
752+ case n if n >= 2 =>
753+ val v0 = initialValue(array(ix + 0 ))
754+ val v1 = initialValue(array(ix + 1 ))
755+ (v0.tpe, v1.tpe) match
756+ case (' [t0], ' [t1]) =>
757+ ' {
758+ var x0 : t0 = $ { v0.as[t0].get }
759+ var x1 : t1 = $ { v1.as[t1].get }
760+ $ {
761+ result(ix + 0 ) = Var .of(' x0 , newX => ' { x0 = $newX })
762+ result(ix + 1 ) = Var .of(' x1 , newX => ' { x1 = $newX })
763+ rec(ix + 2 )
764+ }
765+ }
766+
767+ case n if n >= 1 =>
768+ val v = initialValue(array(ix))
769+ v.tpe match
770+ case ' [t]=>
771+ ' {
772+ var x : t = $ { v.as[t].get }
773+ $ {
774+ result(ix + 0 ) = Var .of(' x , newX => ' { x = $newX })
775+ rec(ix + 1 )
776+ }
777+ }
778+
779+ case _ => next(IArray .unsafeFromArray(result))
780+
599781 rec(0 )
600782
601783 final def withOptVals [A , B : Type ](array : IArray [A ])(initialValue : Quotes ?=> A => Option [Val ])(
602784 next : Quotes ?=> IArray [Option [Val ]] => Expr [B ])(using Quotes ): Expr [B ] =
603- val result = new Array [Option [Val ]](array.size)
785+ val result = Array .fill[Option [Val ]](array.size)(None )
786+ val initialValuesWithIndex = array.zipWithIndex.flatMap { case (x, i) => initialValue(x).map(_ -> i) }
604787 def rec (ix : Int )(using Quotes ): Expr [B ] =
605- if (ix < array.size)
606- initialValue(array(ix)) match
607- case Some (x) =>
608- x.tpe match
609- case ' [t] =>
610- withVal(x.as[t].get) { y =>
611- result(ix) = Some (Val .of(y))
788+ initialValuesWithIndex.size - ix match
789+ case n if n >= 8 =>
790+ val (v0, i0) = initialValuesWithIndex(ix + 0 )
791+ val (v1, i1) = initialValuesWithIndex(ix + 1 )
792+ val (v2, i2) = initialValuesWithIndex(ix + 2 )
793+ val (v3, i3) = initialValuesWithIndex(ix + 3 )
794+ val (v4, i4) = initialValuesWithIndex(ix + 4 )
795+ val (v5, i5) = initialValuesWithIndex(ix + 5 )
796+ val (v6, i6) = initialValuesWithIndex(ix + 6 )
797+ val (v7, i7) = initialValuesWithIndex(ix + 7 )
798+ (v0.tpe, v1.tpe, v2.tpe, v3.tpe, v4.tpe, v5.tpe, v6.tpe, v7.tpe) match
799+ case (' [t0], ' [t1], ' [t2], ' [t3], ' [t4], ' [t5], ' [t6], ' [t7]) =>
800+ ' {
801+ val x0 : t0 = $ { v0.as[t0].get }
802+ val x1 : t1 = $ { v1.as[t1].get }
803+ val x2 : t2 = $ { v2.as[t2].get }
804+ val x3 : t3 = $ { v3.as[t3].get }
805+ val x4 : t4 = $ { v4.as[t4].get }
806+ val x5 : t5 = $ { v5.as[t5].get }
807+ val x6 : t6 = $ { v6.as[t6].get }
808+ val x7 : t7 = $ { v7.as[t7].get }
809+ $ {
810+ result(i0) = Some (Val .of(' x0 ))
811+ result(i1) = Some (Val .of(' x1 ))
812+ result(i2) = Some (Val .of(' x2 ))
813+ result(i3) = Some (Val .of(' x3 ))
814+ result(i4) = Some (Val .of(' x4 ))
815+ result(i5) = Some (Val .of(' x5 ))
816+ result(i6) = Some (Val .of(' x6 ))
817+ result(i7) = Some (Val .of(' x7 ))
818+ rec(ix + 8 )
819+ }
820+ }
821+
822+ case n if n >= 4 =>
823+ val (v0, i0) = initialValuesWithIndex(ix + 0 )
824+ val (v1, i1) = initialValuesWithIndex(ix + 1 )
825+ val (v2, i2) = initialValuesWithIndex(ix + 2 )
826+ val (v3, i3) = initialValuesWithIndex(ix + 3 )
827+ (v0.tpe, v1.tpe, v2.tpe, v3.tpe) match
828+ case (' [t0], ' [t1], ' [t2], ' [t3]) =>
829+ ' {
830+ val x0 : t0 = $ { v0.as[t0].get }
831+ val x1 : t1 = $ { v1.as[t1].get }
832+ val x2 : t2 = $ { v2.as[t2].get }
833+ val x3 : t3 = $ { v3.as[t3].get }
834+ $ {
835+ result(i0) = Some (Val .of(' x0 ))
836+ result(i1) = Some (Val .of(' x1 ))
837+ result(i2) = Some (Val .of(' x2 ))
838+ result(i3) = Some (Val .of(' x3 ))
839+ rec(ix + 4 )
840+ }
841+ }
842+
843+ case n if n >= 2 =>
844+ val (v0, i0) = initialValuesWithIndex(ix + 0 )
845+ val (v1, i1) = initialValuesWithIndex(ix + 1 )
846+ (v0.tpe, v1.tpe) match
847+ case (' [t0], ' [t1]) =>
848+ ' {
849+ val x0 : t0 = $ { v0.as[t0].get }
850+ val x1 : t1 = $ { v1.as[t1].get }
851+ $ {
852+ result(i0) = Some (Val .of(' x0 ))
853+ result(i1) = Some (Val .of(' x1 ))
854+ rec(ix + 2 )
855+ }
856+ }
857+
858+ case n if n >= 1 =>
859+ val (v, i) = initialValuesWithIndex(ix)
860+ v.tpe match
861+ case ' [t] =>
862+ ' {
863+ val x : t = $ { v.as[t].get }
864+ $ {
865+ result(i) = Some (Val .of(' x ))
612866 rec(ix + 1 )
613867 }
614- case None =>
615- result(ix) = None
616- rec(ix + 1 )
617- else next( IArray .unsafeFromArray(result))
868+ }
869+
870+ case _ => next( IArray .unsafeFromArray(result) )
871+
618872 rec(0 )
619873
620874 final def companionApply (companion : Symbol , typeArgs : List [TypeRepr ], args : List [Term ]): Term =
0 commit comments