Skip to content

Commit f7eb2ea

Browse files
committed
builtin: define a symbol_op for a generic op acting on integer
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]>
1 parent 8fd2c0b commit f7eb2ea

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

builtin.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,69 @@ static struct symbol_op overflow_p_op = {
390390
};
391391

392392

393+
///
394+
// Evaluate the arguments of 'generic' integer operators.
395+
//
396+
// Parameters with a complete type are used like in a normal prototype.
397+
// The first parameter with a 'dynamic' type will be consider
398+
// as polymorphic and for each calls will be instancied with the type
399+
// of its effective argument.
400+
// The next dynamic parameters will the use this polymorphic type.
401+
// This allows to declare functions with some parameters having
402+
// a type variably defined at call time:
403+
// int foo(int, T, T);
404+
static int evaluate_generic_int_op(struct expression *expr)
405+
{
406+
struct symbol *fntype = expr->fn->ctype->ctype.base_type;
407+
struct symbol_list *types = NULL;
408+
struct symbol *ctype = NULL;
409+
struct expression *arg;
410+
struct symbol *t;
411+
int n = 0;
412+
413+
PREPARE_PTR_LIST(fntype->arguments, t);
414+
FOR_EACH_PTR(expr->args, arg) {
415+
n++;
416+
417+
if (!is_dynamic_type(t)) {
418+
;
419+
} else if (!ctype) {
420+
// first 'dynamic' type, check that it's an integer
421+
t = arg->ctype;
422+
if (!t)
423+
return 0;
424+
if (t->type == SYM_NODE)
425+
t = t->ctype.base_type;
426+
if (!t)
427+
return 0;
428+
if (t->ctype.base_type != &int_type)
429+
goto err;
430+
431+
// next 'dynamic' arguments will use this type
432+
ctype = t;
433+
} else {
434+
// use the previous 'dynamic' type
435+
t = ctype;
436+
}
437+
add_ptr_list(&types, t);
438+
NEXT_PTR_LIST(t);
439+
} END_FOR_EACH_PTR(arg);
440+
FINISH_PTR_LIST(t);
441+
return evaluate_arguments(types, expr->args);
442+
443+
err:
444+
sparse_error(arg->pos, "non-integer type for argument %d:", n);
445+
info(arg->pos, " %s", show_typename(arg->ctype));
446+
expr->ctype = &bad_ctype;
447+
return 0;
448+
}
449+
450+
struct symbol_op generic_int_op = {
451+
.args = args_prototype,
452+
.evaluate = evaluate_generic_int_op,
453+
};
454+
455+
393456
static int eval_atomic_common(struct expression *expr)
394457
{
395458
struct symbol *fntype = expr->fn->ctype->ctype.base_type;

builtin.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ struct builtin_fn {
1414

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

17+
extern struct symbol_op generic_int_op;
18+
1719
#endif

0 commit comments

Comments
 (0)