1
0
This commit is contained in:
Jon Michael Aanes 2017-11-07 11:06:39 +01:00
parent b1c6693f1f
commit dcee4f6f95
2 changed files with 154 additions and 143 deletions

View File

@ -39,6 +39,9 @@ local function get_value_token (token)
assert(false) assert(false)
end end
--------------------------------------------------------------------------------
-- Parsing
local function parse (tokens) local function parse (tokens)
-- TODO: Make a more general parser -- TODO: Make a more general parser
assert(type(tokens) == 'table') assert(type(tokens) == 'table')
@ -65,10 +68,16 @@ local function parse (tokens)
elseif #tokens == 1 then elseif #tokens == 1 then
return get_value_token(tokens[1]) return get_value_token(tokens[1])
else else
error 'Unknown AST structure!' io.stderr:write '[assert-gooder/internal]: Unknown AST structure!'
end end
end end
local function populate_ast_with_semantics (node, env)
end
--------------------------------------------------------------------------------
local function get_assert_body_text (call_info) local function get_assert_body_text (call_info)
if call_info.what == 'Lua' or call_info.what == 'main' then if call_info.what == 'Lua' or call_info.what == 'main' then
-- Find filetext -- Find filetext
@ -103,33 +112,27 @@ local function get_assert_body (call_info)
return lexer:lex(text), text return lexer:lex(text), text
end end
local function get_variable (var_name, info, level) local function get_variable (var_name, info)
-- --
assert(type(var_name) == 'string') assert(type(var_name) == 'string')
assert(type(info) == 'table') assert(type(info) == 'table')
assert(type(level) == 'number')
-- Local -- Local
local index, func = 0, info.func if info.locals[var_name] then
repeat local var_info = info.locals[var_name]
index = index + 1 return var_info[1], var_info[2] and ('argument #'..var_info[3]) or 'local', info.name or var_info[2] and ''
local name, val = debug.getlocal(level + 1, index)
if name == var_name then
local is_par = index <= info.nparams
return val, is_par and ('argument #'..index) or 'local', info.name or is_par and ''
end end
until not name
-- Up-value -- Up-value
local index = 0 local index = 0
repeat repeat
index = index + 1 index = index + 1
local name, val = debug.getupvalue(func, index) local name, val = debug.getupvalue(info.func, index)
if name == var_name then return val, 'upvalue' end if name == var_name then return val, 'upvalue' end
until not name until not name
-- Global -- Global
return getfenv(func)[var_name], 'global' return getfenv(info.func)[var_name], 'global'
end end
local function get_function_name (call_info) local function get_function_name (call_info)
@ -164,11 +167,10 @@ local function fmt_lvalue (lvalue, var_scope)
end end
end end
local function get_variable_and_prefix (lvalue, call_info, level) local function get_variable_and_prefix (lvalue, call_info)
assert(type(lvalue) == 'table' and lvalue.exp == 'LVALUE') assert(type(lvalue) == 'table' and lvalue.exp == 'LVALUE')
assert(type(level) == 'number')
-- --
local base_value, var_scope, in_func = get_variable(lvalue[1], call_info, level + 1) local base_value, var_scope, in_func = get_variable(lvalue[1], call_info)
-- Determine value of variable -- Determine value of variable
local value = base_value local value = base_value
for i = 2, #lvalue do value = value[lvalue[i].value] end for i = 2, #lvalue do value = value[lvalue[i].value] end
@ -200,12 +202,12 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function determine_error_message (call_info, msg, level, condition) local function determine_error_message (call_info, msg, condition)
local tokens, body_text = get_assert_body(call_info) local tokens, body_text = get_assert_body(call_info)
local ast = parse(tokens) local ast = parse(tokens)
msg[1] = ('expression `%s` evaluated to %s'):format(body_text, condition) msg[1] = ('expression `%s` evaluated to %s'):format(body_text, condition)
local var_prefix = function(token) return get_variable_and_prefix(token, call_info, level + 2) end local var_prefix = function(token) return get_variable_and_prefix(token, call_info) end
if not ast then return nil if not ast then return nil
elseif ast.exp == 'COMPARE' and ast.binop == 'EQ' and ast.left.exp == 'CALL' and ast.left.callee.exp == 'LVALUE' and ast.left.callee[1] == 'type' then elseif ast.exp == 'COMPARE' and ast.binop == 'EQ' and ast.left.exp == 'CALL' and ast.left.callee.exp == 'LVALUE' and ast.left.callee[1] == 'type' then
@ -238,10 +240,19 @@ end
return function (condition) return function (condition)
if condition then return condition end if condition then return condition end
--
local level = 2 local level = 2
local call_info = debug.getinfo(level) local call_info = debug.getinfo(level)
call_info.locals = {}
for i = 1, math.huge do
local name, value = debug.getlocal(level, i)
if not name then break end
print(value, i <= call_info.nparams)
call_info.locals[name] = { value, i <= call_info.nparams, i }
end
--
local msg_container = {''} local msg_container = {''}
local success, internal_error_msg = pcall(determine_error_message, call_info, msg_container, level, condition) local success, internal_error_msg = pcall(determine_error_message, call_info, msg_container, condition)
-- Handle internal errors -- Handle internal errors
if not success then if not success then
io.stderr:write(('[assert-gooder/internal]: Internal error occured while determining error message for calling assert:\n %s'):format(internal_error_msg)) io.stderr:write(('[assert-gooder/internal]: Internal error occured while determining error message for calling assert:\n %s'):format(internal_error_msg))

View File

@ -180,7 +180,7 @@ SUITE:addTest('function as type argument', function ()
assert(type(f) == 'string') assert(type(f) == 'string')
end) end)
-- TODO: How do we test this? -- TODO: How do we test this?
assert_equal('./test/test_assert-gooder.lua:'..curline(-2)..': '..'assertion failed! bad local \'f\' (expected string, but got function)', msg) assert_equal('./test/test_assert-gooder.lua:'..curline(-2)..': '..'assertion failed! bad local \'f\' (string expected, but got function)', msg)
end) end)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------