From 2d1df4714e2736dbde7855ddcd76b4c1de822fa5 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 23 Jan 2012 21:58:02 +1000 Subject: Added a big bunch of example lua scripts for testing the speed of lua compiling. --- LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/README | 51 + LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lcode.lua | 902 +++++++++++ LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/ldump.lua | 362 +++++ LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/llex.lua | 531 ++++++ .../testLua/yueliang-0.4.1/orig-5.0.3/lopcodes.lua | 349 ++++ .../testLua/yueliang-0.4.1/orig-5.0.3/lparser.lua | 1706 ++++++++++++++++++++ LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/luac.lua | 71 + LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lzio.lua | 120 ++ .../yueliang-0.4.1/orig-5.0.3/test/bench_llex.lua | 99 ++ .../yueliang-0.4.1/orig-5.0.3/test/sample.lua | 3 + .../yueliang-0.4.1/orig-5.0.3/test/test_ldump.lua | 98 ++ .../yueliang-0.4.1/orig-5.0.3/test/test_llex.lua | 504 ++++++ .../orig-5.0.3/test/test_lparser.lua | 60 + .../orig-5.0.3/test/test_lparser2.lua | 202 +++ .../yueliang-0.4.1/orig-5.0.3/test/test_lzio.lua | 55 + .../yueliang-0.4.1/orig-5.0.3/test/test_number.lua | 174 ++ .../yueliang-0.4.1/orig-5.0.3/tools/call_graph.lua | 254 +++ .../yueliang-0.4.1/orig-5.0.3/tools/calls.log | 152 ++ .../orig-5.0.3/tools/sample_expr.lua | 195 +++ 19 files changed, 5888 insertions(+) create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/README create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lcode.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/ldump.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/llex.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lopcodes.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lparser.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/luac.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lzio.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/bench_llex.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/sample.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_ldump.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_llex.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lparser.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lparser2.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lzio.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_number.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/call_graph.lua create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/calls.log create mode 100644 LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/sample_expr.lua (limited to 'LuaSL/testLua/yueliang-0.4.1/orig-5.0.3') diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/README b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/README new file mode 100644 index 0000000..e64bf50 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/README @@ -0,0 +1,51 @@ +orig-5.0.3 + +This is a straightforward port of the Lua 5.0.3 front end (lexical +analyzer, parser, code generator, binary chunk dumper.) + +The front end files are: + + lopcodes.lua opcode definition + lzio.lua input streams + llex.lua lexical analyzer + lparser.lua parser + lcode.lua code generator + ldump.lua binary chunk dumper + +Status: operational, passes all current tests (non-exhaustive) + +Major test scripts are: + + test/test_llex.lua exercises test cases + test/test_lparser2.lua exercises test cases + +luac.lua is a clone of Lua 5.0.3's luac.lua, except that it generates a +binary chunk using Yueliang's front end implementation. + +Note that performance is not a consideration. The code tries to stay +faithful to its C roots, so that if you were to do anything using this +codebase, backporting the changes to C will be easy. As such, this +codebase is meant for learning or prototyping purposes. + +Many parameters are unused, because call arguments are retained as far +as possible. Changes and deletions are described wherever possible, but +documentation of changes is not comprehensive. + +These files will stay faithful to the equivalent C files or modules in +Lua 5.0.3. For rewrites or new features, a new directory will be created +and a different set of files maintained. For Lua 5.1, a new directory +will be created. + +The test directory has several primitive test scripts. Much better +testing is planned. Eventually, the codebase will be validated using +automated tests, so that any changes that breaks the system can be +caught easily. + +The tools directory has a call graph generator, showing what gets +called. Specific modules and functions can be monitored, and some +parameters and return values are shown. This is a demonstration of the +flexibility and ease of manipulation of using a relatively inefficient +global table scheme. + +For Lua 5.0.2, see Yueliang 0.1.3, which was the last release of Lua +5.0.2 material. diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lcode.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lcode.lua new file mode 100644 index 0000000..c18dc08 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lcode.lua @@ -0,0 +1,902 @@ +--[[-------------------------------------------------------------------- + + lcode.lua + Lua 5 code generator in Lua + This file is part of Yueliang. + + Copyright (c) 2005-2006 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * one function manipulate a pointer argument with a simple data type +-- (can't be emulated by a table, ambiguous), now returns that value: +-- luaK:concat(fs, l1, l2) +-- * some function parameters changed to boolean, additional code +-- translates boolean back to 1/0 for instruction fields +-- * Added: +-- luaK:ttisnumber(o) (from lobject.h) +-- luaK:nvalue(o) (from lobject.h) +-- luaK:setnilvalue(o) (from lobject.h) +-- luaK:setsvalue(o, x) (from lobject.h) +-- luaK:setnvalue(o, x) (from lobject.h) +-- luaK:sethvalue(o, x) (from lobject.h) +----------------------------------------------------------------------]] + +-- requires luaP, luaX, luaY +luaK = {} + +------------------------------------------------------------------------ +-- Marks the end of a patch list. It is an invalid value both as an absolute +-- address, and as a list link (would link an element to itself). +------------------------------------------------------------------------ +luaK.NO_JUMP = -1 + +------------------------------------------------------------------------ +-- grep "ORDER OPR" if you change these enums +------------------------------------------------------------------------ +luaK.BinOpr = { + OPR_ADD = 0, OPR_SUB = 1, OPR_MULT = 2, OPR_DIV = 3, OPR_POW = 4, + OPR_CONCAT = 5, + OPR_NE = 6, OPR_EQ = 7, + OPR_LT = 8, OPR_LE = 9, OPR_GT = 10, OPR_GE = 11, + OPR_AND = 12, OPR_OR = 13, + OPR_NOBINOPR = 14, +} + +------------------------------------------------------------------------ +-- emulation of TObject macros (these are from lobject.h) +-- * TObject is a table since lcode passes references around +-- * tt member field removed, using Lua's type() instead +------------------------------------------------------------------------ +function luaK:ttisnumber(o) + if o then return type(o.value) == "number" else return false end +end +function luaK:nvalue(o) return o.value end +function luaK:setnilvalue(o) o.value = nil end +function luaK:setsvalue(o, x) o.value = x end +luaK.setnvalue = luaK.setsvalue +luaK.sethvalue = luaK.setsvalue + +------------------------------------------------------------------------ +-- * binopistest appears to be unused +-- * UnOpr is used by luaK:prefix's op argument +------------------------------------------------------------------------ +function luaK:binopistest(op) + return self.BinOpr[op] >= self.BinOpr["OPR_NE"] +end + +luaK.UnOpr = { + OPR_MINUS = 0, OPR_NOT = 1, OPR_NOUNOPR = 2 +} + +------------------------------------------------------------------------ +-- returns the instruction object for given e (expdesc) +------------------------------------------------------------------------ +function luaK:getcode(fs, e) + return fs.f.code[e.info] +end + +------------------------------------------------------------------------ +-- codes an instruction with a signed Bx (sBx) field +------------------------------------------------------------------------ +function luaK:codeAsBx(fs, o, A, sBx) + return self:codeABx(fs, o, A, sBx + luaP.MAXARG_sBx) +end + +------------------------------------------------------------------------ +-- there is a jump if patch lists are not identical +-- * used in luaK:exp2reg(), luaK:exp2anyreg(), luaK:exp2val() +------------------------------------------------------------------------ +function luaK:hasjumps(e) + return e.t ~= e.f +end + +------------------------------------------------------------------------ +-- codes loading of nil, optimization done if consecutive locations +-- * used only in discharge2reg() +------------------------------------------------------------------------ +function luaK:_nil(fs, from, n) + if fs.pc > fs.lasttarget then -- no jumps to current position? + local previous = fs.f.code[fs.pc - 1] + if luaP:GET_OPCODE(previous) == "OP_LOADNIL" then + local pfrom = luaP:GETARG_A(previous) + local pto = luaP:GETARG_B(previous) + if pfrom <= from and from <= pto + 1 then -- can connect both? + if from + n - 1 > pto then + luaP:SETARG_B(previous, from + n - 1) + end + return + end + end + end + self:codeABC(fs, "OP_LOADNIL", from, from + n - 1, 0) -- else no optimization +end + +------------------------------------------------------------------------ +-- +-- * used in multiple locations +------------------------------------------------------------------------ +function luaK:jump(fs) + local jpc = fs.jpc -- save list of jumps to here + fs.jpc = self.NO_JUMP + local j = self:codeAsBx(fs, "OP_JMP", 0, self.NO_JUMP) + return self:concat(fs, j, jpc) -- keep them on hold +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:jumponcond(), luaK:codebinop() +------------------------------------------------------------------------ +function luaK:condjump(fs, op, A, B, C) + self:codeABC(fs, op, A, B, C) + return self:jump(fs) +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:patchlistaux(), luaK:concat() +------------------------------------------------------------------------ +function luaK:fixjump(fs, pc, dest) + local jmp = fs.f.code[pc] + local offset = dest - (pc + 1) + lua_assert(dest ~= self.NO_JUMP) + if math.abs(offset) > luaP.MAXARG_sBx then + luaX:syntaxerror(fs.ls, "control structure too long") + end + luaP:SETARG_sBx(jmp, offset) +end + +------------------------------------------------------------------------ +-- returns current 'pc' and marks it as a jump target (to avoid wrong +-- optimizations with consecutive instructions not in the same basic block). +-- * used in multiple locations +-- * fs.lasttarget tested only by luaK:_nil() when optimizing OP_LOADNIL +------------------------------------------------------------------------ +function luaK:getlabel(fs) + fs.lasttarget = fs.pc + return fs.pc +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:need_value(), luaK:patchlistaux(), luaK:concat() +------------------------------------------------------------------------ +function luaK:getjump(fs, pc) + local offset = luaP:GETARG_sBx(fs.f.code[pc]) + if offset == self.NO_JUMP then -- point to itself represents end of list + return self.NO_JUMP -- end of list + else + return (pc + 1) + offset -- turn offset into absolute position + end +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:need_value(), luaK:patchlistaux(), luaK:invertjump() +------------------------------------------------------------------------ +function luaK:getjumpcontrol(fs, pc) + local pi = fs.f.code[pc] + local ppi = fs.f.code[pc - 1] + if pc >= 1 and luaP:testOpMode(luaP:GET_OPCODE(ppi), "OpModeT") then + return ppi + else + return pi + end +end + +------------------------------------------------------------------------ +-- check whether list has any jump that do not produce a value +-- (or produce an inverted value) +-- * used only in luaK:exp2reg() +------------------------------------------------------------------------ +function luaK:need_value(fs, list, cond) + while list ~= self.NO_JUMP do + local i = self:getjumpcontrol(fs, list) + if luaP:GET_OPCODE(i) ~= "OP_TEST" or + luaP:GETARG_A(i) ~= luaP.NO_REG or + luaP:GETARG_C(i) ~= cond then + return true + end + list = self:getjump(fs, list) + end + return false -- not found +end + +------------------------------------------------------------------------ +-- +-- * used only in luaK:patchlistaux() +------------------------------------------------------------------------ +function luaK:patchtestreg(i, reg) + if reg == luaP.NO_REG then reg = luaP:GETARG_B(i) end + luaP:SETARG_A(i, reg) +end + +------------------------------------------------------------------------ +-- +-- * used only in luaK:codenot() +------------------------------------------------------------------------ + +function luaK:removevalues(fs, list) + while list ~= self.NO_JUMP do + local i = self:getjumpcontrol(fs, list) + if luaP:GET_OPCODE(i) == "OP_TEST" then + self:patchtestreg(i, luaP.NO_REG) + end + list = self:getjump(fs, list) + end +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:dischargejpc(), luaK:patchlist(), luaK:exp2reg() +------------------------------------------------------------------------ +function luaK:patchlistaux(fs, list, vtarget, reg, dtarget) + while list ~= self.NO_JUMP do + local _next = self:getjump(fs, list) + local i = self:getjumpcontrol(fs, list) + if luaP:GET_OPCODE(i) == "OP_TEST" and luaP:GETARG_A(i) == luaP.NO_REG then + self:patchtestreg(i, reg) + self:fixjump(fs, list, vtarget) + else + self:fixjump(fs, list, dtarget) -- jump to default target + end + list = _next + end +end + +------------------------------------------------------------------------ +-- +-- * used only in luaK:code() +------------------------------------------------------------------------ +function luaK:dischargejpc(fs) + self:patchlistaux(fs, fs.jpc, fs.pc, luaP.NO_REG, fs.pc) + fs.jpc = self.NO_JUMP +end + +------------------------------------------------------------------------ +-- +-- * used in (lparser) luaY:whilestat(), luaY:repeatstat(), luaY:forbody() +------------------------------------------------------------------------ +function luaK:patchlist(fs, list, target) + if target == fs.pc then + self:patchtohere(fs, list) + else + lua_assert(target < fs.pc) + self:patchlistaux(fs, list, target, luaP.NO_REG, target) + end +end + +------------------------------------------------------------------------ +-- +-- * used in multiple locations +------------------------------------------------------------------------ +function luaK:patchtohere(fs, list) + self:getlabel(fs) + fs.jpc = self:concat(fs, fs.jpc, list) +end + +------------------------------------------------------------------------ +-- * l1 was a pointer, now l1 is returned and callee assigns the value +-- * used in multiple locations +------------------------------------------------------------------------ +function luaK:concat(fs, l1, l2) + if l2 == self.NO_JUMP then return l1 -- unchanged + elseif l1 == self.NO_JUMP then + return l2 -- changed + else + local list = l1 + local _next = self:getjump(fs, list) + while _next ~= self.NO_JUMP do -- find last element + list = _next + _next = self:getjump(fs, list) + end + self:fixjump(fs, list, l2) + end + return l1 -- unchanged +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:reserveregs(), (lparser) luaY:forlist() +------------------------------------------------------------------------ +function luaK:checkstack(fs, n) + local newstack = fs.freereg + n + if newstack > fs.f.maxstacksize then + if newstack >= luaY.MAXSTACK then + luaX:syntaxerror(fs.ls, "function or expression too complex") + end + fs.f.maxstacksize = newstack + end +end + +------------------------------------------------------------------------ +-- +-- * used in multiple locations +------------------------------------------------------------------------ +function luaK:reserveregs(fs, n) + self:checkstack(fs, n) + fs.freereg = fs.freereg + n +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:freeexp(), luaK:dischargevars() +------------------------------------------------------------------------ +function luaK:freereg(fs, reg) + if reg >= fs.nactvar and reg < luaY.MAXSTACK then + fs.freereg = fs.freereg - 1 + lua_assert(reg == fs.freereg) + end +end + +------------------------------------------------------------------------ +-- +-- * used in multiple locations +------------------------------------------------------------------------ +function luaK:freeexp(fs, e) + if e.k == "VNONRELOC" then + self:freereg(fs, e.info) + end +end + +------------------------------------------------------------------------ +-- * luaH_get, luaH_set deleted; direct table access used instead +-- * luaO_rawequalObj deleted in first assert +-- * setobj2n deleted in assignment of v to f.k table +-- * used in luaK:stringK(), luaK:numberK(), luaK:nil_constant() +------------------------------------------------------------------------ +function luaK:addk(fs, k, v) + local idx = fs.h[k.value] + if self:ttisnumber(idx) then + --TODO this assert currently FAILS, probably something wrong... + --lua_assert(fs.f.k[self:nvalue(idx)] == v) + return self:nvalue(idx) + else -- constant not found; create a new entry + local f = fs.f + luaY:growvector(fs.L, f.k, fs.nk, f.sizek, nil, + luaP.MAXARG_Bx, "constant table overflow") + f.k[fs.nk] = v -- setobj2n deleted + fs.h[k.value] = {} + self:setnvalue(fs.h[k.value], fs.nk) + local nk = fs.nk + fs.nk = fs.nk + 1 + return nk + end +end + +------------------------------------------------------------------------ +-- creates and sets a string object +-- * used in (lparser) luaY:codestring(), luaY:singlevaraux() +------------------------------------------------------------------------ +function luaK:stringK(fs, s) + local o = {} -- TObject + self:setsvalue(o, s) + return self:addk(fs, o, o) +end + +------------------------------------------------------------------------ +-- creates and sets a number object +-- * used in luaK:prefix() for negative (or negation of) numbers +-- * used in (lparser) luaY:simpleexp(), luaY:fornum() +------------------------------------------------------------------------ +function luaK:numberK(fs, r) + local o = {} -- TObject + self:setnvalue(o, r) + return self:addk(fs, o, o) +end + +------------------------------------------------------------------------ +-- +-- * used only in luaK:exp2RK() +------------------------------------------------------------------------ +function luaK:nil_constant(fs) + local k, v = {}, {} -- TObject + self:setnilvalue(v) + self:sethvalue(k, fs.h) -- cannot use nil as key; instead use table itself + return self:addk(fs, k, v) +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:dischargevars() +-- * used in (lparser) luaY:adjust_assign(), luaY:lastlistfield(), +-- luaY:funcargs(), luaY:assignment(), luaY:exprstat(), luaY:retstat() +------------------------------------------------------------------------ +function luaK:setcallreturns(fs, e, nresults) + if e.k == "VCALL" then -- expression is an open function call? + luaP:SETARG_C(self:getcode(fs, e), nresults + 1) + if nresults == 1 then -- 'regular' expression? + e.k = "VNONRELOC" + e.info = luaP:GETARG_A(self:getcode(fs, e)) + end + end +end + +------------------------------------------------------------------------ +-- +-- * used in multiple locations +------------------------------------------------------------------------ +function luaK:dischargevars(fs, e) + local k = e.k + if k == "VLOCAL" then + e.k = "VNONRELOC" + elseif k == "VUPVAL" then + e.info = self:codeABC(fs, "OP_GETUPVAL", 0, e.info, 0) + e.k = "VRELOCABLE" + elseif k == "VGLOBAL" then + e.info = self:codeABx(fs, "OP_GETGLOBAL", 0, e.info) + e.k = "VRELOCABLE" + elseif k == "VINDEXED" then + self:freereg(fs, e.aux) + self:freereg(fs, e.info) + e.info = self:codeABC(fs, "OP_GETTABLE", 0, e.info, e.aux) + e.k = "VRELOCABLE" + elseif k == "VCALL" then + self:setcallreturns(fs, e, 1) + else + -- there is one value available (somewhere) + end +end + +------------------------------------------------------------------------ +-- +-- * used only in luaK:exp2reg() +------------------------------------------------------------------------ +function luaK:code_label(fs, A, b, jump) + self:getlabel(fs) -- those instructions may be jump targets + return self:codeABC(fs, "OP_LOADBOOL", A, b, jump) +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:discharge2anyreg(), luaK:exp2reg() +------------------------------------------------------------------------ +function luaK:discharge2reg(fs, e, reg) + self:dischargevars(fs, e) + local k = e.k + if k == "VNIL" then + self:_nil(fs, reg, 1) + elseif k == "VFALSE" or k == "VTRUE" then + self:codeABC(fs, "OP_LOADBOOL", reg, (e.k == "VTRUE") and 1 or 0, 0) + elseif k == "VK" then + self:codeABx(fs, "OP_LOADK", reg, e.info) + elseif k == "VRELOCABLE" then + local pc = self:getcode(fs, e) + luaP:SETARG_A(pc, reg) + elseif k == "VNONRELOC" then + if reg ~= e.info then + self:codeABC(fs, "OP_MOVE", reg, e.info, 0) + end + else + lua_assert(e.k == "VVOID" or e.k == "VJMP") + return -- nothing to do... + end + e.info = reg + e.k = "VNONRELOC" +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:jumponcond(), luaK:codenot() +------------------------------------------------------------------------ +function luaK:discharge2anyreg(fs, e) + if e.k ~= "VNONRELOC" then + self:reserveregs(fs, 1) + self:discharge2reg(fs, e, fs.freereg - 1) + end +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:exp2nextreg(), luaK:exp2anyreg(), luaK:storevar() +------------------------------------------------------------------------ +function luaK:exp2reg(fs, e, reg) + self:discharge2reg(fs, e, reg) + if e.k == "VJMP" then + e.t = self:concat(fs, e.t, e.info) -- put this jump in 't' list + end + if self:hasjumps(e) then + local final -- position after whole expression + local p_f = self.NO_JUMP -- position of an eventual LOAD false + local p_t = self.NO_JUMP -- position of an eventual LOAD true + if self:need_value(fs, e.t, 1) or self:need_value(fs, e.f, 0) then + local fj = self.NO_JUMP -- first jump (over LOAD ops.) + if e.k ~= "VJMP" then + fj = self:jump(fs) + end + p_f = self:code_label(fs, reg, 0, 1) + p_t = self:code_label(fs, reg, 1, 0) + self:patchtohere(fs, fj) + end + final = self:getlabel(fs) + self:patchlistaux(fs, e.f, final, reg, p_f) + self:patchlistaux(fs, e.t, final, reg, p_t) + end + e.f, e.t = self.NO_JUMP, self.NO_JUMP + e.info = reg + e.k = "VNONRELOC" +end + +------------------------------------------------------------------------ +-- +-- * used in multiple locations +------------------------------------------------------------------------ +function luaK:exp2nextreg(fs, e) + self:dischargevars(fs, e) + self:freeexp(fs, e) + self:reserveregs(fs, 1) + self:exp2reg(fs, e, fs.freereg - 1) +end + +------------------------------------------------------------------------ +-- +-- * used in multiple locations +------------------------------------------------------------------------ +function luaK:exp2anyreg(fs, e) + self:dischargevars(fs, e) + if e.k == "VNONRELOC" then + if not self:hasjumps(e) then -- exp is already in a register + return e.info + end + if e.info >= fs.nactvar then -- reg. is not a local? + self:exp2reg(fs, e, e.info) -- put value on it + return e.info + end + end + self:exp2nextreg(fs, e) -- default + return e.info +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:exp2RK(), luaK:prefix(), luaK:posfix() +-- * used in (lparser) luaY:index() +------------------------------------------------------------------------ +function luaK:exp2val(fs, e) + if self:hasjumps(e) then + self:exp2anyreg(fs, e) + else + self:dischargevars(fs, e) + end +end + +------------------------------------------------------------------------ +-- +-- * used in multiple locations +------------------------------------------------------------------------ +function luaK:exp2RK(fs, e) + self:exp2val(fs, e) + local k = e.k + if k == "VNIL" then + if fs.nk + luaY.MAXSTACK <= luaP.MAXARG_C then -- constant fit in argC? + e.info = self:nil_constant(fs) + e.k = "VK" + return e.info + luaY.MAXSTACK + end + elseif k == "VK" then + if e.info + luaY.MAXSTACK <= luaP.MAXARG_C then -- constant fit in argC? + return e.info + luaY.MAXSTACK + end + end + -- not a constant in the right range: put it in a register + return self:exp2anyreg(fs, e) +end + +------------------------------------------------------------------------ +-- +-- * used in (lparser) luaY:assignment(), luaY:localfunc(), luaY:funcstat() +------------------------------------------------------------------------ +function luaK:storevar(fs, var, exp) + local k = var.k + if k == "VLOCAL" then + self:freeexp(fs, exp) + self:exp2reg(fs, exp, var.info) + return + elseif k == "VUPVAL" then + local e = self:exp2anyreg(fs, exp) + self:codeABC(fs, "OP_SETUPVAL", e, var.info, 0) + elseif k == "VGLOBAL" then + local e = self:exp2anyreg(fs, exp) + self:codeABx(fs, "OP_SETGLOBAL", e, var.info) + elseif k == "VINDEXED" then + local e = self:exp2RK(fs, exp) + self:codeABC(fs, "OP_SETTABLE", var.info, var.aux, e) + else + lua_assert(0) -- invalid var kind to store + end + self:freeexp(fs, exp) +end + +------------------------------------------------------------------------ +-- +-- * used only in (lparser) luaY:primaryexp() +------------------------------------------------------------------------ +function luaK:_self(fs, e, key) + self:exp2anyreg(fs, e) + self:freeexp(fs, e) + local func = fs.freereg + self:reserveregs(fs, 2) + self:codeABC(fs, "OP_SELF", func, e.info, self:exp2RK(fs, key)) + self:freeexp(fs, key) + e.info = func + e.k = "VNONRELOC" +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:goiftrue(), luaK:codenot() +------------------------------------------------------------------------ +function luaK:invertjump(fs, e) + local pc = self:getjumpcontrol(fs, e.info) + lua_assert(luaP:testOpMode(luaP:GET_OPCODE(pc), "OpModeT") and + luaP:GET_OPCODE(pc) ~= "OP_TEST") + luaP:SETARG_A(pc, (luaP:GETARG_A(pc) == 0) and 1 or 0) +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:goiftrue(), luaK:goiffalse() +------------------------------------------------------------------------ +function luaK:jumponcond(fs, e, cond) + if e.k == "VRELOCABLE" then + local ie = self:getcode(fs, e) + if luaP:GET_OPCODE(ie) == "OP_NOT" then + fs.pc = fs.pc - 1 -- remove previous OP_NOT + return self:condjump(fs, "OP_TEST", luaP:GETARG_B(ie), luaP:GETARG_B(ie), + cond and 0 or 1) + end + -- else go through + end + self:discharge2anyreg(fs, e) + self:freeexp(fs, e) + return self:condjump(fs, "OP_TEST", luaP.NO_REG, e.info, cond and 1 or 0) +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:infix(), (lparser) luaY:cond() +------------------------------------------------------------------------ +function luaK:goiftrue(fs, e) + local pc -- pc of last jump + self:dischargevars(fs, e) + local k = e.k + if k == "VK" or k == "VTRUE" then + pc = self.NO_JUMP -- always true; do nothing + elseif k == "VFALSE" then + pc = self:jump(fs) -- always jump + elseif k == "VJMP" then + self:invertjump(fs, e) + pc = e.info + else + pc = self:jumponcond(fs, e, false) + end + e.f = self:concat(fs, e.f, pc) -- insert last jump in 'f' list +end + +------------------------------------------------------------------------ +-- +-- * used in luaK:infix(), (lparser) luaY:whilestat() +------------------------------------------------------------------------ +function luaK:goiffalse(fs, e) + local pc -- pc of last jump + self:dischargevars(fs, e) + local k = e.k + if k == "VNIL" or k == "VFALSE"then + pc = self.NO_JUMP -- always false; do nothing + elseif k == "VTRUE" then + pc = self:jump(fs) -- always jump + elseif k == "VJMP" then + pc = e.info + else + pc = self:jumponcond(fs, e, true) + end + e.t = self:concat(fs, e.t, pc) -- insert last jump in 't' list +end + +------------------------------------------------------------------------ +-- +-- * used only in luaK:prefix() +------------------------------------------------------------------------ +function luaK:codenot(fs, e) + self:dischargevars(fs, e) + local k = e.k + if k == "VNIL" or k == "VFALSE" then + e.k = "VTRUE" + elseif k == "VK" or k == "VTRUE" then + e.k = "VFALSE" + elseif k == "VJMP" then + self:invertjump(fs, e) + elseif k == "VRELOCABLE" or k == "VNONRELOC" then + self:discharge2anyreg(fs, e) + self:freeexp(fs, e) + e.info = self:codeABC(fs, "OP_NOT", 0, e.info, 0) + e.k = "VRELOCABLE" + else + lua_assert(0) -- cannot happen + end + -- interchange true and false lists + e.f, e.t = e.t, e.f + self:removevalues(fs, e.f) + self:removevalues(fs, e.t) +end + +------------------------------------------------------------------------ +-- +-- * used in (lparser) luaY:field(), luaY:primaryexp() +------------------------------------------------------------------------ +function luaK:indexed(fs, t, k) + t.aux = self:exp2RK(fs, k) + t.k = "VINDEXED" +end + +------------------------------------------------------------------------ +-- +-- * used only in (lparser) luaY:subexpr() +------------------------------------------------------------------------ +function luaK:prefix(fs, op, e) + if op == "OPR_MINUS" then + self:exp2val(fs, e) + if e.k == "VK" and self:ttisnumber(fs.f.k[e.info]) then + e.info = self:numberK(fs, -self:nvalue(fs.f.k[e.info])) + else + self:exp2anyreg(fs, e) + self:freeexp(fs, e) + e.info = self:codeABC(fs, "OP_UNM", 0, e.info, 0) + e.k = "VRELOCABLE" + end + else -- op == NOT + self:codenot(fs, e) + end +end + +------------------------------------------------------------------------ +-- +-- * used only in (lparser) luaY:subexpr() +------------------------------------------------------------------------ +function luaK:infix(fs, op, v) + if op == "OPR_AND" then + self:goiftrue(fs, v) + self:patchtohere(fs, v.t) + v.t = self.NO_JUMP + elseif op == "OPR_OR" then + self:goiffalse(fs, v) + self:patchtohere(fs, v.f) + v.f = self.NO_JUMP + elseif op == "OPR_CONCAT" then + self:exp2nextreg(fs, v) -- operand must be on the 'stack' + else + self:exp2RK(fs, v) + end +end + +------------------------------------------------------------------------ +-- +-- grep "ORDER OPR" if you change these enums +-- * used only in luaK:posfix() +------------------------------------------------------------------------ +luaK.arith_opc = { -- done as a table lookup instead of a calc + OPR_ADD = "OP_ADD", + OPR_SUB = "OP_SUB", + OPR_MULT = "OP_MUL", + OPR_DIV = "OP_DIV", + OPR_POW = "OP_POW", +} +luaK.test_opc = { -- was ops[] in the codebinop function + OPR_NE = "OP_EQ", + OPR_EQ = "OP_EQ", + OPR_LT = "OP_LT", + OPR_LE = "OP_LE", + OPR_GT = "OP_LT", + OPR_GE = "OP_LE", +} +function luaK:codebinop(fs, res, op, o1, o2) + if self.BinOpr[op] <= self.BinOpr["OPR_POW"] then -- arithmetic operator? + local opc = self.arith_opc[op] -- ORDER OP + res.info = self:codeABC(fs, opc, 0, o1, o2) + res.k = "VRELOCABLE" + else -- test operator + local cond = true + if self.BinOpr[op] >= self.BinOpr["OPR_GT"] then -- '>' or '>='? + -- exchange args and replace by '<' or '<=' + o1, o2 = o2, o1 -- o1 <==> o2 + elseif op == "OPR_NE" then + cond = false + end + res.info = self:condjump(fs, self.test_opc[op], cond and 1 or 0, o1, o2) + res.k = "VJMP" + end +end + +------------------------------------------------------------------------ +-- +-- * used only in (lparser) luaY:subexpr() +------------------------------------------------------------------------ +function luaK:posfix(fs, op, e1, e2) + if op == "OPR_AND" then + lua_assert(e1.t == self.NO_JUMP) -- list must be closed + self:dischargevars(fs, e2) + e1.f = self:concat(fs, e1.f, e2.f) + e1.k = e2.k; e1.info = e2.info; e1.aux = e2.aux; e1.t = e2.t + elseif op == "OPR_OR" then + lua_assert(e1.f == self.NO_JUMP) -- list must be closed + self:dischargevars(fs, e2) + e1.t = self:concat(fs, e1.t, e2.t) + e1.k = e2.k; e1.info = e2.info; e1.aux = e2.aux; e1.f = e2.f + elseif op == "OPR_CONCAT" then + self:exp2val(fs, e2) + if e2.k == "VRELOCABLE" + and luaP:GET_OPCODE(self:getcode(fs, e2)) == "OP_CONCAT" then + lua_assert(e1.info == luaP:GETARG_B(self:getcode(fs, e2)) - 1) + self:freeexp(fs, e1) + luaP:SETARG_B(self:getcode(fs, e2), e1.info) + e1.k = e2.k; e1.info = e2.info + else + self:exp2nextreg(fs, e2) + self:freeexp(fs, e2) + self:freeexp(fs, e1) + e1.info = self:codeABC(fs, "OP_CONCAT", 0, e1.info, e2.info) + e1.k = "VRELOCABLE" + end + else + local o1 = self:exp2RK(fs, e1) + local o2 = self:exp2RK(fs, e2) + self:freeexp(fs, e2) + self:freeexp(fs, e1) + self:codebinop(fs, e1, op, o1, o2) + end +end + +------------------------------------------------------------------------ +-- adjusts debug information for last instruction written, in order to +-- change the line where item comes into existence +-- * used in (lparser) luaY:funcargs(), luaY:forbody(), luaY:funcstat() +------------------------------------------------------------------------ +function luaK:fixline(fs, line) + fs.f.lineinfo[fs.pc - 1] = line +end + +------------------------------------------------------------------------ +-- general function to write an instruction into the instruction buffer, +-- sets debug information too +-- * used in luaK:codeABC(), luaK:codeABx() +-- * called directly by (lparser) luaY:whilestat() +------------------------------------------------------------------------ +function luaK:code(fs, i, line) + local f = fs.f + self:dischargejpc(fs) -- 'pc' will change + -- put new instruction in code array + luaY:growvector(fs.L, f.code, fs.pc, f.sizecode, nil, + luaY.MAX_INT, "code size overflow") + f.code[fs.pc] = i + -- save corresponding line information + luaY:growvector(fs.L, f.lineinfo, fs.pc, f.sizelineinfo, nil, + luaY.MAX_INT, "code size overflow") + f.lineinfo[fs.pc] = line + local pc = fs.pc + fs.pc = fs.pc + 1 + return pc +end + +------------------------------------------------------------------------ +-- writes an instruction of type ABC +-- * calls luaK:code() +------------------------------------------------------------------------ +function luaK:codeABC(fs, o, a, b, c) + lua_assert(luaP:getOpMode(o) == "iABC") + return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.ls.lastline) +end + +------------------------------------------------------------------------ +-- writes an instruction of type ABx +-- * calls luaK:code(), called by luaK:codeAsBx() +------------------------------------------------------------------------ +function luaK:codeABx(fs, o, a, bc) + lua_assert(luaP:getOpMode(o) == "iABx" or luaP:getOpMode(o) == "iAsBx") + return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.ls.lastline) +end diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/ldump.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/ldump.lua new file mode 100644 index 0000000..1b3c608 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/ldump.lua @@ -0,0 +1,362 @@ +--[[-------------------------------------------------------------------- + + ldump.lua + Save bytecodes in Lua + This file is part of Yueliang. + + Copyright (c) 2005 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * LUA_NUMBER (double), byte order (little endian) and some other +-- header values hard-coded; see other notes below... +-- * One significant difference is that instructions are still in table +-- form (with OP/A/B/C/Bx fields) and luaP:Instruction() is needed to +-- convert them into 4-char strings +-- * Deleted: +-- luaU:DumpVector: folded into DumpLines, DumpCode +-- * Added: +-- luaU:endianness() (from lundump.c) +-- luaU:make_setS: create a chunk writer that writes to a string +-- luaU:make_setF: create a chunk writer that writes to a file +-- (lua.h contains a typedef for a Chunkwriter pointer, and +-- a Lua-based implementation exists, writer() in lstrlib.c) +-- luaU:from_double(x): encode double value for writing +-- luaU:from_int(x): encode integer value for writing +-- (error checking is limited for these conversion functions) +-- (double conversion does not support denormals or NaNs) +-- luaU:ttype(o) (from lobject.h) +----------------------------------------------------------------------]] + +--requires luaP +luaU = {} + +-- constants used by dumper +luaU.LUA_TNUMBER = 3 -- (all in lua.h) +luaU.LUA_TSTRING = 4 +luaU.LUA_TNIL = 0 +luaU.LUA_TNONE = -1 + +-- definitions for headers of binary files +luaU.LUA_SIGNATURE = "\27Lua" -- binary files start with "Lua" +luaU.VERSION = 80 -- 0x50; last format change was in 5.0 +luaU.VERSION0 = 80 -- 0x50; last major change was in 5.0 + +-- a multiple of PI for testing native format +-- multiplying by 1E7 gives non-trivial integer values +luaU.TEST_NUMBER = 3.14159265358979323846E7 + +--[[-------------------------------------------------------------------- +-- Additional functions to handle chunk writing +-- * to use make_setS and make_setF, see test_ldump.lua elsewhere +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- works like the lobject.h version except that TObject used in these +-- scripts only has a 'value' field, no 'tt' field (native types used) +------------------------------------------------------------------------ +function luaU:ttype(o) + local tt = type(o.value) + if tt == "number" then return self.LUA_TNUMBER + elseif tt == "string" then return self.LUA_TSTRING + elseif tt == "nil" then return self.LUA_TNIL + else + return self.LUA_TNONE -- the rest should not appear + end +end + +------------------------------------------------------------------------ +-- create a chunk writer that writes to a string +-- * returns the writer function and a table containing the string +-- * to get the final result, look in buff.data +------------------------------------------------------------------------ +function luaU:make_setS() + local buff = {} + buff.data = "" + local writer = + function(s, buff) -- chunk writer + if not s then return end + buff.data = buff.data..s + end + return writer, buff +end + +------------------------------------------------------------------------ +-- create a chunk writer that writes to a file +-- * returns the writer function and a table containing the file handle +-- * if a nil is passed, then writer should close the open file +------------------------------------------------------------------------ +function luaU:make_setF(filename) + local buff = {} + buff.h = io.open(filename, "wb") + if not buff.h then return nil end + local writer = + function(s, buff) -- chunk writer + if not buff.h then return end + if not s then buff.h:close(); return end + buff.h:write(s) + end + return writer, buff +end + +----------------------------------------------------------------------- +-- converts a IEEE754 double number to an 8-byte little-endian string +-- * luaU:from_double() and luaU:from_int() are from ChunkBake project +-- * supports +/- Infinity, but not denormals or NaNs +----------------------------------------------------------------------- +function luaU:from_double(x) + local function grab_byte(v) + return math.floor(v / 256), + string.char(math.mod(math.floor(v), 256)) + end + local sign = 0 + if x < 0 then sign = 1; x = -x end + local mantissa, exponent = math.frexp(x) + if x == 0 then -- zero + mantissa, exponent = 0, 0 + elseif x == 1/0 then + mantissa, exponent = 0, 2047 + else + mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53) + exponent = exponent + 1022 + end + local v, byte = "" -- convert to bytes + x = mantissa + for i = 1,6 do + x, byte = grab_byte(x); v = v..byte -- 47:0 + end + x, byte = grab_byte(exponent * 16 + x); v = v..byte -- 55:48 + x, byte = grab_byte(sign * 128 + x); v = v..byte -- 63:56 + return v +end + +----------------------------------------------------------------------- +-- converts a number to a little-endian 32-bit integer string +-- * input value assumed to not overflow, can be signed/unsigned +----------------------------------------------------------------------- +function luaU:from_int(x) + local v = "" + x = math.floor(x) + if x >= 0 then + for i = 1, 4 do + v = v..string.char(math.mod(x, 256)); x = math.floor(x / 256) + end + else-- x < 0 + x = -x + local carry = 1 + for i = 1, 4 do + local c = 255 - math.mod(x, 256) + carry + if c == 256 then c = 0; carry = 1 else carry = 0 end + v = v..string.char(c); x = math.floor(x / 256) + end + end + return v +end + +--[[-------------------------------------------------------------------- +-- Functions to make a binary chunk +-- * many functions have the size parameter removed, since output is +-- in the form of a string and some sizes are implicit or hard-coded +-- * luaU:DumpVector has been deleted (used in DumpCode & DumpLines) +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- dump a block of literal bytes +------------------------------------------------------------------------ +function luaU:DumpLiteral(s, D) self:DumpBlock(s, D) end + +--[[-------------------------------------------------------------------- +-- struct DumpState: +-- L -- lua_State (not used in this script) +-- write -- lua_Chunkwriter (chunk writer function) +-- data -- void* (chunk writer context or data already written) +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- dumps a block of bytes +-- * lua_unlock(D.L), lua_lock(D.L) deleted +------------------------------------------------------------------------ +function luaU:DumpBlock(b, D) D.write(b, D.data) end + +------------------------------------------------------------------------ +-- dumps a single byte +------------------------------------------------------------------------ +function luaU:DumpByte(y, D) + self:DumpBlock(string.char(y), D) +end + +------------------------------------------------------------------------ +-- dumps a 32-bit signed integer (for int) +------------------------------------------------------------------------ +function luaU:DumpInt(x, D) + self:DumpBlock(self:from_int(x), D) +end + +------------------------------------------------------------------------ +-- dumps a 32-bit unsigned integer (for size_t) +------------------------------------------------------------------------ +function luaU:DumpSize(x, D) + self:DumpBlock(self:from_int(x), D) +end + +------------------------------------------------------------------------ +-- dumps a LUA_NUMBER (hard-coded as a double) +------------------------------------------------------------------------ +function luaU:DumpNumber(x, D) + self:DumpBlock(self:from_double(x), D) +end + +------------------------------------------------------------------------ +-- dumps a Lua string +------------------------------------------------------------------------ +function luaU:DumpString(s, D) + if s == nil then + self:DumpSize(0, D) + else + s = s.."\0" -- include trailing '\0' + self:DumpSize(string.len(s), D) + self:DumpBlock(s, D) + end +end + +------------------------------------------------------------------------ +-- dumps instruction block from function prototype +------------------------------------------------------------------------ +function luaU:DumpCode(f, D) + local n = f.sizecode + self:DumpInt(n, D) + --was DumpVector + for i = 0, n - 1 do + self:DumpBlock(luaP:Instruction(f.code[i]), D) + end +end + +------------------------------------------------------------------------ +-- dumps local variable names from function prototype +------------------------------------------------------------------------ +function luaU:DumpLocals(f, D) + local n = f.sizelocvars + self:DumpInt(n, D) + for i = 0, n - 1 do + self:DumpString(f.locvars[i].varname, D) + self:DumpInt(f.locvars[i].startpc, D) + self:DumpInt(f.locvars[i].endpc, D) + end +end + +------------------------------------------------------------------------ +-- dumps line information from function prototype +------------------------------------------------------------------------ +function luaU:DumpLines(f, D) + local n = f.sizelineinfo + self:DumpInt(n, D) + --was DumpVector + for i = 0, n - 1 do + self:DumpInt(f.lineinfo[i], D) -- was DumpBlock + end +end + +------------------------------------------------------------------------ +-- dump upvalue names from function prototype +------------------------------------------------------------------------ +function luaU:DumpUpvalues(f, D) + local n = f.sizeupvalues + self:DumpInt(n, D) + for i = 0, n - 1 do + self:DumpString(f.upvalues[i], D) + end +end + +------------------------------------------------------------------------ +-- dump constant pool from function prototype +-- * nvalue(o) and tsvalue(o) macros removed +------------------------------------------------------------------------ +function luaU:DumpConstants(f, D) + local n = f.sizek + self:DumpInt(n, D) + for i = 0, n - 1 do + local o = f.k[i] -- TObject + local tt = self:ttype(o) + self:DumpByte(tt, D) + if tt == self.LUA_TNUMBER then + self:DumpNumber(o.value, D) + elseif tt == self.LUA_TSTRING then + self:DumpString(o.value, D) + elseif tt == self.LUA_TNIL then + else + --lua_assert(0) -- cannot happen + end + end + n = f.sizep + self:DumpInt(n, D) + for i = 0, n - 1 do + self:DumpFunction(f.p[i], f.source, D) + end +end + +------------------------------------------------------------------------ +-- dump child function prototypes from function prototype +------------------------------------------------------------------------ +function luaU:DumpFunction(f, p, D) + local source = f.source + if source == p then source = nil end + self:DumpString(source, D) + self:DumpInt(f.lineDefined, D) + self:DumpByte(f.nups, D) + self:DumpByte(f.numparams, D) + self:DumpByte(f.is_vararg, D) + self:DumpByte(f.maxstacksize, D) + self:DumpLines(f, D) + self:DumpLocals(f, D) + self:DumpUpvalues(f, D) + self:DumpConstants(f, D) + self:DumpCode(f, D) +end + +------------------------------------------------------------------------ +-- dump Lua header section (some sizes hard-coded) +------------------------------------------------------------------------ +function luaU:DumpHeader(D) + self:DumpLiteral(self.LUA_SIGNATURE, D) + self:DumpByte(self.VERSION, D) + self:DumpByte(self:endianness(), D) + self:DumpByte(4, D) -- sizeof(int) + self:DumpByte(4, D) -- sizeof(size_t) + self:DumpByte(4, D) -- sizeof(Instruction) + self:DumpByte(luaP.SIZE_OP, D) + self:DumpByte(luaP.SIZE_A, D) + self:DumpByte(luaP.SIZE_B, D) + self:DumpByte(luaP.SIZE_C, D) + self:DumpByte(8, D) -- sizeof(lua_Number) + self:DumpNumber(self.TEST_NUMBER, D) +end + +------------------------------------------------------------------------ +-- dump function as precompiled chunk +-- * w, data are created from make_setS, make_setF +------------------------------------------------------------------------ +function luaU:dump(L, Main, w, data) + local D = {} -- DumpState + D.L = L + D.write = w + D.data = data + self:DumpHeader(D) + self:DumpFunction(Main, nil, D) + -- added: for a chunk writer writing to a file, this final call with + -- nil data is to indicate to the writer to close the file + D.write(nil, D.data) +end + +------------------------------------------------------------------------ +-- find byte order (from lundump.c) +-- * hard-coded to little-endian +------------------------------------------------------------------------ +function luaU:endianness() + return 1 +end diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/llex.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/llex.lua new file mode 100644 index 0000000..077f1aa --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/llex.lua @@ -0,0 +1,531 @@ +--[[-------------------------------------------------------------------- + + llex.lua + Lua 5 lexical analyzer in Lua + This file is part of Yueliang. + + Copyright (c) 2005-2006 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * intended to 'imitate' llex.c code; performance is not a concern +-- * tokens are strings; code structure largely retained +-- * deleted stuff (compared to llex.c) are noted, comments retained +-- * Added: +-- luaX:chunkid (from lobject.c) +-- * To use the lexer: +-- (1) luaX:init() to initialize the lexer +-- (2) luaX:setinput() to set the input stream to lex, get LS +-- (3) call luaX:lex() to get tokens, until "TK_EOS": +-- LS.t.token = luaX:lex(LS, LS.t) +-- * since EOZ is returned as a string, be careful when regexp testing +----------------------------------------------------------------------]] + +luaX = {} + +-- FIRST_RESERVED is not required as tokens are manipulated as strings +-- TOKEN_LEN deleted; maximum length of a reserved word + +------------------------------------------------------------------------ +-- "ORDER RESERVED" deleted; enumeration in one place: luaX.RESERVED +------------------------------------------------------------------------ + +-- terminal symbols denoted by reserved words: TK_AND to TK_WHILE +-- other terminal symbols: TK_NAME to TK_EOS +luaX.RESERVED = [[ +TK_AND and +TK_BREAK break +TK_DO do +TK_ELSE else +TK_ELSEIF elseif +TK_END end +TK_FALSE false +TK_FOR for +TK_FUNCTION function +TK_IF if +TK_IN in +TK_LOCAL local +TK_NIL nil +TK_NOT not +TK_OR or +TK_REPEAT repeat +TK_RETURN return +TK_THEN then +TK_TRUE true +TK_UNTIL until +TK_WHILE while +TK_NAME *name +TK_CONCAT .. +TK_DOTS ... +TK_EQ == +TK_GE >= +TK_LE <= +TK_NE ~= +TK_NUMBER *number +TK_STRING *string +TK_EOS ]] + +-- NUM_RESERVED is not required; number of reserved words + +--[[-------------------------------------------------------------------- +-- Instead of passing seminfo, the Token struct (e.g. LS.t) is passed +-- so that lexer functions can use its table element, LS.t.seminfo +-- +-- Token (struct of LS.t and LS.lookahead): +-- token -- token symbol +-- seminfo -- semantics information +-- +-- LexState (struct of LS; LS is initialized by luaX:setinput): +-- current -- current character +-- linenumber -- input line counter +-- lastline -- line of last token 'consumed' +-- t -- current token (table: struct Token) +-- lookahead -- look ahead token (table: struct Token) +-- fs -- 'FuncState' is private to the parser +-- L -- LuaState +-- z -- input stream +-- buff -- buffer for tokens +-- source -- current source name +-- nestlevel -- level of nested non-terminals +----------------------------------------------------------------------]] + +-- token2string is now a hash; see luaX:init + +------------------------------------------------------------------------ +-- initialize lexer +------------------------------------------------------------------------ +function luaX:init() + self.token2string = {} + self.string2token = {} + for v in string.gfind(self.RESERVED, "[^\n]+") do + local _, _, tok, str = string.find(v, "(%S+)%s+(%S+)") + self.token2string[tok] = str + self.string2token[str] = tok + end +end + +luaX.MAXSRC = 80 + +------------------------------------------------------------------------ +-- returns a suitably-formatted chunk name or id +-- * from lobject.c, used in llex.c and ldebug.c +-- * the result, out, is returned (was first argument) +------------------------------------------------------------------------ +function luaX:chunkid(source, bufflen) + local out + local first = string.sub(source, 1, 1) + if first == "=" then + out = string.sub(source, 2, bufflen) -- remove first char + else -- out = "source", or "...source" + if first == "@" then + source = string.sub(source, 2) -- skip the '@' + bufflen = bufflen - string.len(" `...' ") + local l = string.len(source) + out = "" + if l > bufflen then + source = string.sub(source, 1 + l - bufflen) -- get last part of file name + out = out.."..." + end + out = out..source + else -- out = [string "string"] + local len = string.find(source, "\n", 1, 1) -- stop at first newline + len = len and (len - 1) or string.len(source) + bufflen = bufflen - string.len(" [string \"...\"] ") + if len > bufflen then len = bufflen end + out = "[string \"" + if len < string.len(source) then -- must truncate? + out = out..string.sub(source, 1, len).."..." + else + out = out..source + end + out = out.."\"]" + end + end + return out +end + +--[[-------------------------------------------------------------------- +-- Support functions for lexer +-- * all lexer errors eventually reaches errorline: + checklimit -> syntaxerror -> error -> errorline + lexerror -> error -> errorline +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- limit check, syntax error if fails (also called by parser) +------------------------------------------------------------------------ +function luaX:checklimit(ls, val, limit, msg) + if val > limit then + msg = string.format("too many %s (limit=%d)", msg, limit) + self:syntaxerror(ls, msg) + end +end + +------------------------------------------------------------------------ +-- formats error message and throws error (also called by parser) +------------------------------------------------------------------------ +function luaX:errorline(ls, s, token, line) + local buff = self:chunkid(ls.source, self.MAXSRC) + error(string.format("%s:%d: %s near `%s'", buff, line, s, token)) +end + +------------------------------------------------------------------------ +-- throws an error, adds line number +------------------------------------------------------------------------ +function luaX:error(ls, s, token) + self:errorline(ls, s, token, ls.linenumber) +end + +------------------------------------------------------------------------ +-- throws a syntax error (mainly called by parser) +-- * ls.t.token has to be set by the function calling luaX:lex +-- (see next() and lookahead() in lparser.c) +------------------------------------------------------------------------ +function luaX:syntaxerror(ls, msg) + local lasttoken + local tok = ls.t.token + if tok == "TK_NAME" then + lasttoken = ls.t.seminfo + elseif tok == "TK_STRING" or tok == "TK_NUMBER" then + lasttoken = ls.buff + else + lasttoken = self:token2str(ls.t.token) + end + self:error(ls, msg, lasttoken) +end + +------------------------------------------------------------------------ +-- look up token and return keyword if found (also called by parser) +------------------------------------------------------------------------ +function luaX:token2str(ls, token) + if string.sub(token, 1, 3) ~= "TK_" then + return token + else + --lua_assert(string.len(token) == 1) + return self.token2string[token] + end +end + +------------------------------------------------------------------------ +-- throws a lexer error +------------------------------------------------------------------------ +function luaX:lexerror(ls, s, token) + if token == "TK_EOS" then + self:error(ls, s, self:token2str(ls, token)) + else + self:error(ls, s, ls.buff) + end +end + +------------------------------------------------------------------------ +-- move on to next line +------------------------------------------------------------------------ +function luaX:inclinenumber(LS) + self:next(LS) -- skip '\n' + LS.linenumber = LS.linenumber + 1 + self:checklimit(LS, LS.linenumber, self.MAX_INT, "lines in a chunk") +end + +luaX.MAX_INT = 2147483645 -- INT_MAX-2 for 32-bit systems (llimits.h) + +------------------------------------------------------------------------ +-- initializes an input stream for lexing +-- * if LS (the lexer state) is passed as a table, then it is filled in, +-- otherwise it has to be retrieved as a return value +------------------------------------------------------------------------ +function luaX:setinput(L, LS, z, source) + if not LS then LS = {} end -- create struct + if not LS.lookahead then LS.lookahead = {} end + if not LS.t then LS.t = {} end + LS.L = L + LS.lookahead.token = "TK_EOS" -- no look-ahead token + LS.z = z + LS.fs = nil + LS.linenumber = 1 + LS.lastline = 1 + LS.source = source + self:next(LS) -- read first char + if LS.current == "#" then + repeat -- skip first line + self:next(LS) + until LS.current == "\n" or LS.current == "EOZ" + end + return LS +end + +--[[-------------------------------------------------------------------- +-- LEXICAL ANALYZER +----------------------------------------------------------------------]] + +-- NOTE the following buffer handling stuff are no longer required: +-- use buffer to store names, literal strings and numbers +-- EXTRABUFF deleted; extra space to allocate when growing buffer +-- MAXNOCHECK deleted; maximum number of chars that can be read without checking buffer size +-- checkbuffer(LS, len) deleted + +------------------------------------------------------------------------ +-- gets the next character and returns it +------------------------------------------------------------------------ +function luaX:next(LS) + local c = luaZ:zgetc(LS.z) + LS.current = c + return c +end + +------------------------------------------------------------------------ +-- saves the given character into the token buffer +------------------------------------------------------------------------ +function luaX:save(LS, c) + LS.buff = LS.buff..c +end + +------------------------------------------------------------------------ +-- save current character into token buffer, grabs next character +------------------------------------------------------------------------ +function luaX:save_and_next(LS) + self:save(LS, LS.current) + return self:next(LS) +end + +------------------------------------------------------------------------ +-- reads a name +-- * originally returns the string length +------------------------------------------------------------------------ +function luaX:readname(LS) + LS.buff = "" + repeat + self:save_and_next(LS) + until LS.current == "EOZ" or not string.find(LS.current, "[_%w]") + return LS.buff +end + +------------------------------------------------------------------------ +-- reads a number (LUA_NUMBER) +------------------------------------------------------------------------ +function luaX:read_numeral(LS, comma, Token) + LS.buff = "" + if comma then self:save(LS, '.') end + while string.find(LS.current, "%d") do + self:save_and_next(LS) + end + if LS.current == "." then + self:save_and_next(LS) + if LS.current == "." then + self:save_and_next(LS) + self:lexerror(LS, + "ambiguous syntax (decimal point x string concatenation)", + "TK_NUMBER") + end + end + while string.find(LS.current, "%d") do + self:save_and_next(LS) + end + if LS.current == "e" or LS.current == "E" then + self:save_and_next(LS) -- read 'E' + if LS.current == "+" or LS.current == "-" then + self:save_and_next(LS) -- optional exponent sign + end + while string.find(LS.current, "%d") do + self:save_and_next(LS) + end + end + local seminfo = tonumber(LS.buff) + if not seminfo then + self:lexerror(LS, "malformed number", "TK_NUMBER") + end + Token.seminfo = seminfo +end + +------------------------------------------------------------------------ +-- reads a long string or long comment +------------------------------------------------------------------------ +function luaX:read_long_string(LS, Token) + local cont = 0 + LS.buff = "" + self:save(LS, "[") -- save first '[' + self:save_and_next(LS) -- pass the second '[' + if LS.current == "\n" then -- string starts with a newline? + self:inclinenumber(LS) -- skip it + end + while true do + local c = LS.current + if c == "EOZ" then + self:lexerror(LS, Token and "unfinished long string" or + "unfinished long comment", "TK_EOS") + elseif c == "[" then + self:save_and_next(LS) + if LS.current == "[" then + cont = cont + 1 + self:save_and_next(LS) + end + elseif c == "]" then + self:save_and_next(LS) + if LS.current == "]" then + if cont == 0 then break end + cont = cont - 1 + self:save_and_next(LS) + end + elseif c == "\n" then + self:save(LS, "\n") + self:inclinenumber(LS) + if not Token then LS.buff = "" end -- reset buffer to avoid wasting space + else + self:save_and_next(LS) + end--if c + end--while + self:save_and_next(LS) -- skip the second ']' + if Token then + Token.seminfo = string.sub(LS.buff, 3, -3) + end +end + +------------------------------------------------------------------------ +-- reads a string +------------------------------------------------------------------------ +function luaX:read_string(LS, del, Token) + LS.buff = "" + self:save_and_next(LS) + while LS.current ~= del do + local c = LS.current + if c == "EOZ" then + self:lexerror(LS, "unfinished string", "TK_EOS") + elseif c == "\n" then + self:lexerror(LS, "unfinished string", "TK_STRING") + elseif c == "\\" then + c = self:next(LS) -- do not save the '\' + if c ~= "EOZ" then -- will raise an error next loop + -- escapes handling greatly simplified here: + local i = string.find("abfnrtv\n", c, 1, 1) + if i then + self:save(LS, string.sub("\a\b\f\n\r\t\v\n", i, i)) + if i == 8 then self:inclinenumber(LS) else self:next(LS) end + elseif not string.find(c, "%d") then + self:save_and_next(LS) -- handles \\, \", \', and \? + else -- \xxx + c, i = 0, 0 + repeat + c = 10 * c + LS.current + self:next(LS) + i = i + 1 + until i >= 3 or not string.find(LS.current, "%d") + if c > 255 then -- UCHAR_MAX + self:lexerror(LS, "escape sequence too large", "TK_STRING") + end + self:save(LS, string.char(c)) + end + end + else + self:save_and_next(LS) + end--if c + end--while + self:save_and_next(LS) -- skip delimiter + Token.seminfo = string.sub(LS.buff, 2, -2) +end + +------------------------------------------------------------------------ +-- main lexer function +------------------------------------------------------------------------ +function luaX:lex(LS, Token) + while true do + local c = LS.current + ---------------------------------------------------------------- + if c == "\n" then + self:inclinenumber(LS) + ---------------------------------------------------------------- + elseif c == "-" then + c = self:next(LS) + if c ~= "-" then return "-" end + -- else is a comment + c = self:next(LS) + if c == "[" and self:next(LS) == "[" then + self:read_long_string(LS) -- long comment + else -- short comment + c = LS.current + while c ~= "\n" and c ~= "EOZ" do + c = self:next(LS) + end + end + ---------------------------------------------------------------- + elseif c == "[" then + c = self:next(LS) + if c ~= "[" then return "[" + else + self:read_long_string(LS, Token) + return "TK_STRING" + end + ---------------------------------------------------------------- + elseif c == "=" then + c = self:next(LS) + if c ~= "=" then return "=" + else self:next(LS); return "TK_EQ" end + ---------------------------------------------------------------- + elseif c == "<" then + c = self:next(LS) + if c ~= "=" then return "<" + else self:next(LS); return "TK_LE" end + ---------------------------------------------------------------- + elseif c == ">" then + c = self:next(LS) + if c ~= "=" then return ">" + else self:next(LS); return "TK_GE" end + ---------------------------------------------------------------- + elseif c == "~" then + c = self:next(LS) + if c ~= "=" then return "~" + else self:next(LS); return "TK_NE" end + ---------------------------------------------------------------- + elseif c == "\"" or c == "'" then + self:read_string(LS, c, Token) + return "TK_STRING" + ---------------------------------------------------------------- + elseif c == "." then + c = self:next(LS) + if c == "." then + c = self:next(LS) + if c == "." then + self:next(LS) + return "TK_DOTS" -- ... + else + return "TK_CONCAT" -- .. + end + elseif not string.find(c, "%d") then + return '.' + else + self:read_numeral(LS, true, Token) + return "TK_NUMBER" + end + ---------------------------------------------------------------- + elseif c == "EOZ" then + return "TK_EOS" + ---------------------------------------------------------------- + else -- default + if string.find(c, "%s") then + self:next(LS) + elseif string.find(c, "%d") then + self:read_numeral(LS, false, Token) + return "TK_NUMBER" + elseif string.find(c, "[_%a]") then + -- identifier or reserved word + local l = self:readname(LS) + local tok = self.string2token[l] + if tok then return tok end -- reserved word? + Token.seminfo = l + return "TK_NAME" + else + if string.find(c, "%c") then + self:error(LS, "invalid control char", + string.format("char(%d)", string.byte(c))) + end + self:next(LS) + return c -- single-char tokens (+ - / ...) + end + ---------------------------------------------------------------- + end--if c + end--while +end diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lopcodes.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lopcodes.lua new file mode 100644 index 0000000..0c4eebd --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lopcodes.lua @@ -0,0 +1,349 @@ +--[[-------------------------------------------------------------------- + + lopcodes.lua + Lua 5 virtual machine opcodes in Lua + This file is part of Yueliang. + + Copyright (c) 2005-2006 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * an Instruction is a table with OP, A, B, C, Bx elements; this +-- should allow instruction handling to work with doubles and ints +-- * Added: +-- luaP:Instruction(i): convert field elements to a 4-char string +-- luaP:DecodeInst(x): convert 4-char string into field elements +-- * WARNING luaP:Instruction outputs instructions encoded in little- +-- endian form and field size and positions are hard-coded +----------------------------------------------------------------------]] + +luaP = {} + +--[[ +=========================================================================== + We assume that instructions are unsigned numbers. + All instructions have an opcode in the first 6 bits. + Instructions can have the following fields: + 'A' : 8 bits + 'B' : 9 bits + 'C' : 9 bits + 'Bx' : 18 bits ('B' and 'C' together) + 'sBx' : signed Bx + + A signed argument is represented in excess K; that is, the number + value is the unsigned value minus K. K is exactly the maximum value + for that argument (so that -max is represented by 0, and +max is + represented by 2*max), which is half the maximum for the corresponding + unsigned argument. +=========================================================================== +--]] + +luaP.OpMode = {"iABC", "iABx", "iAsBx"} -- basic instruction format + +------------------------------------------------------------------------ +-- size and position of opcode arguments. +-- * WARNING size and position is hard-coded elsewhere in this script +------------------------------------------------------------------------ +luaP.SIZE_C = 9 +luaP.SIZE_B = 9 +luaP.SIZE_Bx = luaP.SIZE_C + luaP.SIZE_B +luaP.SIZE_A = 8 + +luaP.SIZE_OP = 6 + +luaP.POS_C = luaP.SIZE_OP +luaP.POS_B = luaP.POS_C + luaP.SIZE_C +luaP.POS_Bx = luaP.POS_C +luaP.POS_A = luaP.POS_B + luaP.SIZE_B + +------------------------------------------------------------------------ +-- limits for opcode arguments. +-- we use (signed) int to manipulate most arguments, +-- so they must fit in BITS_INT-1 bits (-1 for sign) +------------------------------------------------------------------------ +-- removed "#if SIZE_Bx < BITS_INT-1" test, assume this script is +-- running on a Lua VM with double or int as LUA_NUMBER + +luaP.MAXARG_Bx = math.ldexp(1, luaP.SIZE_Bx) - 1 +luaP.MAXARG_sBx = math.floor(luaP.MAXARG_Bx / 2) -- 'sBx' is signed + +luaP.MAXARG_A = math.ldexp(1, luaP.SIZE_A) - 1 +luaP.MAXARG_B = math.ldexp(1, luaP.SIZE_B) - 1 +luaP.MAXARG_C = math.ldexp(1, luaP.SIZE_C) - 1 + +-- creates a mask with 'n' 1 bits at position 'p' +-- MASK1(n,p) deleted +-- creates a mask with 'n' 0 bits at position 'p' +-- MASK0(n,p) deleted + +--[[-------------------------------------------------------------------- + Visual representation for reference: + + 31 | | | 0 bit position + +-----+-----+-----+----------+ + | A | B | C | Opcode | iABC format + +-----+-----+-----+----------+ + - 8 - 9 - 9 - 6 - field sizes + +-----+-----+-----+----------+ + | A | [s]Bx | Opcode | iABx | iAsBx format + +-----+-----+-----+----------+ +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- the following macros help to manipulate instructions +-- * changed to a table object representation, very clean compared to +-- the [nightmare] alternatives of using a number or a string +------------------------------------------------------------------------ + +-- these accept or return opcodes in the form of string names +function luaP:GET_OPCODE(i) return self.ROpCode[i.OP] end +function luaP:SET_OPCODE(i, o) i.OP = self.OpCode[o] end + +function luaP:GETARG_A(i) return i.A end +function luaP:SETARG_A(i, u) i.A = u end + +function luaP:GETARG_B(i) return i.B end +function luaP:SETARG_B(i, b) i.B = b end + +function luaP:GETARG_C(i) return i.C end +function luaP:SETARG_C(i, b) i.C = b end + +function luaP:GETARG_Bx(i) return i.Bx end +function luaP:SETARG_Bx(i, b) i.Bx = b end + +function luaP:GETARG_sBx(i) return i.Bx - self.MAXARG_sBx end +function luaP:SETARG_sBx(i, b) i.Bx = b + self.MAXARG_sBx end + +function luaP:CREATE_ABC(o,a,b,c) + return {OP = self.OpCode[o], A = a, B = b, C = c} +end + +function luaP:CREATE_ABx(o,a,bc) + return {OP = self.OpCode[o], A = a, Bx = bc} +end + +------------------------------------------------------------------------ +-- returns a 4-char string little-endian encoded form of an instruction +------------------------------------------------------------------------ +function luaP:Instruction(i) + local I, c0, c1, c2, c3 + if i.Bx then + -- change to OP/A/B/C format + i.C = math.mod(i.Bx, 512) + i.B = math.floor(i.Bx / 512) + end + I = i.C * 64 + i.OP + c0 = math.mod(I, 256) + I = i.B * 128 + math.floor(I / 256) -- 7 bits of C left + c1 = math.mod(I, 256) + I = math.floor(I / 256) -- 8 bits of B left + c2 = math.mod(I, 256) + c3 = math.mod(i.A, 256) + return string.char(c0, c1, c2, c3) +end + +------------------------------------------------------------------------ +-- decodes a 4-char little-endian string into an instruction struct +------------------------------------------------------------------------ +function luaP:DecodeInst(x) + local i = {} + local I = string.byte(x, 1) + local op = math.mod(I, 64) + i.OP = op + I = string.byte(x, 2) * 4 + math.floor(I / 64) -- 2 bits of c0 left + i.C = math.mod(I, 512) + i.B = string.byte(x, 3) * 2 + math.floor(I / 128) -- 1 bit of c2 left + i.A = string.byte(x, 4) + local opmode = self.OpMode[tonumber(string.sub(self.opmodes[op + 1], 7, 7))] + if opmode ~= "iABC" then + i.Bx = i.B * 512 + i.C + end + return i +end + +------------------------------------------------------------------------ +-- invalid register that fits in 8 bits +------------------------------------------------------------------------ +luaP.NO_REG = luaP.MAXARG_A + +------------------------------------------------------------------------ +-- R(x) - register +-- Kst(x) - constant (in constant table) +-- RK(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK) +------------------------------------------------------------------------ + +------------------------------------------------------------------------ +-- grep "ORDER OP" if you change these enums +------------------------------------------------------------------------ + +--[[-------------------------------------------------------------------- +Lua virtual machine opcodes (enum OpCode): +------------------------------------------------------------------------ +name args description +------------------------------------------------------------------------ +OP_MOVE A B R(A) := R(B) +OP_LOADK A Bx R(A) := Kst(Bx) +OP_LOADBOOL A B C R(A) := (Bool)B; if (C) PC++ +OP_LOADNIL A B R(A) := ... := R(B) := nil +OP_GETUPVAL A B R(A) := UpValue[B] +OP_GETGLOBAL A Bx R(A) := Gbl[Kst(Bx)] +OP_GETTABLE A B C R(A) := R(B)[RK(C)] +OP_SETGLOBAL A Bx Gbl[Kst(Bx)] := R(A) +OP_SETUPVAL A B UpValue[B] := R(A) +OP_SETTABLE A B C R(A)[RK(B)] := RK(C) +OP_NEWTABLE A B C R(A) := {} (size = B,C) +OP_SELF A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] +OP_ADD A B C R(A) := RK(B) + RK(C) +OP_SUB A B C R(A) := RK(B) - RK(C) +OP_MUL A B C R(A) := RK(B) * RK(C) +OP_DIV A B C R(A) := RK(B) / RK(C) +OP_POW A B C R(A) := RK(B) ^ RK(C) +OP_UNM A B R(A) := -R(B) +OP_NOT A B R(A) := not R(B) +OP_CONCAT A B C R(A) := R(B).. ... ..R(C) +OP_JMP sBx PC += sBx +OP_EQ A B C if ((RK(B) == RK(C)) ~= A) then pc++ +OP_LT A B C if ((RK(B) < RK(C)) ~= A) then pc++ +OP_LE A B C if ((RK(B) <= RK(C)) ~= A) then pc++ +OP_TEST A B C if (R(B) <=> C) then R(A) := R(B) else pc++ +OP_CALL A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) +OP_TAILCALL A B C return R(A)(R(A+1), ... ,R(A+B-1)) +OP_RETURN A B return R(A), ... ,R(A+B-2) (see note) +OP_FORLOOP A sBx R(A)+=R(A+2); if R(A) =) R(A) +OP_CLOSURE A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) +----------------------------------------------------------------------]] + +luaP.opnames = {} -- opcode names +luaP.OpCode = {} -- lookup name -> number +luaP.ROpCode = {} -- lookup number -> name + +-- ORDER OP +local i = 0 +for v in string.gfind([[ +MOVE LOADK LOADBOOL LOADNIL GETUPVAL +GETGLOBAL GETTABLE SETGLOBAL SETUPVAL SETTABLE +NEWTABLE SELF ADD SUB MUL +DIV POW UNM NOT CONCAT +JMP EQ LT LE TEST +CALL TAILCALL RETURN FORLOOP TFORLOOP +TFORPREP SETLIST SETLISTO CLOSE CLOSURE +]], "%S+") do + local n = "OP_"..v + luaP.opnames[i] = v + luaP.OpCode[n] = i + luaP.ROpCode[i] = n + i = i + 1 +end +luaP.NUM_OPCODES = i + +--[[ +=========================================================================== + Notes: + (1) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, + and can be 0: OP_CALL then sets 'top' to last_result+1, so + next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use 'top'. + + (2) In OP_RETURN, if (B == 0) then return up to 'top' + + (3) For comparisons, B specifies what conditions the test should accept. + + (4) All 'skips' (pc++) assume that next instruction is a jump + + (5) OP_SETLISTO is used when the last item in a table constructor is a + function, so the number of elements set is up to top of stack +=========================================================================== +--]] + +------------------------------------------------------------------------ +-- masks for instruction properties +------------------------------------------------------------------------ +-- was enum OpModeMask: +luaP.OpModeBreg = 2 -- B is a register +luaP.OpModeBrk = 3 -- B is a register/constant +luaP.OpModeCrk = 4 -- C is a register/constant +luaP.OpModesetA = 5 -- instruction set register A +luaP.OpModeK = 6 -- Bx is a constant +luaP.OpModeT = 1 -- operator is a test + +------------------------------------------------------------------------ +-- get opcode mode, e.g. "iABC" +------------------------------------------------------------------------ +function luaP:getOpMode(m) + return self.OpMode[tonumber(string.sub(self.opmodes[self.OpCode[m] + 1], 7, 7))] +end + +------------------------------------------------------------------------ +-- test an instruction property flag +-- * b is a string, e.g. "OpModeBreg" +------------------------------------------------------------------------ +function luaP:testOpMode(m, b) + return (string.sub(self.opmodes[self.OpCode[m] + 1], self[b], self[b]) == "1") +end + +-- number of list items to accumulate before a SETLIST instruction +-- (must be a power of 2) +-- * used in lparser, lvm, ldebug, ltests +luaP.LFIELDS_PER_FLUSH = 32 + +-- luaP_opnames[] is set above, as the luaP.opnames table +-- opmode(t,b,bk,ck,sa,k,m) deleted + +--[[-------------------------------------------------------------------- + Legend for luaP:opmodes: + T -> T B -> B mode -> m, where iABC = 1 + Bk -> b Ck -> C iABx = 2 + sA -> A K -> K iAsBx = 3 +----------------------------------------------------------------------]] + +-- ORDER OP +luaP.opmodes = { +-- TBbCAKm opcode + "0100101", -- OP_MOVE + "0000112", -- OP_LOADK + "0000101", -- OP_LOADBOOL + "0100101", -- OP_LOADNIL + "0000101", -- OP_GETUPVAL + "0000112", -- OP_GETGLOBAL + "0101101", -- OP_GETTABLE + "0000012", -- OP_SETGLOBAL + "0000001", -- OP_SETUPVAL + "0011001", -- OP_SETTABLE + "0000101", -- OP_NEWTABLE + "0101101", -- OP_SELF + "0011101", -- OP_ADD + "0011101", -- OP_SUB + "0011101", -- OP_MUL + "0011101", -- OP_DIV + "0011101", -- OP_POW + "0100101", -- OP_UNM + "0100101", -- OP_NOT + "0101101", -- OP_CONCAT + "0000003", -- OP_JMP + "1011001", -- OP_EQ + "1011001", -- OP_LT + "1011001", -- OP_LE + "1100101", -- OP_TEST + "0000001", -- OP_CALL + "0000001", -- OP_TAILCALL + "0000001", -- OP_RETURN + "0000003", -- OP_FORLOOP + "1000001", -- OP_TFORLOOP + "0000003", -- OP_TFORPREP + "0000002", -- OP_SETLIST + "0000002", -- OP_SETLISTO + "0000001", -- OP_CLOSE + "0000102", -- OP_CLOSURE +} diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lparser.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lparser.lua new file mode 100644 index 0000000..3180a7f --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lparser.lua @@ -0,0 +1,1706 @@ +--[[-------------------------------------------------------------------- + + lparser.lua + Lua 5 parser in Lua + This file is part of Yueliang. + + Copyright (c) 2005-2006 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * LUA_COMPATUPSYNTAX option changed into a comment block +-- * Added: +-- some constants, see below +-- luaY:newproto (from lfunc.c) -- called by lparser, lundump, luac +-- luaY:int2fb (from lobject.c) -- called by lparser, ltests +-- luaY:log2 (from lobject.c) -- called by lparser, ltests, ltable +-- luaY:growvector (from lmem.h) -- skeleton only, limit checking +-- * Unimplemented: +-- luaG_checkcode() in lua_assert is not currently implemented +----------------------------------------------------------------------]] + +--requires luaP, luaX, luaK +luaY = {} + +------------------------------------------------------------------------ +-- constants used by parser +-- * MAX_INT duplicated in luaX.MAX_INT +------------------------------------------------------------------------ +luaY.MAX_INT = 2147483645 -- INT_MAX-2 for 32-bit systems (llimits.h) +luaY.MAXVARS = 200 -- (llimits.h) +luaY.MAXUPVALUES = 32 -- (llimits.h) +luaY.MAXPARAMS = 100 -- (llimits.h) +luaY.LUA_MAXPARSERLEVEL = 200 -- (llimits.h) +luaY.LUA_MULTRET = -1 -- (lua.h) +luaY.MAXSTACK = 250 -- (llimits.h, used in lcode.lua) + +------------------------------------------------------------------------ +-- Expression descriptor +------------------------------------------------------------------------ + +--[[-------------------------------------------------------------------- +-- * expkind changed to string constants; luaY:assignment was the only +-- function to use a relational operator with this enumeration +-- VVOID -- no value +-- VNIL -- no value +-- VTRUE -- no value +-- VFALSE -- no value +-- VK -- info = index of constant in 'k' +-- VLOCAL -- info = local register +-- VUPVAL, -- info = index of upvalue in 'upvalues' +-- VGLOBAL -- info = index of table; aux = index of global name in 'k' +-- VINDEXED -- info = table register; aux = index register (or 'k') +-- VJMP -- info = instruction pc +-- VRELOCABLE -- info = instruction pc +-- VNONRELOC -- info = result register +-- VCALL -- info = result register +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- struct expdesc: +-- k -- (enum: expkind) +-- info, aux +-- t -- patch list of 'exit when true' +-- f -- patch list of 'exit when false' +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- state needed to generate code for a given function +-- struct FuncState: +-- f -- current function header (table: Proto) +-- h -- table to find (and reuse) elements in 'k' (table: Table) +-- prev -- enclosing function (table: FuncState) +-- ls -- lexical state (table: LexState) +-- L -- copy of the Lua state (table: lua_State) +-- bl -- chain of current blocks (table: BlockCnt) +-- pc -- next position to code (equivalent to 'ncode') +-- lasttarget -- 'pc' of last 'jump target' +-- jpc -- list of pending jumps to 'pc' +-- freereg -- first free register +-- nk -- number of elements in 'k' +-- np -- number of elements in 'p' +-- nlocvars -- number of elements in 'locvars' +-- nactvar -- number of active local variables +-- upvalues[MAXUPVALUES] -- upvalues (table: expdesc) +-- actvar[MAXVARS] -- declared-variable stack +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- converts an integer to a "floating point byte", represented as +-- (mmmmmxxx), where the real value is (xxx) * 2^(mmmmm) +------------------------------------------------------------------------ + +function luaY:int2fb(x) + local m = 0 -- mantissa + while x >= 8 do + x = math.floor((x + 1) / 2) + m = m + 1 + end + return m * 8 + x +end + +------------------------------------------------------------------------ +-- calculates log value for encoding the hash portion's size +-- * there are 2 implementations: the shorter one uses math.frexp +-- while the other one is based on the original code, so pick one... +-- * since LUA_NUMBER is assumed to be a double elsewhere, the +-- shorter version works fine +------------------------------------------------------------------------ +--[[ +function luaY:log2(x) + -- this is based on the original lua0_log2 in lobject.c + local log_8 = { -- index starts from 1 + 0, + 1,1, + 2,2,2,2, + 3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 + } + if x >= 65536 then + if x >= 16777216 then + return log_8[math.mod(math.floor(x / 16777216), 256)] + 24 + else + return log_8[math.mod(math.floor(x / 65536), 256)] + 16 + end + else + if x >= 256 then + return log_8[math.mod(math.floor(x / 256), 256)] + 8 + elseif x > 0 then + return log_8[math.mod(x, 256)] + end + return -1 -- special 'log' for 0 + end +end +--]] +-- [[ +function luaY:log2(x) + -- math result is always one more than lua0_log2() + local mn, ex = math.frexp(x) + return ex - 1 +end +--]] + +------------------------------------------------------------------------ +-- this is a stripped-down luaM_growvector (from lmem.h) which is a +-- macro based on luaM_growaux (in lmem.c); all this function does is +-- reproduce the size limit checking logic of the original function +-- so that error behaviour is identical; all arguments preserved for +-- convenience, even those which are unused +-- * set the t field to nil, since this originally does a sizeof(t) +-- * size (originally a pointer) is never updated, their final values +-- are set by luaY:close_func(), so overall things should still work +------------------------------------------------------------------------ +function luaY:growvector(L, v, nelems, size, t, limit, e) + local MINSIZEARRAY = 4 -- defined in lmem.c + -- still have at least MINSIZEARRAY free places + if nelems >= limit - MINSIZEARRAY then + luaX:syntaxerror(ls, e) + end +end + +-- getlocvar(fs, i) has been placed with functions for locals, changed +-- into a function + +------------------------------------------------------------------------ +-- tracks and limits parsing depth, assert check at end of parsing +------------------------------------------------------------------------ +function luaY:enterlevel(ls) + ls.nestlevel = ls.nestlevel + 1 + if ls.nestlevel > self.LUA_MAXPARSERLEVEL then + luaX:syntaxerror(ls, "too many syntax levels") + end +end + +------------------------------------------------------------------------ +-- tracks parsing depth, a pair with luaY:enterlevel() +------------------------------------------------------------------------ +function luaY:leavelevel(ls) + ls.nestlevel = ls.nestlevel - 1 +end + +------------------------------------------------------------------------ +-- nodes for block list (list of active blocks) +------------------------------------------------------------------------ +--[[-------------------------------------------------------------------- +-- struct BlockCnt: +-- previous -- chain (table: struct BlockCnt) +-- breaklist -- list of jumps out of this loop +-- nactvar -- # active local variables outside the breakable structure +-- upval -- true if some variable in the block is an upvalue (boolean) +-- isbreakable -- true if 'block' is a loop (boolean) +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- prototypes for recursive non-terminal functions +------------------------------------------------------------------------ +-- prototypes deleted; not required in Lua + +------------------------------------------------------------------------ +-- reads in next token +-- * luaX:lex fills in ls.t.seminfo too, lookahead is handled +------------------------------------------------------------------------ +function luaY:next(ls) + ls.lastline = ls.linenumber + if ls.lookahead.token ~= "TK_EOS" then -- is there a look-ahead token? + ls.t.token = ls.lookahead.token -- use this one + ls.t.seminfo = ls.lookahead.seminfo + ls.lookahead.token = "TK_EOS" -- and discharge it + else + ls.t.token = luaX:lex(ls, ls.t) -- read next token + end +end + +------------------------------------------------------------------------ +-- peek at next token (single lookahead only) +------------------------------------------------------------------------ +function luaY:lookahead(ls) + lua_assert(ls.lookahead.token == "TK_EOS") + ls.lookahead.token = luaX:lex(ls, ls.lookahead) +end + +------------------------------------------------------------------------ +-- throws a syntax error if token expected is not there +------------------------------------------------------------------------ +function luaY:error_expected(ls, token) + luaX:syntaxerror(ls, + string.format("`%s' expected", luaX:token2str(ls, token))) +end + +------------------------------------------------------------------------ +-- tests for a token, returns outcome +-- * return value changed to boolean +------------------------------------------------------------------------ +function luaY:testnext(ls, c) + if ls.t.token == c then + self:next(ls) + return true + else + return false + end +end + +------------------------------------------------------------------------ +-- check for existence of a token, throws error if not found +------------------------------------------------------------------------ +function luaY:check(ls, c) + if not self:testnext(ls, c) then + self:error_expected(ls, c) + end +end + +------------------------------------------------------------------------ +-- throws error if condition not matched +------------------------------------------------------------------------ +function luaY:check_condition(ls, c, msg) + if not c then luaX:syntaxerror(ls, msg) end +end + +------------------------------------------------------------------------ +-- verifies token conditions are met or else throw error +------------------------------------------------------------------------ +function luaY:check_match(ls, what, who, where) + if not self:testnext(ls, what) then + if where == ls.linenumber then + self:error_expected(ls, what) + else + luaX:syntaxerror(ls, string.format( + "`%s' expected (to close `%s' at line %d)", + luaX:token2str(ls, what), luaX:token2str(ls, who), where)) + end + end +end + +------------------------------------------------------------------------ +-- expect that token is a name, return the name +------------------------------------------------------------------------ +function luaY:str_checkname(ls) + self:check_condition(ls, ls.t.token == "TK_NAME", " expected") + local ts = ls.t.seminfo + self:next(ls) + return ts +end + +------------------------------------------------------------------------ +-- initialize a struct expdesc, expression description data structure +------------------------------------------------------------------------ +function luaY:init_exp(e, k, i) + e.f, e.t = luaK.NO_JUMP, luaK.NO_JUMP + e.k = k + e.info = i +end + +------------------------------------------------------------------------ +-- adds given string s in string pool, sets e as VK +------------------------------------------------------------------------ +function luaY:codestring(ls, e, s) + self:init_exp(e, "VK", luaK:stringK(ls.fs, s)) +end + +------------------------------------------------------------------------ +-- consume a name token, adds it to string pool, sets e as VK +------------------------------------------------------------------------ +function luaY:checkname(ls, e) + self:codestring(ls, e, self:str_checkname(ls)) +end + +------------------------------------------------------------------------ +-- returns local variable entry struct for a function +------------------------------------------------------------------------ +function luaY:getlocvar(fs, i) + return fs.f.locvars[ fs.actvar[i] ] +end + +------------------------------------------------------------------------ +-- creates struct entry for a local variable +-- * used by new_localvar() only +------------------------------------------------------------------------ +function luaY:registerlocalvar(ls, varname) + local fs = ls.fs + local f = fs.f + self:growvector(ls.L, f.locvars, fs.nlocvars, f.sizelocvars, + nil, self.MAX_INT, "") + f.locvars[fs.nlocvars] = {} -- LocVar + f.locvars[fs.nlocvars].varname = varname + local nlocvars = fs.nlocvars + fs.nlocvars = fs.nlocvars + 1 + return nlocvars +end + +------------------------------------------------------------------------ +-- register a local variable, set in active variable list +-- * used in new_localvarstr(), parlist(), fornum(), forlist(), +-- localfunc(), localstat() +------------------------------------------------------------------------ +function luaY:new_localvar(ls, name, n) + local fs = ls.fs + luaX:checklimit(ls, fs.nactvar + n + 1, self.MAXVARS, "local variables") + fs.actvar[fs.nactvar + n] = self:registerlocalvar(ls, name) +end + +------------------------------------------------------------------------ +-- adds nvars number of new local variables, set debug information +-- * used in create_local(), code_params(), forbody(), localfunc(), +-- localstat() +------------------------------------------------------------------------ +function luaY:adjustlocalvars(ls, nvars) + local fs = ls.fs + fs.nactvar = fs.nactvar + nvars + for i = 1, nvars do + self:getlocvar(fs, fs.nactvar - i).startpc = fs.pc + end +end + +------------------------------------------------------------------------ +-- removes a number of locals, set debug information +-- * used in leaveblock(), close_func() +------------------------------------------------------------------------ +function luaY:removevars(ls, tolevel) + local fs = ls.fs + while fs.nactvar > tolevel do + fs.nactvar = fs.nactvar - 1 + self:getlocvar(fs, fs.nactvar).endpc = fs.pc + end +end + +------------------------------------------------------------------------ +-- creates a new local variable given a name and an offset from nactvar +-- * used in fornum(), forlist() for loop variables; in create_local() +------------------------------------------------------------------------ +function luaY:new_localvarstr(ls, name, n) + self:new_localvar(ls, name, n) +end + +------------------------------------------------------------------------ +-- creates a single local variable and activates it +-- * used only in code_params() for "arg", body() for "self" +------------------------------------------------------------------------ +function luaY:create_local(ls, name) + self:new_localvarstr(ls, name, 0) + self:adjustlocalvars(ls, 1) +end + +------------------------------------------------------------------------ +-- returns an existing upvalue index based on the given name, or +-- creates a new upvalue struct entry and returns the new index +-- * used only in singlevaraux() +------------------------------------------------------------------------ +function luaY:indexupvalue(fs, name, v) + local f = fs.f + for i = 0, f.nups - 1 do + if fs.upvalues[i].k == v.k and fs.upvalues[i].info == v.info then + lua_assert(fs.f.upvalues[i] == name) + return i + end + end + -- new one + luaX:checklimit(fs.ls, f.nups + 1, self.MAXUPVALUES, "upvalues") + self:growvector(fs.L, fs.f.upvalues, f.nups, fs.f.sizeupvalues, + nil, self.MAX_INT, "") + fs.f.upvalues[f.nups] = name + -- this is a partial copy; only k & info fields used + fs.upvalues[f.nups] = { k = v.k, info = v.info } + local nups = f.nups + f.nups = f.nups + 1 + return nups +end + +------------------------------------------------------------------------ +-- search the local variable namespace of the given fs for a match +-- * used only in singlevaraux() +------------------------------------------------------------------------ +function luaY:searchvar(fs, n) + for i = fs.nactvar - 1, 0, -1 do + if n == self:getlocvar(fs, i).varname then + return i + end + end + return -1 -- not found +end + +------------------------------------------------------------------------ +-- * mark upvalue flags in function states up to a given level +-- * used only in singlevaraux() +------------------------------------------------------------------------ +function luaY:markupval(fs, level) + local bl = fs.bl + while bl and bl.nactvar > level do bl = bl.previous end + if bl then bl.upval = true end +end + +------------------------------------------------------------------------ +-- handle locals, globals and upvalues and related processing +-- * search mechanism is recursive, calls itself to search parents +-- * used only in singlevar() +------------------------------------------------------------------------ +function luaY:singlevaraux(fs, n, var, base) + if fs == nil then -- no more levels? + self:init_exp(var, "VGLOBAL", luaP.NO_REG) -- default is global variable + else + local v = self:searchvar(fs, n) -- look up at current level + if v >= 0 then + self:init_exp(var, "VLOCAL", v) + if base == 0 then + self:markupval(fs, v) -- local will be used as an upval + end + else -- not found at current level; try upper one + self:singlevaraux(fs.prev, n, var, 0) + if var.k == "VGLOBAL" then + if base ~= 0 then + var.info = luaK:stringK(fs, n) -- info points to global name + end + else -- LOCAL or UPVAL + var.info = self:indexupvalue(fs, n, var) + var.k = "VUPVAL" -- upvalue in this level + end + end--if v + end--if fs +end + +------------------------------------------------------------------------ +-- consume a name token, creates a variable (global|local|upvalue) +-- * used in prefixexp(), funcname() +------------------------------------------------------------------------ +function luaY:singlevar(ls, var, base) + local varname = self:str_checkname(ls) + self:singlevaraux(ls.fs, varname, var, base) + return varname +end + +------------------------------------------------------------------------ +-- adjust RHS to match LHS in an assignment +-- * used in assignment(), forlist(), localstat() +------------------------------------------------------------------------ +function luaY:adjust_assign(ls, nvars, nexps, e) + local fs = ls.fs + local extra = nvars - nexps + if e.k == "VCALL" then + extra = extra + 1 -- includes call itself + if extra <= 0 then extra = 0 + else luaK:reserveregs(fs, extra - 1) end + luaK:setcallreturns(fs, e, extra) -- call provides the difference + else + if e.k ~= "VVOID" then luaK:exp2nextreg(fs, e) end -- close last expression + if extra > 0 then + local reg = fs.freereg + luaK:reserveregs(fs, extra) + luaK:_nil(fs, reg, extra) + end + end +end + +------------------------------------------------------------------------ +-- perform initialization for a parameter list, adds arg if needed +-- * used only in parlist() +------------------------------------------------------------------------ +function luaY:code_params(ls, nparams, dots) + local fs = ls.fs + self:adjustlocalvars(ls, nparams) + luaX:checklimit(ls, fs.nactvar, self.MAXPARAMS, "parameters") + fs.f.numparams = fs.nactvar + fs.f.is_vararg = dots and 1 or 0 + if dots then + self:create_local(ls, "arg") + end + luaK:reserveregs(fs, fs.nactvar) -- reserve register for parameters +end + +------------------------------------------------------------------------ +-- enters a code unit, initializes elements +------------------------------------------------------------------------ +function luaY:enterblock(fs, bl, isbreakable) + bl.breaklist = luaK.NO_JUMP + bl.isbreakable = isbreakable + bl.nactvar = fs.nactvar + bl.upval = false + bl.previous = fs.bl + fs.bl = bl + lua_assert(fs.freereg == fs.nactvar) +end + +------------------------------------------------------------------------ +-- leaves a code unit, close any upvalues +------------------------------------------------------------------------ +function luaY:leaveblock(fs) + local bl = fs.bl + fs.bl = bl.previous + self:removevars(fs.ls, bl.nactvar) + if bl.upval then + luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0) + end + lua_assert(bl.nactvar == fs.nactvar) + fs.freereg = fs.nactvar -- free registers + luaK:patchtohere(fs, bl.breaklist) +end + +------------------------------------------------------------------------ +-- implement the instantiation of a function prototype, append list of +-- upvalues after the instantiation instruction +-- * used only in body() +------------------------------------------------------------------------ +function luaY:pushclosure(ls, func, v) + local fs = ls.fs + local f = fs.f + self:growvector(ls.L, f.p, fs.np, f.sizep, nil, + luaP.MAXARG_Bx, "constant table overflow") + f.p[fs.np] = func.f + fs.np = fs.np + 1 + self:init_exp(v, "VRELOCABLE", luaK:codeABx(fs, "OP_CLOSURE", 0, fs.np - 1)) + for i = 0, func.f.nups - 1 do + local o = (func.upvalues[i].k == "VLOCAL") and "OP_MOVE" or "OP_GETUPVAL" + luaK:codeABC(fs, o, 0, func.upvalues[i].info, 0) + end +end + +------------------------------------------------------------------------ +-- initialize a new function prototype structure +------------------------------------------------------------------------ +function luaY:newproto(L) + local f = {} -- Proto + -- luaC_link deleted + f.k = {} + f.sizek = 0 + f.p = {} + f.sizep = 0 + f.code = {} + f.sizecode = 0 + f.sizelineinfo = 0 + f.sizeupvalues = 0 + f.nups = 0 + f.upvalues = {} + f.numparams = 0 + f.is_vararg = 0 + f.maxstacksize = 0 + f.lineinfo = {} + f.sizelocvars = 0 + f.locvars = {} + f.lineDefined = 0 + f.source = nil + return f +end + +------------------------------------------------------------------------ +-- opening of a function +------------------------------------------------------------------------ +function luaY:open_func(ls, fs) + local f = self:newproto(ls.L) + fs.f = f + fs.prev = ls.fs -- linked list of funcstates + fs.ls = ls + fs.L = ls.L + ls.fs = fs + fs.pc = 0 + fs.lasttarget = 0 + fs.jpc = luaK.NO_JUMP + fs.freereg = 0 + fs.nk = 0 + fs.h = {} -- constant table; was luaH_new call + fs.np = 0 + fs.nlocvars = 0 + fs.nactvar = 0 + fs.bl = nil + f.source = ls.source + f.maxstacksize = 2 -- registers 0/1 are always valid +end + +------------------------------------------------------------------------ +-- closing of a function +------------------------------------------------------------------------ +function luaY:close_func(ls) + local L = ls.L + local fs = ls.fs + local f = fs.f + self:removevars(ls, 0) + luaK:codeABC(fs, "OP_RETURN", 0, 1, 0) -- final return + -- luaM_reallocvector deleted for f->code, f->lineinfo, f->k, f->p, + -- f->locvars, f->upvalues; not required for Lua table arrays + f.sizecode = fs.pc + f.sizelineinfo = fs.pc + f.sizek = fs.nk + f.sizep = fs.np + f.sizelocvars = fs.nlocvars + f.sizeupvalues = f.nups + --lua_assert(luaG_checkcode(f)) -- currently not implemented + lua_assert(fs.bl == nil) + ls.fs = fs.prev +end + +------------------------------------------------------------------------ +-- parser initialization function +-- * note additional sub-tables needed for LexState, FuncState +------------------------------------------------------------------------ +function luaY:parser(L, z, buff) + local lexstate = {} -- LexState + lexstate.t = {} + lexstate.lookahead = {} + local funcstate = {} -- FuncState + funcstate.upvalues = {} + funcstate.actvar = {} + lexstate.buff = buff + lexstate.nestlevel = 0 + luaX:setinput(L, lexstate, z, z.name) + self:open_func(lexstate, funcstate) + self:next(lexstate) -- read first token + self:chunk(lexstate) + self:check_condition(lexstate, lexstate.t.token == "TK_EOS", " expected") + self:close_func(lexstate) + lua_assert(funcstate.prev == nil) + lua_assert(funcstate.f.nups == 0) + lua_assert(lexstate.nestlevel == 0) + return funcstate.f +end + +--[[-------------------------------------------------------------------- +-- GRAMMAR RULES +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- parse a function name suffix, for function call specifications +-- * used in primaryexp(), funcname() +------------------------------------------------------------------------ +function luaY:field(ls, v) + -- field -> ['.' | ':'] NAME + local fs = ls.fs + local key = {} -- expdesc + luaK:exp2anyreg(fs, v) + self:next(ls) -- skip the dot or colon + self:checkname(ls, key) + luaK:indexed(fs, v, key) +end + +------------------------------------------------------------------------ +-- parse a table indexing suffix, for constructors, expressions +-- * used in recfield(), primaryexp() +------------------------------------------------------------------------ +function luaY:index(ls, v) + -- index -> '[' expr ']' + self:next(ls) -- skip the '[' + self:expr(ls, v) + luaK:exp2val(ls.fs, v) + self:check(ls, "]") +end + +--[[-------------------------------------------------------------------- +-- Rules for Constructors +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- struct ConsControl: +-- v -- last list item read (table: struct expdesc) +-- t -- table descriptor (table: struct expdesc) +-- nh -- total number of 'record' elements +-- na -- total number of array elements +-- tostore -- number of array elements pending to be stored +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- parse a table record (hash) field +-- * used in constructor() +------------------------------------------------------------------------ +function luaY:recfield(ls, cc) + -- recfield -> (NAME | '['exp1']') = exp1 + local fs = ls.fs + local reg = ls.fs.freereg + local key, val = {}, {} -- expdesc + if ls.t.token == "TK_NAME" then + luaX:checklimit(ls, cc.nh, self.MAX_INT, "items in a constructor") + cc.nh = cc.nh + 1 + self:checkname(ls, key) + else -- ls->t.token == '[' + self:index(ls, key) + end + self:check(ls, "=") + luaK:exp2RK(fs, key) + self:expr(ls, val) + luaK:codeABC(fs, "OP_SETTABLE", cc.t.info, luaK:exp2RK(fs, key), + luaK:exp2RK(fs, val)) + fs.freereg = reg -- free registers +end + +------------------------------------------------------------------------ +-- emit a set list instruction if enough elements (LFIELDS_PER_FLUSH) +-- * used in constructor() +------------------------------------------------------------------------ +function luaY:closelistfield(fs, cc) + if cc.v.k == "VVOID" then return end -- there is no list item + luaK:exp2nextreg(fs, cc.v) + cc.v.k = "VVOID" + if cc.tostore == luaP.LFIELDS_PER_FLUSH then + luaK:codeABx(fs, "OP_SETLIST", cc.t.info, cc.na - 1) -- flush + cc.tostore = 0 -- no more items pending + fs.freereg = cc.t.info + 1 -- free registers + end +end + +------------------------------------------------------------------------ +-- emit a set list instruction at the end of parsing list constructor +-- * used in constructor() +------------------------------------------------------------------------ +function luaY:lastlistfield(fs, cc) + if cc.tostore == 0 then return end + if cc.v.k == "VCALL" then + luaK:setcallreturns(fs, cc.v, self.LUA_MULTRET) + luaK:codeABx(fs, "OP_SETLISTO", cc.t.info, cc.na - 1) + else + if cc.v.k ~= "VVOID" then + luaK:exp2nextreg(fs, cc.v) + end + luaK:codeABx(fs, "OP_SETLIST", cc.t.info, cc.na - 1) + end + fs.freereg = cc.t.info + 1 -- free registers +end + +------------------------------------------------------------------------ +-- parse a table list (array) field +-- * used in constructor() +------------------------------------------------------------------------ +function luaY:listfield(ls, cc) + self:expr(ls, cc.v) + luaX:checklimit(ls, cc.na, luaP.MAXARG_Bx, "items in a constructor") + cc.na = cc.na + 1 + cc.tostore = cc.tostore + 1 +end + +------------------------------------------------------------------------ +-- parse a table constructor +-- * used in funcargs(), simpleexp() +------------------------------------------------------------------------ +function luaY:constructor(ls, t) + -- constructor -> '{' [ field { fieldsep field } [ fieldsep ] ] '}' + -- field -> recfield | listfield + -- fieldsep -> ',' | ';' + local fs = ls.fs + local line = ls.linenumber + local pc = luaK:codeABC(fs, "OP_NEWTABLE", 0, 0, 0) + local cc = {} -- ConsControl + cc.v = {} + cc.na, cc.nh, cc.tostore = 0, 0, 0 + cc.t = t + self:init_exp(t, "VRELOCABLE", pc) + self:init_exp(cc.v, "VVOID", 0) -- no value (yet) + luaK:exp2nextreg(ls.fs, t) -- fix it at stack top (for gc) + self:check(ls, "{") + repeat + lua_assert(cc.v.k == "VVOID" or cc.tostore > 0) + self:testnext(ls, ";") -- compatibility only + if ls.t.token == "}" then break end + self:closelistfield(fs, cc) + local c = ls.t.token + if c == "TK_NAME" then -- may be listfields or recfields + self:lookahead(ls) + if ls.lookahead.token ~= "=" then -- expression? + self:listfield(ls, cc) + else + self:recfield(ls, cc) + end + elseif c == "[" then -- constructor_item -> recfield + self:recfield(ls, cc) + else -- constructor_part -> listfield + self:listfield(ls, cc) + end + until not self:testnext(ls, ",") and not self:testnext(ls, ";") + self:check_match(ls, "}", "{", line) + self:lastlistfield(fs, cc) + luaP:SETARG_B(fs.f.code[pc], self:int2fb(cc.na)) -- set initial array size + luaP:SETARG_C(fs.f.code[pc], self:log2(cc.nh) + 1) -- set initial table size +end + +------------------------------------------------------------------------ +-- parse the arguments (parameters) of a function declaration +-- * used in body() +------------------------------------------------------------------------ +function luaY:parlist(ls) + -- parlist -> [ param { ',' param } ] + local nparams = 0 + local dots = false + if ls.t.token ~= ")" then -- is 'parlist' not empty? + repeat + local c = ls.t.token + if c == "TK_DOTS" then + dots = true + self:next(ls) + elseif c == "TK_NAME" then + self:new_localvar(ls, self:str_checkname(ls), nparams) + nparams = nparams + 1 + else + luaX:syntaxerror(ls, " or `...' expected") + end + until dots or not self:testnext(ls, ",") + end + self:code_params(ls, nparams, dots) +end + +------------------------------------------------------------------------ +-- parse function declaration body +-- * used in simpleexp(), localfunc(), funcstat() +------------------------------------------------------------------------ +function luaY:body(ls, e, needself, line) + -- body -> '(' parlist ')' chunk END + local new_fs = {} -- FuncState + new_fs.upvalues = {} + new_fs.actvar = {} + self:open_func(ls, new_fs) + new_fs.f.lineDefined = line + self:check(ls, "(") + if needself then + self:create_local(ls, "self") + end + self:parlist(ls) + self:check(ls, ")") + self:chunk(ls) + self:check_match(ls, "TK_END", "TK_FUNCTION", line) + self:close_func(ls) + self:pushclosure(ls, new_fs, e) +end + +------------------------------------------------------------------------ +-- parse a list of comma-separated expressions +-- * used is multiple locations +------------------------------------------------------------------------ +function luaY:explist1(ls, v) + -- explist1 -> expr { ',' expr } + local n = 1 -- at least one expression + self:expr(ls, v) + while self:testnext(ls, ",") do + luaK:exp2nextreg(ls.fs, v) + self:expr(ls, v) + n = n + 1 + end + return n +end + +------------------------------------------------------------------------ +-- parse the parameters of a function call +-- * contrast with parlist(), used in function declarations +-- * used in primaryexp() +------------------------------------------------------------------------ +function luaY:funcargs(ls, f) + local fs = ls.fs + local args = {} -- expdesc + local nparams + local line = ls.linenumber + local c = ls.t.token + if c == "(" then -- funcargs -> '(' [ explist1 ] ')' + if line ~= ls.lastline then + luaX:syntaxerror(ls, "ambiguous syntax (function call x new statement)") + end + self:next(ls) + if ls.t.token == ")" then -- arg list is empty? + args.k = "VVOID" + else + self:explist1(ls, args) + luaK:setcallreturns(fs, args, self.LUA_MULTRET) + end + self:check_match(ls, ")", "(", line) + elseif c == "{" then -- funcargs -> constructor + self:constructor(ls, args) + elseif c == "TK_STRING" then -- funcargs -> STRING + self:codestring(ls, args, ls.t.seminfo) + self:next(ls) -- must use 'seminfo' before 'next' + else + luaX:syntaxerror(ls, "function arguments expected") + return + end + lua_assert(f.k == "VNONRELOC") + local base = f.info -- base register for call + if args.k == "VCALL" then + nparams = self.LUA_MULTRET -- open call + else + if args.k ~= "VVOID" then + luaK:exp2nextreg(fs, args) -- close last argument + end + nparams = fs.freereg - (base + 1) + end + self:init_exp(f, "VCALL", luaK:codeABC(fs, "OP_CALL", base, nparams + 1, 2)) + luaK:fixline(fs, line) + fs.freereg = base + 1 -- call remove function and arguments and leaves + -- (unless changed) one result +end + +--[[-------------------------------------------------------------------- +-- Expression parsing +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- parses an expression in parentheses or a single variable +-- * used in primaryexp() +------------------------------------------------------------------------ +function luaY:prefixexp(ls, v) + -- prefixexp -> NAME | '(' expr ')' + local c = ls.t.token + if c == "(" then + local line = ls.linenumber + self:next(ls) + self:expr(ls, v) + self:check_match(ls, ")", "(", line) + luaK:dischargevars(ls.fs, v) + elseif c == "TK_NAME" then + self:singlevar(ls, v, 1) + -- LUA_COMPATUPSYNTAX +--[[ + elseif c == "%" then -- for compatibility only + local line = ls.linenumber + self:next(ls) -- skip '%' + local varname = self:singlevar(ls, v, 1) + if v.k ~= "VUPVAL" then + luaX:errorline(ls, "global upvalues are obsolete", varname, line) + end +--]] + else + luaX:syntaxerror(ls, "unexpected symbol") + end--if c + return +end + +------------------------------------------------------------------------ +-- parses a prefixexp (an expression in parentheses or a single variable) +-- or a function call specification +-- * used in simpleexp(), assignment(), exprstat() +------------------------------------------------------------------------ +function luaY:primaryexp(ls, v) + -- primaryexp -> + -- prefixexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } + local fs = ls.fs + self:prefixexp(ls, v) + while true do + local c = ls.t.token + if c == "." then -- field + self:field(ls, v) + elseif c == "[" then -- '[' exp1 ']' + local key = {} -- expdesc + luaK:exp2anyreg(fs, v) + self:index(ls, key) + luaK:indexed(fs, v, key) + elseif c == ":" then -- ':' NAME funcargs + local key = {} -- expdesc + self:next(ls) + self:checkname(ls, key) + luaK:_self(fs, v, key) + self:funcargs(ls, v) + elseif c == "(" or c == "TK_STRING" or c == "{" then -- funcargs + luaK:exp2nextreg(fs, v) + self:funcargs(ls, v) + else + return + end--if c + end--while +end + +------------------------------------------------------------------------ +-- parses general expression types, constants handled here +-- * used in subexpr() +------------------------------------------------------------------------ +function luaY:simpleexp(ls, v) + -- simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | constructor + -- | FUNCTION body | primaryexp + local c = ls.t.token + if c == "TK_NUMBER" then + self:init_exp(v, "VK", luaK:numberK(ls.fs, ls.t.seminfo)) + self:next(ls) -- must use 'seminfo' before 'next' + elseif c == "TK_STRING" then + self:codestring(ls, v, ls.t.seminfo) + self:next(ls) -- must use 'seminfo' before 'next' + elseif c == "TK_NIL" then + self:init_exp(v, "VNIL", 0) + self:next(ls) + elseif c == "TK_TRUE" then + self:init_exp(v, "VTRUE", 0) + self:next(ls) + elseif c == "TK_FALSE" then + self:init_exp(v, "VFALSE", 0) + self:next(ls) + elseif c == "{" then -- constructor + self:constructor(ls, v) + elseif c == "TK_FUNCTION" then + self:next(ls) + self:body(ls, v, false, ls.linenumber) + else + self:primaryexp(ls, v) + end--if c +end + +------------------------------------------------------------------------ +-- Translates unary operators tokens if found, otherwise returns +-- OPR_NOUNOPR. getunopr() and getbinopr() are used in subexpr(). +-- * used in subexpr() +------------------------------------------------------------------------ +function luaY:getunopr(op) + if op == "TK_NOT" then + return "OPR_NOT" + elseif op == "-" then + return "OPR_MINUS" + else + return "OPR_NOUNOPR" + end +end + +------------------------------------------------------------------------ +-- Translates binary operator tokens if found, otherwise returns +-- OPR_NOBINOPR. Code generation uses OPR_* style tokens. +-- * used in subexpr() +------------------------------------------------------------------------ +luaY.getbinopr_table = { + ["+"] = "OPR_ADD", + ["-"] = "OPR_SUB", + ["*"] = "OPR_MULT", + ["/"] = "OPR_DIV", + ["^"] = "OPR_POW", + ["TK_CONCAT"] = "OPR_CONCAT", + ["TK_NE"] = "OPR_NE", + ["TK_EQ"] = "OPR_EQ", + ["<"] = "OPR_LT", + ["TK_LE"] = "OPR_LE", + [">"] = "OPR_GT", + ["TK_GE"] = "OPR_GE", + ["TK_AND"] = "OPR_AND", + ["TK_OR"] = "OPR_OR", +} +function luaY:getbinopr(op) + local opr = self.getbinopr_table[op] + if opr then return opr else return "OPR_NOBINOPR" end +end + +------------------------------------------------------------------------ +-- the following priority table consists of pairs of left/right values +-- for binary operators (was a static const struct); grep for ORDER OPR +------------------------------------------------------------------------ +luaY.priority = { + {6, 6}, {6, 6}, {7, 7}, {7, 7}, -- arithmetic + {10, 9}, {5, 4}, -- power and concat (right associative) + {3, 3}, {3, 3}, -- equality + {3, 3}, {3, 3}, {3, 3}, {3, 3}, -- order + {2, 2}, {1, 1} -- logical (and/or) +} + +luaY.UNARY_PRIORITY = 8 -- priority for unary operators + +------------------------------------------------------------------------ +-- subexpr -> (simpleexp | unop subexpr) { binop subexpr } +-- where 'binop' is any binary operator with a priority higher than 'limit' +------------------------------------------------------------------------ + +------------------------------------------------------------------------ +-- * for priority lookups with self.priority[], 1=left and 2=right +-- +-- Parse subexpressions. Includes handling of unary operators and binary +-- operators. A subexpr is given the rhs priority level of the operator +-- immediately left of it, if any (limit is -1 if none,) and if a binop +-- is found, limit is compared with the lhs priority level of the binop +-- in order to determine which executes first. +-- +-- * recursively called +-- * used in expr() +------------------------------------------------------------------------ +function luaY:subexpr(ls, v, limit) + self:enterlevel(ls) + local uop = self:getunopr(ls.t.token) + if uop ~= "OPR_NOUNOPR" then + self:next(ls) + self:subexpr(ls, v, self.UNARY_PRIORITY) + luaK:prefix(ls.fs, uop, v) + else + self:simpleexp(ls, v) + end + -- expand while operators have priorities higher than 'limit' + local op = self:getbinopr(ls.t.token) + while op ~= "OPR_NOBINOPR" and self.priority[luaK.BinOpr[op] + 1][1] > limit do + local v2 = {} -- expdesc + self:next(ls) + luaK:infix(ls.fs, op, v) + -- read sub-expression with higher priority + local nextop = self:subexpr(ls, v2, self.priority[luaK.BinOpr[op] + 1][2]) + luaK:posfix(ls.fs, op, v, v2) + op = nextop + end + self:leavelevel(ls) + return op -- return first untreated operator +end + +------------------------------------------------------------------------ +-- Expression parsing starts here. Function subexpr is entered with the +-- left operator (which is non-existent) priority of -1, which is lower +-- than all actual operators. Expr information is returned in parm v. +-- * used in multiple locations +------------------------------------------------------------------------ +function luaY:expr(ls, v) + self:subexpr(ls, v, -1) +end + +--[[-------------------------------------------------------------------- +-- Rules for Statements +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- checks next token, used as a look-ahead +-- * returns boolean instead of 0|1 +-- * used in retstat(), chunk() +------------------------------------------------------------------------ +function luaY:block_follow(token) + if token == "TK_ELSE" or token == "TK_ELSEIF" or token == "TK_END" + or token == "TK_UNTIL" or token == "TK_EOS" then + return true + else + return false + end +end + +------------------------------------------------------------------------ +-- parse a code block or unit +-- * used in multiple functions +------------------------------------------------------------------------ +function luaY:block(ls) + -- block -> chunk + local fs = ls.fs + local bl = {} -- BlockCnt + self:enterblock(fs, bl, false) + self:chunk(ls) + lua_assert(bl.breaklist == luaK.NO_JUMP) + self:leaveblock(fs) +end + +------------------------------------------------------------------------ +-- structure to chain all variables in the left-hand side of an +-- assignment +------------------------------------------------------------------------ +--[[-------------------------------------------------------------------- +-- struct LHS_assign: +-- prev -- (table: struct LHS_assign) +-- v -- variable (global, local, upvalue, or indexed) (table: expdesc) +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- check whether, in an assignment to a local variable, the local variable +-- is needed in a previous assignment (to a table). If so, save original +-- local value in a safe place and use this safe copy in the previous +-- assignment. +-- * used in assignment() +------------------------------------------------------------------------ +function luaY:check_conflict(ls, lh, v) + local fs = ls.fs + local extra = fs.freereg -- eventual position to save local variable + local conflict = false + while lh do + if lh.v.k == "VINDEXED" then + if lh.v.info == v.info then -- conflict? + conflict = true + lh.v.info = extra -- previous assignment will use safe copy + end + if lh.v.aux == v.info then -- conflict? + conflict = true + lh.v.aux = extra -- previous assignment will use safe copy + end + end + lh = lh.prev + end + if conflict then + luaK:codeABC(fs, "OP_MOVE", fs.freereg, v.info, 0) -- make copy + luaK:reserveregs(fs, 1) + end +end + +------------------------------------------------------------------------ +-- parse a variable assignment sequence +-- * recursively called +-- * used in exprstat() +------------------------------------------------------------------------ +function luaY:assignment(ls, lh, nvars) + local e = {} -- expdesc + -- test was: VLOCAL <= lh->v.k && lh->v.k <= VINDEXED + local c = lh.v.k + self:check_condition(ls, c == "VLOCAL" or c == "VUPVAL" or c == "VGLOBAL" + or c == "VINDEXED", "syntax error") + if self:testnext(ls, ",") then -- assignment -> ',' primaryexp assignment + local nv = {} -- LHS_assign + nv.v = {} + nv.prev = lh + self:primaryexp(ls, nv.v) + if nv.v.k == "VLOCAL" then + self:check_conflict(ls, lh, nv.v) + end + self:assignment(ls, nv, nvars + 1) + else -- assignment -> '=' explist1 + self:check(ls, "=") + local nexps = self:explist1(ls, e) + if nexps ~= nvars then + self:adjust_assign(ls, nvars, nexps, e) + if nexps > nvars then + ls.fs.freereg = ls.fs.freereg - (nexps - nvars) -- remove extra values + end + else + luaK:setcallreturns(ls.fs, e, 1) -- close last expression + luaK:storevar(ls.fs, lh.v, e) + return -- avoid default + end + end + self:init_exp(e, "VNONRELOC", ls.fs.freereg - 1) -- default assignment + luaK:storevar(ls.fs, lh.v, e) +end + +------------------------------------------------------------------------ +-- parse condition in a repeat statement or an if control structure +-- * used in repeatstat(), test_then_block() +------------------------------------------------------------------------ +function luaY:cond(ls, v) + -- cond -> exp + self:expr(ls, v) -- read condition + if v.k == "VNIL" then v.k = "VFALSE" end -- 'falses' are all equal here + luaK:goiftrue(ls.fs, v) + luaK:patchtohere(ls.fs, v.t) +end + +------------------------------------------------------------------------ +-- The while statement optimizes its code by coding the condition +-- after its body (and thus avoiding one jump in the loop). +------------------------------------------------------------------------ + +------------------------------------------------------------------------ +-- maximum size of expressions for optimizing 'while' code +------------------------------------------------------------------------ +if not luaY.MAXEXPWHILE then + luaY.MAXEXPWHILE = 100 +end + +------------------------------------------------------------------------ +-- the call 'luaK_goiffalse' may grow the size of an expression by +-- at most this: +------------------------------------------------------------------------ +luaY.EXTRAEXP = 5 + +------------------------------------------------------------------------ +-- parse a while-do control structure, body processed by block() +-- * with dynamic array sizes, MAXEXPWHILE + EXTRAEXP limits imposed by +-- the function's implementation can be removed +-- * used in statements() +------------------------------------------------------------------------ +function luaY:whilestat(ls, line) + -- whilestat -> WHILE cond DO block END + -- array size of [MAXEXPWHILE + EXTRAEXP] no longer required + local codeexp = {} -- Instruction + local fs = ls.fs + local v = {} -- expdesc + local bl = {} -- BlockCnt + self:next(ls) -- skip WHILE + local whileinit = luaK:jump(fs) -- jump to condition (which will be moved) + local expinit = luaK:getlabel(fs) + self:expr(ls, v) -- parse condition + if v.k == "VK" then v.k = "VTRUE" end -- 'trues' are all equal here + local lineexp = ls.linenumber + luaK:goiffalse(fs, v) + v.f = luaK:concat(fs, v.f, fs.jpc) + fs.jpc = luaK.NO_JUMP + local sizeexp = fs.pc - expinit -- size of expression code + if sizeexp > self.MAXEXPWHILE then + luaX:syntaxerror(ls, "`while' condition too complex") + end + for i = 0, sizeexp - 1 do -- save 'exp' code + codeexp[i] = fs.f.code[expinit + i] + end + fs.pc = expinit -- remove 'exp' code + self:enterblock(fs, bl, true) + self:check(ls, "TK_DO") + local blockinit = luaK:getlabel(fs) + self:block(ls) + luaK:patchtohere(fs, whileinit) -- initial jump jumps to here + -- move 'exp' back to code + if v.t ~= luaK.NO_JUMP then v.t = v.t + fs.pc - expinit end + if v.f ~= luaK.NO_JUMP then v.f = v.f + fs.pc - expinit end + for i = 0, sizeexp - 1 do + luaK:code(fs, codeexp[i], lineexp) + end + self:check_match(ls, "TK_END", "TK_WHILE", line) + self:leaveblock(fs) + luaK:patchlist(fs, v.t, blockinit) -- true conditions go back to loop + luaK:patchtohere(fs, v.f) -- false conditions finish the loop +end + +------------------------------------------------------------------------ +-- parse a repeat-until control structure, body parsed by block() +-- * used in statements() +------------------------------------------------------------------------ +function luaY:repeatstat(ls, line) + -- repeatstat -> REPEAT block UNTIL cond + local fs = ls.fs + local repeat_init = luaK:getlabel(fs) + local v = {} -- expdesc + local bl = {} -- BlockCnt + self:enterblock(fs, bl, true) + self:next(ls) + self:block(ls) + self:check_match(ls, "TK_UNTIL", "TK_REPEAT", line) + self:cond(ls, v) + luaK:patchlist(fs, v.f, repeat_init) + self:leaveblock(fs) +end + +------------------------------------------------------------------------ +-- parse the single expressions needed in numerical for loops +-- * used in fornum() +------------------------------------------------------------------------ +function luaY:exp1(ls) + local e = {} -- expdesc + self:expr(ls, e) + local k = e.k + luaK:exp2nextreg(ls.fs, e) + return k +end + +------------------------------------------------------------------------ +-- parse a for loop body for both versions of the for loop +-- * used in fornum(), forlist() +------------------------------------------------------------------------ +function luaY:forbody(ls, base, line, nvars, isnum) + local bl = {} -- BlockCnt + local fs = ls.fs + self:adjustlocalvars(ls, nvars) -- scope for all variables + self:check(ls, "TK_DO") + self:enterblock(fs, bl, true) -- loop block + local prep = luaK:getlabel(fs) + self:block(ls) + luaK:patchtohere(fs, prep - 1) + local endfor = isnum and luaK:codeAsBx(fs, "OP_FORLOOP", base, luaK.NO_JUMP) + or luaK:codeABC(fs, "OP_TFORLOOP", base, 0, nvars - 3) + luaK:fixline(fs, line) -- pretend that 'OP_FOR' starts the loop + luaK:patchlist(fs, isnum and endfor or luaK:jump(fs), prep) + self:leaveblock(fs) +end + +------------------------------------------------------------------------ +-- parse a numerical for loop, calls forbody() +-- * used in forstat() +------------------------------------------------------------------------ +function luaY:fornum(ls, varname, line) + -- fornum -> NAME = exp1,exp1[,exp1] DO body + local fs = ls.fs + local base = fs.freereg + self:new_localvar(ls, varname, 0) + self:new_localvarstr(ls, "(for limit)", 1) + self:new_localvarstr(ls, "(for step)", 2) + self:check(ls, "=") + self:exp1(ls) -- initial value + self:check(ls, ",") + self:exp1(ls) -- limit + if self:testnext(ls, ",") then + self:exp1(ls) -- optional step + else -- default step = 1 + luaK:codeABx(fs, "OP_LOADK", fs.freereg, luaK:numberK(fs, 1)) + luaK:reserveregs(fs, 1) + end + luaK:codeABC(fs, "OP_SUB", fs.freereg - 3, fs.freereg - 3, fs.freereg - 1) + luaK:jump(fs) + self:forbody(ls, base, line, 3, true) +end + +------------------------------------------------------------------------ +-- parse a generic for loop, calls forbody() +-- * used in forstat() +------------------------------------------------------------------------ +function luaY:forlist(ls, indexname) + -- forlist -> NAME {,NAME} IN explist1 DO body + local fs = ls.fs + local e = {} -- expdesc + local nvars = 0 + local base = fs.freereg + self:new_localvarstr(ls, "(for generator)", nvars) + nvars = nvars + 1 + self:new_localvarstr(ls, "(for state)", nvars) + nvars = nvars + 1 + self:new_localvar(ls, indexname, nvars) + nvars = nvars + 1 + while self:testnext(ls, ",") do + self:new_localvar(ls, self:str_checkname(ls), nvars) + nvars = nvars + 1 + end + self:check(ls, "TK_IN") + local line = ls.linenumber + self:adjust_assign(ls, nvars, self:explist1(ls, e), e) + luaK:checkstack(fs, 3) -- extra space to call generator + luaK:codeAsBx(fs, "OP_TFORPREP", base, luaK.NO_JUMP) + self:forbody(ls, base, line, nvars, false) +end + +------------------------------------------------------------------------ +-- initial parsing for a for loop, calls fornum() or forlist() +-- * used in statements() +------------------------------------------------------------------------ +function luaY:forstat(ls, line) + -- forstat -> fornum | forlist + local fs = ls.fs + local bl = {} -- BlockCnt + self:enterblock(fs, bl, false) -- block to control variable scope + self:next(ls) -- skip 'for' + local varname = self:str_checkname(ls) -- first variable name + local c = ls.t.token + if c == "=" then + self:fornum(ls, varname, line) + elseif c == "," or c == "TK_IN" then + self:forlist(ls, varname) + else + luaX:syntaxerror(ls, "`=' or `in' expected") + end + self:check_match(ls, "TK_END", "TK_FOR", line) + self:leaveblock(fs) +end + +------------------------------------------------------------------------ +-- parse part of an if control structure, including the condition +-- * used in ifstat() +------------------------------------------------------------------------ +function luaY:test_then_block(ls, v) + -- test_then_block -> [IF | ELSEIF] cond THEN block + self:next(ls) -- skip IF or ELSEIF + self:cond(ls, v) + self:check(ls, "TK_THEN") + self:block(ls) -- 'then' part +end + +------------------------------------------------------------------------ +-- parse an if control structure +-- * used in statements() +------------------------------------------------------------------------ +function luaY:ifstat(ls, line) + -- ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END + local fs = ls.fs + local v = {} -- expdesc + local escapelist = luaK.NO_JUMP + self:test_then_block(ls, v) -- IF cond THEN block + while ls.t.token == "TK_ELSEIF" do + escapelist = luaK:concat(fs, escapelist, luaK:jump(fs)) + luaK:patchtohere(fs, v.f) + self:test_then_block(ls, v) -- ELSEIF cond THEN block + end + if ls.t.token == "TK_ELSE" then + escapelist = luaK:concat(fs, escapelist, luaK:jump(fs)) + luaK:patchtohere(fs, v.f) + self:next(ls) -- skip ELSE (after patch, for correct line info) + self:block(ls) -- 'else' part + else + escapelist = luaK:concat(fs, escapelist, v.f) + end + luaK:patchtohere(fs, escapelist) + self:check_match(ls, "TK_END", "TK_IF", line) +end + +------------------------------------------------------------------------ +-- parse a local function statement +-- * used in statements() +------------------------------------------------------------------------ +function luaY:localfunc(ls) + local v, b = {}, {} -- expdesc + local fs = ls.fs + self:new_localvar(ls, self:str_checkname(ls), 0) + self:init_exp(v, "VLOCAL", fs.freereg) + luaK:reserveregs(fs, 1) + self:adjustlocalvars(ls, 1) + self:body(ls, b, false, ls.linenumber) + luaK:storevar(fs, v, b) + -- debug information will only see the variable after this point! + self:getlocvar(fs, fs.nactvar - 1).startpc = fs.pc +end + +------------------------------------------------------------------------ +-- parse a local variable declaration statement +-- * used in statements() +------------------------------------------------------------------------ +function luaY:localstat(ls) + -- stat -> LOCAL NAME {',' NAME} ['=' explist1] + local nvars = 0 + local nexps + local e = {} -- expdesc + repeat + self:new_localvar(ls, self:str_checkname(ls), nvars) + nvars = nvars + 1 + until not self:testnext(ls, ",") + if self:testnext(ls, "=") then + nexps = self:explist1(ls, e) + else + e.k = "VVOID" + nexps = 0 + end + self:adjust_assign(ls, nvars, nexps, e) + self:adjustlocalvars(ls, nvars) +end + +------------------------------------------------------------------------ +-- parse a function name specification +-- * used in funcstat() +------------------------------------------------------------------------ +function luaY:funcname(ls, v) + -- funcname -> NAME {field} [':' NAME] + local needself = false + self:singlevar(ls, v, 1) + while ls.t.token == "." do + self:field(ls, v) + end + if ls.t.token == ":" then + needself = true + self:field(ls, v) + end + return needself +end + +------------------------------------------------------------------------ +-- parse a function statement +-- * used in statements() +------------------------------------------------------------------------ +function luaY:funcstat(ls, line) + -- funcstat -> FUNCTION funcname body + local v, b = {}, {} -- expdesc + self:next(ls) -- skip FUNCTION + local needself = self:funcname(ls, v) + self:body(ls, b, needself, line) + luaK:storevar(ls.fs, v, b) + luaK:fixline(ls.fs, line) -- definition 'happens' in the first line +end + +------------------------------------------------------------------------ +-- parse a function call with no returns or an assignment statement +-- * used in statements() +------------------------------------------------------------------------ +function luaY:exprstat(ls) + -- stat -> func | assignment + local fs = ls.fs + local v = {} -- LHS_assign + v.v = {} + self:primaryexp(ls, v.v) + if v.v.k == "VCALL" then -- stat -> func + luaK:setcallreturns(fs, v.v, 0) -- call statement uses no results + else -- stat -> assignment + v.prev = nil + self:assignment(ls, v, 1) + end +end + +------------------------------------------------------------------------ +-- parse a return statement +-- * used in statements() +------------------------------------------------------------------------ +function luaY:retstat(ls) + -- stat -> RETURN explist + local fs = ls.fs + local e = {} -- expdesc + local first, nret -- registers with returned values + self:next(ls) -- skip RETURN + if self:block_follow(ls.t.token) or ls.t.token == ";" then + first, nret = 0, 0 -- return no values + else + nret = self:explist1(ls, e) -- optional return values + if e.k == "VCALL" then + luaK:setcallreturns(fs, e, self.LUA_MULTRET) + if nret == 1 then -- tail call? + luaP:SET_OPCODE(luaK:getcode(fs, e), "OP_TAILCALL") + lua_assert(luaP:GETARG_A(luaK:getcode(fs, e)) == fs.nactvar) + end + first = fs.nactvar + nret = self.LUA_MULTRET -- return all values + else + if nret == 1 then -- only one single value? + first = luaK:exp2anyreg(fs, e) + else + luaK:exp2nextreg(fs, e) -- values must go to the 'stack' + first = fs.nactvar -- return all 'active' values + lua_assert(nret == fs.freereg - first) + end + end--if + end--if + luaK:codeABC(fs, "OP_RETURN", first, nret + 1, 0) +end + +------------------------------------------------------------------------ +-- parse a break statement +-- * used in statements() +------------------------------------------------------------------------ +function luaY:breakstat(ls) + -- stat -> BREAK + local fs = ls.fs + local bl = fs.bl + local upval = false + self:next(ls) -- skip BREAK + while bl and not bl.isbreakable do + if bl.upval then upval = true end + bl = bl.previous + end + if not bl then + luaX:syntaxerror(ls, "no loop to break") + end + if upval then + luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0) + end + bl.breaklist = luaK:concat(fs, bl.breaklist, luaK:jump(fs)) +end + +------------------------------------------------------------------------ +-- initial parsing for statements, calls a lot of functions +-- * returns boolean instead of 0|1 +-- * used in chunk() +------------------------------------------------------------------------ +function luaY:statement(ls) + local line = ls.linenumber -- may be needed for error messages + local c = ls.t.token + if c == "TK_IF" then -- stat -> ifstat + self:ifstat(ls, line) + return false + elseif c == "TK_WHILE" then -- stat -> whilestat + self:whilestat(ls, line) + return false + elseif c == "TK_DO" then -- stat -> DO block END + self:next(ls) -- skip DO + self:block(ls) + self:check_match(ls, "TK_END", "TK_DO", line) + return false + elseif c == "TK_FOR" then -- stat -> forstat + self:forstat(ls, line) + return false + elseif c == "TK_REPEAT" then -- stat -> repeatstat + self:repeatstat(ls, line) + return false + elseif c == "TK_FUNCTION" then -- stat -> funcstat + self:funcstat(ls, line) + return false + elseif c == "TK_LOCAL" then -- stat -> localstat + self:next(ls) -- skip LOCAL + if self:testnext(ls, "TK_FUNCTION") then -- local function? + self:localfunc(ls) + else + self:localstat(ls) + end + return false + elseif c == "TK_RETURN" then -- stat -> retstat + self:retstat(ls) + return true -- must be last statement + elseif c == "TK_BREAK" then -- stat -> breakstat + self:breakstat(ls) + return true -- must be last statement + else + self:exprstat(ls) + return false -- to avoid warnings + end--if c +end + +------------------------------------------------------------------------ +-- parse a chunk, which consists of a bunch of statements +-- * used in parser(), body(), block() +------------------------------------------------------------------------ +function luaY:chunk(ls) + -- chunk -> { stat [';'] } + local islast = false + self:enterlevel(ls) + while not islast and not self:block_follow(ls.t.token) do + islast = self:statement(ls) + self:testnext(ls, ";") + lua_assert(ls.fs.freereg >= ls.fs.nactvar) + ls.fs.freereg = ls.fs.nactvar -- free registers + end + self:leavelevel(ls) +end diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/luac.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/luac.lua new file mode 100644 index 0000000..80cc4a5 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/luac.lua @@ -0,0 +1,71 @@ +--[[-------------------------------------------------------------------- + + luac.lua + Primitive luac in Lua + This file is part of Yueliang. + + Copyright (c) 2005 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * based on luac.lua in the test directory of the 5.0.3 distribution +-- * usage: lua luac.lua file.lua +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- load and initialize the required modules +------------------------------------------------------------------------ +require("lzio.lua") +require("llex.lua") +require("lopcodes.lua") +require("ldump.lua") +require("lcode.lua") +require("lparser.lua") + +luaX:init() -- required by llex +local LuaState = {} -- dummy, not actually used, but retained since + -- the intention is to complete a straight port + +------------------------------------------------------------------------ +-- interfacing to yueliang +------------------------------------------------------------------------ + +-- currently asserts are enabled because the codebase hasn't been tested +-- much (if you don't want asserts, just comment them out) +function lua_assert(test) + if not test then error("assertion failed!") end +end + +function yloadfile(filename) + -- luaZ:make_getF returns a file chunk reader + -- luaZ:init returns a zio input stream + local zio = luaZ:init(luaZ:make_getF(filename), nil, "@"..filename) + if not zio then return end + -- luaY:parser parses the input stream + -- func is the function prototype in tabular form; in C, func can + -- now be used directly by the VM, this can't be done in Lua + local func = luaY:parser(LuaState, zio, nil) + -- luaU:make_setS returns a string chunk writer + local writer, buff = luaU:make_setS() + -- luaU:dump builds a binary chunk + luaU:dump(LuaState, func, writer, buff) + -- a string.dump equivalent in returned + return buff.data +end + +------------------------------------------------------------------------ +-- command line interface +------------------------------------------------------------------------ + +assert(arg[1] ~= nil and arg[2] == nil, "usage: lua luac.lua file.lua") +local f = assert(io.open("luac.out","wb")) +f:write(assert(yloadfile(arg[1]))) +io.close(f) + +--end diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lzio.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lzio.lua new file mode 100644 index 0000000..7b98246 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lzio.lua @@ -0,0 +1,120 @@ +--[[-------------------------------------------------------------------- + + lzio.lua + Lua 5 buffered streams in Lua + This file is part of Yueliang. + + Copyright (c) 2005-2006 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * EOZ is implemented as a string, "EOZ" +-- * Format of z structure (ZIO) +-- z.n -- bytes still unread +-- z.p -- last read position in buffer +-- z.reader -- chunk reader function +-- z.data -- additional data +-- z.name -- name of stream +-- * Current position, p, is now last read index instead of a pointer +-- +-- Not implemented: +-- * luaZ_lookahead: used only in lapi.c:lua_load to detect binary chunk +-- * luaZ_read: used only in lundump.c:ezread to read +1 bytes +-- * luaZ_openspace: dropped; let Lua handle buffers as strings +-- * luaZ buffer macros: dropped; unused for now +-- +-- Alternatives: +-- * zname(z) is z.name +-- +-- Added: +-- (both of the following are vaguely adapted from lauxlib.c) +-- * luaZ:make_getS: create Chunkreader from a string +-- * luaZ:make_getF: create Chunkreader that reads from a file +----------------------------------------------------------------------]] + +luaZ = {} + +------------------------------------------------------------------------ +-- * reader() should return a string, or nil if nothing else to parse. +-- Unlike Chunkreaders, there are no arguments like additional data +-- * Chunkreaders are handled in lauxlib.h, see luaL_load(file|buffer) +-- * Original Chunkreader: +-- const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *sz); +-- * This Lua chunk reader implementation: +-- returns string or nil, no arguments to function +------------------------------------------------------------------------ + +------------------------------------------------------------------------ +-- create a chunk reader from a source string +------------------------------------------------------------------------ +function luaZ:make_getS(buff) + local b = buff + return function() -- chunk reader anonymous function here + if not b then return nil end + local data = b + b = nil + return data + end +end + +------------------------------------------------------------------------ +-- create a chunk reader from a source file +------------------------------------------------------------------------ +function luaZ:make_getF(filename) + local LUAL_BUFFERSIZE = 512 + local h = io.open(filename, "r") + if not h then return nil end + return function() -- chunk reader anonymous function here + if not h or io.type(h) == "closed file" then return nil end + local buff = h:read(LUAL_BUFFERSIZE) + if not buff then h:close(); h = nil end + return buff + end +end + +------------------------------------------------------------------------ +-- creates a zio input stream +-- returns the ZIO structure, z +------------------------------------------------------------------------ +function luaZ:init(reader, data, name) + if not reader then return end + local z = {} + z.reader = reader + z.data = data or "" + z.name = name + -- set up additional data for reading + if not data or data == "" then z.n = 0 else z.n = string.len(data) end + z.p = 0 + return z +end + +------------------------------------------------------------------------ +-- fill up input buffer +------------------------------------------------------------------------ +function luaZ:fill(z) + local data = z.reader() + z.data = data + if not data or data == "" then return "EOZ" end + z.n = string.len(data) - 1 + z.p = 1 + return string.sub(data, 1, 1) +end + +------------------------------------------------------------------------ +-- get next character from the input stream +------------------------------------------------------------------------ +function luaZ:zgetc(z) + if z.n > 0 then + z.n = z.n - 1 + z.p = z.p + 1 + return string.sub(z.data, z.p, z.p) + else + return self:fill(z) + end +end diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/bench_llex.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/bench_llex.lua new file mode 100644 index 0000000..0c9403e --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/bench_llex.lua @@ -0,0 +1,99 @@ +--[[-------------------------------------------------------------------- + + bench_llex.lua + Benchmark test for llex.lua + This file is part of Yueliang. + + Copyright (c) 2006 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +require("../lzio") +require("../llex") +luaX:init() + +------------------------------------------------------------------------ +-- load in a standard set of sample files +-- * file set is 5.0.3 front end set sans luac.lua +------------------------------------------------------------------------ + +local fileset, totalsize = {}, 0 +for fn in string.gfind([[ +../lcode.lua +../ldump.lua +../llex.lua +../lopcodes.lua +../lparser.lua +../lzio.lua +]], "%S+") do + table.insert(fileset, fn) +end + +for i = 1, table.getn(fileset) do + local fn = fileset[i] + local inf = io.open(fn, "rb") + if not inf then + error("failed to open "..fn.." for reading") + end + local data = inf:read("*a") + local data_sz = string.len(data) + inf:close() + if not data or data_sz == 0 then + error("failed to read data from "..fn.." or file is zero-length") + end + totalsize = totalsize + data_sz + fileset[i] = data +end + +------------------------------------------------------------------------ +-- benchmark tester +------------------------------------------------------------------------ + +local DURATION = 5 -- how long the benchmark should run + +local L = {} -- LuaState +local LS = {} -- LexState + +local time = os.time +local lexedsize = 0 +local tnow, elapsed = time(), 0 + +while time() == tnow do end -- wait for second to click over +tnow = time() + +while true do + for i = 1, table.getn(fileset) do + ------------------------------------------------------------ + local chunk = fileset[i] + local z = luaZ:init(luaZ:make_getS(chunk), nil, "=string") + luaX:setinput(L, LS, z, z.name) + while true do + LS.t.token = luaX:lex(LS, LS.t) + local tok, seminfo = LS.t.token, LS.t.seminfo + if tok == "TK_EOS" then break end + end + ------------------------------------------------------------ + lexedsize = lexedsize + string.len(chunk) + if time() > tnow then + tnow = time() + elapsed = elapsed + 1 + if elapsed >= DURATION then + -- report performance of lexer + lexedsize = lexedsize / 1024 + local speed = lexedsize / DURATION + print("Lexer performance:") + print("Size of data lexed (KB): "..string.format("%.1f", lexedsize)) + print("Speed of lexer (KB/s): "..string.format("%.1f", speed)) + -- repeat until user breaks program + elapsed = 0 + end + end + ------------------------------------------------------------ + end--for +end--while + +-- end of script diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/sample.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/sample.lua new file mode 100644 index 0000000..dc6eaee --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/sample.lua @@ -0,0 +1,3 @@ +local a = 47 +local b = "hello, world!" +print(a, b) diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_ldump.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_ldump.lua new file mode 100644 index 0000000..d867688 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_ldump.lua @@ -0,0 +1,98 @@ +--[[-------------------------------------------------------------------- + + test_ldump.lua + Test for ldump.lua + This file is part of Yueliang. + + Copyright (c) 2005 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- test dump chunkwriter style +------------------------------------------------------------------------ + +require("../lopcodes") +require("../ldump") + +-- Original typedef: +--int (*lua_Chunkwriter) (lua_State *L, const void* p, size_t sz, void* ud); + +local MyWriter, MyBuff = luaU:make_setS() +if not MyWriter then + error("failed to initialize using make_setS") +end +MyWriter("hello, ", MyBuff) +MyWriter("world!", MyBuff) +print(MyBuff.data) + +local MyWriter, MyBuff = luaU:make_setF("try.txt") +if not MyWriter then + error("failed to initialize using make_setF") +end +MyWriter("hello, ", MyBuff) +MyWriter("world!", MyBuff) +MyWriter(nil, MyBuff) + +------------------------------------------------------------------------ +-- test output of a function prototype +-- * data can be copied from a ChunkSpy listing output +------------------------------------------------------------------------ +-- local a = 47 +-- local b = "hello, world!" +-- print(a, b) +------------------------------------------------------------------------ + +local F = {} +F.source = "sample.lua" +F.lineDefined = 0 +F.nups = 0 +F.numparams = 0 +F.is_vararg = 0 +F.maxstacksize = 5 +F.sizelineinfo = 7 +F.lineinfo = {} +F.lineinfo[0] = 1 +F.lineinfo[1] = 2 +F.lineinfo[2] = 3 +F.lineinfo[3] = 3 +F.lineinfo[4] = 3 +F.lineinfo[5] = 3 +F.lineinfo[6] = 3 +F.sizelocvars = 2 +F.locvars = {} +F.locvars[0] = { varname = "a", startpc = 1, endpc = 6 } +F.locvars[1] = { varname = "b", startpc = 2, endpc = 6 } +F.sizeupvalues = 0 +F.upvalues = {} +F.sizek = 3 +F.k = {} +F.k[0] = { value = 47 } +F.k[1] = { value = "hello, world!" } +F.k[2] = { value = "print" } +F.sizep = 0 +F.p = {} +F.sizecode = 7 +F.code = {} +F.code[0] = { OP = 1, A = 0, Bx = 0 } +F.code[1] = { OP = 1, A = 1, Bx = 1 } +F.code[2] = { OP = 5, A = 2, Bx = 2 } +F.code[3] = { OP = 0, A = 3, B = 0, C = 0 } +F.code[4] = { OP = 0, A = 4, B = 1, C = 0 } +F.code[5] = { OP = 25, A = 2, B = 3, C = 1 } +F.code[6] = { OP = 27, A = 0, B = 1, C = 0 } + +local L = {} +--[[ +local Writer, Buff = luaU:make_setS() +luaU:dump(L, F, Writer, Buff) +for i = 1, string.len(Buff.data) do + io.stdout:write(string.byte(string.sub(Buff.data, i, i)).." ") +end +--]] +local Writer, Buff = luaU:make_setF("try.out") +luaU:dump(L, F, Writer, Buff) diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_llex.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_llex.lua new file mode 100644 index 0000000..6bc834d --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_llex.lua @@ -0,0 +1,504 @@ +--[[-------------------------------------------------------------------- + + test_llex.lua + Test for llex.lua + This file is part of Yueliang. + + Copyright (c) 2005-2006 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- if BRIEF is not set to false, auto-test will silently succeed +------------------------------------------------------------------------ +BRIEF = true -- if set to true, messages are less verbose + +require("../lzio") +require("../llex") +luaX:init() + +------------------------------------------------------------------------ +-- simple manual tests +------------------------------------------------------------------------ + +--[[ +local L = {} -- LuaState +local LS = {} -- LexState + +local function dump(z) + luaX:setinput(L, LS, z, z.name) + while true do + LS.t.token = luaX:lex(LS, LS.t) + local tok, seminfo = LS.t.token, LS.t.seminfo + if tok == "TK_NAME" then + seminfo = " "..seminfo + elseif tok == "TK_NUMBER" then + seminfo = " "..seminfo + elseif tok == "TK_STRING" then + seminfo = " '"..seminfo.."'" + else + seminfo = "" + end + io.stdout:write(tok..seminfo.."\n") + if tok == "TK_EOS" then break end + end +end + +local function try_string(chunk) + dump(luaZ:init(luaZ:make_getS(chunk), nil, "=string")) +end +local function try_file(filename) + dump(luaZ:init(luaZ:make_getF(filename), nil, filename)) +end + +z = try_string("local c = luaZ:zgetc(z)") +z = try_file("test_lzio.lua") +z = try_file("test_llex.lua") +os.exit() +--]] + +------------------------------------------------------------------------ +-- auto-testing of simple test cases to validate lexer behaviour: +-- * NOTE coverage has not been checked; not comprehensive +-- * only test cases with non-empty comments are processed +-- * if no result, then the output is displayed for manual decision +-- (output may be used to set expected success or fail text) +-- * cases expected to be successful may be a partial match +-- * cases expected to fail may also be a partial match +------------------------------------------------------------------------ + +-- [[ +local function auto_test() + local PASS, FAIL = true, false + ------------------------------------------------------------------ + -- table of test cases + ------------------------------------------------------------------ + local test_cases = + { + ------------------------------------------------------------- + --{ "comment", -- comment about the test + -- "chunk", -- chunk to test + -- PASS, -- PASS or FAIL outcome + -- "output", -- output to compare against + --}, + ------------------------------------------------------------- + { "empty chunk string, test EOS", + "", + PASS, "1 TK_EOS", + }, + ------------------------------------------------------------- + { "line number counting", + "\n\n\r\n", + PASS, "4 TK_EOS", + }, + ------------------------------------------------------------- + { "various whitespaces", + " \n\t\t\n \t \t \n\n", + PASS, "5 TK_EOS", + }, + ------------------------------------------------------------- + { "short comment ending in EOS", + "-- moo moo", + PASS, "1 TK_EOS", + }, + ------------------------------------------------------------- + { "short comment ending in newline", + "-- moo moo\n", + PASS, "2 TK_EOS", + }, + ------------------------------------------------------------- + { "several lines of short comments", + "--moo\n-- moo moo\n\n--\tmoo\n", + PASS, "5 TK_EOS", + }, + ------------------------------------------------------------- + { "basic block comment", + "--[[bovine]]", + PASS, "1 TK_EOS", + }, + ------------------------------------------------------------- + { "unterminated block comment 1", + "--[[bovine", + FAIL, ":1: unfinished long comment near `'", + }, + ------------------------------------------------------------- + { "unterminated block comment 2", + "--[[bovine]", + FAIL, ":1: unfinished long comment near `'", + }, + ------------------------------------------------------------- + { "unterminated block comment 3", + "--[[bovine\nmoo moo\nwoof", + FAIL, ":3: unfinished long comment near `'", + }, + ------------------------------------------------------------- + { "basic long string", + "\n[[bovine]]\n", + PASS, "2 TK_STRING = bovine\n3 TK_EOS", + }, + ------------------------------------------------------------- + { "first newline consumed in long string", + "[[\nmoo]]", + PASS, "2 TK_STRING = moo\n2 TK_EOS", + }, + ------------------------------------------------------------- + { "multiline long string", + "[[moo\nmoo moo\n]]", + PASS, "3 TK_STRING = moo\nmoo moo\n\n3 TK_EOS", + }, + ------------------------------------------------------------- + { "unterminated long string 1", + "\n[[\nbovine", + FAIL, ":3: unfinished long string near `'", + }, + ------------------------------------------------------------- + { "unterminated long string 2", + "[[bovine]", + FAIL, ":1: unfinished long string near `'", + }, + ------------------------------------------------------------- + { "unterminated long string 3", + "[[[[ \n", + FAIL, ":2: unfinished long string near `'", + }, + ------------------------------------------------------------- + { "nested long string 1", + "[[moo[[moo]]moo]]", + PASS, "moo[[moo]]moo", + }, + ------------------------------------------------------------- + { "nested long string 2", + "[[moo[[moo[[[[]]]]moo]]moo]]", + PASS, "moo[[moo[[[[]]]]moo]]moo", + }, + ------------------------------------------------------------- + { "nested long string 3", + "[[[[[[]]]][[[[]]]]]]", + PASS, "[[[[]]]][[[[]]]]", + }, + ------------------------------------------------------------- + { "brackets in long strings 1", + "[[moo[moo]]", + PASS, "moo[moo", + }, + ------------------------------------------------------------- + { "brackets in long strings 2", + "[[moo[[moo]moo]]moo]]", + PASS, "moo[[moo]moo]]moo", + }, + ------------------------------------------------------------- + { "unprocessed escapes in long strings", + [[ [[\a\b\f\n\r\t\v\123]] ]], + PASS, [[\a\b\f\n\r\t\v\123]], + }, + ------------------------------------------------------------- + { "unbalanced long string", + "[[moo]]moo]]", + PASS, "1 TK_STRING = moo\n1 TK_NAME = moo\n1 CHAR = ']'\n1 CHAR = ']'\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "keywords 1", + "and break do else", + PASS, "1 TK_AND\n1 TK_BREAK\n1 TK_DO\n1 TK_ELSE\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "keywords 2", + "elseif end false for", + PASS, "1 TK_ELSEIF\n1 TK_END\n1 TK_FALSE\n1 TK_FOR\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "keywords 3", + "function if in local nil", + PASS, "1 TK_FUNCTION\n1 TK_IF\n1 TK_IN\n1 TK_LOCAL\n1 TK_NIL\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "keywords 4", + "not or repeat return", + PASS, "1 TK_NOT\n1 TK_OR\n1 TK_REPEAT\n1 TK_RETURN\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "keywords 5", + "then true until while", + PASS, "1 TK_THEN\n1 TK_TRUE\n1 TK_UNTIL\n1 TK_WHILE\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "concat and dots", + ".. ...", + PASS, "1 TK_CONCAT\n1 TK_DOTS\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "shbang handling 1", + "#blahblah", + PASS, "1 TK_EOS", + }, + ------------------------------------------------------------- + { "shbang handling 2", + "#blahblah\nmoo moo\n", + PASS, "2 TK_NAME = moo\n2 TK_NAME = moo\n3 TK_EOS", + }, + ------------------------------------------------------------- + { "empty string", + [['']], + PASS, "1 TK_STRING = \n1 TK_EOS", + }, + ------------------------------------------------------------- + { "single-quoted string", + [['bovine']], + PASS, "1 TK_STRING = bovine\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "double-quoted string", + [["bovine"]], + PASS, "1 TK_STRING = bovine\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "unterminated string 1", + [['moo ]], + FAIL, ":1: unfinished string near `'", + }, + ------------------------------------------------------------- + { "unterminated string 2", + [["moo \n]], + FAIL, ":1: unfinished string near `'", + }, + ------------------------------------------------------------- + { "escaped newline in string, line number counted", + "\"moo\\\nmoo\\\nmoo\"", + PASS, "3 TK_STRING = moo\nmoo\nmoo\n3 TK_EOS", + }, + ------------------------------------------------------------- + { "escaped characters in string 1", + [["moo\amoo"]], + PASS, "1 TK_STRING = moo\amoo", + }, + ------------------------------------------------------------- + { "escaped characters in string 2", + [["moo\bmoo"]], + PASS, "1 TK_STRING = moo\bmoo", + }, + ------------------------------------------------------------- + { "escaped characters in string 3", + [["moo\f\n\r\t\vmoo"]], + PASS, "1 TK_STRING = moo\f\n\r\t\vmoo", + }, + ------------------------------------------------------------- + { "escaped characters in string 4", + [["\\ \" \' \? \[ \]"]], + PASS, "1 TK_STRING = \\ \" \' \? \[ \]", + }, + ------------------------------------------------------------- + { "escaped characters in string 5", + [["\z \k \: \;"]], + PASS, "1 TK_STRING = z k : ;", + }, + ------------------------------------------------------------- + { "escaped characters in string 6", + [["\8 \65 \160 \180K \097097"]], + PASS, "1 TK_STRING = \8 \65 \160 \180K \097097\n", + }, + ------------------------------------------------------------- + { "escaped characters in string 7", + [["\666"]], + FAIL, ":1: escape sequence too large near `\"'", + }, + ------------------------------------------------------------- + { "simple numbers", + "123 123+", + PASS, "1 TK_NUMBER = 123\n1 TK_NUMBER = 123\n1 CHAR = '+'\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "longer numbers", + "1234567890 12345678901234567890", + PASS, "1 TK_NUMBER = 1234567890\n1 TK_NUMBER = 1.2345678901235e+19\n", + }, + ------------------------------------------------------------- + { "fractional numbers", + ".123 .12345678901234567890", + PASS, "1 TK_NUMBER = 0.123\n1 TK_NUMBER = 0.12345678901235\n", + }, + ------------------------------------------------------------- + { "more numbers with decimal points", + "12345.67890 1.1.", + PASS, "1 TK_NUMBER = 12345.6789\n1 TK_NUMBER = 1.1\n1 CHAR = '.'\n", + }, + ------------------------------------------------------------- + { "double decimal points", + ".1.1", + FAIL, ":1: malformed number near `.1.1'", + }, + ------------------------------------------------------------- + { "double dots within numbers", + "1..1", + FAIL, ":1: ambiguous syntax (decimal point x string concatenation) near `1..'", + }, + ------------------------------------------------------------- + { "incomplete exponential numbers", + "123e", + FAIL, ":1: malformed number near `123e'", + }, + ------------------------------------------------------------- + { "exponential numbers 1", + "1234e5 1234e5.", + PASS, "1 TK_NUMBER = 123400000\n1 TK_NUMBER = 123400000\n1 CHAR = '.'", + }, + ------------------------------------------------------------- + { "exponential numbers 2", + "1234e56 1.23e123", + PASS, "1 TK_NUMBER = 1.234e+59\n1 TK_NUMBER = 1.23e+123\n", + }, + ------------------------------------------------------------- + { "exponential numbers 3", + "12.34e+", + FAIL, ":1: malformed number near `12.34e+'", + }, + ------------------------------------------------------------- + { "exponential numbers 4", + "12.34e+5 123.4e-5 1234.E+5", + PASS, "1 TK_NUMBER = 1234000\n1 TK_NUMBER = 0.001234\n1 TK_NUMBER = 123400000\n", + }, + ------------------------------------------------------------- + { "single character symbols 1", + "= > < ~", + PASS, "1 CHAR = '='\n1 CHAR = '>'\n1 CHAR = '<'\n1 CHAR = '~'\n", + }, + ------------------------------------------------------------- + { "double character symbols", + "== >= <= ~=", + PASS, "1 TK_EQ\n1 TK_GE\n1 TK_LE\n1 TK_NE\n", + }, + ------------------------------------------------------------- + { "simple identifiers", + "abc ABC", + PASS, "1 TK_NAME = abc\n1 TK_NAME = ABC\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "more identifiers", + "_abc _ABC", + PASS, "1 TK_NAME = _abc\n1 TK_NAME = _ABC\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "still more identifiers", + "_aB_ _123", + PASS, "1 TK_NAME = _aB_\n1 TK_NAME = _123\n1 TK_EOS", + }, + ------------------------------------------------------------- + { "invalid control character", + "\4", + FAIL, ":1: invalid control char near `char(4)'", + }, + ------------------------------------------------------------- + { "single character symbols 2", + "` ! @ $ %", + PASS, "1 CHAR = '`'\n1 CHAR = '!'\n1 CHAR = '@'\n1 CHAR = '$'\n1 CHAR = '%'\n", + }, + ------------------------------------------------------------- + { "single character symbols 3", + "^ & * ( )", + PASS, "1 CHAR = '^'\n1 CHAR = '&'\n1 CHAR = '*'\n1 CHAR = '('\n1 CHAR = ')'\n", + }, + ------------------------------------------------------------- + { "single character symbols 4", + "_ - + \\ |", + PASS, "1 TK_NAME = _\n1 CHAR = '-'\n1 CHAR = '+'\n1 CHAR = '\\'\n1 CHAR = '|'\n", + }, + ------------------------------------------------------------- + { "single character symbols 5", + "{ } [ ] :", + PASS, "1 CHAR = '{'\n1 CHAR = '}'\n1 CHAR = '['\n1 CHAR = ']'\n1 CHAR = ':'\n", + }, + ------------------------------------------------------------- + { "single character symbols 6", + "; , . / ?", + PASS, "1 CHAR = ';'\n1 CHAR = ','\n1 CHAR = '.'\n1 CHAR = '/'\n1 CHAR = '?'\n", + }, + ------------------------------------------------------------- + } + ------------------------------------------------------------------ + -- perform a test case + ------------------------------------------------------------------ + function do_test_case(count, test_case) + if comment == "" then return end -- skip empty entries + local comment, chunk, outcome, matcher = unpack(test_case) + local result = PASS + local output = "" + -- initialize lexer + local L, LS = {}, {} + local z = luaZ:init(luaZ:make_getS(chunk), nil, "=test") + luaX:setinput(L, LS, z, z.name) + -- lexer test loop + repeat + -- protected call + local status, token = pcall(luaX.lex, luaX, LS, LS.t) + LS.t.token = token + output = output..LS.linenumber.." " + if status then + -- successful call + if string.len(token) > 1 then + if token == "TK_NAME" + or token == "TK_NUMBER" + or token == "TK_STRING" then + token = token.." = "..LS.t.seminfo + end + elseif string.byte(token) >= 32 then -- displayable chars + token = "CHAR = '"..token.."'" + else -- control characters + token = "CHAR = (".. string.byte(token)..")" + end + output = output..token.."\n" + else + -- failed call + output = output..token -- token is the error message + result = FAIL + break + end + until LS.t.token == "TK_EOS" + -- decision making and reporting + local head = "Test "..count..": "..comment + if matcher == "" then + -- nothing to check against, display for manual check + print(head.."\nMANUAL please check manually".. + "\n--chunk---------------------------------\n"..chunk.. + "\n--actual--------------------------------\n"..output.. + "\n\n") + return + else + if outcome == PASS then + -- success expected, may be a partial match + if string.find(output, matcher, 1, 1) and result == PASS then + if not BRIEF then print(head.."\nOK expected success\n") end + return + end + else + -- failure expected, may be a partial match + if string.find(output, matcher, 1, 1) and result == FAIL then + if not BRIEF then print(head.."\nOK expected failure\n") end + return + end + end + -- failed because of unmatched string or boolean result + local function passfail(status) + if status == PASS then return "PASS" else return "FAIL" end + end + print(head.." *FAILED*".. + "\noutcome="..passfail(outcome).. + "\nactual= "..passfail(result).. + "\n--chunk---------------------------------\n"..chunk.. + "\n--expected------------------------------\n"..matcher.. + "\n--actual--------------------------------\n"..output.. + "\n\n") + end + end + ------------------------------------------------------------------ + -- perform auto testing + ------------------------------------------------------------------ + for i,test_case in ipairs(test_cases) do + do_test_case(i, test_case) + end +end + +auto_test() +--]] diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lparser.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lparser.lua new file mode 100644 index 0000000..b9400cc --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lparser.lua @@ -0,0 +1,60 @@ +--[[-------------------------------------------------------------------- + + test_lparser.lua + Test for lparser.lua + This file is part of Yueliang. + + Copyright (c) 2005 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- test the whole kaboodle +------------------------------------------------------------------------ + +require("../lzio") +require("../llex") +require("../lopcodes") +require("../ldump") +require("../lcode") +require("../lparser") + +function lua_assert(test) + if not test then error("assertion failed!") end +end + +luaX:init() + +------------------------------------------------------------------------ +-- try 1 +------------------------------------------------------------------------ + +local zio = luaZ:init(luaZ:make_getS("local a = 1"), nil, "=string") +local LuaState = {} +local Func = luaY:parser(LuaState, zio, nil) + +--[[ +for i, v in Func do + if type(v) == "string" or type(v) == "number" then + print(i, v) + elseif type(v) == "table" then + print(i, "TABLE") + end +end +--]] + +local Writer, Buff = luaU:make_setF("parse1.out") +luaU:dump(LuaState, Func, Writer, Buff) + +------------------------------------------------------------------------ +-- try 2 +------------------------------------------------------------------------ + +zio = luaZ:init(luaZ:make_getF("sample.lua"), nil, "@sample.lua") +Func = luaY:parser(LuaState, zio, nil) +Writer, Buff = luaU:make_setF("parse2.out") +luaU:dump(LuaState, Func, Writer, Buff) diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lparser2.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lparser2.lua new file mode 100644 index 0000000..b912e68 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lparser2.lua @@ -0,0 +1,202 @@ +--[[-------------------------------------------------------------------- + + test_lparser2.lua + Test for lparser.lua, using the test case file + This file is part of Yueliang. + + Copyright (c) 2006 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * the test cases are in the test_lua directory (test_parser-5.0.lua) +----------------------------------------------------------------------]] + +-- * true if you want an output of all failure cases in native Lua, +-- for checking whether test cases fail where you intend them to +local DEBUG_FAILS = false + +------------------------------------------------------------------------ +-- test the whole kaboodle +------------------------------------------------------------------------ + +require("../lzio") +require("../llex") +require("../lopcodes") +require("../ldump") +require("../lcode") +require("../lparser") + +function lua_assert(test) + if not test then error("assertion failed!") end +end + +luaX:init() + +------------------------------------------------------------------------ +-- load test cases +------------------------------------------------------------------------ + +require("../../test_lua/test_parser-5.0") + +local test, expect, heading = {}, {}, {} +local total, total_pass, total_fail = 0, 0, 0 + +for ln in string.gfind(tests_source, "([^\n]*)\n") do + if string.find(ln, "^%s*%-%-") then + -- comment, ignore + else + local m, _, head = string.find(ln, "^%s*(TESTS:%s*.*)$") + if m then + heading[total + 1] = head -- informational heading + else + total = total + 1 + local n, _, flag = string.find(ln, "%s*%-%-%s*FAIL%s*$") + if n then -- FAIL test case + ln = string.sub(ln, 1, n - 1) -- remove comment + expect[total] = "FAIL" + total_fail = total_fail + 1 + else -- PASS test case + expect[total] = "PASS" + total_pass = total_pass + 1 + end--n + test[total] = ln + end--m + end--ln +end--for + +print("Tests loaded: "..total.." (total), " + ..total_pass.." (passes), " + ..total_fail.." (fails)") + +------------------------------------------------------------------------ +-- verify test cases using native Lua +------------------------------------------------------------------------ + +local last_head = "TESTS: no heading yet" +for i = 1, total do + local test_case, expected, head = test[i], expect[i], heading[i] + -- show progress + if head then + last_head = head + if DEBUG_FAILS then print("\n"..head.."\n") end + end + ------------------------------------------------------------------ + -- perform test + local f, err = loadstring(test_case) + -- look at outcome + ------------------------------------------------------------------ + if f then-- actual PASS + if expected == "FAIL" then + print("\nVerified as PASS but expected to FAIL".. + "\n-------------------------------------") + print("Lastest heading: "..last_head) + print("TEST: "..test_case) + os.exit() + end + ------------------------------------------------------------------ + else-- actual FAIL + if expected == "PASS" then + print("\nVerified as FAIL but expected to PASS".. + "\n-------------------------------------") + print("Lastest heading: "..last_head) + print("TEST: "..test_case) + print("ERROR: "..err) + os.exit() + end + if DEBUG_FAILS then + print("TEST: "..test_case) + print("ERROR: "..err.."\n") + end + ------------------------------------------------------------------ + end--f +end--for + +print("Test cases verified using native Lua, no anomalies.") + +------------------------------------------------------------------------ +-- dump binary chunks to a file if something goes wrong +------------------------------------------------------------------------ +local function Dump(data, filename) + h = io.open(filename, "wb") + if not h then error("failed to open "..filename.." for writing") end + h:write(data) + h:close() +end + +------------------------------------------------------------------------ +-- test using Yueliang front end +------------------------------------------------------------------------ + +local last_head = "TESTS: no heading yet" +for i = 1, total do + local test_case, expected, head = test[i], expect[i], heading[i] + -- show progress + if head then last_head = head end + ------------------------------------------------------------------ + -- perform test + local LuaState = {} + local zio = luaZ:init(luaZ:make_getS(test_case), nil, "test") + local status, func = pcall(luaY.parser, luaY, LuaState, zio, nil) + -- look at outcome + ------------------------------------------------------------------ + if status then-- actual PASS + if expected == "PASS" then + -- actual PASS and expected PASS, so check binary chunks + local writer, buff = luaU:make_setS() + luaU:dump(LuaState, func, writer, buff) + local bc1 = buff.data -- Yueliang's output + local f = loadstring(test_case, "test") + local bc2 = string.dump(f) -- Lua's output + local die + -- compare outputs + if string.len(bc1) ~= string.len(bc2) then + Dump(bc1, "bc1.out") + Dump(bc2, "bc2.out") + die = "binary chunk sizes different" + elseif bc1 ~= bc2 then + Dump(bc1, "bc1.out") + Dump(bc2, "bc2.out") + die = "binary chunks different" + else + -- everything checks out! + end + if die then + print("\nTested PASS and expected to PASS, but chunks different".. + "\n------------------------------------------------------") + print("Reason: "..die) + print("Lastest heading: "..last_head) + print("TEST: "..test_case) + os.exit() + end + else-- expected FAIL + print("\nTested as PASS but expected to FAIL".. + "\n-----------------------------------") + print("Lastest heading: "..last_head) + print("TEST: "..test_case) + os.exit() + end + ------------------------------------------------------------------ + else-- actual FAIL + if expected == "PASS" then + print("\nTested as FAIL but expected to PASS".. + "\n-----------------------------------") + print("Lastest heading: "..last_head) + print("TEST: "..test_case) + print("ERROR: "..err) + os.exit() + end + ------------------------------------------------------------------ + end--status + io.stdout:write("\rTesting ["..i.."]...") +end--for +print(" done.") + +print("Test cases run on Yueliang, no anomalies.") + +-- end diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lzio.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lzio.lua new file mode 100644 index 0000000..cfd3f4b --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_lzio.lua @@ -0,0 +1,55 @@ +--[[-------------------------------------------------------------------- + + test_lzio.lua + Test for lzio.lua + This file is part of Yueliang. + + Copyright (c) 2005 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +-- manual test for lzio.lua lua-style chunk reader + +require("../lzio") + +local z +function dump(z) + while true do + local c = luaZ:zgetc(z) + io.stdout:write("("..c..")") + if c == "EOZ" then break end + end + io.stdout:write("\n") +end + +-- luaZ:make_getS or luaZ:make_getF creates a chunk reader +-- luaZ:init makes a zio stream + +-- [[ +z = luaZ:init(luaZ:make_getS("hello, world!"), nil, "=string") +dump(z) +z = luaZ:init(luaZ:make_getS(", world!"), "hello", "=string") +dump(z) +z = luaZ:init(luaZ:make_getS("line1\nline2\n"), "", "=string") +dump(z) +z = luaZ:init(luaZ:make_getF("test_lzio.lua"), nil, "=string") +dump(z) +--]] + +-- test read beyond end of file +-- bug reported by Adam429 +--[[ +z = luaZ:init(luaZ:make_getF("test_lzio.lua"), nil, "=string") +while true do + local c = luaZ:zgetc(z) + io.stdout:write("("..c..")") + if c == "EOZ" then break end +end +print(luaZ:zgetc(z)) +print(luaZ:zgetc(z)) +io.stdout:write("\n") +--]] diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_number.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_number.lua new file mode 100644 index 0000000..eeabecb --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/test/test_number.lua @@ -0,0 +1,174 @@ +--[[-------------------------------------------------------------------- + + test_number.lua + Test for Lua-based number conversion functions in ldump.lua + This file is part of Yueliang. + + Copyright (c) 2005-2006 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * luaU:from_int(value) does not have overflow checks, but this +-- can presumably be put in for debugging purposes. +-- * TODO: double conversion does not support denormals or NaNs +-- * apparently 0/0 == 0/0 is false (Lua 5.0.2 on Win32/Mingw), so +-- can't use to check for NaNs +----------------------------------------------------------------------]] + +require("../ldump") + +------------------------------------------------------------------------ +-- convert hex string representation to a byte string +-- * must have an even number of hex digits +------------------------------------------------------------------------ +local function from_hexstring(s) + local bs = "" + for i = 1, string.len(s), 2 do + local asc = tonumber(string.sub(s, i, i + 1), 16) + bs = bs..string.char(asc) + end + return bs +end + +------------------------------------------------------------------------ +-- convert a byte string to a hex string representation +-- * big-endian, easier to grok +------------------------------------------------------------------------ +local function to_hexstring(s) + local hs = "" + for i = string.len(s), 1, -1 do + local c = string.byte(string.sub(s, i, i)) + hs = hs..string.format("%02X", c) + end + return hs +end + +------------------------------------------------------------------------ +-- tests for 32-bit signed/unsigned integer +------------------------------------------------------------------------ +local function test_int(value, expected) + local actual = to_hexstring(luaU:from_int(value)) + if not expected or expected == "" then + print(value..": "..actual) + elseif actual ~= expected then + print(value..": FAILED!\n".. + "Converted: "..actual.."\n".. + "Expected: "..expected) + return true + end + return false +end + +local table_int = { + ["0"] = "00000000", + ["1"] = "00000001", + ["256"] = "00000100", + ["-256"] = "FFFFFF00", + ["-1"] = "FFFFFFFF", + ["2147483647"] = "7FFFFFFF", -- LONG_MAX + ["-2147483648"] = "80000000", -- LONG_MIN + ["4294967295"] = "FFFFFFFF", -- ULONG_MAX + --[""] = "", +} + +local success = true +print("Testing luaU:from_int():") +for i, v in pairs(table_int) do + local test_value = tonumber(i) + local expected = v + if test_int(test_value, expected) then + success = false + end +end +if success then + print("All test numbers passed okay.\n") +else + print("There were one or more failures.\n") +end + +------------------------------------------------------------------------ +-- tests for IEEE 754 64-bit double +------------------------------------------------------------------------ + +local function test_double(value, expected) + local actual = to_hexstring(luaU:from_double(value)) + if not expected or expected == "" then + print(value..": "..actual) + elseif actual ~= expected then + print(value..": FAILED!\n".. + "Converted: "..actual.."\n".. + "Expected: "..expected) + return true + end + return false +end + +-- special values, see testing loop for actual lookup +Infinity = 1/0 +Infinity_neg = -1/0 + +-- can't seem to do a comparison test with NaN, so leave them +-- (need to check the IEEE standard on this...) +NaN = 0/0 +NaN_neg = -0/0 +--["NaN"] = "", -- 7FF8000000000000 (djgpp) +--["NaN_neg"] = "", -- FFF8000000000000 (djgpp) + +local table_double = { + -- 0 for exponent, 0 for mantissa + ["0"] = "0000000000000000", + -- 3FF is bias of 1023, so (-1)^0 * (1+0) * 2^0 + ["1"] = "3FF0000000000000", + -- BFF has sign bit on, so (-1)^1 * (1+0) * 2^0 + ["-1"] = "BFF0000000000000", + -- 3FC is bias of 1020, so (-1)^0 * (1+0) * 2^-3 + ["0.125"] = "3FC0000000000000", + ["0.250"] = "3FD0000000000000", + ["0.500"] = "3FE0000000000000", + -- 40F is bias of 1039, so (-1)^0 * (1+0) * 2^16 + ["65536"] = "40F0000000000000", + -- 7FF is bias of 2047, 0 for mantissa + ["Infinity"] = "7FF0000000000000", + -- FFF has sign bit on, 0 for mantissa + ["Infinity_neg"] = "FFF0000000000000", + -- DBL_MIN, exponent=001 ( 1), mantissa=0000000000000 + ["2.2250738585072014e-308"] = "0010000000000000", + -- DBL_MAX, exponent=7FE (2046), mantissa=FFFFFFFFFFFFF + ["1.7976931348623157e+308"] = "7FEFFFFFFFFFFFFF", +--[[ + -- * the following is for float numbers only * + -- FLT_MIN, exponent=01 ( 1), mantissa=000000 + -- altervative value for FLT_MIN: 1.17549435e-38F + ["1.1754943508222875081e-38"] = "00800000", + -- FLT_MAX, exponent=FE (254), mantissa=7FFFFF + -- altervative value for FLT_MAX: 3.402823466e+38F + ["3.4028234663852885982e+38"] = "7F7FFFFF", +--]] + --[""] = "", +} + +local success = true +print("Testing luaU:from_double():") +for i, v in pairs(table_double) do + local test_value + if not string.find(i, "%d") then + test_value = _G[i] + else + test_value = tonumber(i) + end + local expected = v + if test_double(test_value, expected) then + success = false + end +end +if success then + print("All test numbers passed okay.\n") +else + print("There were one or more failures.\n") +end diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/call_graph.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/call_graph.lua new file mode 100644 index 0000000..5c60e17 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/call_graph.lua @@ -0,0 +1,254 @@ +--[[-------------------------------------------------------------------- + + call_graph.lua + Call graph generator. + This file is part of Yueliang. + + Copyright (c) 2005-2006 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * the call tracer wraps function calls in tables to do its work +-- * not very elegant as the namespace of the table/module is affected +-- * tracing using the debugger is probably much more powerful... +-- * use of braces {} allows editors to match braces in the output +-- and do folding, if such facilities are available; for example, the +-- output looks better if Lua syntax highlighting is used on SciTE +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- options +------------------------------------------------------------------------ + +local SHOW_EXPDESC = true -- show expdesc struct data + +------------------------------------------------------------------------ +-- load and initialize modules +------------------------------------------------------------------------ +require("../lzio.lua") +require("../llex.lua") +require("../lopcodes.lua") +require("../ldump.lua") +require("../lcode.lua") +require("../lparser.lua") + +function lua_assert(test) + if not test then error("assertion failed!") end +end +luaX:init() +local LuaState = {} + +------------------------------------------------------------------------ +-- call graph generator +-- * (1) logging functions, (2) the wrapper initializer itself +------------------------------------------------------------------------ + +llog = {} + +------------------------------------------------------------------------ +-- initialize log file; the usual mode is append; can use stdout/stderr +------------------------------------------------------------------------ +function llog:init(filename) + if filename == "stdout" then self.h = io.stdout + elseif filename == "stderr" then self.h = io.stderr + else + self.h = io.open(filename, "ab") + if not self.h then + error("can't open log file "..filename.."for writing") + end + end + self.h:write("\n-- start of log --\n\n") +end + +------------------------------------------------------------------------ +-- cleanly closes log file +------------------------------------------------------------------------ +function llog:exit() + self.h:write("\n-- end of log --\n\n") + if self.h ~= io.stdout and self.h ~= io.stderr then + self.h:close() + end +end + +------------------------------------------------------------------------ +-- logs a message at a particular call depth +------------------------------------------------------------------------ +function llog:msg(msg, level) + if level then msg = string.rep(" ", level)..msg end + self.h:write(msg) + self.h:flush() +end + +------------------------------------------------------------------------ +-- set up wrapper functions to do tracing on a per-module basis +------------------------------------------------------------------------ +function llog:calltrace(parms) + ------------------------------------------------------------------ + -- process parameters + ------------------------------------------------------------------ + local module = parms.module + local modulename = parms.modulename + if type(module) ~= "table" then + error("module table parameter required") + elseif not modulename then + error("module name parameter required") + end + ------------------------------------------------------------------ + -- use either allow or deny list + ------------------------------------------------------------------ + local allow = parms.allow or {} + local deny = parms.deny or {} + if table.getn(allow) > 0 and table.getn(deny) > 0 then + error("can't apply both allow and deny lists at the same time") + end + ------------------------------------------------------------------ + -- select functions to wrap + ------------------------------------------------------------------ + local flist = {} + for i, f in pairs(module) do + local wrapthis + if table.getn(allow) > 0 then -- allow some only + wrapthis = false + for j, v in ipairs(allow) do + if i == v then wrapthis = true; break end + end + elseif table.getn(deny) > 0 then -- deny some only + wrapthis = true + for j, v in ipairs(deny) do + if i == v then wrapthis = false; break end + end + else -- default include + wrapthis = true + end + if wrapthis then flist[i] = f end + end + ------------------------------------------------------------------ + -- wrapped function(s) in a module for tracing + ------------------------------------------------------------------ + llog.level = 0 -- nesting level + for i, f in pairs(flist) do + local ModuleName = modulename..":" + local OldName, OldFunc = i, f + if type(OldFunc) == "function" then + local NewName = "__"..OldName + while module[NewName] ~= nil do -- avoid collisions + NewName = "_"..NewName + end + module[NewName] = OldFunc + module[OldName] = + ---------------------------------------------------------- + -- wrapper function for a module's function + -- old function XYZ is renamed __XYZ + ---------------------------------------------------------- + function(self, ...) + local parms = " (" + local exps = {} + -- look for expdesc structs, identify FuncState structs too + local function checkexpdesc(v) + local typ = type(v) + if typ == "table" then + if v.code then return "func" + elseif v.L then return "ls" + elseif v.seminfo then return "token" + elseif v.k then + table.insert(exps, v) + return "exp"..table.getn(exps) + end + end + return typ + end + -- format parameters for printing + for i,v in ipairs(arg) do + if type(v) == "number" then parms = parms..v.."," + elseif type(v) == "string" then parms = parms.."'"..v.."'," + elseif type(v) == "boolean" then parms = parms..tostring(v).."," + elseif SHOW_EXPDESC then parms = parms..checkexpdesc(v).."," + else parms = parms..type(v).."," + end + end + if table.getn(arg) > 0 then -- chop last comma + parms = string.sub(parms, 1, -2) + end + -- up level + llog:msg(ModuleName..OldName..parms..") {\n", llog.level) + llog.level = llog.level + 1 + -- display contents of expdesc + if SHOW_EXPDESC and table.getn(exps) > 0 then + for i,v in ipairs(exps) do + parms = "k:'"..v.k.."'," + if v.info then parms = parms.."info:"..v.info.."," end + if v.aux then parms = parms.."aux:"..v.aux.."," end + if v.t then parms = parms.."t:"..v.t.."," end + if v.f then parms = parms.."f:"..v.f.."," end + parms = string.sub(parms, 1, -2) + llog:msg("exp"..i.."("..parms..")\n", llog.level) + end + end + -- original function called here... + local retval = {self[NewName](self, unpack(arg))} + -- format return values + local rets = " = " + for i,v in ipairs(retval) do + if type(v) == "number" then rets = rets..v.."," + elseif type(v) == "string" then rets = rets.."'"..v.."'," + elseif type(v) == "boolean" then rets = rets..tostring(v).."," + else rets = rets..type(v).."," + end + end + if table.getn(retval) > 0 then -- chop last comma + rets = string.sub(rets, 1, -2) + else + rets = "" + end + -- down level + llog.level = llog.level - 1 + llog:msg("} "..ModuleName..OldName..rets.."\n", llog.level) + return unpack(retval) + end--function + ---------------------------------------------------------- + --print("patched "..OldName) + end--if + end--for +end + +------------------------------------------------------------------------ +-- testing here +-- * allow/deny works a bit like a somewhat similar Apache syntax +-- * e.g. to show only function 'lex' and 'save' -> allow={"lex","save",} +-- to not show function 'save_and_next' -> deny={"save_and_next",} +-- * you can't do both allow and deny at the same time +------------------------------------------------------------------------ + +-- select the file or stream to output to +--llog:init("calls.log") +llog:init("stdout") + +-- select modules to trace +llog:calltrace{module=luaX, modulename="luaX", allow={"lex"} } + -- here we trace only the main lex() function, to avoid showing + -- too many lexer calls; we want to focus on luaY and luaK +llog:calltrace{module=luaY, modulename="luaY", deny={"growvector"} } + -- growvector() is just a limit checker in Yueliang, so drop it + -- to simplify the output log +llog:calltrace{module=luaK, modulename="luaK"} +--llog:calltrace{module=luaU, modulename="luaU"} + +-- select input stream +local zio = luaZ:init(luaZ:make_getS("local a = 1"), nil, "=string") +--local zio = luaZ:init(luaZ:make_getF("sample.lua"), nil, "@sample.lua") + +-- compile the source +local Func = luaY:parser(LuaState, zio, nil) + +-- write binary chunk +local Writer, Buff = luaU:make_setF("call_graph.out") +luaU:dump(LuaState, Func, Writer, Buff) + +llog:exit() +--end diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/calls.log b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/calls.log new file mode 100644 index 0000000..c163f6c --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/calls.log @@ -0,0 +1,152 @@ + +-- start of log -- + +luaY:parser (table,table) { + luaY:open_func (table,table) { + luaY:newproto (table) { + } luaY:newproto = table + } luaY:open_func + luaY:next (table) { + luaX:lex (table,table) { + } luaX:lex = 'TK_LOCAL' + } luaY:next + luaY:chunk (table) { + luaY:enterlevel (table) { + } luaY:enterlevel + luaY:block_follow ('TK_LOCAL') { + } luaY:block_follow = false + luaY:statement (table) { + luaY:next (table) { + luaX:lex (table,table) { + } luaX:lex = 'TK_NAME' + } luaY:next + luaY:testnext (table,'TK_FUNCTION') { + } luaY:testnext = false + luaY:localstat (table) { + luaY:str_checkname (table) { + luaY:check_condition (table,true,' expected') { + } luaY:check_condition + luaY:next (table) { + luaX:lex (table,table) { + } luaX:lex = '=' + } luaY:next + } luaY:str_checkname = 'a' + luaY:new_localvar (table,'a',0) { + luaY:registerlocalvar (table,'a') { + luaY:growvector (table,table,0,0) { + } luaY:growvector + } luaY:registerlocalvar = 0 + } luaY:new_localvar + luaY:testnext (table,',') { + } luaY:testnext = false + luaY:testnext (table,'=') { + luaY:next (table) { + luaX:lex (table,table) { + } luaX:lex = 'TK_NUMBER' + } luaY:next + } luaY:testnext = true + luaY:explist1 (table,table) { + luaY:expr (table,table) { + luaY:subexpr (table,table,-1) { + luaY:enterlevel (table) { + } luaY:enterlevel + luaY:getunopr ('TK_NUMBER') { + } luaY:getunopr = 'OPR_NOUNOPR' + luaY:simpleexp (table,table) { + luaK:numberK (table,1) { + luaK:setnvalue (table,1) { + } luaK:setnvalue + luaK:addk (table,table,table) { + luaK:ttisnumber ) { + } luaK:ttisnumber = false + luaY:growvector (table,table,0,0) { + } luaY:growvector + luaK:setnvalue (table,0) { + } luaK:setnvalue + } luaK:addk = 0 + } luaK:numberK = 0 + luaY:init_exp (table,'VK',0) { + } luaY:init_exp + luaY:next (table) { + luaX:lex (table,table) { + } luaX:lex = 'TK_EOS' + } luaY:next + } luaY:simpleexp + luaY:getbinopr ('TK_EOS') { + } luaY:getbinopr = 'OPR_NOBINOPR' + luaY:leavelevel (table) { + } luaY:leavelevel + } luaY:subexpr = 'OPR_NOBINOPR' + } luaY:expr + luaY:testnext (table,',') { + } luaY:testnext = false + } luaY:explist1 = 1 + luaY:adjust_assign (table,1,1,table) { + luaK:exp2nextreg (table,table) { + luaK:dischargevars (table,table) { + } luaK:dischargevars + luaK:freeexp (table,table) { + } luaK:freeexp + luaK:reserveregs (table,1) { + luaK:checkstack (table,1) { + } luaK:checkstack + } luaK:reserveregs + luaK:exp2reg (table,table,0) { + luaK:discharge2reg (table,table,0) { + luaK:dischargevars (table,table) { + } luaK:dischargevars + luaK:codeABx (table,'OP_LOADK',0,0) { + luaK:code (table,table,1) { + luaK:dischargejpc (table) { + luaK:patchlistaux (table,-1,0,255,0,255,0) { + } luaK:patchlistaux + } luaK:dischargejpc + luaY:growvector (table,table,0,0) { + } luaY:growvector + luaY:growvector (table,table,0,0) { + } luaY:growvector + } luaK:code = 0 + } luaK:codeABx = 0 + } luaK:discharge2reg + luaK:hasjumps (table) { + } luaK:hasjumps = false + } luaK:exp2reg + } luaK:exp2nextreg + } luaY:adjust_assign + luaY:adjustlocalvars (table,1) { + luaY:getlocvar (table,0) { + } luaY:getlocvar = table + } luaY:adjustlocalvars + } luaY:localstat + } luaY:statement = false + luaY:testnext (table,';') { + } luaY:testnext = false + luaY:block_follow ('TK_EOS') { + } luaY:block_follow = true + luaY:leavelevel (table) { + } luaY:leavelevel + } luaY:chunk + luaY:check_condition (table,true,' expected') { + } luaY:check_condition + luaY:close_func (table) { + luaY:removevars (table,0) { + luaY:getlocvar (table,0) { + } luaY:getlocvar = table + } luaY:removevars + luaK:codeABC (table,'OP_RETURN',0,1,0) { + luaK:code (table,table,1) { + luaK:dischargejpc (table) { + luaK:patchlistaux (table,-1,1,255,1,255,1) { + } luaK:patchlistaux + } luaK:dischargejpc + luaY:growvector (table,table,1,0) { + } luaY:growvector + luaY:growvector (table,table,1,0) { + } luaY:growvector + } luaK:code = 1 + } luaK:codeABC = 1 + } luaY:close_func +} luaY:parser = table + +-- end of log -- + diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/sample_expr.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/sample_expr.lua new file mode 100644 index 0000000..519cd4c --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/sample_expr.lua @@ -0,0 +1,195 @@ +--[[-------------------------------------------------------------------- + + sample_expr.lua + Stand-alone expression parsing demonstrator. + This file is part of Yueliang. + + Copyright (c) 2005 Kein-Hong Man + The COPYRIGHT file describes the conditions + under which this software may be distributed. + + See the ChangeLog for more information. + +----------------------------------------------------------------------]] + +--[[-------------------------------------------------------------------- +-- Notes: +-- * this is an interactive demonstrator for implementing expression +-- parsing in ChunkBake, a Lua assembler +-- * evaluation is immediate, and a result is immediately generated +----------------------------------------------------------------------]] + +require("../lzio.lua") +require("../llex.lua") +luaX:init() + +------------------------------------------------------------------------ +-- expression parser +------------------------------------------------------------------------ + +expr = {} + +expr.unop = { + ["TK_NOT"] = true, + ["-"] = true, +} +expr.binop = { + ["^"] = 10, + ["*"] = 7, + ["/"] = 7, + ["+"] = 6, + ["-"] = 6, + ["TK_CONCAT"] = 5, + ["TK_NE"] = 3, + ["TK_EQ"] = 3, + ["<"] = 3, + ["TK_LE"] = 3, + [">"] = 3, + ["TK_GE"] = 3, + ["TK_AND"] = 2, + ["TK_OR"] = 1, +} +expr.binop_r = { + ["^"] = 9, + ["*"] = 7, + ["/"] = 7, + ["+"] = 6, + ["-"] = 6, + ["TK_CONCAT"] = 4, + ["TK_NE"] = 3, + ["TK_EQ"] = 3, + ["<"] = 3, + ["TK_LE"] = 3, + [">"] = 3, + ["TK_GE"] = 3, + ["TK_AND"] = 2, + ["TK_OR"] = 1, +} + +function expr:parse(str) + self.LS = {} + self.L = {} + self.z = luaZ:init(luaZ:make_getS(str), nil, "=string") + luaX:setinput(self.L, self.LS, self.z, self.z.name) + self:token() + local v = self:expr() + if self.tok ~= "TK_EOS" then + io.stderr:write("parse error: some tokens unparsed\n") + end + return v +end + +function expr:token() + self.tok = luaX:lex(self.LS, self.LS.t) + self.seminfo = self.LS.t.seminfo + return self.tok +end + +function expr:simpleexpr() + local tok = self.tok + if tok == "TK_NIL" then + self:token() + return nil + elseif tok == "TK_TRUE" then + self:token() + return true + elseif tok == "TK_FALSE" then + self:token() + return false + elseif tok == "TK_NUMBER" or tok == "TK_STRING" then + self:token() + return self.seminfo + elseif tok == "(" then + self:token() + local v = self:expr() + if self.tok ~= ")" then + io.stderr:write("parse error: expecting ')' to delimit\n") + else + self:token() + return v + end + end + self:token() + io.stderr:write("parse error: "..tok.." encountered, substituting nil\n") + return nil +end + +function expr:subexpr(prev_op) + local v, op + if self.unop[self.tok] then + op = self.tok + self:token() + v = self:subexpr(8) + if op == "TK_NOT" then + v = not v + else-- op == "-" then + v = -v + end + else + v = self:simpleexpr() + end + op = self.tok + if self.binop[op] then + while self.binop[op] and self.binop[op] > prev_op do + self:token() + local v2, next_op = self:subexpr(self.binop_r[op]) + if op == "^" then + v = v ^ v2 + elseif op == "*" then + v = v * v2 + elseif op == "/" then + v = v / v2 + elseif op == "+" then + v = v + v2 + elseif op == "-" then + v = v - v2 + elseif op == "TK_CONCAT" then + v = v .. v2 + elseif op == "TK_NE" then + v = v ~= v2 + elseif op == "TK_EQ" then + v = v == v2 + elseif op == "<" then + v = v < v2 + elseif op == "TK_LE" then + v = v <= v2 + elseif op == ">" then + v = v > v2 + elseif op == "TK_GE" then + v = v >= v2 + elseif op == "TK_AND" then + v = v and v2 + else-- op == "TK_OR" then + v = v or v2 + end + op = next_op + end + end + return v, op +end + +function expr:expr() + return self:subexpr(-1) +end + +------------------------------------------------------------------------ +-- interactive test code +------------------------------------------------------------------------ + +io.stdout:write([[ +Lua-style expression parsing demonstrator. +Type 'exit' or 'quit' at the prompt to terminate session. +]]) +local done = false +while not done do + io.stdout:write(":>") + io.stdout:flush() + local l = io.stdin:read("*l") + if l == nil or (l == "exit" or l == "quit" and not prevline) then + done = true + else + local v = tostring(expr:parse(l)) + io.stdout:write(v, "\n") + end +end--while +--end -- cgit v1.1