mirror of
https://gitlab.labs.nic.cz/labs/bird.git
synced 2024-05-11 16:54:54 +00:00
Filter: Implement multiple dispatch for methods
- Extend method descriptors with type signature - Daisy chain method descriptors for the same symbol - Dispatch methods for same symbol based on type signature - Split add/delete/filter operations to multiple methods - Replace ad-hoc dispatch of old-style syntax with scope-based dispatch - Also change method->arg_num to count initial arg It still needs some improvements, like better handling of untyped expressions and better error reporting when no dispatch can be done. The multiple dispatch could also be extended to dispatch regular function-like expressions in a uniform way.
This commit is contained in:
@@ -30,7 +30,8 @@ filter_name(const struct filter *filter)
|
||||
return filter->sym->name;
|
||||
}
|
||||
|
||||
struct filter *f_new_where(struct f_inst *where)
|
||||
struct filter *
|
||||
f_new_where(struct f_inst *where)
|
||||
{
|
||||
struct f_inst *cond = f_new_inst(FI_CONDITION, where,
|
||||
f_new_inst(FI_DIE, F_ACCEPT),
|
||||
@@ -41,6 +42,43 @@ struct filter *f_new_where(struct f_inst *where)
|
||||
return f;
|
||||
}
|
||||
|
||||
static inline int
|
||||
f_match_signature(const struct f_method *dsc, struct f_inst *args)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 1; args && (i < dsc->arg_num); args = args->next, i++)
|
||||
if (dsc->args_type[i] && (args->type != dsc->args_type[i]))
|
||||
return 0;
|
||||
|
||||
return !args && !(i < dsc->arg_num);
|
||||
}
|
||||
|
||||
struct f_inst *
|
||||
f_dispatch_method(struct symbol *sym, struct f_inst *obj, struct f_inst *args)
|
||||
{
|
||||
/* Note! We should revert args */
|
||||
|
||||
for (const struct f_method *dsc = sym->method; dsc; dsc = dsc->next)
|
||||
if (f_match_signature(dsc, args))
|
||||
return dsc->new_inst(obj, args);
|
||||
|
||||
cf_error("Cannot dispatch method '%s'", sym->name);
|
||||
}
|
||||
|
||||
struct f_inst *
|
||||
f_dispatch_method_x(const char *name, enum f_type t, struct f_inst *obj, struct f_inst *args)
|
||||
{
|
||||
struct sym_scope *scope = f_type_method_scope(t);
|
||||
struct symbol *sym = cf_find_symbol_scope(scope, name);
|
||||
|
||||
if (!sym)
|
||||
cf_error("Cannot dispatch method '%s'", name);
|
||||
|
||||
return f_dispatch_method(sym, obj, args);
|
||||
}
|
||||
|
||||
|
||||
struct f_inst *
|
||||
f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block)
|
||||
{
|
||||
|
Reference in New Issue
Block a user