Z में Y में X कंपाइलर लिखने के लिए सामान्य नियम


9

मान लीजिए कि X इनपुट भाषा है, Z आउटपुट भाषा है, तो f कंपाइलर है, जिसे भाषा Y में लिखा जाता है।

f = X -> Z

च चूंकि केवल एक कार्यक्रम है, मुझे लगता है कि वाई कोई भी भाषा हो सकती है, है ना? इसलिए हमारे पास F1, f2, प्रत्येक Y1, Y2 में लिखा हुआ है।

f1 = f Y1    
f2 = f Y2

g = Z -> M
h = g . f    # We get a compiler X -> M

उदाहरण के लिए cpython संकलक लें, X Python है, Z Python VM कोड है, Y C है।

cpython = Python -> PythonVMCode C
interpreter = PythonVMCode -> Nothing
interpreter2 = PythonVMCode -> MachineCode

पायथन स्रोतों को पायथन वीएम कोड, .pyc फ़ाइलों के साथ संकलित किया जाता है, फिर दुभाषिया द्वारा व्याख्या की जाती है। ऐसा लगता है कि वहाँ एक संकलक मौजूद है जो सीधे पायथन कर सकता है -> मशीनकोड, हालांकि लागू करने के लिए बहुत कठिन है:

   hardpython = interpreter2 . cpython 

हम एक और संकलक भी कर सकते हैं काम करते हैं पायथन -> पायथन वीएमसीकोड, एक अन्य भाषा में, पायथन ही कहते हैं।

mypython = Python -> PythonVMCode Python
mypython2 = Python -> PythonVMCode Ruby

अब, यहाँ जटिल उदाहरण PyPy है। मैं PyPy का नौसिखिया हूं, अगर मैं गलत हूं तो मुझे सुधारो:

PyPy doc http://doc.pypy.org/en/latest/altecture.html#pypy-the-translation-framework

हमारा लक्ष्य भाषा कार्यान्वयनकर्ताओं की समस्या का एक संभावित समाधान प्रदान करना है: एल डायनामिक भाषाओं के लिए एल * ओ * पी दुभाषियों को लिखना और ओ महत्वपूर्ण डिजाइन निर्णयों के साथ पी प्लेटफार्मों।

हम सोच सकते हैं कि L X है, p है। Y है। एक प्रोग्राम मौजूद है जो सभी RPython प्रोग्राम को C में बदल देता है:

 rpython_compiler = RPython -> C  Python

 pypy = Python -> Nothing RPython

 translate = compile the program pypy written in RPython using rpython_compiler

 py2rpy = Python -> RPython  Python
 py2c = Python -> C Python 
 py2c = rpython_compiler . py2rpy

RPython प्रोग्राम VM निर्देशों की तरह हैं, rpython_compiler VM है।

Q1। pypy दुभाषिया है, एक RPython प्रोग्राम है जो Python कोड की व्याख्या कर सकता है, कोई आउटपुट भाषा नहीं है, इसलिए हम इसे संकलक के रूप में नहीं मान सकते, है ना?

जोड़ा गया:

  • मैंने अभी-अभी पाया कि अनुवाद करने के बाद भी, pypy अभी भी दुभाषिया है, केवल इस बार C में लिखा गया है।
  • यदि हम दुभाषिया पेपी में गहराई से देखते हैं, मेरा मानना ​​है कि किसी प्रकार के संकलक का अस्तित्व होना चाहिए, जो पायथन स्रोतों को कुछ एएसटी के लिए संकलित करता है, तो निष्पादित करें

इस तरह:

compiler_inside_pypy = Python -> AST_or_so

Q2। कंपाइलर py2rpy मौजूद हो सकता है, सभी पायथन प्रोग्राम को RPython में बदल सकता है? यह किस भाषा में लिखी गई है, यह अप्रासंगिक है। यदि हाँ, तो हमें एक और कंपाइलर py2c मिलता है। प्रकृति में pypy और py2rpy के बीच क्या अंतर है? क्या py2rpy को pypy की तुलना में लिखना बहुत कठिन है?

Q3। क्या इस बारे में कुछ सामान्य नियम या सिद्धांत उपलब्ध हैं?

अधिक संकलक:

gcc_c = C -> asm? C  # not sure, gimple or rtl?
g++ =   C++ -> asm? C
clang = C -> LLVM_IR  C++
jython = Python -> JVMCode java
ironpython = Python -> CLI C#

Q4। दिया गया f = X -> Z, एक प्रोग्राम P जो X में लिखा गया है। जब हम P को गति देना चाहते हैं, तो हम क्या कर सकते हैं? जीवाश्म तरीके:

  • अधिक कुशल एल्गोरिथ्म में पी फिर से लिखना

  • बेहतर Z उत्पन्न करने के लिए f को फिर से लिखना

  • यदि Z की व्याख्या की जाती है, तो एक बेहतर Z दुभाषिया लिखें (PyPy यहाँ पर है?)

  • Z में लिखे कार्यक्रमों को तेजी से पुन: लिखें

  • एक बेहतर मशीन प्राप्त करें

ps। यह प्रश्न एक संकलक लिखने के तकनीकी सामान के बारे में नहीं है, लेकिन एक निश्चित प्रकार के संकलक को लिखने की व्यवहार्यता और जटिलता है।


सीधे तौर पर संबंधित नहीं, लेकिन कुछ इसी तरह की अवधारणा: en.wikipedia.org/wiki/Supercompilation
तर्क

1
मुझे यकीन नहीं है कि यह सवाल वास्तव में स्टैक ओवरफ्लो को फिट करता है, खासकर जब इसमें बहुत सारे उपशमन हैं, लेकिन मैं अभी भी उस विचार की प्रशंसा करता हूं जो इस में चला गया।

4
आपको जो सिखाया गया है, उसके बावजूद, एएसटी की आवश्यकता नहीं है - यह बस एक रणनीति है जिसका उपयोग कुछ कंपाइलर करते हैं।

1
संभवतः यह cstheory.stackexchange.com का है
9000

3
PyPy का पायथन कार्यान्वयन, अधिकांश "दुभाषियों" की तरह, वास्तव में एक बाईटेकोड कंपाइलर है और एक में उस बायटेकोड प्रारूप के लिए एक दुभाषिया है।

जवाबों:


4

Q1। pypy दुभाषिया है, एक RPython प्रोग्राम जो Python कोड की व्याख्या कर सकता है, कोई आउटपुट भाषा नहीं है, इसलिए हम इसे एक संकलक के रूप में नहीं मान सकते, है ना?

PyPy CPython के समान है, दोनों में एक संकलक + दुभाषिया है। CPython में C में लिखा गया एक कंपाइलर है जो Python को Python VM bytecode के रूप में संकलित करता है। C. PyPy में लिखे गए दुभाषिए में bytecode को निष्पादित करता है। PyPy में RPython में लिखा गया एक संकलक है जो Python को Python VM bytecode पर संकलित करता है, फिर RPYthon में लिखे PyPy Interpreter में इसे निष्पादित करता है।

Q2। कंपाइलर py2rpy मौजूद हो सकता है, सभी पायथन प्रोग्राम को RPython में बदल सकता है? यह किस भाषा में लिखी गई है, यह अप्रासंगिक है। यदि हाँ, तो हमें एक और कंपाइलर py2c मिलता है। प्रकृति में pypy और py2rpy के बीच क्या अंतर है? क्या py2rpy को pypy की तुलना में लिखना बहुत कठिन है?

एक संकलक py2rpy मौजूद हो सकता है? सैद्धांतिक रूप से हाँ। ट्यूरिंग पूर्णता की गारंटी देता है।

निर्माण करने के लिए एक विधि py2rpyकेवल उत्पन्न स्रोत कोड में RPython में लिखे गए पायथन इंटरप्रेटर के स्रोत कोड को शामिल करना है। Pash2rpy संकलक का एक उदाहरण, बैश में लिखा गया है:

// suppose that /pypy/source/ contains the source code for pypy (i.e. Python -> Nothing RPython)
cp /pypy/source/ /tmp/py2rpy/pypy/

// suppose $inputfile contains an arbitrary Python source code
cp $inputfile /tmp/py2rpy/prog.py

// generate the main.rpy
echo "import pypy; pypy.execfile('prog.py')" > /tmp/py2rpy/main.rpy

cp /tmp/py2rpy/ $outputdir

अब जब भी आपको पायथन कोड को RPython कोड में ट्रांसलेट करने की आवश्यकता होती है, तो आप इस स्क्रिप्ट को कॉल करते हैं, जो $ आउटपुटडीयर में - RPython main.rpy, RPython के पायथन इंटरप्रेटर सोर्स कोड, और एक बाइनरी ब्लॉब prog.py. और फिर आप कॉल करके उत्पन्न RPython स्क्रिप्ट को निष्पादित कर सकते हैं rpython main.rpy

(ध्यान दें: चूंकि मैं रैफथॉन प्रोजेक्ट से परिचित नहीं हूं, रिफ्थॉन दुभाषिया को कॉल करने के लिए वाक्य रचना, pypy आयात करने और pypy.execfile करने की क्षमता, और .rpy एक्सटेंशन विशुद्ध रूप से बनाया गया है, लेकिन मुझे लगता है कि आपको बिंदु मिलता है)

Q3। क्या इस बारे में कुछ सामान्य नियम या सिद्धांत उपलब्ध हैं?

हां, किसी भी ट्यूरिंग पूरी भाषा को सैद्धांतिक रूप से किसी भी ट्यूरिंग पूर्ण भाषा में अनुवादित किया जा सकता है। कुछ भाषाओं में अन्य भाषाओं की तुलना में अनुवाद करना अधिक कठिन हो सकता है, लेकिन यदि प्रश्न "क्या यह संभव है?", तो इसका उत्तर "हाँ" है?

Q4। ...

यहां कोई सवाल नहीं है।


आपका py2rpy संकलक वास्तव में चतुर है। यह मुझे एक और विचार की ओर ले जाता है। 1. क्या आपके कंपाइलर में RPython में pypy लिखना पड़ता है? आप सभी की जरूरत है कुछ पायथन फ़ाइलों की व्याख्या कर सकते हैं, है ना? 2. os.system ('अजगर $ inputfile') भी काम कर सकता है अगर यह RPython में समर्थित है। यह निश्चित नहीं है कि क्या इसे अभी भी संकलक कहा जा सकता है, कम से कम शाब्दिक रूप से नहीं।

क्या पायथन अभी भी पायथन वीएम का उपयोग कर रहा है? अब यह स्पष्ट है। pypy_the_compiler = अजगर -> PythonVMCode RPython, pypy_the_interpreter = PythonVMCode -> कुछ भी नहीं RPython, cpython_the_compiler = अजगर -> PythonVMCode सी, cpython_the_interpreter = PythonVMCode -> कुछ भी नहीं सी

@jaimechen: Does pypy have to be written in RPython in your compiler?नहीं, इसे RPython में लिखने की आवश्यकता नहीं है, लेकिन Python कोड निष्पादित करने के लिए RPython को "सहायक दुभाषिया" / "रनटाइम" बताने में सक्षम होना चाहिए। हाँ यह सच है कि यह व्यावहारिक अर्थ में "संकलक" नहीं है, लेकिन यह एक रचनात्मक प्रमाण है जिसे लिखना संभव है Python -> RPythonIs pypy still using the Python VM?मेरा मानना ​​है कि pypy CPython का उपयोग बिल्कुल नहीं करता है (मैं गलत हो सकता है), इसके बजाय PyPy का "Python VM" का अपना कार्यान्वयन है जो RPython में लिखा गया है।
रेयान

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

शायद यहाँ एक बाधा जोड़ी जानी चाहिए: मौजूदा मशीन X को राज्य मशीन Z में बदलना, बिना मौजूदा 3 मशीन की सहायता के। यह वह स्थिति है जब X पूरी तरह से नया है, अब तक कोई संकलक या दुभाषिया मौजूद नहीं है।
जमैचेन

2

केवल q2 का उत्तर देने के लिए, विलियम मैककिमन द्वारा एक संकलक पुस्तक है जिसमें भाषा X के उत्पादन के लिए भाषा X के उत्पादन के लिए संकलक के सिद्धांत को टी-आरेखों की एक प्रणाली के माध्यम से खोजा गया है। 1970 के दशक में प्रकाशित, शीर्षक हाथ से नहीं, क्षमा करें।


हाँ, यह बात है, धन्यवाद। en.wikipedia.org/wiki/Tombstone_diagram
jaimechen

1

Q1। आम तौर पर, एक दुभाषिया एक संकलक नहीं है। एक कंपाइलर और एक दुभाषिया के बीच महत्वपूर्ण अंतर यह है कि एक दुभाषिया नए सिरे से शुरू होता है, हर बार स्रोत भाषा में स्रोत कोड के साथ। यदि आपका pypy इसके बजाय pyAST, या pyP-code था, और तब आपके पास AST या P-code दुभाषिया था, तो आप pyAST को कंपाइलर कह सकते हैं। इस तरह से पुराने UCSD PASCAL कंपाइलर ने (साथ ही साथ कुछ अन्य लोगों ने भी) काम किया: उन्होंने कुछ P- कोड संकलित किए, जिनकी व्याख्या तब की गई जब कार्यक्रम चलाया गया था। (यहां तक ​​कि .NET कुछ ऐसा प्रदान करता है, जब उत्पन्न ऑब्जेक्ट कोड की कॉम्पैक्टनेस गति की तुलना में कहीं अधिक महत्वपूर्ण होती है।)

Q2। हां बिल्कुल। देखें UCSD PASCAL (और दूसरों का एक समूह)।

Q3। कंप्यूटर विज्ञान में क्लासिक ग्रंथों के माध्यम से खुदाई करें। प्रति Brinch-Hansen (यदि स्मृति मेरी सेवा करता है) द्वारा समवर्ती PASCAL पर पढ़ें। कंपाइलर्स और कोड जेनरेशन के बारे में बहुत कुछ लिखा गया है। मशीन-इंडिपेंडेंट स्यूडोकोड जेनरेट करना आमतौर पर मशीन कोड जनरेट करने की तुलना में बहुत आसान होता है: स्यूडोकोड आमतौर पर उन क्विर्क से मुक्त होता है जिनमें वास्तविक रूप से मशीन होती है।

Q4। यदि आप चाहते हैं कि आपकी उत्पन्न हुई वस्तु तेज़ी से चले, तो आप बेहतर अनुकूलन करने के लिए कंपाइलर को अधिक स्मार्ट बनाते हैं। यदि आपकी वस्तु की व्याख्या की जाती है, तो आप अधिक जटिल परिचालनों को आदिम pseudoinstructions में धकेलने पर विचार करते हैं (CISC बनाम RISC सादृश्य है), तो आप अपने दुभाषिया से बाहर पटाखे को अनुकूलित करने की पूरी कोशिश करते हैं।

यदि आप चाहते हैं कि आपका कंपाइलर तेज गति से चले, तो आपको अपने सोर्स कोड को रीथिंक करने सहित हर उस पर काम करना होगा। संकलक को स्वयं लोड करने के बाद, संकलन का सबसे अधिक समय लेने वाला हिस्सा हमेशा संकलक में स्रोत कोड पढ़ रहा है। (उदाहरण के लिए C ++ पर विचार करें। अन्य सभी चीजें अपेक्षाकृत समान हैं, एक कंपाइलर को एक सरल "हैलो, वर्ल्ड" प्रोग्राम को संकलित करने के लिए #include फ़ाइलों की 9,000 (या शायद 50,000) की संख्या को कम करना पड़ता है, यह कभी भी एक जैसा तेज़ नहीं होने वाला है। केवल चार या पाँच पंक्तियों को पढ़ना होगा।)

मुझे याद नहीं है कि मैंने इसे कहाँ पढ़ा था, लेकिन ETH-Zurich में मूल ओबेरॉन कंपाइलर में एक बहुत ही परिष्कृत प्रतीक तालिका तंत्र था, जो काफी सुरुचिपूर्ण था। संकलक के प्रदर्शन के लिए Wirth का बेंचमार्क वह समय था जिसे संकलक को स्वयं संकलित करने में समय लगता था। एक सुबह, वह अंदर गया, भव्य रूप से जुड़े अल्ट्रा-ट्री प्रतीक तालिका को अलग कर दिया, और इसे एक साधारण रैखिक सरणी और सीधे रैखिक खोजों के साथ बदल दिया। उनके समूह में स्नातक छात्र थे। परिवर्तन के बाद, कंपाइलर तेज था, क्योंकि जो मॉड्यूल संकलन कर रहे थे, वे हमेशा छोटे थे कि सुरुचिपूर्ण राक्षस ने रैखिक सरणी और रैखिक खोज की तुलना में अधिक कुल ओवरहेड लगाया।


1
धन्यवाद। एक संकलक 'संकलन', जबकि एक दुभाषिया 'निष्पादित' करता है, क्या दो प्रकार के कार्यक्रमों के बारे में अधिक जानकारी हो सकती है, जैसे उनके प्रकार अलग हैं?
जमैचेन

1

जैसा कि कहा गया है कि आपके प्रश्न मुझे विश्वास दिलाते हैं कि आप वास्तव में क्या चाहते हैं / आवश्यकता इस बात की व्याख्या है कि एक संकलक क्या है, एक दुभाषिया क्या है और दोनों के बीच अंतर क्या है।

संकलक भाषा X में कार्यात्मक रूप से समतुल्य कार्यक्रम के लिए भाषा X में लिखे गए एक कार्यक्रम का मानचित्र बनाता है। उदाहरण के लिए, पास्कल से C तक एक संकलक संकलित कर सकता है।

function Square(i: Integer)
begin
    Square := i * i
end

सेवा

int Square(int i)
{
    return i * i;
}

अधिकांश कंपाइलर 'डाउनवर्ड' को संकलित करते हैं, इसलिए वे उच्च-स्तरीय प्रोग्रामिंग भाषाओं को निचले-स्तर की भाषाओं में, अंतिम निचले स्तर की भाषा मशीन कोड में संकलित करते हैं।

अधिकांश कंपाइलर सीधे मशीन कोड के लिए संकलित करते हैं, लेकिन कुछ (विशेष रूप से जावा और .NET भाषाओं में) 'बायटेकोड' ( जावा बायटेकोड और सीआईएल ) के लिए संकलित होते हैं । काल्पनिक कंप्यूटर के लिए मशीन कोड के रूप में bytecode के बारे में सोचो। इस बाइटकोड की व्याख्या तब की जाती है या जब इसे चलाया जाता है (उस पर बाद में)।

एक दुभाषिया कुछ भाषा Z में लिखे गए प्रोग्राम को निष्पादित करता है। एक दुभाषिया एक प्रोग्राम को थोड़ा-थोड़ा करके पढ़ता है, उसे उसी तरह से निष्पादित करता है जैसे वह साथ जाता है। उदाहरण के लिए:

int i = 0;
while (i < 1)
{
    i++
}
return i;

लाइन के लिए उस प्रोग्राम लाइन को देखने वाले इंटरप्रेटर की कल्पना करें, लाइन की जांच करना, जो वह करता है उसे क्रियान्वित करना, अगली लाइन और आगे की तरफ देखना।

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

एक JITTER एक जस्ट-इन-टाइम कंपाइलर है। एक JITTER एक संकलक है। एकमात्र अंतर वह समय है जिसे निष्पादित किया जाता है: अधिकांश प्रोग्राम लिखे जाते हैं, संकलित किए जाते हैं, अपने उपयोगकर्ताओं को भेजे जाते हैं और फिर निष्पादित होते हैं, लेकिन जावा बाइटकोड और सीआईएल को पहले अपने उपयोगकर्ताओं को भेज दिया जाता है, और फिर निष्पादित होने से ठीक पहले उन्हें मशीन में संकलित किया जाता है। उनके उपयोगकर्ताओं का कोड।

C # -> (संकलन) -> CIL -> ग्राहक को भेज दिया -> (निष्पादन से ठीक पहले संकलन) -> मशीन कोड -> (निष्पादित)

आखिरी चीज जिसे आप जानना चाहते हैं वह है ट्यूरिंग संपूर्णता ( लिंक )। एक प्रोग्रामिंग लैंग्वेज ट्यूरिंग कम्प्लीट है अगर वह सब कुछ ' ट्यूरिंग मशीन ' की गणना कर सकती है, अर्थात यह ट्यूरिंग मशीन के रूप में कम से कम 'शक्तिशाली' है। चर्च-ट्यूरिंग थीसिस राज्यों एक ट्यूरिंग मशीन कम से कम किसी भी मशीन हम कभी भी निर्माण कर सकते हैं के रूप में शक्तिशाली रूप में है। यह इस प्रकार है कि हर ट्यूरिंग पूरी भाषा ट्यूरिंग मशीन की तरह ही शक्तिशाली है, और इसलिए सभी ट्यूरिंग पूर्ण भाषाएं समान रूप से शक्तिशाली हैं।

दूसरे शब्दों में, जब तक आपकी प्रोग्रामिंग भाषा ट्यूरिंग पूरी हो जाती है (लगभग सभी उनमें से हैं), इससे कोई फर्क नहीं पड़ता कि आप कौन सी भाषा चुनते हैं, क्योंकि वे सभी समान चीजों की गणना कर सकते हैं। इसका मतलब यह भी है कि यह बहुत प्रासंगिक नहीं है कि आप अपने संकलक या अपने दुभाषिया को लिखने के लिए कौन सी प्रोग्रामिंग भाषा चुनते हैं। अंतिम लेकिन कम से कम, इसका मतलब है कि आप हमेशा भाषा X से Y तक एक कंपाइलर लिख सकते हैं यदि X और Y दोनों ट्यूरिंग पूर्ण हैं।

ध्यान दें कि ट्यूरिंग पूर्ण होने से इस बात के बारे में कुछ नहीं कहा जाता है कि आपकी भाषा कुशल है, और न ही आपके सीपीयू और अन्य हार्डवेयर के सभी कार्यान्वयन विवरणों, या आपके द्वारा भाषा के लिए उपयोग किए जाने वाले कंपाइलर की गुणवत्ता के बारे में। इसके अलावा, आपका ऑपरेटिंग सिस्टम यह तय कर सकता है कि आपके प्रोग्राम के पास फ़ाइल खोलने के अधिकार नहीं हैं, लेकिन इससे कुछ भी गणना करने की आपकी क्षमता बाधित नहीं होती है - मैंने जानबूझकर कंप्यूटिंग को परिभाषित नहीं किया है, क्योंकि यह पाठ की एक और दीवार ले जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.