Permalink
Browse files

Added a macro to materialize an inhabitant for the singleton type.

  • Loading branch information...
folone committed Mar 14, 2014
1 parent 88b13e6 commit 094883efb4d1c50981cea41f049c3930c8efbc3c
@@ -20,8 +20,8 @@ trait FastTrack {
private implicit def context2taggers(c0: MacroContext): Taggers { val c: c0.type } =
new { val c: c0.type = c0 } with Taggers
private implicit def context2macroimplementations(c0: MacroContext): FormatInterpolator { val c: c0.type } =
new { val c: c0.type = c0 } with FormatInterpolator
private implicit def context2macroimplementations(c0: MacroContext): FormatInterpolator with SingleInhabitantMacro { val c: c0.type } =
new { val c: c0.type = c0 } with FormatInterpolator with SingleInhabitantMacro
private implicit def context2quasiquote(c0: MacroContext): QuasiquoteImpls { val c: c0.type } =
new { val c: c0.type = c0 } with QuasiquoteImpls
private def makeBlackbox(sym: Symbol)(pf: PartialFunction[Applied, MacroContext => Tree]) =
@@ -48,6 +48,7 @@ trait FastTrack {
makeBlackbox( materializeWeakTypeTag) { case Applied(_, ttag :: Nil, (u :: _) :: _) => _.materializeTypeTag(u, EmptyTree, ttag.tpe, concrete = false) },
makeBlackbox( materializeTypeTag) { case Applied(_, ttag :: Nil, (u :: _) :: _) => _.materializeTypeTag(u, EmptyTree, ttag.tpe, concrete = true) },
makeBlackbox( ApiUniverseReify) { case Applied(_, ttag :: Nil, (expr :: _) :: _) => c => c.materializeExpr(c.prefix.tree, EmptyTree, expr) },
makeBlackbox( SingleInhabitant_witness) { case Applied(_, ttag :: Nil, _) => _.materialize(ttag.tpe) },
makeBlackbox( StringContext_f) { case _ => _.interpolate },
makeBlackbox(ReflectRuntimeCurrentMirror) { case _ => c => currentMirror(c).tree },
makeWhitebox( QuasiquoteClass_api_apply) { case _ => _.expandQuasiquote },
@@ -0,0 +1,26 @@
package scala.tools.reflect
import scala.reflect.macros.runtime.Context
trait SingleInhabitantMacro { self: FormatInterpolator =>
val c: Context
import c.universe._
def materialize(tpe: Type): Tree = {
val value = tpe match {
case ConstantType(const) => Literal(const)
case SingleType(pre, sym) => Select(TypeTree(pre), sym)
case _ =>
c.abort(c.enclosingPosition, tpe + " is not a singleton type!")
}
Apply(
TypeApply(
Select(reify(SingleInhabitant).tree, newTermName("apply")),
TypeTree(tpe) :: Nil
),
value :: Nil
)
}
}
@@ -125,6 +125,8 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef {
// @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0")
def optManifest[T](implicit m: OptManifest[T]) = m
def inhabitant[A](implicit h: SingleInhabitant[A]) = h.a
// Minor variations on identity functions
def identity[A](x: A): A = x // @see `conforms` for the implicit version
@inline def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world -- TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero`
@@ -0,0 +1,18 @@
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala
import scala.language.experimental.macros
case class SingleInhabitant[A](a: A)
object SingleInhabitant {
implicit def witness[A]: SingleInhabitant[A] = macro ???
}
@@ -502,6 +502,8 @@ trait Definitions extends api.StandardDefinitions {
lazy val StringContextClass = requiredClass[scala.StringContext]
lazy val SingleInhabitantModule = requiredModule[scala.SingleInhabitant.type]
// SI-8392 a reflection universe on classpath may not have
// quasiquotes, if e.g. crosstyping with -Xsource on
lazy val QuasiquoteClass = if (ApiUniverseClass != NoSymbol) getMemberIfDefined(ApiUniverseClass, tpnme.Quasiquote) else NoSymbol
@@ -1403,6 +1405,8 @@ trait Definitions extends api.StandardDefinitions {
lazy val StringContext_f = getMemberMethod(StringContextClass, nme.f)
lazy val SingleInhabitant_witness = getMemberMethod(SingleInhabitantModule, nme.witness)
lazy val ArrowAssocClass = getMemberClass(PredefModule, TypeName("ArrowAssoc")) // SI-5731
def isArrowAssoc(sym: Symbol) = sym.owner == ArrowAssocClass
@@ -807,6 +807,7 @@ trait StdNames {
val values : NameType = "values"
val wait_ : NameType = "wait"
val withFilter: NameType = "withFilter"
val witness: NameType = "witness"
val zero: NameType = "zero"
// quasiquote interpolators:
@@ -1,2 +1,3 @@
2
(2,0,1)
Residue(9)
@@ -44,10 +44,17 @@ object Test {
def f[T](x: T)(implicit succ: Succ[T]) = succ(x)
case class Residue[N <: Int : SingleInhabitant](n: Long) { lhs =>
def +(rhs: Residue[N]): Residue[N] =
Residue((lhs.n + rhs.n) % inhabitant[N])
}
def main(args: Array[String]): Unit = {
println(f(1))
// println(f(5))
println((g(1), g(5), g(7)))
println(Residue[13.type](15) + Residue[13.type](20))
}
/*
scala> val x: null.type = null

0 comments on commit 094883e

Please sign in to comment.