私はテンプレートプラグインを作成したいと思います。最初のステップとして任意の文字列を "コンパイル済み" AST表現に変換します(scalaインタプリタのように)。だから、コンパイラプラグインは、例えば「HELLO WORLD」にsomeStringを割り当てることができます:CompilerPlugin内のASTとの文字列をコンパイルしますか?
@StringAnnotation("""("hello world").toString.toUpperCase""")
var someString = ""
私の現在の第1ショットプラグインが短い中で行います。
- runafterパーサ
- 新しい表現のみコンパイラとVirtualFileを作成します注釈内容と
- コンパイルおよび印刷unit.body
を参照してください:現在、"object o{val x = 0}"
はASTを返します。たとえば、ASTを返します。たとえば、"object o{val x = 0}"
は、ASTを返します。たとえば、ASTを返します。たとえば、"object o{val x = 0}"
は、ASTを返します。 "var x = 1+ 2"
は有効な.scalaファイルではないため、表示されません。これをどうすれば解決できますか?
b) 唯一のプレゼンテーションはいいですか?代わりに適切なフェーズでcomputeInternalPhasesをオーバーライドするか、-Ystop:phaseを使用する必要がありますか?
c)のように、例えば が、それは、内側の一つに、外側のコンパイラの環境をバインドすることが可能です
var x = _
(...)
@StringAnnotation("x += 3")
?
私は、[1]と同様の何かをするインタプリタと一つの変数を使用して、次のコードを見つけました:
Interpreter interpreter = new Interpreter(settings);
String[] context = { "FOO" };
interpreter.bind("context", "Array[String]", context);
interpreter
.interpret("de.tutorials.scala2.Test.main(context)");
context[0] = "BAR";
interpreter
.interpret("de.tutorials.scala2.Test.main(context)");
おかげ
完全なコード:
class AnnotationsPI(val global: Global) extends Plugin {
import global._
val name = "a_plugins::AnnotationsPI" //a_ to run before namer
val description = "AST Trans PI"
val components = List[PluginComponent](Component)
private object Component extends PluginComponent with Transform with TypingTransformers with TreeDSL {
val global: AnnotationsPI.this.global.type = AnnotationsPI.this.global
val runsAfter = List[String]("parser");
val phaseName = AnnotationsPI.this.name
def newTransformer(unit: CompilationUnit) = {
new AnnotationsTransformer(unit)
}
val SaTpe = "StringAnnotation".toTypeName
class AnnotationsTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
/** When using <code>preTransform</code>, each node is
* visited before its children.
*/
def preTransform(tree: Tree): Tree = tree match {
case [email protected](Modifiers(_, _, List(Apply(Select(New(Ident(SaTpe)), _), List(Literal(Constant(a))))), _), b, c, d) => //Apply(Select(New(Ident(SaTpe)), /*nme.CONSTRUCTOR*/_), /*List(x)*/x)
val str = a.toString
val strArr = str.getBytes("UTF-8")
import scala.tools.nsc.{ Global, Settings, SubComponent }
import scala.tools.nsc.reporters.{ ConsoleReporter, Reporter }
val settings = new Settings()
val compiler = new Global(settings, new ConsoleReporter(settings)) {
override def onlyPresentation = true
}
val run = new compiler.Run
val vfName = "Script.scala"
var vfile = new scala.tools.nsc.io.VirtualFile(vfName)
val os = vfile.output
os.write(strArr, 0, str.size) // void write(byte[] b, int off, int len)
os.close
new scala.tools.nsc.util.BatchSourceFile(vfName, str)
run.compileFiles(vfile :: Nil)
for (unit <- run.units) {
println("Unit: " + unit)
println("Body:\n" + unit.body)
}
tree
case _ =>
tree
}
override def transform(tree: Tree): Tree = {
super.transform(preTransform(tree))
}
}
}