2009-04-30 3 views
7

स्टैकलेस वीएम द्वारा मेरा मतलब है कार्यान्वयन जो सिस्टम "सी-स्टैक" का उपयोग करने के बजाय ढेर पर अपना खुद का ढेर रखता है। इसमें निरंतरता और क्रमिक स्थिति जैसे कई फायदे हैं, लेकिन सी-बाइंडिंग की बात करते समय कुछ नुकसान भी हैं, खासकर सी-वीएम-सी कॉलबैक (या वीएम-सी-वीएम) के लिए।क्या सी-एकीकरण समस्याएं बेकार वीएम कार्यान्वयन के साथ उत्पन्न होती हैं?

प्रश्न यह है कि वास्तव में ये नुकसान क्या हैं? क्या कोई वास्तविक समस्या का अच्छा उदाहरण दे सकता है?

उत्तर

5

ऐसा लगता है कि आप कुछ नुकसान और फायदों से पहले ही परिचित हैं।

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

पर हाल ही में सी # में एक सरल "योजना" दुभाषिया लिखा था, जिसने शुरुआत में .NET स्टैक का उपयोग किया था। मैं तो एक स्पष्ट ढेर उपयोग करने के लिए फिर से लिखा था यह - तो शायद निम्नलिखित तुम्हारी मदद करेगा:

पहले संस्करण निहित .NET रनटाइम ढेर इस्तेमाल किया ...

प्रारंभ में, यह सिर्फ एक वर्ग पदानुक्रम था, विभिन्न रूपों (लैम्ब्डा, आइए, आदि) निम्नलिखित इंटरफेस की जा रही है कार्यान्वयन के साथ:

// A "form" is an expression that can be evaluted with 
// respect to an environment 
// e.g. 
// "(* x 3)" 
// "x" 
// "3" 
public interface IForm 
{ 
    object Evaluate(IEnvironment environment); 
} 

IEnvironment देखा के रूप में आप उम्मीद थी:

/// <summary> 
/// Fundamental interface for resolving "symbols" subject to scoping. 
/// </summary> 
public interface IEnvironment 
{ 
    object Lookup(string name); 
    IEnvironment Extend(string name, object value); 
} 

जोड़ने के लिए "

/// <summary> 
/// A function is either a builtin function (i.e. implemented directly in CSharp) 
/// or something that's been created by the Lambda form. 
/// </summary> 
public interface IFunction 
{ 
    object Invoke(object[] args); 
} 

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

तो मैं इसे एक स्पष्ट (ढेर आवंटित) ढेर के लिए फिर से लिखता हूं।

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

/// <summary> 
/// A function that wishes to use the thread state to 
/// evaluate its arguments. The function should either: 
/// a) Push tasks on to threadState.Pending which, when evaluated, will 
/// result in the result being placed on to threadState.Results 
/// b) Push its result directly on to threadState.Results 
/// </summary> 
public interface IStackFunction 
{ 
    void Evaluate(IThreadState threadState, object[] args); 
} 

और iform करने के लिए बदल :

public interface IForm 
{ 
    void Evaluate(IEnvironment environment, IThreadState s); 
} 

IThreadState इस प्रकार कहाँ है के रूप में:

/// <summary> 
/// The state of the interpreter. 
/// The implementation of a task which takes some arguments, 
/// call them "x" and "y", and which returns an argument "z", 
/// should follow the following protocol: 
/// a) Call "PopResult" to get x and y 
/// b) Either 
/// i) push "z" directly onto IThreadState using PushResult OR 
/// ii) push a "task" on to the stack which will result in "z" being 
///  pushed on to the result stack. 
/// 
/// Note that ii) is "recursive" in its definition - that is, a task 
/// that is pushed on to the task stack may in turn push other tasks 
/// on the task stack which, when evaluated, 
/// ... ultimately will end up pushing the result via PushResult. 
/// </summary> 
public interface IThreadState 
{ 
    void PushTask(ITask task); 
    object PopResult(); 
    void PushResult(object result); 
} 

और ITask है:

public interface ITask 
{ 
    void Execute(IThreadState s); 
} 

और अपने मुख्य "घटना" पाश है:

ThreadState threadState = new ThreadState(); 
threadState.PushTask(null); 
threadState.PushTask(new EvaluateForm(f, environment)); 
ITask next = null; 

while ((next = threadState.PopTask()) != null) 
    next.Execute(threadState); 

return threadState.PopResult(); // Get what EvaluateForm evaluated to 

EvaluateForm सिर्फ एक काम है कि एक विशेष वातावरण के साथ IForm.Evaluate कॉल है।

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

असल में, आप अंतर्निहित भाषा कार्यान्वयन पर केवल कम निर्भर हैं।

मुझे केवल एक ही नकारात्मक पक्ष के बारे में पता चल सकता है ... लेकिन मेरे मामले में, यह सिर्फ एक दुभाषिया है इसलिए मुझे प्रदर्शन के बारे में बहुत कुछ परवाह नहीं है।

मैं भी की फिर से लिखने के एक ढेर के साथ पुनरावृत्ति कोड के रूप में पुनरावर्ती कोड, काई सी ++ संकलक के लेखकों में से एक द्वारा लाभ पर यह बहुत ही अच्छा लेख के लिए आप बात करेंगे: Considering Recursion

+0

दरअसल, प्रश्न मूल कोड एकीकरण पर विचार करने के लिए डाउनसाइड्स के बारे में था। लेकिन कहानी के लिए धन्यवाद। –

1

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

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

इसका मतलब यह नहीं है कि आप किसी भी परिस्थिति में वीएम राज्य को सही ढंग से बहाल कर सकते हैं, लेकिन कम से कम, आप इसके ऊपर अपनी खुद की विश्वसनीय प्रणाली बना सकते हैं।

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