ref: 847c49884302779ff704c885fc97b58a895714cc
parent: f510f5f6eaa66e5f6a399f6bc4fa7091e00a6151
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Fri Dec 13 01:02:40 EST 2024
aref/aset! on proper lists Fixes: https://todo.sr.ht/~ft/femtolisp/21
--- a/flisp.c
+++ b/flisp.c
@@ -1264,17 +1264,29 @@
apply_aref:
v = FL(stack)[FL(sp)-n];
for(i = n-1; i > 0; i--){
+ if(isarray(v)){
+ FL(stack)[FL(sp)-i-1] = v;
+ v = cvalue_array_aref(&FL(stack)[FL(sp)-i-1]);
+ continue;
+ }
+ e = FL(stack)[FL(sp)-i];
+ isz = tosize(e);
if(isvector(v)){
- e = FL(stack)[FL(sp)-i];
- isz = tosize(e);
if(__unlikely(isz >= vector_size(v)))
bounds_error(v, e);
v = vector_elt(v, isz);
- }else if(__likely(isarray(v))){
- FL(stack)[FL(sp)-i-1] = v;
- v = cvalue_array_aref(&FL(stack)[FL(sp)-i-1]);
- }else{
+ continue;
+ }
+ if(!iscons(v) && v != FL_nil)
type_error("sequence", v);
+ for(value_t v0 = v;; isz--){
+ if(isz == 0){
+ v = car_(v);
+ break;
+ }
+ v = cdr_(v);
+ if(__unlikely(!iscons(v)))
+ bounds_error(v0, e);
}
}
POPN(n);
@@ -1654,28 +1666,50 @@
apply_aset:
v = FL(stack)[FL(sp)-n];
for(i = n-1; i >= 3; i--){
+ if(isarray(v)){
+ FL(stack)[FL(sp)-i-1] = v;
+ v = cvalue_array_aref(&FL(stack)[FL(sp)-i-1]);
+ continue;
+ }
+ e = FL(stack)[FL(sp)-i];
+ isz = tosize(e);
if(isvector(v)){
- e = FL(stack)[FL(sp)-i];
- isz = tosize(e);
if(__unlikely(isz >= vector_size(v)))
bounds_error(v, e);
v = vector_elt(v, isz);
- }else if(__likely(isarray(v))){
- FL(stack)[FL(sp)-i-1] = v;
- v = cvalue_array_aref(&FL(stack)[FL(sp)-i-1]);
- }else{
+ continue;
+ }
+ if(!iscons(v) && v != FL_nil)
type_error("sequence", v);
+ for(value_t v0 = v;; isz--){
+ if(isz == 0){
+ v = car_(v);
+ break;
+ }
+ v = cdr_(v);
+ if(__unlikely(!iscons(v)))
+ bounds_error(v0, e);
}
}
FL(stack)[FL(sp)-3] = v;
}
+ e = FL(stack)[FL(sp)-2];
+ isz = tosize(e);
if(isvector(v)){
- e = FL(stack)[FL(sp)-2];
- isz = tosize(e);
if(__unlikely(isz >= vector_size(v)))
bounds_error(v, e);
vector_elt(v, isz) = (e = FL(stack)[FL(sp)-1]);
- }else if(__likely(isarray(v))){
+ }else if(iscons(v) || v == FL_nil){
+ for(value_t v0 = v;; isz--){
+ if(isz == 0){
+ car_(v) = (e = FL(stack)[FL(sp)-1]);
+ break;
+ }
+ v = cdr_(v);
+ if(__unlikely(!iscons(v)))
+ bounds_error(v0, e);
+ }
+ }else if(isarray(v)){
e = cvalue_array_aset(&FL(stack)[FL(sp)-3]);
}else{
type_error("sequence", v);
--- a/test/unittest.lsp
+++ b/test/unittest.lsp
@@ -412,7 +412,7 @@
(assert (equal? (map (λ (x y z) (+ x y z)) '(1 2) '(3) '(4 5)) '(8)))
;; aref with multiple indices
-(define a #(#(0 1 2) #(3 #(4 5 6) 7)))
+(define a #(#(0 1 2) #(3 (4 5 6) 7)))
(assert (equal? 0 (aref a 0 0)))
(assert (equal? 0 (apply aref (list a 0 0))))
(assert (equal? 2 (aref a 0 2)))
@@ -426,12 +426,12 @@
(assert-fail (aref #("hello") 1 0))
;; aset with multiple indices
-(define a #(#(0 1 2) #(3 #(4 5 6) 7)))
+(define a #(#(0 1 2) #(3 (4 5 6) 7)))
(assert (equal? 8 (apply aset! (list a 0 0 8))))
(assert (equal? 9 (aset! a 1 1 (1+ 1) 9)))
(assert (equal? "hello" (aset! a (1+ 0) 2 "hello")))
(assert-fail (aset! a 1 1 3 "nope"))
-(assert (equal? a #(#(8 1 2) #(3 #(4 5 9) "hello"))))
+(assert (equal? a #(#(8 1 2) #(3 (4 5 9) "hello"))))
;; apply with multiple args
(assert (equal? 15 (apply + 1 2 '(3 4 5))))