成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

當你在糾結學Python還是Java時,大二學生已經開始造編程語言了!

開發 開發工具
我在之前的文章中說過多次,大學生在校期間應該去搞定那些基礎知識,因為大學生沒有工作的壓力,有大塊的時間,基礎知識相對枯燥,要想有成就感,可以做一些簡單的系統,例如一個簡單的編程語言,一個有基本功能的OS......

 導讀

我在之前的文章中說過多次,大學生在校期間應該去搞定那些基礎知識,因為大學生沒有工作的壓力,有大塊的時間,基礎知識相對枯燥,要想有成就感,可以做一些簡單的系統,例如一個簡單的編程語言,一個有基本功能的OS......

楊韜是我的知識星球“碼農翻身”的一個大學生,他在星球提到做了一個簡單的編程語言解釋器,我建議他把過程給寫出來, 就是這篇文章了。

[[257924]]

下文的“我”就是楊韜。

為什么要自己寫一個解釋器?

從大學開始學習編程, 現在已經快兩年了, 接觸了不少的編程語言。最開始入門學了C語言; 后來想寫安卓軟件, 學了Java; 接著接觸后臺開發,學了Python; 后面又陸續地接觸Go, Dart, C++。 仔細算算, 已經接觸過6門語言了!

但是仔細想想我似乎又什么也沒有學到,過年回家的時候, 遇到一個對計算機很感興趣的四年級的小朋友(ps: 小朋友會寫一點點python, html, 現在的小孩也太強了), 問了我諸如計算機上面的程序是怎么跑起來的, 代碼是怎么運行這種看似很基礎的問題, 可悲的是我居然對這些問題似懂非懂, 不能給小朋友很清楚地解釋出來。

我都不好意思說自己是學計算機的了, 居然連這些基礎的問題都沒有搞清楚。 這是促使我去深入學習編譯原理, 計算機組成原理和操作系統這些基礎知識的重要原因。

學習編譯原理最簡單的方法(對我來說)大概是自己實現一門編程語言, 雖然費時費力, 不過能對整個過程有個清晰的了解。

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

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

學習的過程

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

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

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

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

因為更喜歡在實戰中學習, 所以前期只是了解了大致思路沒有特別深入的學習理論知識, 就直接開始碼代碼了。 在具體實現的過程中遇到問題, 再去看書或是網上尋找答案。

設計和實現

我選擇寫一個動態語言的解釋器, 而不是靜態語言的編譯器。

之所以要寫解釋器, 不是因為我更偏好動態語言, 其實相比而言我更喜歡靜態語言。 真正的原因是, 我覺得這只是***次嘗試, 很多東西都不會, 肯定會寫得很爛的,不如先就寫動態語言, 等真正學得比較好了, 再回過頭來寫一門自己喜歡的語言。

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

聽說恰當的函數名或類名還能反應整個項目的設計是否合理, 邏輯清晰, 語言的名字似乎并沒有這樣的意義。

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

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

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

當然后續詞法分析和語法分析肯定會自己實現一下, 畢竟這算是編譯器或者解釋器的前端, 也很重要的。

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

  1. void (*func)(void) 

是一個返回值為空, 參數為空的函數指針;

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

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

之所以用函數指針, 是為了用C語言寫面向對象, 最開始我完全是使用面向過程, 只是簡單的通過不同文件實現簡單的封裝。

后來越寫越大, 就出現各種問題, 比如頭文件交叉引用引起編譯器報錯。 還有很多地方用面向對象可以更好地實現, 比如要處理表達式的創建和求值, 如果能有一個表達式的接口, 就能利用多態的好處, 不需要再寫一個巨大的switch, case語句, 使用枚舉來判斷不同的表達式, 調用不同的函數。

我聽說限制程序員的不是編程語言而是編程思維, C語言當然也可以寫面向對象, 數據可以封裝在結構體中, 再給結構體加上函數指針就實現了類的方法。

多態也可以通過自己實現虛函數表, 在對象初始化時把函數指針指向不同的函數就實現了。 大多數的面向對象的特性都有相應的方法實現, 只不過是語法上不如原生支持面向對象的語言簡單罷了。

還有一些問題是關于這門語言本身的設計問題:

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

一開始我設計的是Java, C++一樣的, for, if的代碼塊中聲明的變量, 它作用域只存在于整個代碼塊中。 后來想到了這是一門弱類型的動態語言, 獨立的運行環境也沒什么特別的用處, 于是就改成了和Python一樣: 這種代碼塊都沒有獨立的運行環境。

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

比如Java這種純粹面向對象的語言, 函數只能是對象的方法。 我這里是把函數作為一種基礎數據類型, 像字符串一樣, 可以直接用于傳參, 賦值。

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

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

這樣的思考, 讓我對之前學過的編程語言有有了更加深刻的認識, 可以說是受益匪淺吧。 我漸漸地也認識到編程語言的設計很多時候都是設計者編程思維的體現。

簡單地介紹一下Hedgehog

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

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

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

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

大多數設計都是為了簡化實現方式, 比如必須加{}, ;是為了簡化語法的解析。

數據類型

  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); 

循環

  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); 

函數

function也被看作一種值(基本數據類型), 不過目前還沒有對它實現垃圾回收, 所以直接以函數賦值或者其他操作會出現內存錯誤。

  1. // 模仿python首頁的函數 
  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)); 

目前只實現了一個原生函數print。 print接收一個基本數據類型作為參數, 輸出并換行, 或者無參數, 直接換行。

運算符

大多數與c保持一致, 除了&, |。 因為沒有提供位運算的功能, 所以直接用這兩個符號表示邏輯與和邏輯或。

  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。” 我喜歡這種從自己制作過程中學習的方式。 這種方式給了我一種踏實感, 讓我覺得自己是真地明白了整個過程,而不是僅僅記住了什么公式, 學會了調用新的API。

【本文為51CTO專欄作者“劉欣”的原創稿件,轉載請通過作者微信公眾號coderising獲取授權】

 

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

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2015-03-13 10:40:37

2020-08-07 07:39:19

編程語言JavaPython

2020-06-01 08:46:35

機器學習數學Python

2017-09-04 17:35:27

麻省理工學院細菌乳膠

2018-07-20 10:32:13

編程語言JavaPython

2017-02-24 14:05:14

AndroidMVCMVP

2019-04-22 09:58:25

C語言Web操作系統

2022-07-20 13:55:28

算法AI人工智能

2019-07-01 08:00:00

編程語言Java技術

2010-03-11 15:39:01

Python編程語言

2021-01-13 14:55:54

JavaPython開發

2021-04-06 15:20:05

編程語言JavaIT

2022-09-16 07:32:15

編程計算機命令

2017-02-07 09:37:46

2023-02-23 19:39:06

華為汽車業務

2020-09-16 13:08:17

微信兒童版天眼查騰訊

2020-06-05 08:31:29

編程語言RPython

2012-06-28 13:37:14

2019-08-05 14:34:41

編程語言技術Java

2024-07-10 12:51:34

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美 日韩精品 | 99re视频在线观看 | 亚洲一区二区免费 | 日韩免费网 | 激情91 | 久优草| 亚洲精品久久久 | 宅女噜噜66国产精品观看免费 | 久久精品综合 | 久久国产精品久久 | 国产天天操 | 夜夜爽99久久国产综合精品女不卡 | 久久er精品 | 91精品麻豆日日躁夜夜躁 | 久久综合av | 91亚洲精品国偷拍自产在线观看 | 午夜影院| 久在线| 最新中文字幕在线 | 亚洲免费在线观看 | 红桃视频一区二区三区免费 | 成人黄色电影在线观看 | 久久精品综合 | 日本久久一区二区三区 | 特级做a爰片毛片免费看108 | 久久免费精品 | av网站在线看 | 欧美中文在线 | 尤物在线视频 | 人人99| 国产美女特级嫩嫩嫩bbb片 | 成人在线a | 日日干日日色 | 人人看人人草 | 成人中文网 | 亚洲精品www.| 不卡视频在线 | 伊人热久久 | 91美女在线 | 久久久久国产一级毛片高清网站 | 五月婷婷导航 |