forked from scala/scala
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExpansion_Impossible_2.scala
53 lines (49 loc) · 1.79 KB
/
Expansion_Impossible_2.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import reflect.api.Modifier
import reflect.makro.Context
object Impls {
def foreach(c: Context)(f: c.Expr[Int => Unit]): c.Expr[Unit] = {
// todo. read the compiler config and print if -Ydebug is set
//println("macro-expand, _this = "+ _this)
object utils extends Utils { val context: c.type = c }
import utils._
import c.mirror._
val initName = newTermName("<init>")
// Either:
// scala"{ var i = $low; val h = $hi; while (i < h) { $f(i); i = i + 1 } }
// or:
// scala"($_this: RangeDefault).foreach($f)"
Expr(c.prefix.tree match {
case Apply(Select(New(tpt), initName), List(lo, hi)) if tpt.symbol.fullName == "Range" =>
val iname = newTermName("$i")
val hname = newTermName("$h")
def iref = Ident(iname)
def href = Ident(hname)
val labelname = newTermName("$while")
val cond = makeBinop(iref, "$less", href)
val body = Block(
List(makeApply(f.tree, List(iref))),
Assign(iref, makeBinop(iref, "$plus", Literal(Constant(1)))))
val generated =
Block(
List(
ValDef(Modifiers(Set(Modifier.mutable)), iname, TypeTree(), lo),
ValDef(Modifiers(), hname, TypeTree(), hi)),
makeWhile(labelname, cond, body))
// todo. read the compiler config and print if -Ydebug is set
//tools.nsc.util.trace("generated: ")(generated)
generated
case _ =>
Apply(
Select(
Typed(c.prefix.tree, Ident(newTypeName("RangeDefault"))),
newTermName("foreach")),
List(f.tree))
})
}
}
class Range(val from: Int, val to: Int) extends RangeDefault {
override def foreach(f: Int => Unit): Unit = macro Impls.foreach
}
object Test extends App {
new Range(1, 10) foreach println
}