From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Howard Yeh! Newsgroups: gmane.emacs.bugs Subject: symbol-macrolet clobbers (match-data), bug or feature? Date: Tue, 14 Aug 2007 20:43:11 -0000 Organization: http://groups.google.com Message-ID: <1187124191.406368.291750@x40g2000prg.googlegroups.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: sea.gmane.org 1187160862 16753 80.91.229.12 (15 Aug 2007 06:54:22 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Wed, 15 Aug 2007 06:54:22 +0000 (UTC) To: bug-gnu-emacs@gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed Aug 15 08:54:21 2007 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1ILClp-0005fE-8f for geb-bug-gnu-emacs@m.gmane.org; Wed, 15 Aug 2007 08:54:21 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1ILClo-00061Z-Ta for geb-bug-gnu-emacs@m.gmane.org; Wed, 15 Aug 2007 02:54:20 -0400 Original-Path: shelby.stanford.edu!newsfeed.stanford.edu!postnews.google.com!x40g2000prg.googlegroups.com!not-for-mail Original-Newsgroups: gnu.emacs.bug Original-Lines: 117 Original-NNTP-Posting-Host: 24.81.236.125 Original-X-Trace: posting.google.com 1187124192 9607 127.0.0.1 (14 Aug 2007 20:43:12 GMT) Original-X-Complaints-To: groups-abuse@google.com Original-NNTP-Posting-Date: Tue, 14 Aug 2007 20:43:12 +0000 (UTC) User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.6 (like Gecko) (Kubuntu),gzip(gfe),gzip(gfe) Complaints-To: groups-abuse@google.com Injection-Info: x40g2000prg.googlegroups.com; posting-host=24.81.236.125; posting-account=ps2QrAMAAAA6_jCuRt2JEIpn5Otqf_w0 Original-Xref: shelby.stanford.edu gnu.emacs.bug:43274 X-Mailman-Approved-At: Wed, 15 Aug 2007 02:54:17 -0400 X-BeenThere: bug-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:16362 Archived-At: Hi, I am writing a macro to make match-data more convenient. I can use it to implement the =~ operator. (defmacro* with-match-data ((&key in-string) &rest body) "setup local symbol macros for $0 ... $n for nth submatch. symbol macros <1 ... 0 $0 $1 $2)) ((0 6 0 3 3 6) 0 6 "abcefg" "abc" "efg") ;;;;;;; bug || feature ;;;;;;;;;; It seems that the expansion of `with-match-data' is correct (it works if I evaluate the "macroexpand-all"ed expression). But `symbol- macrolet' changes the match-data when the expression is interpreted. (macroexpand-all '(=~ "\\(abc\\)\\(efg\\)?" "abcefg" (list (match-data) <0 >0 $0 $1 $2))) => (let ((G34784 "abcefg")) (if (string-match "\\(abc\\)\\(efg\\)?" G34784) (progn (let ((G34785 G34784)) (progn (list (match-data) (match-beginning 0) (match-end 0) (match-string 0 G34785) (match-string 1 G34785) (match-string 2 G34785))))))) which is fine (eval (macroexpand-all '(=~ "\\(abc\\)\\(efg\\)?" "abcefg" (list (match-data) <0 >0 $0 $1 $2)))) => ((0 6 0 3 3 6) 0 6 "abcefg" "abc" "efg") but evaluating the expression without first expanding it is not fine (r=~ "\\(abc\\)\\(efg\\)?" "abcefg" (list (match-data) <0 >0 $0 $1 $2)) => ((0 1) 0 1 "a" nil nil) For a workaround, I save the match-data before entering symbol- macrolet, and (set-match-data) before executing the body. ;;;;;; code ;;;;;;;;; (defmacro* with-match-data ((&key in-string) &rest body) (let ((str (gensym)) (md (gensym))) `(let ((,str ,in-string) (,md (match-data))) ;; workaround for the bug ;;(my-debug "before" (match-data)) ;; here match-data is from the previous match. (symbol-macrolet ,(loop for i to 9 append (let ((match (intern (concat "$" (number-to-string i)))) (beg (intern (concat "<" (number-to-string i)))) (end (intern (concat ">" (number-to-string i))))) (list `(,match (match-string ,i ,str)) `(,beg (match-beginning ,i)) `(,end (match-end ,i))))) ;;(my-debug "after" (match-data)) ;; here match-data is something else. (macrolet (($ (i) `(match-string ,i ,',str)) (sub (replacement i &key fixedcase literal-string) `(replace-match ,replacement ,fixedcase ,literal- string ,',str ,i))) (symbol-macrolet (;; no convenient way to support before/after match for buffer search ;;before ;;($b (substring ,str 0 (match-beginning 0))) ;;after ;;($a (substring ,str (match-end 0) (length ,str))) ;;match ($m (match-string 0 ,str)) (foo ,str) ) (set-match-data ,md) ;; workaround to set match-data back to the original data. ,@body)))))) (defmacro* =~ (regex string &rest body) (let ((str (gensym))) `(let ((,str ,string)) (when (string-match ,regex ,str) (with-match-data (:in-string ,str) ,@body)))))