集成 github.com/vadv/gopher-lua-libs, 并支持 dkjson

This commit is contained in:
白茶清欢 2025-05-12 16:40:33 +08:00
parent a95acc7e36
commit 3253191437
14 changed files with 2811 additions and 4 deletions

105
lib/builtin.lua Normal file
View File

@ -0,0 +1,105 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
-- Built-in Types
---
--- The type *nil* has one single value, **nil**, whose main property is to be
--- different from any other value; it usually represents the absence of a
--- useful value.
---@class nil
---
--- The type *boolean* has two values, **false** and **true**. Both **nil** and
--- **false** make a condition false; any other value makes it true.
---@class boolean
---
--- The type *number* uses two internal representations, or two subtypes, one
--- called *integer* and the other called *float*. Lua has explicit rules about
--- when each representation is used, but it also converts between them
--- automatically as needed. Therefore, the programmer may choose to mostly
--- ignore the difference between integers and floats or to assume complete
--- control over the representation of each number. Standard Lua uses 64-bit
--- integers and double-precision (64-bit) floats, but you can also compile
--- Lua so that it uses 32-bit integers and/or single-precision (32-bit)
--- floats. The option with 32 bits for both integers and floats is
--- particularly attractive for small machines and embedded systems. (See
--- macro LUA_32BITS in file luaconf.h.)
---@class number
---
--- Lua can call (and manipulate) functions written in Lua and functions
--- written in C. Both are represented by the type *function*.
---@class function
---
--- The type *userdata* is provided to allow arbitrary C data to be stored in
--- Lua variables. A userdata value represents a block of raw memory. There
--- are two kinds of userdata: *full userdata*, which is an object with a block
--- of memory managed by Lua, and *light userdata*, which is simply a C pointer
--- value. Userdata has no predefined operations in Lua, except assignment
--- and identity test. By using *metatables*, the programmer can define
--- operations for full userdata values. Userdata values cannot be
--- created or modified in Lua, only through the C API. This guarantees the
--- integrity of data owned by the host program.
---@class userdata
---
--- The type *thread* represents independent threads of execution and it is
--- used to implement coroutines. Lua threads are not related to
--- operating-system threads. Lua supports coroutines on all systems, even those
--- that do not support threads natively.
---@class thread
---
--- The type *table* implements associative arrays, that is, arrays that can
--- have as indices not only numbers, but any Lua value except **nil** and NaN.
--- (*Not a Number* is a special floating-point value used by the IEEE 754
--- standard to represent undefined or unrepresentable numerical results, such
--- as `0/0`.) Tables can be heterogeneous; that is, they can contain values of
--- all types (except **nil**). Any key with value **nil** is not considered
--- part oft he table. Conversely, any key that is not part of a table has an
--- a ssociated value **nil**.
---
--- Tables are the sole data-structuring mechanism in Lua; they can be used to
--- represent ordinary arrays, lists, symbol tables, sets, records, graphs,
--- trees, etc. To represent records, Lua uses the field name as an index. The
--- language supports this representation by providing `a.name` as syntactic
--- sugar for `a["name"]`. There are several convenient ways to create tables
--- in Lua.
---
--- Like indices, the values of table fields can be of any type. In particular,
--- because functions are first-class values, table fields can contain functions.
--- Thus tables can also carry *methods*.
---
--- The indexing of tables follows the definition of raw equality in the
--- language. The expressions `a[i]` and `a[j]` denote the same table element
--- if and only if `i` and `j` are raw equal (that is, equal without
--- metamethods). In particular, floats with integral values are equal to
--- their respective integers. To avoid ambiguities, any float with integral
--- value used as a key is converted to its respective integer. For instance,
--- if you write `a[2.0] = true`, the actual key inserted into the table will
--- be the integer `2`. (On the other hand, 2 and "`2`" are different Lua
--- values and therefore denote different table entries.)
---@class table
---
--- Any of the above Built-in Types.
---@class any
---
---@class void
---@class self

80
lib/coroutine.lua Normal file
View File

@ -0,0 +1,80 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
coroutine = {}
---
--- Creates a new coroutine, with body `f`. `f` must be a Lua function. Returns
--- this new coroutine, an object with type `"thread"`.
---@param f fun():thread
---@return thread
function coroutine.create(f) end
---
--- Returns true when the running coroutine can yield.
---
--- A running coroutine is yieldable if it is not the main thread and it is not
--- inside a non-yieldable C function.
---@return boolean
function coroutine.isyieldable() end
---
--- Starts or continues the execution of coroutine `co`. The first time you
--- resume a coroutine, it starts running its body. The values `val1`, ...
--- are passed as the arguments to the body function. If the coroutine has
--- yielded, `resume` restarts it; the values `val1`, ... are passed as the
--- results from the yield.
---
--- If the coroutine runs without any errors, `resume` returns **true** plus any
--- values passed to `yield` (when the coroutine yields) or any values returned
--- by the body function (when the coroutine terminates). If there is any error,
--- `resume` returns **false** plus the error message.
---@overload fun(co:thread):boolean|any
---@param co thread
---@param val1 string
---@return thread|any
function coroutine.resume(co, val1, ...) end
---
--- Returns the running coroutine plus a boolean, true when the running
--- coroutine is the main one.
---@return thread|boolean
function coroutine.running() end
---
--- Returns the status of coroutine `co`, as a string: "`running`", if the
--- coroutine is running (that is, it called `status`); "`suspended`", if the
--- coroutine is suspended in a call to `yield`, or if it has not started
--- running yet; "`normal`" if the coroutine is active but not running (that
--- is, it has resumed another coroutine); and "`dead`" if the coroutine has
--- finished its body function, or if it has stopped with an error.
---@param co thread
---@return string
function coroutine.status(co) end
---
--- Creates a new coroutine, with body `f`. `f` must be a Lua function. Returns
--- a function that resumes the coroutine each time it is called. Any arguments
--- passed to the function behave as the extra arguments to `resume`. Returns
--- the same values returned by `resume`, except the first
--- boolean. In case of error, propagates the error.
---@param f fun():thread
---@return fun():any
function coroutine.wrap(f) end
---
--- Suspends the execution of the calling coroutine. Any arguments to `yield`
--- are passed as extra results to `resume`.
---@return any
function coroutine.yield(...) end

239
lib/debug.lua Normal file
View File

@ -0,0 +1,239 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
debug = {}
---
--- Enters an interactive mode with the user, running each string that the user
--- enters. Using simple commands and other debug facilities, the user can
--- inspect global and local variables, change their values, evaluate
--- expressions, and so on. A line containing only the word `cont` finishes this
--- function, so that the caller continues its execution.
---
--- Note that commands for `debug.debug` are not lexically nested within any
--- function, and so have no direct access to local variables.
function debug.debug() end
---
--- Returns the current hook settings of the thread, as three values: the
--- current hook function, the current hook mask, and the current hook count
--- (as set by the `debug.sethook` function).
---@overload fun():thread
---@param thread thread
---@return thread
function debug.gethook(thread) end
---@class DebugInfo
---@field linedefined number
---@field lastlinedefined number
---@field currentline number
---@field func function
---@field isvararg boolean
---@field namewhat string
---@field source string
---@field nups number
---@field what string
---@field nparams number
---@field short_src string
---
--- Returns a table with information about a function. You can give the
--- function directly, or you can give a number as the value of `f`,
--- which means the function running at level `f` of the call stack
--- of the given thread: level 0 is the current function (`getinfo` itself);
--- level 1 is the function that called `getinfo` (except for tail calls, which
--- do not count on the stack); and so on. If `f` is a number larger than
--- the number of active functions, then `getinfo` returns **nil**.
---
--- The returned table can contain all the fields returned by `lua_getinfo`,
--- with the string `what` describing which fields to fill in. The default for
--- `what` is to get all information available, except the table of valid
--- lines. If present, the option '`f`' adds a field named `func` with the
--- function itself. If present, the option '`L`' adds a field named
--- `activelines` with the table of valid lines.
---
--- For instance, the expression `debug.getinfo(1,"n").name` returns a table
--- with a name for the current function, if a reasonable name can be found,
--- and the expression `debug.getinfo(print)` returns a table with all available
--- information about the `print` function.
---@overload fun(f:function):DebugInfo
---@param thread thread
---@param f function
---@param what string
---@return DebugInfo
function debug.getinfo(thread, f, what) end
---
--- This function returns the name and the value of the local variable with
--- index `local` of the function at level `level f` of the stack. This function
--- accesses not only explicit local variables, but also parameters,
--- temporaries, etc.
---
--- The first parameter or local variable has index 1, and so on, following the
--- order that they are declared in the code, counting only the variables that
--- are active in the current scope of the function. Negative indices refer to
--- vararg parameters; -1 is the first vararg parameter. The function returns
--- **nil** if there is no variable with the given index, and raises an error
--- when called with a level out of range. (You can call `debug.getinfo` to
--- check whether the level is valid.)
---
--- Variable names starting with '(' (open parenthesis) represent variables with
--- no known names (internal variables such as loop control variables, and
--- variables from chunks saved without debug information).
---
--- The parameter `f` may also be a function. In that case, `getlocal` returns
--- only the name of function parameters.
---@overload fun(f:table, var:string):table
---@param thread thread
---@param f table
---@param var string
---@return table
function debug.getlocal(thread, f, var) end
---
--- Returns the metatable of the given `value` or **nil** if it does not have
--- a metatable.
---@param value table
---@return table
function debug.getmetatable(value) end
---
--- Returns the registry table.
---@return table
function debug.getregistry() end
---
--- This function returns the name and the value of the upvalue with index
--- `up` of the function `f`. The function returns **nil** if there is no
--- upvalue with the given index.
---
--- Variable names starting with '(' (open parenthesis) represent variables with
--- no known names (variables from chunks saved without debug information).
---@param f number
---@param up number
---@return table
function debug.getupvalue(f, up) end
---
--- Returns the `n`-th user value associated to the userdata `u` plus a boolean,
--- **false** if the userdata does not have that value.
---@param u userdata
---@param n number
---@return boolean
function debug.getuservalue(u, n) end
---
--- Sets the given function as a hook. The string `mask` and the number `count`
--- describe when the hook will be called. The string mask may have any
--- combination of the following characters, with the given meaning:
---
--- * `"c"`: the hook is called every time Lua calls a function;
--- * `"r"`: the hook is called every time Lua returns from a function;
--- * `"l"`: the hook is called every time Lua enters a new line of code.
---
--- Moreover, with a `count` different from zero, the hook is called after every
--- `count` instructions.
---
--- When called without arguments, `debug.sethook` turns off the hook.
---
--- When the hook is called, its first parameter is a string describing
--- the event that has triggered its call: `"call"`, (or `"tail
--- call"`), `"return"`, `"line"`, and `"count"`. For line events, the hook also
--- gets the new line number as its second parameter. Inside a hook, you can
--- call `getinfo` with level 2 to get more information about the running
--- function (level 0 is the `getinfo` function, and level 1 is the hook
--- function)
---@overload fun(hook:(fun():any), mask:any)
---@param thread thread
---@param hook fun():any
---@param mask string
---@param count number
function debug.sethook(thread, hook, mask, count) end
---
--- This function assigns the value `value` to the local variable with
--- index `local` of the function at level `level` of the stack. The function
--- returns **nil** if there is no local variable with the given index, and
--- raises an error when called with a `level` out of range. (You can call
--- `getinfo` to check whether the level is valid.) Otherwise, it returns the
--- name of the local variable.
---@overload fun(level:number, var:string, value:any):string
---@param thread thread
---@param level number
---@param var string
---@param value any
---@return string
function debug.setlocal(thread, level, var, value) end
---
--- Sets the metatable for the given `object` to the given `table` (which
--- can be **nil**). Returns value.
---@param value any
---@param table table
---@return boolean
function debug.setmetatable(value, table) end
---
--- This function assigns the value `value` to the upvalue with index `up`
--- of the function `f`. The function returns **nil** if there is no upvalue
--- with the given index. Otherwise, it returns the name of the upvalue.
---@param f fun():any
---@param up number
---@param value any
---@return string
function debug.setupvalue(f, up, value) end
--- Sets the given `value` as the `n`-th associated to the given `udata`.
--- `udata` must be a full userdata.
---
--- Returns `udata`, or **nil** if the userdata does not have that value.
---@param udata userdata
---@param value any
---@param n number
---@return userdata
function debug.setuservalue(udata, value, n) end
--- If `message` is present but is neither a string nor **nil**, this function
--- returns `message` without further processing. Otherwise, it returns a string
--- with a traceback of the call stack. The optional `message` string is
--- appended at the beginning of the traceback. An optional level number
--- `tells` at which level to start the traceback (default is 1, the function
--- c alling `traceback`).
---@overload fun():string
---@param thread thread
---@param message string
---@param level number
---@return string
function debug.traceback(thread, message, level) end
--- Returns a unique identifier (as a light userdata) for the upvalue numbered
--- `n` from the given function.
---
--- These unique identifiers allow a program to check whether different
--- closures share upvalues. Lua closures that share an upvalue (that is, that
--- access a same external local variable) will return identical ids for those
--- upvalue indices.
---@param f fun():number
---@param n number
---@return number
function debug.upvalueid(f, n) end
---
--- Make the `n1`-th upvalue of the Lua closure f1 refer to the `n2`-th upvalue
--- of the Lua closure f2.
---@param f1 fun():any
---@param n1 number
---@param f2 fun():any
---@param n2 number
function debug.upvaluejoin(f1, n1, f2, n2) end

713
lib/dkjson.lua Normal file
View File

@ -0,0 +1,713 @@
-- Module options:
local always_try_using_lpeg = true
local register_global_module_table = false
local global_module_name = 'json'
--[==[
David Kolf's JSON module for Lua 5.1/5.2
Version 2.5
For the documentation see the corresponding readme.txt or visit
<http://dkolf.de/src/dkjson-lua.fsl/>.
You can contact the author by sending an e-mail to 'david' at the
domain 'dkolf.de'.
Copyright (C) 2010-2014 David Heiko Kolf
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]==]
-- global dependencies:
local pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset =
pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset
local error, require, pcall, select = error, require, pcall, select
local floor, huge = math.floor, math.huge
local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat =
string.rep, string.gsub, string.sub, string.byte, string.char,
string.find, string.len, string.format
local strmatch = string.match
local concat = table.concat
local json = { version = "dkjson 2.5" }
if register_global_module_table then
_G[global_module_name] = json
end
local _ENV = nil -- blocking globals in Lua 5.2
pcall (function()
-- Enable access to blocked metatables.
-- Don't worry, this module doesn't change anything in them.
local debmeta = require "debug".getmetatable
if debmeta then getmetatable = debmeta end
end)
json.null = setmetatable ({}, {
__tojson = function () return "null" end
})
local function isarray (tbl)
local max, n, arraylen = 0, 0, 0
for k,v in pairs (tbl) do
if k == 'n' and type(v) == 'number' then
arraylen = v
if v > max then
max = v
end
else
if type(k) ~= 'number' or k < 1 or floor(k) ~= k then
return false
end
if k > max then
max = k
end
n = n + 1
end
end
if max > 10 and max > arraylen and max > n * 2 then
return false -- don't create an array with too many holes
end
return true, max
end
local escapecodes = {
["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f",
["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t"
}
local function escapeutf8 (uchar)
local value = escapecodes[uchar]
if value then
return value
end
local a, b, c, d = strbyte (uchar, 1, 4)
a, b, c, d = a or 0, b or 0, c or 0, d or 0
if a <= 0x7f then
value = a
elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then
value = (a - 0xc0) * 0x40 + b - 0x80
elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then
value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80
elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then
value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80
else
return ""
end
if value <= 0xffff then
return strformat ("\\u%.4x", value)
elseif value <= 0x10ffff then
-- encode as UTF-16 surrogate pair
value = value - 0x10000
local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400)
return strformat ("\\u%.4x\\u%.4x", highsur, lowsur)
else
return ""
end
end
local function fsub (str, pattern, repl)
-- gsub always builds a new string in a buffer, even when no match
-- exists. First using find should be more efficient when most strings
-- don't contain the pattern.
if strfind (str, pattern) then
return gsub (str, pattern, repl)
else
return str
end
end
local function quotestring (value)
-- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8)
if strfind (value, "[\194\216\220\225\226\239]") then
value = fsub (value, "\194[\128-\159\173]", escapeutf8)
value = fsub (value, "\216[\128-\132]", escapeutf8)
value = fsub (value, "\220\143", escapeutf8)
value = fsub (value, "\225\158[\180\181]", escapeutf8)
value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8)
value = fsub (value, "\226\129[\160-\175]", escapeutf8)
value = fsub (value, "\239\187\191", escapeutf8)
value = fsub (value, "\239\191[\176-\191]", escapeutf8)
end
return "\"" .. value .. "\""
end
json.quotestring = quotestring
local function replace(str, o, n)
local i, j = strfind (str, o, 1, true)
if i then
return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1)
else
return str
end
end
-- locale independent num2str and str2num functions
local decpoint, numfilter
local function updatedecpoint ()
decpoint = strmatch(tostring(0.5), "([^05+])")
-- build a filter that can be used to remove group separators
numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+"
end
updatedecpoint()
local function num2str (num)
return replace(fsub(tostring(num), numfilter, ""), decpoint, ".")
end
local function str2num (str)
local num = tonumber(replace(str, ".", decpoint))
if not num then
updatedecpoint()
num = tonumber(replace(str, ".", decpoint))
end
return num
end
local function addnewline2 (level, buffer, buflen)
buffer[buflen+1] = "\n"
buffer[buflen+2] = strrep (" ", level)
buflen = buflen + 2
return buflen
end
function json.addnewline (state)
if state.indent then
state.bufferlen = addnewline2 (state.level or 0,
state.buffer, state.bufferlen or #(state.buffer))
end
end
local encode2 -- forward declaration
local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state)
local kt = type (key)
if kt ~= 'string' and kt ~= 'number' then
return nil, "type '" .. kt .. "' is not supported as a key by JSON."
end
if prev then
buflen = buflen + 1
buffer[buflen] = ","
end
if indent then
buflen = addnewline2 (level, buffer, buflen)
end
buffer[buflen+1] = quotestring (key)
buffer[buflen+2] = ":"
return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder, state)
end
local function appendcustom(res, buffer, state)
local buflen = state.bufferlen
if type (res) == 'string' then
buflen = buflen + 1
buffer[buflen] = res
end
return buflen
end
local function exception(reason, value, state, buffer, buflen, defaultmessage)
defaultmessage = defaultmessage or reason
local handler = state.exception
if not handler then
return nil, defaultmessage
else
state.bufferlen = buflen
local ret, msg = handler (reason, value, state, defaultmessage)
if not ret then return nil, msg or defaultmessage end
return appendcustom(ret, buffer, state)
end
end
function json.encodeexception(reason, value, state, defaultmessage)
return quotestring("<" .. defaultmessage .. ">")
end
encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, state)
local valtype = type (value)
local valmeta = getmetatable (value)
valmeta = type (valmeta) == 'table' and valmeta -- only tables
local valtojson = valmeta and valmeta.__tojson
if valtojson then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
state.bufferlen = buflen
local ret, msg = valtojson (value, state)
if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end
tables[value] = nil
buflen = appendcustom(ret, buffer, state)
elseif value == nil then
buflen = buflen + 1
buffer[buflen] = "null"
elseif valtype == 'number' then
local s
if value ~= value or value >= huge or -value >= huge then
-- This is the behaviour of the original JSON implementation.
s = "null"
else
s = num2str (value)
end
buflen = buflen + 1
buffer[buflen] = s
elseif valtype == 'boolean' then
buflen = buflen + 1
buffer[buflen] = value and "true" or "false"
elseif valtype == 'string' then
buflen = buflen + 1
buffer[buflen] = quotestring (value)
elseif valtype == 'table' then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
level = level + 1
local isa, n = isarray (value)
if n == 0 and valmeta and valmeta.__jsontype == 'object' then
isa = false
end
local msg
if isa then -- JSON array
buflen = buflen + 1
buffer[buflen] = "["
for i = 1, n do
buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
if i < n then
buflen = buflen + 1
buffer[buflen] = ","
end
end
buflen = buflen + 1
buffer[buflen] = "]"
else -- JSON object
local prev = false
buflen = buflen + 1
buffer[buflen] = "{"
local order = valmeta and valmeta.__jsonorder or globalorder
if order then
local used = {}
n = #order
for i = 1, n do
local k = order[i]
local v = value[k]
if v then
used[k] = true
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
prev = true -- add a seperator before the next element
end
end
for k,v in pairs (value) do
if not used[k] then
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
else -- unordered
for k,v in pairs (value) do
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
if indent then
buflen = addnewline2 (level - 1, buffer, buflen)
end
buflen = buflen + 1
buffer[buflen] = "}"
end
tables[value] = nil
else
return exception ('unsupported type', value, state, buffer, buflen,
"type '" .. valtype .. "' is not supported by JSON.")
end
return buflen
end
function json.encode (value, state)
state = state or {}
local oldbuffer = state.buffer
local buffer = oldbuffer or {}
state.buffer = buffer
updatedecpoint()
local ret, msg = encode2 (value, state.indent, state.level or 0,
buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state)
if not ret then
error (msg, 2)
elseif oldbuffer == buffer then
state.bufferlen = ret
return true
else
state.bufferlen = nil
state.buffer = nil
return concat (buffer)
end
end
local function loc (str, where)
local line, pos, linepos = 1, 1, 0
while true do
pos = strfind (str, "\n", pos, true)
if pos and pos < where then
line = line + 1
linepos = pos
pos = pos + 1
else
break
end
end
return "line " .. line .. ", column " .. (where - linepos)
end
local function unterminated (str, what, where)
return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where)
end
local function scanwhite (str, pos)
while true do
pos = strfind (str, "%S", pos)
if not pos then return nil end
local sub2 = strsub (str, pos, pos + 1)
if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then
-- UTF-8 Byte Order Mark
pos = pos + 3
elseif sub2 == "//" then
pos = strfind (str, "[\n\r]", pos + 2)
if not pos then return nil end
elseif sub2 == "/*" then
pos = strfind (str, "*/", pos + 2)
if not pos then return nil end
pos = pos + 2
else
return pos
end
end
end
local escapechars = {
["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f",
["n"] = "\n", ["r"] = "\r", ["t"] = "\t"
}
local function unichar (value)
if value < 0 then
return nil
elseif value <= 0x007f then
return strchar (value)
elseif value <= 0x07ff then
return strchar (0xc0 + floor(value/0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0xffff then
return strchar (0xe0 + floor(value/0x1000),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0x10ffff then
return strchar (0xf0 + floor(value/0x40000),
0x80 + (floor(value/0x1000) % 0x40),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
else
return nil
end
end
local function scanstring (str, pos)
local lastpos = pos + 1
local buffer, n = {}, 0
while true do
local nextpos = strfind (str, "[\"\\]", lastpos)
if not nextpos then
return unterminated (str, "string", pos)
end
if nextpos > lastpos then
n = n + 1
buffer[n] = strsub (str, lastpos, nextpos - 1)
end
if strsub (str, nextpos, nextpos) == "\"" then
lastpos = nextpos + 1
break
else
local escchar = strsub (str, nextpos + 1, nextpos + 1)
local value
if escchar == "u" then
value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16)
if value then
local value2
if 0xD800 <= value and value <= 0xDBff then
-- we have the high surrogate of UTF-16. Check if there is a
-- low surrogate escaped nearby to combine them.
if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then
value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16)
if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then
value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000
else
value2 = nil -- in case it was out of range for a low surrogate
end
end
end
value = value and unichar (value)
if value then
if value2 then
lastpos = nextpos + 12
else
lastpos = nextpos + 6
end
end
end
end
if not value then
value = escapechars[escchar] or escchar
lastpos = nextpos + 2
end
n = n + 1
buffer[n] = value
end
end
if n == 1 then
return buffer[1], lastpos
elseif n > 1 then
return concat (buffer), lastpos
else
return "", lastpos
end
end
local scanvalue -- forward declaration
local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta)
local len = strlen (str)
local tbl, n = {}, 0
local pos = startpos + 1
if what == 'object' then
setmetatable (tbl, objectmeta)
else
setmetatable (tbl, arraymeta)
end
while true do
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
local char = strsub (str, pos, pos)
if char == closechar then
return tbl, pos + 1
end
local val1, err
val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
if char == ":" then
if val1 == nil then
return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")"
end
pos = scanwhite (str, pos + 1)
if not pos then return unterminated (str, what, startpos) end
local val2
val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
tbl[val1] = val2
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
else
n = n + 1
tbl[n] = val1
end
if char == "," then
pos = pos + 1
end
end
end
scanvalue = function (str, pos, nullval, objectmeta, arraymeta)
pos = pos or 1
pos = scanwhite (str, pos)
if not pos then
return nil, strlen (str) + 1, "no valid JSON value (reached the end)"
end
local char = strsub (str, pos, pos)
if char == "{" then
return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta)
elseif char == "[" then
return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta)
elseif char == "\"" then
return scanstring (str, pos)
else
local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos)
if pstart then
local number = str2num (strsub (str, pstart, pend))
if number then
return number, pend + 1
end
end
pstart, pend = strfind (str, "^%a%w*", pos)
if pstart then
local name = strsub (str, pstart, pend)
if name == "true" then
return true, pend + 1
elseif name == "false" then
return false, pend + 1
elseif name == "null" then
return nullval, pend + 1
end
end
return nil, pos, "no valid JSON value at " .. loc (str, pos)
end
end
local function optionalmetatables(...)
if select("#", ...) > 0 then
return ...
else
return {__jsontype = 'object'}, {__jsontype = 'array'}
end
end
function json.decode (str, pos, nullval, ...)
local objectmeta, arraymeta = optionalmetatables(...)
return scanvalue (str, pos, nullval, objectmeta, arraymeta)
end
function json.use_lpeg ()
local g = require ("lpeg")
if g.version() == "0.11" then
error "due to a bug in LPeg 0.11, it cannot be used for JSON matching"
end
local pegmatch = g.match
local P, S, R = g.P, g.S, g.R
local function ErrorCall (str, pos, msg, state)
if not state.msg then
state.msg = msg .. " at " .. loc (str, pos)
state.pos = pos
end
return false
end
local function Err (msg)
return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall)
end
local SingleLineComment = P"//" * (1 - S"\n\r")^0
local MultiLineComment = P"/*" * (1 - P"*/")^0 * P"*/"
local Space = (S" \n\r\t" + P"\239\187\191" + SingleLineComment + MultiLineComment)^0
local PlainChar = 1 - S"\"\\\n\r"
local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars
local HexDigit = R("09", "af", "AF")
local function UTF16Surrogate (match, pos, high, low)
high, low = tonumber (high, 16), tonumber (low, 16)
if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then
return true, unichar ((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000)
else
return false
end
end
local function UTF16BMP (hex)
return unichar (tonumber (hex, 16))
end
local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit))
local UnicodeEscape = g.Cmt (U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence/UTF16BMP
local Char = UnicodeEscape + EscapeSequence + PlainChar
local String = P"\"" * g.Cs (Char ^ 0) * (P"\"" + Err "unterminated string")
local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0))
local Fractal = P"." * R"09"^0
local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1
local Number = (Integer * Fractal^(-1) * Exponent^(-1))/str2num
local Constant = P"true" * g.Cc (true) + P"false" * g.Cc (false) + P"null" * g.Carg (1)
local SimpleValue = Number + String + Constant
local ArrayContent, ObjectContent
-- The functions parsearray and parseobject parse only a single value/pair
-- at a time and store them directly to avoid hitting the LPeg limits.
local function parsearray (str, pos, nullval, state)
local obj, cont
local npos
local t, nt = {}, 0
repeat
obj, cont, npos = pegmatch (ArrayContent, str, pos, nullval, state)
if not npos then break end
pos = npos
nt = nt + 1
t[nt] = obj
until cont == 'last'
return pos, setmetatable (t, state.arraymeta)
end
local function parseobject (str, pos, nullval, state)
local obj, key, cont
local npos
local t = {}
repeat
key, obj, cont, npos = pegmatch (ObjectContent, str, pos, nullval, state)
if not npos then break end
pos = npos
t[key] = obj
until cont == 'last'
return pos, setmetatable (t, state.objectmeta)
end
local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray) * Space * (P"]" + Err "']' expected")
local Object = P"{" * g.Cmt (g.Carg(1) * g.Carg(2), parseobject) * Space * (P"}" + Err "'}' expected")
local Value = Space * (Array + Object + SimpleValue)
local ExpectedValue = Value + Space * Err "value expected"
ArrayContent = Value * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
local Pair = g.Cg (Space * String * Space * (P":" + Err "colon expected") * ExpectedValue)
ObjectContent = Pair * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
local DecodeValue = ExpectedValue * g.Cp ()
function json.decode (str, pos, nullval, ...)
local state = {}
state.objectmeta, state.arraymeta = optionalmetatables(...)
local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state)
if state.msg then
return nil, state.pos, state.msg
else
return obj, retpos
end
end
-- use this function only once:
json.use_lpeg = function () return json end
json.using_lpeg = true
return json -- so you can get the module using json = require "dkjson".use_lpeg()
end
if always_try_using_lpeg then
pcall (json.use_lpeg)
end
return json

317
lib/global.lua Normal file
View File

@ -0,0 +1,317 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
---
--- Calls error if the value of its argument `v` is false (i.e., **nil** or
--- **false**); otherwise, returns all its arguments. In case of error,
--- `message` is the error object; when absent, it defaults to "assertion
--- failed!"
---@overload fun(v:any):any
---@param v any
---@param message string
---@return any
function assert(v, message) end
---
--- This function is a generic interface to the garbage collector. It performs
--- different functions according to its first argument, `opt`:
---
--- **"collect"**: performs a full garbage-collection cycle. This is the default
--- option.
--- **"stop"**: stops automatic execution of the garbage collector. The
--- collector will run only when explicitly invoked, until a call to restart it.
--- **"restart"**: restarts automatic execution of the garbage collector.
--- **"count"**: returns the total memory in use by Lua in Kbytes. The value has
--- a fractional part, so that it multiplied by 1024 gives the exact number of
--- bytes in use by Lua (except for overflows).
--- **"step"**: performs a garbage-collection step. The step "size" is
--- controlled by `arg`. With a zero value, the collector will perform one basic
--- (indivisible) step. For non-zero values, the collector will perform as if
--- that amount of memory (in KBytes) had been allocated by Lua. Returns
--- **true** if the step finished a collection cycle.
--- **"setpause"**: sets `arg` as the new value for the *pause* of the collector
--- (see §2.5). Returns the previous value for *pause`.
--- **"incremental"**: Change the collector mode to incremental. This option can
--- be followed by three numbers: the garbage-collector pause, the step
--- multiplier, and the step size.
--- **"generational"**: Change the collector mode to generational. This option
--- can be followed by two numbers: the garbage-collector minor multiplier and
--- the major multiplier.
--- **"isrunning"**: returns a boolean that tells whether the collector is
--- running (i.e., not stopped).
---@overload fun():any
---@param opt string
---@param arg string
---@return any
function collectgarbage(opt, arg) end
---
--- Opens the named file and executes its contents as a Lua chunk. When called
--- without arguments, `dofile` executes the contents of the standard input
--- (`stdin`). Returns all values returned by the chunk. In case of errors,
--- `dofile` propagates the error to its caller (that is, `dofile` does not run
--- in protected mode).
---@overload fun():table
---@param filename string
---@return table
function dofile(filename) end
---
--- Terminates the last protected function called and returns `message` as the
--- error object. Function `error` never returns. Usually, `error` adds some
--- information about the error position at the beginning of the message, if the
--- message is a string. The `level` argument specifies how to get the error
--- position. With level 1 (the default), the error position is where the
--- `error` function was called. Level 2 points the error to where the function
--- that called `error` was called; and so on. Passing a level 0 avoids the
--- addition of error position information to the message.
---@overload fun(message:string)
---@param message string
---@param level number
function error(message, level) end
---
--- A global variable (not a function) that holds the global environment. Lua
--- itself does not use this variable; changing its value does not affect any
--- environment, nor vice versa.
---@class _G
_G = {}
---
--- If `object` does not have a metatable, returns **nil**. Otherwise, if the
--- object's metatable has a `"__metatable"` field, returns the associated
--- value. Otherwise, returns the metatable of the given object.
---@param object any
---@return any
function getmetatable(object) end
---
--- Returns three values (an iterator function, the table `t`, and 0) so that
--- the construction
--- > `for i,v in ipairs(t) do` *body* `end`
--- will iterate over the keyvalue pairs (1,`t[1]`), (2,`t[2]`), ..., up to
--- the first absent index.
---@generic V
---@param t table<number, V>|V[]
---@return fun(tbl: table<number, V>):number, V
function ipairs(t) end
---
--- Loads a chunk.
--- If `chunk` is a string, the chunk is this string. If `chunk` is a function,
--- `load` calls it repeatedly to get the chunk pieces. Each call to `chunk`
--- must return a string that concatenates with previous results. A return of
--- an empty string, **nil**, or no value signals the end of the chunk.
---
--- If there are no syntactic errors, returns the compiled chunk as a function;
--- otherwise, returns **nil** plus the error message.
---
--- If the resulting function has upvalues, the first upvalue is set to the
--- value of `env`, if that parameter is given, or to the value of the global
--- environment. Other upvalues are initialized with **nil**. (When you load a
--- main chunk, the resulting function will always have exactly one upvalue, the
--- _ENV variable. However, when you load a binary chunk created from a
--- function (see string.dump), the resulting function can have an arbitrary
--- number of upvalues.) All upvalues are fresh, that is, they are not shared
--- with any other function.
---
--- `chunkname` is used as the name of the chunk for error messages and debug
--- information. When absent, it defaults to `chunk`, if `chunk` is a string,
--- or to "=(`load`)" otherwise.
---
--- The string `mode` controls whether the chunk can be text or binary (that is,
--- a precompiled chunk). It may be the string "b" (only binary chunks), "t"
--- (only text chunks), or "bt" (both binary and text). The default is "bt".
---
--- Lua does not check the consistency of binary chunks. Maliciously crafted
--- binary chunks can crash the interpreter.
---@overload fun(chunk:fun():string):any
---@param chunk fun():string
---@param chunkname string
---@param mode string
---@param env any
function load(chunk, chunkname, mode, env) end
---
--- Similar to `load`, but gets the chunk from file `filename` or from the
--- standard input, if no file name is given.
---@overload fun()
---@param filename string
---@param mode string
---@param env any
function loadfile(filename, mode, env) end
---
--- Allows a program to traverse all fields of a table. Its first argument is
--- a table and its second argument is an index in this table. `next` returns
--- the next index of the table and its associated value. When called with
--- **nil** as its second argument, `next` returns an initial index and its
--- associated value. When called with the last index, or with **nil** in an
--- empty table, `next` returns **nil**. If the second argument is absent, then
--- it is interpreted as **nil**. In particular, you can use `next(t)` to check
--- whether a table is empty.
---
--- The order in which the indices are enumerated is not specified, *even for
--- numeric indices*. (To traverse a table in numerical order, use a numerical
--- **for**.)
---
--- The behavior of `next` is undefined if, during the traversal, you assign
--- any value to a non-existent field in the table. You may however modify
--- existing fields. In particular, you may set existing fields to nil.
---@overload fun(table:table):any
---@param table table
---@param index any
---@return any
function next(table, index) end
---
--- If `t` has a metamethod `__pairs`, calls it with `t` as argument and returns
--- the first three results from the call.
---
--- Otherwise, returns three values: the `next` function, the table `t`, and
--- **nil**, so that the construction
--- `for k,v in pairs(t) do *body* end`
--- will iterate over all keyvalue pairs of table `t`.
---
--- See function `next` for the caveats of modifying the table during its
--- traversal.
---@generic K, V
---@param t table<K, V>|V[]
---@return fun(tbl: table<K, V>):K, V
function pairs(t) end
---
--- Calls function `f` with the given arguments in *protected mode*. This
--- means that any error inside `f` is not propagated; instead, `pcall` catches
--- the error and returns a status code. Its first result is the status code (a
--- boolean), which is true if the call succeeds without errors. In such case,
--- `pcall` also returns all results from the call, after this first result. In
--- case of any error, `pcall` returns **false** plus the error message.
---@overload fun(f:fun():any):boolean|table
---@param f fun():any
---@param arg1 table
---@return boolean|table
function pcall(f, arg1, ...) end
---
--- Receives any number of arguments, and prints their values to `stdout`,
--- using the `tostring` function to convert them to strings. `print` is not
--- intended for formatted output, but only as a quick way to show a value,
--- for instance for debugging. For complete control over the output, use
--- `string.format` and `io.write`.
function print(...) end
---
--- Checks whether `v1` is equal to `v2`, without the `__eq` metamethod. Returns
--- a boolean.
---@param v1 any
---@param v2 any
---@return boolean
function rawequal(v1, v2) end
---
--- Gets the real value of `table[index]`, the `__index` metamethod. `table`
--- must be a table; `index` may be any value.
---@param table table
---@param index any
---@return any
function rawget(table, index) end
---
--- Sets the real value of `table[index]` to `value`, without invoking the
--- `__newindex` metamethod. `table` must be a table, `index` any value
--- different from **nil** and NaN, and `value` any Lua value.
---@param table table
---@param index any
---@param value any
function rawset(table, index, value) end
---
--- If `index` is a number, returns all arguments after argument number
--- `index`. a negative number indexes from the end (-1 is the last argument).
--- Otherwise, `index` must be the string "#", and `select` returns
--- the total number of extra arguments it received.
---@generic T
---@param index number|string
---@vararg T
---@return T
function select(index, ...) end
---
--- Sets the metatable for the given table. (To change the metatable of other
--- types from Lua code, you must use the debug library.) If `metatable`
--- is **nil**, removes the metatable of the given table. If the original
--- metatable has a `"__metatable"` field, raises an error.
---
--- This function returns `table`.
---@generic T
---@param table T
---@param metatable table
---@return T
function setmetatable(table, metatable) end
---
--- When called with no `base`, `tonumber` tries to convert its argument to a
--- number. If the argument is already a number or a string convertible to a
--- number, then `tonumber` returns this number; otherwise, it returns **nil**.
---
--- The conversion of strings can result in integers or floats, according to the
--- lexical conventions of Lua. (The string may have leading and trailing
--- spaces and a sign.)
---
--- When called with `base`, then e must be a string to be interpreted as an
--- integer numeral in that base. The base may be any integer between 2 and 36,
--- inclusive. In bases above 10, the letter 'A' (in either upper or lower case)
--- represents 10, 'B' represents 11, and so forth, with 'Z' representing 35. If
--- the string `e` is not a valid numeral in the given base, the function
--- returns **nil**.
---@overload fun(e:string):any
---@param e string
---@param base number
---@return any
function tonumber(e, base) end
---
--- Receives a value of any type and converts it to a string in a human-readable
--- format. (For complete control of how numbers are converted, use `string
--- .format`).
---
--- If the metatable of `v` has a `__tostring` field, then `tostring` calls
--- the corresponding value with `v` as argument, and uses the result of the
--- call as its result.
---@param v any
---@return string
function tostring(v) end
---
--- Returns the type of its only argument, coded as a string. The possible
--- results of this function are "`nil`" (a string, not the value **nil**),
--- "`number`", "`string`", "`boolean`", "`table`", "`function`", "`thread`",
--- and "`userdata`".
---@param v any
---@return string
function type(v) end
---
--- A global variable (not a function) that holds a string containing the
--- running Lua version. The current value of this variable is "`Lua 5.4`".
_VERSION = "Lua 5.4"
---
--- This function is similar to `pcall`, except that it sets a new message
--- handler `msgh`.
---@param f fun():any
---@param msgh fun():string
---@return any
function xpcall(f, msgh, arg1, ...) end

234
lib/io.lua Normal file
View File

@ -0,0 +1,234 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
io = {}
---
--- Equivalent to `file:close()`. Without a file, closes the default output
--- file.
---@overload fun():void
---@param file file
function io.close(file) end
---
--- Equivalent to `io.output():flush()`.
function io.flush() end
---
--- When called with a file name, it opens the named file (in text mode), and
--- sets its handle as the default input file. When called with a file handle,
--- it simply sets this file handle as the default input file. When called
--- without parameters, it returns the current default input file.
---
--- In case of errors this function raises the error, instead of returning an
--- error code.
---@overload fun():file
---@param file string | file
---@return file
function io.input(file) end
---
--- Opens the given file name in read mode and returns an iterator function
--- works like `file:lines(···)` over the opened file. When the iterator
--- function detects the end of file, it returns no values (to finish the loop)
--- and automatically closes the file.
---
--- The call `io.lines()` (with no file name) is equivalent to `io.input():lines
--- ()`; that is, it iterates over the lines of the default
--- input file. In this case, the iterator does not close the file when the loop
--- ends.
---
--- In case of errors this function raises the error, instead of returning an
--- error code.
---@overload fun():any
---@param filename string
---@return fun():any
function io.lines(filename, ...) end
---
--- This function opens a file, in the mode specified in the string `mode`. In
--- case of success, it returns a new file handle. The `mode` string can be
--- any of the following:
---
--- **"r"**: read mode (the default);
--- **"w"**: write mode;
--- **"a"**: append mode;
--- **"r+"**: update mode, all previous data is preserved;
--- **"w+"**: update mode, all previous data is erased;
--- **"a+"**: append update mode, previous data is preserved, writing is only
--- allowed at the end of file.
---
--- The `mode` string can also have a '`b`' at the end, which is needed in
--- some systems to open the file in binary mode.
---@overload fun(filename:string):file
---@param filename string
---@param mode string | '"r"' | '"w"' | '"a"' | '"r+"' | '"w+"' | '"a+"' | '"rb"' | '"wb"' | '"ab"' | '"rb+"' | '"wb+"' | '"ab+"'
---@return file
function io.open(filename, mode) return file end
---
--- Similar to `io.input`, but operates over the default output file.
---@overload fun():file
---@param file string | file
---@return file
function io.output(file) end
---
--- This function is system dependent and is not available on all platforms.
---
--- Starts program `prog` in a separated process and returns a file handle that
--- you can use to read data from this program (if `mode` is "`r`", the default)
--- or to write data to this program (if `mode` is "`w`").
---@overload fun(prog:string):file
---@param prog string
---@param mode string | '"r"' | '"w"'
---@return file
function io.popen(prog, mode) end
---
--- Equivalent to `io.input():read(···)`.
function io.read(...) end
---
--- In case of success, returns a handle for a temporary file. This file is
--- opened in update mode and it is automatically removed when the program ends.
function io.tmpfile() end
---
--- Checks whether `obj` is a valid file handle. Returns the string "`file`"
--- if `obj` is an open file handle, "`closed file`" if `obj` is a closed file
--- handle, or **nil** if `obj` is not a file handle.
---@param obj string|file
---@return file
function io.type(obj) end
---
--- Equivalent to `io.output():write(···)`.
function io.write(...) end
--- File object
---@class file
local file = {}
---
--- Closes `file`. Note that files are automatically closed when their
--- handles are garbage collected, but that takes an unpredictable amount of
--- time to happen.
---
--- When closing a file handle created with `io.popen`, `file:close` returns the
--- same values returned by `os.execute`.
function file:close() end
---
--- Saves any written data to `file`.
function file:flush() end
---
--- Returns an iterator function that, each time it is called, reads the file
--- according to the given formats. When no format is given, uses "l" as a
--- default. As an example, the construction
--- `for c in file:lines(1) do *body* end`
--- will iterate over all characters of the file, starting at the current
--- position. Unlike `io.lines`, this function does not close the file when the
--- loop ends.
---
--- In case of errors this function raises the error, instead of returning an
--- error code.
---@return fun():any
function file:lines(...) end
---
--- Reads the file `file`, according to the given formats, which specify
--- what to read. For each format, the function returns a string or a number
--- with the characters read, or **nil** if it cannot read data with the
--- specified format. (In this latter case, the function does not read
--- subsequent formats.) When called without parameters, it uses a default
--- format that reads the next line (see below).
----
--- The available formats are:
--- **"n"**: reads a numeral and returns it as a float or an integer, following
--- the lexical conventions of Lua. (The numeral may have leading spaces and a
--- sign.) This format always reads the longest input sequence that is a valid
--- prefix for a numeral; if that prefix does not form a valid numeral (e.g., an
--- empty string, "`0x`", or "`3.4e-`"), it is discarded and the format returns
--- **nil**;
--- **"a"**: reads the whole file, starting at the current position. On end of
--- file, it returns the empty string;
--- **"l"**: reads the next line skipping the end of line, returning **nil** on
--- end of file. This is the default format.
--- **"L"**: reads the next line keeping the end-of-line character (if present),
--- returning **nil** on end of file;
--- *number*: reads a string with up to this number of bytes, returning **nil**
--- on end of file. If `number` is zero, it reads nothing and returns an
--- empty string, or **nil** on end of file.
function file:read(...) end
---
--- Sets and gets the file position, measured from the beginning of the
--- file, to the position given by `offset` plus a base specified by the string
--- `whence`, as follows:
--- **"set"**: base is position 0 (beginning of the file);
--- **"cur"**: base is current position;
--- **"end"**: base is end of file;
---
--- In case of success, `seek` returns the final file position, measured in
--- bytes from the beginning of the file. If `seek` fails, it returns **nil**,
--- plus a string describing the error.
---
--- The default value for `whence` is "`cur`", and for `offset` is 0. Therefore,
--- the call `file:seek()` returns the current file position, without changing
--- it; the call `file:seek("set")` sets the position to the beginning of the
--- file (and returns 0); and the call `file:seek("end")` sets the position
--- to the end of the file, and returns its size.
---@overload fun()
---@param whence string | '"set"' | '"cur"' | '"end"'
---@param offset number
function file:seek(whence, offset) end
---
--- Sets the buffering mode for an output file. There are three available
--- modes:
--- **"no"**: no buffering; the result of any output operation appears
--- immediately.
--- **"full"**: full buffering; output operation is performed only when the
--- buffer is full (or when you explicitly `flush` the file (see `io.flush`)).
--- **"line"**: line buffering; output is buffered until a newline is output or
--- there is any input from some special files (such as a terminal device).
---
--- For the last two cases, `size` specifies the size of the buffer, in
--- bytes. The default is an appropriate size.
---@overload fun(mode:string)
---@param mode string | '"no"' | '"full"' | '"line"'
---@param size number
function file:setvbuf(mode, size) end
---
--- Writes the value of each of its arguments to the `file`. The arguments
--- must be strings or numbers.
---
--- In case of success, this function returns `file`. Otherwise it returns
--- **nil** plus a string describing the error.
function file:write(...) end
--- * `io.stderr`: Standard error.
---@type file
stderr = nil
--- * `io.stdin`: Standard in.
---@type file
stdin = nil
--- * `io.stdout`: Standard out.
---@type file
stdout = nil

200
lib/math.lua Normal file
View File

@ -0,0 +1,200 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
math = {}
---
--- Returns the absolute value of `x`. (integer/float)
---@param x number
---@return number
function math.abs(x) return 0 end
---
--- Returns the arc cosine of `x` (in radians).
---@param x number
---@return number
function math.acos(x) return 0 end
---
--- Returns the arc sine of `x` (in radians).
---@param x number
---@return number
function math.asin(x) return 0 end
---
--- Returns the arc tangent of `y/x` (in radians), but uses the signs of both
--- parameters to find the quadrant of the result. (It also handles correctly
--- the case of `x` being zero.)
---
--- The default value for `x` is 1, so that the call `math.atan(y)`` returns the
--- arc tangent of `y`.
---@overload fun(y:number):number
---@param y number
---@param x number
---@return number
function math.atan(y, x) return 0 end
---
--- Returns the smallest integer larger than or equal to `x`.
---@param x number
---@return number
function math.ceil(x) return 0 end
---
--- Returns the cosine of `x` (assumed to be in radians).
---@param x number
---@return number
function math.cos(x) return 0 end
---
--- Converts the angle `x` from radians to degrees.
---@param x number
---@return number
function math.deg(x) return 0 end
---
--- Returns the value *e^x* (where e is the base of natural logarithms).
---@param x number
---@return number
function math.exp(x) end
---
--- Returns the largest integer smaller than or equal to `x`.
---@param x number
---@return number
function math.floor(x) end
---
--- Returns the remainder of the division of `x` by `y` that rounds the
--- quotient towards zero. (integer/float)
---@param x number
---@param y number
---@return number
function math.fmod(x, y) end
---
--- The float value `HUGE_VAL`, a value larger than any other numeric value.
---@type number
math.huge = nil
---
--- Returns the logarithm of `x` in the given base. The default for `base` is
--- *e* (so that the function returns the natural logarithm of `x`).
---@overload fun(x:number):number
---@param x number
---@param base number
---@return number
function math.log(x, base) end
---
--- Returns the argument with the maximum value, according to the Lua operator
--- `<`. (integer/float)
---@param x number
---@return number
function math.max(x, ...) end
---
--- An integer with the maximum value for an integer.
---@type number
math.maxinteger = nil
---
--- Returns the argument with the minimum value, according to the Lua operator
--- `<`. (integer/float)
---@param x number
---@return number
function math.min(x, ...) end
---
--- An integer with the minimum value for an integer.
---@type number
math.mininteger = nil
---
--- Returns the integral part of `x` and the fractional part of `x`. Its second
--- result is always a float.
---@param x number
---@return number
function math.modf(x) end
---
--- The value of π.
math.pi = 3.1415
---
--- Converts the angle `x` from degrees to radians.
---@param x number
---@return number
function math.rad(x) end
---
--- When called without arguments, returns a pseudo-random float with uniform
--- distribution in the range *[0,1)*. When called with two integers `m` and
--- `n`, `math.random` returns a pseudo-random integer with uniform distribution
--- in the range *[m, n]*. The call `math.random(n)` is equivalent to `math
--- .random`(1,n).
---@overload fun():number
---@param m number
---@param n number
---@return number
function math.random(m, n) end
---
--- Sets `x` as the "seed" for the pseudo-random generator: equal seeds
--- produce equal sequences of numbers.
---@param x number
function math.randomseed(x) end
---
--- Returns the sine of `x` (assumed to be in radians).
---@param x number
---@return number
function math.sin(x) return 0 end
---
--- Returns the square root of `x`. (You can also use the expression `x^0.5` to
--- compute this value.)
---@param x number
---@return number
function math.sqrt(x) return 0 end
---
--- Returns the tangent of `x` (assumed to be in radians).
---@param x number
---@return number
function math.tan(x) return 0 end
---
--- If the value `x` is convertible to an integer, returns that integer.
--- Otherwise, returns `nil`.
---@param x number
---@return number
function math.tointeger(x) end
---
--- Returns "`integer`" if `x` is an integer, "`float`" if it is a float, or
--- **nil** if `x` is not a number.
---@param x number
---@return number
function math.type(x) end
---
--- Returns a boolean, true if and only if integer `m` is below integer `n` when
--- they are compared as unsigned integers.
---@param m number
---@param n number
---@return boolean
function math.ult(m, n) end
return math

192
lib/os.lua Normal file
View File

@ -0,0 +1,192 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
os = {}
---
--- Returns an approximation of the amount in seconds of CPU time used by
--- the program.
---@return number
function os.clock() end
---
--- Returns a string or a table containing date and time, formatted according
--- to the given string `format`.
---
--- If the `time` argument is present, this is the time to be formatted (see
--- the `os.time` function for a description of this value). Otherwise,
--- `date` formats the current time.
---
--- If `format` starts with '`!`', then the date is formatted in Coordinated
--- Universal Time. After this optional character, if `format` is the string
--- "`*t`", then `date` returns a table with the following fields:
---
--- **`year`** (four digits)
--- **`month`** (112)
--- **`day`** (1-31)
--- **`hour`** (0-23)
--- **`min`** (0-59)
--- **`sec`** (0-61), due to leap seconds
--- **`wday`** (weekday, 17, Sunday is 1)
--- **`yday`** (day of the year, 1366)
--- **`isdst`** (daylight saving flag, a boolean). This last field may be absent
--- if the information is not available.
---
--- If `format` is not "`*t`", then `date` returns the date as a string,
--- formatted according to the same rules as the ISO C function `strftime`.
---
--- When called without arguments, `date` returns a reasonable date and time
--- representation that depends on the host system and on the current locale.
--- (More specifically, `os.date()` is equivalent to `os.date("%c")`.)
---
--- On non-POSIX systems, this function may be not thread safe because of its
--- reliance on C function `gmtime` and C function `localtime`.
---@overload fun():string|table
---@param format string
---@param time number
---@return string|table
function os.date(format, time) end
---
--- Returns the difference, in seconds, from time `t1` to time `t2`. (where the
--- times are values returned by `os.time`). In POSIX, Windows, and some other
--- systems, this value is exactly `t2`-`t1`.
---@param t2 number
---@param t1 number
---@return number
function os.difftime(t2, t1) end
---
--- This function is equivalent to the C function `system`. It passes `command`
--- to be executed by an operating system shell. Its first result is **true** if
--- the command terminated successfully, or **nil** otherwise. After this first
--- result the function returns a string plus a number, as follows:
---
--- **"exit"**: the command terminated normally; the following number is the
--- exit status of the command.
--- **"signal"**: the command was terminated by a signal; the following number
--- is the signal that terminated the command.
---
--- When called without a command, `os.execute` returns a boolean that is true
--- if a shell is available.
---@overload fun():string|number
---@param command string
---@return string|number
function os.execute(command) end
---
--- Calls the ISO C function `exit` to terminate the host program. If `code` is
--- **true**, the returned status is `EXIT_SUCCESS`; if `code` is **false**, the
--- returned status is `EXIT_FAILURE`; if `code` is a number, the returned
--- status is this number. The default value for `code` is **true**.
---
--- If the optional second argument `close` is true, closes the Lua state before
--- exiting.
---@overload fun():number
---@param code number
---@param close boolean
---@return number
function os.exit(code, close) end
---
--- Returns the value of the process environment variable `varname`, or
--- **nil** if the variable is not defined.
---@param varname string
---@return string
function os.getenv(varname) end
---
--- Deletes the file (or empty directory, on POSIX systems) with the given name.
--- If this function fails, it returns **nil**, plus a string describing the
--- error and the error code. Otherwise, it returns true.
---@param filename string
---@return nil|string
function os.remove(filename) end
---
--- Renames the file or directory named `oldname` to `newname`. If this function
--- fails, it returns **nil**, plus a string describing the error and the error
--- code. Otherwise, it returns true.
---@param oldname string
---@param newname string
---@return nil|string
function os.rename(oldname, newname) end
---
--- Sets the current locale of the program. `locale` is a system-dependent
--- string specifying a locale; `category` is an optional string describing
--- which category to change: `"all"`, `"collate"`, `"ctype"`, `"monetary"`,
--- `"numeric"`, or `"time"`; the default category is `"all"`. The function
--- returns the name of the new locale, or **nil** if the request cannot be
--- honored.
---
--- If `locale` is the empty string, the current locale is set to an
--- implementation-defined native locale. If `locale` is the string "`C`",
--- the current locale is set to the standard C locale.
---
--- When called with **nil** as the first argument, this function only returns
--- the name of the current locale for the given category.
---
--- This function may be not thread safe because of its reliance on C function
--- `setlocale`.
---@overload fun(locale:string):string|nil
---@param locale string
---@param category string
---@return string|nil
function os.setlocale(locale, category) end
---
--- Returns the current time when called without arguments, or a time
--- representing the date and time specified by the given table. This table
--- must have fields `year`, `month`, and `day`, and may have fields `hour`
--- (default is 12), `min` (default is 0), `sec` (default is 0), and `isdst`
--- (default is **nil**). Other fields are ignored. For a description of these
--- fields, see the `os.date` function.
---
--- When the function is called, the values in these fields do not need to be
--- inside their valid ranges. For instance, if `sec` is -10, it means 10 seconds
--- before the time specified by the other fields; if `hour` is 1000, it means
--- 1000 hours after the time specified by the other fields.
---
--- The returned value is a number, whose meaning depends on your system. In
--- POSIX, Windows, and some other systems, this number counts the number of
--- seconds since some given start time (the "epoch"). In other systems, the
--- meaning is not specified, and the number returned by `time` can be used only
--- as an argument to `os.date` and `os.difftime`.
---
--- When called with a table, `os.time` also normalizes all the fields
--- documented in the `os.date` function, so that they represent the same time
--- as before the call but with values inside their valid ranges.
---@overload fun():number
---@param table table
---@return number
function os.time(table) end
---
--- Returns a string with a file name that can be used for a temporary
--- file. The file must be explicitly opened before its use and explicitly
--- removed when no longer needed.
---
--- On some systems (POSIX), this function also creates a file with that
--- name, to avoid security risks. (Someone else might create the file with
--- wrong permissions in the time between getting the name and creating the
--- file.) You still have to open the file to use it and to remove it (even
--- if you do not use it).
---
--- When possible, you may prefer to use `io.tmpfile`, which automatically
--- removes the file when the program ends.
---@return string
function os.tmpname() end
return os

197
lib/package.lua Normal file
View File

@ -0,0 +1,197 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
package = {}
---
--- A string describing some compile-time configurations for packages. This
--- string is a sequence of lines:
---
--- The first line is the directory separator string. Default is '\' for Windows
--- and '/' for all other systems.
--- The second line is the character that separates templates in a path. Default
--- is ';'.
--- The third line is the string that marks the substitution points in a
--- template. Default is '?'.
--- The fourth line is a string that, in a path in Windows, is replaced by the
--- executable's directory. Default is '!'.
--- The fifth line is a mark to ignore all text after it when building the
--- luaopen_ function name. Default is '-'.
package.config = ""
---
--- The path used by `require` to search for a C loader.
---
--- Lua initializes the C path `package.cpath` in the same way it initializes
--- the Lua path `package.path`, using the environment variable `LUA_CPATH_5_4`
--- or the environment variable `LUA_CPATH`, or a default path defined in
--- `luaconf.h`.
package.cpath = ""
---
--- A table used by `require` to control which modules are already
--- loaded. When you require a module `modname` and `package.loaded[modname]``
--- is not false, `require` simply returns the value stored there.
---
--- This variable is only a reference to the real table; assignments to this
--- variable do not change the table used by `require`.
package.loaded = {}
---
--- Dynamically links the host program with the C library `libname`.
---
--- If `funcname` is "*", then it only links with the library, making the
--- symbols exported by the library available to other dynamically linked
--- libraries. Otherwise, it looks for a function `funcname` inside the library
--- and returns this function as a C function. So, `funcname` must follow the
--- `lua_CFunction` prototype (see `lua_CFunction`).
---
--- This is a low-level function. It completely bypasses the package and module
--- system. Unlike `require`, it does not perform any path searching and does
--- not automatically adds extensions. `libname` must be the complete file name
--- of the C library, including if necessary a path and an extension. `funcname`
--- must be the exact name exported by the C library (which may depend on the C
--- compiler and linker used).
---
--- This function is not supported by Standard C. As such, it is only available
--- on some platforms (Windows, Linux, Mac OS X, Solaris, BSD, plus other Unix
--- systems that support the `dlfcn` standard).
---@param libname string
---@param funcname string
---@return fun():nil
function package.loadlib(libname, funcname) end
---
--- The path used by `require` to search for a Lua loader.
---
--- At start-up, Lua initializes this variable with the value of the environment
--- variable `LUA_PATH_5_4` or the environment variable `LUA_PATH` or with a
--- default path defined in `luaconf.h`, if those environment variables are not
--- defined. Any ";;" in the value of the environment variable is replaced by
--- the default path.
package.path = ""
---
--- A table to store loaders for specific modules (see `require`).
---
--- This variable is only a reference to the real table; assignments to this
--- variable do not change the table used by `require`.
package.preload = {}
---
--- A table used by require to control how to load modules.
---
--- Each entry in this table is a *searcher function*. When looking for a
--- module, *require* calls each of these searchers in ascending order, with the
--- module name (the argument given to `require`) as its sole parameter. The
--- function can return another function (the module *loader*) plus an extra
--- value that will be passed to that loader, or a string explaining why it did
--- not find that module (or **nil** if it has nothing to say).
---
--- Lua initializes this table with four searcher functions.
---
--- The first searcher simply looks for a loader in the `package.preload` table.
---
--- The second searcher looks for a loader as a Lua library, using the path
--- stored at `package.path`. The search is done as described in function
--- `package.searchpath`.
---
--- The third searcher looks for a loader as a C library, using the path given
--- by the variable package.cpath`. Again, the search is done as described in
--- function `package.searchpath`. For instance, if the C path is the string
--- > "`./?.so;./?.dll;/usr/local/?/init.so`"
--- the searcher for module foo will try to open the files ``./foo.so, ./foo
--- .dll`, and ``/usr/local/foo/init.so`, in that order. Once it finds a C
--- library, this searcher first uses a dynamic link facility to link the
--- application with the library. Then it tries to find a C function inside the
--- library to be used as the loader. The name of this C function is the string
--- "`luaopen_`" concatenated with a copy of the module name where each dot is
--- replaced by an underscore. Moreover, if the module name has a hyphen, its
--- suffix after (and including) the first hyphen is removed. For instance, if
--- the module name is `a.b.c-v2.1`, the function name will be `luaopen_a_b_c`.
---
--- The fourth searcher tries an *all-in-one loader*. It searches the C path for
--- a library for the root name of the given module. For instance, when
--- requiring `a.b.c`, it will search for a C library for `a`. If found, it
--- looks into it for an open function for the submodule; in our example, that
--- would be `luaopen_a_b_c`. With this facility, a package can pack several C
--- submodules into one single library, with each submodule keeping its original
--- open function.
---
--- All searchers except the first one (preload) return as the extra value the
--- file name where the module was found, as returned by `package.searchpath`.
--- The first searcher returns no extra value.
package.searchers = {}
---
--- Searches for the given name in the given path.
---
--- A path is a string containing a sequence of *templates* separated by
--- semicolons. For each template, the function replaces each interrogation mark
--- (if any) in the template with a copy of name wherein all occurrences of
--- `sep` (a dot, by default) were replaced by `rep` (the system's directory
--- separator, by default), and then tries to open the resulting file name.
---
--- For instance, if the path is the string
--- > "`./?.lua;./?.lc;/usr/local/?/init.lua`"
--- the search for the name `foo.a` will try to open the files `./foo/a.lua`,
--- `./foo/a.lc`, and `/usr/local/foo/a/init.lua`, in that order.
---
--- Returns the resulting name of the first file that it can open in read mode
--- (after closing the file), or **nil** plus an error message if none succeeds.
--- (This error message lists all file names it tried to open.)
---@overload fun(name:string, path:string):string
---@param name string
---@param path string
---@param sep string
---@param rep string
---@return string
function package.searchpath(name, path, sep, rep) end
---
--- Loads the given module. The function starts by looking into the
--- 'package.loaded' table to determine whether `modname` is already
--- loaded. If it is, then `require` returns the value stored at
--- `package.loaded[modname]`. Otherwise, it tries to find a *loader* for
--- the module.
---
--- To find a loader, `require` is guided by the `package.searchers` sequence.
--- By changing this sequence, we can change how `require` looks for a module.
--- The following explanation is based on the default configuration for
--- `package.searchers`.
---
--- First `require` queries `package.preload[modname]`. If it has a value,
--- this value (which should be a function) is the loader. Otherwise `require`
--- searches for a Lua loader using the path stored in `package.path`. If
--- that also fails, it searches for a C loader using the path stored in
--- `package.cpath`. If that also fails, it tries an *all-in-one* loader (see
--- `package.loaders`).
---
--- Once a loader is found, `require` calls the loader with a two argument:
--- `modname` and an extra value dependent on how it got the loader. (If the
--- loader came from a file, this extra value is the file name.) If the loader
--- returns any non-nil value, require assigns the returned value to
--- `package.loaded[modname]`. If the loader does not return a non-nil value and
--- has not assigned any value to `package.loaded[modname]`, then `require`
--- assigns true to this entry. In any case, require returns the final value of
--- `package.loaded[modname]`.
---
--- If there is any error loading or running the module, or if it cannot find
--- any loader for the module, then `require` raises an error.
---@param modname string
---@return any
function require(modname) end
return package

300
lib/string.lua Normal file
View File

@ -0,0 +1,300 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
---
--- The type *string* represents immutable sequences of bytes. Lua is 8-bit
--- clean: strings can contain any 8-bit value, including embedded zeros
--- ('`\0`'). Lua is also encoding-agnostic; it makes no assumptions about
--- the contents of a string.
---@class string
string = {}
---
--- Returns the internal numerical codes of the characters `s[i]`, `s[i+1]`,
--- ..., `s[j]`. The default value for `i` is 1; the default value for `j`
--- is `i`. These indices are corrected following the same rules of function
--- `string.sub`.
---
--- Note that numerical codes are not necessarily portable across platforms.
---@overload fun(s:string):number
---@param s string
---@param i number
---@param j number
---@return number
function string.byte(s, i, j) end
---
--- Receives zero or more integers. Returns a string with length equal to
--- the number of arguments, in which each character has the internal numerical
--- code equal to its corresponding argument.
---
--- Note that numerical codes are not necessarily portable across platforms.
---@return string
function string.char(...) end
---
--- Returns a string containing a binary representation (*a binary chunk*) of
--- the given function, so that a later `load` on this string returns a
--- copy of the function (but with new upvalues). If strip is a true value, the
--- binary representation may not include all debug information about the
--- function, to save space.
---
--- Functions with upvalues have only their number of upvalues saved. When (re)
--- loaded, those upvalues receive fresh instances containing **nil**. (You can
--- use the debug library to serialize and reload the upvalues of a function in
--- a way adequate to your needs.)
---@overload fun(func:fun()):string
---@param func fun()
---@param strip boolean
---@return string
function string.dump(func, strip) end
---
--- Looks for the first match of `pattern` in the string `s`. If it finds a
--- match, then `find` returns the indices of `s` where this occurrence starts
--- and ends; otherwise, it returns **nil**. A third, optional numerical
--- argument `init` specifies where to start the search; its default value is 1
--- and can be negative. A value of **true** as a fourth, optional argument
--- `plain` turns off the pattern matching facilities, so the function does a
--- plain "find substring" operation, with no characters in `pattern` being
--- considered "magic". Note that if `plain` is given, then `init` must be given
--- as well.
---
--- If the pattern has captures, then in a successful match the captured values
--- are also returned, after the two indices.
---@overload fun(s:string, pattern:string):number, number, string
---@param s string
---@param pattern string
---@param init number
---@param plain boolean
---@return number, number, string
function string.find(s, pattern, init, plain) end
---
--- Returns a formatted version of its variable number of arguments following
--- the description given in its first argument (which must be a string). The
--- format string follows the same rules as the ISO C function `sprintf`. The
--- only differences are that the options/modifiers `*`, `h`, `L`, `l`, `n`, and
--- `p` are not supported and that there is an extra option, `q`.
---
--- The `q` option formats booleans, nil, numbers, and strings in a way that the
--- result is a valid constant in Lua source code. Booleans and nil are written
--- in the obvious way (`true`, `false`, `nil`). Floats are written in
--- hexadecimal, to preserve full precision. A string is written between double
--- quotes, using escape sequences when necessary to ensure that it can safely
--- be read back by the Lua interpreter. For instance, the call
---
--- string.format('%q', 'a string with "quotes" and \n new line') may produce
--- the string:
---
--- > "a string with \"quotes\" and \
--- > new line"
---
--- The options `A`, `a`, `E`, `e`, `f`, `g`, `G` and `g` all expect a number as
--- argument. Options `c`, `d`, `i`, `o`, `u`, `X`, and `x` expect an integer.
--- When Lua is compiled with a C89 compiler, options `A` and `a` (hexadecimal
--- floats) do not support any modifier (flags, width, length).
---
--- Option `s` expects a string; if its argument is not a string, it is
--- converted to one following the same rules of `tostring`. If the option
--- has any modifier (flags, width, length), the string argument should not
--- contain embedded zeros.
---@param formatstring string
---@return string
function string.format(formatstring, ...) end
---
--- Returns an iterator function that, each time it is called, returns the
--- next captures from `pattern` over the string `s`. If `pattern` specifies no
--- captures, then the whole match is produced in each call.
---
--- As an example, the following loop will iterate over all the words from
--- string `s`, printing one per line:
---
--- `s = "hello world from Lua"`
--- `for w in string.gmatch(s, "%a+") do`
--- > `print(w)`
--- `end`
---
--- The next example collects all pairs `key=value` from the given string into a
--- table:
---
--- `t = {}`
--- s = "from=world, to=Lua"`
--- `for k, v in string.gmatch(s, "(%w+)=(%w+)") do`
--- > `t[k] = v`
--- `end`
---
--- For this function, a caret '`^`' at the start of a pattern does not work as
--- an anchor, as this would prevent the iteration.
---@param s string
---@param pattern string
---@return fun():string, table
function string.gmatch(s, pattern) end
---
--- Returns a copy of `s` in which all (or the first `n`, if given)
--- occurrences of the `pattern` have been replaced by a replacement string
--- specified by `repl`, which can be a string, a table, or a function. `gsub`
--- also returns, as its second value, the total number of matches that
--- occurred.
---
--- If `repl` is a string, then its value is used for replacement. The character
--- `%` works as an escape character: any sequence in `repl` of the form `%n`,
--- with *n* between 1 and 9, stands for the value of the *n*-th captured
--- substring (see below). The sequence `%0` stands for the whole match. The
--- sequence `%%` stands for a single `%`.
---
--- If `repl` is a table, then the table is queried for every match, using
--- the first capture as the key; if the pattern specifies no captures, then
--- the whole match is used as the key.
---
--- If `repl` is a function, then this function is called every time a match
--- occurs, with all captured substrings passed as arguments, in order; if
--- the pattern specifies no captures, then the whole match is passed as a
--- sole argument.
---
--- If the value returned by the table query or by the function call is a
--- string or a number, then it is used as the replacement string; otherwise,
--- if it is false or nil, then there is no replacement (that is, the original
--- match is kept in the string).
---
--- Here are some examples:
--- `x = string.gsub("hello world", "(%w+)", "%1 %1")`
--- `-- > x="hello hello world world"`
--- `x = string.gsub("hello world", "%w+", "%0 %0", 1)`
--- `-- > x="hello hello world"`
--- `x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")`
--- `-- > x="world hello Lua from"`
--- `x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)`
--- `-- > x="home = /home/roberto, user = roberto"`
--- `x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)`
--- >> return loadstring(s)()
--- > end)
--- `-- > x="4+5 = 9"`
--- `local t = {name="lua", version="5.4"}`
--- `x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)`
--- > x="lua-5.4.tar.gz"
---@overload fun(s:string, pattern:string, repl:string|fun()):string, number
---@param s string
---@param pattern string
---@param repl string|fun()
---@param n number
---@return string, number
function string.gsub(s, pattern, repl, n) end
---
--- Receives a string and returns its length. The empty string `""` has
--- length 0. Embedded zeros are counted, so `"a\000bc\000"` has length 5.
---@param s string
---@return number
function string.len(s) end
---
--- Receives a string and returns a copy of this string with all uppercase
--- letters changed to lowercase. All other characters are left unchanged. The
--- definition of what an uppercase letter is depends on the current locale.
---@param s string
---@return string
function string.lower(s) end
---
--- Looks for the first *match* of `pattern` in the string `s`. If it
--- finds one, then `match` returns the captures from the pattern; otherwise
--- it returns **nil**. If `pattern` specifies no captures, then the whole match
--- is returned. A third, optional numerical argument `init` specifies where
--- to start the search; its default value is 1 and can be negative.
---@overload fun(s:string, pattern:string):any
---@param s string
---@param pattern string
---@param init number
---@return any
function string.match(s, pattern, init) end
---
--- Returns a binary string containing the values `v1`, `v2`, etc. packed (that
--- is, serialized in binary form) according to the format string `fmt`.
---@param fmt string
---@param v1 string
---@param v2 string
---@return string
function string.pack(fmt, v1, v2, ...) end
---
--- Returns the size of a string resulting from `string.pack` with the given
--- format. The format string cannot have the variable-length options '`s`' or
--- '`z`'
---@param fmt string
---@return number
function string.packsize(fmt) end
---
--- Returns a string that is the concatenation of `n` copies of the string
--- `s` separated by the string `sep`. The default value for `sep` is the empty
--- string (that is, no separator). Returns the empty string if n is not
--- positive.
---
--- Note that it is very easy to exhaust the memory of your machine with a
--- single call to this function.
---@overload fun(s:string, n:number):string
---@param s string
---@param n number
---@param sep string
---@return string
function string.rep(s, n, sep) end
---
--- Returns a string that is the string `s` reversed.
---@param s string
---@return string
function string.reverse(s) end
---
--- Returns the substring of `s` that starts at `i` and continues until
--- `j`; `i` and `j` can be negative. If `j` is absent, then it is assumed to
--- be equal to -1 (which is the same as the string length). In particular,
--- the call `string.sub(s,1,j)` returns a prefix of `s` with length `j`, and
--- `string.sub(s, -i)` (for a positive i) returns a suffix of `s` with length
--- `i`.
---
--- If, after the translation of negative indices, `i` is less than 1, it is
--- corrected to 1. If `j` is greater than the string length, it is corrected to
--- that length. If, after these corrections, `i` is greater than `j`, the
--- function returns the empty string.
---@overload fun(s:string, i:number):string
---@param s string
---@param i number
---@param j number
---@return string
function string.sub(s, i, j) end
---
--- Returns the values packed in string `s` according to the format string
--- `fmt`. An optional `pos` marks where to start reading in `s` (default is 1).
--- After the read values, this function also returns the index of the first
--- unread byte in `s`.
---@overload fun(fmt:string, s:string):string
---@param fmt string
---@param s string
---@param pos number
---@return string
function string.unpack(fmt, s, pos) end
---
--- Receives a string and returns a copy of this string with all lowercase
--- letters changed to uppercase. All other characters are left unchanged. The
--- definition of what a lowercase letter is depends on the current locale.
---@param s string
---@return string
function string.upper(s) end

116
lib/table.lua Normal file
View File

@ -0,0 +1,116 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
table = {}
---
--- Given a list where all elements are strings or numbers, returns the string
--- `list[i]..sep..list[i+1] ... sep..list[j]`. The default value for
--- `sep` is the empty string, the default for `i` is 1, and the default for
--- `j` is #list. If `i` is greater than `j`, returns the empty string.
---@overload fun(list:table):string
---@overload fun(list:table, sep:string):string
---@overload fun(list:table, sep:string, i:number):string
---@param list table
---@param sep string
---@param i number
---@param j number
---@return string
function table.concat(list, sep, i, j) end
---
--- Inserts element `value` at position `pos` in `list`, shifting up the
--- elements to `list[pos]`, `list[pos+1]`, `···`, `list[#list]`. The default
--- value for `pos` is ``#list+1`, so that a call `table.insert(t,x)`` inserts
--- `x` at the end of list `t`.
---@overload fun(list:table, value:any):number
---@param list table
---@param pos number
---@param value any
---@return number
function table.insert(list, pos, value) end
---
--- Moves elements from table a1 to table `a2`, performing the equivalent to
--- the following multiple assignment: `a2[t]`,`··· = a1[f]`,`···,a1[e]`. The
--- default for `a2` is `a1`. The destination range can overlap with the source
--- range. The number of elements to be moved must fit in a Lua integer.
---
--- Returns the destination table `a2`.
---@overload fun(a1:table, f:number, e:number, t:number):table
---@param a1 table
---@param f number
---@param e number
---@param t number
---@param a2 table
---@return table
function table.move(a1, f, e, t, a2) end
---
--- Returns a new table with all arguments stored into keys 1, 2, etc. and
--- with a field "`n`" with the total number of arguments. Note that the
--- resulting table may not be a sequence, if some arguments are **nil**.
---@return table
function table.pack(...) end
---
--- Removes from `list` the element at position `pos`, returning the value of
--- the removed element. When `pos` is an integer between 1 and `#list`, it
--- shifts down the elements `list[pos+1]`, `list[pos+2]`, `···`,
--- `list[#list]` and erases element `list[#list]`; The index pos can also be 0
--- when `#list` is 0, or `#list` + 1; in those cases, the function erases
--- the element `list[pos]`.
---
--- The default value for `pos` is `#list`, so that a call `table.remove(l)`
--- removes the last element of list `l`.
---@overload fun<V>(list:table<number, V> | V[]):V
---@generic V
---@param list table<number, V>
---@param pos number
---@return V
function table.remove(list, pos) end
---
--- Sorts list elements in a given order, *in-place*, from `list[1]` to
--- `list[#list]`. If `comp` is given, then it must be a function that receives
--- two list elements and returns true when the first element must come before
--- the second in the final order (so that, after the sort, `i < j` implies not
--- `comp(list[j],list[i]))`. If `comp` is not given, then the standard Lua
--- operator `<` is used instead.
---
--- Note that the `comp` function must define a strict partial order over the
--- elements in the list; that is, it must be asymmetric and transitive.
--- Otherwise, no valid sort may be possible.
---
--- The sort algorithm is not stable: elements considered equal by the given
--- order may have their relative positions changed by the sort.
---@overload fun(list:table):number
---@generic V
---@param list table<number, V> | V[]
---@param comp fun(a:V, b:V):boolean
---@return number
function table.sort(list, comp) end
---
--- Returns the elements from the given list. This function is equivalent to
--- return `list[i]`, `list[i+1]`, `···`, `list[j]`
--- By default, i is 1 and j is #list.
---@overload fun(list:table):any
---@param list table
---@param i number
---@param j number
---@return any
function table.unpack(list, i, j) end
return table

82
lib/utf8.lua Normal file
View File

@ -0,0 +1,82 @@
-- Copyright (c) 2018. tangzx(love.tangzx@qq.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- use this file except in compliance with the License. You may obtain a copy of
-- the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations under
-- the License.
utf8 = {}
---
--- Receives zero or more integers, converts each one to its corresponding
--- UTF-8 byte sequence and returns a string with the concatenation of all
--- these sequences.
---@return string
function utf8.char(...) end
---
--- The pattern (a string, not a function) "`[\0-\x7F\xC2-\xF4][\x80-\xBF]*`",
--- which matches exactly one UTF-8 byte sequence, assuming that the subject
--- is a valid UTF-8 string.
---@type string
utf8.charpattern = ""
---
--- Returns values so that the construction
--- > `for p, c in utf8.codes(s) do` *body* `end`
--- will iterate over all characters in string `s`, with `p` being the position
--- (in bytes) and `c` the code point of each character. It raises an error if
--- it meets any invalid byte sequence.
---@param s string
---@return string
function utf8.codes(s) end
---
--- Returns the codepoints (as integers) from all characters in `s` that start
--- between byte position `i` and `j` (both included). The default for `i` is
--- 1 and for `j` is `i`. It raises an error if it meets any invalid byte
--- sequence.
---@overload fun(s:string):number
---@param s string
---@param i number
---@param j number
---@return number
function utf8.codepoint (s, i, j) end
---
--- Returns the number of UTF-8 characters in string `s` that start between
--- positions `i` and `j` (both inclusive). The default for `i` is 1 and for
--- `j` is -1. If it finds any invalid byte sequence, returns a false value
--- plus the position of the first invalid byte.
---@overload fun(s:string):number
---@param s string
---@param i number
---@param j number
---@return number
function utf8.len(s, i, j) end
---
--- Returns the position (in bytes) where the encoding of the `n`-th character
--- of `s` (counting from position `i`) starts. A negative `n` gets
--- characters before position `i`. The default for `i` is 1 when `n` is
--- non-negative and `#s + 1` otherwise, so that `utf8.offset(s, -n)` gets the
--- offset of the `n`-th character from the end of the string. If the
--- specified character is neither in the subject nor right after its end,
--- the function returns nil. As a special case, when `n` is 0 the function
--- returns the start of the encoding of the character that contains the `i`-th
--- byte of `s`.
---
--- This function assumes that `s` is a valid UTF-8 string.
---@overload fun(s:string):number
---@param s string
---@param n number
---@param i number
---@return number
function utf8.offset (s, n, i) end

20
vm.go
View File

@ -9,10 +9,12 @@ package lua
import (
"fmt"
_ "github.com/vadv/gopher-lua-libs"
libs "github.com/vadv/gopher-lua-libs"
luaCompile "github.com/yuin/gopher-lua"
"github.com/yuin/gopher-lua/ast"
"github.com/yuin/gopher-lua/parse"
"os"
"path/filepath"
"strings"
"sync"
)
@ -22,7 +24,19 @@ var (
)
// InitVM 初始化lua虚拟机
func InitVM(poolSize int, preComplierScript map[string]string) error {
func InitVM(poolSize int, libPath []string, preComplierScript map[string]string) error {
if len(libPath) == 0 {
libPath = []string{"./lib"} // 默认使用内置的lib
}
pathStr := ""
for _, path := range libPath {
// 绝对路径
libDir, _ := filepath.Abs(path)
libDir = filepath.Join(libDir, "?.lua")
pathStr += ";" + libDir
}
pathStr += ";;"
os.Setenv("LUA_PATH", pathStr)
if poolSize <= 0 {
poolSize = 32
}
@ -82,6 +96,8 @@ func (v *VM) GetVm() *luaCompile.LState {
return luaCompile.NewState()
}
l := v.pool[len(v.pool)-1]
// 基于libs预导入lua的常用模块
libs.Preload(l)
v.pool = v.pool[:len(v.pool)-1]
return l
}

View File

@ -8,10 +8,26 @@
package lua
import (
"fmt"
"testing"
)
func TestNewVm(t *testing.T) {
v := NewVm()
v.Run(`print("hello world"); return "hahaha", "heiheihei"`)
scriptTable := map[string]string{
"json": `local json = require("dkjson")
local lua_table = {
name = "wx771720",
age = 18,
married = true,
skills = {"typescript", "unity", "lua"}
}
local json_str = json.encode(lua_table)
print(json_str) -- 输出JSON字符串`,
}
if err := InitVM(1024, nil, scriptTable); err != nil {
panic(err.Error())
}
_, err := VMInstance.RunPreCompileScript("json")
fmt.Println(err)
}