1
0
forked from osmarks/potatOS

performance improvements, probably

This commit is contained in:
osmarks 2021-03-31 19:58:54 +01:00
parent b4d3bd4c89
commit 8238a4e45d
27 changed files with 5296 additions and 17 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
dist dist
update-key update-key
__pycache__ __pycache__
node_modules

View File

@ -8,7 +8,14 @@ cp -r src/LICENSES dist
cp -r src/stdlib.hvl dist cp -r src/stdlib.hvl dist
cp -r src/bin/ dist cp -r src/bin/ dist
cp src/potatobios.lua dist/ cp src/potatobios.lua dist/
luabundler bundle src/main.lua -p "src/lib/?.lua" | perl -pe 'chomp if eof' > dist/autorun.lua npx luabundler bundle src/main.lua -p "src/lib/?.lua" | perl -pe 'chomp if eof' > dist/autorun_full.lua
WORK=$(pwd)
cd ./minify
lua5.1 CommandLineMinify.lua "$WORK/dist/autorun_full.lua" "$WORK/dist/autorun.lua"
lua5.1 CommandLineMinify.lua "$WORK/dist/potatobios.lua" "$WORK/dist/pb_tmp.lua"
mv "$WORK/dist/pb_tmp.lua" "$WORK/dist/potatobios.lua"
cd "$WORK"
rm dist/autorun_full.lua
sed -i '19iif _G.package and _G.package.loaded[package] then loadedModule = _G.package.loaded[package] end if _G.package and _G.package.preload[package] then local pkg = _G.package.preload[package](_G.package) _G.package.loaded[package] = pkg loadedModule = pkg end' dist/autorun.lua sed -i '19iif _G.package and _G.package.loaded[package] then loadedModule = _G.package.loaded[package] end if _G.package and _G.package.preload[package] then local pkg = _G.package.preload[package](_G.package) _G.package.loaded[package] = pkg loadedModule = pkg end' dist/autorun.lua
echo -n "(...)" >> dist/autorun.lua echo -n "(...)" >> dist/autorun.lua
./generate_manifest.py "$@" ./generate_manifest.py "$@"

View File

@ -1,2 +1,2 @@
{"build":190,"description":"factor program","files":{"LICENSES":"f3549d84d66eb53dd4a421a4341d77d3d217c1b117d67e3be8f5211adcda0952","autorun.lua":"03a6ea1216a3611db53158bc59c3ce018c9d2539f9e4241b9221011017b9ce89","bin/5rot26.lua":"91b66cd6d4b33081b25c456142dd7efcb894e819e842693c9e1e17ff48872ff5","bin/ccemux.lua":"239476f58835b86bbcac31ce8af3c3acd3d198a55ab9ada78c62fbf358625a98","bin/chronometer.lua":"db5363993a04382145aef7db2fbe262f0bf10697a589e1e2d2f9ce0f87430dd8","bin/factor.lua":"72a0756f377b1f8a8dc72dc4d565c62e428c3ca6ea86a6598a8347413b99d17a","bin/grep.lua":"1509bc267867b933e528ab74cfbc2a15fa2df0ec7389df4f9033194ab9037865","bin/kristminer.lua":"7e7f9fe2a6493d584ad6926cda915e02c1c3d800dc209680898ce930d0bb0e6f","bin/livegps.lua":"c3d17d495cda01aa1261e4c4fcd43439b29af422671972117ec34f68e32c5bba","bin/loading.lua":"c85f7aa1765170325155b921c1fceeb62643f552f12d41b529a22af3a67f5a97","bin/potatoflight.lua":"2fbb0b6f8d78728d8cb0ec64af1bc598bd00cb55f202378e7acdb86bba71efd1","bin/potatoplex.lua":"86c9e7597bbe23d7de7e7f1bfc976d0b94dcdf3af9e6c7c6c9b18b98596898c8","bin/relay.lua":"261ae6c220b83506e3326e8f2b091d246baae458ff0d2ee87512be2c4e35a75d","bin/tryhaskell.lua":"07810d85145da65a3e434154c79d5a9d72f2dcbe59c8d6829040fb925df878ec","potatobios.lua":"7593e0f9d0755eea05e3c0fff5c4c9e036745a8cbc20e9e19609d8743a77b87e","signing-key.tbl":"b32af5229c23af3bc03d538e42751b26044e404a7b1af064ed89894efe421607","startup":"f17bfb9b4322c4467dc9170d50827f2d75717e5c3125d734f21f3406657917bc","stdlib.hvl":"a6fd2620068f47794a9bbeed77bee3fd4962f848e6dd7c75137b30cd5665272e","update-key.hex":"8d8afb7a45833bb7d68f929421ad60a211d4d73e0ee03b24dc0106ba1de2e1a0","xlib/00_cbor.lua":"464b075e4f094b8db42506bd4bdaad0db87699ea7fbf80e5b87739b4aa9279af","xlib/01_skynet.lua":"9cb565d639a0acd7c763c3e7422482532cd0bda0cdfcc720089ab4a87e551339","xlib/03_heavlisp.lua":"82cdabd5286058c0ea4f27956f8c1144e198769c8b8ce9e91b26c930d711f710"},"sizes":{"LICENSES":4725,"autorun.lua":182536,"bin/5rot26.lua":914,"bin/ccemux.lua":1673,"bin/chronometer.lua":1152,"bin/factor.lua":4273,"bin/grep.lua":1196,"bin/kristminer.lua":5566,"bin/livegps.lua":980,"bin/loading.lua":7707,"bin/potatoflight.lua":3417,"bin/potatoplex.lua":6526,"bin/relay.lua":3075,"bin/tryhaskell.lua":1867,"potatobios.lua":71272,"signing-key.tbl":190,"startup":8313,"stdlib.hvl":851,"update-key.hex":44,"xlib/00_cbor.lua":15808,"xlib/01_skynet.lua":3286,"xlib/03_heavlisp.lua":15643},"timestamp":1612529895} {"build":231,"description":"craftos-pc workaround for broken HTTP","files":{"LICENSES":"f3549d84d66eb53dd4a421a4341d77d3d217c1b117d67e3be8f5211adcda0952","autorun.lua":"7855e924c92280ad92db72cf02f711653db5a43159763e44e461af1b32e03090","bin/5rot26.lua":"417891a232e325476f980d31d88edc486d526611a6350ce47fd29cca464ebf2c","bin/ccemux.lua":"239476f58835b86bbcac31ce8af3c3acd3d198a55ab9ada78c62fbf358625a98","bin/chronometer.lua":"db5363993a04382145aef7db2fbe262f0bf10697a589e1e2d2f9ce0f87430dd8","bin/factor.lua":"3b7578dd4fca7586dc19d651d4838fba8fffe504b11d037f8d02acf062df5178","bin/grep.lua":"1509bc267867b933e528ab74cfbc2a15fa2df0ec7389df4f9033194ab9037865","bin/kristminer.lua":"7e7f9fe2a6493d584ad6926cda915e02c1c3d800dc209680898ce930d0bb0e6f","bin/livegps.lua":"c3d17d495cda01aa1261e4c4fcd43439b29af422671972117ec34f68e32c5bba","bin/loading.lua":"c85f7aa1765170325155b921c1fceeb62643f552f12d41b529a22af3a67f5a97","bin/potatoflight.lua":"2fbb0b6f8d78728d8cb0ec64af1bc598bd00cb55f202378e7acdb86bba71efd1","bin/potatoplex.lua":"86c9e7597bbe23d7de7e7f1bfc976d0b94dcdf3af9e6c7c6c9b18b98596898c8","bin/relay.lua":"261ae6c220b83506e3326e8f2b091d246baae458ff0d2ee87512be2c4e35a75d","bin/tryhaskell.lua":"07810d85145da65a3e434154c79d5a9d72f2dcbe59c8d6829040fb925df878ec","potatobios.lua":"2f904f672d2c370244e9d4d17443bf38848701d3cd69a4acedfff9fc00b19981","signing-key.tbl":"b32af5229c23af3bc03d538e42751b26044e404a7b1af064ed89894efe421607","startup":"2140cb64ba53e7405c411e9e889a2ce6ba1b6f531d89b58865364cc77dd473f9","stdlib.hvl":"a6fd2620068f47794a9bbeed77bee3fd4962f848e6dd7c75137b30cd5665272e","update-key.hex":"8d8afb7a45833bb7d68f929421ad60a211d4d73e0ee03b24dc0106ba1de2e1a0","xlib/00_cbor.lua":"464b075e4f094b8db42506bd4bdaad0db87699ea7fbf80e5b87739b4aa9279af","xlib/01_skynet.lua":"9cb565d639a0acd7c763c3e7422482532cd0bda0cdfcc720089ab4a87e551339","xlib/03_heavlisp.lua":"82cdabd5286058c0ea4f27956f8c1144e198769c8b8ce9e91b26c930d711f710"},"sizes":{"LICENSES":4725,"autorun.lua":101488,"bin/5rot26.lua":1661,"bin/ccemux.lua":1673,"bin/chronometer.lua":1152,"bin/factor.lua":4269,"bin/grep.lua":1196,"bin/kristminer.lua":5566,"bin/livegps.lua":980,"bin/loading.lua":7707,"bin/potatoflight.lua":3417,"bin/potatoplex.lua":6526,"bin/relay.lua":3075,"bin/tryhaskell.lua":1867,"potatobios.lua":40411,"signing-key.tbl":190,"startup":8378,"stdlib.hvl":851,"update-key.hex":44,"xlib/00_cbor.lua":15808,"xlib/01_skynet.lua":3286,"xlib/03_heavlisp.lua":15643},"timestamp":1617216858}
{"hash":"5fa6cfe69f3547f5b3360713f0126c44c69269aad2d76c553e58b7f721021897","sig":"f50a861154fc851603fe13c431b8f7664c3df547313454187d0e2607b0c3af98651312ef1dfaf4ba6a22"} {"hash":"9a33a8b4a5557449e41520b9bc716ea4fff8ed713820aeb5041edf297b70a321","sig":"c6952057de361d534f8e0d96cc30fed7668c32a3313abf56261a3519f7d27bba70c69176887b988d1b32"}

View File

@ -0,0 +1,121 @@
--
-- beautify
--
-- A command line utility for beautifying lua source code using the beautifier.
--
local util = require'Util'
local Parser = require'ParseLua'
local Format_Beautify = require'FormatBeautiful'
local ParseLua = Parser.ParseLua
local PrintTable = util.PrintTable
local function splitFilename(name)
--table.foreach(arg, print)
if name:find(".") then
local p, ext = name:match("()%.([^%.]*)$")
if p and ext then
if #ext == 0 then
return name, nil
else
local filename = name:sub(1,p-1)
return filename, ext
end
else
return name, nil
end
else
return name, nil
end
end
if #arg == 1 then
local name, ext = splitFilename(arg[1])
local outname = name.."_formatted"
if ext then outname = outname.."."..ext end
--
local inf = io.open(arg[1], 'r')
if not inf then
print("Failed to open '"..arg[1].."' for reading")
return
end
--
local sourceText = inf:read('*all')
inf:close()
--
local st, ast = ParseLua(sourceText)
if not st then
--we failed to parse the file, show why
print(ast)
return
end
--
local outf = io.open(outname, 'w')
if not outf then
print("Failed to open '"..outname.."' for writing")
return
end
--
outf:write(Format_Beautify(ast))
outf:close()
--
print("Beautification complete")
elseif #arg == 2 then
--keep the user from accidentally overwriting their non-minified file with
if arg[1]:find("_formatted") then
print("Did you mix up the argument order?\n"..
"Current command will beautify '"..arg[1].."' and overwrite '"..arg[2].."' with the results")
while true do
io.write("Confirm (yes/no): ")
local msg = io.read('*line')
if msg == 'yes' then
break
elseif msg == 'no' then
return
end
end
end
local inf = io.open(arg[1], 'r')
if not inf then
print("Failed to open '"..arg[1].."' for reading")
return
end
--
local sourceText = inf:read('*all')
inf:close()
--
local st, ast = ParseLua(sourceText)
if not st then
--we failed to parse the file, show why
print(ast)
return
end
--
if arg[1] == arg[2] then
print("Are you SURE you want to overwrite the source file with a beautified version?\n"..
"You will be UNABLE to get the original source back!")
while true do
io.write("Confirm (yes/no): ")
local msg = io.read('*line')
if msg == 'yes' then
break
elseif msg == 'no' then
return
end
end
end
local outf = io.open(arg[2], 'w')
if not outf then
print("Failed to open '"..arg[2].."' for writing")
return
end
--
outf:write(Format_Beautify(ast))
outf:close()
--
print("Beautification complete")
else
print("Invalid arguments!\nUsage: lua CommandLineLuaBeautify.lua source_file [destination_file]")
end

View File

@ -0,0 +1,47 @@
--
-- beautify.interactive
--
-- For testing: Lets you enter lines of text to be beautified to verify the
-- correctness of their implementation.
--
local util = require'Util'
local Parser = require'ParseLua'
local Format_Beautify = require'FormatBeautiful'
local ParseLua = Parser.ParseLua
local PrintTable = util.PrintTable
while true do
io.write('> ')
local line = io.read('*line')
local fileFrom, fileTo = line:match("^file (.*) (.*)")
if fileFrom and fileTo then
local file = io.open(fileFrom, 'r')
local fileTo = io.open(fileTo, 'w')
if file and fileTo then
local st, ast = ParseLua(file:read('*all'))
if st then
fileTo:write(Format_Beautify(ast)..'\n')
io.write("Beautification Complete\n")
else
io.write(""..tostring(ast).."\n")
end
file:close()
fileTo:close()
else
io.write("File does not exist\n")
end
else
local st, ast = ParseLua(line)
if st then
io.write("====== AST =======\n")
io.write(PrintTable(ast)..'\n')
io.write("==== BEAUTIFIED ====\n")
io.write(Format_Beautify(ast))
io.write("==================\n")
else
io.write(""..tostring(ast).."\n")
end
end
end

View File

@ -0,0 +1,47 @@
--
-- CommandLineLiveMinify.lua
--
-- For testing: Lets you enter lines of text to be minified to verify the
-- correctness of their implementation.
--
local util = require'Util'
local Parser = require'ParseLua'
local Format_Mini = require'FormatMini'
local ParseLua = Parser.ParseLua
local PrintTable = util.PrintTable
while true do
io.write('> ')
local line = io.read('*line')
local fileFrom, fileTo = line:match("^file (.*) (.*)")
if fileFrom and fileTo then
local file = io.open(fileFrom, 'r')
local fileTo = io.open(fileTo, 'w')
if file and fileTo then
local st, ast = ParseLua(file:read('*all'))
if st then
fileTo:write(Format_Mini(ast)..'\n')
io.write("Minification Complete\n")
else
io.write(""..tostring(ast).."\n")
end
file:close()
fileTo:close()
else
io.write("File does not exist\n")
end
else
local st, ast = ParseLua(line)
if st then
io.write("====== AST =======\n")
io.write(PrintTable(ast)..'\n')
io.write("==== MINIFIED ====\n")
io.write(Format_Mini(ast)..'\n')
io.write("==================\n")
else
io.write(""..tostring(ast).."\n")
end
end
end

View File

@ -0,0 +1,122 @@
--
-- CommandlineMinify.lua
--
-- A command line utility for minifying lua source code using the minifier.
--
local util = require'Util'
local Parser = require'ParseLua'
local Format_Mini = require'FormatMini'
local ParseLua = Parser.ParseLua
local PrintTable = util.PrintTable
local function splitFilename(name)
table.foreach(arg, print)
if name:find(".") then
local p, ext = name:match("()%.([^%.]*)$")
if p and ext then
if #ext == 0 then
return name, nil
else
local filename = name:sub(1,p-1)
return filename, ext
end
else
return name, nil
end
else
return name, nil
end
end
if #arg == 1 then
local name, ext = splitFilename(arg[1])
local outname = name.."_min"
if ext then outname = outname.."."..ext end
--
local inf = io.open(arg[1], 'r')
if not inf then
print("Failed to open `"..arg[1].."` for reading")
return
end
--
local sourceText = inf:read('*all')
inf:close()
--
local st, ast = ParseLua(sourceText)
if not st then
--we failed to parse the file, show why
print(ast)
return
end
--
local outf = io.open(outname, 'w')
if not outf then
print("Failed to open `"..outname.."` for writing")
return
end
--
outf:write(Format_Mini(ast))
outf:close()
--
print("Minification complete")
elseif #arg == 2 then
--keep the user from accidentally overwriting their non-minified file with
if arg[1]:find("_min") then
print("Did you mix up the argument order?\n"..
"Current command will minify `"..arg[1].."` and OVERWRITE `"..arg[2].."` with the results")
while true do
io.write("Confirm (yes/cancel): ")
local msg = io.read('*line')
if msg == 'yes' then
break
elseif msg == 'cancel' then
return
end
end
end
local inf = io.open(arg[1], 'r')
if not inf then
print("Failed to open `"..arg[1].."` for reading")
return
end
--
local sourceText = inf:read('*all')
inf:close()
--
local st, ast = ParseLua(sourceText)
if not st then
--we failed to parse the file, show why
print(ast)
return
end
--
if arg[1] == arg[2] then
print("Are you SURE you want to overwrite the source file with a minified version?\n"..
"You will be UNABLE to get the original source back!")
while true do
io.write("Confirm (yes/cancel): ")
local msg = io.read('*line')
if msg == 'yes' then
break
elseif msg == 'cancel' then
return
end
end
end
local outf = io.open(arg[2], 'w')
if not outf then
print("Failed to open `"..arg[2].."` for writing")
return
end
--
outf:write(Format_Mini(ast))
outf:close()
--
print("Minification complete")
else
print("Invalid arguments, Usage:\nLuaMinify source [destination]")
end

347
minify/FormatBeautiful.lua Normal file
View File

@ -0,0 +1,347 @@
--
-- Beautifier
--
-- Returns a beautified version of the code, including comments
--
local parser = require"ParseLua"
local ParseLua = parser.ParseLua
local util = require'Util'
local lookupify = util.lookupify
local LowerChars = lookupify{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
local UpperChars = lookupify{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
local Digits = lookupify{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
local function Format_Beautify(ast)
local formatStatlist, formatExpr
local indent = 0
local EOL = "\n"
local function getIndentation()
return string.rep(" ", indent)
end
local function joinStatementsSafe(a, b, sep)
sep = sep or ''
local aa, bb = a:sub(-1,-1), b:sub(1,1)
if UpperChars[aa] or LowerChars[aa] or aa == '_' then
if not (UpperChars[bb] or LowerChars[bb] or bb == '_' or Digits[bb]) then
--bb is a symbol, can join without sep
return a .. b
elseif bb == '(' then
--prevent ambiguous syntax
return a..sep..b
else
return a..sep..b
end
elseif Digits[aa] then
if bb == '(' then
--can join statements directly
return a..b
else
return a..sep..b
end
elseif aa == '' then
return a..b
else
if bb == '(' then
--don't want to accidentally call last statement, can't join directly
return a..sep..b
else
return a..b
end
end
end
formatExpr = function(expr)
local out = string.rep('(', expr.ParenCount or 0)
if expr.AstType == 'VarExpr' then
if expr.Variable then
out = out .. expr.Variable.Name
else
out = out .. expr.Name
end
elseif expr.AstType == 'NumberExpr' then
out = out..expr.Value.Data
elseif expr.AstType == 'StringExpr' then
out = out..expr.Value.Data
elseif expr.AstType == 'BooleanExpr' then
out = out..tostring(expr.Value)
elseif expr.AstType == 'NilExpr' then
out = joinStatementsSafe(out, "nil")
elseif expr.AstType == 'BinopExpr' then
out = joinStatementsSafe(out, formatExpr(expr.Lhs)) .. " "
out = joinStatementsSafe(out, expr.Op) .. " "
out = joinStatementsSafe(out, formatExpr(expr.Rhs))
elseif expr.AstType == 'UnopExpr' then
out = joinStatementsSafe(out, expr.Op) .. (#expr.Op ~= 1 and " " or "")
out = joinStatementsSafe(out, formatExpr(expr.Rhs))
elseif expr.AstType == 'DotsExpr' then
out = out.."..."
elseif expr.AstType == 'CallExpr' then
out = out..formatExpr(expr.Base)
out = out.."("
for i = 1, #expr.Arguments do
out = out..formatExpr(expr.Arguments[i])
if i ~= #expr.Arguments then
out = out..", "
end
end
out = out..")"
elseif expr.AstType == 'TableCallExpr' then
out = out..formatExpr(expr.Base) .. " "
out = out..formatExpr(expr.Arguments[1])
elseif expr.AstType == 'StringCallExpr' then
out = out..formatExpr(expr.Base) .. " "
out = out..expr.Arguments[1].Data
elseif expr.AstType == 'IndexExpr' then
out = out..formatExpr(expr.Base).."["..formatExpr(expr.Index).."]"
elseif expr.AstType == 'MemberExpr' then
out = out..formatExpr(expr.Base)..expr.Indexer..expr.Ident.Data
elseif expr.AstType == 'Function' then
-- anonymous function
out = out.."function("
if #expr.Arguments > 0 then
for i = 1, #expr.Arguments do
out = out..expr.Arguments[i].Name
if i ~= #expr.Arguments then
out = out..", "
elseif expr.VarArg then
out = out..", ..."
end
end
elseif expr.VarArg then
out = out.."..."
end
out = out..")" .. EOL
indent = indent + 1
out = joinStatementsSafe(out, formatStatlist(expr.Body))
indent = indent - 1
out = joinStatementsSafe(out, getIndentation() .. "end")
elseif expr.AstType == 'ConstructorExpr' then
out = out.."{ "
for i = 1, #expr.EntryList do
local entry = expr.EntryList[i]
if entry.Type == 'Key' then
out = out.."["..formatExpr(entry.Key).."] = "..formatExpr(entry.Value)
elseif entry.Type == 'Value' then
out = out..formatExpr(entry.Value)
elseif entry.Type == 'KeyString' then
out = out..entry.Key.." = "..formatExpr(entry.Value)
end
if i ~= #expr.EntryList then
out = out..", "
end
end
out = out.." }"
elseif expr.AstType == 'Parentheses' then
out = out.."("..formatExpr(expr.Inner)..")"
end
out = out..string.rep(')', expr.ParenCount or 0)
return out
end
local formatStatement = function(statement)
local out = ""
if statement.AstType == 'AssignmentStatement' then
out = getIndentation()
for i = 1, #statement.Lhs do
out = out..formatExpr(statement.Lhs[i])
if i ~= #statement.Lhs then
out = out..", "
end
end
if #statement.Rhs > 0 then
out = out.." = "
for i = 1, #statement.Rhs do
out = out..formatExpr(statement.Rhs[i])
if i ~= #statement.Rhs then
out = out..", "
end
end
end
elseif statement.AstType == 'CallStatement' then
out = getIndentation() .. formatExpr(statement.Expression)
elseif statement.AstType == 'LocalStatement' then
out = getIndentation() .. out.."local "
for i = 1, #statement.LocalList do
out = out..statement.LocalList[i].Name
if i ~= #statement.LocalList then
out = out..", "
end
end
if #statement.InitList > 0 then
out = out.." = "
for i = 1, #statement.InitList do
out = out..formatExpr(statement.InitList[i])
if i ~= #statement.InitList then
out = out..", "
end
end
end
elseif statement.AstType == 'IfStatement' then
out = getIndentation() .. joinStatementsSafe("if ", formatExpr(statement.Clauses[1].Condition))
out = joinStatementsSafe(out, " then") .. EOL
indent = indent + 1
out = joinStatementsSafe(out, formatStatlist(statement.Clauses[1].Body))
indent = indent - 1
for i = 2, #statement.Clauses do
local st = statement.Clauses[i]
if st.Condition then
out = getIndentation() .. joinStatementsSafe(out, getIndentation() .. "elseif ")
out = joinStatementsSafe(out, formatExpr(st.Condition))
out = joinStatementsSafe(out, " then") .. EOL
else
out = joinStatementsSafe(out, getIndentation() .. "else") .. EOL
end
indent = indent + 1
out = joinStatementsSafe(out, formatStatlist(st.Body))
indent = indent - 1
end
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
elseif statement.AstType == 'WhileStatement' then
out = getIndentation() .. joinStatementsSafe("while ", formatExpr(statement.Condition))
out = joinStatementsSafe(out, " do") .. EOL
indent = indent + 1
out = joinStatementsSafe(out, formatStatlist(statement.Body))
indent = indent - 1
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
elseif statement.AstType == 'DoStatement' then
out = getIndentation() .. joinStatementsSafe(out, "do") .. EOL
indent = indent + 1
out = joinStatementsSafe(out, formatStatlist(statement.Body))
indent = indent - 1
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
elseif statement.AstType == 'ReturnStatement' then
out = getIndentation() .. "return "
for i = 1, #statement.Arguments do
out = joinStatementsSafe(out, formatExpr(statement.Arguments[i]))
if i ~= #statement.Arguments then
out = out..", "
end
end
elseif statement.AstType == 'BreakStatement' then
out = getIndentation() .. "break"
elseif statement.AstType == 'RepeatStatement' then
out = getIndentation() .. "repeat" .. EOL
indent = indent + 1
out = joinStatementsSafe(out, formatStatlist(statement.Body))
indent = indent - 1
out = joinStatementsSafe(out, getIndentation() .. "until ")
out = joinStatementsSafe(out, formatExpr(statement.Condition)) .. EOL
elseif statement.AstType == 'Function' then
if statement.IsLocal then
out = "local "
end
out = joinStatementsSafe(out, "function ")
out = getIndentation() .. out
if statement.IsLocal then
out = out..statement.Name.Name
else
out = out..formatExpr(statement.Name)
end
out = out.."("
if #statement.Arguments > 0 then
for i = 1, #statement.Arguments do
out = out..statement.Arguments[i].Name
if i ~= #statement.Arguments then
out = out..", "
elseif statement.VarArg then
out = out..",..."
end
end
elseif statement.VarArg then
out = out.."..."
end
out = out..")" .. EOL
indent = indent + 1
out = joinStatementsSafe(out, formatStatlist(statement.Body))
indent = indent - 1
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
elseif statement.AstType == 'GenericForStatement' then
out = getIndentation() .. "for "
for i = 1, #statement.VariableList do
out = out..statement.VariableList[i].Name
if i ~= #statement.VariableList then
out = out..", "
end
end
out = out.." in "
for i = 1, #statement.Generators do
out = joinStatementsSafe(out, formatExpr(statement.Generators[i]))
if i ~= #statement.Generators then
out = joinStatementsSafe(out, ', ')
end
end
out = joinStatementsSafe(out, " do") .. EOL
indent = indent + 1
out = joinStatementsSafe(out, formatStatlist(statement.Body))
indent = indent - 1
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
elseif statement.AstType == 'NumericForStatement' then
out = getIndentation() .. "for "
out = out..statement.Variable.Name.." = "
out = out..formatExpr(statement.Start)..", "..formatExpr(statement.End)
if statement.Step then
out = out..", "..formatExpr(statement.Step)
end
out = joinStatementsSafe(out, " do") .. EOL
indent = indent + 1
out = joinStatementsSafe(out, formatStatlist(statement.Body))
indent = indent - 1
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
elseif statement.AstType == 'LabelStatement' then
out = getIndentation() .. "::" .. statement.Label .. "::" .. EOL
elseif statement.AstType == 'GotoStatement' then
out = getIndentation() .. "goto " .. statement.Label .. EOL
elseif statement.AstType == 'Comment' then
if statement.CommentType == 'Shebang' then
out = getIndentation() .. statement.Data
--out = out .. EOL
elseif statement.CommentType == 'Comment' then
out = getIndentation() .. statement.Data
--out = out .. EOL
elseif statement.CommentType == 'LongComment' then
out = getIndentation() .. statement.Data
--out = out .. EOL
end
elseif statement.AstType == 'Eof' then
-- Ignore
else
print("Unknown AST Type: ", statement.AstType)
end
return out
end
formatStatlist = function(statList)
local out = ''
for _, stat in pairs(statList.Body) do
out = joinStatementsSafe(out, formatStatement(stat) .. EOL)
end
return out
end
return formatStatlist(ast)
end
return Format_Beautify

436
minify/FormatIdentity.lua Normal file
View File

@ -0,0 +1,436 @@
require'strict'
require'ParseLua'
local util = require'Util'
local function debug_printf(...)
--[[
util.printf(...)
--]]
end
--
-- FormatIdentity.lua
--
-- Returns the exact source code that was used to create an AST, preserving all
-- comments and whitespace.
-- This can be used to get back a Lua source after renaming some variables in
-- an AST.
--
local function Format_Identity(ast)
local out = {
rope = {}, -- List of strings
line = 1,
char = 1,
appendStr = function(self, str)
table.insert(self.rope, str)
local lines = util.splitLines(str)
if #lines == 1 then
self.char = self.char + #str
else
self.line = self.line + #lines - 1
local lastLine = lines[#lines]
self.char = #lastLine
end
end,
appendToken = function(self, token)
self:appendWhite(token)
--[*[
--debug_printf("appendToken(%q)", token.Data)
local data = token.Data
local lines = util.splitLines(data)
while self.line + #lines < token.Line do
print("Inserting extra line")
self.str = self.str .. '\n'
self.line = self.line + 1
self.char = 1
end
--]]
self:appendStr(token.Data)
end,
appendTokens = function(self, tokens)
for _,token in ipairs(tokens) do
self:appendToken( token )
end
end,
appendWhite = function(self, token)
if token.LeadingWhite then
self:appendTokens( token.LeadingWhite )
--self.str = self.str .. ' '
end
end
}
local formatStatlist, formatExpr;
formatExpr = function(expr)
local tok_it = 1
local function appendNextToken(str)
local tok = expr.Tokens[tok_it];
if str and tok.Data ~= str then
error("Expected token '" .. str .. "'. Tokens: " .. util.PrintTable(expr.Tokens))
end
out:appendToken( tok )
tok_it = tok_it + 1
end
local function appendToken(token)
out:appendToken( token )
tok_it = tok_it + 1
end
local function appendWhite()
local tok = expr.Tokens[tok_it];
if not tok then error(util.PrintTable(expr)) end
out:appendWhite( tok )
tok_it = tok_it + 1
end
local function appendStr(str)
appendWhite()
out:appendStr(str)
end
local function peek()
if tok_it < #expr.Tokens then
return expr.Tokens[tok_it].Data
end
end
local function appendComma(mandatory, seperators)
if true then
seperators = seperators or { "," }
seperators = util.lookupify( seperators )
if not mandatory and not seperators[peek()] then
return
end
assert(seperators[peek()], "Missing comma or semicolon")
appendNextToken()
else
local p = peek()
if p == "," or p == ";" then
appendNextToken()
end
end
end
debug_printf("formatExpr(%s) at line %i", expr.AstType, expr.Tokens[1] and expr.Tokens[1].Line or -1)
if expr.AstType == 'VarExpr' then
if expr.Variable then
appendStr( expr.Variable.Name )
else
appendStr( expr.Name )
end
elseif expr.AstType == 'NumberExpr' then
appendToken( expr.Value )
elseif expr.AstType == 'StringExpr' then
appendToken( expr.Value )
elseif expr.AstType == 'BooleanExpr' then
appendNextToken( expr.Value and "true" or "false" )
elseif expr.AstType == 'NilExpr' then
appendNextToken( "nil" )
elseif expr.AstType == 'BinopExpr' then
formatExpr(expr.Lhs)
appendStr( expr.Op )
formatExpr(expr.Rhs)
elseif expr.AstType == 'UnopExpr' then
appendStr( expr.Op )
formatExpr(expr.Rhs)
elseif expr.AstType == 'DotsExpr' then
appendNextToken( "..." )
elseif expr.AstType == 'CallExpr' then
formatExpr(expr.Base)
appendNextToken( "(" )
for i,arg in ipairs( expr.Arguments ) do
formatExpr(arg)
appendComma( i ~= #expr.Arguments )
end
appendNextToken( ")" )
elseif expr.AstType == 'TableCallExpr' then
formatExpr( expr.Base )
formatExpr( expr.Arguments[1] )
elseif expr.AstType == 'StringCallExpr' then
formatExpr(expr.Base)
appendToken( expr.Arguments[1] )
elseif expr.AstType == 'IndexExpr' then
formatExpr(expr.Base)
appendNextToken( "[" )
formatExpr(expr.Index)
appendNextToken( "]" )
elseif expr.AstType == 'MemberExpr' then
formatExpr(expr.Base)
appendNextToken() -- . or :
appendToken(expr.Ident)
elseif expr.AstType == 'Function' then
-- anonymous function
appendNextToken( "function" )
appendNextToken( "(" )
if #expr.Arguments > 0 then
for i = 1, #expr.Arguments do
appendStr( expr.Arguments[i].Name )
if i ~= #expr.Arguments then
appendNextToken(",")
elseif expr.VarArg then
appendNextToken(",")
appendNextToken("...")
end
end
elseif expr.VarArg then
appendNextToken("...")
end
appendNextToken(")")
formatStatlist(expr.Body)
appendNextToken("end")
elseif expr.AstType == 'ConstructorExpr' then
appendNextToken( "{" )
for i = 1, #expr.EntryList do
local entry = expr.EntryList[i]
if entry.Type == 'Key' then
appendNextToken( "[" )
formatExpr(entry.Key)
appendNextToken( "]" )
appendNextToken( "=" )
formatExpr(entry.Value)
elseif entry.Type == 'Value' then
formatExpr(entry.Value)
elseif entry.Type == 'KeyString' then
appendStr(entry.Key)
appendNextToken( "=" )
formatExpr(entry.Value)
end
appendComma( i ~= #expr.EntryList, { ",", ";" } )
end
appendNextToken( "}" )
elseif expr.AstType == 'Parentheses' then
appendNextToken( "(" )
formatExpr(expr.Inner)
appendNextToken( ")" )
else
print("Unknown AST Type: ", statement.AstType)
end
assert(tok_it == #expr.Tokens + 1)
debug_printf("/formatExpr")
end
local formatStatement = function(statement)
local tok_it = 1
local function appendNextToken(str)
local tok = statement.Tokens[tok_it];
assert(tok, string.format("Not enough tokens for %q. First token at %i:%i",
str, statement.Tokens[1].Line, statement.Tokens[1].Char))
assert(tok.Data == str,
string.format('Expected token %q, got %q', str, tok.Data))
out:appendToken( tok )
tok_it = tok_it + 1
end
local function appendWhite()
local tok = statement.Tokens[tok_it];
out:appendWhite( tok )
tok_it = tok_it + 1
end
local function appendStr(str)
appendWhite()
out:appendStr(str)
end
local function appendComma(mandatory)
if mandatory
or (tok_it < #statement.Tokens and statement.Tokens[tok_it].Data == ",") then
appendNextToken( "," )
end
end
debug_printf("")
debug_printf(string.format("formatStatement(%s) at line %i", statement.AstType, statement.Tokens[1] and statement.Tokens[1].Line or -1))
if statement.AstType == 'AssignmentStatement' then
for i,v in ipairs(statement.Lhs) do
formatExpr(v)
appendComma( i ~= #statement.Lhs )
end
if #statement.Rhs > 0 then
appendNextToken( "=" )
for i,v in ipairs(statement.Rhs) do
formatExpr(v)
appendComma( i ~= #statement.Rhs )
end
end
elseif statement.AstType == 'CallStatement' then
formatExpr(statement.Expression)
elseif statement.AstType == 'LocalStatement' then
appendNextToken( "local" )
for i = 1, #statement.LocalList do
appendStr( statement.LocalList[i].Name )
appendComma( i ~= #statement.LocalList )
end
if #statement.InitList > 0 then
appendNextToken( "=" )
for i = 1, #statement.InitList do
formatExpr(statement.InitList[i])
appendComma( i ~= #statement.InitList )
end
end
elseif statement.AstType == 'IfStatement' then
appendNextToken( "if" )
formatExpr( statement.Clauses[1].Condition )
appendNextToken( "then" )
formatStatlist( statement.Clauses[1].Body )
for i = 2, #statement.Clauses do
local st = statement.Clauses[i]
if st.Condition then
appendNextToken( "elseif" )
formatExpr(st.Condition)
appendNextToken( "then" )
else
appendNextToken( "else" )
end
formatStatlist(st.Body)
end
appendNextToken( "end" )
elseif statement.AstType == 'WhileStatement' then
appendNextToken( "while" )
formatExpr(statement.Condition)
appendNextToken( "do" )
formatStatlist(statement.Body)
appendNextToken( "end" )
elseif statement.AstType == 'DoStatement' then
appendNextToken( "do" )
formatStatlist(statement.Body)
appendNextToken( "end" )
elseif statement.AstType == 'ReturnStatement' then
appendNextToken( "return" )
for i = 1, #statement.Arguments do
formatExpr(statement.Arguments[i])
appendComma( i ~= #statement.Arguments )
end
elseif statement.AstType == 'BreakStatement' then
appendNextToken( "break" )
elseif statement.AstType == 'RepeatStatement' then
appendNextToken( "repeat" )
formatStatlist(statement.Body)
appendNextToken( "until" )
formatExpr(statement.Condition)
elseif statement.AstType == 'Function' then
--print(util.PrintTable(statement))
if statement.IsLocal then
appendNextToken( "local" )
end
appendNextToken( "function" )
if statement.IsLocal then
appendStr(statement.Name.Name)
else
formatExpr(statement.Name)
end
appendNextToken( "(" )
if #statement.Arguments > 0 then
for i = 1, #statement.Arguments do
appendStr( statement.Arguments[i].Name )
appendComma( i ~= #statement.Arguments or statement.VarArg )
if i == #statement.Arguments and statement.VarArg then
appendNextToken( "..." )
end
end
elseif statement.VarArg then
appendNextToken( "..." )
end
appendNextToken( ")" )
formatStatlist(statement.Body)
appendNextToken( "end" )
elseif statement.AstType == 'GenericForStatement' then
appendNextToken( "for" )
for i = 1, #statement.VariableList do
appendStr( statement.VariableList[i].Name )
appendComma( i ~= #statement.VariableList )
end
appendNextToken( "in" )
for i = 1, #statement.Generators do
formatExpr(statement.Generators[i])
appendComma( i ~= #statement.Generators )
end
appendNextToken( "do" )
formatStatlist(statement.Body)
appendNextToken( "end" )
elseif statement.AstType == 'NumericForStatement' then
appendNextToken( "for" )
appendStr( statement.Variable.Name )
appendNextToken( "=" )
formatExpr(statement.Start)
appendNextToken( "," )
formatExpr(statement.End)
if statement.Step then
appendNextToken( "," )
formatExpr(statement.Step)
end
appendNextToken( "do" )
formatStatlist(statement.Body)
appendNextToken( "end" )
elseif statement.AstType == 'LabelStatement' then
appendNextToken( "::" )
appendStr( statement.Label )
appendNextToken( "::" )
elseif statement.AstType == 'GotoStatement' then
appendNextToken( "goto" )
appendStr( statement.Label )
elseif statement.AstType == 'Eof' then
appendWhite()
else
print("Unknown AST Type: ", statement.AstType)
end
if statement.Semicolon then
appendNextToken(";")
end
assert(tok_it == #statement.Tokens + 1)
debug_printf("/formatStatment")
end
formatStatlist = function(statList)
for _, stat in ipairs(statList.Body) do
formatStatement(stat)
end
end
formatStatlist(ast)
return true, table.concat(out.rope)
end
return Format_Identity

365
minify/FormatMini.lua Normal file
View File

@ -0,0 +1,365 @@
local parser = require'ParseLua'
local ParseLua = parser.ParseLua
local util = require'Util'
local lookupify = util.lookupify
--
-- FormatMini.lua
--
-- Returns the minified version of an AST. Operations which are performed:
-- - All comments and whitespace are ignored
-- - All local variables are renamed
--
local LowerChars = lookupify{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
local UpperChars = lookupify{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
local Digits = lookupify{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
local Symbols = lookupify{'+', '-', '*', '/', '^', '%', ',', '{', '}', '[', ']', '(', ')', ';', '#'}
local function Format_Mini(ast)
local formatStatlist, formatExpr;
local count = 0
--
local function joinStatementsSafe(a, b, sep)
--print(a, b)
if count > 150 then
count = 0
return a.."\n"..b
end
sep = sep or ' '
local aa, bb = a:sub(-1,-1), b:sub(1,1)
if UpperChars[aa] or LowerChars[aa] or aa == '_' then
if not (UpperChars[bb] or LowerChars[bb] or bb == '_' or Digits[bb]) then
--bb is a symbol, can join without sep
return a..b
elseif bb == '(' then
print("==============>>>",aa,bb)
--prevent ambiguous syntax
return a..sep..b
else
return a..sep..b
end
elseif Digits[aa] then
if bb == '(' then
--can join statements directly
return a..b
elseif Symbols[bb] then
return a .. b
else
return a..sep..b
end
elseif aa == '' then
return a..b
else
if bb == '(' then
--don't want to accidentally call last statement, can't join directly
return a..sep..b
else
--print("asdf", '"'..a..'"', '"'..b..'"')
return a..b
end
end
end
formatExpr = function(expr, precedence)
local precedence = precedence or 0
local currentPrecedence = 0
local skipParens = false
local out = ""
if expr.AstType == 'VarExpr' then
if expr.Variable then
out = out..expr.Variable.Name
else
out = out..expr.Name
end
elseif expr.AstType == 'NumberExpr' then
out = out..expr.Value.Data
elseif expr.AstType == 'StringExpr' then
out = out..expr.Value.Data
elseif expr.AstType == 'BooleanExpr' then
out = out..tostring(expr.Value)
elseif expr.AstType == 'NilExpr' then
out = joinStatementsSafe(out, "nil")
elseif expr.AstType == 'BinopExpr' then
currentPrecedence = expr.OperatorPrecedence
out = joinStatementsSafe(out, formatExpr(expr.Lhs, currentPrecedence))
out = joinStatementsSafe(out, expr.Op)
out = joinStatementsSafe(out, formatExpr(expr.Rhs))
if expr.Op == '^' or expr.Op == '..' then
currentPrecedence = currentPrecedence - 1
end
if currentPrecedence < precedence then
skipParens = false
else
skipParens = true
end
--print(skipParens, precedence, currentPrecedence)
elseif expr.AstType == 'UnopExpr' then
out = joinStatementsSafe(out, expr.Op)
out = joinStatementsSafe(out, formatExpr(expr.Rhs))
elseif expr.AstType == 'DotsExpr' then
out = out.."..."
elseif expr.AstType == 'CallExpr' then
out = out..formatExpr(expr.Base)
out = out.."("
for i = 1, #expr.Arguments do
out = out..formatExpr(expr.Arguments[i])
if i ~= #expr.Arguments then
out = out..","
end
end
out = out..")"
elseif expr.AstType == 'TableCallExpr' then
out = out..formatExpr(expr.Base)
out = out..formatExpr(expr.Arguments[1])
elseif expr.AstType == 'StringCallExpr' then
out = out..formatExpr(expr.Base)
out = out..expr.Arguments[1].Data
elseif expr.AstType == 'IndexExpr' then
out = out..formatExpr(expr.Base).."["..formatExpr(expr.Index).."]"
elseif expr.AstType == 'MemberExpr' then
out = out..formatExpr(expr.Base)..expr.Indexer..expr.Ident.Data
elseif expr.AstType == 'Function' then
expr.Scope:ObfuscateVariables()
out = out.."function("
if #expr.Arguments > 0 then
for i = 1, #expr.Arguments do
out = out..expr.Arguments[i].Name
if i ~= #expr.Arguments then
out = out..","
elseif expr.VarArg then
out = out..",..."
end
end
elseif expr.VarArg then
out = out.."..."
end
out = out..")"
out = joinStatementsSafe(out, formatStatlist(expr.Body))
out = joinStatementsSafe(out, "end")
elseif expr.AstType == 'ConstructorExpr' then
out = out.."{"
for i = 1, #expr.EntryList do
local entry = expr.EntryList[i]
if entry.Type == 'Key' then
out = out.."["..formatExpr(entry.Key).."]="..formatExpr(entry.Value)
elseif entry.Type == 'Value' then
out = out..formatExpr(entry.Value)
elseif entry.Type == 'KeyString' then
out = out..entry.Key.."="..formatExpr(entry.Value)
end
if i ~= #expr.EntryList then
out = out..","
end
end
out = out.."}"
elseif expr.AstType == 'Parentheses' then
out = out.."("..formatExpr(expr.Inner)..")"
end
--print(">>", skipParens, expr.ParenCount, out)
if not skipParens then
--print("hehe")
out = string.rep('(', expr.ParenCount or 0) .. out
out = out .. string.rep(')', expr.ParenCount or 0)
--print("", out)
end
count = count + #out
return --[[print(out) or]] out
end
local formatStatement = function(statement)
local out = ''
if statement.AstType == 'AssignmentStatement' then
for i = 1, #statement.Lhs do
out = out..formatExpr(statement.Lhs[i])
if i ~= #statement.Lhs then
out = out..","
end
end
if #statement.Rhs > 0 then
out = out.."="
for i = 1, #statement.Rhs do
out = out..formatExpr(statement.Rhs[i])
if i ~= #statement.Rhs then
out = out..","
end
end
end
elseif statement.AstType == 'CallStatement' then
out = formatExpr(statement.Expression)
elseif statement.AstType == 'LocalStatement' then
out = out.."local "
for i = 1, #statement.LocalList do
out = out..statement.LocalList[i].Name
if i ~= #statement.LocalList then
out = out..","
end
end
if #statement.InitList > 0 then
out = out.."="
for i = 1, #statement.InitList do
out = out..formatExpr(statement.InitList[i])
if i ~= #statement.InitList then
out = out..","
end
end
end
elseif statement.AstType == 'IfStatement' then
out = joinStatementsSafe("if", formatExpr(statement.Clauses[1].Condition))
out = joinStatementsSafe(out, "then")
out = joinStatementsSafe(out, formatStatlist(statement.Clauses[1].Body))
for i = 2, #statement.Clauses do
local st = statement.Clauses[i]
if st.Condition then
out = joinStatementsSafe(out, "elseif")
out = joinStatementsSafe(out, formatExpr(st.Condition))
out = joinStatementsSafe(out, "then")
else
out = joinStatementsSafe(out, "else")
end
out = joinStatementsSafe(out, formatStatlist(st.Body))
end
out = joinStatementsSafe(out, "end")
elseif statement.AstType == 'WhileStatement' then
out = joinStatementsSafe("while", formatExpr(statement.Condition))
out = joinStatementsSafe(out, "do")
out = joinStatementsSafe(out, formatStatlist(statement.Body))
out = joinStatementsSafe(out, "end")
elseif statement.AstType == 'DoStatement' then
out = joinStatementsSafe(out, "do")
out = joinStatementsSafe(out, formatStatlist(statement.Body))
out = joinStatementsSafe(out, "end")
elseif statement.AstType == 'ReturnStatement' then
out = "return"
for i = 1, #statement.Arguments do
out = joinStatementsSafe(out, formatExpr(statement.Arguments[i]))
if i ~= #statement.Arguments then
out = out..","
end
end
elseif statement.AstType == 'BreakStatement' then
out = "break"
elseif statement.AstType == 'RepeatStatement' then
out = "repeat"
out = joinStatementsSafe(out, formatStatlist(statement.Body))
out = joinStatementsSafe(out, "until")
out = joinStatementsSafe(out, formatExpr(statement.Condition))
elseif statement.AstType == 'Function' then
statement.Scope:ObfuscateVariables()
if statement.IsLocal then
out = "local"
end
out = joinStatementsSafe(out, "function ")
if statement.IsLocal then
out = out..statement.Name.Name
else
out = out..formatExpr(statement.Name)
end
out = out.."("
if #statement.Arguments > 0 then
for i = 1, #statement.Arguments do
out = out..statement.Arguments[i].Name
if i ~= #statement.Arguments then
out = out..","
elseif statement.VarArg then
--print("Apply vararg")
out = out..",..."
end
end
elseif statement.VarArg then
out = out.."..."
end
out = out..")"
out = joinStatementsSafe(out, formatStatlist(statement.Body))
out = joinStatementsSafe(out, "end")
elseif statement.AstType == 'GenericForStatement' then
statement.Scope:ObfuscateVariables()
out = "for "
for i = 1, #statement.VariableList do
out = out..statement.VariableList[i].Name
if i ~= #statement.VariableList then
out = out..","
end
end
out = out.." in"
for i = 1, #statement.Generators do
out = joinStatementsSafe(out, formatExpr(statement.Generators[i]))
if i ~= #statement.Generators then
out = joinStatementsSafe(out, ',')
end
end
out = joinStatementsSafe(out, "do")
out = joinStatementsSafe(out, formatStatlist(statement.Body))
out = joinStatementsSafe(out, "end")
elseif statement.AstType == 'NumericForStatement' then
statement.Scope:ObfuscateVariables()
out = "for "
out = out..statement.Variable.Name.."="
out = out..formatExpr(statement.Start)..","..formatExpr(statement.End)
if statement.Step then
out = out..","..formatExpr(statement.Step)
end
out = joinStatementsSafe(out, "do")
out = joinStatementsSafe(out, formatStatlist(statement.Body))
out = joinStatementsSafe(out, "end")
elseif statement.AstType == 'LabelStatement' then
out = getIndentation() .. "::" .. statement.Label .. "::"
elseif statement.AstType == 'GotoStatement' then
out = getIndentation() .. "goto " .. statement.Label
elseif statement.AstType == 'Comment' then
-- ignore
elseif statement.AstType == 'Eof' then
-- ignore
else
print("Unknown AST Type: " .. statement.AstType)
end
count = count + #out
return out
end
formatStatlist = function(statList)
local out = ''
statList.Scope:ObfuscateVariables()
for _, stat in pairs(statList.Body) do
out = joinStatementsSafe(out, formatStatement(stat), ';')
end
return out
end
ast.Scope:ObfuscateVariables()
return formatStatlist(ast)
end
return Format_Mini

20
minify/LICENSE.md Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2012-2013
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.

1411
minify/ParseLua.lua Normal file

File diff suppressed because it is too large Load Diff

44
minify/README.md Normal file
View File

@ -0,0 +1,44 @@
Lua Parsing and Refactorization tools
=========
A collection of tools for working with Lua source code. Primarily a Lua source code minifier, but also includes some static analysis tools and a general Lua lexer and parser.
Currently the minifier performs:
- Stripping of all comments and whitespace
- True semantic renaming of all local variables to a reduced form
- Reduces the source to the minimal spacing, spaces are only inserted where actually needed.
LuaMinify Command Line Utility Usage
------------------------------------
The `LuaMinify` shell and batch files are given as shortcuts to running a command line instance of the minifier with the following usage:
LuaMinify sourcefile [destfile]
Which will minify to a given destination file, or to a copy of the source file with _min appended to the filename if no output file is given.
LuaMinify Roblox Plugin Usage
-----------------------------
First, download the source code, which you can do by hitting this button:
![Click That](http://github.com/stravant/LuaMinify/raw/master/RobloxPluginInstructions.png)
Then copy the `RobloxPlugin` folder from the source into your Roblox Plugins directory, which can be found by hitting `Tools->Open Plugins Folder` in Roblox Studio.
Features/Todo
-------------
Features:
- Lua scanner/parser, which generates a full AST
- Lua reconstructor
- minimal
- full reconstruction (TODO: options, comments)
- TODO: exact reconstructor
- support for embedded long strings/comments e.g. [[abc [[ def ]] ghi]]
Todo:
- use table.concat instead of appends in the reconstructors

217
minify/Scope.lua Normal file
View File

@ -0,0 +1,217 @@
local var_count = 0
local util = require'Util'
local lookupify = util.lookupify
local Keywords = lookupify{
'and', 'break', 'do', 'else', 'elseif',
'end', 'false', 'for', 'function', 'goto', 'if',
'in', 'local', 'nil', 'not', 'or', 'repeat',
'return', 'then', 'true', 'until', 'while',
};
local Scope = {
new = function(self, parent)
local s = {
Parent = parent,
Locals = { },
Globals = { },
oldLocalNamesMap = { },
oldGlobalNamesMap = { },
Children = { },
}
if parent then
table.insert(parent.Children, s)
end
return setmetatable(s, { __index = self })
end,
AddLocal = function(self, v)
table.insert(self.Locals, v)
end,
AddGlobal = function(self, v)
table.insert(self.Globals, v)
end,
CreateLocal = function(self, name)
local v
v = self:GetLocal(name)
if v then return v end
v = { }
v.Scope = self
v.Name = name
v.IsGlobal = false
v.CanRename = true
v.References = 1
self:AddLocal(v)
return v
end,
GetLocal = function(self, name)
for k, var in pairs(self.Locals) do
if var.Name == name then return var end
end
if self.Parent then
return self.Parent:GetLocal(name)
end
end,
GetOldLocal = function(self, name)
if self.oldLocalNamesMap[name] then
return self.oldLocalNamesMap[name]
end
return self:GetLocal(name)
end,
mapLocal = function(self, name, var)
self.oldLocalNamesMap[name] = var
end,
GetOldGlobal = function(self, name)
if self.oldGlobalNamesMap[name] then
return self.oldGlobalNamesMap[name]
end
return self:GetGlobal(name)
end,
mapGlobal = function(self, name, var)
self.oldGlobalNamesMap[name] = var
end,
GetOldVariable = function(self, name)
return self:GetOldLocal(name) or self:GetOldGlobal(name)
end,
RenameLocal = function(self, oldName, newName)
oldName = type(oldName) == 'string' and oldName or oldName.Name
local found = false
local var = self:GetLocal(oldName)
if var then
var.Name = newName
self:mapLocal(oldName, var)
found = true
end
if not found and self.Parent then
self.Parent:RenameLocal(oldName, newName)
end
end,
RenameGlobal = function(self, oldName, newName)
oldName = type(oldName) == 'string' and oldName or oldName.Name
local found = false
local var = self:GetGlobal(oldName)
if var then
var.Name = newName
self:mapGlobal(oldName, var)
found = true
end
if not found and self.Parent then
self.Parent:RenameGlobal(oldName, newName)
end
end,
RenameVariable = function(self, oldName, newName)
oldName = type(oldName) == 'string' and oldName or oldName.Name
if self:GetLocal(oldName) then
self:RenameLocal(oldName, newName)
else
self:RenameGlobal(oldName, newName)
end
end,
GetAllVariables = function(self)
local ret = self:getVars(true) -- down
for k, v in pairs(self:getVars(false)) do -- up
table.insert(ret, v)
end
return ret
end,
getVars = function(self, top)
local ret = { }
if top then
for k, v in pairs(self.Children) do
for k2, v2 in pairs(v:getVars(true)) do
table.insert(ret, v2)
end
end
else
for k, v in pairs(self.Locals) do
table.insert(ret, v)
end
for k, v in pairs(self.Globals) do
table.insert(ret, v)
end
if self.Parent then
for k, v in pairs(self.Parent:getVars(false)) do
table.insert(ret, v)
end
end
end
return ret
end,
CreateGlobal = function(self, name)
local v
v = self:GetGlobal(name)
if v then return v end
v = { }
v.Scope = self
v.Name = name
v.IsGlobal = true
v.CanRename = true
v.References = 1
self:AddGlobal(v)
return v
end,
GetGlobal = function(self, name)
for k, v in pairs(self.Globals) do
if v.Name == name then return v end
end
if self.Parent then
return self.Parent:GetGlobal(name)
end
end,
GetVariable = function(self, name)
return self:GetLocal(name) or self:GetGlobal(name)
end,
ObfuscateLocals = function(self, recommendedMaxLength, validNameChars)
recommendedMaxLength = recommendedMaxLength or 7
local chars = validNameChars or "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuioplkjhgfdsazxcvbnm_"
--local chars2 = validNameChars or "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuioplkjhgfdsazxcvbnm_1234567890"
for _, var in pairs(self.Locals) do
local id = ""
local tries = 0
--[[
repeat
local n = math.random(1, #chars)
id = id .. chars:sub(n, n)
for i = 1, math.random(0, tries > 5 and 30 or recommendedMaxLength) do
local n = math.random(1, #chars2)
id = id .. chars2:sub(n, n)
end
tries = tries + 1
until not self:GetVariable(id)]]
local id
repeat
local n = var_count
id = ""
repeat
local x = n % #chars
id = id .. chars:sub(x + 1, x + 1)
n = math.floor(n / #chars)
until n == 0
var_count = var_count + 1
until not Keywords[id]
self:RenameLocal(var.Name, id)
end
end,
}
return Scope

91
minify/Util.lua Normal file
View File

@ -0,0 +1,91 @@
--
-- Util.lua
--
-- Provides some common utilities shared throughout the project.
--
local function lookupify(tb)
for _, v in pairs(tb) do
tb[v] = true
end
return tb
end
local function CountTable(tb)
local c = 0
for _ in pairs(tb) do c = c + 1 end
return c
end
local function PrintTable(tb, atIndent)
if tb.Print then
return tb.Print()
end
atIndent = atIndent or 0
local useNewlines = (CountTable(tb) > 1)
local baseIndent = string.rep(' ', atIndent+1)
local out = "{"..(useNewlines and '\n' or '')
for k, v in pairs(tb) do
if type(v) ~= 'function' then
--do
out = out..(useNewlines and baseIndent or '')
if type(k) == 'number' then
--nothing to do
elseif type(k) == 'string' and k:match("^[A-Za-z_][A-Za-z0-9_]*$") then
out = out..k.." = "
elseif type(k) == 'string' then
out = out.."[\""..k.."\"] = "
else
out = out.."["..tostring(k).."] = "
end
if type(v) == 'string' then
out = out.."\""..v.."\""
elseif type(v) == 'number' then
out = out..v
elseif type(v) == 'table' then
out = out..PrintTable(v, atIndent+(useNewlines and 1 or 0))
else
out = out..tostring(v)
end
if next(tb, k) then
out = out..","
end
if useNewlines then
out = out..'\n'
end
end
end
out = out..(useNewlines and string.rep(' ', atIndent) or '').."}"
return out
end
local function splitLines(str)
if str:match("\n") then
local lines = {}
for line in str:gmatch("[^\n]*") do
table.insert(lines, line)
end
assert(#lines > 0)
return lines
else
return { str }
end
end
local function printf(fmt, ...)
return print(string.format(fmt, ...))
end
return {
PrintTable = PrintTable,
CountTable = CountTable,
lookupify = lookupify,
splitLines = splitLines,
printf = printf,
}

39
minify/strict.lua Normal file
View File

@ -0,0 +1,39 @@
-- From http://metalua.luaforge.net/src/lib/strict.lua.html
--
-- strict.lua
-- checks uses of undeclared global variables
-- All global variables must be 'declared' through a regular assignment
-- (even assigning nil will do) in a main chunk before being used
-- anywhere or assigned to inside a function.
--
local mt = getmetatable(_G)
if mt == nil then
mt = {}
setmetatable(_G, mt)
end
__STRICT = true
mt.__declared = {}
mt.__newindex = function (t, n, v)
if __STRICT and not mt.__declared[n] then
local w = debug.getinfo(2, "S").what
if w ~= "main" and w ~= "C" then
error("assign to undeclared variable '"..n.."'", 2)
end
mt.__declared[n] = true
end
rawset(t, n, v)
end
mt.__index = function (t, n)
if not mt.__declared[n] and debug.getinfo(2, "S").what ~= "C" then
error("variable '"..n.."' is not declared", 2)
end
return rawget(t, n)
end
function global(...)
for _, v in ipairs{...} do mt.__declared[v] = true end
end

View File

@ -0,0 +1,60 @@
-- Adapted from Yueliang
package.path = "../?.lua;" .. package.path
local util = require'Util'
local Parser = require'ParseLua'
local Format = require'FormatBeautiful'
for w in io.lines("test_lines.txt") do
--print(w)
local success, ast = Parser.ParseLua(w)
if w:find("FAIL") then
--[[if success then
print("ERROR PARSING LINE:")
print("Should fail: true. Did fail: " .. tostring(not success))
print("Line: " .. w)
else
--print("Suceeded!")
end]]
else
if not success then
print("ERROR PARSING LINE:")
print("Should fail: false. Did fail: " .. tostring(not success))
print("Line: " .. w)
else
success, ast = Format(ast)
--print(success, ast)
if not success then
print("ERROR BEAUTIFYING LINE:")
print("Message: " .. ast)
print("Line: " .. w)
end
local success_ = success
success, ast = loadstring(success)
if not success then
print("ERROR PARSING BEAUTIFIED LINE:")
print("Message: " .. ast)
print("Line: " .. success_)
end
--print("Suceeded!")
end
end
end
print"Done!"
os.remove("tmp")
--[[
function readAll(file)
local f = io.open(file, "rb")
local content = f:read("*all")
f:close()
return content
end
local text = readAll('../ParseLua.lua')
local success, ast = Parser.ParseLua(text)
local nice
nice = Format(ast)
print(nice)
--]]

View File

@ -0,0 +1,124 @@
package.path = "../?.lua;" .. package.path
local Parser = require'ParseLua'
local util = require'Util'
local FormatIdentity = require'FormatIdentity'
local FormatMini = require'FormatMini'
local FormatBeautiful = require'FormatBeautiful'
require'strict'
function readAll(file)
local f = io.open(file, "rb")
local content = f:read("*all")
f:close()
return content
end
local g_lexTime = 0
local g_parseTime = 0
local g_reconstructTime = 0
function reconstructText(text)
local preLex = os.clock()
local success, tokens, ast, reconstructed
success, tokens = Parser.LexLua(text)
if not success then
print("ERROR: " .. tokens)
return
end
local preParse = os.clock()
success, ast = Parser.ParseLua(tokens)
if not success then
print("ERROR: " .. ast)
return
end
local preReconstruct = os.clock()
local DO_MINI = false
local DO_CHECK = false
if DO_MINI then
success, reconstructed = FormatMini(ast)
else
success, reconstructed = FormatIdentity(ast)
end
if not success then
print("ERROR: " .. reconstructed)
return
end
local post = os.clock()
g_lexTime = g_lexTime + (preParse - preLex)
g_parseTime = g_parseTime + (preReconstruct - preParse)
g_reconstructTime = g_reconstructTime + (post - preReconstruct)
if DO_CHECK then
--[[
print()
print("Reconstructed: ")
print("--------------------")
print(reconstructed)
print("--------------------")
print("Done. ")
--]]
if reconstructed == text then
--print("Reconstruction succeeded")
else
print("Reconstruction failed")
local inputLines = util.splitLines(text)
local outputLines = util.splitLines(reconstructed)
local n = math.max(#inputLines, #outputLines)
for i = 1,n do
if inputLines[i] ~= outputLines[i] then
util.printf("ERROR on line %i", i)
util.printf("Input: %q", inputLines[i])
util.printf("Output: %q", outputLines[i])
break
end
end
end
end
end
--[*[
local files = {
"../ParseLua.lua",
"../FormatIdentity.lua",
"../Scope.lua",
"../strict.lua",
"../Type.lua",
"Test_identity.lua"
}
for _,path in ipairs(files) do
print(path)
local text = readAll(path)
reconstructText(text)
end
--]]
print("test_lines.txt")
local line_nr = 0
for text in io.lines("test_lines.txt") do
line_nr = line_nr + 1
if not text:find("FAIL") then
--util.printf("\nText: %q", text)
reconstructText(text)
end
end
reconstructText('function a(p,q,r,...) end')
util.printf("Lex time: %f s", g_lexTime)
util.printf("Parse time: %f s", g_parseTime)
util.printf("Format time: %f s", g_reconstructTime)

523
minify/tests/test_lines.txt Normal file
View File

@ -0,0 +1,523 @@
; -- FAIL
local -- FAIL
local; -- FAIL
local = -- FAIL
local end -- FAIL
local a
local a;
local a, b, c
local a; local b local c;
local a = 1
local a local b = a
local a, b = 1, 2
local a, b, c = 1, 2, 3
local a, b, c = 1
local a = 1, 2, 3
local a, local -- FAIL
local 1 -- FAIL
local "foo" -- FAIL
local a = local -- FAIL
local a, b, = -- FAIL
local a, b = 1, local -- FAIL
local a, b = , local -- FAIL
do -- FAIL
end -- FAIL
do end
do ; end -- FAIL
do 1 end -- FAIL
do "foo" end -- FAIL
do local a, b end
do local a local b end
do local a; local b; end
do local a = 1 end
do do end end
do do end; end
do do do end end end
do do do end; end; end
do do do return end end end
do end do -- FAIL
do end end -- FAIL
do return end
do return return end -- FAIL
do break end -- FAIL
while -- FAIL
while do -- FAIL
while = -- FAIL
while 1 do -- FAIL
while 1 do end
while 1 do local a end
while 1 do local a local b end
while 1 do local a; local b; end
while 1 do 2 end -- FAIL
while 1 do "foo" end -- FAIL
while true do end
while 1 do ; end -- FAIL
while 1 do while -- FAIL
while 1 end -- FAIL
while 1 2 do -- FAIL
while 1 = 2 do -- FAIL
while 1 do return end
while 1 do return return end -- FAIL
while 1 do do end end
while 1 do do return end end
while 1 do break end
while 1 do break break end -- FAIL
while 1 do do break end end
repeat -- FAIL
repeat until -- FAIL
repeat until 0
repeat until false
repeat until local -- FAIL
repeat end -- FAIL
repeat 1 -- FAIL
repeat = -- FAIL
repeat local a until 1
repeat local a local b until 0
repeat local a; local b; until 0
repeat ; until 1 -- FAIL
repeat 2 until 1 -- FAIL
repeat "foo" until 1 -- FAIL
repeat return until 0
repeat return return until 0 -- FAIL
repeat break until 0
repeat break break until 0 -- FAIL
repeat do end until 0
repeat do return end until 0
repeat do break end until 0
for -- FAIL
for do -- FAIL
for end -- FAIL
for 1 -- FAIL
for a -- FAIL
for true -- FAIL
for a, in -- FAIL
for a in -- FAIL
for a do -- FAIL
for a in do -- FAIL
for a in b do -- FAIL
for a in b end -- FAIL
for a in b, do -- FAIL
for a in b do end
for a in b do local a local b end
for a in b do local a; local b; end
for a in b do 1 end -- FAIL
for a in b do "foo" end -- FAIL
for a b in -- FAIL
for a, b, c in p do end
for a, b, c in p, q, r do end
for a in 1 do end
for a in true do end
for a in "foo" do end
for a in b do break end
for a in b do break break end -- FAIL
for a in b do return end
for a in b do return return end -- FAIL
for a in b do do end end
for a in b do do break end end
for a in b do do return end end
for = -- FAIL
for a = -- FAIL
for a, b = -- FAIL
for a = do -- FAIL
for a = 1, do -- FAIL
for a = p, q, do -- FAIL
for a = p q do -- FAIL
for a = b do end -- FAIL
for a = 1, 2, 3, 4 do end -- FAIL
for a = p, q do end
for a = 1, 2 do end
for a = 1, 2 do local a local b end
for a = 1, 2 do local a; local b; end
for a = 1, 2 do 3 end -- FAIL
for a = 1, 2 do "foo" end -- FAIL
for a = p, q, r do end
for a = 1, 2, 3 do end
for a = p, q do break end
for a = p, q do break break end -- FAIL
for a = 1, 2 do return end
for a = 1, 2 do return return end -- FAIL
for a = p, q do do end end
for a = p, q do do break end end
for a = p, q do do return end end
break -- FAIL
return
return;
return return -- FAIL
return 1
return local -- FAIL
return "foo"
return 1, -- FAIL
return 1,2,3
return a,b,c,d
return 1,2;
return ...
return 1,a,...
if -- FAIL
elseif -- FAIL
else -- FAIL
then -- FAIL
if then -- FAIL
if 1 -- FAIL
if 1 then -- FAIL
if 1 else -- FAIL
if 1 then else -- FAIL
if 1 then elseif -- FAIL
if 1 then end
if 1 then local a end
if 1 then local a local b end
if 1 then local a; local b; end
if 1 then else end
if 1 then local a else local b end
if 1 then local a; else local b; end
if 1 then elseif 2 -- FAIL
if 1 then elseif 2 then -- FAIL
if 1 then elseif 2 then end
if 1 then local a elseif 2 then local b end
if 1 then local a; elseif 2 then local b; end
if 1 then elseif 2 then else end
if 1 then else if 2 then end end
if 1 then else if 2 then end -- FAIL
if 1 then break end -- FAIL
if 1 then return end
if 1 then return return end -- FAIL
if 1 then end; if 1 then end;
function -- FAIL
function 1 -- FAIL
function end -- FAIL
function a -- FAIL
function a end -- FAIL
function a( end -- FAIL
function a() end
function a(1 -- FAIL
function a("foo" -- FAIL
function a(p -- FAIL
function a(p,) -- FAIL
function a(p q -- FAIL
function a(p) end
function a(p,q,) end -- FAIL
function a(p,q,r) end
function a(p,q,1 -- FAIL
function a(p) do -- FAIL
function a(p) 1 end -- FAIL
function a(p) return end
function a(p) break end -- FAIL
function a(p) return return end -- FAIL
function a(p) do end end
function a.( -- FAIL
function a.1 -- FAIL
function a.b() end
function a.b, -- FAIL
function a.b.( -- FAIL
function a.b.c.d() end
function a: -- FAIL
function a:1 -- FAIL
function a:b() end
function a:b: -- FAIL
function a:b. -- FAIL
function a.b.c:d() end
function a(...) end
function a(..., -- FAIL
function a(p,...) end
function a(p,q,r,...) end
function a() local a local b end
function a() local a; local b; end
function a() end; function a() end;
local function -- FAIL
local function 1 -- FAIL
local function end -- FAIL
local function a -- FAIL
local function a end -- FAIL
local function a( end -- FAIL
local function a() end
local function a(1 -- FAIL
local function a("foo" -- FAIL
local function a(p -- FAIL
local function a(p,) -- FAIL
local function a(p q -- FAIL
local function a(p) end
local function a(p,q,) end -- FAIL
local function a(p,q,r) end
local function a(p,q,1 -- FAIL
local function a(p) do -- FAIL
local function a(p) 1 end -- FAIL
local function a(p) return end
local function a(p) break end -- FAIL
local function a(p) return return end -- FAIL
local function a(p) do end end
local function a. -- FAIL
local function a: -- FAIL
local function a(...) end
local function a(..., -- FAIL
local function a(p,...) end
local function a(p,q,r,...) end
local function a() local a local b end
local function a() local a; local b; end
local function a() end; local function a() end;
a -- FAIL
a, -- FAIL
a,b,c -- FAIL
a,b = -- FAIL
a = 1
a = 1,2,3
a,b,c = 1
a,b,c = 1,2,3
a.b = 1
a.b.c = 1
a[b] = 1
a[b][c] = 1
a.b[c] = 1
a[b].c = 1
0 = -- FAIL
"foo" = -- FAIL
true = -- FAIL
(a) = -- FAIL
{} = -- FAIL
a:b() = -- FAIL
a() = -- FAIL
a.b:c() = -- FAIL
a[b]() = -- FAIL
a = a b -- FAIL
a = 1 2 -- FAIL
a = a = 1 -- FAIL
a( -- FAIL
a()
a(1)
a(1,) -- FAIL
a(1,2,3)
1() -- FAIL
a()()
a.b()
a[b]()
a.1 -- FAIL
a.b -- FAIL
a[b] -- FAIL
a.b.( -- FAIL
a.b.c()
a[b][c]()
a[b].c()
a.b[c]()
a:b()
a:b -- FAIL
a:1 -- FAIL
a.b:c()
a[b]:c()
a:b: -- FAIL
a:b():c()
a:b().c[d]:e()
a:b()[c].d:e()
(a)()
()() -- FAIL
(1)()
("foo")()
(true)()
(a)()()
(a.b)()
(a[b])()
(a).b()
(a)[b]()
(a):b()
(a).b[c]:d()
(a)[b].c:d()
(a):b():c()
(a):b().c[d]:e()
(a):b()[c].d:e()
a"foo"
a[[foo]]
a.b"foo"
a[b]"foo"
a:b"foo"
a{}
a.b{}
a[b]{}
a:b{}
a()"foo"
a"foo"()
a"foo".b()
a"foo"[b]()
a"foo":c()
a"foo""bar"
a"foo"{}
(a):b"foo".c[d]:e"bar"
(a):b"foo"[c].d:e"bar"
a(){}
a{}()
a{}.b()
a{}[b]()
a{}:c()
a{}"foo"
a{}{}
(a):b{}.c[d]:e{}
(a):b{}[c].d:e{}
a = -- FAIL
a = a
a = nil
a = false
a = 1
a = "foo"
a = [[foo]]
a = {}
a = (a)
a = (nil)
a = (true)
a = (1)
a = ("foo")
a = ([[foo]])
a = ({})
a = a.b
a = a.b. -- FAIL
a = a.b.c
a = a:b -- FAIL
a = a[b]
a = a[1]
a = a["foo"]
a = a[b][c]
a = a.b[c]
a = a[b].c
a = (a)[b]
a = (a).c
a = () -- FAIL
a = a()
a = a.b()
a = a[b]()
a = a:b()
a = (a)()
a = (a).b()
a = (a)[b]()
a = (a):b()
a = a"foo"
a = a{}
a = function -- FAIL
a = function 1 -- FAIL
a = function a -- FAIL
a = function end -- FAIL
a = function( -- FAIL
a = function() end
a = function(1 -- FAIL
a = function(p) end
a = function(p,) -- FAIL
a = function(p q -- FAIL
a = function(p,q,r) end
a = function(p,q,1 -- FAIL
a = function(...) end
a = function(..., -- FAIL
a = function(p,...) end
a = function(p,q,r,...) end
a = ...
a = a, b, ...
a = (...)
a = ..., 1, 2
a = function() return ... end -- FAIL
a = -10
a = -"foo"
a = -a
a = -nil
a = -true
a = -{}
a = -function() end
a = -a()
a = -(a)
a = - -- FAIL
a = not 10
a = not "foo"
a = not a
a = not nil
a = not true
a = not {}
a = not function() end
a = not a()
a = not (a)
a = not -- FAIL
a = #10
a = #"foo"
a = #a
a = #nil
a = #true
a = #{}
a = #function() end
a = #a()
a = #(a)
a = # -- FAIL
a = 1 + 2; a = 1 - 2
a = 1 * 2; a = 1 / 2
a = 1 ^ 2; a = 1 % 2
a = 1 .. 2
a = 1 + -- FAIL
a = 1 .. -- FAIL
a = 1 * / -- FAIL
a = 1 + -2; a = 1 - -2
a = 1 * - -- FAIL
a = 1 * not 2; a = 1 / not 2
a = 1 / not -- FAIL
a = 1 * #"foo"; a = 1 / #"foo"
a = 1 / # -- FAIL
a = 1 + 2 - 3 * 4 / 5 % 6 ^ 7
a = ((1 + 2) - 3) * (4 / (5 % 6 ^ 7))
a = (1 + (2 - (3 * (4 / (5 % 6 ^ ((7)))))))
a = ((1 -- FAIL
a = ((1 + 2) -- FAIL
a = 1) -- FAIL
a = a + b - c
a = "foo" + "bar"
a = "foo".."bar".."baz"
a = true + false - nil
a = {} * {}
a = function() end / function() end
a = a() ^ b()
a = ... % ...
a = 1 == 2; a = 1 ~= 2
a = 1 < 2; a = 1 <= 2
a = 1 > 2; a = 1 >= 2
a = 1 < 2 < 3
a = 1 >= 2 >= 3
a = 1 == -- FAIL
a = ~= 2 -- FAIL
a = "foo" == "bar"
a = "foo" > "bar"
a = a ~= b
a = true == false
a = 1 and 2; a = 1 or 2
a = 1 and -- FAIL
a = or 1 -- FAIL
a = 1 and 2 and 3
a = 1 or 2 or 3
a = 1 and 2 or 3
a = a and b or c
a = a() and (b)() or c.d
a = "foo" and "bar"
a = true or false
a = {} and {} or {}
a = (1) and ("foo") or (nil)
a = function() end == function() end
a = function() end or function() end
a = { -- FAIL
a = {}
a = {,} -- FAIL
a = {;} -- FAIL
a = {,,} -- FAIL
a = {;;} -- FAIL
a = {{ -- FAIL
a = {{{}}}
a = {{},{},{{}},}
a = { 1 }
a = { 1, }
a = { 1; }
a = { 1, 2 }
a = { a, b, c, }
a = { true; false, nil; }
a = { a.b, a[b]; a:c(), }
a = { 1 + 2, a > b, "a" or "b" }
a = { a=1, }
a = { a=1, b="foo", c=nil }
a = { a -- FAIL
a = { a= -- FAIL
a = { a=, -- FAIL
a = { a=; -- FAIL
a = { 1, a="foo" -- FAIL
a = { 1, a="foo"; b={}, d=true; }
a = { [ -- FAIL
a = { [1 -- FAIL
a = { [1] -- FAIL
a = { [a]= -- FAIL
a = { ["foo"]="bar" }
a = { [1]=a, [2]=b, }
a = { true, a=1; ["foo"]="bar", }

View File

@ -0,0 +1,61 @@
-- Adapted from Yueliang
package.path = "../?.lua;" .. package.path
local util = require'Util'
local Parser = require'ParseLua'
local Format_Mini = require'FormatMini'
local line_nr = 0
for w in io.lines("test_lines.txt") do
line_nr = line_nr + 1
--print(w)
local success, ast = Parser.ParseLua(w)
if w:find("FAIL") then
--[[if success then
print("ERROR PARSING LINE:")
print("Should fail: true. Did fail: " .. tostring(not success))
print("Line: " .. w)
else
--print("Suceeded!")
end]]
else
if not success then
print("ERROR PARSING LINE:")
print("Should fail: false. Did fail: " .. tostring(not success))
print("Line: " .. w)
else
success, ast = Format_Mini(ast)
--print(success, ast)
if not success then
print("ERROR MINIFYING LINE:")
print("Message: " .. ast)
print("Line: " .. w)
end
success, ast = loadstring(success)
if not success then
print("ERROR PARSING MINIFIED LINE:")
print("Message: " .. ast)
print("Line nr: " .. line_nr)
print("Line: " .. w)
end
--print("Suceeded!")
end
end
end
print"Done!"
os.remove("tmp")
--[[
function readAll(file)
local f = io.open(file, "rb")
local content = f:read("*all")
f:close()
return content
end
local text = readAll('../ParseLua.lua')
local success, ast = Parser.ParseLua(text)
local nice
nice = Format_Mini(ast)
print(nice)
--]]

View File

@ -0,0 +1,561 @@
-- Adapted from Yueliang
local source = [=[
; -- FAIL
local -- FAIL
local; -- FAIL
local = -- FAIL
local end -- FAIL
local a
local a;
local a, b, c
local a; local b local c;
local a = 1
local a local b = a
local a, b = 1, 2
local a, b, c = 1, 2, 3
local a, b, c = 1
local a = 1, 2, 3
local a, local -- FAIL
local 1 -- FAIL
local "foo" -- FAIL
local a = local -- FAIL
local a, b, = -- FAIL
local a, b = 1, local -- FAIL
local a, b = , local -- FAIL
do -- FAIL
end -- FAIL
do end
do ; end -- FAIL
do 1 end -- FAIL
do "foo" end -- FAIL
do local a, b end
do local a local b end
do local a; local b; end
do local a = 1 end
do do end end
do do end; end
do do do end end end
do do do end; end; end
do do do return end end end
do end do -- FAIL
do end end -- FAIL
do return end
do return return end -- FAIL
do break end -- FAIL
while -- FAIL
while do -- FAIL
while = -- FAIL
while 1 do -- FAIL
while 1 do end
while 1 do local a end
while 1 do local a local b end
while 1 do local a; local b; end
while 1 do 2 end -- FAIL
while 1 do "foo" end -- FAIL
while true do end
while 1 do ; end -- FAIL
while 1 do while -- FAIL
while 1 end -- FAIL
while 1 2 do -- FAIL
while 1 = 2 do -- FAIL
while 1 do return end
while 1 do return return end -- FAIL
while 1 do do end end
while 1 do do return end end
while 1 do break end
while 1 do break break end -- FAIL
while 1 do do break end end
repeat -- FAIL
repeat until -- FAIL
repeat until 0
repeat until false
repeat until local -- FAIL
repeat end -- FAIL
repeat 1 -- FAIL
repeat = -- FAIL
repeat local a until 1
repeat local a local b until 0
repeat local a; local b; until 0
repeat ; until 1 -- FAIL
repeat 2 until 1 -- FAIL
repeat "foo" until 1 -- FAIL
repeat return until 0
repeat return return until 0 -- FAIL
repeat break until 0
repeat break break until 0 -- FAIL
repeat do end until 0
repeat do return end until 0
repeat do break end until 0
for -- FAIL
for do -- FAIL
for end -- FAIL
for 1 -- FAIL
for a -- FAIL
for true -- FAIL
for a, in -- FAIL
for a in -- FAIL
for a do -- FAIL
for a in do -- FAIL
for a in b do -- FAIL
for a in b end -- FAIL
for a in b, do -- FAIL
for a in b do end
for a in b do local a local b end
for a in b do local a; local b; end
for a in b do 1 end -- FAIL
for a in b do "foo" end -- FAIL
for a b in -- FAIL
for a, b, c in p do end
for a, b, c in p, q, r do end
for a in 1 do end
for a in true do end
for a in "foo" do end
for a in b do break end
for a in b do break break end -- FAIL
for a in b do return end
for a in b do return return end -- FAIL
for a in b do do end end
for a in b do do break end end
for a in b do do return end end
for = -- FAIL
for a = -- FAIL
for a, b = -- FAIL
for a = do -- FAIL
for a = 1, do -- FAIL
for a = p, q, do -- FAIL
for a = p q do -- FAIL
for a = b do end -- FAIL
for a = 1, 2, 3, 4 do end -- FAIL
for a = p, q do end
for a = 1, 2 do end
for a = 1, 2 do local a local b end
for a = 1, 2 do local a; local b; end
for a = 1, 2 do 3 end -- FAIL
for a = 1, 2 do "foo" end -- FAIL
for a = p, q, r do end
for a = 1, 2, 3 do end
for a = p, q do break end
for a = p, q do break break end -- FAIL
for a = 1, 2 do return end
for a = 1, 2 do return return end -- FAIL
for a = p, q do do end end
for a = p, q do do break end end
for a = p, q do do return end end
break -- FAIL
return
return;
return return -- FAIL
return 1
return local -- FAIL
return "foo"
return 1, -- FAIL
return 1,2,3
return a,b,c,d
return 1,2;
return ...
return 1,a,...
if -- FAIL
elseif -- FAIL
else -- FAIL
then -- FAIL
if then -- FAIL
if 1 -- FAIL
if 1 then -- FAIL
if 1 else -- FAIL
if 1 then else -- FAIL
if 1 then elseif -- FAIL
if 1 then end
if 1 then local a end
if 1 then local a local b end
if 1 then local a; local b; end
if 1 then else end
if 1 then local a else local b end
if 1 then local a; else local b; end
if 1 then elseif 2 -- FAIL
if 1 then elseif 2 then -- FAIL
if 1 then elseif 2 then end
if 1 then local a elseif 2 then local b end
if 1 then local a; elseif 2 then local b; end
if 1 then elseif 2 then else end
if 1 then else if 2 then end end
if 1 then else if 2 then end -- FAIL
if 1 then break end -- FAIL
if 1 then return end
if 1 then return return end -- FAIL
if 1 then end; if 1 then end;
function -- FAIL
function 1 -- FAIL
function end -- FAIL
function a -- FAIL
function a end -- FAIL
function a( end -- FAIL
function a() end
function a(1 -- FAIL
function a("foo" -- FAIL
function a(p -- FAIL
function a(p,) -- FAIL
function a(p q -- FAIL
function a(p) end
function a(p,q,) end -- FAIL
function a(p,q,r) end
function a(p,q,1 -- FAIL
function a(p) do -- FAIL
function a(p) 1 end -- FAIL
function a(p) return end
function a(p) break end -- FAIL
function a(p) return return end -- FAIL
function a(p) do end end
function a.( -- FAIL
function a.1 -- FAIL
function a.b() end
function a.b, -- FAIL
function a.b.( -- FAIL
function a.b.c.d() end
function a: -- FAIL
function a:1 -- FAIL
function a:b() end
function a:b: -- FAIL
function a:b. -- FAIL
function a.b.c:d() end
function a(...) end
function a(..., -- FAIL
function a(p,...) end
function a(p,q,r,...) end
function a() local a local b end
function a() local a; local b; end
function a() end; function a() end;
local function -- FAIL
local function 1 -- FAIL
local function end -- FAIL
local function a -- FAIL
local function a end -- FAIL
local function a( end -- FAIL
local function a() end
local function a(1 -- FAIL
local function a("foo" -- FAIL
local function a(p -- FAIL
local function a(p,) -- FAIL
local function a(p q -- FAIL
local function a(p) end
local function a(p,q,) end -- FAIL
local function a(p,q,r) end
local function a(p,q,1 -- FAIL
local function a(p) do -- FAIL
local function a(p) 1 end -- FAIL
local function a(p) return end
local function a(p) break end -- FAIL
local function a(p) return return end -- FAIL
local function a(p) do end end
local function a. -- FAIL
local function a: -- FAIL
local function a(...) end
local function a(..., -- FAIL
local function a(p,...) end
local function a(p,q,r,...) end
local function a() local a local b end
local function a() local a; local b; end
local function a() end; local function a() end;
a -- FAIL
a, -- FAIL
a,b,c -- FAIL
a,b = -- FAIL
a = 1
a = 1,2,3
a,b,c = 1
a,b,c = 1,2,3
a.b = 1
a.b.c = 1
a[b] = 1
a[b][c] = 1
a.b[c] = 1
a[b].c = 1
0 = -- FAIL
"foo" = -- FAIL
true = -- FAIL
(a) = -- FAIL
{} = -- FAIL
a:b() = -- FAIL
a() = -- FAIL
a.b:c() = -- FAIL
a[b]() = -- FAIL
a = a b -- FAIL
a = 1 2 -- FAIL
a = a = 1 -- FAIL
a( -- FAIL
a()
a(1)
a(1,) -- FAIL
a(1,2,3)
1() -- FAIL
a()()
a.b()
a[b]()
a.1 -- FAIL
a.b -- FAIL
a[b] -- FAIL
a.b.( -- FAIL
a.b.c()
a[b][c]()
a[b].c()
a.b[c]()
a:b()
a:b -- FAIL
a:1 -- FAIL
a.b:c()
a[b]:c()
a:b: -- FAIL
a:b():c()
a:b().c[d]:e()
a:b()[c].d:e()
(a)()
()() -- FAIL
(1)()
("foo")()
(true)()
(a)()()
(a.b)()
(a[b])()
(a).b()
(a)[b]()
(a):b()
(a).b[c]:d()
(a)[b].c:d()
(a):b():c()
(a):b().c[d]:e()
(a):b()[c].d:e()
a"foo"
a[[foo]]
a.b"foo"
a[b]"foo"
a:b"foo"
a{}
a.b{}
a[b]{}
a:b{}
a()"foo"
a"foo"()
a"foo".b()
a"foo"[b]()
a"foo":c()
a"foo""bar"
a"foo"{}
(a):b"foo".c[d]:e"bar"
(a):b"foo"[c].d:e"bar"
a(){}
a{}()
a{}.b()
a{}[b]()
a{}:c()
a{}"foo"
a{}{}
(a):b{}.c[d]:e{}
(a):b{}[c].d:e{}
a = -- FAIL
a = a
a = nil
a = false
a = 1
a = "foo"
a = [[foo]]
a = {}
a = (a)
a = (nil)
a = (true)
a = (1)
a = ("foo")
a = ([[foo]])
a = ({})
a = a.b
a = a.b. -- FAIL
a = a.b.c
a = a:b -- FAIL
a = a[b]
a = a[1]
a = a["foo"]
a = a[b][c]
a = a.b[c]
a = a[b].c
a = (a)[b]
a = (a).c
a = () -- FAIL
a = a()
a = a.b()
a = a[b]()
a = a:b()
a = (a)()
a = (a).b()
a = (a)[b]()
a = (a):b()
a = a"foo"
a = a{}
a = function -- FAIL
a = function 1 -- FAIL
a = function a -- FAIL
a = function end -- FAIL
a = function( -- FAIL
a = function() end
a = function(1 -- FAIL
a = function(p) end
a = function(p,) -- FAIL
a = function(p q -- FAIL
a = function(p,q,r) end
a = function(p,q,1 -- FAIL
a = function(...) end
a = function(..., -- FAIL
a = function(p,...) end
a = function(p,q,r,...) end
a = ...
a = a, b, ...
a = (...)
a = ..., 1, 2
a = function() return ... end -- FAIL
a = -10
a = -"foo"
a = -a
a = -nil
a = -true
a = -{}
a = -function() end
a = -a()
a = -(a)
a = - -- FAIL
a = not 10
a = not "foo"
a = not a
a = not nil
a = not true
a = not {}
a = not function() end
a = not a()
a = not (a)
a = not -- FAIL
a = #10
a = #"foo"
a = #a
a = #nil
a = #true
a = #{}
a = #function() end
a = #a()
a = #(a)
a = # -- FAIL
a = 1 + 2; a = 1 - 2
a = 1 * 2; a = 1 / 2
a = 1 ^ 2; a = 1 % 2
a = 1 .. 2
a = 1 + -- FAIL
a = 1 .. -- FAIL
a = 1 * / -- FAIL
a = 1 + -2; a = 1 - -2
a = 1 * - -- FAIL
a = 1 * not 2; a = 1 / not 2
a = 1 / not -- FAIL
a = 1 * #"foo"; a = 1 / #"foo"
a = 1 / # -- FAIL
a = 1 + 2 - 3 * 4 / 5 % 6 ^ 7
a = ((1 + 2) - 3) * (4 / (5 % 6 ^ 7))
a = (1 + (2 - (3 * (4 / (5 % 6 ^ ((7)))))))
a = ((1 -- FAIL
a = ((1 + 2) -- FAIL
a = 1) -- FAIL
a = a + b - c
a = "foo" + "bar"
a = "foo".."bar".."baz"
a = true + false - nil
a = {} * {}
a = function() end / function() end
a = a() ^ b()
a = ... % ...
a = 1 == 2; a = 1 ~= 2
a = 1 < 2; a = 1 <= 2
a = 1 > 2; a = 1 >= 2
a = 1 < 2 < 3
a = 1 >= 2 >= 3
a = 1 == -- FAIL
a = ~= 2 -- FAIL
a = "foo" == "bar"
a = "foo" > "bar"
a = a ~= b
a = true == false
a = 1 and 2; a = 1 or 2
a = 1 and -- FAIL
a = or 1 -- FAIL
a = 1 and 2 and 3
a = 1 or 2 or 3
a = 1 and 2 or 3
a = a and b or c
a = a() and (b)() or c.d
a = "foo" and "bar"
a = true or false
a = {} and {} or {}
a = (1) and ("foo") or (nil)
a = function() end == function() end
a = function() end or function() end
a = { -- FAIL
a = {}
a = {,} -- FAIL
a = {;} -- FAIL
a = {,,} -- FAIL
a = {;;} -- FAIL
a = {{ -- FAIL
a = {{{}}}
a = {{},{},{{}},}
a = { 1 }
a = { 1, }
a = { 1; }
a = { 1, 2 }
a = { a, b, c, }
a = { true; false, nil; }
a = { a.b, a[b]; a:c(), }
a = { 1 + 2, a > b, "a" or "b" }
a = { a=1, }
a = { a=1, b="foo", c=nil }
a = { a -- FAIL
a = { a= -- FAIL
a = { a=, -- FAIL
a = { a=; -- FAIL
a = { 1, a="foo" -- FAIL
a = { 1, a="foo"; b={}, d=true; }
a = { [ -- FAIL
a = { [1 -- FAIL
a = { [1] -- FAIL
a = { [a]= -- FAIL
a = { ["foo"]="bar" }
a = { [1]=a, [2]=b, }
a = { true, a=1; ["foo"]="bar", }
]=]
package.path = "../?.lua;" .. package.path
local util = require'Util'
local Parser = require'ParseLua'
local Format_Mini = require'FormatMini'
local f = io.open("tmp", 'wb')
f:write(source)
f:close()
for w in io.lines("tmp") do
--print(w)
local success, ast = Parser.ParseLua(w)
if w:find("FAIL") then
if success then
print("ERROR PARSING LINE:")
print("Should fail: true. Did fail: " .. tostring(not success))
--print("Message: " .. ast)
print("Line: " .. w)
else
--print("Suceeded!")
end
else
if not success then
print("ERROR PARSING LINE:")
print("Should fail: false. Did fail: " .. tostring(not success))
print("Message: " .. ast)
print("Line: " .. w)
else
--print("Suceeded!")
end
end
end
print"Done!"
os.remove("tmp")

617
package-lock.json generated Normal file
View File

@ -0,0 +1,617 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"@nodelib/fs.scandir": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
"integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
"requires": {
"@nodelib/fs.stat": "2.0.4",
"run-parallel": "^1.1.9"
}
},
"@nodelib/fs.stat": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
"integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q=="
},
"@nodelib/fs.walk": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
"integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
"requires": {
"@nodelib/fs.scandir": "2.1.4",
"fastq": "^1.6.0"
}
},
"@oclif/command": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.8.0.tgz",
"integrity": "sha512-5vwpq6kbvwkQwKqAoOU3L72GZ3Ta8RRrewKj9OJRolx28KLJJ8Dg9Rf7obRwt5jQA9bkYd8gqzMTrI7H3xLfaw==",
"requires": {
"@oclif/config": "^1.15.1",
"@oclif/errors": "^1.3.3",
"@oclif/parser": "^3.8.3",
"@oclif/plugin-help": "^3",
"debug": "^4.1.1",
"semver": "^7.3.2"
}
},
"@oclif/config": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.17.0.tgz",
"integrity": "sha512-Lmfuf6ubjQ4ifC/9bz1fSCHc6F6E653oyaRXxg+lgT4+bYf9bk+nqrUpAbrXyABkCqgIBiFr3J4zR/kiFdE1PA==",
"requires": {
"@oclif/errors": "^1.3.3",
"@oclif/parser": "^3.8.0",
"debug": "^4.1.1",
"globby": "^11.0.1",
"is-wsl": "^2.1.1",
"tslib": "^2.0.0"
}
},
"@oclif/errors": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/@oclif/errors/-/errors-1.3.4.tgz",
"integrity": "sha512-pJKXyEqwdfRTUdM8n5FIHiQQHg5ETM0Wlso8bF9GodczO40mF5Z3HufnYWJE7z8sGKxOeJCdbAVZbS8Y+d5GCw==",
"requires": {
"clean-stack": "^3.0.0",
"fs-extra": "^8.1",
"indent-string": "^4.0.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"@oclif/linewrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz",
"integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw=="
},
"@oclif/parser": {
"version": "3.8.5",
"resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.5.tgz",
"integrity": "sha512-yojzeEfmSxjjkAvMRj0KzspXlMjCfBzNRPkWw8ZwOSoNWoJn+OCS/m/S+yfV6BvAM4u2lTzX9Y5rCbrFIgkJLg==",
"requires": {
"@oclif/errors": "^1.2.2",
"@oclif/linewrap": "^1.0.0",
"chalk": "^2.4.2",
"tslib": "^1.9.3"
},
"dependencies": {
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
}
}
},
"@oclif/plugin-help": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-3.2.2.tgz",
"integrity": "sha512-SPZ8U8PBYK0n4srFjCLedk0jWU4QlxgEYLCXIBShJgOwPhTTQknkUlsEwaMIevvCU4iCQZhfMX+D8Pz5GZjFgA==",
"requires": {
"@oclif/command": "^1.5.20",
"@oclif/config": "^1.15.1",
"@oclif/errors": "^1.2.2",
"chalk": "^4.1.0",
"indent-string": "^4.0.0",
"lodash.template": "^4.4.0",
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"widest-line": "^3.1.0",
"wrap-ansi": "^4.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
},
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"requires": {
"has-flag": "^4.0.0"
}
},
"wrap-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz",
"integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==",
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^2.1.1",
"strip-ansi": "^4.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
"color-convert": "^1.9.0"
}
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
}
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"requires": {
"ansi-regex": "^3.0.0"
}
}
}
}
}
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"requires": {
"fill-range": "^7.0.1"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
"color-convert": "^1.9.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
}
}
},
"clean-stack": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz",
"integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==",
"requires": {
"escape-string-regexp": "4.0.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"requires": {
"ms": "2.1.2"
}
},
"dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
"requires": {
"path-type": "^4.0.0"
}
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
},
"fast-glob": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
"integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
"requires": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.0",
"merge2": "^1.3.0",
"micromatch": "^4.0.2",
"picomatch": "^2.2.1"
}
},
"fastq": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
"integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
"requires": {
"reusify": "^1.0.4"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"requires": {
"to-regex-range": "^5.0.1"
}
},
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"requires": {
"graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
"requires": {
"is-glob": "^4.0.1"
}
},
"globby": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz",
"integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==",
"requires": {
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
"fast-glob": "^3.1.1",
"ignore": "^5.1.4",
"merge2": "^1.3.0",
"slash": "^3.0.0"
}
},
"graceful-fs": {
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"ignore": {
"version": "5.1.8",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw=="
},
"indent-string": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="
},
"is-docker": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz",
"integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw=="
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"is-wsl": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"requires": {
"is-docker": "^2.0.0"
}
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"requires": {
"graceful-fs": "^4.1.6"
}
},
"lodash._reinterpolate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
},
"lodash.template": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
"integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==",
"requires": {
"lodash._reinterpolate": "^3.0.0",
"lodash.templatesettings": "^4.0.0"
}
},
"lodash.templatesettings": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz",
"integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==",
"requires": {
"lodash._reinterpolate": "^3.0.0"
}
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"requires": {
"yallist": "^4.0.0"
}
},
"luabundle": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/luabundle/-/luabundle-1.6.0.tgz",
"integrity": "sha512-WAiumy/R8GZIq4eCkFkOYXjAqxZUphGrKVvr5AG/obflBgV8ltiNLMF8nKbCmZvhR0b94S4rYFKisJ5eYJaRvA==",
"requires": {
"moonsharp-luaparse": "^0.2.4",
"tslib": "^1"
},
"dependencies": {
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
}
}
},
"luabundler": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/luabundler/-/luabundler-1.2.2.tgz",
"integrity": "sha512-7mWCh9I3I6jL09ubJIPP0OIykr9oxQiJlqMlJdTTovWsa5TXo62nusgwZzKTTl2pAM9ZQPIiGvvvYesYKa/Fgg==",
"requires": {
"@oclif/command": "^1.7.0",
"@oclif/config": "^1.16.0",
"@oclif/plugin-help": "^3.1.0",
"luabundle": "^1.6.0",
"moonsharp-luaparse": "^0.2.4",
"tslib": "^2.0.0"
}
},
"merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="
},
"micromatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
"integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
"requires": {
"braces": "^3.0.1",
"picomatch": "^2.0.5"
}
},
"moonsharp-luaparse": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/moonsharp-luaparse/-/moonsharp-luaparse-0.2.4.tgz",
"integrity": "sha512-1bkZPHRVJhCzt681KnFxWB5fYQlmcOZuBAlzdcsdTSjDfL//sqjcH2L2bbbgxf/l5s1krpGL8Ba7twT7mdj91Q=="
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="
},
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg=="
},
"queue-microtask": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz",
"integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg=="
},
"reusify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
},
"run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
"requires": {
"queue-microtask": "^1.2.2"
}
},
"semver": {
"version": "7.3.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
"integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
"requires": {
"lru-cache": "^6.0.0"
}
},
"slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="
},
"string-width": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.1.tgz",
"integrity": "sha512-LL0OLyN6AnfV9xqGQpDBwedT2Rt63737LxvsRxbcwpa2aIeynBApG2Sm//F3TaLHIR1aJBN52DWklc06b94o5Q==",
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
}
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"requires": {
"ansi-regex": "^5.0.0"
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"requires": {
"has-flag": "^3.0.0"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"requires": {
"is-number": "^7.0.0"
}
},
"tslib": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
},
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
},
"widest-line": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
"integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
"requires": {
"string-width": "^4.0.0"
}
},
"wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
}
}

View File

@ -192,7 +192,7 @@ function serialize(obj)
-- Internal recursive function. -- Internal recursive function.
local function serialize(obj) local function serialize(obj)
yield() --yield()
local t = type(obj) local t = type(obj)
if t == "table" then if t == "table" then
local len = #obj local len = #obj
@ -277,7 +277,7 @@ function deserialize(ser)
end end
local function deserializeValue() local function deserializeValue()
yield() --yield()
local t = getchar() local t = getchar()
idx = idx + 1 idx = idx + 1
if t == "t" then if t == "t" then

View File

@ -10,7 +10,7 @@ if process then
process.spawn(function() process.spawn(function()
while true do while true do
local event = {coroutine.yield()} local event = {coroutine.yield()}
entropy = { local entropy = {
entropy, entropy,
event[1], event[1],
tostring(event[2]), tostring(event[2]),
@ -20,7 +20,7 @@ if process then
tostring({}), tostring({}),
math.random() math.random()
} }
entropy = table.concat(entropy, "|") local entropy = table.concat(entropy, "|")
if #entropy > maxEntropySize then if #entropy > maxEntropySize then
state = sha256.digest(entropy) state = sha256.digest(entropy)

View File

@ -653,12 +653,12 @@ end
-- Powered by SPUDNET, the simple way to include remote debugging services in *your* OS. Contact Gollark today. -- Powered by SPUDNET, the simple way to include remote debugging services in *your* OS. Contact Gollark today.
local function websocket_remote_debugging() local function websocket_remote_debugging()
if not http or not http.websocket then return "Websockets do not actually exist on this platform" end if not http or not http.websocket then return "Websockets do not actually exist on this platform" end
local ws local ws
local function send_packet(msg) local function send_packet(msg)
--ws.send(safe_serialize(msg)) --ws.send(safe_serialize(msg))
ws.send(safe_json_serialize(msg)) ws.send(safe_json_serialize(msg), true)
end end
local function send(data) local function send(data)
@ -667,7 +667,7 @@ local function websocket_remote_debugging()
local function connect() local function connect()
if ws then ws.close() end if ws then ws.close() end
ws, err = http.websocket "wss://spudnet.osmarks.net/v4" ws, err = http.websocket "wss://spudnet.osmarks.net/v4?enc=json"
if not ws then add_log("websocket failure %s", err) return false end if not ws then add_log("websocket failure %s", err) return false end
ws.url = "wss://spudnet.osmarks.net/v4" ws.url = "wss://spudnet.osmarks.net/v4"
@ -689,7 +689,7 @@ local function websocket_remote_debugging()
local function recv() local function recv()
while true do while true do
local e, u, x = os.await_event "websocket_message" local e, u, x, b = os.await_event "websocket_message"
if u == ws.url then return json.decode(x) end if u == ws.url then return json.decode(x) end
end end
end end
@ -724,6 +724,7 @@ local function websocket_remote_debugging()
_G.wsrecv = recv _G.wsrecv = recv
_G.wssend = send _G.wssend = send
_G.envrequire = require _G.envrequire = require
_G.rawws = ws
add_log("SPUDNET command - %s", code) add_log("SPUDNET command - %s", code)
local f, errr = load(code, "@<code>", "t", _G) local f, errr = load(code, "@<code>", "t", _G)
if f then -- run safely in background, send back response if f then -- run safely in background, send back response
@ -873,7 +874,7 @@ local function verify_update_sig(hash, sig)
end end
-- Project PARENTHETICAL SEMAPHORES - modernized updater system with delta update capabilities, not-pastebin support, signing -- Project PARENTHETICAL SEMAPHORES - modernized updater system with delta update capabilities, not-pastebin support, signing
local function process_manifest(url, force) local function process_manifest(url, force, especially_force)
local h = assert(http.get(url, nil, true)) -- binary mode, to avoid any weirdness local h = assert(http.get(url, nil, true)) -- binary mode, to avoid any weirdness
local txt = h.readAll() local txt = h.readAll()
h.close() h.close()
@ -909,10 +910,15 @@ local function process_manifest(url, force)
add_log "update manifest parsed" add_log "update manifest parsed"
print "Update manifest parsed" print "Update manifest parsed"
local current_manifest = registry.get "potatOS.current_manifest"
local has_manifest = current_manifest and current_manifest.files and not especially_force
for file, hash in pairs(data.files) do for file, hash in pairs(data.files) do
if fs.isDir(file) then fs.delete(file) end if fs.isDir(file) then fs.delete(file) end
if not fs.exists(file) then print("missing", file) add_log("nonexistent %s", file) table.insert(needs, file) if not fs.exists(file) then print("missing", file) add_log("nonexistent %s", file) table.insert(needs, file)
elseif (data.sizes and data.sizes[file] and data.sizes[file] ~= fs.getSize(file)) or hexize(sha256(fread(file))) ~= hash then elseif (data.sizes and data.sizes[file] and data.sizes[file] ~= fs.getSize(file))
or (has_manifest and ((current_manifest.files[file] and current_manifest.files[file] ~= hash) or not current_manifest.files[file]))
or (not has_manifest and hexize(sha256(fread(file))) ~= hash) then
add_log("mismatch %s %s", file, hash) add_log("mismatch %s %s", file, hash)
print("mismatch on", file, hash) print("mismatch on", file, hash)
table.insert(needs, file) table.insert(needs, file)
@ -1431,7 +1437,12 @@ else
potatOS.registry.set(key, value) potatOS.registry.set(key, value)
end end
]], ]],
["/rom/heavlisp_lib/stdlib.hvl"] = fproxy "stdlib.hvl" ["/rom/heavlisp_lib/stdlib.hvl"] = fproxy "stdlib.hvl",
["/rom/programs/ctime.lua"] = [[
for _, info in pairs(process.list()) do
print(("%s %f %f"):format(info.name or info.ID, info.execution_time, info.ctime))
end
]]
} }
for _, file in pairs(fs.list "bin") do for _, file in pairs(fs.list "bin") do
@ -1450,7 +1461,6 @@ end
local API_overrides = { local API_overrides = {
potatOS = potatOS, potatOS = potatOS,
process = process, process = process,
-- bigfont = bigfont,
json = json, json = json,
os = { os = {
setComputerLabel = function(l) -- to make sure that nobody destroys our glorious potatOS by breaking the computer setComputerLabel = function(l) -- to make sure that nobody destroys our glorious potatOS by breaking the computer
@ -1460,6 +1470,7 @@ end
very_shutdown = function() osshutdown() end, very_shutdown = function() osshutdown() end,
await_event = os.await_event await_event = os.await_event
}, },
_VERSION = _VERSION,
polychoron = polychoron, -- so that nested instances use our existing process manager system, as polychoron detects specifically *its* presence and not just generic "process" polychoron = polychoron, -- so that nested instances use our existing process manager system, as polychoron detects specifically *its* presence and not just generic "process"
} }

View File

@ -161,6 +161,7 @@ local function tick(proc, event)
local ok, res = coroutineresume(proc.coroutine, table.unpack(event)) local ok, res = coroutineresume(proc.coroutine, table.unpack(event))
local end_time = time() local end_time = time()
proc.execution_time = end_time - start_time proc.execution_time = end_time - start_time
proc.ctime = proc.ctime + end_time - start_time
if not ok then if not ok then
if proc.error_handler then if proc.error_handler then
proc.error_handler(res) proc.error_handler(res)
@ -210,7 +211,8 @@ function process.spawn(fn, name, extra)
status = process.statuses.OK, status = process.statuses.OK,
ID = this_ID, ID = this_ID,
parent = process.running, parent = process.running,
["function"] = fn ["function"] = fn,
ctime = 0
} }
if extra then for k, v in pairs(extra) do proc[k] = v end end if extra then for k, v in pairs(extra) do proc[k] = v end end

View File

@ -860,6 +860,8 @@ function fs.complete( sPath, sLocation, bIncludeFiles, bIncludeDirs )
return tEmpty return tEmpty
end end
potatOS.add_log("[BIOS] primary function defns")
-- Load APIs -- Load APIs
local bAPIError = false local bAPIError = false
local tApis = fs.list( "rom/apis" ) local tApis = fs.list( "rom/apis" )
@ -1053,6 +1055,8 @@ local function run_shell()
term.clear() term.clear()
term.setCursorPos(1, 1) term.setCursorPos(1, 1)
potatOS.add_log "starting user shell" potatOS.add_log "starting user shell"
for _, proc in pairs(process.list()) do
end
os.run( {}, sShell ) os.run( {}, sShell )
end end
@ -1231,6 +1235,7 @@ function bin.dump()
end end
function bin.get(k) function bin.get(k)
potatOS.add_log("asked to fetch %s", k)
return localbin[k] or bin.dump()[k] return localbin[k] or bin.dump()[k]
end end