2012-05-02 14 views
113

मैं Roslyn CTP को एक बार देख लेने दिया गया है और, यह Expression tree API लिए एक समान समस्या का हल है, जबकि दोनों अपरिवर्तनीय हैं, लेकिन रोसलिन एक काफी अलग तरीके से ऐसा नहीं करता है:Roslyn SyntaxNodes पुन: उपयोग कर रहे हैं?

  • Expression नोड्स के लिए कोई संदर्भ है अभिभावक नोड, ExpressionVisitor का उपयोग करके संशोधित किया जाता है और इसीलिए बड़े हिस्सों का पुन: उपयोग किया जा सकता है।

  • दूसरी ओर, रोज़लिन की SyntaxNode, इसके माता-पिता का संदर्भ है, इसलिए सभी नोड्स प्रभावी रूप से एक ब्लॉक बन जाते हैं जो पुन: उपयोग करना असंभव है। Update, ReplaceNode, आदि जैसे तरीके संशोधनों को प्रदान करने के लिए प्रदान किए जाते हैं।

यह कहां समाप्त होता है? Document? Project? ISolution? एपीआई पेड़ के चरण-दर-चरण परिवर्तन को बढ़ावा देता है (बटन के बजाए), लेकिन क्या प्रत्येक चरण एक पूर्ण प्रति बनाता है?

उन्होंने ऐसा क्यों चुना? क्या कोई दिलचस्प चाल है जो मुझे याद आ रही है?

उत्तर

163

अद्यतन: यह प्रश्न the subject of my blog on June 8th, 2012 था। महान सवाल के लिए धन्यवाद!


महान प्रश्न। हमने आपके द्वारा उठाए गए मुद्दों पर लंबे समय तक बहस की।

  • अपरिवर्तनीय:

    हम एक डेटा संरचना है कि निम्नलिखित विशेषताएं हैं करना चाहते हैं।

  • एक पेड़ का रूप।
  • बाल नोड्स से पैरेंट नोड्स तक सस्ती पहुंच।
  • पेड़ में किसी नोड से टेक्स्ट में किसी चरित्र ऑफ़सेट से मानचित्र करना संभव है।
  • लगातार

हठ से मेरा पुन: उपयोग के पेड़ में मौजूदा नोड्स के सबसे करने की क्षमता का मतलब यह पाठ संपादित करें बफर करने के लिए किया जाता है। चूंकि नोड्स अपरिवर्तनीय हैं, इसलिए उनका पुन: उपयोग करने में कोई बाधा नहीं है। हमें प्रदर्शन के लिए इसकी आवश्यकता है; प्रत्येक बार जब आप कुंजी दबाते हैं तो हम फ़ाइल के विशाल वज़न को फिर से पार्स नहीं कर सकते हैं। हमें संपादन से प्रभावित पेड़ के केवल हिस्सों को फिर से लेक्स और फिर से पार करने की आवश्यकता है।

अब आप तुरंत समस्याएं आ एक डेटा संरचना में उन चीजों के सभी पांच डाल करने का प्रयास करते समय:

  • कैसे आप पहली जगह में एक नोड का निर्माण करते हैं? माता-पिता और बच्चे दोनों एक दूसरे को संदर्भित करते हैं, और अपरिवर्तनीय हैं, तो कौन सा पहले बनाया जाता है?
  • मान लीजिए कि आप उस समस्या को हल करने के लिए प्रबंधन करते हैं: आप इसे लगातार कैसे बनाते हैं? आप एक बच्चे के नोड को एक अलग माता-पिता में दोबारा उपयोग नहीं कर सकते क्योंकि इसमें बच्चे को यह बताने में शामिल होगा कि उसके पास एक नया माता पिता है। लेकिन बच्चा अपरिवर्तनीय है।
  • मान लीजिए कि आप उस समस्या को हल करने के लिए प्रबंधन करते हैं: जब आप संपादन बफर में कोई नया वर्ण डालते हैं, तो की पूर्ण स्थिति परिवर्तन के बाद किसी स्थिति में मैप किए गए प्रत्येक नोड को बदलती है। यह लगातार डेटा संरचना बनाने में बहुत मुश्किल बनाता है, क्योंकि कोई भी संपादन अधिकांश नोड्स के स्पैन को बदल सकता है!

लेकिन रोज़लिन टीम पर हम नियमित रूप से असंभव चीजें करते हैं। हम वास्तव में दो पार्स पेड़ रखते हुए असंभव करते हैं। "हरा" पेड़ अपरिवर्तनीय, लगातार, कोई अभिभावक संदर्भ नहीं है, "तल-अप" बनाया गया है, और प्रत्येक नोड चौड़ाई ट्रैक करता है लेकिन इसकी पूर्ण स्थिति नहीं है। जब कोई संपादन होता है तो हम संपादन द्वारा प्रभावित हरे पेड़ के केवल हिस्सों का पुनर्निर्माण करते हैं, जो आम तौर पर पेड़ में कुल पार्स नोड्स के ओ (लॉग एन) के बारे में होता है।

"लाल" पेड़ एक अपरिवर्तनीय मुखौटा है जो हरे पेड़ के चारों ओर बनाया गया है; यह मांग पर पर "टॉप-डाउन" बनाया गया है और प्रत्येक संपादन पर फेंक दिया गया है। यह द्वारा माता-पिता संदर्भों की गणना करता है क्योंकि आप शीर्ष पर से पेड़ के माध्यम से उतरते हैं। जब आप उतरते हैं, तो उन्हें चौड़ाई से कंप्यूटिंग करके पूर्ण स्थिति बनाती है।

आप, उपयोगकर्ता, केवल लाल पेड़ को देखते हैं; हरा पेड़ एक कार्यान्वयन विस्तार है। यदि आप एक पार्स नोड की आंतरिक स्थिति में आते हैं तो आप वास्तव में देखेंगे कि एक अन्य प्रकार के पार्स नोड का संदर्भ है; वह हरा पेड़ नोड है।

संयोग से, इन्हें "लाल/हरे पेड़" कहा जाता है क्योंकि वे व्हाइटबोर्ड मार्कर रंग थे जिन्हें हम डिजाइन मीटिंग में डेटा संरचना खींचते थे। रंगों के लिए कोई और अर्थ नहीं है।

इस रणनीति का लाभ यह है कि हमें उन सभी महान चीजें मिलती हैं: अपरिवर्तनीयता, दृढ़ता, अभिभावक संदर्भ आदि। लागत यह है कि यह प्रणाली जटिल है और अगर "लाल" मुखौटे बड़े हो जाते हैं तो बहुत सारी स्मृति का उपभोग कर सकते हैं। वर्तमान में हम यह देखने के लिए प्रयोग कर रहे हैं कि क्या हम लाभ खोए बिना कुछ लागत कम कर सकते हैं।

+3

और आईप्रोजेक्ट्स और आईडी दस्तावेज़ों के बारे में आपके प्रश्न के हिस्से को संबोधित करने के लिए: हम सेवा परत में एक समान मॉडल का उपयोग करते हैं। आंतरिक रूप से "दस्तावेज़स्टेट" और "प्रोजेक्टस्टेट" प्रकार हैं जो नैतिक रूप से सिंटैक्स पेड़ के हरे नोड्स के बराबर हैं। आपके लिए प्राप्त आईप्रोजेक्ट/आईडी दस्तावेज़ ऑब्जेक्ट्स इनके लिए लाल नोड facades हैं। यदि आप Roslyn.Services.Project के कार्यान्वयन को देखते हैं तो एक डिकंपेलर में, आप देखेंगे कि लगभग सभी कॉल आंतरिक राज्य वस्तुओं के लिए आगे बढ़ती हैं। –

+0

@Eric टिप्पणी के लिए खेद है, लेकिन आप खुद के खिलाफ विरोधाभास कर रहे हैं। 'जटिल निरंतर डेटा संरचना बनाने की व्यय और कठिनाई खुद के लिए भुगतान नहीं करती है।' रेफरी: http://stackoverflow.com/questions/6742923/if-strings-are-immutable-in-net-then-why- करता है-substring-take-on-time/6750591 # 6750591 यदि आपके पास उच्च प्रदर्शन लक्ष्य थे तो आपने इसे पहली जगह क्यों अपरिवर्तनीय बना दिया? क्या स्पष्ट लोगों के अलावा कोई अन्य कारण है? जैसे थ्रेडसेफ बनाने के लिए आसान, आदि के बारे में कारण –

+2

@lukas आप उस उद्धरण को संदर्भ से बाहर ले रहे हैं। पिछली वाक्य "क्योंकि जब आप आमतौर पर .NET कार्यक्रमों में तारों पर किए गए संचालन को देखते हैं, तो यह पूरी तरह से पूरी तरह से नई स्ट्रिंग बनाने के लिए हर संभव तरीके से खराब होता है।" ओटीओएच, जब आप उन परिचालनों को देखते हैं जो आमतौर पर अभिव्यक्ति वृक्ष पर किए जाते हैं - उदा। स्रोत फ़ाइल में कुछ वर्ण टाइप करना - यह एक पूरी तरह से नया अभिव्यक्ति वृक्ष बनाने के लिए काफी खराब है। तो वे केवल इसका आधा हिस्सा बनाते हैं। – Timbo

संबंधित मुद्दे