Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala宏获取术语名称的值_Scala_Scala Macros - Fatal编程技术网

Scala宏获取术语名称的值

Scala宏获取术语名称的值,scala,scala-macros,Scala,Scala Macros,我有以下代码: scala的用法 scala宏 它返回: ExprSelectThisnewTypeNameTest,newTermNamef 如何从termNamef中提取1值? 一般来说,使用宏是可能的——f可以是抽象的,也可以定义为外部调用、用户输入、随机或其他许多情况之一 但在某些特殊情况下,你可以得到它。你几乎知道所有编译器知道的 请看c.enclosingClass: 这里有趣的部分是ValDefModifiers、newTermNamef、TypeTree、LiteralConst

我有以下代码:

scala的用法 scala宏 它返回:

ExprSelectThisnewTypeNameTest,newTermNamef

如何从termNamef中提取1值? 一般来说,使用宏是可能的——f可以是抽象的,也可以定义为外部调用、用户输入、随机或其他许多情况之一

但在某些特殊情况下,你可以得到它。你几乎知道所有编译器知道的

请看c.enclosingClass:

这里有趣的部分是ValDefModifiers、newTermNamef、TypeTree、LiteralConstant1

我们必须提取它:

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值


我很确定这不是您所期望的。

例如,如果您的val f=1+0或val g=1;val f=g,你已经出局了。如果您想捕获所有类型的其他情况,您的启发式算法将爆炸。@0\uuuo:我猜OP想从编译器api中获得一些可以称为常量预测器的内容。如果封闭类是匿名函数,该怎么办?
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 "), TypeTree(), Literal(Constant(1))), Apply(Select(Ident(newTermName("Macros")), newTermName("get")), List(Ident(newTermName("f")))))))
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