先来个 hello, world! 看看解释器是否能正常工作:
print("hello, world")
可以正常输出,说明解释器能正常干活。
再看看几个官方自带的测试文件是干什么的:
array.lua
$debug a = @() i=0 while i<10 do a[i] = i*i i=i+1 end r,v = next(a,nil) while r ~= nil do print ("array["..r.."] = "..v) r,v = next(a,r) end
定义一个数组,设置值并输出。数组的下标从 0 开始,这个和后来的较新的 Lua 版本不一样,在后来的版本里,Lua 数组下标都是从 1 开始的。
文件的头一行的 $debug 这里看不出有什么用,这个用法到 Lua1.1 里就可以看出有什么作用了。到时候再说。
这里用到了 next 函数来遍历数组。
globals.lua
k,v=nextvar(k) while k do print(k) k,v=nextvar(k) end print(i)
打印全局变量
nextvar 用来返回下一个全局变量
看看全局变量都有哪些:
type, tonumber, next, nextvar, print 在 table.c 中定义
callfunc, execstr, test 在 lua.c 中定义
readfrom, writeto, read, write, execute, remove 在 iolib.c 中定义, io 库函数
strfind, strlen, strsub, strlower, strupper 在 strlib.c 中定义, 字符串库函数
abs, sin, cos, tan, asin, acos, atan, ceil, floor, mod, sqrt, pow, min, max 在 mathlb.c 中定义, 数学库函数。
k 当前的文件中定义,
不知道为什么 v 没有在全局变量中出现。这个应该是 Lua1.0 的一个 bug 吧,这个等到 Lua1.1 时再分析。
save.lua
$debug function savevar (n,v) if v = nil then return end; if type(v) = "number" then print(n.."="..v) return end if type(v) = "string" then print(n.."='"..v.."'") return end if type(v) = "table" then if v.__visited__ ~= nil then print(n .. "=" .. v.__visited__); else print(n.."=@()") v.__visited__ = n; local r,f; r,f = next(v,nil); while r ~= nil do if r ~= "__visited__" then if type(r) = 'string' then savevar(n.."['"..r.."']",f) else savevar(n.."["..r.."]",f) end end r,f = next(v,r) end end end end function save () local n,v n,v = nextvar(nil) while n ~= nil do savevar(n,v); n,v = nextvar(n) end end a = 3 x = @{a = 4, b = "name", l=@[4,5,67]} b = @{t=5} x.next = b save()
打印在当前的 lua 代码中定义的全局变量
由于 savevar 中 type(v) 的限定,在 C 代码中定义的全局变量不会被打印,因为它们的 type 是 cfunction。
sort.lua
$debug function quicksort(r,s) if s<=r then return end -- caso basico da recursao local v=x[r] local i=r local j=s+1 i=i+1; while x[i]<v do i=i+1 end j=j-1; while x[j]>v do j=j-1 end x[i],x[j]=x[j],x[i] while j>i do -- separacao i=i+1; while x[i]<v do i=i+1 end j=j-1; while x[j]>v do j=j-1 end x[i],x[j]=x[j],x[i] end x[i],x[j]=x[j],x[i] -- undo last swap x[j],x[r]=x[r],x[j] quicksort(r,j-1) -- recursao quicksort(j+1,s) end function sort(a,n) -- selection sort local i=1 while i<=n do local m=i local j=i+1 while j<=n do if a[j]<a[m] then m=j end j=j+1 end a[i],a[m]=a[m],a[i] -- swap a[i] and a[m] i=i+1 end end function main() x=@() n=-1 n=n+1; x[n]="a" n=n+1; x[n]="waldemar" n=n+1; x[n]="luiz" n=n+1; x[n]="lula" n=n+1; x[n]="peter" n=n+1; x[n]="raquel" n=n+1; x[n]="camilo" n=n+1; x[n]="andre" n=n+1; x[n]="marcelo" n=n+1; x[n]="sedrez" n=n+1; x[n]="z" -- quicksort(1,n-1) print(x[0]..","..x[1]..","..x[2]..","..x[3]..","..x[4]..","..x[5]..","..x[6]..","..x[7]..","..x[8]..","..x[9]..","..x[10]) sort (x, n-1) print(x[0]..","..x[1]..","..x[2]..","..x[3]..","..x[4]..","..x[5]..","..x[6]..","..x[7]..","..x[8]..","..x[9]..","..x[10]) end main()
快速排序和选择排序
test.lua
$debug function somaP (x1,y1,x2,y2) return x1+x2, y1+y2 end function norma (x,y) return x*x+y*y end function retorno_multiplo () print (norma(somaP(2,3,4,5))) end
运行这个文件没有什么反应,因为它只有函数定义,没有调用。加个 print 看看:
print(retorno_multiplo ())
很好,可以正常执行并输出。
或者可以在命令行中这个文件后加个 retorno_multiplo 同样会调用到, 因为 Lua1.0 把第一个参数(文件名)之后的参数当作函数调用来处理。
type.lua
$debug function check (object, class) local v = next(object,nil) while v ~= nil do if class[v] = nil then print("unknown field: " .. v) elseif type(object[v]) ~= class[v].type then print("wrong type for field " .. v) end v = next(object,v); end v = next(class,nil); while v ~= nil do if object[v] = nil then if class[v].default ~= nil then object[v] = class[v].default else print("field "..v.." not initialized") end end v = next(class,v); end end typetrilha = @{x = @{default = 0, type = "number"}, y = @{default = 0, type = "number"}, name = @{type = "string"} } function trilha (t) check(t,typetrilha) end --t1 = @trilha{ x = 4, name = "3"} t1 = @{ x = 4, name = "3"} a = "na".."me" trilha(t1) print(a)
关联数组的类型检查以及设置默认值。
总体来看,语法和现在的版本相比差别很大。对于语法相关的部分不过多分析,计划主要分析编译器后端的实现,也就是字节码在虚拟机中的执行部分。当然,前端也没有什么好分析的,Lua1.0 的词法分析和语法分析部分是用工具(Lex 和 Yacc)生成的,看下原始文件就明白了。