From 4892c63e92bf82386b4ebb54a5a1dd76dcd792f8 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Wed, 25 Apr 2018 17:56:18 -0700 Subject: Renamed lua_obj -> code_obj --- code_obj.lua | 473 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ code_obj.moon | 254 +++++++++++++++++++++++++++++++ lua_obj.lua | 473 ---------------------------------------------------------- lua_obj.moon | 254 ------------------------------- 4 files changed, 727 insertions(+), 727 deletions(-) create mode 100644 code_obj.lua create mode 100644 code_obj.moon delete mode 100644 lua_obj.lua delete mode 100644 lua_obj.moon diff --git a/code_obj.lua b/code_obj.lua new file mode 100644 index 0000000..4e7de9b --- /dev/null +++ b/code_obj.lua @@ -0,0 +1,473 @@ +local insert, remove, concat +do + local _obj_0 = table + insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat +end +local immutable = require('immutable') +local Lua, Source +Source = immutable({ + "filename", + "start", + "stop" +}, { + name = "Source", + __new = function(self, filename, start, stop) + if not start then + start, stop = 1, #FILE_CACHE[filename] + end + if stop then + assert(start <= stop, "Invalid range: " .. tostring(start) .. ", " .. tostring(stop)) + end + return filename, start, stop + end, + __tostring = function(self) + if self.stop then + return "\"" .. tostring(self.filename) .. "[" .. tostring(self.start) .. ":" .. tostring(self.stop) .. "]\"" + else + return "\"" .. tostring(self.filename) .. "[" .. tostring(self.start) .. "]\"" + end + end, + __lt = function(self, other) + assert(self.filename == other.filename, "Cannot compare sources from different files") + if self.start == other.start then + return (self.stop or self.start) < (other.stop or other.start) + else + return self.start < other.start + end + end, + __le = function(self, other) + assert(self.filename == other.filename, "Cannot compare sources from different files") + if self.start == other.start then + return (self.stop or self.start) <= (other.stop or other.start) + else + return self.start <= other.start + end + end, + __add = function(self, offset) + if type(self) == 'number' then + offset, self = self, offset + else + assert(type(offset) == 'number', "Cannot add Source and " .. tostring(type(offset))) + end + return Source(self.filename, self.start + offset, self.stop) + end, + sub = function(self, start, stop) + start = start or 1 + assert(start > 0 and (stop == nil or stop > 0), "Negative subscripts not supported") + if not self.stop then + assert(not stop, "cannot subscript non-range with range") + return Source(self.filename, self.start + start - 1) + else + stop = stop or self.stop + return Source(self.filename, self.start + start - 1, self.start + stop - 1) + end + end, + get_text = function(self) + return FILE_CACHE[self.filename]:sub(self.start, self.stop) + end, + get_line_number = function(self) + local src = FILE_CACHE[self.filename] + local line_starts = LINE_STARTS[src] + local start_line = 1 + while (line_starts[start_line + 1] or math.huge) <= self.start do + start_line = start_line + 1 + end + local stop_line = start_line + while (line_starts[stop_line + 1] or math.huge) <= self.stop do + stop_line = stop_line + 1 + end + return start_line, stop_line + end, + get_line = function(self) + return tostring(self.filename) .. ":" .. tostring(self:get_line_number()) + end, + get_line_range = function(self) + local start_line, stop_line = self:get_line_number() + if stop_line == start_line then + return tostring(self.filename) .. ":" .. tostring(start_line) + else + return tostring(self.filename) .. ":" .. tostring(start_line) .. "-" .. tostring(stop_line) + end + end +}) +local Code +do + local _class_0 + local _base_0 = { + sub = function(self, start, stop) + local str = tostring(self):sub(start, stop) + local cls = self.__class + return cls(self.source:sub(start, stop), str) + end, + append = function(self, ...) + local n = select("#", ...) + local bits = self.bits + for i = 1, n do + local b = select(i, ...) + assert(b ~= self, "No recursion please.") + 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, 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 + assert(b ~= self, "No recursion please.") + 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 = { + ... + } + if type(self.source) == 'string' then + local filename, start, stop = self.source:match("^(.-)%[(%d+):(%d+)%]$") + if not (filename) then + filename, start = self.source:match("^(.-)%[(%d+)%]$") + end + if start or stop then + self.source = Source(filename, tonumber(start), tonumber(stop)) + else + self.source = Source(self.source, 1, #self + 1) + end + end + assert(self.source == nil or Source:is_instance(self.source)) + 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" + }, { + __index = _base_0, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + Code = _class_0 +end +do + local _class_0 + local _parent_0 = Code + local _base_0 = { + add_free_vars = function(self, ...) + local seen + do + local _tbl_0 = { } + local _list_0 = self.free_vars + for _index_0 = 1, #_list_0 do + local v = _list_0[_index_0] + local _key_0, _val_0 = { + [v] = true + } + _tbl_0[_key_0] = _val_0 + end + seen = _tbl_0 + end + for i = 1, select("#", ...) do + local var = select(i, ...) + if type(var) == 'userdata' and var.type == "Var" then + var = tostring(var:as_lua()) + elseif type(var) ~= 'string' then + var = tostring(var) + end + if not (seen[var]) then + self.free_vars[#self.free_vars + 1] = var + seen[var] = true + end + end + self.__str = nil + end, + remove_free_vars = function(self, ...) + local removals = { } + for i = 1, select("#", ...) do + local var = select(i, ...) + if type(var) == 'userdata' and var.type == "Var" then + var = tostring(var:as_lua()) + elseif type(var) ~= 'string' then + var = tostring(var) + end + removals[var] = true + end + local stack = { + self + } + while #stack > 0 do + local lua + lua, stack[#stack] = stack[#stack], nil + for i = #lua.free_vars, 1, -1 do + if removals[lua.free_vars[i]] then + remove(lua.free_vars, i) + end + end + local _list_0 = lua.bits + for _index_0 = 1, #_list_0 do + local b = _list_0[_index_0] + if type(b) ~= 'string' then + stack[#stack + 1] = b + end + end + end + self.__str = nil + end, + convert_to_statements = function(self, prefix, suffix) + if prefix == nil then + prefix = "" + end + if suffix == nil then + suffix = ";" + end + if not (self.is_value) then + return + end + if prefix ~= "" then + self:prepend(prefix) + end + if suffix ~= "" then + return self:append(suffix) + end + end, + declare_locals = function(self, to_declare) + if to_declare == nil then + to_declare = nil + end + if to_declare == nil then + local seen + to_declare, seen = { }, { } + local gather_from + gather_from = function(self) + local _list_0 = self.free_vars + for _index_0 = 1, #_list_0 do + local var = _list_0[_index_0] + if not (seen[var]) then + seen[var] = true + to_declare[#to_declare + 1] = var + end + end + local _list_1 = self.bits + for _index_0 = 1, #_list_1 do + local bit = _list_1[_index_0] + if bit.__class == Lua then + gather_from(bit) + end + end + end + gather_from(self) + end + if #to_declare > 0 then + self:remove_free_vars(unpack(to_declare)) + return self:prepend("local " .. tostring(concat(to_declare, ", ")) .. ";\n") + end + end, + __tostring = function(self) + 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 + return self.__str + end, + __len = function(self) + return #tostring(self) + end, + make_offset_table = function(self) + local lua_to_nomsu, nomsu_to_lua = { }, { } + local walk + walk = function(lua, pos) + local _list_0 = lua.bits + for _index_0 = 1, #_list_0 do + local b = _list_0[_index_0] + if type(b) == 'string' then + if lua.source then + lua_to_nomsu[pos] = lua.source.start + nomsu_to_lua[lua.source.start] = pos + end + else + walk(b, pos) + end + pos = pos + #b + end + end + walk(self, 1) + return { + nomsu_filename = self.source.filename, + lua_filename = tostring(self.source) .. ".lua", + lua_file = self:stringify(), + lua_to_nomsu = lua_to_nomsu, + nomsu_to_lua = nomsu_to_lua + } + end, + parenthesize = function(self) + if self.is_value then + self:prepend("(") + return self:append(")") + else + return error("Cannot parenthesize lua statements") + end + end + } + _base_0.__index = _base_0 + setmetatable(_base_0, _parent_0.__base) + _class_0 = setmetatable({ + __init = function(self, ...) + _class_0.__parent.__init(self, ...) + self.free_vars = { } + self.is_value = false + self.__str = nil + end, + __base = _base_0, + __name = "Lua", + __parent = _parent_0 + }, { + __index = function(cls, name) + local val = rawget(_base_0, name) + if val == nil then + local parent = rawget(cls, "__parent") + if parent then + return parent[name] + end + else + return val + end + end, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + local self = _class_0 + self.Value = function(...) + local lua = Lua(...) + lua.is_value = true + return lua + end + if _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + Lua = _class_0 +end +local Nomsu +do + local _class_0 + local _parent_0 = Code + local _base_0 = { + __tostring = function(self) + 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 + return self.__str + end, + __len = function(self) + return #tostring(self) + end, + parenthesize = function(self) + self:prepend("(") + return self:append(")") + end + } + _base_0.__index = _base_0 + setmetatable(_base_0, _parent_0.__base) + _class_0 = setmetatable({ + __init = function(self, ...) + return _class_0.__parent.__init(self, ...) + end, + __base = _base_0, + __name = "Nomsu", + __parent = _parent_0 + }, { + __index = function(cls, name) + local val = rawget(_base_0, name) + if val == nil then + local parent = rawget(cls, "__parent") + if parent then + return parent[name] + end + else + return val + end + end, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + if _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + Nomsu = _class_0 +end +return { + Code = Code, + Nomsu = Nomsu, + Lua = Lua, + Source = Source +} diff --git a/code_obj.moon b/code_obj.moon new file mode 100644 index 0000000..9df218c --- /dev/null +++ b/code_obj.moon @@ -0,0 +1,254 @@ +{:insert, :remove, :concat} = table +immutable = require 'immutable' +local Lua, Source +export LINE_STARTS + +Source = immutable {"filename","start","stop"}, { + name:"Source" + __new: (filename, start, stop)=> + if not start + start, stop = 1, #FILE_CACHE[filename] + if stop then assert(start <= stop, "Invalid range: #{start}, #{stop}") + return filename, start, stop + __tostring: => + if @stop + "\"#{@filename}[#{@start}:#{@stop}]\"" + else + "\"#{@filename}[#{@start}]\"" + __lt: (other)=> + assert(@filename == other.filename, "Cannot compare sources from different files") + return if @start == other.start + (@stop or @start) < (other.stop or other.start) + else @start < other.start + __le: (other)=> + assert(@filename == other.filename, "Cannot compare sources from different files") + return if @start == other.start + (@stop or @start) <= (other.stop or other.start) + else @start <= other.start + __add: (offset)=> + if type(self) == 'number' + offset, self = self, offset + else assert(type(offset) == 'number', "Cannot add Source and #{type(offset)}") + return Source(@filename, @start+offset, @stop) + sub: (start, stop)=> + start or= 1 + assert(start > 0 and (stop == nil or stop > 0), "Negative subscripts not supported") + if not @stop + assert(not stop, "cannot subscript non-range with range") + return Source(@filename, @start + start - 1) + else + stop or= @stop + return Source(@filename, @start + start - 1, @start + stop - 1) + get_text: => + FILE_CACHE[@filename]\sub(@start,@stop) + get_line_number: => + -- TODO: do a binary search if this is actually slow, which I doubt + src = FILE_CACHE[@filename] + line_starts = LINE_STARTS[src] + start_line = 1 + while (line_starts[start_line+1] or math.huge) <= @start + start_line += 1 + stop_line = start_line + while (line_starts[stop_line+1] or math.huge) <= @stop + stop_line += 1 + return start_line, stop_line + get_line: => "#{@filename}:#{@get_line_number!}" + get_line_range: => + start_line, stop_line = @get_line_number! + return if stop_line == start_line + "#{@filename}:#{start_line}" + else "#{@filename}:#{start_line}-#{stop_line}" +} + +class Code + new: (@source, ...)=> + @indents = {} + @bits = {...} + if type(@source) == 'string' + filename,start,stop = @source\match("^(.-)%[(%d+):(%d+)%]$") + unless filename + filename,start = @source\match("^(.-)%[(%d+)%]$") + if start or stop + @source = Source(filename, tonumber(start), tonumber(stop)) + else + @source = Source(@source, 1, #self+1) + assert(@source == nil or Source\is_instance(@source)) + indent = 0 + for i,b in ipairs @bits + assert(not Source\is_instance(b)) + if type(b) == 'string' + if spaces = b\match("\n([ ]*)[^\n]*$") + indent = #spaces + elseif indent != 0 + @indents[i] = indent + @current_indent = indent + @__str = nil + + sub: (start,stop)=> + -- TODO: implement this better + str = tostring(self)\sub(start,stop) + cls = @__class + return cls(@source\sub(start,stop), str) + + append: (...)=> + n = select("#",...) + bits = @bits + for i=1,n + b = select(i, ...) + assert(b != self, "No recursion please.") + bits[#bits+1] = b + if type(b) == 'string' + if spaces = b\match("\n([ ]*)[^\n]*$") + @current_indent = #spaces + elseif @current_indent != 0 + @indents[#bits] = @current_indent + @__str = nil + + prepend: (...)=> + n = select("#",...) + bits, indents = @bits, @indents + for i=#bits+n,n+1,-1 + bits[i] = bits[i-n] + for i=1,n + bits[i] = select(i, ...) + @current_indent = 0 + for i,b in ipairs(bits) + assert(b != self, "No recursion please.") + if type(b) == 'string' + if spaces = b\match("\n([ ]*)[^\n]*$") + @current_indent = #spaces + elseif @current_indent != 0 + indents[i] = @current_indent + else indents[i] = nil + @__str = nil + +class Lua extends Code + new: (...)=> + super ... + @free_vars = {} + @is_value = false + @__str = nil + + @Value = (...)-> + lua = Lua(...) + lua.is_value = true + return lua + + add_free_vars: (...)=> + seen = {[v]:true for v in *@free_vars} + for i=1,select("#",...) + var = select(i, ...) + if type(var) == 'userdata' and var.type == "Var" + var = tostring(var\as_lua!) + elseif type(var) != 'string' + var = tostring(var) + unless seen[var] + @free_vars[#@free_vars+1] = var + seen[var] = true + @__str = nil + + remove_free_vars: (...)=> + removals = {} + for i=1,select("#",...) + var = select(i, ...) + if type(var) == 'userdata' and var.type == "Var" + var = tostring(var\as_lua!) + elseif type(var) != 'string' + var = tostring(var) + removals[var] = true + + stack = {self} + while #stack > 0 + lua, stack[#stack] = stack[#stack], nil + for i=#lua.free_vars,1,-1 + if removals[lua.free_vars[i]] + remove lua.free_vars, i + for b in *lua.bits + if type(b) != 'string' + stack[#stack+1] = b + @__str = nil + + convert_to_statements: (prefix="", suffix=";")=> + unless @is_value + return + if prefix != "" + @prepend prefix + if suffix != "" + @append suffix + + declare_locals: (to_declare=nil)=> + if to_declare == nil + to_declare, seen = {}, {} + gather_from = => + for var in *@free_vars + unless seen[var] + seen[var] = true + to_declare[#to_declare+1] = var + for bit in *@bits + if bit.__class == Lua + gather_from bit + gather_from self + if #to_declare > 0 + @remove_free_vars unpack(to_declare) + @prepend "local #{concat to_declare, ", "};\n" + + __tostring: => + if @__str == nil + buff, indents = {}, @indents + for i,b in ipairs @bits + b = tostring(b) + if indents[i] + b = b\gsub("\n", "\n"..((" ")\rep(indents[i]))) + buff[#buff+1] = b + @__str = concat(buff, "") + return @__str + + __len: => + #tostring(self) + + make_offset_table: => + -- Return a mapping from output (lua) character number to input (nomsu) character number + lua_to_nomsu, nomsu_to_lua = {}, {} + walk = (lua, pos)-> + for b in *lua.bits + if type(b) == 'string' + if lua.source + lua_to_nomsu[pos] = lua.source.start + nomsu_to_lua[lua.source.start] = pos + else + walk b, pos + pos += #b + walk self, 1 + return { + nomsu_filename:@source.filename + lua_filename:tostring(@source)..".lua", lua_file:@stringify! + :lua_to_nomsu, :nomsu_to_lua + } + + parenthesize: => + if @is_value + @prepend "(" + @append ")" + else + error "Cannot parenthesize lua statements" + +class Nomsu extends Code + __tostring: => + if @__str == nil + buff, indents = {}, @indents + for i,b in ipairs @bits + b = tostring(b) + if indents[i] + b = b\gsub("\n", "\n"..((" ")\rep(indents[i]))) + buff[#buff+1] = b + @__str = concat(buff, "") + return @__str + + __len: => + #tostring(self) + + parenthesize: => + @prepend "(" + @append ")" + +return {:Code, :Nomsu, :Lua, :Source} diff --git a/lua_obj.lua b/lua_obj.lua deleted file mode 100644 index 4e7de9b..0000000 --- a/lua_obj.lua +++ /dev/null @@ -1,473 +0,0 @@ -local insert, remove, concat -do - local _obj_0 = table - insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat -end -local immutable = require('immutable') -local Lua, Source -Source = immutable({ - "filename", - "start", - "stop" -}, { - name = "Source", - __new = function(self, filename, start, stop) - if not start then - start, stop = 1, #FILE_CACHE[filename] - end - if stop then - assert(start <= stop, "Invalid range: " .. tostring(start) .. ", " .. tostring(stop)) - end - return filename, start, stop - end, - __tostring = function(self) - if self.stop then - return "\"" .. tostring(self.filename) .. "[" .. tostring(self.start) .. ":" .. tostring(self.stop) .. "]\"" - else - return "\"" .. tostring(self.filename) .. "[" .. tostring(self.start) .. "]\"" - end - end, - __lt = function(self, other) - assert(self.filename == other.filename, "Cannot compare sources from different files") - if self.start == other.start then - return (self.stop or self.start) < (other.stop or other.start) - else - return self.start < other.start - end - end, - __le = function(self, other) - assert(self.filename == other.filename, "Cannot compare sources from different files") - if self.start == other.start then - return (self.stop or self.start) <= (other.stop or other.start) - else - return self.start <= other.start - end - end, - __add = function(self, offset) - if type(self) == 'number' then - offset, self = self, offset - else - assert(type(offset) == 'number', "Cannot add Source and " .. tostring(type(offset))) - end - return Source(self.filename, self.start + offset, self.stop) - end, - sub = function(self, start, stop) - start = start or 1 - assert(start > 0 and (stop == nil or stop > 0), "Negative subscripts not supported") - if not self.stop then - assert(not stop, "cannot subscript non-range with range") - return Source(self.filename, self.start + start - 1) - else - stop = stop or self.stop - return Source(self.filename, self.start + start - 1, self.start + stop - 1) - end - end, - get_text = function(self) - return FILE_CACHE[self.filename]:sub(self.start, self.stop) - end, - get_line_number = function(self) - local src = FILE_CACHE[self.filename] - local line_starts = LINE_STARTS[src] - local start_line = 1 - while (line_starts[start_line + 1] or math.huge) <= self.start do - start_line = start_line + 1 - end - local stop_line = start_line - while (line_starts[stop_line + 1] or math.huge) <= self.stop do - stop_line = stop_line + 1 - end - return start_line, stop_line - end, - get_line = function(self) - return tostring(self.filename) .. ":" .. tostring(self:get_line_number()) - end, - get_line_range = function(self) - local start_line, stop_line = self:get_line_number() - if stop_line == start_line then - return tostring(self.filename) .. ":" .. tostring(start_line) - else - return tostring(self.filename) .. ":" .. tostring(start_line) .. "-" .. tostring(stop_line) - end - end -}) -local Code -do - local _class_0 - local _base_0 = { - sub = function(self, start, stop) - local str = tostring(self):sub(start, stop) - local cls = self.__class - return cls(self.source:sub(start, stop), str) - end, - append = function(self, ...) - local n = select("#", ...) - local bits = self.bits - for i = 1, n do - local b = select(i, ...) - assert(b ~= self, "No recursion please.") - 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, 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 - assert(b ~= self, "No recursion please.") - 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 = { - ... - } - if type(self.source) == 'string' then - local filename, start, stop = self.source:match("^(.-)%[(%d+):(%d+)%]$") - if not (filename) then - filename, start = self.source:match("^(.-)%[(%d+)%]$") - end - if start or stop then - self.source = Source(filename, tonumber(start), tonumber(stop)) - else - self.source = Source(self.source, 1, #self + 1) - end - end - assert(self.source == nil or Source:is_instance(self.source)) - 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" - }, { - __index = _base_0, - __call = function(cls, ...) - local _self_0 = setmetatable({}, _base_0) - cls.__init(_self_0, ...) - return _self_0 - end - }) - _base_0.__class = _class_0 - Code = _class_0 -end -do - local _class_0 - local _parent_0 = Code - local _base_0 = { - add_free_vars = function(self, ...) - local seen - do - local _tbl_0 = { } - local _list_0 = self.free_vars - for _index_0 = 1, #_list_0 do - local v = _list_0[_index_0] - local _key_0, _val_0 = { - [v] = true - } - _tbl_0[_key_0] = _val_0 - end - seen = _tbl_0 - end - for i = 1, select("#", ...) do - local var = select(i, ...) - if type(var) == 'userdata' and var.type == "Var" then - var = tostring(var:as_lua()) - elseif type(var) ~= 'string' then - var = tostring(var) - end - if not (seen[var]) then - self.free_vars[#self.free_vars + 1] = var - seen[var] = true - end - end - self.__str = nil - end, - remove_free_vars = function(self, ...) - local removals = { } - for i = 1, select("#", ...) do - local var = select(i, ...) - if type(var) == 'userdata' and var.type == "Var" then - var = tostring(var:as_lua()) - elseif type(var) ~= 'string' then - var = tostring(var) - end - removals[var] = true - end - local stack = { - self - } - while #stack > 0 do - local lua - lua, stack[#stack] = stack[#stack], nil - for i = #lua.free_vars, 1, -1 do - if removals[lua.free_vars[i]] then - remove(lua.free_vars, i) - end - end - local _list_0 = lua.bits - for _index_0 = 1, #_list_0 do - local b = _list_0[_index_0] - if type(b) ~= 'string' then - stack[#stack + 1] = b - end - end - end - self.__str = nil - end, - convert_to_statements = function(self, prefix, suffix) - if prefix == nil then - prefix = "" - end - if suffix == nil then - suffix = ";" - end - if not (self.is_value) then - return - end - if prefix ~= "" then - self:prepend(prefix) - end - if suffix ~= "" then - return self:append(suffix) - end - end, - declare_locals = function(self, to_declare) - if to_declare == nil then - to_declare = nil - end - if to_declare == nil then - local seen - to_declare, seen = { }, { } - local gather_from - gather_from = function(self) - local _list_0 = self.free_vars - for _index_0 = 1, #_list_0 do - local var = _list_0[_index_0] - if not (seen[var]) then - seen[var] = true - to_declare[#to_declare + 1] = var - end - end - local _list_1 = self.bits - for _index_0 = 1, #_list_1 do - local bit = _list_1[_index_0] - if bit.__class == Lua then - gather_from(bit) - end - end - end - gather_from(self) - end - if #to_declare > 0 then - self:remove_free_vars(unpack(to_declare)) - return self:prepend("local " .. tostring(concat(to_declare, ", ")) .. ";\n") - end - end, - __tostring = function(self) - 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 - return self.__str - end, - __len = function(self) - return #tostring(self) - end, - make_offset_table = function(self) - local lua_to_nomsu, nomsu_to_lua = { }, { } - local walk - walk = function(lua, pos) - local _list_0 = lua.bits - for _index_0 = 1, #_list_0 do - local b = _list_0[_index_0] - if type(b) == 'string' then - if lua.source then - lua_to_nomsu[pos] = lua.source.start - nomsu_to_lua[lua.source.start] = pos - end - else - walk(b, pos) - end - pos = pos + #b - end - end - walk(self, 1) - return { - nomsu_filename = self.source.filename, - lua_filename = tostring(self.source) .. ".lua", - lua_file = self:stringify(), - lua_to_nomsu = lua_to_nomsu, - nomsu_to_lua = nomsu_to_lua - } - end, - parenthesize = function(self) - if self.is_value then - self:prepend("(") - return self:append(")") - else - return error("Cannot parenthesize lua statements") - end - end - } - _base_0.__index = _base_0 - setmetatable(_base_0, _parent_0.__base) - _class_0 = setmetatable({ - __init = function(self, ...) - _class_0.__parent.__init(self, ...) - self.free_vars = { } - self.is_value = false - self.__str = nil - end, - __base = _base_0, - __name = "Lua", - __parent = _parent_0 - }, { - __index = function(cls, name) - local val = rawget(_base_0, name) - if val == nil then - local parent = rawget(cls, "__parent") - if parent then - return parent[name] - end - else - return val - end - end, - __call = function(cls, ...) - local _self_0 = setmetatable({}, _base_0) - cls.__init(_self_0, ...) - return _self_0 - end - }) - _base_0.__class = _class_0 - local self = _class_0 - self.Value = function(...) - local lua = Lua(...) - lua.is_value = true - return lua - end - if _parent_0.__inherited then - _parent_0.__inherited(_parent_0, _class_0) - end - Lua = _class_0 -end -local Nomsu -do - local _class_0 - local _parent_0 = Code - local _base_0 = { - __tostring = function(self) - 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 - return self.__str - end, - __len = function(self) - return #tostring(self) - end, - parenthesize = function(self) - self:prepend("(") - return self:append(")") - end - } - _base_0.__index = _base_0 - setmetatable(_base_0, _parent_0.__base) - _class_0 = setmetatable({ - __init = function(self, ...) - return _class_0.__parent.__init(self, ...) - end, - __base = _base_0, - __name = "Nomsu", - __parent = _parent_0 - }, { - __index = function(cls, name) - local val = rawget(_base_0, name) - if val == nil then - local parent = rawget(cls, "__parent") - if parent then - return parent[name] - end - else - return val - end - end, - __call = function(cls, ...) - local _self_0 = setmetatable({}, _base_0) - cls.__init(_self_0, ...) - return _self_0 - end - }) - _base_0.__class = _class_0 - if _parent_0.__inherited then - _parent_0.__inherited(_parent_0, _class_0) - end - Nomsu = _class_0 -end -return { - Code = Code, - Nomsu = Nomsu, - Lua = Lua, - Source = Source -} diff --git a/lua_obj.moon b/lua_obj.moon deleted file mode 100644 index 9df218c..0000000 --- a/lua_obj.moon +++ /dev/null @@ -1,254 +0,0 @@ -{:insert, :remove, :concat} = table -immutable = require 'immutable' -local Lua, Source -export LINE_STARTS - -Source = immutable {"filename","start","stop"}, { - name:"Source" - __new: (filename, start, stop)=> - if not start - start, stop = 1, #FILE_CACHE[filename] - if stop then assert(start <= stop, "Invalid range: #{start}, #{stop}") - return filename, start, stop - __tostring: => - if @stop - "\"#{@filename}[#{@start}:#{@stop}]\"" - else - "\"#{@filename}[#{@start}]\"" - __lt: (other)=> - assert(@filename == other.filename, "Cannot compare sources from different files") - return if @start == other.start - (@stop or @start) < (other.stop or other.start) - else @start < other.start - __le: (other)=> - assert(@filename == other.filename, "Cannot compare sources from different files") - return if @start == other.start - (@stop or @start) <= (other.stop or other.start) - else @start <= other.start - __add: (offset)=> - if type(self) == 'number' - offset, self = self, offset - else assert(type(offset) == 'number', "Cannot add Source and #{type(offset)}") - return Source(@filename, @start+offset, @stop) - sub: (start, stop)=> - start or= 1 - assert(start > 0 and (stop == nil or stop > 0), "Negative subscripts not supported") - if not @stop - assert(not stop, "cannot subscript non-range with range") - return Source(@filename, @start + start - 1) - else - stop or= @stop - return Source(@filename, @start + start - 1, @start + stop - 1) - get_text: => - FILE_CACHE[@filename]\sub(@start,@stop) - get_line_number: => - -- TODO: do a binary search if this is actually slow, which I doubt - src = FILE_CACHE[@filename] - line_starts = LINE_STARTS[src] - start_line = 1 - while (line_starts[start_line+1] or math.huge) <= @start - start_line += 1 - stop_line = start_line - while (line_starts[stop_line+1] or math.huge) <= @stop - stop_line += 1 - return start_line, stop_line - get_line: => "#{@filename}:#{@get_line_number!}" - get_line_range: => - start_line, stop_line = @get_line_number! - return if stop_line == start_line - "#{@filename}:#{start_line}" - else "#{@filename}:#{start_line}-#{stop_line}" -} - -class Code - new: (@source, ...)=> - @indents = {} - @bits = {...} - if type(@source) == 'string' - filename,start,stop = @source\match("^(.-)%[(%d+):(%d+)%]$") - unless filename - filename,start = @source\match("^(.-)%[(%d+)%]$") - if start or stop - @source = Source(filename, tonumber(start), tonumber(stop)) - else - @source = Source(@source, 1, #self+1) - assert(@source == nil or Source\is_instance(@source)) - indent = 0 - for i,b in ipairs @bits - assert(not Source\is_instance(b)) - if type(b) == 'string' - if spaces = b\match("\n([ ]*)[^\n]*$") - indent = #spaces - elseif indent != 0 - @indents[i] = indent - @current_indent = indent - @__str = nil - - sub: (start,stop)=> - -- TODO: implement this better - str = tostring(self)\sub(start,stop) - cls = @__class - return cls(@source\sub(start,stop), str) - - append: (...)=> - n = select("#",...) - bits = @bits - for i=1,n - b = select(i, ...) - assert(b != self, "No recursion please.") - bits[#bits+1] = b - if type(b) == 'string' - if spaces = b\match("\n([ ]*)[^\n]*$") - @current_indent = #spaces - elseif @current_indent != 0 - @indents[#bits] = @current_indent - @__str = nil - - prepend: (...)=> - n = select("#",...) - bits, indents = @bits, @indents - for i=#bits+n,n+1,-1 - bits[i] = bits[i-n] - for i=1,n - bits[i] = select(i, ...) - @current_indent = 0 - for i,b in ipairs(bits) - assert(b != self, "No recursion please.") - if type(b) == 'string' - if spaces = b\match("\n([ ]*)[^\n]*$") - @current_indent = #spaces - elseif @current_indent != 0 - indents[i] = @current_indent - else indents[i] = nil - @__str = nil - -class Lua extends Code - new: (...)=> - super ... - @free_vars = {} - @is_value = false - @__str = nil - - @Value = (...)-> - lua = Lua(...) - lua.is_value = true - return lua - - add_free_vars: (...)=> - seen = {[v]:true for v in *@free_vars} - for i=1,select("#",...) - var = select(i, ...) - if type(var) == 'userdata' and var.type == "Var" - var = tostring(var\as_lua!) - elseif type(var) != 'string' - var = tostring(var) - unless seen[var] - @free_vars[#@free_vars+1] = var - seen[var] = true - @__str = nil - - remove_free_vars: (...)=> - removals = {} - for i=1,select("#",...) - var = select(i, ...) - if type(var) == 'userdata' and var.type == "Var" - var = tostring(var\as_lua!) - elseif type(var) != 'string' - var = tostring(var) - removals[var] = true - - stack = {self} - while #stack > 0 - lua, stack[#stack] = stack[#stack], nil - for i=#lua.free_vars,1,-1 - if removals[lua.free_vars[i]] - remove lua.free_vars, i - for b in *lua.bits - if type(b) != 'string' - stack[#stack+1] = b - @__str = nil - - convert_to_statements: (prefix="", suffix=";")=> - unless @is_value - return - if prefix != "" - @prepend prefix - if suffix != "" - @append suffix - - declare_locals: (to_declare=nil)=> - if to_declare == nil - to_declare, seen = {}, {} - gather_from = => - for var in *@free_vars - unless seen[var] - seen[var] = true - to_declare[#to_declare+1] = var - for bit in *@bits - if bit.__class == Lua - gather_from bit - gather_from self - if #to_declare > 0 - @remove_free_vars unpack(to_declare) - @prepend "local #{concat to_declare, ", "};\n" - - __tostring: => - if @__str == nil - buff, indents = {}, @indents - for i,b in ipairs @bits - b = tostring(b) - if indents[i] - b = b\gsub("\n", "\n"..((" ")\rep(indents[i]))) - buff[#buff+1] = b - @__str = concat(buff, "") - return @__str - - __len: => - #tostring(self) - - make_offset_table: => - -- Return a mapping from output (lua) character number to input (nomsu) character number - lua_to_nomsu, nomsu_to_lua = {}, {} - walk = (lua, pos)-> - for b in *lua.bits - if type(b) == 'string' - if lua.source - lua_to_nomsu[pos] = lua.source.start - nomsu_to_lua[lua.source.start] = pos - else - walk b, pos - pos += #b - walk self, 1 - return { - nomsu_filename:@source.filename - lua_filename:tostring(@source)..".lua", lua_file:@stringify! - :lua_to_nomsu, :nomsu_to_lua - } - - parenthesize: => - if @is_value - @prepend "(" - @append ")" - else - error "Cannot parenthesize lua statements" - -class Nomsu extends Code - __tostring: => - if @__str == nil - buff, indents = {}, @indents - for i,b in ipairs @bits - b = tostring(b) - if indents[i] - b = b\gsub("\n", "\n"..((" ")\rep(indents[i]))) - buff[#buff+1] = b - @__str = concat(buff, "") - return @__str - - __len: => - #tostring(self) - - parenthesize: => - @prepend "(" - @append ")" - -return {:Code, :Nomsu, :Lua, :Source} -- cgit v1.2.3