Skip to content

Instantly share code, notes, and snippets.

@axel22
Created October 21, 2015 14:27
Show Gist options
  • Save axel22/1fe179be8b91a5ca83a2 to your computer and use it in GitHub Desktop.
Save axel22/1fe179be8b91a5ca83a2 to your computer and use it in GitHub Desktop.
import scala.language.experimental.macros
object Input {
//val universe: scala.reflect.runtime.universe.type = scala.reflect.runtime.universe
//import universe._
import scala.reflect.macros.whitebox.Context
type Query[T] = () => Option[T]
implicit class QueryOps[T](q: Query[T]) {
def map[S](f: T => S): Query[S] = {
() => for (x <- q()) yield f(x)
}
def flatMap[S](f: T => Query[S]): Query[S] = {
() => for (x <- q(); y <- f(x)()) yield y
}
}
trait Parsable[T] {
def parse(s: String): T
}
object Parsable {
implicit val stringParsable = new Parsable[String] {
def parse(s: String) = s
}
implicit val intParsable = new Parsable[Int] {
def parse(s: String) = s.toInt
}
}
def text(q: String): Query[String] = () => {
println(q)
val v = scala.io.StdIn.readLine()
if (v == null) None else Some(v)
}
def read[T: Parsable](q: String): Query[T] =
() => for (v <- text(q)()) yield implicitly[Parsable[T]].parse(v)
def query(ctor: Any): Any = macro queryImpl
def queryImpl(c: Context)(ctor: c.Tree): c.Tree = {
import c.universe._
val q"(..$args) => new $cls(..$_)" = ctor
val names = for (arg <- args) yield c.freshName("x$")
val reads = for ((q"$_ val $arg: $tp", name) <- args zip names) yield {
fq"${TermName(name)} <- new Input.QueryOps(Input.read[$tp](${arg + ": "}))"
}
q"for (..$reads) yield new $cls(..${names.map(TermName(_))})"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment