Overhaul of error reporting and removing nomsu:call(stub, line_no, ...) in favor of nomsu.defs[stub].fn(...)
This commit is contained in:
parent
53a9d4eae8
commit
c0333ca315
@ -19,7 +19,7 @@ immediately:
|
|||||||
|
|
||||||
immediately:
|
immediately:
|
||||||
lua> ".."
|
lua> ".."
|
||||||
nomsu:defmacro("compile %macro_def to %body", function(nomsu, \%macro_def, \%body)
|
nomsu:defmacro("compile %macro_def to %body", \(__line_no__), function(nomsu, \%macro_def, \%body)
|
||||||
nomsu:assert(\%macro_def.type == "List",
|
nomsu:assert(\%macro_def.type == "List",
|
||||||
"Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
|
"Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
|
||||||
nomsu:assert(\%body.type == "Block",
|
nomsu:assert(\%body.type == "Block",
|
||||||
@ -33,13 +33,14 @@ immediately:
|
|||||||
%s
|
%s
|
||||||
end
|
end
|
||||||
local function macro_wrapper(...) return {expr=macro(...)}; end
|
local function macro_wrapper(...) return {expr=macro(...)}; end
|
||||||
nomsu:defmacro(%s, macro_wrapper, %s);
|
nomsu:defmacro(%s, %s, macro_wrapper, %s);
|
||||||
end]]):format(args, body_lua, signature, nomsu:repr(("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src)));
|
end]]):format(args, body_lua, signature, nomsu:repr(\%macro_def:get_line_no()),
|
||||||
|
nomsu:repr(("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src)));
|
||||||
return {statements=lua};
|
return {statements=lua};
|
||||||
end, \(__src__ 1));
|
end, \(__src__ 1));
|
||||||
|
|
||||||
lua> ".."
|
lua> ".."
|
||||||
nomsu:defmacro("compile %macro_def to code %body", function(nomsu, \%macro_def, \%body)
|
nomsu:defmacro("compile %macro_def to code %body", \(__line_no__), function(nomsu, \%macro_def, \%body)
|
||||||
nomsu:assert(\%macro_def.type == "List",
|
nomsu:assert(\%macro_def.type == "List",
|
||||||
"Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
|
"Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type));
|
||||||
nomsu:assert(\%body.type == "Block",
|
nomsu:assert(\%body.type == "Block",
|
||||||
@ -53,8 +54,9 @@ immediately:
|
|||||||
%s
|
%s
|
||||||
end
|
end
|
||||||
local function macro_wrapper(...) return {statements=macro(...)}; end
|
local function macro_wrapper(...) return {statements=macro(...)}; end
|
||||||
nomsu:defmacro(%s, macro_wrapper, %s);
|
nomsu:defmacro(%s, %s, macro_wrapper, %s);
|
||||||
end]]):format(args, body_lua, signature, nomsu:repr(("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src)));
|
end]]):format(args, body_lua, signature, nomsu:repr(\%macro_def:get_line_no()),
|
||||||
|
nomsu:repr(("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src)));
|
||||||
return {statements=lua};
|
return {statements=lua};
|
||||||
end, \(__src__ 1));
|
end, \(__src__ 1));
|
||||||
|
|
||||||
@ -71,7 +73,7 @@ immediately:
|
|||||||
body_lua = body_lua.statements or ("return "..body_lua.expr..";");
|
body_lua = body_lua.statements or ("return "..body_lua.expr..";");
|
||||||
local src = nomsu:dedent(nomsu:source_code(0));
|
local src = nomsu:dedent(nomsu:source_code(0));
|
||||||
local def_lua = ([[
|
local def_lua = ([[
|
||||||
nomsu:def(%s, function(%s)
|
nomsu:def(%s, \(__line_no__), function(%s)
|
||||||
%s
|
%s
|
||||||
end, %s);]]):format(signature, args, body_lua, nomsu:repr(src));
|
end, %s);]]):format(signature, args, body_lua, nomsu:repr(src));
|
||||||
return def_lua;
|
return def_lua;
|
||||||
@ -79,7 +81,7 @@ immediately:
|
|||||||
# Rule to make nomsu macros:
|
# Rule to make nomsu macros:
|
||||||
immediately:
|
immediately:
|
||||||
lua> ".."
|
lua> ".."
|
||||||
nomsu:defmacro("parse %shorthand as %longhand", (function(nomsu, \%shorthand, \%longhand)
|
nomsu:defmacro("parse %shorthand as %longhand", \(__line_no__), (function(nomsu, \%shorthand, \%longhand)
|
||||||
nomsu:assert(\%shorthand.type == "List",
|
nomsu:assert(\%shorthand.type == "List",
|
||||||
"Invalid type for parse definition signature. Expected List, but got: "..tostring(\%shorthand.type));
|
"Invalid type for parse definition signature. Expected List, but got: "..tostring(\%shorthand.type));
|
||||||
nomsu:assert(\%longhand.type == "Block",
|
nomsu:assert(\%longhand.type == "Block",
|
||||||
@ -95,11 +97,12 @@ immediately:
|
|||||||
for i, a in ipairs(arg_names) do replacements[i] = "["..nomsu:repr(a).."]=_"..nomsu:var_to_lua_identifier(a); end
|
for i, a in ipairs(arg_names) do replacements[i] = "["..nomsu:repr(a).."]=_"..nomsu:var_to_lua_identifier(a); end
|
||||||
replacements = "{"..table.concat(replacements, ", ").."}";
|
replacements = "{"..table.concat(replacements, ", ").."}";
|
||||||
local lua_code = ([[
|
local lua_code = ([[
|
||||||
nomsu:defmacro(%s, (function(%s)
|
nomsu:defmacro(%s, %s, (function(%s)
|
||||||
local template = nomsu:parse(%s, %s);
|
local template = nomsu:parse(%s, %s);
|
||||||
local replacement = nomsu:replaced_vars(template, %s);
|
local replacement = nomsu:replaced_vars(template, %s);
|
||||||
return nomsu:tree_to_lua(replacement);
|
return nomsu:tree_to_lua(replacement);
|
||||||
end), %s)]]):format(signature, args, template, nomsu:repr(\%shorthand:get_line_no()), replacements, nomsu:repr(nomsu:source_code(0)));
|
end), %s)]]):format(signature, nomsu:repr(\%shorthand:get_line_no()), args, template,
|
||||||
|
nomsu:repr(\%shorthand:get_line_no()), replacements, nomsu:repr(nomsu:source_code(0)));
|
||||||
return {statements=lua_code};
|
return {statements=lua_code};
|
||||||
end), \(__src__ 1));
|
end), \(__src__ 1));
|
||||||
|
|
||||||
|
@ -19,14 +19,24 @@ compile [..]
|
|||||||
%when_true_expr if %condition otherwise %when_false_expr
|
%when_true_expr if %condition otherwise %when_false_expr
|
||||||
%when_false_expr unless %condition else %when_true_expr
|
%when_false_expr unless %condition else %when_true_expr
|
||||||
%when_false_expr unless %condition then %when_true_expr
|
%when_false_expr unless %condition then %when_true_expr
|
||||||
..to: ".."
|
..to:
|
||||||
(function(nomsu, condition)
|
lua> ".."
|
||||||
if condition then
|
local condition = nomsu:tree_to_lua(\%condition).expr;
|
||||||
return \(%when_true_expr as lua);
|
local when_true = nomsu:tree_to_lua(\%when_true_expr).expr;
|
||||||
|
local when_false = nomsu:tree_to_lua(\%when_false_expr).expr;
|
||||||
|
local safe = {String=true, List=true, Dict=true, Number=true};
|
||||||
|
if safe[\%when_true_expr.type] then
|
||||||
|
return "("..condition.." and "..when_true.." or "..when_false..")";
|
||||||
else
|
else
|
||||||
return \(%when_false_expr as lua);
|
return ([[
|
||||||
|
(function(nomsu)
|
||||||
|
if %s then
|
||||||
|
return %s;
|
||||||
|
else
|
||||||
|
return %s;
|
||||||
|
end
|
||||||
|
end)(nomsu)]]):format(condition, when_true, when_false);
|
||||||
end
|
end
|
||||||
end)(nomsu, \(%condition as lua))
|
|
||||||
parse [..]
|
parse [..]
|
||||||
%true if %x == %y else %false, %true if %x == %y otherwise %false
|
%true if %x == %y else %false, %true if %x == %y otherwise %false
|
||||||
%false unless %x == %y else %true, %false unless %x == %y otherwise %true
|
%false unless %x == %y else %true, %false unless %x == %y otherwise %true
|
||||||
|
@ -113,7 +113,7 @@ lua> ".."
|
|||||||
};
|
};
|
||||||
for name,code in pairs(colors) do
|
for name,code in pairs(colors) do
|
||||||
local escape = "\\"\\\\27["..tostring(code).."m\\""
|
local escape = "\\"\\\\27["..tostring(code).."m\\""
|
||||||
nomsu:defmacro(name, function() return escape end, "");
|
nomsu:defmacro(name, \(__line_no__), function() return escape end, "");
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
302
nomsu.lua
302
nomsu.lua
@ -204,7 +204,7 @@ do
|
|||||||
self:write_err(...)
|
self:write_err(...)
|
||||||
return self:write_err("\n")
|
return self:write_err("\n")
|
||||||
end,
|
end,
|
||||||
def = function(self, signature, fn, src, is_macro)
|
def = function(self, signature, line_no, fn, src, is_macro)
|
||||||
if is_macro == nil then
|
if is_macro == nil then
|
||||||
is_macro = false
|
is_macro = false
|
||||||
end
|
end
|
||||||
@ -221,6 +221,7 @@ do
|
|||||||
local def = {
|
local def = {
|
||||||
fn = fn,
|
fn = fn,
|
||||||
src = src,
|
src = src,
|
||||||
|
line_no = line_no,
|
||||||
is_macro = is_macro,
|
is_macro = is_macro,
|
||||||
aliases = { },
|
aliases = { },
|
||||||
def_number = self.__class.def_number,
|
def_number = self.__class.def_number,
|
||||||
@ -275,28 +276,8 @@ do
|
|||||||
rawset(where_defs_go, stub, stub_def)
|
rawset(where_defs_go, stub, stub_def)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
defmacro = function(self, signature, fn, src)
|
defmacro = function(self, signature, line_no, fn, src)
|
||||||
return self:def(signature, fn, src, true)
|
return self:def(signature, line_no, fn, src, true)
|
||||||
end,
|
|
||||||
scoped = function(self, thunk)
|
|
||||||
local old_defs = self.defs
|
|
||||||
local new_defs = {
|
|
||||||
["#vars"] = setmetatable({ }, {
|
|
||||||
__index = self.defs["#vars"]
|
|
||||||
}),
|
|
||||||
["#loaded_files"] = setmetatable({ }, {
|
|
||||||
__index = self.defs["#loaded_files"]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
self.defs = setmetatable(new_defs, {
|
|
||||||
__index = old_defs
|
|
||||||
})
|
|
||||||
local ok, ret1, ret2 = pcall(thunk, self)
|
|
||||||
self.defs = old_defs
|
|
||||||
if not ok then
|
|
||||||
self:error(ret1)
|
|
||||||
end
|
|
||||||
return ret1, ret2
|
|
||||||
end,
|
end,
|
||||||
serialize_defs = function(self, scope, after)
|
serialize_defs = function(self, scope, after)
|
||||||
if scope == nil then
|
if scope == nil then
|
||||||
@ -367,50 +348,6 @@ do
|
|||||||
end
|
end
|
||||||
return concat(buff, "\n")
|
return concat(buff, "\n")
|
||||||
end,
|
end,
|
||||||
call = function(self, stub, line_no, ...)
|
|
||||||
local def = self.defs[stub]
|
|
||||||
if def and def.is_macro and self.callstack[#self.callstack] ~= "#macro" then
|
|
||||||
self:error("Attempt to call macro at runtime: " .. tostring(stub) .. "\nThis can be caused by using a macro in a function that is defined before the macro.")
|
|
||||||
end
|
|
||||||
insert(self.callstack, {
|
|
||||||
stub,
|
|
||||||
line_no
|
|
||||||
})
|
|
||||||
if not (def) then
|
|
||||||
self:error("Attempt to call undefined function: " .. tostring(stub))
|
|
||||||
end
|
|
||||||
if not (def.is_macro) then
|
|
||||||
self:assert_permission(stub)
|
|
||||||
end
|
|
||||||
local fn, arg_positions
|
|
||||||
fn, arg_positions = def.fn, def.arg_positions
|
|
||||||
local args
|
|
||||||
do
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
for _index_0 = 1, #arg_positions do
|
|
||||||
local p = arg_positions[_index_0]
|
|
||||||
_accum_0[_len_0] = select(p, ...)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
args = _accum_0
|
|
||||||
end
|
|
||||||
if self.debug then
|
|
||||||
self:write(tostring(colored.bright("CALLING")) .. " " .. tostring(colored.magenta(colored.underscore(stub))) .. " ")
|
|
||||||
self:writeln(tostring(colored.bright("WITH ARGS:")))
|
|
||||||
for i, value in ipairs(args) do
|
|
||||||
self:writeln(" " .. tostring(colored.bright("* " .. tostring(def.args[i]))) .. " = " .. tostring(colored.dim(repr(value))))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local old_defs
|
|
||||||
old_defs, self.defs = self.defs, def.defs
|
|
||||||
local rets = {
|
|
||||||
fn(self, unpack(args))
|
|
||||||
}
|
|
||||||
self.defs = old_defs
|
|
||||||
remove(self.callstack)
|
|
||||||
return unpack(rets)
|
|
||||||
end,
|
|
||||||
run_macro = function(self, tree)
|
run_macro = function(self, tree)
|
||||||
local args
|
local args
|
||||||
do
|
do
|
||||||
@ -430,10 +367,7 @@ do
|
|||||||
self:write(tostring(colored.bright("RUNNING MACRO")) .. " " .. tostring(colored.underscore(colored.magenta(tree.stub))) .. " ")
|
self:write(tostring(colored.bright("RUNNING MACRO")) .. " " .. tostring(colored.underscore(colored.magenta(tree.stub))) .. " ")
|
||||||
self:writeln(tostring(colored.bright("WITH ARGS:")) .. " " .. tostring(colored.dim(repr(args))))
|
self:writeln(tostring(colored.bright("WITH ARGS:")) .. " " .. tostring(colored.dim(repr(args))))
|
||||||
end
|
end
|
||||||
insert(self.callstack, "#macro")
|
return self.defs[tree.stub].fn(self, unpack(args))
|
||||||
local ret = self:call(tree.stub, tree:get_line_no(), unpack(args))
|
|
||||||
remove(self.callstack)
|
|
||||||
return ret
|
|
||||||
end,
|
end,
|
||||||
dedent = function(self, code)
|
dedent = function(self, code)
|
||||||
if not (code:find("\n")) then
|
if not (code:find("\n")) then
|
||||||
@ -614,11 +548,7 @@ end]]):format(lua_code))
|
|||||||
self:error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(err))
|
self:error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(err))
|
||||||
end
|
end
|
||||||
local run_lua_fn = load_lua_fn()
|
local run_lua_fn = load_lua_fn()
|
||||||
local ok, ret = pcall(run_lua_fn, self)
|
run_lua_fn(self)
|
||||||
if not ok then
|
|
||||||
self:errorln(debug.traceback())
|
|
||||||
self:error(ret)
|
|
||||||
end
|
|
||||||
return ret
|
return ret
|
||||||
end,
|
end,
|
||||||
tree_to_value = function(self, tree, filename)
|
tree_to_value = function(self, tree, filename)
|
||||||
@ -639,7 +569,6 @@ end]]):format(lua_code))
|
|||||||
end
|
end
|
||||||
self:assert(tree, "No tree provided.")
|
self:assert(tree, "No tree provided.")
|
||||||
if not tree.type then
|
if not tree.type then
|
||||||
self:errorln(debug.traceback())
|
|
||||||
self:error("Invalid tree: " .. tostring(repr(tree)))
|
self:error("Invalid tree: " .. tostring(repr(tree)))
|
||||||
end
|
end
|
||||||
local _exp_0 = tree.type
|
local _exp_0 = tree.type
|
||||||
@ -829,7 +758,6 @@ end]]):format(lua_code))
|
|||||||
tree_to_lua = function(self, tree, filename)
|
tree_to_lua = function(self, tree, filename)
|
||||||
self:assert(tree, "No tree provided.")
|
self:assert(tree, "No tree provided.")
|
||||||
if not tree.type then
|
if not tree.type then
|
||||||
self:errorln(debug.traceback())
|
|
||||||
self:error("Invalid tree: " .. tostring(repr(tree)))
|
self:error("Invalid tree: " .. tostring(repr(tree)))
|
||||||
end
|
end
|
||||||
local _exp_0 = tree.type
|
local _exp_0 = tree.type
|
||||||
@ -905,57 +833,45 @@ end]]):format(lua_code))
|
|||||||
expr = "(" .. tostring(concat(bits, " ")) .. ")"
|
expr = "(" .. tostring(concat(bits, " ")) .. ")"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
local args = {
|
local arg_positions = def and def.arg_positions or { }
|
||||||
repr(tree.stub),
|
local args = { }
|
||||||
repr(tree:get_line_no())
|
|
||||||
}
|
|
||||||
local arg_names, escaped_args
|
|
||||||
if def then
|
|
||||||
arg_names, escaped_args = def.arg_names, def.escaped_args
|
|
||||||
else
|
|
||||||
arg_names, escaped_args = (function()
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
local _list_0 = tree.value
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local w = _list_0[_index_0]
|
|
||||||
if w.type == "Word" then
|
|
||||||
_accum_0[_len_0] = w.value
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return _accum_0
|
|
||||||
end)(), { }
|
|
||||||
end
|
|
||||||
local arg_num = 1
|
|
||||||
local _list_0 = tree.value
|
local _list_0 = tree.value
|
||||||
for _index_0 = 1, #_list_0 do
|
for _index_0 = 1, #_list_0 do
|
||||||
local _continue_0 = false
|
local _continue_0 = false
|
||||||
repeat
|
repeat
|
||||||
local arg = _list_0[_index_0]
|
local tok = _list_0[_index_0]
|
||||||
if arg.type == 'Word' then
|
if tok.type == "Word" then
|
||||||
_continue_0 = true
|
_continue_0 = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
if escaped_args[arg_names[arg_num]] then
|
local lua = self:tree_to_lua(tok, filename)
|
||||||
insert(args, "nomsu:parse(" .. tostring(repr(arg.src)) .. ", " .. tostring(repr(tree:get_line_no())) .. ").value[1]")
|
self:assert(lua.expr, "Cannot use " .. tostring(tok.src) .. " as an argument, since it's not an expression.")
|
||||||
else
|
|
||||||
local lua = self:tree_to_lua(arg, filename)
|
|
||||||
if lua.statements then
|
|
||||||
self:error("Cannot use [[" .. tostring(arg.src) .. "]] as a function argument to " .. tostring(tree.stub) .. ", since it's not an expression.")
|
|
||||||
end
|
|
||||||
insert(args, lua.expr)
|
insert(args, lua.expr)
|
||||||
end
|
|
||||||
arg_num = arg_num + 1
|
|
||||||
_continue_0 = true
|
_continue_0 = true
|
||||||
until true
|
until true
|
||||||
if not _continue_0 then
|
if not _continue_0 then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if def then
|
||||||
|
local new_args
|
||||||
|
do
|
||||||
|
local _accum_0 = { }
|
||||||
|
local _len_0 = 1
|
||||||
|
local _list_1 = def.arg_positions
|
||||||
|
for _index_0 = 1, #_list_1 do
|
||||||
|
local p = _list_1[_index_0]
|
||||||
|
_accum_0[_len_0] = args[p]
|
||||||
|
_len_0 = _len_0 + 1
|
||||||
|
end
|
||||||
|
new_args = _accum_0
|
||||||
|
end
|
||||||
|
args = new_args
|
||||||
|
end
|
||||||
|
insert(args, 1, "nomsu")
|
||||||
remove(self.compilestack)
|
remove(self.compilestack)
|
||||||
return {
|
return {
|
||||||
expr = self.__class:comma_separated_items("nomsu:call(", args, ")")
|
expr = self.__class:comma_separated_items("nomsu.defs[" .. tostring(repr(tree.stub)) .. "].fn(", args, ")")
|
||||||
}
|
}
|
||||||
elseif "String" == _exp_0 then
|
elseif "String" == _exp_0 then
|
||||||
local concat_parts = { }
|
local concat_parts = { }
|
||||||
@ -1266,52 +1182,12 @@ end]]):format(lua_code))
|
|||||||
msg = ''
|
msg = ''
|
||||||
end
|
end
|
||||||
if not condition then
|
if not condition then
|
||||||
return self:error("Assertion failed: " .. msg)
|
self:error("Assertion failed: " .. msg)
|
||||||
end
|
end
|
||||||
|
return condition
|
||||||
end,
|
end,
|
||||||
error = function(self, msg)
|
error = function(self, msg)
|
||||||
local error_msg = colored.red("ERROR!")
|
return error(msg, 0)
|
||||||
if msg and #msg > 0 then
|
|
||||||
error_msg = error_msg .. ("\n" .. (colored.bright(colored.yellow(colored.onred(msg)))))
|
|
||||||
else
|
|
||||||
error_msg = error_msg .. "\n<no message>"
|
|
||||||
end
|
|
||||||
error_msg = error_msg .. "\nCallstack:"
|
|
||||||
local maxlen = max((function()
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
local _list_0 = self.callstack
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local c = _list_0[_index_0]
|
|
||||||
if c ~= "#macro" then
|
|
||||||
_accum_0[_len_0] = #c[2]
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return _accum_0
|
|
||||||
end)())
|
|
||||||
for i = #self.callstack, 1, -1 do
|
|
||||||
if self.callstack[i] ~= "#macro" then
|
|
||||||
local line_no = self.callstack[i][2]
|
|
||||||
if line_no then
|
|
||||||
local nums
|
|
||||||
do
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
for n in line_no:gmatch(":([0-9]+)") do
|
|
||||||
_accum_0[_len_0] = tonumber(n)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
nums = _accum_0
|
|
||||||
end
|
|
||||||
line_no = line_no:gsub(":.*$", ":" .. tostring(sum(nums) - #nums + 1))
|
|
||||||
end
|
|
||||||
error_msg = error_msg .. "\n " .. tostring(("%-" .. tostring(maxlen) .. "s"):format(line_no)) .. "| " .. tostring(self.callstack[i][1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error_msg = error_msg .. "\n <top level>"
|
|
||||||
self.callstack = { }
|
|
||||||
return error(error_msg, 3)
|
|
||||||
end,
|
end,
|
||||||
source_code = function(self, level)
|
source_code = function(self, level)
|
||||||
if level == nil then
|
if level == nil then
|
||||||
@ -1338,7 +1214,7 @@ end]]):format(lua_code))
|
|||||||
end
|
end
|
||||||
return concat(concat_parts)
|
return concat(concat_parts)
|
||||||
end
|
end
|
||||||
self:defmacro("do %block", function(self, _block)
|
self:defmacro("do %block", "nomsu.moon", function(self, _block)
|
||||||
local make_line
|
local make_line
|
||||||
make_line = function(lua)
|
make_line = function(lua)
|
||||||
return lua.expr and (lua.expr .. ";") or lua.statements
|
return lua.expr and (lua.expr .. ";") or lua.statements
|
||||||
@ -1351,7 +1227,7 @@ end]]):format(lua_code))
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
self:defmacro("immediately %block", function(self, _block)
|
self:defmacro("immediately %block", "nomsu.moon", function(self, _block)
|
||||||
local lua = self:tree_to_lua(_block)
|
local lua = self:tree_to_lua(_block)
|
||||||
local lua_code = lua.statements or (lua.expr .. ";")
|
local lua_code = lua.statements or (lua.expr .. ";")
|
||||||
lua_code = "-- Immediately:\n" .. lua_code
|
lua_code = "-- Immediately:\n" .. lua_code
|
||||||
@ -1360,27 +1236,32 @@ end]]):format(lua_code))
|
|||||||
statements = lua_code
|
statements = lua_code
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
self:defmacro("lua> %code", function(self, _code)
|
self:defmacro("lua> %code", "nomsu.moon", function(self, _code)
|
||||||
local lua = nomsu_string_as_lua(self, _code)
|
local lua = nomsu_string_as_lua(self, _code)
|
||||||
return {
|
return {
|
||||||
statements = lua
|
statements = lua
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
self:defmacro("=lua %code", function(self, _code)
|
self:defmacro("=lua %code", "nomsu.moon", function(self, _code)
|
||||||
local lua = nomsu_string_as_lua(self, _code)
|
local lua = nomsu_string_as_lua(self, _code)
|
||||||
return {
|
return {
|
||||||
expr = lua
|
expr = lua
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
self:defmacro("__src__ %level", function(self, _level)
|
self:defmacro("__line_no__", "nomsu.moon", function(self)
|
||||||
|
return {
|
||||||
|
expr = repr(self.compilestack[#self.compilestack]:get_line_no())
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
self:defmacro("__src__ %level", "nomsu.moon", function(self, _level)
|
||||||
return {
|
return {
|
||||||
expr = repr(self:source_code(self:tree_to_value(_level)))
|
expr = repr(self:source_code(self:tree_to_value(_level)))
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
self:def("run file %filename", function(self, _filename)
|
self:def("run file %filename", "nomsu.moon", function(self, _filename)
|
||||||
return self:run_file(_filename)
|
return self:run_file(_filename)
|
||||||
end)
|
end)
|
||||||
return self:defmacro("require %filename", function(self, _filename)
|
return self:defmacro("require %filename", "nomsu.moon", function(self, _filename)
|
||||||
local filename = self:tree_to_value(_filename)
|
local filename = self:tree_to_value(_filename)
|
||||||
self:require_file(filename)
|
self:require_file(filename)
|
||||||
return {
|
return {
|
||||||
@ -1485,25 +1366,27 @@ if arg then
|
|||||||
print("Usage: lua nomsu.lua [-c] [-i] [-p] [-O] [--help] [input [-o output]]")
|
print("Usage: lua nomsu.lua [-c] [-i] [-p] [-O] [--help] [input [-o output]]")
|
||||||
os.exit()
|
os.exit()
|
||||||
end
|
end
|
||||||
local c = NomsuCompiler()
|
local nomsu = NomsuCompiler()
|
||||||
|
local run
|
||||||
|
run = function()
|
||||||
if args.flags["-v"] then
|
if args.flags["-v"] then
|
||||||
c.debug = true
|
nomsu.debug = true
|
||||||
end
|
end
|
||||||
c.skip_precompiled = not args.flags["-O"]
|
nomsu.skip_precompiled = not args.flags["-O"]
|
||||||
if args.input then
|
if args.input then
|
||||||
if args.flags["-c"] and not args.output then
|
if args.flags["-c"] and not args.output then
|
||||||
args.output = args.input:gsub("%.nom", ".lua")
|
args.output = args.input:gsub("%.nom", ".lua")
|
||||||
end
|
end
|
||||||
local compiled_output = nil
|
local compiled_output = nil
|
||||||
if args.flags["-p"] then
|
if args.flags["-p"] then
|
||||||
local _write = c.write
|
local _write = nomsu.write
|
||||||
c.write = function() end
|
nomsu.write = function() end
|
||||||
compiled_output = io.output()
|
compiled_output = io.output()
|
||||||
elseif args.output then
|
elseif args.output then
|
||||||
compiled_output = io.open(args.output, 'w')
|
compiled_output = io.open(args.output, 'w')
|
||||||
end
|
end
|
||||||
if args.input:match(".*%.lua") then
|
if args.input:match(".*%.lua") then
|
||||||
local retval = dofile(args.input)(c, { })
|
local retval = dofile(args.input)(nomsu, { })
|
||||||
else
|
else
|
||||||
local input
|
local input
|
||||||
if args.input == '-' then
|
if args.input == '-' then
|
||||||
@ -1511,17 +1394,17 @@ if arg then
|
|||||||
else
|
else
|
||||||
input = io.open(args.input):read("*a")
|
input = io.open(args.input):read("*a")
|
||||||
end
|
end
|
||||||
local retval, code = c:run(input, args.input)
|
local retval, code = nomsu:run(input, args.input)
|
||||||
if args.output then
|
if args.output then
|
||||||
compiled_output:write(code)
|
compiled_output:write(code)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if args.flags["-p"] then
|
if args.flags["-p"] then
|
||||||
c.write = _write
|
nomsu.write = _write
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if args.flags["-i"] then
|
if args.flags["-i"] then
|
||||||
c:run('require "lib/core.nom"', "stdin")
|
nomsu:run('require "lib/core.nom"', "stdin")
|
||||||
while true do
|
while true do
|
||||||
local buff = ""
|
local buff = ""
|
||||||
while true do
|
while true do
|
||||||
@ -1536,7 +1419,7 @@ if arg then
|
|||||||
break
|
break
|
||||||
end
|
end
|
||||||
local ok, ret = pcall(function()
|
local ok, ret = pcall(function()
|
||||||
return c:run(buff, "stdin")
|
return nomsu:run(buff, "stdin")
|
||||||
end)
|
end)
|
||||||
if ok and ret ~= nil then
|
if ok and ret ~= nil then
|
||||||
print("= " .. repr(ret))
|
print("= " .. repr(ret))
|
||||||
@ -1544,4 +1427,77 @@ if arg then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local err_hand
|
||||||
|
err_hand = function(error_message)
|
||||||
|
print(tostring(colored.red("ERROR:")) .. " " .. tostring(colored.bright(colored.yellow(colored.onred((error_message or ""))))))
|
||||||
|
print("stack traceback:")
|
||||||
|
local to_lua
|
||||||
|
to_lua = require("moonscript.base").to_lua
|
||||||
|
local nomsu_file = io.open("nomsu.moon")
|
||||||
|
local nomsu_source = nomsu_file:read("*a")
|
||||||
|
local _, line_table = to_lua(nomsu_source)
|
||||||
|
nomsu_file:close()
|
||||||
|
local function_defs
|
||||||
|
do
|
||||||
|
local _tbl_0 = { }
|
||||||
|
for _, def in pairs(nomsu.defs) do
|
||||||
|
if def.fn then
|
||||||
|
_tbl_0[def.fn] = def
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function_defs = _tbl_0
|
||||||
|
end
|
||||||
|
local level = 2
|
||||||
|
while true do
|
||||||
|
local _continue_0 = false
|
||||||
|
repeat
|
||||||
|
local calling_fn = debug.getinfo(level)
|
||||||
|
if not calling_fn then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if calling_fn.func == run then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
level = level + 1
|
||||||
|
local name = calling_fn.name
|
||||||
|
if name == "run_lua_fn" then
|
||||||
|
_continue_0 = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
local line = nil
|
||||||
|
do
|
||||||
|
local def = function_defs[calling_fn.func]
|
||||||
|
if def then
|
||||||
|
line = colored.yellow(def.line_no)
|
||||||
|
name = colored.bright(colored.yellow(def.aliases[1]))
|
||||||
|
else
|
||||||
|
if calling_fn.istailcall and not name then
|
||||||
|
name = "<tail call>"
|
||||||
|
end
|
||||||
|
if calling_fn.short_src == "./nomsu.moon" then
|
||||||
|
local char = line_table[calling_fn.linedefined - 2]
|
||||||
|
local line_num = 3
|
||||||
|
for _ in nomsu_source:sub(1, char):gmatch("\n") do
|
||||||
|
line_num = line_num + 1
|
||||||
|
end
|
||||||
|
line = colored.cyan(tostring(calling_fn.short_src) .. ":" .. tostring(line_num))
|
||||||
|
name = colored.bright(colored.cyan(name or "???"))
|
||||||
|
else
|
||||||
|
line = colored.blue(tostring(calling_fn.short_src) .. ":" .. tostring(calling_fn.linedefined))
|
||||||
|
name = colored.bright(colored.blue(name or "???"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local _from = colored.dim(colored.white("|"))
|
||||||
|
print(("%32s %s %s"):format(name, _from, line))
|
||||||
|
_continue_0 = true
|
||||||
|
until true
|
||||||
|
if not _continue_0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return os.exit(false, true)
|
||||||
|
end
|
||||||
|
xpcall(run, err_hand)
|
||||||
|
end
|
||||||
return NomsuCompiler
|
return NomsuCompiler
|
||||||
|
187
nomsu.moon
187
nomsu.moon
@ -171,7 +171,7 @@ class NomsuCompiler
|
|||||||
@write_err(...)
|
@write_err(...)
|
||||||
@write_err("\n")
|
@write_err("\n")
|
||||||
|
|
||||||
def: (signature, fn, src, is_macro=false)=>
|
def: (signature, line_no, fn, src, is_macro=false)=>
|
||||||
if type(signature) == 'string'
|
if type(signature) == 'string'
|
||||||
signature = @get_stubs {signature}
|
signature = @get_stubs {signature}
|
||||||
elseif type(signature) == 'table' and type(signature[1]) == 'string'
|
elseif type(signature) == 'table' and type(signature[1]) == 'string'
|
||||||
@ -179,7 +179,7 @@ class NomsuCompiler
|
|||||||
@assert type(fn) == 'function', "Bad fn: #{repr fn}"
|
@assert type(fn) == 'function', "Bad fn: #{repr fn}"
|
||||||
aliases = {}
|
aliases = {}
|
||||||
@@def_number += 1
|
@@def_number += 1
|
||||||
def = {:fn, :src, :is_macro, aliases:{}, def_number:@@def_number, defs:@defs}
|
def = {:fn, :src, :line_no, :is_macro, aliases:{}, def_number:@@def_number, defs:@defs}
|
||||||
where_defs_go = (getmetatable(@defs) or {}).__newindex or @defs
|
where_defs_go = (getmetatable(@defs) or {}).__newindex or @defs
|
||||||
for sig_i=1,#signature
|
for sig_i=1,#signature
|
||||||
stub, arg_names, escaped_args = unpack(signature[sig_i])
|
stub, arg_names, escaped_args = unpack(signature[sig_i])
|
||||||
@ -204,19 +204,8 @@ class NomsuCompiler
|
|||||||
stub_def = setmetatable({:stub, :arg_names, :arg_positions}, {__index:def})
|
stub_def = setmetatable({:stub, :arg_names, :arg_positions}, {__index:def})
|
||||||
rawset(where_defs_go, stub, stub_def)
|
rawset(where_defs_go, stub, stub_def)
|
||||||
|
|
||||||
defmacro: (signature, fn, src)=>
|
defmacro: (signature, line_no, fn, src)=>
|
||||||
@def(signature, fn, src, true)
|
@def(signature, line_no, fn, src, true)
|
||||||
|
|
||||||
scoped: (thunk)=>
|
|
||||||
old_defs = @defs
|
|
||||||
new_defs =
|
|
||||||
["#vars"]: setmetatable({}, {__index:@defs["#vars"]})
|
|
||||||
["#loaded_files"]: setmetatable({}, {__index:@defs["#loaded_files"]})
|
|
||||||
@defs = setmetatable(new_defs, {__index:old_defs})
|
|
||||||
ok, ret1, ret2 = pcall thunk, @
|
|
||||||
@defs = old_defs
|
|
||||||
if not ok then @error(ret1)
|
|
||||||
return ret1, ret2
|
|
||||||
|
|
||||||
serialize_defs: (scope=nil, after=nil)=>
|
serialize_defs: (scope=nil, after=nil)=>
|
||||||
after or= @core_defs or 0
|
after or= @core_defs or 0
|
||||||
@ -253,39 +242,12 @@ class NomsuCompiler
|
|||||||
|
|
||||||
return concat buff, "\n"
|
return concat buff, "\n"
|
||||||
|
|
||||||
call: (stub,line_no,...)=>
|
|
||||||
def = @defs[stub]
|
|
||||||
-- This is a little bit hacky, but having this check is handy for catching mistakes
|
|
||||||
-- I use a hash sign in "#macro" so it's guaranteed to not be a valid function name
|
|
||||||
if def and def.is_macro and @callstack[#@callstack] != "#macro"
|
|
||||||
@error "Attempt to call macro at runtime: #{stub}\nThis can be caused by using a macro in a function that is defined before the macro."
|
|
||||||
insert @callstack, {stub, line_no}
|
|
||||||
unless def
|
|
||||||
@error "Attempt to call undefined function: #{stub}"
|
|
||||||
unless def.is_macro
|
|
||||||
@assert_permission(stub)
|
|
||||||
{:fn, :arg_positions} = def
|
|
||||||
args = [select(p, ...) for p in *arg_positions]
|
|
||||||
if @debug
|
|
||||||
@write "#{colored.bright "CALLING"} #{colored.magenta(colored.underscore stub)} "
|
|
||||||
@writeln "#{colored.bright "WITH ARGS:"}"
|
|
||||||
for i, value in ipairs(args)
|
|
||||||
@writeln " #{colored.bright "* #{def.args[i]}"} = #{colored.dim repr(value)}"
|
|
||||||
old_defs, @defs = @defs, def.defs
|
|
||||||
rets = {fn(self,unpack(args))}
|
|
||||||
@defs = old_defs
|
|
||||||
remove @callstack
|
|
||||||
return unpack(rets)
|
|
||||||
|
|
||||||
run_macro: (tree)=>
|
run_macro: (tree)=>
|
||||||
args = [arg for arg in *tree.value when arg.type != "Word"]
|
args = [arg for arg in *tree.value when arg.type != "Word"]
|
||||||
if @debug
|
if @debug
|
||||||
@write "#{colored.bright "RUNNING MACRO"} #{colored.underscore colored.magenta(tree.stub)} "
|
@write "#{colored.bright "RUNNING MACRO"} #{colored.underscore colored.magenta(tree.stub)} "
|
||||||
@writeln "#{colored.bright "WITH ARGS:"} #{colored.dim repr args}"
|
@writeln "#{colored.bright "WITH ARGS:"} #{colored.dim repr args}"
|
||||||
insert @callstack, "#macro"
|
return @defs[tree.stub].fn(self, unpack(args))
|
||||||
ret = @call(tree.stub, tree\get_line_no!, unpack(args))
|
|
||||||
remove @callstack
|
|
||||||
return ret
|
|
||||||
|
|
||||||
dedent: (code)=>
|
dedent: (code)=>
|
||||||
unless code\find("\n")
|
unless code\find("\n")
|
||||||
@ -405,11 +367,7 @@ end]]\format(lua_code))
|
|||||||
code = "1 |"..lua_code\gsub("\n", fn)
|
code = "1 |"..lua_code\gsub("\n", fn)
|
||||||
@error("Failed to compile generated code:\n#{colored.bright colored.blue colored.onblack code}\n\n#{err}")
|
@error("Failed to compile generated code:\n#{colored.bright colored.blue colored.onblack code}\n\n#{err}")
|
||||||
run_lua_fn = load_lua_fn!
|
run_lua_fn = load_lua_fn!
|
||||||
ok,ret = pcall(run_lua_fn, self)
|
run_lua_fn(self)
|
||||||
if not ok
|
|
||||||
--@errorln "#{colored.red "Error occurred in statement:"}\n#{colored.yellow tree.src}"
|
|
||||||
@errorln debug.traceback!
|
|
||||||
@error(ret)
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
tree_to_value: (tree, filename)=>
|
tree_to_value: (tree, filename)=>
|
||||||
@ -426,7 +384,7 @@ end]]\format(lua_code))
|
|||||||
-- Return <nomsu code>, <is safe for inline use>
|
-- Return <nomsu code>, <is safe for inline use>
|
||||||
@assert tree, "No tree provided."
|
@assert tree, "No tree provided."
|
||||||
if not tree.type
|
if not tree.type
|
||||||
@errorln debug.traceback()
|
--@errorln debug.traceback()
|
||||||
@error "Invalid tree: #{repr(tree)}"
|
@error "Invalid tree: #{repr(tree)}"
|
||||||
switch tree.type
|
switch tree.type
|
||||||
when "File"
|
when "File"
|
||||||
@ -558,7 +516,7 @@ end]]\format(lua_code))
|
|||||||
-- Return <lua code for value>, <additional lua code>
|
-- Return <lua code for value>, <additional lua code>
|
||||||
@assert tree, "No tree provided."
|
@assert tree, "No tree provided."
|
||||||
if not tree.type
|
if not tree.type
|
||||||
@errorln debug.traceback()
|
--@errorln debug.traceback()
|
||||||
@error "Invalid tree: #{repr(tree)}"
|
@error "Invalid tree: #{repr(tree)}"
|
||||||
switch tree.type
|
switch tree.type
|
||||||
when "File"
|
when "File"
|
||||||
@ -609,26 +567,21 @@ end]]\format(lua_code))
|
|||||||
remove @compilestack
|
remove @compilestack
|
||||||
return expr:"(#{concat bits, " "})"
|
return expr:"(#{concat bits, " "})"
|
||||||
|
|
||||||
args = {repr(tree.stub), repr(tree\get_line_no!)}
|
arg_positions = def and def.arg_positions or {}
|
||||||
local arg_names, escaped_args
|
args = {}
|
||||||
if def
|
for tok in *tree.value
|
||||||
arg_names, escaped_args = def.arg_names, def.escaped_args
|
if tok.type == "Word" then continue
|
||||||
else
|
lua = @tree_to_lua(tok, filename)
|
||||||
arg_names, escaped_args = [w.value for w in *tree.value when w.type == "Word"], {}
|
@assert(lua.expr, "Cannot use #{tok.src} as an argument, since it's not an expression.")
|
||||||
arg_num = 1
|
|
||||||
for arg in *tree.value
|
|
||||||
if arg.type == 'Word' then continue
|
|
||||||
if escaped_args[arg_names[arg_num]]
|
|
||||||
insert args, "nomsu:parse(#{repr arg.src}, #{repr tree\get_line_no!}).value[1]"
|
|
||||||
else
|
|
||||||
lua = @tree_to_lua arg, filename
|
|
||||||
if lua.statements
|
|
||||||
@error "Cannot use [[#{arg.src}]] as a function argument to #{tree.stub}, since it's not an expression."
|
|
||||||
insert args, lua.expr
|
insert args, lua.expr
|
||||||
arg_num += 1
|
|
||||||
|
|
||||||
|
if def
|
||||||
|
new_args = [args[p] for p in *def.arg_positions]
|
||||||
|
args = new_args
|
||||||
|
|
||||||
|
insert args, 1, "nomsu"
|
||||||
remove @compilestack
|
remove @compilestack
|
||||||
return expr:@@comma_separated_items("nomsu:call(", args, ")")
|
return expr:@@comma_separated_items("nomsu.defs[#{repr tree.stub}].fn(", args, ")")
|
||||||
|
|
||||||
when "String"
|
when "String"
|
||||||
concat_parts = {}
|
concat_parts = {}
|
||||||
@ -818,25 +771,10 @@ end]]\format(lua_code))
|
|||||||
assert: (condition, msg='')=>
|
assert: (condition, msg='')=>
|
||||||
if not condition
|
if not condition
|
||||||
@error("Assertion failed: "..msg)
|
@error("Assertion failed: "..msg)
|
||||||
|
return condition
|
||||||
|
|
||||||
error: (msg)=>
|
error: (msg)=>
|
||||||
error_msg = colored.red "ERROR!"
|
error msg, 0
|
||||||
if msg and #msg > 0
|
|
||||||
error_msg ..= "\n" .. (colored.bright colored.yellow colored.onred msg)
|
|
||||||
else
|
|
||||||
error_msg ..= "\n<no message>"
|
|
||||||
error_msg ..= "\nCallstack:"
|
|
||||||
maxlen = max([#c[2] for c in *@callstack when c != "#macro"])
|
|
||||||
for i=#@callstack,1,-1
|
|
||||||
if @callstack[i] != "#macro"
|
|
||||||
line_no = @callstack[i][2]
|
|
||||||
if line_no
|
|
||||||
nums = [tonumber(n) for n in line_no\gmatch(":([0-9]+)")]
|
|
||||||
line_no = line_no\gsub(":.*$", ":#{sum(nums) - #nums + 1}")
|
|
||||||
error_msg ..= "\n #{"%-#{maxlen}s"\format line_no}| #{@callstack[i][1]}"
|
|
||||||
error_msg ..= "\n <top level>"
|
|
||||||
@callstack = {}
|
|
||||||
error error_msg, 3
|
|
||||||
|
|
||||||
source_code: (level=0)=>
|
source_code: (level=0)=>
|
||||||
@dedent @compilestack[#@compilestack-level].src
|
@dedent @compilestack[#@compilestack-level].src
|
||||||
@ -855,35 +793,38 @@ end]]\format(lua_code))
|
|||||||
insert concat_parts, lua.expr
|
insert concat_parts, lua.expr
|
||||||
return concat(concat_parts)
|
return concat(concat_parts)
|
||||||
|
|
||||||
@defmacro "do %block", (_block)=>
|
@defmacro "do %block", "nomsu.moon", (_block)=>
|
||||||
make_line = (lua)-> lua.expr and (lua.expr..";") or lua.statements
|
make_line = (lua)-> lua.expr and (lua.expr..";") or lua.statements
|
||||||
if _block.type == "Block"
|
if _block.type == "Block"
|
||||||
return @tree_to_lua(_block)
|
return @tree_to_lua(_block)
|
||||||
else
|
else
|
||||||
return expr:"#{@tree_to_lua _block}(nomsu)"
|
return expr:"#{@tree_to_lua _block}(nomsu)"
|
||||||
|
|
||||||
@defmacro "immediately %block", (_block)=>
|
@defmacro "immediately %block", "nomsu.moon", (_block)=>
|
||||||
lua = @tree_to_lua(_block)
|
lua = @tree_to_lua(_block)
|
||||||
lua_code = lua.statements or (lua.expr..";")
|
lua_code = lua.statements or (lua.expr..";")
|
||||||
lua_code = "-- Immediately:\n"..lua_code
|
lua_code = "-- Immediately:\n"..lua_code
|
||||||
@run_lua(lua_code)
|
@run_lua(lua_code)
|
||||||
return statements:lua_code
|
return statements:lua_code
|
||||||
|
|
||||||
@defmacro "lua> %code", (_code)=>
|
@defmacro "lua> %code", "nomsu.moon", (_code)=>
|
||||||
lua = nomsu_string_as_lua(@, _code)
|
lua = nomsu_string_as_lua(@, _code)
|
||||||
return statements:lua
|
return statements:lua
|
||||||
|
|
||||||
@defmacro "=lua %code", (_code)=>
|
@defmacro "=lua %code", "nomsu.moon", (_code)=>
|
||||||
lua = nomsu_string_as_lua(@, _code)
|
lua = nomsu_string_as_lua(@, _code)
|
||||||
return expr:lua
|
return expr:lua
|
||||||
|
|
||||||
@defmacro "__src__ %level", (_level)=>
|
@defmacro "__line_no__", "nomsu.moon", ()=>
|
||||||
|
expr: repr(@compilestack[#@compilestack]\get_line_no!)
|
||||||
|
|
||||||
|
@defmacro "__src__ %level", "nomsu.moon", (_level)=>
|
||||||
expr: repr(@source_code(@tree_to_value(_level)))
|
expr: repr(@source_code(@tree_to_value(_level)))
|
||||||
|
|
||||||
@def "run file %filename", (_filename)=>
|
@def "run file %filename", "nomsu.moon", (_filename)=>
|
||||||
@run_file(_filename)
|
@run_file(_filename)
|
||||||
|
|
||||||
@defmacro "require %filename", (_filename)=>
|
@defmacro "require %filename", "nomsu.moon", (_filename)=>
|
||||||
filename = @tree_to_value(_filename)
|
filename = @tree_to_value(_filename)
|
||||||
@require_file(filename)
|
@require_file(filename)
|
||||||
return statements:"nomsu:require_file(#{repr filename});"
|
return statements:"nomsu:require_file(#{repr filename});"
|
||||||
@ -904,40 +845,41 @@ if arg
|
|||||||
print "Usage: lua nomsu.lua [-c] [-i] [-p] [-O] [--help] [input [-o output]]"
|
print "Usage: lua nomsu.lua [-c] [-i] [-p] [-O] [--help] [input [-o output]]"
|
||||||
os.exit!
|
os.exit!
|
||||||
|
|
||||||
c = NomsuCompiler()
|
nomsu = NomsuCompiler()
|
||||||
|
|
||||||
|
run = ->
|
||||||
if args.flags["-v"]
|
if args.flags["-v"]
|
||||||
c.debug = true
|
nomsu.debug = true
|
||||||
|
|
||||||
c.skip_precompiled = not args.flags["-O"]
|
nomsu.skip_precompiled = not args.flags["-O"]
|
||||||
if args.input
|
if args.input
|
||||||
-- Read a file or stdin and output either the printouts or the compiled lua
|
-- Read a file or stdin and output either the printouts or the compiled lua
|
||||||
if args.flags["-c"] and not args.output
|
if args.flags["-c"] and not args.output
|
||||||
args.output = args.input\gsub("%.nom", ".lua")
|
args.output = args.input\gsub("%.nom", ".lua")
|
||||||
compiled_output = nil
|
compiled_output = nil
|
||||||
if args.flags["-p"]
|
if args.flags["-p"]
|
||||||
_write = c.write
|
_write = nomsu.write
|
||||||
c.write = ->
|
nomsu.write = ->
|
||||||
compiled_output = io.output()
|
compiled_output = io.output()
|
||||||
elseif args.output
|
elseif args.output
|
||||||
compiled_output = io.open(args.output, 'w')
|
compiled_output = io.open(args.output, 'w')
|
||||||
|
|
||||||
if args.input\match(".*%.lua")
|
if args.input\match(".*%.lua")
|
||||||
retval = dofile(args.input)(c, {})
|
retval = dofile(args.input)(nomsu, {})
|
||||||
else
|
else
|
||||||
input = if args.input == '-'
|
input = if args.input == '-'
|
||||||
io.read('*a')
|
io.read('*a')
|
||||||
else io.open(args.input)\read("*a")
|
else io.open(args.input)\read("*a")
|
||||||
retval, code = c\run(input, args.input)
|
retval, code = nomsu\run(input, args.input)
|
||||||
if args.output
|
if args.output
|
||||||
compiled_output\write(code)
|
compiled_output\write(code)
|
||||||
|
|
||||||
if args.flags["-p"]
|
if args.flags["-p"]
|
||||||
c.write = _write
|
nomsu.write = _write
|
||||||
|
|
||||||
if args.flags["-i"]
|
if args.flags["-i"]
|
||||||
-- REPL
|
-- REPL
|
||||||
c\run('require "lib/core.nom"', "stdin")
|
nomsu\run('require "lib/core.nom"', "stdin")
|
||||||
while true
|
while true
|
||||||
buff = ""
|
buff = ""
|
||||||
while true
|
while true
|
||||||
@ -948,8 +890,51 @@ if arg
|
|||||||
buff ..= line
|
buff ..= line
|
||||||
if #buff == 0
|
if #buff == 0
|
||||||
break
|
break
|
||||||
ok, ret = pcall(-> c\run(buff, "stdin"))
|
ok, ret = pcall(-> nomsu\run(buff, "stdin"))
|
||||||
if ok and ret != nil
|
if ok and ret != nil
|
||||||
print "= "..repr(ret)
|
print "= "..repr(ret)
|
||||||
|
|
||||||
|
err_hand = (error_message)->
|
||||||
|
print("#{colored.red "ERROR:"} #{colored.bright colored.yellow colored.onred (error_message or "")}")
|
||||||
|
print("stack traceback:")
|
||||||
|
|
||||||
|
import to_lua from require "moonscript.base"
|
||||||
|
nomsu_file = io.open("nomsu.moon")
|
||||||
|
nomsu_source = nomsu_file\read("*a")
|
||||||
|
_, line_table = to_lua(nomsu_source)
|
||||||
|
nomsu_file\close!
|
||||||
|
|
||||||
|
function_defs = {def.fn, def for _,def in pairs(nomsu.defs) when def.fn}
|
||||||
|
level = 2
|
||||||
|
while true
|
||||||
|
calling_fn = debug.getinfo(level)
|
||||||
|
if not calling_fn then break
|
||||||
|
if calling_fn.func == run then break
|
||||||
|
level += 1
|
||||||
|
name = calling_fn.name
|
||||||
|
if name == "run_lua_fn" then continue
|
||||||
|
line = nil
|
||||||
|
if def = function_defs[calling_fn.func]
|
||||||
|
line = colored.yellow(def.line_no)
|
||||||
|
name = colored.bright(colored.yellow(def.aliases[1]))
|
||||||
|
else
|
||||||
|
if calling_fn.istailcall and not name
|
||||||
|
name = "<tail call>"
|
||||||
|
if calling_fn.short_src == "./nomsu.moon"
|
||||||
|
-- Ugh, magic numbers, but this works
|
||||||
|
char = line_table[calling_fn.linedefined-2]
|
||||||
|
line_num = 3
|
||||||
|
for _ in nomsu_source\sub(1,char)\gmatch("\n") do line_num += 1
|
||||||
|
line = colored.cyan("#{calling_fn.short_src}:#{line_num}")
|
||||||
|
name = colored.bright(colored.cyan(name or "???"))
|
||||||
|
else
|
||||||
|
line = colored.blue("#{calling_fn.short_src}:#{calling_fn.linedefined}")
|
||||||
|
name = colored.bright(colored.blue(name or "???"))
|
||||||
|
_from = colored.dim colored.white "|"
|
||||||
|
print(("%32s %s %s")\format(name, _from, line))
|
||||||
|
|
||||||
|
os.exit(false, true)
|
||||||
|
|
||||||
|
xpcall(run, err_hand)
|
||||||
|
|
||||||
return NomsuCompiler
|
return NomsuCompiler
|
||||||
|
Loading…
Reference in New Issue
Block a user