~ 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' operationsTrap