Skip to content

Instantly share code, notes, and snippets.

@xeno-by
Created January 4, 2014 07:09
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/8252596 to your computer and use it in GitHub Desktop.
Save xeno-by/8252596 to your computer and use it in GitHub Desktop.
import scala.reflect.macros.WhiteboxContext
import scala.language.experimental.macros
object Macros {
def impl[T](c: WhiteboxContext)(implicit T: c.WeakTypeTag[T]) = {
import c.universe._
val allMeths = T.tpe.declarations.collect { case m: MethodSymbol => m }
val goodMeths = allMeths.filter(m => m.isPublic && !m.isConstructor && !m.isSynthetic)
val defDefs = goodMeths.map(m => {
def toMods(sym: Symbol) =
// TODO: not sure what to do with annotations and privateWithin
Modifiers(sym.asInstanceOf[scala.reflect.internal.Symbols#Symbol].flags.asInstanceOf[FlagSet])
def toTypeDef(sym: TypeSymbol): TypeDef =
TypeDef(toMods(sym), sym.name.toTypeName, sym.typeParams.map(t => toTypeDef(t.asType)), EmptyTree)
def toValDef(sym: TermSymbol): ValDef =
// TODO: need to do better than sym.tpe, otherwise owner's tparams will remain unresolved
// TODO: uh-oh, we can't just use typeSignature, because we need to rebind type and value parameters...
// TODO: not sure how to reproduce the default value
ValDef(toMods(sym), sym.name.toTermName, TypeTree(sym.typeSignature), EmptyTree)
val typeParams = m.typeParams.map(t => toTypeDef(t.asType))
val paramss = m.paramss.map(_.map(v => toValDef(v.asTerm)))
val returns = TypeTree(m.returnType)
q"def ${m.name.toTermName}[..$typeParams](...$paramss): ${m.returnType} = ???"
})
q"new { ..$defDefs }"
}
def proxy[T]: Any = macro impl[T]
}
=======
object Test extends App {
class C(x: Int) { def foo[T](x: T)(y: T): Int = ??? }
Macros.proxy[C]
}
=======
10:08 ~/Projects/Master/sandbox (master)$ sst -uniqid
Test.scala:3: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
Macros.proxy[C]
^
[[syntax trees at end of typer]] // Test.scala
package <empty>#4 {
object Test#7833 extends AnyRef#2745 with App#681 {
def <init>#7937(): Test#7834.type = {
Test#7834.super.<init>#3097();
()
};
class C#7938 extends scala#24.AnyRef#2745 {
<paramaccessor> private[this] val x#14905: Int#1836 = _;
def <init>#14906(x#15174: Int#1836): Test#7834.C#7938 = {
C#7938.super.<init>#3097();
()
};
def foo#14907[T#14908](x#15175: T#14909)(y#15176: T#14909): Int#1836 = scala#25.this.Predef#2068.???#7451
};
{
final class $anon#15345 extends scala#24.AnyRef#2745 {
def <init>#15346(): <$anon: AnyRef#2745> = {
$anon#15345.super.<init>#3097();
()
};
def foo#15347[T#15348](x#15350: T#14908)(y#15351: T#14908): Int#1836 = scala#25.this.Predef#2068.???#7451
};
new $anon#15345()
}
}
}
one error found
@xeno-by
Copy link
Author

xeno-by commented Jan 4, 2014

Please don't comment here, because I don't get notifications about gist comments. Use http://stackoverflow.com/questions/20908036/how-do-i-splice-symbols-of-various-types-in-a-quasiquote instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment