Skip to content

Commit

Permalink
builtin: define a symbol_op for a generic op acting on integer
Browse files Browse the repository at this point in the history
This can be used to define some generic (polymorphic) builtin
with a signature like:
	<name>(int)
	<name>(T, T)
	<name>(int, T)
	<name>(int, T, long, T, ... T)
where T is some integer type which will be instantiated at each call.

Signed-off-by: Luc Van Oostenryck <[email protected]>
  • Loading branch information
lucvoo committed Apr 13, 2021
1 parent 8fd2c0b commit f7eb2ea
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
63 changes: 63 additions & 0 deletions builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,69 @@ static struct symbol_op overflow_p_op = {
};


///
// Evaluate the arguments of 'generic' integer operators.
//
// Parameters with a complete type are used like in a normal prototype.
// The first parameter with a 'dynamic' type will be consider
// as polymorphic and for each calls will be instancied with the type
// of its effective argument.
// The next dynamic parameters will the use this polymorphic type.
// This allows to declare functions with some parameters having
// a type variably defined at call time:
// int foo(int, T, T);
static int evaluate_generic_int_op(struct expression *expr)
{
struct symbol *fntype = expr->fn->ctype->ctype.base_type;
struct symbol_list *types = NULL;
struct symbol *ctype = NULL;
struct expression *arg;
struct symbol *t;
int n = 0;

PREPARE_PTR_LIST(fntype->arguments, t);
FOR_EACH_PTR(expr->args, arg) {
n++;

if (!is_dynamic_type(t)) {
;
} else if (!ctype) {
// first 'dynamic' type, check that it's an integer
t = arg->ctype;
if (!t)
return 0;
if (t->type == SYM_NODE)
t = t->ctype.base_type;
if (!t)
return 0;
if (t->ctype.base_type != &int_type)
goto err;

// next 'dynamic' arguments will use this type
ctype = t;
} else {
// use the previous 'dynamic' type
t = ctype;
}
add_ptr_list(&types, t);
NEXT_PTR_LIST(t);
} END_FOR_EACH_PTR(arg);
FINISH_PTR_LIST(t);
return evaluate_arguments(types, expr->args);

err:
sparse_error(arg->pos, "non-integer type for argument %d:", n);
info(arg->pos, " %s", show_typename(arg->ctype));
expr->ctype = &bad_ctype;
return 0;
}

struct symbol_op generic_int_op = {
.args = args_prototype,
.evaluate = evaluate_generic_int_op,
};


static int eval_atomic_common(struct expression *expr)
{
struct symbol *fntype = expr->fn->ctype->ctype.base_type;
Expand Down
2 changes: 2 additions & 0 deletions builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ struct builtin_fn {

void declare_builtins(int stream, const struct builtin_fn tbl[]);

extern struct symbol_op generic_int_op;

#endif

0 comments on commit f7eb2ea

Please sign in to comment.