Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Avril112113 committed Apr 9, 2024
0 parents commit 27f925b
Show file tree
Hide file tree
Showing 9 changed files with 683 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
release/
test_addon/

build.log
26 changes: 26 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"Lua.runtime.version": "LuaJIT",
"Lua.workspace.library": [
"c:/Users/avril/.vscode/extensions/nameouschangey.lifeboatapi-0.0.33/assets/lua/Common/",
"c:/Users/avril/.vscode/extensions/nameouschangey.lifeboatapi-0.0.33/assets/lua/Addon/",
"C:/Users/avril/AppData/Roaming/Code/User/globalStorage/sumneko.lua/addonManager/addons/luafilesystem/module/library",
"../SelenScript",
"../SelenScript/libs"
],
"Lua.workspace.checkThirdParty": false,
"Lua.runtime.pathStrict": true,
"Lua.runtime.path": [
"?.lua",
"?/init.lua",
"../SelenScript/libs/?.lua",
"../SelenScript/libs/?/init.lua",
"../SelenScript/?.lua",
"../SelenScript/?/init.lua"
],
"Lua.workspace.ignoreDir": [
".vscode",
"release",
"test_addon",
"IMAI"
]
}
16 changes: 16 additions & 0 deletions build_release.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@echo off
@REM I really hate batch...


if exist "./release/" rmdir "./release/" /q /s
mkdir "./release/"

mkdir "./release/SSSWTool"
copy "./main.lua" "./release/SSSWTool/main.lua"
copy "./ssswtool.bat" "./release/SSSWTool/ssswtool.bat"
copy "./transform_lua_to_swaddon.lua" "./release/SSSWTool/transform_lua_to_swaddon.lua"
copy "./transform_swaddon_tracing.lua" "./release/SSSWTool/transform_swaddon_tracing.lua"

mkdir "./release/SelenScript"
xcopy "../SelenScript/libs" "./release/SelenScript/libs" /s /e /i
xcopy "../SelenScript/SelenScript" "./release/SelenScript/SelenScript" /s /e /i
137 changes: 137 additions & 0 deletions main.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
local args = assert(arg)

local tool_path = assert(args[0]):gsub("[\\/][^\\/]*$", "")

package.path = ("%s/?.lua;%s/?/init.lua;%s/../SelenScript/libs/?.lua;%s/../SelenScript/libs/?/init.lua;%s/../SelenScript/?.lua;%s/../SelenScript/?/init.lua;"):gsub("%%s", tool_path)
package.cpath = ("%s/?.dll;%s/../SelenScript/libs/?.dll;"):gsub("%%s", tool_path)

local lfs = require "lfs"
local logging = require "logging".windows_enable_ansi().set_log_file("build.log", true)
---@diagnostic disable-next-line: duplicate-set-field
logging.get_source = function() return "" end

local Parser = require "SelenScript.parser.parser"
local Transformer = require "SelenScript.transformer.transformer"
local Emitter = require "SelenScript.emitter.emitter"
local Utils = require "SelenScript.utils"
local ASTHelpers = require "SelenScript.transformer.ast_helpers"

local SWAddonTransformerDefs = require "transform_lua_to_swaddon"
local SWAddonTracerTransformerDefs = require "transform_swaddon_tracing"


if table.remove(args, 1) ~= "build" then
print_error("Argument #1 expected 'build'")
os.exit(-1)
end

local addon_dir = (table.remove(args, 1) or ""):gsub("\\", "/"):gsub("^./", ""):gsub("/$", "")
if #addon_dir <= 0 then
addon_dir = "."
end
local addon_dir_attributes = assert(lfs.attributes(addon_dir), "Invalid arg #1 addon path.")
assert(addon_dir_attributes.mode == "directory", "Invalid arg #1 addon path must be a directory.")

local script_file = addon_dir .. "/script.lua"
assert(lfs.attributes(script_file), "Addon directory does not contain 'script.lua'.")

local script_file_src = Utils.readFile(script_file)

local enable_tracing = false
for i, arg in ipairs(args) do
if arg == "--trace" then
enable_tracing = true
elseif arg == "--no-trace" then
enable_tracing = false
else
print_warn(("Unexpected argument #%i '%s'"):format(i, arg))
end
end

local time_start = os.clock()

local parser
do
local errors
print_info("Creating parser")
parser, errors = Parser.new()
if #errors > 0 then
print_error("-- Parser creation Errors: " .. #errors .. " --")
for _, v in ipairs(errors) do
print_error((v.id or "NO_ID") .. ": " .. v.msg)
end
os.exit(-1)
end
if parser == nil or #errors > 0 then
print_error("Failed to create parser.")
os.exit(-1)
end
end

local ast, comments
do
local errors
print_info("Parsing 'script.lua'")
ast, errors, comments = parser:parse(script_file_src, script_file)
if #errors > 0 then
print_error("-- Parse Errors: " .. #errors .. " --")
for _, v in ipairs(errors) do
print_error(v.id .. ": " .. v.msg)
end
os.exit(-1)
end
end

do
print_info("Transforming AST")
local transformer = Transformer.new(SWAddonTransformerDefs)
local errors = transformer:transform(ast, {
addon_dir=addon_dir,
parser=parser,
})
if #errors > 0 then
print_error("-- Transformer Errors: " .. #errors .. " --")
for _, v in ipairs(errors) do
print_error(v.id .. ": " .. v.msg)
end
os.exit(-1)
end
end


if enable_tracing then
print_info("Transforming AST (DBG Tracer)")
local transformer = Transformer.new(SWAddonTracerTransformerDefs)
local errors = transformer:transform(ast, {
addon_dir=addon_dir,
parser=parser,
})
if #errors > 0 then
print_error("-- Transformer Errors: " .. #errors .. " --")
for _, v in ipairs(errors) do
print_error(v.id .. ": " .. v.msg)
end
os.exit(-1)
end
end

do
-- Add comment at beginning of file to disable all diagnostics of the file.
-- This isn't required but is nice to have.
table.insert(ast.block.block, 1, ASTHelpers.Nodes.LineComment(ast.block.block[1], "---", "@diagnostic disable"))
end

do
print_info("Emitting Lua")
local emitter_lua = Emitter.new("lua", {})
local script_out, script_out_source_map = emitter_lua:generate(ast, {
base_path = addon_dir,
luacats_source_prefix = "..",
})

lfs.mkdir(addon_dir .. "/_build")
Utils.writeFile(addon_dir .. "/_build/script.lua", script_out)

local time_finish = os.clock()
print_info(("Finished in %ss."):format(time_finish-time_start))
end
29 changes: 29 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SSSWTool
A tool utilizing [SelenScript](https://github.com/Avril112113/selenscript)'s parser to combine your StormWorks addon code into a single file.
The catch, it's intelligent and adds more features!

This project is currently **VERY work in progress**, it's lacking a decent CLI and various features.
As it is right now, it's not considered a replacement for other tools until further testing and features has been finished.

To clarify, the following is what this tool provides:
- Combining multiple files into one.
- Optional tracing with `--trace` which provides full stack traces at runtime with source file, line and column info
- TODO: Config file (for predefined options and output path, eg)
- TODO: Build output path.
- TODO: Custom build actions.
- TODO: vscode task template.

## Usage
Run `ssswtool.bat` either directly or `ssswtool` if it's on your PATH.
The file `script.lua` is the entrypoint, any files `require()` from there will be directly included into the output.
Build with `ssswtool build ./`, or with tracing `ssswtool build ./ --trace`
The default output directory is `<ADDON_SRC>/_build/script.lua` (not configurable yet)

## [Releases](https://github.com/Avril112113/SSSWTool/releases)
See the [releases](https://github.com/Avril112113/SSSWTool/releases) for download.
If you want to use `ssswtool` anywhere, consider adding the `./SSSWTool/` to your PATH (the directory containing `ssswtool.bat`).
See (usage)[#Usage] for how to use this tool.

**Pre-Built Binaries:**
The releases come with `luajit` pre-built, you can delete the files and it'll use your system version instead.
SelenScript also comes with pre-built libraries for `lfs` and `lpeglabel` in `./SelenScript/libs`.
9 changes: 9 additions & 0 deletions ssswtool.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@echo off

if exist "%~dp0luajit.exe" (
echo - Using provided luajit.
"%~dp0\luajit.exe" "%~dp0main.lua" %*
) else (
echo - Using system luajit.
luajit "%~dp0main.lua" %*
)
69 changes: 69 additions & 0 deletions tracing_prefix.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---@diagnostic disable: duplicate-set-field


---@alias SS_SW_DBG.INFO {name:string, line:integer, column:integer, file:string}

SS_SW_DBG = {}
---@type integer[]
SS_SW_DBG._stack = {}

function SS_SW_DBG._trace_enter(id)
table.insert(SS_SW_DBG._stack, #SS_SW_DBG._stack+1, id)
end

function SS_SW_DBG._trace_exit(id)
local removed_id = table.remove(SS_SW_DBG._stack, #SS_SW_DBG._stack)
if removed_id ~= id then
local msg = ("Attempt to exit trace '%s' but found '%s' instead."):format(id, removed_id)
debug.log("[SW] [ERROR] " .. msg)
server.announce(server.getAddonData((server.getAddonIndex())).name, msg, -1)
end
end

function SS_SW_DBG._trace_func(id, f, ...)
SS_SW_DBG._trace_enter(id)
local results = {f(...)}
SS_SW_DBG._trace_exit(id)
return table.unpack(results)
end

---@param depth integer?
function SS_SW_DBG.stacktrace(depth)
depth = depth or #SS_SW_DBG._stack
local lines = {}
local prev_file
for i=depth,1,-1 do
local id = SS_SW_DBG._stack[i]
local trace = SS_SW_DBG._info[id]
if trace.file ~= prev_file then
prev_file = trace.file
table.insert(lines, (" '%s'"):format(trace.file))
end
table.insert(lines, ("%s %s @ %s:%s"):format(i, trace.name, trace.line, trace.column))
end
return lines
end

---@param expected_depth integer
---@return boolean # true when stack was to be deeper than expected and was shortend with error been logged.
function SS_SW_DBG.check_stack(expected_depth)
if #SS_SW_DBG._stack > expected_depth then
local lines = SS_SW_DBG.stacktrace(#SS_SW_DBG._stack-expected_depth)
table.insert(lines, 1, "Detected unwound stacktrace:")
for i=#SS_SW_DBG._stack-expected_depth,1,-1 do
table.remove(SS_SW_DBG._stack, i)
end
for _, s in ipairs(lines) do debug.log("[SW] [ERROR] " .. s) end
server.announce(server.getAddonData((server.getAddonIndex())).name, table.concat(lines, "\n"), -1)
return true
end
return false
end

---@return SS_SW_DBG.INFO
function SS_SW_DBG.get_current_info()
return SS_SW_DBG._info[SS_SW_DBG._stack[#SS_SW_DBG._stack]]
end

---@type SS_SW_DBG.INFO[]
SS_SW_DBG._info = {}
Loading

0 comments on commit 27f925b

Please sign in to comment.