لغة برمجة جديدة افعلها بنفسك

مرحبا يا هبر! الذهاب مباشرة إلى هذه النقطة. في الوقت الحالي ، أقرأ كتاب The Dragon Book وأقوم بتطوير مترجم للغة البرمجة الخاصة بي تسمى Lolo (تكريماً لبطريق البطريق من الرسوم الكاريكاتورية السوفيتية اليابانية). أخطط للانتهاء في غضون عام إذا لم يكن هناك شيء مؤلم. في موازاة ذلك ، سأنشر مقتطفات مثيرة للاهتمام من تجربة الترجمة ، وبناء الشفرة الوسيطة ، والتحسين ، وما إلى ذلك ، حسنًا ، اليوم سوف أعرض عليك اللغة. اجلس واذهب.

يتم تجميع اللغة وإلحاحها وليست موجهة نحو الكائن ؛ فقد تم شطب الدلالات اللغوية من C وتكميلها بالعديد من الميزات المفيدة. لنبدأ معهم.

التعديلات الدلالية


مؤشرات آمنة


ربما فكرت في المؤشرات الذكية من Rust في الوقت الحالي ، لكنها ليست كذلك. في لغتي ، يتم توفير سلامة الوصول إلى الذاكرة من قبل اثنين من التعبيرات الاصطلاحية. أولاً: عدم وجود مؤشرات للتراجع عن المؤشرات. بدلاً من ذلك ، عند الوصول إلى المؤشر المعلن ، تتم الإشارة إلى الكائن نفسه. وهذا هو ، يمكنك ويجب أن تكتب مثل هذا:

int # pointer ~~ new int(5) int variable ~ pointer + 7 

يحتوي المتغير المتغير الآن على الرقم 12. الآن ترى بناء جملة غير مألوف ، وربما أنت في حيرة بعض الشيء ، لكنني سأشرح كل شيء في سياق المقال. المصطلح الثاني: قلة العمليات على المؤشرات. مرة أخرى: يتم تنفيذ جميع العمليات عند الوصول إلى المؤشرات ، بما في ذلك التعيين والزيادة والتناقص على الكائنات. العملية الوحيدة التي تتصل مباشرة بالمؤشر هي التعيين حسب العنوان ، أو ، كما أسميها ، التعريف. في مثال التعليمة البرمجية أعلاه ، في السطر الأول ، يتم التحديد بدقة. يمكن تعيين أي مؤشر على عنوان منطقة الذاكرة المخصصة بالفعل فقط ، وهي العملية الجديدة التي يتم إرجاعها. يمكنك أيضًا وضع مؤشر على عنوان متغير آخر مخصص حتى على الكومة ، حتى على المكدس. هنا مثال:

 int variable ~ 5 int # pointer ~~ variable 

هنا "~" هي عملية التعيين المعتادة. يمكنك أيضًا تحديد المؤشرات بمؤشر فارغ خاص. إنه بمثابة مؤشر يشير إلى عنوان فارغ. بعد تحديد عمليات المقارنة والمقارنة على الهوية (العناوين المتطابقة) مع وجود قيمة خالية ، سوف تسفر عن:

 int # pointer ~~ null if (pointer = null) nop ;; true if (pointer == nul) nop ;; true 

هنا "=" هي مقارنة القيم ، "==" هي مقارنة بالعناوين ، "nop" هي عملية فارغة ، وبعد "؛؛" - تعليق. ونعم ، null هي عمليات المؤشر الوحيدة التي يمكن تنفيذها دون التحقق من توافق النوعية.

وبالتالي ، لا يمكن تعيين المؤشرات إلا للذاكرة المخصصة أو المناطق الخالية ولا يمكن نقلها إلى أي مكان. ومع ذلك ، لا تحمي هذه التدابير الحماية الكاملة من أخطاء تجزئة الأخطاء. للحصول عليه ، فقط اتبع الخطوات التالية:

 int # pointer1 ~~ new int(5) int # pointer2 ~~ pointer1 delete pointer1 int variable ~ pointer2 ;; segmentation fault! 

أعتقد أن كل شيء واضح هنا. ولكن لارتكاب مثل هذا الخطأ لا يمكن أن يتم إلا عن قصد ، وبعد ذلك ، عملت بجد. بعد كل شيء ، عملية الحذف تفعل نفس الشيء مثل جامع القمامة ، فقط بأمان أقل. يتحدث عنه ...

جامع القمامة


جامع القمامة - هو أيضًا جامع في لولو. ربما لا حاجة لشرح ما هو عليه. أستطيع فقط أن أقول أنه يمكن تعطيله عن طريق خيار خاص أثناء التحويل البرمجي. لقد اختبرنا البرنامج مع المجمع ، كل شيء يعمل كما ينبغي - يمكنك إدخال الخيار ومحاولة تحسين البرنامج باستخدام إدارة الذاكرة اليدوية.

المدمج في المصفوفات


على الرغم من أنني قلت أن دلالات اللغة يتم شطبها من C ، إلا أن الاختلافات كبيرة جدًا. المصفوفات هنا هي مؤشرات. المصفوفات لها بناء جملة خاص بها وعناوين آمنة. لا ، ليس مع فحص المدى. من الصعب عليهم الحصول على خطأ وقت التشغيل. هذا لأن كل صفيف يخزن الطول في الحجم المتغير ، كما في جافا ، ومع كل فهرسة من الفهرس ... هناك ما تبقى من القسمة بهذا الحجم! قرار غبي ، للوهلة الأولى ، حتى ننظر إلى المؤشرات السلبية. إذا وجدت ما تبقى من القسمة -1 على طول المصفوفة ، فستحصل على رقم يساوي size-1 ، أي العنصر الأكثر تحديدًا. من خلال مثل هذه المناورة ، يمكننا الوصول إلى المؤشرات ليس فقط من البداية ، ولكن أيضًا من نهاية المصفوفة. حيلة أخرى هي أن يلقي أي نوع البدائية إلى مجموعة بايت []. ولكن كيف تحصل على خطأ وقت التشغيل ، تسأل؟ سأترك هذا السؤال لك باعتباره لغزًا سهلًا.

مراجع


لا أعرف على وجه اليقين ما إذا كان معيار C الحالي يشتمل على روابط ، ولكن سيكون بالتأكيد في لولو. ربما يكون نقص المراجع في الإصدارات السابقة من C أحد الأسباب الرئيسية لمؤشرات المؤشرات. هناك حاجة لتمرير الوسائط إلى العنوان ، لإرجاع القيم من الوظائف دون النسخ. يمكن أيضًا تمرير المؤشرات والمصفوفات بالرجوع إليها (لأنه عند المرور بالقيمة ، سيتم نسخ المصفوفات بالكامل ، ولن تحفظ المؤشرات التي تم تعيينها إلى موقع جديد بواسطة ~~ العملية).

خاصية تعدد


كل شيء أكثر جمالا وأكثر جمالا. أنا بالفعل في حب لغتي. هوايته التالية هي تعدد العمليات. بصراحة ، لم أقرر بالكامل الأدوات التي سيتم توفيرها بها. على الأرجح ، الكلمة الرئيسية المتزامنة مع جميع خصائص ala-Java ، وربما الكلمة الأساسية المتزامنة أمام الوظائف غير المضمنة ، مما يعني "تشغيل هذه الوظائف في سلاسل رسائل متوازية".

سلاسل مضمنة


إنها سلاسل ، وليس حرفية سلسلة ، كما في C ++. سيكون لكل سطر طوله الخاص ، وسيحدث الفهرسة مع العثور على الباقي. بشكل عام ، تتشابه السلاسل في Lolo بشكل كبير مع صفائف الأحرف ، باستثناء أن الصفائف لا تحتوي على تسلسل عبر "+" ، والرسوم المتحركة من خلال "*" ، والمقارنات من خلال "<" و ">". وبما أننا نتحدث عن الخطوط ، يجب أن نذكر الشخصيات. الرموز في Lolo ليست أرقامًا ، كما هو الحال في C ++. ولا تحتوي على بايت واحد ، ولكن 4 أحرف DKOTI و 6 أحرف UTF. سأتحدث عن DKOTI في المرة القادمة ، لكن الآن ، أعرف أن Lolo يدعم الحروف والسلاسل في ترميزين. ونعم ، يمكن أن تؤخذ خاصية الطول من الثوابت:

 int len ~ "Hello, world!".length ;; len = 13 

نوع منطقية مع ثلاث قيم


الغالبية العظمى من لغات البرمجة التي لديها نوع بيانات منطقي تستخدم المنطق الثنائي. لكن في لولو ، سيكون الثلاثي ، أو بالأحرى ، الثلاثي الغامض. ثلاث قيم: صواب - صواب ، خطأ - خطأ ، لا شيء - لا شيء. لم أجد حتى الآن لغة العمليات التي لا تُرجع إلى شيء ، لكنني أتذكر العديد من الأمثلة من الممارسة عندما تكون الأعلام ذات القيم الثلاثة مفيدة جدًا. كان لاستخدام التعداد أو نوع عدد صحيح. لم يعد لديك ل. هذا مجرد اسم من هذا النوع لا أستطيع اختيار. الأكثر شيوعًا هو "المنطق" ، ولكنه طويل جدًا. لا تزال الخيارات "luk" تكريما لـ Jan Lukasevich ، و "brus" تكريما لـ N. P. Brusnetsov و "trit" ، ولكن بالمعنى الدقيق للكلمة ، هذا النوع ليس ميزة. بشكل عام ، المسح في نهاية المقال.

قوائم لتهيئة الهياكل والقوائم


إذا ، بعد التصريح عن متغير هيكلي ، وضعت علامة ~ وفتحت الأقواس المربعة ، فيمكنك تعيين قيم حقولها بدوره أو في شكل قاموس. إذا قمت بتنفيذ مثل هذا الإجراء باستخدام صفيف ، فيمكنك تعيين قيم خلاياه ، بدون القاموس. لا يوجد شيء خاص يمكن قوله ، فقط انظر إلى الكود:

 struct { int i; real r; str s; } variable ~ [ i: 5, r: 3.14, s: "Hello!" ] int[5] arr ~ [ 1, 2, 3, 4, 5 ] 


إرجاع قيم متعددة من الوظائف


تماما مثل في الذهاب! يمكنك كتابة العديد من أسماء المتغيرات مفصولة بفواصل وتعيين كل القيم التي تم إرجاعها من الوظيفة في وقت واحد:

 int, real function() { return 5, 3.14 } byte § { int i; real r i, r ~ function } 

وحدات بدلا من الرؤوس


كل شيء واضح هنا. بدلا من رؤوس C- خجولة - وحدات من جافا.

لـ (عنصر تلقائي: صفيف)


مرة أخرى جافا الأصلي. نظرًا لأن لدينا مصفوفات بطول ، فمن الخطيئة عدم استخدام التعبير لكل منها.

مشغل التحديد ليس فقط من أجل int


لا أعلم عنك ، لكن في C و C ++ ، أشعر بالغضب الشديد بسبب عدم القدرة على استخدام عملية تبديل المفاتيح للمتغيرات غير الصحيحة. وغضب بناء الجملة أيضا. هنا في باسكال مسألة أخرى. والآن في لولو:

 case variable { "hello", "HELLO": nop "world": { nop; nop } "WORLD": nop } 

المشغلين وقسم المشغلين


وهذا من بيثون.

 real r ~ 3.14 ** 2 int i ~ r // 3 

وظيفة المعلمات tuples


تذكر أن جميع العمليات مع مؤشرات محظورة في لولو ، باستثناء تحديد الهوية؟ الآن دعونا نتذكر كيفية الوصول إلى معلمات الوظيفة من قوائم المعلمات متغيرة الطول. تحتاج إلى إعلان مؤشر للعنصر الأول ، ثم زيادة حتى يتحقق التحقق من الحقيقة صحيحاً. لا يمكنك الزيادة في لولو. لكن هذا جيد. بعد كل شيء ، يتم تقديم قائمة المعلمات هنا في شكل مجموعة من طول ثابت (يعتمد على المكالمة) ، مع مؤشر آمن ، كما في المصفوفات. اسمه "؟" يتم إجراء فحص النوع فقط للمعلمات المحددة في تعريف الوظيفة. يتم تقليل المعلمات الباقية ("متعددة النقاط") إلى أي نوع ، وبواسطة حركة محرجة لا يتم تعريف سلوكهم. ولكن لا يزال ، مثل هذه المجموعة أكثر أمانًا وأكثر راحة من وحدات الماكرو في C.

 void function(...) { if (?.size > 1) { int i ~ ?[0] real r ~ ?[1] } } 

فواصل عددية


وشخصية أخرى - عائلة من أنواع الفاصل (النطاق ، urange ، lrange ، وما إلى ذلك). يتم تقديمهما بواسطة عددين صحيحين من خلال نقطتين (..) ويمكنهما قطع صفيف من صفيف ، سلسلة من سلسلة ، بشكل عام ، شيء مفيد ، على ما أعتقد.

 int[5] arr ~ [ 1, 2, 3, 4, 5 ] int[3] subarr = arr[1..3] ;; [ 2, 3, 4 ] 

في المشغل


من باسكال. يعمل مع سلاسل ، صفائف ، tuples؟ ويتراوح.

 int[5] arr ~ [ 1, 2, 3, 4, 5 ] if (4 in arr) nop 

وظيفة المعلمة قاموس


بصراحة ، لقد كنت مرتبكًا بالفعل حول كيفية تسمية هذا الشيء بشكل صحيح ، حيث يمكنك تحديد وسيطات الدالات غير الخالصة مباشرةً:

 int pos = str_find(string, npos: -1) 

الخيارات الافتراضية


من C ++. هنا ، حتى المثال ليس من الضروري إعطاء ، وهكذا كل شيء واضح.

استثناءات


حسنا ، وأين بدونهم؟

 try { raise SEGMENTATION_FAULT_EXCEPTION } except (Exception e) { print(e.rus) } 

لا قفزة غير مشروطة


لأنه في عام 2019 ، فإن استخدام مشغل GOTO للموت مشابه.

بناء الجملة


حسنا ، حديث قليل عن بناء الجملة. كما لاحظت ، فاصلة منقوطة ضحلة. لغات البرمجة الحديثة تبلي بلاء حسناً دون مصدر الخطأ هذا. ومن الأمثلة على ذلك بيثون ، كوتلين. يتم دمج عامل السهم (->) مع عامل النقطة. عند استدعاء الوظائف بدون وسائط ، تكون الأقواس اختيارية. يتم إعطاء السلاسل بالأرقام والعكس. يتم الجمع بين العوامل المنطقية و bitwise. هناك معدلات وظيفة لجدولة. وظائف متداخلة type_of. والأهم من ذلك - تعدد اللغات. نعم ، سأقوم بتكرار الكلمات الرئيسية وخصائص السلاسل والمصفوفات وجميع معرّفات المكتبة القياسية بجميع لغات الاتصال الدولي ، وهي: الإنجليزية والروسية واليابانية والصينية والإسبانية والبرتغالية والعربية والفرنسية والألمانية واللاتينية.

في الواقع ، كل ما سبق لا يشمل نصف قدرات لولو. لا يمكنني تذكر جميع ميزاته على الفور. سأضيف كمترجم جاهز.

Source: https://habr.com/ru/post/ar460283/


All Articles