SoUI 0.5版本占坑
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.8 KiB

3 years ago
local select=select
local load=load
local string=string
local table=table
local storm = require 'ffi.storm'
local function result(...)
return select("#",...), select(1,...)
end
local function precompile(code, output_func, lua_codes)
if lua_codes == nil then
lua_codes = {''}
end
local start_tag = '<?'
local end_tag = '?>'
local start1, end1 = string.find(code, start_tag, 1, true)
local start2 = nil
local end2 = 0
local cEqual = string.byte('=', 1)
while start1 ~= nil do
if start1 > end2 + 1 then
table.insert(lua_codes, output_func..'('..string.format("%q", string.sub(code, end2 + 1, start1 - 1))..')')
end
start2, end2 = string.find(code, end_tag, end1 + 1, true)
if start2 ~= nil then
if string.byte(code, end1 + 1) ~= cEqual then
table.insert(lua_codes, string.sub(code, end1 + 1, start2 - 1))
else
table.insert(lua_codes, output_func..'('..string.sub(code, end1 + 2, start2 - 1)..')')
end
start1, end1 = string.find(code, start_tag, end2 + 1, true)
else
-- end tag not found
end2 = end1
start1 = nil
-- we could error it, but we ignore it here
end
end
table.insert(lua_codes, output_func..'('..string.format("%q", string.sub(code, end2 + 1))..')')
return
end
local function map_file_import(path_in_archive)
return function (buf, is_path)
if is_path then
log.trace("[stormlib]import file", path_in_archive)
__map_handle__:add_file(path_in_archive, __map_path__:parent_path() / buf)
return
else
local temp_file_path = fs.ydwe_path() / "logs" / "import" / path_in_archive
fs.create_directories(temp_file_path:parent_path())
if not io.save(temp_file_path, buf) then
log.error("failed: save " .. temp_file_path:string())
return
end
log.trace("[stormlib]import file", path_in_archive)
__map_handle__:add_file(path_in_archive, temp_file_path)
return
end
end
end
local function string_hash(str)
return string.format('0x%08X', storm.string_hash(str))
end
template = {}
function template:do_compile(op)
local code, err = io.load(op.input)
if not code then
log.error("Template read " .. op.input:string() .. ". Error: " .. err)
return false, err
end
local lua_codes = {''}
table.insert(lua_codes, "local __jass_result__ = {''}")
table.insert(lua_codes, "local function __jass_output__(str) table.insert(__jass_result__, str) end")
local r, err = pcall(precompile, code, '__jass_output__', lua_codes)
if not r then
return r, err
end
package.loaded['slk'] = nil
__map_handle__ = op.map_handle
__map_path__ = op.map_path
local env = {
import = map_file_import,
StringHash = string_hash,
ability2order = require 'computed.ability2order',
}
setmetatable(env, {__index = _G})
table.insert(lua_codes, "return table.concat(__jass_result__)")
local f, err = load(table.concat(lua_codes, '\n'), nil, 't', env)
if not f then
return f, err
end
local suc, content = xpcall(f, function(msg) return debug.traceback(msg) end)
if not suc then
return false, content
end
if package.loaded['slk'] then
package.loaded['slk']:refresh(__map_handle__.handle)
end
return true, content
end
function template:compile(op)
log.trace("Template compilation start.")
op.output = fs.ydwe_path() / "logs" / "lua_processed.j"
local success, content = self:do_compile(op)
if not success then
if content then
local msg = content
local pos = content:find 'stack traceback:'
if pos then
msg = msg:sub(1, pos-1)
end
gui.error_message(nil, __(msg))
else
gui.error_message(nil, _("Unknown"))
end
log.error("Template error processing: " .. tostring(content))
return false
end
local result, err = io.save(op.output, content)
if not result then
log.error("Template write " .. op.output:string() .. ". Error: " .. err)
return false
end
log.debug("Template compilation succeeded.")
return true
end