Cleaned and fixed up colored console text output for error messages.
This commit is contained in:
parent
e697689ddd
commit
8806d7639e
158
nomsu.lua
158
nomsu.lua
@ -124,18 +124,6 @@ LINE_STARTS = setmetatable({ }, {
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
local LUA_METADATA = { }
|
local LUA_METADATA = { }
|
||||||
local lua_line_to_nomsu_line
|
|
||||||
lua_line_to_nomsu_line = function(lua_filename, lua_line_no)
|
|
||||||
local metadata = assert(LUA_METADATA[lua_filename], "Failed to find nomsu metadata for: " .. tostring(lua_filename) .. ".")
|
|
||||||
local lua_offset = LINE_STARTS[metadata.lua_file][lua_line_no]
|
|
||||||
local best = metadata.nomsu_sources[1]
|
|
||||||
for lua, nomsu in pairs(metadata.lua_to_nomsu) do
|
|
||||||
if lua.start <= lua_offset and lua > best then
|
|
||||||
best = lua
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return best:get_line_number()
|
|
||||||
end
|
|
||||||
do
|
do
|
||||||
local STRING_METATABLE = getmetatable("")
|
local STRING_METATABLE = getmetatable("")
|
||||||
STRING_METATABLE.__add = function(self, other)
|
STRING_METATABLE.__add = function(self, other)
|
||||||
@ -453,19 +441,8 @@ do
|
|||||||
local offset = 1
|
local offset = 1
|
||||||
local source = lua.source
|
local source = lua.source
|
||||||
local nomsu_raw = FILE_CACHE[source.filename]:sub(source.start, source.stop)
|
local nomsu_raw = FILE_CACHE[source.filename]:sub(source.start, source.stop)
|
||||||
local get_line_starts
|
local nomsu_line_to_pos = LINE_STARTS[nomsu_raw]
|
||||||
get_line_starts = function(s)
|
local lua_line_to_pos = LINE_STARTS[tostring(lua)]
|
||||||
local starts = { }
|
|
||||||
local pos = 1
|
|
||||||
for line in s:gmatch("[^\n]*\n") do
|
|
||||||
insert(starts, pos)
|
|
||||||
pos = pos + #line
|
|
||||||
end
|
|
||||||
insert(starts, pos)
|
|
||||||
return starts
|
|
||||||
end
|
|
||||||
local nomsu_line_to_pos = get_line_starts(nomsu_raw)
|
|
||||||
local lua_line_to_pos = get_line_starts(tostring(lua))
|
|
||||||
local pos_to_line
|
local pos_to_line
|
||||||
pos_to_line = function(line_starts, pos)
|
pos_to_line = function(line_starts, pos)
|
||||||
local lo, hi = 1, #line_starts
|
local lo, hi = 1, #line_starts
|
||||||
@ -1459,10 +1436,10 @@ OPTIONS
|
|||||||
return info
|
return info
|
||||||
end
|
end
|
||||||
if info.short_src or info.source or info.linedefine or info.currentline then
|
if info.short_src or info.source or info.linedefine or info.currentline then
|
||||||
for k, v in pairs(nomsu.environment.ACTIONS) do
|
do
|
||||||
if v == info.func then
|
local arg_orders = nomsu.environment.ARG_ORDERS[info.func]
|
||||||
info.name = k
|
if arg_orders then
|
||||||
break
|
info.name = next(arg_orders)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
do
|
do
|
||||||
@ -1486,7 +1463,7 @@ OPTIONS
|
|||||||
local print_err_msg
|
local print_err_msg
|
||||||
print_err_msg = function(error_message, stack_offset)
|
print_err_msg = function(error_message, stack_offset)
|
||||||
if stack_offset == nil then
|
if stack_offset == nil then
|
||||||
stack_offset = 2
|
stack_offset = 3
|
||||||
end
|
end
|
||||||
io.stderr:write(tostring(colored.red("ERROR:")) .. " " .. tostring(colored.bright(colored.red((error_message or "")))) .. "\n")
|
io.stderr:write(tostring(colored.red("ERROR:")) .. " " .. tostring(colored.bright(colored.red((error_message or "")))) .. "\n")
|
||||||
io.stderr:write("stack traceback:\n")
|
io.stderr:write("stack traceback:\n")
|
||||||
@ -1499,7 +1476,19 @@ OPTIONS
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local nomsu_source = FILE_CACHE["nomsu.moon"]
|
local nomsu_source = FILE_CACHE["nomsu.moon"]
|
||||||
local _, line_table = to_lua(nomsu_source)
|
local LINE_TABLES = setmetatable({ }, {
|
||||||
|
__index = function(self, file)
|
||||||
|
local _, line_table = to_lua(file)
|
||||||
|
self[file] = line_table or false
|
||||||
|
return line_table or false
|
||||||
|
end
|
||||||
|
})
|
||||||
|
local get_line
|
||||||
|
get_line = function(file, line_no)
|
||||||
|
local start = LINE_STARTS[file][line_no] or 1
|
||||||
|
local stop = (LINE_STARTS[file][line_no + 1] or 0) - 1
|
||||||
|
return file:sub(start, stop)
|
||||||
|
end
|
||||||
local level = stack_offset
|
local level = stack_offset
|
||||||
while true do
|
while true do
|
||||||
local _continue_0 = false
|
local _continue_0 = false
|
||||||
@ -1513,40 +1502,91 @@ OPTIONS
|
|||||||
end
|
end
|
||||||
level = level + 1
|
level = level + 1
|
||||||
local name = calling_fn.name
|
local name = calling_fn.name
|
||||||
|
if calling_fn.linedefined == 0 then
|
||||||
|
name = "main chunk"
|
||||||
|
end
|
||||||
if name == "run_lua_fn" then
|
if name == "run_lua_fn" then
|
||||||
_continue_0 = true
|
_continue_0 = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
local line = nil
|
local line = nil
|
||||||
_ = [=[ if metadata = nomsu.action_metadata[calling_fn.func]
|
do
|
||||||
filename, start, stop = metadata.source\match("([^:]*):([0-9]*),([0-9]*)")
|
local map = nomsu.source_map[calling_fn.source]
|
||||||
if filename
|
if map then
|
||||||
file = FILE_CACHE[filename]
|
if calling_fn.currentline then
|
||||||
line_no = 1
|
calling_fn.currentline = assert(map[calling_fn.currentline])
|
||||||
for _ in file\sub(1,tonumber(start))\gmatch("\n") do line_no += 1
|
end
|
||||||
offending_statement = file\sub(tonumber(start),tonumber(stop))
|
if calling_fn.linedefined then
|
||||||
if #offending_statement > 50
|
calling_fn.linedefined = assert(map[calling_fn.linedefined])
|
||||||
offending_statement = offending_statement\sub(1,50).."..."
|
end
|
||||||
offending_statement = colored.red(offending_statement)
|
if calling_fn.lastlinedefined then
|
||||||
line = colored.yellow(filename..":"..tostring(line_no).."\n "..offending_statement)
|
calling_fn.lastlinedefined = assert(map[calling_fn.lastlinedefined])
|
||||||
else
|
end
|
||||||
line = colored.yellow(metadata.source)
|
calling_fn.short_src = calling_fn.source:match('"([^[]*)')
|
||||||
name = colored.bright(colored.yellow(metadata.aliases[1]))
|
local filename, start, stop = calling_fn.source:match('"([^[]*)%[([0-9]+):([0-9]+)]"')
|
||||||
|
assert(filename)
|
||||||
|
local file = FILE_CACHE[filename]:sub(tonumber(start), tonumber(stop))
|
||||||
|
local err_line = get_line(file, calling_fn.currentline):sub(1, -2)
|
||||||
|
local offending_statement = colored.red(err_line)
|
||||||
|
line = colored.yellow(tostring(filename) .. ":" .. tostring(calling_fn.currentline) .. "\n" .. tostring(offending_statement))
|
||||||
|
do
|
||||||
|
local arg_orders = nomsu.environment.ARG_ORDERS[calling_fn.func]
|
||||||
|
if arg_orders then
|
||||||
|
name = colored.bright(colored.yellow(next(arg_orders)))
|
||||||
|
else
|
||||||
|
name = colored.bright(colored.yellow("main chunk"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if calling_fn.istailcall and not name then
|
||||||
|
name = "<tail call>"
|
||||||
|
end
|
||||||
|
local file
|
||||||
|
ok, file = pcall(function()
|
||||||
|
return FILE_CACHE[calling_fn.short_src]
|
||||||
|
end)
|
||||||
|
if not ok then
|
||||||
|
file = nil
|
||||||
|
end
|
||||||
|
local line_num
|
||||||
|
if name == nil and debug.getinfo(level + 1) then
|
||||||
|
local i = 1
|
||||||
|
while true do
|
||||||
|
local varname, val = debug.getlocal(level + 1, i)
|
||||||
|
if not varname then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if val == calling_fn.func then
|
||||||
|
name = varname
|
||||||
|
if not varname:match("%(") then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if file and calling_fn.short_src:match(".moon$") and LINE_TABLES[file] then
|
||||||
|
local char = LINE_TABLES[file][calling_fn.currentline]
|
||||||
|
line_num = 1
|
||||||
|
for _ in file: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
|
else
|
||||||
if calling_fn.istailcall and not name
|
line_num = calling_fn.currentline
|
||||||
name = "<tail call>"
|
line = colored.blue(tostring(calling_fn.short_src) .. ":" .. tostring(calling_fn.currentline))
|
||||||
if calling_fn.short_src == "./nomsu.moon" and line_table
|
name = colored.bright(colored.blue(name or "???"))
|
||||||
char = line_table[calling_fn.currentline]
|
end
|
||||||
line_num = 1
|
if file then
|
||||||
for _ in nomsu_source\sub(1,char)\gmatch("\n") do line_num += 1
|
local err_line = get_line(file, line_num):sub(1, -2)
|
||||||
line = colored.cyan("#{calling_fn.short_src}:#{line_num}")
|
local offending_statement = colored.red(err_line)
|
||||||
name = colored.bright(colored.cyan(name or "???"))
|
line = line .. ("\n" .. offending_statement)
|
||||||
else
|
end
|
||||||
line = colored.blue("#{calling_fn.short_src}:#{calling_fn.currentline}")
|
end
|
||||||
name = colored.bright(colored.blue(name or "???"))
|
end
|
||||||
_from = colored.dim colored.white "|"
|
local _from = colored.dim(colored.white("|"))
|
||||||
io.stderr\write(("%32s %s %s\n")\format(name, _from, line))
|
io.stderr:write(("%32s %s %s\n"):format(name, _from, line))
|
||||||
]=]
|
|
||||||
_continue_0 = true
|
_continue_0 = true
|
||||||
until true
|
until true
|
||||||
if not _continue_0 then
|
if not _continue_0 then
|
||||||
|
102
nomsu.moon
102
nomsu.moon
@ -114,15 +114,6 @@ LINE_STARTS = setmetatable {}, {
|
|||||||
-- nomsu_filename, nomsu_file, lua_filename, lua_file
|
-- nomsu_filename, nomsu_file, lua_filename, lua_file
|
||||||
LUA_METADATA = {}
|
LUA_METADATA = {}
|
||||||
|
|
||||||
lua_line_to_nomsu_line = (lua_filename, lua_line_no)->
|
|
||||||
metadata = assert LUA_METADATA[lua_filename], "Failed to find nomsu metadata for: #{lua_filename}."
|
|
||||||
lua_offset = LINE_STARTS[metadata.lua_file][lua_line_no]
|
|
||||||
best = metadata.nomsu_sources[1]
|
|
||||||
for lua,nomsu in pairs metadata.lua_to_nomsu
|
|
||||||
if lua.start <= lua_offset and lua > best
|
|
||||||
best = lua
|
|
||||||
return best\get_line_number!
|
|
||||||
|
|
||||||
-- Use + operator for string coercive concatenation (note: "asdf" + 3 == "asdf3")
|
-- Use + operator for string coercive concatenation (note: "asdf" + 3 == "asdf3")
|
||||||
-- Use [] for accessing string characters, or s[{3,4}] for s:sub(3,4)
|
-- Use [] for accessing string characters, or s[{3,4}] for s:sub(3,4)
|
||||||
-- Note: This globally affects all strings in this instance of Lua!
|
-- Note: This globally affects all strings in this instance of Lua!
|
||||||
@ -420,17 +411,8 @@ class NomsuCompiler
|
|||||||
source = lua.source
|
source = lua.source
|
||||||
nomsu_raw = FILE_CACHE[source.filename]\sub(source.start, source.stop)
|
nomsu_raw = FILE_CACHE[source.filename]\sub(source.start, source.stop)
|
||||||
|
|
||||||
get_line_starts = (s)->
|
nomsu_line_to_pos = LINE_STARTS[nomsu_raw]
|
||||||
starts = {}
|
lua_line_to_pos = LINE_STARTS[tostring(lua)]
|
||||||
pos = 1
|
|
||||||
for line in s\gmatch("[^\n]*\n")
|
|
||||||
insert starts, pos
|
|
||||||
pos += #line
|
|
||||||
insert starts, pos
|
|
||||||
return starts
|
|
||||||
|
|
||||||
nomsu_line_to_pos = get_line_starts(nomsu_raw)
|
|
||||||
lua_line_to_pos = get_line_starts(tostring(lua))
|
|
||||||
|
|
||||||
pos_to_line = (line_starts, pos)->
|
pos_to_line = (line_starts, pos)->
|
||||||
-- Binary search for line number of position
|
-- Binary search for line number of position
|
||||||
@ -1036,11 +1018,8 @@ OPTIONS
|
|||||||
else debug_getinfo(thread,f,what)
|
else debug_getinfo(thread,f,what)
|
||||||
if not info or not info.func then return info
|
if not info or not info.func then return info
|
||||||
if info.short_src or info.source or info.linedefine or info.currentline
|
if info.short_src or info.source or info.linedefine or info.currentline
|
||||||
for k,v in pairs(nomsu.environment.ACTIONS)
|
if arg_orders = nomsu.environment.ARG_ORDERS[info.func]
|
||||||
if v == info.func
|
info.name = next(arg_orders)
|
||||||
info.name = k
|
|
||||||
break
|
|
||||||
|
|
||||||
if map = nomsu.source_map[info.source]
|
if map = nomsu.source_map[info.source]
|
||||||
if info.currentline
|
if info.currentline
|
||||||
info.currentline = assert(map[info.currentline])
|
info.currentline = assert(map[info.currentline])
|
||||||
@ -1051,7 +1030,7 @@ OPTIONS
|
|||||||
info.short_src = info.source\match('"([^[]*)')
|
info.short_src = info.source\match('"([^[]*)')
|
||||||
return info
|
return info
|
||||||
|
|
||||||
print_err_msg = (error_message, stack_offset=2)->
|
print_err_msg = (error_message, stack_offset=3)->
|
||||||
io.stderr\write("#{colored.red "ERROR:"} #{colored.bright colored.red (error_message or "")}\n")
|
io.stderr\write("#{colored.red "ERROR:"} #{colored.bright colored.red (error_message or "")}\n")
|
||||||
io.stderr\write("stack traceback:\n")
|
io.stderr\write("stack traceback:\n")
|
||||||
|
|
||||||
@ -1059,7 +1038,16 @@ OPTIONS
|
|||||||
ok, to_lua = pcall -> require('moonscript.base').to_lua
|
ok, to_lua = pcall -> require('moonscript.base').to_lua
|
||||||
if not ok then to_lua = -> nil
|
if not ok then to_lua = -> nil
|
||||||
nomsu_source = FILE_CACHE["nomsu.moon"]
|
nomsu_source = FILE_CACHE["nomsu.moon"]
|
||||||
_, line_table = to_lua(nomsu_source)
|
LINE_TABLES = setmetatable {},
|
||||||
|
__index: (file)=>
|
||||||
|
_, line_table = to_lua(file)
|
||||||
|
self[file] = line_table or false
|
||||||
|
return line_table or false
|
||||||
|
|
||||||
|
get_line = (file, line_no)->
|
||||||
|
start = LINE_STARTS[file][line_no] or 1
|
||||||
|
stop = (LINE_STARTS[file][line_no+1] or 0) - 1
|
||||||
|
return file\sub(start, stop)
|
||||||
|
|
||||||
level = stack_offset
|
level = stack_offset
|
||||||
while true
|
while true
|
||||||
@ -1069,38 +1057,62 @@ OPTIONS
|
|||||||
if calling_fn.func == run then break
|
if calling_fn.func == run then break
|
||||||
level += 1
|
level += 1
|
||||||
name = calling_fn.name
|
name = calling_fn.name
|
||||||
|
if calling_fn.linedefined == 0 then name = "main chunk"
|
||||||
if name == "run_lua_fn" then continue
|
if name == "run_lua_fn" then continue
|
||||||
line = nil
|
line = nil
|
||||||
[=[
|
if map = nomsu.source_map[calling_fn.source]
|
||||||
if metadata = nomsu.action_metadata[calling_fn.func]
|
if calling_fn.currentline
|
||||||
filename, start, stop = metadata.source\match("([^:]*):([0-9]*),([0-9]*)")
|
calling_fn.currentline = assert(map[calling_fn.currentline])
|
||||||
if filename
|
if calling_fn.linedefined
|
||||||
file = FILE_CACHE[filename]
|
calling_fn.linedefined = assert(map[calling_fn.linedefined])
|
||||||
line_no = 1
|
if calling_fn.lastlinedefined
|
||||||
for _ in file\sub(1,tonumber(start))\gmatch("\n") do line_no += 1
|
calling_fn.lastlinedefined = assert(map[calling_fn.lastlinedefined])
|
||||||
offending_statement = file\sub(tonumber(start),tonumber(stop))
|
calling_fn.short_src = calling_fn.source\match('"([^[]*)')
|
||||||
if #offending_statement > 50
|
filename,start,stop = calling_fn.source\match('"([^[]*)%[([0-9]+):([0-9]+)]"')
|
||||||
offending_statement = offending_statement\sub(1,50).."..."
|
assert(filename)
|
||||||
offending_statement = colored.red(offending_statement)
|
file = FILE_CACHE[filename]\sub(tonumber(start),tonumber(stop))
|
||||||
line = colored.yellow(filename..":"..tostring(line_no).."\n "..offending_statement)
|
err_line = get_line(file, calling_fn.currentline)\sub(1,-2)
|
||||||
|
offending_statement = colored.red(err_line)
|
||||||
|
line = colored.yellow("#{filename}:#{calling_fn.currentline}\n#{offending_statement}")
|
||||||
|
if arg_orders = nomsu.environment.ARG_ORDERS[calling_fn.func]
|
||||||
|
name = colored.bright(colored.yellow next(arg_orders))
|
||||||
else
|
else
|
||||||
line = colored.yellow(metadata.source)
|
name = colored.bright(colored.yellow "main chunk")
|
||||||
name = colored.bright(colored.yellow(metadata.aliases[1]))
|
|
||||||
else
|
else
|
||||||
if calling_fn.istailcall and not name
|
if calling_fn.istailcall and not name
|
||||||
name = "<tail call>"
|
name = "<tail call>"
|
||||||
if calling_fn.short_src == "./nomsu.moon" and line_table
|
ok, file = pcall ->FILE_CACHE[calling_fn.short_src]
|
||||||
char = line_table[calling_fn.currentline]
|
if not ok then file = nil
|
||||||
|
local line_num
|
||||||
|
if name == nil and debug.getinfo(level+1)
|
||||||
|
i = 1
|
||||||
|
while true
|
||||||
|
-- '+1' to get to one level higher than the callsite
|
||||||
|
varname, val = debug.getlocal(level+1, i)
|
||||||
|
if not varname then break
|
||||||
|
if val == calling_fn.func
|
||||||
|
name = varname
|
||||||
|
if not varname\match("%(")
|
||||||
|
break
|
||||||
|
i += 1
|
||||||
|
if file and calling_fn.short_src\match(".moon$") and LINE_TABLES[file]
|
||||||
|
char = LINE_TABLES[file][calling_fn.currentline]
|
||||||
line_num = 1
|
line_num = 1
|
||||||
for _ in nomsu_source\sub(1,char)\gmatch("\n") do line_num += 1
|
for _ in file\sub(1,char)\gmatch("\n") do line_num += 1
|
||||||
line = colored.cyan("#{calling_fn.short_src}:#{line_num}")
|
line = colored.cyan("#{calling_fn.short_src}:#{line_num}")
|
||||||
name = colored.bright(colored.cyan(name or "???"))
|
name = colored.bright(colored.cyan(name or "???"))
|
||||||
else
|
else
|
||||||
|
line_num = calling_fn.currentline
|
||||||
line = colored.blue("#{calling_fn.short_src}:#{calling_fn.currentline}")
|
line = colored.blue("#{calling_fn.short_src}:#{calling_fn.currentline}")
|
||||||
name = colored.bright(colored.blue(name or "???"))
|
name = colored.bright(colored.blue(name or "???"))
|
||||||
|
|
||||||
|
if file
|
||||||
|
err_line = get_line(file, line_num)\sub(1,-2)
|
||||||
|
offending_statement = colored.red(err_line)
|
||||||
|
line ..= "\n"..offending_statement
|
||||||
_from = colored.dim colored.white "|"
|
_from = colored.dim colored.white "|"
|
||||||
io.stderr\write(("%32s %s %s\n")\format(name, _from, line))
|
io.stderr\write(("%32s %s %s\n")\format(name, _from, line))
|
||||||
]=]
|
|
||||||
io.stderr\flush!
|
io.stderr\flush!
|
||||||
|
|
||||||
run = ->
|
run = ->
|
||||||
|
Loading…
Reference in New Issue
Block a user