diff --git a/automation/include/moonscript.lua b/automation/include/moonscript.lua index b8d45cd3c..78806c870 100644 --- a/automation/include/moonscript.lua +++ b/automation/include/moonscript.lua @@ -1,218 +1,839 @@ -package.preload['moonscript.base'] = function() - local compile = require("moonscript.compile") - local parse = require("moonscript.parse") - local concat, insert, remove - do - local _obj_0 = table - concat, insert, remove = _obj_0.concat, _obj_0.insert, _obj_0.remove - end - local split, dump, get_options, unpack - do - local _obj_0 = require("moonscript.util") - split, dump, get_options, unpack = _obj_0.split, _obj_0.dump, _obj_0.get_options, _obj_0.unpack - end - local lua = { - loadstring = loadstring, - load = load - } - local dirsep, line_tables, create_moonpath, to_lua, 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" +package.preload['moonscript.transform.comprehension'] = function() + local is_value + is_value = require("moonscript.types").is_value + local construct_comprehension + construct_comprehension = function(inner, clauses) + local current_stms = inner + for i = #clauses, 1, -1 do + local clause = clauses[i] + local t = clause[1] + local _exp_0 = t + if "for" == _exp_0 then + local _, name, bounds + _, name, bounds = clause[1], clause[2], clause[3] + current_stms = { + "for", + name, + bounds, + current_stms + } + elseif "foreach" == _exp_0 then + local _, names, iter + _, names, iter = clause[1], clause[2], clause[3] + current_stms = { + "foreach", + names, + { + iter + }, + current_stms + } + elseif "when" == _exp_0 then + local _, cond + _, cond = clause[1], clause[2] + current_stms = { + "if", + cond, + current_stms + } + else + current_stms = error("Unknown comprehension clause: " .. t) end + current_stms = { + current_stms + } end - return concat(paths, ";") + return current_stms[1] 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 .. ")" - 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) - end - return code, ltable - 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, "@" .. tostring(fname), ...) - end - dofile = function(...) - local f = assert(loadfile(...)) - return f() + local comprehension_has_value + comprehension_has_value = function(comp) + return is_value(comp[2]) end return { - _NAME = "moonscript", - to_lua = to_lua, - dirsep = dirsep, - dofile = dofile, - loadfile = loadfile, - loadstring = loadstring + construct_comprehension = construct_comprehension, + comprehension_has_value = comprehension_has_value } end -package.preload['moonscript.cmd.coverage'] = function() - local log - log = function(str) - if str == nil then - str = "" - end - return io.stderr:write(str .. "\n") - end - local create_counter - create_counter = function() - return setmetatable({ }, { - __index = function(self, name) - do - local tbl = setmetatable({ }, { - __index = function(self) - return 0 - end - }) - self[name] = tbl - return tbl - end - end - }) - end - local position_to_lines - position_to_lines = function(file_content, positions) - local lines = { } - local current_pos = 0 - local line_no = 1 - for char in file_content:gmatch(".") do - do - local count = rawget(positions, current_pos) - if count then - lines[line_no] = count - end - end - if char == "\n" then - line_no = line_no + 1 - end - current_pos = current_pos + 1 - end - return lines - end - local format_file - format_file = function(fname, positions) - local file = assert(io.open(fname)) - local content = file:read("*a") - file:close() - local lines = position_to_lines(content, positions) - log("------| @" .. tostring(fname)) - local line_no = 1 - for line in (content .. "\n"):gmatch("(.-)\n") do - local foramtted_no = ("% 5d"):format(line_no) - local sym = lines[line_no] and "*" or " " - log(tostring(sym) .. tostring(foramtted_no) .. "| " .. tostring(line)) - line_no = line_no + 1 - end - return log() - end - local CodeCoverage +package.preload['moonscript.transform.value'] = function() + local Transformer + Transformer = require("moonscript.transform.transformer").Transformer + local build, ntype, smart_node do - local _base_0 = { - reset = function(self) - self.line_counts = create_counter() - end, - start = function(self) - return debug.sethook((function() - local _base_1 = self - local _fn_0 = _base_1.process_line - return function(...) - return _fn_0(_base_1, ...) + local _obj_0 = require("moonscript.types") + build, ntype, smart_node = _obj_0.build, _obj_0.ntype, _obj_0.smart_node + end + local NameProxy + NameProxy = require("moonscript.transform.names").NameProxy + local Accumulator, default_accumulator + do + local _obj_0 = require("moonscript.transform.accumulator") + Accumulator, default_accumulator = _obj_0.Accumulator, _obj_0.default_accumulator + end + local lua_keywords + lua_keywords = require("moonscript.data").lua_keywords + local Run, transform_last_stm, implicitly_return, chain_is_stub + do + local _obj_0 = require("moonscript.transform.statements") + Run, transform_last_stm, implicitly_return, chain_is_stub = _obj_0.Run, _obj_0.transform_last_stm, _obj_0.implicitly_return, _obj_0.chain_is_stub + end + local construct_comprehension + construct_comprehension = require("moonscript.transform.comprehension").construct_comprehension + local insert + insert = table.insert + local unpack + unpack = require("moonscript.util").unpack + return 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 + if type(node[3]) == "string" then + return node + else + return convert_part(node[3]) + 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, 2) + 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 = transform_last_stm(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) + for i = 2, #node do + local part = node[i] + if ntype(part) == "dot" and lua_keywords[part[2]] then + node[i] = { + "index", + { + "string", + '"', + part[2] + } + } + end + end + if ntype(node[2]) == "string" then + node[2] = { + "parens", + node[2] + } + end + if chain_is_stub(node) then + local base_name = NameProxy("base") + local fn_name = NameProxy("fn") + local colon = table.remove(node) + local is_super = ntype(node[2]) == "ref" and node[2][2] == "super" + return build.block_exp({ + build.assign({ + names = { + base_name + }, + values = { + node + } + }), + build.assign({ + names = { + fn_name + }, + values = { + build.chain({ + base = base_name, + { + "dot", + colon[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, 2) + 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 + }) + +end +package.preload['moonscript.transform.class'] = function() + local NameProxy, LocalName + do + local _obj_0 = require("moonscript.transform.names") + NameProxy, LocalName = _obj_0.NameProxy, _obj_0.LocalName + end + local Run + Run = require("moonscript.transform.statements").Run + local CONSTRUCTOR_NAME = "new" + local insert + insert = table.insert + local build, ntype, NOOP + do + local _obj_0 = require("moonscript.types") + build, ntype, NOOP = _obj_0.build, _obj_0.ntype, _obj_0.NOOP + end + local unpack + unpack = require("moonscript.util").unpack + local transform_super + transform_super = function(cls_name, on_base, block, chain) + if on_base == nil then + on_base = true + end + local relative_parent = { + "chain", + cls_name, + { + "dot", + "__parent" + } + } + if not (chain) then + return relative_parent + end + local chain_tail = { + unpack(chain, 3) + } + local head = chain_tail[1] + if head == nil then + return relative_parent + end + local new_chain = relative_parent + local _exp_0 = head[1] + if "call" == _exp_0 then + if on_base then + insert(new_chain, { + "dot", + "__base" + }) + end + local calling_name = block:get("current_method") + assert(calling_name, "missing calling name") + chain_tail[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_0 then + local call = chain_tail[2] + if call and call[1] == "call" then + chain_tail[1] = { + "dot", + head[2] + } + chain_tail[2] = { + "call", + { + "self", + unpack(call[2]) + } + } + end + end + for _index_0 = 1, #chain_tail do + local item = chain_tail[_index_0] + insert(new_chain, item) + end + return new_chain + end + local super_scope + super_scope = function(value, t, key) + local prev_method + return { + "scoped", + Run(function(self) + prev_method = self:get("current_method") + self:set("current_method", key) + return self:set("super", t) + end), + value, + Run(function(self) + return self:set("current_method", prev_method) + end) + } + end + return function(self, node, ret, parent_assign) + local name, parent_val, body = unpack(node, 2) + if parent_val == "" then + parent_val = nil + end + local parent_cls_name = NameProxy("parent") + local base_name = NameProxy("base") + local self_name = NameProxy("self") + local cls_name = NameProxy("class") + local cls_instance_super + cls_instance_super = function(...) + return transform_super(cls_name, true, ...) + end + local cls_super + cls_super = function(...) + return transform_super(cls_name, false, ...) + end + local statements = { } + local properties = { } + for _index_0 = 1, #body do + local item = body[_index_0] + local _exp_0 = item[1] + if "stm" == _exp_0 then + insert(statements, item[2]) + elseif "props" == _exp_0 then + for _index_1 = 2, #item do + local tuple = item[_index_1] + if ntype(tuple[1]) == "self" then + local k, v + k, v = tuple[1], tuple[2] + v = super_scope(v, cls_super, { + "key_literal", + k[2] + }) + insert(statements, build.assign_one(k, v)) + else + insert(properties, tuple) end - end)(), "l") - end, - stop = function(self) - return debug.sethook() - end, - print_results = function(self) - return self:format_results() - end, - process_line = function(self, _, line_no) - local debug_data = debug.getinfo(2, "S") - local source = debug_data.source - self.line_counts[source][line_no] = self.line_counts[source][line_no] + 1 - end, - format_results = function(self) - local line_table = require("moonscript.line_tables") - local positions = create_counter() - for file, lines in pairs(self.line_counts) do - local _continue_0 = false - repeat - local file_table = line_table[file] - if not (file_table) then - _continue_0 = true - break - end - for line, count in pairs(lines) do - local _continue_1 = false - repeat - local position = file_table[line] - if not (position) then - _continue_1 = true - break - end - positions[file][position] = positions[file][position] + count - _continue_1 = true - until true - if not _continue_1 then - break - end - end + end + end + end + local constructor + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #properties do + local _continue_0 = false + repeat + local tuple = properties[_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 - until true - if not _continue_0 then break + else + local val + key, val = tuple[1], tuple[2] + _value_0 = { + key, + super_scope(val, cls_instance_super, key) + } end + _accum_0[_len_0] = _value_0 + _len_0 = _len_0 + 1 + _continue_0 = true + until true + if not _continue_0 then + break end - for file, ps in pairs(positions) do - format_file(file, ps) - end + end + properties = _accum_0 + end + if not (constructor) then + if parent_val then + constructor = build.fndef({ + args = { + { + "..." + } + }, + arrow = "fat", + body = { + build.chain({ + base = "super", + { + "call", + { + "..." + } + } + }) + } + }) + else + constructor = build.fndef() + end + 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 + local name_t = type(real_name) + local flattened_name + if name_t == "string" then + flattened_name = real_name + elseif name_t == "table" and real_name[1] == "ref" then + flattened_name = real_name[2] + else + flattened_name = error("don't know how to extract name from " .. tostring(name_t)) + end + real_name = { + "string", + '"', + flattened_name + } + end + local cls = build.table({ + { + "__init", + super_scope(constructor, cls_super, { + "key_literal", + "__init" + }) + }, + { + "__base", + base_name + }, + { + "__name", + real_name + }, + parent_val and { + "__parent", + parent_cls_name + } or nil + }) + local class_index + if parent_val then + local class_lookup = build["if"]({ + cond = { + "exp", + { + "ref", + "val" + }, + "==", + "nil" + }, + ["then"] = { + build.assign_one(LocalName("parent"), build.chain({ + base = "rawget", + { + "call", + { + { + "ref", + "cls" + }, + { + "string", + '"', + "__parent" + } + } + } + })), + build["if"]({ + cond = LocalName("parent"), + ["then"] = { + build.chain({ + base = LocalName("parent"), + { + "index", + "name" + } + }) + } + }) + } + }) + insert(class_lookup, { + "else", + { + "val" + } + }) + class_index = build.fndef({ + args = { + { + "cls" + }, + { + "name" + } + }, + body = { + build.assign_one(LocalName("val"), build.chain({ + base = "rawget", + { + "call", + { + base_name, + { + "ref", + "name" + } + } + } + })), + class_lookup + } + }) + else + class_index = base_name + end + local cls_mt = build.table({ + { + "__index", + class_index + }, + { + "__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 out_body = { + Run(function(self) + if name then + return self:put_name(name) + end + end), + { + "declare", + { + cls_name + } + }, + { + "declare_glob", + "*" + }, + parent_val and build.assign_one(parent_cls_name, parent_val) or NOOP, + build.assign_one(base_name, { + "table", + properties + }), + build.assign_one(base_name:chain("__index"), base_name), + parent_val and build.chain({ + base = "setmetatable", + { + "call", + { + base_name, + build.chain({ + base = parent_cls_name, + { + "dot", + "__base" + } + }) + } + } + }) or NOOP, + build.assign_one(cls_name, cls), + build.assign_one(base_name:chain("__class"), cls_name), + build.group((function() + if #statements > 0 then + return { + build.assign_one(LocalName("self"), cls_name), + build.group(statements) + } + end + end)()), + parent_val and build["if"]({ + cond = { + "exp", + parent_cls_name:chain("__inherited") + }, + ["then"] = { + parent_cls_name:chain("__inherited", { + "call", + { + parent_cls_name, + cls_name + } + }) + } + }) or NOOP, + build.group((function() + if name then + return { + build.assign_one(name, cls_name) + } + end + end)()), + (function() + if ret then + return ret(cls_name) + end + end)() + } + value = build.group({ + build.group((function() + if ntype(name) == "value" then + return { + build.declare({ + names = { + name + } + }) + } + end + end)()), + build["do"](out_body) + }) + end + return value + end + +end +package.preload['moonscript.transform.statements'] = function() + local types = require("moonscript.types") + local ntype, mtype, is_value, NOOP + ntype, mtype, is_value, NOOP = types.ntype, types.mtype, types.is_value, types.NOOP + local comprehension_has_value + comprehension_has_value = require("moonscript.transform.comprehension").comprehension_has_value + local Run + do + local _class_0 + local _base_0 = { + call = function(self, state) + return self.fn(state) end } _base_0.__index = _base_0 - local _class_0 = setmetatable({ - __init = function(self) - return self:reset() + _class_0 = setmetatable({ + __init = function(self, fn) + self.fn = fn + self[1] = "run" end, __base = _base_0, - __name = "CodeCoverage" + __name = "Run" }, { __index = _base_0, __call = function(cls, ...) @@ -222,10 +843,1747 @@ package.preload['moonscript.cmd.coverage'] = function() end }) _base_0.__class = _class_0 - CodeCoverage = _class_0 + Run = _class_0 + end + local last_stm + last_stm = function(stms) + local last_exp_id = 0 + for i = #stms, 1, -1 do + local stm = stms[i] + if stm and mtype(stm) ~= Run then + if ntype(stm) == "group" then + return last_stm(stm[2]) + end + last_exp_id = i + break + end + end + return stms[last_exp_id], last_exp_id, stms + end + local transform_last_stm + transform_last_stm = function(stms, fn) + local _, last_idx, _stms = last_stm(stms) + if _stms ~= stms then + error("cannot transform last node in group") + end + return (function() + local _accum_0 = { } + local _len_0 = 1 + for i, stm in ipairs(stms) do + if i == last_idx then + _accum_0[_len_0] = { + "transform", + stm, + fn + } + else + _accum_0[_len_0] = stm + end + _len_0 = _len_0 + 1 + end + return _accum_0 + end)() + end + local chain_is_stub + chain_is_stub = function(chain) + local stub = chain[#chain] + return stub and ntype(stub) == "colon" + end + local implicitly_return + 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 is_value(stm) then + if is_top and t == "return" and stm[2] == "" then + return NOOP + else + return stm + end + else + if t == "comprehension" and not comprehension_has_value(stm) then + return stm + else + return { + "return", + stm + } + end + end + end + return fn end return { - CodeCoverage = CodeCoverage + Run = Run, + last_stm = last_stm, + transform_last_stm = transform_last_stm, + chain_is_stub = chain_is_stub, + implicitly_return = implicitly_return + } + +end +package.preload['moonscript.transform.destructure'] = function() + local ntype, mtype, build + do + local _obj_0 = require("moonscript.types") + ntype, mtype, build = _obj_0.ntype, _obj_0.mtype, _obj_0.build + end + local NameProxy + NameProxy = require("moonscript.transform.names").NameProxy + local insert + insert = table.insert + local unpack + unpack = require("moonscript.util").unpack + local user_error + user_error = require("moonscript.errors").user_error + local join + join = function(...) + do + local out = { } + local i = 1 + local _list_0 = { + ... + } + for _index_0 = 1, #_list_0 do + local tbl = _list_0[_index_0] + for _index_1 = 1, #tbl do + local v = tbl[_index_1] + out[i] = v + i = i + 1 + end + end + return out + end + end + local has_destructure + has_destructure = function(names) + for _index_0 = 1, #names do + local n = names[_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 + local key_name = key[2] + if ntype(key_name) == "colon" then + s = key_name + else + s = { + "dot", + key_name + } + end + else + s = { + "index", + key + } + end + value, suffix = tuple[2], s + end + suffix = join(prefix, { + suffix + }) + local _exp_0 = ntype(value) + if "value" == _exp_0 or "ref" == _exp_0 or "chain" == _exp_0 or "self" == _exp_0 then + insert(accum, { + value, + suffix + }) + elseif "table" == _exp_0 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(scope, destruct_literal, receiver) + local extracted_names = extract_assign_names(destruct_literal) + local names = { } + local values = { } + local inner = { + "assign", + names, + values + } + local obj + if scope:is_local(receiver) or #extracted_names == 1 then + obj = receiver + else + do + obj = NameProxy("obj") + inner = build["do"]({ + build.assign_one(obj, receiver), + { + "assign", + names, + values + } + }) + obj = obj + end + end + for _index_0 = 1, #extracted_names do + local tuple = extracted_names[_index_0] + insert(names, tuple[1]) + local chain + if obj then + chain = NameProxy.chain(obj, unpack(tuple[2])) + else + chain = "nil" + end + insert(values, chain) + end + return build.group({ + { + "declare", + names + }, + inner + }) + end + local split_assign + split_assign = function(scope, 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(scope, 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 + do + 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 + name_slice = _accum_0 + end + end + local value_slice + if total_values < start then + value_slice = { + "nil" + } + else + do + 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 + value_slice = _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, + extract_assign_names = extract_assign_names + } + +end +package.preload['moonscript.transform.names'] = function() + local build + build = require("moonscript.types").build + local unpack + unpack = require("moonscript.util").unpack + local LocalName + do + local _class_0 + local _base_0 = { + get_name = function(self) + return self.name + end + } + _base_0.__index = _base_0 + _class_0 = setmetatable({ + __init = function(self, name) + self.name = name + self[1] = "temp_name" + end, + __base = _base_0, + __name = "LocalName" + }, { + __index = _base_0, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + LocalName = _class_0 + end + local NameProxy + do + local _class_0 + 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 = { + base = self, + ... + } + for k, v in ipairs(items) do + if type(v) == "string" then + items[k] = { + "dot", + v + } + else + items[k] = v + end + end + return build.chain(items) + end, + index = function(self, key) + if type(key) == "string" then + key = { + "ref", + key + } + end + 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 + _class_0 = setmetatable({ + __init = function(self, prefix) + self.prefix = prefix + self[1] = "temp_name" + end, + __base = _base_0, + __name = "NameProxy" + }, { + __index = _base_0, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + NameProxy = _class_0 + end + local is_name_proxy + is_name_proxy = function(v) + if not (type(v) == "table") then + return false + end + local _exp_0 = v.__class + if LocalName == _exp_0 or NameProxy == _exp_0 then + return true + end + end + return { + NameProxy = NameProxy, + LocalName = LocalName, + is_name_proxy = is_name_proxy + } + +end +package.preload['moonscript.transform.statement'] = function() + local Transformer + Transformer = require("moonscript.transform.transformer").Transformer + local NameProxy, LocalName, is_name_proxy + do + local _obj_0 = require("moonscript.transform.names") + NameProxy, LocalName, is_name_proxy = _obj_0.NameProxy, _obj_0.LocalName, _obj_0.is_name_proxy + end + local Run, transform_last_stm, implicitly_return, last_stm + do + local _obj_0 = require("moonscript.transform.statements") + Run, transform_last_stm, implicitly_return, last_stm = _obj_0.Run, _obj_0.transform_last_stm, _obj_0.implicitly_return, _obj_0.last_stm + end + local types = require("moonscript.types") + local build, ntype, is_value, smart_node, value_is_singular, is_slice, NOOP + build, ntype, is_value, smart_node, value_is_singular, is_slice, NOOP = types.build, types.ntype, types.is_value, types.smart_node, types.value_is_singular, types.is_slice, types.NOOP + local insert + insert = table.insert + local destructure = require("moonscript.transform.destructure") + local construct_comprehension + construct_comprehension = require("moonscript.transform.comprehension").construct_comprehension + local unpack + unpack = require("moonscript.util").unpack + 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 + local last = last_stm(body) + local enclose_lines = types.terminating[last and ntype(last)] + self:put_name(continue_name, nil) + return self:splice(function(lines) + if enclose_lines then + lines = { + "do", + { + lines + } + } + end + return { + { + "assign", + { + continue_name + }, + { + "false" + } + }, + { + "repeat", + "true", + { + lines, + { + "assign", + { + continue_name + }, + { + "true" + } + } + } + }, + { + "if", + { + "not", + continue_name + }, + { + { + "break" + } + } + } + } + end) + 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 ntype(name) == "ref" then + insert(out, name) + elseif 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 + return Transformer({ + transform = function(self, tuple) + local _, node, fn + _, node, fn = tuple[1], tuple[2], tuple[3] + return fn(node) + end, + root_stms = function(self, body) + return transform_last_stm(body, implicitly_return(self)) + end, + ["return"] = function(self, node) + local ret_val = node[2] + local ret_val_type = ntype(ret_val) + if ret_val_type == "explist" and #ret_val == 2 then + ret_val = ret_val[2] + ret_val_type = ntype(ret_val) + end + if types.cascading[ret_val_type] then + return implicitly_return(self)(ret_val) + end + if ret_val_type == "chain" or ret_val_type == "comprehension" or ret_val_type == "tblcomprehension" then + local Value = require("moonscript.transform.value") + ret_val = Value:transform_once(self, ret_val) + if ntype(ret_val) == "block_exp" then + return build.group(transform_last_stm(ret_val[2], function(stm) + return { + "return", + stm + } + end)) + end + end + node[2] = ret_val + return node + end, + declare_glob = function(self, node) + local names = extract_declarations(self) + if node[2] == "^" then + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #names do + local _continue_0 = false + repeat + local name = names[_index_0] + local str_name + if ntype(name) == "ref" then + str_name = name[2] + else + str_name = name + end + if not (str_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 + names = _accum_0 + end + end + return { + "declare", + names + } + end, + assign = function(self, node) + local names, values = unpack(node, 2) + local num_values = #values + local num_names = #values + if num_names == 1 and num_values == 1 then + local first_value = values[1] + local first_name = names[1] + local first_type = ntype(first_value) + if first_type == "chain" then + local Value = require("moonscript.transform.value") + first_value = Value:transform_once(self, first_value) + first_type = ntype(first_value) + end + local _exp_0 = ntype(first_value) + if "block_exp" == _exp_0 then + local block_body = first_value[2] + local idx = #block_body + block_body[idx] = build.assign_one(first_name, block_body[idx]) + return build.group({ + { + "declare", + { + first_name + } + }, + { + "do", + block_body + } + }) + elseif "comprehension" == _exp_0 or "tblcomprehension" == _exp_0 or "foreach" == _exp_0 or "for" == _exp_0 or "while" == _exp_0 then + local Value = require("moonscript.transform.value") + return build.assign_one(first_name, Value:transform_once(self, first_value)) + else + values[1] = first_value + end + end + local transformed + if num_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 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(self, 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({ + { + "export", + node[2] + }, + build.assign({ + names = node[2], + values = node[3] + }) + }) + end + else + return nil + end + end, + update = function(self, node) + local name, op, exp = unpack(node, 2) + local op_final = op:match("^(.+)=$") + if not op_final then + error("Unknown op: " .. op) + end + local lifted + if ntype(name) == "chain" then + lifted = { } + local new_chain + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 3, #name do + local part = name[_index_0] + if ntype(part) == "index" then + local proxy = NameProxy("update") + table.insert(lifted, { + proxy, + part[2] + }) + _accum_0[_len_0] = { + "index", + proxy + } + else + _accum_0[_len_0] = part + end + _len_0 = _len_0 + 1 + end + new_chain = _accum_0 + end + if next(lifted) then + name = { + name[1], + name[2], + unpack(new_chain) + } + end + end + if not (value_is_singular(exp)) then + exp = { + "parens", + exp + } + end + local out = build.assign_one(name, { + "exp", + name, + op_final, + exp + }) + if lifted and next(lifted) then + local names + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #lifted do + local l = lifted[_index_0] + _accum_0[_len_0] = l[1] + _len_0 = _len_0 + 1 + end + names = _accum_0 + end + local values + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #lifted do + local l = lifted[_index_0] + _accum_0[_len_0] = l[2] + _len_0 = _len_0 + 1 + end + values = _accum_0 + end + out = build.group({ + { + "assign", + names, + values + }, + out + }) + end + return out + end, + import = function(self, node) + local names, source = unpack(node, 2) + local table_values + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #names do + local name = names[_index_0] + local dest_name + if ntype(name) == "colon" then + dest_name = name[2] + else + dest_name = name + end + local _value_0 = { + { + "key_literal", + name + }, + dest_name + } + _accum_0[_len_0] = _value_0 + _len_0 = _len_0 + 1 + end + table_values = _accum_0 + end + local dest = { + "table", + table_values + } + return { + "assign", + { + dest + }, + { + source + }, + [-1] = node[-1] + } + end, + comprehension = function(self, node, action) + local exp, clauses = unpack(node, 2) + 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] = transform_last_stm(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 ntype(name) == "ref" 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) + local clause = node[2] + if ntype(clause) == "assign" then + if destructure.has_destructure(clause[2]) then + error("destructure not allowed in unless assignment") + end + return build["do"]({ + clause, + { + "if", + { + "not", + clause[2][1] + }, + unpack(node, 3) + } + }) + else + return { + "if", + { + "not", + { + "parens", + clause + } + }, + unpack(node, 3) + } + end + end, + ["if"] = function(self, node, ret) + if ntype(node[2]) == "assign" then + local assign, body = unpack(node, 2) + if destructure.has_destructure(assign[2]) then + local name = NameProxy("des") + body = { + destructure.build_assign(self, 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'] = transform_last_stm(node['then'], ret) + for i = 4, #node do + local case = node[i] + local body_idx = #node[i] + case[body_idx] = transform_last_stm(case[body_idx], ret) + end + end + return node + end, + with = function(self, node, ret) + local exp, block = unpack(node, 2) + local copy_scope = true + local scope_name, named_assign + do + local last = last_stm(block) + if last then + if types.terminating[ntype(last)] then + ret = false + end + end + end + if ntype(exp) == "assign" then + local names, values = unpack(exp, 2) + local first_name = names[1] + if ntype(first_name) == "ref" then + scope_name = first_name + named_assign = exp + exp = values[1] + copy_scope = false + else + scope_name = NameProxy("with") + exp = values[1] + values[1] = scope_name + named_assign = { + "assign", + names, + values + } + end + elseif self:is_local(exp) then + scope_name = exp + copy_scope = false + end + scope_name = scope_name or NameProxy("with") + local out = build["do"]({ + copy_scope and build.assign_one(scope_name, exp) or NOOP, + named_assign or NOOP, + Run(function(self) + return self:set("scope_var", scope_name) + end), + unpack(block) + }) + if ret then + table.insert(out[2], ret(scope_name)) + end + return out + end, + foreach = function(self, node, _) + smart_node(node) + local source = unpack(node.iter) + local destructures = { } + do + local _accum_0 = { } + local _len_0 = 1 + for i, name in ipairs(node.names) do + if ntype(name) == "table" then + do + local proxy = NameProxy("des") + insert(destructures, destructure.build_assign(self, name, proxy)) + _accum_0[_len_0] = proxy + end + else + _accum_0[_len_0] = name + end + _len_0 = _len_0 + 1 + end + node.names = _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 = self:is_local(list) and list or 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 self:is_local(list) then + list_name = list + end + 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 + local names + do + local _accum_0 = { } + local _len_0 = 1 + local _list_0 = node.names + for _index_0 = 1, #_list_0 do + local n = _list_0[_index_0] + _accum_0[_len_0] = is_name_proxy(n) and n or LocalName(n) or n + _len_0 = _len_0 + 1 + end + names = _accum_0 + end + return build.group({ + list_name ~= list and build.assign_one(list_name, list) or NOOP, + slice_var or NOOP, + build["for"]({ + name = index_name, + bounds = bounds, + body = { + { + "assign", + names, + { + NameProxy.index(list_name, 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, 2) + 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 = transform_last_stm(body, ret) + end + insert(out, body) + return out + end + local first = true + local if_stm = { + "if" + } + for _index_0 = 1, #conds do + local cond = conds[_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 = require("moonscript.transform.class") + }) + +end +package.preload['moonscript.transform.transformer'] = function() + local ntype + ntype = require("moonscript.types").ntype + local Transformer + do + local _class_0 + local _base_0 = { + transform_once = function(self, scope, node, ...) + if self.seen_nodes[node] then + return node + end + self.seen_nodes[node] = true + local transformer = self.transformers[ntype(node)] + if transformer then + return transformer(scope, node, ...) or node + else + return node + end + end, + 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 + _class_0 = setmetatable({ + __init = function(self, transformers) + self.transformers = transformers + self.seen_nodes = setmetatable({ }, { + __mode = "k" + }) + end, + __base = _base_0, + __name = "Transformer" + }, { + __index = _base_0, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + Transformer = _class_0 + end + return { + Transformer = Transformer + } + +end +package.preload['moonscript.transform.accumulator'] = function() + local types = require("moonscript.types") + local build, ntype, NOOP + build, ntype, NOOP = types.build, types.ntype, types.NOOP + local NameProxy + NameProxy = require("moonscript.transform.names").NameProxy + local insert + insert = table.insert + 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 transform_last_stm + transform_last_stm = require("moonscript.transform.statements").transform_last_stm + local Accumulator + do + local _class_0 + 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, group_type) + if group_type == nil then + group_type = "block_exp" + end + return build[group_type]({ + build.assign_one(self.accum_name, build.table()), + build.assign_one(self.len_name, 1), + node, + group_type == "block_exp" and self.accum_name or NOOP + }) + 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 = transform_last_stm(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(NameProxy.index(self.accum_name, self.len_name), val), + { + "update", + self.len_name, + "+=", + 1 + } + } + insert(body, build.group(update)) + return body + end + } + _base_0.__index = _base_0 + _class_0 = setmetatable({ + __init = function(self, accum_name) + self.accum_name = NameProxy("accum") + self.value_name = NameProxy("value") + self.len_name = NameProxy("len") + end, + __base = _base_0, + __name = "Accumulator" + }, { + __index = _base_0, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + Accumulator = _class_0 + end + local default_accumulator + default_accumulator = function(self, node) + return Accumulator():convert(node) + end + return { + Accumulator = Accumulator, + default_accumulator = default_accumulator + } + +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 + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #op do + local item = op[_index_0] + _accum_0[_len_0] = flat_value(item, depth + 1) + _len_0 = _len_0 + 1 + end + items = _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 + local value = _list_0[_index_0] + print(flat_value(value)) + end + end + return { + value = value, + tree = tree + } + +end +package.preload['moonscript.util'] = function() + local concat + 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 split + split = function(str, delim) + if str == "" then + return { } + end + str = str .. delim + 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 + 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 + do + 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 + lines = _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 + do + 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 + tuples = _accum_0 + end + table.sort(tuples, function(a, b) + return a[1] < b[1] + end) + local lines + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #tuples do + local pair = tuples[_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 + lines = _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 + local safe_module + safe_module = function(name, tbl) + return setmetatable(tbl, { + __index = function(self, key) + return error("Attempted to import non-existent `" .. tostring(key) .. "` from " .. tostring(name)) + end + }) + end + return { + moon = moon, + pos_to_line = pos_to_line, + get_closest_line = get_closest_line, + get_line = get_line, + trim = trim, + split = split, + dump = dump, + debug_posmap = debug_posmap, + getfenv = getfenv, + setfenv = setfenv, + get_options = get_options, + unpack = unpack, + safe_module = safe_module } end @@ -284,6 +2642,7 @@ package.preload['moonscript.cmd.lint'] = function() }) local LinterBlock do + local _class_0 local _parent_0 = Block local _base_0 = { lint_mark_used = function(self, name) @@ -352,11 +2711,11 @@ package.preload['moonscript.cmd.lint'] = function() end, render = function(self, ...) self:lint_check_unused() - return _parent_0.render(self, ...) + return _class_0.__parent.__base.render(self, ...) end, block = function(self, ...) do - local _with_0 = _parent_0.block(self, ...) + local _with_0 = _class_0.__parent.__base.block(self, ...) _with_0.block = self.block _with_0.render = self.render _with_0.get_root_block = self.get_root_block @@ -370,12 +2729,12 @@ package.preload['moonscript.cmd.lint'] = function() } _base_0.__index = _base_0 setmetatable(_base_0, _parent_0.__base) - local _class_0 = setmetatable({ + _class_0 = setmetatable({ __init = function(self, whitelist_globals, ...) if whitelist_globals == nil then whitelist_globals = default_whitelist end - _parent_0.__init(self, ...) + _class_0.__parent.__init(self, ...) self.get_root_block = function() return self end @@ -438,7 +2797,10 @@ package.preload['moonscript.cmd.lint'] = function() __index = function(cls, name) local val = rawget(_base_0, name) if val == nil then - return _parent_0[name] + local parent = rawget(cls, "__parent") + if parent then + return parent[name] + end else return val end @@ -550,6 +2912,496 @@ package.preload['moonscript.cmd.lint'] = function() lint_file = lint_file } +end +package.preload['moonscript.cmd.args'] = function() + local unpack + unpack = require("moonscript.util").unpack + local parse_spec + parse_spec = function(spec) + local flags, words + if type(spec) == "table" then + flags, words = unpack(spec), spec + else + flags, words = spec, { } + end + assert("no flags for arguments") + local out = { } + for part in flags:gmatch("%w:?") do + if part:match(":$") then + out[part:sub(1, 1)] = { + value = true + } + else + out[part] = { } + end + end + return out + end + local parse_arguments + parse_arguments = function(spec, args) + spec = parse_spec(spec) + local out = { } + local remaining = { } + local last_flag = nil + for _index_0 = 1, #args do + local _continue_0 = false + repeat + local arg = args[_index_0] + local group = { } + if last_flag then + out[last_flag] = arg + _continue_0 = true + break + end + do + local flag = arg:match("-(%w+)") + if flag then + do + local short_name = spec[flag] + if short_name then + out[short_name] = true + else + for char in flag:gmatch(".") do + out[char] = true + end + end + end + _continue_0 = true + break + end + end + table.insert(remaining, arg) + _continue_0 = true + until true + if not _continue_0 then + break + end + end + return out, remaining + end + return { + parse_arguments = parse_arguments, + parse_spec = parse_spec + } + +end +package.preload['moonscript.cmd.watchers'] = function() + local remove_dupes + remove_dupes = function(list, key_fn) + local seen = { } + return (function() + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #list do + local _continue_0 = false + repeat + local item = list[_index_0] + local key + if key_fn then + key = key_fn(item) + else + key = item + end + if seen[key] then + _continue_0 = true + break + end + seen[key] = true + local _value_0 = item + _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 + local plural + plural = function(count, word) + return tostring(count) .. " " .. tostring(word) .. tostring(count == 1 and "" or "s") + end + local Watcher + do + local _class_0 + local _base_0 = { + start_msg = "Starting watch loop (Ctrl-C to exit)", + print_start = function(self, mode, misc) + return io.stderr:write(tostring(self.start_msg) .. " with " .. tostring(mode) .. " [" .. tostring(misc) .. "]\n") + end + } + _base_0.__index = _base_0 + _class_0 = setmetatable({ + __init = function(self, file_list) + self.file_list = file_list + end, + __base = _base_0, + __name = "Watcher" + }, { + __index = _base_0, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + Watcher = _class_0 + end + local InotifyWacher + do + local _class_0 + local _parent_0 = Watcher + local _base_0 = { + get_dirs = function(self) + local parse_dir + parse_dir = require("moonscript.cmd.moonc").parse_dir + local dirs + do + local _accum_0 = { } + local _len_0 = 1 + local _list_0 = self.file_list + for _index_0 = 1, #_list_0 do + local _des_0 = _list_0[_index_0] + local file_path + file_path = _des_0[1] + local dir = parse_dir(file_path) + if dir == "" then + dir = "./" + end + local _value_0 = dir + _accum_0[_len_0] = _value_0 + _len_0 = _len_0 + 1 + end + dirs = _accum_0 + end + return remove_dupes(dirs) + end, + each_update = function(self) + return coroutine.wrap(function() + local dirs = self:get_dirs() + self:print_start("inotify", plural(#dirs, "dir")) + local wd_table = { } + local inotify = require("inotify") + local handle = inotify.init() + for _index_0 = 1, #dirs do + local dir = dirs[_index_0] + local wd = handle:addwatch(dir, inotify.IN_CLOSE_WRITE, inotify.IN_MOVED_TO) + wd_table[wd] = dir + end + while true do + local events = handle:read() + if not (events) then + break + end + for _index_0 = 1, #events do + local _continue_0 = false + repeat + local ev = events[_index_0] + local fname = ev.name + if not (fname:match("%.moon$")) then + _continue_0 = true + break + end + local dir = wd_table[ev.wd] + if dir ~= "./" then + fname = dir .. fname + end + coroutine.yield(fname) + _continue_0 = true + until true + if not _continue_0 then + break + end + end + end + end) + end + } + _base_0.__index = _base_0 + setmetatable(_base_0, _parent_0.__base) + _class_0 = setmetatable({ + __init = function(self, ...) + return _class_0.__parent.__init(self, ...) + end, + __base = _base_0, + __name = "InotifyWacher", + __parent = _parent_0 + }, { + __index = function(cls, name) + local val = rawget(_base_0, name) + if val == nil then + local parent = rawget(cls, "__parent") + if parent then + return parent[name] + end + else + return val + end + end, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + local self = _class_0 + self.available = function(self) + return pcall(function() + return require("inotify") + end) + end + if _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + InotifyWacher = _class_0 + end + local SleepWatcher + do + local _class_0 + local _parent_0 = Watcher + local _base_0 = { + polling_rate = 1.0, + get_sleep_func = function(self) + local sleep + pcall(function() + sleep = require("socket").sleep + end) + sleep = sleep or require("moonscript")._sleep + if not (sleep) then + error("Missing sleep function; install LuaSocket") + end + return sleep + end, + each_update = function(self) + return coroutine.wrap(function() + local lfs = require("lfs") + local sleep = self:get_sleep_func() + self:print_start("polling", plural(#self.file_list, "files")) + local mod_time = { } + while true do + local _list_0 = self.file_list + for _index_0 = 1, #_list_0 do + local _continue_0 = false + repeat + local _des_0 = _list_0[_index_0] + local file + file = _des_0[1] + local time = lfs.attributes(file, "modification") + if not (time) then + mod_time[file] = nil + _continue_0 = true + break + end + if not (mod_time[file]) then + mod_time[file] = time + _continue_0 = true + break + end + if time > mod_time[file] then + mod_time[file] = time + coroutine.yield(file) + end + _continue_0 = true + until true + if not _continue_0 then + break + end + end + sleep(self.polling_rate) + end + end) + end + } + _base_0.__index = _base_0 + setmetatable(_base_0, _parent_0.__base) + _class_0 = setmetatable({ + __init = function(self, ...) + return _class_0.__parent.__init(self, ...) + end, + __base = _base_0, + __name = "SleepWatcher", + __parent = _parent_0 + }, { + __index = function(cls, name) + local val = rawget(_base_0, name) + if val == nil then + local parent = rawget(cls, "__parent") + if parent then + return parent[name] + end + else + return val + end + end, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + if _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + SleepWatcher = _class_0 + end + return { + Watcher = Watcher, + SleepWatcher = SleepWatcher, + InotifyWacher = InotifyWacher + } + +end +package.preload['moonscript.cmd.coverage'] = function() + local log + log = function(str) + if str == nil then + str = "" + end + return io.stderr:write(str .. "\n") + end + local create_counter + create_counter = function() + return setmetatable({ }, { + __index = function(self, name) + do + local tbl = setmetatable({ }, { + __index = function(self) + return 0 + end + }) + self[name] = tbl + return tbl + end + end + }) + end + local position_to_lines + position_to_lines = function(file_content, positions) + local lines = { } + local current_pos = 0 + local line_no = 1 + for char in file_content:gmatch(".") do + do + local count = rawget(positions, current_pos) + if count then + lines[line_no] = count + end + end + if char == "\n" then + line_no = line_no + 1 + end + current_pos = current_pos + 1 + end + return lines + end + local format_file + format_file = function(fname, positions) + fname = fname:gsub("^@", "") + local file = assert(io.open(fname)) + local content = file:read("*a") + file:close() + local lines = position_to_lines(content, positions) + log("------| @" .. tostring(fname)) + local line_no = 1 + for line in (content .. "\n"):gmatch("(.-)\n") do + local foramtted_no = ("% 5d"):format(line_no) + local sym = lines[line_no] and "*" or " " + log(tostring(sym) .. tostring(foramtted_no) .. "| " .. tostring(line)) + line_no = line_no + 1 + end + return log() + end + local CodeCoverage + do + local _class_0 + local _base_0 = { + reset = function(self) + self.line_counts = create_counter() + end, + start = function(self) + return debug.sethook((function() + local _base_1 = self + local _fn_0 = _base_1.process_line + return function(...) + return _fn_0(_base_1, ...) + end + end)(), "l") + end, + stop = function(self) + return debug.sethook() + end, + print_results = function(self) + return self:format_results() + end, + process_line = function(self, _, line_no) + local debug_data = debug.getinfo(2, "S") + local source = debug_data.source + self.line_counts[source][line_no] = self.line_counts[source][line_no] + 1 + end, + format_results = function(self) + local line_table = require("moonscript.line_tables") + local positions = create_counter() + for file, lines in pairs(self.line_counts) do + local _continue_0 = false + repeat + local file_table = line_table[file] + if not (file_table) then + _continue_0 = true + break + end + for line, count in pairs(lines) do + local _continue_1 = false + repeat + local position = file_table[line] + if not (position) then + _continue_1 = true + break + end + positions[file][position] = positions[file][position] + count + _continue_1 = true + until true + if not _continue_1 then + break + end + end + _continue_0 = true + until true + if not _continue_0 then + break + end + end + for file, ps in pairs(positions) do + format_file(file, ps) + end + end + } + _base_0.__index = _base_0 + _class_0 = setmetatable({ + __init = function(self) + return self:reset() + end, + __base = _base_0, + __name = "CodeCoverage" + }, { + __index = _base_0, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + CodeCoverage = _class_0 + end + return { + CodeCoverage = CodeCoverage + } + end package.preload['moonscript.cmd.moonc'] = function() local lfs = require("lfs") @@ -635,6 +3487,12 @@ package.preload['moonscript.cmd.moonc'] = function() if opts.benchmark then compile_time = gettime() end + do + local mod = opts.transform_module + if mod then + tree = assert(require(mod)(tree)) + end + end local code, posmap_or_err, err_pos = compile.tree(tree) if not (code) then return nil, compile.format_error(posmap_or_err, err_pos, text) @@ -656,7 +3514,7 @@ package.preload['moonscript.cmd.moonc'] = function() "Compile time\t" .. format_time(compile_time), "" }, "\n")) - return nil + return true end return code end @@ -745,248 +3603,8 @@ package.preload['moonscript.cmd.moonc'] = function() } end -package.preload['moonscript.compile.statement'] = function() - local util = require("moonscript.util") - local reversed, unpack - reversed, unpack = util.reversed, util.unpack - local ntype - ntype = require("moonscript.types").ntype - local concat, insert - do - local _obj_0 = table - concat, insert = _obj_0.concat, _obj_0.insert - end - return { - 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 - for _index_0 = 1, #undeclared do - local name = undeclared[_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 - for _index_0 = 1, #names do - local name = names[_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, node[-1]) - end - _with_0:append_list((function() - local _accum_0 = { } - local _len_0 = 1 - for _index_0 = 1, #names do - local name = names[_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 - for _index_0 = 1, #values do - local v = values[_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 - for _index_0 = 4, #node do - cond = node[_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 - for _index_0 = 1, #names do - local name = names[_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 - for _index_0 = 1, #exps do - local exp = exps[_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, - noop = function(self) end - } +package.preload['moonscript.line_tables'] = function() + return { } end package.preload['moonscript.compile.value'] = function() @@ -1009,6 +3627,16 @@ package.preload['moonscript.compile.value'] = function() ["\n"] = "\\n" } return { + scoped = function(self, node) + local _, before, value, after + _, before, value, after = node[1], node[2], node[3], node[4] + _ = before and before:call(self) + do + local _with_0 = self:value(value) + _ = after and after:call(self) + return _with_0 + end + end, exp = function(self, node) local _comp _comp = function(i, value) @@ -1053,7 +3681,7 @@ package.preload['moonscript.compile.value'] = function() return self:line("(", self:value(node[2]), ")") end, string = function(self, node) - local _, delim, inner = unpack(node) + local delim, inner = unpack(node, 2) local end_delim = delim:gsub("%[", "]") if delim == "'" or delim == '"' then inner = inner:gsub("[\r\n]", string_chars) @@ -1063,11 +3691,13 @@ package.preload['moonscript.compile.value'] = function() chain = function(self, node) local callee = node[2] local callee_type = ntype(callee) - if callee == -1 then + local item_offset = 3 + if callee_type == "dot" or callee_type == "colon" or callee_type == "index" then callee = self:get("scope_var") - if not callee then + if not (callee) then user_error("Short-dot syntax must be called within a with block") end + item_offset = 2 end if callee_type == "ref" and callee[2] == "super" or callee == "super" then do @@ -1087,7 +3717,7 @@ package.preload['moonscript.compile.value'] = function() elseif t == "dot" then return ".", tostring(arg) elseif t == "colon" then - return ":", arg, chain_item(node[3]) + return ":", tostring(arg) elseif t == "colon_stub" then return user_error("Uncalled colon stub") else @@ -1104,7 +3734,7 @@ package.preload['moonscript.compile.value'] = function() local actions do local _with_0 = self:line() - for _index_0 = 3, #node do + for _index_0 = item_offset, #node do local action = node[_index_0] _with_0:append(chain_item(action)) end @@ -1113,7 +3743,7 @@ package.preload['moonscript.compile.value'] = function() return self:line(callee_value, actions) end, fndef = function(self, node) - local _, args, whitelist, arrow, block = unpack(node) + local args, whitelist, arrow, block = unpack(node, 2) local default_args = { } local self_args = { } local arg_names @@ -1218,7 +3848,7 @@ package.preload['moonscript.compile.value'] = function() end end, table = function(self, node) - local _, items = unpack(node) + local items = unpack(node, 2) do local _with_0 = self:block("{", "}") local format_line @@ -1238,9 +3868,7 @@ package.preload['moonscript.compile.value'] = function() 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])) @@ -1268,6 +3896,9 @@ package.preload['moonscript.compile.value'] = function() number = function(self, node) return node[2] end, + bitnot = function(self, node) + return self:line("~", self:value(node[2])) + end, length = function(self, node) return self:line("#", self:value(node[2])) end, @@ -1303,6 +3934,1058 @@ package.preload['moonscript.compile.value'] = function() end } +end +package.preload['moonscript.compile.statement'] = function() + local ntype + ntype = require("moonscript.types").ntype + local concat, insert + do + local _obj_0 = table + concat, insert = _obj_0.concat, _obj_0.insert + end + local unpack + unpack = require("moonscript.util").unpack + return { + 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 + for _index_0 = 1, #undeclared do + local name = undeclared[_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 + for _index_0 = 1, #names do + local name = names[_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, 2) + 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, node[-1]) + end + _with_0:append_list((function() + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #names do + local name = names[_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 + for _index_0 = 1, #values do + local v = values[_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 + for _index_0 = 4, #node do + local cond = node[_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, 2) + 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, 2) + 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, 2) + 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 + for _index_0 = 1, #names do + local name = names[_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 + for _index_0 = 1, #exps do + local exp = exps[_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, 2) + 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, + noop = function(self) end + } + +end +package.preload['moonscript.types'] = function() + local util = require("moonscript.util") + local Set + Set = require("moonscript.data").Set + local insert + insert = table.insert + local unpack + unpack = util.unpack + local manual_return = Set({ + "foreach", + "for", + "while", + "return" + }) + local cascading = Set({ + "if", + "unless", + "with", + "switch", + "class", + "do" + }) + local terminating = Set({ + "return", + "break" + }) + 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 value_can_be_statement + value_can_be_statement = function(node) + if not (ntype(node) == "chain") then + return false + end + return ntype(node[#node]) == "call" + 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 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 + for _index_0 = 1, #tbl do + local tuple = tbl[_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") + if type(base) == "string" then + base = { + "ref", + base + } + end + local node = { + "chain", + base + } + for _index_0 = 1, #parts do + local part = parts[_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 + local NOOP = { + "noop" + } + 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, + value_can_be_statement = value_can_be_statement, + mtype = mtype, + terminating = terminating, + NOOP = NOOP + } + +end +package.preload['moonscript.version'] = function() + local version = "0.5.0" + return { + version = version, + print_version = function() + return print("MoonScript version " .. tostring(version)) + end + } + +end +package.preload['moonscript.errors'] = function() + local util = require("moonscript.util") + local lpeg = require("lpeg") + local concat, insert + do + local _obj_0 = table + concat, insert = _obj_0.concat, _obj_0.insert + end + local split, pos_to_line + 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 = assert(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 + do + local _accum_0 = { } + local _len_0 = 1 + local _max_0 = stop + for _index_0 = 1, _max_0 < 0 and #traceback + _max_0 or _max_0 do + local t = traceback[_index_0] + _accum_0[_len_0] = t + _len_0 = _len_0 + 1 + end + traceback = _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 + 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('^(.-):(%d+): (.*)$') + local tbl = line_tables["@" .. tostring(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, + reverse_line_number = reverse_line_number + } + +end +package.preload['moonscript.parse'] = function() + local debug_grammar = false + local lpeg = require("lpeg") + lpeg.setmaxstack(10000) + local err_msg = "Failed to parse:%s\n [%d] >> %s" + local Stack + Stack = require("moonscript.data").Stack + local trim, pos_to_line, get_line + do + local _obj_0 = require("moonscript.util") + trim, pos_to_line, get_line = _obj_0.trim, _obj_0.pos_to_line, _obj_0.get_line + end + local unpack + unpack = require("moonscript.util").unpack + local wrap_env + wrap_env = require("moonscript.parse.env").wrap_env + local R, S, V, P, C, Ct, Cmt, Cg, Cb, Cc + R, S, V, P, C, Ct, Cmt, Cg, Cb, Cc = lpeg.R, lpeg.S, lpeg.V, lpeg.P, lpeg.C, lpeg.Ct, lpeg.Cmt, lpeg.Cg, lpeg.Cb, lpeg.Cc + local White, Break, Stop, Comment, Space, SomeSpace, SpaceBreak, EmptyLine, AlphaNum, Num, Shebang, L, _Name + do + local _obj_0 = require("moonscript.parse.literals") + White, Break, Stop, Comment, Space, SomeSpace, SpaceBreak, EmptyLine, AlphaNum, Num, Shebang, L, _Name = _obj_0.White, _obj_0.Break, _obj_0.Stop, _obj_0.Comment, _obj_0.Space, _obj_0.SomeSpace, _obj_0.SpaceBreak, _obj_0.EmptyLine, _obj_0.AlphaNum, _obj_0.Num, _obj_0.Shebang, _obj_0.L, _obj_0.Name + end + local SpaceName = Space * _Name + Num = Space * (Num / function(v) + return { + "number", + v + } + end) + local Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, join_chain, wrap_decorator, check_lua_string, self_assign, got + do + local _obj_0 = require("moonscript.parse.util") + Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, join_chain, wrap_decorator, check_lua_string, self_assign, got = _obj_0.Indent, _obj_0.Cut, _obj_0.ensure, _obj_0.extract_line, _obj_0.mark, _obj_0.pos, _obj_0.flatten_or_mark, _obj_0.is_assignable, _obj_0.check_assignable, _obj_0.format_assign, _obj_0.format_single_assign, _obj_0.sym, _obj_0.symx, _obj_0.simple_string, _obj_0.wrap_func_arg, _obj_0.join_chain, _obj_0.wrap_decorator, _obj_0.check_lua_string, _obj_0.self_assign, _obj_0.got + end + local build_grammar = wrap_env(debug_grammar, function(root) + local _indent = Stack(0) + local _do_stack = Stack(0) + local state = { + last_pos = 0 + } + local check_indent + check_indent = function(str, pos, indent) + state.last_pos = pos + return _indent:top() == indent + end + local advance_indent + advance_indent = function(str, pos, indent) + local top = _indent:top() + if top ~= -1 and indent > top then + _indent:push(indent) + return true + end + end + local push_indent + push_indent = function(str, pos, indent) + _indent:push(indent) + return true + end + local pop_indent + pop_indent = function() + assert(_indent:pop(), "unexpected outdent") + return true + end + local check_do + check_do = function(str, pos, do_node) + local top = _do_stack:top() + if top == nil or top then + return true, do_node + end + return false + end + local disable_do + disable_do = function() + _do_stack:push(false) + return true + end + local pop_do + pop_do = function() + assert(_do_stack:pop() ~= nil, "unexpected do pop") + return true + end + local DisableDo = Cmt("", disable_do) + local PopDo = Cmt("", pop_do) + local keywords = { } + local key + key = function(chars) + keywords[chars] = true + return Space * chars * -AlphaNum + end + local op + op = function(chars) + local patt = Space * C(chars) + if chars:match("^%w*$") then + keywords[chars] = true + patt = patt * -AlphaNum + end + return patt + end + local Name = Cmt(SpaceName, 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 VarArg = Space * P("...") / trim + local g = P({ + root or File, + File = Shebang ^ -1 * (Block + Ct("")), + Block = Ct(Line * (Break ^ 1 * Line) ^ 0), + CheckIndent = Cmt(Indent, check_indent), + Line = (CheckIndent * Statement + Space * L(Stop)), + Statement = pos(Import + While + With + For + ForEach + Switch + Return + Local + Export + BreakLoop + Ct(ExpList) * (Update + Assign) ^ -1 / format_assign) * Space * ((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), + Advance = L(Cmt(Indent, advance_indent)), + 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) * SpaceBreak ^ 0 * key("from") * Exp / mark("import"), + ImportName = (sym("\\") * Ct(Cc("colon") * Name) + Name), + ImportNameList = SpaceBreak ^ 0 * ImportName * ((SpaceBreak ^ 1 + sym(",") * SpaceBreak ^ 0) * ImportName) ^ 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, + IfElse = (Break * EmptyLine ^ 0 * CheckIndent) ^ -1 * key("else") * Body / mark("else"), + IfElseIf = (Break * EmptyLine ^ 0 * CheckIndent) ^ -1 * key("elseif") * pos(IfCond) * key("then") ^ -1 * Body / mark("elseif"), + If = key("if") * IfCond * key("then") ^ -1 * Body * IfElseIf ^ 0 * IfElse ^ -1 / mark("if"), + Unless = key("unless") * IfCond * key("then") ^ -1 * Body * IfElseIf ^ 0 * IfElse ^ -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(AssignableNameList) * 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=") + sym("&=") + sym("|=") + sym(">>=") + sym("<<=")) / trim) * Exp / mark("update"), + CharOperators = Space * C(S("+-*/%^><|&")), + WordOperators = op("or") + op("and") + op("<=") + op(">=") + op("~=") + op("!=") + op("==") + op("..") + op("<<") + op(">>") + op("//"), + BinaryOperator = (WordOperators + CharOperators) * SpaceBreak ^ 0, + Assignable = Cmt(Chain, check_assignable) + Name + SelfName, + Exp = Ct(Value * (BinaryOperator * 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") + sym("~") * Exp / mark("bitnot") + key("not") * Exp / mark("not") + TblComprehension + TableLit + Comprehension + FunLit + Num, + ChainValue = (Chain + Callable) * Ct(InvokeArgs ^ -1) / join_chain, + Value = pos(SimpleValue + Ct(KeyValueList) / mark("table") + ChainValue + String), + SliceValue = Exp, + 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 = pos(Name / mark("ref")) + SelfName + VarArg + Parens / mark("parens"), + Parens = sym("(") * SpaceBreak ^ 0 * Exp * SpaceBreak ^ 0 * sym(")"), + FnArgs = symx("(") * SpaceBreak ^ 0 * Ct(FnArgsExpList ^ -1) * SpaceBreak ^ 0 * sym(")") + sym("!") * -P("=") * Ct(""), + FnArgsExpList = Exp * ((Break + sym(",")) * White * Exp) ^ 0, + Chain = (Callable + String + -S(".\\")) * ChainItems / mark("chain") + Space * (DotChainItem * ChainItems ^ -1 + ColonChain) / mark("chain"), + ChainItems = ChainItem ^ 1 * ColonChain ^ -1 + ColonChain, + ChainItem = Invoke + DotChainItem + Slice + symx("[") * Exp / mark("index") * sym("]"), + DotChainItem = symx(".") * _Name / mark("dot"), + ColonChainItem = symx("\\") * _Name / mark("colon"), + ColonChain = ColonChainItem * (Invoke * ChainItems ^ -1) ^ -1, + Slice = symx("[") * (SliceValue + Cc(1)) * sym(",") * (SliceValue + Cc("")) * (sym(",") * SliceValue) ^ -1 * sym("]") / mark("slice"), + Invoke = FnArgs / mark("call") + SingleString / wrap_func_arg + DoubleString / wrap_func_arg + L(P("[")) * LuaString / 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, + 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(":") * -SomeSpace * Name * lpeg.Cp()) / self_assign + Ct((KeyName + sym("[") * Exp * sym("]") + Space * DoubleString + Space * SingleString) * symx(":") * (Exp + TableBlock + SpaceBreak ^ 1 * Exp)), + KeyValueList = KeyValue * (sym(",") * KeyValue) ^ 0, + KeyValueLine = CheckIndent * KeyValueList * sym(",") ^ -1, + FnArgsDef = sym("(") * White * Ct(FnArgDefList ^ -1) * (key("using") * Ct(NameList + Space * "nil") + Ct("")) * White * sym(")") + Ct("") * Ct(""), + FnArgDefList = FnArgDef * ((sym(",") + Break) * White * FnArgDef) ^ 0 * ((sym(",") + Break) * White * Ct(VarArg)) ^ 0 + Ct(VarArg), + FnArgDef = Ct((Name + SelfName) * (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, state + end) + local file_parser + file_parser = function() + local g, state = build_grammar() + local file_grammar = White * g * White * -1 + return { + match = function(self, str) + local tree + local _, err = xpcall((function() + tree = file_grammar:match(str) + end), function(err) + return debug.traceback(err, 2) + end) + if type(err) == "string" then + return nil, err + end + if not (tree) then + local msg + local err_pos = state.last_pos + if err then + local node + node, msg = unpack(err) + if msg then + msg = " " .. msg + end + err_pos = node[-1] + end + local line_no = pos_to_line(str, err_pos) + local line_str = get_line(str, 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, + build_grammar = build_grammar, + string = function(str) + return file_parser():match(str) + end + } + +end +package.preload['moonscript.base'] = function() + local compile = require("moonscript.compile") + local parse = require("moonscript.parse") + local concat, insert, remove + do + local _obj_0 = table + concat, insert, remove = _obj_0.concat, _obj_0.insert, _obj_0.remove + end + local split, dump, get_options, unpack + do + local _obj_0 = require("moonscript.util") + split, dump, get_options, unpack = _obj_0.split, _obj_0.dump, _obj_0.get_options, _obj_0.unpack + end + local lua = { + loadstring = loadstring, + load = load + } + local dirsep, line_tables, create_moonpath, to_lua, loadstring, loadfile, dofile + dirsep = "/" + line_tables = require("moonscript.line_tables") + create_moonpath = function(package_path) + local moonpaths + do + local _accum_0 = { } + local _len_0 = 1 + local _list_0 = split(package_path, ";") + for _index_0 = 1, #_list_0 do + local _continue_0 = false + repeat + local path = _list_0[_index_0] + local prefix = path:match("^(.-)%.lua$") + if not (prefix) then + _continue_0 = true + break + end + local _value_0 = prefix .. ".moon" + _accum_0[_len_0] = _value_0 + _len_0 = _len_0 + 1 + _continue_0 = true + until true + if not _continue_0 then + break + end + end + moonpaths = _accum_0 + end + return concat(moonpaths, ";") + 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 .. ")" + 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) + end + return code, ltable + 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, "@" .. tostring(fname), ...) + end + dofile = function(...) + local f = assert(loadfile(...)) + return f() + end + return { + _NAME = "moonscript", + to_lua = to_lua, + dirsep = dirsep, + dofile = dofile, + loadfile = loadfile, + loadstring = loadstring, + create_moonpath = create_moonpath + } + end package.preload['moonscript.compile'] = function() local util = require("moonscript.util") @@ -1315,10 +4998,10 @@ package.preload['moonscript.compile'] = function() end local Set Set = require("moonscript.data").Set - local ntype, has_value + local ntype, value_can_be_statement do local _obj_0 = require("moonscript.types") - ntype, has_value = _obj_0.ntype, _obj_0.has_value + ntype, value_can_be_statement = _obj_0.ntype, _obj_0.value_can_be_statement end local statement_compilers = require("moonscript.compile.statement") local value_compilers = require("moonscript.compile.value") @@ -1333,6 +5016,7 @@ package.preload['moonscript.compile'] = function() local indent_char = " " local Line, DelayedLine, Lines, Block, RootBlock do + local _class_0 local _base_0 = { mark_pos = function(self, pos, line) if line == nil then @@ -1434,7 +5118,7 @@ package.preload['moonscript.compile'] = function() end } _base_0.__index = _base_0 - local _class_0 = setmetatable({ + _class_0 = setmetatable({ __init = function(self) self.posmap = { } end, @@ -1452,6 +5136,7 @@ package.preload['moonscript.compile'] = function() Lines = _class_0 end do + local _class_0 local _base_0 = { pos = nil, append_list = function(self, items, delim) @@ -1515,7 +5200,7 @@ package.preload['moonscript.compile'] = function() end } _base_0.__index = _base_0 - local _class_0 = setmetatable({ + _class_0 = setmetatable({ __init = function() end, __base = _base_0, __name = "Line" @@ -1531,6 +5216,7 @@ package.preload['moonscript.compile'] = function() Line = _class_0 end do + local _class_0 local _base_0 = { prepare = function() end, render = function(self) @@ -1539,7 +5225,7 @@ package.preload['moonscript.compile'] = function() end } _base_0.__index = _base_0 - local _class_0 = setmetatable({ + _class_0 = setmetatable({ __init = function(self, fn) self.prepare = fn end, @@ -1557,6 +5243,7 @@ package.preload['moonscript.compile'] = function() DelayedLine = _class_0 end do + local _class_0 local _base_0 = { header = "do", footer = "end", @@ -1832,7 +5519,9 @@ package.preload['moonscript.compile'] = function() if fn then result = fn(self, node, ...) else - if has_value(node) then + if value_can_be_statement(node) then + result = self:value(node) + else result = self:stm({ "assign", { @@ -1842,8 +5531,6 @@ package.preload['moonscript.compile'] = function() node } }) - else - result = self:value(node) end end end @@ -1880,7 +5567,7 @@ package.preload['moonscript.compile'] = function() end } _base_0.__index = _base_0 - local _class_0 = setmetatable({ + _class_0 = setmetatable({ __init = function(self, parent, header, footer) self.parent, self.header, self.footer = parent, header, footer self._lines = Lines() @@ -1920,6 +5607,7 @@ package.preload['moonscript.compile'] = function() Block = _class_0 end do + local _class_0 local _parent_0 = Block local _base_0 = { __tostring = function(self) @@ -1941,11 +5629,11 @@ package.preload['moonscript.compile'] = function() } _base_0.__index = _base_0 setmetatable(_base_0, _parent_0.__base) - local _class_0 = setmetatable({ + _class_0 = setmetatable({ __init = function(self, options) self.options = options self.root = self - return _parent_0.__init(self) + return _class_0.__parent.__init(self) end, __base = _base_0, __name = "RootBlock", @@ -1954,7 +5642,10 @@ package.preload['moonscript.compile'] = function() __index = function(cls, name) local val = rawget(_base_0, name) if val == nil then - return _parent_0[name] + local parent = rawget(cls, "__parent") + if parent then + return parent[name] + end else return val end @@ -2046,375 +5737,6 @@ package.preload['moonscript.compile'] = function() RootBlock = RootBlock } -end -package.preload['moonscript.data'] = function() - local concat, remove, insert - do - local _obj_0 = table - concat, remove, insert = _obj_0.concat, _obj_0.remove, _obj_0.insert - end - local Set - Set = function(items) - local _tbl_0 = { } - for _index_0 = 1, #items do - local k = items[_index_0] - _tbl_0[k] = true - end - return _tbl_0 - end - local Stack - do - local _base_0 = { - __tostring = function(self) - return "" - end, - pop = function(self) - return remove(self) - end, - push = function(self, value, ...) - insert(self, value) - if ... then - return self:push(...) - else - return value - end - end, - top = function(self) - return self[#self] - end - } - _base_0.__index = _base_0 - local _class_0 = setmetatable({ - __init = function(self, ...) - self:push(...) - return nil - end, - __base = _base_0, - __name = "Stack" - }, { - __index = _base_0, - __call = function(cls, ...) - local _self_0 = setmetatable({}, _base_0) - cls.__init(_self_0, ...) - return _self_0 - end - }) - _base_0.__class = _class_0 - 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 - do - local _accum_0 = { } - local _len_0 = 1 - for _index_0 = 1, #op do - local item = op[_index_0] - _accum_0[_len_0] = flat_value(item, depth + 1) - _len_0 = _len_0 + 1 - end - items = _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 - do - local _obj_0 = table - concat, insert = _obj_0.concat, _obj_0.insert - end - local split, pos_to_line - 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 = assert(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 - do - local _accum_0 = { } - local _len_0 = 1 - local _max_0 = stop - for _index_0 = 1, _max_0 < 0 and #traceback + _max_0 or _max_0 do - local t = traceback[_index_0] - _accum_0[_len_0] = t - _len_0 = _len_0 + 1 - end - traceback = _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 - 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('^(.-):(%d+): (.*)$') - local tbl = line_tables["@" .. tostring(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, - reverse_line_number = reverse_line_number - } - -end -package.preload['moonscript'] = function() - do - local _with_0 = require("moonscript.base") - return _with_0 - end - -end -package.preload['moonscript.line_tables'] = function() - return { } - -end -package.preload['moonscript.parse.env'] = function() - local getfenv, setfenv - do - local _obj_0 = require("moonscript.util") - getfenv, setfenv = _obj_0.getfenv, _obj_0.setfenv - end - local wrap_env - wrap_env = function(debug, fn) - local V, Cmt - do - local _obj_0 = require("lpeg") - V, Cmt = _obj_0.V, _obj_0.Cmt - end - local env = getfenv(fn) - local wrap_name = V - if debug then - local indent = 0 - local indent_char = " " - local iprint - iprint = function(...) - local args = table.concat((function(...) - local _accum_0 = { } - local _len_0 = 1 - local _list_0 = { - ... - } - for _index_0 = 1, #_list_0 do - local a = _list_0[_index_0] - _accum_0[_len_0] = tostring(a) - _len_0 = _len_0 + 1 - end - return _accum_0 - end)(...), ", ") - return io.stderr:write(tostring(indent_char:rep(indent)) .. tostring(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) - return v - end - return error("unknown variable referenced: " .. tostring(name)) - end - })) - end - return { - wrap_env = wrap_env - } - -end -package.preload['moonscript.parse.literals'] = function() - local safe_module - safe_module = require("moonscript.util").safe_module - local S, P, R, C - do - local _obj_0 = require("lpeg") - S, P, R, C = _obj_0.S, _obj_0.P, _obj_0.R, _obj_0.C - end - local White = S(" \t\r\n") ^ 0 - local plain_space = S(" \t") ^ 0 - local Break = P("\r") ^ -1 * P("\n") - local Stop = Break + -1 - local Comment = P("--") * (1 - S("\r\n")) ^ 0 * #Stop - local Space = plain_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 Num = P("0x") * R("09", "af", "AF") ^ 1 * (S("uU") ^ -1 * S("lL") ^ 2) ^ -1 + R("09") ^ 1 * (S("uU") ^ -1 * S("lL") ^ 2) + (R("09") ^ 1 * (P(".") * R("09") ^ 1) ^ -1 + P(".") * R("09") ^ 1) * (S("eE") * P("-") ^ -1 * R("09") ^ 1) ^ -1 - local Shebang = P("#!") * P(1 - Stop) ^ 0 - return safe_module("moonscript.parse.literals", { - White = White, - Break = Break, - Stop = Stop, - Comment = Comment, - Space = Space, - SomeSpace = SomeSpace, - SpaceBreak = SpaceBreak, - EmptyLine = EmptyLine, - AlphaNum = AlphaNum, - Name = Name, - Num = Num, - Shebang = Shebang - }) - end package.preload['moonscript.parse.util'] = function() local unpack @@ -2460,6 +5782,58 @@ package.preload['moonscript.parse.util'] = function() end return str:match("^.-$") end + local show_line_position + show_line_position = function(str, pos, context) + if context == nil then + context = true + end + local lines = { + { } + } + for c in str:gmatch(".") do + lines[#lines] = lines[#lines] or { } + table.insert(lines[#lines], c) + if c == "\n" then + lines[#lines + 1] = { } + end + end + for i, line in ipairs(lines) do + lines[i] = table.concat(line) + end + local out + local remaining = pos - 1 + for k, line in ipairs(lines) do + if remaining < #line then + local left = line:sub(1, remaining) + local right = line:sub(remaining + 1) + out = { + tostring(left) .. "â—‰" .. tostring(right) + } + if context then + do + local before = lines[k - 1] + if before then + table.insert(out, 1, before) + end + end + do + local after = lines[k + 1] + if after then + table.insert(out, after) + end + end + end + break + else + remaining = remaining - #line + end + end + if not (out) then + return "-" + end + out = table.concat(out) + return (out:gsub("\n*$", "")) + end local mark mark = function(name) return function(...) @@ -2479,9 +5853,12 @@ package.preload['moonscript.parse.util'] = function() end end local got - got = function(what) + got = function(what, context) + if context == nil then + context = true + end return Cmt("", function(str, pos) - print("++ got " .. tostring(what), "[" .. tostring(extract_line(str, pos)) .. "]") + print("++ got " .. tostring(what), "[" .. tostring(show_line_position(str, pos, context)) .. "]") return true end) end @@ -2597,8 +5974,8 @@ package.preload['moonscript.parse.util'] = function() } } end - local flatten_func - flatten_func = function(callee, args) + local join_chain + join_chain = function(callee, args) if #args == 0 then return callee end @@ -2607,13 +5984,7 @@ package.preload['moonscript.parse.util'] = function() args } if ntype(callee) == "chain" then - local stub = callee[#callee] - if ntype(stub) == "colon_stub" then - stub[1] = "colon" - table.insert(stub, args) - else - table.insert(callee, args) - end + table.insert(callee, args) return callee end return { @@ -2622,17 +5993,6 @@ package.preload['moonscript.parse.util'] = function() args } end - local flatten_string_chain - flatten_string_chain = function(str, chain, args) - if not (chain) then - return str - end - return flatten_func({ - "chain", - str, - unpack(chain) - }, args) - end local wrap_decorator wrap_decorator = function(stm, dec) if not (dec) then @@ -2678,578 +6038,182 @@ package.preload['moonscript.parse.util'] = function() symx = symx, simple_string = simple_string, wrap_func_arg = wrap_func_arg, - flatten_func = flatten_func, - flatten_string_chain = flatten_string_chain, + join_chain = join_chain, wrap_decorator = wrap_decorator, check_lua_string = check_lua_string, - self_assign = self_assign + self_assign = self_assign, + got = got, + show_line_position = show_line_position } end -package.preload['moonscript.parse'] = function() - local debug_grammar = false +package.preload['moonscript.parse.literals'] = function() + local safe_module + safe_module = require("moonscript.util").safe_module + local S, P, R, C + do + local _obj_0 = require("lpeg") + S, P, R, C = _obj_0.S, _obj_0.P, _obj_0.R, _obj_0.C + end local lpeg = require("lpeg") - lpeg.setmaxstack(10000) - local err_msg = "Failed to parse:%s\n [%d] >> %s" - local Stack - Stack = require("moonscript.data").Stack - local trim, pos_to_line, get_line + local L = lpeg.luversion and lpeg.L or function(v) + return #v + end + local White = S(" \t\r\n") ^ 0 + local plain_space = S(" \t") ^ 0 + local Break = P("\r") ^ -1 * P("\n") + local Stop = Break + -1 + local Comment = P("--") * (1 - S("\r\n")) ^ 0 * L(Stop) + local Space = plain_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 Num = P("0x") * R("09", "af", "AF") ^ 1 * (S("uU") ^ -1 * S("lL") ^ 2) ^ -1 + R("09") ^ 1 * (S("uU") ^ -1 * S("lL") ^ 2) + (R("09") ^ 1 * (P(".") * R("09") ^ 1) ^ -1 + P(".") * R("09") ^ 1) * (S("eE") * P("-") ^ -1 * R("09") ^ 1) ^ -1 + local Shebang = P("#!") * P(1 - Stop) ^ 0 + return safe_module("moonscript.parse.literals", { + L = L, + White = White, + Break = Break, + Stop = Stop, + Comment = Comment, + Space = Space, + SomeSpace = SomeSpace, + SpaceBreak = SpaceBreak, + EmptyLine = EmptyLine, + AlphaNum = AlphaNum, + Name = Name, + Num = Num, + Shebang = Shebang + }) + +end +package.preload['moonscript.parse.env'] = function() + local getfenv, setfenv do local _obj_0 = require("moonscript.util") - trim, pos_to_line, get_line = _obj_0.trim, _obj_0.pos_to_line, _obj_0.get_line + getfenv, setfenv = _obj_0.getfenv, _obj_0.setfenv end - local unpack - unpack = require("moonscript.util").unpack local wrap_env - wrap_env = require("moonscript.parse.env").wrap_env - local R, S, V, P, C, Ct, Cmt, Cg, Cb, Cc - R, S, V, P, C, Ct, Cmt, Cg, Cb, Cc = lpeg.R, lpeg.S, lpeg.V, lpeg.P, lpeg.C, lpeg.Ct, lpeg.Cmt, lpeg.Cg, lpeg.Cb, lpeg.Cc - local White, Break, Stop, Comment, Space, SomeSpace, SpaceBreak, EmptyLine, AlphaNum, Num, Shebang, _Name - do - local _obj_0 = require("moonscript.parse.literals") - White, Break, Stop, Comment, Space, SomeSpace, SpaceBreak, EmptyLine, AlphaNum, Num, Shebang, _Name = _obj_0.White, _obj_0.Break, _obj_0.Stop, _obj_0.Comment, _obj_0.Space, _obj_0.SomeSpace, _obj_0.SpaceBreak, _obj_0.EmptyLine, _obj_0.AlphaNum, _obj_0.Num, _obj_0.Shebang, _obj_0.Name - end - local SpaceName = Space * _Name - Num = Space * (Num / function(v) - return { - "number", - v - } - end) - local Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, flatten_func, flatten_string_chain, wrap_decorator, check_lua_string, self_assign - do - local _obj_0 = require("moonscript.parse.util") - Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, flatten_func, flatten_string_chain, wrap_decorator, check_lua_string, self_assign = _obj_0.Indent, _obj_0.Cut, _obj_0.ensure, _obj_0.extract_line, _obj_0.mark, _obj_0.pos, _obj_0.flatten_or_mark, _obj_0.is_assignable, _obj_0.check_assignable, _obj_0.format_assign, _obj_0.format_single_assign, _obj_0.sym, _obj_0.symx, _obj_0.simple_string, _obj_0.wrap_func_arg, _obj_0.flatten_func, _obj_0.flatten_string_chain, _obj_0.wrap_decorator, _obj_0.check_lua_string, _obj_0.self_assign - end - local build_grammar = wrap_env(debug_grammar, function() - local _indent = Stack(0) - local _do_stack = Stack(0) - local last_pos = 0 - local check_indent - check_indent = function(str, pos, indent) - last_pos = pos - return _indent:top() == indent - end - local advance_indent - advance_indent = function(str, pos, indent) - local top = _indent:top() - if top ~= -1 and indent > top then - _indent:push(indent) - return true - end - end - local push_indent - push_indent = function(str, pos, indent) - _indent:push(indent) - return true - end - local pop_indent - pop_indent = function() - assert(_indent:pop(), "unexpected outdent") - return true - end - local check_do - check_do = function(str, pos, do_node) - local top = _do_stack:top() - if top == nil or top then - return true, do_node - end - return false - end - local disable_do - disable_do = function() - _do_stack:push(false) - return true - end - local pop_do - pop_do = function() - assert(_do_stack:pop() ~= nil, "unexpected do pop") - return true - end - local DisableDo = Cmt("", disable_do) - local PopDo = Cmt("", pop_do) - local keywords = { } - local key - key = function(chars) - keywords[chars] = true - return Space * chars * -AlphaNum - end - local op - op = function(chars) - local patt = Space * C(chars) - if chars:match("^%w*$") then - keywords[chars] = true - patt = patt * -AlphaNum - end - return patt - end - local Name = Cmt(SpaceName, 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 VarArg = Space * P("...") / trim - local g = P({ - File, - File = Shebang ^ -1 * (Block + Ct("")), - Block = Ct(Line * (Break ^ 1 * Line) ^ 0), - CheckIndent = Cmt(Indent, check_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 * ((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), - Advance = #Cmt(Indent, advance_indent), - 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) * SpaceBreak ^ 0 * key("from") * Exp / mark("import"), - ImportName = (sym("\\") * Ct(Cc("colon_stub") * Name) + Name), - ImportNameList = SpaceBreak ^ 0 * ImportName * ((SpaceBreak ^ 1 + sym(",") * SpaceBreak ^ 0) * ImportName) ^ 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"), - CharOperators = Space * C(S("+-*/%^><")), - WordOperators = op("or") + op("and") + op("<=") + op(">=") + op("~=") + op("!=") + op("==") + op(".."), - BinaryOperator = (WordOperators + CharOperators) * SpaceBreak ^ 0, - Assignable = Cmt(DotChain + Chain, check_assignable) + Name + SelfName, - Exp = Ct(Value * (BinaryOperator * 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 = 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 = pos(Name / mark("ref")) + SelfName + VarArg + Parens / mark("parens"), - Parens = sym("(") * SpaceBreak ^ 0 * Exp * SpaceBreak ^ 0 * sym(")"), - FnArgs = symx("(") * SpaceBreak ^ 0 * Ct(ExpList ^ -1) * SpaceBreak ^ 0 * sym(")") + sym("!") * -P("=") * Ct(""), - ChainTail = ChainItem ^ 1 * ColonSuffix ^ -1 + ColonSuffix, - Chain = Callable * ChainTail / mark("chain"), - 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, - 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(":") * -SomeSpace * Name * lpeg.Cp()) / self_assign + Ct((KeyName + sym("[") * Exp * sym("]") + DoubleString + SingleString) * symx(":") * (Exp + TableBlock + SpaceBreak ^ 1 * Exp)), - 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 * (sym(",") * Ct(VarArg)) ^ 0 + Ct(VarArg), - FnArgDef = Ct((Name + SelfName) * (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 - }) - local file_grammar = White * g * White * -1 - return { - match = function(self, str) - local tree - local _, err = xpcall((function() - tree = file_grammar:match(str) - end), function(err) - return debug.traceback(err, 2) - end) - if type(err) == "string" then - return nil, err - end - if not (tree) then - local msg - local err_pos = last_pos - if err then - local node - node, msg = unpack(err) - if msg then - msg = " " .. msg - end - err_pos = node[-1] - end - local line_no = pos_to_line(str, err_pos) - local line_str = get_line(str, 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, - string = function(str) - return build_grammar():match(str) - end - } - -end -package.preload['moonscript.transform.destructure'] = function() - local ntype, mtype, build - do - local _obj_0 = require("moonscript.types") - ntype, mtype, build = _obj_0.ntype, _obj_0.mtype, _obj_0.build - end - local NameProxy - NameProxy = require("moonscript.transform.names").NameProxy - local insert - insert = table.insert - local unpack - unpack = require("moonscript.util").unpack - local user_error - user_error = require("moonscript.errors").user_error - local join - join = function(...) + wrap_env = function(debug, fn) + local V, Cmt do - local out = { } - local i = 1 - local _list_0 = { - ... - } - for _index_0 = 1, #_list_0 do - local tbl = _list_0[_index_0] - for _index_1 = 1, #tbl do - local v = tbl[_index_1] - out[i] = v - i = i + 1 - end - end - return out + local _obj_0 = require("lpeg") + V, Cmt = _obj_0.V, _obj_0.Cmt end - end - local has_destructure - has_destructure = function(names) - for _index_0 = 1, #names do - local n = names[_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 - local key_name = key[2] - if ntype(key_name) == "colon_stub" then - s = key_name - else - s = { - "dot", - key_name - } - end - else - s = { - "index", - key - } - end - value, suffix = tuple[2], s - end - suffix = join(prefix, { - suffix - }) - local _exp_0 = ntype(value) - if "value" == _exp_0 or "ref" == _exp_0 or "chain" == _exp_0 or "self" == _exp_0 then - insert(accum, { - value, - suffix - }) - elseif "table" == _exp_0 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(scope, destruct_literal, receiver) - local extracted_names = extract_assign_names(destruct_literal) - local names = { } - local values = { } - local inner = { - "assign", - names, - values - } - local obj - if scope:is_local(receiver) or #extracted_names == 1 then - obj = receiver - else - do - obj = NameProxy("obj") - inner = build["do"]({ - build.assign_one(obj, receiver), - { - "assign", - names, - values - } - }) - obj = obj - end - end - for _index_0 = 1, #extracted_names do - local tuple = extracted_names[_index_0] - insert(names, tuple[1]) - local chain - if obj then - chain = NameProxy.chain(obj, unpack(tuple[2])) - else - chain = "nil" - end - insert(values, chain) - end - return build.group({ - { - "declare", - names - }, - inner - }) - end - local split_assign - split_assign = function(scope, 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(scope, 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 - do + local env = getfenv(fn) + local wrap_name = V + if debug then + local indent = 0 + local indent_char = " " + local iprint + iprint = function(...) + local args = table.concat((function(...) local _accum_0 = { } local _len_0 = 1 - for i = start, total_names do - _accum_0[_len_0] = names[i] + local _list_0 = { + ... + } + for _index_0 = 1, #_list_0 do + local a = _list_0[_index_0] + _accum_0[_len_0] = tostring(a) _len_0 = _len_0 + 1 end - name_slice = _accum_0 - end + return _accum_0 + end)(...), ", ") + return io.stderr:write(tostring(indent_char:rep(indent)) .. tostring(args) .. "\n") end - local value_slice - if total_values < start then - value_slice = { - "nil" - } - else - do - 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 - value_slice = _accum_0 - end + wrap_name = function(name) + local v = V(name) + v = Cmt("", function(str, pos) + local rest = str:sub(pos, -1):match("^([^\n]*)") + iprint("* " .. tostring(name) .. " (" .. tostring(rest) .. ")") + 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 - insert(g, { - "assign", - name_slice, - value_slice - }) end - return build.group(g) + 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) + return v + end + return error("unknown variable referenced: " .. tostring(name)) + end + })) end return { - has_destructure = has_destructure, - split_assign = split_assign, - build_assign = build_assign + wrap_env = wrap_env } end -package.preload['moonscript.transform.names'] = function() - local build - build = require("moonscript.types").build - local unpack - unpack = require("moonscript.util").unpack - local LocalName +package.preload['moonscript'] = function() do - local _base_0 = { - get_name = function(self) - return self.name - end - } - _base_0.__index = _base_0 - local _class_0 = setmetatable({ - __init = function(self, name) - self.name = name - self[1] = "temp_name" - end, - __base = _base_0, - __name = "LocalName" - }, { - __index = _base_0, - __call = function(cls, ...) - local _self_0 = setmetatable({}, _base_0) - cls.__init(_self_0, ...) - return _self_0 - end - }) - _base_0.__class = _class_0 - LocalName = _class_0 + local _with_0 = require("moonscript.base") + return _with_0 end - local NameProxy + +end +package.preload['moonscript.data'] = function() + local concat, remove, insert do + local _obj_0 = table + concat, remove, insert = _obj_0.concat, _obj_0.remove, _obj_0.insert + end + local Set + Set = function(items) + local _tbl_0 = { } + for _index_0 = 1, #items do + local k = items[_index_0] + _tbl_0[k] = true + end + return _tbl_0 + end + local Stack + do + local _class_0 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 = { - base = self, - ... - } - for k, v in ipairs(items) do - if type(v) == "string" then - items[k] = { - "dot", - v - } - else - items[k] = v - end - end - return build.chain(items) - end, - index = function(self, key) - if type(key) == "string" then - key = { - "ref", - key - } - end - return build.chain({ - base = self, - { - "index", - key - } - }) - end, __tostring = function(self) - if self.name then - return ("name<%s>"):format(self.name) + return "" + end, + pop = function(self) + return remove(self) + end, + push = function(self, value, ...) + insert(self, value) + if ... then + return self:push(...) else - return ("name"):format(self.prefix) + return value end + end, + top = function(self) + return self[#self] end } _base_0.__index = _base_0 - local _class_0 = setmetatable({ - __init = function(self, prefix) - self.prefix = prefix - self[1] = "temp_name" + _class_0 = setmetatable({ + __init = function(self, ...) + self:push(...) + return nil end, __base = _base_0, - __name = "NameProxy" + __name = "Stack" }, { __index = _base_0, __call = function(cls, ...) @@ -3259,2207 +6223,42 @@ package.preload['moonscript.transform.names'] = function() end }) _base_0.__class = _class_0 - NameProxy = _class_0 + 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 { - NameProxy = NameProxy, - LocalName = LocalName + Set = Set, + Stack = Stack, + lua_keywords = lua_keywords } end package.preload['moonscript.transform'] = function() - local types = require("moonscript.types") - local util = require("moonscript.util") - local data = require("moonscript.data") - local reversed, unpack - reversed, unpack = util.reversed, util.unpack - local ntype, mtype, build, smart_node, is_slice, value_is_singular - 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 - insert = table.insert - local NameProxy, LocalName - do - local _obj_0 = require("moonscript.transform.names") - NameProxy, LocalName = _obj_0.NameProxy, _obj_0.LocalName - end - local destructure = require("moonscript.transform.destructure") - local NOOP = { - "noop" - } - local Run, apply_to_last, is_singular, extract_declarations, expand_elseif_assign, constructor_name, with_continue_listener, Transformer, construct_comprehension, Statement, Accumulator, default_accumulator, implicitly_return, Value - do - local _base_0 = { - call = function(self, state) - return self.fn(state) - end - } - _base_0.__index = _base_0 - local _class_0 = setmetatable({ - __init = function(self, fn) - self.fn = fn - self[1] = "run" - end, - __base = _base_0, - __name = "Run" - }, { - __index = _base_0, - __call = function(cls, ...) - local _self_0 = setmetatable({}, _base_0) - cls.__init(_self_0, ...) - return _self_0 - end - }) - _base_0.__class = _class_0 - Run = _class_0 - end - 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] = { - "transform", - stm, - fn - } - else - _accum_0[_len_0] = stm - end - _len_0 = _len_0 + 1 - end - return _accum_0 - end)() - end - 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 - 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 ntype(name) == "ref" then - insert(out, name) - elseif 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 - 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 - constructor_name = "new" - 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 - do - local _base_0 = { - transform_once = function(self, scope, node, ...) - if self.seen_nodes[node] then - return node - end - self.seen_nodes[node] = true - local transformer = self.transformers[ntype(node)] - if transformer then - return transformer(scope, node, ...) or node - else - return node - end - end, - 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 - local _class_0 = setmetatable({ - __init = function(self, transformers) - self.transformers = transformers - self.seen_nodes = setmetatable({ }, { - __mode = "k" - }) - end, - __base = _base_0, - __name = "Transformer" - }, { - __index = _base_0, - __call = function(cls, ...) - local _self_0 = setmetatable({}, _base_0) - cls.__init(_self_0, ...) - return _self_0 - end - }) - _base_0.__class = _class_0 - Transformer = _class_0 - end - 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 - _, name, bounds = clause[1], clause[2], clause[3] - current_stms = { - "for", - name, - bounds, - current_stms - } - elseif "foreach" == _exp_0 then - local names, iter - _, names, iter = clause[1], clause[2], clause[3] - current_stms = { - "foreach", - names, - { - iter - }, - current_stms - } - elseif "when" == _exp_0 then - local cond - _, cond = clause[1], clause[2] - 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 - Statement = Transformer({ - transform = function(self, tuple) - local _, node, fn - _, node, fn = tuple[1], tuple[2], tuple[3] - return fn(node) - end, - root_stms = function(self, body) - return apply_to_last(body, implicitly_return(self)) - end, - ["return"] = function(self, node) - local ret_val = node[2] - local ret_val_type = ntype(ret_val) - if ret_val_type == "explist" and #ret_val == 2 then - ret_val = ret_val[2] - ret_val_type = ntype(ret_val) - end - if types.cascading[ret_val_type] then - return implicitly_return(self)(ret_val) - end - if ret_val_type == "chain" or ret_val_type == "comprehension" or ret_val_type == "tblcomprehension" then - ret_val = Value:transform_once(self, ret_val) - if ntype(ret_val) == "block_exp" then - return build.group(apply_to_last(ret_val[2], function(stm) - return { - "return", - stm - } - end)) - end - end - node[2] = ret_val - return node - end, - declare_glob = function(self, node) - local names = extract_declarations(self) - if node[2] == "^" then - do - local _accum_0 = { } - local _len_0 = 1 - for _index_0 = 1, #names do - local _continue_0 = false - repeat - local name = names[_index_0] - if not (name[2]: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 - names = _accum_0 - end - end - return { - "declare", - names - } - end, - assign = function(self, node) - local names, values = unpack(node, 2) - local num_values = #values - local num_names = #values - if num_names == 1 and num_values == 1 then - local first_value = values[1] - local first_name = names[1] - local first_type = ntype(first_value) - if first_type == "chain" then - first_value = Value:transform_once(self, first_value) - first_type = ntype(first_value) - end - local _exp_0 = ntype(first_value) - if "block_exp" == _exp_0 then - local block_body = first_value[2] - local idx = #block_body - block_body[idx] = build.assign_one(first_name, block_body[idx]) - return build.group({ - { - "declare", - { - first_name - } - }, - { - "do", - block_body - } - }) - elseif "comprehension" == _exp_0 or "tblcomprehension" == _exp_0 or "foreach" == _exp_0 or "for" == _exp_0 or "while" == _exp_0 then - return build.assign_one(first_name, Value:transform_once(self, first_value)) - else - values[1] = first_value - end - end - local transformed - if num_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(self, 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({ - { - "export", - node[2] - }, - 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 table_values - do - local _accum_0 = { } - local _len_0 = 1 - for _index_0 = 1, #names do - local name = names[_index_0] - local dest_val - if ntype(name) == "colon_stub" then - dest_val = name[2] - else - dest_val = name - end - local _value_0 = { - { - "key_literal", - name - }, - dest_val - } - _accum_0[_len_0] = _value_0 - _len_0 = _len_0 + 1 - end - table_values = _accum_0 - end - local dest = { - "table", - table_values - } - return { - "assign", - { - dest - }, - { - source - }, - [-1] = node[-1] - } - 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 ntype(name) == "ref" 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(self, 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, 2) - local copy_scope = true - local scope_name, named_assign - if ntype(exp) == "assign" then - local names, values = unpack(exp, 2) - local first_name = names[1] - if ntype(first_name) == "ref" then - scope_name = first_name - named_assign = exp - exp = values[1] - copy_scope = false - else - scope_name = NameProxy("with") - exp = values[1] - values[1] = scope_name - named_assign = { - "assign", - names, - values - } - end - elseif self:is_local(exp) then - scope_name = exp - copy_scope = false - end - scope_name = scope_name or NameProxy("with") - return build["do"]({ - Run(function(self) - return self:set("scope_var", scope_name) - end), - copy_scope and build.assign_one(scope_name, exp) or NOOP, - named_assign or NOOP, - 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 = { } - do - local _accum_0 = { } - local _len_0 = 1 - for i, name in ipairs(node.names) do - if ntype(name) == "table" then - do - local proxy = NameProxy("des") - insert(destructures, destructure.build_assign(self, name, proxy)) - _accum_0[_len_0] = proxy - end - else - _accum_0[_len_0] = name - end - _len_0 = _len_0 + 1 - end - node.names = _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 = self:is_local(list) and list or 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 self:is_local(list) then - list_name = list - end - 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({ - list_name ~= list and build.assign_one(list_name, list) or NOOP, - slice_var or NOOP, - build["for"]({ - name = index_name, - bounds = bounds, - body = { - { - "assign", - node.names, - { - NameProxy.index(list_name, 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" - } - for _index_0 = 1, #conds do - local cond = conds[_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) - if parent_val == "" then - parent_val = nil - end - local statements = { } - local properties = { } - for _index_0 = 1, #body do - local item = body[_index_0] - local _exp_0 = item[1] - if "stm" == _exp_0 then - insert(statements, item[2]) - elseif "props" == _exp_0 then - for _index_1 = 2, #item do - local tuple = item[_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 - do - local _accum_0 = { } - local _len_0 = 1 - for _index_0 = 1, #properties do - local _continue_0 = false - repeat - local tuple = properties[_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 - properties = _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 - if parent_val then - constructor = build.fndef({ - args = { - { - "..." - } - }, - arrow = "fat", - body = { - build.chain({ - base = "super", - { - "call", - { - "..." - } - } - }) - } - }) - else - constructor = build.fndef() - end - 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 - local name_t = type(real_name) - local flattened_name - if name_t == "string" then - flattened_name = real_name - elseif name_t == "table" and real_name[1] == "ref" then - flattened_name = real_name[2] - else - flattened_name = error("don't know how to extract name from " .. tostring(name_t)) - end - real_name = { - "string", - '"', - flattened_name - } - end - local cls = build.table({ - { - "__init", - constructor - }, - { - "__base", - base_name - }, - { - "__name", - real_name - }, - parent_val and { - "__parent", - parent_cls_name - } or nil - }) - local class_index - if parent_val then - local class_lookup = build["if"]({ - cond = { - "exp", - { - "ref", - "val" - }, - "==", - "nil" - }, - ["then"] = { - parent_cls_name:index("name") - } - }) - insert(class_lookup, { - "else", - { - "val" - } - }) - class_index = build.fndef({ - args = { - { - "cls" - }, - { - "name" - } - }, - body = { - build.assign_one(LocalName("val"), build.chain({ - base = "rawget", - { - "call", - { - base_name, - { - "ref", - "name" - } - } - } - })), - class_lookup - } - }) - else - class_index = base_name - end - local cls_mt = build.table({ - { - "__index", - class_index - }, - { - "__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 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 - do - local _accum_0 = { } - local _len_0 = 1 - for _index_0 = 3, #chain do - local item = chain[_index_0] - _accum_0[_len_0] = item - _len_0 = _len_0 + 1 - end - slice = _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 - for _index_0 = 1, #slice do - local item = slice[_index_0] - insert(new_chain, item) - end - return new_chain - else - return parent_cls_name - end - end) - end), - { - "declare_glob", - "*" - }, - parent_val and build.assign_one(parent_cls_name, parent_val) or NOOP, - build.assign_one(base_name, { - "table", - properties - }), - build.assign_one(base_name:chain("__index"), base_name), - parent_val and build.chain({ - base = "setmetatable", - { - "call", - { - base_name, - build.chain({ - base = parent_cls_name, - { - "dot", - "__base" - } - }) - } - } - }) or NOOP, - build.assign_one(cls_name, cls), - build.assign_one(base_name:chain("__class"), cls_name), - build.group((function() - if #statements > 0 then - return { - build.assign_one(LocalName("self"), cls_name), - build.group(statements) - } - end - end)()), - parent_val and build["if"]({ - cond = { - "exp", - parent_cls_name:chain("__inherited") - }, - ["then"] = { - parent_cls_name:chain("__inherited", { - "call", - { - parent_cls_name, - cls_name - } - }) - } - }) or NOOP, - build.group((function() - if name then - return { - build.assign_one(name, cls_name) - } - end - end)()), - (function() - if ret then - return ret(cls_name) - end - end)() - } - value = build.group({ - build.group((function() - if ntype(name) == "value" then - return { - build.declare({ - names = { - name - } - }) - } - end - end)()), - build["do"](out_body) - }) - end - return value - end - }) - do - 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, group_type) - if group_type == nil then - group_type = "block_exp" - end - return build[group_type]({ - build.assign_one(self.accum_name, build.table()), - build.assign_one(self.len_name, 1), - node, - group_type == "block_exp" and self.accum_name or NOOP - }) - 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(NameProxy.index(self.accum_name, self.len_name), val), - { - "update", - self.len_name, - "+=", - 1 - } - } - insert(body, build.group(update)) - return body - end - } - _base_0.__index = _base_0 - local _class_0 = setmetatable({ - __init = function(self, accum_name) - self.accum_name = NameProxy("accum") - self.value_name = NameProxy("value") - self.len_name = NameProxy("len") - end, - __base = _base_0, - __name = "Accumulator" - }, { - __index = _base_0, - __call = function(cls, ...) - local _self_0 = setmetatable({}, _base_0) - cls.__init(_self_0, ...) - return _self_0 - end - }) - _base_0.__class = _class_0 - Accumulator = _class_0 - end - 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 NOOP - 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 - 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 - if type(node[3]) == "string" then - return node - else - return convert_part(node[3]) - 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 = ntype(node[2]) == "ref" and node[2][2] == "super" - return 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 Set - Set = require("moonscript.data").Set - local insert - insert = table.insert - local unpack - unpack = util.unpack - local manual_return = Set({ - "foreach", - "for", - "while", - "return" - }) - local cascading = 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 - for _index_0 = 1, #tbl do - local tuple = tbl[_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") - if type(base) == "string" then - base = { - "ref", - base - } - end - local node = { - "chain", - base - } - for _index_0 = 1, #parts do - local part = parts[_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 - 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 - 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 - 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 - do - 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 - lines = _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 - do - 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 - tuples = _accum_0 - end - table.sort(tuples, function(a, b) - return a[1] < b[1] - end) - local lines - do - local _accum_0 = { } - local _len_0 = 1 - for _index_0 = 1, #tuples do - local pair = tuples[_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 - lines = _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 - local safe_module - safe_module = function(name, tbl) - return setmetatable(tbl, { - __index = function(self, key) - return error("Attempted to import non-existent `" .. tostring(key) .. "` from " .. tostring(name)) - 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, - safe_module = safe_module - } - -end -package.preload['moonscript.version'] = function() - local version = "0.3.0" - return { - version = version, - print_version = function() - return print("MoonScript version " .. tostring(version)) - end + Statement = require("moonscript.transform.statement"), + Value = require("moonscript.transform.value") } end