প্রোগ্রামিং ভাষা কীভাবে কার্যকারিতা সংজ্ঞায়িত করে?


28

প্রোগ্রামিং ভাষা কীভাবে কার্য / পদ্ধতিগুলি সংজ্ঞায়িত এবং সংরক্ষণ করে? আমি রুবিতে একটি ব্যাখ্যাযুক্ত প্রোগ্রামিং ল্যাঙ্গুয়েজ তৈরি করছি, এবং আমি কীভাবে ফাংশন ঘোষণাটি বাস্তবায়িত করব তা নির্ধারণ করার চেষ্টা করছি।

আমার প্রথম ধারণাটি হ'ল ঘোষণার সামগ্রীটি একটি মানচিত্রে সংরক্ষণ করা। উদাহরণস্বরূপ, যদি আমি এমন কিছু করি

def a() {
    callSomething();
    x += 5;
}

তারপরে আমি আমার মানচিত্রে একটি এন্ট্রি যুক্ত করব:

{
    'a' => 'callSomething(); x += 5;'
}

এর সাথে সমস্যাটি হ'ল এটি পুনরাবৃত্ত হয়ে উঠবে, কারণ আমার parseস্ট্রিংয়ে আমার পদ্ধতিটি কল parseকরতে হবে, যা পরে যখন পুনরায় কল করবে তখন এটির মুখোমুখি হবে doSomethingএবং পরে আমি স্ট্যাকের জায়গাটি শেষ পর্যন্ত ছুটতে পারব।

সুতরাং, ব্যাখ্যা করা ভাষাগুলি কীভাবে এটি পরিচালনা করে?


ওহ, এবং এটি প্রোগ্রামার্স.এসইতে আমার প্রথম পোস্ট, সুতরাং দয়া করে আমাকে জানান যে আমি যদি কিছু ভুল করছি বা এটি বিষয়বস্তু না। :)
ডোরকনব

অতীতে আমি আমার টোকেনগুলির মধ্যে সেগুলি সমস্ত ইনলাইন সঞ্চিত করেছি এবং ফাংশন কলগুলি একটি নির্দিষ্ট অফসেটে কেবল লাফিয়ে যায় (অনেকটা সমাবেশে লেবেলের মতো)। আপনি স্ক্রিপ্ট টোকনাইজিং করছেন? নাকি প্রতিবার স্ট্রিং পার্সিং করছেন?
সাইমন হোয়াইটহেড

@ সিমনওহাইটহেড আমি স্ট্রিংটিকে টোকেনে বিভক্ত করেছি এবং তারপরে প্রতিটি টোকেনকে আলাদাভাবে পার্স করব।
দুরকনব

3
আপনি যদি প্রোগ্রামিং ভাষার নকশা এবং বাস্তবায়নে নতুন হন তবে আপনি এই বিষয়টির কিছু সাহিত্য পরীক্ষা করতে চাইতে পারেন। সর্বাধিক জনপ্রিয় একটি হ'ল "ড্রাগন বুক": এন.ইউইকিপিডিয়া.আর / উইকি / , তবে আরও কয়েকটি সংক্ষিপ্ত পাঠ রয়েছে যা খুব ভাল। উদাহরণস্বরূপ, আর্ন রান্তা দ্বারা প্রোগ্রামিং ল্যাঙ্গুয়েজগুলি বাস্তবায়ন এখানে নিখরচায় পাওয়া যাবে: bit.ly/15CF6gC
অশ্বচালনাবিগ

1
@ ডিয়ার ধন্যবাদ! আমি বিভিন্ন ভাষায় একটি লিসপ ইন্টারপ্রেটারের জন্য গুগল করেছি এবং এটি সত্যই সহায়তা করেছিল। :)
ডোরকনব

উত্তর:


31

আপনার "পার্স" ফাংশনটি কেবল কোডকে বিশ্লেষণ করে না একই সাথে এটি কার্যকর করে তা অনুমান করে আমি কি সঠিক হতে পারি? আপনি যদি সেভাবে এটি করতে চান তবে আপনার মানচিত্রে কোনও ফাংশনের বিষয়বস্তু সংরক্ষণের পরিবর্তে ফাংশনের অবস্থানটি সংরক্ষণ করুন ।

তবে এর থেকে আরও ভাল উপায় আছে। সামনের দিকে সামান্য বেশি প্রচেষ্টা লাগবে, তবে জটিলতা বাড়ার সাথে আরও ভাল ফলাফল পাওয়া যায়: একটি বিমূর্ত সিনট্যাক্স ট্রি ব্যবহার করুন।

প্রাথমিক ধারণাটি হ'ল আপনি একবারে কোডটি একবারে পার্স করেছেন ever তারপরে আপনার কাছে ক্রিয়াকলাপ এবং মানগুলির প্রতিনিধিত্বকারী ডেটা ধরণের একটি সেট রয়েছে এবং আপনি সেগুলির মতো একটি গাছ তৈরি করেন:

def a() {
    callSomething();
    x += 5;
}

হয়ে:

Function Definition: [
   Name: a
   ParamList: []
   Code:[
      Call Operation: [
         Routine: callSomething
         ParamList: []
      ]
      Increment Operation: [
         Operand: x
         Value: 5
      ]
   ]
]

(এটি একটি অনুমানিক এএসটির কাঠামোর কেবল একটি পাঠ্য উপস্থাপনা is প্রকৃত গাছটি সম্ভবত পাঠ্য আকারে হবে না)) যাইহোক, আপনি নিজের কোডটি একটি এএসটিতে ভাগ করে নিন, এবং তারপরে আপনি হয় আপনার এএসটি-র মাধ্যমে সরাসরি আপনার দোভাষীকে চালাবেন, বা কিছু আউটপুট ফর্ম এএসটি রূপান্তর করতে একটি দ্বিতীয় ("কোড জেনারেশন") পাস ব্যবহার করুন।

আপনার ভাষার ক্ষেত্রে, আপনি সম্ভবত যা করবেন তা হ'ল একটি মানচিত্র যা ফাংশন নামের পরিবর্তে ফাংশন স্ট্রিংয়ের পরিবর্তে এএসটি ফাংশনের নামগুলি ম্যাপ করে।


ঠিক আছে, তবে সমস্যাটি এখনও রয়েছে: এটি পুনরাবৃত্তি ব্যবহার করে। আমি যদি এই কাজটি করি তবে অবশেষে আমি স্ট্যাক স্পেস ছেড়ে চলে যাব।
দুরকনব

3
@ ডুরকনব: বিশেষত পুনরাবৃত্তি কী ব্যবহার করে? যে কোনও ব্লক-স্ট্রাকচার্ড প্রোগ্রামিং ল্যাঙ্গুয়েজ (যা এএসএমের তুলনায় উচ্চ স্তরের প্রতিটি আধুনিক ভাষা) প্রকৃতিগতভাবে গাছ-ভিত্তিক এবং প্রকৃতির পুনরাবৃত্ত হয়। স্ট্যাকের ওভারফ্লোগুলি সম্পর্কে সুনির্দিষ্ট কোন দিকটি আপনি উদ্বিগ্ন?
ম্যাসন হুইলার

1
@ ডুরকনব: হ্যাঁ, এটি কোনও ভাষার অন্তর্নিহিত সম্পত্তি, এমনকি এটি মেশিন কোডে সংকলিত হলেও। (কল স্ট্যাকটি এই আচরণেরই বহিঃপ্রকাশ)) আমি আসলে কোনও স্ক্রিপ্ট সিস্টেমে অবদানকারী যা আমার বর্ণনার মতো কাজ করে। Chat.stackexchange.com/rooms/10470/…চ্যাটে আমার সাথে যোগ দিন এবং আমি আপনার সাথে স্ট্যাকের আকারের প্রভাব হ্রাস এবং দক্ষতা ব্যাখ্যা করার জন্য কিছু কৌশল নিয়ে আলোচনা করব। :)
ম্যাসন হুইলার

2
@ ডুরকনব: এখানে কোনও পুনরাবৃত্তি সমস্যা নেই কারণ এটিএসটিতে ফাংশন কল নাম অনুসারে ফাংশনটি উল্লেখ করছে , এটি প্রকৃত ফাংশনটির জন্য কোনও রেফারেন্সের প্রয়োজন নেই । আপনি যদি মেশিন কোডে সংকলন করে থাকেন তবে শেষ পর্যন্ত আপনার ফাংশন ঠিকানা প্রয়োজন হবে, এজন্য বেশিরভাগ সংকলক একাধিক পাস করেন। আপনি যদি একটি পাসের সংকলক রাখতে চান তবে আপনার সমস্ত ফাংশনের "ফরওয়ার্ড ডিক্লেয়ারেশন" দরকার যাতে সংকলকটি আগেই ঠিকানাগুলি নির্ধারণ করতে পারে। বাইটকোড সংকলকরা এটি নিয়েও মাথা ঘামায় না, জিটারটি নাম সন্ধানকে পরিচালনা করে।
অ্যারোনআউট

5
@ ডুরকনব: এটি আসলে পুনরাবৃত্তিযোগ্য। এবং হ্যাঁ, যদি আপনার স্ট্যাকের কেবল 16 টি এন্ট্রি থাকে তবে আপনি বিশ্লেষণ করতে ব্যর্থ হবেন (((((((((((((((( x )))))))))))))))))। বাস্তবে, স্ট্যাকগুলি অনেক বেশি বড় হতে পারে এবং বাস্তব কোডটির ব্যাকরণগত জটিলতা বেশ সীমাবদ্ধ। অবশ্যই যদি সেই কোডটি মানব-পঠনযোগ্য হতে হয়।
MSalters

4

দেখার পরে আপনার পার্স করা উচিত হবে না callSomething()(আমি মনে করি আপনি এর callSomethingচেয়ে বরং বোঝাতে চেয়েছিলেন doSomething)। aএবং এর মধ্যে পার্থক্যটি callSomethingহ'ল একটি হল একটি পদ্ধতি সংজ্ঞা এবং অন্যটি একটি মেথড কল।

আপনি যখন একটি নতুন সংজ্ঞা দেখেন, আপনি যে সংজ্ঞাটি যোগ করতে পারেন তা নিশ্চিত করার সাথে সম্পর্কিত চেকগুলি করতে চান, সুতরাং:

  • একই স্বাক্ষর সহ ফাংশনটি ইতিমধ্যে উপস্থিত নেই কিনা তা পরীক্ষা করুন
  • নিশ্চিত করুন যে পদ্ধতি ঘোষণা যথাযথ স্কোপে করা হচ্ছে (যেমন পদ্ধতিগুলি অন্যান্য পদ্ধতির ঘোষণার মধ্যে ঘোষণা করা যেতে পারে?)

এই চেকগুলি পাস বলে ধরে নিয়েছেন, আপনি এটি আপনার মানচিত্রে যুক্ত করতে পারেন এবং সেই পদ্ধতির সামগ্রীগুলি পরীক্ষা করতে শুরু করতে পারেন।

আপনি যখন কোনও মেথড কলের মতো সন্ধান করেন callSomething(), আপনার নিম্নলিখিত চেকগুলি করা উচিত:

  • না callSomethingআপনার মানচিত্রে বিদ্যমান?
  • এটি কি সঠিকভাবে বলা হচ্ছে (যুক্তিগুলির সংখ্যা আপনি যে স্বাক্ষরের সাথে মিলেছেন)?
  • যুক্তিগুলি কি বৈধ (যদি পরিবর্তনশীল নাম ব্যবহার করা হয়, তবে তারা কি ঘোষিত হয়? তারা কি এই সুযোগে অ্যাক্সেস করা যায়?)?
  • আপনি যেখানে আছেন সেখান থেকে কলসামিংয়ের জন্য কিছু কল করা যেতে পারে (এটি কি ব্যক্তিগত, সর্বজনীন, সুরক্ষিত?)

যদি আপনি এটি callSomething()ঠিকঠাক পেয়ে থাকেন তবে এই মুহুর্তে আপনি কী করতে চান তা নির্ভর করে আপনি কীভাবে এটির কাছে যেতে চান তার উপর নির্ভর করে। কড়া কথায় বলতে গেলে, আপনি যদি জানতে পারবেন যে এই মুহুর্তে এই জাতীয় কল ঠিক আছে, আপনি কেবল বিশদটি না নিয়ে কেবল পদ্ধতি এবং যুক্তিগুলির নাম সংরক্ষণ করতে পারবেন। আপনি যখন আপনার প্রোগ্রামটি চালাবেন, আপনি রানটাইমের সময় আপনার থাকা উচিত যুক্তিগুলির সাথে পদ্ধতিটি উপস্থাপন করবেন।

আপনি যদি আরও যেতে চান তবে আপনি কেবল স্ট্রিংই নয় বরং আসল পদ্ধতির একটি লিঙ্ক সংরক্ষণ করতে পারেন। এটি আরও কার্যকর হবে তবে আপনার যদি মেমরি পরিচালনা করতে হয় তবে এটি বিভ্রান্তিকর হতে পারে। আমি আপনাকে প্রথমে স্ট্রিংটি ধরে রাখার পরামর্শ দিচ্ছি। পরে আপনি অনুকূলিত করার চেষ্টা করতে পারেন।

মনে রাখবেন যে এই সব অভিমানী যে আপনি আপনার প্রোগ্রাম, যার মানে আপনি আপনার প্রোগ্রামে সব টোকেন স্বীকৃত এবং জানতে পারে তারা কি আছে lexxed করেছি হয় । এর অর্থ এই নয় যে তারা জানেন যে তারা এখনও একসাথে অর্থ বোধ করে, যা পার্সিং পর্ব। যদি আপনি এখনও টোকেনগুলি কী তা জানেন না, তবে আমি আপনাকে প্রথমে সেই তথ্যটি পাওয়ার আগে মনোযোগ দেওয়ার পরামর্শ দিই।

আমি আশা করি এটি সাহায্য করবে! প্রোগ্রামার এসই তে আপনাকে স্বাগতম!


2

আপনার পোস্ট পড়া, আমি আপনার প্রশ্নের দুটি প্রশ্ন লক্ষ্য। সর্বাধিক গুরুত্বপূর্ণটি হল কীভাবে পার্স করা যায়। এখানে অনেক ধরণের পার্সার রয়েছে (যেমন রিকার্সিভ ডেসেন্ট পার্সার , এলআর পার্সার্স , প্যাক্র্যাট পার্সারস ) এবং পার্সার জেনারেটর (যেমন জিএনইউ বাইসন , এএনটিএলআর ) আপনি একটি পাঠ্য প্রোগ্রামকে "পুনরাবৃত্ত" ব্যাকরণ প্রদত্ত ব্যবহার করতে পারেন।

দ্বিতীয় প্রশ্নটি ফাংশনগুলির জন্য স্টোরেজ ফর্ম্যাট সম্পর্কে। আপনি যখন সিনট্যাক্স-নির্দেশিত অনুবাদ করছেন না , আপনি নিজের প্রোগ্রামটির একটি অন্তর্বর্তী উপস্থাপনা তৈরি করেন যা এটির সাথে আরও প্রক্রিয়া করার জন্য একটি বিমূর্ত সিনট্যাক্স ট্রি বা কিছু কাস্টম মধ্যবর্তী ভাষা হতে পারে (সংকলন, রূপান্তর, সম্পাদন, লেখালেখি একটি ফাইল, ইত্যাদি)।


1

জেনেরিক দৃষ্টিকোণ থেকে, কোনও ফাংশনের সংজ্ঞা কোডে লেবেল বা বুকমার্কের চেয়ে কিছুটা বেশি। বেশিরভাগ অন্যান্য লুপ, স্কোপ এবং শর্তসাপেক্ষ অপারেটরগুলি একই রকম; তারা বিমূর্ততার নিম্ন স্তরের বেসিক "জাম্প" বা "গোটো" কমান্ডের জন্য স্ট্যান্ড-ইনস। একটি ফাংশন কলটি মূলত নিম্নলিখিত নিম্ন-স্তরের কম্পিউটার কমান্ডগুলিতে সিদ্ধ হয়:

  • "কল স্ট্যাক ফ্রেম" হিসাবে পরিচিত একটি কাঠামোতে সমস্ত পরামিতিগুলির ডেটা, এবং বর্তমান ফাংশনের পরবর্তী নির্দেশের পয়েন্টার সংযুক্ত করুন।
  • কল স্ট্যাকের উপর এই ফ্রেমটি পুশ করুন।
  • ফাংশনের কোডের প্রথম লাইনের মেমরি অফসেটে ঝাঁপুন।

একটি "রিটার্ন" বিবৃতি বা অনুরূপ নিম্নলিখিতগুলি করবে:

  • একটি রেজিস্টারে ফেরতের জন্য মানটি লোড করুন।
  • কলকারীকে একটি রেজিস্টারে পয়েন্টারটি লোড করুন।
  • বর্তমান স্ট্যাক ফ্রেমটি পপ করুন।
  • কলারের নির্দেশকের দিকে ঝাঁপুন।

কাজগুলি, তাই কেবল উচ্চ স্তরের ভাষার নির্দিষ্টকরণে বিমূর্ততা, যা মানুষকে আরও রক্ষণাবেক্ষণযোগ্য এবং স্বজ্ঞাত উপায়ে কোড সংগঠিত করতে দেয়। যখন কোনও অ্যাসেম্বলি বা মধ্যবর্তী ভাষার (জিল, এমএসআইএল, আইএলএক্স) সংকলন করা হয় এবং অবশ্যই মেশিন কোড হিসাবে রেন্ডার করা হয়, তখন প্রায় সমস্ত বিমূর্ততা চলে যায়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.