mirror of
https://github.com/leafo/moonscript.git
synced 2024-11-22 02:44:23 +00:00
simple stack rewriting
This commit is contained in:
parent
f0b3690362
commit
56c3af06d2
68
moon
68
moon
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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!
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
|
||||||
@ -406,7 +417,6 @@ local build_grammar = wrap(function()
|
|||||||
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)
|
||||||
local line_str = get_line(line_no)
|
local line_str = get_line(line_no)
|
||||||
|
Loading…
Reference in New Issue
Block a user