, Scala. typecheck tpt , , X[A] X.Txn[Tx, A] X, TxnMarker, .
, ( ) ( typechecker) , ( Scala macros: (aka typechecked) ), .
, 2.10, 2.11 , , (, Var Var[...] - , , , , , Var). , , , .
import scala.reflect.macros.whitebox._
import scala.language.experimental.macros
import scala.annotation.StaticAnnotation
trait Var[T]
trait TxnMarker
object txnMacro {
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
// NOTE: this pattern is only going to work with simple traits
// for a full pattern that captures all traits, refer to Denys quasiquote guide:
// http://den.sh/quasiquotes.html
val q"$mods trait $name[..$targs] extends ..$parents { ..$stats }" = annottees.head.tree
def rewire(tpt: Tree): Tree = {
object RewireTransformer extends Transformer {
override def transform(tree: Tree): Tree = tree match {
case AppliedTypeTree(x @ RefTree(xqual, xname), a :: Nil) =>
val dummyType = q"type SomeUniqueName[T] = $x[T]"
val dummyTrait = q"$mods trait $name[..$targs] extends ..$parents { ..${stats :+ dummyType} }"
val dummyTrait1 = c.typecheck(dummyTrait)
val q"$_ trait $_[..$_] extends ..$_ { ..${_ :+ dummyType1} }" = dummyTrait1
def refersToSelf = dummyTrait1.symbol == dummyType1.symbol.info.typeSymbol
def refersToSubtypeOfTxnMarker = dummyType1.symbol.info.baseClasses.contains(symbolOf[TxnMarker])
if (refersToSelf || refersToSubtypeOfTxnMarker) transform(tq"${RefTree(xqual, xname.toTermName)}.Txn[Tx, $a]")
else super.transform(tree)
case _ =>
super.transform(tree)
}
}
RewireTransformer.transform(tpt)
}
val stats1 = stats map {
// this is a simplification, probably you'll also want to do recursive rewiring and whatnot
// but I'm omitting that here to focus on the question at hand
case q"$mods val $name: $tpt = $_" => q"$mods def $name: $tpt"
case q"$mods var $name: $tpt = $_" => q"$mods def $name: Var[${rewire(tpt)}]"
case stat => stat
}
val annottee1 = q"$mods trait $name[..$targs] extends ..${parents :+ tq"TxnMarker"} { ..$stats }"
val companion = q"""
object ${name.toTermName} {
trait Txn[Tx, A] { ..$stats1 }
}
"""
c.Expr[Any](Block(List(annottee1, companion), Literal(Constant(()))))
}
}
class txn extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro txnMacro.impl
}
, , , @txn - . info.baseClasses.contains(symbolOf[TxnMarker]) /, info, . SOE , - scalac .
, . , . , , , !
object Cell {
trait Txn[-Tx, A] {
def value: A
def next: Var[Option[Cell.Txn[Tx, A]]]
}
}
trait Cell[A] {
val value: A
var next: Option[Cell[A]]
}
:
object Cell {
trait Txn[-Tx, A] {
def value: A
def next[U](implicit ev: TxnTypeMapper[Option[Cell[A]], U]): U
}
}
trait Cell[A] {
val value: A
var next: Option[Cell[A]]
}
TxnTypeMapper[T, U] fundage materializer, Type => Type, Type.map, , , ( typer), . , , !!