aboutsummaryrefslogtreecommitdiff
path: root/code_obj.lua
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-04-25 17:56:18 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-04-25 17:56:26 -0700
commit4892c63e92bf82386b4ebb54a5a1dd76dcd792f8 (patch)
treef0c80a1a9416f537a9606640694309711cea9649 /code_obj.lua
parent4e821308af654706b8bda5f3d00dce7a933d9942 (diff)
Renamed lua_obj -> code_obj
Diffstat (limited to 'code_obj.lua')
-rw-r--r--code_obj.lua473
1 files changed, 473 insertions, 0 deletions
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
+}