summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/lace/builtin.lua6
-rw-r--r--lib/lace/compiler.lua2
-rw-r--r--lib/lace/engine.lua8
-rw-r--r--lib/lace/error.lua65
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,
+}