Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.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_Macros - Fatal编程技术网

Scala 需要宏取消类型检查

Scala 需要宏取消类型检查,scala,macros,Scala,Macros,我在使用宏生成代码的开源项目中遇到了问题。如果我使用c.untypecheck,一切都很好,但理想情况下,我不想这样做 以下是相关代码: 如果删除c.untypecheck,则会出现以下编译时错误: [error] (reactifyJVM/test:compileIncremental) java.lang.AssertionError: assertion failed: [error] transformCaseApply: name = previousVal tree = pre

我在使用宏生成代码的开源项目中遇到了问题。如果我使用
c.untypecheck
,一切都很好,但理想情况下,我不想这样做

以下是相关代码:

如果删除
c.untypecheck
,则会出现以下编译时错误:

[error] (reactifyJVM/test:compileIncremental) java.lang.AssertionError: assertion failed: 
[error]   transformCaseApply: name = previousVal tree = previousVal / class scala.reflect.internal.Trees$Ident
[error]      while compiling: /home/mhicks/projects/open-source/reactify/shared/src/test/scala/specs/BasicSpec.scala
[error]         during phase: refchecks
[error]      library version: version 2.12.1
[error]     compiler version: version 2.12.1
[error]   reconstructed args: -classpath /home/mhicks/projects/open-source/reactify/jvm/target/scala-2.12/test-classes:/home/mhicks/projects/open-source/reactify/jvm/target/scala-2.12/classes:/home/mhicks/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.12.1.jar:/home/mhicks/.ivy2/cache/org.scalatest/scalatest_2.12/bundles/scalatest_2.12-3.0.1.jar:/home/mhicks/.ivy2/cache/org.scalactic/scalactic_2.12/bundles/scalactic_2.12-3.0.1.jar:/home/mhicks/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12/bundles/scala-xml_2.12-1.0.5.jar:/home/mhicks/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.12/bundles/scala-parser-combinators_2.12-1.0.4.jar -bootclasspath /usr/java/jdk1.8.0_92/jre/lib/resources.jar:/usr/java/jdk1.8.0_92/jre/lib/rt.jar:/usr/java/jdk1.8.0_92/jre/lib/sunrsasign.jar:/usr/java/jdk1.8.0_92/jre/lib/jsse.jar:/usr/java/jdk1.8.0_92/jre/lib/jce.jar:/usr/java/jdk1.8.0_92/jre/lib/charsets.jar:/usr/java/jdk1.8.0_92/jre/lib/jfr.jar:/usr/java/jdk1.8.0_92/jre/classes:/home/mhicks/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.12.1.jar
[error] 
[error]   last tree to typer: TypeTree(class Position)
[error]        tree position: line 148 of /home/mhicks/projects/open-source/reactify/shared/src/test/scala/specs/BasicSpec.scala
[error]             tree tpe: org.scalactic.source.Position
[error]               symbol: case class Position in package source
[error]    symbol definition: case class Position extends Product with Serializable (a ClassSymbol)
[error]       symbol package: org.scalactic.source
[error]        symbol owners: class Position
[error]            call site: <$anon: com.outr.reactify.ChangeListener[Int]> in package specs
[error] 
[error] == Source file context for tree position ==
[error] 
[error]    145       current should be(15)
[error]    146     }
[error]    147     "observe a complex change" in {
[error]    148       val v1 = Var(5)
[error]    149       val v2 = Var(10)
[error]    150       val v3 = Var(v1 + v2)
[error]    151       var changed = 0
[error] Total time: 1 s, completed Jan 31, 2017 4:43:03 PM
[错误](reactifyJVM/test:compileIncremental)java.lang.AssertionError:断言失败:
[错误]transformCaseApply:name=previousVal tree=previousVal/class scala.reflect.internal.Trees$Ident
编译时发生[错误]:home/mhicks/projects/open-source/reactify/shared/src/test/scala/specs/basicsec.scala
阶段期间[错误]:参考检查
[错误]库版本:版本2.12.1
[错误]编译器版本:版本2.12.1
[错误]重构参数:-类路径/home/mhicks/projects/open-source/reactify/jvm/target/scala-2.12/test classes:/home/mhicks/projects/reactify/jvm/target/scala-2.12/classes:/home/mhicks/.ivy2/cache/org.scala lang/scala reflect/jars/scala-reflect-2.12.1.jar:/home/mhicks/.ivy2/cache/org.scalatest/scalatest/scalatest\u 2.12/3.0.1.1.jar:/home/icks/或ivy2/g、 scalactic/scalactic_2.12/bundles/scalactic_2.12-3.0.1.jar:/home/mhicks/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12/bundles/scala-xml_2.12-1.0.5.jar:/home/mhicks/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.12/bundles/scala-parser-combinators_2.12-1.0.4.jar-类路径/1/7/java/jdk1.8/java/java/JDK11.8.8/java/java/JDK11.8.8.9 9 9/9 9 9/JJ9/9 9 9/jre///////java/java/JDK11.8.8.8.8.8.8.8.8.1/1/java/java/java/java/java/JDK11.8.8.8.8.8.8.8.8.0 0 0/9/9 9 9 9 9/9 9 9 9 9///////J9 9 9 9 9 9/////////9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9/J荣荣9////////////////////////////////////////////////J荣荣荣荣荣荣9 9 9 8.0_92/jre/classes:/home/mhicks/.ivy2/cache/org.scalalang/scala-library/jars/scala-library-2.12.1.jar
[错误]
[错误]打字机的最后一棵树:TypeTree(类位置)
[错误]树位置:第148行/home/mhicks/projects/open-source/reactify/shared/src/test/scala/specs/basicsec.scala
[错误]树tpe:org.scalatic.source.Position
[错误]符号:包源中的案例类位置
[错误]符号定义:案例类位置使用可序列化(类符号)扩展产品
[错误]符号包:org.scalactic.source
[错误]符号所有者:类位置
[错误]调用站点:在程序包规范中
[错误]
[错误]==树位置的源文件上下文==
[错误]
[错误]145电流应为(15)
[错误]146}
[错误]147“观察复杂的变化”{
[错误]148 val v1=Var(5)
[错误]149 val v2=Var(10)
[错误]150 val v3=Var(v1+v2)
[错误]151变量已更改=0
[错误]总时间:1秒,已完成2017年1月31日下午4:43:03
如果我把它加回去,一切都可以编译并正常工作。在更复杂的用例中,我在编译时遇到了一些问题,
无法找到…
的代理,我想这可能就是原因


如果您有任何建议,我们将不胜感激。

您正在将非类型树引入到类型树中

输入树将进行类型检查,然后输出树(宏发出的)将再次进行类型检查,但打字机不会下降到已进行类型检查的树(即,已为其指定类型的树)中

因为要引入新符号,所以不能仅使用传入的上下文来检查引用

因此,最简单的解决方案是,取消对传出树的类型检查。取消对
转换后的
树的类型检查也就足够了,这样打字机就可以下降到新的非类型树

我不得不通过注释代码来减少爆炸性测试。不幸的是,现在还不清楚是什么源代码行导致了错误。如果您熟悉所涉及的宏,可能更明显

class Sample {
  def sample(): Unit = {
    val v = Var(5)
    v := v + 5
  }
}
正在讨论的树,来自
-Xprint:typer-Yshow trees

            Apply( // def +(x: Int): Int in class Int, tree.tpe=Int
              com.outr.reactify.`package`.state2Value[Int](previousVal)."$plus" // def +(x: Int): Int in class Int, tree.tpe=(x: Int)Int
              5
            )
还值得一提的是,在错误消息中使用“重构的参数”编写快速编译脚本更容易,从而消除sbt增量编译、ScalaTest宏和其他谜团

编辑,手动设置的API:

def setStateChannel(value: c.Tree): c.Tree = {
  val observables = retrieveObservables(c)(value)
  val channel = c.prefix.tree
  val selfReference = observables.exists(_.equalsStructure(channel))

  val untyped =
    q"""
      val previousValue = com.outr.reactify.State.internalFunction($channel)
      val previousVal = com.outr.reactify.Val(previousValue())
    """
  val retyped = c.typecheck(untyped)
  val transformed = if (selfReference) {
    val transformer = new Transformer {
      override def transform(tree: c.universe.Tree): c.universe.Tree = if (tree.equalsStructure(channel)) {
        val t = q"previousVal"
        val Block(_ :: v :: Nil, _) = retyped
        c.internal.setSymbol(t, v.symbol)
        c.internal.setType(t, v.tpe)
      } else {
        super.transform(tree)
      }
    }
    transformer.transform(value)
  } else {
    value
  }
  val res = q"$channel.update(List(..$observables), $transformed)"
  q"$retyped ; $res"
}

您正在将非类型化树引入类型化树

输入树将进行类型检查,然后输出树(宏发出的)将再次进行类型检查,但打字机不会下降到已进行类型检查的树(即,已为其指定类型的树)中

因为要引入新符号,所以不能仅使用传入的上下文来检查引用

因此,最简单的解决方案是,取消对传出树的类型检查。取消对
转换后的
树的类型检查也就足够了,这样打字机就可以下降到新的非类型树

我不得不通过注释代码来减少爆炸性测试。不幸的是,现在还不清楚是什么源代码行导致了错误。如果您熟悉所涉及的宏,可能更明显

class Sample {
  def sample(): Unit = {
    val v = Var(5)
    v := v + 5
  }
}
正在讨论的树,来自
-Xprint:typer-Yshow trees

            Apply( // def +(x: Int): Int in class Int, tree.tpe=Int
              com.outr.reactify.`package`.state2Value[Int](previousVal)."$plus" // def +(x: Int): Int in class Int, tree.tpe=(x: Int)Int
              5
            )
还值得一提的是,在错误消息中使用“重构的参数”编写快速编译脚本更容易,从而消除sbt增量编译、ScalaTest宏和其他谜团

编辑,手动设置的API:

def setStateChannel(value: c.Tree): c.Tree = {
  val observables = retrieveObservables(c)(value)
  val channel = c.prefix.tree
  val selfReference = observables.exists(_.equalsStructure(channel))

  val untyped =
    q"""
      val previousValue = com.outr.reactify.State.internalFunction($channel)
      val previousVal = com.outr.reactify.Val(previousValue())
    """
  val retyped = c.typecheck(untyped)
  val transformed = if (selfReference) {
    val transformer = new Transformer {
      override def transform(tree: c.universe.Tree): c.universe.Tree = if (tree.equalsStructure(channel)) {
        val t = q"previousVal"
        val Block(_ :: v :: Nil, _) = retyped
        c.internal.setSymbol(t, v.symbol)
        c.internal.setType(t, v.tpe)
      } else {
        super.transform(tree)
      }
    }
    transformer.transform(value)
  } else {
    value
  }
  val res = q"$channel.update(List(..$observables), $transformed)"
  q"$retyped ; $res"
}

我很感谢您的反馈,但我有点不确定这将如何使我更接近解决方案。我知道它是在
previousVal
上爆炸的,我的问题是如何在不使用非类型树的情况下解决这个问题。
previousVal
的目的是避免递归自调用,因为
:=
采用了onymous函数,因此
v+5
将创建一个递归场景。
previousVal
在赋值时获取该值,并将其存储为s