summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-06-27 07:23:08 -0700
committerKaz Kylheku <kaz@kylheku.com>2014-06-27 07:23:08 -0700
commit0367ad753c7749c33f57e1e0805e0dbcea115af3 (patch)
treeea27bc337fa8de6eacd48e9084ac0eee1aa23ae6 /eval.c
parentea452c6fdc1b9d900ffe65b1cdeb0b098a4c20f6 (diff)
downloadtxr-0367ad753c7749c33f57e1e0805e0dbcea115af3.tar.gz
txr-0367ad753c7749c33f57e1e0805e0dbcea115af3.tar.bz2
txr-0367ad753c7749c33f57e1e0805e0dbcea115af3.zip
Bugfix: apply_intrinsic and iapply must not destructively
manipulate argument lists. * eval.c (apply_frob_args): Rewrite to non-destructive one-pass version. (iapply): Likewise. * lib.c (term): New function. * lib.h (term): Declared.
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c49
1 files changed, 27 insertions, 22 deletions
diff --git a/eval.c b/eval.c
index f113d879..6b6fbc16 100644
--- a/eval.c
+++ b/eval.c
@@ -646,12 +646,16 @@ val apply(val fun, val arglist, val ctx_form)
static val apply_frob_args(val args)
{
- loc plast = lastcons(args);
- if (!nullocp(plast)) {
- deref(plast) = car(deref(plast));
- return args;
- } else {
+ if (!cdr(args)) {
return car(args);
+ } else {
+ list_collect_decl (out, ptail);
+
+ for (; cdr(args); args = cdr(args))
+ ptail = list_collect(ptail, car(args));
+
+ list_collect_nconc(ptail, car(args));
+ return out;
}
}
@@ -662,27 +666,28 @@ val apply_intrinsic(val fun, val args)
static val iapply(val fun, val args)
{
- if (args && atom(args)) {
- args = cons(args, nil);
- } else {
- loc plast = lastcons(args);
- if (!nullocp(plast)) {
- deref(plast) = car(deref(plast));
- } else {
- args = car(args);
- }
+ list_collect_decl (mod_args, ptail);
+ loc saved_ptail;
+
+ for (; cdr(args); args = cdr(args))
+ ptail = list_collect(ptail, car(args));
+
+ saved_ptail = ptail;
+
+ ptail = list_collect_nconc(ptail, car(args));
+
+ {
+ loc pterm = term(ptail);
+ val tatom = deref(pterm);
- if (args && atom(args)) {
- args = cons(args, nil);
- } else if (args) {
- val la = last(args);
- val cd = cdr(la);
- if (cd && atom(cd))
- rplacd(la, cons(cd, nil));
+ if (tatom) {
+ deref(ptail) = nil;
+ ptail = list_collect_nconc(saved_ptail, copy_list(car(args)));
+ set(term(ptail), cons(tatom, nil));
}
}
- return apply(fun, args, nil);
+ return apply(fun, mod_args, nil);
}
static val call(val fun, val args)