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 : |
