From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Frank Terbeck Newsgroups: gmane.lisp.guile.devel Subject: Recursive Macros generating Definitions Date: Mon, 03 Oct 2022 13:32:59 +0200 Message-ID: <87zgedkuqc.fsf@ft.bewatermyfriend.org> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="27466"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) To: guile-devel@gnu.org Original-X-From: guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org Mon Oct 03 13:34:06 2022 Return-path: Envelope-to: guile-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ofJi1-0006q4-Pg for guile-devel@m.gmane-mx.org; Mon, 03 Oct 2022 13:34:05 +0200 Original-Received: from localhost ([::1]:52354 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ofJi0-0006nP-BF for guile-devel@m.gmane-mx.org; Mon, 03 Oct 2022 07:34:04 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:42926) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ofJh9-0006le-6z for guile-devel@gnu.org; Mon, 03 Oct 2022 07:33:13 -0400 Original-Received: from smtprelay08.ispgateway.de ([134.119.228.98]:59462) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ofJh7-0003PE-I9 for guile-devel@gnu.org; Mon, 03 Oct 2022 07:33:10 -0400 Original-Received: from [62.155.197.123] (helo=jim.voodoo.lan) by smtprelay08.ispgateway.de with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1ofJhF-0001HO-FG for guile-devel@gnu.org; Mon, 03 Oct 2022 13:33:17 +0200 Original-Received: by jim.voodoo.lan (Postfix, from userid 1000) id 8F1A5634A44; Mon, 3 Oct 2022 13:32:59 +0200 (CEST) X-Df-Sender: NDMwNDQ0 Received-SPF: none client-ip=134.119.228.98; envelope-from=ft@bewatermyfriend.org; helo=smtprelay08.ispgateway.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_PASS=-0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org Original-Sender: "guile-devel" Xref: news.gmane.io gmane.lisp.guile.devel:21379 Archived-At: Good day, good people! There might be a bug in recursive macro expansion, at least when the definition of parameters, using (define =E2=80=A6) and similar is involved.= Here is a slightly simplified example. The purpose of this macro is to define a couple of short-hands for a generic encoder/decoder pair of functions. The intention is to call it like this: (generate-shorthands (unsigned-integer twos-complement zig-zag) (32 64 128 256 512)) =E2=80=A6to generate 5*3*2 =3D 30 functions, that call the generic functio= ns with the proper concrete arguments. The macro is implemented recursively to generate all desired combinations. If called like that, this implementation generates names like: varint:sint32-decode-ea351ae5fca3566 This seems to be connected to the recursiveness of the macro. If calling the base case manually (see example at the end to reproduce), the inten- ded name is generated: varint:sint32-decode This happens with guile 3.0.5, 3.0.8 as well as the current git main branch HEAD. It does not seem to happen in 2.0.0. I've bisected this down to: commit de41e56492666801078e73860a358e1c63cbc8c2 Author: Andy Wingo Date: Fri Nov 4 19:34:22 2011 +0100 hygienically rename macro-introduced bindings, reproducibly * module/ice-9/psyntax.scm (chi-top-sequence): Detect bindings to identifiers introduced by macros. In that case, in order to preserve hygiene, uniquify the variable's name, but in a way that is reproduceable (i.e., yields the same uniquified name after a recompile). module/ice-9/psyntax.scm | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) When looking at this, I also saw the following, which might be related if =E2=80=98syntax-rules=E2=80=99 is implemented using =E2=80=98syntax-cas= e=E2=80=99 (I didn't check if this is the case): (define-syntax-rule (foobar n) (define quux n)) ,exp (foobar 23) =E2=86=92 (define quux-ea7bdcf8675f4a4 23) Here's the code, that can be loaded into a REPL and example REPL macro expansion calls to reproduce the issue: (use-modules (ice-9 match)) (define-syntax generate-shorthands (lambda (x) ;; This is a helper that makes a name depending on semantics and width.= It is ;; completely inconsequential to the issue and can be ignored. (define (make-base-name s w) (symbol-append 'varint: (match (syntax->datum s) ('unsigned-integer 'uint) ('twos-complement 'int) ('zig-zag 'sint)) (string->symbol (number->string (syntax->datum w))))) ;; The first two cases of this syntax-case recur on generate-shorthands= , to ;; iterate on the list input to generate all desired combinations. (syntax-case x () ;; (_ LIST-OF-SEMANTICS-SYMBOLS LIST-OF-WIDTH-LITERALS) ((_ (sems ...) (widths ...)) (format #t "# Outer~%") ;; (format #t =E2=80=A6) returns #t, so it = can be ;; called in guard position to get a trace. #'(begin (generate-shorthands sems (widths ...)) ...)) ;; (_ SEMANTICS-SYMBOL LIST-OF-WIDTH-LITERALS) ((_ sem (widths ...)) (and (format #t "# Middle~%") (identifier? #'sem)) #'(begin (generate-shorthands sem widths) ...)) ;; Base case: ;; (_ SEMANTICS-SYMBOL WIDTH-LITERAL) ((_ s w) (and (format #t "# Inner~%") (identifier? #'s) (integer? (syntax->datum #'w))) (let ((base (make-base-name #'s #'w))) (with-syntax ((enc (datum->syntax x (symbol-append base '-encode))) (dec (datum->syntax x (symbol-append base '-decode))= )) #'(begin (define (dec bv) (varint-decode bv w s)) (define (enc n) (varint-encode n w s))))))))) ;; Example expansions: ;; ,exp (generate-shorthands (zig-zag) (32)) ;; # Outer ;; # Middle ;; # Inner ;; (begin (define (varint:sint32-decode-ea351ae5fca3566 bv) (varint-decode = bv 32 zig-zag)) ;; (define (varint:sint32-encode-e47ba11af8c0627 n) (varint-encode = n 32 zig-zag))) ;; ,exp (generate-shorthands zig-zag (32)) ;; # Middle ;; # Inner ;; (begin (define (varint:sint32-decode-ea351ae5fca3566 bv) (varint-decode = bv 32 zig-zag)) ;; (define (varint:sint32-encode-e47ba11af8c0627 n) (varint-encode = n 32 zig-zag))) ;; ,exp (generate-shorthands zig-zag 32) ;; # Inner ;; (begin (define (varint:sint32-decode bv) (varint-decode bv 32 zig-zag)) ;; (define (varint:sint32-encode n) (varint-encode n 32 zig-zag)))