mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-28 00:59:31 +00:00
Add function references
This commit is contained in:
parent
5e7ac83854
commit
6e5cbf9e7e
12 changed files with 245 additions and 49 deletions
|
|
@ -174,7 +174,7 @@ common = {
|
|||
if not exp then return nil, rem end
|
||||
if not rem:match("^%s*}") then return nil, ("expected closing } at end of expression before %q"):format(rem) end
|
||||
-- wrap in format() call
|
||||
local variant, err = common.find_function_variant(state, namespace, "{}", { type = "parentheses", expression = exp }, true)
|
||||
local variant, err = common.find_function(state, namespace, "{}", { type = "parentheses", expression = exp }, true)
|
||||
if not variant then return variant, err end
|
||||
-- add to text
|
||||
table.insert(l, variant)
|
||||
|
|
@ -211,13 +211,13 @@ common = {
|
|||
return text_exp
|
||||
end
|
||||
end,
|
||||
-- find compatible function variants from a fully qualified name
|
||||
-- this functions does not guarantee that functions are fully compatible with the given arguments and only performs a pre-selection without the ones which definitely aren't
|
||||
-- * list of variants: if success
|
||||
-- find a list of compatible function variants from a fully qualified name
|
||||
-- this functions does not guarantee that the returned variants are fully compatible with the given arguments and only performs a pre-selection without the ones which definitely aren't
|
||||
-- * list of compatible variants: if success
|
||||
-- * nil, err: if error
|
||||
find_function_variant_from_fqm = function(fqm, state, arg)
|
||||
local err = ("compatible function %q variant not found"):format(fqm)
|
||||
local func = state.functions[fqm] or {}
|
||||
local func = state.functions[fqm]
|
||||
local args = arg and common.flatten_list(arg) or {}
|
||||
local variants = {}
|
||||
for _, variant in ipairs(func) do
|
||||
|
|
@ -248,7 +248,7 @@ common = {
|
|||
--- same as find_function_variant_from_fqm, but will search every function from the current namespace and up using find
|
||||
-- returns directly a function expression in case of success
|
||||
-- return nil, err otherwise
|
||||
find_function_variant = function(state, namespace, name, arg, explicit_call)
|
||||
find_function = function(state, namespace, name, arg, explicit_call)
|
||||
local variants = {}
|
||||
local err = ("compatible function %q variant not found"):format(name)
|
||||
local l = common.find_all(state.aliases, state.functions, namespace, name)
|
||||
|
|
@ -263,7 +263,7 @@ common = {
|
|||
end
|
||||
if #variants > 0 then
|
||||
return {
|
||||
type = "function",
|
||||
type = "function call",
|
||||
called_name = name,
|
||||
explicit_call = explicit_call,
|
||||
variants = variants,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local identifier_pattern, format_identifier, find, escape, find_function_variant, parse_text
|
||||
local identifier_pattern, format_identifier, find, escape, find_function, parse_text, find_all
|
||||
|
||||
--- binop priority
|
||||
local binops_prio = {
|
||||
|
|
@ -132,7 +132,7 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
|||
right = val
|
||||
}
|
||||
-- find compatible variant
|
||||
local variant, err = find_function_variant(state, namespace, ":", args, true)
|
||||
local variant, err = find_function(state, namespace, ":", args, true)
|
||||
if not variant then return variant, err end
|
||||
return expression(r, state, namespace, current_priority, variant)
|
||||
end
|
||||
|
|
@ -171,9 +171,22 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
|||
end
|
||||
end
|
||||
-- find compatible variant
|
||||
local variant, err = find_function_variant(state, namespace, name, args, explicit_call)
|
||||
local variant, err = find_function(state, namespace, name, args, explicit_call)
|
||||
if not variant then return variant, err end
|
||||
return expression(r, state, namespace, current_priority, variant)
|
||||
-- function reference
|
||||
elseif s:match("^%&"..identifier_pattern) then
|
||||
local name, r = s:match("^%&("..identifier_pattern..")(.-)$")
|
||||
name = format_identifier(name)
|
||||
-- get all functions this name can reference
|
||||
local lfnqm = find_all(state.aliases, state.functions, namespace, name)
|
||||
if #lfnqm > 0 then
|
||||
return expression(r, state, namespace, current_priority, {
|
||||
type = "function reference",
|
||||
names = lfnqm
|
||||
})
|
||||
end
|
||||
return nil, ("can't find function %q to reference"):format(name)
|
||||
end
|
||||
-- unops
|
||||
for prio, oplist in ipairs(unops_prio) do
|
||||
|
|
@ -183,7 +196,7 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
|||
local right, r = expression(s:match("^"..escaped.."(.*)$"), state, namespace, prio)
|
||||
if not right then return nil, ("invalid expression after unop %q: %s"):format(op, r) end
|
||||
-- find variant
|
||||
local variant, err = find_function_variant(state, namespace, op, right, true)
|
||||
local variant, err = find_function(state, namespace, op, right, true)
|
||||
if not variant then return variant, err end
|
||||
return expression(r, state, namespace, current_priority, variant)
|
||||
end
|
||||
|
|
@ -227,7 +240,7 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
|||
}
|
||||
end
|
||||
-- find compatible variant
|
||||
local variant, err = find_function_variant(state, namespace, name, args, explicit_call)
|
||||
local variant, err = find_function(state, namespace, name, args, explicit_call)
|
||||
if not variant then return variant, err end
|
||||
return expression(r, state, namespace, current_priority, variant)
|
||||
-- other binops
|
||||
|
|
@ -250,12 +263,12 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
|||
left = operating_on,
|
||||
right = right
|
||||
}
|
||||
local variant, err = find_function_variant(state, namespace, op:match("^(.*)%=$"), args, true)
|
||||
local variant, err = find_function(state, namespace, op:match("^(.*)%=$"), args, true)
|
||||
if not variant then return variant, err end
|
||||
right = variant
|
||||
end
|
||||
-- assign to a function
|
||||
if operating_on.type == "function" then
|
||||
if operating_on.type == "function call" then
|
||||
-- remove non-assignment functions
|
||||
for i=#operating_on.variants, 1, -1 do
|
||||
if not operating_on.variants[i].assignment then
|
||||
|
|
@ -291,7 +304,7 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
|||
left = operating_on,
|
||||
right = right
|
||||
}
|
||||
local variant, err = find_function_variant(state, namespace, op, args, true)
|
||||
local variant, err = find_function(state, namespace, op, args, true)
|
||||
if not variant then return variant, err end
|
||||
return expression(r, state, namespace, current_priority, variant)
|
||||
end
|
||||
|
|
@ -300,15 +313,19 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
|||
end
|
||||
end
|
||||
end
|
||||
-- index
|
||||
-- index / call
|
||||
if s:match("^%b()") then
|
||||
local content, r = s:match("^(%b())(.*)$")
|
||||
-- get arguments (parentheses are kept)
|
||||
local right, r_paren = expression(content, state, namespace)
|
||||
if not right then return right, r_paren end
|
||||
if r_paren:match("[^%s]") then return nil, ("unexpected %q at end of index expression"):format(r_paren) end
|
||||
local args = { type = "list", left = operating_on, right = right }
|
||||
local variant, err = find_function_variant(state, namespace, "()", args, true)
|
||||
content = content:gsub("^%(", ""):gsub("%)$", "")
|
||||
-- get arguments
|
||||
local args = operating_on
|
||||
if content:match("[^%s]") then
|
||||
local right, r_paren = expression(content, state, namespace)
|
||||
if not right then return right, r_paren end
|
||||
if r_paren:match("[^%s]") then return nil, ("unexpected %q at end of index/call expression"):format(r_paren) end
|
||||
args = { type = "list", left = args, right = right }
|
||||
end
|
||||
local variant, err = find_function(state, namespace, "()", args, true)
|
||||
if not variant then return variant, err end
|
||||
return expression(r, state, namespace, current_priority, variant)
|
||||
end
|
||||
|
|
@ -319,6 +336,6 @@ end
|
|||
|
||||
package.loaded[...] = expression
|
||||
local common = require((...):gsub("expression$", "common"))
|
||||
identifier_pattern, format_identifier, find, escape, find_function_variant, parse_text = common.identifier_pattern, common.format_identifier, common.find, common.escape, common.find_function_variant, common.parse_text
|
||||
identifier_pattern, format_identifier, find, escape, find_function, parse_text, find_all = common.identifier_pattern, common.format_identifier, common.find, common.escape, common.find_function, common.parse_text, common.find_all
|
||||
|
||||
return expression
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ local function parse(state)
|
|||
end
|
||||
param.default = default_exp
|
||||
-- extract type annotation from default value
|
||||
if default_exp.type == "function" and default_exp.called_name == "::" then
|
||||
if default_exp.type == "function call" and default_exp.called_name == "::" then
|
||||
param.type_annotation = default_exp.argument.expression.right
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue