From 8cd970eb53a823d6159686ff0eadf2edb96545c3 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 3 Feb 2015 09:54:34 -0800 Subject: [PATCH] Update moonscript to 0.3.1 --- automation/include/moonscript.lua | 1769 ++++++++++++++++------------- 1 file changed, 1001 insertions(+), 768 deletions(-) diff --git a/automation/include/moonscript.lua b/automation/include/moonscript.lua index 88257f5ca..b8d45cd3c 100644 --- a/automation/include/moonscript.lua +++ b/automation/include/moonscript.lua @@ -15,7 +15,7 @@ package.preload['moonscript.base'] = function() loadstring = loadstring, load = load } - local dirsep, line_tables, create_moonpath, to_lua, moon_loader, loadstring, loadfile, dofile, insert_loader, remove_loader + local dirsep, line_tables, create_moonpath, to_lua, loadstring, loadfile, dofile dirsep = "/" line_tables = require("moonscript.line_tables") create_moonpath = function(package_path) @@ -34,7 +34,7 @@ package.preload['moonscript.base'] = function() end if "string" ~= type(text) then local t = type(text) - return nil, "expecting string (got " .. t .. ")", 2 + return nil, "expecting string (got " .. t .. ")" end local tree, err = parse.string(text) if not tree then @@ -42,7 +42,7 @@ package.preload['moonscript.base'] = function() end local code, ltable, pos = compile.tree(tree, options) if not code then - return nil, compile.format_error(ltable, pos, text), 2 + return nil, compile.format_error(ltable, pos, text) end return code, ltable end @@ -68,7 +68,7 @@ package.preload['moonscript.base'] = function() end local text = assert(file:read("*a")) file:close() - return loadstring(text, fname, ...) + return loadstring(text, "@" .. tostring(fname), ...) end dofile = function(...) local f = assert(loadfile(...)) @@ -77,7 +77,6 @@ package.preload['moonscript.base'] = function() return { _NAME = "moonscript", to_lua = to_lua, - moon_chunk = moon_chunk, dirsep = dirsep, dofile = dofile, loadfile = loadfile, @@ -232,20 +231,13 @@ package.preload['moonscript.cmd.coverage'] = function() end package.preload['moonscript.cmd.lint'] = function() local insert - do - local _obj_0 = table - insert = _obj_0.insert - end + insert = table.insert local Set - do - local _obj_0 = require("moonscript.data") - Set = _obj_0.Set - end + Set = require("moonscript.data").Set local Block - do - local _obj_0 = require("moonscript.compile") - Block = _obj_0.Block - end + Block = require("moonscript.compile").Block + local mtype + mtype = require("moonscript.util").moon.type local default_whitelist = Set({ '_G', '_VERSION', @@ -294,11 +286,84 @@ package.preload['moonscript.cmd.lint'] = function() do local _parent_0 = Block local _base_0 = { + lint_mark_used = function(self, name) + if self.lint_unused_names and self.lint_unused_names[name] then + self.lint_unused_names[name] = false + return + end + if self.parent then + return self.parent:lint_mark_used(name) + end + end, + lint_check_unused = function(self) + if not (self.lint_unused_names and next(self.lint_unused_names)) then + return + end + local names_by_position = { } + for name, pos in pairs(self.lint_unused_names) do + local _continue_0 = false + repeat + if not (pos) then + _continue_0 = true + break + end + names_by_position[pos] = names_by_position[pos] or { } + insert(names_by_position[pos], name) + _continue_0 = true + until true + if not _continue_0 then + break + end + end + local tuples + do + local _accum_0 = { } + local _len_0 = 1 + for pos, names in pairs(names_by_position) do + _accum_0[_len_0] = { + pos, + names + } + _len_0 = _len_0 + 1 + end + tuples = _accum_0 + end + table.sort(tuples, function(a, b) + return a[1] < b[1] + end) + for _index_0 = 1, #tuples do + local _des_0 = tuples[_index_0] + local pos, names + pos, names = _des_0[1], _des_0[2] + insert(self:get_root_block().lint_errors, { + "assigned but unused " .. tostring(table.concat((function() + local _accum_0 = { } + local _len_0 = 1 + for _index_1 = 1, #names do + local n = names[_index_1] + _accum_0[_len_0] = "`" .. tostring(n) .. "`" + _len_0 = _len_0 + 1 + end + return _accum_0 + end)(), ", ")), + pos + }) + end + end, + render = function(self, ...) + self:lint_check_unused() + return _parent_0.render(self, ...) + end, block = function(self, ...) do local _with_0 = _parent_0.block(self, ...) _with_0.block = self.block + _with_0.render = self.render + _with_0.get_root_block = self.get_root_block + _with_0.lint_check_unused = self.lint_check_unused + _with_0.lint_mark_used = self.lint_mark_used _with_0.value_compilers = self.value_compilers + _with_0.statement_compilers = self.statement_compilers return _with_0 end end @@ -311,6 +376,9 @@ package.preload['moonscript.cmd.lint'] = function() whitelist_globals = default_whitelist end _parent_0.__init(self, ...) + self.get_root_block = function() + return self + end self.lint_errors = { } local vc = self.value_compilers self.value_compilers = setmetatable({ @@ -318,15 +386,50 @@ package.preload['moonscript.cmd.lint'] = function() local name = val[2] if not (block:has_name(name) or whitelist_globals[name] or name:match("%.")) then insert(self.lint_errors, { - "accessing global " .. tostring(name), + "accessing global `" .. tostring(name) .. "`", val[-1] }) end + block:lint_mark_used(name) return vc.ref(block, val) end }, { __index = vc }) + local sc = self.statement_compilers + self.statement_compilers = setmetatable({ + assign = function(block, node) + local names = node[2] + for _index_0 = 1, #names do + local _continue_0 = false + repeat + local name = names[_index_0] + if type(name) == "table" and name[1] == "temp_name" then + _continue_0 = true + break + end + local real_name, is_local = block:extract_assign_name(name) + if not (is_local or real_name and not block:has_name(real_name, true)) then + _continue_0 = true + break + end + if real_name == "_" then + _continue_0 = true + break + end + block.lint_unused_names = block.lint_unused_names or { } + block.lint_unused_names[real_name] = node[-1] or 0 + _continue_0 = true + until true + if not _continue_0 then + break + end + end + return sc.assign(block, node) + end + }, { + __index = sc + }) end, __base = _base_0, __name = "LinterBlock", @@ -431,6 +534,7 @@ package.preload['moonscript.cmd.lint'] = function() end local scope = LinterBlock(whitelist_globals) scope:stms(tree) + scope:lint_check_unused() return format_lint(scope.lint_errors, code, name) end local lint_file @@ -446,17 +550,207 @@ package.preload['moonscript.cmd.lint'] = function() lint_file = lint_file } +end +package.preload['moonscript.cmd.moonc'] = function() + local lfs = require("lfs") + local split + split = require("moonscript.util").split + local dirsep, dirsep_chars, mkdir, normalize_dir, parse_dir, parse_file, convert_path, format_time, gettime, compile_file_text, write_file, compile_and_write, is_abs_path, path_to_target + dirsep = package.config:sub(1, 1) + if dirsep == "\\" then + dirsep_chars = "\\/" + else + dirsep_chars = dirsep + end + mkdir = function(path) + local chunks = split(path, dirsep) + local accum + for _index_0 = 1, #chunks do + local dir = chunks[_index_0] + accum = accum and tostring(accum) .. tostring(dirsep) .. tostring(dir) or dir + lfs.mkdir(accum) + end + return lfs.attributes(path, "mode") + end + normalize_dir = function(path) + return path:match("^(.-)[" .. tostring(dirsep_chars) .. "]*$") .. dirsep + end + parse_dir = function(path) + return (path:match("^(.-)[^" .. tostring(dirsep_chars) .. "]*$")) + end + parse_file = function(path) + return (path:match("^.-([^" .. tostring(dirsep_chars) .. "]*)$")) + end + convert_path = function(path) + local new_path = path:gsub("%.moon$", ".lua") + if new_path == path then + new_path = path .. ".lua" + end + return new_path + end + format_time = function(time) + return ("%.3fms"):format(time * 1000) + end + do + local socket + gettime = function() + if socket == nil then + pcall(function() + socket = require("socket") + end) + if not (socket) then + socket = false + end + end + if socket then + return socket.gettime() + else + return nil, "LuaSocket needed for benchmark" + end + end + end + compile_file_text = function(text, opts) + if opts == nil then + opts = { } + end + local parse = require("moonscript.parse") + local compile = require("moonscript.compile") + local parse_time + if opts.benchmark then + parse_time = assert(gettime()) + end + local tree, err = parse.string(text) + if not (tree) then + return nil, err + end + if parse_time then + parse_time = gettime() - parse_time + end + if opts.show_parse_tree then + local dump = require("moonscript.dump") + dump.tree(tree) + return true + end + local compile_time + if opts.benchmark then + compile_time = gettime() + 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) + end + if compile_time then + compile_time = gettime() - compile_time + end + if opts.show_posmap then + local debug_posmap + debug_posmap = require("moonscript.util").debug_posmap + print("Pos", "Lua", ">>", "Moon") + print(debug_posmap(posmap_or_err, text, code)) + return true + end + if opts.benchmark then + print(table.concat({ + opts.fname or "stdin", + "Parse time \t" .. format_time(parse_time), + "Compile time\t" .. format_time(compile_time), + "" + }, "\n")) + return nil + end + return code + end + write_file = function(fname, code) + mkdir(parse_dir(fname)) + local f, err = io.open(fname, "w") + if not (f) then + return nil, err + end + assert(f:write(code)) + assert(f:write("\n")) + f:close() + return "build" + end + compile_and_write = function(src, dest, opts) + if opts == nil then + opts = { } + end + local f = io.open(src) + if not (f) then + return nil, "Can't find file" + end + local text = assert(f:read("*a")) + f:close() + local code, err = compile_file_text(text, opts) + if not code then + return nil, err + end + if code == true then + return true + end + if opts.print then + print(code) + return true + end + return write_file(dest, code) + end + is_abs_path = function(path) + local first = path:sub(1, 1) + if dirsep == "\\" then + return first == "/" or first == "\\" or path:sub(2, 1) == ":" + else + return first == dirsep + end + end + path_to_target = function(path, target_dir, base_dir) + if target_dir == nil then + target_dir = nil + end + if base_dir == nil then + base_dir = nil + end + local target = convert_path(path) + if target_dir then + target_dir = normalize_dir(target_dir) + end + if base_dir and target_dir then + local head = base_dir:match("^(.-)[^" .. tostring(dirsep_chars) .. "]*[" .. tostring(dirsep_chars) .. "]?$") + if head then + local start, stop = target:find(head, 1, true) + if start == 1 then + target = target:sub(stop + 1) + end + end + end + if target_dir then + if is_abs_path(target) then + target = parse_file(target) + end + target = target_dir .. target + end + return target + end + return { + dirsep = dirsep, + mkdir = mkdir, + normalize_dir = normalize_dir, + parse_dir = parse_dir, + parse_file = parse_file, + convert_path = convert_path, + gettime = gettime, + format_time = format_time, + path_to_target = path_to_target, + compile_file_text = compile_file_text, + compile_and_write = compile_and_write + } + end package.preload['moonscript.compile.statement'] = function() local util = require("moonscript.util") - local data = require("moonscript.data") local reversed, unpack reversed, unpack = util.reversed, util.unpack local ntype - do - local _obj_0 = require("moonscript.types") - ntype = _obj_0.ntype - end + ntype = require("moonscript.types").ntype local concat, insert do local _obj_0 = table @@ -529,7 +823,7 @@ package.preload['moonscript.compile.statement'] = function() _with_0:append(declare) else if #undeclared > 0 then - self:add(declare) + self:add(declare, node[-1]) end _with_0:append_list((function() local _accum_0 = { } @@ -699,15 +993,9 @@ package.preload['moonscript.compile.value'] = function() local util = require("moonscript.util") local data = require("moonscript.data") local ntype - do - local _obj_0 = require("moonscript.types") - ntype = _obj_0.ntype - end + ntype = require("moonscript.types").ntype local user_error - do - local _obj_0 = require("moonscript.errors") - user_error = _obj_0.user_error - end + user_error = require("moonscript.errors").user_error local concat, insert do local _obj_0 = table @@ -1026,10 +1314,7 @@ package.preload['moonscript.compile'] = function() NameProxy, LocalName = _obj_0.NameProxy, _obj_0.LocalName end local Set - do - local _obj_0 = require("moonscript.data") - Set = _obj_0.Set - end + Set = require("moonscript.data").Set local ntype, has_value do local _obj_0 = require("moonscript.types") @@ -1121,7 +1406,6 @@ package.preload['moonscript.compile'] = function() end end insert(buffer, "\n") - local last = l elseif Lines == _exp_0 then l:flatten(indent and indent .. indent_char or indent_char, buffer) else @@ -1279,6 +1563,7 @@ package.preload['moonscript.compile'] = function() export_all = false, export_proper = false, value_compilers = value_compilers, + statement_compilers = statement_compilers, __tostring = function(self) local h if "string" == type(self.header) then @@ -1311,6 +1596,22 @@ package.preload['moonscript.compile'] = function() end end end, + extract_assign_name = function(self, node) + local is_local = false + local real_name + local _exp_0 = mtype(node) + if LocalName == _exp_0 then + is_local = true + real_name = node:get_name(self) + elseif NameProxy == _exp_0 then + real_name = node:get_name(self) + elseif "table" == _exp_0 then + real_name = node[1] == "ref" and node[2] + elseif "string" == _exp_0 then + real_name = node + end + return real_name, is_local + end, declare = function(self, names) local undeclared do @@ -1320,19 +1621,7 @@ package.preload['moonscript.compile'] = function() local _continue_0 = false repeat local name = names[_index_0] - local is_local = false - local real_name - local _exp_0 = mtype(name) - if LocalName == _exp_0 then - is_local = true - real_name = name:get_name(self) - elseif NameProxy == _exp_0 then - real_name = name:get_name(self) - elseif "table" == _exp_0 then - real_name = name[1] == "ref" and name[2] - elseif "string" == _exp_0 then - real_name = name - end + local real_name, is_local = self:extract_assign_name(name) if not (is_local or real_name and not self:has_name(real_name, true)) then _continue_0 = true break @@ -1435,8 +1724,14 @@ package.preload['moonscript.compile'] = function() }) return name end, - add = function(self, item) - self._lines:add(item) + add = function(self, item, pos) + do + local _with_0 = self._lines + _with_0:add(item) + if pos then + _with_0:mark_pos(pos) + end + end return item end, render = function(self, buffer) @@ -1467,7 +1762,7 @@ package.preload['moonscript.compile'] = function() end end, is_stm = function(self, node) - return statement_compilers[ntype(node)] ~= nil + return self.statement_compilers[ntype(node)] ~= nil end, is_value = function(self, node) local t = ntype(node) @@ -1533,7 +1828,7 @@ package.preload['moonscript.compile'] = function() node = self.transform.statement(node) local result do - local fn = statement_compilers[ntype(node)] + local fn = self.statement_compilers[ntype(node)] if fn then result = fn(self, node, ...) else @@ -1715,7 +2010,6 @@ package.preload['moonscript.compile'] = function() if not (success) then local error_msg, error_pos if type(err) == "table" then - local error_type = err[1] local _exp_0 = err[1] if "user-error" == _exp_0 or "compile-error" == _exp_0 then error_msg, error_pos = unpack(err, 2) @@ -1903,7 +2197,7 @@ package.preload['moonscript.errors'] = function() lookup_line = function(fname, pos, cache) if not cache[fname] then do - local _with_0 = io.open(fname) + local _with_0 = assert(io.open(fname)) cache[fname] = _with_0:read("*a") _with_0:close() end @@ -1963,8 +2257,8 @@ package.preload['moonscript.errors'] = function() local cache = { } local rewrite_single rewrite_single = function(trace) - local fname, line, msg = trace:match('^%[string "(.-)"]:(%d+): (.*)$') - local tbl = line_tables[fname] + local fname, line, msg = trace:match('^(.-):(%d+): (.*)$') + local tbl = line_tables["@" .. tostring(fname)] if fname and tbl then return concat({ fname, @@ -2003,676 +2297,631 @@ package.preload['moonscript.errors'] = function() end package.preload['moonscript'] = function() - return require("moonscript.base") + do + local _with_0 = require("moonscript.base") + return _with_0 + end + end package.preload['moonscript.line_tables'] = function() return { } end -package.preload['moonscript.parse'] = function() - - local util = require"moonscript.util" - - local lpeg = require"lpeg" - - local debug_grammar = false - - local data = require"moonscript.data" - local types = require"moonscript.types" - - local ntype = types.ntype - - local dump = util.dump - local trim = util.trim - - local getfenv = util.getfenv - local setfenv = util.setfenv - local unpack = util.unpack - - local Stack = data.Stack - - local function count_indent(str) - local sum = 0 - for v in str:gmatch("[\t ]") do - if v == ' ' then sum = sum + 1 end - if v == '\t' then sum = sum + 4 end - end - return sum +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 R, S, V, P = lpeg.R, lpeg.S, lpeg.V, lpeg.P - local C, Ct, Cmt, Cg, Cb, Cc = lpeg.C, lpeg.Ct, lpeg.Cmt, lpeg.Cg, lpeg.Cb, lpeg.Cc - - lpeg.setmaxstack(10000) - - local White = S" \t\r\n"^0 - local _Space = S" \t"^0 - local Break = P"\r"^-1 * P"\n" - local Stop = Break + -1 - local Indent = C(S"\t "^0) / count_indent - - local Comment = P"--" * (1 - S"\r\n")^0 * #Stop - local Space = _Space * Comment^-1 - local SomeSpace = S" \t"^1 * Comment^-1 - - local SpaceBreak = Space * Break - local EmptyLine = SpaceBreak - - local AlphaNum = R("az", "AZ", "09", "__") - - local _Name = C(R("az", "AZ", "__") * AlphaNum^0) - local Name = Space * _Name - - local Num = P"0x" * R("09", "af", "AF")^1 * (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 - - Num = Space * (Num / function(value) return {"number", value} end) - - local FactorOp = Space * C(S"+-") - local TermOp = Space * C(S"*/%^") - - local Shebang = P"#!" * P(1 - Stop)^0 - - -- can't have P(false) because it causes preceding patterns not to run - local Cut = P(function() return false end) - - local function ensure(patt, finally) - return patt * finally + finally * Cut - end - - -- auto declare Proper variables with lpeg.V - local function wrap_env(fn) - local env = getfenv(fn) - local wrap_name = V - - if debug_grammar then - local indent = 0 - local indent_char = " " - - local function iprint(...) - local args = {...} - for i=1,#args do - args[i] = tostring(args[i]) - end - - io.stdout:write(indent_char:rep(indent) .. table.concat(args, ", ") .. "\n") - end - - wrap_name = function(name) - local v = V(name) - v = Cmt("", function() - iprint("* " .. name) - indent = indent + 1 - return true - end) * Cmt(v, function(str, pos, ...) - iprint(name, true) - indent = indent - 1 - return true, ... - end) + Cmt("", function() - iprint(name, false) - indent = indent - 1 - return false - end) - return v - end - end - - return setfenv(fn, setmetatable({}, { - __index = function(self, name) - local value = env[name] - if value ~= nil then return value end - - if name:match"^[A-Z][A-Za-z0-9]*$" then - local v = wrap_name(name) - rawset(self, name, v) - return v - end - error("unknown variable referenced: "..name) - end - })) - end - - local function extract_line(str, start_pos) - str = str:sub(start_pos) - m = str:match"^(.-)\n" - if m then return m end - return str:match"^.-$" - end - - local function mark(name) - return function(...) - return {name, ...} - end - end - - local function insert_pos(pos, value) - if type(value) == "table" then - value[-1] = pos + 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 - return value + 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 - - local function pos(patt) - return (lpeg.Cp() * patt) / insert_pos - end - - local function got(what) - return Cmt("", function(str, pos, ...) - local cap = {...} - print("++ got "..what, "["..extract_line(str, pos).."]") - return true - end) - end - - local function flatten(tbl) - if #tbl == 1 then - return tbl[1] - end - return tbl - end - - local function flatten_or_mark(name) - return function(tbl) - if #tbl == 1 then return tbl[1] end - table.insert(tbl, 1, name) - return tbl - end - end - - -- makes sure the last item in a chain is an index - local _chain_assignable = { index = true, dot = true, slice = true } - - local function is_assignable(node) - if node == "..." then - return false - end - - local t = ntype(node) - return t == "ref" or t == "self" or t == "value" or t == "self_class" or - t == "chain" and _chain_assignable[ntype(node[#node])] or - t == "table" - end - - local function check_assignable(str, pos, value) - if is_assignable(value) then - return true, value - end - return false - end - - local flatten_explist = flatten_or_mark"explist" - local function format_assign(lhs_exps, assign) - if not assign then - return flatten_explist(lhs_exps) - end - - for _, assign_exp in ipairs(lhs_exps) do - if not is_assignable(assign_exp) then - error {assign_exp, "left hand expression is not assignable"} - end - end - - local t = ntype(assign) - if t == "assign" then - return {"assign", lhs_exps, unpack(assign, 2)} - elseif t == "update" then - return {"update", lhs_exps[1], unpack(assign, 2)} - end - - error "unknown assign expression" - end - - -- the if statement only takes a single lhs, so we wrap in table to git to - -- "assign" tuple format - local function format_single_assign(lhs, assign) - if assign then - return format_assign({lhs}, assign) - end - return lhs - end - - local function sym(chars) - return Space * chars - end - - local function symx(chars) - return chars - end - - local function simple_string(delim, allow_interpolation) - local inner = P('\\'..delim) + "\\\\" + (1 - P(delim)) - if allow_interpolation then - inter = symx"#{" * V"Exp" * sym"}" - inner = (C((inner - inter)^1) + inter / mark"interpolate")^0 - else - inner = C(inner^0) - end - - return C(symx(delim)) * - inner * sym(delim) / mark"string" - end - - local function wrap_func_arg(value) - return {"call", {value}} - end - - -- DOCME - local function flatten_func(callee, args) - if #args == 0 then return callee end - - args = {"call", args} - if ntype(callee) == "chain" then - -- check for colon stub that needs arguments - if ntype(callee[#callee]) == "colon_stub" then - local stub = callee[#callee] - stub[1] = "colon" - table.insert(stub, args) - else - table.insert(callee, args) - end - - return callee - end - - return {"chain", callee, args} - end - - local function flatten_string_chain(str, chain, args) - if not chain then return str end - return flatten_func({"chain", str, unpack(chain)}, args) - end - - -- transforms a statement that has a line decorator - local function wrap_decorator(stm, dec) - if not dec then return stm end - return { "decorated", stm, dec } - end - - -- wrap if statement if there is a conditional decorator - local function wrap_if(stm, cond) - if cond then - local pass, fail = unpack(cond) - if fail then fail = {"else", {fail}} end - return {"if", cond[2], {stm}, fail} - end - return stm - end - - local function check_lua_string(str, pos, right, left) - return #left == #right - end - - -- :name in table literal - local function self_assign(name) - return {{"key_literal", name}, name} - end - - local err_msg = "Failed to parse:%s\n [%d] >> %s" - - local build_grammar = wrap_env(function() - local _indent = Stack(0) -- current indent - local _do_stack = Stack(0) - - local last_pos = 0 -- used to know where to report error - local function check_indent(str, pos, indent) - last_pos = pos - return _indent:top() == indent - end - - local function advance_indent(str, pos, indent) - local top = _indent:top() - if top ~= -1 and indent > _indent:top() then - _indent:push(indent) - return true - end - end - - local function push_indent(str, pos, indent) - _indent:push(indent) - return true - end - - local function pop_indent(str, pos) - if not _indent:pop() then error("unexpected outdent") end - return true - end - - - local function check_do(str, pos, do_node) - local top = _do_stack:top() - if top == nil or top then - return true, do_node - end - return false - end - - local function disable_do(str_pos) - _do_stack:push(false) - return true - end - - local function enable_do(str_pos) - _do_stack:push(true) - return true - end - - local function pop_do(str, pos) - if nil == _do_stack:pop() then error("unexpected do pop") end - return true - end - - local DisableDo = Cmt("", disable_do) - local EnableDo = Cmt("", enable_do) - local PopDo = Cmt("", pop_do) - - local keywords = {} - local function key(chars) - keywords[chars] = true - return Space * chars * -AlphaNum - end - - local function op(word) - local patt = Space * C(word) - if word:match("^%w*$") then - keywords[word] = true - patt = patt * -AlphaNum - end - return patt - end - - -- make sure name is not a keyword - local Name = Cmt(Name, function(str, pos, name) - if keywords[name] then return false end - return true - end) / trim - - local SelfName = Space * "@" * ( - "@" * (_Name / mark"self_class" + Cc"self.__class") + - _Name / mark"self" + Cc"self") - - local KeyName = SelfName + Space * _Name / mark"key_literal" - local VarArg = Space * P"..." / trim - - local g = lpeg.P{ - File, - File = Shebang^-1 * (Block + Ct""), - Block = Ct(Line * (Break^1 * Line)^0), - CheckIndent = Cmt(Indent, check_indent), -- validates line is in correct indent - Line = (CheckIndent * Statement + Space * #Stop), - - Statement = pos( - Import + While + With + For + ForEach + Switch + Return + - Local + Export + BreakLoop + - Ct(ExpList) * (Update + Assign)^-1 / format_assign - ) * Space * (( - -- statement decorators - key"if" * Exp * (key"else" * Exp)^-1 * Space / mark"if" + - key"unless" * Exp / mark"unless" + - CompInner / mark"comprehension" - ) * Space)^-1 / wrap_decorator, - - Body = Space^-1 * Break * EmptyLine^0 * InBlock + Ct(Statement), -- either a statement, or an indented block - - Advance = #Cmt(Indent, advance_indent), -- Advances the indent, gives back whitespace for CheckIndent - PushIndent = Cmt(Indent, push_indent), - PreventIndent = Cmt(Cc(-1), push_indent), - PopIndent = Cmt("", pop_indent), - InBlock = Advance * Block * PopIndent, - - Local = key"local" * ((op"*" + op"^") / mark"declare_glob" + Ct(NameList) / mark"declare_with_shadows"), - - Import = key"import" * Ct(ImportNameList) * 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", - - -- we can ignore precedence for now - OtherOps = op"or" + op"and" + op"<=" + op">=" + op"~=" + op"!=" + op"==" + op".." + op"<" + op">", - - Assignable = Cmt(DotChain + Chain, check_assignable) + Name + SelfName, - - Exp = Ct(Value * ((OtherOps + FactorOp + TermOp) * Value)^0) / flatten_or_mark"exp", - - -- Exp = Ct(Factor * (OtherOps * Factor)^0) / flatten_or_mark"exp", - -- Factor = Ct(Term * (FactorOp * Term)^0) / flatten_or_mark"exp", - -- Term = Ct(Value * (TermOp * Value)^0) / flatten_or_mark"exp", - - SimpleValue = - If + Unless + - Switch + - With + - ClassDecl + - ForEach + For + While + - Cmt(Do, check_do) + - sym"-" * -SomeSpace * Exp / mark"minus" + - sym"#" * Exp / mark"length" + - key"not" * Exp / mark"not" + - TblComprehension + - TableLit + - Comprehension + - FunLit + - Num, - - ChainValue = -- a function call or an object access - StringChain + - ((Chain + DotChain + Callable) * Ct(InvokeArgs^-1)) / flatten_func, - - Value = pos( - SimpleValue + - Ct(KeyValueList) / mark"table" + - ChainValue), - - SliceValue = SimpleValue + ChainValue, - - StringChain = String * - (Ct((ColonCall + ColonSuffix) * ChainTail^-1) * Ct(InvokeArgs^-1))^-1 / flatten_string_chain, - - String = Space * DoubleString + Space * SingleString + LuaString, - SingleString = simple_string("'"), - DoubleString = simple_string('"', true), - - LuaString = Cg(LuaStringOpen, "string_open") * Cb"string_open" * Break^-1 * - C((1 - Cmt(C(LuaStringClose) * Cb"string_open", check_lua_string))^0) * - LuaStringClose / mark"string", - - LuaStringOpen = sym"[" * P"="^0 * "[" / trim, - LuaStringClose = "]" * P"="^0 * "]", - - Callable = pos(Name / mark"ref") + SelfName + VarArg + Parens / mark"parens", - Parens = sym"(" * Exp * sym")", - - FnArgs = symx"(" * Ct(ExpList^-1) * sym")" + sym"!" * -P"=" * Ct"", - - ChainTail = ChainItem^1 * ColonSuffix^-1 + ColonSuffix, - - -- a list of funcalls and indexes on a callable - Chain = Callable * ChainTail / mark"chain", - - -- shorthand dot call for use in with statement - DotChain = - (sym"." * Cc(-1) * (_Name / mark"dot") * ChainTail^-1) / mark"chain" + - (sym"\\" * Cc(-1) * ( - (_Name * Invoke / mark"colon") * ChainTail^-1 + - (_Name / mark"colon_stub") - )) / mark"chain", - - ChainItem = - Invoke + - Slice + - symx"[" * Exp/mark"index" * sym"]" + - symx"." * _Name/mark"dot" + - ColonCall, - - Slice = symx"[" * (SliceValue + Cc(1)) * sym"," * (SliceValue + Cc"") * - (sym"," * SliceValue)^-1 *sym"]" / mark"slice", - - ColonCall = symx"\\" * (_Name * Invoke) / mark"colon", - ColonSuffix = symx"\\" * _Name / mark"colon_stub", - - Invoke = FnArgs/mark"call" + - SingleString / wrap_func_arg + - DoubleString / wrap_func_arg, - - TableValue = KeyValue + Ct(Exp), - - TableLit = sym"{" * Ct( - TableValueList^-1 * sym","^-1 * - (SpaceBreak * TableLitLine * (sym","^-1 * SpaceBreak * TableLitLine)^0 * sym","^-1)^-1 - ) * White * sym"}" / mark"table", - - TableValueList = TableValue * (sym"," * TableValue)^0, - TableLitLine = PushIndent * ((TableValueList * PopIndent) + (PopIndent * Cut)) + Space, - - -- the unbounded table - TableBlockInner = Ct(KeyValueLine * (SpaceBreak^1 * KeyValueLine)^0), - TableBlock = SpaceBreak^1 * Advance * ensure(TableBlockInner, PopIndent) / mark"table", - - ClassDecl = key"class" * -P":" * (Assignable + Cc(nil)) * (key"extends" * PreventIndent * ensure(Exp, PopIndent) + C"")^-1 * (ClassBlock + Ct("")) / mark"class", - - ClassBlock = SpaceBreak^1 * Advance * - Ct(ClassLine * (SpaceBreak^1 * ClassLine)^0) * PopIndent, - ClassLine = CheckIndent * (( - KeyValueList / mark"props" + - Statement / mark"stm" + - Exp / mark"stm" - ) * sym","^-1), - - Export = key"export" * ( - Cc"class" * ClassDecl + - op"*" + op"^" + - Ct(NameList) * (sym"=" * Ct(ExpListLow))^-1) / mark"export", - - KeyValue = (sym":" * -SomeSpace * Name) / self_assign + Ct((KeyName + sym"[" * Exp * sym"]" + DoubleString + SingleString) * symx":" * (Exp + TableBlock)), - KeyValueList = KeyValue * (sym"," * KeyValue)^0, - KeyValueLine = CheckIndent * KeyValueList * sym","^-1, - - FnArgsDef = sym"(" * Ct(FnArgDefList^-1) * - (key"using" * Ct(NameList + Space * "nil") + Ct"") * - sym")" + Ct"" * Ct"", - - FnArgDefList = FnArgDef * (sym"," * FnArgDef)^0 * (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 - } - - return { - _g = White * g * White * -1, - match = function(self, str, ...) - - local pos_to_line = function(pos) - return util.pos_to_line(str, pos) - end - - local get_line = function(num) - return util.get_line(str, num) - end - - local tree - local parse_args = {...} - - local pass, err = xpcall(function() - tree = self._g:match(str, unpack(parse_args)) - end, function(err) - return debug.traceback(err, 2) - end) - - -- regular error, let it bubble up - if type(err) == "string" then - return nil, err - end - - if not tree then - local pos = last_pos - local msg - - if err then - local node - node, msg = unpack(err) - msg = msg and " " .. msg - pos = node[-1] - end - - local line_no = pos_to_line(pos) - local line_str = get_line(line_no) or "" - - return nil, err_msg:format(msg or "", line_no, trim(line_str)) - end - return tree - end - } - end) - return { - extract_line = extract_line, - - -- parse a string - -- returns tree, or nil and error message - string = function (str) - local g = build_grammar() - return g:match(str) - end + 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 + unpack = require("moonscript.util").unpack + local P, C, S, Cp, Cmt, V + do + local _obj_0 = require("lpeg") + P, C, S, Cp, Cmt, V = _obj_0.P, _obj_0.C, _obj_0.S, _obj_0.Cp, _obj_0.Cmt, _obj_0.V + end + local ntype + ntype = require("moonscript.types").ntype + local Space + Space = require("moonscript.parse.literals").Space + local Indent = C(S("\t ") ^ 0) / function(str) + do + local sum = 0 + for v in str:gmatch("[\t ]") do + local _exp_0 = v + if " " == _exp_0 then + sum = sum + 1 + elseif "\t" == _exp_0 then + sum = sum + 4 + end + end + return sum + end + end + local Cut = P(function() + return false + end) + local ensure + ensure = function(patt, finally) + return patt * finally + finally * Cut + end + local extract_line + extract_line = function(str, start_pos) + str = str:sub(start_pos) + do + local m = str:match("^(.-)\n") + if m then + return m + end + end + return str:match("^.-$") + end + local mark + mark = function(name) + return function(...) + return { + name, + ... + } + end + end + local pos + pos = function(patt) + return (Cp() * patt) / function(pos, value) + if type(value) == "table" then + value[-1] = pos + end + return value + end + end + local got + got = function(what) + return Cmt("", function(str, pos) + print("++ got " .. tostring(what), "[" .. tostring(extract_line(str, pos)) .. "]") + return true + end) + end + local flatten_or_mark + flatten_or_mark = function(name) + return function(tbl) + if #tbl == 1 then + return tbl[1] + end + table.insert(tbl, 1, name) + return tbl + end + end + local is_assignable + do + local chain_assignable = { + index = true, + dot = true, + slice = true + } + is_assignable = function(node) + if node == "..." then + return false + end + local _exp_0 = ntype(node) + if "ref" == _exp_0 or "self" == _exp_0 or "value" == _exp_0 or "self_class" == _exp_0 or "table" == _exp_0 then + return true + elseif "chain" == _exp_0 then + return chain_assignable[ntype(node[#node])] + else + return false + end + end + end + local check_assignable + check_assignable = function(str, pos, value) + if is_assignable(value) then + return true, value + else + return false + end + end + local format_assign + do + local flatten_explist = flatten_or_mark("explist") + format_assign = function(lhs_exps, assign) + if not (assign) then + return flatten_explist(lhs_exps) + end + for _index_0 = 1, #lhs_exps do + local assign_exp = lhs_exps[_index_0] + if not (is_assignable(assign_exp)) then + error({ + assign_exp, + "left hand expression is not assignable" + }) + end + end + local t = ntype(assign) + local _exp_0 = t + if "assign" == _exp_0 then + return { + "assign", + lhs_exps, + unpack(assign, 2) + } + elseif "update" == _exp_0 then + return { + "update", + lhs_exps[1], + unpack(assign, 2) + } + else + return error("unknown assign expression: " .. tostring(t)) + end + end + end + local format_single_assign + format_single_assign = function(lhs, assign) + if assign then + return format_assign({ + lhs + }, assign) + else + return lhs + end + end + local sym + sym = function(chars) + return Space * chars + end + local symx + symx = function(chars) + return chars + end + local simple_string + simple_string = function(delim, allow_interpolation) + local inner = P("\\" .. tostring(delim)) + "\\\\" + (1 - P(delim)) + if allow_interpolation then + local interp = symx('#{') * V("Exp") * sym('}') + inner = (C((inner - interp) ^ 1) + interp / mark("interpolate")) ^ 0 + else + inner = C(inner ^ 0) + end + return C(symx(delim)) * inner * sym(delim) / mark("string") + end + local wrap_func_arg + wrap_func_arg = function(value) + return { + "call", + { + value + } + } + end + local flatten_func + flatten_func = function(callee, args) + if #args == 0 then + return callee + end + args = { + "call", + 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 + return callee + end + return { + "chain", + callee, + 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 + return stm + end + return { + "decorated", + stm, + dec + } + end + local check_lua_string + check_lua_string = function(str, pos, right, left) + return #left == #right + end + local self_assign + self_assign = function(name, pos) + return { + { + "key_literal", + name + }, + { + "ref", + name, + [-1] = pos + } + } + end + return { + Indent = Indent, + Cut = Cut, + ensure = ensure, + extract_line = extract_line, + mark = mark, + pos = pos, + flatten_or_mark = flatten_or_mark, + is_assignable = is_assignable, + check_assignable = check_assignable, + format_assign = format_assign, + format_single_assign = format_single_assign, + sym = sym, + symx = symx, + simple_string = simple_string, + wrap_func_arg = wrap_func_arg, + flatten_func = flatten_func, + flatten_string_chain = flatten_string_chain, + wrap_decorator = wrap_decorator, + check_lua_string = check_lua_string, + self_assign = self_assign + } + +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, _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() @@ -2682,26 +2931,13 @@ package.preload['moonscript.transform.destructure'] = function() ntype, mtype, build = _obj_0.ntype, _obj_0.mtype, _obj_0.build end local NameProxy - do - local _obj_0 = require("moonscript.transform.names") - NameProxy = _obj_0.NameProxy - end + NameProxy = require("moonscript.transform.names").NameProxy local insert - do - local _obj_0 = table - insert = _obj_0.insert - end + insert = table.insert local unpack - do - local _obj_0 = require("moonscript.util") - unpack = _obj_0.unpack - end + unpack = require("moonscript.util").unpack local user_error - do - local _obj_0 = require("moonscript.errors") - user_error = _obj_0.user_error - end - local util = require("moonscript.util") + user_error = require("moonscript.errors").user_error local join join = function(...) do @@ -2803,7 +3039,7 @@ package.preload['moonscript.transform.destructure'] = function() values } local obj - if scope:is_local(receiver) then + if scope:is_local(receiver) or #extracted_names == 1 then obj = receiver else do @@ -2822,7 +3058,13 @@ package.preload['moonscript.transform.destructure'] = function() for _index_0 = 1, #extracted_names do local tuple = extracted_names[_index_0] insert(names, tuple[1]) - insert(values, NameProxy.chain(obj, unpack(tuple[2]))) + local chain + if obj then + chain = NameProxy.chain(obj, unpack(tuple[2])) + else + chain = "nil" + end + insert(values, chain) end return build.group({ { @@ -2919,15 +3161,9 @@ package.preload['moonscript.transform.destructure'] = function() end package.preload['moonscript.transform.names'] = function() local build - do - local _obj_0 = require("moonscript.types") - build = _obj_0.build - end + build = require("moonscript.types").build local unpack - do - local _obj_0 = require("moonscript.util") - unpack = _obj_0.unpack - end + unpack = require("moonscript.util").unpack local LocalName do local _base_0 = { @@ -3040,10 +3276,7 @@ package.preload['moonscript.transform'] = function() 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 - do - local _obj_0 = table - insert = _obj_0.insert - end + insert = table.insert local NameProxy, LocalName do local _obj_0 = require("moonscript.transform.names") @@ -4674,15 +4907,9 @@ end package.preload['moonscript.types'] = function() local util = require("moonscript.util") local Set - do - local _obj_0 = require("moonscript.data") - Set = _obj_0.Set - end + Set = require("moonscript.data").Set local insert - do - local _obj_0 = table - insert = _obj_0.insert - end + insert = table.insert local unpack unpack = util.unpack local manual_return = Set({ @@ -5003,10 +5230,7 @@ package.preload['moonscript.types'] = function() end package.preload['moonscript.util'] = function() local concat - do - local _obj_0 = table - concat = _obj_0.concat - end + concat = table.concat local unpack = unpack or table.unpack local type = type local moon = { @@ -5203,6 +5427,14 @@ package.preload['moonscript.util'] = function() 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, @@ -5216,18 +5448,19 @@ package.preload['moonscript.util'] = function() getfenv = getfenv, setfenv = setfenv, get_options = get_options, - unpack = unpack + unpack = unpack, + safe_module = safe_module } end package.preload['moonscript.version'] = function() - - module("moonscript.version", package.seeall) - - version = "0.2.5" - function print_version() - print("MoonScript version "..version) - end + local version = "0.3.0" + return { + version = version, + print_version = function() + return print("MoonScript version " .. tostring(version)) + end + } end return package.preload["moonscript"]()