More cleanup, generalize apply_va logic

This commit is contained in:
Justin Ethier 2016-06-29 22:55:18 -04:00
parent 4f65fdb6e2
commit 9cf016e1a6

View file

@ -3230,24 +3230,6 @@ void _call_95cc(void *data, object cont, object args)
return_closcall2(data, __glo_call_95cc_scheme_base, cont, car(args));
}
void apply_va(void *data, object cont, int argc, object func, ...)
{
object tmp = NULL;
int i;
va_list ap;
va_start(ap, func);
for (i = 1; i < argc; i++) {
tmp = va_arg(ap, object);
}
va_end(ap);
// fprintf(stdout, "DEBUG applying argc %d, func ", argc);
// Cyc_display(func, stdout);
// fprintf(stdout, " to values ");
// Cyc_display(tmp, stdout);
// fprintf(stdout, "\n");
apply(data, cont, func, tmp);
}
// Prepend value to the given list
#define stack_prepend(lis, value) { \
pair_type *tmp2 = alloca(sizeof(pair_type)); \
@ -3265,38 +3247,60 @@ void apply_va(void *data, object cont, int argc, object func, ...)
} \
}
// Front-end to apply
//
// Core of va processing is done here, because we need different
// functions for apply_va and dispatch_apply_va, and those functions
// need to start and end va. BUT, we need to allocate new objects
// so this stuff can't be returned, so a workaround is to put it in
// this macro.
//
// Fast path is just to take list, if we only have func and 1 arg.
// Otherwise append all args together into a single list, per r7rs.
#define do_apply_va \
va_start(ap, func); \
if (argc == 2) { \
lis = va_arg(ap, object); \
Cyc_check_pair_or_null(data, lis); \
} else { \
for (i = 1; i < argc; i++) { \
tmp = va_arg(ap, object); \
if (tmp == NULL){ \
continue; \
} else if (is_object_type(tmp) && type_of(tmp) == pair_tag) { \
l = tmp; \
stack_list_prepend(l, lis); \
} else { \
stack_prepend(lis, tmp); \
} \
} \
l = lis; \
lis = NULL; \
stack_list_prepend(l, lis); \
} \
va_end(ap);
void dispatch_apply_va(void *data, int argc, object clo, object cont, object func, ...)
{
list lis = NULL, tmp, l;
list lis = NULL, l;
object tmp;
int i;
va_list ap;
argc = argc - 1; // Required for "dispatch" function
va_start(ap, func);
if (argc == 2) {
// Fast path, nothing to append
lis = va_arg(ap, object);
Cyc_check_pair_or_null(data, lis);
} else {
for (i = 1; i < argc; i++) {
tmp = va_arg(ap, object);
if (tmp == NULL){
continue;
} else if (is_object_type(tmp) && type_of(tmp) == pair_tag) {
l = tmp;
stack_list_prepend(l, lis);
} else {
stack_prepend(lis, tmp);
}
}
// Reverse lis
l = lis;
lis = NULL;
stack_list_prepend(l, lis);
}
va_end(ap);
do_apply_va
apply(data, cont, func, lis);
}
void apply_va(void *data, object cont, int argc, object func, ...)
{
list lis = NULL, l;
object tmp;
int i;
va_list ap;
do_apply_va
apply(data, cont, func, tmp);
}
/*
* @param cont - Continuation for the function to call into
* @param func - Function to execute