shithub: sl

Download patch

ref: 16b9ff5fd8840555c30a22402ece715609992d7f
parent: fd1e36f98d997c8183d3040b66fa6f9cd91e825b
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Jan 28 00:13:45 EST 2025

keyword args: allow ":arg" as such only

There was confusion with :abc vs abc: in C and
compiler - stick to one way to define those.

Fixes: https://todo.sr.ht/~ft/femtolisp/43

--- a/builtins.c
+++ b/builtins.c
@@ -159,8 +159,7 @@
 BUILTIN("keyword?", keywordp)
 {
 	argcount(nargs, 1);
-	return (issymbol(args[0]) &&
-			iskeyword((symbol_t*)ptr(args[0]))) ? FL_t : FL_f;
+	return (issymbol(args[0]) && iskeyword((symbol_t*)ptr(args[0]))) ? FL_t : FL_f;
 }
 
 fl_purefn
@@ -200,7 +199,7 @@
 	const char *k = nil;
 	symbol_t *v;
 	while(Tnext(FL(symtab), &k, (void**)&v)){
-		if(v->binding != UNBOUND && !fl_is_keyword_name(v->name, strlen(v->name)))
+		if(v->binding != UNBOUND && (v->flags & FLAG_KEYWORD) == 0)
 			lst = fl_cons(tagptr(v, TAG_SYM), lst);
 	}
 	fl_free_gc_handles(1);
--- a/compiler.lsp
+++ b/compiler.lsp
@@ -550,7 +550,7 @@
 (define (keyword->symbol k)
   (if (keyword? k)
       (symbol (let ((s (string k)))
-                (string-sub s 0 (1- (string-length s)))))
+                (string-sub s 1 (string-length s))))
       k))
 
 (define (lambda-vars l)
@@ -559,7 +559,7 @@
           ((and (cons? l) (symbol? (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)
@@ -570,7 +570,7 @@
                (check-formals (cdr l) o opt #t)
                (if kw
                    (error "compile error: invalid argument list "
-                          o ". keyword arguments must come last.")
+                          o ": keyword arguments must come last.")
                    (check-formals (cdr l) o #t kw))))
           ((cons? l)
            (error "compile error: invalid formal argument " (car l)
--- a/flisp.boot
+++ b/flisp.boot
@@ -257,17 +257,17 @@
 	    io-readline #fn("7000n12002162:" #(#fn(io-readuntil) #\newline) io-readline)
 	    io-readlines #fn("7000n17071062:" #(read-all-of io-readline) io-readlines) iota
 	    #fn("7000n17071062:" #(map-int identity) iota) is-lambda? #fn("6000n1020Q;I704020Q:" #(λ) is-lambda?)
-	    keyword->symbol #fn("<000n1200513O021220512386E742586515153^161:0:" #(#fn(keyword?)
-										  #fn(symbol)
-										  #fn(string)
-										  #fn(string-sub)
-										  1- #fn(string-length)) keyword->symbol)
+	    keyword->symbol #fn(";000n1200513K021220512386K24865153^161:0:" #(#fn(keyword?)
+									      #fn(symbol)
+									      #fn(string)
+									      #fn(string-sub)
+									      #fn(string-length)) keyword->symbol)
 	    keyword-arg? #fn("6000n10B;3904200<61:" #(#fn(keyword?)) keyword-arg?) lambda-vars
 	    #fn(":000n1\x8d\x8a520852185>1_51485<00OO54422237405162:" #(#0#
 									#fn(":000n40V;I5040R340D:0B3Z00<R3T082;I504833<0702112263:A<0=1828364:0B3\x8d00<B3\x870730<r2523?074051R360O@=070250<2615442774051513=0A<0=182D64:833<0702112863:A<0=1D8364:0B3>070290<26164:01C:07021162:7029026164:" #(error
-  "compile error: invalid argument list " ". optional arguments must come after required." length=
+  "compile error: invalid argument list " ": optional arguments must come after required." length=
   caar "compile error: invalid optional argument " " in list " #fn(keyword?)
-  ". keyword arguments must come last." "compile error: invalid formal argument ") check-formals)
+  ": keyword arguments must come last." "compile error: invalid formal argument ") check-formals)
 									#fn(map)
 									#fn("6000n10B390700<61:0:" #(keyword->symbol))
 									to-proper) lambda-vars)
binary files a/flisp.boot.builtin b/flisp.boot.builtin differ
--- a/flisp.c
+++ b/flisp.c
@@ -184,18 +184,12 @@
 
 // symbol table ---------------------------------------------------------------
 
-bool
-fl_is_keyword_name(const char *str, size_t len)
-{
-	return (str[0] == ':' || str[len-1] == ':') && str[1] != '\0';
-}
-
 static symbol_t *
 mk_symbol(const char *str, int len, bool copy)
 {
 	symbol_t *sym = MEM_ALLOC(sizeof(*sym) + (copy ? len+1 : 0));
 	sym->numtype = NONNUMERIC;
-	if(fl_is_keyword_name(str, len)){
+	if(str[0] == ':' && str[1] != 0){
 		value_t s = tagptr(sym, TAG_SYM);
 		sym->flags = FLAG_KEYWORD;
 		setc(s, s);
--- a/flisp.h
+++ b/flisp.h
@@ -207,7 +207,6 @@
 value_t fl_cons(value_t a, value_t b);
 value_t fl_list2(value_t a, value_t b);
 value_t fl_listn(size_t n, ...);
-bool fl_is_keyword_name(const char *str, size_t len) fl_purefn fl_hotfn;
 bool fl_isnumber(value_t v) fl_purefn;
 value_t alloc_vector(size_t n, int init);
 
--- a/test/unittest.lsp
+++ b/test/unittest.lsp
@@ -241,22 +241,23 @@
 (assert (equal? ((λ ((x 0) . r) (list x r)) 1 2 3) '(1 (2 3))))
 
 ; keyword arguments
-(assert (keyword? kw:))
+(assert (keyword? :kw))
+(assert (not (keyword? 'kw:)))
 (assert (not (keyword? 'kw)))
 (assert (not (keyword? ':)))
-(assert (equal? ((λ (x (a 2) (b: a) . r) (list x a b r)) 1 0 8 4 5)
+(assert (equal? ((λ (x (a 2) (:b a) . r) (list x a b r)) 1 0 8 4 5)
                 '(1 0 0 (8 4 5))))
-(assert (equal? ((λ (x (a 2) (b: a) . r) (list x a b r)) 0 b: 3 1)
+(assert (equal? ((λ (x (a 2) (:b a) . r) (list x a b r)) 0 :b 3 1)
                 '(0 2 3 (1))))
-(define (keys4 (a: 8) (b: 3) (c: 7) (d: 6)) (list a b c d))
-(assert (equal? (keys4 a: 10) '(10 3 7 6)))
-(assert (equal? (keys4 b: 10) '(8 10 7 6)))
-(assert (equal? (keys4 c: 10) '(8 3 10 6)))
-(assert (equal? (keys4 d: 10) '(8 3 7 10)))
-(assert-fail (keys4 e: 10))   ; unsupported keyword
-(assert-fail (keys4 a: 1 b:)) ; keyword with no argument
-(define (keys1 (a: 8)) (+ a 1))
-(assert (equal? (keys1 a: 11) 12))
+(define (keys4 (:a 8) (:b 3) (:c 7) (:d 6)) (list a b c d))
+(assert (equal? (keys4 :a 10) '(10 3 7 6)))
+(assert (equal? (keys4 :b 10) '(8 10 7 6)))
+(assert (equal? (keys4 :c 10) '(8 3 10 6)))
+(assert (equal? (keys4 :d 10) '(8 3 7 10)))
+(assert-fail (keys4 :e 10))   ; unsupported keyword
+(assert-fail (keys4 :a 1 :b)) ; keyword with no argument
+(define (keys1 (:a 8)) (+ a 1))
+(assert (equal? (keys1 :a 11) 12))
 
 ; cvalues and arrays
 (assert (equal? (typeof "") '(array byte)))