shithub: sl

Download patch

ref: 5822146e55b3aff8396e434c8724650251b97dfb
parent: 8bbdd2c99299b922e60a3e7868027909b97d918f
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Mar 18 15:19:49 EDT 2025

keyword args: error on duplicates

Fixes: https://todo.sr.ht/~ft/sl/50

--- a/boot/sl.boot
+++ b/boot/sl.boot
@@ -152,11 +152,13 @@
 "n570018283D218467:" #(compile-short-circuit
   brn) compile-and)
             compile-app #fn("n483<88R3U07088152JK088Z3E0218851[3;0218851@40887283=23523q07401q895440r40r4GKMp4750183=530r40r4G8:UMp47608237027@40288:63:89[;3904798951892:Cf07089152J\\0212:517:d3P07;83r2523E07401q83T5447602:62:89B3P07<89<513F07=83513=07>01828364:8:360q@F07401q895440r40r4GKMp4750183=530r40r4G8;UMp48:360q@=00r40r4Gr/Mp48:3C07?018283898:8;67:760823702@@402A8;63:" #(in-env?
-892:Cf07089152J\\0212:517:d3P07;83r2523E07401q83T5447602:62:89B3P07<89<513F07=83513=07>01828364:8:360q@F07401q895440r40r4GKMp4750183=530r40r4G8;UMp48:360q@=00r40r4Gr/Mp48:3C07?018283898:8;67:760823702@@402A8;63:" #(in-env?
-  #fn(top-level-value) length> 255 compile-in compile-arglist emit tcall.l call.l
-  builtin->instruction cadr length= lambda? inlineable? compile-let compile-builtin-call tcall call) compile-app)
-            compile-arglist #fn("n3202101>282524228261:" #(#fn(for-each)
-                                                           #fn("n170AFq0544Ar4Ar4GKMp:" #(compile-in))
+892:Cf07089152J\\0212:517:d3P07;83r2523E07401q83T5447602:62:89B3P07<89<513F07=83513=07>01828364:8:360q@F07401q895440r40r4GKMp4750183=530r40r4G8;UMp48:360q@=00r40r4Gr/Mp48:3C07?018283898:8;67:760823702@@402A8;63:" #(in-env?
+  #fn(top-level-value) length> 255 compile-in compile-arglist emit tcall.l call.l
+  builtin->instruction cadr length= lambda? inlineable? compile-let compile-builtin-call tcall call) compile-app)
+            compile-arglist #fn("n3202101>282524228261:" #(#fn(for-each)
+                                                           #fn("n170AFq0544Ar4Ar4GKMp:" #(compile-in))
+                                                           #fn(length)) compile-arglist)
+            compile-aset! #fn("n3208251r2~87Kl23?07101q2282P64:K87L23h07101q2374828752P544750176828752530r40r4G88UMp47702262:7822r362:" #(#fn(length)
 87L23h07101q2374828752P544750176828752530r40r4G88UMp47702262:7822r362:" #(#fn(length)
   compile-app aset! aref list-head compile-arglist list-tail emit argc-error) compile-aset!)
             compile-begin #fn("n483H3?0700182715064:83=H3>070018283<64:7001q83<5447202352474018283=64:" #(compile-in
@@ -223,7 +225,7 @@
 ndexfor #fn(assq) ((loadv loadv.l) (loadg loadg.l) (setg setg.l) (loada
   loada.l)
                                                                (seta seta.l) (box box.l)) 255 ((loadc
-n("n582B3\x91020507102284534710238953474075176838452q53q7782515447102884534710295247102:895347;0182=8384KM65:q:" #(#fn(gensym)
+n("n582B3\x91020507102284534710238953474075176838452q53q7782515447102884534710295247102:895347;0182=8384KM65:q:" #(#fn(gensym)
  emit brbound brnn compile-in extend-env list-head cadar seta pop label emit-optional-arg-inits) emit-optional-arg-inits)
             encode-byte-code #fn("n17005171855172238651r3238651r2ki2M2452238651E255025502650qqI8988L23\xbc148689G?=48=27CP0288:8689KMG298<5153489r2M?9@\x8b12:8<2;7<873k08=8C2=C702>@X08C2?C702@@L08C2AC702B@@08C2CC702D@408=^1@408=5252489KM?948988L2;38048689G?>42E8=2F523`0288;298<518>5342:8<873707G@407HE5152489KM?9@\xeb08=2ICH02:8<2J8>5152489KM?9@\xce08>X3\xc708=2E8?2K523H02:8<2J8>5152489KM?9@\x9f02E8?2L523\x8102:8<2J8>5152489KM?942:8<2J8689G5152489KM?948=2MCK02:8<2J8689G5152489KM?9@30q@E02:8<2N8>5152489KM?9^1@30q@\x9f.42O2P8<878:>38;5242Q8<61:" #(reverse!
   list->vec >= #fn(length) 65536 #fn(table) #fn(buffer) label #fn(put!)
@@ -266,7 +268,7 @@
 82=5362:" #(foldr) foldr) get-defined-vars #fn("n170A<05161:" #(delete-duplicates) #(#2=(#fn("n10H340q:0<20Cj00=B3d00TR;37040Te1;JS040TB;3E0471051R;3:0471051e1;J404q:0<22C?07324A<0=52}2:q:" #(def
   caadr begin nconc #fn(map)) #(#2#)))))
             get-syntax #fn("n120710q63:" #(#fn(get)
-3;J50482:" #(#fn(get)
+3;J50482:" #(#fn(get)
         *properties*) getprop)
             hex5 #fn("n170210r@52r52263:" #(str-lpad #fn(num->str) #\0) hex5) identity
             #fn("n10:" #() identity) in-env? #fn("n21B;3F042001<52;J:047101=62:" #(#fn(assq)
--- a/src/compiler.lsp
+++ b/src/compiler.lsp
@@ -540,7 +540,7 @@
           ((and (cons? l) (sym? (car l)))
            (if (or opt kw)
                (error "compile error: invalid argument list "
-                      o ": optional arguments must come after required.")
+                      o ": optional arguments must come after required")
                (check-formals (cdr l) o opt kw)))
           ((and (cons? l) (cons? (car l)))
            (unless (and (length= (car l) 2)
@@ -695,6 +695,13 @@
            ff))
 
 (def (compile-f- env f)
+  (def (any-duplicate-kw kw)
+    (let ((k (caar kw))
+          (rest (cdr kw)))
+      (when rest
+        (or (any (λ (next) (and (eq? k (car next)) k)) rest)
+            (any-duplicate-kw rest)))))
+
   ;; compile lambda expression, assuming defines already lowered
   (let ((g     (make-code-emitter))
         (args  (cadr f))
@@ -705,8 +712,12 @@
     (let* ((name  (if (not last) 'λ last))
            (nargs (if (atom? args) 0 (length args)))
            (nreq  (- nargs (length opta)))
-           (kwa   (filter keyword-arg? opta)))
+           (kwa   (filter keyword-arg? opta))
+           (dupkw (any-duplicate-kw kwa)))
 
+      (when dupkw
+        (error "compile error: duplicate keyword " dupkw))
+
       ;; emit argument checking prologue
       (when opta
         (if (not kwa)
@@ -843,7 +854,8 @@
 ;
 ; and the associated value is at index X+1.
 (def (make-perfect-hash-table alist)
-  (def ($hash-keyword key n) (mod0 (abs (hash key)) n))
+  (def ($hash-keyword key n)
+    (mod0 (abs (hash key)) n))
   (let loop1 ((n (length alist)))
     (let ((v (vec-alloc (* 2 n) nil)))
       (let loop2 ((lst alist))