mirror of
https://github.com/leafo/moonscript.git
synced 2024-11-22 02:44:23 +00:00
moved error rewriting and moonloader into module
This commit is contained in:
parent
2d7e52a674
commit
d41d9c457c
134
moon
134
moon
@ -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
|
||||
|
@ -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
1
moonscript.lua
Normal file
@ -0,0 +1 @@
|
||||
require "moonscript.init"
|
65
moonscript/errors.lua
Normal file
65
moonscript/errors.lua
Normal 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
64
moonscript/errors.moon
Normal 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
70
moonscript/init.lua
Normal 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
62
moonscript/init.moon
Normal 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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user