aboutsummaryrefslogtreecommitdiff
path: root/nomsu.lua
diff options
context:
space:
mode:
Diffstat (limited to 'nomsu.lua')
-rw-r--r--nomsu.lua374
1 files changed, 156 insertions, 218 deletions
diff --git a/nomsu.lua b/nomsu.lua
index 282831c..5689426 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -35,9 +35,6 @@ do
return string[i]
end
end
- STRING_METATABLE.__mul = function(self, other)
- return string.rep(self, other)
- end
end
lpeg.setmaxstack(10000)
local P, R, V, S, Cg, C, Cp, B, Cmt
@@ -45,7 +42,7 @@ P, R, V, S, Cg, C, Cp, B, Cmt = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.Cg, lpeg.C,
local NOMSU_DEFS
do
local _with_0 = { }
- _with_0.nl = P("\n")
+ _with_0.nl = P("\r") ^ -1 * P("\n")
_with_0.ws = S(" \t")
_with_0.tonumber = tonumber
_with_0.print = function(src, pos, msg)
@@ -100,8 +97,8 @@ do
end
end)
_with_0.error = function(src, pos, err_msg)
- if lpeg.userdata.source_code:sub(pos, pos) == "\n" then
- pos = pos + #lpeg.userdata.source_code:match("[ \t\n]*", pos)
+ if lpeg.userdata.source_code:sub(pos, pos):match("[\r\n]") then
+ pos = pos + #lpeg.userdata.source_code:match("[ \t\n\r]*", pos)
end
local line_no = 1
while (lpeg.userdata.line_starts[line_no + 1] or math.huge) < pos do
@@ -109,14 +106,14 @@ do
end
local prev_line
if line_no > 1 then
- prev_line = lpeg.userdata.source_code:match("[^\n]*", lpeg.userdata.line_starts[line_no - 1])
+ prev_line = lpeg.userdata.source_code:match("[^\r\n]*", lpeg.userdata.line_starts[line_no - 1])
else
prev_line = ""
end
- local err_line = lpeg.userdata.source_code:match("[^\n]*", lpeg.userdata.line_starts[line_no])
+ local err_line = lpeg.userdata.source_code:match("[^\r\n]*", lpeg.userdata.line_starts[line_no])
local next_line
if line_no < #lpeg.userdata.line_starts then
- next_line = lpeg.userdata.source_code:match("[^\n]*", lpeg.userdata.line_starts[line_no + 1])
+ next_line = lpeg.userdata.source_code:match("[^\r\n]*", lpeg.userdata.line_starts[line_no + 1])
else
next_line = ""
end
@@ -138,13 +135,14 @@ do
end)(), " ")
local src = lpeg.userdata.source_code:sub(start, stop - 1)
return {
+ type = "FunctionCall",
start = start,
stop = stop,
- type = "FunctionCall",
- src = src,
- get_line_no = lpeg.userdata.get_line_no,
value = value,
- stub = stub
+ stub = stub,
+ filename = lpeg.userdata.filename,
+ get_line_no = lpeg.userdata.get_line_no,
+ get_src = lpeg.userdata.get_src
}
end
NOMSU_DEFS = _with_0
@@ -154,12 +152,13 @@ setmetatable(NOMSU_DEFS, {
local make_node
make_node = function(start, value, stop)
return {
+ type = key,
start = start,
stop = stop,
value = value,
- src = lpeg.userdata.source_code:sub(start, stop - 1),
- get_line_no = lpeg.userdata.get_line_no,
- type = key
+ filename = lpeg.userdata.filename,
+ get_src = lpeg.userdata.get_src,
+ get_line_no = lpeg.userdata.get_line_no
}
end
self[key] = make_node
@@ -183,28 +182,28 @@ end
local NomsuCompiler
do
local _class_0
+ local line_counter, stub_defs, stub_pattern, var_pattern
local _base_0 = {
writeln = function(self, ...)
self:write(...)
return self:write("\n")
end,
- errorln = function(self, ...)
- self:write_err(...)
- return self:write_err("\n")
- end,
- define_action = function(self, signature, line_no, fn, src, compile_time)
- if compile_time == nil then
- compile_time = false
+ define_action = function(self, signature, source, fn)
+ if self.debug then
+ self:writeln(tostring(colored.bright("DEFINING ACTION:")) .. " " .. tostring(colored.green(repr(signature))))
+ end
+ if type(fn) ~= 'function' then
+ error('function', "Bad fn: " .. tostring(repr(fn)))
end
if type(signature) == 'string' then
- signature = self:get_stubs({
+ signature = {
signature
- })
- elseif type(signature) == 'table' and type(signature[1]) == 'string' then
- signature = self:get_stubs(signature)
+ }
+ elseif type(signature) ~= 'table' or signature.type ~= nil then
+ error("Invalid signature, expected list of strings, but got: " .. tostring(repr(signature)), 0)
end
- assert(type(fn) == 'function', "Bad fn: " .. tostring(repr(fn)))
- local aliases = { }
+ local stubs = self:get_stubs_from_signature(signature)
+ local stub_args = self:get_args_from_signature(signature)
self.__class.def_number = self.__class.def_number + 1
local fn_info = debug.getinfo(fn, "u")
local fn_arg_positions, arg_orders
@@ -218,11 +217,10 @@ do
end
arg_orders = { }
end
- for sig_i = 1, #signature do
- local stub, arg_names = unpack(signature[sig_i])
- assert(stub, "NO STUB FOUND: " .. tostring(repr(signature)))
+ for sig_i = 1, #stubs do
+ local stub, args = stubs[sig_i], stub_args[sig_i]
if self.debug then
- self:writeln(tostring(colored.bright("DEFINING ACTION:")) .. " " .. tostring(colored.underscore(colored.magenta(repr(stub)))) .. " " .. tostring(colored.bright("WITH ARGS")) .. " " .. tostring(colored.dim(repr(arg_names))) .. " ON: " .. tostring(self.environment.ACTIONS))
+ self:writeln(tostring(colored.bright("ALIAS:")) .. " " .. tostring(colored.underscore(colored.magenta(repr(stub)))) .. " " .. tostring(colored.bright("WITH ARGS")) .. " " .. tostring(colored.dim(repr(args))) .. " ON: " .. tostring(self.environment.ACTIONS))
end
self.environment.ACTIONS[stub] = fn
if not (fn_info.isvararg) then
@@ -230,33 +228,31 @@ do
do
local _accum_0 = { }
local _len_0 = 1
- for _index_0 = 1, #arg_names do
- local a = arg_names[_index_0]
- _accum_0[_len_0] = fn_arg_positions[self:var_to_lua_identifier(a)]
+ for _index_0 = 1, #args do
+ local a = args[_index_0]
+ _accum_0[_len_0] = fn_arg_positions[a]
_len_0 = _len_0 + 1
end
arg_positions = _accum_0
end
- assert(#arg_positions == #arg_names, "Mismatch in args between lua function's " .. tostring(repr(fn_arg_positions)) .. " and stub's " .. tostring(repr(arg_names)))
+ if #arg_positions ~= #args then
+ error("Mismatch in args between lua function's " .. tostring(repr(fn_arg_positions)) .. " and stub's " .. tostring(repr(args)) .. " for " .. tostring(repr(stub)), 0)
+ end
arg_orders[stub] = arg_positions
end
end
self.action_metadata[fn] = {
fn = fn,
- src = src,
- line_no = line_no,
- aliases = aliases,
+ source = source,
+ aliases = stubs,
arg_orders = arg_orders,
arg_positions = fn_arg_positions,
def_number = self.__class.def_number
}
end,
- define_compile_action = function(self, signature, line_no, fn, src)
- self:define_action(signature, line_no, fn, src, true)
+ define_compile_action = function(self, signature, source, fn, src)
+ self:define_action(signature, source, fn)
self.action_metadata[fn].compile_time = true
- if self.debug then
- return self:writeln(tostring(colored.bright(colored.green("(it was compile time)"))))
- end
end,
serialize_defs = function(self, scope, after)
if scope == nil then
@@ -265,68 +261,7 @@ do
if after == nil then
after = nil
end
- error("Not currently functional.")
- after = after or (self.core_defs or 0)
- scope = scope or self.defs
- local defs_by_num = { }
- for stub, def in pairs(scope) do
- if def and stub:sub(1, 1) ~= "#" then
- defs_by_num[def.def_number] = def
- end
- end
- local keys
- do
- local _accum_0 = { }
- local _len_0 = 1
- for k, v in pairs(defs_by_num) do
- _accum_0[_len_0] = k
- _len_0 = _len_0 + 1
- end
- keys = _accum_0
- end
- table.sort(keys)
- local buff = { }
- local k_i = 1
- local _using = nil
- local _using_do = { }
- for k_i, i in ipairs(keys) do
- local _continue_0 = false
- repeat
- if i <= after then
- _continue_0 = true
- break
- end
- local def = defs_by_num[i]
- if def.defs == scope then
- if def.src then
- insert(buff, def.src)
- end
- _continue_0 = true
- break
- end
- if _using == def.defs then
- if def.src then
- insert(_using_do, def.src)
- end
- else
- _using = def.defs
- _using_do = {
- def.src
- }
- end
- if k_i == #keys or defs_by_num[keys[k_i + 1]].defs ~= _using then
- insert(buff, "using:\n " .. tostring(self:indent(self:serialize_defs(_using))) .. "\n..do:\n " .. tostring(self:indent(concat(_using_do, "\n"))))
- end
- _continue_0 = true
- until true
- if not _continue_0 then
- break
- end
- end
- for k, v in pairs(scope["#vars"] or { }) do
- insert(buff, "<%" .. tostring(k) .. "> = " .. tostring(self:value_to_nomsu(v)))
- end
- return concat(buff, "\n")
+ return error("Not currently functional.", 0)
end,
dedent = function(self, code)
if not (code:find("\n")) then
@@ -336,7 +271,7 @@ do
for line in code:gmatch("\n([^\n]*)") do
local _continue_0 = false
repeat
- if line:match("^%s*#.*") then
+ if line:match("^%s*#.*") or line:match("^%s*$") then
_continue_0 = true
break
else
@@ -362,8 +297,10 @@ do
end
if spaces ~= math.huge and spaces < indent_spaces then
return (code:gsub("\n" .. (" "):rep(spaces), "\n"))
- else
+ elseif indent_spaces ~= math.huge then
return (code:gsub("\n" .. (" "):rep(indent_spaces), "\n "))
+ else
+ return code
end
end,
indent = function(self, code, levels)
@@ -377,7 +314,6 @@ do
if self.debug then
self:writeln(tostring(colored.bright("PARSING:")) .. "\n" .. tostring(colored.yellow(nomsu_code)))
end
- nomsu_code = nomsu_code:gsub("\r", "")
local userdata
do
local _with_0 = {
@@ -387,11 +323,14 @@ do
0
}
}
- _with_0.line_starts = re.compile("lines <- {| line ('\n' line)* |} line <- {} [^\n]*"):match(nomsu_code)
+ _with_0.get_src = function(self)
+ return nomsu_code:sub(self.start, self.stop - 1)
+ end
+ _with_0.line_starts = line_counter:match(_with_0.source_code)
_with_0.get_line_no = function(self)
if not (self._line_no) then
local line_no = 1
- while (_with_0.line_starts[line_no + 1] or math.huge) < self.start do
+ while line_no < #_with_0.line_starts and _with_0.line_starts[line_no + 1] < self.start do
line_no = line_no + 1
end
self._line_no = tostring(_with_0.filename) .. ":" .. tostring(line_no)
@@ -425,7 +364,7 @@ do
local timeout
timeout = function()
debug.sethook()
- return error("Execution quota exceeded. Your code took too long.")
+ return error("Execution quota exceeded. Your code took too long.", 0)
end
debug.sethook(timeout, "", max_operations)
end
@@ -434,9 +373,8 @@ do
assert(tree.type == "File", "Attempt to run non-file: " .. tostring(tree.type))
local lua = self:tree_to_lua(tree)
local lua_code = lua.statements or (lua.expr .. ";")
- local locals = lua_code.locals or { }
- if #locals > 0 then
- lua_code = "local " .. concat(locals, ", ") .. ";\n" .. lua_code
+ if lua_code.locals and #lua_code.locals > 0 then
+ lua_code = "local " .. concat(lua_code.locals, ", ") .. ";\n" .. lua_code
end
lua_code = "-- File: " .. tostring(filename) .. "\n" .. lua_code
local ret = self:run_lua(lua_code)
@@ -466,13 +404,13 @@ do
end
local file = file or io.open(filename)
if not file then
- error("File does not exist: " .. tostring(filename))
+ error("File does not exist: " .. tostring(filename), 0)
end
local nomsu_code = file:read('*a')
file:close()
return self:run(nomsu_code, filename)
else
- return error("Invalid filetype for " .. tostring(filename))
+ return error("Invalid filetype for " .. tostring(filename), 0)
end
end,
require_file = function(self, filename)
@@ -495,18 +433,21 @@ do
return ("\n%-3d|"):format(n)
end
local code = "1 |" .. lua_code:gsub("\n", fn)
- error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(err))
+ error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(err), 0)
end
return run_lua_fn()
end,
tree_to_value = function(self, tree, filename)
+ if tree.type == 'Text' and #tree.value == 1 and type(tree.value[1]) == 'string' then
+ return tree.value[1]
+ end
local code = "return " .. tostring(self:tree_to_lua(tree).expr) .. ";"
if self.debug then
self:writeln(tostring(colored.bright("RUNNING LUA TO GET VALUE:")) .. "\n" .. tostring(colored.blue(colored.bright(code))))
end
local lua_thunk, err = load(code, nil, nil, self.environment)
if not lua_thunk then
- error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(colored.red(err)))
+ error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(code)))) .. "\n\n" .. tostring(colored.red(err)), 0)
end
return lua_thunk()
end,
@@ -828,7 +769,7 @@ do
for _index_0 = 1, #_list_0 do
local line = _list_0[_index_0]
nomsu = expression(line)
- assert(nomsu, "Failed to produce output for:\n" .. tostring(colored.yellow(line.src)))
+ assert(nomsu, "Failed to produce output for:\n" .. tostring(colored.yellow(line:get_src())))
insert(lines, nomsu)
end
return concat(lines, "\n")
@@ -884,13 +825,13 @@ do
return '".."\n ' .. (self:indent(value))
end
else
- return error("Unsupported value_to_nomsu type: " .. tostring(type(value)))
+ return error("Unsupported value_to_nomsu type: " .. tostring(type(value)), 0)
end
end,
tree_to_lua = function(self, tree)
assert(tree, "No tree provided.")
if not tree.type then
- error("Invalid tree: " .. tostring(repr(tree)))
+ error("Invalid tree: " .. tostring(repr(tree)), 0)
end
local _exp_0 = tree.type
if "File" == _exp_0 then
@@ -899,12 +840,13 @@ do
end
local declared_locals = { }
local lua_bits = { }
+ local line_no = 1
local _list_0 = tree.value
for _index_0 = 1, #_list_0 do
local line = _list_0[_index_0]
local lua = self:tree_to_lua(line)
if not lua then
- error("No lua produced by " .. tostring(repr(line)))
+ error("No lua produced by " .. tostring(repr(line)), 0)
end
if lua.locals then
local new_locals
@@ -944,7 +886,7 @@ do
}
elseif "Nomsu" == _exp_0 then
return {
- expr = "nomsu:parse(" .. tostring(repr(tree.value.src)) .. ", " .. tostring(repr(tree:get_line_no())) .. ").value[1]"
+ expr = "nomsu:parse(" .. tostring(repr(tree.value:get_src())) .. ", " .. tostring(repr(tree:get_line_no())) .. ").value[1]"
}
elseif "Block" == _exp_0 then
local lua_bits = { }
@@ -971,9 +913,10 @@ do
insert(lua_bits, tostring(lua.expr) .. ";")
end
end
+ utils.deduplicate(locals)
return {
statements = concat(lua_bits, "\n"),
- locals = (next(locals) and utils.keys(locals) or nil)
+ locals = (#locals > 0 and locals or nil)
}
elseif "FunctionCall" == _exp_0 then
insert(self.compilestack, tree)
@@ -1034,7 +977,7 @@ do
insert(bits, tok.value)
else
local lua = self:tree_to_lua(tok)
- assert(lua.expr, "non-expression value inside math expression: " .. tostring(tok.src))
+ assert(lua.expr, "non-expression value inside math expression: " .. tostring(tok:get_src()))
insert(bits, lua.expr)
end
end
@@ -1054,7 +997,7 @@ do
break
end
local lua = self:tree_to_lua(tok)
- assert(lua.expr, tostring(tree:get_line_no()) .. ": Cannot use:\n" .. tostring(colored.yellow(tok.src)) .. "\nas an argument to " .. tostring(tree.stub) .. ", since it's not an expression, it produces: " .. tostring(repr(lua)))
+ assert(lua.expr, tostring(tree:get_line_no()) .. ": Cannot use:\n" .. tostring(colored.yellow(tok:get_src())) .. "\nas an argument to " .. tostring(tree.stub) .. ", since it's not an expression, it produces: " .. tostring(repr(lua)))
insert(args, lua.expr)
_continue_0 = true
until true
@@ -1104,7 +1047,7 @@ do
self:print_tree(bit)
self:writeln(tostring(colored.bright("EXPR:")) .. " " .. tostring(lua.expr) .. ", " .. tostring(colored.bright("STATEMENT:")) .. " " .. tostring(lua.statements))
end
- assert(lua.expr, "Cannot use [[" .. tostring(bit.src) .. "]] as a string interpolation value, since it's not an expression.")
+ assert(lua.expr, "Cannot use [[" .. tostring(bit:get_src()) .. "]] as a string interpolation value, since it's not an expression.")
insert(concat_parts, "stringify(" .. tostring(lua.expr) .. ")")
_continue_0 = true
until true
@@ -1134,7 +1077,7 @@ do
for _index_0 = 1, #_list_0 do
local item = _list_0[_index_0]
local lua = self:tree_to_lua(item)
- assert(lua.expr, "Cannot use [[" .. tostring(item.src) .. "]] as a list item, since it's not an expression.")
+ assert(lua.expr, "Cannot use [[" .. tostring(item:get_src()) .. "]] as a list item, since it's not an expression.")
insert(items, lua.expr)
end
return {
@@ -1153,9 +1096,9 @@ do
else
key_lua = self:tree_to_lua(entry.dict_key)
end
- assert(key_lua.expr, "Cannot use [[" .. tostring(entry.dict_key.src) .. "]] as a dict key, since it's not an expression.")
+ assert(key_lua.expr, "Cannot use [[" .. tostring(entry.dict_key:get_src()) .. "]] as a dict key, since it's not an expression.")
local value_lua = self:tree_to_lua(entry.dict_value)
- assert(value_lua.expr, "Cannot use [[" .. tostring(entry.dict_value.src) .. "]] as a dict value, since it's not an expression.")
+ assert(value_lua.expr, "Cannot use [[" .. tostring(entry.dict_value:get_src()) .. "]] as a dict value, since it's not an expression.")
local key_str = key_lua.expr:match([=[["']([a-zA-Z_][a-zA-Z0-9_]*)['"]]=])
if key_str then
insert(items, tostring(key_str) .. "=" .. tostring(value_lua.expr))
@@ -1177,7 +1120,7 @@ do
expr = self:var_to_lua_identifier(tree.value)
}
else
- return error("Unknown/unimplemented thingy: " .. tostring(tree.type))
+ return error("Unknown/unimplemented thingy: " .. tostring(tree.type), 0)
end
end,
walk_tree = function(self, tree, depth)
@@ -1239,8 +1182,9 @@ do
end
local _exp_0 = tree.type
if "Var" == _exp_0 then
- if replacements[tree.value] ~= nil then
- tree = replacements[tree.value]
+ local id = self:var_to_lua_identifier(tree.value)
+ if replacements[id] ~= nil then
+ tree = replacements[id]
end
elseif "File" == _exp_0 or "Nomsu" == _exp_0 or "Block" == _exp_0 or "List" == _exp_0 or "FunctionCall" == _exp_0 or "Text" == _exp_0 then
local new_value = self:tree_with_replaced_vars(tree.value, replacements)
@@ -1289,69 +1233,41 @@ do
end
return tree
end,
- get_stub = function(self, x)
- if not x then
- error("Nothing to get stub from")
- end
- if type(x) == 'string' then
- local spec = concat(self.__class.stub_patt:match(x), " ")
- local arg_names = { }
- local stub = spec:gsub("%%(%S*)", function(arg)
- insert(arg_names, arg)
- return "%"
- end)
- return stub, arg_names
- end
- if type(x) ~= 'table' then
- error("Invalid type for getting stub: " .. tostring(type(x)) .. " for:\n" .. tostring(repr(x)))
- end
- local _exp_0 = x.type
- if "Text" == _exp_0 then
- return self:get_stub(x.value)
- elseif "FunctionCall" == _exp_0 then
- return self:get_stub(x.src)
- else
- return error("Unsupported get stub type: " .. tostring(x.type) .. " for " .. tostring(repr(x)))
+ get_stubs_from_signature = function(self, signature)
+ if type(signature) ~= 'table' or signature.type then
+ error("Invalid signature: " .. tostring(repr(signature)), 0)
+ end
+ local stubs = { }
+ for i, alias in ipairs(signature) do
+ if type(alias) ~= 'string' then
+ error("Expected entries in signature to be strings, not " .. tostring(type(alias)) .. "s like: " .. tostring(repr(alias)) .. "\nsignature: " .. tostring(repr(signature)), 0)
+ end
+ stubs[i] = stub_pattern:match(alias)
+ if not (stubs[i]) then
+ error("Failed to match stub pattern on alias: " .. tostring(repr(alias)))
+ end
end
+ return stubs
end,
- get_stubs = function(self, x)
- if type(x) ~= 'table' then
- return {
- {
- self:get_stub(x)
- }
- }
- end
- local _exp_0 = x.type
- if nil == _exp_0 then
- local _accum_0 = { }
- local _len_0 = 1
- for _index_0 = 1, #x do
- local i = x[_index_0]
- _accum_0[_len_0] = {
- self:get_stub(i)
- }
- _len_0 = _len_0 + 1
+ get_args_from_signature = function(self, signature)
+ if type(signature) ~= 'table' or signature.type then
+ error("Invalid signature: " .. tostring(repr(signature)), 0)
+ end
+ local stub_args = { }
+ for i, alias in ipairs(signature) do
+ if type(alias) ~= 'string' then
+ error("Invalid type for signature: " .. tostring(type(alias)) .. " for:\n" .. tostring(repr(alias)), 0)
end
- return _accum_0
- elseif "List" == _exp_0 then
- local _accum_0 = { }
- local _len_0 = 1
- local _list_0 = x.value
- for _index_0 = 1, #_list_0 do
- local i = _list_0[_index_0]
- _accum_0[_len_0] = {
- self:get_stub(i)
- }
- _len_0 = _len_0 + 1
+ local args = var_pattern:match(alias)
+ if not (args) then
+ error("Failed to match arg pattern on alias: " .. tostring(repr(alias)), 0)
end
- return _accum_0
+ for j = 1, #args do
+ args[j] = self:var_to_lua_identifier(args[j])
+ end
+ stub_args[i] = args
end
- return {
- {
- self:get_stub(x)
- }
- }
+ return stub_args
end,
var_to_lua_identifier = function(self, var)
if type(var) == 'table' and var.type == "Var" then
@@ -1369,9 +1285,13 @@ do
if level == nil then
level = 0
end
- return self:dedent(self.compilestack[#self.compilestack - level].src)
+ return self:dedent(self.compilestack[#self.compilestack - level]:get_src())
end,
initialize_core = function(self)
+ local get_line_no
+ get_line_no = function()
+ return "nomsu.moon:" .. tostring(debug.getinfo(2).currentline)
+ end
local nomsu = self
local nomsu_string_as_lua
nomsu_string_as_lua = function(code)
@@ -1383,23 +1303,24 @@ do
insert(concat_parts, bit)
else
local lua = nomsu:tree_to_lua(bit)
- assert(lua.expr, "Cannot use [[" .. tostring(bit.src) .. "]] as a string interpolation value, since it's not an expression.")
+ if not (lua.expr) then
+ error("Cannot use [[" .. tostring(bit:get_src()) .. "]] as a string interpolation value, since it's not an expression.", 0)
+ end
insert(concat_parts, lua.expr)
end
end
return concat(concat_parts)
end
- self:define_compile_action("immediately %block", "nomsu.moon", function(_block)
+ self:define_compile_action("immediately %block", get_line_no(), function(_block)
local lua = nomsu:tree_to_lua(_block)
local lua_code = lua.statements or (lua.expr .. ";")
- lua_code = "-- Immediately:\n" .. lua_code
nomsu:run_lua(lua_code)
return {
- statements = lua_code,
+ statements = "if IMMEDIATE then\n" .. tostring(lua_code) .. "\nend",
locals = lua.locals
}
end)
- self:define_compile_action("lua> %code", "nomsu.moon", function(_code)
+ self:define_compile_action("lua> %code", get_line_no(), function(_code)
if _code.type == "Text" then
local lua = nomsu_string_as_lua(_code)
return {
@@ -1411,26 +1332,22 @@ do
}
end
end)
- self:define_compile_action("=lua %code", "nomsu.moon", function(_code)
+ self:define_compile_action("=lua %code", get_line_no(), function(_code)
local lua = nomsu_string_as_lua(_code)
return {
expr = lua
}
end)
- self:define_compile_action("__line_no__", "nomsu.moon", function()
- return {
- expr = repr(nomsu.compilestack[#nomsu.compilestack]:get_line_no())
- }
- end)
- self:define_compile_action("__src__ %level", "nomsu.moon", function(_level)
+ self:define_compile_action("!! code location !!", get_line_no(), function()
+ local tree = nomsu.compilestack[#nomsu.compilestack - 1]
return {
- expr = repr(nomsu:source_code(nomsu:tree_to_value(_level)))
+ expr = repr(tostring(tree.filename) .. ":" .. tostring(tree.start) .. "," .. tostring(tree.stop))
}
end)
- self:define_action("run file %filename", "nomsu.moon", function(_filename)
+ self:define_action("run file %filename", get_line_no(), function(_filename)
return nomsu:run_file(_filename)
end)
- return self:define_compile_action("use %filename", "nomsu.moon", function(_filename)
+ return self:define_compile_action("use %filename", get_line_no(), function(_filename)
local filename = nomsu:tree_to_value(_filename)
nomsu:require_file(filename)
return {
@@ -1445,9 +1362,6 @@ do
self.write = function(self, ...)
return io.write(...)
end
- self.write_err = function(self, ...)
- return io.stderr:write(...)
- end
local NaN_surrogate = { }
local nil_surrogate = { }
self.ids = setmetatable({ }, {
@@ -1534,6 +1448,11 @@ do
_base_0.__class = _class_0
local self = _class_0
self.def_number = 0
+ line_counter = re.compile([[ lines <- {| line (%nl line)* |}
+ line <- {} (!%nl .)*
+ ]], {
+ nl = NOMSU_DEFS.nl
+ })
self.math_patt = re.compile([[ "%" (" " [*/^+-] " %")+ ]])
self.unescape_string = function(self, str)
return Cs(((P("\\\\") / "\\") + (P("\\\"") / '"') + NOMSU_DEFS.escaped_char + P(1)) ^ 0):match(str)
@@ -1557,10 +1476,13 @@ do
insert(bits, close)
return concat(bits)
end
- self.stub_patt = re.compile("{|(' '+ / '\n..' / {'%' %id*} / {%id+} / {%op})*|}", {
- id = NOMSU_DEFS.ident_char,
- op = NOMSU_DEFS.operator
- })
+ stub_defs = {
+ space = (P(' ') + P('\n..')) ^ 0,
+ word = (NOMSU_DEFS.ident_char ^ 1 + NOMSU_DEFS.operator ^ 1),
+ varname = (R('az', 'AZ', '09') + P('_') + NOMSU_DEFS.utf8_char) ^ 0
+ }
+ stub_pattern = re.compile("{~ (%space->'') (('%' (%varname->'')) / %word)? ((%space->' ') (('%' (%varname->'')) / %word))* (%space->'') ~}", stub_defs)
+ var_pattern = re.compile("{| %space ((('%' {%varname}) / %word) %space)+ |}", stub_defs)
NomsuCompiler = _class_0
end
if arg then
@@ -1608,7 +1530,8 @@ if arg then
input = io.open(args.input):read("*a")
end
local retval, code = nomsu:run(input, args.input)
- if args.output then
+ if compiled_output then
+ compiled_output:write("local IMMEDIATE = true;\n")
compiled_output:write(code)
end
end
@@ -1671,7 +1594,22 @@ if arg then
do
local metadata = nomsu.action_metadata[calling_fn.func]
if metadata then
- line = colored.yellow(metadata.line_no)
+ local filename, start, stop = metadata.source:match("([^:]*):([0-9]*),([0-9]*)")
+ if filename then
+ local file = io.open(filename):read("*a")
+ local line_no = 1
+ for _ in file:sub(1, tonumber(start)):gmatch("\n") do
+ line_no = line_no + 1
+ end
+ local offending_statement = file:sub(tonumber(start), tonumber(stop))
+ if #offending_statement > 50 then
+ offending_statement = offending_statement:sub(1, 50) .. "..."
+ end
+ offending_statement = colored.red(offending_statement)
+ line = colored.yellow(filename .. ":" .. tostring(line_no) .. "\n " .. offending_statement)
+ else
+ line = colored.yellow(metadata.source)
+ end
name = colored.bright(colored.yellow(metadata.aliases[1]))
else
if calling_fn.istailcall and not name then