最近這一段時間忙着工作和開發Hulo編程語言,滿打滿算已經過了三個月多了。心血來潮,想梳理下Hulo編程語言的開發流程,也順帶以個人的視角解讀下編程語言是如何從零開始誕生的。希望通過這篇文章,能夠為對編程語言實現感興趣的開發者提供一個實踐性的參考,同時也記錄下這段充滿挑戰和收穫的開發歷程。
架構
Hulo語言的定位是批處理腳本的編譯器,最終經過編譯後的目標語言是Bash、Batch、VBS、PowerShell等腳本語言。為了統一抽象這些不同的目標語言,Hulo不僅僅包含解析器和轉譯器,還為此設計了完整的編譯工具鏈:
核心組件
- 解析器 (Parser): 將源代碼轉換為抽象語法樹(AST)
- 模塊管理 (Module Manager): 處理依賴關係和符號解析
- 解釋器 (Interpreter): 支持元編程和編譯時計算
- 調試器 (Debugger): 配合解釋器進行調試和錯誤診斷
- 優化器 (Optimizer): 負責代碼剪枝和性能優化
- 轉譯器 (Transpiler): 將AST轉換為目標語言代碼
- Unsafe模板引擎: 在轉譯過程中支持嵌入原生代碼
- 鏈接器 (Linker): 負責將原生代碼塊鏈接到一起
編譯流程
從上面的專有名詞上看,Hulo好像該有的都有。但是,大部分組件都還在開發中,只是局部實現並通過了單元測試嘿嘿。不過,這並不影響本次科普的開展。
至此,Hulo的完整編譯流程大概是這樣的:
源代碼 → 解析器 → 模塊管理 → 解釋器(調試器) → 優化器 → 轉譯器(攜帶着unsafe模板引擎) → 鏈接器 → 目標語言代碼
編譯概念
這個完整的過程,Hulo將其稱之為編譯。整個生命週期都是由編譯器(compiler)控制的,編譯也就是從一個語法轉換成另一個語法的過程,比如説C語言編譯成彙編,Hulo語言編譯成批處理腳本。
與傳統編譯器的對比
| 傳統編譯器 | Hulo編譯器 |
|---|---|
| C → 彙編 | Hulo → Bash/Batch/VBS/PowerShell |
| 機器碼執行 | 腳本解釋執行 |
| 多平台彙編 | 多腳本語言 |
這種設計使得Hulo能夠為不同的腳本環境生成相應的代碼,同時保持了統一的開發體驗。
源代碼
源代碼是編程語言實現的基礎,每個開發者都熟悉這個概念:編寫代碼需要創建文件並在其中編寫邏輯。源代碼主要包含兩個部分:文件的擴展名和文件的內容(語法部分)。
語法
語法可以説是一個編程語言區別於其他編程語言的重要標誌。每種語言都有其獨特的語法特性,這些特性在很大程度上決定了語言的風格和用途。例如:
- Golang: 管道運算符
<-、chan、go、defer關鍵字等,這些特性與其他語言相比有很強的辨識度 - C語言: 宏定義滿天飛,預處理器功能強大
- TypeScript: 類型體操,複雜的類型系統
- Rust: 所有權系統、生命週期標註
- Python: 縮進語法、列表推導式
這些語法特性不僅影響代碼的編寫風格,也在很大程度上決定了標準庫的設計和實現方式。當然,也不排除各種語法大雜燴的語言,比如説Hulo就位列其中 :)
文件名
和普通的文本文件類似,代碼本身也是一種結構化的文本格式。文件的擴展名可以自由選擇,在這裏Hulo語言選擇了.hl作為擴展名。建議在選擇擴展名時要與市面上現有的語言區分開來,避免同名擴展名可能導致的編譯衝突。儘管文件內容的存儲與擴展名無關,但在解析過程中,編譯器通常會根據擴展名來確定文件類型和處理方式,因此選擇合適的擴展名有助於避免潛在的編譯問題。