मैं एक टेम्पलेटिंग प्लगइन बनाना चाहता हूं और जैसा कि पहला चरण एक "मनोनीत" एएसटी प्रतिनिधित्व (जैसा स्केल दुभाषिया करता है, मुझे लगता है) के लिए एक मनमानी स्ट्रिंग को परिवर्तित करता है। तो एक संकलक प्लगइन जैसे आवंटित कर सकते हैं someString को "नमस्ते दुनिया":कंपाइलर प्लगइन के अंदर एएसटी में स्ट्रिंग स्ट्रिंग?
- runafter पार्सर
- केवल संकलक और एक VirtualFile एक नया प्रतिनिधित्व बनाएँ:
@StringAnnotation("""("hello world").toString.toUpperCase""") var someString = ""
मेरे वर्तमान पहला शॉट प्लगइन संक्षेप में करता है एनोटेशन सामग्री के साथ
- संकलन और प्रिंट unit.body
देखें: 0,123,
ए) अभी, "object o{val x = 0}"
एक एएसटी देता है, लेकिन उदा। "var x = 1+ 2"
ऐसा इसलिए नहीं है क्योंकि यह वैध .scala फ़ाइल नहीं होगी। मैं इसे कैसे ठीक करूं?
बी) केवल प्रतिनिधित्व एक अच्छा विकल्प है? क्या मुझे इसके बजाय उचित चरणों या उपयोग के साथ गणना इंटरफेस को ओवरराइड करना चाहिए -स्टॉप: चरण?
सी) क्या आंतरिक कंपाइलर के वातावरण को आंतरिक में बांधना संभव है, उदाहरण के लिए
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))
}
}
}