Skip to content

Instantly share code, notes, and snippets.

@kmizu
Created December 12, 2019 16:34
Show Gist options
  • Save kmizu/b78ee4221ebd3478e3854223a7565afa to your computer and use it in GitHub Desktop.
Save kmizu/b78ee4221ebd3478e3854223a7565afa to your computer and use it in GitHub Desktop.
A macro that reverse String
import scala.reflect.macros.whitebox.Context
import scala.language.experimental.macros
object Macros {
// 文字列をコンパイル時に反転させるマクロ
def reverse(str: String): String = macro reverseImpl
// マクロの実装
def reverseImpl(c: Context)(str: c.Expr[String]) : c.Expr[String] = {
import c.universe._
val Literal(Constant(s:String)) = str.tree
c.Expr[String](Literal(Constant(s.reverse)))
}
}
[mizushima]$ scalac Macros.scala
~/work
[mizushima]$ scalac Usage.scala
~/work
[mizushima]$ javap -c Usage$
Compiled from "Usage.scala"
public final class Usage$ {
public static final Usage$ MODULE$;
public static {};
Code:
0: new #2 // class Usage$
3: dup
4: invokespecial #12 // Method "<init>":()V
7: putstatic #14 // Field MODULE$:LUsage$;
10: return
public void main(java.lang.String[]);
Code:
0: getstatic #22 // Field scala/Predef$.MODULE$:Lscala/Predef$;
3: ldc #24 // String OOF // <-- コンパイル時に、文字列がreverseされている
5: invokevirtual #28 // Method scala/Predef$.println:(Ljava/lang/Object;)V
8: return
}
object Usage {
// Scalaのマクロは、呼び出し側を別コンパイル単位にする必要があるため
def main(args: Array[String]): Unit = {
println(Macros.reverse("FOO"))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment