Scala Macro获得术语名称的值
发布时间:2020-12-16 18:38:40 所属栏目:安全 来源:网络整理
导读:我有以下代码: usage.scala object Test extends App { import Macros._ val f = 1 Macros.get(f) } macros.scala import language.experimental.macrosimport scala.reflect.macros.Contextobject Macros { def get(a: Int) = macro getImpl def getImpl(c
我有以下代码:
usage.scala object Test extends App { import Macros._ val f = 1 Macros.get(f) } macros.scala import language.experimental.macros import scala.reflect.macros.Context object Macros { def get(a: Int) = macro getImpl def getImpl(c: Context)(a: c.Expr[Int]) = { import c.universe._ println(showRaw(a)) } } 它返回: Expr(选择(This(newTypeName(“Test”)),newTermName(“f”))) 如何从termName(“f”)中提取1值? 解决方法
一般来说 – 没有. f可以是抽象的或定义为外部呼叫或用户输入或随机或许多其他情况之一.
但在某些特殊情况下,你可以得到它.你知道几乎所有的编译器都知道! 看一下c.enclosingClass: object Macros { def get(a: Int) = macro getImpl def getImpl(c: Context)(a: c.Expr[Int]) = { import c.universe._ println(showRaw(c.enclosingClass)) c.Expr[Unit](Literal(Constant(()))) } } object Test { val f = 1; Macros.get(f) } // ModuleDef(Modifiers(),$line55.$read.$iw.$iw.$iw.$iw.Test,Template(List(Select(Ident(scala),newTypeName("AnyRef"))),emptyValDef,List(DefDef(Modifiers(),nme.CONSTRUCTOR,List(),List(List()),TypeTree(),Block(List(Apply(Select(Super(This(newTypeName("Test")),tpnme.EMPTY),nme.CONSTRUCTOR),List())),Literal(Constant(())))),ValDef(Modifiers(),newTermName("f "),Literal(Constant(1))),Apply(Select(Ident(newTermName("Macros")),newTermName("get")),List(Ident(newTermName("f"))))))) 这里有趣的部分是ValDef(Modifiers(),newTermName(“f”),Literal(Constant(1))). 我们必须提取它: object Macros { def get(a: Int) = macro getImpl def getImpl(c: Context)(a: c.Expr[Int]) = { import c.universe._ val (enclosing,name) = a.tree match { case Select(This(enclosing),name) => enclosing -> name case _ => c.abort(c.enclosingPosition,"Not a `this` memver") } val impl = c.enclosingClass match { case impl: ImplDef if impl.name.toString == enclosing.toString => impl case impl: ImplDef => c.abort(c.enclosingPosition,"Should search in another parent") case _ => c.abort(c.enclosingPosition,"Not an `ImplDef`") } val body = impl.children.collect{ case Template(_,_,body) => body } match { case Seq(body) => body case _ => c.abort(c.enclosingPosition,"Should be a single template.") } val rhss = body.collect{ case ValDef(_,valName,rhs) if valName.toString == name.toString => rhs } val rhs = rhss match { case Seq(rhs) => rhs case Seq() => c.abort(c.enclosingPosition,"Not found. Maybe it's a DefDef or somethong else") case _ => c.abort(c.enclosingPosition,"Some other error.") } val res = rhs match { case Literal(Constant(i: Int)) => i case Literal(Constant(_)) => c.abort(c.enclosingPosition,"Literal,but not an Int.") case _ => c.abort(c.enclosingPosition,"Implemented not as literal.") } println(s"Int value in this particular case: $res") c.Expr[Any](Literal(Constant(res))) } } 结果: object Test { val f = 1; Macros.get(f) } // Int value in this particular case: 1 所以我们在编译时有一个f的值. 我很确定这不是你的预期. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |