3 पॉइंट द्वारा GN⁺ 2024-05-03 | 1 टिप्पणियां | WhatsApp पर शेयर करें

Cognition प्रोग्रामिंग भाषा का परिचय

समस्या

  • Lisp प्रोग्रामर यह दावा करते हैं कि वे S-expression code और functional macro system से meta-programming और generalized systems बना सकते हैं।
  • लेकिन Lisp में एक मूलभूत समस्या है
    • meta-programming और programming एक समान नहीं हैं, इसलिए Lisp में हमेशा कठोर syntax रहता है (जैसे parenthesis या look-ahead के लिए कुछ निश्चित character)
    • left parenthesis Lisp को यह बताता है कि जब तक right parenthesis नहीं मिलता, पढ़ना जारी रखना चाहिए
    • इससे भाषा के अंदर left/right parenthesis बदलना लगभग असंभव हो जाता है (सैद्धांतिक रूप से नहीं, लेकिन कुछ implementations में इसे बदलना संभव नहीं होता)
    • इससे भी अधिक महत्वपूर्ण यह है कि इन्हें बाद में केवल string processing के बिना बदलना संभव नहीं होता
  • अन्य भाषाओं में भी token देखकर आगे क्या पढ़ना है तय करने के अन्य तरीके होते हैं
    • इसी प्रक्रिया को syntax कहते हैं
  • Cognition पूर्ण postfix notation (antisyntax) इस्तेमाल करके अलग रास्ता अपनाता है
    • यह concatenative programming language जैसा दिखता है, लेकिन concatenative languages में भी दो प्रमुख समस्याएँ हैं
      1. left/right bracket characters की जरूरत पड़ती है (वास्तव में यह prefix notation जैसा है)
      2. strings के लिए quote character
    • यह सामान्य भाषाओं के लिए उपयुक्त नहीं है
    • Lisp की C-style syntax implementation में भी वही समस्याएँ दिखीं (escape character की अधिकता, और किसी token की शुरुआत/अंत अलग करने के लिए space character की जरूरत)
  • Racket में macro system है, लेकिन यह runtime में dynamic नहीं है और preprocessing का सहारा लेता है

Cognition परिचय

  • यह project Matthew Hinton के साथ कई महीनों के शोध के बाद बना
  • लक्ष्य है कि पूर्ण postfix notation को इस्तेमाल करके ज्ञात सबसे generalized syntax systems में से एक बनाया जाए
  • syntax, tokenization और parsing की पृष्ठभूमि की जरूरत पड़ सकती है, लेकिन इसे आसान तरीके से समझाने की कोशिश की गई है
  • Repository: https://github.com/metacrank/cognition

Baremetal Cognition

  • Baremetal Cognition Brainfuck जैसा है, लेकिन इसमें गंभीर स्तर का meta-programming संभव है
  • bootstrap कोड उदाहरण:
ldfgldftgldfdtgldf dfiff1 crank f
  • whitespace और newline यहाँ महत्वपूर्ण हैं
    • दूसरी लाइन में df के बाद space है
    • तीसरी लाइन में space character शामिल है
  • इससे delimiter और ignore नाम के दो नए concepts introduce किए जा सकते हैं

Tokenization

  • delimiter (डिलीमीटर) tokenizer को token की शुरुआत और अंत को अलग करने में मदद करता है
  • single-character tokenizer सूची सार्वजनिक है और Cognition के भीतर से editable/readable है
  • ignored character वह होता है जिसे read-eval-print loop के पहले चरण में tokenizer पूरी तरह छोड़ देता है
    • यानी token collection शुरू करते समय सेट की गई ignored character सेट को skip किया जाता है
  • डिफ़ॉल्ट रूप से सभी characters delimiter होते हैं और कोई भी ignored नहीं होता
  • delimiter और ignored सूची दिए गए characters के लिए blacklist/whitelist toggle उपलब्ध कराती है (जो संक्षिप्तता और व्यावहारिकता देती है)

Falias

  • Falias वह शब्द सूची है जो stack पर रखे जाने पर execute होती है
  • सभी Falias stack के शीर्ष को execute करती हैं (Stem के eval के equivalent)
  • f default Falias है; यह stack पर नहीं रखा जाता और stack शीर्ष पर मौजूद d को execute करता है
  • d delimiter सूची को शब्द की string value में बदल देता है (यानी केवल l character को delimiter सूची से हटाता है)
  • डिफ़ॉल्ट environment में special Falias छोड़कर कोई शब्द execute नहीं होता

डिलीमीटर नोट्स

  • delimiter के साथ एक रोचक नियम है
    • यदि tokenization loop किसी character को ignore नहीं करता, तो delimiter character वर्तमान token का हिस्सा बनकर आगे बढ़ता रहता है
    • यह singlet के उलट है (जो token में खुद को शामिल करके skip करके token collection समाप्त करता है)
  • blacklist सेटिंग भी की जा सकती है
    • delimiter, singlet और ignored सूची को blacklist/whitelist किया जा सकता है
    • डिफ़ॉल्ट रूप से blacklist किए गए delimiters, whitelist किए गए singlets और whitelist किए गए ignored characters मौजूद नहीं होते
  • अन्य सभी characters वर्तमान token का भाग बनते रहते हैं और नए characters जोड़ते रहते हैं जब तक delimiter या singlet नियम loop रोक न दे

bootstrap कोड जारी

ldf
  • l को non-delimiter बनाया जाता है
gldftgldfdtgldf  dfiff1 crank f
  • d delimiter होने के कारण gl stack पर रख दिया जाता है, और Falias f call होकर gl को non-delimiter बना देता है
  • tgl stack पर रखा जाता है और df द्वारा non-delimiter बना दिया जाता है
  • dtgl stack पर रखा जाता है और \\ndf द्वारा newline (\\n) सिर्फ non-delimiter बनता है (newline वास्तविक कोड में मौजूद है)
  • delimiter नियम से space character और \\n stack पर रखे जाते हैं (तीसरी लाइन में space शामिल है)
  • एक और \\ \\n शब्द tokenize होता है
  • वर्तमान stack इस प्रकार है (नीचे से ऊपर की ओर): 3. dtgl 2. [space character]\n
    1. [space character]\n
  • df \\ \\n को non-delimiter सेट करता है
  • if \\ \\n को ignored character सेट करता है (tokenization शुरू होते ही ignore)
  • f dtgl execute करके delimiter के whitelist/blacklist विभाजन को store करने वाला dflag toggle करता है
  • अब सभी non-delimiter characters delimiter बन जाते हैं और सभी delimiters non-delimiter बन जाते हैं
  • अंत में space और newline टोकन delimiter बनते हैं और tokenization शुरू में ignored हो जाते हैं
  • इसके बाद 1 tokenized होकर stack पर आता है, फिर crank शब्द tokenized होने पर f द्वारा execute होता है (1 इस केस में number माना जाता है, लेकिन Cognition में हर चीज़ शब्द है)
  • bootstrap sequence पूरा! crank क्या करता है, यह अगले सेक्शन में बताया गया है

बूटस्ट्रैपिंग सारांश

  • Cognition में tokenization approach को programmatic तरीके से runtime पर बदलना संभव है
    • दूसरी भाषाओं में यह संभव नहीं है
    • किसी बाहरी भाषा के लिए tokenizer को Cognition के अंदर प्रोग्राम करके चाहने पर tokenization किया जा सकता है
  • postfix notation और look-ahead न होने की वजह से यह संभव है
    • expression evaluate करने से पहले एक से अधिक tokens parse करने की जरूरत नहीं पड़ती
  • Falias की मदद से बिना prefix शब्द या base शब्द को सीधे execute किए शब्द execute किए जा सकते हैं

Crank

  • metacrank system stack पर शब्द execute करने का default तरीका सेट करने की सुविधा देता है
  • crank शब्द एक number argument लेता है और stack पर n शब्द रखे जाने पर stack शीर्ष को execute करता है
  • उदाहरण कोड (जब crank 1 सेट हो):
5 crank 2
crank 2 crank 
1 crank unglue swap quote prepose def
  • crank 1 environment में token evaluation के दौरान f का उपयोग बंद रखा जा सकता है
    • प्रत्येक tokenized शब्द के अनुसार 1 शब्द evaluate होता है
    • क्योंकि syntax लाइन breaks और spaces से विभाजित कर program किया गया है, इसलिए कोड सीधे समझ आता है
  • कोड 5 evaluate करने की कोशिश से शुरू होता है (यह builtin नहीं है, इसलिए खुद को ही evaluate करता है)
  • crank ऐसा सेट किया गया है कि stack में 5 शब्द होने पर execute हो
  • 2crank, 2, crank, 1 सभी stack पर पड़े हैं (crank 5 सेट होने के कारण यहाँ crank builtin होने पर भी execute नहीं होता): 4. 2crank 3. 2 2. crank
    1. 1
  • crank पाँचवाँ शब्द है, इसलिए execute होता है (crank 1 सेट के कारण)
  • unglue एक builtin है जो stack शीर्ष पर मौजूद शब्द (1 से चुना गया) का value लेता है
    • यानी crank builtin के साथ जुड़ा function pointer लेता है
  • stack इस समय इस तरह है: 3. 2crank 2. 2
    1. [CLIB]
    • CLIB वह function pointer है जो crank builtin को point करता है
  • swap execute: 3. 2crank 2. [CLIB]
    1. 2
  • quote (stack शीर्ष को quote करने वाला builtin) execute: 3. 2crank 2. [CLIB]
    1. [2]
  • prepose (stem के compose जैसा, लेकिन आगे रखकर VMACRO में रखने वाला) execute: 2. 2crank
    1. ([2] [CLIB])
  • def call
    • 2 को stack पर रखता है और crank builtin के function pointer को call करने वाला शब्द 2crank define करता है
  • VMACRO क्या है और Cognition stack तथा Stem stack के बीच का अंतर समझाने की ज़रूरत है

Stem के साथ अंतर

  • Stem stack में शब्द सीधे stack पर रखे जा सकते हैं
  • Cognition में शब्द evaluate नहीं होते, पहले container में जाते हैं और फिर stack पर रखे जाते हैं
    • Stem में compose जैसे शब्द शब्द (या single-word वाले container) और अलग container पर काम करते हैं
    • इससे Cognition का API अधिक consistent बनता है
  • cd शब्द भी इसी concept का उपयोग करता है

मैक्रो

  • Stem quote और Cognition container का एक और अंतर
  • macro evaluation में macro के अंदर की सभी चीजें evaluate होती हैं और crank ignore होता है
  • शब्द पर bind किए जाने पर, उस शब्द के eval होने पर

1 टिप्पणियां

 
GN⁺ 2024-05-03
Hacker News टिप्पणियाँ

कुछ प्रमुख टिप्पणियों का सार इस प्रकार है:

  • दस्तावेज़ के परिचय भाग में Cognition प्रोजेक्ट की व्याख्या बहुत देर से आती है। पाठकों का समय बचाने के लिए सबसे ज़रूरी जानकारी पहले देनी चाहिए।
  • Racket की reader लेयर सेटिंग के तरीके की तरह, सिंटैक्स को एक्सटेंड करते हुए भी इंटरऑपरेबिलिटी बनाए रखने के अन्य तरीके पहले से मौजूद हैं। इसलिए यह सवाल स्वाभाविक है कि Cognition का दृष्टिकोण मूल रूप से सचमुच "बेहतर" है या नहीं।
  • Common Lisp में भी reader macro, macro और compiler macro के ज़रिए सिंटैक्स को काफ़ी लचीले तरीके से बदला जा सकता है। मेटा-प्रोग्रामिंग का मूल बिंदु सिंटैक्स नहीं, बल्कि सेमांटिक्स पर काम करना है।
  • Cognition की रनटाइम पर सिंटैक्स स्ट्रक्चर को परिभाषित करने, फिर से परिभाषित करने और बीच में प्रवेश/निकास करने की क्षमता सुंदर और रोचक है। यह सच में "सोचने वाली" मशीन बनाने की संभावना खोलती है।
  • सिंटैक्स हमें संरचना देता है, इसलिए उसे ही हटा देना विरोधाभासी है। बहुत अधिक संक्षिप्त सिंटैXxस पठनीयता और समझने की क्षमता को नुकसान पहुँचा सकता है।
  • दस्तावेज़ का खुद का प्रस्तुतीकरण थोड़ा लंबा और कहीं-कहीं व्यंग्यात्मक लगता है, जिससे पढ़ना कठिन हो जाता है। फिर भी इसमें विषय पर गहराई से चर्चा की गई है।