mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-28 00:59:31 +00:00
Improve alias system
This commit is contained in:
parent
b0d7a0bfb5
commit
51e8c82181
6 changed files with 165 additions and 40 deletions
|
|
@ -3,6 +3,21 @@ local expression
|
|||
local escapeCache = {}
|
||||
|
||||
local common
|
||||
|
||||
--- rewrite name to use defined aliases (under namespace only)
|
||||
-- namespace should not contain aliases
|
||||
local replace_aliases = function(aliases, namespace, name)
|
||||
namespace = namespace == "" and "" or namespace.."."
|
||||
local name_list = common.split(name)
|
||||
for i=1, #name_list, 1 do
|
||||
local n = ("%s%s"):format(namespace, table.concat(name_list, ".", 1, i))
|
||||
if aliases[n] then
|
||||
name_list[i] = aliases[n]:match("[^%.]+$")
|
||||
end
|
||||
end
|
||||
return table.concat(name_list, ".")
|
||||
end
|
||||
|
||||
common = {
|
||||
--- valid identifier pattern
|
||||
identifier_pattern = "[^%%%/%*%+%-%(%)%!%&%|%=%$%§%?%>%<%:%{%}%[%]%,%\"]+",
|
||||
|
|
@ -26,24 +41,27 @@ common = {
|
|||
return address
|
||||
end,
|
||||
--- find a variable/function in a list, going up through the namespace hierarchy
|
||||
find = function(list, namespace, name)
|
||||
-- will apply aliases
|
||||
find = function(aliases, list, namespace, name)
|
||||
local ns = common.split(namespace)
|
||||
for i=#ns, 1, -1 do
|
||||
local fqm = ("%s.%s"):format(table.concat(ns, ".", 1, i), name)
|
||||
local current_namespace = table.concat(ns, ".", 1, i)
|
||||
local fqm = ("%s.%s"):format(current_namespace, replace_aliases(aliases, current_namespace, name))
|
||||
if list[fqm] then
|
||||
return list[fqm], fqm
|
||||
end
|
||||
end
|
||||
-- root namespace
|
||||
name = replace_aliases(aliases, "", name)
|
||||
if list[name] then
|
||||
return list[name], name
|
||||
end
|
||||
return nil, ("can't find %q in namespace %s"):format(name, namespace)
|
||||
end,
|
||||
--- transform an identifier into a clean version (trim & alias)
|
||||
--- transform an identifier into a clean version (trim each part)
|
||||
format_identifier = function(identifier, state)
|
||||
local r = identifier:gsub("[^%.]+", function(str)
|
||||
str = common.trim(str)
|
||||
return state.aliases[str] or str
|
||||
return common.trim(str)
|
||||
end)
|
||||
return r
|
||||
end,
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ local function expression(s, state, namespace, currentPriority, operatingOn)
|
|||
local name, r = s:match("^("..identifier_pattern..")(.-)$")
|
||||
name = format_identifier(name, state)
|
||||
-- variables
|
||||
local var, vfqm = find(state.variables, namespace, name)
|
||||
local var, vfqm = find(state.aliases, state.variables, namespace, name)
|
||||
if var then
|
||||
return expression(r, state, namespace, currentPriority, {
|
||||
type = "variable",
|
||||
|
|
@ -103,7 +103,7 @@ local function expression(s, state, namespace, currentPriority, operatingOn)
|
|||
-- suffix call: detect if prefix is valid variable, suffix call is handled in the binop section below
|
||||
local sname, suffix = name:match("^(.*)(%."..identifier_pattern..")$")
|
||||
if sname then
|
||||
local svar, svfqm = find(state.variables, namespace, sname)
|
||||
local svar, svfqm = find(state.aliases, state.variables, namespace, sname)
|
||||
if svar then
|
||||
return expression(suffix..r, state, namespace, currentPriority, {
|
||||
type = "variable",
|
||||
|
|
@ -113,7 +113,7 @@ local function expression(s, state, namespace, currentPriority, operatingOn)
|
|||
end
|
||||
end
|
||||
-- functions
|
||||
local funcs, ffqm = find(state.functions, namespace, name)
|
||||
local funcs, ffqm = find(state.aliases, state.functions, namespace, name)
|
||||
if funcs then
|
||||
local args, explicit_call
|
||||
if r:match("^%b()") then
|
||||
|
|
@ -162,7 +162,7 @@ local function expression(s, state, namespace, currentPriority, operatingOn)
|
|||
if op == "." and sright:match("^"..identifier_pattern) then
|
||||
local name, r = sright:match("^("..identifier_pattern..")(.-)$")
|
||||
name = format_identifier(name, state)
|
||||
local funcs, ffqm = find(state.functions, namespace, name)
|
||||
local funcs, ffqm = find(state.aliases, state.functions, namespace, name)
|
||||
if funcs then
|
||||
local args, explicit_call
|
||||
if r:match("^%b()") then
|
||||
|
|
|
|||
|
|
@ -29,9 +29,25 @@ local function parse_line(line, state, namespace)
|
|||
l, name = l:match("^(.-)%s*§(.-)$")
|
||||
local identifier, rem = name:match("^("..identifier_pattern..")(.-)$")
|
||||
if not identifier then return nil, ("no valid identifier in paragraph decorator %q; at %s"):format(identifier, line.source) end
|
||||
if rem:match("[^%s]") then return nil, ("expected end-of-line after identifier in paragraph decorator, but got %q; at %s"):format(rem, line.source) end
|
||||
-- format identifier
|
||||
local fqm = ("%s%s"):format(namespace, format_identifier(identifier, state))
|
||||
-- get alias
|
||||
if rem:match("^%:") then
|
||||
local content = rem:sub(2)
|
||||
local alias, rem2 = content:match("^("..identifier_pattern..")(.-)$")
|
||||
if not alias then return nil, ("expected an identifier in alias in paragraph decorator, but got %q; at %s"):format(content, line.source) end
|
||||
if rem2:match("[^%s]") then return nil, ("expected end-of-line after identifier in alias in paragraph decorator, but got %q; at %s"):format(rem2, line.source) end
|
||||
-- format alias
|
||||
local aliasfqm = ("%s%s"):format(namespace, format_identifier(alias, state))
|
||||
-- define alias
|
||||
if state.aliases[aliasfqm] ~= nil and state.aliases[aliasfqm] ~= fqm then
|
||||
return nil, ("trying to define alias %q for variable %q, but already exist and refer to different variable %q; at %s"):format(aliasfqm, fqm, state.aliases[aliasfqm], line.source)
|
||||
end
|
||||
state.aliases[aliasfqm] = fqm
|
||||
elseif rem:match("[^%s]") then
|
||||
return nil, ("expected end-of-line after identifier in paragraph decorator, but got %q; at %s"):format(rem, line.source)
|
||||
end
|
||||
-- define paragraph
|
||||
namespace = fqm.."."
|
||||
r.paragraph = true
|
||||
r.parent_function = true
|
||||
|
|
@ -50,6 +66,15 @@ local function parse_line(line, state, namespace)
|
|||
value = 0
|
||||
}
|
||||
end
|
||||
-- define alias for 👁️
|
||||
local seen_alias = state.builtin_aliases["👁️"]
|
||||
if seen_alias then
|
||||
local alias = ("%s.%s"):format(fqm, seen_alias)
|
||||
if state.aliases[alias] ~= nil and state.aliases[alias] then
|
||||
return nil, ("trying to define alias %q for variable %q, but already exist and refer to different variable %q; at %s"):format(alias, fqm..".👁️", state.aliases[alias], line.source)
|
||||
end
|
||||
state.aliases[alias] = fqm..".👁️"
|
||||
end
|
||||
else
|
||||
table.insert(state.functions[fqm], {
|
||||
arity = 0,
|
||||
|
|
@ -89,6 +114,20 @@ local function parse_line(line, state, namespace)
|
|||
if not identifier then return nil, ("no valid identifier in paragraph/function definition line %q; at %s"):format(lc, line.source) end
|
||||
-- format identifier
|
||||
local fqm = ("%s%s"):format(namespace, format_identifier(identifier, state))
|
||||
-- get alias
|
||||
if rem:match("^%:") then
|
||||
local content = rem:sub(2)
|
||||
local alias
|
||||
alias, rem = content:match("^("..identifier_pattern..")(.-)$")
|
||||
if not alias then return nil, ("expected an identifier in alias in paragraph/function definition line, but got %q; at %s"):format(content, line.source) end
|
||||
-- format alias
|
||||
local aliasfqm = ("%s%s"):format(namespace, format_identifier(alias, state))
|
||||
-- define alias
|
||||
if state.aliases[aliasfqm] ~= nil and state.aliases[aliasfqm] ~= fqm then
|
||||
return nil, ("trying to define alias %q for function/paragraph %q, but already exist and refer to %q; at %s"):format(aliasfqm, fqm, state.aliases[aliasfqm], line.source)
|
||||
end
|
||||
state.aliases[aliasfqm] = fqm
|
||||
end
|
||||
-- get params
|
||||
r.params = {}
|
||||
if r.type == "function" and rem:match("^%b()$") then
|
||||
|
|
@ -113,12 +152,6 @@ local function parse_line(line, state, namespace)
|
|||
-- don't keep function node in block AST
|
||||
if r.type == "function" then
|
||||
r.remove_from_block_ast = true
|
||||
if not state.variables[fqm..".🏁"] then
|
||||
state.variables[fqm..".🏁"] = {
|
||||
type = "string",
|
||||
value = ""
|
||||
}
|
||||
end
|
||||
end
|
||||
-- define function and variables
|
||||
r.namespace = fqm.."."
|
||||
|
|
@ -130,14 +163,44 @@ local function parse_line(line, state, namespace)
|
|||
vararg = vararg,
|
||||
value = r
|
||||
}
|
||||
-- new function (no overloading yet)
|
||||
if not state.functions[fqm] then
|
||||
state.functions[fqm] = { r.variant }
|
||||
-- define 👁️ variable
|
||||
if not state.variables[fqm..".👁️"] then
|
||||
state.variables[fqm..".👁️"] = {
|
||||
type = "number",
|
||||
value = 0
|
||||
}
|
||||
end
|
||||
-- define alias for 👁️
|
||||
local seen_alias = state.builtin_aliases["👁️"]
|
||||
if seen_alias then
|
||||
local alias = ("%s.%s"):format(fqm, seen_alias)
|
||||
if state.aliases[alias] ~= nil and state.aliases[alias] then
|
||||
return nil, ("trying to define alias %q for variable %q, but already exist and refer to different variable %q; at %s"):format(alias, fqm..".👁️", state.aliases[alias], line.source)
|
||||
end
|
||||
state.aliases[alias] = fqm..".👁️"
|
||||
end
|
||||
if r.type == "function" then
|
||||
-- define 🏁 variable
|
||||
if not state.variables[fqm..".🏁"] then
|
||||
state.variables[fqm..".🏁"] = {
|
||||
type = "string",
|
||||
value = ""
|
||||
}
|
||||
end
|
||||
-- define alias for 🏁
|
||||
local checkpoint_alias = state.builtin_aliases["🏁"]
|
||||
if checkpoint_alias then
|
||||
local alias = ("%s.%s"):format(fqm, checkpoint_alias)
|
||||
if state.aliases[alias] ~= nil and state.aliases[alias] then
|
||||
return nil, ("trying to define alias %q for variable %q, but already exist and refer to different variable %q; at %s"):format(alias, fqm..".🏁", state.aliases[alias], line.source)
|
||||
end
|
||||
state.aliases[alias] = fqm..".🏁"
|
||||
end
|
||||
end
|
||||
-- overloading
|
||||
else
|
||||
-- check for arity conflict
|
||||
for _, variant in ipairs(state.functions[fqm]) do
|
||||
|
|
@ -181,9 +244,25 @@ local function parse_line(line, state, namespace)
|
|||
-- get identifier
|
||||
local identifier, rem2 = rem:match("^("..identifier_pattern..")(.-)$")
|
||||
if not identifier then return nil, ("no valid identifier after expression in definition line %q; at %s"):format(rem, line.source) end
|
||||
if rem2:match("[^%s]") then return nil, ("expected end-of-line after identifier in definition line, but got %q; at %s"):format(rem2, line.source) end
|
||||
-- format identifier & define
|
||||
-- format identifier
|
||||
local fqm = ("%s%s"):format(namespace, format_identifier(identifier, state))
|
||||
-- get alias
|
||||
if rem2:match("^%:") then
|
||||
local content = rem2:sub(2)
|
||||
local alias, rem3 = content:match("^("..identifier_pattern..")(.-)$")
|
||||
if not alias then return nil, ("expected an identifier in alias in definition line, but got %q; at %s"):format(content, line.source) end
|
||||
if rem3:match("[^%s]") then return nil, ("expected end-of-line after identifier in alias in definition line, but got %q; at %s"):format(rem3, line.source) end
|
||||
-- format alias
|
||||
local aliasfqm = ("%s%s"):format(namespace, format_identifier(alias, state))
|
||||
-- define alias
|
||||
if state.aliases[aliasfqm] ~= nil and state.aliases[aliasfqm] ~= fqm then
|
||||
return nil, ("trying to define alias %s for variable %s, but already exist and refer to different variable %s; at %s"):format(aliasfqm, fqm, state.aliases[aliasfqm], line.source)
|
||||
end
|
||||
state.aliases[aliasfqm] = fqm
|
||||
elseif rem2:match("[^%s]") then
|
||||
return nil, ("expected end-of-line after identifier in definition line, but got %q; at %s"):format(rem2, line.source)
|
||||
end
|
||||
-- define identifier
|
||||
if state.functions[fqm] then return nil, ("trying to define variable %s, but a function with the same name exists; at %s"):format(fqm, line.source) end
|
||||
if not state.variables[fqm] or state.variables[fqm].type == "undefined argument" then
|
||||
local v, e = eval(state, exp)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue