2011-12-08 9 views
8

मेरे पास एक बहुत सी ++ - सिंटैक्स जैसी भाषा है। लेक्सर और पार्सर जगह पर हैं और सही एएसटी का उत्पादन करते हैं। सबसे बड़े हिस्से के लिए बैकएंड भी किया जाता है।एक कंपाइलर लिखना: काम करने के लिए सरल टेम्पलेट कैसे प्राप्त करें?

प्रकार बनाने के लिए कंपाइलर का उपयोग करने वाली मूल प्रणाली बहुत सरल है: सभी प्रकारों को अंतर्निहित माना जाता है और सभी उदाहरण वैश्विक हैं। तो वहां एक साधारण नक्शा है जो एक प्रकार के नाम से मेल खाता है जो वैरिएबल बनाता है जो मूल रूप से बूस्ट :: किसी भी प्रकार का सामान्य प्रकार है। कुंजी के रूप में चर के नाम के साथ एक और नक्शा और मूल्य के रूप में कार्य करता है चर वैश्विक क्षेत्र के रूप में:

std::map< std::string, std::function< Variable() > typeList; 

    //register some types 
typeList[ "X" ] = Variable::Create<X>; 
typeList[ "Y" ] = CreateInstanceOfY; 
.... 

संकलक X myVar; की तरह एक आरंभीकरण के लिए एएसटी नोड हो जाता है जब यह मूल रूप से करता है

std::map< std::string, Variable > globalScope; 
globalScope[ "myVar" ] = typeList[ "X" ](); 

जब myVar बाद में प्रयोग किया जाता है पर ऐसा लगता है जैसे

X& x = myVar.GetReference<X>(); 

सरल प्रकार भेजने द्वारा पहुँचा जा सकता अब मैं इस एक सा विस्तार और सरल टेम्पलेट का उपयोग करना चाहते हैं। मान लीजिए कि एक प्रकार "सरणी" है जिसे एक वेक्टर का उपयोग करके कार्यान्वित किया जाता है। मैं

typeList[ "array<X>" ] = Variable::Create< std::vector<X> >; 

पर सब कुछ पंजीकृत कर सकता है लेकिन यह काफी अनुकूल नहीं है क्योंकि इसे सभी संयोजनों के लिए दोहराया जाना होगा। आदर्श रूप में मैं कुछ इस तरह लिखने के लिए अनुमति देता है कार्यक्षमता आवश्यकता होगी:

typeList.CreateTemplateVariable("array", "X") 

जो फिर एक चर उदाहरण है, जिसमें आंतरिक रूप से एक std :: वेक्टर < एक्स> रखती पैदा करेगा। मैंने कड़ी मेहनत की लेकिन यह पता नहीं लगा कि यह कैसे करना है। हो सकता है कि मैंने सरल प्रकार के मैपिंग के साथ गलत तरीके से शुरू किया और यही वजह है कि मैं इसके चारों ओर अपना सिर नहीं ले सकता।

तो सवाल सरल है: क्या ऐसा करना संभव है? और कैसे?

+0

जब आप एएसटी से सी ++ कोड बनाते हैं, तो यह पहले से ही एक कंपाइलर है। – belgther

+0

शब्दावली के बारे में थोड़ा सा नाइटपिक: एक कंपाइलर एक प्रारूप से दूसरे प्रारूप में कोड का अनुवाद करता है।एक दुभाषिया कुछ कोड निष्पादित करता है। –

+0

@ जोचिमपिलबोर्ग यह इंगित करने के लिए धन्यवाद .. मैं वास्तव में शब्दावली के साथ अच्छा नहीं हूं। – stijn

उत्तर

2

मुझे यकीन है कि मैं सही आपकी समस्या को मिला है नहीं कर रहा हूँ, लेकिन अगर आप एम पैरामीट्रिक प्रकार (vector<>, list<>, ...) और एन सरल प्रकार (int, double, ...) है, तो आप की आवश्यकता होगी एम * एन यदि आप सभी संयोजनों का समर्थन करना चाहते हैं तो वास्तविक कार्यान्वयन। इन सभी कार्यान्वयनों को संकलन समय पर जाना जाना चाहिए (या सिद्धांत रूप में आप सी ++ कंपाइलर ऑन-द-फ्लाई का आह्वान कर सकते हैं)। क्या आप वास्तव में यह चाहते हैं?

इसके बजाय गैर-टाइप किए गए कंटेनर का उपयोग करने के लिए एक वर्कअराउंड हो सकता है। उदाहरण के लिए, vector<Object*> पॉइंटर्स को संग्रहीत करना जिन्हें बाद में आवश्यक प्रकार में परिवर्तित किया जा सकता है, उदाहरण के लिए dynamic_cast के साथ। इस तरह आपको केवल पैरामीट्रिक प्रकारों के लिए एम कार्यान्वयन की आवश्यकता होगी, और vector पर "सरणी" को हल कर सकते हैं, और "एक्स" से X स्वतंत्र रूप से।

+0

आप एम * एन के बारे में सही हैं, हालांकि कुछ गतिशील प्रणाली होना बेहतर होगा जो नेस्टेड टेम्पलेट्स और एकाधिक टेम्पलेट पैरामीटर को भी समर्थन या बढ़ाया जा सकता है। मैं यह देखने जा रहा हूं कि गैर-टाइप किए गए दृष्टिकोण मुझे कहीं कहीं मिलते हैं, दिलचस्प लग रहा है। – stijn

+0

@stijn, आप अभी भी अपनी भाषा में टाइप की गई सब कुछ, टेम्पलेट्स और अन्य कुछ भी कर सकते हैं। समस्या तब उत्पन्न होती है जब आप अपनी भाषा से प्रकारों को सी ++ में एक-से-एक में मैप करने का प्रयास करते हैं, जैसे कि आप "सरणी " -> वेक्टर "के लिए करने का प्रयास कर रहे हैं। आपको ऐसा करने की ज़रूरत नहीं है, हालांकि - आपकी भाषा में टाइप की गई किसी भी चीज को कार्यान्वयन में टाइप नहीं किया जाना चाहिए, जैसे ही आपका कंपाइलर टाइपिंग करता है। –

1

आम तौर पर आप जिस तरह से टेम्पलेट की तरह करते हैं, वैसे ही आप वर्णन करते हैं, लेकिन समय से पहले सभी संभव संयोजन बनाने के बजाय, आप उन्हें मांग पर बनाते हैं।

std::function< Variable() > getType(std::string name) { 
    auto rv = typeList[name]; 
    if (rv) return rv; 
    auto template_start = name.find('<'); 
    if (template_start != string::npos) { 
     auto template_end = name.rfind('>'); 
     std::string arg = name.substr(template_start+1, template_end); 
     std::string base = name.substr(0, template_start); 
     typeList[name] = rv = InstantiateTemplate(base, arg); 
     return rv; } 
    throw UnknownTypeError(name); 
} 

यह किसी भी प्रकार के कार्यक्रम में निर्दिष्ट के लिए बुलाया जाता है, मांग पर जरूरत के मुताबिक खाके instantiations बनाने: तो तुम एक getType दिनचर्या की तरह हो सकता है।

+0

इनपुट के लिए धन्यवाद, लेकिन आपके फ़ंक्शन का सबसे बड़ा हिस्सा वास्तव में पार्सर पहले से ही करता है; इसके अलावा यह बार-बार ऐसा करता है, इसलिए मेरा पार्सर घोंसला वाले टेम्पलेट्स को असीमित तर्कों जैसे सरणी <सर <ए >> के साथ संभालता है और इसके लिए टाइपस्पेसिफर नामक एएसटी नोड बनाता है। मेरा सवाल है कि 'InstantiateTemplate' कार्यक्षमता को लिखना, यानी टाइपस्पेसिफ़ियर को किसी प्रकार के वास्तविक उदाहरण में कैसे परिवर्तित करना है। – stijn

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

  • कोई संबंधित समस्या नहीं^_^