偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

當(dāng)你在糾結(jié)學(xué)Python還是Java時(shí),大二學(xué)生已經(jīng)開始造編程語言了!

開發(fā) 開發(fā)工具
我在之前的文章中說過多次,大學(xué)生在校期間應(yīng)該去搞定那些基礎(chǔ)知識(shí),因?yàn)榇髮W(xué)生沒有工作的壓力,有大塊的時(shí)間,基礎(chǔ)知識(shí)相對(duì)枯燥,要想有成就感,可以做一些簡(jiǎn)單的系統(tǒng),例如一個(gè)簡(jiǎn)單的編程語言,一個(gè)有基本功能的OS......

 導(dǎo)讀

我在之前的文章中說過多次,大學(xué)生在校期間應(yīng)該去搞定那些基礎(chǔ)知識(shí),因?yàn)榇髮W(xué)生沒有工作的壓力,有大塊的時(shí)間,基礎(chǔ)知識(shí)相對(duì)枯燥,要想有成就感,可以做一些簡(jiǎn)單的系統(tǒng),例如一個(gè)簡(jiǎn)單的編程語言,一個(gè)有基本功能的OS......

楊韜是我的知識(shí)星球“碼農(nóng)翻身”的一個(gè)大學(xué)生,他在星球提到做了一個(gè)簡(jiǎn)單的編程語言解釋器,我建議他把過程給寫出來, 就是這篇文章了。

[[257924]]

下文的“我”就是楊韜。

為什么要自己寫一個(gè)解釋器?

從大學(xué)開始學(xué)習(xí)編程, 現(xiàn)在已經(jīng)快兩年了, 接觸了不少的編程語言。最開始入門學(xué)了C語言; 后來想寫安卓軟件, 學(xué)了Java; 接著接觸后臺(tái)開發(fā),學(xué)了Python; 后面又陸續(xù)地接觸Go, Dart, C++。 仔細(xì)算算, 已經(jīng)接觸過6門語言了!

但是仔細(xì)想想我似乎又什么也沒有學(xué)到,過年回家的時(shí)候, 遇到一個(gè)對(duì)計(jì)算機(jī)很感興趣的四年級(jí)的小朋友(ps: 小朋友會(huì)寫一點(diǎn)點(diǎn)python, html, 現(xiàn)在的小孩也太強(qiáng)了), 問了我諸如計(jì)算機(jī)上面的程序是怎么跑起來的, 代碼是怎么運(yùn)行這種看似很基礎(chǔ)的問題, 可悲的是我居然對(duì)這些問題似懂非懂, 不能給小朋友很清楚地解釋出來。

我都不好意思說自己是學(xué)計(jì)算機(jī)的了, 居然連這些基礎(chǔ)的問題都沒有搞清楚。 這是促使我去深入學(xué)習(xí)編譯原理, 計(jì)算機(jī)組成原理和操作系統(tǒng)這些基礎(chǔ)知識(shí)的重要原因。

學(xué)習(xí)編譯原理最簡(jiǎn)單的方法(對(duì)我來說)大概是自己實(shí)現(xiàn)一門編程語言, 雖然費(fèi)時(shí)費(fèi)力, 不過能對(duì)整個(gè)過程有個(gè)清晰的了解。

另外一個(gè)重要原因是有一種想要自己寫一門語言的沖動(dòng)。 尤其是在學(xué)了這么多門語言之后就會(huì)萌生出這樣的念頭。不同的語言有不同的讓我喜歡的特性: Python有漂亮簡(jiǎn)潔的語法, 靜態(tài)語言Go實(shí)現(xiàn)了像動(dòng)態(tài)語言一樣的鴨子類型的接口, Dart有很多語法糖和方便的異步… (當(dāng)然這些特性是仁者見仁, 智者見智的)。

但是又不能找到一門語言,具備所有自己喜歡的特性, 那就自己寫一個(gè)好了,可以把自己喜歡的特性都加上。

學(xué)習(xí)的過程

學(xué)校的編譯原理的課程安排在了大三, 我還沒有學(xué)過, 所以一切都是從0開始。 我先看了前橋和彌寫的《自制編程語言》一書, 這本書的實(shí)戰(zhàn)性很強(qiáng), 沒有介紹太多的理論知識(shí), 而是直接教你怎么寫編程語言。

我從這本書中了解了寫一門編程語言的大致過程和大致的思路。 不過書中的很多解釋不夠充分, 對(duì)于完全沒有接觸過編譯技術(shù)的人來說還是有點(diǎn)費(fèi)解(也可能是我自己理解能力不夠好)。

我也是在自己了解了大致思路后就開始自己嘗試寫, 然后再回過頭來看書, 看作者提供的源代碼, 才能比較好地了解作者是在干嘛。

還有一些書中內(nèi)容介紹的不夠充分, 比如yacc和lex的使用。 這種工具畢竟比較流行, 網(wǎng)上找找別人寫的博客多看看, 自己再多嘗試就能很好地掌握。

因?yàn)楦矚g在實(shí)戰(zhàn)中學(xué)習(xí), 所以前期只是了解了大致思路沒有特別深入的學(xué)習(xí)理論知識(shí), 就直接開始碼代碼了。 在具體實(shí)現(xiàn)的過程中遇到問題, 再去看書或是網(wǎng)上尋找答案。

設(shè)計(jì)和實(shí)現(xiàn)

我選擇寫一個(gè)動(dòng)態(tài)語言的解釋器, 而不是靜態(tài)語言的編譯器。

之所以要寫解釋器, 不是因?yàn)槲腋脛?dòng)態(tài)語言, 其實(shí)相比而言我更喜歡靜態(tài)語言。 真正的原因是, 我覺得這只是***次嘗試, 很多東西都不會(huì), 肯定會(huì)寫得很爛的,不如先就寫動(dòng)態(tài)語言, 等真正學(xué)得比較好了, 再回過頭來寫一門自己喜歡的語言。

正式開始寫代碼前, 我還要給這門語言取個(gè)名字,雖然只是個(gè)練手的項(xiàng)目, 不過還是得有個(gè)名字吧。 取名字還正不是一件容易得事, 就像給函數(shù)或者類取一個(gè)恰如其分的名字一樣。

聽說恰當(dāng)?shù)暮瘮?shù)名或類名還能反應(yīng)整個(gè)項(xiàng)目的設(shè)計(jì)是否合理, 邏輯清晰, 語言的名字似乎并沒有這樣的意義。

我腦袋里閃過的***個(gè)名字是Cactus(仙人球, 仙人掌)。 我覺得很喜歡這個(gè)名字, 就把Cactus暫時(shí)留個(gè)我要寫的靜態(tài)語言了(希望我真的會(huì)寫, 沒有白留)。 仙人球是植物(正好是靜態(tài)的), 同樣帶刺的動(dòng)物是刺猬(Hedgehog)。 動(dòng)物是動(dòng)態(tài)的, 正好符合我要寫的動(dòng)態(tài)語言, 于是就叫Hedgehog了。

前面提到了lex和yacc, 我在自己寫的編程語言里面也使用了這兩個(gè)工具做詞法分析和語法分析。 既然是自己要寫一門語言為什么還要用別的工具呢? 當(dāng)然不能以”不重復(fù)造輪子”作為借口, 我就是為了造輪子才想要自己寫編程語言的, 真正的目的是為了簡(jiǎn)單。

前面提到我把這當(dāng)作一個(gè)練手的項(xiàng)目, 為了熟悉整個(gè)過程, 我把簡(jiǎn)單作為了整個(gè)過程的一個(gè)原則,很多地方我可以想到更優(yōu)但更加復(fù)雜的實(shí)現(xiàn)方式, 但是大多數(shù)仍然采用了最簡(jiǎn)單最能保持整個(gè)項(xiàng)目邏輯清晰的實(shí)現(xiàn)方式。 我更多的目的是為了了解整體過程, 整體結(jié)構(gòu), 所以局部就盡量保持簡(jiǎn)單了吧(當(dāng)然比較懶也是重要原因)。

當(dāng)然后續(xù)詞法分析和語法分析肯定會(huì)自己實(shí)現(xiàn)一下, 畢竟這算是編譯器或者解釋器的前端, 也很重要的。

解釋器是用C語言寫的。 之前從來沒有用C語言寫過這么大的項(xiàng)目(雖然到目前一共也就2千多行的代碼), 這次也讓我學(xué)會(huì)了很多C語言的高級(jí)用法。 比如 :

  1. void (*func)(void) 

是一個(gè)返回值為空, 參數(shù)為空的函數(shù)指針;

  1. void (*signal(int signo,void(*func)(int)))(int); 

是一個(gè)返回值為函數(shù)指針, 參數(shù)為(int signo,void(*func)(int)), (一個(gè)int, 一個(gè)函數(shù)指針)的函數(shù), 其中函數(shù)名為signal。

之所以用函數(shù)指針, 是為了用C語言寫面向?qū)ο螅?最開始我完全是使用面向過程, 只是簡(jiǎn)單的通過不同文件實(shí)現(xiàn)簡(jiǎn)單的封裝。

后來越寫越大, 就出現(xiàn)各種問題, 比如頭文件交叉引用引起編譯器報(bào)錯(cuò)。 還有很多地方用面向?qū)ο罂梢愿玫貙?shí)現(xiàn), 比如要處理表達(dá)式的創(chuàng)建和求值, 如果能有一個(gè)表達(dá)式的接口, 就能利用多態(tài)的好處, 不需要再寫一個(gè)巨大的switch, case語句, 使用枚舉來判斷不同的表達(dá)式, 調(diào)用不同的函數(shù)。

我聽說限制程序員的不是編程語言而是編程思維, C語言當(dāng)然也可以寫面向?qū)ο螅?數(shù)據(jù)可以封裝在結(jié)構(gòu)體中, 再給結(jié)構(gòu)體加上函數(shù)指針就實(shí)現(xiàn)了類的方法。

多態(tài)也可以通過自己實(shí)現(xiàn)虛函數(shù)表, 在對(duì)象初始化時(shí)把函數(shù)指針指向不同的函數(shù)就實(shí)現(xiàn)了。 大多數(shù)的面向?qū)ο蟮奶匦远加邢鄳?yīng)的方法實(shí)現(xiàn), 只不過是語法上不如原生支持面向?qū)ο蟮恼Z言簡(jiǎn)單罷了。

還有一些問題是關(guān)于這門語言本身的設(shè)計(jì)問題:

(1) for, if這類的語句中變量的作用域問題

一開始我設(shè)計(jì)的是Java, C++一樣的, for, if的代碼塊中聲明的變量, 它作用域只存在于整個(gè)代碼塊中。 后來想到了這是一門弱類型的動(dòng)態(tài)語言, 獨(dú)立的運(yùn)行環(huán)境也沒什么特別的用處, 于是就改成了和Python一樣: 這種代碼塊都沒有獨(dú)立的運(yùn)行環(huán)境。

(2) 把函數(shù)看成什么的問題。

比如Java這種純粹面向?qū)ο蟮恼Z言, 函數(shù)只能是對(duì)象的方法。 我這里是把函數(shù)作為一種基礎(chǔ)數(shù)據(jù)類型, 像字符串一樣, 可以直接用于傳參, 賦值。

畢竟這是自己的編程語言,可以把它設(shè)計(jì)成自己喜歡的樣子, 所以大多數(shù)的設(shè)計(jì)都是根據(jù)自己的想法, 自己覺得怎么合理就怎么來(當(dāng)然不是天馬行空地胡亂設(shè)計(jì), 而是根據(jù)自己地實(shí)際經(jīng)驗(yàn)選擇合理的設(shè)計(jì)吧)。

當(dāng)然最開始寫一門編程語言的時(shí)候,有很多地方不知道怎么設(shè)計(jì)才合理, 這個(gè)時(shí)候我就參考自己學(xué)過的編程語言, 想想它為什么要采用這種設(shè)計(jì), 出于怎樣的考慮。

這樣的思考, 讓我對(duì)之前學(xué)過的編程語言有有了更加深刻的認(rèn)識(shí), 可以說是受益匪淺吧。 我漸漸地也認(rèn)識(shí)到編程語言的設(shè)計(jì)很多時(shí)候都是設(shè)計(jì)者編程思維的體現(xiàn)。

簡(jiǎn)單地介紹一下Hedgehog

說了這么多, 是時(shí)候簡(jiǎn)單地介紹一下我寫的這門編程語言了。目前還很簡(jiǎn)陋, 后面再慢慢地完善它吧。

hedgehog 的多數(shù)設(shè)計(jì)和 python 比較相似, 無需聲明變量類型, if,for等語句沒有塊級(jí)作用域。

語法上又有點(diǎn)像 go 語言: if, for后面不需要(), 但是后面的代碼塊都必須加{};

沒有while, 不過有for condition {}來替代。 不過行尾必須加;這點(diǎn)和 go 不同。

大多數(shù)設(shè)計(jì)都是為了簡(jiǎn)化實(shí)現(xiàn)方式, 比如必須加{}, ;是為了簡(jiǎn)化語法的解析。

數(shù)據(jù)類型

  1. a = 10;  //int 
  2. b = 3.14;//float 
  3. c = true;//boolean 
  4. d = null;//null 
  5. s = "Hello, World!";//string 

控制語句

  1. a = 10; 
  2. if a > 10 { // `()` is not necessary. 
  3.     b = a+20; 
  4. } elsif a==10 { 
  5.     b = a+10; 
  6. else { 
  7.     b = a-10; 
  8. print(b); 

循環(huán)

  1. for i=0; i<10; i=i+1 { 
  2.     print(i); 
  3.     if i>=4 {break;} 
  4. i = 0; 
  5. for i<10 { 
  6.     if i<5 {continue;} 
  7.     print(i); 

函數(shù)

function也被看作一種值(基本數(shù)據(jù)類型), 不過目前還沒有對(duì)它實(shí)現(xiàn)垃圾回收, 所以直接以函數(shù)賦值或者其他操作會(huì)出現(xiàn)內(nèi)存錯(cuò)誤。

  1. // 模仿python首頁(yè)的函數(shù) 
  2. func fbi(n) { 
  3.     a, b = 0, 1; 
  4.     for a<n { 
  5.         print(a); 
  6.         a, b = b, a+b;//支持這種賦值方式 
  7.     } 
  8. fbi(100); 
  1. func factorial(n) { 
  2.     if n==0 {return 1;} 
  3.     return n*factorial(n-1); 
  4. print(factorial(5)); 

目前只實(shí)現(xiàn)了一個(gè)原生函數(shù)print。 print接收一個(gè)基本數(shù)據(jù)類型作為參數(shù), 輸出并換行, 或者無參數(shù), 直接換行。

運(yùn)算符

大多數(shù)與c保持一致, 除了&, |。 因?yàn)闆]有提供位運(yùn)算的功能, 所以直接用這兩個(gè)符號(hào)表示邏輯與和邏輯或。

  1. b = 2; 
  2. a = 10; 
  3. if a>20 & b<10 { 
  4.     print("`b` is less than 10 and `a` is greater than 20"); 
  5. if a>20 | b<10 { 
  6.     print("`b` is less than 10 or `a` is greater than 20"); 

“What I cannot create, I do not understand。” 我喜歡這種從自己制作過程中學(xué)習(xí)的方式。 這種方式給了我一種踏實(shí)感, 讓我覺得自己是真地明白了整個(gè)過程,而不是僅僅記住了什么公式, 學(xué)會(huì)了調(diào)用新的API。

【本文為51CTO專欄作者“劉欣”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過作者微信公眾號(hào)coderising獲取授權(quán)】

 

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2015-03-13 10:40:37

2020-08-07 07:39:19

編程語言JavaPython

2020-06-01 08:46:35

機(jī)器學(xué)習(xí)數(shù)學(xué)Python

2017-09-04 17:35:27

麻省理工學(xué)院細(xì)菌乳膠

2018-07-20 10:32:13

編程語言JavaPython

2017-02-24 14:05:14

AndroidMVCMVP

2022-07-20 13:55:28

算法AI人工智能

2019-04-22 09:58:25

C語言Web操作系統(tǒng)

2019-07-01 08:00:00

編程語言Java技術(shù)

2010-03-11 15:39:01

Python編程語言

2021-01-13 14:55:54

JavaPython開發(fā)

2021-04-06 15:20:05

編程語言JavaIT

2022-09-16 07:32:15

編程計(jì)算機(jī)命令

2017-02-07 09:37:46

2023-02-23 19:39:06

華為汽車業(yè)務(wù)

2020-09-16 13:08:17

微信兒童版天眼查騰訊

2020-06-05 08:31:29

編程語言RPython

2012-06-28 13:37:14

2024-07-10 12:51:34

2021-09-18 14:59:58

語言PythonC語言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)