Created
October 21, 2015 14:27
-
-
Save axel22/1fe179be8b91a5ca83a2 to your computer and use it in GitHub Desktop.
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
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