summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2015-11-24 17:30:09 +0000
committerDaniel Silverstone <dsilvers@digital-scurf.org>2015-11-24 17:30:09 +0000
commita6a6ee4f86f354477e4b5d374dba4c4e90d03df6 (patch)
tree4afdaa2aa73ad8c2a666dacbec8c58a376ee4c67
parent5e6124ea7eb07797e2df2d8ea5aa07e951ed4168 (diff)
parent0cde41427841ad6f031175e9312f536837e40d35 (diff)
downloadlace-a6a6ee4f86f354477e4b5d374dba4c4e90d03df6.tar.gz
Merge branch 'subword-errors' of git://git.gitano.org.uk/personal/richardmaw/lacev1.2
-rw-r--r--lib/lace/builtin.lua17
-rw-r--r--lib/lace/error.lua67
-rw-r--r--lib/lace/lex.lua4
-rw-r--r--test/test-lace.engine.lua4
4 files changed, 73 insertions, 19 deletions
diff --git a/lib/lace/builtin.lua b/lib/lace/builtin.lua
index 147da6a..b0c7ad1 100644
--- a/lib/lace/builtin.lua
+++ b/lib/lace/builtin.lua
@@ -35,7 +35,12 @@ local function run_conditions(exec_context, cond, anyof)
end
local res, msg = engine.test(exec_context, name)
if res == nil then
- msg.words = {i}
+ local subwords = msg.words
+ if subwords and #subwords > 0 then
+ msg.words = {{nr = i, sub = subwords}}
+ else
+ msg.words = {i}
+ end
return nil, msg
end
if invert then
@@ -208,7 +213,15 @@ local function _compile_any_all_of(compcontext, mtype, first, second, ...)
end
return {
- fn = run_conditions,
+ fn = (function(exec_context, cond, anyof)
+ local pass, msg = run_conditions(exec_context, cond, anyof)
+ if pass == nil then
+ -- Offset error location by anyof/allof word
+ err.offset(msg, 1)
+ return nil, msg
+ end
+ return pass, msg
+ end),
args = { { first, second, ...}, mtype == "anyof" }
}
end
diff --git a/lib/lace/error.lua b/lib/lace/error.lua
index 96998bd..6277233 100644
--- a/lib/lace/error.lua
+++ b/lib/lace/error.lua
@@ -49,7 +49,12 @@ local function _offset(err, offs)
err.words = {}
end
for k, w in ipairs(err.words) do
- err.words[k] = w + offs
+ if type(w) == "table" then
+ nr = w.nr
+ err.words[k] = {nr = nr + offs, sub=w.sub}
+ else
+ err.words[k] = w + offs
+ end
end
return err
end
@@ -96,23 +101,55 @@ local function _render(err)
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
+ local function build_wordset(words, wordset)
+ for _, word in ipairs(words) do
+ if type(word) ~= "table" then
+ wordset[word] = true
+ else
+ local subwordset = {}
+ build_wordset(word.sub, subwordset)
+ wordset[word.nr] = subwordset
+ end
end
- -- Highlight this word if appropriate
- while (cpos <= info.epos) do
- hlstr = hlstr .. (wordset[w] and "^" or " ")
- cpos = cpos + 1
+ end
+ build_wordset(err.words, wordset)
+
+ local function mark_my_words(line, wordset)
+ local hlstr, cpos = "", 1
+ for w, info in ipairs(line) do
+ -- Ensure that we're up to the start position of the word
+ while (cpos < info.spos) do
+ hlstr = hlstr .. " "
+ cpos = cpos + 1
+ end
+ -- TODO: The subword can be defined in a different line entirely,
+ -- at which point it's not a subword of word in this line.
+ -- This is the norm for explicit definitions.
+ -- Eventually we should trace back to the define's
+ -- definition and highlight where in that line the problem is.
+ if type(wordset[w]) == "table" and info.sub then
+ -- space for [
+ hlstr, cpos = hlstr .. " ", cpos + 1
+
+ -- mark subword
+ local subhlstr, subcpos = mark_my_words(info.sub, wordset[w])
+ hlstr = hlstr .. subhlstr
+ cpos = cpos + subcpos
+
+ -- space for ]
+ hlstr, cpos = hlstr .. " ", cpos + 1
+ else
+ -- Highlight this word if appropriate
+ while (cpos <= info.epos) do
+ hlstr = hlstr .. (wordset[w] and "^" or " ")
+ cpos = cpos + 1
+ end
+ end
end
+ return hlstr, cpos
end
+ local hlstr, _ = mark_my_words(srcline.content, wordset)
+
ret[4] = hlstr
-- The rendered error is those four strings joined by newlines
return table.concat(ret, "\n")
diff --git a/lib/lace/lex.lua b/lib/lace/lex.lua
index d7d18da..3bd9ec2 100644
--- a/lib/lace/lex.lua
+++ b/lib/lace/lex.lua
@@ -46,6 +46,10 @@ local function _lex_one_line(line, terminator)
else
if c == terminator and quoting == false then
-- Reached the terminator, break out
+ -- The terminator is not actually part of the last word in the line
+ -- so we push back that character,
+ -- since it's the only case we actually need to put any back.
+ cpos = cpos - 1
break
elseif c == "'" and quoting == false then
-- Start single quotes
diff --git a/test/test-lace.engine.lua b/test/test-lace.engine.lua
index c5f7751..936a2ed 100644
--- a/test/test-lace.engine.lua
+++ b/test/test-lace.engine.lua
@@ -263,7 +263,7 @@ function suite.subdefine_err_reported()
assert(line1 == "woah", "The first line must mention the error")
assert(line2 == "real-subdefine-error :: 2", "The second line is where the error happened")
assert(line3 == 'allow "Yay" [error]', "The third line is the original line")
- assert(line4 == " ^^^^^^^", "The fourth line highlights relevant words")
+ assert(line4 == " ^^^^^ ", "The fourth line highlights relevant words")
end
function suite.subsubdefine_works()
@@ -286,7 +286,7 @@ function suite.subsubdefine_err_reported()
assert(line1 == "woah", "The first line must mention the error")
assert(line2 == "real-subsubdefine-error :: 1", "The second line is where the error happened")
assert(line3 == 'allow "FAIL" [anyof [equal jeff banana] [error]]', "The third line is the original line")
- assert(line4 == " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", "The fourth line highlights relevant words")
+ assert(line4 == " ^^^^^ ", "The fourth line highlights relevant words")
end
local count_ok = 0