복붙노트

[SCALA] (의 AST를 얻을) 스칼라에서 식을 구체화 사용하는 가장 쉬운 방법은 무엇입니까?

SCALA

(의 AST를 얻을) 스칼라에서 식을 구체화 사용하는 가장 쉬운 방법은 무엇입니까?

나는 컴파일러는 스칼라에서 무엇을하고 있는지 파악하는 방법으로 -print 또는은 javap에 대한 대안을 찾고 있어요. retronym의 대우주의 desugar 같이 새로운 반사 / 매크로 라이브러리로, 구체화, 그것을위한 좋은 후보를 보인다. 하나는, 사전 M4를 그렇게 사용하는 방법이도 보여줍니다.

질문은 그래서, 내가 스칼라의 REPL에 입력 할 수 있습니다 짧은 / 쉬운 일이 후 스칼라 2.10.0-M4 식의 AST를 얻기 위해 무엇인가?

해결법

  1. ==============================

    1.이전에 패키지 scala.reflect.mirror에 정의 된 많은 것들이 scala.reflect.runtime.universe로 이동했다 :

    이전에 패키지 scala.reflect.mirror에 정의 된 많은 것들이 scala.reflect.runtime.universe로 이동했다 :

    scala> import scala.reflect.runtime.{universe => u}
    import scala.reflect.runtime.{universe=>u}
    
    scala> val expr = u reify { 1 to 3 map (_+1) }
    expr: reflect.runtime.universe.Expr[scala.collection.immutable.IndexedSeq[Int]] = Expr[scala.collection.immutable.IndexedSeq[Int]](scala.this.Predef.intWrapper(1).to(3).map(((x$1) => x$1.$plus(1)))(immutable.this.IndexedSeq.canBuildFrom))
    
    scala> u show expr.tree
    res57: String = scala.this.Predef.intWrapper(1).to(3).map(((x$1) => x$1.$plus(1)))(immutable.this.IndexedSeq.canBuildFrom)
    
    scala> u showRaw expr.tree
    res58: String = Apply(Apply(Select(Apply(Select(Apply(Select(Select(This(newTypeName("scala")), newTermName("Predef")), newTermName("intWrapper")), List(Literal(Constant(1)))), newTermName("to")), List(Literal(Constant(3)))), newTermName("map")), List(Function(List(ValDef(Modifiers(<param> <synthetic>), newTermName("x$1"), TypeTree(), EmptyTree)), Apply(Select(Ident(newTermName("x$1")), newTermName("$plus")), List(Literal(Constant(1))))))), List(Select(Select(This(newTypeName("immutable")), newTermName("IndexedSeq")), newTermName("canBuildFrom"))))
    

    더 나은 - - 또한 어떤 스칼라 코드가 포함 된 문자열이 유효한 스칼라 표현하고 있는지 확인 할 수 있습니다 어떤 평가를 수행

    편집하다. 2.10.0-RC1에서 도구 상자의 몇 가지 방법이 변경되었습니다. parseExpr은 구문 분석 현재, 그리고 runExpr 지금 평가라고합니다.

    scala> import scala.tools.reflect.ToolBox
    import scala.tools.reflect.ToolBox
    
    scala> import scala.reflect.runtime.{currentMirror => m}
    import scala.reflect.runtime.{currentMirror=>m}
    
    scala> val tb = m.mkToolBox()
    tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@9293709
    
    scala> val tree = tb.parse("1 to 3 map (_+1)")
    tree: tb.u.Tree = 1.to(3).map(((x$1) => x$1.$plus(1)))
    
    scala> val eval = tb.eval(tree)
    eval: Any = Vector(2, 3, 4)
    

    여기서 가장 복잡한 것은 표현의 원시 트리 표현이다. 하나는 매크로를 사용하고자하는 경우 showRaw 같이, 매크로는 같은 방법으로 정의 할 수있다. 그러나 일부 도우미 방법으로는 어떤 추한하지 찾고 매크로 구현을 정의 할 수 있습니다 :

    object IntMacro {
    
      import language.experimental.macros
      import scala.reflect.makro.Context
      import scala.reflect.NameTransformer.encode
    
      def isEven(i: Int): Boolean = macro isEvenImpl
    
      def isEvenImpl(c: Context)(i: c.Expr[Int]): c.Expr[Boolean] = {
        import c.universe._
        implicit val cc: c.type = c
    
        val `x = i%2` = Apply(Select(i.tree, op("%")), const(2))
        val `x == 0` = Apply(Select(`x = i%2`, op("==")), const(0))
    
        c.Expr(`x == 0`)
      }
    
      def op(s: String)(implicit c: Context): c.universe.TermName =
        c.universe.newTermName(encode(s))
    
      def const(a: Any)(implicit c: Context): List[c.universe.Literal] =
        List(c.universe.Literal(c.universe.Constant(a)))
    }
    
    scala> import IntMacro._
    import IntMacro._
    
    scala> isEven(2)
    res60: Boolean = true
    
    scala> isEven(3)
    res61: Boolean = false
    

    하지만 지금 우리는 경로 의존적-유형의 문제에 와서 - 우리는 우리가 그들을 가져 오지 원하는 경우 명시 적으로 경로를 작성해야합니다.

  2. ==============================

    2.새로운 스칼라 버전의 개선이

    새로운 스칼라 버전의 개선이

    scala> import scala.tools.reflect.ToolBox
    import scala.tools.reflect.ToolBox
    
    scala> import scala.reflect.runtime.{currentMirror => m}
    import scala.reflect.runtime.{currentMirror=>m}
    
    scala> val tb = m.mkToolBox()
    tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@78dc5f15
    
    scala> val tree = tb.parseExpr("1 to 3 map (_+1)")
    <console>:10: error: value parseExpr is not a member of scala.tools.reflect.ToolBox[reflect.runtime.universe.type]
           val tree = tb.parseExpr("1 to 3 map (_+1)")
                         ^
    
    scala> val tree = tb.parse("1 to 3 map (_+1)")
    tree: tb.u.Tree = 1.to(3).map(((x$1) => x$1.$plus(1)))
    
    scala> val eval = tb.eval(tree)
    eval: Any = Vector(2, 3, 4)
    
  3. from https://stackoverflow.com/questions/11055210/whats-the-easiest-way-to-use-reify-get-an-ast-of-an-expression-in-scala by cc-by-sa and MIT license