aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexander Pickering <alexandermpickering@gmail.com>2016-09-02 21:42:28 -0400
committerAlexander Pickering <alexandermpickering@gmail.com>2016-09-02 21:42:28 -0400
commit81fb5ea551c3dd8cfcb8e30c0dfed32a9000eea1 (patch)
treeeadec4ff981e758170194f17f1796b60ea5cde7e /src
parent25af93b5d1281e7a0f8d8869c5bff0a2ce8cf1bf (diff)
downloadglum-81fb5ea551c3dd8cfcb8e30c0dfed32a9000eea1.tar.gz
glum-81fb5ea551c3dd8cfcb8e30c0dfed32a9000eea1.tar.bz2
glum-81fb5ea551c3dd8cfcb8e30c0dfed32a9000eea1.zip
Added local variable counting and long string replacement
Diffstat (limited to 'src')
-rw-r--r--src/glum.lua145
-rw-r--r--src/parser.lua10
2 files changed, 127 insertions, 28 deletions
diff --git a/src/glum.lua b/src/glum.lua
index 7ee37b6..969dc27 100644
--- a/src/glum.lua
+++ b/src/glum.lua
@@ -14,7 +14,15 @@ This moudle allows you to minify gLua code
lpeg
]]
-local parser = dofile("../src/parser.lua")
+local parser
+local msg
+if include ~= nil then
+ parser = include("./parser.lua")
+ msg = Msg
+else
+ parser = dofile("../src/parser.lua")
+ msg = io.write
+end
local lpeg = require("lpeg")
lpeg.locale(lpeg)
@@ -67,17 +75,47 @@ end
local function printtable(tbl, tabset)
tabset = tabset or 0
for k,v in pairs(tbl) do
- for i = 0,tabset do io.write("\t") end
- io.write(k .. ":")
+ for i = 0,tabset do msg("\t") end
+ msg(k .. ":")
if type(v) == "table" then
- io.write("\n")
+ msg("\n")
printtable(v, tabset + 1)
else
- io.write(tostring(v) .. "\n")
+ msg(tostring(v) .. "\n")
end
end
end
+local stringreps
+local function findstrings(ast)
+ if type(ast) ~= "table" then return end
+ if ast and ast.tag == "String" then
+ local lnum = stringreps[ast[1]]
+ stringreps[ast[1]] = lnum and lnum + 1 or 1
+ return
+ end
+ for k = 1, #ast do
+ findstrings(ast[k])
+ end
+end
+
+local getstringreps = function(ast)
+ stringreps = {}
+ findstrings(ast)
+
+ local function bytessaved(str,instances,bytereplacement)
+ local spacetaken = string.len(str) * instances
+ local minspacetaken = instances * bytereplacement
+ return spacetaken - minspacetaken
+ end
+
+ local sstbl = {}
+ for k,v in pairs(stringreps) do table.insert(sstbl,{k,bytessaved(k,v,2)}) end
+ table.sort(sstbl,function(a,b) return a[2] > b[2] end)
+
+ return sstbl
+end
+
local syntax = {}
local function stringfor(ast,tbl)
@@ -88,6 +126,7 @@ local function stringfor(ast,tbl)
for k,v in pairs(syntax) do
print(k)
end
+ printtable(ast)
error("Attempted to use unknown tag type:" .. ast.tag)
end
end
@@ -116,9 +155,11 @@ syntax = {
local output = func
local inv
--A short hand if it's a simple thing
- if ast[2].tag == "String" and #ast[2][1] < (#func + 2) then
+ if ast[2].tag == "String" and ast[2][1]:find(" ") == nil and tbl.strings[ast[2][1]] == nil then
inv = ast[2][1]
output = table.concat({output, ":", inv, "("})
+ elseif tbl.strings[ast[2][1]] ~= nil then
+ output = table.concat({output,"[", tbl.strings[ast[2][1]], "]","("})
else
inv = stringfor(ast[2],tbl)
output = table.concat({output, "[", inv, "](", func, ","})
@@ -128,6 +169,12 @@ syntax = {
end,
["String"] = function(ast,tbl)
local sop,eop = "\"","\""
+ print("looking for",ast[1],"in")
+ printtable(tbl.strings)
+ if tbl.strings[ast[1]] then
+ print("Found it, it is", tbl.strings[ast[1]])
+ return tbl.strings[ast[1]]
+ end
if tbl.strings[ast[1]] == nil then
if string.find(ast[1],"\"") then
sop = "[["
@@ -160,9 +207,12 @@ syntax = {
["Forin"] = function(ast,tbl)
local nadd = deepcopy(tbl)
local nl = stringfor(ast[1],nadd)
+ nadd.numlocals = nadd.numlocals + #ast[1]
+ print("Found",#ast[1],"locals as Forin")
local el = stringfor(ast[2],nadd)
local code = stringfor(ast[3],nadd)
local output = table.concat({" for ", nl, " in ", el, " do ", code, " end "})
+ tbl.numlocals = nadd.numlocals
return output
end,
["NameList"] = function(ast,tbl)
@@ -207,6 +257,16 @@ syntax = {
end
return " return " .. table.concat(retargs,",")
end,
+ ["Do"] = function(ast,tbl)
+ local ntbl = deepcopy(tbl)
+ local allst = {}
+ for k = 1,#ast do
+ allst[k] = stringfor(ast[k],ntbl)
+ end
+ local code = table.concat(allst,";")
+ tbl.numlocals = ntbl.numlocals
+ return table.concat({" do ", code," end "})
+ end,
["If"] = function(ast,tbl)
local expr1 = stringfor(ast[1],tbl)
@@ -222,7 +282,9 @@ syntax = {
if #ast % 2 == 1 then
local block = stringfor(ast[#ast],tbl)
- codeblocks[#codeblocks + 1] = " else " .. block
+ if block ~= "" then --If for some reason there's an empty else block, forget about it.
+ codeblocks[#codeblocks + 1] = " else " .. block
+ end
end
codeblocks[#codeblocks + 1] = " end "
return table.concat(codeblocks)
@@ -253,6 +315,8 @@ syntax = {
end
local incstr = incrementer ~= 1 and ("," .. incrementer) or ""
tbl[var] = nil
+ tbl.numlocals = tbl.numlocals + 1
+ print("Found 1 locals as Fornum")
return table.concat({" for ",var,"=",start,",",endnum,incstr," do ",code," end "})
end,
["Op"] = function(ast,tbl)
@@ -305,10 +369,11 @@ syntax = {
return ast[1]
end,
["Local"] = function(ast,tbl)
- local tblcpy = tbl
- local lhs,rhs = stringfor(ast[1],tblcpy),nil
+ local lhs,rhs = stringfor(ast[1],tbl),nil
+ tbl.numlocals = tbl.numlocals + #ast[1]
+ print("Found",#ast[1],"locals as Local")
if ast[2].tag ~= nil then
- rhs = stringfor(ast[2],tblcpy)
+ rhs = stringfor(ast[2],tbl)
end
local output = "local " .. lhs
if ast[2].tag ~= nil then
@@ -371,6 +436,8 @@ syntax = {
end
local argstr = ast[2][1][1].tag ~= nil and stringfor(ast[2][1][1],tbl) or ""
local expr = stringfor(ast[2][1][2],tbl)
+ tbl.numlocals = tbl.numlocals + 1
+ print("Found 1 local as Localrec")
return table.concat({" local function ",ident,"(",argstr,")",expr," end "})
end,
["Continue"] = function(ast,tbl)
@@ -393,20 +460,8 @@ syntax = {
codeblocks[#codeblocks + 1] = stringfor(ast[k],tbl)
end
local code = table.concat(codeblocks)
- local lhss,rhss = {},{}
- for k,v in pairs(tbl.strings) do
- if oldtbl.strings[k] ~= tbl.strings[k] then
- lhss[#lhss + 1] = v
- rhss[#rhss + 1] = string.format("%q",k)
- end
- end
- local inits = ""
- local lhs = " local " .. table.concat(lhss,",")
- local rhs = table.concat(rhss,",")
- if string.len(rhs) > 0 then
- inits = table.concat({lhs, "=", rhs, ";"})
- end
- return inits .. code
+ oldtbl.numlocals = tbl.numlocals
+ return code
end,
}
@@ -441,19 +496,57 @@ glum.minify = function(str, name)
local ast, error_msg = parser.parse(str, name)
if not ast then
error(error_msg)
+ return nil
end
- local localvar = {
+ print("Finding string reps")
+ local strreps = getstringreps(ast)
+ printtable(strreps)
+
+ local olocalvar = {
["numlocals"] = 0,
["strings"] = {},
["ids"] = {},
["lname"] = "",
["nids"] = {},
}
+
--printtable(ast)
- return stringfor(ast,localvar)
+ local lvt = deepcopy(olocalvar)
+ local ret = stringfor(ast,olocalvar)
+ local numstrreplaced = 0
+ local maxlocals = lvt.numlocals
+ while
+ (numstrreplaced + maxlocals < 200) and --We have some locals left
+ (numstrreplaced < #strreps) and --We have more strings to replace
+ (strreps[numstrreplaced+1][2] > 5) do --Replaceing this string will at least cover the cost of "local "
+ numstrreplaced = numstrreplaced + 1
+ local nvar = getnextvarname(olocalvar.lname)
+ olocalvar.strings[strreps[numstrreplaced][1]] = nvar
+ olocalvar.lname = nvar
+ end
+
+ local lhss,rhss = {},{}
+ for k,v in pairs(olocalvar.strings) do
+ lhss[#lhss + 1] = v
+ rhss[#rhss + 1] = string.format("%q",k)
+ end
+ local inits = ""
+ print("lhss is")
+ printtable(lhss)
+ local lhs = " local " .. table.concat(lhss,",")
+ local rhs = table.concat(rhss,",")
+ if string.len(rhs) > 0 then
+ inits = table.concat({lhs, "=", rhs, ";"})
+ end
+
+ print("Before doing stringfor for the second time, olocalvar is")
+ printtable(olocalvar)
+
+ return inits .. stringfor(ast,olocalvar)
end
glum.uglify = function(str)
+ assert(str ~= nil, "Cannot uglify a nil string")
local avalchars = {}
local capture_chars = {"%","(","[","\13"}
local skipchars = {}
diff --git a/src/parser.lua b/src/parser.lua
index 0770bf7..56375d6 100644
--- a/src/parser.lua
+++ b/src/parser.lua
@@ -48,7 +48,12 @@ opid: 'add' | 'sub' | 'mul' | 'div' | 'idiv' | 'mod' | 'pow' | 'concat'
]]
local parser = {}
local lpeg = require("lpeg")
-local scope = dofile("../src/scope.lua")
+local scope
+if include ~= nil then
+ scope = include("./scope.lua")
+else
+ scope = dofile("../src/scope.lua")
+end
lpeg.locale(lpeg)
@@ -843,7 +848,8 @@ end
function parser.parse (subject, filename)
local errorinfo = { subject = subject, filename = filename }
- --lpeg.setmaxstack(1000)
+ lpeg.setmaxstack(1000)
+ --debug.getregistry()["lpeg-maxstack"] = 1000
local ast, error_msg = lpeg.match(G, subject, nil, errorinfo)
if not ast then return ast, error_msg end
return traverse(ast, errorinfo)