फ़ंक्शन कॉल शब्दार्थ का प्रतिनिधित्व करने के लिए स्टैक का उपयोग करने के लिए कौन से विकल्प हैं?


19

हम सभी जानते हैं और प्यार करते हैं कि फ़ंक्शन कॉल आमतौर पर स्टैक का उपयोग करके कार्यान्वित किया जाता है; फ़्रेम, रिटर्न एड्रेस, पैरामीटर, पूरे लॉट हैं।

हालांकि, स्टैक एक कार्यान्वयन विवरण है: कॉलिंग कन्वेंशन अलग-अलग चीजें कर सकते हैं (यानी x86 फास्टकॉल का उपयोग करता है (कुछ) रजिस्टर, एमआइपी और अनुयायी रजिस्टर विंडो का उपयोग करते हैं, और इसी तरह) और अनुकूलन भी अन्य चीजें कर सकते हैं (इनलाइनिंग, फ्रेम पॉइंटर चूक) पूंछ-कॉल अनुकूलन ..)।

ज़रूर, कई मशीनों पर सुविधाजनक स्टैक इंस्ट्रक्शन की मौजूदगी (VMs जैसे JVM और CLR, लेकिन असली मशीनें जैसे x86 जैसे कि उनके PUSH / POP आदि) भी इसे फ़ंक्शन कॉल के लिए उपयोग करने के लिए सुविधाजनक बनाते हैं, लेकिन कुछ मामलों में यह संभव है। इस तरह से प्रोग्राम करने के लिए जिसमें कॉल स्टैक की जरूरत नहीं है (मैं यहां कंटीन्यूएशन पासिंग स्टाइल के बारे में सोच रहा हूं, या एक्टर्स इन द मेसेज पासिंग सिस्टम)

तो, मुझे आश्चर्य हो रहा था: क्या एक स्टैक के बिना फ़ंक्शन कॉल शब्दार्थ को लागू करना संभव है, या बेहतर है, एक अलग डेटा संरचना (एक कतार, शायद, या एक साहचर्य मानचित्र?)
का उपयोग करके , मैं समझता हूं कि एक स्टैक बहुत है? सुविधाजनक (एक कारण है कि यह सर्वव्यापी क्यों है) लेकिन मैं हाल ही में एक कार्यान्वयन में टकरा गया जिसने मुझे आश्चर्यचकित कर दिया।

क्या आप में से किसी को पता है कि क्या यह कभी किसी भाषा / मशीन / आभासी मशीन में किया गया है, और यदि ऐसा है तो हड़ताली मतभेद और कमियां हैं?

संपादित करें: मेरी आंत की भावनाएं हैं कि विभिन्न उप-संगणना दृष्टिकोण विभिन्न डेटा संरचनाओं का उपयोग कर सकते हैं। उदाहरण के लिए, लैम्ब्डा कैलकुलस स्टैक आधारित नहीं है (फ़ंक्शन एप्लिकेशन के विचार में कटौती द्वारा कब्जा कर लिया गया है) लेकिन मैं एक वास्तविक भाषा / मशीन / उदाहरण देख रहा था। इसलिए मैं पूछ रहा हूँ ...


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

वर्चुअल मशीनों के लिए, एक लिंक की गई सूची का उपयोग किया जा सकता है। सूची का प्रत्येक नोड एक फ्रेम है। चूंकि वीएम द्वारा हार्डवेयर स्टैक का उपयोग किया जाता है, यह फ्रेम को ओवरहेड के बिना ढेर पर मौजूद होने की अनुमति देता है realloc()
shawnhcorey

जवाबों:


19

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

फोरट्रान IV (और पहले) और उन भाषाओं के उदाहरणों के लिए COBOL के शुरुआती संस्करणों का संदर्भ लें जिनमें कॉल स्टैक्स की आवश्यकता नहीं है।

अत्यधिक सफल शुरुआती सुपर कंप्यूटर के उदाहरण के लिए कंट्रोल डेटा 6600 (और पहले कंट्रोल डेटा मशीन) का संदर्भ लें जो कॉल स्टैक के लिए प्रत्यक्ष हार्डवेयर समर्थन प्रदान नहीं करता है। पीडीपी -8 का संदर्भ लें एक बहुत ही सफल प्रारंभिक मिनीकंप्यूटर के उदाहरण के लिए जो कॉल स्टैक का समर्थन नहीं करता था।

जहाँ तक मुझे पता है, बरोज़ बी 5000 स्टैक मशीन हार्डवेयर कॉल स्टैक वाली पहली मशीनें थीं। B5000 मशीनों को ALGOL चलाने के लिए जमीन से डिजाइन किया गया था, जिसे पुनरावृत्ति की आवश्यकता थी। उनके पास पहले डिस्क्रिप्टर-आधारित आर्किटेक्चर में से एक था, जिसने क्षमता आर्किटेक्चर के लिए नींव रखी थी।

जहाँ तक मुझे पता है, यह PDP-6 (जो कि DEC-10 में विकसित हुआ) ने कॉल स्टैक हार्डवेयर को लोकप्रिय बनाया, जब MIT के हैकर समुदाय ने एक की डिलीवरी ली और पता चला कि PUSHJ (पुश रिटर्न एड्रेस और जंप): ऑपरेशन दशमलव प्रिंट दिनचर्या को 50 निर्देशों से घटाकर 10 करने की अनुमति दी।

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

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

एबेल्सन और सुस्मैन की "संरचना और कंप्यूटर प्रोग्राम की व्याख्या" निरंतरता पर कुछ विस्तार में जाती है।


2
यह एक महान ऐतिहासिक अंतर्दृष्टि थी, धन्यवाद! जब मैंने अपना प्रश्न पूछा, तो मेरे मन में वास्तव में निरंतरता थी, विशेष रूप से निरंतरता-गुजर शैली (सीपीएस)। उस मामले में, एक स्टैक न केवल असुविधाजनक है, बल्कि संभवतः आवश्यक नहीं है: आपको यह याद रखने की आवश्यकता नहीं है कि कहां वापस लौटना है, आप एक बिंदु प्रदान करते हैं जहां अपना निष्पादन जारी रखना है। मुझे आश्चर्य है कि अगर अन्य स्टैक-कम दृष्टिकोण आम हैं, और आपने कुछ बहुत अच्छे दिए, जिनके बारे में मुझे जानकारी नहीं थी।
लोरेंजो डेमेटे

थोड़ा संबंधित: आपने सही ढंग से कहा "अगर भाषा पुनरावृत्ति की अनुमति नहीं देती है"। पुनरावृत्ति के साथ भाषा के बारे में, विशेष कार्यों में जो पूंछ-पुनरावर्ती नहीं हैं? क्या उन्हें "डिजाइन द्वारा" स्टैक की आवश्यकता है?
लोरेंजो डेमेटे

"कॉल स्टैक केवल उन भाषाओं में आवश्यक हैं जो पुनरावृत्ति या पारस्परिक पुनरावृत्ति की अनुमति देते हैं" - नहीं। यदि किसी फ़ंक्शन को एक से अधिक स्थानों से कॉल किया जा सकता है (जैसे दोनों fooऔर barकॉल कर सकते हैं baz), तो फ़ंक्शन को यह जानना होगा कि किस पर वापस लौटना है। यदि आप इस घोंसले को "जो" जानकारी पर वापस लौटना चाहते हैं, तो आप एक ढेर के साथ समाप्त होते हैं। इससे कोई फर्क नहीं पड़ता कि आप इसे क्या कहते हैं या अगर यह सीपीयू के हार्डवेयर द्वारा समर्थित है या कुछ ऐसा है जिसका आप सॉफ्टवेयर में अनुकरण करते हैं (या इसके स्टैटिकली आवंटित प्रविष्टियों की लिंक की गई सूची), तो भी यह एक स्टैक है।
ब्रेंडन

@ ब्रेंडन जरूरी नहीं (कम से कम, यह मेरे सवाल का पूरा उद्देश्य है)। "कहाँ वापस जाना है" या बेहतर "अगले कहाँ जाना है" क्या यह एक स्टैक होने की आवश्यकता है, अर्थात एक एलआईएफओ संरचना? क्या यह एक पेड़, एक नक्शा, एक कतार या कुछ और हो सकता है?
लोरेंजो डेमेटे

उदाहरण के लिए, मेरी आंत की भावनाएं हैं कि सीपीएस को केवल एक पेड़ की जरूरत है, लेकिन मुझे यकीन नहीं है, और न ही मुझे पता है कि कहां देखना है। इसलिए मैं पूछ रहा हूँ ..
लोरेंजो डेमेटे

6

कुछ प्रकार के स्टैक का उपयोग किए बिना फ़ंक्शन कॉल सिमेंटिक्स को लागू करना संभव नहीं है। केवल शब्द का खेल खेलना संभव है (उदाहरण के लिए इसके लिए एक अलग नाम का उपयोग करें, जैसे "FILO रिटर्न बफर")।

ऐसा कुछ उपयोग करना संभव है जो फ़ंक्शन कॉल सिमेंटिक्स को लागू नहीं करता है (जैसे निरंतर गुजर शैली, अभिनेता), और फिर इसके ऊपर फ़ंक्शन कॉल शब्दार्थ का निर्माण करें; लेकिन इसका मतलब यह है कि फ़ंक्शन के वापस आने पर नियंत्रण को ट्रैक करने के लिए किसी प्रकार की डेटा संरचना को जोड़ना, और यह कि डेटा संरचना एक प्रकार का स्टैक होगा (या एक अलग नाम / विवरण के साथ एक स्टैक)।

कल्पना कीजिए कि आपके पास कई कार्य हैं जो सभी एक दूसरे को कॉल कर सकते हैं। रन-टाइम पर, प्रत्येक फ़ंक्शन को पता होना चाहिए कि फ़ंक्शन से बाहर निकलने के लिए कहां वापस लौटना है। यदि आपके पास firstकॉल है secondतो आपके पास:

second returns to somewhere in first

फिर, यदि आपके पास secondकॉल thirdहै:

third returns to somewhere in second
second returns to somewhere in first

फिर, यदि आपके पास thirdकॉल fourthहै:

fourth returns to somewhere in third
third returns to somewhere in second
second returns to somewhere in first

जैसा कि प्रत्येक फ़ंक्शन को कहा जाता है, अधिक "कहां लौटना है" जानकारी को कहीं संग्रहीत किया जाना चाहिए।

यदि कोई फ़ंक्शन वापस आता है, तो इसकी "जहां लौटने के लिए" जानकारी का उपयोग किया जाता है और अब इसकी आवश्यकता नहीं है। उदाहरण के लिए, यदि fourthकहीं वापस लौटा जाता है thirdतो "कहाँ वापस लौटना है" की मात्रा बन जाएगी:

third returns to somewhere in second
second returns to somewhere in first

मूल रूप से; "फ़ंक्शन कॉल शब्दार्थ" का तात्पर्य है:

  • आपके पास "कहाँ वापस लौटना है" जानकारी होनी चाहिए
  • फ़ंक्शन के रूप में जानकारी की मात्रा बढ़ती है और फ़ंक्शन वापस आने पर कम हो जाती है
  • संग्रहीत जानकारी "जहां वापस लौटना है" का पहला टुकड़ा "जहां वापस लौटने के लिए" जानकारी को छोड़ दिया गया, का अंतिम टुकड़ा होगा

यह एक FILO / LIFO बफर या स्टैक का वर्णन करता है।

यदि आप एक प्रकार के पेड़ का उपयोग करने का प्रयास करते हैं, तो पेड़ में प्रत्येक नोड में एक से अधिक बच्चे नहीं होंगे। नोट: कई बच्चों के साथ एक नोड केवल तभी हो सकता है जब कोई फ़ंक्शन एक ही समय में 2 या अधिक फ़ंक्शन कॉल करता है , जिसके लिए किसी प्रकार की संगामिति (उदाहरण के लिए थ्रेड, कांटा (), आदि) की आवश्यकता होती है और यह "फ़ंक्शन कॉल शब्दार्थ" नहीं होगा। यदि पेड़ में प्रत्येक नोड में एक से अधिक बच्चे नहीं होंगे; फिर उस "पेड़" का उपयोग केवल फिलो / लिफो बफर या स्टैक के रूप में किया जाएगा; और क्योंकि यह केवल एक फिलो / LIFO बफर या स्टैक के रूप में उपयोग किया जाता है, यह दावा करना उचित है कि "ट्री" एक स्टैक है (और केवल अंतर शब्द गेम और / या कार्यान्वयन विवरण है)।

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

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

नोट: यदि किसी भी प्रक्रिया का केवल एक ही आह्वान किसी भी समय सक्रिय हो सकता है; फिर आप "जहां वापस लौटने के लिए" जानकारी के लिए सांख्यिकीय रूप से स्थान आवंटित कर सकते हैं। यह अभी भी एक स्टैक है (उदाहरण के लिए एक FILO / LIFO रास्ते में प्रयुक्त सांख्यिकीय रूप से आवंटित प्रविष्टियों की एक लिंक की गई सूची)।

यह भी ध्यान दें कि कुछ चीजें हैं जो "फ़ंक्शन कॉल शब्दार्थ" का पालन नहीं करती हैं। इन चीजों में "संभावित रूप से बहुत अलग शब्दार्थ" (जैसे निरंतरता गुजरना, अभिनेता मॉडल) शामिल हैं; और समसामयिक एक्सटेंशन जैसे "फ़ंक्शन कॉल शब्दार्थ" को सम्‍मिलित करें (थ्रेड्स, फ़ाइबर, जो भी हो), setjmp/ longjmp, अपवाद हैंडलिंग, आदि शामिल हैं।


परिभाषा के अनुसार, एक स्टैक एक LIFO संग्रह है: अंतिम में, पहले बाहर। एक कतार एक FIFO संग्रह है।
जॉन आर। स्ट्रोम

तो क्या एक स्टैक केवल स्वीकार्य डेटा संरचना है? यदि हां, तो क्यों?
लोरेंजो डेमेटे

@ JohnR.Strohm: फिक्स्ड :-)
ब्रेंडन

1
पुनरावृत्ति (प्रत्यक्ष या पारस्परिक) के बिना भाषाओं के लिए, प्रत्येक विधि के लिए सांख्यिकीय रूप से आवंटित करना संभव है एक चर जो उस स्थान की पहचान करेगा जहां से उस पद्धति को अंतिम रूप से बुलाया गया था। यदि लिंकर को ऐसी चीजों के बारे में पता है, तो यह एक फैशन में ऐसे चर को आवंटित कर सकता है जो कि एक स्टैक क्या करेंगे, इससे ज्यादा बुरा नहीं होगा अगर हर सांख्यिकीय-संभव निष्पादन पथ वास्तव में लिया गया था
सुपरकैट

4

खिलौना संघात्मक भाषा XY निष्पादन के लिए कॉल-क्यू और डेटा स्टैक का उपयोग करती है।

प्रत्येक संगणना कदम में बस अगले शब्द को निष्पादित करना और बिल्डरों के मामले में शामिल करना शामिल है, यह आंतरिक कार्य को फीड करता है डेटा स्टैक और कॉल-कतार को तर्क के रूप में, या उपयोगकर्ता के शब्दों के साथ, इसे कतार के सामने लाने वाले शब्दों को धकेलता है।

तो अगर हमारे पास शीर्ष तत्व को दोगुना करने का कोई कार्य है:

; double dup + ;
// defines 'double' to be composed of 'dup' followed by '+'
// dup duplicates the top element of the data stack
// + pops the top two elements and push their sum

फिर रचना कार्य +और dupनिम्नलिखित स्टैक / कतार टाइप हस्ताक्षर हैं:

// X is arbitraty stack, Y is arbitrary queue, ^ is concatenation
+      [X^a^b Y] -> [X^(a + b) Y]
dup    [X^a Y] -> [X^a^a Y]

और विरोधाभास, doubleइस तरह दिखेगा:

double [X Y] -> [X dup^+^Y]

तो एक मायने में, XY स्टैकलेस है।


वाह धन्यवाद! मैं उस पर गौर करूंगा ... निश्चित रूप से यह फ़ंक्शन कॉल पर लागू नहीं होता है, लेकिन फिर भी देखने लायक है
लोरेंजो डेमेटे

1
@ कार्ल दामगार्ड अस्मुसेन "क्युब के सामने इसे लिखने वाले शब्दों को आगे बढ़ाते हुए" "आगे की ओर धकेलते हुए" क्या यह स्टैक नहीं है?

@ guesttttt222222222 वास्तव में नहीं है। एक कॉलस्टैक स्टोर पॉइंटर लौटाता है, और जब फ़ंक्शन वापस आता है, तो कॉलस्टैक पॉप होता है। निष्पादन कतार केवल फ़ंक्शंस को इंगित करती है, और अगले फ़ंक्शन को निष्पादित करते समय, इसे इसकी परिभाषा में विस्तारित किया जाता है और कतार के सामने धकेल दिया जाता है। एक्सवाई में निष्पादन कतार वास्तव में एक धोखा है, क्योंकि ऐसे ऑपरेशन हैं जो निष्पादन कतार के पीछे भी काम करते हैं।
कार्ल दामगार्ड असमसुसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.