moved error rewriting and moonloader into module

This commit is contained in:
leaf corcoran 2011-07-18 23:17:45 -07:00
parent 2d7e52a674
commit d41d9c457c
8 changed files with 272 additions and 128 deletions

134
moon
View File

@ -1,14 +1,9 @@
#!/usr/bin/lua
module("moonscript", package.seeall)
require "moonscript.parse"
require "moonscript.compile"
require "moonscript.util"
require "alt_getopt"
require "moonscript.errors"
require "moonscript"
require "lpeg"
-- moonloader and repl
local opts, ind = alt_getopt.get_opts(arg, "chd", { help = "h" })
@ -28,128 +23,13 @@ end
if opts.h then print_help() end
local script = arg[ind]
if not script then
local script_fname = arg[ind]
if not script_fname then
print_help("repl not yet supported")
return
end
local dirsep = "/"
local function create_moonpath(package_path)
local paths = util.split(package_path, ";")
for i=1,#paths do
local p = paths[i]:match("^(.-)%.lua$")
if p then
paths[i] = p..".moon"
end
end
return table.concat(paths, ";")
end
local line_tables = {}
local function moon_chunk(file, file_path)
local text = file:read"*a"
local tree, err = parse.string(text)
if not tree then error("Parse error: "..err) end
local code, ltable, pos = compile.tree(tree)
if not code then
error(compile.format_error(ltable, pos, text))
end
line_tables[file_path] = ltable
return load(function()
local out = code
code = nil
return out
end, file_path)
end
local function moon_loader(name)
name_path = name:gsub("%.", dirsep)
paths = util.split(package.moonpath, ";")
local file, file_path
for i=1,#paths do
file_path = paths[i]:gsub("?", name_path)
file = io.open(file_path)
if file then break end
end
if not file then
return nil, "Could not find moon file"
end
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 function rewrite_single(trace)
local fname, line, msg = trace:match('^%[string "(.-)"]:(%d+): (.*)$')
if fname then
if line_tables[fname] then
local table = line_tables[fname]
return fname .. ":" .. reverse_line(fname, table, line) .. ": " .. msg
end
end
end
err = rewrite_single(err)
local match = g:match(text)
for i, trace in pairs(match) do
match[i] = rewrite_single(trace)
end
return table.concat({
"moon: "..err,
header_text,
"\t" .. table.concat(match, "\n\t")
}, "\n")
end
local file, err = io.open(script)
local file, err = io.open(script_fname)
if not file then error(err) end
local new_arg = {
@ -158,7 +38,7 @@ local new_arg = {
select(ind + 1, unpack(arg))
}
local chunk = moon_chunk(file, script)
local chunk = moonscript.moon_chunk(file, script_fname)
getfenv(chunk).arg = new_arg
local runner = coroutine.create(chunk)
@ -166,7 +46,7 @@ local success, err = coroutine.resume(runner, unpack(new_arg))
if not success then
local trace = debug.traceback(runner)
if not opts.d then
print(rewrite_traceback(trace, err))
print(moonscript.errors.rewrite_traceback(trace, err))
else
print(trace)
end

View File

@ -30,6 +30,8 @@ build = {
["moonscript.dump"] = "moonscript/dump.lua",
["moonscript.data"] = "moonscript/data.lua",
["moonscript.util"] = "moonscript/util.lua",
["moonscript.init"] = "moonscript/init.lua",
["moonscript.errors"] = "moonscript/errors.lua",
},
install = {
bin = { "moon", "moonc" }

1
moonscript.lua Normal file
View File

@ -0,0 +1 @@
require "moonscript.init"

65
moonscript/errors.lua Normal file
View File

@ -0,0 +1,65 @@
module("moonscript.errors", package.seeall)
local moon = require("moonscript")
local util = require("moonscript.util")
require("lpeg")
local concat, insert = table.concat, table.insert
local split, pos_to_line = util.split, util.pos_to_line
local lookup_line
lookup_line = function(fname, pos, cache)
if not cache[fname] then
do
local _with_0 = io.open(fname)
cache[fname] = _with_0:read("*a")
_with_0:close()
end
end
return pos_to_line(cache[fname], pos)
end
local reverse_line_number
reverse_line_number = function(fname, line_table, line_num, cache)
for i = line_num, 0, -1 do
if line_table[i] then
return lookup_line(fname, line_table[i], cache)
end
end
return "unknown"
end
rewrite_traceback = function(text, err)
local line_tables = moon.line_tables
local V, S, Ct, C = lpeg.V, lpeg.S, lpeg.Ct, lpeg.C
local header_text = "stack traceback:"
local Header, Line = V("Header"), V("Line")
local Break = lpeg.S("\n")
local g = lpeg.P({
Header,
Header = header_text * Break * Ct(Line ^ 1),
Line = "\t" * C((1 - Break) ^ 0) * (Break + -1)
})
local cache = { }
local rewrite_single
rewrite_single = function(trace)
local fname, line, msg = trace:match('^%[string "(.-)"]:(%d+): (.*)$')
local tbl = line_tables[fname]
if fname and tbl then
return concat({
fname,
":",
reverse_line_number(fname, tbl, line, cache),
": ",
msg
})
else
return trace
end
end
err = rewrite_single(err)
local match = g:match(text)
for i, trace in ipairs(match) do
match[i] = rewrite_single(trace)
end
return concat({
"moon:" .. err,
header_text,
"\t" .. concat(match, "\n\t")
}, "\n")
end

64
moonscript/errors.moon Normal file
View File

@ -0,0 +1,64 @@
module "moonscript.errors", package.seeall
moon = require "moonscript"
util = require "moonscript.util"
require "lpeg"
import concat, insert from table
import split, pos_to_line from util
export rewrite_traceback
-- find the line number of `pos` chars into fname
lookup_line = (fname, pos, cache) ->
if not cache[fname]
with io.open fname
cache[fname] = \read "*a"
\close!
pos_to_line cache[fname], pos
-- reverse the line number in fname using line_table
reverse_line_number = (fname, line_table, line_num, cache) ->
for i = line_num,0,-1
if line_table[i]
return lookup_line fname, line_table[i], cache
"unknown"
rewrite_traceback = (text, err) ->
line_tables = moon.line_tables
import V, S, Ct, C from lpeg
header_text = "stack traceback:"
Header, Line = V("Header"), V("Line")
Break = lpeg.S "\n"
g = lpeg.P {
Header
Header: header_text * Break * Ct(Line^1)
Line: "\t" * C((1 - Break)^0) * (Break + -1)
}
cache = {} -- loaded file cache
rewrite_single = (trace) ->
fname, line, msg = trace\match '^%[string "(.-)"]:(%d+): (.*)$'
tbl = line_tables[fname]
if fname and tbl
concat {
fname, ":"
reverse_line_number(fname, tbl, line, cache)
": ", msg
}
else
trace
err = rewrite_single err
match = g\match text
for i, trace in ipairs match
match[i] = rewrite_single trace
concat {
"moon:" .. err
header_text
"\t" .. concat match, "\n\t"
}, "\n"

70
moonscript/init.lua Normal file
View File

@ -0,0 +1,70 @@
module("moonscript", package.seeall)
require("moonscript.parse")
require("moonscript.compile")
require("moonscript.util")
local concat, insert = table.concat, table.insert
local split, dump = util.split, util.dump
dirsep = "/"
line_tables = { }
local create_moonpath
create_moonpath = function(package_path)
local paths = split(package_path, ";")
for i, path in ipairs(paths) do
local p = path:match("^(.-)%.lua$")
if p then
paths[i] = p .. ".moon"
end
end
return concat(paths, ";")
end
moon_chunk = function(file, file_path)
local text = file:read("*a")
local tree, err = parse.string(text)
if not tree then
error("Parse error: " .. err)
end
local code, ltable, pos = compile.tree(tree)
if not code then
error(compile.format_error(ltable, pos, text))
end
line_tables[file_path] = ltable
local runner
runner = function()
do
local _with_0 = code
code = nil
return _with_0
end
end
return load(runner, file_path)
end
moon_loader = function(name)
local name_path = name:gsub("%.", dirsep)
local file, file_path = nil, nil
do
local _item_0 = split(package.moonpath, ";")
for _index_0 = 1, #_item_0 do
local path = _item_0[_index_0]
file_path = path:gsub("?", name_path)
file = io.open(file_path)
if file then
break
end
end
end
if file then
return moon_chunk(file, file_path)
else
return nil, "Could not find moon file"
end
end
if not package.moonpath then
package.moonpath = create_moonpath(package.path)
end
local init_loader
init_loader = function()
return insert(package.loaders, 2, moon_loader)
end
if not _G.moon_no_loader then
init_loader()
end

62
moonscript/init.moon Normal file
View File

@ -0,0 +1,62 @@
module "moonscript", package.seeall
require "moonscript.parse"
require "moonscript.compile"
require "moonscript.util"
import concat, insert from table
import split, dump from util
export moon_chunk, moon_loader, dirsep, line_tables
dirsep = "/"
line_tables = {}
-- create moon path package from lua package path
create_moonpath = (package_path) ->
paths = split package_path, ";"
for i, path in ipairs paths
p = path\match "^(.-)%.lua$"
if p then paths[i] = p..".moon"
concat paths, ";"
-- load the chunk function from a file objec:
moon_chunk = (file, file_path) ->
text = file\read "*a"
tree, err = parse.string text
if not tree
error "Parse error: " .. err
code, ltable, pos = compile.tree tree
if not code
error compile.format_error ltable, pos, text
line_tables[file_path] = ltable
runner = -> with code do code = nil
load runner, file_path
moon_loader = (name) ->
name_path = name\gsub "%.", dirsep
file, file_path = nil, nil
for path in *split package.moonpath, ";"
file_path = path\gsub "?", name_path
file = io.open file_path
break if file
if file
moon_chunk file, file_path
else
nil, "Could not find moon file"
if not package.moonpath
package.moonpath = create_moonpath package.path
init_loader = ->
insert package.loaders, 2, moon_loader
init_loader! if not _G.moon_no_loader

View File

@ -42,7 +42,7 @@ local Name = Space * _Name
local Num = Space * C(R("09")^1) / tonumber
local FactorOp = Space * C(S"+-")
local TermOp = Space * C(S"*/%")
local TermOp = Space * C(S"*/%^")
local function wrap(fn)
local env = getfenv(fi)