simple stack rewriting

This commit is contained in:
leaf corcoran 2011-07-04 09:02:17 -07:00
parent f0b3690362
commit 56c3af06d2
7 changed files with 111 additions and 10 deletions

68
moon
View File

@ -8,6 +8,8 @@ require "moonscript.util"
require "alt_getopt"
require "lpeg"
-- moonloader and repl
local opts, ind = alt_getopt.get_opts(arg, "ch", { help = "h" })
@ -43,11 +45,13 @@ local function create_moonpath(package_path)
return table.concat(paths, ";")
end
local line_tables = {}
local function moon_chunk(file, file_path)
-- print("loading", file_path)
local tree, err = parse.string(file:read"*a")
if not tree then error("Parse error: "..err) end
local code = compile.tree(tree)
local code, ltable = compile.tree(tree)
line_tables[file_path] = ltable
return load(function()
local out = code
@ -74,13 +78,64 @@ local function moon_loader(name)
return moon_chunk(file, file_path)
end
if not package.moonpath then
package.moonpath = create_moonpath(package.path)
end
table.insert(package.loaders, 2, moon_loader)
local lookup_text = {}
local function lookup_line(fname, pos)
if not lookup_text[fname] then
local f = io.open(fname)
lookup_text[fname] = f:read"*a"
f:close()
end
local sub = lookup_text[fname]:sub(1, pos)
local count = 1
for _ in sub:gmatch("\n") do
count = count + 1
end
return count
end
local function reverse_line(fname, line_table, line)
for i = line,0,-1 do
if line_table[i] then
return lookup_line(fname, line_table[i])
end
end
return "unknown"
end
local function rewrite_traceback(text, err)
local header_text = "stack traceback:"
local Header, Line = lpeg.V"Header", lpeg.V"Line"
local Break = lpeg.S"\n"
local g = lpeg.P {
Header,
Header = header_text * Break * lpeg.Ct(Line^1),
Line = "\t" * lpeg.C((1 -Break)^0) * (Break + -1)
}
local match = g:match(text)
table.insert(match, 1, err)
for i, trace in pairs(match) do
local fname, line, msg = trace:match('^%[string "(.-)"]:(%d+): (.*)$')
if fname then
if line_tables[fname] then
local table = line_tables[fname]
match[i] = fname .. ":" ..
reverse_line(fname, table, line) .. ": " .. msg
end
end
end
return header_text .. "\n\t" .. table.concat(match, "\n\t")
end
local file, err = io.open(script)
if not file then error(err) end
@ -92,4 +147,9 @@ local new_arg = {
local chunk = moon_chunk(file, script)
getfenv(chunk).arg = new_arg
chunk(unpack(new_arg))
local runner = coroutine.create(chunk)
local success, err = coroutine.resume(runner, unpack(new_arg))
if not success then
print(rewrite_traceback(debug.traceback(runner), err))
end

View File

@ -68,3 +68,10 @@ has_value = function(node)
end
end
is_non_atomic = function(node) return non_atomic[ntype(node)] end
count_lines = function(str)
local count = 1
for _ in str:gmatch("\n") do
count = count + 1
end
return count
end

View File

@ -8,6 +8,7 @@ import Set, ntype from data
import concat, insert from table
export indent_char, pretty, returner, moonlib, cascading, non_atomic, has_value, is_non_atomic
export count_lines
indent_char = " "
pretty = (lines, indent) ->
@ -56,3 +57,9 @@ has_value = (node) ->
is_non_atomic = (node) ->
non_atomic[ntype(node)]
count_lines = (str) ->
count = 1
count += 1 for _ in str\gmatch "\n"
count

View File

@ -179,6 +179,7 @@ local value_compile = {
local Block
Block = (function(_parent_0)
local _base_0 = {
line_table = function(self) return self._posmap end,
set = function(self, name, value) self._state[name] = value end,
get = function(self, name) return self._state[name] end,
set_indent = function(self, depth)
@ -220,6 +221,7 @@ Block = (function(_parent_0)
end
return name
end,
mark_pos = function(self, node) self._posmap[#self._lines + 1] = node[-1] end,
add_lines = function(self, lines)
local _item_0 = lines
for _index_0=1,#_item_0 do
@ -263,6 +265,7 @@ Block = (function(_parent_0)
if not fn then
error("Failed to compile value: " .. dump.value(node))
end
self:mark_pos(node)
return fn(self, node, ...)
end,
values = function(self, values, delim)
@ -336,6 +339,7 @@ Block = (function(_parent_0)
self.parent = parent
self:set_indent(self.parent and self.parent.indent + 1 or 0)
self._lines = { }
self._posmap = { }
self._names = { }
self._state = { }
if self.parent then
@ -360,5 +364,5 @@ tree = function(tree)
local line = _item_0[_index_0]
scope:stm(line)
end
return scope:render()
return scope:render(), scope:line_table()
end

View File

@ -163,6 +163,7 @@ class Block
new: (@parent) =>
@set_indent @parent and @parent.indent + 1 or 0
@_lines = {}
@_posmap = {}
@_names = {}
@_state = {}
@ -170,6 +171,9 @@ class Block
setmetatable @_state, { __index: @parent._state }
setmetatable @_names, { __index: @parent._names }
line_table: =>
@_posmap
set: (name, value) =>
@_state[name] = value
@ -203,6 +207,9 @@ class Block
@put_name name if not dont_put
name
mark_pos: (node) =>
@_posmap[#@_lines + 1] = node[-1]
add_lines: (lines) =>
insert @_lines, line for line in *lines
nil
@ -244,6 +251,7 @@ class Block
return tostring node if type(node) != "table"
fn = value_compile[node[1]]
error "Failed to compile value: "..dump.value node if not fn
@mark_pos node
fn self, node, ...
values: (values, delim) =>
@ -303,5 +311,8 @@ build_compiler = ->
tree = (tree) ->
scope = Block!
scope\stm line for line in *tree
scope\render!
-- print util.dump scope._posmap
scope\render!, scope\line_table!

View File

@ -11,7 +11,9 @@ local function flat_value(op, depth)
table.insert(items, flat_value(item, depth+1))
end
return "{"..table.concat(items, ", ").."}"
local pos = op[-1]
return "{"..(pos and "["..pos.."] " or "")..table.concat(items, ", ").."}"
end
function value(op)

View File

@ -75,6 +75,17 @@ local function mark(name)
end
end
local function insert_pos(pos, value)
if type(value) == "table" then
value[-1] = pos
end
return value
end
local function pos(patt)
return (lpeg.Cp() * patt) / insert_pos
end
local function got(what)
return Cmt("", function(str, pos, ...)
local cap = {...}
@ -294,10 +305,10 @@ local build_grammar = wrap(function()
ChainValue =
((Chain + DotChain + Callable) * Ct(ExpList^0)) / flatten_func,
Value =
Value = pos(
SimpleValue +
Ct(KeyValueList) / mark"table" +
ChainValue,
ChainValue),
SliceValue = SimpleValue + ChainValue,
@ -405,7 +416,6 @@ local build_grammar = wrap(function()
print("stopped at", line_no)
error(err)
end
if not tree then
local line_no = pos_to_line(last_pos)