summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-01-03 03:17:33 -0800
committerKaz Kylheku <kaz@kylheku.com>2018-01-03 03:17:33 -0800
commite75e6bda47819e2be53615a2cc8f3d1d20741be2 (patch)
treed5014baa3b32111d3adcf566bd151c8aa0edfcf2 /lib.c
parent18d1c715712c74f709240fb389a6601a1a812895 (diff)
downloadtxr-e75e6bda47819e2be53615a2cc8f3d1d20741be2.tar.gz
txr-e75e6bda47819e2be53615a2cc8f3d1d20741be2.tar.bz2
txr-e75e6bda47819e2be53615a2cc8f3d1d20741be2.zip
car, cdr: fall back on lambda method.
* lib.c (car, cdr): Don't fail if the struct object has no car or cdr method. Use it if it is available, otherwise try to fall back on the lambda method if that is available.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/lib.c b/lib.c
index 6bb5f809..c126cada 100644
--- a/lib.c
+++ b/lib.c
@@ -380,8 +380,18 @@ val car(val cons)
return nil;
return chr_str(cons, zero);
case COBJ:
- if (obj_struct_p(cons))
- return funcall1(slot(cons, car_s), cons);
+ if (obj_struct_p(cons)) {
+ {
+ val car_meth = maybe_slot(cons, car_s);
+ if (car_meth)
+ return funcall1(car_meth, cons);
+ }
+ {
+ val lambda_meth = maybe_slot(cons, lambda_s);
+ if (lambda_meth)
+ return funcall2(lambda_meth, cons, zero);
+ }
+ }
default:
type_mismatch(lit("~s is not a cons"), cons, nao);
}
@@ -411,8 +421,18 @@ val cdr(val cons)
return nil;
return sub(cons, one, t);
case COBJ:
- if (obj_struct_p(cons))
- return funcall1(slot(cons, cdr_s), cons);
+ if (obj_struct_p(cons)) {
+ {
+ val cdr_meth = maybe_slot(cons, cdr_s);
+ if (cdr_meth)
+ return funcall1(cdr_meth, cons);
+ }
+ {
+ val lambda_meth = maybe_slot(cons, lambda_s);
+ if (lambda_meth)
+ return funcall2(lambda_meth, cons, rcons(one, t));
+ }
+ }
default:
type_mismatch(lit("~s is not a cons"), cons, nao);
}