How to transform and apply a partial function using Scala Macros? -


i want implement scala macro takes partial function, performs transformations on patterns of function, , applies given expression.

to so, started following code:

def mymatchimpl[a: c.weaktypetag, b: c.weaktypetag](c: context)(expr: c.expr[a])(patterns: c.expr[partialfunction[a, b]]): c.expr[b] = {   import c.universe._    /*    * deconstruct partial function , select relevant case definitions.    *     * partial, anonymus function translated new class of following form:    *     * { @serialversionuid(0) final <synthetic> class $anonfun extends scala.runtime.abstractpartialfunction[a,b] serializable {    *     *     def <init>(): anonymous class $anonfun = ...    *    *     final override def applyorelse[...](x1: ..., default: ...): ... = ... match {    *       case ... => ...    *       case (defaultcase$ @ _) => default.apply(x1)    *     }    *    *     def isdefined ...    *   }    *   new $anonfun()    * }: partialfunction[a,b]    *    */   val typed(block(list(classdef(a, b, x, template(d, e, list(f, defdef(g, h, i, j, k, match(l, allcasedefs)), m)))), n), o) = patterns.tree    /* perform transformation on cases */   val transformedcasedefs: list[casedef] = allcasedefs map {     case casedef => casedef // code perform desired transformations, it's identity   }    /* construct anonymus partial function transformed case patterns */   val result = typed(block(list(classdef(a, b, x, template(d, e, list(f, defdef(g, h, i, j, k, match(l, transformedcasedefs)), m)))), n), o)   // println(show(result))    c.expr[b](q"$result($expr)") } 

i deconstruct partial function, select case definitions of applyorelse function, perform desired transformation on each definition, , put together. macro invoked this:

def mymatch[a, b](expr: a)(patterns: partialfunction[a, b]): b = macro mymatchimpl[a,b] 

unfortunately, doesn't work expected. using macro in simple example

def test(x: option[int]) = mymatch(x){   case some(n) => n   case none    => 0 } 

results in following error message:

object creation impossible, since method isdefinedat in trait partialfunction of type (x: option[int])boolean not defined 

this bit confusing, since printing generated partial function yields

({   final <synthetic> class $anonfun extends scala.runtime.abstractpartialfunction[option[int],int] serializable {     def <init>(): anonymous class $anonfun = {       $anonfun.super.<init>();       ()     };     final override def applyorelse[a1 <: option[int], b1 >: int](x2: a1, default: a1 => b1): b1 = ((x2.asinstanceof[option[int]]: option[int]): option[int] @unchecked) match {       case (x: int)some[int]((n @ _)) => n       case scala.none => 0     };     final def isdefinedat(x2: option[int]): boolean = ((x2.asinstanceof[option[int]]: option[int]): option[int] @unchecked) match {       case (x: int)some[int]((n @ _)) => true       case scala.none => true       case (defaultcase$ @ _) => false     }   };   new $anonfun() }: partialfunction[option[int],int]) 

which defines isdefinedat method.

does has idea, what's problem here , how right?

the new reflection api provides transformer class that's designed kind of tree transformation:

import scala.language.experimental.macros import scala.reflect.macros.context  def mymatchimpl[a: c.weaktypetag, b: c.weaktypetag](c: context)(   expr: c.expr[a] )(   patterns: c.expr[partialfunction[a, b]] ): c.expr[b] = {   import c.universe._    val transformer = new transformer {     override def transformcasedefs(trees: list[casedef]) = trees.map {       case casedef => casedef     }   }    c.expr[b](q"${transformer.transform(patterns.tree)}($expr)") }  def mymatch[a, b](expr: a)(patterns: partialfunction[a, b]): b =   macro mymatchimpl[a,b]  def test(x: option[int]) = mymatch(x) {   case some(n) => n   case none    => 0 } 

you may need additional machinery make sure transformation being applied case lists want applied to, in general approach going more robust transforming tree manually.

i'm still curious why version doesn't work, though, , if have time might worth putting reduced example question here.


Comments

Popular posts from this blog

java - activate/deactivate sonar maven plugin by profile? -

python - TypeError: can only concatenate tuple (not "float") to tuple -

java - What is the difference between String. and String.this. ? -