كل مبرمج لديه حلم - لإنشاء لغته البرمجة الخاصة. الأفضل والأكثر ملاءمة ، بالطبع - ليس مثل تلك الموجودة. بالنسبة لي شخصيًا ، كانت فكرة الإصلاح هي إنشاء لغة لا يوجد بها مطلقًا أي لغة مرجعية ، والتي ستكون قصيرة قدر الإمكان ، لكنها بليغة للغاية. لقد حاولت منذ عامين تحقيق النتيجة المرجوة ، لكن أينما بدأت ، في النهاية ، بعد قطع كل ما كان لا لزوم له ، كنت دائماً أحصل على لشب. ثم حدث تفكير بارع بالنسبة لي - لأخذ Lisp ، وتحسينه وفقًا لأفكاري. على شرف أول ما لفت انتباهي ، تم تسمية المشروع باسم Sova.
لجعل اللغة خارج الصندوق تعمل على الخادم ، وعلى شبكة الإنترنت ، وعلى منصات الهواتف المحمولة ، قررت أن أجمعها في Javascript ، والتي ، في رأيي ، ليست سوى واحدة من أفضل اللغات في عصرنا ، والأهم من ذلك ، لديها نظام بيئي قوي في npm ، Node.js ، التفاعل والتفاعل الأصلي.
وقبل البدء في رحلتنا ، من أجل إثارة الاهتمام على الفور بمزيد من قراءة المقال ، إليك مثال على ملف Express-application واحد على Sova:
=-> './database' database =-> 'express' express = application express () application.get '/' -> (request response) (response.sendStatus 200) application.get '/user/:id' -> (request response) (response.send (database.getUserById request.params.id)) application.listen 8080 -> () (console.log 'Application is listening on port 8080')
حسنًا ، لنبدأ ...
الخطوة 1: سحب الأقواس من Lisp باستخدام المسافة البادئة Python

على الرغم من أن هذا الكتاب الهزلي يجعلني أبتسم في كل مرة أنظر فيه ، إلا أنني لا أتفق مع العبارة الرئيسية. الأقواس ليست أنيقة ، والأقواس عازلة.
لذلك ، أول شيء في لغتي الرائعة قررت أن أتخلص من الأقواس. أفضل حل كان المسافة البادئة ذات الصلة ، مثلما حدث في بيثون. خذ على سبيل المثال قطعة من الشفرة الخاطئة:
(* 2 (+ 1 2) (- 4 (/ 2 1)))
بالطبع ، يمكن نشر هذا التعبير في سطور مختلفة ، لكن هذا لا يعفينا من المهرج من عيون الانسداد.
(* 2 (+ 1 2) (- 4 (/ 2 1)))
الآن دعنا نرى كيف من الممكن أن تكتب بأناقة وجيدة التهوية نفس التعبير في Sova بمساعدة المسافة البادئة الكبيرة:
* 2 + 1 2 - 4 (/ 2 1)
هذا هو ، في Sova ، التعبير a (bc) (d (ef))
مكافئ للتعبير:
a bc d ef
الخطوة 2: اجعل اللغة مختصرة
ما لم يعجبني في معظم لغات البرمجة هو انسداد بناء الجملة بدون أي معنى ، ولكن شغل مكان على الشاشة باستخدام لوحة نحاسية - كلمات رئيسية إضافية وعلامات ترقيم لا معنى لها وغيرها الكثير. حتى في الحالة الشائعة ، بدلاً من الأحرف البسيطة defn
، غالبًا ما تستخدم الكلمات للإشارة إلى العمليات البسيطة ، مثل كلمة defn
نفسها.
إعلان الثوابت
خذ على سبيل المثال إعلان ثابت في Javascript:
const a = 1
Sova هي لغة وظيفية للغاية وجميع المتغيرات غير قابلة للتغيير فيها ، لذلك لا تحتاج إلى تحديد const كلمة أساسية إضافية ، ولكن كل شيء مكتوب ببساطة:
= a 1
وظائف
العنصر الأساسي في أي لغة هو الوظيفة. أضيق الحدود حتى أنها تبدو في سوفا:
= addOne -> number + number 1 = doubleAndAddOne -> number = doubled (* number 2) addOne doubled console.log (doubleAndAddOne 2)
كما هو الحال في أي لغة وظيفية ، فإن التعبير الأخير في نص الوظيفة قابل للإرجاع. وهذا يعني أن الكود أعلاه في جافا سكريبت المترجمة سيبدو:
const addOne = number => { return number + 1 } const doubleAndAddOne = number => { const doubled = number * 2 return addOne(doubled) } console.log(doubleAndAddOne(2))
المقارنات والشروط
يمكن أن يكون للتعبير الشرطي في Sova حجة أو حجة واحدة.
فيما يلي أمثلة للشروط التي تحتوي على وسيطين:
console.log ? true 1 0 console.log ? (> 2 1) 'Greater' 'Less' console.log ? (> 2 1) ? (> 1 2) 'x' 'y' 'z'
وهنا ، على سبيل المثال ، في دالة checkNumber ، نرجع القيم حسب الحالة:
= checkNumber -> number ? (=== number 1) (<- 'One') ? (=== number 2) (<- 'Two') ? (<= number 9) (<- 'From three to nine') 'Ten or more' console.log (checkNumber 1) console.log (checkNumber 4) console.log (checkNumber 11)
في JavaScipt المترجمة ، يبدو كما يلي:
const checkNumber = number => { if (number === 1) return 'One' if (number === 2) return 'Two' if (number <= 9) return 'From three to nine' return 'Ten or more' } console.log(checkNumber(1)) console.log(checkNumber(4)) console.log(checkNumber(11))
مجموعات
مجموعة
المجموعة الرئيسية من أي لغة هي مجموعة. هذه هي الطريقة التي يظهر بها الإعلان وتفكيك الصفيف في Sova:
= list | 1 2 3 4 console.log list console.log list.map (-> x (+ x 1)) = (| first second) list console.log first console.log second
في JavaScript المترجمة ، سيبدو كما يلي:
const list = [1, 2, 3, 4] console.log(list) console.log(list.map(x => x + 1)) const [first, second] = list console.log(first) console.log(second)
موضوع
المجموعة الثانية الأكثر أهمية هي hashmap. في Sova ، يبدو الإعلان عن الخريطة وتفكيكها كما يلي:
= map : a 1 b 2 c : d 3 e 4 f 'Hello' console.log map = (: a (c (: de))) map console.log a console.log d console.log e
في جافا سكريبت المترجمة ، يبدو كما يلي:
const map = { a: 1, b: 2, c: { d: 3, e: 4 }, f: 'Hello' } console.log(map) const { a, c: { d, e }} = map console.log(a) console.log(d) console.log(e)
إذا كنا نريد استدعاء طريقة على كائن ما ، فهناك طريقتان للقيام بذلك. يمكننا أن نسميها object.method parameter1 parameter2
أو. الطريقة الثانية تسمح لنا بإنشاء سلسلة من المكالمات الأسلوب.
استيراد وتصدير وحدات
واردات
يمكنك استيراد الوحدات النمطية إلى رمز Sova من ملفات .sv
الأخرى وكذلك من ملفات .js
. على سبيل المثال ، في هذا المثال ، يتم استيراد وحدتين - data/index.js
و handler/index.sv
:
=-> './data' (: greeting name) =-> './handler' handle handle greeting name
في جافا سكريبت المترجمة ، يبدو كما يلي:
const { greeting, name } = require('./data') const handle = require('./handler') handle(greeting, name)
يتيح استيراد كل من وحدات JavaScript و Sova دمج Sova قليلاً في مشروع Javascript موجود.
صادرات
في هذا المثال ، يتم تصدير الوظيفة من الوحدة النمطية:
<-= -> (greeting name) console.log greeting console.log name
في جافا سكريبت المترجمة ، يبدو كما يلي:
module.exports = (greeting, name) => { console.log(greeting) console.log(name) }
أمثلة الاستخدام
لرؤية كل جمال وسرعة وإيجاز Sova ، تحتاج إلى إلقاء نظرة على برنامج كبير إلى حد ما. على سبيل المثال ، فيما يلي برنامج يحسب متوسط عمر الأشخاص ويجد اسم الشخص الذي يكون عمره أقرب إلى متوسط العمر.
=-> 'lodash' _ = people | : (name 'Alice') (age 24) : (name 'Bob') (age 15) : (name 'Chris') (age 46) : (name 'Daniel') (age 35) : (name 'Elisabeth') (age 29) : (name 'Fred') (age 52) = averageAge / .reduce (.map people (-> man man.age)) -> (xy) (+ xy) 0 .length people = manWithClosestToAverageAge _.minBy .map people (-> man (: (name man.name) (distance (Math.abs (- averageAge man.age))))) 'distance' console.log averageAge console.log manWithClosestToAverageAge.name
نظرًا لحقيقة أن اللغة يتم تجميعها في JavaScript ، يصبح تطوير أي نظام أساسي ممكنًا. على سبيل المثال ، فيما يلي مثال صغير لتطبيق React لمتصفحات الويب:
=-> 'react' React =-> 'react-dom' ReactDOM =-> './styles' styles = (: createElement:e) React = App -> ((: name)) e 'div' (: (style styles.container)) e 'div' (: (style styles.hello)) 'Hello' e 'div' (: (style styles.name)) name ReactDOM.render (e App (: (name 'John'))) (document.getElementById 'root')
يوجد أيضًا في المستودع أمثلة لتطبيقات Express server و React Native لأنظمة المحمول.
استنتاج
وبالتالي ، تضم Sova أفضل لغات أخرى عديدة:
- بساطة وقوة اللثغة
- المسافة البادئة بيثون نظيفة
- وقت التشغيل ونظام جافا سكريبت
رمز المترجم مع أمثلة لاستخدام اللغة هنا هنا https://github.com/sergeyshpadyrev/sova . سأكون سعيدًا لرؤية النجوم على المستودع من كل من أحبوا مفهوم اللغة والذين يرغبون في مواصلة العمل عليها. لكنني سأحذرك على الفور من أن هذا في الوقت الحالي هو مجرد دليل على المفهوم ، وحتى اللعب باللغة بسبب نقص الوثائق وبعض الميزات أمر صعب للغاية. على سبيل المثال ، لا تحتوي اللغة بعد على استثناءات وفصول وأشياء ضرورية أخرى. ومن غير المرجح أن ينجح تشغيل Windows.
في الخطوات التالية ، أخطط لاستكمال بناء الجملة واستقراره ، وإعادة كتابة المحلل اللغوي ، وكتابة اختبارات للمحلل والمترجم ، وكتابة الوثائق. في غضون ذلك ، أشكركم على اهتمامكم وأراك قريباً.