Spaces:
Running
Running
(define-module (lang elisp primitives match) | |
#:use-module (lang elisp internals fset) | |
#:use-module (ice-9 regex) | |
#:use-module (ice-9 optargs)) | |
(define last-match #f) | |
(fset 'string-match | |
(lambda (regexp string . start) | |
(define emacs-string-match | |
(if (defined? 'make-emacs-regexp) | |
;; This is what we would do if we had an | |
;; Emacs-compatible regexp primitive, here called | |
;; `make-emacs-regexp'. | |
(lambda (pattern str . args) | |
(let ((rx (make-emacs-regexp pattern)) | |
(start (if (pair? args) (car args) 0))) | |
(regexp-exec rx str start))) | |
;; But we don't have Emacs-compatible regexps, and I | |
;; don't think it's worthwhile at this stage to write | |
;; generic regexp conversion code. So work around the | |
;; discrepancies between Guile/libc and Emacs regexps by | |
;; substituting the regexps that actually occur in the | |
;; elisp code that we want to read. | |
(lambda (pattern str . args) | |
(let loop ((discrepancies '(("^[0-9]+\\.\\([0-9]+\\)" . | |
"^[0-9]+\\.([0-9]+)")))) | |
(or (null? discrepancies) | |
(if (string=? pattern (caar discrepancies)) | |
(set! pattern (cdar discrepancies)) | |
(loop (cdr discrepancies))))) | |
(apply string-match pattern str args)))) | |
(let ((match (apply emacs-string-match regexp string start))) | |
(set! last-match | |
(if match | |
(apply append! | |
(map (lambda (n) | |
(list (match:start match n) | |
(match:end match n))) | |
(iota (match:count match)))) | |
#f))) | |
(if last-match (car last-match) %nil))) | |
(fset 'match-beginning | |
(lambda (subexp) | |
(list-ref last-match (* 2 subexp)))) | |
(fset 'match-end | |
(lambda (subexp) | |
(list-ref last-match (+ (* 2 subexp) 1)))) | |
(fset 'substring substring) | |
(fset 'match-data | |
(lambda* (#:optional integers reuse) | |
last-match)) | |
(fset 'set-match-data | |
(lambda (list) | |
(set! last-match list))) | |
(fset 'store-match-data 'set-match-data) | |