package.preload['moonscript.base'] = function() _G.moon_no_loader = true return require("moonscript") end package.preload['moonscript.compile.statement'] = function() local util = require("moonscript.util") local data = require("moonscript.data") local reversed, unpack = util.reversed, util.unpack local ntype do local _table_0 = require("moonscript.types") ntype = _table_0.ntype end local concat, insert = table.concat, table.insert local statement_compilers = { raw = function(self, node) return self:add(node[2]) end, lines = function(self, node) local _list_0 = node[2] for _index_0 = 1, #_list_0 do local line = _list_0[_index_0] self:add(line) end end, declare = function(self, node) local names = node[2] local undeclared = self:declare(names) if #undeclared > 0 then do local _with_0 = self:line("local ") _with_0:append_list((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = undeclared for _index_0 = 1, #_list_0 do local name = _list_0[_index_0] _accum_0[_len_0] = self:name(name) _len_0 = _len_0 + 1 end return _accum_0 end)(), ", ") return _with_0 end end end, declare_with_shadows = function(self, node) local names = node[2] self:declare(names) do local _with_0 = self:line("local ") _with_0:append_list((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = names for _index_0 = 1, #_list_0 do local name = _list_0[_index_0] _accum_0[_len_0] = self:name(name) _len_0 = _len_0 + 1 end return _accum_0 end)(), ", ") return _with_0 end end, assign = function(self, node) local _, names, values = unpack(node) local undeclared = self:declare(names) local declare = "local " .. concat(undeclared, ", ") local has_fndef = false local i = 1 while i <= #values do if ntype(values[i]) == "fndef" then has_fndef = true end i = i + 1 end do local _with_0 = self:line() if #undeclared == #names and not has_fndef then _with_0:append(declare) else if #undeclared > 0 then self:add(declare) end _with_0:append_list((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = names for _index_0 = 1, #_list_0 do local name = _list_0[_index_0] _accum_0[_len_0] = self:value(name) _len_0 = _len_0 + 1 end return _accum_0 end)(), ", ") end _with_0:append(" = ") _with_0:append_list((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = values for _index_0 = 1, #_list_0 do local v = _list_0[_index_0] _accum_0[_len_0] = self:value(v) _len_0 = _len_0 + 1 end return _accum_0 end)(), ", ") return _with_0 end end, ["return"] = function(self, node) return self:line("return ", (function() if node[2] ~= "" then return self:value(node[2]) end end)()) end, ["break"] = function(self, node) return "break" end, ["if"] = function(self, node) local cond, block = node[2], node[3] local root do local _with_0 = self:block(self:line("if ", self:value(cond), " then")) _with_0:stms(block) root = _with_0 end local current = root local add_clause add_clause = function(clause) local type = clause[1] local i = 2 local next if type == "else" then next = self:block("else") else i = i + 1 next = self:block(self:line("elseif ", self:value(clause[2]), " then")) end next:stms(clause[i]) current.next = next current = next end local _list_0 = node for _index_0 = 4, #_list_0 do cond = _list_0[_index_0] add_clause(cond) end return root end, ["repeat"] = function(self, node) local cond, block = unpack(node, 2) do local _with_0 = self:block("repeat", self:line("until ", self:value(cond))) _with_0:stms(block) return _with_0 end end, ["while"] = function(self, node) local _, cond, block = unpack(node) do local _with_0 = self:block(self:line("while ", self:value(cond), " do")) _with_0:stms(block) return _with_0 end end, ["for"] = function(self, node) local _, name, bounds, block = unpack(node) local loop = self:line("for ", self:name(name), " = ", self:value({ "explist", unpack(bounds) }), " do") do local _with_0 = self:block(loop) _with_0:declare({ name }) _with_0:stms(block) return _with_0 end end, foreach = function(self, node) local _, names, exps, block = unpack(node) local loop do local _with_0 = self:line() _with_0:append("for ") loop = _with_0 end do local _with_0 = self:block(loop) loop:append_list((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = names for _index_0 = 1, #_list_0 do local name = _list_0[_index_0] _accum_0[_len_0] = _with_0:name(name, false) _len_0 = _len_0 + 1 end return _accum_0 end)(), ", ") loop:append(" in ") loop:append_list((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = exps for _index_0 = 1, #_list_0 do local exp = _list_0[_index_0] _accum_0[_len_0] = self:value(exp) _len_0 = _len_0 + 1 end return _accum_0 end)(), ",") loop:append(" do") _with_0:declare(names) _with_0:stms(block) return _with_0 end end, export = function(self, node) local _, names = unpack(node) if type(names) == "string" then if names == "*" then self.export_all = true elseif names == "^" then self.export_proper = true end else self:declare(names) end return nil end, run = function(self, code) code:call(self) return nil end, group = function(self, node) return self:stms(node[2]) end, ["do"] = function(self, node) do local _with_0 = self:block() _with_0:stms(node[2]) return _with_0 end end } return { statement_compilers = statement_compilers } end package.preload['moonscript.compile.value'] = function() local util = require("moonscript.util") local data = require("moonscript.data") local ntype do local _table_0 = require("moonscript.types") ntype = _table_0.ntype end local user_error do local _table_0 = require("moonscript.errors") user_error = _table_0.user_error end local concat, insert = table.concat, table.insert local unpack = util.unpack local table_delim = "," local string_chars = { ["\r"] = "\\r", ["\n"] = "\\n" } local value_compilers = { exp = function(self, node) local _comp _comp = function(i, value) if i % 2 == 1 and value == "!=" then value = "~=" end return self:value(value) end do local _with_0 = self:line() _with_0:append_list((function() local _accum_0 = { } local _len_0 = 1 for i, v in ipairs(node) do if i > 1 then _accum_0[_len_0] = _comp(i, v) _len_0 = _len_0 + 1 end end return _accum_0 end)(), " ") return _with_0 end end, explist = function(self, node) do local _with_0 = self:line() _with_0:append_list((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = node for _index_0 = 2, #_list_0 do local v = _list_0[_index_0] _accum_0[_len_0] = self:value(v) _len_0 = _len_0 + 1 end return _accum_0 end)(), ", ") return _with_0 end end, parens = function(self, node) return self:line("(", self:value(node[2]), ")") end, string = function(self, node) local _, delim, inner = unpack(node) local end_delim = delim:gsub("%[", "]") if delim == "'" or delim == '"' then inner = inner:gsub("[\r\n]", string_chars) end return delim .. inner .. end_delim end, chain = function(self, node) local callee = node[2] if callee == -1 then callee = self:get("scope_var") if not callee then user_error("Short-dot syntax must be called within a with block") end end local sup = self:get("super") if callee == "super" and sup then return self:value(sup(self, node)) end local chain_item chain_item = function(node) local t, arg = unpack(node) if t == "call" then return "(", self:values(arg), ")" elseif t == "index" then return "[", self:value(arg), "]" elseif t == "dot" then return ".", tostring(arg) elseif t == "colon" then return ":", arg, chain_item(node[3]) elseif t == "colon_stub" then return user_error("Uncalled colon stub") else return error("Unknown chain action: " .. t) end end local t = ntype(callee) if (t == "self" or t == "self_class") and node[3] and ntype(node[3]) == "call" then callee[1] = t .. "_colon" end local callee_value = self:value(callee) if ntype(callee) == "exp" then callee_value = self:line("(", callee_value, ")") end local actions do local _with_0 = self:line() local _list_0 = node for _index_0 = 3, #_list_0 do local action = _list_0[_index_0] _with_0:append(chain_item(action)) end actions = _with_0 end return self:line(callee_value, actions) end, fndef = function(self, node) local _, args, whitelist, arrow, block = unpack(node) local default_args = { } local self_args = { } local arg_names = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = args for _index_0 = 1, #_list_0 do local arg = _list_0[_index_0] local name, default_value = unpack(arg) if type(name) == "string" then name = name else if name[1] == "self" or name[1] == "self_class" then insert(self_args, name) end name = name[2] end if default_value then insert(default_args, arg) end local _value_0 = name _accum_0[_len_0] = _value_0 _len_0 = _len_0 + 1 end return _accum_0 end)() if arrow == "fat" then insert(arg_names, 1, "self") end do local _with_0 = self:block() if #whitelist > 0 then _with_0:whitelist_names(whitelist) end local _list_0 = arg_names for _index_0 = 1, #_list_0 do local name = _list_0[_index_0] _with_0:put_name(name) end local _list_1 = default_args for _index_0 = 1, #_list_1 do local default = _list_1[_index_0] local name, value = unpack(default) if type(name) == "table" then name = name[2] end _with_0:stm({ 'if', { 'exp', name, '==', 'nil' }, { { 'assign', { name }, { value } } } }) end local self_arg_values = (function() local _accum_0 = { } local _len_0 = 1 local _list_2 = self_args for _index_0 = 1, #_list_2 do local arg = _list_2[_index_0] _accum_0[_len_0] = arg[2] _len_0 = _len_0 + 1 end return _accum_0 end)() if #self_args > 0 then _with_0:stm({ "assign", self_args, self_arg_values }) end _with_0:stms(block) if #args > #arg_names then arg_names = (function() local _accum_0 = { } local _len_0 = 1 local _list_2 = args for _index_0 = 1, #_list_2 do local arg = _list_2[_index_0] _accum_0[_len_0] = arg[1] _len_0 = _len_0 + 1 end return _accum_0 end)() end _with_0.header = "function(" .. concat(arg_names, ", ") .. ")" return _with_0 end end, table = function(self, node) local _, items = unpack(node) do local _with_0 = self:block("{", "}") local format_line format_line = function(tuple) if #tuple == 2 then local key, value = unpack(tuple) if ntype(key) == "key_literal" and data.lua_keywords[key[2]] then key = { "string", '"', key[2] } end local assign if ntype(key) == "key_literal" then assign = key[2] else assign = self:line("[", _with_0:value(key), "]") end _with_0:set("current_block", key) local out = self:line(assign, " = ", _with_0:value(value)) _with_0:set("current_block", nil) return out else return self:line(_with_0:value(tuple[1])) end end if items then local count = #items for i, tuple in ipairs(items) do local line = format_line(tuple) if not (count == i) then line:append(table_delim) end _with_0:add(line) end end return _with_0 end end, minus = function(self, node) return self:line("-", self:value(node[2])) end, temp_name = function(self, node, ...) return node:get_name(self, ...) end, number = function(self, node) return node[2] end, length = function(self, node) return self:line("#", self:value(node[2])) end, ["not"] = function(self, node) return self:line("not ", self:value(node[2])) end, self = function(self, node) return "self." .. self:value(node[2]) end, self_class = function(self, node) return "self.__class." .. self:value(node[2]) end, self_colon = function(self, node) return "self:" .. self:value(node[2]) end, self_class_colon = function(self, node) return "self.__class:" .. self:value(node[2]) end, raw_value = function(self, value) local sup = self:get("super") if value == "super" and sup then return self:value(sup(self)) end if value == "..." then self:send("varargs") end return tostring(value) end } return { value_compilers = value_compilers } end package.preload['moonscript.compile'] = function() local util = require("moonscript.util") local dump = require("moonscript.dump") local transform = require("moonscript.transform") local NameProxy, LocalName do local _table_0 = require("moonscript.transform.names") NameProxy, LocalName = _table_0.NameProxy, _table_0.LocalName end local Set do local _table_0 = require("moonscript.data") Set = _table_0.Set end local ntype, has_value do local _table_0 = require("moonscript.types") ntype, has_value = _table_0.ntype, _table_0.has_value end local statement_compilers do local _table_0 = require("moonscript.compile.statement") statement_compilers = _table_0.statement_compilers end local value_compilers do local _table_0 = require("moonscript.compile.value") value_compilers = _table_0.value_compilers end local concat, insert = table.concat, table.insert local pos_to_line, get_closest_line, trim, unpack = util.pos_to_line, util.get_closest_line, util.trim, util.unpack local mtype = util.moon.type local indent_char = " " local Line, DelayedLine, Lines, Block, RootBlock do local _parent_0 = nil local _base_0 = { mark_pos = function(self, pos, line) if line == nil then line = #self end if not (self.posmap[line]) then self.posmap[line] = pos end end, add = function(self, item) local _exp_0 = mtype(item) if Line == _exp_0 then item:render(self) elseif Block == _exp_0 then item:render(self) else self[#self + 1] = item end return self end, flatten_posmap = function(self, line_no, out) if line_no == nil then line_no = 0 end if out == nil then out = { } end local posmap = self.posmap for i, l in ipairs(self) do local _exp_0 = mtype(l) if "string" == _exp_0 or DelayedLine == _exp_0 then line_no = line_no + 1 out[line_no] = posmap[i] elseif Lines == _exp_0 then local _ _, line_no = l:flatten_posmap(line_no, out) else error("Unknown item in Lines: " .. tostring(l)) end end return out, line_no end, flatten = function(self, indent, buffer) if indent == nil then indent = nil end if buffer == nil then buffer = { } end for i = 1, #self do local l = self[i] local t = mtype(l) if t == DelayedLine then l = l:render() t = "string" end local _exp_0 = t if "string" == _exp_0 then if indent then insert(buffer, indent) end insert(buffer, l) if "string" == type(self[i + 1]) then local lc = l:sub(-1) if (lc == ")" or lc == "]") and self[i + 1]:sub(1, 1) == "(" then insert(buffer, ";") end end insert(buffer, "\n") local last = l elseif Lines == _exp_0 then l:flatten(indent and indent .. indent_char or indent_char, buffer) else error("Unknown item in Lines: " .. tostring(l)) end end return buffer end, __tostring = function(self) local strip strip = function(t) if "table" == type(t) then return (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = t for _index_0 = 1, #_list_0 do local v = _list_0[_index_0] _accum_0[_len_0] = strip(v) _len_0 = _len_0 + 1 end return _accum_0 end)() else return t end end return "Lines<" .. tostring(util.dump(strip(self)):sub(1, -2)) .. ">" end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self) self.posmap = { } end, __base = _base_0, __name = "Lines", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end Lines = _class_0 end do local _parent_0 = nil local _base_0 = { pos = nil, _append_single = function(self, item) if Line == mtype(item) then if not (self.pos) then self.pos = item.pos end local _list_0 = item for _index_0 = 1, #_list_0 do local value = _list_0[_index_0] self:_append_single(value) end else insert(self, item) end return nil end, append_list = function(self, items, delim) for i = 1, #items do self:_append_single(items[i]) if i < #items then insert(self, delim) end end return nil end, append = function(self, ...) local _list_0 = { ... } for _index_0 = 1, #_list_0 do local item = _list_0[_index_0] self:_append_single(item) end return nil end, render = function(self, buffer) local current = { } local add_current add_current = function() buffer:add(concat(current)) return buffer:mark_pos(self.pos) end local _list_0 = self for _index_0 = 1, #_list_0 do local chunk = _list_0[_index_0] local _exp_0 = mtype(chunk) if Block == _exp_0 then local _list_1 = chunk:render(Lines()) for _index_1 = 1, #_list_1 do local block_chunk = _list_1[_index_1] if "string" == type(block_chunk) then insert(current, block_chunk) else add_current() buffer:add(block_chunk) current = { } end end else insert(current, chunk) end end if #current > 0 then add_current() end return buffer end, __tostring = function(self) return "Line<" .. tostring(util.dump(self):sub(1, -2)) .. ">" end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, ...) if _parent_0 then return _parent_0.__init(self, ...) end end, __base = _base_0, __name = "Line", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end Line = _class_0 end do local _parent_0 = nil local _base_0 = { prepare = function() end, render = function(self) self:prepare() return concat(self) end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, fn) self.prepare = fn end, __base = _base_0, __name = "DelayedLine", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end DelayedLine = _class_0 end do local _parent_0 = nil local _base_0 = { header = "do", footer = "end", export_all = false, export_proper = false, __tostring = function(self) local h if "string" == type(self.header) then h = self.header else h = unpack(self.header:render({ })) end return "Block<" .. tostring(h) .. "> <- " .. tostring(self.parent) end, set = function(self, name, value) self._state[name] = value end, get = function(self, name) return self._state[name] end, get_current = function(self, name) return rawget(self._state, name) end, listen = function(self, name, fn) self._listeners[name] = fn end, unlisten = function(self, name) self._listeners[name] = nil end, send = function(self, name, ...) do local fn = self._listeners[name] if fn then return fn(self, ...) end end end, declare = function(self, names) local undeclared = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = names for _index_0 = 1, #_list_0 do local _continue_0 = false repeat local name = _list_0[_index_0] local is_local = false local real_name local _exp_0 = mtype(name) if LocalName == _exp_0 then is_local = true real_name = name:get_name(self) elseif NameProxy == _exp_0 then real_name = name:get_name(self) elseif "string" == _exp_0 then real_name = name end if not (is_local or real_name and not self:has_name(real_name, true)) then _continue_0 = true break end self:put_name(real_name) if self:name_exported(real_name) then _continue_0 = true break end local _value_0 = real_name _accum_0[_len_0] = _value_0 _len_0 = _len_0 + 1 _continue_0 = true until true if not _continue_0 then break end end return _accum_0 end)() return undeclared end, whitelist_names = function(self, names) self._name_whitelist = Set(names) end, name_exported = function(self, name) if self.export_all then return true end if self.export_proper and name:match("^%u") then return true end end, put_name = function(self, name, ...) local value = ... if select("#", ...) == 0 then value = true end if NameProxy == mtype(name) then name = name:get_name(self) end self._names[name] = value end, has_name = function(self, name, skip_exports) if not skip_exports and self:name_exported(name) then return true end local yes = self._names[name] if yes == nil and self.parent then if not self._name_whitelist or self._name_whitelist[name] then return self.parent:has_name(name, true) end else return yes end end, free_name = function(self, prefix, dont_put) prefix = prefix or "moon" local searching = true local name, i = nil, 0 while searching do name = concat({ "", prefix, i }, "_") i = i + 1 searching = self:has_name(name, true) end if not dont_put then self:put_name(name) end return name end, init_free_var = function(self, prefix, value) local name = self:free_name(prefix, true) self:stm({ "assign", { name }, { value } }) return name end, add = function(self, item) self._lines:add(item) return item end, render = function(self, buffer) buffer:add(self.header) buffer:mark_pos(self.pos) if self.next then buffer:add(self._lines) self.next:render(buffer) else if #self._lines == 0 and "string" == type(buffer[#buffer]) then buffer[#buffer] = buffer[#buffer] .. (" " .. (unpack(Lines():add(self.footer)))) else buffer:add(self._lines) buffer:add(self.footer) buffer:mark_pos(self.pos) end end return buffer end, block = function(self, header, footer) return Block(self, header, footer) end, line = function(self, ...) do local _with_0 = Line() _with_0:append(...) return _with_0 end end, is_stm = function(self, node) return statement_compilers[ntype(node)] ~= nil end, is_value = function(self, node) local t = ntype(node) return value_compilers[t] ~= nil or t == "value" end, name = function(self, node, ...) return self:value(node, ...) end, value = function(self, node, ...) node = self.transform.value(node) local action if type(node) ~= "table" then action = "raw_value" else action = node[1] end local fn = value_compilers[action] if not fn then error("Failed to compile value: " .. dump.value(node)) end local out = fn(self, node, ...) if type(node) == "table" and node[-1] then if type(out) == "string" then do local _with_0 = Line() _with_0:append(out) out = _with_0 end end out.pos = node[-1] end return out end, values = function(self, values, delim) delim = delim or ', ' do local _with_0 = Line() _with_0:append_list((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = values for _index_0 = 1, #_list_0 do local v = _list_0[_index_0] _accum_0[_len_0] = self:value(v) _len_0 = _len_0 + 1 end return _accum_0 end)(), delim) return _with_0 end end, stm = function(self, node, ...) if not node then return end node = self.transform.statement(node) local result do local fn = statement_compilers[ntype(node)] if fn then result = fn(self, node, ...) else if has_value(node) then result = self:stm({ "assign", { "_" }, { node } }) else result = self:value(node) end end end if result then if type(node) == "table" and type(result) == "table" and node[-1] then result.pos = node[-1] end self:add(result) end return nil end, stms = function(self, stms, ret) if ret then error("deprecated stms call, use transformer") end local current_stms, current_stm_i do local _obj_0 = self current_stms, current_stm_i = _obj_0.current_stms, _obj_0.current_stm_i end self.current_stms = stms for i = 1, #stms do self.current_stm_i = i self:stm(stms[i]) end self.current_stms = current_stms self.current_stm_i = current_stm_i return nil end, splice = function(self, fn) local lines = { "lines", self._lines } self._lines = Lines() return self:stms(fn(lines)) end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, parent, header, footer) self.parent, self.header, self.footer = parent, header, footer self._lines = Lines() self._names = { } self._state = { } self._listeners = { } do local _with_0 = transform self.transform = { value = _with_0.Value:bind(self), statement = _with_0.Statement:bind(self) } end if self.parent then self.root = self.parent.root self.indent = self.parent.indent + 1 setmetatable(self._state, { __index = self.parent._state }) return setmetatable(self._listeners, { __index = self.parent._listeners }) else self.indent = 0 end end, __base = _base_0, __name = "Block", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end Block = _class_0 end do local _parent_0 = Block local _base_0 = { __tostring = function(self) return "RootBlock<>" end, root_stms = function(self, stms) if not (self.options.implicitly_return_root == false) then stms = transform.Statement.transformers.root_stms(self, stms) end return self:stms(stms) end, render = function(self) local buffer = self._lines:flatten() if buffer[#buffer] == "\n" then buffer[#buffer] = nil end return table.concat(buffer) end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, options) self.options = options self.root = self return _parent_0.__init(self) end, __base = _base_0, __name = "RootBlock", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end RootBlock = _class_0 end local format_error format_error = function(msg, pos, file_str) local line = pos_to_line(file_str, pos) local line_str line_str, line = get_closest_line(file_str, line) line_str = line_str or "" return concat({ "Compile error: " .. msg, (" [%d] >> %s"):format(line, trim(line_str)) }, "\n") end local value value = function(value) local out = nil do local _with_0 = RootBlock() _with_0:add(_with_0:value(value)) out = _with_0:render() end return out end local tree tree = function(tree, options) if options == nil then options = { } end assert(tree, "missing tree") local scope = (options.scope or RootBlock)(options) local runner = coroutine.create(function() return scope:root_stms(tree) end) local success, err = coroutine.resume(runner) if not success then local error_msg if type(err) == "table" then local error_type = err[1] if error_type == "user-error" then error_msg = err[2] else error_msg = error("Unknown error thrown", util.dump(error_msg)) end else error_msg = concat({ err, debug.traceback(runner) }, "\n") end return nil, error_msg, scope.last_pos else local lua_code = scope:render() local posmap = scope._lines:flatten_posmap() return lua_code, posmap end end do local _with_0 = require("moonscript.data") local data = _with_0 for name, cls in pairs({ Line = Line, Lines = Lines, DelayedLine = DelayedLine }) do data[name] = cls end end return { tree = tree, value = value, format_error = format_error, Block = Block, RootBlock = RootBlock } end package.preload['moonscript.data'] = function() local concat, remove, insert = table.concat, table.remove, table.insert local Set Set = function(items) local self = { } local _list_0 = items for _index_0 = 1, #_list_0 do local key = _list_0[_index_0] self[key] = true end return self end local Stack do local _parent_0 = nil local _base_0 = { __tostring = function(self) return "" end, pop = function(self) return remove(self) end, push = function(self, value) insert(self, value) return value end, top = function(self) return self[#self] end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, ...) local _list_0 = { ... } for _index_0 = 1, #_list_0 do local v = _list_0[_index_0] self:push(v) end return nil end, __base = _base_0, __name = "Stack", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end Stack = _class_0 end local lua_keywords = Set({ 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while' }) return { Set = Set, Stack = Stack, lua_keywords = lua_keywords } end package.preload['moonscript.dump'] = function() local flat_value flat_value = function(op, depth) if depth == nil then depth = 1 end if type(op) == "string" then return '"' .. op .. '"' end if type(op) ~= "table" then return tostring(op) end local items = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = op for _index_0 = 1, #_list_0 do local item = _list_0[_index_0] _accum_0[_len_0] = flat_value(item, depth + 1) _len_0 = _len_0 + 1 end return _accum_0 end)() local pos = op[-1] return "{" .. (pos and "[" .. pos .. "] " or "") .. table.concat(items, ", ") .. "}" end local value value = function(op) return flat_value(op) end local tree tree = function(block) local _list_0 = block for _index_0 = 1, #_list_0 do value = _list_0[_index_0] print(flat_value(value)) end end return { value = value, tree = tree } end package.preload['moonscript.errors'] = function() local util = require("moonscript.util") local lpeg = require("lpeg") local concat, insert = table.concat, table.insert local split, pos_to_line = util.split, util.pos_to_line local user_error user_error = function(...) return error({ "user-error", ... }) end local lookup_line lookup_line = function(fname, pos, cache) if not cache[fname] then do local _with_0 = io.open(fname) cache[fname] = _with_0:read("*a") _with_0:close() end end return pos_to_line(cache[fname], pos) end local reverse_line_number reverse_line_number = function(fname, line_table, line_num, cache) for i = line_num, 0, -1 do if line_table[i] then return lookup_line(fname, line_table[i], cache) end end return "unknown" end local truncate_traceback truncate_traceback = function(traceback, chunk_func) if chunk_func == nil then chunk_func = "moonscript_chunk" end traceback = split(traceback, "\n") local stop = #traceback while stop > 1 do if traceback[stop]:match(chunk_func) then break end stop = stop - 1 end traceback = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = traceback local _max_0 = stop for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do local t = _list_0[_index_0] _accum_0[_len_0] = t _len_0 = _len_0 + 1 end return _accum_0 end)() local rep = "function '" .. chunk_func .. "'" traceback[#traceback] = traceback[#traceback]:gsub(rep, "main chunk") return concat(traceback, "\n") end local rewrite_traceback rewrite_traceback = function(text, err) local line_tables = require("moonscript.line_tables") local V, S, Ct, C = lpeg.V, lpeg.S, lpeg.Ct, lpeg.C local header_text = "stack traceback:" local Header, Line = V("Header"), V("Line") local Break = lpeg.S("\n") local g = lpeg.P({ Header, Header = header_text * Break * Ct(Line ^ 1), Line = "\t" * C((1 - Break) ^ 0) * (Break + -1) }) local cache = { } local rewrite_single rewrite_single = function(trace) local fname, line, msg = trace:match('^%[string "(.-)"]:(%d+): (.*)$') local tbl = line_tables[fname] if fname and tbl then return concat({ fname, ":", reverse_line_number(fname, tbl, line, cache), ": ", "(", line, ") ", msg }) else return trace end end err = rewrite_single(err) local match = g:match(text) if not (match) then return nil end for i, trace in ipairs(match) do match[i] = rewrite_single(trace) end return concat({ "moon: " .. err, header_text, "\t" .. concat(match, "\n\t") }, "\n") end return { rewrite_traceback = rewrite_traceback, truncate_traceback = truncate_traceback, user_error = user_error } end package.preload['moonscript'] = function() local compile = require("moonscript.compile") local parse = require("moonscript.parse") local concat, insert = table.concat, table.insert local split, dump, get_options, unpack do local _table_0 = require("moonscript.util") split, dump, get_options, unpack = _table_0.split, _table_0.dump, _table_0.get_options, _table_0.unpack end local lua = { loadstring = loadstring, load = load } local dirsep, line_tables, create_moonpath, to_lua, moon_loader, init_loader, loadstring, loadfile, dofile dirsep = "/" line_tables = require("moonscript.line_tables") create_moonpath = function(package_path) local paths = split(package_path, ";") for i, path in ipairs(paths) do local p = path:match("^(.-)%.lua$") if p then paths[i] = p .. ".moon" end end return concat(paths, ";") end to_lua = function(text, options) if options == nil then options = { } end if "string" ~= type(text) then local t = type(text) return nil, "expecting string (got " .. t .. ")", 2 end local tree, err = parse.string(text) if not tree then return nil, err end local code, ltable, pos = compile.tree(tree, options) if not code then return nil, compile.format_error(ltable, pos, text), 2 end return code, ltable end moon_loader = function(name) local name_path = name:gsub("%.", dirsep) local file, file_path local _list_0 = split(package.moonpath, ";") for _index_0 = 1, #_list_0 do local path = _list_0[_index_0] file_path = path:gsub("?", name_path) file = io.open(file_path) if file then break end end if file then local text = file:read("*a") file:close() return loadstring(text, file_path) else return nil, "Could not find moon file" end end if not package.moonpath then package.moonpath = create_moonpath(package.path) end init_loader = function() return insert(package.loaders or package.searchers, 2, moon_loader) end if not (_G.moon_no_loader) then init_loader() end loadstring = function(...) local options, str, chunk_name, mode, env = get_options(...) chunk_name = chunk_name or "=(moonscript.loadstring)" local code, ltable_or_err = to_lua(str, options) if not (code) then return nil, ltable_or_err end if chunk_name then line_tables[chunk_name] = ltable_or_err end return (lua.loadstring or lua.load)(code, chunk_name, unpack({ mode, env })) end loadfile = function(fname, ...) local file, err = io.open(fname) if not (file) then return nil, err end local text = assert(file:read("*a")) file:close() return loadstring(text, fname, ...) end dofile = function(...) local f = assert(loadfile(...)) return f() end return { _NAME = "moonscript", to_lua = to_lua, moon_chunk = moon_chunk, moon_loader = moon_loader, dirsep = dirsep, dofile = dofile, loadfile = loadfile, loadstring = loadstring } end package.preload['moonscript.line_tables'] = function() return { } end package.preload['moonscript.parse'] = function() local util = require"moonscript.util" local lpeg = require"lpeg" local debug_grammar = false local data = require"moonscript.data" local types = require"moonscript.types" local ntype = types.ntype local dump = util.dump local trim = util.trim local getfenv = util.getfenv local setfenv = util.setfenv local unpack = util.unpack local Stack = data.Stack local function count_indent(str) local sum = 0 for v in str:gmatch("[\t ]") do if v == ' ' then sum = sum + 1 end if v == '\t' then sum = sum + 4 end end return sum end local R, S, V, P = lpeg.R, lpeg.S, lpeg.V, lpeg.P local C, Ct, Cmt, Cg, Cb, Cc = lpeg.C, lpeg.Ct, lpeg.Cmt, lpeg.Cg, lpeg.Cb, lpeg.Cc lpeg.setmaxstack(10000) local White = S" \t\r\n"^0 local _Space = S" \t"^0 local Break = P"\r"^-1 * P"\n" local Stop = Break + -1 local Indent = C(S"\t "^0) / count_indent local Comment = P"--" * (1 - S"\r\n")^0 * #Stop local Space = _Space * Comment^-1 local SomeSpace = S" \t"^1 * Comment^-1 local SpaceBreak = Space * Break local EmptyLine = SpaceBreak local AlphaNum = R("az", "AZ", "09", "__") local _Name = C(R("az", "AZ", "__") * AlphaNum^0) local Name = Space * _Name local Num = P"0x" * R("09", "af", "AF")^1 + ( R"09"^1 * (P"." * R"09"^1)^-1 + P"." * R"09"^1 ) * (S"eE" * P"-"^-1 * R"09"^1)^-1 Num = Space * (Num / function(value) return {"number", value} end) local FactorOp = Space * C(S"+-") local TermOp = Space * C(S"*/%^") local Shebang = P"#!" * P(1 - Stop)^0 -- can't have P(false) because it causes preceding patterns not to run local Cut = P(function() return false end) local function ensure(patt, finally) return patt * finally + finally * Cut end -- auto declare Proper variables with lpeg.V local function wrap_env(fn) local env = getfenv(fn) local wrap_name = V if debug_grammar then local indent = 0 local indent_char = " " local function iprint(...) local args = {...} for i=1,#args do args[i] = tostring(args[i]) end io.stdout:write(indent_char:rep(indent) .. table.concat(args, ", ") .. "\n") end wrap_name = function(name) local v = V(name) v = Cmt("", function() iprint("* " .. name) indent = indent + 1 return true end) * Cmt(v, function(str, pos, ...) iprint(name, true) indent = indent - 1 return true, ... end) + Cmt("", function() iprint(name, false) indent = indent - 1 return false end) return v end end return setfenv(fn, setmetatable({}, { __index = function(self, name) local value = env[name] if value ~= nil then return value end if name:match"^[A-Z][A-Za-z0-9]*$" then local v = wrap_name(name) rawset(self, name, v) return v end error("unknown variable referenced: "..name) end })) end local function extract_line(str, start_pos) str = str:sub(start_pos) m = str:match"^(.-)\n" if m then return m end return str:match"^.-$" end local function mark(name) return function(...) return {name, ...} end end local function insert_pos(pos, value) if type(value) == "table" then value[-1] = pos end return value end local function pos(patt) return (lpeg.Cp() * patt) / insert_pos end local function got(what) return Cmt("", function(str, pos, ...) local cap = {...} print("++ got "..what, "["..extract_line(str, pos).."]") return true end) end local function flatten(tbl) if #tbl == 1 then return tbl[1] end return tbl end local function flatten_or_mark(name) return function(tbl) if #tbl == 1 then return tbl[1] end table.insert(tbl, 1, name) return tbl end end -- makes sure the last item in a chain is an index local _chain_assignable = { index = true, dot = true, slice = true } local function is_assignable(node) local t = ntype(node) return t == "self" or t == "value" or t == "self_class" or t == "chain" and _chain_assignable[ntype(node[#node])] or t == "table" end local function check_assignable(str, pos, value) if is_assignable(value) then return true, value end return false end local flatten_explist = flatten_or_mark"explist" local function format_assign(lhs_exps, assign) if not assign then return flatten_explist(lhs_exps) end for _, assign_exp in ipairs(lhs_exps) do if not is_assignable(assign_exp) then error {assign_exp, "left hand expression is not assignable"} end end local t = ntype(assign) if t == "assign" then return {"assign", lhs_exps, unpack(assign, 2)} elseif t == "update" then return {"update", lhs_exps[1], unpack(assign, 2)} end error "unknown assign expression" end -- the if statement only takes a single lhs, so we wrap in table to git to -- "assign" tuple format local function format_single_assign(lhs, assign) if assign then return format_assign({lhs}, assign) end return lhs end local function sym(chars) return Space * chars end local function symx(chars) return chars end local function simple_string(delim, allow_interpolation) local inner = P('\\'..delim) + "\\\\" + (1 - P(delim)) if allow_interpolation then inter = symx"#{" * V"Exp" * sym"}" inner = (C((inner - inter)^1) + inter / mark"interpolate")^0 else inner = C(inner^0) end return C(symx(delim)) * inner * sym(delim) / mark"string" end local function wrap_func_arg(value) return {"call", {value}} end -- DOCME local function flatten_func(callee, args) if #args == 0 then return callee end args = {"call", args} if ntype(callee) == "chain" then -- check for colon stub that needs arguments if ntype(callee[#callee]) == "colon_stub" then local stub = callee[#callee] stub[1] = "colon" table.insert(stub, args) else table.insert(callee, args) end return callee end return {"chain", callee, args} end local function flatten_string_chain(str, chain, args) if not chain then return str end return flatten_func({"chain", str, unpack(chain)}, args) end -- transforms a statement that has a line decorator local function wrap_decorator(stm, dec) if not dec then return stm end return { "decorated", stm, dec } end -- wrap if statement if there is a conditional decorator local function wrap_if(stm, cond) if cond then local pass, fail = unpack(cond) if fail then fail = {"else", {fail}} end return {"if", cond[2], {stm}, fail} end return stm end local function check_lua_string(str, pos, right, left) return #left == #right end -- :name in table literal local function self_assign(name) return {{"key_literal", name}, name} end local err_msg = "Failed to parse:%s\n [%d] >> %s" local build_grammar = wrap_env(function() local _indent = Stack(0) -- current indent local _do_stack = Stack(0) local last_pos = 0 -- used to know where to report error local function check_indent(str, pos, indent) last_pos = pos return _indent:top() == indent end local function advance_indent(str, pos, indent) local top = _indent:top() if top ~= -1 and indent > _indent:top() then _indent:push(indent) return true end end local function push_indent(str, pos, indent) _indent:push(indent) return true end local function pop_indent(str, pos) if not _indent:pop() then error("unexpected outdent") end return true end local function check_do(str, pos, do_node) local top = _do_stack:top() if top == nil or top then return true, do_node end return false end local function disable_do(str_pos) _do_stack:push(false) return true end local function enable_do(str_pos) _do_stack:push(true) return true end local function pop_do(str, pos) if nil == _do_stack:pop() then error("unexpected do pop") end return true end local DisableDo = Cmt("", disable_do) local EnableDo = Cmt("", enable_do) local PopDo = Cmt("", pop_do) local keywords = {} local function key(chars) keywords[chars] = true return Space * chars * -AlphaNum end local function op(word) local patt = Space * C(word) if word:match("^%w*$") then keywords[word] = true patt = patt * -AlphaNum end return patt end -- make sure name is not a keyword local Name = Cmt(Name, function(str, pos, name) if keywords[name] then return false end return true end) / trim local SelfName = Space * "@" * ( "@" * (_Name / mark"self_class" + Cc"self.__class") + _Name / mark"self" + Cc"self") local KeyName = SelfName + Space * _Name / mark"key_literal" local Name = SelfName + Name + Space * "..." / trim local g = lpeg.P{ File, File = Shebang^-1 * (Block + Ct""), Block = Ct(Line * (Break^1 * Line)^0), CheckIndent = Cmt(Indent, check_indent), -- validates line is in correct indent Line = (CheckIndent * Statement + Space * #Stop), Statement = pos( Import + While + With + For + ForEach + Switch + Return + Local + Export + BreakLoop + Ct(ExpList) * (Update + Assign)^-1 / format_assign ) * Space * (( -- statement decorators key"if" * Exp * (key"else" * Exp)^-1 * Space / mark"if" + key"unless" * Exp / mark"unless" + CompInner / mark"comprehension" ) * Space)^-1 / wrap_decorator, Body = Space^-1 * Break * EmptyLine^0 * InBlock + Ct(Statement), -- either a statement, or an indented block Advance = #Cmt(Indent, advance_indent), -- Advances the indent, gives back whitespace for CheckIndent PushIndent = Cmt(Indent, push_indent), PreventIndent = Cmt(Cc(-1), push_indent), PopIndent = Cmt("", pop_indent), InBlock = Advance * Block * PopIndent, Local = key"local" * ((op"*" + op"^") / mark"declare_glob" + Ct(NameList) / mark"declare_with_shadows"), Import = key"import" * Ct(ImportNameList) * key"from" * Exp / mark"import", ImportName = (sym"\\" * Ct(Cc"colon_stub" * Name) + Name), ImportNameList = ImportName * (sym"," * ImportName)^0, NameList = Name * (sym"," * Name)^0, BreakLoop = Ct(key"break"/trim) + Ct(key"continue"/trim), Return = key"return" * (ExpListLow/mark"explist" + C"") / mark"return", WithExp = Ct(ExpList) * Assign^-1 / format_assign, With = key"with" * DisableDo * ensure(WithExp, PopDo) * key"do"^-1 * Body / mark"with", Switch = key"switch" * DisableDo * ensure(Exp, PopDo) * key"do"^-1 * Space^-1 * Break * SwitchBlock / mark"switch", SwitchBlock = EmptyLine^0 * Advance * Ct(SwitchCase * (Break^1 * SwitchCase)^0 * (Break^1 * SwitchElse)^-1) * PopIndent, SwitchCase = key"when" * Ct(ExpList) * key"then"^-1 * Body / mark"case", SwitchElse = key"else" * Body / mark"else", IfCond = Exp * Assign^-1 / format_single_assign, If = key"if" * IfCond * key"then"^-1 * Body * ((Break * CheckIndent)^-1 * EmptyLine^0 * key"elseif" * pos(IfCond) * key"then"^-1 * Body / mark"elseif")^0 * ((Break * CheckIndent)^-1 * EmptyLine^0 * key"else" * Body / mark"else")^-1 / mark"if", Unless = key"unless" * IfCond * key"then"^-1 * Body * ((Break * CheckIndent)^-1 * EmptyLine^0 * key"else" * Body / mark"else")^-1 / mark"unless", While = key"while" * DisableDo * ensure(Exp, PopDo) * key"do"^-1 * Body / mark"while", For = key"for" * DisableDo * ensure(Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1), PopDo) * key"do"^-1 * Body / mark"for", ForEach = key"for" * Ct(AssignableNameList) * key"in" * DisableDo * ensure(Ct(sym"*" * Exp / mark"unpack" + ExpList), PopDo) * key"do"^-1 * Body / mark"foreach", Do = key"do" * Body / mark"do", Comprehension = sym"[" * Exp * CompInner * sym"]" / mark"comprehension", TblComprehension = sym"{" * Ct(Exp * (sym"," * Exp)^-1) * CompInner * sym"}" / mark"tblcomprehension", CompInner = Ct((CompForEach + CompFor) * CompClause^0), CompForEach = key"for" * Ct(NameList) * key"in" * (sym"*" * Exp / mark"unpack" + Exp) / mark"foreach", CompFor = key "for" * Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1) / mark"for", CompClause = CompFor + CompForEach + key"when" * Exp / mark"when", Assign = sym"=" * (Ct(With + If + Switch) + Ct(TableBlock + ExpListLow)) / mark"assign", Update = ((sym"..=" + sym"+=" + sym"-=" + sym"*=" + sym"/=" + sym"%=" + sym"or=" + sym"and=") / trim) * Exp / mark"update", -- we can ignore precedence for now OtherOps = op"or" + op"and" + op"<=" + op">=" + op"~=" + op"!=" + op"==" + op".." + op"<" + op">", Assignable = Cmt(DotChain + Chain, check_assignable) + Name, AssignableList = Assignable * (sym"," * Assignable)^0, Exp = Ct(Value * ((OtherOps + FactorOp + TermOp) * Value)^0) / flatten_or_mark"exp", -- Exp = Ct(Factor * (OtherOps * Factor)^0) / flatten_or_mark"exp", -- Factor = Ct(Term * (FactorOp * Term)^0) / flatten_or_mark"exp", -- Term = Ct(Value * (TermOp * Value)^0) / flatten_or_mark"exp", SimpleValue = If + Unless + Switch + With + ClassDecl + ForEach + For + While + Cmt(Do, check_do) + sym"-" * -SomeSpace * Exp / mark"minus" + sym"#" * Exp / mark"length" + key"not" * Exp / mark"not" + TblComprehension + TableLit + Comprehension + FunLit + Num, ChainValue = -- a function call or an object access StringChain + ((Chain + DotChain + Callable) * Ct(InvokeArgs^-1)) / flatten_func, Value = pos( SimpleValue + Ct(KeyValueList) / mark"table" + ChainValue), SliceValue = SimpleValue + ChainValue, StringChain = String * (Ct((ColonCall + ColonSuffix) * ChainTail^-1) * Ct(InvokeArgs^-1))^-1 / flatten_string_chain, String = Space * DoubleString + Space * SingleString + LuaString, SingleString = simple_string("'"), DoubleString = simple_string('"', true), LuaString = Cg(LuaStringOpen, "string_open") * Cb"string_open" * Break^-1 * C((1 - Cmt(C(LuaStringClose) * Cb"string_open", check_lua_string))^0) * LuaStringClose / mark"string", LuaStringOpen = sym"[" * P"="^0 * "[" / trim, LuaStringClose = "]" * P"="^0 * "]", Callable = Name + Parens / mark"parens", Parens = sym"(" * Exp * sym")", FnArgs = symx"(" * Ct(ExpList^-1) * sym")" + sym"!" * -P"=" * Ct"", ChainTail = ChainItem^1 * ColonSuffix^-1 + ColonSuffix, -- a list of funcalls and indexes on a callable Chain = Callable * ChainTail / mark"chain", -- shorthand dot call for use in with statement DotChain = (sym"." * Cc(-1) * (_Name / mark"dot") * ChainTail^-1) / mark"chain" + (sym"\\" * Cc(-1) * ( (_Name * Invoke / mark"colon") * ChainTail^-1 + (_Name / mark"colon_stub") )) / mark"chain", ChainItem = Invoke + Slice + symx"[" * Exp/mark"index" * sym"]" + symx"." * _Name/mark"dot" + ColonCall, Slice = symx"[" * (SliceValue + Cc(1)) * sym"," * (SliceValue + Cc"") * (sym"," * SliceValue)^-1 *sym"]" / mark"slice", ColonCall = symx"\\" * (_Name * Invoke) / mark"colon", ColonSuffix = symx"\\" * _Name / mark"colon_stub", Invoke = FnArgs/mark"call" + SingleString / wrap_func_arg + DoubleString / wrap_func_arg, TableValue = KeyValue + Ct(Exp), TableLit = sym"{" * Ct( TableValueList^-1 * sym","^-1 * (SpaceBreak * TableLitLine * (sym","^-1 * SpaceBreak * TableLitLine)^0 * sym","^-1)^-1 ) * White * sym"}" / mark"table", TableValueList = TableValue * (sym"," * TableValue)^0, TableLitLine = PushIndent * ((TableValueList * PopIndent) + (PopIndent * Cut)) + Space, -- the unbounded table TableBlockInner = Ct(KeyValueLine * (SpaceBreak^1 * KeyValueLine)^0), TableBlock = SpaceBreak^1 * Advance * ensure(TableBlockInner, PopIndent) / mark"table", ClassDecl = key"class" * -P":" * (Assignable + Cc(nil)) * (key"extends" * PreventIndent * ensure(Exp, PopIndent) + C"")^-1 * (ClassBlock + Ct("")) / mark"class", ClassBlock = SpaceBreak^1 * Advance * Ct(ClassLine * (SpaceBreak^1 * ClassLine)^0) * PopIndent, ClassLine = CheckIndent * (( KeyValueList / mark"props" + Statement / mark"stm" + Exp / mark"stm" ) * sym","^-1), Export = key"export" * ( Cc"class" * ClassDecl + op"*" + op"^" + Ct(NameList) * (sym"=" * Ct(ExpListLow))^-1) / mark"export", KeyValue = (sym":" * Name) / self_assign + Ct((KeyName + sym"[" * Exp * sym"]" + DoubleString + SingleString) * symx":" * (Exp + TableBlock)), KeyValueList = KeyValue * (sym"," * KeyValue)^0, KeyValueLine = CheckIndent * KeyValueList * sym","^-1, FnArgsDef = sym"(" * Ct(FnArgDefList^-1) * (key"using" * Ct(NameList + Space * "nil") + Ct"") * sym")" + Ct"" * Ct"", FnArgDefList = FnArgDef * (sym"," * FnArgDef)^0, FnArgDef = Ct(Name * (sym"=" * Exp)^-1), FunLit = FnArgsDef * (sym"->" * Cc"slim" + sym"=>" * Cc"fat") * (Body + Ct"") / mark"fndef", NameList = Name * (sym"," * Name)^0, NameOrDestructure = Name + TableLit, AssignableNameList = NameOrDestructure * (sym"," * NameOrDestructure)^0, ExpList = Exp * (sym"," * Exp)^0, ExpListLow = Exp * ((sym"," + sym";") * Exp)^0, InvokeArgs = -P"-" * (ExpList * (sym"," * (TableBlock + SpaceBreak * Advance * ArgBlock * TableBlock^-1) + TableBlock)^-1 + TableBlock), ArgBlock = ArgLine * (sym"," * SpaceBreak * ArgLine)^0 * PopIndent, ArgLine = CheckIndent * ExpList } return { _g = White * g * White * -1, match = function(self, str, ...) local pos_to_line = function(pos) return util.pos_to_line(str, pos) end local get_line = function(num) return util.get_line(str, num) end local tree local pass, err = pcall(function(...) tree = self._g:match(str, ...) end, ...) -- regular error, let it bubble up if type(err) == "string" then error(err) end if not tree then local pos = last_pos local msg if err then local node node, msg = unpack(err) msg = msg and " " .. msg pos = node[-1] end local line_no = pos_to_line(pos) local line_str = get_line(line_no) or "" return nil, err_msg:format(msg or "", line_no, trim(line_str)) end return tree end } end) return { extract_line = extract_line, -- parse a string -- returns tree, or nil and error message string = function (str) local g = build_grammar() return g:match(str) end } end package.preload['moonscript.transform.destructure'] = function() local ntype, mtype, build do local _table_0 = require("moonscript.types") ntype, mtype, build = _table_0.ntype, _table_0.mtype, _table_0.build end local NameProxy do local _table_0 = require("moonscript.transform.names") NameProxy = _table_0.NameProxy end local insert = table.insert local unpack do local _table_0 = require("moonscript.util") unpack = _table_0.unpack end local user_error do local _table_0 = require("moonscript.errors") user_error = _table_0.user_error end local join join = function(...) do local _with_0 = { } local out = _with_0 local i = 1 local _list_0 = { ... } for _index_0 = 1, #_list_0 do local tbl = _list_0[_index_0] local _list_1 = tbl for _index_1 = 1, #_list_1 do local v = _list_1[_index_1] out[i] = v i = i + 1 end end return _with_0 end end local has_destructure has_destructure = function(names) local _list_0 = names for _index_0 = 1, #_list_0 do local n = _list_0[_index_0] if ntype(n) == "table" then return true end end return false end local extract_assign_names extract_assign_names = function(name, accum, prefix) if accum == nil then accum = { } end if prefix == nil then prefix = { } end local i = 1 local _list_0 = name[2] for _index_0 = 1, #_list_0 do local tuple = _list_0[_index_0] local value, suffix if #tuple == 1 then local s = { "index", { "number", i } } i = i + 1 value, suffix = tuple[1], s else local key = tuple[1] local s if ntype(key) == "key_literal" then s = { "dot", key[2] } else s = { "index", key } end value, suffix = tuple[2], s end suffix = join(prefix, { suffix }) local t = ntype(value) if t == "value" or t == "chain" or t == "self" then insert(accum, { value, suffix }) elseif t == "table" then extract_assign_names(value, accum, suffix) else user_error("Can't destructure value of type: " .. tostring(ntype(value))) end end return accum end local build_assign build_assign = function(destruct_literal, receiver) local extracted_names = extract_assign_names(destruct_literal) local names = { } local values = { } local inner = { "assign", names, values } local obj if mtype(receiver) == NameProxy then obj = receiver else do local _with_0 = NameProxy("obj") obj = _with_0 inner = build["do"]({ build.assign_one(obj, receiver), { "assign", names, values } }) obj = _with_0 end end local _list_0 = extracted_names for _index_0 = 1, #_list_0 do local tuple = _list_0[_index_0] insert(names, tuple[1]) insert(values, obj:chain(unpack(tuple[2]))) end return build.group({ { "declare", names }, inner }) end local split_assign split_assign = function(assign) local names, values = unpack(assign, 2) local g = { } local total_names = #names local total_values = #values local start = 1 for i, n in ipairs(names) do if ntype(n) == "table" then if i > start then local stop = i - 1 insert(g, { "assign", (function() local _accum_0 = { } local _len_0 = 1 for i = start, stop do _accum_0[_len_0] = names[i] _len_0 = _len_0 + 1 end return _accum_0 end)(), (function() local _accum_0 = { } local _len_0 = 1 for i = start, stop do _accum_0[_len_0] = values[i] _len_0 = _len_0 + 1 end return _accum_0 end)() }) end insert(g, build_assign(n, values[i])) start = i + 1 end end if total_names >= start or total_values >= start then local name_slice if total_names < start then name_slice = { "_" } else name_slice = (function() local _accum_0 = { } local _len_0 = 1 for i = start, total_names do _accum_0[_len_0] = names[i] _len_0 = _len_0 + 1 end return _accum_0 end)() end local value_slice if total_values < start then value_slice = { "nil" } else value_slice = (function() local _accum_0 = { } local _len_0 = 1 for i = start, total_values do _accum_0[_len_0] = values[i] _len_0 = _len_0 + 1 end return _accum_0 end)() end insert(g, { "assign", name_slice, value_slice }) end return build.group(g) end return { has_destructure = has_destructure, split_assign = split_assign, build_assign = build_assign } end package.preload['moonscript.transform.names'] = function() local build do local _table_0 = require("moonscript.types") build = _table_0.build end local unpack do local _table_0 = require("moonscript.util") unpack = _table_0.unpack end local LocalName do local _parent_0 = nil local _base_0 = { get_name = function(self) return self.name end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, name) self.name = name self[1] = "temp_name" end, __base = _base_0, __name = "LocalName", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end LocalName = _class_0 end local NameProxy do local _parent_0 = nil local _base_0 = { get_name = function(self, scope, dont_put) if dont_put == nil then dont_put = true end if not self.name then self.name = scope:free_name(self.prefix, dont_put) end return self.name end, chain = function(self, ...) local items = (function(...) local _accum_0 = { } local _len_0 = 1 local _list_0 = { ... } for _index_0 = 1, #_list_0 do local i = _list_0[_index_0] if type(i) == "string" then _accum_0[_len_0] = { "dot", i } else _accum_0[_len_0] = i end _len_0 = _len_0 + 1 end return _accum_0 end)(...) return build.chain({ base = self, unpack(items) }) end, index = function(self, key) return build.chain({ base = self, { "index", key } }) end, __tostring = function(self) if self.name then return ("name<%s>"):format(self.name) else return ("name"):format(self.prefix) end end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, prefix) self.prefix = prefix self[1] = "temp_name" end, __base = _base_0, __name = "NameProxy", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end NameProxy = _class_0 end return { NameProxy = NameProxy, LocalName = LocalName } end package.preload['moonscript.transform'] = function() local types = require("moonscript.types") local util = require("moonscript.util") local data = require("moonscript.data") local reversed, unpack = util.reversed, util.unpack local ntype, mtype, build, smart_node, is_slice, value_is_singular = types.ntype, types.mtype, types.build, types.smart_node, types.is_slice, types.value_is_singular local insert = table.insert local NameProxy, LocalName do local _table_0 = require("moonscript.transform.names") NameProxy, LocalName = _table_0.NameProxy, _table_0.LocalName end local destructure = require("moonscript.transform.destructure") local implicitly_return local Run do local _parent_0 = nil local _base_0 = { call = function(self, state) return self.fn(state) end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, fn) self.fn = fn self[1] = "run" end, __base = _base_0, __name = "Run", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end Run = _class_0 end local apply_to_last apply_to_last = function(stms, fn) local last_exp_id = 0 for i = #stms, 1, -1 do local stm = stms[i] if stm and mtype(stm) ~= Run then last_exp_id = i break end end return (function() local _accum_0 = { } local _len_0 = 1 for i, stm in ipairs(stms) do if i == last_exp_id then _accum_0[_len_0] = fn(stm) else _accum_0[_len_0] = stm end _len_0 = _len_0 + 1 end return _accum_0 end)() end local is_singular is_singular = function(body) if #body ~= 1 then return false end if "group" == ntype(body) then return is_singular(body[2]) else return body[1] end end local extract_declarations extract_declarations = function(self, body, start, out) if body == nil then body = self.current_stms end if start == nil then start = self.current_stm_i + 1 end if out == nil then out = { } end for i = start, #body do local _continue_0 = false repeat local stm = body[i] if stm == nil then _continue_0 = true break end stm = self.transform.statement(stm) body[i] = stm local _exp_0 = stm[1] if "assign" == _exp_0 or "declare" == _exp_0 then local _list_0 = stm[2] for _index_0 = 1, #_list_0 do local name = _list_0[_index_0] if type(name) == "string" then insert(out, name) end end elseif "group" == _exp_0 then extract_declarations(self, stm[2], 1, out) end _continue_0 = true until true if not _continue_0 then break end end return out end local expand_elseif_assign expand_elseif_assign = function(ifstm) for i = 4, #ifstm do local case = ifstm[i] if ntype(case) == "elseif" and ntype(case[2]) == "assign" then local split = { unpack(ifstm, 1, i - 1) } insert(split, { "else", { { "if", case[2], case[3], unpack(ifstm, i + 1) } } }) return split end end return ifstm end local constructor_name = "new" local with_continue_listener with_continue_listener = function(body) local continue_name = nil return { Run(function(self) return self:listen("continue", function() if not (continue_name) then continue_name = NameProxy("continue") self:put_name(continue_name) end return continue_name end) end), build.group(body), Run(function(self) if not (continue_name) then return end self:put_name(continue_name, nil) return self:splice(function(lines) return { { "assign", { continue_name }, { "false" } }, { "repeat", "true", { lines, { "assign", { continue_name }, { "true" } } } }, { "if", { "not", continue_name }, { { "break" } } } } end) end) } end local Transformer do local _parent_0 = nil local _base_0 = { transform = function(self, scope, node, ...) if self.seen_nodes[node] then return node end self.seen_nodes[node] = true while true do local transformer = self.transformers[ntype(node)] local res if transformer then res = transformer(scope, node, ...) or node else res = node end if res == node then return node end node = res end return node end, bind = function(self, scope) return function(...) return self:transform(scope, ...) end end, __call = function(self, ...) return self:transform(...) end, can_transform = function(self, node) return self.transformers[ntype(node)] ~= nil end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self, transformers) self.transformers = transformers self.seen_nodes = setmetatable({ }, { __mode = "k" }) end, __base = _base_0, __name = "Transformer", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end Transformer = _class_0 end local construct_comprehension construct_comprehension = function(inner, clauses) local current_stms = inner for _, clause in reversed(clauses) do local t = clause[1] local _exp_0 = t if "for" == _exp_0 then local name, bounds do local _obj_0 = clause _, name, bounds = _obj_0[1], _obj_0[2], _obj_0[3] end current_stms = { "for", name, bounds, current_stms } elseif "foreach" == _exp_0 then local names, iter do local _obj_0 = clause _, names, iter = _obj_0[1], _obj_0[2], _obj_0[3] end current_stms = { "foreach", names, { iter }, current_stms } elseif "when" == _exp_0 then local cond do local _obj_0 = clause _, cond = _obj_0[1], _obj_0[2] end current_stms = { "if", cond, current_stms } else current_stms = error("Unknown comprehension clause: " .. t) end current_stms = { current_stms } end return current_stms[1] end local Statement = Transformer({ root_stms = function(self, body) return apply_to_last(body, implicitly_return(self)) end, declare_glob = function(self, node) local names = extract_declarations(self) if node[2] == "^" then names = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = names for _index_0 = 1, #_list_0 do local _continue_0 = false repeat local name = _list_0[_index_0] if not (name:match("^%u")) then _continue_0 = true break end local _value_0 = name _accum_0[_len_0] = _value_0 _len_0 = _len_0 + 1 _continue_0 = true until true if not _continue_0 then break end end return _accum_0 end)() end return { "declare", names } end, assign = function(self, node) local names, values = unpack(node, 2) local transformed if #values == 1 then local value = values[1] local t = ntype(value) if t == "decorated" then value = self.transform.statement(value) t = ntype(value) end if types.cascading[t] then local ret ret = function(stm) if types.is_value(stm) then return { "assign", names, { stm } } else return stm end end transformed = build.group({ { "declare", names }, self.transform.statement(value, ret, node) }) end end node = transformed or node if destructure.has_destructure(names) then return destructure.split_assign(node) end return node end, continue = function(self, node) local continue_name = self:send("continue") if not (continue_name) then error("continue must be inside of a loop") end return build.group({ build.assign_one(continue_name, "true"), { "break" } }) end, export = function(self, node) if #node > 2 then if node[2] == "class" then local cls = smart_node(node[3]) return build.group({ { "export", { cls.name } }, cls }) else return build.group({ node, build.assign({ names = node[2], values = node[3] }) }) end else return nil end end, update = function(self, node) local _, name, op, exp = unpack(node) local op_final = op:match("^(.+)=$") if not op_final then error("Unknown op: " .. op) end if not (value_is_singular(exp)) then exp = { "parens", exp } end return build.assign_one(name, { "exp", name, op_final, exp }) end, import = function(self, node) local _, names, source = unpack(node) local stubs = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = names for _index_0 = 1, #_list_0 do local name = _list_0[_index_0] if type(name) == "table" then _accum_0[_len_0] = name else _accum_0[_len_0] = { "dot", name } end _len_0 = _len_0 + 1 end return _accum_0 end)() local real_names = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = names for _index_0 = 1, #_list_0 do local name = _list_0[_index_0] _accum_0[_len_0] = type(name) == "table" and name[2] or name _len_0 = _len_0 + 1 end return _accum_0 end)() if type(source) == "string" then return build.assign({ names = real_names, values = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = stubs for _index_0 = 1, #_list_0 do local stub = _list_0[_index_0] _accum_0[_len_0] = build.chain({ base = source, stub }) _len_0 = _len_0 + 1 end return _accum_0 end)() }) else local source_name = NameProxy("table") return build.group({ { "declare", real_names }, build["do"]({ build.assign_one(source_name, source), build.assign({ names = real_names, values = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = stubs for _index_0 = 1, #_list_0 do local stub = _list_0[_index_0] _accum_0[_len_0] = build.chain({ base = source_name, stub }) _len_0 = _len_0 + 1 end return _accum_0 end)() }) }) }) end end, comprehension = function(self, node, action) local _, exp, clauses = unpack(node) action = action or function(exp) return { exp } end return construct_comprehension(action(exp), clauses) end, ["do"] = function(self, node, ret) if ret then node[2] = apply_to_last(node[2], ret) end return node end, decorated = function(self, node) local stm, dec = unpack(node, 2) local wrapped local _exp_0 = dec[1] if "if" == _exp_0 then local cond, fail = unpack(dec, 2) if fail then fail = { "else", { fail } } end wrapped = { "if", cond, { stm }, fail } elseif "unless" == _exp_0 then wrapped = { "unless", dec[2], { stm } } elseif "comprehension" == _exp_0 then wrapped = { "comprehension", stm, dec[2] } else wrapped = error("Unknown decorator " .. dec[1]) end if ntype(stm) == "assign" then wrapped = build.group({ build.declare({ names = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = stm[2] for _index_0 = 1, #_list_0 do local name = _list_0[_index_0] if type(name) == "string" then _accum_0[_len_0] = name _len_0 = _len_0 + 1 end end return _accum_0 end)() }), wrapped }) end return wrapped end, unless = function(self, node) return { "if", { "not", { "parens", node[2] } }, unpack(node, 3) } end, ["if"] = function(self, node, ret) if ntype(node[2]) == "assign" then local _, assign, body = unpack(node) if destructure.has_destructure(assign[2]) then local name = NameProxy("des") body = { destructure.build_assign(assign[2][1], name), build.group(node[3]) } return build["do"]({ build.assign_one(name, assign[3][1]), { "if", name, body, unpack(node, 4) } }) else local name = assign[2][1] return build["do"]({ assign, { "if", name, unpack(node, 3) } }) end end node = expand_elseif_assign(node) if ret then smart_node(node) node['then'] = apply_to_last(node['then'], ret) for i = 4, #node do local case = node[i] local body_idx = #node[i] case[body_idx] = apply_to_last(case[body_idx], ret) end end return node end, with = function(self, node, ret) local _, exp, block = unpack(node) local scope_name = NameProxy("with") local named_assign if ntype(exp) == "assign" then local names, values = unpack(exp, 2) local assign_name = names[1] exp = values[1] values[1] = scope_name named_assign = { "assign", names, values } end return build["do"]({ Run(function(self) return self:set("scope_var", scope_name) end), build.assign_one(scope_name, exp), build.group({ named_assign }), build.group(block), (function() if ret then return ret(scope_name) end end)() }) end, foreach = function(self, node) smart_node(node) local source = unpack(node.iter) local destructures = { } node.names = (function() local _accum_0 = { } local _len_0 = 1 for i, name in ipairs(node.names) do if ntype(name) == "table" then do local _with_0 = NameProxy("des") local proxy = _with_0 insert(destructures, destructure.build_assign(name, proxy)) _accum_0[_len_0] = _with_0 end else _accum_0[_len_0] = name end _len_0 = _len_0 + 1 end return _accum_0 end)() if next(destructures) then insert(destructures, build.group(node.body)) node.body = destructures end if ntype(source) == "unpack" then local list = source[2] local index_name = NameProxy("index") local list_name = NameProxy("list") local slice_var = nil local bounds if is_slice(list) then local slice = list[#list] table.remove(list) table.remove(slice, 1) if slice[2] and slice[2] ~= "" then local max_tmp_name = NameProxy("max") slice_var = build.assign_one(max_tmp_name, slice[2]) slice[2] = { "exp", max_tmp_name, "<", 0, "and", { "length", list_name }, "+", max_tmp_name, "or", max_tmp_name } else slice[2] = { "length", list_name } end bounds = slice else bounds = { 1, { "length", list_name } } end return build.group({ build.assign_one(list_name, list), slice_var, build["for"]({ name = index_name, bounds = bounds, body = { { "assign", node.names, { list_name:index(index_name) } }, build.group(node.body) } }) }) end node.body = with_continue_listener(node.body) end, ["while"] = function(self, node) smart_node(node) node.body = with_continue_listener(node.body) end, ["for"] = function(self, node) smart_node(node) node.body = with_continue_listener(node.body) end, switch = function(self, node, ret) local _, exp, conds = unpack(node) local exp_name = NameProxy("exp") local convert_cond convert_cond = function(cond) local t, case_exps, body = unpack(cond) local out = { } insert(out, t == "case" and "elseif" or "else") if t ~= "else" then local cond_exp = { } for i, case in ipairs(case_exps) do if i == 1 then insert(cond_exp, "exp") else insert(cond_exp, "or") end if not (value_is_singular(case)) then case = { "parens", case } end insert(cond_exp, { "exp", case, "==", exp_name }) end insert(out, cond_exp) else body = case_exps end if ret then body = apply_to_last(body, ret) end insert(out, body) return out end local first = true local if_stm = { "if" } local _list_0 = conds for _index_0 = 1, #_list_0 do local cond = _list_0[_index_0] local if_cond = convert_cond(cond) if first then first = false insert(if_stm, if_cond[2]) insert(if_stm, if_cond[3]) else insert(if_stm, if_cond) end end return build.group({ build.assign_one(exp_name, exp), if_stm }) end, class = function(self, node, ret, parent_assign) local _, name, parent_val, body = unpack(node) local statements = { } local properties = { } local _list_0 = body for _index_0 = 1, #_list_0 do local item = _list_0[_index_0] local _exp_0 = item[1] if "stm" == _exp_0 then insert(statements, item[2]) elseif "props" == _exp_0 then local _list_1 = item for _index_1 = 2, #_list_1 do local tuple = _list_1[_index_1] if ntype(tuple[1]) == "self" then insert(statements, build.assign_one(unpack(tuple))) else insert(properties, tuple) end end end end local constructor properties = (function() local _accum_0 = { } local _len_0 = 1 local _list_1 = properties for _index_0 = 1, #_list_1 do local _continue_0 = false repeat local tuple = _list_1[_index_0] local key = tuple[1] local _value_0 if key[1] == "key_literal" and key[2] == constructor_name then constructor = tuple[2] _continue_0 = true break else _value_0 = tuple end _accum_0[_len_0] = _value_0 _len_0 = _len_0 + 1 _continue_0 = true until true if not _continue_0 then break end end return _accum_0 end)() local parent_cls_name = NameProxy("parent") local base_name = NameProxy("base") local self_name = NameProxy("self") local cls_name = NameProxy("class") if not (constructor) then constructor = build.fndef({ args = { { "..." } }, arrow = "fat", body = { build["if"]({ cond = parent_cls_name, ["then"] = { build.chain({ base = "super", { "call", { "..." } } }) } }) } }) end local real_name = name or parent_assign and parent_assign[2][1] local _exp_0 = ntype(real_name) if "chain" == _exp_0 then local last = real_name[#real_name] local _exp_1 = ntype(last) if "dot" == _exp_1 then real_name = { "string", '"', last[2] } elseif "index" == _exp_1 then real_name = last[2] else real_name = "nil" end elseif "nil" == _exp_0 then real_name = "nil" else real_name = { "string", '"', real_name } end local cls = build.table({ { "__init", constructor }, { "__base", base_name }, { "__name", real_name }, { "__parent", parent_cls_name } }) local class_lookup = build["if"]({ cond = { "exp", "val", "==", "nil", "and", parent_cls_name }, ["then"] = { parent_cls_name:index("name") } }) insert(class_lookup, { "else", { "val" } }) local cls_mt = build.table({ { "__index", build.fndef({ args = { { "cls" }, { "name" } }, body = { build.assign_one(LocalName("val"), build.chain({ base = "rawget", { "call", { base_name, "name" } } })), class_lookup } }) }, { "__call", build.fndef({ args = { { "cls" }, { "..." } }, body = { build.assign_one(self_name, build.chain({ base = "setmetatable", { "call", { "{}", base_name } } })), build.chain({ base = "cls.__init", { "call", { self_name, "..." } } }), self_name } }) } }) cls = build.chain({ base = "setmetatable", { "call", { cls, cls_mt } } }) local value = nil do local _with_0 = build local out_body = { Run(function(self) if name then self:put_name(name) end return self:set("super", function(block, chain) if chain then local slice = (function() local _accum_0 = { } local _len_0 = 1 local _list_1 = chain for _index_0 = 3, #_list_1 do local item = _list_1[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 end return _accum_0 end)() local new_chain = { "chain", parent_cls_name } local head = slice[1] if head == nil then return parent_cls_name end local _exp_1 = head[1] if "call" == _exp_1 then local calling_name = block:get("current_block") slice[1] = { "call", { "self", unpack(head[2]) } } if ntype(calling_name) == "key_literal" then insert(new_chain, { "dot", calling_name[2] }) else insert(new_chain, { "index", calling_name }) end elseif "colon" == _exp_1 then local call = head[3] insert(new_chain, { "dot", head[2] }) slice[1] = { "call", { "self", unpack(call[2]) } } end local _list_1 = slice for _index_0 = 1, #_list_1 do local item = _list_1[_index_0] insert(new_chain, item) end return new_chain else return parent_cls_name end end) end), { "declare_glob", "*" }, _with_0.assign_one(parent_cls_name, parent_val == "" and "nil" or parent_val), _with_0.assign_one(base_name, { "table", properties }), _with_0.assign_one(base_name:chain("__index"), base_name), _with_0["if"]({ cond = parent_cls_name, ["then"] = { _with_0.chain({ base = "setmetatable", { "call", { base_name, _with_0.chain({ base = parent_cls_name, { "dot", "__base" } }) } } }) } }), _with_0.assign_one(cls_name, cls), _with_0.assign_one(base_name:chain("__class"), cls_name), _with_0.group((function() if #statements > 0 then return { _with_0.assign_one(LocalName("self"), cls_name), _with_0.group(statements) } end end)()), _with_0["if"]({ cond = { "exp", parent_cls_name, "and", parent_cls_name:chain("__inherited") }, ["then"] = { parent_cls_name:chain("__inherited", { "call", { parent_cls_name, cls_name } }) } }), _with_0.group((function() if name then return { _with_0.assign_one(name, cls_name) } end end)()), (function() if ret then return ret(cls_name) end end)() } value = _with_0.group({ _with_0.group((function() if ntype(name) == "value" then return { _with_0.declare({ names = { name } }) } end end)()), _with_0["do"](out_body) }) end return value end }) local Accumulator do local _parent_0 = nil local _base_0 = { body_idx = { ["for"] = 4, ["while"] = 3, foreach = 4 }, convert = function(self, node) local index = self.body_idx[ntype(node)] node[index] = self:mutate_body(node[index]) return self:wrap(node) end, wrap = function(self, node) return build.block_exp({ build.assign_one(self.accum_name, build.table()), build.assign_one(self.len_name, 1), node, self.accum_name }) end, mutate_body = function(self, body) local single_stm = is_singular(body) local val if single_stm and types.is_value(single_stm) then body = { } val = single_stm else body = apply_to_last(body, function(n) if types.is_value(n) then return build.assign_one(self.value_name, n) else return build.group({ { "declare", { self.value_name } }, n }) end end) val = self.value_name end local update = { build.assign_one(self.accum_name:index(self.len_name), val), { "update", self.len_name, "+=", 1 } } insert(body, build.group(update)) return body end } _base_0.__index = _base_0 if _parent_0 then setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ __init = function(self) self.accum_name = NameProxy("accum") self.value_name = NameProxy("value") self.len_name = NameProxy("len") end, __base = _base_0, __name = "Accumulator", __parent = _parent_0 }, { __index = function(cls, name) local val = rawget(_base_0, name) if val == nil and _parent_0 then return _parent_0[name] 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 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end Accumulator = _class_0 end local default_accumulator default_accumulator = function(self, node) return Accumulator():convert(node) end implicitly_return = function(scope) local is_top = true local fn fn = function(stm) local t = ntype(stm) if t == "decorated" then stm = scope.transform.statement(stm) t = ntype(stm) end if types.cascading[t] then is_top = false return scope.transform.statement(stm, fn) elseif types.manual_return[t] or not types.is_value(stm) then if is_top and t == "return" and stm[2] == "" then return nil else return stm end else if t == "comprehension" and not types.comprehension_has_value(stm) then return stm else return { "return", stm } end end end return fn end local Value = Transformer({ ["for"] = default_accumulator, ["while"] = default_accumulator, foreach = default_accumulator, ["do"] = function(self, node) return build.block_exp(node[2]) end, decorated = function(self, node) return self.transform.statement(node) end, class = function(self, node) return build.block_exp({ node }) end, string = function(self, node) local delim = node[2] local convert_part convert_part = function(part) if type(part) == "string" or part == nil then return { "string", delim, part or "" } else return build.chain({ base = "tostring", { "call", { part[2] } } }) end end if #node <= 3 then return (function() if type(node[3]) == "string" then return node else return convert_part(node[3]) end end)() end local e = { "exp", convert_part(node[3]) } for i = 4, #node do insert(e, "..") insert(e, convert_part(node[i])) end return e end, comprehension = function(self, node) local a = Accumulator() node = self.transform.statement(node, function(exp) return a:mutate_body({ exp }) end) return a:wrap(node) end, tblcomprehension = function(self, node) local _, explist, clauses = unpack(node) local key_exp, value_exp = unpack(explist) local accum = NameProxy("tbl") local inner if value_exp then local dest = build.chain({ base = accum, { "index", key_exp } }) inner = { build.assign_one(dest, value_exp) } else local key_name, val_name = NameProxy("key"), NameProxy("val") local dest = build.chain({ base = accum, { "index", key_name } }) inner = { build.assign({ names = { key_name, val_name }, values = { key_exp } }), build.assign_one(dest, val_name) } end return build.block_exp({ build.assign_one(accum, build.table()), construct_comprehension(inner, clauses), accum }) end, fndef = function(self, node) smart_node(node) node.body = apply_to_last(node.body, implicitly_return(self)) node.body = { Run(function(self) return self:listen("varargs", function() end) end), unpack(node.body) } return node end, ["if"] = function(self, node) return build.block_exp({ node }) end, unless = function(self, node) return build.block_exp({ node }) end, with = function(self, node) return build.block_exp({ node }) end, switch = function(self, node) return build.block_exp({ node }) end, chain = function(self, node) local stub = node[#node] for i = 3, #node do local part = node[i] if ntype(part) == "dot" and data.lua_keywords[part[2]] then node[i] = { "index", { "string", '"', part[2] } } end end if ntype(node[2]) == "string" then node[2] = { "parens", node[2] } elseif type(stub) == "table" and stub[1] == "colon_stub" then table.remove(node, #node) local base_name = NameProxy("base") local fn_name = NameProxy("fn") local is_super = node[2] == "super" return self.transform.value(build.block_exp({ build.assign({ names = { base_name }, values = { node } }), build.assign({ names = { fn_name }, values = { build.chain({ base = base_name, { "dot", stub[2] } }) } }), build.fndef({ args = { { "..." } }, body = { build.chain({ base = fn_name, { "call", { is_super and "self" or base_name, "..." } } }) } }) })) end end, block_exp = function(self, node) local _, body = unpack(node) local fn = nil local arg_list = { } fn = smart_node(build.fndef({ body = { Run(function(self) return self:listen("varargs", function() insert(arg_list, "...") insert(fn.args, { "..." }) return self:unlisten("varargs") end) end), unpack(body) } })) return build.chain({ base = { "parens", fn }, { "call", arg_list } }) end }) return { Statement = Statement, Value = Value, Run = Run } end package.preload['moonscript.types'] = function() local util = require("moonscript.util") local data = require("moonscript.data") local insert = table.insert local unpack = util.unpack local manual_return = data.Set({ "foreach", "for", "while", "return" }) local cascading = data.Set({ "if", "unless", "with", "switch", "class", "do" }) local ntype ntype = function(node) local _exp_0 = type(node) if "nil" == _exp_0 then return "nil" elseif "table" == _exp_0 then return node[1] else return "value" end end local mtype do local moon_type = util.moon.type mtype = function(val) local mt = getmetatable(val) if mt and mt.smart_node then return "table" end return moon_type(val) end end local has_value has_value = function(node) if ntype(node) == "chain" then local ctype = ntype(node[#node]) return ctype ~= "call" and ctype ~= "colon" else return true end end local is_value is_value = function(stm) local compile = require("moonscript.compile") local transform = require("moonscript.transform") return compile.Block:is_value(stm) or transform.Value:can_transform(stm) end local comprehension_has_value comprehension_has_value = function(comp) return is_value(comp[2]) end local value_is_singular value_is_singular = function(node) return type(node) ~= "table" or node[1] ~= "exp" or #node == 2 end local is_slice is_slice = function(node) return ntype(node) == "chain" and ntype(node[#node]) == "slice" end local t = { } local node_types = { class = { { "name", "Tmp" }, { "body", t } }, fndef = { { "args", t }, { "whitelist", t }, { "arrow", "slim" }, { "body", t } }, foreach = { { "names", t }, { "iter" }, { "body", t } }, ["for"] = { { "name" }, { "bounds", t }, { "body", t } }, ["while"] = { { "cond", t }, { "body", t } }, assign = { { "names", t }, { "values", t } }, declare = { { "names", t } }, ["if"] = { { "cond", t }, { "then", t } } } local build_table build_table = function() local key_table = { } for node_name, args in pairs(node_types) do local index = { } for i, tuple in ipairs(args) do local prop_name = tuple[1] index[prop_name] = i + 1 end key_table[node_name] = index end return key_table end local key_table = build_table() local make_builder make_builder = function(name) local spec = node_types[name] if not spec then error("don't know how to build node: " .. name) end return function(props) if props == nil then props = { } end local node = { name } for i, arg in ipairs(spec) do local key, default_value = unpack(arg) local val if props[key] then val = props[key] else val = default_value end if val == t then val = { } end node[i + 1] = val end return node end end local build = nil build = setmetatable({ group = function(body) if body == nil then body = { } end return { "group", body } end, ["do"] = function(body) return { "do", body } end, assign_one = function(name, value) return build.assign({ names = { name }, values = { value } }) end, table = function(tbl) if tbl == nil then tbl = { } end local _list_0 = tbl for _index_0 = 1, #_list_0 do local tuple = _list_0[_index_0] if type(tuple[1]) == "string" then tuple[1] = { "key_literal", tuple[1] } end end return { "table", tbl } end, block_exp = function(body) return { "block_exp", body } end, chain = function(parts) local base = parts.base or error("expecting base property for chain") local node = { "chain", base } local _list_0 = parts for _index_0 = 1, #_list_0 do local part = _list_0[_index_0] insert(node, part) end return node end }, { __index = function(self, name) self[name] = make_builder(name) return rawget(self, name) end }) local smart_node_mt = setmetatable({ }, { __index = function(self, node_type) local index = key_table[node_type] local mt = { smart_node = true, __index = function(node, key) if index[key] then return rawget(node, index[key]) elseif type(key) == "string" then return error("unknown key: `" .. key .. "` on node type: `" .. ntype(node) .. "`") end end, __newindex = function(node, key, value) if index[key] then key = index[key] end return rawset(node, key, value) end } self[node_type] = mt return mt end }) local smart_node smart_node = function(node) return setmetatable(node, smart_node_mt[ntype(node)]) end return { ntype = ntype, smart_node = smart_node, build = build, is_value = is_value, is_slice = is_slice, manual_return = manual_return, cascading = cascading, value_is_singular = value_is_singular, comprehension_has_value = comprehension_has_value, has_value = has_value, mtype = mtype } end package.preload['moonscript.util'] = function() local concat = table.concat local unpack = unpack or table.unpack local type = type local moon = { is_object = function(value) return type(value) == "table" and value.__class end, is_a = function(thing, t) if not (type(thing) == "table") then return false end local cls = thing.__class while cls do if cls == t then return true end cls = cls.__parent end return false end, type = function(value) local base_type = type(value) if base_type == "table" then local cls = value.__class if cls then return cls end end return base_type end } local pos_to_line pos_to_line = function(str, pos) local line = 1 for _ in str:sub(1, pos):gmatch("\n") do line = line + 1 end return line end local trim trim = function(str) return str:match("^%s*(.-)%s*$") end local get_line get_line = function(str, line_num) for line in str:gmatch("([^\n]*)\n?") do if line_num == 1 then return line end line_num = line_num - 1 end end local get_closest_line get_closest_line = function(str, line_num) local line = get_line(str, line_num) if (not line or trim(line) == "") and line_num > 1 then return get_closest_line(str, line_num - 1) else return line, line_num end end local reversed reversed = function(seq) return coroutine.wrap(function() for i = #seq, 1, -1 do coroutine.yield(i, seq[i]) end end) end local split split = function(str, delim) if str == "" then return { } end str = str .. delim return (function() local _accum_0 = { } local _len_0 = 1 for m in str:gmatch("(.-)" .. delim) do _accum_0[_len_0] = m _len_0 = _len_0 + 1 end return _accum_0 end)() end local dump dump = function(what) local seen = { } local _dump _dump = function(what, depth) if depth == nil then depth = 0 end local t = type(what) if t == "string" then return '"' .. what .. '"\n' elseif t == "table" then if seen[what] then return "recursion(" .. tostring(what) .. ")...\n" end seen[what] = true depth = depth + 1 local lines = (function() local _accum_0 = { } local _len_0 = 1 for k, v in pairs(what) do _accum_0[_len_0] = (" "):rep(depth * 4) .. "[" .. tostring(k) .. "] = " .. _dump(v, depth) _len_0 = _len_0 + 1 end return _accum_0 end)() seen[what] = false return "{\n" .. concat(lines) .. (" "):rep((depth - 1) * 4) .. "}\n" else return tostring(what) .. "\n" end end return _dump(what) end local debug_posmap debug_posmap = function(posmap, moon_code, lua_code) local tuples = (function() local _accum_0 = { } local _len_0 = 1 for k, v in pairs(posmap) do _accum_0[_len_0] = { k, v } _len_0 = _len_0 + 1 end return _accum_0 end)() table.sort(tuples, function(a, b) return a[1] < b[1] end) local lines = (function() local _accum_0 = { } local _len_0 = 1 local _list_0 = tuples for _index_0 = 1, #_list_0 do local pair = _list_0[_index_0] local lua_line, pos = unpack(pair) local moon_line = pos_to_line(moon_code, pos) local lua_text = get_line(lua_code, lua_line) local moon_text = get_closest_line(moon_code, moon_line) local _value_0 = tostring(pos) .. "\t " .. tostring(lua_line) .. ":[ " .. tostring(trim(lua_text)) .. " ] >> " .. tostring(moon_line) .. ":[ " .. tostring(trim(moon_text)) .. " ]" _accum_0[_len_0] = _value_0 _len_0 = _len_0 + 1 end return _accum_0 end)() return concat(lines, "\n") end local setfenv = setfenv or function(fn, env) local name local i = 1 while true do name = debug.getupvalue(fn, i) if not name or name == "_ENV" then break end i = i + 1 end if name then debug.upvaluejoin(fn, i, (function() return env end), 1) end return fn end local getfenv = getfenv or function(fn) local i = 1 while true do local name, val = debug.getupvalue(fn, i) if not (name) then break end if name == "_ENV" then return val end i = i + 1 end return nil end local get_options get_options = function(...) local count = select("#", ...) local opts = select(count, ...) if type(opts) == "table" then return opts, unpack({ ... }, nil, count - 1) else return { }, ... end end return { moon = moon, pos_to_line = pos_to_line, get_closest_line = get_closest_line, get_line = get_line, reversed = reversed, trim = trim, split = split, dump = dump, debug_posmap = debug_posmap, getfenv = getfenv, setfenv = setfenv, get_options = get_options, unpack = unpack } end package.preload['moonscript.version'] = function() module("moonscript.version", package.seeall) version = "0.2.3-2" function print_version() print("MoonScript version "..version) end end return package.preload["moonscript"]()