diff --git a/bin/moon b/bin/moon index e5b3119..5665a80 100755 --- a/bin/moon +++ b/bin/moon @@ -17,7 +17,7 @@ local help = [=[Usage: %s [options] [script [args]] ]=] local function print_err(...) - msg = table.concat({...}, "\t") + local msg = table.concat({...}, "\t") io.stderr:write(msg .. "\n") end @@ -49,7 +49,7 @@ local new_arg = { local moonscript_chunk, lua_parse_error local passed, err = pcall(function() - moonscript_chunk, lua_parse_error = moonscript.loadfile(script_fname) + moonscript_chunk, lua_parse_error = moonscript.loadfile(script_fname, { implicitly_return_root = false }) end) if not passed then @@ -70,16 +70,25 @@ getfenv(moonscript_chunk).arg = new_arg if not opts.d then local err, trace + xpcall(function() moonscript_chunk(unpack(new_arg)) end, function(_err) err = _err trace = debug.traceback("", 2) end) if err then - local traceback = util.trim(trace) - traceback = moonscript.errors.truncate_traceback(traceback) - print_err(moonscript.errors.rewrite_traceback(traceback, err)) - os.exit(1) + local truncated = moonscript.errors.truncate_traceback(util.trim(trace)) + local rewritten = moonscript.errors.rewrite_traceback(truncated, err) + + if rewritten then + print_err(rewritten) + else + -- faield to rewrite, show original + print_err(table.concat({ + err, + util.trim(trace) + }, "\n")) + end end else moonscript_chunk(unpack(new_arg)) diff --git a/moonscript/compile.lua b/moonscript/compile.lua index 6891c3c..35a1321 100644 --- a/moonscript/compile.lua +++ b/moonscript/compile.lua @@ -587,7 +587,9 @@ RootBlock = (function() return "RootBlock<>" end, root_stms = function(self, stms) - stms = transform.Statement.transformers.root_stms(self, stms) + if not (self.options.implicitly_return_root == false) then + stms = transform.Statement.transformers.root_stms(self, stms) + end local _list_0 = stms for _index_0 = 1, #_list_0 do local s = _list_0[_index_0] @@ -607,9 +609,10 @@ RootBlock = (function() setmetatable(_base_0, _parent_0.__base) end local _class_0 = setmetatable({ - __init = function(self, ...) + __init = function(self, options) + self.options = options self.root = self - return _parent_0.__init(self, ...) + return _parent_0.__init(self) end, __base = _base_0, __name = "RootBlock", @@ -654,11 +657,12 @@ value = function(value) end return out end -tree = function(tree, scope) - if scope == nil then - scope = RootBlock() +tree = function(tree, options) + if options == nil then + options = { } end assert(tree, "missing tree") + local scope = (options.scope or RootBlock)(options) local runner = coroutine.create(function() return scope:root_stms(tree) end) diff --git a/moonscript/compile.moon b/moonscript/compile.moon index c1aae94..411ee9f 100644 --- a/moonscript/compile.moon +++ b/moonscript/compile.moon @@ -340,14 +340,15 @@ class Block @stms fn lines class RootBlock extends Block - new: (...) => + new: (@options) => @root = self - super ... + super! __tostring: => "RootBlock<>" root_stms: (stms) => - stms = transform.Statement.transformers.root_stms self, stms + unless @options.implicitly_return_root == false + stms = transform.Statement.transformers.root_stms self, stms @stm s for s in *stms render: => @@ -372,9 +373,11 @@ value = (value) -> out = \render! out -tree = (tree, scope=RootBlock!) -> +tree = (tree, options={}) -> assert tree, "missing tree" + scope = (options.scope or RootBlock) options + runner = coroutine.create -> scope\root_stms tree diff --git a/moonscript/errors.lua b/moonscript/errors.lua index 08c65e2..d895e50 100644 --- a/moonscript/errors.lua +++ b/moonscript/errors.lua @@ -85,11 +85,14 @@ rewrite_traceback = function(text, err) 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, + "moon: " .. err, header_text, "\t" .. concat(match, "\n\t") }, "\n") diff --git a/moonscript/errors.moon b/moonscript/errors.moon index 4b48021..ede5fce 100644 --- a/moonscript/errors.moon +++ b/moonscript/errors.moon @@ -71,11 +71,14 @@ rewrite_traceback = (text, err) -> err = rewrite_single err match = g\match text + + return nil unless match + for i, trace in ipairs match match[i] = rewrite_single trace concat { - "moon:" .. err + "moon: " .. err header_text "\t" .. concat match, "\n\t" }, "\n" diff --git a/moonscript/init.lua b/moonscript/init.lua index 51a1e04..e895224 100644 --- a/moonscript/init.lua +++ b/moonscript/init.lua @@ -20,7 +20,10 @@ create_moonpath = function(package_path) end return concat(paths, ";") end -to_lua = function(text) +to_lua = function(text, options) + if options == nil then + options = { } + end if "string" ~= type(text) then local t = type(text) error("expecting string (got " .. t .. ")", 2) @@ -29,7 +32,7 @@ to_lua = function(text) if not tree then error(err, 2) end - local code, ltable, pos = compile.tree(tree) + local code, ltable, pos = compile.tree(tree, options) if not code then error(compile.format_error(ltable, pos, text), 2) end @@ -65,9 +68,12 @@ end if not _G.moon_no_loader then init_loader() end -loadstring = function(str, chunk_name) +loadstring = function(str, chunk_name, options) + if options == nil then + options = nil + end local passed, code, ltable = pcall(function() - return to_lua(str) + return to_lua(str, options) end) if not passed then error(chunk_name .. ": " .. code, 2) @@ -77,16 +83,19 @@ loadstring = function(str, chunk_name) end return lua.loadstring(code, chunk_name or "=(moonscript.loadstring)") end -loadfile = function(fname) +loadfile = function(fname, options) + if options == nil then + options = nil + end local file, err = io.open(fname) if not file then return nil, err end local text = assert(file:read("*a")) file:close() - return loadstring(text, fname) + return loadstring(text, fname, options) end -dofile = function(fname) +dofile = function(fname, options) local f = assert(loadfile(fname)) return f() end diff --git a/moonscript/init.moon b/moonscript/init.moon index b059387..61f15f8 100644 --- a/moonscript/init.moon +++ b/moonscript/init.moon @@ -24,7 +24,7 @@ create_moonpath = (package_path) -> if p then paths[i] = p..".moon" concat paths, ";" -to_lua = (text) -> +to_lua = (text, options={}) -> if "string" != type text t = type text error "expecting string (got ".. t ..")", 2 @@ -33,7 +33,7 @@ to_lua = (text) -> if not tree error err, 2 - code, ltable, pos = compile.tree tree + code, ltable, pos = compile.tree tree, options if not code error compile.format_error(ltable, pos, text), 2 @@ -63,23 +63,23 @@ init_loader = -> init_loader! if not _G.moon_no_loader -loadstring = (str, chunk_name) -> - passed, code, ltable = pcall -> to_lua str +loadstring = (str, chunk_name, options=nil) -> + passed, code, ltable = pcall -> to_lua str, options if not passed error chunk_name .. ": " .. code, 2 line_tables[chunk_name] = ltable if chunk_name lua.loadstring code, chunk_name or "=(moonscript.loadstring)" -loadfile = (fname) -> +loadfile = (fname, options=nil) -> file, err = io.open fname return nil, err if not file text = assert file\read "*a" file\close! - loadstring text, fname + loadstring text, fname, options -- throws errros -dofile = (fname) -> +dofile = (fname, options) -> f = assert loadfile fname f!