पहचान
एक विशिष्ट संकलक निम्न चरण करता है:
- पार्सिंग: स्रोत पाठ एक सार वाक्यविन्यास ट्री (एएसटी) में बदल जाता है।
- अन्य मॉड्यूल के संदर्भ का समाधान (सी लिंकिंग तक इस चरण को स्थगित करें)।
- सिमेंटिक मान्यता: वाक्य-रचना संबंधी सही कथनों का निराकरण करना, जिसका कोई अर्थ नहीं है, जैसे अगम्य कोड या डुप्लिकेट घोषणाएँ।
- समतुल्य परिवर्तन और उच्च-स्तरीय अनुकूलन: एएसटी को एक ही शब्दार्थ के साथ अधिक कुशल संगणना का प्रतिनिधित्व करने के लिए रूपांतरित किया जाता है। इसमें सामान्य सबएक्सप्रेस और प्रारंभिक अभिव्यक्तियों की प्रारंभिक गणना शामिल है, अत्यधिक स्थानीय असाइनमेंट को समाप्त करना ( एसएसए भी देखें ), आदि।
- कोड जनरेशन: एएसपी को रैखिक निम्न-स्तरीय कोड में बदल दिया जाता है, छलांग, रजिस्टर आवंटन और इसी तरह। इस चरण में कुछ फ़ंक्शन कॉल को इनलाइन किया जा सकता है, कुछ लूप अनियंत्रित, आदि।
- Peephole अनुकूलन: निम्न-स्तरीय कोड को सरल स्थानीय अक्षमताओं के लिए स्कैन किया जाता है, जिन्हें समाप्त कर दिया जाता है।
अधिकांश आधुनिक संकलक (उदाहरण के लिए, जीसीसी और क्लैंग) पिछले दो चरणों को एक बार फिर दोहराते हैं। वे प्रारंभिक कोड पीढ़ी के लिए एक मध्यवर्ती निम्न-स्तरीय लेकिन प्लेटफ़ॉर्म-स्वतंत्र भाषा का उपयोग करते हैं। फिर उस भाषा को प्लेटफ़ॉर्म-विशिष्ट कोड (x86, ARM इत्यादि) में परिवर्तित कर दिया जाता है, जो प्लेटफ़ॉर्म-अनुकूलित तरीके से लगभग एक ही काम करता है। इसमें उदाहरण के लिए, जब संभव हो तो वेक्टर निर्देशों का उपयोग, शाखा भविष्यवाणी दक्षता को बढ़ाने के लिए पुन: निर्देश, और इसी तरह शामिल हैं।
उसके बाद, लिंक करने के लिए ऑब्जेक्ट कोड तैयार है। अधिकांश देशी-कोड संकलक जानते हैं कि एक निष्पादन योग्य उत्पादन करने के लिए लिंकर को कैसे कॉल किया जाए, लेकिन यह प्रति संकलन संकलन कदम नहीं है। जावा और C # जैसी भाषाओं में लोडिंग समय में VM द्वारा किया गया पूरी तरह से गतिशील हो सकता है।
मूल बातें याद रखें
- इसे काम करने लायक बनाओ
- इसे सुंदर बनाओ
- इसे कुशल बनाएं
यह क्लासिक अनुक्रम सभी सॉफ्टवेयर विकास पर लागू होता है, लेकिन दोहराव को सहन करता है।
अनुक्रम के पहले चरण पर ध्यान लगाओ। सबसे सरल चीज़ बनाएं जो संभवतः काम कर सकती है।
किताबें पढ़ें!
ड्रैगन बुक को अहो और उल्मैन द्वारा पढ़ें । यह क्लासिक है और आज भी काफी लागू है।
मॉडर्न कंपाइलर डिज़ाइन की भी प्रशंसा की जाती है।
यदि यह सामान अभी आपके लिए बहुत कठिन है, तो पहले पार्सिंग पर कुछ इंट्रो पढ़ें; आमतौर पर पुस्तकालयों को पार्स करने में इंट्रो और उदाहरण शामिल होते हैं।
सुनिश्चित करें कि आप ग्राफ़, विशेष रूप से पेड़ों के साथ काम करने में सहज हैं। ये चीजें हैं सामान कार्यक्रम तार्किक स्तर पर बने हैं।
अपनी भाषा को अच्छी तरह से परिभाषित करें
जो भी संकेतन आप चाहते हैं उसका उपयोग करें, लेकिन सुनिश्चित करें कि आपके पास आपकी भाषा का पूर्ण और सुसंगत विवरण हो। इसमें वाक्य रचना और शब्दार्थ दोनों शामिल हैं।
भविष्य संकलक के लिए परीक्षण मामलों के रूप में अपनी नई भाषा में कोड के स्निपेट्स को लिखने के लिए उच्च समय है।
अपनी पसंदीदा भाषा का उपयोग करें
पायथन या रूबी या जो भी भाषा आपके लिए आसान है, में एक कंपाइलर लिखना पूरी तरह से ठीक है। सरल एल्गोरिदम का उपयोग करें जिसे आप अच्छी तरह से समझते हैं। पहले संस्करण को तेज, या कुशल या सुविधा-पूर्ण होने की आवश्यकता नहीं है। इसे केवल पर्याप्त रूप से सही करना और संशोधित करना आसान है।
जरूरत पड़ने पर अलग-अलग भाषाओं में कंपाइलर के विभिन्न चरणों को लिखना भी ठीक है।
बहुत सारे परीक्षण लिखने के लिए तैयार करें
आपकी पूरी भाषा को परीक्षण मामलों द्वारा कवर किया जाना चाहिए; प्रभावी रूप से यह उनके द्वारा परिभाषित किया जाएगा। अपने पसंदीदा परीक्षण ढांचे से अच्छी तरह परिचित हों। पहले दिन से ही परीक्षण लिखें। गलत कोड का पता लगाने के विपरीत, सही कोड स्वीकार करने वाले 'सकारात्मक' परीक्षणों पर ध्यान केंद्रित करें।
सभी परीक्षण नियमित रूप से चलाएं। आगे बढ़ने से पहले टूटे हुए परीक्षणों को ठीक करें। यह एक गलत परिभाषित भाषा के साथ समाप्त होने के लिए शर्म की बात होगी जो मान्य कोड को स्वीकार नहीं कर सकता है।
एक अच्छा पार्सर बनाएं
पार्सर जनरेटर कई हैं । जो चाहो उठाओ। आप अपने स्वयं के पार्सर को खरोंच से भी लिख सकते हैं, लेकिन यह केवल इसके लायक है अगर आपकी भाषा का वाक्यविन्यास मृत सरल है।
पार्सर को सिंटैक्स त्रुटियों का पता लगाना और रिपोर्ट करना चाहिए। सकारात्मक और नकारात्मक दोनों में बहुत सारे परीक्षण मामले लिखें; भाषा को परिभाषित करते हुए आपके द्वारा लिखे गए कोड का पुन: उपयोग करें।
आपके पार्सर का आउटपुट एक सार सिंटैक्स ट्री है।
यदि आपकी भाषा में मॉड्यूल हैं, तो पार्सर का उत्पादन आपके द्वारा उत्पन्न 'ऑब्जेक्ट कोड' का सबसे सरल प्रतिनिधित्व हो सकता है। एक फ़ाइल को एक पेड़ को डंप करने और इसे जल्दी से वापस लोड करने के बहुत सारे सरल तरीके हैं।
एक अर्थपूर्ण सत्यापनकर्ता बनाएँ
अधिकांश शायद आपकी भाषा वाक्यात्मक रूप से सही निर्माण के लिए अनुमति देती है जो कुछ संदर्भों में कोई मतलब नहीं हो सकता है। एक उदाहरण एक ही चर की डुप्लिकेट घोषणा या गलत प्रकार के पैरामीटर को पारित करना है। मान्यवर पेड़ को देखने वाली ऐसी त्रुटियों का पता लगाएगा।
सत्यापनकर्ता आपकी भाषा में लिखे गए अन्य मॉड्यूल के संदर्भों को भी हल करेगा, इन अन्य मॉड्यूल को लोड करेगा और सत्यापन प्रक्रिया में उपयोग करेगा। उदाहरण के लिए, यह चरण सुनिश्चित करेगा कि किसी मॉड्यूल से किसी फ़ंक्शन को दिए गए मापदंडों की संख्या सही है।
फिर से, बहुत सारे परीक्षण मामले लिखें और चलाएं। तुच्छ मामले स्मार्ट और जटिल के रूप में समस्या निवारण में अपरिहार्य हैं।
कोड जनरेट करें
सबसे सरल तकनीकों का उपयोग करें जो आप जानते हैं। अक्सर किसी भाषा निर्माण (जैसे if
कथन) का सीधे हलके-पैराड्राइज्ड कोड टेम्प्लेट में अनुवाद करना ठीक है , एचटीएमएल टेम्पलेट के विपरीत नहीं।
फिर से, दक्षता को अनदेखा करें और शुद्धता पर ध्यान केंद्रित करें।
एक प्लेटफ़ॉर्म-स्वतंत्र निम्न-स्तरीय VM को लक्षित करें
मुझे लगता है कि आप निम्न स्तर के सामान की उपेक्षा करते हैं जब तक कि आप हार्डवेयर-विशिष्ट विवरणों में रुचि नहीं लेते। ये विवरण गैरी और जटिल हैं।
आपके विकल्प:
- LLVM: आमतौर पर x86 और ARM के लिए कुशल मशीन कोड जेनरेशन की अनुमति देता है।
- CLR: लक्ष्य .NET, ज्यादातर x86 / Windows- आधारित; अच्छी JIT है।
- JVM: जावा वर्ल्ड को लक्षित करता है, काफी मल्टीप्लायर्ड, एक अच्छा JIT है।
अनुकूलन को अनदेखा करें
अनुकूलन कठिन है। लगभग हमेशा अनुकूलन समय से पहले होता है। अयोग्य लेकिन सही कोड उत्पन्न करें। परिणामी कोड को अनुकूलित करने का प्रयास करने से पहले पूरी भाषा को लागू करें।
बेशक, तुच्छ अनुकूलन का परिचय देना ठीक है। लेकिन आपके कंपाइलर के स्थिर होने से पहले किसी भी चालाक, बालों वाले सामान से बचें।
तो क्या?
यदि यह सब सामान आपके लिए बहुत डराने वाला नहीं है, तो कृपया आगे बढ़ें! एक सरल भाषा के लिए, प्रत्येक चरण जितना आप सोच सकते हैं उससे अधिक सरल हो सकता है।
एक प्रोग्राम से 'हैलो वर्ल्ड' देखकर जो आपके कंपाइलर ने बनाया है वह प्रयास के लायक हो सकता है।