diff options
author | Philipp Janda <siffiejoe@gmx.net> | 2015-01-17 20:36:32 +0100 |
---|---|---|
committer | Philipp Janda <siffiejoe@gmx.net> | 2015-01-17 20:36:32 +0100 |
commit | 4c062846ae003dd747dfcd3eca91493c7eee4f50 (patch) | |
tree | 583f36eab79954b8bb354d81f4f08cf1472be2b5 /compat53.lua | |
parent | 64783408a4a108812f22268c12f71c75f5399d81 (diff) | |
download | lua-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.lua | 158 |
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 @@ | |||
1 | local lua_version = _VERSION:sub(-3) | 1 | local lua_version = _VERSION:sub(-3) |
2 | 2 | ||
3 | if lua_version ~= "5.3" then | 3 | if 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 | |||
115 | end | 251 | end |
116 | 252 | ||
117 | -- vi: set expandtab softtabstop=3 shiftwidth=3 : | 253 | -- vi: set expandtab softtabstop=3 shiftwidth=3 : |