aboutsummaryrefslogtreecommitdiff
path: root/compat53.lua
diff options
context:
space:
mode:
authorPhilipp Janda <siffiejoe@gmx.net>2015-01-17 20:36:32 +0100
committerPhilipp Janda <siffiejoe@gmx.net>2015-01-17 20:36:32 +0100
commit4c062846ae003dd747dfcd3eca91493c7eee4f50 (patch)
tree583f36eab79954b8bb354d81f4f08cf1472be2b5 /compat53.lua
parent64783408a4a108812f22268c12f71c75f5399d81 (diff)
downloadlua-compat-5.3-4c062846ae003dd747dfcd3eca91493c7eee4f50.tar.gz
lua-compat-5.3-4c062846ae003dd747dfcd3eca91493c7eee4f50.tar.bz2
lua-compat-5.3-4c062846ae003dd747dfcd3eca91493c7eee4f50.zip
table library (except table.sort for now) respects metamethods
Diffstat (limited to 'compat53.lua')
-rw-r--r--compat53.lua158
1 files changed, 147 insertions, 11 deletions
diff --git a/compat53.lua b/compat53.lua
index 8bf6bd8..761d554 100644
--- a/compat53.lua
+++ b/compat53.lua
@@ -1,12 +1,31 @@
1local lua_version = _VERSION:sub(-3) 1local lua_version = _VERSION:sub(-3)
2 2
3if lua_version ~= "5.3" then 3if lua_version < "5.3" then
4 local _type = type 4 -- local aliases for commonly used functions
5 local type, select, error = type, select, error
6
5 -- select the most powerful getmetatable function available 7 -- select the most powerful getmetatable function available
6 local gmt = _type(debug) == "table" and debug.getmetatable or 8 local gmt = type(debug) == "table" and debug.getmetatable or
7 getmetatable or function() return false end 9 getmetatable or function() return false end
10
11 -- type checking functions
8 local checkinteger -- forward declararation 12 local checkinteger -- forward declararation
9 13
14 local function argcheck(cond, i, f, extra)
15 if not cond then
16 error("bad argument #"..i.." to '"..f.."' ("..extra..")", 0)
17 end
18 end
19
20 local function checktype(x, t, i, f)
21 local xt = type(x)
22 if xt ~= t then
23 error("bad argument #"..i.." to '"..f.."' ("..t..
24 " expected, got "..xt..")", 0)
25 end
26 end
27
28
10 -- load utf8 library 29 -- load utf8 library
11 local ok, utf8lib = pcall(require, "compat53.utf8") 30 local ok, utf8lib = pcall(require, "compat53.utf8")
12 if ok then 31 if ok then
@@ -17,6 +36,7 @@ if lua_version ~= "5.3" then
17 end 36 end
18 end 37 end
19 38
39
20 -- use Roberto's struct module for string packing/unpacking for now 40 -- use Roberto's struct module for string packing/unpacking for now
21 -- maybe we'll later extract the functions from the 5.3 string 41 -- maybe we'll later extract the functions from the 5.3 string
22 -- library for greater compatiblity, but it uses the 5.3 buffer API 42 -- library for greater compatiblity, but it uses the 5.3 buffer API
@@ -47,14 +67,14 @@ if lua_version ~= "5.3" then
47 math.mininteger = minint 67 math.mininteger = minint
48 68
49 function math.tointeger(n) 69 function math.tointeger(n)
50 if _type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then 70 if type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then
51 return n 71 return n
52 end 72 end
53 return nil 73 return nil
54 end 74 end
55 75
56 function math.type(n) 76 function math.type(n)
57 if _type(n) == "number" then 77 if type(n) == "number" then
58 if n <= maxint and n >= minint and n % 1 == 0 then 78 if n <= maxint and n >= minint and n % 1 == 0 then
59 return "integer" 79 return "integer"
60 else 80 else
@@ -65,15 +85,14 @@ if lua_version ~= "5.3" then
65 end 85 end
66 end 86 end
67 87
68 local _error = error
69 function checkinteger(x, i, f) 88 function checkinteger(x, i, f)
70 local t = _type(x) 89 local t = type(x)
71 if t ~= "number" then 90 if t ~= "number" then
72 _error("bad argument #"..i.." to '"..f.. 91 error("bad argument #"..i.." to '"..f..
73 "' (number expected, got "..t..")", 0) 92 "' (number expected, got "..t..")", 0)
74 elseif x > maxint or x < minint or x % 1 ~= 0 then 93 elseif x > maxint or x < minint or x % 1 ~= 0 then
75 _error("bad argument #"..i.." to '"..f.. 94 error("bad argument #"..i.." to '"..f..
76 "' (number has no integer representation)", 0) 95 "' (number has no integer representation)", 0)
77 else 96 else
78 return x 97 return x
79 end 98 end
@@ -112,6 +131,123 @@ if lua_version ~= "5.3" then
112 end 131 end
113 end 132 end
114 133
134
135 -- update table library
136 do
137 local table_concat = table.concat
138 function table.concat(list, sep, i, j)
139 local mt = gmt(list)
140 if type(mt) == "table" and type(mt.__len) == "function" then
141 local src = list
142 list, i, j = {}, i or 1, j or mt.__len(src)
143 for k = i, j do
144 list[k] = src[k]
145 end
146 end
147 return table_concat(list, sep, i, j)
148 end
149
150 local table_insert = table.insert
151 function table.insert(list, ...)
152 local mt = gmt(list)
153 local has_mt = type(mt) == "table"
154 local has_len = has_mt and type(mt.__len) == "function"
155 if has_mt and (has_len or mt.__index or mt.__newindex) then
156 local e = (has_len and mt.__len(list) or #list)+1
157 local nargs, pos, value = select('#', ...), ...
158 if nargs == 1 then
159 pos, value = e, pos
160 elseif nargs == 2 then
161 pos = checkinteger(pos, "2", "table.insert")
162 argcheck(1 <= pos and pos <= e, "2", "table.insert",
163 "position out of bounds" )
164 else
165 error("wrong number of arguments to 'insert'", 0)
166 end
167 for i = e-1, pos, -1 do
168 list[i+1] = list[i]
169 end
170 list[pos] = value
171 else
172 return table_insert(list, ...)
173 end
174 end
175
176 function table.move(a1, f, e, t, a2)
177 a2 = a2 or a1
178 f = checkinteger(f, "2", "table.move")
179 argcheck(f > 0, "2", "table.move",
180 "initial position must be positive")
181 e = checkinteger(e, "3", "table.move")
182 t = checkinteger(t, "4", "table.move")
183 if e >= f then
184 local m, n, d = 0, e-f, 1
185 if t > f then m, n, d = n, m, -1 end
186 for i = m, n, d do
187 a2[t+i] = a1[f+i]
188 end
189 end
190 return a2
191 end
192
193 local table_remove = table.remove
194 function table.remove(list, pos)
195 local mt = gmt(list)
196 local has_mt = type(mt) == "table"
197 local has_len = has_mt and type(mt.__len) == "function"
198 if has_mt and (has_len or mt.__index or mt.__newindex) then
199 local e = (has_len and mt.__len(list) or #list)
200 pos = pos ~= nil and checkinteger(pos, "2", "table.remove") or e
201 if pos ~= e then
202 argcheck(1 <= pos and pos <= e+1, "2", "table.remove",
203 "position out of bounds" )
204 end
205 local result = list[pos]
206 while pos < e do
207 list[pos] = list[pos+1]
208 pos = pos + 1
209 end
210 list[pos] = nil
211 return result
212 else
213 return table_remove(list, pos)
214 end
215 end
216
217 -- TODO: table.sort
218
219 local table_unpack = lua_version == "5.1" and unpack or table.unpack
220 local function unpack_helper(list, i, j, ...)
221 if j < i then
222 return ...
223 else
224 return unpack_helper(list, i, j-1, list[j], ...)
225 end
226 end
227 function table.unpack(list, i, j)
228 local mt = gmt(list)
229 local has_mt = type(mt) == "table"
230 local has_len = has_mt and type(mt.__len) == "function"
231 if has_mt and (has_len or mt.__index) then
232 i, j = i or 1, j or (has_len and mt.__len(list)) or #list
233 return unpack_helper(list, i, j)
234 else
235 return table_unpack(list, i, j)
236 end
237 end
238 end
239
240
241 if lua_version == "5.1" then
242 -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag)
243 local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ"
244 local is_luajit52 = is_luajit and
245 #setmetatable({}, { __len = function() return 1 end }) == 1
246
247 -- TODO: add functions from lua-compat-5.2
248
249 end
250
115end 251end
116 252
117-- vi: set expandtab softtabstop=3 shiftwidth=3 : 253-- vi: set expandtab softtabstop=3 shiftwidth=3 :