~ chicken-core (chicken-5) 5760e2dc26dcc5cc24a3d09b6042e3acfb49251c


commit 5760e2dc26dcc5cc24a3d09b6042e3acfb49251c
Author:     felix <bunny351@gmail.com>
AuthorDate: Mon May 17 11:55:42 2010 +0200
Commit:     felix <bunny351@gmail.com>
CommitDate: Mon May 17 11:55:42 2010 +0200

    cache precompiled regular expressions

diff --git a/regex.scm b/regex.scm
index 3494781c..f0d7783b 100644
--- a/regex.scm
+++ b/regex.scm
@@ -61,6 +61,44 @@
 
 (define-record regexp x)
 
+(define-syntax (build-cache x r c)
+  ;; (build-cache N ARG FAIL) 
+  (let* ((n (cadr x))
+	 (n2 (* n 2))
+	 (arg (caddr x))
+	 (fail (cadddr x))
+	 (%cache (r 'cache))
+	 (%index (r 'index))
+	 (%arg (r 'arg))
+	 (%let (r 'let))
+	 (%let* (r 'let*))
+	 (%if (r 'if))
+	 (%fx+ (r 'fx+))
+	 (%fxmod (r 'fxmod))
+	 (%equal? (r 'equal?))
+	 (%quote (r 'quote))
+	 (%tmp (r 'tmp))
+	 (%begin (r 'begin))
+	 (cache (make-vector (add1 n2) #f)))
+    (vector-set! cache n2 0)
+    `(,%let* ((,%cache (,%quote ,cache))
+	      (,%arg ,arg))
+	     ,(let fold ((i 0))
+		(if (>= i n)
+		    ;; this should be thread-safe: a context-switch can only
+		    ;; happen before this code and in the call to FAIL.
+		    `(,%let ((,%tmp ,fail)
+			     (,%index (##sys#slot ,%cache ,n2)))
+			    (##sys#setslot ,%cache ,%index ,%arg)
+			    (##sys#setslot ,%cache (,%fx+ ,%index 1) ,%tmp)
+			    (##sys#setislot 
+			     ,%cache ,n2
+			     (##core#inline "C_u_fixnum_modulo" (,%fx+ ,%index 2) ,n2))
+			    ,%tmp)
+		    `(,%if (,%equal? (##sys#slot ,%cache ,(* i 2)) ,%arg)
+			   (##sys#slot ,%cache ,(add1 (* i 2)))
+			   ,(fold (add1 i))))))))
+
 (define (regexp pat #!optional caseless extended utf8)
   (if (regexp? pat)
       pat
@@ -77,7 +115,10 @@
 (define (unregexp x)
   (cond ((regexp? x) (regexp-x x))
 	((irregex? x) x)
-	(else (irregex x))))
+	(else
+	 (build-cache
+	  5 x
+	  (irregex x)))))
 
 
 ;;; Basic `regexp' operations
Trap