Created
February 21, 2013 09:21
-
-
Save Mononofu/5003436 to your computer and use it in GitHub Desktop.
Fails to compile with: /home/mononofu/tmp/minimal/minimal.scala:7: erroneous or inaccessible type
[error] def plus(x: Measure[T],y: Measure[T]): Measure[T] = x + y
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
scalaVersion in ThisBuild := "2.10.0" | |
scalacOptions in ThisBuild += "-language:experimental.macros" | |
libraryDependencies in ThisBuild ++= Seq( | |
"org.scala-lang" % "scala-reflect" % "2.10.0" | |
) |
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 language.experimental.macros | |
import scala.reflect.macros.Context | |
import collection.mutable.ListBuffer | |
import scala.reflect.runtime.universe.{WeakTypeTag, TypeRef, TypeTag} | |
class MyNumeric[T] extends Numeric[Measure[T]] { | |
def plus(x: Measure[T],y: Measure[T]): Measure[T] = x + y | |
} | |
class Measure[T](val n: Int) extends AnyVal { | |
def +[U](that: Measure[U])(implicit tag: WeakTypeTag[T], tag2: WeakTypeTag[U]) = | |
macro MeasureImpl.addition_impl[T, U] | |
} | |
object MeasureImpl { | |
def precompute(c: Context)(a: c.Tree, b: c.Tree) = { | |
import c.universe._ | |
val evals = ListBuffer[ValDef]() | |
def _precompute(value: Tree, tpe: Type): Ident = { | |
val freshName = newTermName(c.fresh("eval$")) | |
evals += ValDef(Modifiers(), freshName, TypeTree(tpe), value) | |
Ident(freshName) | |
} | |
val aID = _precompute(a, typeOf[Measure[_]]) | |
val bID = _precompute(b, typeOf[Measure[_]]) | |
(evals, aID, bID) | |
} | |
def addition_impl[T: c.WeakTypeTag, U: c.WeakTypeTag] | |
(c: Context) | |
(that: c.Expr[Measure[U]]) | |
(tag: c.Expr[WeakTypeTag[T]], tag2: c.Expr[WeakTypeTag[U]]): c.Expr[Any] = { | |
import c.universe._ | |
val resultType = c.universe.AppliedTypeTree( | |
c.universe.Ident(c.universe.newTypeName("SUnit")), | |
List(c.universe.Ident(c.universe.newTypeName("Meter")), | |
c.universe.Ident(c.universe.newTypeName("Pos1")))) | |
val (evals, aID, bID) = precompute(c)(that.tree, c.prefix.tree) | |
val stats = Apply(Select(New(AppliedTypeTree( | |
Ident(newTypeName("Measure")), | |
List( resultType ) | |
)), nme.CONSTRUCTOR), | |
List(Apply(Select( | |
Select( | |
Ident(newTermName(aID.toString)), | |
newTermName("n")), | |
newTermName("$plus")), | |
List( | |
Select( | |
Ident(newTermName(bID.toString)), | |
newTermName("n")))))) | |
c.Expr(Block(evals.toList, stats)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment