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
|
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)
|
local function get_variable (var_name, info)
|
||||||
--
|
-- Assertions
|
||||||
assert(type(var_name) == 'string')
|
assert(type(var_name) == 'string')
|
||||||
assert(type(info) == 'table')
|
assert(type(info) == 'table')
|
||||||
|
assert(type(info.func) == 'function')
|
||||||
|
assert(type(info.locals) == 'table')
|
||||||
|
|
||||||
-- Local
|
-- Local
|
||||||
if info.locals[var_name] then
|
if info.locals[var_name] then
|
||||||
|
@ -47,7 +70,7 @@ local function get_variable (var_name, info)
|
||||||
until not name
|
until not name
|
||||||
|
|
||||||
-- Global
|
-- Global
|
||||||
local env = getfenv(info.func)[var_name]
|
local env = safe_index(getfenv(info.func), var_name)
|
||||||
return env, 'global'
|
return env, 'global'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -251,25 +274,27 @@ local function for_each_node_in_ast (ast, func)
|
||||||
return func(ast)
|
return func(ast)
|
||||||
end
|
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_BINOP.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_BINOP.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_BINOP.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_BINOP.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_BINOP.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_BINOP.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_BINOP.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_BINOP.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_BINOP.CARET (node) return node[1].value ^ node[2].value end
|
||||||
function CONSTANT_OP.HASHTAG (node) return #node[1].value end
|
function CONSTANT_BINOP.EQ (node) return node[1].value == node[2].value end
|
||||||
function CONSTANT_OP.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_OP.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_OP.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_OP.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_OP.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_OP.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_OP.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)
|
local function populate_ast_with_semantics (ast, info)
|
||||||
assert(type(ast) == 'table')
|
assert(type(ast) == 'table')
|
||||||
|
@ -281,15 +306,21 @@ local function populate_ast_with_semantics (ast, info)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
--print 'Semantics!'
|
||||||
return for_each_node_in_ast(ast, function(node)
|
return for_each_node_in_ast(ast, function(node)
|
||||||
|
--print(require'pretty'(node))
|
||||||
if node.exp == 'IDENTIFIER' then
|
if node.exp == 'IDENTIFIER' then
|
||||||
node.value, node.scope, node.function_local = get_variable(node.text, info)
|
node.value, node.scope, node.function_local = get_variable(node.text, info)
|
||||||
elseif CONSTANT_VALUE_TOKEN[node.exp] then
|
elseif CONSTANT_VALUE_TOKEN[node.exp] then
|
||||||
node.value = CONSTANT_VALUE_TOKEN[node.exp](node.text)
|
node.value = CONSTANT_VALUE_TOKEN[node.exp](node.text)
|
||||||
node.is_constant = true
|
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))
|
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)
|
node.is_constant = node[1].is_constant and (not node[2] or node[2].is_constant)
|
||||||
end
|
end
|
||||||
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
|
return ('key %s in %s'):format(fmt_val(node[2].value), base), function_local
|
||||||
end
|
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!'
|
error 'Not implemented yet!'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -413,7 +451,8 @@ local function fmt_prefix (ast, call_info)
|
||||||
assert(type(ast) == 'table')
|
assert(type(ast) == 'table')
|
||||||
--
|
--
|
||||||
local name, is_function_local = fmt_lvalue(ast, true)
|
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)
|
return ('bad %s%s'):format(name, func_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -680,6 +719,7 @@ local function determine_error_message (call_info, msg, condition)
|
||||||
elseif not ast.exp then
|
elseif not ast.exp then
|
||||||
error(('[assert-gooder/internal]: Root node did not have expression type.'))
|
error(('[assert-gooder/internal]: Root node did not have expression type.'))
|
||||||
else
|
else
|
||||||
|
--print(require'pretty'(ast))
|
||||||
error(('[assert-gooder/internal]: Unknown expression type %s'):format(ast.exp))
|
error(('[assert-gooder/internal]: Unknown expression type %s'):format(ast.exp))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -53,7 +53,7 @@ return Lexer {
|
||||||
--
|
--
|
||||||
{ '%d+%.?%d*', 'NUMBER' },
|
{ '%d+%.?%d*', 'NUMBER' },
|
||||||
{ '%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' },
|
{ '\'.-\'', 'STRING' },
|
||||||
{ '%[%[.-%]%]', 'STRING' },
|
{ '%[%[.-%]%]', 'STRING' },
|
||||||
|
|
Loading…
Reference in New Issue
Block a user