diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/lace/builtin.lua | 6 | ||||
-rw-r--r-- | lib/lace/compiler.lua | 2 | ||||
-rw-r--r-- | lib/lace/engine.lua | 8 | ||||
-rw-r--r-- | lib/lace/error.lua | 65 |
4 files changed, 66 insertions, 15 deletions
diff --git a/lib/lace/builtin.lua b/lib/lace/builtin.lua index 03fe7bc..e6c02f1 100644 --- a/lib/lace/builtin.lua +++ b/lib/lace/builtin.lua @@ -183,11 +183,7 @@ function builtin.define(compcontext, define, name, controltype, ...) local ctrltab, msg = controlfn(compcontext, controltype, ...) if type(ctrltab) ~= "table" then -- offset all the words in the error by 2 (for define and name) - if msg.words then - for i = 1, #msg.words do - msg.words[i] = msg.words[i] + 2 - end - end + msg = err.offset(msg, 2) return false, msg end diff --git a/lib/lace/compiler.lua b/lib/lace/compiler.lua index 4fd975b..1b0b21a 100644 --- a/lib/lace/compiler.lua +++ b/lib/lace/compiler.lua @@ -124,7 +124,7 @@ local function internal_compile_ruleset(compcontext, sourcename, content, suppre -- There's no unconditional result and no default, fake up a default and -- then use it. if not suppress_default and not uncond and not result then - return false, { msg = "No result set whatsoever", words = {} } + return err.error("No result set whatsoever") end if not suppress_default and not uncond then diff --git a/lib/lace/engine.lua b/lib/lace/engine.lua index dcf8a68..b4db68d 100644 --- a/lib/lace/engine.lua +++ b/lib/lace/engine.lua @@ -7,9 +7,7 @@ -- For licence terms, see COPYING -- -local function _error(str, words) - return { msg = str, words = words } -end +local err = require 'lace.error' local function _dlace(ctx) local ret = ctx._lace or {} @@ -21,7 +19,7 @@ local function set_define(exec_context, name, defn) local dlace = _dlace(exec_context) dlace.defs = dlace.defs or {} if dlace.defs[name] then - return false, _error("Attempted to redefine " .. name, {2}) + return err.error("Attempted to redefine " .. name, {2}) end dlace.defs[name] = defn return true @@ -32,7 +30,7 @@ local function test_define(exec_context, name) dlace.defs = dlace.defs or {} local defn = dlace.defs[name] if not defn then - return nil, _error("Unknown definition: " .. name) + return err.error("Unknown definition: " .. name, {2}, true) end -- Otherwise we evaluate the definition and return it return defn.fn(exec_context, unpack(defn.args)) diff --git a/lib/lace/error.lua b/lib/lace/error.lua index d52da1d..d71d21d 100644 --- a/lib/lace/error.lua +++ b/lib/lace/error.lua @@ -7,10 +7,67 @@ -- For licence terms, see COPYING -- -local function _error(str, words) - return false, { msg = str, words = words or {} } +local function _error(str, words, rnil) + local ret = false + if rnil then + ret = nil + end + return ret, { msg = str, words = words or {} } +end + +local function _offset(err, offs) + if not err.words then + err.words = {} + end + for k, w in ipairs(err.words) do + err.words[k] = w + offs + end + return err +end + +local function _augment(err, source, linenr) + err.source = source + err.linenr = linenr +end + +local function _render(err) + -- A rendered error has four lines + -- The first line is the error message + local ret = { err.msg } + -- The second is the source filename and line + ret[2] = err.source.source .. " :: " .. tostring(err.linenr) + -- The third line is the line of the input + local srcline = err.source.lines[err.linenr] or { + original = "???", content = { {spos = 1, epos = 3, str = "???"} } + } + ret[3] = srcline.original + -- The fourth line is the highlight for each word in question + local wordset = {} + for _, word in ipairs(err.words) do + wordset[word] = true + end + local hlstr = "" + local cpos = 1 + for w, info in ipairs(srcline.content) do + -- Ensure that we're up to the start position of the word + while (cpos < info.spos) do + hlstr = hlstr .. " " + cpos = cpos + 1 + end + -- Highlight this word if appropriate + while (cpos <= info.epos) do + hlstr = hlstr .. (wordset[w] and "^" or " ") + cpos = cpos + 1 + end + end + ret[4] = hlstr + -- The rendered error is those four strings joined by newlines + return table.concat(ret, "\n") end return { - error = _error -}
\ No newline at end of file + error = _error, + offset = _offset, + augment = _augment, + render = _render, +} |