[SCALA] (의 AST를 얻을) 스칼라에서 식을 구체화 사용하는 가장 쉬운 방법은 무엇입니까?
SCALA(의 AST를 얻을) 스칼라에서 식을 구체화 사용하는 가장 쉬운 방법은 무엇입니까?
나는 컴파일러는 스칼라에서 무엇을하고 있는지 파악하는 방법으로 -print 또는은 javap에 대한 대안을 찾고 있어요. retronym의 대우주의 desugar 같이 새로운 반사 / 매크로 라이브러리로, 구체화, 그것을위한 좋은 후보를 보인다. 하나는, 사전 M4를 그렇게 사용하는 방법이도 보여줍니다.
질문은 그래서, 내가 스칼라의 REPL에 입력 할 수 있습니다 짧은 / 쉬운 일이 후 스칼라 2.10.0-M4 식의 AST를 얻기 위해 무엇인가?
해결법
-
==============================
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.새로운 스칼라 버전의 개선이
새로운 스칼라 버전의 개선이
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)
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
'SCALA' 카테고리의 다른 글
[SCALA] 스칼라의 경우 클래스 상속 (0) | 2019.11.08 |
---|---|
[SCALA] 어떻게 SBT에 대한 힙 크기를 설정하는 방법? (0) | 2019.11.08 |
[SCALA] 스칼라에서 "새로운"키워드 (0) | 2019.11.08 |
[SCALA] 스칼라 모음으로 자바 컬렉션을 변환 (0) | 2019.11.08 |
[SCALA] 선물과 스칼라의 "에 대한 이해" (0) | 2019.11.08 |