aboutsummaryrefslogtreecommitdiff
path: root/tests/run/generic/SearchResult.scala
blob: d4380a072b9fc907508958d12095d2a1ff30574a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package generic

import Shapes._

/** enum SearchResult {
 *    case Success(result: Color)
 *    case Diverging
 *    case NoMatch
 *    case Ambiguous(alt1: SearchResult, alt2: SearchResult)
 *  }
 */
sealed trait SearchResult extends Enum

object SearchResult extends {

  private val $values = new runtime.EnumValues[SearchResult]
  def valueOf = $values.fromInt
  def withName = $values.fromName
  def values = $values.values

  private def $new(tag: Int, name: String) = new SearchResult {
    def enumTag = tag
    override def toString = name
    $values.register(this)
  }

  abstract case class Success(result: Color) extends SearchResult {
    def enumTag = 0
  }
  object Success {
    def apply(result: Color): SearchResult = new Success(result) {}
    implicit def SuccessShape: Success `shaped` Color =
      new (Success `shaped` Color) {
        def toShape(s: Success) = s.result
        def fromShape(c: Color) = new Success(c) {}
    }
  }

  val Diverging: SearchResult = $new(1, "Diverging")
  val NoMatch: SearchResult = $new(2, "NoMatch")

  abstract case class Ambiguous(alt1: SearchResult, alt2: SearchResult) extends SearchResult {
    def enumTag = 3
  }
  object Ambiguous {
    def apply(alt1: SearchResult, alt2: SearchResult): SearchResult = new Ambiguous(alt1, alt2) {}
    implicit def AmbiguousShape: Ambiguous `shaped` Prod[SearchResult, SearchResult] =
      new (Ambiguous `shaped` Prod[SearchResult, SearchResult]) {
        def toShape(a: Ambiguous) = Prod(a.alt1, a.alt2)
        def fromShape(p: Prod[SearchResult, SearchResult]) = new Ambiguous(p.fst, p.snd) {}
    }
  }

  type Shape = Sum[Success, Sum[Ambiguous, EnumValue[SearchResult]]]

  implicit def SearchResultShape: SearchResult `unfolds` Shape =
    new (SearchResult `shaped` Shape) {
      def toShape(x: SearchResult) = x match {
        case x: Success => Fst(x)
        case x: Ambiguous => Snd(Fst(x))
        case x => Snd(Snd(EnumValue(x.enumTag)))
      }
      def fromShape(x: Sum[Success, Sum[Ambiguous, EnumValue[SearchResult]]]): SearchResult = x match {
        case Fst(s) => s
        case Snd(Fst(a)) => a
        case Snd(Snd(ev)) => valueOf(ev.tag)
      }
    }
}