Поиск неявного внутри вызова reify (макрос scala) - PullRequest
0 голосов
/ 23 апреля 2019

Мне нужно искать неявное значение в заданной позиции.Я сохранил позицию предыдущего вызова макроса в классе, например:

class Delayed[+Kind[_[_]]](val sourceFilePath: String, val callSitePoint: Int) {
  def find[F[_]]: Kind[F] = macro Impl.find[Kind, F]
}

Предыдущий макрос очень прост:

def build[Kind[_[_]]](c: blackbox.Context): c.Expr[Delayed[Kind]] = {
    import c.universe._

    c.Expr(
      q"""
        new Delayed(${c.enclosingPosition.point}, ${c.enclosingPosition.source.path})
       """
    )
  }

С этим у меня есть позиция, все, что янужно сделать, это запустить неявный поиск, верно?

def find[Kind[_[_]], F[_]](c: blackbox.Context)(implicit kindTag: c.WeakTypeTag[Kind[F]], fTag: c.WeakTypeTag[F[_]]): c.Expr[Kind[F]] = {
    import c.universe._

    reify {
      val self = c.prefix.splice.asInstanceOf[Delayed[Kind]]
      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
      )).splice
    }
  }

Я получаю позицию, используя вызовы reify / splice, а затем применяю 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 работает.

1 Ответ

1 голос
/ 23 апреля 2019

Попробуйте Context#eval(expr)

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
  ))
}
...