Skip to content

Instantly share code, notes, and snippets.

@xeno-by
Created January 3, 2014 18:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xeno-by/8243032 to your computer and use it in GitHub Desktop.
Save xeno-by/8243032 to your computer and use it in GitHub Desktop.
import scala.reflect.macros.{BlackboxContext, WhiteboxContext}
import scala.annotation.compileTimeOnly
import scala.language.experimental.macros
object Macros {
def impl(c: WhiteboxContext)(body: c.Tree) = {
import c.universe._
val Block(stats0, expr) = body
val stats: List[Tree] = stats0 :+ expr
def yyTransform(stats: List[Tree]): List[List[Tree]] = {
object Yret {
def unapply(stat: Tree): Option[Tree] = {
// println(stat)
// println(showRaw(stat))
stat match {
case q"Macros.yret($x)" => Some(x)
case _ => None
}
}
}
// println(stats)
// println(Yret.unapply(stats.head))
val (prefix, suffix) = (stats.span(s => Yret.unapply(s).isEmpty))
// println(prefix, suffix)
suffix match {
case Yret(x) :: rest => List(prefix :+ x) ++ yyTransform(rest)
case Nil => List(prefix)
}
}
val transformed = yyTransform(stats) match {
case init :+ Nil => init
case xs => xs
}
// println(transformed)
val thunks = transformed.map(stats => q"() => { ..$stats }")
// println(thunks)
q"List(..$thunks).iterator.map(thunk => thunk())"
}
def yy[T](body: T): Any = macro impl
@compileTimeOnly("can't use yret outside yy")
def yret(x: Any): Unit = ???
}
===========
import Macros._
object Test extends App {
val x = yy {
println("returning 2")
yret(2)
println("returning 3")
yret(3)
}
println("hello")
println(x.toList)
}
===========
Если заменить сигнатуру `def yret(x: Any): Unit` на `def yret[T](x: T): Unit`, то получается проблема с КЦ. Ни `q"Macros.yret[Int]($x)"`, ни `q"Macros.yret[$_]($x)"` не будут матчить вызовы yret.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment