在具体化调用中搜索隐式(scala宏)

在具体化调用中搜索隐式(scala宏),scala,implicit,scala-macros,type-level-computation,Scala,Implicit,Scala Macros,Type Level Computation,我需要在给定位置搜索隐式值。我保留了以前在类中调用宏时的位置,如下所示: 类延迟[+Kind[[]]](val sourceFilePath:String,val callSitePoint:Int){ def find[F[]]:种类[F]=宏Impl.find[Kind,F] } 前面的宏非常简单: def build[Kind[[]]](c:blackbox.Context):c.Expr[Delayed[Kind]={ 导入c.universe_ c、 Expr( q”“” 新的延迟(

我需要在给定位置搜索隐式值。我保留了以前在类中调用宏时的位置,如下所示:

类延迟[+Kind[[]]](val sourceFilePath:String,val callSitePoint:Int){
def find[F[]]:种类[F]=宏Impl.find[Kind,F]
}
前面的宏非常简单:

def build[Kind[[]]](c:blackbox.Context):c.Expr[Delayed[Kind]={
导入c.universe_
c、 Expr(
q”“”
新的延迟(${c.EnclosuringPosition.point},${c.EnclosuringPosition.source.path})
"""
)
}
有了这个职位,我所需要做的就是启动隐式搜索,对吗

def find[Kind[[]],F[]](c:blackbox.Context)(隐式kindTag:c.WeakTypeTag[Kind[F]],fTag:c.WeakTypeTag[F[]]):c.Expr[Kind[F]={
导入c.universe_
具体化{
val self=c.prefix.splice.asInstanceOf[Delayed[Kind]]
val sourceFile=AbstractFile.getFile(self.sourceFilePath)
val batchSourceFile=新的batchSourceFile(sourceFile,sourceFile.toCharArray)
val implicitSearchPosition=新的偏移位置(batchSourceFile,self.callSitePoint)。asInstanceOf[c.Position]
c、 Expr[Kind[F]](c.inferitvalue(
应用类型(kindTag.tpe.typeConstructor,fTag.tpe.typeConstructor),
pos=隐式搜索位置
)).拼接
}
}
我使用具体化/拼接调用获得职位,然后应用
inferImplicitValue
。但是编译器抱怨隐式值上的最后一个拼接:

the splice cannot be resolved statically, 
which means there is a cross-stage evaluation involved
它要求我添加编译器jar作为依赖项,但这样做只会导致另一个错误:

Macro expansion contains free term variable c defined by find in Delayed.scala
我理解,从概念上讲,物化是价值观的世界。我不明白的是,隐式搜索应该在宏生成的代码写入源代码之前解决。这是我能想到的隐式搜索在宏观环境中工作的唯一方法

我错在哪里?我确实理解编译器消息,但对我来说,在这个特定的上下文中,它没有任何意义。也许我不明白
inferImplicitValue
是如何工作的。

试试
Context#eval(expr)


使用您的代码,我在第一行遇到以下错误:
java.lang.IndexOutOfBoundsException:0
经过大量阅读,我的错误似乎是使用了
c.prefix
。我认为它是
延迟的
实例的
这个
自我
。这似乎有点不同,取决于宏的调用位置。你知道如何随时指向延迟的“this”吗?(当然也感谢您的帮助)@Merlin如果您向宏中添加
println(c.prefix.tree)
,然后编译
对象应用程序{trait-Kind[\uu[\ u]];trait F[\u];隐式val-kindF:Kind[F]=新种类[F]{;新延迟[Kind](“某些现有文件”,0)。查找[F]}
打印
警告:scalac:new App.Delayed[App.Kind](“某些现有文件”,0)
。所以
c.prefix
就像
这个
。它似乎是在存储
延迟的
实例并传递它的时候。现在这还不够信息,我会在下班后继续搜索。如果我稍微更改一下示例:
val tmp=new delayed[Kind](…);tmp.find[F]
在本例中,它将打印
YourApp.type.tmp
作为前缀。这显然不是我的意思。
def find[Kind[_[_]], F[_]](c: blackbox.Context)(implicit kindTag: c.WeakTypeTag[Kind[F]], fTag: c.WeakTypeTag[F[_]]): c.Expr[Kind[F]] = {
  import c.universe._

  val self = c.eval(c.Expr[Delayed[Kind]](c.untypecheck(c.prefix.tree.duplicate)))
  val sourceFile = AbstractFile.getFile(self.sourceFilePath)
  val batchSourceFile = new BatchSourceFile(sourceFile, sourceFile.toCharArray)
  val implicitSearchPosition = new OffsetPosition(batchSourceFile, self.callSitePoint).asInstanceOf[c.Position]

  c.Expr[Kind[F]](c.inferImplicitValue(
    appliedType(kindTag.tpe.typeConstructor, fTag.tpe.typeConstructor),
    pos = implicitSearchPosition
  ))
}