# 自己动手实现Lua **Repository Path**: Kocola/do_it_yourself_lua ## Basic Information - **Project Name**: 自己动手实现Lua - **Description**: No description available - **Primary Language**: Go - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2018-11-01 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 自己动手实现Lua 实践《自己动手实现Lua: 虚拟机、编译器和标准库》 11.1 第二章
测试用例:
``` 1b4c 7561 5300 1993 0d0a 1a0a 0404 0408 0878 5600 0000 0000 0000 0000 0000 2877 4001 0a40 7465 7374 2e6c 7561 0000 0000 0000 0000 0001 0204 0000 0006 0040 0041 4000 0024 4000 0126 0080 0002 0000 0004 0670 7269 6e74 040b 4865 6c6c 6f57 6f72 6c64 0100 0000 0100 0000 0000 0400 0000 0100 0000 0100 0000 0100 0000 0100 0000 0000 0000 0100 0000 055f 454e 56 ``` 运行结果:
``` main <@test.lua:0,0> (4 instructions) 0+ params, 2 slots, 1 upvalues, 0 locals, 2 constants, 0 functions 1 [1] 0x00400006 2 [1] 0x00004041 3 [1] 0x01004024 4 [1] 0x00800026 constants (2): 1 "print" 2 "HelloWorld" locals (0): upvalues (1): 0 _ENV 1 0 [Finished in 0.7s] ``` 11.2 第三章
测试用例:
``` 1b4c 7561 5300 1993 0d0a 1a0a 0404 0408 0878 5600 0000 0000 0000 0000 0000 2877 4001 0a40 7465 7374 2e6c 7561 0000 0000 0000 0000 0001 0204 0000 0006 0040 0041 4000 0024 4000 0126 0080 0002 0000 0004 0670 7269 6e74 040b 4865 6c6c 6f57 6f72 6c64 0100 0000 0100 0000 0000 0400 0000 0100 0000 0100 0000 0100 0000 0100 0000 0000 0000 0100 0000 055f 454e 56 ``` 运行结果:
``` main <@test.lua:0,0> (4 instructions) 0+ params, 2 slots, 1 upvalues, 0 locals, 2 constants, 0 functions 1 [1] GETTABUP 0 -1 0 2 [1] LOADK 1 -2 3 [1] CALL 0 1 2 4 [1] RETURN 0 0 constants (2): 1 "print" 2 "HelloWorld" locals (0): upvalues (1): 0 _ENV 1 0 [Finished in 0.7s] ``` 11.2 第4章
操作过程:
``` ls := state.New() ls.PushBoolean(true) printStack(ls) ls.PushInteger(10) printStack(ls) ls.PushNil() printStack(ls) ls.PushString("hello") printStack(ls) ls.PushValue(-4) printStack(ls) ls.Replace(3) // 将栈顶弹出,然后写入到指定位置 printStack(ls) ls.SetTop(6) printStack(ls) ls.Remove(-3) printStack(ls) ls.SetTop(-5) printStack(ls) ``` 运行结果:
``` [true] [true][10] [true][10][nil] [true][10][nil]["hello"] [true][10][nil]["hello"][true] [true][10][true]["hello"] [true][10][true]["hello"][nil][nil] [true][10][true][nil][nil] [true] [Finished in 0.6s] ``` 11.2~11.3 第五章 运算符
操作过程:
``` func main() { ls := state.New() ls.PushInteger(1) ls.PushString("2.0") ls.PushString("3.0") ls.PushNumber(4.0) printStack(ls) ls.Arith(api.LUA_OPADD) printStack(ls) ls.Arith(api.LUA_OPBNOT) printStack(ls) ls.Len(2) printStack(ls) ls.Concat(2) printStack(ls) ls.PushBoolean(ls.Compare(1, 2, api.LUA_OPEQ)) printStack(ls) } ``` 运行结果:
``` [1]["2.0"]["3.0"][4] [1]["2.0"][7] [1]["2.0"][-8] [1]["2.0"][-8][3] [1]["2.0"]["-83"] [1]["2.0"]["-83"][false] [Finished in 0.7s] ``` 11.3 第6章 虚拟机雏形
测试用例:
``` local sum = 0 for i = 1, 5 do if i % 2 == 0 then sum = sum + i end end ``` 运行结果:
``` [01] LOADK [0][nil][nil][nil][nil][nil] [02] LOADK [0][1][nil][nil][nil][nil] [03] LOADK [0][1][5][nil][nil][nil] [04] LOADK [0][1][5][1][nil][nil] [05] FORPREP[0][0][5][1][nil][nil] [10] FORLOOP[0][1][5][1][1][nil] [06] MOD [0][1][5][1][1][1] [07] EQ [0][1][5][1][1][1] [08] JMP [0][1][5][1][1][1] [10] FORLOOP[0][2][5][1][2][1] [06] MOD [0][2][5][1][2][0] [07] EQ [0][2][5][1][2][0] [09] ADD [2][2][5][1][2][0] [10] FORLOOP[2][3][5][1][3][0] [06] MOD [2][3][5][1][3][1] [07] EQ [2][3][5][1][3][1] [08] JMP [2][3][5][1][3][1] [10] FORLOOP[2][4][5][1][4][1] [06] MOD [2][4][5][1][4][0] [07] EQ [2][4][5][1][4][0] [09] ADD [6][4][5][1][4][0] [10] FORLOOP[6][5][5][1][5][0] [06] MOD [6][5][5][1][5][1] [07] EQ [6][5][5][1][5][1] [08] JMP [6][5][5][1][5][1] [10] FORLOOP[6][6][5][1][5][1] [Finished in 0.6s] ``` 11.3 第7章 表
测试数据:
``` local t = {"a", "b", "c"} t[2] = "B" t["foo"] = "BAR" local s = t[3] .. t[2] .. t[1] .. t["foo"] .. #t ``` 运行结果:
``` [01] NEWTABLE[table][nil][nil][nil][nil][nil] [02] LOADK [table]["a"][nil][nil][nil][nil] [03] LOADK [table]["a"]["b"][nil][nil][nil] [04] LOADK [table]["a"]["b"]["c"][nil][nil] [05] SETLIST [table]["a"]["b"]["c"][nil][nil] [06] SETTABLE[table]["a"]["b"]["c"][nil][nil] [07] SETTABLE[table]["a"]["b"]["c"][nil][nil] [08] GETTABLE[table]["c"]["b"]["c"][nil][nil] [09] GETTABLE[table]["c"]["B"]["c"][nil][nil] [10] GETTABLE[table]["c"]["B"]["a"][nil][nil] [11] GETTABLE[table]["c"]["B"]["a"]["BAR"][nil] [12] LEN [table]["c"]["B"]["a"]["BAR"][3] [13] CONCAT [table]["cBaBAR3"]["B"]["a"]["BAR"][3] [Finished in 0.7s] ``` 11.7 第11章 元编程
测试数据:
``` local mt = {} mt.__add = function(v1, v2) return vector(v1.x + v2.x, v1.y + v2.y) end mt.__sub = function(v1, v2) return vector(v1.x - v2.x, v1.y - v2.y) end mt.__mul = function(v1, n) return vector(v1.x * n, v1.y * n) end mt.__div = function(v1, n) return vector(v1.x / n, v1.y / n) end mt.__len = function(v) return (v.x * v.x + v.y * v.y) ^ 0.5 end mt.__eq = function(v1, v2) return v1.x == v2.x and v1.y == v2.y end mt.__index = function(v, k) if k == "print" then return function() print("[" .. v.x .. ", " .. v.y .. "]") end end end mt.__call = function(v) print("[" .. v.x .. ", " .. v.y .. "]") end function vector(x, y) local v = {x = x, y = y} setmetatable(v, mt) return v end v1 = vector(1, 2) v2 = vector(3, 4) v3 = v1 * 3 v3:print() v4 = v2 / 2 v4:print() v5 = v1 - v2 v5:print() print(#v2) print(v1 == v2) print(v2 == vector(3, 4)) v4() ``` 运行结果:
``` [3, 6] [1.5, 2] [-2, -2] 5 false true [1.5, 2] [Finished in 0.6s] ``` 11.7 第12章 迭代器
``` t = {a = 1, b = 2, c = 3} for k, v in pairs(t) do print(k, v) end t = {"a", "b", "c"} for k, v in ipairs(t) do print(k, v) end ``` 运行结果:
``` a 1 b 2 c 3 1 a 2 b 3 c [Finished in 1.0s] ``` 第13章-异常和错误处理
``` function div0(a, b) if b == 0 then error("DIV BY ZERO!") else return a / b end end function div1(a, b) return div0(a, b) end function div2(a, b) return div1(a, b) end ok, result = pcall(div2, 4, 2) print(ok, result) ok, err = pcall(div2, 5, 0) print(ok, err) ``` 运行结果:
``` true 2 false DIV BY ZERO! [Finished in 0.6s] ``` 第14章-词法分析
词法分析文件:
``` package main import "fmt" import "io/ioutil" import ."compiler/lexer" func main() { data, err := ioutil.ReadFile("test.lua") if err != nil { panic("err") } testLexer(string(data), "test.lua") } func testLexer(chunk, chunkName string) { lexer := NewLexer(chunk, chunkName) for { line, kind, token := lexer.NextToken() fmt.Printf("[%02d] [%-10s] %s\n", line, kindOfCategory(kind), token) if kind == TOKEN_EOF { break } } } func kindOfCategory(kind int) string { switch { case kind < TOKEN_SEP_SEMI: return "other" case kind <= TOKEN_SEP_RCURLY: return "seperator" case kind <= TOKEN_OP_NOT: return "operator" case kind <= TOKEN_KW_WHILE: return "keyword" case kind == TOKEN_IDENTIFIER: return "identifier" case kind == TOKEN_NUMBER: return "number" case kind == TOKEN_STRING: return "string" default: return "other" } } ``` 运行结果:
``` [01] [keyword ] function [01] [identifier] div0 [01] [seperator ] ( [01] [identifier] a [01] [seperator ] , [01] [identifier] b [01] [seperator ] ) [03] [keyword ] if [03] [identifier] b [03] [operator ] == [03] [number ] 0 [03] [keyword ] then [04] [identifier] error [04] [seperator ] ( [04] [string ] DIV BY ZERO! [04] [seperator ] ) [05] [keyword ] else [06] [identifier] return [06] [identifier] a [06] [operator ] / [06] [identifier] b [07] [keyword ] end [09] [keyword ] end [12] [keyword ] function [12] [identifier] div1 [12] [seperator ] ( [12] [identifier] a [12] [seperator ] , [12] [identifier] b [12] [seperator ] ) [12] [identifier] return [12] [identifier] div0 [12] [seperator ] ( [12] [identifier] a [12] [seperator ] , [12] [identifier] b [12] [seperator ] ) [12] [keyword ] end [14] [keyword ] function [14] [identifier] div2 [14] [seperator ] ( [14] [identifier] a [14] [seperator ] , [14] [identifier] b [14] [seperator ] ) [14] [identifier] return [14] [identifier] div1 [14] [seperator ] ( [14] [identifier] a [14] [seperator ] , [14] [identifier] b [14] [seperator ] ) [14] [keyword ] end [16] [identifier] ok [16] [seperator ] , [16] [identifier] result [16] [operator ] == [16] [identifier] pcall [16] [seperator ] ( [16] [identifier] div2 [16] [seperator ] , [16] [number ] 4 [16] [seperator ] , [16] [number ] 2 [16] [seperator ] ) [17] [identifier] print [17] [seperator ] ( [17] [identifier] ok [17] [seperator ] , [17] [identifier] result [17] [seperator ] ) [19] [identifier] ok [19] [seperator ] , [19] [identifier] err [19] [operator ] == [19] [identifier] pcall [19] [seperator ] ( [19] [identifier] div2 [19] [seperator ] , [19] [number ] 5 [19] [seperator ] , [19] [number ] 0 [19] [seperator ] ) [20] [identifier] print [20] [seperator ] ( [20] [identifier] ok [20] [seperator ] , [20] [identifier] err [20] [seperator ] ) [20] [other ] EOF [Finished in 0.5s] ``` 第16章 语法分析
测试Lua脚本:
``` function div0(a, b) if b == 0 then error("DIV BY ZERO!") else return a / b end end function div1(a, b) return div0(a, b) end local div2 = function(a, b) return div1(a, b) end ok, result = pcall(div2, 4, 2) print(ok, result) ret = 1 and 2 and 2 ^ 2 ^ 3 ``` 运行结果:
``` {"LastLine":19,"Stats":[{"LastLine":1,"VarList":[{"Line":1,"Name":"div0"}],"ExpList":[{"Line":1,"LastLine":9,"ParList":["a","b"],"IsVararg":false,"Block":{"LastLine":7,"Stats":[{"Exps":[{"Line":3,"Op":31,"Exp1":{"Line":3,"Name":"b"},"Exp2":{"Line":3,"Val":0}},{"Line":5}],"Blocks":[{"LastLine":4,"Stats":[{"Line":4,"LastLine":4,"PrefixExp":{"Line":4,"Name":"error"},"NameExp":null,"Args":[{"Line":4,"Str":"DIV BY ZERO!"}]}],"RetExps":null},{"LastLine":6,"Stats":[],"RetExps":[{"Line":6,"Op":18,"Exp1":{"Line":6,"Name":"a"},"Exp2":{"Line":6,"Name":"b"}}]}]}],"RetExps":null}}]},{"LastLine":12,"VarList":[{"Line":12,"Name":"div1"}],"ExpList":[{"Line":12,"LastLine":12,"ParList":["a","b"],"IsVararg":false,"Block":{"LastLine":12,"Stats":[],"RetExps":[{"Line":12,"LastLine":12,"PrefixExp":{"Line":12,"Name":"div0"},"NameExp":null,"Args":[{"Line":12,"Name":"a"},{"Line":12,"Name":"b"}]}]}}]},{"LastLine":14,"NameList":["div2"],"ExpList":[{"Line":14,"LastLine":14,"ParList":["a","b"],"IsVararg":false,"Block":{"LastLine":14,"Stats":[],"RetExps":[{"Line":14,"LastLine":14,"PrefixExp":{"Line":14,"Name":"div1"},"NameExp":null,"Args":[{"Line":14,"Name":"a"},{"Line":14,"Name":"b"}]}]}}]},{"LastLine":16,"VarList":[{"Line":16,"Name":"ok"},{"Line":16,"Name":"result"}],"ExpList":[{"Line":16,"LastLine":16,"PrefixExp":{"Line":16,"Name":"pcall"},"NameExp":null,"Args":[{"Line":16,"Name":"div2"},{"Line":16,"Val":4},{"Line":16,"Val":2}]}]},{"Line":17,"LastLine":17,"PrefixExp":{"Line":17,"Name":"print"},"NameExp":null,"Args":[{"Line":17,"Name":"ok"},{"Line":17,"Name":"result"}]},{"LastLine":19,"VarList":[{"Line":19,"Name":"ret"}],"ExpList":[{"Line":19,"Val":256}]}],"RetExps":null} [Finished in 0.6s] ``` 第17章 代码生成
暂时还有问题 第17章 代码生成
2018.11.18 出现BUG的Lua代码
``` function func() local var = 10 function func1() var = var + 1 print(var) end function func2() var = var + 10 print(var) end return func1, func2 end f1, f2 = func() f1() f2() ``` 问题已修复! 运行结果:
``` function 0xc000054770 function 0xc0000547a0 11 21 [Finished in 0.7s] ``` 第18章 辅助API和基础库
测试Lua代码:
``` function func() local var = 10 function func1() var = var + 1 print(var) end function func2() var = var + 10 print(var) end return func1, func2 end f1, f2 = func() f1() f2() print(_VERSION) print("Hello World!") ``` 运行结果:
``` 11 21 Lua 5.3 Hello World! [Finished in 0.6s] ``` 第20章 包和模块
测试Lua文件
main.lua ``` print("parameter:", ...) local t = {} t.foo = function() print("foo") end t.bar = function() print("bar") end return t ``` test.lua ``` local mod = require "main" print("-----------") mod.bar() print("package.loaded:") for k, v in pairs(package.loaded) do print(k, v) end ``` 运行(test.lua)结果: ``` parameter: main ./main.lua ----------- bar package.loaded: table table: 0xc0000a44b0 string table: 0xc0000a4500 utf8 table: 0xc0000a45a0 os table: 0xc0000a45f0 package table: 0xc0000a4640 main table: 0xc0000a4870 _G table: 0xc0000a43c0 math table: 0xc0000a4460 [Finished in 1.1s] ``` 第21章 协程
测试Lua代码:
``` co = coroutine.create(function(a, b, c) print(1, coroutine.running(co)) coroutine.yield(1,2,3) print(2, coroutine.running(co)) return 4,5,6 end) print(3, coroutine.running(co)) coroutine.resume(co, -1, -2, -3) print(4, coroutine.running(co)) coroutine.resume(co, -11, -12, -13) print(5, coroutine.running(co)) print("-------------------------------") co = coroutine.create(function() print(coroutine.status(co)) coroutine.resume(coroutine.create(function() print(coroutine.status(co)) end)) end) print(coroutine.status(co)) coroutine.resume(co) print(coroutine.status(co)) ``` 运行结果:
``` 3 thread: 0xc000074840 true 1 thread: 0xc0000ea420 false 4 thread: 0xc000074840 true 2 thread: 0xc0000ea420 false 5 thread: 0xc000074840 true ------------------------------- suspended running normal dead [Finished in 9.8s] ```