自己動手實現Lua:虛擬機、編譯器和標準庫 ( 簡體 字) |
作者:張秀宏 著 | 類別:1. -> 遊戲 -> 遊戲程式 |
譯者: |
出版社:機械工業出版社 | 3dWoo書號: 49999 詢問書籍請說出此書號!【缺書】 NT售價: 445 元 |
出版日:9/1/2018 |
頁數:415 |
光碟數:0 |
|
站長推薦: |
印刷:黑白印刷 | 語系: ( 簡體 版 ) |
|
加入購物車 │加到我的最愛 (請先登入會員) |
ISBN:9787111610229 |
作者序 | 譯者序 | 前言 | 內容簡介 | 目錄 | 序 |
(簡體書上所述之下載連結耗時費功, 恕不適用在台灣, 若讀者需要請自行嘗試, 恕不保證) |
作者序: |
譯者序: |
前言:為什么編寫本書 Lua是一門強大、高效、輕量、可嵌入的腳本語言。Lua語言設計十分精巧,在一個很小的內核上可以支持函數式編程、面向對象編程、元編程等多種編程范式。以本書完稿時的最新版本Lua 5.3.4為例,全部代碼(包括Lua虛擬機、編譯器、標準庫等)僅有2萬多行,這其中還包括注釋和空行。 Lua語言大約于1993年誕生于巴西PUC-Rio大學,之后在游戲領域大放異彩,被很多游戲客戶端選為腳本語言,比如知名游戲《魔獸世界》《模擬城市4》《憤怒的小鳥》等。很多流行的游戲引擎也選擇Lua作為腳本語言,比如CryENGINE2、Cocos2d-x及Corona SDK等。另外,也有很多游戲服務端采用C/C++搭配Lua的開發模式。除了游戲領域,Lua語言在其他地方也有很多應用,例如被廣泛使用的NoSQL數據庫Redis就使用Lua作為腳本語言擴展其能力。 相信自己動手設計并實現一門編程語言是每個程序員都會有的一個夢想,目前國內也已經出版或引進了一些指導讀者自己實現編程語言的書籍。不過這些書籍要么只介紹了語言實現環節中的一小部分,無法縱觀全局;要么只討論某種大幅裁減后的簡化語言,離真正的工業語言還有一定距離。例如,我自己的《自己動手寫Java虛擬機》,只討論了Java虛擬機實現,沒有涉及Java編譯器和Java標準庫。 如上所述,之所以選擇Lua語言,就是因為它足夠小巧,并且有很好的流行度。麻雀雖小,五臟俱全,這使得我們可以在一本書的篇幅范圍內覆蓋虛擬機、編譯器、標準庫這三個方面的內容。希望讀者可以通過本書完整體驗一門編程語言的實現過程,為將來打造屬于自己的語言做好準備。這正是本書的與眾不同之處。 本書主要內容 本書主要內容可以分為四個部分:第一部分(第1章)為準備工作;第二部分(第2∼ 13章)主要討論Lua虛擬機和Lua API;第三部分(第14∼17章)主要討論Lua語法和編譯器,第四部分(第18∼21章)主要討論Lua標準庫。 全書共21章,各章內容安排如下: 第一部分(準備) 第1章:準備工作。 準備編程環境,編寫“Hello,World!”程序。 第二部分(Lua虛擬機和Lua API) 第2章:二進制chunk。 介紹Lua二進制chuck文件格式,編寫代碼解析二進制chunk文件。 第3章:指令集 介紹Lua虛擬機指令集和指令編碼格式,編寫代碼對指令進行解碼。 第4章:Lua API 初步介紹Lua API和Lua State,實現棧相關API方法。 第5章:Lua運算符 介紹Lua語言運算符,給Lua API添加運算符相關方法。 第6章:虛擬機雛形 初步實現Lua虛擬機,可以解釋執行大約一半的Lua虛擬機指令。 第7章:表 介紹并實現Lua表、表相關API方法,以及表相關指令。 第8章:函數調用 介紹并實現Lua函數調用。 第9章:Go函數調用 介紹如何在Lua中調用Go語言函數。 第10章:閉包和Upvalue 介紹并實現閉包和Upvalue,以及Upvalue相關指令。 第11章:元編程 介紹并實現Lua元表、元方法及元編程。 第12章:迭代器 介紹并實現Lua迭代器。 第13章:異常和錯誤處理 介紹Lua異常和錯誤處理機制。 第三部分(Lua語法和編譯器) 第14章:詞法分析 介紹Lua語言詞法規則,實現詞法分析器。 第15章:抽象語法樹 初步介紹Lua語言語法規則,定義抽象語法樹。 第16章:語法分析 進一步介紹Lua語言語法規則,編寫語法分析器。 第17章:代碼生成 編寫代碼生成器。 第四部分(Lua標準庫) 第18章:輔助API和基礎庫 介紹Lua輔助API和標準庫,實現基礎庫。 第19章:工具庫 介紹并實現數學、表、字符串、UTF-8、OS等標準庫。 第20章:包和模塊 介紹Lua包和模塊機制,實現package標準庫。 第21章:協程 介紹Lua協程,實現coroutine標準庫。 本書面向的讀者 本書假定讀者已經了解Go語言和Lua語言,所以不會對這兩種語言的語法進行專門介紹。本書使用Go語言實現Lua解釋器,但并沒有用到特別高深的技術,加之Go語言語法比較簡單,相信有C系列語言(比如C、C++、C#、Java等)基礎的程序員都可以輕松讀懂書中的代碼。此外,如果讀者更加熟悉Java語言,本書也提供了Java版實現代碼。簡而言之,本書主要面向以下三類讀者: 對腳本語言實現原理感興趣的讀者。 對編譯原理和高級語言虛擬機感興趣的讀者。 對Lua語言感興趣,想探究其內部實現的讀者。 如何閱讀本書 本書內容主要圍繞代碼對Lua虛擬機、編譯器和標準庫展開討論。本書代碼經過精心安排,除第1章外,每一章都建立在前一章的基礎之上,但每一章又都可以單獨編譯和運行。建議讀者從第1章開始,按順序閱讀本書并學習每一章的代碼。但也可以直接跳到感興趣的章節進行閱讀,必要時再閱讀其他章節。 參考資料 相比C/C++、Java、Python等主流語言,Lua算是較為小眾的語言,因此能夠找到的介紹其內部實現原理和細節的資料并不多,這也是本書寫作的動機之一。除了Lua官方實現的源代碼,本書在寫作過程中主要參考了下面這些資料: 《Programming in Lua, Fourth Edition》 《Lua 5.3 Reference Manual》 《The Evolution of Lua》 《The Implementation of Lua 5.0》 《A No-Frills Introduction to Lua 5.1 VM Instructions》 《Lua 5.3 Bytecode Reference》 除此之外,筆者在本書的寫作過程中還查閱了網絡上(特別是StackOverflow和Wikipedia)的各種相關資料,這里就不一一羅列了。如果讀者需要了解Go語法和標準庫 。 獲取本書源代碼 本書源代碼可以從https://github.com/zxh0/luago-book 獲取,代碼分為Go、Java和Lua三部分,總體目錄結構如下: go/ ch01/src/luago/ ch02/src/luago/ ... ch21/src/luago/ java/ ch02/ ... ch18/ lua/ ch02/ ... ch21/ 其中Go語言部分是Lua解釋器實現代碼,每章為一個子目錄,可以單獨編譯和運行(詳見第1章)。Lua語言部分也是每章一個目錄,里面包含每一章的Lua示例代碼和測試腳本。Java語言部分是Lua解釋器的Java版實現代碼,僅供讀者參考。Java版實現只提供了前18章的代表,剩下的3章留給讀者作為練習。 如果讀者對Git比較熟悉,希望每次將注意力集中在某一章的代碼上,也可以使用git checkout命令單獨檢出某一章的代碼。本書為每一章都創建了對應的分支,例如,第1章的代碼在ch01分支里,以此類推。 勘誤和支持 受筆者技術水平和表達能力所限,本書并非盡善盡美,如有不合理之處,懇請讀者批評指正。由于時間倉促,書中也難免會存在一些疏漏之處,還請讀者諒解。 本書的勘誤將通過發布和更新。如果讀者發現書中的錯誤、有改進意見,或者有任何問題需要和作者討論,都可以在本書的Github項目上創建Issue。另外,也可以加入QQ群和本書作者以及其他讀者進行交流。 致謝 首先感謝家人。為了盡快完成這本書,在過去一年多的寫作過程中,我不得不在咖啡廳里度過幾十個周末。這些時間本應該用來陪伴家人,或者陪孩子玩耍。沒有家人的理解和支持,這本書就不可能這么快問世,謝謝你們! 其次要感謝朋友和同事。感謝樂元素CTO凌聰的大力幫助,同時也感謝R大、竇建偉、田生彩、張飛、王世華、楊兵、蔡曉均等閱讀本書初稿并提出寶貴意見。特別感謝武岳為本書每一章繪制可愛的鼴鼠圖。此外還有許多人也為我寫作本書提供了幫助和鼓勵,這里無法一一列出,但同樣感謝各位。 最后感謝華章公司的各位編輯,你們的認真負責是本書質量的保證。 |
內容簡介:本書是一本面向Lua程序員和腳本語言愛好者的語言自制指南和實戰寶典。
全書將帶給讀者3個維度的收獲:
維度1:深入理解Lua語言本身
作者融合自己豐富的工程實踐經驗,詳細闡述了Lua語言的核心語法和實現原理,深入探討了Lua虛擬機、編譯器和標準庫的實現,并給出了實際可以編譯執行的代碼。
維度2:從零開始實現一門腳本語言
本書以Lua語言為例,系統、完整地(涵蓋虛擬機、編譯器和標準庫)講解了如何零基礎編寫一門腳本語言,幫助讀者徹底理解腳本語言的工作原理。
維度3:提升Go和Java語言編程能力
本書分別用Go語言和Java語言來實現Lua,包含大量對Go和Java的使用,有很多巧妙的設計,能幫助讀者提升Go和Java的編程能力。
全書共21章,分為3個部分:
第一部分(第1-13章) 主要講解Lua API和虛擬機的實現,包括二進制chunk格式、Lua虛擬機指令集、元編程、錯誤處理等。
第二部分(第14-17章) 主要討論Lua語法和編譯器的實現,包括詞法分析、語法分析、代碼優化、代碼生成等。
第三部分(第18-21章) 主要講解Lua輔助API和標準庫實現,包括基礎庫、實用工具庫、包和模塊、協程等。 |
目錄:第一部分 準備 第1章 準備工作 3 1.1 準備開發環境 3 1.1.1 操作系統 3 1.1.2 安裝Lua 4 1.1.3 安裝Go 4 1.2 準備目錄結構 4 1.3 本章小結 6 第二部分 Lua虛擬機和Lua API 第2章 二進制chunk 9 2.1 什么是二進制chunk 10 2.2 luac命令介紹 11 2.2.1 編譯Lua源文件 11 2.2.2 查看二進制chunk 13 2.3 二進制chunk格式 15 2.3.1 數據類型 16 2.3.2 總體結構 17 2.3.3 頭部 18 2.3.4 函數原型 22 2.4 解析二進制chunk 27 2.4.1 讀取基本數據類型 28 2.4.2 檢查頭部 29 2.4.3 讀取函數原型 30 2.5 測試本章代碼 33 2.6 本章小結 36 第3章 指令集 37 3.1 指令集介紹 37 3.2 指令編碼格式 38 3.2.1 編碼模式 38 3.2.2 操作碼 39 3.2.3 操作數 40 3.2.4 指令表 41 3.3 指令解碼 42 3.4 測試本章代碼 44 3.5 本章小結 47 第4章 Lua API 49 4.1 Lua API介紹 49 4.2 Lua棧 51 4.2.1 Lua數據類型和值 51 4.2.2 棧索引 54 4.2.3 定義luaStack結構體 54 4.3 Lua State 57 4.3.1 定義LuaState接口 57 4.3.2 定義luaState結構體 58 4.3.3 基礎棧操縱方法 59 4.3.4 Push方法 64 4.3.5 Access方法 65 4.4 測試本章代碼 69 4.5 本章小結 70 第5章 Lua運算符 71 5.1 Lua運算符介紹 71 5.2 自動類型轉換 75 5.3 擴展LuaState接口 79 5.3.1 Arith()方法 80 5.3.2 Compare()方法 83 5.3.3 Len()方法 85 5.3.4 Concat()方法 86 5.4 測試本章代碼 87 5.5 本章小結 88 第6章 虛擬機雛形 89 6.1 添加LuaVM接口 89 6.1.1 定義LuaVM接口 91 6.1.2 改造luaState結構體 92 6.1.3 實現LuaVM接口 93 6.2 實現Lua虛擬機指令 94 6.2.1 移動和跳轉指令 94 6.2.2 加載指令 96 6.2.3 算術運算指令 101 6.2.4 長度和拼接指令 103 6.2.5 比較指令 106 6.2.6 邏輯運算指令 107 6.2.7 for循環指令 110 6.3 指令分派 113 6.4 測試本章代碼 115 6.5 本章小結 118 第7章 表 119 7.1 表介紹 119 7.2 表內部實現 121 7.3 表相關API 125 7.3.1 Get方法 126 7.3.2 Set方法 129 7.4 表相關指令 131 7.4.1 NEWTABLE 131 7.4.2 GETTABLE 133 7.4.3 SETTABLE 135 7.4.4 SETLIST 136 7.5 測試本章代碼 138 7.6 本章小結 140 第8章 函數調用 141 8.1 函數調用介紹 141 8.2 函數調用棧 143 8.2.1 調用幀實現 144 8.2.2 調用棧實現 145 8.3 函數調用API 147 8.3.1 Load() 148 8.3.2 Call() 149 8.4 函數調用指令 152 8.4.1 CLOSURE 152 8.4.2 CALL 153 8.4.3 RETURN 157 8.4.4 VARARG 158 8.4.5 TAILCALL 159 8.4.6 SELF 160 8.4.7 擴展LuaVM接口 162 8.4.8 改進SETLIST指令 163 8.5 測試本章代碼 164 8.6 本章小結 166 第9章 Go函數調用 167 9.1 Go函數登場 167 9.1.1 添加Go函數類型 168 9.1.2 擴展Lua API 169 9.1.3 調用Go函數 170 9.2 Lua注冊表 172 9.2.1 添加注冊表 172 9.2.2 操作注冊表 173 9.3 全局環境 175 9.3.1 使用API操作全局環境 175 9.3.2 在Lua里訪問全局環境 178 9.4 測試本章代碼 179 9.5 本章小結 181 第10章 閉包和Upvalue 183 10.1 閉包和Upvalue介紹 183 10.1.1 背景知識 183 10.1.2 Upvalue介紹 185 10.1.3 全局變量 187 10.2 Upvalue底層支持 189 10.2.1 修改closure結構體 189 10.2.2 Lua閉包支持 191 10.2.3 Go閉包支持 192 10.3 Upvalue相關指令 195 10.3.1 GETUPVAL 195 10.3.2 SETUPVAL 196 10.3.3 GETTABUP 197 10.3.4 SETTABUP 199 10.3.5 JMP 200 10.4 測試本章代碼 202 10.5 本章小結 203 第11章 元編程 205 11.1 元表和元方法介紹 205 11.1.1 元表 206 11.1.2 元方法 206 11.2 支持元表 207 11.3 調用元方法 208 11.3.1 算術元方法 209 11.3.2 長度元方法 211 11.3.3 拼接元方法 211 11.3.4 比較元方法 212 11.3.5 索引元方法 214 11.3.6 函數調用元方法 216 11.4 擴展Lua API 217 11.4.1 GetMetatable() 218 11.4.2 SetMetatable() 218 11.5 測試本章代碼 219 11.6 本章小結 222 第12章 迭代器 223 12.1 迭代器介紹 223 12.2 next()函數 226 12.2.1 修改luaTable結構體 227 12.2.2 擴展Lua API 228 12.2.3 實現next()函數 229 12.3 通用for循環指令 229 12.4 測試本章代碼 232 12.5 本章小結 234 第13章 異常和錯誤處理 235 13.1 異常和錯誤處理介紹 235 13.2 異常和錯誤處理API 237 13.2.1 Error() 238 13.2.2 PCall() 239 13.3 error()和pcall()函數 240 13.4 測試本章代碼 241 13.5 本章小結 242 第三部分 Lua語法和編譯器 第14章 詞法分析 245 14.1 編譯器介紹 245 14.2 Lua詞法介紹 247 14.3 實現詞法分析器 251 14.3.1 定義Token類型 252 14.3.2 空白字符 254 14.3.3 注釋 256 14.3.4 分隔符和運算符 256 14.3.5 長字符串字面量 258 14.3.6 短字符串字面量 259 14.3.7 數字字面量 262 14.3.8 標識符和關鍵字 263 14.4 LookAhead()和其他方法 264 14.5 測試本章代碼 265 14.6 本章小結 267 第15章 抽象語法樹 269 15.1 抽象語法樹介紹 269 15.2 Chunk和塊 270 15.3 語句 272 15.3.1 簡單語句 273 15.3.2 while和repeat語句 273 15.3.3 if語句 274 15.3.4 數值for循環語句 275 15.3.5 通用for循環語句 275 15.3.6 局部變量聲明語句 276 15.3.7 賦值語句 277 15.3.8 非局部函數定義語句 278 15.3.9 局部函數定義語句 279 15.4 表達式 280 15.4.1 簡單表達式 280 15.4.2 運算符表達式 281 15.4.3 表構造表達式 281 15.4.4 函數定義表達式 282 15.4.5 前綴表達式 283 15.4.6 圓括號表達式 284 15.4.7 表訪問表達式 284 15.4.8 函數調用表達式 285 15.5 本章小結 286 第16章 語法分析 287 16.1 語法分析介紹 287 16.1.1 歧義 288 16.1.2 前瞻和回溯 289 16.1.3 解析方式 290 16.2 解析塊 290 16.3 解析語句 293 16.3.1 簡單語句 294 16.3.2 if語句 296 16.3.3 for循環語句 297 16.3.4 局部變量聲明和函數定義語句 299 16.3.5 賦值和函數調用語句 300 16.3.6 非局部函數定義語句 302 16.4 解析表達式 303 16.4.1 運算符表達式 304 16.4.2 非運算符表達式 306 16.4.3 函數定義表達式 307 16.4.4 表構造表達式 308 16.4.5 前綴表達式 310 16.4.6 圓括號表達式 311 16.4.7 函數調用表達式 312 16.4.8 表達式優化 313 16.5 測試本章代碼 315 16.6 本章小結 316 第17章 代碼生成 317 17.1 定義funcInfo結構體 317 17.1.1 常量表 318 17.1.2 寄存器分配 319 17.1.3 局部變量表 320 17.1.4 Break表 323 17.1.5 Upvalue表 324 17.1.6 字節碼 325 17.1.7 其他信息 327 17.2 編譯塊 327 17.3 編譯語句 329 17.3.1 簡單語句 330 17.3.2 while和repeat語句 331 17.3.3 if語句 333 17.3.4 for循環語句 334 17.3.5 局部變量聲明語句 335 17.3.6 賦值語句 337 17.4 編譯表達式 339 17.4.1 函數定義表達式 340 17.4.2 表構造表達式 341 17.4.3 運算符表達式 343 17.4.4 名字和表訪問表達式 345 17.4.5 函數調用表達式 346 17.5 生成函數原型 347 17.6 使用編譯器 349 17.7 測試本章代碼 350 17.8 本章小結 350 第四部分 Lua標準庫 第18章 輔助API和基礎庫 353 18.1 Lua標準庫介紹 353 18.2 輔助API 355 18.2.1 增強版方法 357 18.2.2 加載方法 358 18.2.3 參數檢查方法 359 18.2.4 標準庫開啟方法 360 18.3 基礎庫 361 18.3.1 基礎庫介紹 362 18.3.2 基礎庫實現 362 18.4 測試本章代碼 365 18.5 本章小結 366 第19章 工具庫 367 19.1 數學庫 367 19.2 表庫 369 19.3 字符串庫 372 19.4 UTF-8庫 374 19.5 OS庫 376 19.6 本章小結 379 第20章 包和模塊 381 20.1 包和模塊介紹 381 20.2 實現包庫 386 20.3 測試本章代碼 391 20.4 本章小結 392 第21章 協程 393 21.1 協程介紹 393 21.2 協程API 396 21.2.1 支持線程類型 396 21.2.2 支持協程操作 398 21.3 實現協程庫 400 21.4 測試本章代碼 403 21.5 本章小結 404 附錄A Lua虛擬機指令集 405 附錄B Lua語法EBNF描述 407 后記 409 |
序: |