Re: [Chicken-hackers] [PATH] fix for srfi-13 string-trim-right start par

2014-01-24 Thread Evan Hanson
+1, here are Seth's and Mario's patches in order. I think I've picked
the right patches out of the thread... IMHO these are the correct two to
apply, anyway.

Evan
From 2de4f3bda8609bec20c8a55fc6647a2f0b884c1c Mon Sep 17 00:00:00 2001
From: Mario Domenech Goulart 
Date: Sat, 11 Jan 2014 18:11:47 -0200
Subject: [PATCH 1/2] Fix bug in string-index-right and string-skip-right

Patch by David Van Horn to the SRFI-13 mailing list (see
http://srfi.schemers.org/srfi-13/post-mail-archive/msg7.html).
Ported to CHICKEN by Seth Alves (see
http://lists.nongnu.org/archive/html/chicken-hackers/2014-01/msg00022.html).

Signed-off-by: Evan Hanson 
---
 srfi-13.scm |   12 ++--
 tests/srfi-13-tests.scm |   18 ++
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/srfi-13.scm b/srfi-13.scm
index 7b16153..876a2bd 100644
--- a/srfi-13.scm
+++ b/srfi-13.scm
@@ -1208,17 +1208,17 @@
   (let-string-start+end (start end) string-index-right str maybe-start+end
 (cond ((char? criteria)
   (let lp ((i (- end 1)))
-(and (>= i 0)
+(and (>= i start)
  (if (char=? criteria (string-ref str i)) i
  (lp (- i 1))
  ((char-set? criteria)
   (let lp ((i (- end 1)))
-(and (>= i 0)
+(and (>= i start)
  (if (char-set-contains? criteria (string-ref str i)) i
  (lp (- i 1))
  ((procedure? criteria)
   (let lp ((i (- end 1)))
-(and (>= i 0)
+(and (>= i start)
  (if (criteria (string-ref str i)) i
  (lp (- i 1))
  (else (##sys#error 'string-index-right "Second param is neither 
char-set, char, or predicate procedure."
@@ -1250,19 +1250,19 @@
   (let-string-start+end (start end) string-skip-right str maybe-start+end
 (cond ((char? criteria)
   (let lp ((i (- end 1)))
-(and (>= i 0)
+(and (>= i start)
  (if (char=? criteria (string-ref str i))
  (lp (- i 1))
  i
  ((char-set? criteria)
   (let lp ((i (- end 1)))
-(and (>= i 0)
+(and (>= i start)
  (if (char-set-contains? criteria (string-ref str i))
  (lp (- i 1))
  i
  ((procedure? criteria)
   (let lp ((i (- end 1)))
-(and (>= i 0)
+(and (>= i start)
  (if (criteria (string-ref str i)) (lp (- i 1))
  i
  (else (##sys#error 'string-skip-right "CRITERIA param is neither 
char-set or char."
diff --git a/tests/srfi-13-tests.scm b/tests/srfi-13-tests.scm
index 29d6b80..a9735cc 100644
--- a/tests/srfi-13-tests.scm
+++ b/tests/srfi-13-tests.scm
@@ -688,3 +688,21 @@
 (handle-exceptions exn
   (k #f)
   (string=? "abrcaaba" (string-delete char-set:upper-case 
"abrAcaDabRa"))
+
+
+; http://srfi.schemers.org/srfi-13/post-mail-archive/msg7.html
+; From: David Van Horn 
+; Date: Wed, 01 Nov 2006 07:53:34 +0100
+;
+; Both string-index-right and string-skip-right will continue to search
+; left past a given start index.
+;
+;(string-index-right "abbb" #\a 1) ;; => 0, but should be #f
+;(string-skip-right  "abbb" #\b 1) ;; => 0, but should be #f
+;
+; This also causes incorrect results for string-trim-right,
+; string-trim-both and string-tokenize when given a non-zero start
+; argument.
+
+(test "string-index-right" #f (string-index-right "abbb" #\a 1))
+(test "string-skip-right" #f (string-skip-right  "abbb" #\b 1))
-- 
1.7.10.4


From 80cd2075669dd66cb3841ad209ef9e786b6754ec Mon Sep 17 00:00:00 2001
From: Mario Domenech Goulart 
Date: Sun, 19 Jan 2014 20:08:17 -0200
Subject: [PATCH 2/2] srfi-13: fix bug in string-trim-right

The bug in srfi-13's reference implementation was found by Seth Alves,
who also provided the fix (see
http://lists.gnu.org/archive/html/chicken-hackers/2014-01/msg00016.html )

His patch has been amended with some tests.

Signed-off-by: Evan Hanson 
---
 srfi-13.scm |2 +-
 tests/srfi-13-tests.scm |8 
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/srfi-13.scm b/srfi-13.scm
index 876a2bd..65b748f 100644
--- a/srfi-13.scm
+++ b/srfi-13.scm
@@ -1066,7 +1066,7 @@
   (let-optionals* criteria+start+end ((criteria char-set:whitespace) rest)
 (let-string-start+end (start end) string-trim-right s rest
   (cond ((string-skip-right s criteria start end) =>
-(lambda (i) (%substring/shared s 0 (+ 1 i
+(lambda (i) (%substring/shared s start (+ 1 i
(else "")
 
 (define (string-trim-both s . criteria+start+end)
diff --git a/tests/srfi-13-tests.scm b/tests/srfi-13-tests.scm
index a9735cc..1262b82 100644
--- a/tests/srfi-13-tests.scm
+++ b/tests/srfi-13-tests.scm
@@ -706,3 +706,11 

[Chicken-hackers] [PATCH] Add proper list checks to assq/assv/assoc and memq/memv/member

2014-01-24 Thread Moritz Heidkamp
Fellow Chickeneers,

please see the commit message of the attached patch for details!

Cheers
Moritz

>From 16396c41c63699e261f108af4cf48e15eb54bdde Mon Sep 17 00:00:00 2001
From: Moritz Heidkamp 
Date: Tue, 21 Jan 2014 12:20:11 +0100
Subject: [PATCH] Add proper list checks to assq/assv/assoc and
 memq/memv/member

Previously it was possible to pass any kind of value to these procedures
as their list argument and they would just return #f in that case. This
patch adds checks to the checked variants at the end of the loop so it
will only incur additional runtime cost if either a non-list is passed
as the list argument or if the sought element is not found.

Note that this patch has the side-effect of also erroring out on
improper lists in the not-found case. This lead to an error getting
raised in the scrutinizer which is taken care of in this patch, too.

Furthermore, the test cases added for all procedures affected by this
patch uncovered a bug in the specializations defined for assq, assv, and
assoc in types.db which would specialize to the unsafe inlined variant
of assq for any kind of list rather than lists of pairs. This is also
fixed.
---
 runtime.c   | 18 ++
 scrutinizer.scm |  2 +-
 tests/library-tests.scm | 35 +++
 types.db|  6 +++---
 4 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/runtime.c b/runtime.c
index c90b9dd..58dde49 100644
--- a/runtime.c
+++ b/runtime.c
@@ -5518,6 +5518,9 @@ C_regparm C_word C_fcall C_i_assq(C_word x, C_word lst)
 lst = C_u_i_cdr(lst);
   }
 
+  if(lst!=C_SCHEME_END_OF_LIST)
+barf(C_BAD_ARGUMENT_TYPE_ERROR, "assq", lst);
+
   return C_SCHEME_FALSE;
 }
 
@@ -5537,6 +5540,9 @@ C_regparm C_word C_fcall C_i_assv(C_word x, C_word lst)
 lst = C_u_i_cdr(lst);
   }
 
+  if(lst!=C_SCHEME_END_OF_LIST)
+barf(C_BAD_ARGUMENT_TYPE_ERROR, "assv", lst);
+
   return C_SCHEME_FALSE;
 }
 
@@ -5556,6 +5562,9 @@ C_regparm C_word C_fcall C_i_assoc(C_word x, C_word lst)
 lst = C_u_i_cdr(lst);
   }
 
+  if(lst!=C_SCHEME_END_OF_LIST)
+barf(C_BAD_ARGUMENT_TYPE_ERROR, "assoc", lst);
+
   return C_SCHEME_FALSE;
 }
 
@@ -5567,6 +5576,9 @@ C_regparm C_word C_fcall C_i_memq(C_word x, C_word lst)
 else lst = C_u_i_cdr(lst);
   }
 
+  if(lst!=C_SCHEME_END_OF_LIST)
+barf(C_BAD_ARGUMENT_TYPE_ERROR, "memq", lst);
+
   return C_SCHEME_FALSE;
 }
 
@@ -5589,6 +5601,9 @@ C_regparm C_word C_fcall C_i_memv(C_word x, C_word lst)
 else lst = C_u_i_cdr(lst);
   }
 
+  if(lst!=C_SCHEME_END_OF_LIST)
+barf(C_BAD_ARGUMENT_TYPE_ERROR, "memv", lst);
+
   return C_SCHEME_FALSE;
 }
 
@@ -5599,6 +5614,9 @@ C_regparm C_word C_fcall C_i_member(C_word x, C_word lst)
 if(C_equalp(C_u_i_car(lst), x)) return lst;
 else lst = C_u_i_cdr(lst);
   }
+
+  if(lst!=C_SCHEME_END_OF_LIST)
+barf(C_BAD_ARGUMENT_TYPE_ERROR, "member", lst);
   
   return C_SCHEME_FALSE;
 }
diff --git a/scrutinizer.scm b/scrutinizer.scm
index 020949d..e29e847 100644
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -2029,7 +2029,7 @@
 		  t))
 	((eq? 'deprecated (car t))
 	 (and (= 2 (length t)) (symbol? (second t)) t))
-	((or (memq '--> t) (memq '-> t)) =>
+	((and (list? t) (or (memq '--> t) (memq '-> t))) =>
 	 (lambda (p)
 	   (let* ((cleanf (eq? '--> (car p)))
 		  (ok (or (not rec) (not cleanf
diff --git a/tests/library-tests.scm b/tests/library-tests.scm
index 5418fbb..df0639f 100644
--- a/tests/library-tests.scm
+++ b/tests/library-tests.scm
@@ -541,3 +541,38 @@ A
 (assert (equal? '#(2 3) (subvector '#(1 2 3) 1)))
 (assert (equal? '#(2)   (subvector '#(1 2 3) 1 2)))
 (assert (equal? '#()(subvector '#(1 2 3) 1 1)))
+
+;;; alist accessors
+
+(assert (equal? '(foo) (assq 'foo '((foo)
+(assert (not (assq 'foo '(
+(assert-fail (assq 'foo '(bar)))
+(assert-fail (assq 'foo 'bar))
+
+
+(assert (equal? '(foo) (assv 'foo '((foo)
+(assert (not (assv 'foo '(
+(assert-fail (assv 'foo '(bar)))
+(assert-fail (assv 'foo 'bar))
+
+(assert (equal? '("foo") (assoc "foo" '(("foo")
+(assert (not (assoc "foo" '(
+(assert-fail (assoc "foo" '("bar")))
+(assert-fail (assoc "foo" "bar"))
+
+;;; list membership
+
+(assert (equal? '(foo) (memq 'foo '(bar foo
+(assert (not (memq 'foo '(bar
+(assert (not (memq 'foo '(
+(assert-fail (memq 'foo 'foo))
+
+(assert (equal? '(foo) (memv 'foo '(bar foo
+(assert (not (memv 'foo '(bar
+(assert (not (memv 'foo '(
+(assert-fail (memv 'foo 'foo))
+
+(assert (equal? '("foo") (member "foo" '("bar" "foo"
+(assert (not (member "foo" '("bar"
+(assert (not (member "foo" '(
+(assert-fail (member "foo" "foo"))
diff --git a/types.db b/types.db
index f1d87a3..7156c9b 100644
--- a/types.db
+++ b/types.db
@@ -189,11 +189,11 @@
 
 (assq (forall (a b) (#(procedure #:clean) assq (* (list-of (pair a b)))
 		 (or boolean (pair a b
-  ((* list) (##core#inline "C_u_i_assq" #(1) #(2
+  ((* (list-of pai