Skip to content

Instantly share code, notes, and snippets.

@Mononofu
Created February 21, 2013 09:21
Show Gist options
  • Save Mononofu/5003436 to your computer and use it in GitHub Desktop.
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
scalaVersion in ThisBuild := "2.10.0"
scalacOptions in ThisBuild += "-language:experimental.macros"
libraryDependencies in ThisBuild ++= Seq(
"org.scala-lang" % "scala-reflect" % "2.10.0"
)
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