├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── benchmarks ├── ack.lua ├── binary-trees.lua ├── fannkuch-redux.lua ├── fasta.lua ├── fixpoint-fact.lua ├── heapsort.lua ├── k-nucleotide.lua ├── mandel.lua ├── n-body.lua ├── plot.gpi ├── qt.lua ├── queen.lua ├── regex-dna.lua ├── scimark.lua ├── sieve.lua └── spectral-norm.lua ├── doc ├── contents.html ├── index.css ├── logo.gif ├── lua.1 ├── lua.css ├── luac.1 ├── manual.css ├── manual.html ├── osi-certified-72x60.png └── readme.html ├── fltests ├── binop.lua ├── forloop.lua └── moveload.lua ├── luatests ├── all.lua ├── api.lua ├── attrib.lua ├── big.lua ├── bitwise.lua ├── calls.lua ├── closure.lua ├── code.lua ├── constructs.lua ├── coroutine.lua ├── db.lua ├── errors.lua ├── events.lua ├── files.lua ├── gc.lua ├── goto.lua ├── libs │ ├── lib1.c │ ├── lib11.c │ ├── lib2.c │ ├── lib21.c │ └── makefile ├── literals.lua ├── locals.lua ├── ltests │ ├── ltests.c │ └── ltests.h ├── main.lua ├── math.lua ├── nextvar.lua ├── pm.lua ├── sort.lua ├── strings.lua ├── tpack.lua ├── utf8.lua ├── vararg.lua └── verybig.lua ├── runbenchmarks.lua ├── runtests.sh ├── src ├── Makefile ├── containers.h ├── fl_asm.h ├── fl_asm_llvm.c ├── fl_containers.h ├── fl_defs.c ├── fl_defs.h ├── fl_instr.c ├── fl_instr.h ├── fl_ir.c ├── fl_ir.h ├── fl_jitc.c ├── fl_jitc.h ├── fl_lib.c ├── fl_logger.c ├── fl_logger.h ├── fl_rec.c ├── fl_rec.h ├── fl_trace.c ├── fl_trace.h ├── fl_vm.c ├── fl_vm.h ├── lapi.c ├── lapi.h ├── lauxlib.c ├── lauxlib.h ├── lbaselib.c ├── lbitlib.c ├── lcode.c ├── lcode.h ├── lcorolib.c ├── lctype.c ├── lctype.h ├── ldblib.c ├── ldebug.c ├── ldebug.h ├── ldo.c ├── ldo.h ├── ldump.c ├── lfunc.c ├── lfunc.h ├── lgc.c ├── lgc.h ├── linit.c ├── liolib.c ├── llex.c ├── llex.h ├── llimits.h ├── lmathlib.c ├── lmem.c ├── lmem.h ├── loadlib.c ├── lobject.c ├── lobject.h ├── lopcodes.c ├── lopcodes.h ├── loslib.c ├── lparser.c ├── lparser.h ├── lprefix.h ├── lstate.c ├── lstate.h ├── lstring.c ├── lstring.h ├── lstrlib.c ├── ltable.c ├── ltable.h ├── ltablib.c ├── ltm.c ├── ltm.h ├── lua.c ├── lua.h ├── lua.hpp ├── luac.c ├── luaconf.h ├── lualib.h ├── lundump.c ├── lundump.h ├── lutf8lib.c ├── lvm.c ├── lvm.h ├── lzio.c └── lzio.h └── test.lua /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | 4 | # Dependencies 5 | *.d 6 | 7 | # Libraries 8 | *.a 9 | 10 | # Executables 11 | src/lua 12 | src/luac 13 | 14 | # benchmark outputs 15 | benchmark_out* 16 | 17 | # Vim temporaries 18 | *.swp 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Gabriel de Quadros Ligneul 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for installing Lua 2 | # See doc/readme.html for installation and customization instructions. 3 | 4 | # == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= 5 | 6 | # Your platform. See PLATS for possible values. 7 | PLAT= none 8 | 9 | # Where to install. The installation starts in the src and doc directories, 10 | # so take care if INSTALL_TOP is not an absolute path. See the local target. 11 | # You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with 12 | # LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h. 13 | INSTALL_TOP= /usr/local 14 | INSTALL_BIN= $(INSTALL_TOP)/bin 15 | INSTALL_INC= $(INSTALL_TOP)/include 16 | INSTALL_LIB= $(INSTALL_TOP)/lib 17 | INSTALL_MAN= $(INSTALL_TOP)/man/man1 18 | INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V 19 | INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V 20 | 21 | # How to install. If your install program does not support "-p", then 22 | # you may have to run ranlib on the installed liblua.a. 23 | INSTALL= install -p 24 | INSTALL_EXEC= $(INSTALL) -m 0755 25 | INSTALL_DATA= $(INSTALL) -m 0644 26 | # 27 | # If you don't have "install" you can use "cp" instead. 28 | # INSTALL= cp -p 29 | # INSTALL_EXEC= $(INSTALL) 30 | # INSTALL_DATA= $(INSTALL) 31 | 32 | # Other utilities. 33 | MKDIR= mkdir -p 34 | RM= rm -f 35 | 36 | # == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= 37 | 38 | # Convenience platforms targets. 39 | PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris 40 | 41 | # What to install. 42 | TO_BIN= lua luac 43 | TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp 44 | TO_LIB= liblua.a 45 | TO_MAN= lua.1 luac.1 46 | 47 | # Lua version and release. 48 | V= 5.3 49 | R= $V.3 50 | 51 | # Targets start here. 52 | all: $(PLAT) 53 | 54 | $(PLATS) clean: 55 | cd src && $(MAKE) $@ 56 | 57 | test: dummy 58 | src/lua -v 59 | 60 | install: dummy 61 | cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) 62 | cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) 63 | cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) 64 | cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) 65 | cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) 66 | 67 | uninstall: 68 | cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN) 69 | cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC) 70 | cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB) 71 | cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN) 72 | 73 | local: 74 | $(MAKE) install INSTALL_TOP=../install 75 | 76 | none: 77 | @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" 78 | @echo " $(PLATS)" 79 | @echo "See doc/readme.html for complete instructions." 80 | 81 | # make may get confused with test/ and install/ 82 | dummy: 83 | 84 | # echo config parameters 85 | echo: 86 | @cd src && $(MAKE) -s echo 87 | @echo "PLAT= $(PLAT)" 88 | @echo "V= $V" 89 | @echo "R= $R" 90 | @echo "TO_BIN= $(TO_BIN)" 91 | @echo "TO_INC= $(TO_INC)" 92 | @echo "TO_LIB= $(TO_LIB)" 93 | @echo "TO_MAN= $(TO_MAN)" 94 | @echo "INSTALL_TOP= $(INSTALL_TOP)" 95 | @echo "INSTALL_BIN= $(INSTALL_BIN)" 96 | @echo "INSTALL_INC= $(INSTALL_INC)" 97 | @echo "INSTALL_LIB= $(INSTALL_LIB)" 98 | @echo "INSTALL_MAN= $(INSTALL_MAN)" 99 | @echo "INSTALL_LMOD= $(INSTALL_LMOD)" 100 | @echo "INSTALL_CMOD= $(INSTALL_CMOD)" 101 | @echo "INSTALL_EXEC= $(INSTALL_EXEC)" 102 | @echo "INSTALL_DATA= $(INSTALL_DATA)" 103 | 104 | # echo pkg-config data 105 | pc: 106 | @echo "version=$R" 107 | @echo "prefix=$(INSTALL_TOP)" 108 | @echo "libdir=$(INSTALL_LIB)" 109 | @echo "includedir=$(INSTALL_INC)" 110 | 111 | # list targets that do not create files (but not all makes understand .PHONY) 112 | .PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho 113 | 114 | # (end of Makefile) 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FastLua 2 | 3 | ## Brief 4 | 5 | FastLua is an trace JIT compiler that works as an Lua (5.3) extension. 6 | There are only some minor modifications in the original interpreter. 7 | Currently, FastLua uses the LLVM toolchain to generate native code (there are plans to change the backend). 8 | 9 | For further information about Lua, see https://www.lua.org. 10 | 11 | **ATENTION: This is still on development state.** 12 | 13 | ## Requiriments 14 | 15 | LLVM (only tested with version 3.9) 16 | 17 | ## Compilation 18 | 19 | Run `make ` in project root folder. 20 | The build infrastructure is the same that Lua uses. 21 | 22 | ## Usage 23 | 24 | The usage should be equal to the standard Lua interpreter. 25 | The compilation is done automatically when a hotspot is detected. 26 | Since this is still a prototype, only few instructions will be compiled. 27 | If the compilation fails, FastLua will fallback to the original interpreter and everything should work just fine. 28 | 29 | ## Tests 30 | 31 | FastLua use Lua tests and a custom test suite. Use `runtests.sh` to run the tests. 32 | 33 | ## Benchmarks 34 | 35 | There is also a benchmark suite. Type `runbenchmarks.sh` to run it. 36 | -------------------------------------------------------------------------------- /benchmarks/ack.lua: -------------------------------------------------------------------------------- 1 | -- $Id: ackermann.lua,v 1.5 2000/12/09 20:07:43 doug Exp $ 2 | -- http://www.bagley.org/~doug/shootout/ 3 | 4 | local function Ack(M, N) 5 | if (M == 0) then 6 | return N + 1 7 | end 8 | if (N == 0) then 9 | return Ack(M - 1, 1) 10 | end 11 | return Ack(M - 1, Ack(M, (N - 1))) 12 | end 13 | 14 | N = tonumber((arg and arg[1])) or 3 15 | M = tonumber((arg and arg[2])) or 8 16 | print(string.format("Ack(%d, %d) = %d\n", N, M, Ack(N,M))) 17 | -------------------------------------------------------------------------------- /benchmarks/binary-trees.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://benchmarksgame.alioth.debian.org/ 3 | -- contributed by Mike Pall 4 | 5 | local function BottomUpTree(item, depth) 6 | if depth > 0 then 7 | local i = item + item 8 | depth = depth - 1 9 | local left, right = BottomUpTree(i-1, depth), BottomUpTree(i, depth) 10 | return { item, left, right } 11 | else 12 | return { item } 13 | end 14 | end 15 | 16 | local function ItemCheck(tree) 17 | if tree[2] then 18 | return tree[1] + ItemCheck(tree[2]) - ItemCheck(tree[3]) 19 | else 20 | return tree[1] 21 | end 22 | end 23 | 24 | local N = tonumber(arg and arg[1]) or 0 25 | local mindepth = 4 26 | local maxdepth = mindepth + 2 27 | if maxdepth < N then maxdepth = N end 28 | 29 | do 30 | local stretchdepth = maxdepth + 1 31 | local stretchtree = BottomUpTree(0, stretchdepth) 32 | io.write(string.format("stretch tree of depth %d\t check: %d\n", 33 | stretchdepth, ItemCheck(stretchtree))) 34 | end 35 | 36 | local longlivedtree = BottomUpTree(0, maxdepth) 37 | 38 | for depth=mindepth,maxdepth,2 do 39 | local iterations = 2 ^ (maxdepth - depth + mindepth) 40 | local check = 0 41 | for i=1,iterations do 42 | check = check + ItemCheck(BottomUpTree(1, depth)) + 43 | ItemCheck(BottomUpTree(-1, depth)) 44 | end 45 | io.write(string.format("%d\t trees of depth %d\t check: %d\n", 46 | iterations*2, depth, check)) 47 | end 48 | 49 | io.write(string.format("long lived tree of depth %d\t check: %d\n", 50 | maxdepth, ItemCheck(longlivedtree))) 51 | -------------------------------------------------------------------------------- /benchmarks/fannkuch-redux.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://benchmarksgame.alioth.debian.org/ 3 | -- contributed by Mike Pall 4 | 5 | local function fannkuch(n) 6 | local p, q, s, sign, maxflips, sum = {}, {}, {}, 1, 0, 0 7 | for i=1,n do p[i] = i; q[i] = i; s[i] = i end 8 | repeat 9 | -- Copy and flip. 10 | local q1 = p[1] -- Cache 1st element. 11 | if q1 ~= 1 then 12 | for i=2,n do q[i] = p[i] end -- Work on a copy. 13 | local flips = 1 14 | repeat 15 | local qq = q[q1] 16 | if qq == 1 then -- ... until 1st element is 1. 17 | sum = sum + sign*flips 18 | if flips > maxflips then maxflips = flips end -- New maximum? 19 | break 20 | end 21 | q[q1] = q1 22 | if q1 >= 4 then 23 | local i, j = 2, q1 - 1 24 | repeat q[i], q[j] = q[j], q[i]; i = i + 1; j = j - 1; until i >= j 25 | end 26 | q1 = qq; flips = flips + 1 27 | until false 28 | end 29 | -- Permute. 30 | if sign == 1 then 31 | p[2], p[1] = p[1], p[2]; sign = -1 -- Rotate 1<-2. 32 | else 33 | p[2], p[3] = p[3], p[2]; sign = 1 -- Rotate 1<-2 and 1<-2<-3. 34 | for i=3,n do 35 | local sx = s[i] 36 | if sx ~= 1 then s[i] = sx-1; break end 37 | if i == n then return sum, maxflips end -- Out of permutations. 38 | s[i] = i 39 | -- Rotate 1<-...<-i+1. 40 | local t = p[1]; for j=1,i do p[j] = p[j+1] end; p[i+1] = t 41 | end 42 | end 43 | until false 44 | end 45 | 46 | local n = tonumber(arg and arg[1]) or 7 47 | local sum, flips = fannkuch(n) 48 | io.write(sum, "\nPfannkuchen(", n, ") = ", flips, "\n") 49 | -------------------------------------------------------------------------------- /benchmarks/fasta.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://benchmarksgame.alioth.debian.org/ 3 | -- contributed by Mike Pall 4 | 5 | -- Compability with Lua 5.3 6 | if not loadstring then 7 | loadstring = load 8 | end 9 | if not unpack then 10 | unpack = table.unpack 11 | end 12 | 13 | local Last = 42 14 | local function random(max) 15 | local y = (Last * 3877 + 29573) % 139968 16 | Last = y 17 | return (max * y) / 139968 18 | end 19 | 20 | local function make_repeat_fasta(id, desc, s, n) 21 | local write, sub = io.write, string.sub 22 | write(">", id, " ", desc, "\n") 23 | local p, sn, s2 = 1, #s, s..s 24 | for i=60,n,60 do 25 | write(sub(s2, p, p + 59), "\n") 26 | p = p + 60; if p > sn then p = p - sn end 27 | end 28 | local tail = n % 60 29 | if tail > 0 then write(sub(s2, p, p + tail-1), "\n") end 30 | end 31 | 32 | local function make_random_fasta(id, desc, bs, n) 33 | io.write(">", id, " ", desc, "\n") 34 | loadstring([=[ 35 | local write, char, unpack, n, random = io.write, string.char, unpack, ... 36 | local buf, p = {}, 1 37 | for i=60,n,60 do 38 | for j=p,p+59 do ]=]..bs..[=[ end 39 | buf[p+60] = 10; p = p + 61 40 | if p >= 2048 then write(char(unpack(buf, 1, p-1))); p = 1 end 41 | end 42 | local tail = n % 60 43 | if tail > 0 then 44 | for j=p,p+tail-1 do ]=]..bs..[=[ end 45 | p = p + tail; buf[p] = 10; p = p + 1 46 | end 47 | write(char(unpack(buf, 1, p-1))) 48 | ]=], desc)(n, random) 49 | end 50 | 51 | local function bisect(c, p, lo, hi) 52 | local n = hi - lo 53 | if n == 0 then return "buf[j] = "..c[hi].."\n" end 54 | local mid = math.floor(n / 2) 55 | return "if r < "..p[lo+mid].." then\n"..bisect(c, p, lo, lo+mid).. 56 | "else\n"..bisect(c, p, lo+mid+1, hi).."end\n" 57 | end 58 | 59 | local function make_bisect(tab) 60 | local c, p, sum = {}, {}, 0 61 | for i,row in ipairs(tab) do 62 | c[i] = string.byte(row[1]) 63 | sum = sum + row[2] 64 | p[i] = sum 65 | end 66 | return "local r = random(1)\n"..bisect(c, p, 1, #tab) 67 | end 68 | 69 | local alu = 70 | "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG".. 71 | "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA".. 72 | "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT".. 73 | "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA".. 74 | "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG".. 75 | "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC".. 76 | "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA" 77 | 78 | local iub = make_bisect{ 79 | { "a", 0.27 }, 80 | { "c", 0.12 }, 81 | { "g", 0.12 }, 82 | { "t", 0.27 }, 83 | { "B", 0.02 }, 84 | { "D", 0.02 }, 85 | { "H", 0.02 }, 86 | { "K", 0.02 }, 87 | { "M", 0.02 }, 88 | { "N", 0.02 }, 89 | { "R", 0.02 }, 90 | { "S", 0.02 }, 91 | { "V", 0.02 }, 92 | { "W", 0.02 }, 93 | { "Y", 0.02 }, 94 | } 95 | 96 | local homosapiens = make_bisect{ 97 | { "a", 0.3029549426680 }, 98 | { "c", 0.1979883004921 }, 99 | { "g", 0.1975473066391 }, 100 | { "t", 0.3015094502008 }, 101 | } 102 | 103 | local N = tonumber(arg and arg[1]) or 1000 104 | make_repeat_fasta('ONE', 'Homo sapiens alu', alu, N*2) 105 | make_random_fasta('TWO', 'IUB ambiguity codes', iub, N*3) 106 | make_random_fasta('THREE', 'Homo sapiens frequency', homosapiens, N*5) 107 | -------------------------------------------------------------------------------- /benchmarks/fixpoint-fact.lua: -------------------------------------------------------------------------------- 1 | -- fixed-point operator 2 | local Z = function (le) 3 | local a = function (f) 4 | return le(function (x) return f(f)(x) end) 5 | end 6 | return a(a) 7 | end 8 | 9 | 10 | -- non-recursive factorial 11 | 12 | local F = function (f) 13 | return function (n) 14 | if n == 0 then return 1 15 | else return n*f(n-1) end 16 | end 17 | end 18 | 19 | local fat = Z(F) 20 | 21 | local s = 0 22 | for i = 1, arg[1] or 100 do s = s + fat(i) end 23 | print(s) 24 | 25 | -------------------------------------------------------------------------------- /benchmarks/heapsort.lua: -------------------------------------------------------------------------------- 1 | local random, floor = math.random, math.floor 2 | floor = math.ifloor or floor 3 | 4 | function heapsort(n, ra) 5 | local j, i, rra 6 | local l = floor(n/2) + 1 7 | -- local l = (n//2) + 1 8 | local ir = n; 9 | while 1 do 10 | if l > 1 then 11 | l = l - 1 12 | rra = ra[l] 13 | else 14 | rra = ra[ir] 15 | ra[ir] = ra[1] 16 | ir = ir - 1 17 | if (ir == 1) then 18 | ra[1] = rra 19 | return 20 | end 21 | end 22 | i = l 23 | j = l * 2 24 | while j <= ir do 25 | if (j < ir) and (ra[j] < ra[j+1]) then 26 | j = j + 1 27 | end 28 | if rra < ra[j] then 29 | ra[i] = ra[j] 30 | i = j 31 | j = j + i 32 | else 33 | j = ir + 1 34 | end 35 | end 36 | ra[i] = rra 37 | end 38 | end 39 | 40 | local Num = tonumber((arg and arg[1])) or 4 41 | for i=1,Num do 42 | local N = tonumber((arg and arg[2])) or 10000 43 | local a = {} 44 | for i=1,N do a[i] = random() end 45 | heapsort(N, a) 46 | for i=1,N-1 do assert(a[i] <= a[i+1]) end 47 | end 48 | 49 | -------------------------------------------------------------------------------- /benchmarks/k-nucleotide.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://benchmarksgame.alioth.debian.org/ 3 | -- contributed by Mike Pall 4 | 5 | local function kfrequency(seq, freq, k, frame) 6 | local sub = string.sub 7 | local k1 = k - 1 8 | for i=frame,string.len(seq)-k1,k do 9 | local c = sub(seq, i, i+k1) 10 | freq[c] = freq[c] + 1 11 | end 12 | end 13 | 14 | local function freqdefault() 15 | return 0 16 | end 17 | 18 | local function count(seq, frag) 19 | local k = string.len(frag) 20 | local freq = setmetatable({}, { __index = freqdefault }) 21 | for frame=1,k do kfrequency(seq, freq, k, frame) end 22 | io.write(freq[frag] or 0, "\t", frag, "\n") 23 | end 24 | 25 | local function frequency(seq, k) 26 | local freq = setmetatable({}, { __index = freqdefault }) 27 | for frame=1,k do kfrequency(seq, freq, k, frame) end 28 | local sfreq, sn = {}, 1 29 | for c,v in pairs(freq) do sfreq[sn] = c; sn = sn + 1 end 30 | table.sort(sfreq, function(a, b) 31 | local fa, fb = freq[a], freq[b] 32 | return fa == fb and a > b or fa > fb 33 | end) 34 | sum = string.len(seq)-k+1 35 | for _,c in ipairs(sfreq) do 36 | io.write(string.format("%s %0.3f\n", c, (freq[c]*100)/sum)) 37 | end 38 | io.write("\n") 39 | end 40 | 41 | local function readseq() 42 | local sub = string.sub 43 | for line in io.lines() do 44 | if sub(line, 1, 1) == ">" and sub(line, 2, 6) == "THREE" then break end 45 | end 46 | local lines, ln = {}, 0 47 | for line in io.lines() do 48 | local c = sub(line, 1, 1) 49 | if c == ">" then 50 | break 51 | elseif c ~= ";" then 52 | ln = ln + 1 53 | lines[ln] = line 54 | end 55 | end 56 | return string.upper(table.concat(lines, "", 1, ln)) 57 | end 58 | 59 | local seq = readseq() 60 | frequency(seq, 1) 61 | frequency(seq, 2) 62 | count(seq, "GGT") 63 | count(seq, "GGTA") 64 | count(seq, "GGTATT") 65 | count(seq, "GGTATTTTAATT") 66 | count(seq, "GGTATTTTAATTTATAGT") 67 | -------------------------------------------------------------------------------- /benchmarks/mandel.lua: -------------------------------------------------------------------------------- 1 | local Complex={type="package"} 2 | 3 | local function complex(x,y) 4 | return setmetatable({ re=x, im=y }, Complex.metatable) 5 | end 6 | 7 | function Complex.conj(x,y) 8 | return complex(x.re,-x.im) 9 | end 10 | 11 | function Complex.norm2(x) 12 | local n=Complex.mul(x,Complex.conj(x)) 13 | return n.re 14 | end 15 | 16 | function Complex.abs(x) 17 | return sqrt(Complex.norm2(x)) 18 | end 19 | 20 | function Complex.add(x,y) 21 | return complex(x.re+y.re,x.im+y.im) 22 | end 23 | 24 | function Complex.mul(x,y) 25 | return complex(x.re*y.re-x.im*y.im,x.re*y.im+x.im*y.re) 26 | end 27 | 28 | Complex.metatable={ 29 | __add = Complex.add, 30 | __mul = Complex.mul, 31 | } 32 | 33 | local function abs(x) 34 | return math.sqrt(Complex.norm2(x)) 35 | end 36 | 37 | xmin=-2.0 xmax=2.0 ymin=-2.0 ymax=2.0 38 | N=arg[1] or 256 39 | 40 | function level(x,y) 41 | local c=complex(x,y) 42 | local l=0 43 | local z=c 44 | repeat 45 | z=z*z+c 46 | l=l+1 47 | until abs(z)>2.0 or l>255 48 | return l-1 49 | end 50 | 51 | dx=(xmax-xmin)/N 52 | dy=(ymax-ymin)/N 53 | 54 | print("P2") 55 | print("# mandelbrot set",xmin,xmax,ymin,ymax,N) 56 | print(N,N,255) 57 | local S = 0 58 | for i=1,N do 59 | local x=xmin+(i-1)*dx 60 | for j=1,N do 61 | local y=ymin+(j-1)*dy 62 | S = S + level(x,y) 63 | end 64 | -- if i % 10 == 0 then print(collectgarbage"count") end 65 | end 66 | print(S) 67 | -------------------------------------------------------------------------------- /benchmarks/n-body.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://benchmarksgame.alioth.debian.org/ 3 | -- contributed by Mike Pall 4 | -- modified by Geoff Leyland 5 | -- modified by Mario Pernici 6 | 7 | sun = {} 8 | jupiter = {} 9 | saturn = {} 10 | uranus = {} 11 | neptune = {} 12 | 13 | local sqrt = math.sqrt 14 | 15 | local PI = 3.141592653589793 16 | local SOLAR_MASS = 4 * PI * PI 17 | local DAYS_PER_YEAR = 365.24 18 | sun.x = 0.0 19 | sun.y = 0.0 20 | sun.z = 0.0 21 | sun.vx = 0.0 22 | sun.vy = 0.0 23 | sun.vz = 0.0 24 | sun.mass = SOLAR_MASS 25 | jupiter.x = 4.84143144246472090e+00 26 | jupiter.y = -1.16032004402742839e+00 27 | jupiter.z = -1.03622044471123109e-01 28 | jupiter.vx = 1.66007664274403694e-03 * DAYS_PER_YEAR 29 | jupiter.vy = 7.69901118419740425e-03 * DAYS_PER_YEAR 30 | jupiter.vz = -6.90460016972063023e-05 * DAYS_PER_YEAR 31 | jupiter.mass = 9.54791938424326609e-04 * SOLAR_MASS 32 | saturn.x = 8.34336671824457987e+00 33 | saturn.y = 4.12479856412430479e+00 34 | saturn.z = -4.03523417114321381e-01 35 | saturn.vx = -2.76742510726862411e-03 * DAYS_PER_YEAR 36 | saturn.vy = 4.99852801234917238e-03 * DAYS_PER_YEAR 37 | saturn.vz = 2.30417297573763929e-05 * DAYS_PER_YEAR 38 | saturn.mass = 2.85885980666130812e-04 * SOLAR_MASS 39 | uranus.x = 1.28943695621391310e+01 40 | uranus.y = -1.51111514016986312e+01 41 | uranus.z = -2.23307578892655734e-01 42 | uranus.vx = 2.96460137564761618e-03 * DAYS_PER_YEAR 43 | uranus.vy = 2.37847173959480950e-03 * DAYS_PER_YEAR 44 | uranus.vz = -2.96589568540237556e-05 * DAYS_PER_YEAR 45 | uranus.mass = 4.36624404335156298e-05 * SOLAR_MASS 46 | neptune.x = 1.53796971148509165e+01 47 | neptune.y = -2.59193146099879641e+01 48 | neptune.z = 1.79258772950371181e-01 49 | neptune.vx = 2.68067772490389322e-03 * DAYS_PER_YEAR 50 | neptune.vy = 1.62824170038242295e-03 * DAYS_PER_YEAR 51 | neptune.vz = -9.51592254519715870e-05 * DAYS_PER_YEAR 52 | neptune.mass = 5.15138902046611451e-05 * SOLAR_MASS 53 | 54 | local bodies = {sun,jupiter,saturn,uranus,neptune} 55 | 56 | local function advance(bodies, nbody, dt) 57 | for i=1,nbody do 58 | local bi = bodies[i] 59 | local bix, biy, biz, bimass = bi.x, bi.y, bi.z, bi.mass 60 | local bivx, bivy, bivz = bi.vx, bi.vy, bi.vz 61 | for j=i+1,nbody do 62 | local bj = bodies[j] 63 | local dx, dy, dz = bix-bj.x, biy-bj.y, biz-bj.z 64 | local dist2 = dx*dx + dy*dy + dz*dz 65 | local mag = sqrt(dist2) 66 | mag = dt / (mag * dist2) 67 | local bm = bj.mass*mag 68 | bivx = bivx - (dx * bm) 69 | bivy = bivy - (dy * bm) 70 | bivz = bivz - (dz * bm) 71 | bm = bimass*mag 72 | bj.vx = bj.vx + (dx * bm) 73 | bj.vy = bj.vy + (dy * bm) 74 | bj.vz = bj.vz + (dz * bm) 75 | end 76 | bi.vx = bivx 77 | bi.vy = bivy 78 | bi.vz = bivz 79 | bi.x = bix + dt * bivx 80 | bi.y = biy + dt * bivy 81 | bi.z = biz + dt * bivz 82 | end 83 | end 84 | 85 | local function energy(bodies, nbody) 86 | local e = 0 87 | for i=1,nbody do 88 | local bi = bodies[i] 89 | local vx, vy, vz, bim = bi.vx, bi.vy, bi.vz, bi.mass 90 | e = e + (0.5 * bim * (vx*vx + vy*vy + vz*vz)) 91 | for j=i+1,nbody do 92 | local bj = bodies[j] 93 | local dx, dy, dz = bi.x-bj.x, bi.y-bj.y, bi.z-bj.z 94 | local distance = sqrt(dx*dx + dy*dy + dz*dz) 95 | e = e - ((bim * bj.mass) / distance) 96 | end 97 | end 98 | return e 99 | end 100 | 101 | local function offsetMomentum(b, nbody) 102 | local px, py, pz = 0, 0, 0 103 | for i=1,nbody do 104 | local bi = b[i] 105 | local bim = bi.mass 106 | px = px + (bi.vx * bim) 107 | py = py + (bi.vy * bim) 108 | pz = pz + (bi.vz * bim) 109 | end 110 | b[1].vx = -px / SOLAR_MASS 111 | b[1].vy = -py / SOLAR_MASS 112 | b[1].vz = -pz / SOLAR_MASS 113 | end 114 | 115 | local N = tonumber(arg and arg[1]) or 1000 116 | local nbody = #bodies 117 | 118 | offsetMomentum(bodies, nbody) 119 | io.write( string.format("%0.9f",energy(bodies, nbody)), "\n") 120 | for i=1,N do advance(bodies, nbody, 0.01) end 121 | io.write( string.format("%0.9f",energy(bodies, nbody)), "\n") 122 | -------------------------------------------------------------------------------- /benchmarks/plot.gpi: -------------------------------------------------------------------------------- 1 | set encoding utf8 2 | set terminal png size 3000,1000 font 'Helvetica,22' 3 | set output outfile 4 | 5 | set style data histogram 6 | set style histogram cluster gap 1 7 | set style fill solid border -1 8 | set xtic font "Helvetica,14" 9 | set boxwidth 0.9 10 | set grid 11 | 12 | set xlabel 'Programa' 13 | set ylabel 'Tempo de execução' 14 | 15 | plot for[i=2:6] datafile \ 16 | using i:xtic(1) \ 17 | title column \ 18 | ls i 19 | -------------------------------------------------------------------------------- /benchmarks/queen.lua: -------------------------------------------------------------------------------- 1 | local N = tonumber(arg[1] or 8) -- board size 2 | 3 | 4 | -- check whether position (n,c) is free from attacks 5 | local function isplaceok (a, n, c) 6 | for i = 1, n - 1 do -- for each queen already placed 7 | if (a[i] == c) or -- same column? 8 | (a[i] - i == c - n) or -- same diagonal? 9 | (a[i] + i == c + n) then -- same diagonal? 10 | return false -- place can be attacked 11 | end 12 | end 13 | return true -- no attacks; place is OK 14 | end 15 | 16 | 17 | -- print a board 18 | local function printsolution (a) 19 | for i = 1, N do 20 | for j = 1, N do 21 | io.write(a[i] == j and "X" or "-", " ") 22 | end 23 | io.write("\n") 24 | end 25 | io.write("\n") 26 | end 27 | 28 | 29 | -- add to board 'a' all queens from 'n' to 'N' 30 | local function addqueen (a, n) 31 | if n > N then -- all queens have been placed? 32 | printsolution(a) 33 | else -- try to place n-th queen 34 | for c = 1, N do 35 | if isplaceok(a, n, c) then 36 | a[n] = c -- place n-th queen at column 'c' 37 | addqueen(a, n + 1) 38 | end 39 | end 40 | end 41 | end 42 | 43 | 44 | -- run the program 45 | addqueen({}, 1) 46 | 47 | -------------------------------------------------------------------------------- /benchmarks/regex-dna.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://benchmarksgame.alioth.debian.org/ 3 | -- contributed by Jim Roseborough 4 | -- modified by Victor Tang 5 | -- optimized & replaced inefficient use of gsub with gmatch 6 | -- partitioned sequence to prevent extraneous redundant string copy 7 | 8 | seq = io.read("*a") 9 | ilen, seq = #seq, seq:gsub('>[^%c]*%c*', ''):gsub('%c+', '') 10 | clen = #seq 11 | 12 | local variants = { 'agggtaaa|tttaccct', 13 | '[cgt]gggtaaa|tttaccc[acg]', 14 | 'a[act]ggtaaa|tttacc[agt]t', 15 | 'ag[act]gtaaa|tttac[agt]ct', 16 | 'agg[act]taaa|ttta[agt]cct', 17 | 'aggg[acg]aaa|ttt[cgt]ccct', 18 | 'agggt[cgt]aa|tt[acg]accct', 19 | 'agggta[cgt]a|t[acg]taccct', 20 | 'agggtaa[cgt]|[acg]ttaccct', } 21 | 22 | local subst = { B='(c|g|t)', D='(a|g|t)', H='(a|c|t)', K='(g|t)', 23 | M='(a|c)', N='(a|c|g|t)', R='(a|g)', S='(c|g)', 24 | V='(a|c|g)', W='(a|t)', Y='(c|t)' } 25 | 26 | function countmatches(variant) 27 | local n = 0 28 | variant:gsub('([^|]+)|?', function(pattern) 29 | for _ in seq:gmatch(pattern) do n = n + 1 end 30 | end) 31 | return n 32 | end 33 | 34 | for _, p in ipairs(variants) do 35 | io.write( string.format('%s %d\n', p, countmatches(p)) ) 36 | end 37 | 38 | function partitionstring(seq) 39 | local seg = math.floor( math.sqrt(#seq) ) 40 | local seqtable = {} 41 | for nextstart = 1, #seq, seg do 42 | table.insert(seqtable, seq:sub(nextstart, nextstart + seg - 1)) 43 | end 44 | return seqtable 45 | end 46 | function chunk_gsub(t, k, v) 47 | for i, p in ipairs(t) do 48 | t[i] = p:find(k) and p:gsub(k, v) or t[i] 49 | end 50 | return t 51 | end 52 | 53 | seq = partitionstring(seq) 54 | for k, v in pairs(subst) do 55 | chunk_gsub(seq, k, v) 56 | end 57 | seq = table.concat(seq) 58 | io.write(string.format('\n%d\n%d\n%d\n', ilen, clen, #seq)) 59 | 60 | -------------------------------------------------------------------------------- /benchmarks/sieve.lua: -------------------------------------------------------------------------------- 1 | -- $Id: sieve.lua,v 1.9 2001/05/06 04:37:45 doug Exp $ 2 | -- http://www.bagley.org/~doug/shootout/ 3 | -- 4 | -- Roberto Ierusalimschy pointed out the for loop is much 5 | -- faster for our purposes here than using a while loop. 6 | 7 | local count = 0 8 | 9 | function main(num, lim) 10 | local flags = {} 11 | for num=num,1,-1 do 12 | count = 0 13 | for i=1,lim do 14 | flags[i] = 1 15 | end 16 | for i=2,lim do 17 | if flags[i] == 1 then 18 | k = 0 19 | for k=i+i, lim, i do 20 | flags[k] = 0 21 | end 22 | count = count + 1 23 | end 24 | end 25 | end 26 | end 27 | 28 | NUM = tonumber((arg and arg[1])) or 100 29 | lim = (arg and arg[2]) or 8192 30 | print(NUM,lim) 31 | count = 0 32 | main(NUM, lim) 33 | print("Count: ", count) 34 | -------------------------------------------------------------------------------- /benchmarks/spectral-norm.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://benchmarksgame.alioth.debian.org/ 3 | -- contributed by Mike Pall 4 | 5 | local function A(i, j) 6 | local ij = i+j-1 7 | return 1.0 / (ij * (ij-1) * 0.5 + i) 8 | end 9 | 10 | local function Av(x, y, N) 11 | for i=1,N do 12 | local a = 0 13 | for j=1,N do a = a + x[j] * A(i, j) end 14 | y[i] = a 15 | end 16 | end 17 | 18 | local function Atv(x, y, N) 19 | for i=1,N do 20 | local a = 0 21 | for j=1,N do a = a + x[j] * A(j, i) end 22 | y[i] = a 23 | end 24 | end 25 | 26 | local function AtAv(x, y, t, N) 27 | Av(x, t, N) 28 | Atv(t, y, N) 29 | end 30 | 31 | local N = tonumber(arg and arg[1]) or 100 32 | local u, v, t = {}, {}, {} 33 | for i=1,N do u[i] = 1 end 34 | 35 | for i=1,10 do AtAv(u, v, t, N) AtAv(v, u, t, N) end 36 | 37 | local vBv, vv = 0, 0 38 | for i=1,N do 39 | local ui, vi = u[i], v[i] 40 | vBv = vBv + ui*vi 41 | vv = vv + vi*vi 42 | end 43 | io.write(string.format("%0.9f\n", math.sqrt(vBv / vv))) 44 | -------------------------------------------------------------------------------- /doc/index.css: -------------------------------------------------------------------------------- 1 | ul { 2 | list-style-type: none ; 3 | } 4 | 5 | ul.contents { 6 | padding: 0 ; 7 | } 8 | 9 | table { 10 | border: none ; 11 | border-spacing: 0 ; 12 | border-collapse: collapse ; 13 | } 14 | 15 | td { 16 | vertical-align: top ; 17 | padding: 0 ; 18 | text-align: left ; 19 | line-height: 1.25 ; 20 | width: 15% ; 21 | } 22 | -------------------------------------------------------------------------------- /doc/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gligneul/FastLua/bef536d0140a7ff7fd440865f890a7345143f7a8/doc/logo.gif -------------------------------------------------------------------------------- /doc/lua.1: -------------------------------------------------------------------------------- 1 | .TH LUA 1 "$Date: 2014/12/10 15:55:45 $" 2 | .SH NAME 3 | lua \- Lua interpreter 4 | .SH SYNOPSIS 5 | .B lua 6 | [ 7 | .I options 8 | ] 9 | [ 10 | .I script 11 | [ 12 | .I args 13 | ] 14 | ] 15 | .SH DESCRIPTION 16 | .B lua 17 | is the standalone Lua interpreter. 18 | It loads and executes Lua programs, 19 | either in textual source form or 20 | in precompiled binary form. 21 | (Precompiled binaries are output by 22 | .BR luac , 23 | the Lua compiler.) 24 | .B lua 25 | can be used as a batch interpreter and also interactively. 26 | .LP 27 | The given 28 | .I options 29 | are handled in order and then 30 | the Lua program in file 31 | .I script 32 | is loaded and executed. 33 | The given 34 | .I args 35 | are available to 36 | .I script 37 | as strings in a global table named 38 | .BR arg . 39 | If no options or arguments are given, 40 | then 41 | .B "\-v \-i" 42 | is assumed when the standard input is a terminal; 43 | otherwise, 44 | .B "\-" 45 | is assumed. 46 | .LP 47 | In interactive mode, 48 | .B lua 49 | prompts the user, 50 | reads lines from the standard input, 51 | and executes them as they are read. 52 | If the line contains an expression or list of expressions, 53 | then the line is evaluated and the results are printed. 54 | If a line does not contain a complete statement, 55 | then a secondary prompt is displayed and 56 | lines are read until a complete statement is formed or 57 | a syntax error is found. 58 | .LP 59 | At the very start, 60 | before even handling the command line, 61 | .B lua 62 | checks the contents of the environment variables 63 | .B LUA_INIT_5_3 64 | or 65 | .BR LUA_INIT , 66 | in that order. 67 | If the contents is of the form 68 | .RI '@ filename ', 69 | then 70 | .I filename 71 | is executed. 72 | Otherwise, the string is assumed to be a Lua statement and is executed. 73 | .SH OPTIONS 74 | .TP 75 | .BI \-e " stat" 76 | execute statement 77 | .IR stat . 78 | .TP 79 | .B \-i 80 | enter interactive mode after executing 81 | .IR script . 82 | .TP 83 | .BI \-l " name" 84 | execute the equivalent of 85 | .IB name =require(' name ') 86 | before executing 87 | .IR script . 88 | .TP 89 | .B \-v 90 | show version information. 91 | .TP 92 | .B \-E 93 | ignore environment variables. 94 | .TP 95 | .B \-\- 96 | stop handling options. 97 | .TP 98 | .B \- 99 | stop handling options and execute the standard input as a file. 100 | .SH "SEE ALSO" 101 | .BR luac (1) 102 | .br 103 | The documentation at lua.org, 104 | especially section 7 of the reference manual. 105 | .SH DIAGNOSTICS 106 | Error messages should be self explanatory. 107 | .SH AUTHORS 108 | R. Ierusalimschy, 109 | L. H. de Figueiredo, 110 | W. Celes 111 | .\" EOF 112 | -------------------------------------------------------------------------------- /doc/lua.css: -------------------------------------------------------------------------------- 1 | html { 2 | background-color: #F8F8F8 ; 3 | } 4 | 5 | body { 6 | background-color: #FFFFFF ; 7 | color: #000000 ; 8 | font-family: Helvetica, Arial, sans-serif ; 9 | text-align: justify ; 10 | line-height: 1.25 ; 11 | margin: 16px auto ; 12 | padding: 32px ; 13 | border: solid #a0a0a0 1px ; 14 | border-radius: 20px ; 15 | max-width: 70em ; 16 | width: 90% ; 17 | } 18 | 19 | h1, h2, h3, h4 { 20 | color: #000080 ; 21 | font-family: Verdana, Geneva, sans-serif ; 22 | font-weight: normal ; 23 | font-style: normal ; 24 | text-align: left ; 25 | } 26 | 27 | h1 { 28 | font-size: 28pt ; 29 | } 30 | 31 | h1 img { 32 | vertical-align: text-bottom ; 33 | } 34 | 35 | h2:before { 36 | content: "\2756" ; 37 | padding-right: 0.5em ; 38 | } 39 | 40 | a { 41 | text-decoration: none ; 42 | } 43 | 44 | a:link { 45 | color: #000080 ; 46 | } 47 | 48 | a:link:hover, a:visited:hover { 49 | background-color: #D0D0FF ; 50 | color: #000080 ; 51 | border-radius: 4px ; 52 | } 53 | 54 | a:link:active, a:visited:active { 55 | color: #FF0000 ; 56 | } 57 | 58 | div.menubar { 59 | padding-bottom: 0.5em ; 60 | } 61 | 62 | p.menubar { 63 | margin-left: 2.5em ; 64 | } 65 | 66 | .menubar a:hover { 67 | margin: -3px -3px -3px -3px ; 68 | padding: 3px 3px 3px 3px ; 69 | border-radius: 4px ; 70 | } 71 | 72 | :target { 73 | background-color: #F0F0F0 ; 74 | margin: -8px ; 75 | padding: 8px ; 76 | border-radius: 8px ; 77 | outline: none ; 78 | } 79 | 80 | hr { 81 | display: none ; 82 | } 83 | 84 | table hr { 85 | background-color: #a0a0a0 ; 86 | color: #a0a0a0 ; 87 | border: 0 ; 88 | height: 1px ; 89 | display: block ; 90 | } 91 | 92 | .footer { 93 | color: gray ; 94 | font-size: x-small ; 95 | text-transform: lowercase ; 96 | } 97 | 98 | input[type=text] { 99 | border: solid #a0a0a0 2px ; 100 | border-radius: 2em ; 101 | background-image: url('images/search.png') ; 102 | background-repeat: no-repeat ; 103 | background-position: 4px center ; 104 | padding-left: 20px ; 105 | height: 2em ; 106 | } 107 | 108 | pre.session { 109 | background-color: #F8F8F8 ; 110 | padding: 1em ; 111 | border-radius: 8px ; 112 | } 113 | 114 | td.gutter { 115 | width: 4% ; 116 | } 117 | 118 | table.columns { 119 | border: none ; 120 | border-spacing: 0 ; 121 | border-collapse: collapse ; 122 | } 123 | 124 | table.columns td { 125 | vertical-align: top ; 126 | padding: 0 ; 127 | padding-bottom: 1em ; 128 | text-align: justify ; 129 | line-height: 1.25 ; 130 | } 131 | 132 | p.logos a:link:hover, p.logos a:visited:hover { 133 | background-color: inherit ; 134 | } 135 | 136 | table.book { 137 | border: none ; 138 | border-spacing: 0 ; 139 | border-collapse: collapse ; 140 | } 141 | 142 | table.book td { 143 | padding: 0 ; 144 | vertical-align: top ; 145 | } 146 | 147 | table.book td.cover { 148 | padding-right: 1em ; 149 | } 150 | 151 | table.book img { 152 | border: solid #000080 1px ; 153 | } 154 | 155 | table.book span { 156 | font-size: small ; 157 | text-align: left ; 158 | display: block ; 159 | margin-top: 0.25em ; 160 | } 161 | 162 | img { 163 | background-color: white ; 164 | } 165 | -------------------------------------------------------------------------------- /doc/luac.1: -------------------------------------------------------------------------------- 1 | .\" $Id: luac.man,v 1.29 2011/11/16 13:53:40 lhf Exp $ 2 | .TH LUAC 1 "$Date: 2011/11/16 13:53:40 $" 3 | .SH NAME 4 | luac \- Lua compiler 5 | .SH SYNOPSIS 6 | .B luac 7 | [ 8 | .I options 9 | ] [ 10 | .I filenames 11 | ] 12 | .SH DESCRIPTION 13 | .B luac 14 | is the Lua compiler. 15 | It translates programs written in the Lua programming language 16 | into binary files containing precompiled chunks 17 | that can be later loaded and executed. 18 | .LP 19 | The main advantages of precompiling chunks are: 20 | faster loading, 21 | protecting source code from accidental user changes, 22 | and 23 | off-line syntax checking. 24 | Precompiling does not imply faster execution 25 | because in Lua chunks are always compiled into bytecodes before being executed. 26 | .B luac 27 | simply allows those bytecodes to be saved in a file for later execution. 28 | Precompiled chunks are not necessarily smaller than the corresponding source. 29 | The main goal in precompiling is faster loading. 30 | .LP 31 | In the command line, 32 | you can mix 33 | text files containing Lua source and 34 | binary files containing precompiled chunks. 35 | .B luac 36 | produces a single output file containing the combined bytecodes 37 | for all files given. 38 | Executing the combined file is equivalent to executing the given files. 39 | By default, 40 | the output file is named 41 | .BR luac.out , 42 | but you can change this with the 43 | .B \-o 44 | option. 45 | .LP 46 | Precompiled chunks are 47 | .I not 48 | portable across different architectures. 49 | Moreover, 50 | the internal format of precompiled chunks 51 | is likely to change when a new version of Lua is released. 52 | Make sure you save the source files of all Lua programs that you precompile. 53 | .LP 54 | .SH OPTIONS 55 | .TP 56 | .B \-l 57 | produce a listing of the compiled bytecode for Lua's virtual machine. 58 | Listing bytecodes is useful to learn about Lua's virtual machine. 59 | If no files are given, then 60 | .B luac 61 | loads 62 | .B luac.out 63 | and lists its contents. 64 | Use 65 | .B \-l \-l 66 | for a full listing. 67 | .TP 68 | .BI \-o " file" 69 | output to 70 | .IR file , 71 | instead of the default 72 | .BR luac.out . 73 | (You can use 74 | .B "'\-'" 75 | for standard output, 76 | but not on platforms that open standard output in text mode.) 77 | The output file may be one of the given files because 78 | all files are loaded before the output file is written. 79 | Be careful not to overwrite precious files. 80 | .TP 81 | .B \-p 82 | load files but do not generate any output file. 83 | Used mainly for syntax checking and for testing precompiled chunks: 84 | corrupted files will probably generate errors when loaded. 85 | If no files are given, then 86 | .B luac 87 | loads 88 | .B luac.out 89 | and tests its contents. 90 | No messages are displayed if the file loads without errors. 91 | .TP 92 | .B \-s 93 | strip debug information before writing the output file. 94 | This saves some space in very large chunks, 95 | but if errors occur when running a stripped chunk, 96 | then the error messages may not contain the full information they usually do. 97 | In particular, 98 | line numbers and names of local variables are lost. 99 | .TP 100 | .B \-v 101 | show version information. 102 | .TP 103 | .B \-\- 104 | stop handling options. 105 | .TP 106 | .B \- 107 | stop handling options and process standard input. 108 | .SH "SEE ALSO" 109 | .BR lua (1) 110 | .br 111 | The documentation at lua.org. 112 | .SH DIAGNOSTICS 113 | Error messages should be self explanatory. 114 | .SH AUTHORS 115 | R. Ierusalimschy, 116 | L. H. de Figueiredo, 117 | W. Celes 118 | .\" EOF 119 | -------------------------------------------------------------------------------- /doc/manual.css: -------------------------------------------------------------------------------- 1 | h3 code { 2 | font-family: inherit ; 3 | font-size: inherit ; 4 | } 5 | 6 | pre, code { 7 | font-size: 12pt ; 8 | } 9 | 10 | span.apii { 11 | color: gray ; 12 | float: right ; 13 | font-family: inherit ; 14 | font-style: normal ; 15 | font-size: small ; 16 | } 17 | 18 | h2:before { 19 | content: "" ; 20 | padding-right: 0em ; 21 | } 22 | -------------------------------------------------------------------------------- /doc/osi-certified-72x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gligneul/FastLua/bef536d0140a7ff7fd440865f890a7345143f7a8/doc/osi-certified-72x60.png -------------------------------------------------------------------------------- /fltests/binop.lua: -------------------------------------------------------------------------------- 1 | if jit and jit.logger then jit.logger('none') end 2 | 3 | do 4 | print('add r k') 5 | local a = 0 6 | for i = 0, 100 do a = a + 1 end 7 | print(a) 8 | end 9 | 10 | do 11 | print('add k r') 12 | local a = 0 13 | for i = 0, 100 do a = 1 + a end 14 | print(a) 15 | end 16 | 17 | do 18 | print('add r r') 19 | local a, b = 0, 10 20 | for i = 0, 100 do a = b + a end 21 | print(a) 22 | end 23 | 24 | do 25 | print('add r r') 26 | local a, b = 0, 10 27 | for i = 0, 100 do a = b + a end 28 | print(a) 29 | end 30 | 31 | do 32 | print('add cast kb') 33 | local a = 0.5 34 | for i = 0, 100 do a = 1 + a end 35 | print(a) 36 | end 37 | 38 | do 39 | print('add cast kc') 40 | local a = 0.5 41 | for i = 0, 100 do a = a + 1 end 42 | print(a) 43 | end 44 | -------------------------------------------------------------------------------- /fltests/forloop.lua: -------------------------------------------------------------------------------- 1 | if jit and jit.logger then jit.logger('none') end 2 | 3 | do 4 | print('empty loop') 5 | for i = 0, 100 do end 6 | end 7 | 8 | print('-----------------------------------------------------------------------') 9 | 10 | do 11 | print('basic test with integers') 12 | local a = 0 13 | for i = 1, 100 do a = a + i end 14 | print(a) 15 | for i = 1, 100 do a = a + 1 end 16 | print(a) 17 | end 18 | 19 | print('-----------------------------------------------------------------------') 20 | 21 | do 22 | print('values that are not phi') 23 | local function f(n) 24 | local a = 0 25 | for i = 1, n do a = 123 end 26 | print(a) 27 | end 28 | f(100) 29 | f(1) 30 | f(0) 31 | end 32 | 33 | print('-----------------------------------------------------------------------') 34 | 35 | do 36 | print('change index') 37 | local a = 0 38 | for i = 1, 100 do 39 | i = 10 40 | a = a + i 41 | end 42 | print(a) 43 | end 44 | 45 | print('-----------------------------------------------------------------------') 46 | 47 | do 48 | print('change step direction') 49 | local function f(start, limit, step) 50 | local a = 0 51 | for i = start, limit, step do a = a + i end 52 | print(a) 53 | end 54 | f(0, 100, 1) 55 | f(100, 0, -1) 56 | end 57 | 58 | -------------------------------------------------------------------------------- /fltests/moveload.lua: -------------------------------------------------------------------------------- 1 | if jit and jit.logger then jit.logger('none') end 2 | 3 | print('testing move') 4 | 5 | function testmove(v) 6 | local f = 7 | 'local a, b = nil, ' .. v .. '\n' .. 8 | 'for i = 1, 100 do a = b end\n' .. 9 | 'print(a)' 10 | load(f)() 11 | end 12 | 13 | testmove('nil') 14 | testmove('true') 15 | testmove('false') 16 | testmove('0') 17 | testmove('1') 18 | testmove('0xFFFFFFFFFFFFFFFF') 19 | testmove('0.001') 20 | testmove('123.456') 21 | testmove('0/0') 22 | testmove('"hello"') 23 | -- testmove('{}') 24 | -- testmove('function() end') 25 | 26 | -- TODO: test c-functions, threads, uservalues, etc 27 | -- TODO: test type changes that yield a trace exit 28 | 29 | -------------------------------------------------------------------------------- 30 | 31 | print('testing loadk') 32 | 33 | function testloadk(k) 34 | local f = 35 | 'local a\n' .. 36 | 'for i = 1, 100 do a = ' .. k .. ' end\n' .. 37 | 'print(a)' 38 | load(f)() 39 | end 40 | 41 | testloadk('nil') 42 | testloadk('true') 43 | testloadk('false') 44 | testloadk('0') 45 | testloadk('1') 46 | testloadk('0xFFFFFFFFFFFFFFFF') 47 | testloadk('0.001') 48 | testloadk('123.456') 49 | testloadk('0/0') 50 | testloadk('"hello"') 51 | 52 | -------------------------------------------------------------------------------- /luatests/big.lua: -------------------------------------------------------------------------------- 1 | -- $Id: big.lua,v 1.31 2014/12/26 17:20:53 roberto Exp $ 2 | 3 | if _soft then 4 | return 'a' 5 | end 6 | 7 | print "testing large tables" 8 | 9 | local debug = require"debug" 10 | 11 | local lim = 2^18 + 1000 12 | local prog = { "local y = {0" } 13 | for i = 1, lim do prog[#prog + 1] = i end 14 | prog[#prog + 1] = "}\n" 15 | prog[#prog + 1] = "X = y\n" 16 | prog[#prog + 1] = ("assert(X[%d] == %d)"):format(lim - 1, lim - 2) 17 | prog[#prog + 1] = "return 0" 18 | prog = table.concat(prog, ";") 19 | 20 | local env = {string = string, assert = assert} 21 | local f = assert(load(prog, nil, nil, env)) 22 | 23 | f() 24 | assert(env.X[lim] == lim - 1 and env.X[lim + 1] == lim) 25 | for k in pairs(env) do env[k] = nil end 26 | 27 | -- yields during accesses larger than K (in RK) 28 | setmetatable(env, { 29 | __index = function (t, n) coroutine.yield('g'); return _G[n] end, 30 | __newindex = function (t, n, v) coroutine.yield('s'); _G[n] = v end, 31 | }) 32 | 33 | X = nil 34 | co = coroutine.wrap(f) 35 | assert(co() == 's') 36 | assert(co() == 'g') 37 | assert(co() == 'g') 38 | assert(co() == 0) 39 | 40 | assert(X[lim] == lim - 1 and X[lim + 1] == lim) 41 | 42 | -- errors in accesses larger than K (in RK) 43 | getmetatable(env).__index = function () end 44 | getmetatable(env).__newindex = function () end 45 | local e, m = pcall(f) 46 | assert(not e and m:find("global 'X'")) 47 | 48 | -- errors in metamethods 49 | getmetatable(env).__newindex = function () error("hi") end 50 | local e, m = xpcall(f, debug.traceback) 51 | assert(not e and m:find("'__newindex'")) 52 | 53 | f, X = nil 54 | 55 | coroutine.yield'b' 56 | 57 | if 2^32 == 0 then -- (small integers) { 58 | 59 | print "testing string length overflow" 60 | 61 | local repstrings = 192 -- number of strings to be concatenated 62 | local ssize = math.ceil(2.0^32 / repstrings) + 1 -- size of each string 63 | 64 | assert(repstrings * ssize > 2.0^32) -- it should be larger than maximum size 65 | 66 | local longs = string.rep("\0", ssize) -- create one long string 67 | 68 | -- create function to concatentate 'repstrings' copies of its argument 69 | local rep = assert(load( 70 | "local a = ...; return " .. string.rep("a", repstrings, ".."))) 71 | 72 | local a, b = pcall(rep, longs) -- call that function 73 | 74 | -- it should fail without creating string (result would be too large) 75 | assert(not a and string.find(b, "overflow")) 76 | 77 | end -- } 78 | 79 | print'OK' 80 | 81 | return 'a' 82 | -------------------------------------------------------------------------------- /luatests/closure.lua: -------------------------------------------------------------------------------- 1 | -- $Id: closure.lua,v 1.58 2014/12/26 17:20:53 roberto Exp $ 2 | 3 | print "testing closures" 4 | 5 | local A,B = 0,{g=10} 6 | function f(x) 7 | local a = {} 8 | for i=1,1000 do 9 | local y = 0 10 | do 11 | a[i] = function () B.g = B.g+1; y = y+x; return y+A end 12 | end 13 | end 14 | local dummy = function () return a[A] end 15 | collectgarbage() 16 | A = 1; assert(dummy() == a[1]); A = 0; 17 | assert(a[1]() == x) 18 | assert(a[3]() == x) 19 | collectgarbage() 20 | assert(B.g == 12) 21 | return a 22 | end 23 | 24 | local a = f(10) 25 | -- force a GC in this level 26 | local x = {[1] = {}} -- to detect a GC 27 | setmetatable(x, {__mode = 'kv'}) 28 | while x[1] do -- repeat until GC 29 | local a = A..A..A..A -- create garbage 30 | A = A+1 31 | end 32 | assert(a[1]() == 20+A) 33 | assert(a[1]() == 30+A) 34 | assert(a[2]() == 10+A) 35 | collectgarbage() 36 | assert(a[2]() == 20+A) 37 | assert(a[2]() == 30+A) 38 | assert(a[3]() == 20+A) 39 | assert(a[8]() == 10+A) 40 | assert(getmetatable(x).__mode == 'kv') 41 | assert(B.g == 19) 42 | 43 | 44 | -- testing equality 45 | a = {} 46 | for i = 1, 5 do a[i] = function (x) return x + a + _ENV end end 47 | assert(a[3] == a[4] and a[4] == a[5]) 48 | 49 | for i = 1, 5 do a[i] = function (x) return i + a + _ENV end end 50 | assert(a[3] ~= a[4] and a[4] ~= a[5]) 51 | 52 | local function f() 53 | return function (x) return math.sin(_ENV[x]) end 54 | end 55 | assert(f() == f()) 56 | 57 | 58 | -- testing closures with 'for' control variable 59 | a = {} 60 | for i=1,10 do 61 | a[i] = {set = function(x) i=x end, get = function () return i end} 62 | if i == 3 then break end 63 | end 64 | assert(a[4] == nil) 65 | a[1].set(10) 66 | assert(a[2].get() == 2) 67 | a[2].set('a') 68 | assert(a[3].get() == 3) 69 | assert(a[2].get() == 'a') 70 | 71 | a = {} 72 | local t = {"a", "b"} 73 | for i = 1, #t do 74 | local k = t[i] 75 | a[i] = {set = function(x, y) i=x; k=y end, 76 | get = function () return i, k end} 77 | if i == 2 then break end 78 | end 79 | a[1].set(10, 20) 80 | local r,s = a[2].get() 81 | assert(r == 2 and s == 'b') 82 | r,s = a[1].get() 83 | assert(r == 10 and s == 20) 84 | a[2].set('a', 'b') 85 | r,s = a[2].get() 86 | assert(r == "a" and s == "b") 87 | 88 | 89 | -- testing closures with 'for' control variable x break 90 | for i=1,3 do 91 | f = function () return i end 92 | break 93 | end 94 | assert(f() == 1) 95 | 96 | for k = 1, #t do 97 | local v = t[k] 98 | f = function () return k, v end 99 | break 100 | end 101 | assert(({f()})[1] == 1) 102 | assert(({f()})[2] == "a") 103 | 104 | 105 | -- testing closure x break x return x errors 106 | 107 | local b 108 | function f(x) 109 | local first = 1 110 | while 1 do 111 | if x == 3 and not first then return end 112 | local a = 'xuxu' 113 | b = function (op, y) 114 | if op == 'set' then 115 | a = x+y 116 | else 117 | return a 118 | end 119 | end 120 | if x == 1 then do break end 121 | elseif x == 2 then return 122 | else if x ~= 3 then error() end 123 | end 124 | first = nil 125 | end 126 | end 127 | 128 | for i=1,3 do 129 | f(i) 130 | assert(b('get') == 'xuxu') 131 | b('set', 10); assert(b('get') == 10+i) 132 | b = nil 133 | end 134 | 135 | pcall(f, 4); 136 | assert(b('get') == 'xuxu') 137 | b('set', 10); assert(b('get') == 14) 138 | 139 | 140 | local w 141 | -- testing multi-level closure 142 | function f(x) 143 | return function (y) 144 | return function (z) return w+x+y+z end 145 | end 146 | end 147 | 148 | y = f(10) 149 | w = 1.345 150 | assert(y(20)(30) == 60+w) 151 | 152 | -- testing closures x repeat-until 153 | 154 | local a = {} 155 | local i = 1 156 | repeat 157 | local x = i 158 | a[i] = function () i = x+1; return x end 159 | until i > 10 or a[i]() ~= x 160 | assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4) 161 | 162 | 163 | -- testing closures created in 'then' and 'else' parts of 'if's 164 | a = {} 165 | for i = 1, 10 do 166 | if i % 3 == 0 then 167 | local y = 0 168 | a[i] = function (x) local t = y; y = x; return t end 169 | elseif i % 3 == 1 then 170 | goto L1 171 | error'not here' 172 | ::L1:: 173 | local y = 1 174 | a[i] = function (x) local t = y; y = x; return t end 175 | elseif i % 3 == 2 then 176 | local t 177 | goto l4 178 | ::l4a:: a[i] = t; goto l4b 179 | error("should never be here!") 180 | ::l4:: 181 | local y = 2 182 | t = function (x) local t = y; y = x; return t end 183 | goto l4a 184 | error("should never be here!") 185 | ::l4b:: 186 | end 187 | end 188 | 189 | for i = 1, 10 do 190 | assert(a[i](i * 10) == i % 3 and a[i]() == i * 10) 191 | end 192 | 193 | print'+' 194 | 195 | 196 | -- test for correctly closing upvalues in tail calls of vararg functions 197 | local function t () 198 | local function c(a,b) assert(a=="test" and b=="OK") end 199 | local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end 200 | local x = 1 201 | return v(function() return x end) 202 | end 203 | t() 204 | 205 | 206 | -- test for debug manipulation of upvalues 207 | local debug = require'debug' 208 | 209 | do 210 | local a , b, c = 3, 5, 7 211 | foo1 = function () return a+b end; 212 | foo2 = function () return b+a end; 213 | do 214 | local a = 10 215 | foo3 = function () return a+b end; 216 | end 217 | end 218 | 219 | assert(debug.upvalueid(foo1, 1)) 220 | assert(debug.upvalueid(foo1, 2)) 221 | assert(not pcall(debug.upvalueid, foo1, 3)) 222 | assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2)) 223 | assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1)) 224 | assert(debug.upvalueid(foo3, 1)) 225 | assert(debug.upvalueid(foo1, 1) ~= debug.upvalueid(foo3, 1)) 226 | assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2)) 227 | 228 | assert(debug.upvalueid(string.gmatch("x", "x"), 1) ~= nil) 229 | 230 | assert(foo1() == 3 + 5 and foo2() == 5 + 3) 231 | debug.upvaluejoin(foo1, 2, foo2, 2) 232 | assert(foo1() == 3 + 3 and foo2() == 5 + 3) 233 | assert(foo3() == 10 + 5) 234 | debug.upvaluejoin(foo3, 2, foo2, 1) 235 | assert(foo3() == 10 + 5) 236 | debug.upvaluejoin(foo3, 2, foo2, 2) 237 | assert(foo3() == 10 + 3) 238 | 239 | assert(not pcall(debug.upvaluejoin, foo1, 3, foo2, 1)) 240 | assert(not pcall(debug.upvaluejoin, foo1, 1, foo2, 3)) 241 | assert(not pcall(debug.upvaluejoin, foo1, 0, foo2, 1)) 242 | assert(not pcall(debug.upvaluejoin, print, 1, foo2, 1)) 243 | assert(not pcall(debug.upvaluejoin, {}, 1, foo2, 1)) 244 | assert(not pcall(debug.upvaluejoin, foo1, 1, print, 1)) 245 | 246 | print'OK' 247 | -------------------------------------------------------------------------------- /luatests/code.lua: -------------------------------------------------------------------------------- 1 | -- $Id: code.lua,v 1.41 2014/12/26 17:18:43 roberto Exp $ 2 | 3 | if T==nil then 4 | (Message or print)('\n >>> testC not active: skipping opcode tests <<<\n') 5 | return 6 | end 7 | print "testing code generation and optimizations" 8 | 9 | 10 | -- this code gave an error for the code checker 11 | do 12 | local function f (a) 13 | for k,v,w in a do end 14 | end 15 | end 16 | 17 | 18 | -- testing reuse in constant table 19 | local function checkKlist (func, list) 20 | local k = T.listk(func) 21 | assert(#k == #list) 22 | for i = 1, #k do 23 | assert(k[i] == list[i] and math.type(k[i]) == math.type(list[i])) 24 | end 25 | end 26 | 27 | local function foo () 28 | local a 29 | a = 3; 30 | a = 0; a = 0.0; a = -7 + 7 31 | a = 3.78/4; a = 3.78/4 32 | a = -3.78/4; a = 3.78/4; a = -3.78/4 33 | a = -3.79/4; a = 0.0; a = -0; 34 | a = 3; a = 3.0; a = 3; a = 3.0 35 | end 36 | 37 | checkKlist(foo, {3, 0, 0.0, 3.78/4, -3.78/4, -3.79/4, 3.0}) 38 | 39 | 40 | -- testing opcodes 41 | 42 | function check (f, ...) 43 | local arg = {...} 44 | local c = T.listcode(f) 45 | for i=1, #arg do 46 | -- print(arg[i], c[i]) 47 | assert(string.find(c[i], '- '..arg[i]..' *%d')) 48 | end 49 | assert(c[#arg+2] == nil) 50 | end 51 | 52 | 53 | function checkequal (a, b) 54 | a = T.listcode(a) 55 | b = T.listcode(b) 56 | for i = 1, #a do 57 | a[i] = string.gsub(a[i], '%b()', '') -- remove line number 58 | b[i] = string.gsub(b[i], '%b()', '') -- remove line number 59 | assert(a[i] == b[i]) 60 | end 61 | end 62 | 63 | 64 | -- some basic instructions 65 | check(function () 66 | (function () end){f()} 67 | end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN') 68 | 69 | 70 | -- sequence of LOADNILs 71 | check(function () 72 | local a,b,c 73 | local d; local e; 74 | local f,g,h; 75 | d = nil; d=nil; b=nil; a=nil; c=nil; 76 | end, 'LOADNIL', 'RETURN') 77 | 78 | check(function () 79 | local a,b,c,d = 1,1,1,1 80 | d=nil;c=nil;b=nil;a=nil 81 | end, 'LOADK', 'LOADK', 'LOADK', 'LOADK', 'LOADNIL', 'RETURN') 82 | 83 | do 84 | local a,b,c,d = 1,1,1,1 85 | d=nil;c=nil;b=nil;a=nil 86 | assert(a == nil and b == nil and c == nil and d == nil) 87 | end 88 | 89 | 90 | -- single return 91 | check (function (a,b,c) return a end, 'RETURN') 92 | 93 | 94 | -- infinite loops 95 | check(function () while true do local a = -1 end end, 96 | 'LOADK', 'JMP', 'RETURN') 97 | 98 | check(function () while 1 do local a = -1 end end, 99 | 'LOADK', 'JMP', 'RETURN') 100 | 101 | check(function () repeat local x = 1 until true end, 102 | 'LOADK', 'RETURN') 103 | 104 | 105 | -- concat optimization 106 | check(function (a,b,c,d) return a..b..c..d end, 107 | 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN') 108 | 109 | -- not 110 | check(function () return not not nil end, 'LOADBOOL', 'RETURN') 111 | check(function () return not not false end, 'LOADBOOL', 'RETURN') 112 | check(function () return not not true end, 'LOADBOOL', 'RETURN') 113 | check(function () return not not 1 end, 'LOADBOOL', 'RETURN') 114 | 115 | -- direct access to locals 116 | check(function () 117 | local a,b,c,d 118 | a = b*2 119 | c[4], a[b] = -((a + d/-20.5 - a[b]) ^ a.x), b 120 | end, 121 | 'LOADNIL', 122 | 'MUL', 123 | 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW', 124 | 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN') 125 | 126 | 127 | -- direct access to constants 128 | check(function () 129 | local a,b 130 | a.x = 0 131 | a.x = b 132 | a[b] = 'y' 133 | a = 1 - a 134 | b = 1/a 135 | b = 5+4 136 | a[true] = false 137 | end, 138 | 'LOADNIL', 139 | 'SETTABLE', 'SETTABLE', 'SETTABLE', 'SUB', 'DIV', 'LOADK', 140 | 'SETTABLE', 'RETURN') 141 | 142 | 143 | -- constant folding 144 | local function checkK (func, val) 145 | check(func, 'LOADK', 'RETURN') 146 | local k = T.listk(func) 147 | assert(#k == 1 and k[1] == val and math.type(k[1]) == math.type(val)) 148 | assert(func() == val) 149 | end 150 | checkK(function () return 0.0 end, 0.0) 151 | checkK(function () return 0 end, 0) 152 | checkK(function () return -0//1 end, 0) 153 | checkK(function () return 3^-1 end, 1/3) 154 | checkK(function () return (1 + 1)^(50 + 50) end, 2^100) 155 | checkK(function () return (-2)^(31 - 2) end, -0x20000000 + 0.0) 156 | checkK(function () return (-3^0 + 5) // 3.0 end, 1.0) 157 | checkK(function () return -3 % 5 end, 2) 158 | checkK(function () return -((2.0^8 + -(-1)) % 8)/2 * 4 - 3 end, -5.0) 159 | checkK(function () return -((2^8 + -(-1)) % 8)//2 * 4 - 3 end, -7.0) 160 | checkK(function () return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD end, 0xF4) 161 | checkK(function () return ~(~0xFF0 | 0xFF0) end, 0) 162 | checkK(function () return ~~-100024.0 end, -100024) 163 | checkK(function () return ((100 << 6) << -4) >> 2 end, 100) 164 | 165 | 166 | -- no foldings 167 | check(function () return -0.0 end, 'LOADK', 'UNM', 'RETURN') 168 | check(function () return 3/0 end, 'DIV', 'RETURN') 169 | check(function () return 0%0 end, 'MOD', 'RETURN') 170 | check(function () return -4//0 end, 'IDIV', 'RETURN') 171 | 172 | -- bug in constant folding for 5.1 173 | check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN') 174 | 175 | 176 | check(function () 177 | local a,b,c 178 | b[c], a = c, b 179 | b[a], a = c, b 180 | a, b = c, a 181 | a = a 182 | end, 183 | 'LOADNIL', 184 | 'MOVE', 'MOVE', 'SETTABLE', 185 | 'MOVE', 'MOVE', 'MOVE', 'SETTABLE', 186 | 'MOVE', 'MOVE', 'MOVE', 187 | -- no code for a = a 188 | 'RETURN') 189 | 190 | 191 | -- x == nil , x ~= nil 192 | checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end, 193 | function () if (a==9) then a=1 end; if a~=9 then a=1 end end) 194 | 195 | check(function () if a==nil then a=1 end end, 196 | 'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN') 197 | 198 | -- de morgan 199 | checkequal(function () local a; if not (a or b) then b=a end end, 200 | function () local a; if (not a and not b) then b=a end end) 201 | 202 | checkequal(function (l) local a; return 0 <= a and a <= l end, 203 | function (l) local a; return not (not(a >= 0) or not(a <= l)) end) 204 | 205 | 206 | -- if-goto optimizations 207 | check(function (a) 208 | if a == 1 then goto l1 209 | elseif a == 2 then goto l2 210 | elseif a == 3 then goto l2 211 | else if a == 4 then goto l3 212 | else goto l3 213 | end 214 | end 215 | ::l1:: ::l2:: ::l3:: ::l4:: 216 | end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', 'RETURN') 217 | 218 | checkequal( 219 | function (a) while a < 10 do a = a + 1 end end, 220 | function (a) ::L2:: if not(a < 10) then goto L1 end; a = a + 1; 221 | goto L2; ::L1:: end 222 | ) 223 | 224 | checkequal( 225 | function (a) while a < 10 do a = a + 1 end end, 226 | function (a) while true do if not(a < 10) then break end; a = a + 1; end end 227 | ) 228 | 229 | print 'OK' 230 | 231 | -------------------------------------------------------------------------------- /luatests/db.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gligneul/FastLua/bef536d0140a7ff7fd440865f890a7345143f7a8/luatests/db.lua -------------------------------------------------------------------------------- /luatests/files.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gligneul/FastLua/bef536d0140a7ff7fd440865f890a7345143f7a8/luatests/files.lua -------------------------------------------------------------------------------- /luatests/goto.lua: -------------------------------------------------------------------------------- 1 | -- $Id: goto.lua,v 1.12 2016/03/07 19:26:18 roberto Exp $ 2 | 3 | collectgarbage() 4 | 5 | local function errmsg (code, m) 6 | local st, msg = load(code) 7 | assert(not st and string.find(msg, m)) 8 | end 9 | 10 | -- cannot see label inside block 11 | errmsg([[ goto l1; do ::l1:: end ]], "label 'l1'") 12 | errmsg([[ do ::l1:: end goto l1; ]], "label 'l1'") 13 | 14 | -- repeated label 15 | errmsg([[ ::l1:: ::l1:: ]], "label 'l1'") 16 | 17 | 18 | -- undefined label 19 | errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "local 'aa'") 20 | 21 | -- jumping over variable definition 22 | errmsg([[ 23 | do local bb, cc; goto l1; end 24 | local aa 25 | ::l1:: print(3) 26 | ]], "local 'aa'") 27 | 28 | -- jumping into a block 29 | errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'") 30 | errmsg([[ goto l1 do ::l1:: end ]], "label 'l1'") 31 | 32 | -- cannot continue a repeat-until with variables 33 | errmsg([[ 34 | repeat 35 | if x then goto cont end 36 | local xuxu = 10 37 | ::cont:: 38 | until xuxu < x 39 | ]], "local 'xuxu'") 40 | 41 | -- simple gotos 42 | local x 43 | do 44 | local y = 12 45 | goto l1 46 | ::l2:: x = x + 1; goto l3 47 | ::l1:: x = y; goto l2 48 | end 49 | ::l3:: ::l3_1:: assert(x == 13) 50 | 51 | 52 | -- long labels 53 | do 54 | local prog = [[ 55 | do 56 | local a = 1 57 | goto l%sa; a = a + 1 58 | ::l%sa:: a = a + 10 59 | goto l%sb; a = a + 2 60 | ::l%sb:: a = a + 20 61 | return a 62 | end 63 | ]] 64 | local label = string.rep("0123456789", 40) 65 | prog = string.format(prog, label, label, label, label) 66 | assert(assert(load(prog))() == 31) 67 | end 68 | 69 | -- goto to correct label when nested 70 | do goto l3; ::l3:: end -- does not loop jumping to previous label 'l3' 71 | 72 | -- ok to jump over local dec. to end of block 73 | do 74 | goto l1 75 | local a = 23 76 | x = a 77 | ::l1::; 78 | end 79 | 80 | while true do 81 | goto l4 82 | goto l1 -- ok to jump over local dec. to end of block 83 | goto l1 -- multiple uses of same label 84 | local x = 45 85 | ::l1:: ;;; 86 | end 87 | ::l4:: assert(x == 13) 88 | 89 | if print then 90 | goto l1 -- ok to jump over local dec. to end of block 91 | error("should not be here") 92 | goto l2 -- ok to jump over local dec. to end of block 93 | local x 94 | ::l1:: ; ::l2:: ;; 95 | else end 96 | 97 | -- to repeat a label in a different function is OK 98 | local function foo () 99 | local a = {} 100 | goto l3 101 | ::l1:: a[#a + 1] = 1; goto l2; 102 | ::l2:: a[#a + 1] = 2; goto l5; 103 | ::l3:: 104 | ::l3a:: a[#a + 1] = 3; goto l1; 105 | ::l4:: a[#a + 1] = 4; goto l6; 106 | ::l5:: a[#a + 1] = 5; goto l4; 107 | ::l6:: assert(a[1] == 3 and a[2] == 1 and a[3] == 2 and 108 | a[4] == 5 and a[5] == 4) 109 | if not a[6] then a[6] = true; goto l3a end -- do it twice 110 | end 111 | 112 | ::l6:: foo() 113 | 114 | 115 | do -- bug in 5.2 -> 5.3.2 116 | local x 117 | ::L1:: 118 | local y -- cannot join this SETNIL with previous one 119 | assert(y == nil) 120 | y = true 121 | if x == nil then 122 | x = 1 123 | goto L1 124 | else 125 | x = x + 1 126 | end 127 | assert(x == 2 and y == true) 128 | end 129 | 130 | -------------------------------------------------------------------------------- 131 | -- testing closing of upvalues 132 | 133 | local debug = require 'debug' 134 | 135 | local function foo () 136 | local t = {} 137 | do 138 | local i = 1 139 | local a, b, c, d 140 | t[1] = function () return a, b, c, d end 141 | ::l1:: 142 | local b 143 | do 144 | local c 145 | t[#t + 1] = function () return a, b, c, d end -- t[2], t[4], t[6] 146 | if i > 2 then goto l2 end 147 | do 148 | local d 149 | t[#t + 1] = function () return a, b, c, d end -- t[3], t[5] 150 | i = i + 1 151 | local a 152 | goto l1 153 | end 154 | end 155 | end 156 | ::l2:: return t 157 | end 158 | 159 | local a = foo() 160 | assert(#a == 6) 161 | 162 | -- all functions share same 'a' 163 | for i = 2, 6 do 164 | assert(debug.upvalueid(a[1], 1) == debug.upvalueid(a[i], 1)) 165 | end 166 | 167 | -- 'b' and 'c' are shared among some of them 168 | for i = 2, 6 do 169 | -- only a[1] uses external 'b'/'b' 170 | assert(debug.upvalueid(a[1], 2) ~= debug.upvalueid(a[i], 2)) 171 | assert(debug.upvalueid(a[1], 3) ~= debug.upvalueid(a[i], 3)) 172 | end 173 | 174 | for i = 3, 5, 2 do 175 | -- inner functions share 'b'/'c' with previous ones 176 | assert(debug.upvalueid(a[i], 2) == debug.upvalueid(a[i - 1], 2)) 177 | assert(debug.upvalueid(a[i], 3) == debug.upvalueid(a[i - 1], 3)) 178 | -- but not with next ones 179 | assert(debug.upvalueid(a[i], 2) ~= debug.upvalueid(a[i + 1], 2)) 180 | assert(debug.upvalueid(a[i], 3) ~= debug.upvalueid(a[i + 1], 3)) 181 | end 182 | 183 | -- only external 'd' is shared 184 | for i = 2, 6, 2 do 185 | assert(debug.upvalueid(a[1], 4) == debug.upvalueid(a[i], 4)) 186 | end 187 | 188 | -- internal 'd's are all different 189 | for i = 3, 5, 2 do 190 | for j = 1, 6 do 191 | assert((debug.upvalueid(a[i], 4) == debug.upvalueid(a[j], 4)) 192 | == (i == j)) 193 | end 194 | end 195 | 196 | -------------------------------------------------------------------------------- 197 | -- testing if x goto optimizations 198 | 199 | local function testG (a) 200 | if a == 1 then 201 | goto l1 202 | error("should never be here!") 203 | elseif a == 2 then goto l2 204 | elseif a == 3 then goto l3 205 | elseif a == 4 then 206 | goto l1 -- go to inside the block 207 | error("should never be here!") 208 | ::l1:: a = a + 1 -- must go to 'if' end 209 | else 210 | goto l4 211 | ::l4a:: a = a * 2; goto l4b 212 | error("should never be here!") 213 | ::l4:: goto l4a 214 | error("should never be here!") 215 | ::l4b:: 216 | end 217 | do return a end 218 | ::l2:: do return "2" end 219 | ::l3:: do return "3" end 220 | ::l1:: return "1" 221 | end 222 | 223 | assert(testG(1) == "1") 224 | assert(testG(2) == "2") 225 | assert(testG(3) == "3") 226 | assert(testG(4) == 5) 227 | assert(testG(5) == 10) 228 | -------------------------------------------------------------------------------- 229 | 230 | 231 | print'OK' 232 | -------------------------------------------------------------------------------- /luatests/libs/lib1.c: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | #include "lauxlib.h" 3 | 4 | static int id (lua_State *L) { 5 | return lua_gettop(L); 6 | } 7 | 8 | 9 | static const struct luaL_Reg funcs[] = { 10 | {"id", id}, 11 | {NULL, NULL} 12 | }; 13 | 14 | 15 | /* function used by lib11.c */ 16 | LUAMOD_API int lib1_export (lua_State *L) { 17 | lua_pushstring(L, "exported"); 18 | return 1; 19 | } 20 | 21 | 22 | LUAMOD_API int onefunction (lua_State *L) { 23 | luaL_checkversion(L); 24 | lua_settop(L, 2); 25 | lua_pushvalue(L, 1); 26 | return 2; 27 | } 28 | 29 | 30 | LUAMOD_API int anotherfunc (lua_State *L) { 31 | luaL_checkversion(L); 32 | lua_pushfstring(L, "%d%%%d\n", (int)lua_tointeger(L, 1), 33 | (int)lua_tointeger(L, 2)); 34 | return 1; 35 | } 36 | 37 | 38 | LUAMOD_API int luaopen_lib1_sub (lua_State *L) { 39 | lua_setglobal(L, "y"); /* 2nd arg: extra value (file name) */ 40 | lua_setglobal(L, "x"); /* 1st arg: module name */ 41 | luaL_newlib(L, funcs); 42 | return 1; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /luatests/libs/lib11.c: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | 3 | /* function from lib1.c */ 4 | int lib1_export (lua_State *L); 5 | 6 | LUAMOD_API int luaopen_lib11 (lua_State *L) { 7 | return lib1_export(L); 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /luatests/libs/lib2.c: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | #include "lauxlib.h" 3 | 4 | static int id (lua_State *L) { 5 | return lua_gettop(L); 6 | } 7 | 8 | 9 | static const struct luaL_Reg funcs[] = { 10 | {"id", id}, 11 | {NULL, NULL} 12 | }; 13 | 14 | 15 | LUAMOD_API int luaopen_lib2 (lua_State *L) { 16 | lua_settop(L, 2); 17 | lua_setglobal(L, "y"); /* y gets 2nd parameter */ 18 | lua_setglobal(L, "x"); /* x gets 1st parameter */ 19 | luaL_newlib(L, funcs); 20 | return 1; 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /luatests/libs/lib21.c: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | 3 | 4 | int luaopen_lib2 (lua_State *L); 5 | 6 | LUAMOD_API int luaopen_lib21 (lua_State *L) { 7 | return luaopen_lib2(L); 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /luatests/libs/makefile: -------------------------------------------------------------------------------- 1 | # change this variable to point to the directory with Lua headers 2 | # of the version being tested 3 | LUA_DIR = ../.. 4 | 5 | CC = gcc 6 | 7 | # compilation should generate Dynamic-Link Libraries 8 | CFLAGS = -Wall -std=gnu99 -O2 -I$(LUA_DIR) -fPIC -shared 9 | 10 | # libraries used by the tests 11 | all: lib1.so lib11.so lib2.so lib21.so lib2-v2.so 12 | 13 | lib1.so: lib1.c 14 | $(CC) $(CFLAGS) -o lib1.so lib1.c 15 | 16 | lib11.so: lib11.c 17 | $(CC) $(CFLAGS) -o lib11.so lib11.c 18 | 19 | lib2.so: lib2.c 20 | $(CC) $(CFLAGS) -o lib2.so lib2.c 21 | 22 | lib21.so: lib21.c 23 | $(CC) $(CFLAGS) -o lib21.so lib21.c 24 | 25 | lib2-v2.so: lib2.so 26 | mv lib2.so ./lib2-v2.so 27 | -------------------------------------------------------------------------------- /luatests/locals.lua: -------------------------------------------------------------------------------- 1 | -- $Id: locals.lua,v 1.36 2015/03/04 13:09:38 roberto Exp $ 2 | 3 | print('testing local variables and environments') 4 | 5 | local debug = require"debug" 6 | 7 | 8 | -- bug in 5.1: 9 | 10 | local function f(x) x = nil; return x end 11 | assert(f(10) == nil) 12 | 13 | local function f() local x; return x end 14 | assert(f(10) == nil) 15 | 16 | local function f(x) x = nil; local y; return x, y end 17 | assert(f(10) == nil and select(2, f(20)) == nil) 18 | 19 | do 20 | local i = 10 21 | do local i = 100; assert(i==100) end 22 | do local i = 1000; assert(i==1000) end 23 | assert(i == 10) 24 | if i ~= 10 then 25 | local i = 20 26 | else 27 | local i = 30 28 | assert(i == 30) 29 | end 30 | end 31 | 32 | 33 | 34 | f = nil 35 | 36 | local f 37 | x = 1 38 | 39 | a = nil 40 | load('local a = {}')() 41 | assert(a == nil) 42 | 43 | function f (a) 44 | local _1, _2, _3, _4, _5 45 | local _6, _7, _8, _9, _10 46 | local x = 3 47 | local b = a 48 | local c,d = a,b 49 | if (d == b) then 50 | local x = 'q' 51 | x = b 52 | assert(x == 2) 53 | else 54 | assert(nil) 55 | end 56 | assert(x == 3) 57 | local f = 10 58 | end 59 | 60 | local b=10 61 | local a; repeat local b; a,b=1,2; assert(a+1==b); until a+b==3 62 | 63 | 64 | assert(x == 1) 65 | 66 | f(2) 67 | assert(type(f) == 'function') 68 | 69 | 70 | local function getenv (f) 71 | local a,b = debug.getupvalue(f, 1) 72 | assert(a == '_ENV') 73 | return b 74 | end 75 | 76 | -- test for global table of loaded chunks 77 | assert(getenv(load"a=3") == _G) 78 | local c = {}; local f = load("a = 3", nil, nil, c) 79 | assert(getenv(f) == c) 80 | assert(c.a == nil) 81 | f() 82 | assert(c.a == 3) 83 | 84 | -- old test for limits for special instructions (now just a generic test) 85 | do 86 | local i = 2 87 | local p = 4 -- p == 2^i 88 | repeat 89 | for j=-3,3 do 90 | assert(load(string.format([[local a=%s; 91 | a=a+%s; 92 | assert(a ==2^%s)]], j, p-j, i), '')) () 93 | assert(load(string.format([[local a=%s; 94 | a=a-%s; 95 | assert(a==-2^%s)]], -j, p-j, i), '')) () 96 | assert(load(string.format([[local a,b=0,%s; 97 | a=b-%s; 98 | assert(a==-2^%s)]], -j, p-j, i), '')) () 99 | end 100 | p = 2 * p; i = i + 1 101 | until p <= 0 102 | end 103 | 104 | print'+' 105 | 106 | 107 | if rawget(_G, "querytab") then 108 | -- testing clearing of dead elements from tables 109 | collectgarbage("stop") -- stop GC 110 | local a = {[{}] = 4, [3] = 0, alo = 1, 111 | a1234567890123456789012345678901234567890 = 10} 112 | 113 | local t = querytab(a) 114 | 115 | for k,_ in pairs(a) do a[k] = nil end 116 | collectgarbage() -- restore GC and collect dead fiels in `a' 117 | for i=0,t-1 do 118 | local k = querytab(a, i) 119 | assert(k == nil or type(k) == 'number' or k == 'alo') 120 | end 121 | end 122 | 123 | 124 | -- testing lexical environments 125 | 126 | assert(_ENV == _G) 127 | 128 | do 129 | local dummy 130 | local _ENV = (function (...) return ... end)(_G, dummy) -- { 131 | 132 | do local _ENV = {assert=assert}; assert(true) end 133 | mt = {_G = _G} 134 | local foo,x 135 | A = false -- "declare" A 136 | do local _ENV = mt 137 | function foo (x) 138 | A = x 139 | do local _ENV = _G; A = 1000 end 140 | return function (x) return A .. x end 141 | end 142 | end 143 | assert(getenv(foo) == mt) 144 | x = foo('hi'); assert(mt.A == 'hi' and A == 1000) 145 | assert(x('*') == mt.A .. '*') 146 | 147 | do local _ENV = {assert=assert, A=10}; 148 | do local _ENV = {assert=assert, A=20}; 149 | assert(A==20);x=A 150 | end 151 | assert(A==10 and x==20) 152 | end 153 | assert(x==20) 154 | 155 | 156 | print('OK') 157 | 158 | return 5,f 159 | 160 | end -- } 161 | 162 | -------------------------------------------------------------------------------- /luatests/ltests/ltests.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltests.h,v 2.49 2015/09/22 14:18:24 roberto Exp $ 3 | ** Internal Header for Debugging of the Lua Implementation 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltests_h 8 | #define ltests_h 9 | 10 | 11 | #include 12 | 13 | /* test Lua with no compatibility code */ 14 | #undef LUA_COMPAT_MATHLIB 15 | #undef LUA_COMPAT_IPAIRS 16 | #undef LUA_COMPAT_BITLIB 17 | #undef LUA_COMPAT_APIINTCASTS 18 | #undef LUA_COMPAT_FLOATSTRING 19 | #undef LUA_COMPAT_UNPACK 20 | #undef LUA_COMPAT_LOADERS 21 | #undef LUA_COMPAT_LOG10 22 | #undef LUA_COMPAT_LOADSTRING 23 | #undef LUA_COMPAT_MAXN 24 | #undef LUA_COMPAT_MODULE 25 | 26 | 27 | #define LUA_DEBUG 28 | 29 | 30 | /* turn on assertions */ 31 | #undef NDEBUG 32 | #include 33 | #define lua_assert(c) assert(c) 34 | 35 | 36 | /* to avoid warnings, and to make sure value is really unused */ 37 | #define UNUSED(x) (x=0, (void)(x)) 38 | 39 | 40 | /* test for sizes in 'l_sprintf' (make sure whole buffer is available) */ 41 | #undef l_sprintf 42 | #if !defined(LUA_USE_C89) 43 | #define l_sprintf(s,sz,f,i) (memset(s,0xAB,sz), snprintf(s,sz,f,i)) 44 | #else 45 | #define l_sprintf(s,sz,f,i) (memset(s,0xAB,sz), sprintf(s,f,i)) 46 | #endif 47 | 48 | 49 | /* memory-allocator control variables */ 50 | typedef struct Memcontrol { 51 | unsigned long numblocks; 52 | unsigned long total; 53 | unsigned long maxmem; 54 | unsigned long memlimit; 55 | unsigned long objcount[LUA_NUMTAGS]; 56 | } Memcontrol; 57 | 58 | LUA_API Memcontrol l_memcontrol; 59 | 60 | 61 | /* 62 | ** generic variable for debug tricks 63 | */ 64 | extern void *l_Trick; 65 | 66 | 67 | 68 | /* 69 | ** Function to traverse and check all memory used by Lua 70 | */ 71 | int lua_checkmemory (lua_State *L); 72 | 73 | 74 | /* test for lock/unlock */ 75 | 76 | struct L_EXTRA { int lock; int *plock; }; 77 | #undef LUA_EXTRASPACE 78 | #define LUA_EXTRASPACE sizeof(struct L_EXTRA) 79 | #define getlock(l) cast(struct L_EXTRA*, lua_getextraspace(l)) 80 | #define luai_userstateopen(l) \ 81 | (getlock(l)->lock = 0, getlock(l)->plock = &(getlock(l)->lock)) 82 | #define luai_userstateclose(l) \ 83 | lua_assert(getlock(l)->lock == 1 && getlock(l)->plock == &(getlock(l)->lock)) 84 | #define luai_userstatethread(l,l1) \ 85 | lua_assert(getlock(l1)->plock == getlock(l)->plock) 86 | #define luai_userstatefree(l,l1) \ 87 | lua_assert(getlock(l)->plock == getlock(l1)->plock) 88 | #define lua_lock(l) lua_assert((*getlock(l)->plock)++ == 0) 89 | #define lua_unlock(l) lua_assert(--(*getlock(l)->plock) == 0) 90 | 91 | 92 | 93 | LUA_API int luaB_opentests (lua_State *L); 94 | 95 | LUA_API void *debug_realloc (void *ud, void *block, 96 | size_t osize, size_t nsize); 97 | 98 | #if defined(lua_c) 99 | #define luaL_newstate() lua_newstate(debug_realloc, &l_memcontrol) 100 | #define luaL_openlibs(L) \ 101 | { (luaL_openlibs)(L); luaL_requiref(L, "T", luaB_opentests, 1); } 102 | #endif 103 | 104 | 105 | 106 | /* change some sizes to give some bugs a chance */ 107 | 108 | #undef LUAL_BUFFERSIZE 109 | #define LUAL_BUFFERSIZE 23 110 | #define MINSTRTABSIZE 2 111 | 112 | 113 | /* make stack-overflow tests run faster */ 114 | #undef LUAI_MAXSTACK 115 | #define LUAI_MAXSTACK 50000 116 | 117 | 118 | #undef LUAI_USER_ALIGNMENT_T 119 | #define LUAI_USER_ALIGNMENT_T union { char b[sizeof(void*) * 8]; } 120 | 121 | 122 | #define STRCACHE_N 23 123 | #define STRCACHE_M 5 124 | 125 | #endif 126 | 127 | -------------------------------------------------------------------------------- /luatests/pm.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gligneul/FastLua/bef536d0140a7ff7fd440865f890a7345143f7a8/luatests/pm.lua -------------------------------------------------------------------------------- /luatests/sort.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gligneul/FastLua/bef536d0140a7ff7fd440865f890a7345143f7a8/luatests/sort.lua -------------------------------------------------------------------------------- /luatests/strings.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gligneul/FastLua/bef536d0140a7ff7fd440865f890a7345143f7a8/luatests/strings.lua -------------------------------------------------------------------------------- /luatests/utf8.lua: -------------------------------------------------------------------------------- 1 | -- $Id: utf8.lua,v 1.11 2014/12/26 17:20:53 roberto Exp $ 2 | 3 | print "testing UTF-8 library" 4 | 5 | local utf8 = require'utf8' 6 | 7 | 8 | local function checkerror (msg, f, ...) 9 | local s, err = pcall(f, ...) 10 | assert(not s and string.find(err, msg)) 11 | end 12 | 13 | 14 | local function len (s) 15 | return #string.gsub(s, "[\x80-\xBF]", "") 16 | end 17 | 18 | 19 | local justone = "^" .. utf8.charpattern .. "$" 20 | 21 | -- 't' is the list of codepoints of 's' 22 | local function checksyntax (s, t) 23 | local ts = {"return '"} 24 | for i = 1, #t do ts[i + 1] = string.format("\\u{%x}", t[i]) end 25 | ts[#t + 2] = "'" 26 | ts = table.concat(ts) 27 | assert(assert(load(ts))() == s) 28 | end 29 | 30 | assert(utf8.offset("alo", 5) == nil) 31 | assert(utf8.offset("alo", -4) == nil) 32 | 33 | -- 't' is the list of codepoints of 's' 34 | local function check (s, t) 35 | local l = utf8.len(s) 36 | assert(#t == l and len(s) == l) 37 | assert(utf8.char(table.unpack(t)) == s) 38 | 39 | assert(utf8.offset(s, 0) == 1) 40 | 41 | checksyntax(s, t) 42 | 43 | local t1 = {utf8.codepoint(s, 1, -1)} 44 | assert(#t == #t1) 45 | for i = 1, #t do assert(t[i] == t1[i]) end 46 | 47 | for i = 1, l do 48 | local pi = utf8.offset(s, i) -- position of i-th char 49 | local pi1 = utf8.offset(s, 2, pi) -- position of next char 50 | assert(string.find(string.sub(s, pi, pi1 - 1), justone)) 51 | assert(utf8.offset(s, -1, pi1) == pi) 52 | assert(utf8.offset(s, i - l - 1) == pi) 53 | assert(pi1 - pi == #utf8.char(utf8.codepoint(s, pi))) 54 | for j = pi, pi1 - 1 do 55 | assert(utf8.offset(s, 0, j) == pi) 56 | end 57 | for j = pi + 1, pi1 - 1 do 58 | assert(not utf8.len(s, j)) 59 | end 60 | assert(utf8.len(s, pi, pi) == 1) 61 | assert(utf8.len(s, pi, pi1 - 1) == 1) 62 | assert(utf8.len(s, pi) == l - i + 1) 63 | assert(utf8.len(s, pi1) == l - i) 64 | assert(utf8.len(s, 1, pi) == i) 65 | end 66 | 67 | local i = 0 68 | for p, c in utf8.codes(s) do 69 | i = i + 1 70 | assert(c == t[i] and p == utf8.offset(s, i)) 71 | assert(utf8.codepoint(s, p) == c) 72 | end 73 | assert(i == #t) 74 | 75 | i = 0 76 | for p, c in utf8.codes(s) do 77 | i = i + 1 78 | assert(c == t[i] and p == utf8.offset(s, i)) 79 | end 80 | assert(i == #t) 81 | 82 | i = 0 83 | for c in string.gmatch(s, utf8.charpattern) do 84 | i = i + 1 85 | assert(c == utf8.char(t[i])) 86 | end 87 | assert(i == #t) 88 | 89 | for i = 1, l do 90 | assert(utf8.offset(s, i) == utf8.offset(s, i - l - 1, #s + 1)) 91 | end 92 | 93 | end 94 | 95 | 96 | do -- error indication in utf8.len 97 | local function check (s, p) 98 | local a, b = utf8.len(s) 99 | assert(not a and b == p) 100 | end 101 | check("abc\xE3def", 4) 102 | check("汉字\x80", #("汉字") + 1) 103 | check("\xF4\x9F\xBF", 1) 104 | check("\xF4\x9F\xBF\xBF", 1) 105 | end 106 | 107 | -- error in utf8.codes 108 | checkerror("invalid UTF%-8 code", 109 | function () 110 | local s = "ab\xff" 111 | for c in utf8.codes(s) do assert(c) end 112 | end) 113 | 114 | 115 | -- error in initial position for offset 116 | checkerror("position out of range", utf8.offset, "abc", 1, 5) 117 | checkerror("position out of range", utf8.offset, "abc", 1, -4) 118 | checkerror("position out of range", utf8.offset, "", 1, 2) 119 | checkerror("position out of range", utf8.offset, "", 1, -1) 120 | checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) 121 | checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) 122 | checkerror("continuation byte", utf8.offset, "\x80", 1) 123 | 124 | 125 | 126 | local s = "hello World" 127 | local t = {string.byte(s, 1, -1)} 128 | for i = 1, utf8.len(s) do assert(t[i] == string.byte(s, i)) end 129 | check(s, t) 130 | 131 | check("汉字/漢字", {27721, 23383, 47, 28450, 23383,}) 132 | 133 | do 134 | local s = "áéí\128" 135 | local t = {utf8.codepoint(s,1,#s - 1)} 136 | assert(#t == 3 and t[1] == 225 and t[2] == 233 and t[3] == 237) 137 | checkerror("invalid UTF%-8 code", utf8.codepoint, s, 1, #s) 138 | checkerror("out of range", utf8.codepoint, s, #s + 1) 139 | t = {utf8.codepoint(s, 4, 3)} 140 | assert(#t == 0) 141 | checkerror("out of range", utf8.codepoint, s, -(#s + 1), 1) 142 | checkerror("out of range", utf8.codepoint, s, 1, #s + 1) 143 | end 144 | 145 | assert(utf8.char() == "") 146 | assert(utf8.char(97, 98, 99) == "abc") 147 | 148 | assert(utf8.codepoint(utf8.char(0x10FFFF)) == 0x10FFFF) 149 | 150 | checkerror("value out of range", utf8.char, 0x10FFFF + 1) 151 | 152 | local function invalid (s) 153 | checkerror("invalid UTF%-8 code", utf8.codepoint, s) 154 | assert(not utf8.len(s)) 155 | end 156 | 157 | -- UTF-8 representation for 0x11ffff (value out of valid range) 158 | invalid("\xF4\x9F\xBF\xBF") 159 | 160 | -- overlong sequences 161 | invalid("\xC0\x80") -- zero 162 | invalid("\xC1\xBF") -- 0x7F (should be coded in 1 byte) 163 | invalid("\xE0\x9F\xBF") -- 0x7FF (should be coded in 2 bytes) 164 | invalid("\xF0\x8F\xBF\xBF") -- 0xFFFF (should be coded in 3 bytes) 165 | 166 | 167 | -- invalid bytes 168 | invalid("\x80") -- continuation byte 169 | invalid("\xBF") -- continuation byte 170 | invalid("\xFE") -- invalid byte 171 | invalid("\xFF") -- invalid byte 172 | 173 | 174 | -- empty string 175 | check("", {}) 176 | 177 | -- minimum and maximum values for each sequence size 178 | s = "\0 \x7F\z 179 | \xC2\x80 \xDF\xBF\z 180 | \xE0\xA0\x80 \xEF\xBF\xBF\z 181 | \xF0\x90\x80\x80 \xF4\x8F\xBF\xBF" 182 | s = string.gsub(s, " ", "") 183 | check(s, {0,0x7F, 0x80,0x7FF, 0x800,0xFFFF, 0x10000,0x10FFFF}) 184 | 185 | x = "日本語a-4\0éó" 186 | check(x, {26085, 26412, 35486, 97, 45, 52, 0, 233, 243}) 187 | 188 | 189 | -- Supplementary Characters 190 | check("𣲷𠜎𠱓𡁻𠵼ab𠺢", 191 | {0x23CB7, 0x2070E, 0x20C53, 0x2107B, 0x20D7C, 0x61, 0x62, 0x20EA2,}) 192 | 193 | check("𨳊𩶘𦧺𨳒𥄫𤓓\xF4\x8F\xBF\xBF", 194 | {0x28CCA, 0x29D98, 0x269FA, 0x28CD2, 0x2512B, 0x244D3, 0x10ffff}) 195 | 196 | 197 | local i = 0 198 | for p, c in string.gmatch(x, "()(" .. utf8.charpattern .. ")") do 199 | i = i + 1 200 | assert(utf8.offset(x, i) == p) 201 | assert(utf8.len(x, p) == utf8.len(x) - i + 1) 202 | assert(utf8.len(c) == 1) 203 | for j = 1, #c - 1 do 204 | assert(utf8.offset(x, 0, p + j - 1) == p) 205 | end 206 | end 207 | 208 | print'ok' 209 | 210 | -------------------------------------------------------------------------------- /luatests/vararg.lua: -------------------------------------------------------------------------------- 1 | -- $Id: vararg.lua,v 1.24 2015/06/01 16:38:36 roberto Exp $ 2 | 3 | print('testing vararg') 4 | 5 | function f(a, ...) 6 | local arg = {n = select('#', ...), ...} 7 | for i=1,arg.n do assert(a[i]==arg[i]) end 8 | return arg.n 9 | end 10 | 11 | function c12 (...) 12 | assert(arg == _G.arg) -- no local 'arg' 13 | local x = {...}; x.n = #x 14 | local res = (x.n==2 and x[1] == 1 and x[2] == 2) 15 | if res then res = 55 end 16 | return res, 2 17 | end 18 | 19 | function vararg (...) return {n = select('#', ...), ...} end 20 | 21 | local call = function (f, args) return f(table.unpack(args, 1, args.n)) end 22 | 23 | assert(f() == 0) 24 | assert(f({1,2,3}, 1, 2, 3) == 3) 25 | assert(f({"alo", nil, 45, f, nil}, "alo", nil, 45, f, nil) == 5) 26 | 27 | assert(c12(1,2)==55) 28 | a,b = assert(call(c12, {1,2})) 29 | assert(a == 55 and b == 2) 30 | a = call(c12, {1,2;n=2}) 31 | assert(a == 55 and b == 2) 32 | a = call(c12, {1,2;n=1}) 33 | assert(not a) 34 | assert(c12(1,2,3) == false) 35 | local a = vararg(call(next, {_G,nil;n=2})) 36 | local b,c = next(_G) 37 | assert(a[1] == b and a[2] == c and a.n == 2) 38 | a = vararg(call(call, {c12, {1,2}})) 39 | assert(a.n == 2 and a[1] == 55 and a[2] == 2) 40 | a = call(print, {'+'}) 41 | assert(a == nil) 42 | 43 | local t = {1, 10} 44 | function t:f (...) local arg = {...}; return self[...]+#arg end 45 | assert(t:f(1,4) == 3 and t:f(2) == 11) 46 | print('+') 47 | 48 | lim = 20 49 | local i, a = 1, {} 50 | while i <= lim do a[i] = i+0.3; i=i+1 end 51 | 52 | function f(a, b, c, d, ...) 53 | local more = {...} 54 | assert(a == 1.3 and more[1] == 5.3 and 55 | more[lim-4] == lim+0.3 and not more[lim-3]) 56 | end 57 | 58 | function g(a,b,c) 59 | assert(a == 1.3 and b == 2.3 and c == 3.3) 60 | end 61 | 62 | call(f, a) 63 | call(g, a) 64 | 65 | a = {} 66 | i = 1 67 | while i <= lim do a[i] = i; i=i+1 end 68 | assert(call(math.max, a) == lim) 69 | 70 | print("+") 71 | 72 | 73 | -- new-style varargs 74 | 75 | function oneless (a, ...) return ... end 76 | 77 | function f (n, a, ...) 78 | local b 79 | assert(arg == _G.arg) -- no local 'arg' 80 | if n == 0 then 81 | local b, c, d = ... 82 | return a, b, c, d, oneless(oneless(oneless(...))) 83 | else 84 | n, b, a = n-1, ..., a 85 | assert(b == ...) 86 | return f(n, a, ...) 87 | end 88 | end 89 | 90 | a,b,c,d,e = assert(f(10,5,4,3,2,1)) 91 | assert(a==5 and b==4 and c==3 and d==2 and e==1) 92 | 93 | a,b,c,d,e = f(4) 94 | assert(a==nil and b==nil and c==nil and d==nil and e==nil) 95 | 96 | 97 | -- varargs for main chunks 98 | f = load[[ return {...} ]] 99 | x = f(2,3) 100 | assert(x[1] == 2 and x[2] == 3 and x[3] == nil) 101 | 102 | 103 | f = load[[ 104 | local x = {...} 105 | for i=1,select('#', ...) do assert(x[i] == select(i, ...)) end 106 | assert(x[select('#', ...)+1] == nil) 107 | return true 108 | ]] 109 | 110 | assert(f("a", "b", nil, {}, assert)) 111 | assert(f()) 112 | 113 | a = {select(3, table.unpack{10,20,30,40})} 114 | assert(#a == 2 and a[1] == 30 and a[2] == 40) 115 | a = {select(1)} 116 | assert(next(a) == nil) 117 | a = {select(-1, 3, 5, 7)} 118 | assert(a[1] == 7 and a[2] == nil) 119 | a = {select(-2, 3, 5, 7)} 120 | assert(a[1] == 5 and a[2] == 7 and a[3] == nil) 121 | pcall(select, 10000) 122 | pcall(select, -10000) 123 | 124 | 125 | -- bug in 5.2.2 126 | 127 | function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, 128 | p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, 129 | p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, 130 | p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, 131 | p41, p42, p43, p44, p45, p46, p48, p49, p50, ...) 132 | local a1,a2,a3,a4,a5,a6,a7 133 | local a8,a9,a10,a11,a12,a13,a14 134 | end 135 | 136 | -- assertion fail here 137 | f() 138 | 139 | 140 | print('OK') 141 | 142 | -------------------------------------------------------------------------------- /luatests/verybig.lua: -------------------------------------------------------------------------------- 1 | -- $Id: verybig.lua,v 1.24 2014/12/26 17:20:53 roberto Exp $ 2 | 3 | print "testing RK" 4 | 5 | -- testing opcodes with RK arguments larger than K limit 6 | local function foo () 7 | local dummy = { 8 | -- fill first 256 entries in table of constants 9 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 10 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 11 | 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 12 | 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 13 | 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 14 | 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 15 | 97, 98, 99, 100, 101, 102, 103, 104, 16 | 105, 106, 107, 108, 109, 110, 111, 112, 17 | 113, 114, 115, 116, 117, 118, 119, 120, 18 | 121, 122, 123, 124, 125, 126, 127, 128, 19 | 129, 130, 131, 132, 133, 134, 135, 136, 20 | 137, 138, 139, 140, 141, 142, 143, 144, 21 | 145, 146, 147, 148, 149, 150, 151, 152, 22 | 153, 154, 155, 156, 157, 158, 159, 160, 23 | 161, 162, 163, 164, 165, 166, 167, 168, 24 | 169, 170, 171, 172, 173, 174, 175, 176, 25 | 177, 178, 179, 180, 181, 182, 183, 184, 26 | 185, 186, 187, 188, 189, 190, 191, 192, 27 | 193, 194, 195, 196, 197, 198, 199, 200, 28 | 201, 202, 203, 204, 205, 206, 207, 208, 29 | 209, 210, 211, 212, 213, 214, 215, 216, 30 | 217, 218, 219, 220, 221, 222, 223, 224, 31 | 225, 226, 227, 228, 229, 230, 231, 232, 32 | 233, 234, 235, 236, 237, 238, 239, 240, 33 | 241, 242, 243, 244, 245, 246, 247, 248, 34 | 249, 250, 251, 252, 253, 254, 255, 256, 35 | } 36 | assert(24.5 + 0.6 == 25.1) 37 | local t = {foo = function (self, x) return x + self.x end, x = 10} 38 | t.t = t 39 | assert(t:foo(1.5) == 11.5) 40 | assert(t.t:foo(0.5) == 10.5) -- bug in 5.2 alpha 41 | assert(24.3 == 24.3) 42 | assert((function () return t.x end)() == 10) 43 | end 44 | 45 | 46 | foo() 47 | foo = nil 48 | 49 | if _soft then return 10 end 50 | 51 | print "testing large programs (>64k)" 52 | 53 | -- template to create a very big test file 54 | prog = [[$ 55 | 56 | local a,b 57 | 58 | b = {$1$ 59 | b30009 = 65534, 60 | b30010 = 65535, 61 | b30011 = 65536, 62 | b30012 = 65537, 63 | b30013 = 16777214, 64 | b30014 = 16777215, 65 | b30015 = 16777216, 66 | b30016 = 16777217, 67 | b30017 = 0x7fffff, 68 | b30018 = -0x7fffff, 69 | b30019 = 0x1ffffff, 70 | b30020 = -0x1ffffd, 71 | b30021 = -65534, 72 | b30022 = -65535, 73 | b30023 = -65536, 74 | b30024 = -0xffffff, 75 | b30025 = 15012.5, 76 | $2$ 77 | }; 78 | 79 | assert(b.a50008 == 25004 and b["a11"] == -5.5) 80 | assert(b.a33007 == -16503.5 and b.a50009 == -25004.5) 81 | assert(b["b"..30024] == -0xffffff) 82 | 83 | function b:xxx (a,b) return a+b end 84 | assert(b:xxx(10, 12) == 22) -- pushself with non-constant index 85 | b.xxx = nil 86 | 87 | s = 0; n=0 88 | for a,b in pairs(b) do s=s+b; n=n+1 end 89 | -- with 32-bit floats, exact value of 's' depends on summation order 90 | assert(81800000.0 < s and s < 81860000 and n == 70001) 91 | 92 | a = nil; b = nil 93 | print'+' 94 | 95 | function f(x) b=x end 96 | 97 | a = f{$3$} or 10 98 | 99 | assert(a==10) 100 | assert(b[1] == "a10" and b[2] == 5 and b[#b-1] == "a50009") 101 | 102 | 103 | function xxxx (x) return b[x] end 104 | 105 | assert(xxxx(3) == "a11") 106 | 107 | a = nil; b=nil 108 | xxxx = nil 109 | 110 | return 10 111 | 112 | ]] 113 | 114 | -- functions to fill in the $n$ 115 | 116 | local function sig (x) 117 | return (x % 2 == 0) and '' or '-' 118 | end 119 | 120 | F = { 121 | function () -- $1$ 122 | for i=10,50009 do 123 | io.write('a', i, ' = ', sig(i), 5+((i-10)/2), ',\n') 124 | end 125 | end, 126 | 127 | function () -- $2$ 128 | for i=30026,50009 do 129 | io.write('b', i, ' = ', sig(i), 15013+((i-30026)/2), ',\n') 130 | end 131 | end, 132 | 133 | function () -- $3$ 134 | for i=10,50009 do 135 | io.write('"a', i, '", ', sig(i), 5+((i-10)/2), ',\n') 136 | end 137 | end, 138 | } 139 | 140 | file = os.tmpname() 141 | io.output(file) 142 | for s in string.gmatch(prog, "$([^$]+)") do 143 | local n = tonumber(s) 144 | if not n then io.write(s) else F[n]() end 145 | end 146 | io.close() 147 | result = dofile(file) 148 | assert(os.remove(file)) 149 | print'OK' 150 | return result 151 | 152 | -------------------------------------------------------------------------------- /runbenchmarks.lua: -------------------------------------------------------------------------------- 1 | #!/bin/env lua 2 | 3 | -- Configuration: 4 | local n_runs = 3 5 | local supress_errors = true 6 | 7 | local binaries = { 8 | { 'lua-5.3.3', 'lua' }, 9 | { 'luajit-2.0.3', 'luajit' }, 10 | { 'fastlua', 'src/lua' }, 11 | } 12 | 13 | local tests_root = 'benchmarks/' 14 | local tests = { 15 | --[[ 16 | { 'ack', 'ack.lua' }, 17 | --]] 18 | ---[[ 19 | { 'ack', 'ack.lua 3 10' }, 20 | { 'fixpoint-fact', 'fixpoint-fact.lua 3000' }, 21 | { 'heapsort', 'heapsort.lua 10 250000' }, 22 | { 'mandelbrot', 'mandel.lua' }, 23 | { 'juliaset', 'qt.lua' }, 24 | { 'queen', 'queen.lua 12' }, 25 | { 'sieve', 'sieve.lua 5000' }, -- Sieve of Eratosthenes 26 | ---[[ 27 | -- benchmarksgame: 28 | { 'binary', 'binary-trees.lua 17' }, 29 | { 'n-body', 'n-body.lua 5000000' }, 30 | { 'fannkuch', 'fannkuch-redux.lua 10' }, 31 | { 'fasta', 'fasta.lua 2500000' }, 32 | { 'k-nucleotide', 'k-nucleotide.lua < fasta2500000.txt' }, 33 | { 'regex-dna', 'regex-dna.lua < fasta2500000.txt' }, 34 | { 'spectral-norm', 'spectral-norm.lua 2000' }, 35 | --]] 36 | } 37 | 38 | -- Runs the binary a single time and returns the time elapsed 39 | local function measure(binary, test) 40 | local cmd = binary .. ' ' .. test 41 | local time_cmd = '{ TIMEFORMAT=\'%3R\'; time ' .. cmd .. 42 | ' > /dev/null; } 2>&1' 43 | local handle = io.popen(time_cmd) 44 | local result = handle:read("*a") 45 | local time_elapsed = tonumber(result) 46 | handle:close() 47 | if not time_elapsed then 48 | error('Invalid output for "' .. cmd .. '":\n' .. result) 49 | end 50 | return time_elapsed 51 | end 52 | 53 | -- Runs the binary $n_runs and returns the fastest time 54 | local function benchmark(binary, test) 55 | local min = 999 56 | for _ = 1, n_runs do 57 | local time = measure(binary, test) 58 | min = math.min(min, time) 59 | end 60 | return min 61 | end 62 | 63 | -- Measures the time for each binary and test 64 | -- Returns a matrix with the result (test x binary) 65 | local function run_all() 66 | local results = {} 67 | for _, test in ipairs(tests) do 68 | io.write('running "' .. test[1] .. '"... ') 69 | local rline = {} 70 | for j, binary in ipairs(binaries) do 71 | local time = 0 72 | local ok, msg = pcall(function() 73 | local test_path = tests_root .. test[2] 74 | time = benchmark(binary[2], test_path) 75 | end) 76 | if not ok and not supress_errors then 77 | io.write('error:\n' .. msg .. '\n---\n') 78 | end 79 | table.insert(rline, time) 80 | end 81 | table.insert(results, rline) 82 | io.write('done\n') 83 | end 84 | return results 85 | end 86 | 87 | -- Normalize the results given the base_index 88 | local function normalize_results(results, base_index) 89 | for _, line in ipairs(results) do 90 | local base = line[base_index] 91 | for i = 1, #line do 92 | line[i] = line[i] / base 93 | end 94 | end 95 | end 96 | 97 | -- Creates and saves the gnuplot data file 98 | local function create_data_file(results, fname) 99 | local data = 'test\t' 100 | for _, binary in ipairs(binaries) do 101 | data = data .. binary[1] .. '\t' 102 | end 103 | data = data .. '\n' 104 | for i, test in ipairs(tests) do 105 | data = data .. test[1] .. '\t' 106 | for j, _ in ipairs(binaries) do 107 | data = data .. results[i][j] .. '\t' 108 | end 109 | data = data .. '\n' 110 | end 111 | local f = io.open(fname, 'w') 112 | f:write(data) 113 | f:close() 114 | end 115 | 116 | -- Generates the output image with gnuplot 117 | local function generate_image(results, suffix) 118 | suffix = suffix or '' 119 | local basename = 'benchmark_out' .. suffix 120 | local data_fname = basename .. '.txt' 121 | local image_fname = basename .. '.png' 122 | create_data_file(results, data_fname) 123 | os.execute('gnuplot -e "datafile=\'' .. data_fname .. '\'" ' .. 124 | '-e "outfile=\'' .. image_fname .. '\'" ' .. 125 | 'benchmarks/plot.gpi') 126 | end 127 | 128 | local function setup() 129 | os.execute('luajit benchmarks/fasta.lua 2500000 > fasta2500000.txt') 130 | end 131 | 132 | local function teardown() 133 | os.execute('rm fasta2500000.txt') 134 | end 135 | 136 | local function main() 137 | setup() 138 | local results = run_all() 139 | teardown() 140 | generate_image(results) 141 | normalize_results(results, 1) 142 | generate_image(results, '_normalized') 143 | print('final done') 144 | end 145 | 146 | main() 147 | -------------------------------------------------------------------------------- /runtests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "FL tests" 4 | for f in fltests/*; do 5 | echo -n "testing $f... " 6 | lua $f &> luaresult.txt 7 | src/lua $f &> flresult.txt 8 | if ! cmp --silent luaresult.txt flresult.txt; then 9 | echo "failed" 10 | echo "diff:" 11 | diff -u luaresult.txt flresult.txt 12 | rm -f luaresult.txt flresult.txt 13 | exit 1 14 | fi 15 | echo "done" 16 | done 17 | rm -f luaresult.txt flresult.txt 18 | 19 | # lua tests: 20 | # TODO fix 21 | # cd tests 22 | # ../src/lua -e"_U=true" all.lua 23 | # cd - 24 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for building Lua 2 | # See ../doc/readme.html for installation and customization instructions. 3 | 4 | # == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= 5 | 6 | # Your platform. See PLATS for possible values. 7 | PLAT= linux 8 | 9 | WARNINGS= \ 10 | -Wall \ 11 | -Wextra \ 12 | -Werror \ 13 | -Wundef \ 14 | -Wshadow \ 15 | -Wcast-align \ 16 | -Wstrict-prototypes \ 17 | -Wmissing-prototypes \ 18 | -pedantic 19 | 20 | DEPDIR= .d 21 | $(shell mkdir -p $(DEPDIR) >/dev/null) 22 | DEPFLAGS= -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td 23 | SRCS=$(wildcard %.o,%.c,$(BASE_O)) 24 | 25 | CC= gcc -std=c99 26 | CFLAGS= -g -O0 $(WARNINGS) -DLUA_COMPAT_5_2 $(SYSCFLAGS) $(MYCFLAGS) 27 | LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) 28 | LIBS= -lm $(SYSLIBS) $(MYLIBS) 29 | 30 | LD= g++ 31 | AR= ar rcu 32 | RANLIB= ranlib 33 | RM= rm -f 34 | 35 | SYSCFLAGS= 36 | SYSLDFLAGS= 37 | SYSLIBS= 38 | 39 | MYCFLAGS= -DFL_ENABLE -DFL_LOGGER -I`llvm-config --includedir` 40 | MYLDFLAGS= `llvm-config --ldflags` 41 | MYLIBS= `llvm-config --libs --system-libs` 42 | MYOBJS= \ 43 | fl_asm_llvm.o \ 44 | fl_defs.o \ 45 | fl_instr.o \ 46 | fl_ir.o \ 47 | fl_jitc.o \ 48 | fl_lib.o \ 49 | fl_logger.o \ 50 | fl_rec.o \ 51 | fl_trace.o \ 52 | fl_vm.o 53 | 54 | # == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= 55 | 56 | PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris 57 | 58 | LUA_A= liblua.a 59 | CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ 60 | lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \ 61 | ltm.o lundump.o lvm.o lzio.o 62 | LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \ 63 | lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o 64 | BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) 65 | 66 | LUA_T= lua 67 | LUA_O= lua.o 68 | 69 | LUAC_T= luac 70 | LUAC_O= luac.o 71 | 72 | ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O) 73 | ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) 74 | ALL_A= $(LUA_A) 75 | 76 | # Targets start here. 77 | default: $(PLAT) 78 | 79 | all: $(ALL_T) 80 | 81 | o: $(ALL_O) 82 | 83 | a: $(ALL_A) 84 | 85 | %.o: %.c 86 | %.o: %.c $(DEPDIR)/%.d 87 | $(CC) $(DEPFLAGS) $(CFLAGS) $< -c 88 | mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d 89 | 90 | $(LUA_A): $(BASE_O) 91 | $(AR) $@ $(BASE_O) 92 | $(RANLIB) $@ 93 | 94 | $(LUA_T): $(LUA_O) $(LUA_A) 95 | $(LD) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) 96 | 97 | $(LUAC_T): $(LUAC_O) $(LUA_A) 98 | $(LD) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) 99 | 100 | clean: 101 | $(RM) $(ALL_T) $(ALL_O) 102 | 103 | depend: 104 | @$(CC) $(DEPFLAGS) $(CFLAGS) -MM *.c 105 | 106 | echo: 107 | @echo "PLAT= $(PLAT)" 108 | @echo "CC= $(CC)" 109 | @echo "CFLAGS= $(CFLAGS)" 110 | @echo "LDFLAGS= $(SYSLDFLAGS)" 111 | @echo "LIBS= $(LIBS)" 112 | @echo "AR= $(AR)" 113 | @echo "RANLIB= $(RANLIB)" 114 | @echo "RM= $(RM)" 115 | 116 | # Convenience targets for popular platforms 117 | ALL= all 118 | 119 | none: 120 | @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" 121 | @echo " $(PLATS)" 122 | 123 | aix: 124 | $(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall" 125 | 126 | bsd: 127 | $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E" 128 | 129 | c89: 130 | $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89" 131 | @echo '' 132 | @echo '*** C89 does not guarantee 64-bit integers for Lua.' 133 | @echo '' 134 | 135 | 136 | freebsd: 137 | $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -lreadline" 138 | 139 | generic: $(ALL) 140 | 141 | linux: 142 | $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline" 143 | 144 | macosx: 145 | $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc 146 | 147 | mingw: 148 | $(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \ 149 | "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ 150 | "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe 151 | $(MAKE) "LUAC_T=luac.exe" luac.exe 152 | 153 | posix: 154 | $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" 155 | 156 | solaris: 157 | $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl" 158 | 159 | # list targets that do not create files (but not all makes understand .PHONY) 160 | .PHONY: all $(PLATS) default o a clean depend echo none 161 | 162 | # automatic dependencies 163 | $(DEPDIR)/%.d: ; 164 | .PRECIOUS: $(DEPDIR)/%.d 165 | 166 | include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS)))) 167 | 168 | -------------------------------------------------------------------------------- /src/fl_asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Compile a ir function into machine code. 27 | */ 28 | 29 | #ifndef fl_asm_h 30 | #define fl_asm_h 31 | 32 | #include "fl_defs.h" 33 | 34 | struct IRFunction; 35 | struct lua_State; 36 | struct lua_TValue; 37 | struct Proto; 38 | 39 | /* Jitted function prototype. */ 40 | typedef int (*AsmFunction)(struct lua_State *L, struct lua_TValue *base); 41 | 42 | /* Jitted function return codes */ 43 | enum AsmReturnCode { 44 | FL_SUCCESS, 45 | FL_EARLY_EXIT, 46 | FL_SIDE_EXIT 47 | }; 48 | 49 | /* Opaque data that should be saved in the Lua proto. */ 50 | typedef struct AsmInstrData AsmInstrData; 51 | 52 | /* Obtain the function given the instruction. */ 53 | AsmFunction flasm_getfunction(struct Proto *p, Instruction *i); 54 | 55 | /* Compile a function and add it to the proto. */ 56 | void flasm_compile(struct lua_State *L, struct Proto *p, Instruction *i, 57 | struct IRFunction *F); 58 | 59 | /* Delete a function and change the opcode to the default one. */ 60 | void flasm_destroy(struct lua_State *L, struct Proto *p, Instruction *i); 61 | 62 | /* Destroy all asm functions in the proto. */ 63 | void flasm_closeproto(struct lua_State *L, struct Proto *p); 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /src/fl_containers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef fl_containers 26 | #define fl_containers 27 | 28 | #include "lmem.h" 29 | 30 | #include "fl_logger.h" 31 | 32 | #define TsccAllocator struct lua_State * 33 | #define tscc_realloc luaM_realloc_ 34 | #define tscc_assert fll_assert 35 | 36 | #include "containers.h" 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /src/fl_defs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #include "lprefix.h" 26 | #include "lmem.h" 27 | #include "lobject.h" 28 | #include "lstate.h" 29 | 30 | #include "fl_asm.h" 31 | #include "fl_defs.h" 32 | #include "fl_instr.h" 33 | 34 | void fl_initstate(struct lua_State *L) { 35 | L->fl.trace = NULL; 36 | } 37 | 38 | void fl_closestate(struct lua_State *L) { 39 | (void)L; 40 | } 41 | 42 | void fl_initproto(struct Proto *p) { 43 | p->fl.initialized = 0; 44 | } 45 | 46 | void fl_closeproto(struct lua_State *L, struct Proto *p) { 47 | if (!p->fl.initialized) return; 48 | flasm_closeproto(L, p); 49 | fliv_destroy(&p->fl.instr); 50 | } 51 | 52 | void fl_loadproto(struct lua_State *L, struct Proto *p) { 53 | p->fl.initialized = 1; 54 | fliv_create(&p->fl.instr, L); 55 | fli_foreach(p, i, fli_toprof(p, i)); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/fl_defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * FastLua global definitions. 27 | */ 28 | 29 | #ifndef fl_defs_h 30 | #define fl_defs_h 31 | 32 | #include "fl_instr.h" 33 | 34 | /* Foward declarations */ 35 | struct lua_State; 36 | struct Proto; 37 | struct AsmInstrData; 38 | struct TraceRecording; 39 | 40 | /* Numbers of opcode executions required to record a trace. */ 41 | #ifndef FL_JIT_THRESHOLD 42 | #define FL_JIT_THRESHOLD 50 43 | #endif 44 | 45 | /* Global data that should be stored in lua_State. */ 46 | struct FLState { 47 | struct TraceRecording *trace; /* trace beeing recorded */ 48 | }; 49 | 50 | /* Data that should be stored in lua Proto. */ 51 | struct FLProto { 52 | unsigned int initialized : 1; 53 | FLInstrExtVector instr; 54 | }; 55 | 56 | /* Init/destroy FastLua state. */ 57 | void fl_initstate(struct lua_State *L); 58 | void fl_closestate(struct lua_State *L); 59 | 60 | /* Init/destroy FastLua proto. */ 61 | void fl_initproto(struct Proto *p); 62 | void fl_closeproto(struct lua_State *L, struct Proto *p); 63 | 64 | /* Load the jit information in the proto after other fields. */ 65 | void fl_loadproto(struct lua_State *L, struct Proto *p); 66 | 67 | #endif 68 | 69 | -------------------------------------------------------------------------------- /src/fl_instr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #include "lprefix.h" 26 | #include "lmem.h" 27 | #include "lobject.h" 28 | #include "lopcodes.h" 29 | 30 | #include "fl_instr.h" 31 | #include "fl_logger.h" 32 | 33 | #define flivec(p) (&p->fl.instr) 34 | 35 | struct FLInstrExt *fli_getext(struct Proto *p, Instruction *i) { 36 | fll_assert(fli_isfl(i), "invalid opcode"); 37 | return fliv_getref(flivec(p), fli_getextindex(i)); 38 | } 39 | 40 | void fli_reset(struct Proto *p, Instruction *i) { 41 | size_t extidx, removed; 42 | fll_assert(fli_isfl(i), "invalid opcode"); 43 | removed = fli_getextindex(i); 44 | *i = fli_getext(p, i)->original; 45 | fliv_erase(flivec(p), removed); 46 | for (extidx = removed; extidx < fliv_size(flivec(p)); ++extidx) { 47 | struct FLInstrExt *ext = fliv_getref(flivec(p), extidx); 48 | fli_setextindex(ext->address, extidx); 49 | } 50 | } 51 | 52 | /* Convert a instruction to a fl instruction */ 53 | static void convertinstr(struct Proto *p, Instruction *i, enum FLOpcode flop) { 54 | size_t extidx = fliv_size(flivec(p)); 55 | struct FLInstrExt ext; 56 | memset(&ext, 0, sizeof(struct FLInstrExt)); 57 | ext.original = *i; 58 | ext.address = i; 59 | fliv_push(flivec(p), ext); 60 | SET_OPCODE(*i, OP_FLVM); 61 | fli_setflop(i, flop); 62 | fli_setextindex(i, extidx); 63 | } 64 | 65 | void fli_toprof(struct Proto *p, Instruction *i) { 66 | switch (GET_OPCODE(*i)) { 67 | case OP_FORPREP: convertinstr(p, i, FLOP_FORPREP_PROF); break; 68 | default: break; 69 | } 70 | } 71 | 72 | void fli_tojit(struct Proto *p, Instruction *i) { 73 | switch (GET_OPCODE(*i)) { 74 | case OP_FORLOOP: convertinstr(p, i, FLOP_FORLOOP_EXEC); break; 75 | default: break; 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /src/fl_instr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Some Lua instructions are replaced by FL instructions (eg. for profiling and 27 | * execution of jited code). 28 | * The original opcode is replaced by the OP_FLVM opcode and a new FL opcode is 29 | * stored in the A argument of the original instruction. 30 | * Aditional information about the instruction is stored in the FLInstrExt 31 | * struct. 32 | * The extension vector only contains data about the converted instructions. 33 | * Finaly, the B argument is used to store the index of the instruction's 34 | * extension. 35 | */ 36 | 37 | #ifndef fl_instr_h 38 | #define fl_instr_h 39 | 40 | #include "llimits.h" 41 | 42 | #include "fl_containers.h" 43 | 44 | struct Proto; 45 | 46 | /* FL opcodes. These opcodes are executed in the fl_vm. */ 47 | enum FLOpcode { 48 | FLOP_FORPREP_PROF, 49 | FLOP_FORLOOP_EXEC 50 | }; 51 | 52 | /* Extra information about a FL instruction. */ 53 | struct FLInstrExt { 54 | Instruction original; /* original instruction */ 55 | Instruction *address; /* original instruction address */ 56 | union { 57 | int count; /* number of times executed */ 58 | struct AsmInstrData *asmdata; /* compiled function */ 59 | } u; 60 | }; 61 | 62 | /* struct FLInstrExt container. */ 63 | TSCC_DECL_VECTOR(FLInstrExtVector, fliv_, struct FLInstrExt) 64 | 65 | /* Obtain the instruction index given the address. */ 66 | #define fli_instrindex(p, addr) ((addr) - (p)->code) 67 | 68 | /* Obtain a instruction given the proto and the index. */ 69 | #define fli_getinstr(p, idx) (p->code + idx) 70 | 71 | /* Obtain the current instruction. */ 72 | #define fli_currentinstr(ci, p) (Instruction *)(ci->u.l.savedpc - 1) 73 | 74 | /* Foreach instruction in the proto. */ 75 | #define fli_foreach(p, i, cmd) \ 76 | do { \ 77 | Instruction *i = p->code; \ 78 | Instruction *last##i = i + p->sizecode; \ 79 | for (; i != last##i; ++i) { \ 80 | cmd; \ 81 | } \ 82 | } while (0) 83 | 84 | /* Manipulate the fl fields in the Lua instruction. */ 85 | #define fli_getflop(i) (GETARG_A(*i)) 86 | #define fli_setflop(i, op) (SETARG_A(*i, op)) 87 | #define fli_getextindex(i) (GETARG_B(*i)) 88 | #define fli_setextindex(i, idx) (SETARG_B(*i, idx)) 89 | #define fli_isfl(i) (GET_OPCODE(*i) == OP_FLVM) 90 | #define fli_isexec(i) \ 91 | (fli_isfl(i) && fli_getflop(i) >= FLOP_FORLOOP_EXEC) 92 | 93 | /* Obtain the instruction's extension. */ 94 | struct FLInstrExt *fli_getext(struct Proto *p, Instruction *i); 95 | 96 | /* Convert an instruction back to the original one. */ 97 | void fli_reset(struct Proto *p, Instruction *i); 98 | 99 | /* Convert an instruction to the profiling one. */ 100 | void fli_toprof(struct Proto *p, Instruction *i); 101 | 102 | /* Convert an instruction to the jit one. */ 103 | void fli_tojit(struct Proto *p, Instruction *i); 104 | 105 | #endif 106 | 107 | -------------------------------------------------------------------------------- /src/fl_jitc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * This module compiles the recorded trace into FLIR and then into machine code. 27 | */ 28 | 29 | #ifndef fl_jit_h 30 | #define fl_jit_h 31 | 32 | #include "llimits.h" 33 | 34 | #include "fl_defs.h" 35 | #include "fl_trace.h" 36 | 37 | /* Compiles the trace recording. */ 38 | void fljit_compile(TraceRecording *tr); 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /src/fl_lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include "lprefix.h" 28 | #include "lua.h" 29 | #include "lauxlib.h" 30 | #include "lualib.h" 31 | 32 | #include "fl_logger.h" 33 | 34 | /* 35 | * Change the logger level. 36 | * Parameters: 37 | * level : string Possible values: 'none', 'error', 'all' 38 | */ 39 | static int logger(lua_State *L) { 40 | const char *level = luaL_checkstring(L, 1); 41 | if (!strcmp(level, "none")) 42 | fll_enable = FL_LOGGER_NONE; 43 | else if (!strcmp(level, "error")) 44 | fll_enable = FL_LOGGER_ERROR; 45 | else if (!strcmp(level, "all")) 46 | fll_enable = FL_LOGGER_ALL; 47 | else 48 | luaL_error(L, "bad argument #1 to 'logger' " 49 | "('none', 'error' or 'all' expected)"); 50 | return 0; 51 | } 52 | 53 | static const luaL_Reg jit_funcs[] = { 54 | {"logger", logger}, 55 | {NULL, NULL} 56 | }; 57 | 58 | LUAMOD_API int luaopen_jit(lua_State *L) { 59 | luaL_newlib(L, jit_funcs); 60 | return 1; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /src/fl_logger.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #ifdef FL_LOGGER 28 | 29 | #include "lprefix.h" 30 | #include "lobject.h" 31 | #include "lstate.h" 32 | 33 | #include "fl_logger.h" 34 | 35 | int fll_enable = FL_LOGGER_ERROR; 36 | 37 | #define fllog_impl(format) \ 38 | do { \ 39 | if (fll_enable < FL_LOGGER_ALL) return; \ 40 | va_list args; \ 41 | va_start(args, format); \ 42 | vfprintf(stderr, format, args); \ 43 | va_end(args); \ 44 | } while (0) 45 | 46 | void fllog(const char *format, ...) { 47 | fllog_impl(format); 48 | } 49 | 50 | void fllogln(const char *format, ...) { 51 | fllog_impl(format); 52 | fputs("\n", stderr); 53 | } 54 | 55 | void fll_write(const void *buffer, size_t nbytes) { 56 | if (fll_enable < FL_LOGGER_ALL) return; 57 | fwrite(buffer, sizeof(char), nbytes, stderr); 58 | } 59 | 60 | void fll_error_(const char *file, int line, const char *message) { 61 | if (fll_enable < FL_LOGGER_ERROR) return; 62 | fprintf(stderr, "error at line %d in %s: %s\n", line, file, message); 63 | } 64 | 65 | void fll_dumpstack(lua_State *L) { 66 | StkId pos; 67 | for (pos = L->ci->u.l.base; pos != L->top; ++pos) { 68 | size_t len; 69 | const char *s; 70 | TValue val = *pos; 71 | luaO_tostring(L, &val); 72 | fllog("%p: ", (void*)pos); 73 | len = vslen(&val); 74 | s = svalue(&val); 75 | fll_write(s, len); 76 | fllog("\n"); 77 | } 78 | } 79 | 80 | #endif 81 | 82 | -------------------------------------------------------------------------------- /src/fl_logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * To use this module, the flag FL_LOGGER must be defined in the Makefile. 27 | */ 28 | 29 | #ifndef fl_logger_h 30 | #define fl_logger_h 31 | 32 | #ifdef FL_LOGGER 33 | 34 | struct lua_State; 35 | 36 | enum FLLoggerLevel { 37 | FL_LOGGER_NONE, 38 | FL_LOGGER_ERROR, 39 | FL_LOGGER_ALL 40 | }; 41 | 42 | /* Enable/disable de logger. Since this is a debug module, global variables 43 | * are used and this module isn't thread safe. */ 44 | extern int fll_enable; 45 | 46 | /* Print the message in stderr. */ 47 | void fllog(const char *format, ...); 48 | 49 | /* Print the message in stderr and print a newline. */ 50 | void fllogln(const char *format, ...); 51 | 52 | /* Print the buffer in stderr (usefull for Lua strings). */ 53 | void fll_write(const void *buffer, size_t nbytes); 54 | 55 | /* Print the stack of the current function. */ 56 | void fll_dumpstack(struct lua_State *L); 57 | 58 | /* Print an error message */ 59 | void fll_error_(const char *file, int line, const char *message); 60 | #define fll_error(message) fll_error_(__FILE__, __LINE__, message) 61 | 62 | /* Print the message if the condition fail. */ 63 | #define fll_assert(condition, message) \ 64 | do { \ 65 | if (!(condition)) \ 66 | fll_error(message); \ 67 | } while (0) 68 | 69 | /* 70 | * Define empty function when the logger is disabled: 71 | */ 72 | #else 73 | static __inline void fllog(const char *format, ...) { (void)format; } 74 | #define fll_enable(enable) (void)0 75 | #define fll_write(buffer, nbytes) (void)0 76 | #define fll_dumpstack() (void)0 77 | static __inline void fllog(const char *format, ...) { (void)format; } 78 | #define fll_error(message) (void)0 79 | #define fll_assert(condition, msg) (void)0 80 | #endif 81 | 82 | #endif 83 | 84 | -------------------------------------------------------------------------------- /src/fl_rec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * This module records the executed opcodes and create the trace. 27 | * After the trace is recorded, if it is valid, the fl_jit module is called and 28 | * the trace will be compiled into machine code. 29 | */ 30 | 31 | #ifndef fl_rec_h 32 | #define fl_rec_h 33 | 34 | #include "llimits.h" 35 | 36 | /* Foward declarations */ 37 | struct lua_State; 38 | struct CallInfo; 39 | 40 | /* Obtains the recording enabled/disabled flag. */ 41 | #define flrec_isrecording(L) (L->fl.trace != NULL) 42 | 43 | /* Start the recording. */ 44 | void flrec_start(struct lua_State *L); 45 | 46 | /* Record the current opcode and write it into the current trace. */ 47 | #define flrec_record(L, ci) \ 48 | do { if (flrec_isrecording(L)) flrec_record_(L, ci); } while (0) 49 | 50 | void flrec_record_(struct lua_State *L, struct CallInfo *ci); 51 | 52 | #endif 53 | 54 | -------------------------------------------------------------------------------- /src/fl_trace.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #include "lprefix.h" 26 | #include "lmem.h" 27 | #include "lstate.h" 28 | 29 | #include "fl_trace.h" 30 | 31 | TraceRecording *flt_createtrace(struct lua_State *L) { 32 | TraceRecording *tr = luaM_new(L, TraceRecording); 33 | tr->L = L; 34 | tr->p = NULL; 35 | tr->start = NULL; 36 | flt_rtvec_create(&tr->instrs, L); 37 | tr->regs = NULL; 38 | tr->completeloop = 0; 39 | return tr; 40 | } 41 | 42 | void flt_destroytrace(TraceRecording *tr) { 43 | if (tr->p) luaM_freearray(tr->L, tr->regs, tr->p->maxstacksize); 44 | flt_rtvec_destroy(&tr->instrs); 45 | luaM_free(tr->L, tr); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/fl_trace.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * The structure that contains the recored trace data. 27 | */ 28 | 29 | #ifndef fl_trace_h 30 | #define fl_trace_h 31 | 32 | #include "fl_containers.h" 33 | 34 | /* Foward declarations */ 35 | struct lua_State; 36 | 37 | /* Runtime information for each instruction */ 38 | struct TraceInstr { 39 | const Instruction *instr; /* instruction */ 40 | union { /* specific fields for each opcode */ 41 | struct { lu_byte steplt0; } forloop; 42 | } u; 43 | }; 44 | 45 | /* TraceInstr container */ 46 | TSCC_DECL_VECTOR(TraceInstrVector, flt_rtvec_, struct TraceInstr) 47 | #define flt_rtvec_foreach(vec, val, cmd) \ 48 | TSCC_VECTOR_FOREACH(flt_rtvec_, vec, struct TraceInstr, val, cmd) 49 | 50 | /* Runtime information about the registers */ 51 | struct TraceRegister { 52 | lu_byte tag; /* register's tag */ 53 | lu_byte loadedtag; /* tag when loaded from the stack */ 54 | lu_byte tagset : 1; /* the tag was set */ 55 | lu_byte loaded : 1; /* should be loaded from the stack */ 56 | lu_byte set : 1; /* the register changed */ 57 | }; 58 | 59 | /* TraceRecording */ 60 | typedef struct TraceRecording { 61 | struct lua_State *L; /* Lua state */ 62 | struct Proto *p; /* Lua function */ 63 | const Instruction *start; /* first instruction of the trace */ 64 | TraceInstrVector instrs; /* runtime info for each instruction */ 65 | struct TraceRegister *regs; /* runtime info for each register */ 66 | lu_byte completeloop; /* tell if the trace is a full loop */ 67 | } TraceRecording; 68 | 69 | /* Creates/destroys a trace recording. */ 70 | TraceRecording *flt_createtrace(struct lua_State *L); 71 | void flt_destroytrace(TraceRecording *tr); 72 | 73 | #endif 74 | 75 | -------------------------------------------------------------------------------- /src/fl_vm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #include "lprefix.h" 26 | #include "lobject.h" 27 | #include "lstate.h" 28 | #include "lvm.h" 29 | 30 | #include "fl_logger.h" 31 | #include "fl_rec.h" 32 | #include "fl_vm.h" 33 | 34 | void flvm_profile(struct lua_State *L, CallInfo *ci, int loopcount) { 35 | fll_assert(loopcount > 0, "flprof_profile: loopcount <= 0"); 36 | if (!flrec_isrecording(L)) { 37 | Proto *p = getproto(ci->func); 38 | Instruction *i = fli_currentinstr(ci, p); 39 | int *count = &fli_getext(p, i)->u.count; 40 | fll_assert(*count < FL_JIT_THRESHOLD, "threshold already reached"); 41 | *count += loopcount; 42 | if (*count >= FL_JIT_THRESHOLD) { 43 | fli_reset(p, i); 44 | flrec_start(L); 45 | } 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/fl_vm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Gabriel de Quadros Ligneul 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * VM for FL instructions. 27 | */ 28 | 29 | #ifndef fl_vm_h 30 | #define fl_vm_h 31 | 32 | #include "fl_instr.h" 33 | 34 | struct lua_State; 35 | struct lua_TValue; 36 | 37 | /* Counts the number of times that a loop is executed. When the inner part of 38 | * the loop is executed enough times (JIT_THRESHOLD), the fl_rec module is 39 | * called and the trace is recorded. */ 40 | void flvm_profile(struct lua_State *L, CallInfo *ci, int loopcount); 41 | 42 | #define flvm_execute() { \ 43 | Proto *p = cl->p; \ 44 | Instruction *currinstr = fli_currentinstr(ci, p); \ 45 | i = fli_getext(p, currinstr)->original; \ 46 | ra = RA(i); \ 47 | switch (fli_getflop(currinstr)) { \ 48 | case FLOP_FORPREP_PROF: { \ 49 | TValue *init = ra; \ 50 | TValue *plimit = ra + 1; \ 51 | TValue *pstep = ra + 2; \ 52 | lua_Integer ilimit; \ 53 | int stopnow; \ 54 | lua_Integer loopcount = 0; \ 55 | if (ttisinteger(init) && ttisinteger(pstep) && \ 56 | forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) { \ 57 | /* all values are integer */ \ 58 | lua_Integer initv = (stopnow ? 0 : ivalue(init)); \ 59 | setivalue(plimit, ilimit); \ 60 | setivalue(init, intop(-, initv, ivalue(pstep))); \ 61 | if (ivalue(pstep) == 0) \ 62 | loopcount = FL_JIT_THRESHOLD; \ 63 | else \ 64 | loopcount = intop(/, intop(-, ilimit, ivalue(init)), ivalue(pstep)); \ 65 | } \ 66 | else { /* try making all values floats */ \ 67 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; \ 68 | if (!tonumber(plimit, &nlimit)) \ 69 | luaG_runerror(L, "'for' limit must be a number"); \ 70 | setfltvalue(plimit, nlimit); \ 71 | if (!tonumber(pstep, &nstep)) \ 72 | luaG_runerror(L, "'for' step must be a number"); \ 73 | setfltvalue(pstep, nstep); \ 74 | if (!tonumber(init, &ninit)) \ 75 | luaG_runerror(L, "'for' initial value must be a number"); \ 76 | setfltvalue(init, luai_numsub(L, ninit, nstep)); \ 77 | if (nstep == 0.0) \ 78 | loopcount = FL_JIT_THRESHOLD; \ 79 | else \ 80 | loopcount = cast_int((nlimit - fltvalue(init)) / nstep); \ 81 | } \ 82 | if (loopcount > 0) { \ 83 | short lc = (loopcount > FL_JIT_THRESHOLD ? \ 84 | FL_JIT_THRESHOLD : loopcount); \ 85 | flvm_profile(L, ci, lc); \ 86 | } \ 87 | ci->u.l.savedpc += GETARG_sBx(i); \ 88 | break; \ 89 | } \ 90 | case FLOP_FORLOOP_EXEC: { \ 91 | AsmFunction f = flasm_getfunction(p, currinstr); \ 92 | switch (f(L, base)) { \ 93 | case FL_SUCCESS: \ 94 | break; \ 95 | case FL_EARLY_EXIT: \ 96 | flasm_destroy(L, p, currinstr); \ 97 | goto l_forloop; \ 98 | break; \ 99 | case FL_SIDE_EXIT: \ 100 | flasm_destroy(L, p, currinstr); \ 101 | lua_assert(0); \ 102 | break; \ 103 | default: \ 104 | lua_assert(0); \ 105 | break; \ 106 | } \ 107 | break; \ 108 | } \ 109 | default: { \ 110 | fll_error("unhandled flop"); \ 111 | break; \ 112 | } \ 113 | } \ 114 | } 115 | 116 | 117 | #endif 118 | 119 | -------------------------------------------------------------------------------- /src/lapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp $ 3 | ** Auxiliary functions from Lua API 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lapi_h 8 | #define lapi_h 9 | 10 | 11 | #include "llimits.h" 12 | #include "lstate.h" 13 | 14 | #define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ 15 | "stack overflow");} 16 | 17 | #define adjustresults(L,nres) \ 18 | { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } 19 | 20 | #define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ 21 | "not enough elements in the stack") 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/lbitlib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lbitlib.c,v 1.30 2015/11/11 19:08:09 roberto Exp $ 3 | ** Standard library for bitwise operations 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lbitlib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include "lua.h" 14 | 15 | #include "lauxlib.h" 16 | #include "lualib.h" 17 | 18 | 19 | #if defined(LUA_COMPAT_BITLIB) /* { */ 20 | 21 | 22 | #define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) 23 | #define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i)) 24 | 25 | 26 | /* number of bits to consider in a number */ 27 | #if !defined(LUA_NBITS) 28 | #define LUA_NBITS 32 29 | #endif 30 | 31 | 32 | /* 33 | ** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must 34 | ** be made in two parts to avoid problems when LUA_NBITS is equal to the 35 | ** number of bits in a lua_Unsigned.) 36 | */ 37 | #define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) 38 | 39 | 40 | /* macro to trim extra bits */ 41 | #define trim(x) ((x) & ALLONES) 42 | 43 | 44 | /* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ 45 | #define mask(n) (~((ALLONES << 1) << ((n) - 1))) 46 | 47 | 48 | 49 | static lua_Unsigned andaux (lua_State *L) { 50 | int i, n = lua_gettop(L); 51 | lua_Unsigned r = ~(lua_Unsigned)0; 52 | for (i = 1; i <= n; i++) 53 | r &= checkunsigned(L, i); 54 | return trim(r); 55 | } 56 | 57 | 58 | static int b_and (lua_State *L) { 59 | lua_Unsigned r = andaux(L); 60 | pushunsigned(L, r); 61 | return 1; 62 | } 63 | 64 | 65 | static int b_test (lua_State *L) { 66 | lua_Unsigned r = andaux(L); 67 | lua_pushboolean(L, r != 0); 68 | return 1; 69 | } 70 | 71 | 72 | static int b_or (lua_State *L) { 73 | int i, n = lua_gettop(L); 74 | lua_Unsigned r = 0; 75 | for (i = 1; i <= n; i++) 76 | r |= checkunsigned(L, i); 77 | pushunsigned(L, trim(r)); 78 | return 1; 79 | } 80 | 81 | 82 | static int b_xor (lua_State *L) { 83 | int i, n = lua_gettop(L); 84 | lua_Unsigned r = 0; 85 | for (i = 1; i <= n; i++) 86 | r ^= checkunsigned(L, i); 87 | pushunsigned(L, trim(r)); 88 | return 1; 89 | } 90 | 91 | 92 | static int b_not (lua_State *L) { 93 | lua_Unsigned r = ~checkunsigned(L, 1); 94 | pushunsigned(L, trim(r)); 95 | return 1; 96 | } 97 | 98 | 99 | static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) { 100 | if (i < 0) { /* shift right? */ 101 | i = -i; 102 | r = trim(r); 103 | if (i >= LUA_NBITS) r = 0; 104 | else r >>= i; 105 | } 106 | else { /* shift left */ 107 | if (i >= LUA_NBITS) r = 0; 108 | else r <<= i; 109 | r = trim(r); 110 | } 111 | pushunsigned(L, r); 112 | return 1; 113 | } 114 | 115 | 116 | static int b_lshift (lua_State *L) { 117 | return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2)); 118 | } 119 | 120 | 121 | static int b_rshift (lua_State *L) { 122 | return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2)); 123 | } 124 | 125 | 126 | static int b_arshift (lua_State *L) { 127 | lua_Unsigned r = checkunsigned(L, 1); 128 | lua_Integer i = luaL_checkinteger(L, 2); 129 | if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1)))) 130 | return b_shift(L, r, -i); 131 | else { /* arithmetic shift for 'negative' number */ 132 | if (i >= LUA_NBITS) r = ALLONES; 133 | else 134 | r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */ 135 | pushunsigned(L, r); 136 | return 1; 137 | } 138 | } 139 | 140 | 141 | static int b_rot (lua_State *L, lua_Integer d) { 142 | lua_Unsigned r = checkunsigned(L, 1); 143 | int i = d & (LUA_NBITS - 1); /* i = d % NBITS */ 144 | r = trim(r); 145 | if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ 146 | r = (r << i) | (r >> (LUA_NBITS - i)); 147 | pushunsigned(L, trim(r)); 148 | return 1; 149 | } 150 | 151 | 152 | static int b_lrot (lua_State *L) { 153 | return b_rot(L, luaL_checkinteger(L, 2)); 154 | } 155 | 156 | 157 | static int b_rrot (lua_State *L) { 158 | return b_rot(L, -luaL_checkinteger(L, 2)); 159 | } 160 | 161 | 162 | /* 163 | ** get field and width arguments for field-manipulation functions, 164 | ** checking whether they are valid. 165 | ** ('luaL_error' called without 'return' to avoid later warnings about 166 | ** 'width' being used uninitialized.) 167 | */ 168 | static int fieldargs (lua_State *L, int farg, int *width) { 169 | lua_Integer f = luaL_checkinteger(L, farg); 170 | lua_Integer w = luaL_optinteger(L, farg + 1, 1); 171 | luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); 172 | luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); 173 | if (f + w > LUA_NBITS) 174 | luaL_error(L, "trying to access non-existent bits"); 175 | *width = (int)w; 176 | return (int)f; 177 | } 178 | 179 | 180 | static int b_extract (lua_State *L) { 181 | int w; 182 | lua_Unsigned r = trim(checkunsigned(L, 1)); 183 | int f = fieldargs(L, 2, &w); 184 | r = (r >> f) & mask(w); 185 | pushunsigned(L, r); 186 | return 1; 187 | } 188 | 189 | 190 | static int b_replace (lua_State *L) { 191 | int w; 192 | lua_Unsigned r = trim(checkunsigned(L, 1)); 193 | lua_Unsigned v = trim(checkunsigned(L, 2)); 194 | int f = fieldargs(L, 3, &w); 195 | lua_Unsigned m = mask(w); 196 | r = (r & ~(m << f)) | ((v & m) << f); 197 | pushunsigned(L, r); 198 | return 1; 199 | } 200 | 201 | 202 | static const luaL_Reg bitlib[] = { 203 | {"arshift", b_arshift}, 204 | {"band", b_and}, 205 | {"bnot", b_not}, 206 | {"bor", b_or}, 207 | {"bxor", b_xor}, 208 | {"btest", b_test}, 209 | {"extract", b_extract}, 210 | {"lrotate", b_lrot}, 211 | {"lshift", b_lshift}, 212 | {"replace", b_replace}, 213 | {"rrotate", b_rrot}, 214 | {"rshift", b_rshift}, 215 | {NULL, NULL} 216 | }; 217 | 218 | 219 | 220 | LUAMOD_API int luaopen_bit32 (lua_State *L) { 221 | luaL_newlib(L, bitlib); 222 | return 1; 223 | } 224 | 225 | 226 | #else /* }{ */ 227 | 228 | 229 | LUAMOD_API int luaopen_bit32 (lua_State *L) { 230 | return luaL_error(L, "library 'bit32' has been deprecated"); 231 | } 232 | 233 | #endif /* } */ 234 | -------------------------------------------------------------------------------- /src/lcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lcode.h,v 1.64 2016/01/05 16:22:37 roberto Exp $ 3 | ** Code generator for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lcode_h 8 | #define lcode_h 9 | 10 | #include "llex.h" 11 | #include "lobject.h" 12 | #include "lopcodes.h" 13 | #include "lparser.h" 14 | 15 | 16 | /* 17 | ** Marks the end of a patch list. It is an invalid value both as an absolute 18 | ** address, and as a list link (would link an element to itself). 19 | */ 20 | #define NO_JUMP (-1) 21 | 22 | 23 | /* 24 | ** grep "ORDER OPR" if you change these enums (ORDER OP) 25 | */ 26 | typedef enum BinOpr { 27 | OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, 28 | OPR_DIV, 29 | OPR_IDIV, 30 | OPR_BAND, OPR_BOR, OPR_BXOR, 31 | OPR_SHL, OPR_SHR, 32 | OPR_CONCAT, 33 | OPR_EQ, OPR_LT, OPR_LE, 34 | OPR_NE, OPR_GT, OPR_GE, 35 | OPR_AND, OPR_OR, 36 | OPR_NOBINOPR 37 | } BinOpr; 38 | 39 | 40 | typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; 41 | 42 | 43 | /* get (pointer to) instruction of given 'expdesc' */ 44 | #define getinstruction(fs,e) ((fs)->f->code[(e)->u.info]) 45 | 46 | #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) 47 | 48 | #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) 49 | 50 | #define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) 51 | 52 | LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); 53 | LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); 54 | LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k); 55 | LUAI_FUNC void luaK_fixline (FuncState *fs, int line); 56 | LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); 57 | LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); 58 | LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); 59 | LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); 60 | LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n); 61 | LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); 62 | LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); 63 | LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); 64 | LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); 65 | LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); 66 | LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); 67 | LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); 68 | LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); 69 | LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); 70 | LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); 71 | LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); 72 | LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); 73 | LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); 74 | LUAI_FUNC int luaK_jump (FuncState *fs); 75 | LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); 76 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); 77 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); 78 | LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); 79 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); 80 | LUAI_FUNC int luaK_getlabel (FuncState *fs); 81 | LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); 82 | LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); 83 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, 84 | expdesc *v2, int line); 85 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); 86 | 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/lcorolib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lcorolib.c,v 1.10 2016/04/11 19:19:55 roberto Exp $ 3 | ** Coroutine Library 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lcorolib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "lauxlib.h" 18 | #include "lualib.h" 19 | 20 | 21 | static lua_State *getco (lua_State *L) { 22 | lua_State *co = lua_tothread(L, 1); 23 | luaL_argcheck(L, co, 1, "thread expected"); 24 | return co; 25 | } 26 | 27 | 28 | static int auxresume (lua_State *L, lua_State *co, int narg) { 29 | int status; 30 | if (!lua_checkstack(co, narg)) { 31 | lua_pushliteral(L, "too many arguments to resume"); 32 | return -1; /* error flag */ 33 | } 34 | if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { 35 | lua_pushliteral(L, "cannot resume dead coroutine"); 36 | return -1; /* error flag */ 37 | } 38 | lua_xmove(L, co, narg); 39 | status = lua_resume(co, L, narg); 40 | if (status == LUA_OK || status == LUA_YIELD) { 41 | int nres = lua_gettop(co); 42 | if (!lua_checkstack(L, nres + 1)) { 43 | lua_pop(co, nres); /* remove results anyway */ 44 | lua_pushliteral(L, "too many results to resume"); 45 | return -1; /* error flag */ 46 | } 47 | lua_xmove(co, L, nres); /* move yielded values */ 48 | return nres; 49 | } 50 | else { 51 | lua_xmove(co, L, 1); /* move error message */ 52 | return -1; /* error flag */ 53 | } 54 | } 55 | 56 | 57 | static int luaB_coresume (lua_State *L) { 58 | lua_State *co = getco(L); 59 | int r; 60 | r = auxresume(L, co, lua_gettop(L) - 1); 61 | if (r < 0) { 62 | lua_pushboolean(L, 0); 63 | lua_insert(L, -2); 64 | return 2; /* return false + error message */ 65 | } 66 | else { 67 | lua_pushboolean(L, 1); 68 | lua_insert(L, -(r + 1)); 69 | return r + 1; /* return true + 'resume' returns */ 70 | } 71 | } 72 | 73 | 74 | static int luaB_auxwrap (lua_State *L) { 75 | lua_State *co = lua_tothread(L, lua_upvalueindex(1)); 76 | int r = auxresume(L, co, lua_gettop(L)); 77 | if (r < 0) { 78 | if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ 79 | luaL_where(L, 1); /* add extra info */ 80 | lua_insert(L, -2); 81 | lua_concat(L, 2); 82 | } 83 | return lua_error(L); /* propagate error */ 84 | } 85 | return r; 86 | } 87 | 88 | 89 | static int luaB_cocreate (lua_State *L) { 90 | lua_State *NL; 91 | luaL_checktype(L, 1, LUA_TFUNCTION); 92 | NL = lua_newthread(L); 93 | lua_pushvalue(L, 1); /* move function to top */ 94 | lua_xmove(L, NL, 1); /* move function from L to NL */ 95 | return 1; 96 | } 97 | 98 | 99 | static int luaB_cowrap (lua_State *L) { 100 | luaB_cocreate(L); 101 | lua_pushcclosure(L, luaB_auxwrap, 1); 102 | return 1; 103 | } 104 | 105 | 106 | static int luaB_yield (lua_State *L) { 107 | return lua_yield(L, lua_gettop(L)); 108 | } 109 | 110 | 111 | static int luaB_costatus (lua_State *L) { 112 | lua_State *co = getco(L); 113 | if (L == co) lua_pushliteral(L, "running"); 114 | else { 115 | switch (lua_status(co)) { 116 | case LUA_YIELD: 117 | lua_pushliteral(L, "suspended"); 118 | break; 119 | case LUA_OK: { 120 | lua_Debug ar; 121 | if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ 122 | lua_pushliteral(L, "normal"); /* it is running */ 123 | else if (lua_gettop(co) == 0) 124 | lua_pushliteral(L, "dead"); 125 | else 126 | lua_pushliteral(L, "suspended"); /* initial state */ 127 | break; 128 | } 129 | default: /* some error occurred */ 130 | lua_pushliteral(L, "dead"); 131 | break; 132 | } 133 | } 134 | return 1; 135 | } 136 | 137 | 138 | static int luaB_yieldable (lua_State *L) { 139 | lua_pushboolean(L, lua_isyieldable(L)); 140 | return 1; 141 | } 142 | 143 | 144 | static int luaB_corunning (lua_State *L) { 145 | int ismain = lua_pushthread(L); 146 | lua_pushboolean(L, ismain); 147 | return 2; 148 | } 149 | 150 | 151 | static const luaL_Reg co_funcs[] = { 152 | {"create", luaB_cocreate}, 153 | {"resume", luaB_coresume}, 154 | {"running", luaB_corunning}, 155 | {"status", luaB_costatus}, 156 | {"wrap", luaB_cowrap}, 157 | {"yield", luaB_yield}, 158 | {"isyieldable", luaB_yieldable}, 159 | {NULL, NULL} 160 | }; 161 | 162 | 163 | 164 | LUAMOD_API int luaopen_coroutine (lua_State *L) { 165 | luaL_newlib(L, co_funcs); 166 | return 1; 167 | } 168 | 169 | -------------------------------------------------------------------------------- /src/lctype.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lctype.c,v 1.12 2014/11/02 19:19:04 roberto Exp $ 3 | ** 'ctype' functions for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lctype_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include "lctype.h" 14 | 15 | #if !LUA_USE_CTYPE /* { */ 16 | 17 | #include 18 | 19 | LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { 20 | 0x00, /* EOZ */ 21 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ 22 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 23 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ 24 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 25 | 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ 26 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 27 | 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ 28 | 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 29 | 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ 30 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 31 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ 32 | 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, 33 | 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ 34 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 35 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ 36 | 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ 40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ 42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ 44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ 48 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | }; 54 | 55 | #endif /* } */ 56 | -------------------------------------------------------------------------------- /src/lctype.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $ 3 | ** 'ctype' functions for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lctype_h 8 | #define lctype_h 9 | 10 | #include "lua.h" 11 | 12 | 13 | /* 14 | ** WARNING: the functions defined here do not necessarily correspond 15 | ** to the similar functions in the standard C ctype.h. They are 16 | ** optimized for the specific needs of Lua 17 | */ 18 | 19 | #if !defined(LUA_USE_CTYPE) 20 | 21 | #if 'A' == 65 && '0' == 48 22 | /* ASCII case: can use its own tables; faster and fixed */ 23 | #define LUA_USE_CTYPE 0 24 | #else 25 | /* must use standard C ctype */ 26 | #define LUA_USE_CTYPE 1 27 | #endif 28 | 29 | #endif 30 | 31 | 32 | #if !LUA_USE_CTYPE /* { */ 33 | 34 | #include 35 | 36 | #include "llimits.h" 37 | 38 | 39 | #define ALPHABIT 0 40 | #define DIGITBIT 1 41 | #define PRINTBIT 2 42 | #define SPACEBIT 3 43 | #define XDIGITBIT 4 44 | 45 | 46 | #define MASK(B) (1 << (B)) 47 | 48 | 49 | /* 50 | ** add 1 to char to allow index -1 (EOZ) 51 | */ 52 | #define testprop(c,p) (luai_ctype_[(c)+1] & (p)) 53 | 54 | /* 55 | ** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' 56 | */ 57 | #define lislalpha(c) testprop(c, MASK(ALPHABIT)) 58 | #define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) 59 | #define lisdigit(c) testprop(c, MASK(DIGITBIT)) 60 | #define lisspace(c) testprop(c, MASK(SPACEBIT)) 61 | #define lisprint(c) testprop(c, MASK(PRINTBIT)) 62 | #define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) 63 | 64 | /* 65 | ** this 'ltolower' only works for alphabetic characters 66 | */ 67 | #define ltolower(c) ((c) | ('A' ^ 'a')) 68 | 69 | 70 | /* two more entries for 0 and -1 (EOZ) */ 71 | LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; 72 | 73 | 74 | #else /* }{ */ 75 | 76 | /* 77 | ** use standard C ctypes 78 | */ 79 | 80 | #include 81 | 82 | 83 | #define lislalpha(c) (isalpha(c) || (c) == '_') 84 | #define lislalnum(c) (isalnum(c) || (c) == '_') 85 | #define lisdigit(c) (isdigit(c)) 86 | #define lisspace(c) (isspace(c)) 87 | #define lisprint(c) (isprint(c)) 88 | #define lisxdigit(c) (isxdigit(c)) 89 | 90 | #define ltolower(c) (tolower(c)) 91 | 92 | #endif /* } */ 93 | 94 | #endif 95 | 96 | -------------------------------------------------------------------------------- /src/ldebug.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp $ 3 | ** Auxiliary functions from Debug Interface module 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ldebug_h 8 | #define ldebug_h 9 | 10 | 11 | #include "lstate.h" 12 | 13 | 14 | #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) 15 | 16 | #define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1) 17 | 18 | #define resethookcount(L) (L->hookcount = L->basehookcount) 19 | 20 | 21 | LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, 22 | const char *opname); 23 | LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, 24 | const TValue *p2); 25 | LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, 26 | const TValue *p2, 27 | const char *msg); 28 | LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, 29 | const TValue *p2); 30 | LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, 31 | const TValue *p2); 32 | LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); 33 | LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, 34 | TString *src, int line); 35 | LUAI_FUNC l_noret luaG_errormsg (lua_State *L); 36 | LUAI_FUNC void luaG_traceexec (lua_State *L); 37 | 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/ldo.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldo.h,v 2.29 2015/12/21 13:02:14 roberto Exp $ 3 | ** Stack and Call structure of Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ldo_h 8 | #define ldo_h 9 | 10 | 11 | #include "lobject.h" 12 | #include "lstate.h" 13 | #include "lzio.h" 14 | 15 | 16 | /* 17 | ** Macro to check stack size and grow stack if needed. Parameters 18 | ** 'pre'/'pos' allow the macro to preserve a pointer into the 19 | ** stack across reallocations, doing the work only when needed. 20 | ** 'condmovestack' is used in heavy tests to force a stack reallocation 21 | ** at every check. 22 | */ 23 | #define luaD_checkstackaux(L,n,pre,pos) \ 24 | if (L->stack_last - L->top <= (n)) \ 25 | { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); } 26 | 27 | /* In general, 'pre'/'pos' are empty (nothing to save) */ 28 | #define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) 29 | 30 | 31 | 32 | #define savestack(L,p) ((char *)(p) - (char *)L->stack) 33 | #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) 34 | 35 | 36 | /* type of protected functions, to be ran by 'runprotected' */ 37 | typedef void (*Pfunc) (lua_State *L, void *ud); 38 | 39 | LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, 40 | const char *mode); 41 | LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); 42 | LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); 43 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); 44 | LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); 45 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, 46 | ptrdiff_t oldtop, ptrdiff_t ef); 47 | LUAI_FUNC int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, 48 | int nres); 49 | LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); 50 | LUAI_FUNC void luaD_growstack (lua_State *L, int n); 51 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); 52 | LUAI_FUNC void luaD_inctop (lua_State *L); 53 | 54 | LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); 55 | LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); 56 | 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /src/ldump.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldump.c,v 2.37 2015/10/08 15:53:49 roberto Exp $ 3 | ** save precompiled Lua chunks 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define ldump_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "lobject.h" 18 | #include "lstate.h" 19 | #include "lundump.h" 20 | 21 | 22 | typedef struct { 23 | lua_State *L; 24 | lua_Writer writer; 25 | void *data; 26 | int strip; 27 | int status; 28 | } DumpState; 29 | 30 | 31 | /* 32 | ** All high-level dumps go through DumpVector; you can change it to 33 | ** change the endianness of the result 34 | */ 35 | #define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D) 36 | 37 | #define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D) 38 | 39 | 40 | static void DumpBlock (const void *b, size_t size, DumpState *D) { 41 | if (D->status == 0 && size > 0) { 42 | lua_unlock(D->L); 43 | D->status = (*D->writer)(D->L, b, size, D->data); 44 | lua_lock(D->L); 45 | } 46 | } 47 | 48 | 49 | #define DumpVar(x,D) DumpVector(&x,1,D) 50 | 51 | 52 | static void DumpByte (int y, DumpState *D) { 53 | lu_byte x = (lu_byte)y; 54 | DumpVar(x, D); 55 | } 56 | 57 | 58 | static void DumpInt (int x, DumpState *D) { 59 | DumpVar(x, D); 60 | } 61 | 62 | 63 | static void DumpNumber (lua_Number x, DumpState *D) { 64 | DumpVar(x, D); 65 | } 66 | 67 | 68 | static void DumpInteger (lua_Integer x, DumpState *D) { 69 | DumpVar(x, D); 70 | } 71 | 72 | 73 | static void DumpString (const TString *s, DumpState *D) { 74 | if (s == NULL) 75 | DumpByte(0, D); 76 | else { 77 | size_t size = tsslen(s) + 1; /* include trailing '\0' */ 78 | const char *str = getstr(s); 79 | if (size < 0xFF) 80 | DumpByte(cast_int(size), D); 81 | else { 82 | DumpByte(0xFF, D); 83 | DumpVar(size, D); 84 | } 85 | DumpVector(str, size - 1, D); /* no need to save '\0' */ 86 | } 87 | } 88 | 89 | 90 | static void DumpCode (const Proto *f, DumpState *D) { 91 | DumpInt(f->sizecode, D); 92 | DumpVector(f->code, f->sizecode, D); 93 | } 94 | 95 | 96 | static void DumpFunction(const Proto *f, TString *psource, DumpState *D); 97 | 98 | static void DumpConstants (const Proto *f, DumpState *D) { 99 | int i; 100 | int n = f->sizek; 101 | DumpInt(n, D); 102 | for (i = 0; i < n; i++) { 103 | const TValue *o = &f->k[i]; 104 | DumpByte(ttype(o), D); 105 | switch (ttype(o)) { 106 | case LUA_TNIL: 107 | break; 108 | case LUA_TBOOLEAN: 109 | DumpByte(bvalue(o), D); 110 | break; 111 | case LUA_TNUMFLT: 112 | DumpNumber(fltvalue(o), D); 113 | break; 114 | case LUA_TNUMINT: 115 | DumpInteger(ivalue(o), D); 116 | break; 117 | case LUA_TSHRSTR: 118 | case LUA_TLNGSTR: 119 | DumpString(tsvalue(o), D); 120 | break; 121 | default: 122 | lua_assert(0); 123 | } 124 | } 125 | } 126 | 127 | 128 | static void DumpProtos (const Proto *f, DumpState *D) { 129 | int i; 130 | int n = f->sizep; 131 | DumpInt(n, D); 132 | for (i = 0; i < n; i++) 133 | DumpFunction(f->p[i], f->source, D); 134 | } 135 | 136 | 137 | static void DumpUpvalues (const Proto *f, DumpState *D) { 138 | int i, n = f->sizeupvalues; 139 | DumpInt(n, D); 140 | for (i = 0; i < n; i++) { 141 | DumpByte(f->upvalues[i].instack, D); 142 | DumpByte(f->upvalues[i].idx, D); 143 | } 144 | } 145 | 146 | 147 | static void DumpDebug (const Proto *f, DumpState *D) { 148 | int i, n; 149 | n = (D->strip) ? 0 : f->sizelineinfo; 150 | DumpInt(n, D); 151 | DumpVector(f->lineinfo, n, D); 152 | n = (D->strip) ? 0 : f->sizelocvars; 153 | DumpInt(n, D); 154 | for (i = 0; i < n; i++) { 155 | DumpString(f->locvars[i].varname, D); 156 | DumpInt(f->locvars[i].startpc, D); 157 | DumpInt(f->locvars[i].endpc, D); 158 | } 159 | n = (D->strip) ? 0 : f->sizeupvalues; 160 | DumpInt(n, D); 161 | for (i = 0; i < n; i++) 162 | DumpString(f->upvalues[i].name, D); 163 | } 164 | 165 | 166 | static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { 167 | if (D->strip || f->source == psource) 168 | DumpString(NULL, D); /* no debug info or same source as its parent */ 169 | else 170 | DumpString(f->source, D); 171 | DumpInt(f->linedefined, D); 172 | DumpInt(f->lastlinedefined, D); 173 | DumpByte(f->numparams, D); 174 | DumpByte(f->is_vararg, D); 175 | DumpByte(f->maxstacksize, D); 176 | DumpCode(f, D); 177 | DumpConstants(f, D); 178 | DumpUpvalues(f, D); 179 | DumpProtos(f, D); 180 | DumpDebug(f, D); 181 | } 182 | 183 | 184 | static void DumpHeader (DumpState *D) { 185 | DumpLiteral(LUA_SIGNATURE, D); 186 | DumpByte(LUAC_VERSION, D); 187 | DumpByte(LUAC_FORMAT, D); 188 | DumpLiteral(LUAC_DATA, D); 189 | DumpByte(sizeof(int), D); 190 | DumpByte(sizeof(size_t), D); 191 | DumpByte(sizeof(Instruction), D); 192 | DumpByte(sizeof(lua_Integer), D); 193 | DumpByte(sizeof(lua_Number), D); 194 | DumpInteger(LUAC_INT, D); 195 | DumpNumber(LUAC_NUM, D); 196 | } 197 | 198 | 199 | /* 200 | ** dump Lua function as precompiled chunk 201 | */ 202 | int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, 203 | int strip) { 204 | DumpState D; 205 | D.L = L; 206 | D.writer = w; 207 | D.data = data; 208 | D.strip = strip; 209 | D.status = 0; 210 | DumpHeader(&D); 211 | DumpByte(f->sizeupvalues, &D); 212 | DumpFunction(f, NULL, &D); 213 | return D.status; 214 | } 215 | 216 | -------------------------------------------------------------------------------- /src/lfunc.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lfunc.c,v 2.45 2014/11/02 19:19:04 roberto Exp $ 3 | ** Auxiliary functions to manipulate prototypes and closures 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lfunc_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "lfunc.h" 18 | #include "lgc.h" 19 | #include "lmem.h" 20 | #include "lobject.h" 21 | #include "lstate.h" 22 | 23 | #ifdef FL_ENABLE 24 | #include "fl_defs.h" 25 | #endif 26 | 27 | 28 | CClosure *luaF_newCclosure (lua_State *L, int n) { 29 | GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n)); 30 | CClosure *c = gco2ccl(o); 31 | c->nupvalues = cast_byte(n); 32 | return c; 33 | } 34 | 35 | 36 | LClosure *luaF_newLclosure (lua_State *L, int n) { 37 | GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); 38 | LClosure *c = gco2lcl(o); 39 | c->p = NULL; 40 | c->nupvalues = cast_byte(n); 41 | while (n--) c->upvals[n] = NULL; 42 | return c; 43 | } 44 | 45 | /* 46 | ** fill a closure with new closed upvalues 47 | */ 48 | void luaF_initupvals (lua_State *L, LClosure *cl) { 49 | int i; 50 | for (i = 0; i < cl->nupvalues; i++) { 51 | UpVal *uv = luaM_new(L, UpVal); 52 | uv->refcount = 1; 53 | uv->v = &uv->u.value; /* make it closed */ 54 | setnilvalue(uv->v); 55 | cl->upvals[i] = uv; 56 | } 57 | } 58 | 59 | 60 | UpVal *luaF_findupval (lua_State *L, StkId level) { 61 | UpVal **pp = &L->openupval; 62 | UpVal *p; 63 | UpVal *uv; 64 | lua_assert(isintwups(L) || L->openupval == NULL); 65 | while (*pp != NULL && (p = *pp)->v >= level) { 66 | lua_assert(upisopen(p)); 67 | if (p->v == level) /* found a corresponding upvalue? */ 68 | return p; /* return it */ 69 | pp = &p->u.open.next; 70 | } 71 | /* not found: create a new upvalue */ 72 | uv = luaM_new(L, UpVal); 73 | uv->refcount = 0; 74 | uv->u.open.next = *pp; /* link it to list of open upvalues */ 75 | uv->u.open.touched = 1; 76 | *pp = uv; 77 | uv->v = level; /* current value lives in the stack */ 78 | if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ 79 | L->twups = G(L)->twups; /* link it to the list */ 80 | G(L)->twups = L; 81 | } 82 | return uv; 83 | } 84 | 85 | 86 | void luaF_close (lua_State *L, StkId level) { 87 | UpVal *uv; 88 | while (L->openupval != NULL && (uv = L->openupval)->v >= level) { 89 | lua_assert(upisopen(uv)); 90 | L->openupval = uv->u.open.next; /* remove from 'open' list */ 91 | if (uv->refcount == 0) /* no references? */ 92 | luaM_free(L, uv); /* free upvalue */ 93 | else { 94 | setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ 95 | uv->v = &uv->u.value; /* now current value lives here */ 96 | luaC_upvalbarrier(L, uv); 97 | } 98 | } 99 | } 100 | 101 | 102 | Proto *luaF_newproto (lua_State *L) { 103 | GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); 104 | Proto *f = gco2p(o); 105 | f->k = NULL; 106 | f->sizek = 0; 107 | f->p = NULL; 108 | f->sizep = 0; 109 | f->code = NULL; 110 | f->cache = NULL; 111 | f->sizecode = 0; 112 | f->lineinfo = NULL; 113 | f->sizelineinfo = 0; 114 | f->upvalues = NULL; 115 | f->sizeupvalues = 0; 116 | f->numparams = 0; 117 | f->is_vararg = 0; 118 | f->maxstacksize = 0; 119 | f->locvars = NULL; 120 | f->sizelocvars = 0; 121 | f->linedefined = 0; 122 | f->lastlinedefined = 0; 123 | f->source = NULL; 124 | #ifdef FL_ENABLE 125 | fl_initproto(f); 126 | #endif 127 | return f; 128 | } 129 | 130 | 131 | void luaF_freeproto (lua_State *L, Proto *f) { 132 | luaM_freearray(L, f->code, f->sizecode); 133 | luaM_freearray(L, f->p, f->sizep); 134 | luaM_freearray(L, f->k, f->sizek); 135 | luaM_freearray(L, f->lineinfo, f->sizelineinfo); 136 | luaM_freearray(L, f->locvars, f->sizelocvars); 137 | luaM_freearray(L, f->upvalues, f->sizeupvalues); 138 | #ifdef FL_ENABLE 139 | fl_closeproto(L, f); 140 | #endif 141 | luaM_free(L, f); 142 | } 143 | 144 | 145 | /* 146 | ** Look for n-th local variable at line 'line' in function 'func'. 147 | ** Returns NULL if not found. 148 | */ 149 | const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { 150 | int i; 151 | for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { 152 | if (pc < f->locvars[i].endpc) { /* is variable active? */ 153 | local_number--; 154 | if (local_number == 0) 155 | return getstr(f->locvars[i].varname); 156 | } 157 | } 158 | return NULL; /* not found */ 159 | } 160 | 161 | -------------------------------------------------------------------------------- /src/lfunc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lfunc.h,v 2.15 2015/01/13 15:49:11 roberto Exp $ 3 | ** Auxiliary functions to manipulate prototypes and closures 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lfunc_h 8 | #define lfunc_h 9 | 10 | 11 | #include "lobject.h" 12 | 13 | 14 | #define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ 15 | cast(int, sizeof(TValue)*((n)-1))) 16 | 17 | #define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ 18 | cast(int, sizeof(TValue *)*((n)-1))) 19 | 20 | 21 | /* test whether thread is in 'twups' list */ 22 | #define isintwups(L) (L->twups != L) 23 | 24 | 25 | /* 26 | ** maximum number of upvalues in a closure (both C and Lua). (Value 27 | ** must fit in a VM register.) 28 | */ 29 | #define MAXUPVAL 255 30 | 31 | 32 | /* 33 | ** Upvalues for Lua closures 34 | */ 35 | struct UpVal { 36 | TValue *v; /* points to stack or to its own value */ 37 | lu_mem refcount; /* reference counter */ 38 | union { 39 | struct { /* (when open) */ 40 | UpVal *next; /* linked list */ 41 | int touched; /* mark to avoid cycles with dead threads */ 42 | } open; 43 | TValue value; /* the value (when closed) */ 44 | } u; 45 | }; 46 | 47 | #define upisopen(up) ((up)->v != &(up)->u.value) 48 | 49 | 50 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); 51 | LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); 52 | LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); 53 | LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); 54 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); 55 | LUAI_FUNC void luaF_close (lua_State *L, StkId level); 56 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); 57 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, 58 | int pc); 59 | 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/lgc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lgc.h,v 2.91 2015/12/21 13:02:14 roberto Exp $ 3 | ** Garbage Collector 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lgc_h 8 | #define lgc_h 9 | 10 | 11 | #include "lobject.h" 12 | #include "lstate.h" 13 | 14 | /* 15 | ** Collectable objects may have one of three colors: white, which 16 | ** means the object is not marked; gray, which means the 17 | ** object is marked, but its references may be not marked; and 18 | ** black, which means that the object and all its references are marked. 19 | ** The main invariant of the garbage collector, while marking objects, 20 | ** is that a black object can never point to a white one. Moreover, 21 | ** any gray object must be in a "gray list" (gray, grayagain, weak, 22 | ** allweak, ephemeron) so that it can be visited again before finishing 23 | ** the collection cycle. These lists have no meaning when the invariant 24 | ** is not being enforced (e.g., sweep phase). 25 | */ 26 | 27 | 28 | 29 | /* how much to allocate before next GC step */ 30 | #if !defined(GCSTEPSIZE) 31 | /* ~100 small strings */ 32 | #define GCSTEPSIZE (cast_int(100 * sizeof(TString))) 33 | #endif 34 | 35 | 36 | /* 37 | ** Possible states of the Garbage Collector 38 | */ 39 | #define GCSpropagate 0 40 | #define GCSatomic 1 41 | #define GCSswpallgc 2 42 | #define GCSswpfinobj 3 43 | #define GCSswptobefnz 4 44 | #define GCSswpend 5 45 | #define GCScallfin 6 46 | #define GCSpause 7 47 | 48 | 49 | #define issweepphase(g) \ 50 | (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) 51 | 52 | 53 | /* 54 | ** macro to tell when main invariant (white objects cannot point to black 55 | ** ones) must be kept. During a collection, the sweep 56 | ** phase may break the invariant, as objects turned white may point to 57 | ** still-black objects. The invariant is restored when sweep ends and 58 | ** all objects are white again. 59 | */ 60 | 61 | #define keepinvariant(g) ((g)->gcstate <= GCSatomic) 62 | 63 | 64 | /* 65 | ** some useful bit tricks 66 | */ 67 | #define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) 68 | #define setbits(x,m) ((x) |= (m)) 69 | #define testbits(x,m) ((x) & (m)) 70 | #define bitmask(b) (1<<(b)) 71 | #define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) 72 | #define l_setbit(x,b) setbits(x, bitmask(b)) 73 | #define resetbit(x,b) resetbits(x, bitmask(b)) 74 | #define testbit(x,b) testbits(x, bitmask(b)) 75 | 76 | 77 | /* Layout for bit use in 'marked' field: */ 78 | #define WHITE0BIT 0 /* object is white (type 0) */ 79 | #define WHITE1BIT 1 /* object is white (type 1) */ 80 | #define BLACKBIT 2 /* object is black */ 81 | #define FINALIZEDBIT 3 /* object has been marked for finalization */ 82 | /* bit 7 is currently used by tests (luaL_checkmemory) */ 83 | 84 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) 85 | 86 | 87 | #define iswhite(x) testbits((x)->marked, WHITEBITS) 88 | #define isblack(x) testbit((x)->marked, BLACKBIT) 89 | #define isgray(x) /* neither white nor black */ \ 90 | (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) 91 | 92 | #define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) 93 | 94 | #define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) 95 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) 96 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) 97 | 98 | #define changewhite(x) ((x)->marked ^= WHITEBITS) 99 | #define gray2black(x) l_setbit((x)->marked, BLACKBIT) 100 | 101 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) 102 | 103 | 104 | /* 105 | ** Does one step of collection when debt becomes positive. 'pre'/'pos' 106 | ** allows some adjustments to be done only when needed. macro 107 | ** 'condchangemem' is used only for heavy tests (forcing a full 108 | ** GC cycle on every opportunity) 109 | */ 110 | #define luaC_condGC(L,pre,pos) \ 111 | { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \ 112 | condchangemem(L,pre,pos); } 113 | 114 | /* more often than not, 'pre'/'pos' are empty */ 115 | #define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) 116 | 117 | 118 | #define luaC_barrier(L,p,v) ( \ 119 | (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ 120 | luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) 121 | 122 | #define luaC_barrierback(L,p,v) ( \ 123 | (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ 124 | luaC_barrierback_(L,p) : cast_void(0)) 125 | 126 | #define luaC_objbarrier(L,p,o) ( \ 127 | (isblack(p) && iswhite(o)) ? \ 128 | luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) 129 | 130 | #define luaC_upvalbarrier(L,uv) ( \ 131 | (iscollectable((uv)->v) && !upisopen(uv)) ? \ 132 | luaC_upvalbarrier_(L,uv) : cast_void(0)) 133 | 134 | LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); 135 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); 136 | LUAI_FUNC void luaC_step (lua_State *L); 137 | LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); 138 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); 139 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); 140 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); 141 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); 142 | LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); 143 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); 144 | LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); 145 | 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /src/linit.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: linit.c,v 1.38 2015/01/05 13:48:33 roberto Exp $ 3 | ** Initialization of libraries for lua.c and other clients 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #define linit_c 9 | #define LUA_LIB 10 | 11 | /* 12 | ** If you embed Lua in your program and need to open the standard 13 | ** libraries, call luaL_openlibs in your program. If you need a 14 | ** different set of libraries, copy this file to your project and edit 15 | ** it to suit your needs. 16 | ** 17 | ** You can also *preload* libraries, so that a later 'require' can 18 | ** open the library, which is already linked to the application. 19 | ** For that, do the following code: 20 | ** 21 | ** luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); 22 | ** lua_pushcfunction(L, luaopen_modname); 23 | ** lua_setfield(L, -2, modname); 24 | ** lua_pop(L, 1); // remove _PRELOAD table 25 | */ 26 | 27 | #include "lprefix.h" 28 | 29 | 30 | #include 31 | 32 | #include "lua.h" 33 | 34 | #include "lualib.h" 35 | #include "lauxlib.h" 36 | 37 | 38 | /* 39 | ** these libs are loaded by lua.c and are readily available to any Lua 40 | ** program 41 | */ 42 | static const luaL_Reg loadedlibs[] = { 43 | {"_G", luaopen_base}, 44 | {LUA_LOADLIBNAME, luaopen_package}, 45 | {LUA_COLIBNAME, luaopen_coroutine}, 46 | {LUA_TABLIBNAME, luaopen_table}, 47 | {LUA_IOLIBNAME, luaopen_io}, 48 | {LUA_OSLIBNAME, luaopen_os}, 49 | {LUA_STRLIBNAME, luaopen_string}, 50 | {LUA_MATHLIBNAME, luaopen_math}, 51 | {LUA_UTF8LIBNAME, luaopen_utf8}, 52 | {LUA_DBLIBNAME, luaopen_debug}, 53 | #if defined(LUA_COMPAT_BITLIB) 54 | {LUA_BITLIBNAME, luaopen_bit32}, 55 | #endif 56 | #ifdef FL_ENABLE 57 | {LUA_JITLIBNAME, luaopen_jit}, 58 | #endif 59 | {NULL, NULL} 60 | }; 61 | 62 | 63 | LUALIB_API void luaL_openlibs (lua_State *L) { 64 | const luaL_Reg *lib; 65 | /* "require" functions from 'loadedlibs' and set results to global table */ 66 | for (lib = loadedlibs; lib->func; lib++) { 67 | luaL_requiref(L, lib->name, lib->func, 1); 68 | lua_pop(L, 1); /* remove lib */ 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /src/llex.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: llex.h,v 1.79 2016/05/02 14:02:12 roberto Exp $ 3 | ** Lexical Analyzer 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef llex_h 8 | #define llex_h 9 | 10 | #include "lobject.h" 11 | #include "lzio.h" 12 | 13 | 14 | #define FIRST_RESERVED 257 15 | 16 | 17 | #if !defined(LUA_ENV) 18 | #define LUA_ENV "_ENV" 19 | #endif 20 | 21 | 22 | /* 23 | * WARNING: if you change the order of this enumeration, 24 | * grep "ORDER RESERVED" 25 | */ 26 | enum RESERVED { 27 | /* terminal symbols denoted by reserved words */ 28 | TK_AND = FIRST_RESERVED, TK_BREAK, 29 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, 30 | TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, 31 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, 32 | /* other terminal symbols */ 33 | TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, 34 | TK_SHL, TK_SHR, 35 | TK_DBCOLON, TK_EOS, 36 | TK_FLT, TK_INT, TK_NAME, TK_STRING 37 | }; 38 | 39 | /* number of reserved words */ 40 | #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) 41 | 42 | 43 | typedef union { 44 | lua_Number r; 45 | lua_Integer i; 46 | TString *ts; 47 | } SemInfo; /* semantics information */ 48 | 49 | 50 | typedef struct Token { 51 | int token; 52 | SemInfo seminfo; 53 | } Token; 54 | 55 | 56 | /* state of the lexer plus state of the parser when shared by all 57 | functions */ 58 | typedef struct LexState { 59 | int current; /* current character (charint) */ 60 | int linenumber; /* input line counter */ 61 | int lastline; /* line of last token 'consumed' */ 62 | Token t; /* current token */ 63 | Token lookahead; /* look ahead token */ 64 | struct FuncState *fs; /* current function (parser) */ 65 | struct lua_State *L; 66 | ZIO *z; /* input stream */ 67 | Mbuffer *buff; /* buffer for tokens */ 68 | Table *h; /* to avoid collection/reuse strings */ 69 | struct Dyndata *dyd; /* dynamic structures used by the parser */ 70 | TString *source; /* current source name */ 71 | TString *envn; /* environment variable name */ 72 | } LexState; 73 | 74 | 75 | LUAI_FUNC void luaX_init (lua_State *L); 76 | LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, 77 | TString *source, int firstchar); 78 | LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); 79 | LUAI_FUNC void luaX_next (LexState *ls); 80 | LUAI_FUNC int luaX_lookahead (LexState *ls); 81 | LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); 82 | LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); 83 | 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/lmem.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 roberto Exp $ 3 | ** Interface to Memory Manager 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lmem_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "ldebug.h" 18 | #include "ldo.h" 19 | #include "lgc.h" 20 | #include "lmem.h" 21 | #include "lobject.h" 22 | #include "lstate.h" 23 | 24 | 25 | 26 | /* 27 | ** About the realloc function: 28 | ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); 29 | ** ('osize' is the old size, 'nsize' is the new size) 30 | ** 31 | ** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no 32 | ** matter 'x'). 33 | ** 34 | ** * frealloc(ud, p, x, 0) frees the block 'p' 35 | ** (in this specific case, frealloc must return NULL); 36 | ** particularly, frealloc(ud, NULL, 0, 0) does nothing 37 | ** (which is equivalent to free(NULL) in ISO C) 38 | ** 39 | ** frealloc returns NULL if it cannot create or reallocate the area 40 | ** (any reallocation to an equal or smaller size cannot fail!) 41 | */ 42 | 43 | 44 | 45 | #define MINSIZEARRAY 4 46 | 47 | 48 | void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, 49 | int limit, const char *what) { 50 | void *newblock; 51 | int newsize; 52 | if (*size >= limit/2) { /* cannot double it? */ 53 | if (*size >= limit) /* cannot grow even a little? */ 54 | luaG_runerror(L, "too many %s (limit is %d)", what, limit); 55 | newsize = limit; /* still have at least one free place */ 56 | } 57 | else { 58 | newsize = (*size)*2; 59 | if (newsize < MINSIZEARRAY) 60 | newsize = MINSIZEARRAY; /* minimum size */ 61 | } 62 | newblock = luaM_reallocv(L, block, *size, newsize, size_elems); 63 | *size = newsize; /* update only when everything else is OK */ 64 | return newblock; 65 | } 66 | 67 | 68 | l_noret luaM_toobig (lua_State *L) { 69 | luaG_runerror(L, "memory allocation error: block too big"); 70 | } 71 | 72 | 73 | 74 | /* 75 | ** generic allocation routine. 76 | */ 77 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { 78 | void *newblock; 79 | global_State *g = G(L); 80 | size_t realosize = (block) ? osize : 0; 81 | lua_assert((realosize == 0) == (block == NULL)); 82 | #if defined(HARDMEMTESTS) 83 | if (nsize > realosize && g->gcrunning) 84 | luaC_fullgc(L, 1); /* force a GC whenever possible */ 85 | #endif 86 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); 87 | if (newblock == NULL && nsize > 0) { 88 | lua_assert(nsize > realosize); /* cannot fail when shrinking a block */ 89 | if (g->version) { /* is state fully built? */ 90 | luaC_fullgc(L, 1); /* try to free some memory... */ 91 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ 92 | } 93 | if (newblock == NULL) 94 | luaD_throw(L, LUA_ERRMEM); 95 | } 96 | lua_assert((nsize == 0) == (newblock == NULL)); 97 | g->GCdebt = (g->GCdebt + nsize) - realosize; 98 | return newblock; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/lmem.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lmem.h,v 1.43 2014/12/19 17:26:14 roberto Exp $ 3 | ** Interface to Memory Manager 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lmem_h 8 | #define lmem_h 9 | 10 | 11 | #include 12 | 13 | #include "llimits.h" 14 | #include "lua.h" 15 | 16 | 17 | /* 18 | ** This macro reallocs a vector 'b' from 'on' to 'n' elements, where 19 | ** each element has size 'e'. In case of arithmetic overflow of the 20 | ** product 'n'*'e', it raises an error (calling 'luaM_toobig'). Because 21 | ** 'e' is always constant, it avoids the runtime division MAX_SIZET/(e). 22 | ** 23 | ** (The macro is somewhat complex to avoid warnings: The 'sizeof' 24 | ** comparison avoids a runtime comparison when overflow cannot occur. 25 | ** The compiler should be able to optimize the real test by itself, but 26 | ** when it does it, it may give a warning about "comparison is always 27 | ** false due to limited range of data type"; the +1 tricks the compiler, 28 | ** avoiding this warning but also this optimization.) 29 | */ 30 | #define luaM_reallocv(L,b,on,n,e) \ 31 | (((sizeof(n) >= sizeof(size_t) && cast(size_t, (n)) + 1 > MAX_SIZET/(e)) \ 32 | ? luaM_toobig(L) : cast_void(0)) , \ 33 | luaM_realloc_(L, (b), (on)*(e), (n)*(e))) 34 | 35 | /* 36 | ** Arrays of chars do not need any test 37 | */ 38 | #define luaM_reallocvchar(L,b,on,n) \ 39 | cast(char *, luaM_realloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) 40 | 41 | #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) 42 | #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) 43 | #define luaM_freearray(L, b, n) luaM_realloc_(L, (b), (n)*sizeof(*(b)), 0) 44 | 45 | #define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) 46 | #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) 47 | #define luaM_newvector(L,n,t) \ 48 | cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) 49 | 50 | #define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) 51 | 52 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ 53 | if ((nelems)+1 > (size)) \ 54 | ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) 55 | 56 | #define luaM_reallocvector(L, v,oldn,n,t) \ 57 | ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) 58 | 59 | LUAI_FUNC l_noret luaM_toobig (lua_State *L); 60 | 61 | /* not to be called directly */ 62 | LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, 63 | size_t size); 64 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, 65 | size_t size_elem, int limit, 66 | const char *what); 67 | 68 | #endif 69 | 70 | -------------------------------------------------------------------------------- /src/lopcodes.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lopcodes.c,v 1.55 2015/01/05 13:48:33 roberto Exp $ 3 | ** Opcodes for Lua virtual machine 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lopcodes_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lopcodes.h" 16 | 17 | 18 | /* ORDER OP */ 19 | 20 | LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { 21 | "MOVE", 22 | "LOADK", 23 | "LOADKX", 24 | "LOADBOOL", 25 | "LOADNIL", 26 | "GETUPVAL", 27 | "GETTABUP", 28 | "GETTABLE", 29 | "SETTABUP", 30 | "SETUPVAL", 31 | "SETTABLE", 32 | "NEWTABLE", 33 | "SELF", 34 | "ADD", 35 | "SUB", 36 | "MUL", 37 | "MOD", 38 | "POW", 39 | "DIV", 40 | "IDIV", 41 | "BAND", 42 | "BOR", 43 | "BXOR", 44 | "SHL", 45 | "SHR", 46 | "UNM", 47 | "BNOT", 48 | "NOT", 49 | "LEN", 50 | "CONCAT", 51 | "JMP", 52 | "EQ", 53 | "LT", 54 | "LE", 55 | "TEST", 56 | "TESTSET", 57 | "CALL", 58 | "TAILCALL", 59 | "RETURN", 60 | "FORLOOP", 61 | "FORPREP", 62 | "TFORCALL", 63 | "TFORLOOP", 64 | "SETLIST", 65 | "CLOSURE", 66 | "VARARG", 67 | "EXTRAARG", 68 | "OP_FLVM", 69 | NULL 70 | }; 71 | 72 | 73 | #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) 74 | 75 | LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { 76 | /* T A B C mode opcode */ 77 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ 78 | ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ 79 | ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ 80 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ 81 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ 82 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ 83 | ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ 84 | ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ 85 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ 86 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ 87 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ 88 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ 89 | ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ 90 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ 91 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ 92 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ 93 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ 94 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ 95 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ 96 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */ 97 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BAND */ 98 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BOR */ 99 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BXOR */ 100 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHL */ 101 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHR */ 102 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ 103 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_BNOT */ 104 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ 105 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ 106 | ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ 107 | ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ 108 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ 109 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ 110 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ 111 | ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ 112 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ 113 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ 114 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ 115 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ 116 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ 117 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ 118 | ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ 119 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ 120 | ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ 121 | ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ 122 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ 123 | ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ 124 | }; 125 | 126 | -------------------------------------------------------------------------------- /src/lparser.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lparser.h,v 1.76 2015/12/30 18:16:13 roberto Exp $ 3 | ** Lua Parser 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lparser_h 8 | #define lparser_h 9 | 10 | #include "llimits.h" 11 | #include "lobject.h" 12 | #include "lzio.h" 13 | 14 | 15 | /* 16 | ** Expression and variable descriptor. 17 | ** Code generation for variables and expressions can be delayed to allow 18 | ** optimizations; An 'expdesc' structure describes a potentially-delayed 19 | ** variable/expression. It has a description of its "main" value plus a 20 | ** list of conditional jumps that can also produce its value (generated 21 | ** by short-circuit operators 'and'/'or'). 22 | */ 23 | 24 | /* kinds of variables/expressions */ 25 | typedef enum { 26 | VVOID, /* when 'expdesc' describes the last expression a list, 27 | this kind means an empty list (so, no expression) */ 28 | VNIL, /* constant nil */ 29 | VTRUE, /* constant true */ 30 | VFALSE, /* constant false */ 31 | VK, /* constant in 'k'; info = index of constant in 'k' */ 32 | VKFLT, /* floating constant; nval = numerical float value */ 33 | VKINT, /* integer constant; nval = numerical integer value */ 34 | VNONRELOC, /* expression has its value in a fixed register; 35 | info = result register */ 36 | VLOCAL, /* local variable; info = local register */ 37 | VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ 38 | VINDEXED, /* indexed variable; 39 | ind.vt = whether 't' is register or upvalue; 40 | ind.t = table register or upvalue; 41 | ind.idx = key's R/K index */ 42 | VJMP, /* expression is a test/comparison; 43 | info = pc of corresponding jump instruction */ 44 | VRELOCABLE, /* expression can put result in any register; 45 | info = instruction pc */ 46 | VCALL, /* expression is a function call; info = instruction pc */ 47 | VVARARG /* vararg expression; info = instruction pc */ 48 | } expkind; 49 | 50 | 51 | #define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) 52 | #define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) 53 | 54 | typedef struct expdesc { 55 | expkind k; 56 | union { 57 | lua_Integer ival; /* for VKINT */ 58 | lua_Number nval; /* for VKFLT */ 59 | int info; /* for generic use */ 60 | struct { /* for indexed variables (VINDEXED) */ 61 | short idx; /* index (R/K) */ 62 | lu_byte t; /* table (register or upvalue) */ 63 | lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ 64 | } ind; 65 | } u; 66 | int t; /* patch list of 'exit when true' */ 67 | int f; /* patch list of 'exit when false' */ 68 | } expdesc; 69 | 70 | 71 | /* description of active local variable */ 72 | typedef struct Vardesc { 73 | short idx; /* variable index in stack */ 74 | } Vardesc; 75 | 76 | 77 | /* description of pending goto statements and label statements */ 78 | typedef struct Labeldesc { 79 | TString *name; /* label identifier */ 80 | int pc; /* position in code */ 81 | int line; /* line where it appeared */ 82 | lu_byte nactvar; /* local level where it appears in current block */ 83 | } Labeldesc; 84 | 85 | 86 | /* list of labels or gotos */ 87 | typedef struct Labellist { 88 | Labeldesc *arr; /* array */ 89 | int n; /* number of entries in use */ 90 | int size; /* array size */ 91 | } Labellist; 92 | 93 | 94 | /* dynamic structures used by the parser */ 95 | typedef struct Dyndata { 96 | struct { /* list of active local variables */ 97 | Vardesc *arr; 98 | int n; 99 | int size; 100 | } actvar; 101 | Labellist gt; /* list of pending gotos */ 102 | Labellist label; /* list of active labels */ 103 | } Dyndata; 104 | 105 | 106 | /* control of blocks */ 107 | struct BlockCnt; /* defined in lparser.c */ 108 | 109 | 110 | /* state needed to generate code for a given function */ 111 | typedef struct FuncState { 112 | Proto *f; /* current function header */ 113 | struct FuncState *prev; /* enclosing function */ 114 | struct LexState *ls; /* lexical state */ 115 | struct BlockCnt *bl; /* chain of current blocks */ 116 | int pc; /* next position to code (equivalent to 'ncode') */ 117 | int lasttarget; /* 'label' of last 'jump label' */ 118 | int jpc; /* list of pending jumps to 'pc' */ 119 | int nk; /* number of elements in 'k' */ 120 | int np; /* number of elements in 'p' */ 121 | int firstlocal; /* index of first local var (in Dyndata array) */ 122 | short nlocvars; /* number of elements in 'f->locvars' */ 123 | lu_byte nactvar; /* number of active local variables */ 124 | lu_byte nups; /* number of upvalues */ 125 | lu_byte freereg; /* first free register */ 126 | } FuncState; 127 | 128 | 129 | LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, 130 | Dyndata *dyd, const char *name, int firstchar); 131 | 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /src/lprefix.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $ 3 | ** Definitions for Lua code that must come before any other header file 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lprefix_h 8 | #define lprefix_h 9 | 10 | 11 | /* 12 | ** Allows POSIX/XSI stuff 13 | */ 14 | #if !defined(LUA_USE_C89) /* { */ 15 | 16 | #if !defined(_XOPEN_SOURCE) 17 | #define _XOPEN_SOURCE 600 18 | #elif _XOPEN_SOURCE == 0 19 | #undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ 20 | #endif 21 | 22 | /* 23 | ** Allows manipulation of large files in gcc and some other compilers 24 | */ 25 | #if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) 26 | #define _LARGEFILE_SOURCE 1 27 | #define _FILE_OFFSET_BITS 64 28 | #endif 29 | 30 | #endif /* } */ 31 | 32 | 33 | /* 34 | ** Windows stuff 35 | */ 36 | #if defined(_WIN32) /* { */ 37 | 38 | #if !defined(_CRT_SECURE_NO_WARNINGS) 39 | #define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ 40 | #endif 41 | 42 | #endif /* } */ 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /src/lstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstring.h,v 1.61 2015/11/03 15:36:01 roberto Exp $ 3 | ** String table (keep all strings handled by Lua) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lstring_h 8 | #define lstring_h 9 | 10 | #include "lgc.h" 11 | #include "lobject.h" 12 | #include "lstate.h" 13 | 14 | 15 | #define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) 16 | 17 | #define sizeludata(l) (sizeof(union UUdata) + (l)) 18 | #define sizeudata(u) sizeludata((u)->len) 19 | 20 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ 21 | (sizeof(s)/sizeof(char))-1)) 22 | 23 | 24 | /* 25 | ** test whether a string is a reserved word 26 | */ 27 | #define isreserved(s) ((s)->tt == LUA_TSHRSTR && (s)->extra > 0) 28 | 29 | 30 | /* 31 | ** equality for short strings, which are always internalized 32 | */ 33 | #define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (a) == (b)) 34 | 35 | 36 | LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); 37 | LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); 38 | LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); 39 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); 40 | LUAI_FUNC void luaS_clearcache (global_State *g); 41 | LUAI_FUNC void luaS_init (lua_State *L); 42 | LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); 43 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); 44 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); 45 | LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); 46 | LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); 47 | 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/ltable.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltable.h,v 2.21 2015/11/03 15:47:30 roberto Exp $ 3 | ** Lua tables (hash) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltable_h 8 | #define ltable_h 9 | 10 | #include "lobject.h" 11 | 12 | 13 | #define gnode(t,i) (&(t)->node[i]) 14 | #define gval(n) (&(n)->i_val) 15 | #define gnext(n) ((n)->i_key.nk.next) 16 | 17 | 18 | /* 'const' to avoid wrong writings that can mess up field 'next' */ 19 | #define gkey(n) cast(const TValue*, (&(n)->i_key.tvk)) 20 | 21 | /* 22 | ** writable version of 'gkey'; allows updates to individual fields, 23 | ** but not to the whole (which has incompatible type) 24 | */ 25 | #define wgkey(n) (&(n)->i_key.nk) 26 | 27 | #define invalidateTMcache(t) ((t)->flags = 0) 28 | 29 | 30 | /* returns the key, given the value of a table entry */ 31 | #define keyfromval(v) \ 32 | (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) 33 | 34 | 35 | LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); 36 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, 37 | TValue *value); 38 | LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); 39 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); 40 | LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); 41 | LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); 42 | LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); 43 | LUAI_FUNC Table *luaH_new (lua_State *L); 44 | LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, 45 | unsigned int nhsize); 46 | LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize); 47 | LUAI_FUNC void luaH_free (lua_State *L, Table *t); 48 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); 49 | LUAI_FUNC int luaH_getn (Table *t); 50 | 51 | 52 | #if defined(LUA_DEBUG) 53 | LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); 54 | LUAI_FUNC int luaH_isdummy (Node *n); 55 | #endif 56 | 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/ltm.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltm.c,v 2.37 2016/02/26 19:20:15 roberto Exp $ 3 | ** Tag methods 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define ltm_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "ldebug.h" 18 | #include "ldo.h" 19 | #include "lobject.h" 20 | #include "lstate.h" 21 | #include "lstring.h" 22 | #include "ltable.h" 23 | #include "ltm.h" 24 | #include "lvm.h" 25 | 26 | 27 | static const char udatatypename[] = "userdata"; 28 | 29 | LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { 30 | "no value", 31 | "nil", "boolean", udatatypename, "number", 32 | "string", "table", "function", udatatypename, "thread", 33 | "proto" /* this last case is used for tests only */ 34 | }; 35 | 36 | 37 | void luaT_init (lua_State *L) { 38 | static const char *const luaT_eventname[] = { /* ORDER TM */ 39 | "__index", "__newindex", 40 | "__gc", "__mode", "__len", "__eq", 41 | "__add", "__sub", "__mul", "__mod", "__pow", 42 | "__div", "__idiv", 43 | "__band", "__bor", "__bxor", "__shl", "__shr", 44 | "__unm", "__bnot", "__lt", "__le", 45 | "__concat", "__call" 46 | }; 47 | int i; 48 | for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); 50 | luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ 51 | } 52 | } 53 | 54 | 55 | /* 56 | ** function to be used with macro "fasttm": optimized for absence of 57 | ** tag methods 58 | */ 59 | const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { 60 | const TValue *tm = luaH_getshortstr(events, ename); 61 | lua_assert(event <= TM_EQ); 62 | if (ttisnil(tm)) { /* no tag method? */ 63 | events->flags |= cast_byte(1u<metatable; 75 | break; 76 | case LUA_TUSERDATA: 77 | mt = uvalue(o)->metatable; 78 | break; 79 | default: 80 | mt = G(L)->mt[ttnov(o)]; 81 | } 82 | return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject); 83 | } 84 | 85 | 86 | /* 87 | ** Return the name of the type of an object. For tables and userdata 88 | ** with metatable, use their '__name' metafield, if present. 89 | */ 90 | const char *luaT_objtypename (lua_State *L, const TValue *o) { 91 | Table *mt; 92 | if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || 93 | (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { 94 | const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name")); 95 | if (ttisstring(name)) /* is '__name' a string? */ 96 | return getstr(tsvalue(name)); /* use it as type name */ 97 | } 98 | return ttypename(ttnov(o)); /* else use standard type name */ 99 | } 100 | 101 | 102 | void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, 103 | const TValue *p2, TValue *p3, int hasres) { 104 | ptrdiff_t result = savestack(L, p3); 105 | StkId func = L->top; 106 | setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ 107 | setobj2s(L, func + 1, p1); /* 1st argument */ 108 | setobj2s(L, func + 2, p2); /* 2nd argument */ 109 | L->top += 3; 110 | if (!hasres) /* no result? 'p3' is third argument */ 111 | setobj2s(L, L->top++, p3); /* 3rd argument */ 112 | /* metamethod may yield only when called from Lua code */ 113 | if (isLua(L->ci)) 114 | luaD_call(L, func, hasres); 115 | else 116 | luaD_callnoyield(L, func, hasres); 117 | if (hasres) { /* if has result, move it to its place */ 118 | p3 = restorestack(L, result); 119 | setobjs2s(L, p3, --L->top); 120 | } 121 | } 122 | 123 | 124 | int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, 125 | StkId res, TMS event) { 126 | const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ 127 | if (ttisnil(tm)) 128 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ 129 | if (ttisnil(tm)) return 0; 130 | luaT_callTM(L, tm, p1, p2, res, 1); 131 | return 1; 132 | } 133 | 134 | 135 | void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 136 | StkId res, TMS event) { 137 | if (!luaT_callbinTM(L, p1, p2, res, event)) { 138 | switch (event) { 139 | case TM_CONCAT: 140 | luaG_concaterror(L, p1, p2); 141 | /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ 142 | case TM_BAND: case TM_BOR: case TM_BXOR: 143 | case TM_SHL: case TM_SHR: case TM_BNOT: { 144 | lua_Number dummy; 145 | if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) 146 | luaG_tointerror(L, p1, p2); 147 | else 148 | luaG_opinterror(L, p1, p2, "perform bitwise operation on"); 149 | } 150 | /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ 151 | default: 152 | luaG_opinterror(L, p1, p2, "perform arithmetic on"); 153 | } 154 | } 155 | } 156 | 157 | 158 | int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, 159 | TMS event) { 160 | if (!luaT_callbinTM(L, p1, p2, L->top, event)) 161 | return -1; /* no metamethod */ 162 | else 163 | return !l_isfalse(L->top); 164 | } 165 | 166 | -------------------------------------------------------------------------------- /src/ltm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltm.h,v 2.22 2016/02/26 19:20:15 roberto Exp $ 3 | ** Tag methods 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltm_h 8 | #define ltm_h 9 | 10 | 11 | #include "lobject.h" 12 | 13 | 14 | /* 15 | * WARNING: if you change the order of this enumeration, 16 | * grep "ORDER TM" and "ORDER OP" 17 | */ 18 | typedef enum { 19 | TM_INDEX, 20 | TM_NEWINDEX, 21 | TM_GC, 22 | TM_MODE, 23 | TM_LEN, 24 | TM_EQ, /* last tag method with fast access */ 25 | TM_ADD, 26 | TM_SUB, 27 | TM_MUL, 28 | TM_MOD, 29 | TM_POW, 30 | TM_DIV, 31 | TM_IDIV, 32 | TM_BAND, 33 | TM_BOR, 34 | TM_BXOR, 35 | TM_SHL, 36 | TM_SHR, 37 | TM_UNM, 38 | TM_BNOT, 39 | TM_LT, 40 | TM_LE, 41 | TM_CONCAT, 42 | TM_CALL, 43 | TM_N /* number of elements in the enum */ 44 | } TMS; 45 | 46 | 47 | 48 | #define gfasttm(g,et,e) ((et) == NULL ? NULL : \ 49 | ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) 50 | 51 | #define fasttm(l,et,e) gfasttm(G(l), et, e) 52 | 53 | #define ttypename(x) luaT_typenames_[(x) + 1] 54 | 55 | LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; 56 | 57 | 58 | LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o); 59 | 60 | LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); 61 | LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, 62 | TMS event); 63 | LUAI_FUNC void luaT_init (lua_State *L); 64 | 65 | LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, 66 | const TValue *p2, TValue *p3, int hasres); 67 | LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, 68 | StkId res, TMS event); 69 | LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 70 | StkId res, TMS event); 71 | LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, 72 | const TValue *p2, TMS event); 73 | 74 | 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/lua.hpp: -------------------------------------------------------------------------------- 1 | // lua.hpp 2 | // Lua header files for C++ 3 | // <> not supplied automatically because Lua also compiles as C++ 4 | 5 | extern "C" { 6 | #include "lua.h" 7 | #include "lualib.h" 8 | #include "lauxlib.h" 9 | } 10 | -------------------------------------------------------------------------------- /src/lualib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp $ 3 | ** Lua standard libraries 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lualib_h 9 | #define lualib_h 10 | 11 | #include "lua.h" 12 | 13 | 14 | 15 | LUAMOD_API int (luaopen_base) (lua_State *L); 16 | 17 | #define LUA_COLIBNAME "coroutine" 18 | LUAMOD_API int (luaopen_coroutine) (lua_State *L); 19 | 20 | #define LUA_TABLIBNAME "table" 21 | LUAMOD_API int (luaopen_table) (lua_State *L); 22 | 23 | #define LUA_IOLIBNAME "io" 24 | LUAMOD_API int (luaopen_io) (lua_State *L); 25 | 26 | #define LUA_OSLIBNAME "os" 27 | LUAMOD_API int (luaopen_os) (lua_State *L); 28 | 29 | #define LUA_STRLIBNAME "string" 30 | LUAMOD_API int (luaopen_string) (lua_State *L); 31 | 32 | #define LUA_UTF8LIBNAME "utf8" 33 | LUAMOD_API int (luaopen_utf8) (lua_State *L); 34 | 35 | #define LUA_BITLIBNAME "bit32" 36 | LUAMOD_API int (luaopen_bit32) (lua_State *L); 37 | 38 | #define LUA_MATHLIBNAME "math" 39 | LUAMOD_API int (luaopen_math) (lua_State *L); 40 | 41 | #define LUA_DBLIBNAME "debug" 42 | LUAMOD_API int (luaopen_debug) (lua_State *L); 43 | 44 | #define LUA_LOADLIBNAME "package" 45 | LUAMOD_API int (luaopen_package) (lua_State *L); 46 | 47 | #ifdef FL_ENABLE 48 | #define LUA_JITLIBNAME "jit" 49 | LUAMOD_API int (luaopen_jit) (lua_State *L); 50 | #endif 51 | 52 | 53 | /* open all previous libraries */ 54 | LUALIB_API void (luaL_openlibs) (lua_State *L); 55 | 56 | 57 | 58 | #if !defined(lua_assert) 59 | #define lua_assert(x) ((void)0) 60 | #endif 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/lundump.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lundump.h,v 1.45 2015/09/08 15:41:05 roberto Exp $ 3 | ** load precompiled Lua chunks 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lundump_h 8 | #define lundump_h 9 | 10 | #include "llimits.h" 11 | #include "lobject.h" 12 | #include "lzio.h" 13 | 14 | 15 | /* data to catch conversion errors */ 16 | #define LUAC_DATA "\x19\x93\r\n\x1a\n" 17 | 18 | #define LUAC_INT 0x5678 19 | #define LUAC_NUM cast_num(370.5) 20 | 21 | #define MYINT(s) (s[0]-'0') 22 | #define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)) 23 | #define LUAC_FORMAT 0 /* this is the official format */ 24 | 25 | /* load one chunk; from lundump.c */ 26 | LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); 27 | 28 | /* dump one chunk; from ldump.c */ 29 | LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, 30 | void* data, int strip); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/lvm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lvm.h,v 2.40 2016/01/05 16:07:21 roberto Exp $ 3 | ** Lua virtual machine 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lvm_h 8 | #define lvm_h 9 | 10 | 11 | #include "ldo.h" 12 | #include "lobject.h" 13 | #include "ltm.h" 14 | 15 | 16 | #if !defined(LUA_NOCVTN2S) 17 | #define cvt2str(o) ttisnumber(o) 18 | #else 19 | #define cvt2str(o) 0 /* no conversion from numbers to strings */ 20 | #endif 21 | 22 | 23 | #if !defined(LUA_NOCVTS2N) 24 | #define cvt2num(o) ttisstring(o) 25 | #else 26 | #define cvt2num(o) 0 /* no conversion from strings to numbers */ 27 | #endif 28 | 29 | 30 | /* 31 | ** You can define LUA_FLOORN2I if you want to convert floats to integers 32 | ** by flooring them (instead of raising an error if they are not 33 | ** integral values) 34 | */ 35 | #if !defined(LUA_FLOORN2I) 36 | #define LUA_FLOORN2I 0 37 | #endif 38 | 39 | 40 | #define tonumber(o,n) \ 41 | (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) 42 | 43 | #define tointeger(o,i) \ 44 | (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I)) 45 | 46 | #define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) 47 | 48 | #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) 49 | 50 | 51 | /* 52 | ** fast track for 'gettable': if 't' is a table and 't[k]' is not nil, 53 | ** return 1 with 'slot' pointing to 't[k]' (final result). Otherwise, 54 | ** return 0 (meaning it will have to check metamethod) with 'slot' 55 | ** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise). 56 | ** 'f' is the raw get function to use. 57 | */ 58 | #define luaV_fastget(L,t,k,slot,f) \ 59 | (!ttistable(t) \ 60 | ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ 61 | : (slot = f(hvalue(t), k), /* else, do raw access */ \ 62 | !ttisnil(slot))) /* result not nil? */ 63 | 64 | /* 65 | ** standard implementation for 'gettable' 66 | */ 67 | #define luaV_gettable(L,t,k,v) { const TValue *slot; \ 68 | if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ 69 | else luaV_finishget(L,t,k,v,slot); } 70 | 71 | 72 | /* 73 | ** Fast track for set table. If 't' is a table and 't[k]' is not nil, 74 | ** call GC barrier, do a raw 't[k]=v', and return true; otherwise, 75 | ** return false with 'slot' equal to NULL (if 't' is not a table) or 76 | ** 'nil'. (This is needed by 'luaV_finishget'.) Note that, if the macro 77 | ** returns true, there is no need to 'invalidateTMcache', because the 78 | ** call is not creating a new entry. 79 | */ 80 | #define luaV_fastset(L,t,k,slot,f,v) \ 81 | (!ttistable(t) \ 82 | ? (slot = NULL, 0) \ 83 | : (slot = f(hvalue(t), k), \ 84 | ttisnil(slot) ? 0 \ 85 | : (luaC_barrierback(L, hvalue(t), v), \ 86 | setobj2t(L, cast(TValue *,slot), v), \ 87 | 1))) 88 | 89 | 90 | #define luaV_settable(L,t,k,v) { const TValue *slot; \ 91 | if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ 92 | luaV_finishset(L,t,k,v,slot); } 93 | 94 | 95 | 96 | LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); 97 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); 98 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); 99 | LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); 100 | LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); 101 | LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, 102 | StkId val, const TValue *slot); 103 | LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, 104 | StkId val, const TValue *slot); 105 | LUAI_FUNC void luaV_finishOp (lua_State *L); 106 | LUAI_FUNC void luaV_execute (lua_State *L); 107 | LUAI_FUNC void luaV_concat (lua_State *L, int total); 108 | LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); 109 | LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); 110 | LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); 111 | LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /src/lzio.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lzio.c,v 1.37 2015/09/08 15:41:05 roberto Exp $ 3 | ** Buffered streams 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lzio_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "llimits.h" 18 | #include "lmem.h" 19 | #include "lstate.h" 20 | #include "lzio.h" 21 | 22 | 23 | int luaZ_fill (ZIO *z) { 24 | size_t size; 25 | lua_State *L = z->L; 26 | const char *buff; 27 | lua_unlock(L); 28 | buff = z->reader(L, z->data, &size); 29 | lua_lock(L); 30 | if (buff == NULL || size == 0) 31 | return EOZ; 32 | z->n = size - 1; /* discount char being returned */ 33 | z->p = buff; 34 | return cast_uchar(*(z->p++)); 35 | } 36 | 37 | 38 | void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { 39 | z->L = L; 40 | z->reader = reader; 41 | z->data = data; 42 | z->n = 0; 43 | z->p = NULL; 44 | } 45 | 46 | 47 | /* --------------------------------------------------------------- read --- */ 48 | size_t luaZ_read (ZIO *z, void *b, size_t n) { 49 | while (n) { 50 | size_t m; 51 | if (z->n == 0) { /* no bytes in buffer? */ 52 | if (luaZ_fill(z) == EOZ) /* try to read more */ 53 | return n; /* no more input; return number of missing bytes */ 54 | else { 55 | z->n++; /* luaZ_fill consumed first byte; put it back */ 56 | z->p--; 57 | } 58 | } 59 | m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ 60 | memcpy(b, z->p, m); 61 | z->n -= m; 62 | z->p += m; 63 | b = (char *)b + m; 64 | n -= m; 65 | } 66 | return 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/lzio.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lzio.h,v 1.31 2015/09/08 15:41:05 roberto Exp $ 3 | ** Buffered streams 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lzio_h 9 | #define lzio_h 10 | 11 | #include "lua.h" 12 | 13 | #include "lmem.h" 14 | 15 | 16 | #define EOZ (-1) /* end of stream */ 17 | 18 | typedef struct Zio ZIO; 19 | 20 | #define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) 21 | 22 | 23 | typedef struct Mbuffer { 24 | char *buffer; 25 | size_t n; 26 | size_t buffsize; 27 | } Mbuffer; 28 | 29 | #define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) 30 | 31 | #define luaZ_buffer(buff) ((buff)->buffer) 32 | #define luaZ_sizebuffer(buff) ((buff)->buffsize) 33 | #define luaZ_bufflen(buff) ((buff)->n) 34 | 35 | #define luaZ_buffremove(buff,i) ((buff)->n -= (i)) 36 | #define luaZ_resetbuffer(buff) ((buff)->n = 0) 37 | 38 | 39 | #define luaZ_resizebuffer(L, buff, size) \ 40 | ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \ 41 | (buff)->buffsize, size), \ 42 | (buff)->buffsize = size) 43 | 44 | #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) 45 | 46 | 47 | LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, 48 | void *data); 49 | LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ 50 | 51 | 52 | 53 | /* --------- Private Part ------------------ */ 54 | 55 | struct Zio { 56 | size_t n; /* bytes still unread */ 57 | const char *p; /* current position in buffer */ 58 | lua_Reader reader; /* reader function */ 59 | void *data; /* additional data */ 60 | lua_State *L; /* Lua state (for reader) */ 61 | }; 62 | 63 | 64 | LUAI_FUNC int luaZ_fill (ZIO *z); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | if jit and jit.logger then jit.logger('all') end 2 | 3 | local a = 0 4 | for i = 1, 100 do a = a + i end 5 | print(a) 6 | --------------------------------------------------------------------------------