Skip to content

Commit ae47ccc

Browse files
committed
Merge pull request scala#3016 from xeno-by/topic/vampires
[master] assorted fixes for vampire macros
2 parents 686fb48 + b747209 commit ae47ccc

File tree

5 files changed

+62
-1
lines changed

5 files changed

+62
-1
lines changed

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4747,7 +4747,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
47474747
def sym = tree1.symbol
47484748
if (tree.isInstanceOf[PostfixSelect])
47494749
checkFeature(tree.pos, PostfixOpsFeature, name.decode)
4750-
if (sym != null && sym.isOnlyRefinementMember)
4750+
if (sym != null && sym.isOnlyRefinementMember && !sym.isMacro)
47514751
checkFeature(tree1.pos, ReflectiveCallsFeature, sym.toString)
47524752

47534753
qualStableOrError.symbol match {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2
2+
3
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Xfatal-warnings
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// As per http://meta.plasm.us/posts/2013/08/31/feeding-our-vampires/
2+
3+
import scala.annotation.StaticAnnotation
4+
import scala.reflect.macros.Context
5+
import scala.language.experimental.macros
6+
7+
class body(tree: Any) extends StaticAnnotation
8+
9+
object Macros {
10+
def selFieldImpl(c: Context) = {
11+
import c.universe._
12+
val field = c.macroApplication.symbol
13+
val bodyAnn = field.annotations.filter(_.tpe <:< typeOf[body]).head
14+
c.Expr[Any](bodyAnn.scalaArgs.head)
15+
}
16+
17+
def mkObjectImpl(c: Context)(xs: c.Expr[Any]*) = {
18+
import c.universe._
19+
import Flag._
20+
// val kvps = xs.toList map { case q"${_}(${Literal(Constant(name: String))}).->[${_}]($value)" => name -> value }
21+
val kvps = xs.map(_.tree).toList map { case Apply(TypeApply(Select(Apply(_, List(Literal(Constant(name: String)))), _), _), List(value)) => name -> value }
22+
// val fields = kvps map { case (k, v) => q"@body($v) def ${TermName(k)} = macro Macros.selFieldImpl" }
23+
val fields = kvps map { case (k, v) => DefDef(
24+
Modifiers(MACRO, tpnme.EMPTY, List(Apply(Select(New(Ident(TypeName("body"))), nme.CONSTRUCTOR), List(v)))),
25+
TermName(k), Nil, Nil, TypeTree(), Select(Ident(TermName("Macros")), TermName("selFieldImpl"))) }
26+
// q"import scala.language.experimental.macros; class Workaround { ..$fields }; new Workaround{}"
27+
c.Expr[Any](Block(
28+
List(
29+
Import(Select(Select(Ident(TermName("scala")), TermName("language")), TermName("experimental")), List(ImportSelector(TermName("macros"), 51, TermName("macros"), 51))),
30+
ClassDef(
31+
NoMods, TypeName("Workaround"), Nil,
32+
Template(
33+
List(Select(Ident(TermName("scala")), TypeName("AnyRef"))), noSelfType,
34+
DefDef(
35+
NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(),
36+
Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(()))))
37+
+: fields)),
38+
ClassDef(
39+
Modifiers(FINAL), TypeName("$anon"), Nil,
40+
Template(
41+
List(Ident(TypeName("Workaround"))), noSelfType,
42+
List(
43+
DefDef(
44+
NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(),
45+
Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))))))),
46+
Apply(Select(New(Ident(TypeName("$anon"))), nme.CONSTRUCTOR), List())))
47+
}
48+
}
49+
50+
object mkObject {
51+
def apply(xs: Any*) = macro Macros.mkObjectImpl
52+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object Test extends App {
2+
val foo = mkObject("x" -> "2", "y" -> 3)
3+
println(foo.x)
4+
println(foo.y)
5+
// println(foo.z) => will result in a compilation error
6+
}

0 commit comments

Comments
 (0)