मैं एक स्कैला एम्बेडेड डीएसएल में काम कर रहा हूं और मैक्रोज़ मेरे उद्देश्यों को प्राप्त करने के लिए एक मुख्य उपकरण बन रहे हैं। परिणामी एक में आने वाली मैक्रो अभिव्यक्ति से एक उपट्री का पुन: उपयोग करने का प्रयास करते समय मुझे एक त्रुटि मिल रही है। स्थिति काफी जटिल है, लेकिन (मुझे उम्मीद है) मैंने इसकी समझ के लिए इसे सरल बना दिया है।मैक्रो में परिभाषा (एएसटी) सबट्रीज़ का पुन: उपयोग कैसे कर सकता हूं?
मान लीजिए कि हमें इस कोड है:
val y = transform {
val x = 3
x
}
println(y) // prints 3
जहां 'को बदलने' शामिल मैक्रो है। यह प्रतीत हो सकता है हालांकि यह पूरी तरह से कुछ भी नहीं है, यह वास्तव में पता चला ब्लॉक इस अभिव्यक्ति में बदलाव ला रहा है करता है:
def transform(c: Context)(block: c.Expr[Int]): c.Expr[Int] = {
import c.universe._
import definitions._
block.tree match {
/* {
* val xNam = xVal
* xExp
* }
*/
case Block(List(ValDef(_, xNam, _, xVal)), xExp) =>
println("# " + showRaw(xExp)) // prints Ident(newTermName("x"))
c.Expr(
Match(
xVal,
List(CaseDef(
Bind(xNam, Ident(newTermName("_"))),
EmptyTree,
/* xExp */ Ident(newTermName("x"))))))
case _ =>
c.error(c.enclosingPosition, "Can't transform block to function")
block // keep original expression
}
}
सूचना है कि xNam साथ मेल खाती है:
3 match { case x => x }
यह इस मैक्रो कार्यान्वयन के साथ किया जाता है परिवर्तनीय नाम, xVal इसके संबंधित मूल्य से मेल खाता है और अंत में xExp चर युक्त अभिव्यक्ति के साथ मेल खाता है। खैर, अगर मैं xExp कच्चे पेड़ को मुद्रित करता हूं तो मुझे पहचान (नयाTermName ("x")) मिलता है, और यह वही है जो आरएचएस मामले में सेट है। चूंकि अभिव्यक्ति को संशोधित किया जा सकता है (उदाहरण के लिए x के बजाय x + 2), यह मेरे लिए एक वैध समाधान नहीं है। मैं क्या करना चाहता हूं कि xExp पेड़ का पुन: उपयोग करना (xExp टिप्पणी देखें) 'x' अर्थ को बदलते समय (यह इनपुट अभिव्यक्ति में एक परिभाषा है लेकिन आउटपुट में एलएचएस वैरिएबल होगा), लेकिन यह एक लॉन्च करता है लंबे त्रुटि में संक्षेप:
symbol value x does not exist in org.habla.main.Main$delayedInit$body.apply); see the error output for details.
मेरे वर्तमान समाधान xExp की पार्स नए लोगों के साथ सभी idents sustitute करने पर होते हैं, लेकिन यह पूरी तरह से संकलक internals पर निर्भर है, और इसलिए, एक अस्थायी वैकल्पिक हल। यह स्पष्ट है कि xExp शोरो द्वारा प्रदान की जाने वाली अधिक जानकारी के साथ आता है। 'X' को केस वैरिएबल की भूमिका देने के लिए मैं xExp को कैसे साफ़ कर सकता हूं? क्या कोई इस त्रुटि की पूरी तस्वीर समझा सकता है?
पीएस: मैं TreeApi से विकल्प * विधि परिवार का उपयोग करने में असफल प्रयास कर रहा हूं लेकिन मुझे इसके प्रभावों को समझने के लिए मूल बातें गायब हैं।
क्या रीसेटअलएटर्स का काम था, आखिरकार? –
हां, ऐसा हुआ। यह दिखाए गए कोड में काम करता है, साथ ही साथ कई जटिल "परिवर्तन" वाले जटिल पेड़ में भी काम करता है। – jeslg
आपने 'c.Expr' परिणाम पर 'ब्लॉक' पर, या कुछ चयनित पेड़ पर 'resetAllAttrs'' कहा था? –