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 "alt_getopt"
require "lpeg"
-- moonloader and repl -- moonloader and repl
local opts, ind = alt_getopt.get_opts(arg, "ch", { help = "h" }) 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, ";") return table.concat(paths, ";")
end end
local line_tables = {}
local function moon_chunk(file, file_path) local function moon_chunk(file, file_path)
-- print("loading", file_path)
local tree, err = parse.string(file:read"*a") local tree, err = parse.string(file:read"*a")
if not tree then error("Parse error: "..err) end 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() return load(function()
local out = code local out = code
@ -74,13 +78,64 @@ local function moon_loader(name)
return moon_chunk(file, file_path) return moon_chunk(file, file_path)
end end
if not package.moonpath then if not package.moonpath then
package.moonpath = create_moonpath(package.path) package.moonpath = create_moonpath(package.path)
end end
table.insert(package.loaders, 2, moon_loader) 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) local file, err = io.open(script)
if not file then error(err) end if not file then error(err) end
@ -92,4 +147,9 @@ local new_arg = {
local chunk = moon_chunk(file, script) local chunk = moon_chunk(file, script)
getfenv(chunk).arg = new_arg 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
end end
is_non_atomic = function(node) return non_atomic[ntype(node)] 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 import concat, insert from table
export indent_char, pretty, returner, moonlib, cascading, non_atomic, has_value, is_non_atomic export indent_char, pretty, returner, moonlib, cascading, non_atomic, has_value, is_non_atomic
export count_lines
indent_char = " " indent_char = " "
pretty = (lines, indent) -> pretty = (lines, indent) ->
@ -56,3 +57,9 @@ has_value = (node) ->
is_non_atomic = (node) -> is_non_atomic = (node) ->
non_atomic[ntype(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 local Block
Block = (function(_parent_0) Block = (function(_parent_0)
local _base_0 = { local _base_0 = {
line_table = function(self) return self._posmap end,
set = function(self, name, value) self._state[name] = value end, set = function(self, name, value) self._state[name] = value end,
get = function(self, name) return self._state[name] end, get = function(self, name) return self._state[name] end,
set_indent = function(self, depth) set_indent = function(self, depth)
@ -220,6 +221,7 @@ Block = (function(_parent_0)
end end
return name return name
end, end,
mark_pos = function(self, node) self._posmap[#self._lines + 1] = node[-1] end,
add_lines = function(self, lines) add_lines = function(self, lines)
local _item_0 = lines local _item_0 = lines
for _index_0=1,#_item_0 do for _index_0=1,#_item_0 do
@ -263,6 +265,7 @@ Block = (function(_parent_0)
if not fn then if not fn then
error("Failed to compile value: " .. dump.value(node)) error("Failed to compile value: " .. dump.value(node))
end end
self:mark_pos(node)
return fn(self, node, ...) return fn(self, node, ...)
end, end,
values = function(self, values, delim) values = function(self, values, delim)
@ -336,6 +339,7 @@ Block = (function(_parent_0)
self.parent = parent self.parent = parent
self:set_indent(self.parent and self.parent.indent + 1 or 0) self:set_indent(self.parent and self.parent.indent + 1 or 0)
self._lines = { } self._lines = { }
self._posmap = { }
self._names = { } self._names = { }
self._state = { } self._state = { }
if self.parent then if self.parent then
@ -360,5 +364,5 @@ tree = function(tree)
local line = _item_0[_index_0] local line = _item_0[_index_0]
scope:stm(line) scope:stm(line)
end end
return scope:render() return scope:render(), scope:line_table()
end end

View File

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

View File

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