2011-01-26 5 views
6

मैं एक टेम्पलेटिंग प्लगइन बनाना चाहता हूं और जैसा कि पहला चरण एक "मनोनीत" एएसटी प्रतिनिधित्व (जैसा स्केल दुभाषिया करता है, मुझे लगता है) के लिए एक मनमानी स्ट्रिंग को परिवर्तित करता है। तो एक संकलक प्लगइन जैसे आवंटित कर सकते हैं 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)"); 

[1] http://www.tutorials.de/java/320639-beispiel-zur-einbindung-des-scala-interpreters-kompilierte-scala-anwendungen.html#post1653884

धन्यवाद

पूरा कोड:

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)) 
     } 
    } 
    } 

उत्तर

1

मुझे नहीं पता कि यह आपको बहुत मदद करता है, लेकिन फिडल की बजाय इंटरप्रेटर के साथ, आप पेड़ से (एस्ट्रिंग) का उपयोग कर सकते हैं जो स्कैला-रिफैक्टरिंग प्रोजेक्ट (http://scala-refactoring.org/) का हिस्सा है। क्रॉस-बाइंडिंग के बारे में आपके प्रश्न का उत्तर नहीं देता है, हालांकि ...