diff --git a/lua_obj.lua b/lua_obj.lua index 8375016..076ac1c 100644 --- a/lua_obj.lua +++ b/lua_obj.lua @@ -94,32 +94,6 @@ local Code do local _class_0 local _base_0 = { - clone = function(self) - local cls = self.__class - local copy = cls(self.source, unpack(self.bits)) - copy.is_value = self.is_value - for k, v in pairs(self.free_vars) do - copy.free_vars[k] = v - end - return copy - end, - __tostring = function(self) - local buff = { } - for i, b in ipairs(self.bits) do - buff[#buff + 1] = tostring(b) - end - local ret = concat(buff, "") - return ret - end, - __len = function(self) - local len = 0 - local _list_0 = self.bits - for _index_0 = 1, #_list_0 do - local b = _list_0[_index_0] - len = len + #b - end - return len - end, sub = function(self, start, stop) local str = tostring(self):sub(start, stop) local cls = self.__class @@ -129,24 +103,53 @@ do local n = select("#", ...) local bits = self.bits for i = 1, n do - bits[#bits + 1] = select(i, ...) + local b = select(i, ...) + bits[#bits + 1] = b + if type(b) == 'string' then + do + local spaces = b:match("\n([ ]*)[^\n]*$") + if spaces then + self.current_indent = #spaces + end + end + elseif self.current_indent ~= 0 then + self.indents[#bits] = self.current_indent + end end + self.__str = nil end, prepend = function(self, ...) local n = select("#", ...) - local bits = self.bits + local bits, indents = self.bits, self.indents for i = #bits + n, n + 1, -1 do bits[i] = bits[i - n] end for i = 1, n do bits[i] = select(i, ...) end + self.current_indent = 0 + for i, b in ipairs(bits) do + if type(b) == 'string' then + do + local spaces = b:match("\n([ ]*)[^\n]*$") + if spaces then + self.current_indent = #spaces + end + end + elseif self.current_indent ~= 0 then + indents[i] = self.current_indent + else + indents[i] = nil + end + end + self.__str = nil end } _base_0.__index = _base_0 _class_0 = setmetatable({ __init = function(self, source, ...) self.source = source + self.indents = { } self.bits = { ... } @@ -162,11 +165,22 @@ do end end assert(self.source == nil or Source:is_instance(self.source)) - local _list_0 = self.bits - for _index_0 = 1, #_list_0 do - local b = _list_0[_index_0] + local indent = 0 + for i, b in ipairs(self.bits) do assert(not Source:is_instance(b)) + if type(b) == 'string' then + do + local spaces = b:match("\n([ ]*)[^\n]*$") + if spaces then + indent = #spaces + end + end + elseif indent ~= 0 then + self.indents[i] = indent + end end + self.current_indent = indent + self.__str = nil end, __base = _base_0, __name = "Code" @@ -289,17 +303,18 @@ do end gather_from(self) end - self:remove_free_vars(to_declare) if #to_declare > 0 then + self:remove_free_vars(unpack(to_declare)) return self:prepend("local " .. tostring(concat(to_declare, ", ")) .. ";\n") end end, - stringify = function(self) + __tostring = function(self) if self.__str == nil then - local buff = { } + local buff, indents = { }, self.indents for i, b in ipairs(self.bits) do - if type(b) ~= 'string' then - b = b:stringify() + b = tostring(b) + if indents[i] then + b = b:gsub("\n", "\n" .. ((" "):rep(indents[i]))) end buff[#buff + 1] = b end @@ -307,51 +322,8 @@ do end return self.__str end, - __tostring = function(self) - if self.__str == nil then - local buff = { } - for i, b in ipairs(self.bits) do - buff[#buff + 1] = tostring(b) - end - self.__str = concat(buff, "") - end - return self.__str - end, __len = function(self) - local len = 0 - local _list_0 = self.bits - for _index_0 = 1, #_list_0 do - local b = _list_0[_index_0] - len = len + #b - end - return len - end, - append = function(self, ...) - local n = select("#", ...) - local bits = self.bits - for i = 1, n do - local bit = select(i, ...) - bits[#bits + 1] = bit - if type(bit) ~= 'string' and not bit.is_value and #self.bits > 0 then - bits[#bits + 1] = "\n" - end - end - self.__str = nil - end, - prepend = function(self, ...) - local n = select("#", ...) - local bits = self.bits - local insert_index = 1 - for i = 1, n do - local bit = select(i, ...) - insert(bits, insert_index, bit) - insert_index = insert_index + 1 - if type(bit) ~= 'string' and not bit.is_value and insert_index < #self.bits + 1 then - insert(bits, insert_index, "\n") - insert_index = insert_index + 1 - end - end - self.__str = nil + return #tostring(self) end, make_offset_table = function(self) local lua_to_nomsu, nomsu_to_lua = { }, { } @@ -437,21 +409,21 @@ do local _parent_0 = Code local _base_0 = { __tostring = function(self) - local buff = { } - for i, b in ipairs(self.bits) do - buff[#buff + 1] = tostring(b) + if self.__str == nil then + local buff, indents = { }, self.indents + for i, b in ipairs(self.bits) do + b = tostring(b) + if indents[i] then + b = b:gsub("\n", "\n" .. ((" "):rep(indents[i]))) + end + buff[#buff + 1] = b + end + self.__str = concat(buff, "") end - local ret = concat(buff, "") - return ret + return self.__str end, __len = function(self) - local len = 0 - local _list_0 = self.bits - for _index_0 = 1, #_list_0 do - local b = _list_0[_index_0] - len = len + #b - end - return len + return #tostring(self) end } _base_0.__index = _base_0 diff --git a/nomsu.lua b/nomsu.lua index b1427d3..7261a72 100644 --- a/nomsu.lua +++ b/nomsu.lua @@ -424,7 +424,7 @@ do end, run_lua = function(self, lua) assert(type(lua) ~= 'string', "Attempt to run lua string instead of Lua (object)") - local lua_string = lua:stringify() + local lua_string = tostring(lua) if rawget(FILE_CACHE, lua.source.filename) == nil then FILE_CACHE[lua.source.filename] = lua_string end @@ -451,355 +451,8 @@ do local lua = Lua(tree.source, "return ", self:tree_to_lua(tree), ";") return self:run_lua(lua) end, - tree_to_nomsu = function(self, tree, indentation, max_line, expr_type) - if indentation == nil then - indentation = "" - end - if max_line == nil then - max_line = 80 - end - if expr_type == nil then - expr_type = nil - end - assert(tree, "No tree provided to tree_to_nomsu.") - assert(Types.is_node(tree), "Invalid tree: " .. tostring(repr(tree))) - local join_lines - join_lines = function(lines) - for _index_0 = 1, #lines do - local line = lines[_index_0] - if #indentation + #line > max_line then - return nil - end - end - return concat(lines, "\n" .. indentation) - end - local is_operator - is_operator = function(tok) - return tok and tok.type == "Word" and NOMSU_DEFS.operator:match(tok.value) - end - local inline_expression, noeol_expression, expression - inline_expression = function(tok) - local _exp_0 = tok.type - if "Block" == _exp_0 then - if #tok.value > 1 then - return nil - end - local nomsu = inline_expression(tok.value) - return nomsu and "(: " .. tostring(nomsu) .. ")" - elseif "Action" == _exp_0 then - local buff = "" - for i, bit in ipairs(tok.value) do - if bit.type == "Word" then - if i == 1 or (is_operator(bit) and is_operator(tok.value[i - 1])) then - buff = buff .. bit.value - else - buff = buff .. (" " .. bit.value) - end - else - local nomsu = inline_expression(bit) - if not (nomsu) then - return nil - end - if not (i == 1 or bit.type == "Block") then - buff = buff .. " " - end - buff = buff .. (function() - if bit.type == "Action" then - return "(" .. nomsu .. ")" - else - return nomsu - end - end)() - end - end - return buff - elseif "IndexChain" == _exp_0 then - local bits = { } - local _list_0 = tok.value - for _index_0 = 1, #_list_0 do - local bit = _list_0[_index_0] - local nomsu = inline_expression(bit) - if not (nomsu) then - return nil - end - insert(bits, nomsu) - end - return concat(bits, ".") - elseif "List" == _exp_0 then - local bits = { } - local _list_0 = tok.value - for _index_0 = 1, #_list_0 do - local bit = _list_0[_index_0] - local nomsu = inline_expression(bit) - if not (nomsu) then - return nil - end - insert(bits, nomsu) - end - return "[" .. concat(bits, ", ") .. "]" - elseif "Dict" == _exp_0 then - local bits = { } - local _list_0 = tok.value - for _index_0 = 1, #_list_0 do - local bit = _list_0[_index_0] - local key_nomsu - if bit.key.type == "Word" then - key_nomsu = bit.key.value - else - key_nomsu = inline_expression(bit.key) - end - if not (key_nomsu) then - return nil - end - if bit.key.type == "Action" then - key_nomsu = "(" .. key_nomsu .. ")" - end - local value_nomsu = inline_expression(bit.value) - if not (value_nomsu) then - return nil - end - insert(bits, key_nomsu .. "=" .. value_nomsu) - end - return "{" .. concat(bits, ", ") .. "}" - elseif "Text" == _exp_0 then - local buff = '"' - local _list_0 = tok.value - for _index_0 = 1, #_list_0 do - local bit = _list_0[_index_0] - if type(bit) == 'string' then - if bit:find("\n") then - return nil - end - buff = buff .. bit:gsub("\\", "\\\\"):gsub("\n", "\\n") - else - local nomsu = inline_expression(bit) - if not (nomsu) then - return nil - end - buff = buff .. (function() - if bit.type == "Var" or bit.type == "List" or bit.type == "Dict" then - return "\\" .. nomsu - else - return "\\(" .. nomsu .. ")" - end - end)() - end - if #buff > max_line then - return nil - end - end - return buff .. '"' - elseif "Nomsu" == _exp_0 then - local nomsu = inline_expression(tok.value) - if not nomsu then - return nil - end - return "\\(" .. nomsu .. ")" - elseif "Number" == _exp_0 then - return tostring(tok.value) - elseif "Var" == _exp_0 then - return "%" .. tok.value - else - return nil - end - end - noeol_expression = function(tok) - local nomsu = inline_expression(tok) - if nomsu and #nomsu < max_line then - return nomsu - end - local _exp_0 = tok.type - if "Block" == _exp_0 then - local buff = ":" - local _list_0 = tok.value - for _index_0 = 1, #_list_0 do - local line = _list_0[_index_0] - nomsu = expression(line) - if not (nomsu) then - return nil - end - buff = buff .. ("\n " .. self:indent(nomsu)) - end - return buff - elseif "Action" == _exp_0 then - nomsu = expression(tok) - if not (nomsu) then - return nil - end - return "(..)\n " .. self:indent(nomsu) - elseif "IndexChain" == _exp_0 then - return nil - elseif "List" == _exp_0 then - local buff = "[..]" - local line = "\n " - local _list_0 = tok.value - for _index_0 = 1, #_list_0 do - local bit = _list_0[_index_0] - nomsu = inline_expression(bit) - if line ~= "\n " and #line + #", " + #nomsu > max_line then - buff = buff .. line - line = "\n " - end - local sep = line == "\n " and "" or ", " - if nomsu then - line = line .. (sep .. nomsu) - if #line >= max_line then - buff = buff .. line - line = "\n " - end - else - line = line .. (sep .. expression(bit)) - buff = buff .. line - line = "\n " - end - end - if line ~= "\n " then - buff = buff .. line - end - return buff - elseif "Dict" == _exp_0 then - local buff = "{..}" - local line = "\n " - local _list_0 = tok.value - for _index_0 = 1, #_list_0 do - local bit = _list_0[_index_0] - local key_nomsu = inline_expression(bit.key) - if not (key_nomsu) then - return nil - end - if bit.key.type == "Action" then - key_nomsu = "(" .. key_nomsu .. ")" - end - local value_nomsu = inline_expression(bit.value) - if value_nomsu and #key_nomsu + #value_nomsu < max_line then - line = line .. (key_nomsu .. "=" .. value_nomsu .. ",") - if #line >= max_line then - buff = buff .. line - line = "\n " - end - else - line = line .. (key_nomsu .. "=" .. expression(bit.value)) - buff = buff .. line - line = "\n " - end - end - if line ~= "\n " then - buff = buff .. line - end - return buff - elseif "Text" == _exp_0 then - local buff = '".."\n ' - local _list_0 = tok.value - for _index_0 = 1, #_list_0 do - local bit = _list_0[_index_0] - if type(bit) == 'string' then - buff = buff .. bit:gsub("\\", "\\\\"):gsub("\n", "\n ") - else - nomsu = inline_expression(bit) - if not (nomsu) then - return nil - end - buff = buff .. (function() - if bit.type == "Var" or bit.type == "List" or bit.type == "Dict" then - return "\\" .. nomsu - else - return "\\(" .. nomsu .. ")" - end - end)() - end - end - return buff - elseif "Nomsu" == _exp_0 then - nomsu = expression(tok.value) - if not nomsu then - return nil - end - return "\\(..)\n " .. self:indent(nomsu) - elseif "Comment" == _exp_0 then - if tok.value:find("\n") then - return "#.." .. tok.value:gsub("\n", "\n ") - else - return "#" .. tok.value - end - else - return inline_expression(tok) - end - end - expression = function(tok) - local nomsu = inline_expression(tok) - if nomsu and #nomsu < max_line then - return nomsu - end - local _exp_0 = tok.type - if "Block" == _exp_0 then - if #tok.value == 1 then - if tok.value[1].type == "Action" then - nomsu = inline_expression(tok.value[1]) - else - nomsu = noeol_expression(tok.value[1]) - end - if nomsu and #(nomsu:match("[^\n]*")) < max_line then - return ": " .. nomsu - end - end - return noeol_expression(tok) - elseif "Action" == _exp_0 then - local buff = "" - for i, bit in ipairs(tok.value) do - if bit.type == "Word" then - if i == 1 or (is_operator(bit) and is_operator(tok.value[i - 1])) or buff:sub(-2, -1) == ".." then - buff = buff .. bit.value - else - buff = buff .. (" " .. bit.value) - end - else - nomsu = inline_expression(bit) - if nomsu and #nomsu < max_line then - if bit.type == "Action" then - nomsu = "(" .. nomsu .. ")" - end - else - nomsu = expression(bit) - if not (nomsu) then - return nil - end - if bit.type == "Action" then - nomsu = "(..)\n " .. self:indent(nomsu) - end - if i < #tok.value then - nomsu = nomsu .. "\n.." - end - end - if not (i == 1 or bit.type == "Block") then - buff = buff .. " " - end - buff = buff .. nomsu - end - end - return buff - elseif "File" == _exp_0 then - local lines = { } - local _list_0 = tree.value - for _index_0 = 1, #_list_0 do - local line = _list_0[_index_0] - nomsu = expression(line) - if not (nomsu) then - error("Failed to produce output for:\n" .. tostring(colored.yellow(line.source:get_text())), 0) - end - insert(lines, nomsu) - end - return concat(lines, "\n") - elseif "Comment" == _exp_0 then - if tok.value:find("\n") then - return "#.." .. tok.value:gsub("\n", "\n ") - else - return "#" .. tok.value - end - else - return noeol_expression(tok) - end - end - return expression(tree) + tree_to_nomsu = function(self, tree) + return tree:as_nomsu() end, value_to_nomsu = function(self, value) local _exp_0 = type(value) @@ -946,7 +599,7 @@ do tree_with_replaced_vars = function(self, tree, replacements) return self:tree_map(tree, function(t) if t.type == "Var" then - local id = t:as_lua(self):stringify() + local id = tostring(t:as_lua(self)) if replacements[id] ~= nil then return replacements[id] end @@ -1044,7 +697,7 @@ do lua:convert_to_statements() lua:declare_locals() nomsu:run_lua(lua) - return Lua(self.source, "if IMMEDIATE then\n", lua, "\nend") + return Lua(self.source, "if IMMEDIATE then\n ", lua, "\nend") end) local add_lua_bits add_lua_bits = function(lua, code) @@ -1094,7 +747,7 @@ do end) self:define_compile_action("lua> %code", get_line_no(), function(self, _code) if _code.type ~= "Text" then - return Lua.Value(self.source, "nomsu:run_lua(Lua(", repr(_code.source), ", ", repr(nomsu:tree_to_lua(_code):stringify()), "))") + return Lua.Value(self.source, "nomsu:run_lua(Lua(", repr(_code.source), ", ", repr(tostring(nomsu:tree_to_lua(_code))), "))") end local lua = Lua(_code.source) local _list_0 = _code.value @@ -1115,7 +768,7 @@ do end) self:define_compile_action("=lua %code", get_line_no(), function(self, _code) if _code.type ~= "Text" then - return Lua.Value(self.source, "nomsu:run_lua(Lua(", repr(_code.source), ", ", repr(nomsu:tree_to_lua(_code):stringify()), "))") + return Lua.Value(self.source, "nomsu:run_lua(Lua(", repr(_code.source), ", ", repr(tostring(nomsu:tree_to_lua(_code))), "))") end local lua = Lua.Value(self.source) local _list_0 = _code.value @@ -1359,11 +1012,11 @@ if arg and debug_getinfo(2).func ~= require then if args.flags["-p"] then nomsu.environment.print = function() end compile_fn = function(code) - return io.output():write("local IMMEDIATE = true;\n" .. (code:stringify())) + return io.output():write("local IMMEDIATE = true;\n" .. tostring(code)) end elseif args.output then compile_fn = function(code) - return io.open(args.output, 'w'):write("local IMMEDIATE = true;\n" .. (code:stringify())) + return io.open(args.output, 'w'):write("local IMMEDIATE = true;\n" .. tostring(code)) end end if args.input:match(".*%.lua") then