Skip to content
Permalink
Browse files

Simplify type logic in ActionOpsSupport

  • Loading branch information...
sirthias committed May 3, 2019
1 parent 7ed425a commit 1275155e04028e8ed9a24003fff60298c07959fa
@@ -18,7 +18,7 @@ package org.parboiled2.support

import shapeless._
import org.parboiled2.Rule
import shapeless.ops.hlist.ReversePrepend
import shapeless.ops.hlist.Prepend

/*
* The main ActionOps boilerplate is generated by a custom SBT sourceGenerator.
@@ -36,84 +36,38 @@ object FCapture {

// builds `In` and `Out` types according to this logic:
// if (R == Unit)
// In = I, Out = L1 ::: L2
// In = I, Out = L
// else if (R <: HList)
// In = I, Out = L1 ::: L2 ::: R
// In = I, Out = L ::: R
// else if (R <: Rule[I2, O2])
// In = TailSwitch[I2, L1 ::: L2, I], Out = TailSwitch[L1 ::: L2, I2, O2]
// In = TailSwitch[I2, L, I], Out = TailSwitch[L, I2, O2]
// else
// In = I, Out = L1 ::: L2 ::: R :: HNil
sealed trait Join[I <: HList, L1 <: HList, L2 <: HList, R] {
// In = I, Out = L ::: R :: HNil
sealed trait Join[I <: HList, L <: HList, R] {
type In <: HList
type Out <: HList
}

object Join {
implicit def join[I <: HList, L1 <: HList, L2 <: HList, R, In0 <: HList, Out0 <: HList](
implicit x: Aux[I, L1, L2, R, HNil, In0, Out0]
): Join[I, L1, L2, R] { type In = In0; type Out = Out0 } = `n/a`
object Join extends LowPrioJoin {

sealed trait Aux[I <: HList, L1 <: HList, L2 <: HList, R, Acc <: HList, In <: HList, Out <: HList]
implicit def forUnit[I <: HList, L <: HList]: Aux[I, L, Unit, I, L] = `n/a`

object Aux extends Aux1 {
// if R == Unit convert to HNil
implicit def forUnit[I <: HList, L1 <: HList, L2 <: HList, Acc <: HList, Out <: HList](
implicit x: Aux[I, L1, L2, HNil, Acc, I, Out]
): Aux[I, L1, L2, Unit, Acc, I, Out] = `n/a`
implicit def forHList[I <: HList, L <: HList, R <: HList, O <: HList](
implicit x: Prepend.Aux[L, R, O]
): Aux[I, L, R, I, O] = `n/a`

// if R <: HList and L1 non-empty move head of L1 to Acc
implicit def iter1[I <: HList, H, T <: HList, L2 <: HList, R <: HList, Acc <: HList, Out <: HList](
implicit x: Aux[I, T, L2, R, H :: Acc, I, Out]
): Aux[I, H :: T, L2, R, Acc, I, Out] = `n/a`

// if R <: HList and L1 empty and L2 non-empty move head of L2 to Acc
implicit def iter2[I <: HList, H, T <: HList, R <: HList, Acc <: HList, Out <: HList](
implicit x: Aux[I, HNil, T, R, H :: Acc, I, Out]
): Aux[I, HNil, H :: T, R, Acc, I, Out] = `n/a`

// if R <: HList and L1 and L2 empty set Out = reversePrepend Acc before R
implicit def terminate[I <: HList, R <: HList, Acc <: HList, Out <: HList](
implicit x: ReversePrepend.Aux[Acc, R, Out]
): Aux[I, HNil, HNil, R, Acc, I, Out] = `n/a`
implicit def forRule[I <: HList, O <: HList, I2 <: HList, O2 <: HList, In <: HList, Out <: HList](
implicit i: TailSwitch.Aux[I2, I2, O, O, I, HNil, In],
o: TailSwitch.Aux[O, O, I2, I2, O2, HNil, Out]
): Aux[I, O, Rule[I2, O2], In, Out] = `n/a`
}

// if R <: Rule and L1 non-empty move head of L1 to Acc
implicit def iterRule1[
I <: HList,
L2 <: HList,
I2 <: HList,
O2 <: HList,
In0 <: HList,
Acc <: HList,
Out0 <: HList,
H,
T <: HList
](implicit x: Aux[I, T, L2, Rule[I2, O2], H :: Acc, In0, Out0]): Aux[I, H :: T, L2, Rule[I2, O2], HNil, In0, Out0] =
`n/a`
sealed abstract class LowPrioJoin {

// if R <: Rule and L1 empty and Acc non-empty move head of Acc to L2
implicit def iterRule2[
I <: HList,
L2 <: HList,
I2 <: HList,
O2 <: HList,
In0 <: HList,
Out0 <: HList,
H,
T <: HList
](
implicit x: Aux[I, HNil, H :: L2, Rule[I2, O2], T, In0, Out0]
): Aux[I, HNil, L2, Rule[I2, O2], H :: T, In0, Out0] = `n/a`
type Aux[I <: HList, L <: HList, R, In0 <: HList, Out0 <: HList] =
Join[I, L, R] { type In = In0; type Out = Out0 }

// if R <: Rule and L1 and Acc empty set In and Out to tailswitches result
implicit def terminateRule[I <: HList, O <: HList, I2 <: HList, O2 <: HList, In <: HList, Out <: HList](
implicit i: TailSwitch.Aux[I2, I2, O, O, I, HNil, In],
o: TailSwitch.Aux[O, O, I2, I2, O2, HNil, Out]
): Aux[I, HNil, O, Rule[I2, O2], HNil, In, Out] = `n/a`
}
abstract class Aux1 {
// convert R to R :: HNil
implicit def forAny[I <: HList, L1 <: HList, L2 <: HList, R, Acc <: HList, Out <: HList](
implicit x: Aux[I, L1, L2, R :: HNil, Acc, I, Out]
): Aux[I, L1, L2, R, Acc, I, Out] = `n/a`
}
implicit def forAny[I <: HList, L <: HList, R, In <: HList, Out <: HList](
implicit x: Aux[I, L, R :: HNil, In, Out]
): Aux[I, L, R, In, Out] = `n/a`
}
@@ -52,7 +52,7 @@ object RunResult {
}

abstract class Aux2 {
protected type JA[I <: HList, R, In0 <: HList, Out0 <: HList] = Join.Aux[I, HNil, HNil, R, HNil, In0, Out0]
protected type JA[I <: HList, R, In0 <: HList, Out0 <: HList] = Join.Aux[I, HNil, R, In0, Out0]
implicit def forAny[T]: Aux[T, Rule0] = `n/a`
}
}
@@ -63,7 +63,6 @@ object ActionOpsBoilerplate {
|
|sealed trait ActionOps[I <: HList, O <: HList] { type Out }
|object ActionOps {
| private type SJoin[I <: HList, O <: HList, R] = Join[I, HNil, O, R]
|
|""".stripMargin

@@ -76,22 +75,22 @@ object ActionOpsBoilerplate {
def generate0 = {
def consumeStack(i: Int) =
s""" def apply[${`..., Z`(i)}, RR](f: (${`..., Z`(i)}) => RR)
| (implicit j: SJoin[${`... :: Z`(i)} :: II, HNil, RR],
| (implicit j: Join[${`... :: Z`(i)} :: II, HNil, RR],
| c: FCapture[(${`..., Z`(i)}) => RR]): Rule[j.In, j.Out]
""".stripMargin

// implicit def ops0[II <: HList, OO <: HNil]: ActionOps[II, OO] { type Out = Ops0[II] } = `n/a`
// sealed trait Ops0[II <: HList] {
// def apply[RR](f: () => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out]
// def apply[Z, RR](f: Z => RR)(implicit j: SJoin[Z :: II, HNil, RR], c: FCapture[Z => RR]): Rule[j.In, j.Out]
// def apply[Y, Z, RR](f: (Y, Z) => RR)(implicit j: SJoin[Y :: Z :: II, HNil, RR], c: FCapture[(Y, Z) => RR]): Rule[j.In, j.Out]
// def apply[X, Y, Z, RR](f: (X, Y, Z) => RR)(implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], c: FCapture[(X, Y, Z) => RR]): Rule[j.In, j.Out]
// def apply[RR](f: () => RR)(implicit j: Join[II, HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out]
// def apply[Z, RR](f: Z => RR)(implicit j: Join[Z :: II, HNil, RR], c: FCapture[Z => RR]): Rule[j.In, j.Out]
// def apply[Y, Z, RR](f: (Y, Z) => RR)(implicit j: Join[Y :: Z :: II, HNil, RR], c: FCapture[(Y, Z) => RR]): Rule[j.In, j.Out]
// def apply[X, Y, Z, RR](f: (X, Y, Z) => RR)(implicit j: Join[X :: Y :: Z :: II, HNil, RR], c: FCapture[(X, Y, Z) => RR]): Rule[j.In, j.Out]
// ...
// }

s""" implicit def ops0[II <: HList, OO <: HNil]: ActionOps[II, OO] { type Out = Ops0[II] } = `n/a`
| sealed trait Ops0[II <: HList] {
| def apply[RR](f: () => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out]
| def apply[RR](f: () => RR)(implicit j: Join[II, HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out]
|
|${(1 to MaxArity) map consumeStack mkString "\n"}
| }
@@ -102,37 +101,37 @@ object ActionOpsBoilerplate {
def consumeOut(j: Int) = {
val consumedTypes = AtoZ take i takeRight j mkString ", "
s""" def apply[RR](f: ($consumedTypes) => RR)
| (implicit j: SJoin[II, ${`A ::...`(i - j)} :: HNil, RR],
| (implicit j: Join[II, ${`A ::...`(i - j)} :: HNil, RR],
| c: FCapture[($consumedTypes) => RR]): Rule[j.In, j.Out]
""".stripMargin
}

def consumeStack(j: Int) =
s""" def apply[${`..., Z`(j)}, RR](f: (${`..., Z`(j)}, ${`A, ...`(i)}) => RR)
| (implicit j: SJoin[${`... :: Z`(j)} :: II, HNil, RR],
| (implicit j: Join[${`... :: Z`(j)} :: II, HNil, RR],
| c: FCapture[(${`..., Z`(j)}, ${`A, ...`(i)}) => RR]): Rule[j.In, j.Out]
""".stripMargin

// e.g.
// implicit def ops3[II <: HList, A, B, C]: ActionOps[II, A :: B :: C :: HNil] { type Out = Ops3[II, A, B, C] } = `n/a`
// sealed trait Ops3[II <: HList, A, B, C] {
// def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out]
// def apply[RR](f: C => RR)(implicit j: SJoin[II, A :: B :: HNil, RR], c: FCapture[C => RR]): Rule[j.In, j.Out]
// def apply[RR](f: (B, C) => RR)(implicit j: SJoin[II, A :: HNil, RR], c: FCapture[(B, C) => RR]): Rule[j.In, j.Out]
// def apply[RR](f: (A, B, C) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C) => RR]): Rule[j.In, j.Out]
// def apply[Z, RR](f: (Z, A, B, C) => RR)(implicit j: SJoin[Z :: II, HNil, RR], c: FCapture[(Z, A, B, C) => RR]): Rule[j.In, j.Out]
// def apply[Y, Z, RR](f: (Y, Z, A, B, C) => RR)(implicit j: SJoin[Y :: Z :: II, HNil, RR], c: FCapture[(Y, Z, A, B, C) => RR]): Rule[j.In, j.Out]
// def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C) => RR)(implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], c: FCapture[(X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out]
// def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out]
// def apply[RR](f: C => RR)(implicit j: Join[II, A :: B :: HNil, RR], c: FCapture[C => RR]): Rule[j.In, j.Out]
// def apply[RR](f: (B, C) => RR)(implicit j: Join[II, A :: HNil, RR], c: FCapture[(B, C) => RR]): Rule[j.In, j.Out]
// def apply[RR](f: (A, B, C) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C) => RR]): Rule[j.In, j.Out]
// def apply[Z, RR](f: (Z, A, B, C) => RR)(implicit j: Join[Z :: II, HNil, RR], c: FCapture[(Z, A, B, C) => RR]): Rule[j.In, j.Out]
// def apply[Y, Z, RR](f: (Y, Z, A, B, C) => RR)(implicit j: Join[Y :: Z :: II, HNil, RR], c: FCapture[(Y, Z, A, B, C) => RR]): Rule[j.In, j.Out]
// def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C) => RR)(implicit j: Join[X :: Y :: Z :: II, HNil, RR], c: FCapture[(X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out]
// ...
// }

s"""
| implicit def ops$i[II <: HList, ${`A, ...`(i)}]: ActionOps[II, ${`A ::...`(i)} :: HNil] { type Out = Ops$i[II, ${`A, ...`(i)}] } = `n/a`
| sealed trait Ops$i[II <: HList, ${`A, ...`(i)}] {
| def apply[RR](f: () => RR)(implicit j: SJoin[II, ${`A ::...`(i)} :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out]
| def apply[RR](f: () => RR)(implicit j: Join[II, ${`A ::...`(i)} :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out]
|
|${(1 to i-1) map consumeOut mkString "\n"}
| def apply[RR](f: (${`A, ...`(i)}) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(${`A, ...`(i)}) => RR]): Rule[j.In, j.Out]
| def apply[RR](f: (${`A, ...`(i)}) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(${`A, ...`(i)}) => RR]): Rule[j.In, j.Out]
|
|${(1 to 22-i) map consumeStack mkString "\n"}
| }

0 comments on commit 1275155

Please sign in to comment.
You can’t perform that action at this time.