前 言
接觸Lua 是在很早之前,但是那時僅限於基本的學習,沒有在專案中使用,也沒有意識到這門語言真正的魅力。
時間來到2011年,那時我在從事網頁遊戲的開發工作。遊戲開發有其獨有的特點——上線週期短,經常一兩周就要有一個版本上線,而這個過程中需要實現的功能並不見得少。簡單地說,就是時間緊、工作重。
假如採用C++ 這樣的編譯型語言來開發遊戲,典型的開發流程大致是這樣的:捲起袖子寫了一大段程式,然後編譯、解決偵錯編譯的錯誤,中間可能還要處理類似當機、段錯誤、記憶體洩露等問題。另外,由於
重新編譯了程式,又需要重新啟動伺服器,而重新啟動過程中勢必有關資料的載入。總而言之,採用純編譯型語言開發的情況下,有一部分時間並沒有用在真正的業務邏輯開發中。
當時專案採用的是C++ 撰寫的核心引擎模組,曝露核心介面給Lua 指令稿層,網路資料的收發等都在C++ 層完成,而業務邏輯採用Lua 實現。這個架構也是很多遊戲伺服器採用的經典架構。使用這個架構來開發遊戲服務時,不會再把大量的精力放在語言本身的問題上,而可以集中精力來做業務邏輯。另外,借助於Lua 的熱更新能力,整個開發過程中需要重新啟動服務的次數並不多。
可以說,這個專案經歷開啟了一扇新的視窗,開闊我的視野。由於在專案開發過程中嘗到了甜頭,並且自己也對程式語言的實現很有興趣,所以業餘時間就開始慢慢閱讀Lua 解譯器的實現原理。當時在網際網路上能找到的分析Lua 實現的文章並不多,加上自己編譯原理等相關知識的基礎薄弱,大部分時候只能硬啃程式。我一邊摸索,一邊開始逐步整理相關的文章並將其放在網上,希望對其他有類似需求的朋友有幫助。
Lua 身為誕生已經超過20 年的語言,在設計上是非常克制的。以本書說明所有相關的Lua 5.1.4 版本來說,這個版本是Lua 發展十幾年之後穩定很長時間的版本,其解譯器加上週邊的函數庫函數等不過就是一萬多行的程式量,如果再進行精簡,只需要最核心的幾千行程式就可以了。
這樣一種廣泛使用的工業等級的指令碼語言,只需要幾千行程式就能明白其核心原理,這個對比值極高的誘惑對當時的我來說無疑是極大的。
Lua 在設計上,從一開始就把簡潔、高效、可攜性、可嵌入型、可擴充性等作為自己的目標。打一個可能不是太恰當的比方,Lua 專注於做一個配角,作為膠水語言來輔助像C、C++ 這樣的主角來更進一步地完成工作。當其他語言在前面攻城拔寨時,它在後方完成自己輔助的作用。在現在大部分主流程式語言都在走大而全的路線,號稱學會某一種語言就能成為所謂的「全端工程師」的年代,Lua 始終恪守本分地做好
自己膠水語言的本職工作,不得不說是一個異類的存在。
「上善若水,水善利萬物而不爭」,簡單、極致、強大的可擴充性,大概是我能想到的最適合用來描述Lua 語言設計哲學的句子。
本書將對Lua 語言的設計原理做一些分析討論,採用的是Lua 5.1.4 版本,在參考到該版本中的程式時,會在參考程式的同時加上程式所在的檔案以及行號,方便讀者對應到實際的程式中一起跟著閱讀。另外,我也把自己在閱讀Lua 程式中做了一些註釋的程式版本放在GitHub 上,位址是:https://github.com/lichuang/Lua-5.1.4-codedump。
本書適用於以下讀者:
■ 希望進一步了解Lua 實現的內部原理的Lua 語言使用者。
■ 對程式語言設計有興趣的讀者。
閱讀本書,讀者至少需要具備以下的基礎知識:
■ 紮實的C 語言功力,Lua 虛擬機器採用純C 撰寫。在我看過不算少的純C 語言完成的專案中,Lua 虛擬機器的程式品質是最高的。
■ 一定的編譯原理知識,例如了解詞法分析、語法分析、遞迴下降分析、BNF 規則等,如果不清楚這些原理,閱讀Lua 虛擬機器實現時會遇到很多問題。
本書架構如下:
■ 第一部分說明Lua 中的資料結構,如通用資料是如何表示的,Lua 的字串以及表類型的實現原理。
■ 第二部分是本書最重要的部分,主要討論Lua 虛擬機器的實現。另外,這裡分類說明Lua 虛擬機器中的一些重點指令。
■ 第三部分的內容比較雜,這部分討論垃圾回收、模組實現、熱更新、程式碼協同等的實現原理。
本書的完成要特別感謝以下幾個人:
感謝圖靈公司的王軍花編輯,在茫茫的網際網路中找到我在網上開放原始碼的Lua 分析系列文章(這也是本書撰寫的基礎),並且鼓勵我整理出版,在多次跳票的情況下給予我很多的鼓勵和幫助。沒有她的發掘和鼓勵,就不會有本書。
感謝雲風在百忙之中抽空對本書初稿進行審稿,給予很多中肯的意見。
有一些我聽取並進行改進,一些則因為各種原因很遺憾無法進行增強。
感謝我太太對我工作的理解,家人的理解和支援是一切的基礎。
最後,由於本人能力有限,在很多問題的討論上可能還會有一些錯誤,希望讀者不吝賜教。請從這裡開始您的旅程⋯⋯