2011-01-26 2 views
6

템플릿 플러그인을 만들고 첫 번째 단계에서 임의의 문자열을 "컴파일 된"AST 표현으로 변환하고 싶습니다. (스칼라 인터프리터는 그렇듯이). 그래서 컴파일러 플러그인 예를 들어 someString을 할당 할 수 있습니다에 "HELLO WORLD"CompilerPlugin에서 AST에 문자열을 컴파일 하시겠습니까?

  • runafter 파서
  • 는 컴파일러와 VirtualFile을 새로운 표현을 만들어 :

    @StringAnnotation("""("hello world").toString.toUpperCase""") 
        var someString = "" 
    

    나의 현재 첫 번째 촬영 플러그인은 짧은 않습니다 주석 함량이

  • 컴파일 및 인쇄 unit.body

참조 :예 : "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)"); 

[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

이것이 많은 도움이되는지는 모르겠지만 대신 fiddl 인터프리터를 사용하면 scala-refactoring 프로젝트 (http://scala-refactoring.org/)의 일부인 treeFrom (aString)을 사용할 수 있습니다. 그래도 교차 바인딩에 대한 질문에 대답하지 않습니다 ...

관련 문제