Search code examples
scalascala-macrosscala-quasiquotes

How to pass arguments to a function of arbitrary number of parameters via macro?


I have deconstructed Function, got it vparams, and now I am able to call:

  case class Action(f: Function, ts: List[TypeName]) {
    def render(ruleName: String): Expr[Unit] = c.Expr[Unit](q"""
      val p = ${c.prefix}
      val value1 = p.valueStack.pop().asInstanceOf[${ts(0)}]
      val value2 = p.valueStack.pop().asInstanceOf[${ts(1)}]
      p.valueStack.push($f(value1, value2))
    """)
  }

f is of arbitrary number of parameters that is known at compile time.

How to pass ts.count parameters from p.valueStack to a function f?


Solution

  • How about something like this:

    case class Action(f: Function, ts: List[TypeName]) {
      def render(ruleName: String): Expr[Unit] = {
        val argNames = (1 to ts.size).map(i => newTermName(s"value$i"))
        val args = argNames.map(name => Ident(name))
        val valDefs = (ts zip argNames).map {
          case (tn, argName) =>
            q"val $argName = p.valueStack.pop().asInstanceOf[$tn]"
        }
    
        c.Expr[Unit]( q"""
          val p = ${c.prefix}
          ..$valDefs
          p.valueStack.push($f(..$args))
          """)
      }
    }
    

    This compiles (in Scala 2.10.2 with Macro Paradise plugin), but I didn't test whether it works.