The lost additions
This commit is contained in:
parent
9bfcd3beb3
commit
aec8db9c15
0
.gitignore
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
|
@ -27,10 +27,33 @@ local CONSTANT_VALUE_TOKEN = {
|
|||
NIL = function() return nil end
|
||||
}
|
||||
|
||||
local function table_indexing (t, k) return t[k] end
|
||||
|
||||
local function safe_index (t, index)
|
||||
assert(type(t) == 'table')
|
||||
|
||||
-- Attempt rawget first
|
||||
local value = rawget(t, index)
|
||||
if value ~= nil then return value end
|
||||
|
||||
local mt = debug.getmetatable(t)
|
||||
if mt.__index then
|
||||
-- If weird indexing, use pcall
|
||||
local success, value = pcall(table_indexing, t, index)
|
||||
if success then return value end
|
||||
return nil
|
||||
else
|
||||
-- Then attempt normal indexing, if no weirdness
|
||||
return t[index]
|
||||
end
|
||||
end
|
||||
|
||||
local function get_variable (var_name, info)
|
||||
--
|
||||
-- Assertions
|
||||
assert(type(var_name) == 'string')
|
||||
assert(type(info) == 'table')
|
||||
assert(type(info.func) == 'function')
|
||||
assert(type(info.locals) == 'table')
|
||||
|
||||
-- Local
|
||||
if info.locals[var_name] then
|
||||
|
@ -47,7 +70,7 @@ local function get_variable (var_name, info)
|
|||
until not name
|
||||
|
||||
-- Global
|
||||
local env = getfenv(info.func)[var_name]
|
||||
local env = safe_index(getfenv(info.func), var_name)
|
||||
return env, 'global'
|
||||
end
|
||||
|
||||
|
@ -251,25 +274,27 @@ local function for_each_node_in_ast (ast, func)
|
|||
return func(ast)
|
||||
end
|
||||
|
||||
local CONSTANT_OP = {}
|
||||
local CONSTANT_BINOP = {}
|
||||
local CONSTANT_UNOP = {}
|
||||
|
||||
function CONSTANT_OP.DOT (node) return node[1].value[ node[2].value ] end -- TODO
|
||||
function CONSTANT_OP.AND (node) return node[1].value and node[2].value end
|
||||
function CONSTANT_OP.OR (node) return node[1].value or node[2].value end
|
||||
function CONSTANT_OP.PLUS (node) return node[1].value + node[2].value end
|
||||
function CONSTANT_OP.MINUS (node) return node[1].value - node[2].value end
|
||||
function CONSTANT_OP.TIMES (node) return node[1].value * node[2].value end
|
||||
function CONSTANT_OP.DIVIDE (node) return node[1].value / node[2].value end
|
||||
function CONSTANT_OP.MODULO (node) return node[1].value % node[2].value end
|
||||
function CONSTANT_OP.CARET (node) return node[1].value ^ node[2].value end
|
||||
function CONSTANT_OP.HASHTAG (node) return #node[1].value end
|
||||
function CONSTANT_OP.EQ (node) return node[1].value == node[2].value end
|
||||
function CONSTANT_OP.NEQ (node) return node[1].value ~= node[2].value end
|
||||
function CONSTANT_OP.LEQ (node) return node[1].value <= node[2].value end
|
||||
function CONSTANT_OP.GEQ (node) return node[1].value >= node[2].value end
|
||||
function CONSTANT_OP.LE (node) return node[1].value < node[2].value end
|
||||
function CONSTANT_OP.GT (node) return node[1].value > node[2].value end
|
||||
function CONSTANT_OP.CONCAT (node) return node[1].value .. node[2].value end
|
||||
function CONSTANT_BINOP.DOT (node) return node[1].value[ node[2].value ] end -- TODO
|
||||
function CONSTANT_BINOP.AND (node) return node[1].value and node[2].value end
|
||||
function CONSTANT_BINOP.OR (node) return node[1].value or node[2].value end
|
||||
function CONSTANT_BINOP.PLUS (node) return node[1].value + node[2].value end
|
||||
function CONSTANT_BINOP.MINUS (node) return node[1].value - node[2].value end
|
||||
function CONSTANT_BINOP.TIMES (node) return node[1].value * node[2].value end
|
||||
function CONSTANT_BINOP.DIVIDE (node) return node[1].value / node[2].value end
|
||||
function CONSTANT_BINOP.MODULO (node) return node[1].value % node[2].value end
|
||||
function CONSTANT_BINOP.CARET (node) return node[1].value ^ node[2].value end
|
||||
function CONSTANT_BINOP.EQ (node) return node[1].value == node[2].value end
|
||||
function CONSTANT_BINOP.NEQ (node) return node[1].value ~= node[2].value end
|
||||
function CONSTANT_BINOP.LEQ (node) return node[1].value <= node[2].value end
|
||||
function CONSTANT_BINOP.GEQ (node) return node[1].value >= node[2].value end
|
||||
function CONSTANT_BINOP.LE (node) return node[1].value < node[2].value end
|
||||
function CONSTANT_BINOP.GT (node) return node[1].value > node[2].value end
|
||||
function CONSTANT_BINOP.CONCAT (node) return node[1].value .. node[2].value end
|
||||
|
||||
function CONSTANT_UNOP.HASHTAG (node) return #node[1].value end
|
||||
|
||||
local function populate_ast_with_semantics (ast, info)
|
||||
assert(type(ast) == 'table')
|
||||
|
@ -281,15 +306,21 @@ local function populate_ast_with_semantics (ast, info)
|
|||
end
|
||||
end)
|
||||
|
||||
--print 'Semantics!'
|
||||
return for_each_node_in_ast(ast, function(node)
|
||||
--print(require'pretty'(node))
|
||||
if node.exp == 'IDENTIFIER' then
|
||||
node.value, node.scope, node.function_local = get_variable(node.text, info)
|
||||
elseif CONSTANT_VALUE_TOKEN[node.exp] then
|
||||
node.value = CONSTANT_VALUE_TOKEN[node.exp](node.text)
|
||||
node.is_constant = true
|
||||
elseif node.exp == 'OP' and CONSTANT_OP[node.binop] and node[1].value and node[2] and node[2].value then
|
||||
elseif node.exp == 'OP' and CONSTANT_UNOP[node.binop] and node[1].value then
|
||||
assert(node[1].value)
|
||||
node.value = CONSTANT_UNOP[node.binop](node)
|
||||
node.is_constant = node[1].is_constant
|
||||
elseif node.exp == 'OP' and CONSTANT_BINOP[node.binop] and node[1].value and node[2] and node[2].value then
|
||||
assert(node[1].value and (not node[2] or node[2].value))
|
||||
node.value = CONSTANT_OP[node.binop](node)
|
||||
node.value = CONSTANT_BINOP[node.binop](node)
|
||||
node.is_constant = node[1].is_constant and (not node[2] or node[2].is_constant)
|
||||
end
|
||||
end)
|
||||
|
@ -406,6 +437,13 @@ local function fmt_lvalue (node, with_scope)
|
|||
return ('key %s in %s'):format(fmt_val(node[2].value), base), function_local
|
||||
end
|
||||
|
||||
--
|
||||
if node.exp == 'OP' and node.binop == 'HASHTAG' and #node == 1 then
|
||||
local base, is_local = fmt_lvalue(node[1], with_scope)
|
||||
return ('length of %s'):format(base), is_local
|
||||
end
|
||||
|
||||
--print(require'pretty'(node))
|
||||
error 'Not implemented yet!'
|
||||
end
|
||||
|
||||
|
@ -413,7 +451,8 @@ local function fmt_prefix (ast, call_info)
|
|||
assert(type(ast) == 'table')
|
||||
--
|
||||
local name, is_function_local = fmt_lvalue(ast, true)
|
||||
local func_name = is_function_local and (' to '..get_function_name(call_info)) or ''
|
||||
local binder = ast.node == 'argument' and 'to' or 'in'
|
||||
local func_name = is_function_local and (' '..binder..' '..get_function_name(call_info)) or ''
|
||||
return ('bad %s%s'):format(name, func_name)
|
||||
end
|
||||
|
||||
|
@ -680,6 +719,7 @@ local function determine_error_message (call_info, msg, condition)
|
|||
elseif not ast.exp then
|
||||
error(('[assert-gooder/internal]: Root node did not have expression type.'))
|
||||
else
|
||||
--print(require'pretty'(ast))
|
||||
error(('[assert-gooder/internal]: Unknown expression type %s'):format(ast.exp))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -53,7 +53,7 @@ return Lexer {
|
|||
--
|
||||
{ '%d+%.?%d*', 'NUMBER' },
|
||||
{ '%d*%.?%d+', 'NUMBER' },
|
||||
{ '[%a_][%d%a_]*', 'IDENTIFIER' },
|
||||
{ '[_a-zA-Z\128-\255][_a-zA-Z0-9\128-\255]*', 'IDENTIFIER' },
|
||||
{ '\".-\"', 'STRING' },
|
||||
{ '\'.-\'', 'STRING' },
|
||||
{ '%[%[.-%]%]', 'STRING' },
|
||||
|
|
Loading…
Reference in New Issue
Block a user