2013-08-30 3 views
7

में 'this` का उपयोग करें यह मेरे previous question पर एक फॉलो-अप है।जेनरेट मैक्रो विधि

मुझे काम करने के लिए नीचे दिए गए कोड की तरह कुछ चाहिए। मैं एक वृहद उत्पन्न विधि उत्पन्न करने में सक्षम होना चाहता हूँ:

case class Cat() 

test[Cat].method(1) 

कहाँ उत्पन्न विधि अपने आप में एक मैक्रो (एक "vampire" method) उपयोग कर रहा है के कार्यान्वयन:

// macro call 
def test[T] = macro testImpl[T] 

// macro implementation 
def testImpl[T : c.WeakTypeTag](c: Context): c.Expr[Any] = { 
    import c.universe._ 
    val className = newTypeName("Test") 

    // IS IT POSSIBLE TO CALL `otherMethod` HERE? 
    val bodyInstance = q"(p: Int) => otherMethod(p * 2)" 

    c.Expr { q""" 
    class $className { 
     protected val aValue = 1 

     @body($bodyInstance) 
     def method(p: Int): Int = macro methodImpl[Int] 

     def otherMethod(p: Int): Int = p 
    } 
    new $className {} 
    """} 
} 

// method implementation 
def methodImpl[F](c: Context)(p: c.Expr[F]): c.Expr[F] = { 
    import c.universe._ 

    val field = c.macroApplication.symbol 
    val bodyAnnotation = field.annotations.filter(_.tpe <:< typeOf[body]).head 
    c.Expr(q"${bodyAnnotation.scalaArgs.head}.apply(${p.tree.duplicate})") 
} 

इस कोड के साथ संकलित करने के लिए विफल रहता है :

[error] no-symbol does not have an owner 
last tree to typer: This(anonymous class $anonfun) 
[error]    symbol: anonymous class $anonfun (flags: final <synthetic>) 
[error] symbol definition: final class $anonfun extends AbstractFunction1$mcII$sp with Serializable 
[error]     tpe: examples.MacroMatcherSpec.Test.$anonfun.type 
[error]  symbol owners: anonymous class $anonfun -> value <local Test> -> class Test -> method e1 -> class MacroMatcherSpec -> package examples 
[error]  context owners: value $outer -> anonymous class $anonfun -> value <local Test> -> class Test -> method e1 -> class MacroMatcherSpec -> package examples 
[error] 
[error] == Enclosing template or block == 
[error] 
[error] DefDef(// val $outer(): Test.this.type 
[error] <method> <synthetic> <stable> <expandedname> 
[error] "examples$MacroMatcherSpec$Test$$anonfun$$$outer" 
[error] [] 
[error] List(Nil) 
[error] <tpt> // tree.tpe=Any 
[error] $anonfun.this."$outer " // private[this] val $outer: Test.this.type, tree.tpe=Test.this.type 
[error]) 

मैं गूढ़ रहस्य इसका क्या मतलब है पर वास्तव में बुरा हूँ, लेकिन मुझे लगता है कि यह तथ्य से संबंधित है कि मैं के शरीर में this.otherMethod संदर्भ नहीं दे सकता पिशाच विधि। क्या ऐसा करने के लिए कोई रास्ता है?

इस काम करता है, मेरी अगले कदम otherMethod के लिए इस प्रकार का कार्यान्वयन करने के लिए किया जाएगा:

def otherMethod(p: Int) = new $className { 
    override protected val aValue = p 
} 
+0

कुछ मैं बस के रूप में [एक ब्लॉग पोस्ट] (http://meta.plasm.us/posts/2013/08/31/feeding- इस समस्या का एक अधिक सामान्य प्रतिक्रिया ऊपर लिखा है हमारे-पिशाच /)। यदि आप यही चाहते हैं तो मैं यहां एक उत्तर के रूप में एक संघीय संस्करण जोड़ सकता हूं। –

उत्तर

2

"इस" आमतौर पर c.prefix.tree के रूप में उपलब्ध है। तो शायद की तरह

val bodyInstance = 
    q"(p: Int) => ${c.prefix.tree}.otherMethod(p * 2)"