shithub: sl

Download patch

ref: cc921b1f729e89c07aaaff880aaaf9b238d9eedb
parent: 4a1245bdde29a4664d70a1a3976178a4e8f51ef8
author: spew <spew@cbza.org>
date: Wed Apr 23 13:42:16 EDT 2025

implement append in lisp

--- a/boot/sl.boot
+++ b/boot/sl.boot
@@ -50,14 +50,14 @@
 -group . builtin))  buffer ((:doc-group . io))  num? ((:doc-group . builtin))  rand-float ((:doc-group . rand))  builtin? ((:doc-group . builtin))  set-car! ((:doc-group . list)
   (:doc-group . builtin))  cons? ((:doc-group . builtin))  doc-group ((:doc-group . doc))  aref ((:doc-group . builtin))  *properties* ((:doc-group . prop))  vec ((:doc-group . builtin))  >= ((:doc-group . compare))  sym? ((:doc-group . builtin))  zero? ((:doc-group . compare))  length= ((:doc-group . list))  positive? ((:doc-group . compare))  doc-for ((:doc-group . doc))  aset! ((:doc-group . builtin))  T ((:doc-see))  car ((:doc-group . list)
   (:doc-group . builtin))  *builtins* ((:doc-group . builtin))  str ((:doc-group . string))  cons ((:doc-group . list)
-ltin))  zero? ((:doc-group . compare))  length= ((:doc-group . list))  positive? ((:doc-group . compare))  doc-for ((:doc-group . doc))  aset! ((:doc-group . builtin))  T ((:doc-see))  car ((:doc-group . list)
-  (:doc-group . builtin))  *builtins* ((:doc-group . builtin))  str ((:doc-group . string))  cons ((:doc-group . list)
+ltin))  zero? ((:doc-group . compare))  length= ((:doc-group . list))  positive? ((:doc-group . compare))  doc-for ((:doc-group . doc))  aset! ((:doc-group . builtin))  T ((:doc-see))  car ((:doc-group . list)
+  (:doc-group . builtin))  *builtins* ((:doc-group . builtin))  str ((:doc-group . string))  cons ((:doc-group . list)
 )  - ((:doc-group . builtin))  remprop ((:doc-group . prop))  <= ((:doc-group . compare))  rand ((:doc-group . rand))  negative? ((:doc-group . compare))  Instructions ((:doc-group . builtin))  file ((:doc-group . io))  rand-double ((:doc-group . rand))  cdr ((:doc-group . list)
   (:doc-group . builtin))  atom? ((:doc-group . builtin))  vec? ((:doc-group . builtin))  / ((:doc-group . builtin))  equal? ((:doc-group . compare)
-doc-group . builtin))  vec? ((:doc-group . builtin))  / ((:doc-group . builtin))  equal? ((:doc-group . compare)
+? ((:doc-group . builtin))  vec? ((:doc-group . builtin))  / ((:doc-group . builtin))  equal? ((:doc-group . compare)
 ? ((:doc-group . compare) (:doc-group . builtin))  io? ((:doc-group . io))  eof-object? ((:doc-group . io))  list ((:doc-group . builtin))  apply ((:doc-group . builtin))  help ((:doc-group . doc))  rand-u32 ((:doc-group . rand))  = ((:doc-group . compare)
   (:doc-group . builtin))  rand-u64 ((:doc-group . rand))  not ((:doc-group . builtin))  separate-doc-from-body ((:doc-group . doc))  set-cdr! ((:doc-group . list)
-list)
+up . list)
 p . doc))  lz-pack ((:doc-group . compress))  arg-counts ((:doc-group . builtin))  eq? ((:doc-group . compare)
   (:doc-group . builtin))  getprop ((:doc-group . prop) (:doc-see . putprop))  vm-stats ((:doc-group . vm))  * ((:doc-group . builtin))  putprop ((:doc-group . prop)
   (:doc-see . getprop))  io->str ((:doc-group . io))))
@@ -95,12 +95,12 @@
 nless type-error quote if not aref assv :read-only error str "slot "
   " in struct " " is :read-only" aset!) 21)) 33)  make-label #fn("n120e1:" #(gensym) 5)  bcode:cenv #fn("n1200r3e3:" #(aref) 7)  mark-label #fn("n22002122e21e4:" #(emit
   quote label) 8)  quasiquote #fn("n1700E62:" #(bq-process) 7)  > #fn("z12021e1721510e163:" #(#fn(nconc)
-) 7)  > #fn("z12021e1721510e163:" #(#fn(nconc)
+) 7)  > #fn("z12021e1721510e163:" #(#fn(nconc)
 07588265275882752IIIIIb;b<288;29_514288<2:_514282;?=514282<87>1?>514282=??51402>CM02?2@8<>18?2A7B26528=5252@$089;J5048:3\xe3082888:2C154475882D527E2F8@527E2G8@52893H07H7I2J898A535147K50@30q48B3W07K5047H2L5147K5042?2M8;>18B5247K50@30q^1^1^1413c07K5047H2N5147K5042?2O8;>18?2A7B26528>525247K50@30q47P50@g07H2Q13<02R12S52@402T05341JE00R3@00ZJ;07H2U51@30q47K5047P60:" #(#(:print-header
   0) help-print-header #fn(sym) ":doc-" doc getprop *doc* *formals-list* #0#
-K5042?2M8;>18B5247K50@30q^1^1^1413c07K5047H2N5147K5042?2O8;>18?2A7B26528>525247K50@30q47P50@g07H2Q13<02R12S52@402T05341JE00R3@00ZJ;07H2U51@30q47K5047P60:" #(#(:print-header
+K5042?2M8;>18B5247K50@30q^1^1^1413c07K5047H2N5147K5042?2O8;>18?2A7B26528>525247K50@30q47P50@g07H2Q13<02R12S52@402T05341JE00R3@00ZJ;07H2U51@30q47K5047P60:" #(#(:print-header
 m) ":doc-" doc getprop *doc* *formals-list* #0#
-                         #fn("n17050471A51472F0P61:" #(newline princ print) 7)
+                              #fn("n17050471A51472F0P61:" #(newline princ print) 7)
 0E8563:0:" #(#fn(str-find) "\n" #fn(str-sub)) first-line 9)
   #fn("n10B;3B040<20Q;38040T21Q:" #(doc group) doc-group? 6)
   #fn("n10H;3?0470A710225262:" #(member getprop *doc-extra*) doc-extra-term? 9)
@@ -110,7 +110,7 @@
 021522263:" #(getprop *formals-list* "    ") 9)
   void "no help for " #fn(str) " " "" " (undefined)") 21)  defstruct #fn("z0700=5185<85=0<I21228887>2?9514863H0738824862589Pe15252@30q42627e188e178875163:" #(separate-doc-from-body
   #0# #fn("n12002152853=0220E8553@300853<02208552@402324752627AF5351285229862:7;882<528764:" #(#fn(str-find)
-r #fn(list*) defstruct "\n" #fn(str) "\n\n    "
+to-str #fn(list*) defstruct "\n" #fn(str) "\n\n    "
 -fmt #fn(nconc) %defstruct% copy-list) 15)  bcode:ctable #fn("n1200Ke3:" #(aref) 7)  with-output-to #fn("z12021e1220e2e1e17315163:" #(#fn(nconc)
   with-bindings *io-out* copy-list) 9)  catch #fn("n22012122e123242522e2262722e22829e2e3262:22e20e3e42;22e22<22e2e4e3e3:" #(trycatch
   λ #:g464 if and cons? eq? car quote thrown-value cadr caddr raise) 15)  let* #fn("z10H3E02021e1qe17215153e1:2021e173051e1e1720=B3H02024e10=e17215153e1@301515375051e2:" #(#fn(nconc)
@@ -136,6 +136,9 @@
 - #u8(56)  brn.l #u8(49)  optargs #u8(87)  closure #u8(14)  vec? #u8(45)  pop #u8(4)  eqv? #u8(51)  list #u8(53)  seta #u8(15)  seta.l #u8(73)  brnn #u8(26)  loadnil #u8(65)  loadg #u8(7)  loada #u8(8)  tcall #u8(6))
             S #fn("z1700215286380861}2:7223062:" #(getprop constructor error "no default constructor for struct: ") S 8)
             __finish #fn("n120Z3>021220>17062:q:" #(*exit-hooks* #fn(for-each)
+:7223062:" #(getprop constructor error "no default constructor for struct: ") S 8)
+            __finish #fn("n120Z3>021220>17062:q:" #(*exit-hooks* #fn(for-each)
+                                                    #fn("n10A61:" 6)) __finish 7)
 :7223062:" #(getprop constructor error "no default constructor for struct: ") S 8)
             __finish #fn("n120Z3>021220>17062:q:" #(*exit-hooks* #fn(for-each)
                                                     #fn("n10A61:" 6)) __finish 7)
@@ -196,13 +199,13 @@
 n bcode:stack compile-arglist emit tcall.l call.l
   builtin->instruction cadr length= λ inlineable? compile-let compile-builtin-call tcall call) compile-app 16)
             compile-arglist #fn("n3202101>282524228261:" #(#fn(for-each)
-                                              #fn("n170AFq054471AK62:" #(compile-in
+                                              #fn("n170AFq054471AK62:" #(compile-in
 egin #fn("n483H3?0700182715064:83=H3>070018283<64:7001q83<5447202352474018283=64:" #(compile-in
   void emit pop compile-begin) compile-begin 9)
             compile-builtin-call #fn("n7I202186850>3?;514227385q538<3I07483=8<52J=075858<52@30q4858=26CL086El23:07702862:770858663:8=29C708;60:8=2:C708;60:8=2;C]086El23:07702<62:86r2l23:07702=62:770858663:8=2>Cm086El23:07585K62:86Kl23:07702?62:86r2l23:07702@62:770858663:8=2ACL086El23:07702B62:770858663:8=2CCL086El23:07585K62:770858663:8=2DCN086El23<07702E2F63:770858663:8=2GCX086r2L23;07585r262:770823702H@402G8663:8=2ICb086r2l23:07702J62:r286L23?07708586r3~63:7585r262:7708562:" #(#0#
-8;60:8=2;C]086El23:07702<62:86r2l23:07702=62:770858663:8=2>Cm086El23:07585K62:86Kl23:07702?62:86r2l23:07702@62:770858663:8=2ACL086El23:07702B62:770858663:8=2CCL086El23:07585K62:770858663:8=2DCN086El23<07702E2F63:770858663:8=2GCX086r2L23;07585r262:770823702H@402G8663:8=2ICb086r2l23:07702J62:r286L23?07708586r3~63:7585r262:7708562:" #(#0#
-  #fn("n0AEl239070FK62:7192FA63:" #(argc-error emit) num-compare 8)
-  #fn(get) arg-counts length= argc-error list emit loadnil < = + load0 add2 - neg sub2 * load1 /
+8;60:8=2;C]086El23:07702<62:86r2l23:07702=62:770858663:8=2>Cm086El23:07585K62:86Kl23:07702?62:86r2l23:07702@62:770858663:8=2ACL086El23:07702B62:770858663:8=2CCL086El23:07585K62:770858663:8=2DCN086El23<07702E2F63:770858663:8=2GCX086r2L23;07585r262:770823702H@402G8663:8=2ICb086r2l23:07702J62:r286L23?07708586r3~63:7585r262:7708562:" #(#0#
+  #fn("n0AEl239070FK62:7192FA63:" #(argc-error emit) num-compare 8)
+  #fn(get) arg-counts length= argc-error list emit loadnil < = + load0 add2 - neg sub2 * load1 /
 62:770823702H@402G8663:8=2ICb086r2l23:07702J62:r286L23?07708586r3~63:7585r262:7708562:" #(#0#
   #fn("n0AEl239070FK62:7192FA63:" #(argc-error emit) num-compare 8)
   #fn(get) arg-counts length= argc-error list emit loadnil < = + load0 add2 - neg sub2 * load1 /
@@ -346,8 +349,8 @@
 bda:body #fn("n170061:" #(caddr) lambda:body 6) lambda:vars
             #fn("n1700T61:" #(lambda-vars) lambda:vars 6) last-pair #fn("n10=H3400:700=61:" #(last-pair) last-pair 6)
             lastcdr #fn("n10H3400:70051=:" #(last-pair) lastcdr 6) length=
-;34040:0B3<0700=1K~62:121051L2:" #(length> #fn(length)) length> 8)
-            list->vec #fn("n1202172063:" #(#fn(map) vec identity) list->vec 8) list-ref
+;34040:0B3<0700=1K~62:121051L2:" #(length> #fn(length)) length> 8)
+            list->vec #fn("n1202172063:" #(#fn(map) vec identity) list->vec 8) list-ref
 85>12385>1{:" #(#fn(file) :read #fn("n0Ib48420A84>2_484<^1III63:" #(#fn("n320A51JG0F<21A510721514735063:24A514737215161:" #(#fn(io-eof?)
   #fn(read) load-process void #fn(io-close)) 9)) 8)
                                             #fn("n120A51421220e261:" #(#fn(io-close)
@@ -491,12 +494,12 @@
 182122051~52062:" #(#fn(str) str-rep #fn(str-length)) str-lpad 10)
             str-map #fn("n2205021151EI8887L23O0422860231885251524748851?8@\f/^14258661:" #(#fn(buffer)
   #fn(str-length) #fn(io-putrune) #fn(str-rune) 1+ #fn(io->str)) str-map 13)
-p #fn("n21r4L23b0701E5235021:1Kl238022061:1r2l2390220062:2200063:731513@02207401K~5262:742200521r2j262:" #(<=
+p #fn("n21r4L23b0701E5235021:1Kl238022061:1r2l2390220062:2200063:731513@02207401K~5262:742200521r2j262:" #(<=
 (str-sub)) str-tail 7) str-trim
             #fn("n3IIb7b820872187>1_51420882288>1_5142305124087<01E895488<082895363:" #(#0#
                                                                                         #fn("n48283L23P02012108252523A0A<017282518364:82:" #(#fn(str-find)
   #fn(str-rune) 1+) trim-start 9) #fn("n3E82L23R020121072825152523?0A<0172825163:82:" #(#fn(str-find)
-                                                   #fn(str-rune)
+                                                   #fn(str-rune)
                #fn(str-rune)
                                                                                         1-) trim-end 10)
                                                                                         #fn(str-length)
@@ -515,7 +518,7 @@
 
   #fn("n10H3700:@30q40<85B3I07085r2523>07185Er253@4085A<0=51P:" #(length> subseq) formals-clean 9)
   #fn(str?) #fn(map) str-join #fn(str-split) "\n" any #fn("n1E20051L2;3B04210E5222Q;34040:" #(#fn(str-length)
-tra* getprop *formals-list* filter #fn("n1700A52S:" #(member) 7)
+oc-extra* getprop *formals-list* filter #fn("n1700A52S:" #(member) 7)
 0)
             table-clone #fn("n12050212285>1q053485:" #(#fn(table)
                                                        #fn(table-foldl)
--- a/src/sl.c
+++ b/src/sl.c
@@ -747,34 +747,6 @@
 }
 
 static sl_v
-copy_list(sl_v L)
-{
-	if(!iscons(L))
-		return sl_nil;
-	usize plcons = sl.sp - sl.stack;
-	usize pL = plcons+1;
-	PUSH(sl_nil);
-	PUSH(L);
-	sl_v c;
-	c = alloc_cons(); PUSH(c);  // save first cons
-	car_(c) = car_(sl.stack[pL]);
-	cdr_(c) = sl_nil;
-	sl.stack[plcons] = c;
-	sl.stack[pL] = cdr_(sl.stack[pL]);
-	while(iscons(sl.stack[pL])){
-		c = alloc_cons();
-		car_(c) = car_(sl.stack[pL]);
-		cdr_(c) = sl_nil;
-		cdr_(sl.stack[plcons]) = c;
-		sl.stack[plcons] = c;
-		sl.stack[pL] = cdr_(sl.stack[pL]);
-	}
-	c = POP();  // first cons
-	POPN(2);
-	return c;
-}
-
-static sl_v
 do_trycatch(void)
 {
 	usize osp = sl.sp - sl.stack;
@@ -1096,31 +1068,6 @@
 	if(isfn(v))
 		return size_wrap(fn_maxstack(v));
 	bthrow(type_error(nil, "fn", v));
-}
-
-BUILTIN("append", append)
-{
-	if(nargs == 0)
-		return sl_nil;
-
-	sl_v first = sl_nil, lastcons = sl_nil;
-	sl_gc_handle(&first);
-	sl_gc_handle(&lastcons);
-	for(int i = 0; i < nargs; i++){
-		sl_v lst = args[i];
-		if(iscons(lst)){
-			lst = copy_list(lst);
-			if(first == sl_nil)
-				first = lst;
-			else
-				cdr_(lastcons) = lst;
-			lastcons = tagptr((((sl_cons*)slg.curheap)-1), TAG_CONS);
-		}else if(lst != sl_nil){
-			bthrow(type_error(nil, "cons", lst));
-		}
-	}
-	sl_free_gc_handles(2);
-	return first;
 }
 
 BUILTIN("list*", liststar)
--- a/src/system.sl
+++ b/src/system.sl
@@ -513,15 +513,32 @@
         ((cons? seq) (length> (cdr seq) (- n 1)))
         (else        (> (length seq) n))))
 
-(def (copy-list seq (n NIL))
-  (def (copy- last seq n)
+(def (append . lists)
+  (def (copy- last l)
+    (if (not l)
+        last
+        (let {[next (cons (car l) NIL)]}
+          (set-cdr! last next)
+          (copy- next (cdr l)))))
+  (def (append- last lists)
+    (unless (cdr lists)
+            (set-cdr! last (car lists))
+            (return))
+    (let {[next (copy- last (car lists))]}
+      (append- next (cdr lists))))
+  (let {[fst (cons NIL NIL)]}
+    (append- fst lists)
+    (cdr fst)))
+
+(def (copy-list l (n NIL))
+  (def (copy- last l n)
     (and n (= n 0) (return))
-    (unless seq (return))
-    (let {[next (cons (car seq) NIL)]}
+    (unless l (return))
+    (let {[next (cons (car l) NIL)]}
       (set-cdr! last next)
-      (copy- next (cdr seq) (and n (1- n)))))
+      (copy- next (cdr l) (and n (1- n)))))
   (let {[fst (cons NIL NIL)]}
-    (copy- fst seq n)
+    (copy- fst l n)
     (cdr fst)))
 
 (def (subseq seq start (end NIL))
--- a/test/unittest.sl
+++ b/test/unittest.sl
@@ -379,8 +379,8 @@
 (assert (equal? `(a `(b c)) '(a (quasiquote (b c)))))
 (assert (equal? ````x '```x))
 
-(assert-fail (eval '(append 1)))
-(assert-fail (eval '(append NIL 1)))
+(assert (equal? (append 1) 1))
+(assert (equal? (append NIL 1) 1))
 (assert (equal? (append) NIL))
 (assert (equal? (append NIL) NIL))
 (assert (equal? (append NIL NIL) NIL))