Created
April 4, 2015 05:53
-
-
Save LPTK/01a1f873eab83e45a5de to your computer and use it in GitHub Desktop.
DSL for generic pattern matching
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
object GenPattern extends App { | |
abstract class TypeBase(val name: String) | |
trait Type[+T] { val base: TypeBase; val params: Seq[Type[_]]; override def toString = s"${base.name}[${params mkString ","}]" } | |
type Rep[+T] = Node[T] | |
trait Node[+T] { val typ: Type[T]; val args: Seq[_] } | |
case class Comp[+T](typ: Type[T], args: Rep[_]*) extends Node[T] | |
{ override def toString = s"$typ(${args mkString ","})" } | |
case class Const[+T](typ: Type[T], v: T) extends Node[T] { val args = Seq(v) } | |
object Int extends TypeBase("Int") with Type[scala.Int] { val base = this; val params = List() } | |
implicit def int2Const(x: Int) = Const(Int, x) | |
object Vector extends TypeBase("Vector") { | |
def <[T] (t: Type[T]) = new { def > (xs: Rep[T]*) = Vector(t) of (xs: _*) } | |
} | |
case class Vector[+A](p: Type[A]) extends Type[Seq[A]] { val name = "Seq"; val base = Vector; val params = List(p) } | |
implicit class VectorOf[A](val self: Vector[A]) { | |
def of(xs: Rep[A]*) = Comp[Seq[A]](self, xs: _*) | |
} | |
object VectorOf { | |
def unapplySeq(n: Node[Seq[_]]) = n match { case Comp(typ,args@_*) => Some(Seq(typ.base) ++ args) } | |
} | |
object Hashmap extends TypeBase("Map") | |
case class Hashmap[A,+B](pa: Type[A], pb: Type[B]) extends Type[Map[A,B]] { val base = Hashmap; val params = List(pa,pb) } | |
implicit class HashmapOf[A,B](val self: Hashmap[A,B]) { | |
def of() = Comp[Map[A,B]](self) | |
} | |
object of { | |
def unapplySeq[T](n: Node[T]) = Some(Seq(n.typ) ++ n.args) | |
} | |
object ofSome { | |
def unapply[T](n: Node[T]) = Some(n.typ, n.args.size) | |
} | |
object < { | |
def unapplySeq[T](n: Node[T]) = Some(Seq(n.typ.base) ++ n.typ.params) | |
} | |
object > { | |
def unapplySeq[T](n: Node[T]) = Some(Seq(n) ++ n.args) | |
} | |
{ | |
val v = Vector(Int) of (1,2,3) | |
val m = Hashmap(Int, Vector(Int)) of () | |
Vector(Int) match { | |
case Vector(t) => println(s"Vector with type $t") | |
} | |
Vector(Vector(Int)) match { | |
case Vector(t) if false => // idea infers t: Type[Seq[Int]] | |
case Vector(Vector(t)) => Hashmap(Int,t) | |
} | |
Vector(Int) of (1,2,3) match { | |
case Vector(Int) of (Const(Int,1),Const(Int,2),Const(Int,3)) => | |
} | |
Vector(Int) of (1,2,3) match { case Vector(_) of (x,y,z) => println(s"$x,$y,$z") } | |
Vector(Int) of (1,2,3) match { case VectorOf(args @ _*) => println(s"$args") } | |
Vector<Int>(1,2,3) match { case Vector<Int>(x,y,z) => println(s"$x,$y,$z") } | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment