From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: =?UTF-8?Q?Marc_Nieper-Wi=c3=9fkirchen?= Newsgroups: gmane.lisp.guile.devel Subject: Re: Feature request: Expose `ellipsis?' from psyntax.ss Date: Thu, 15 Nov 2018 20:41:09 +0100 Message-ID: <124085ab-2a76-4892-e790-d58b07bcb3fc@nieper-wisskirchen.de> References: <875zwzmq4n.fsf@netris.org> <87pnv6iss7.fsf@netris.org> <87k1leip2i.fsf@netris.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="------------F4245CEE7348835D6CB11F8F" X-Trace: blaine.gmane.org 1542310758 32499 195.159.176.226 (15 Nov 2018 19:39:18 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Thu, 15 Nov 2018 19:39:18 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 To: mhw@netris.org, guile-devel@gnu.org Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Thu Nov 15 20:39:14 2018 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gNNTu-0008Mf-2N for guile-devel@m.gmane.org; Thu, 15 Nov 2018 20:39:14 +0100 Original-Received: from localhost ([::1]:40504 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gNNW0-00062R-El for guile-devel@m.gmane.org; Thu, 15 Nov 2018 14:41:24 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:59684) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gNNVv-00062J-3H for guile-devel@gnu.org; Thu, 15 Nov 2018 14:41:20 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gNNVt-0007YE-EL for guile-devel@gnu.org; Thu, 15 Nov 2018 14:41:19 -0500 Original-Received: from mail-wm1-x334.google.com ([2a00:1450:4864:20::334]:52350) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gNNVp-0007Uf-L0 for guile-devel@gnu.org; Thu, 15 Nov 2018 14:41:15 -0500 Original-Received: by mail-wm1-x334.google.com with SMTP id r11-v6so19901868wmb.2 for ; Thu, 15 Nov 2018 11:41:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:subject:to:references:message-id:date:user-agent :mime-version:in-reply-to:content-language; bh=+VxTikc0vGues+qvipnFf+PPMrzNzAGu5+wjTjxqYWI=; b=tjoOrPRmP8HRrx16nv4XtXry7SA7wLra5Tkd5nnWlSEjj+QKbztl54NPfE8GMc8XfY ZI8X7Hfv6Q4yxSVF3MdBmLWRaHZ1ifyvk7yvtNPYdSIF/p3cU5x50UDex3xxUTKRO8Ga AMZ8vvZhdDZKlAtOWxEk7K69vimkiwpFvl4wBjeLExNMKQQLTPP6GiEBgZC1OBjmZIw0 XcOMhW2XStfvZGLXHjqnUuDomvtDZ3qO/mWe2k1pbMtZOOJWCeDI3Qf6gH2xxYD0Q+sM zJfMDsMe7QGOND0JVlElaYa1w2wt6oeFcDT5zxcbl/ke2gNfJ28AaODf/iEs9jn+WC1q Bcpg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:subject:to:references:message-id :date:user-agent:mime-version:in-reply-to:content-language; bh=+VxTikc0vGues+qvipnFf+PPMrzNzAGu5+wjTjxqYWI=; b=LzZf+gWzD2iP0MafzLVR86NRKD/3Na1AbB/tXNpoWlmgMzQFwWWu3pm5Nard7oEfz7 jnxR/dk0RPt2f2af98ZOenv8WtQK9hTTps3IXrK1GOqF42hom+oLZ6wRdpaKNX2uU+d5 IvGh0SpzC41GXRHfz8buDtijeCM/vTW4HBjbeZpn9K6rEhSQHxZjsjiOJnH4bx2bn/NP msf3tSXVHJ4MLYDww7UsJBomTErrNfh042OLypeiJnJBTz0mWYza+XUx1S64wzS2kw8y B3oDsIGF/KpwjA2KeVwJRNSRqO7lKWAaKk5Xa8guDxADnsgAOPF/As09sFL1WEag7+sK He7w== X-Gm-Message-State: AGRZ1gISFj/mjFGC/bjBv+FggLyKs8pif3p+vGzsUyfQCdjFvvZcrMLT bppbsy67lZh8XJzAC9zfSjSMCqk9jt4= X-Google-Smtp-Source: AJdET5eMGw3vnrB1fd2eVnlET2rtiLBSPjkGyp16zmgW4GG2QYKIZjAsHrvtIKpFnG/9ZXSe4OFsBw== X-Received: by 2002:a1c:6783:: with SMTP id b125-v6mr6097272wmc.147.1542310871409; Thu, 15 Nov 2018 11:41:11 -0800 (PST) Original-Received: from ?IPv6:2a02:810d:340:25f8:8435:626d:d53:9097? ([2a02:810d:340:25f8:8435:626d:d53:9097]) by smtp.gmail.com with ESMTPSA id m69-v6sm25613448wmb.8.2018.11.15.11.41.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 15 Nov 2018 11:41:10 -0800 (PST) In-Reply-To: <87k1leip2i.fsf@netris.org> Content-Language: en-US X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::334 X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.21 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.org@gnu.org Original-Sender: "guile-devel" Xref: news.gmane.org gmane.lisp.guile.devel:19742 Archived-At: This is a multi-part message in MIME format. --------------F4245CEE7348835D6CB11F8F Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Hi Mark, > Let's assume we are writing a macro that reimplements syntax (or some > variation thereof) and which has to check whether identifiers are > ellipses. For example, the following could be given: > > (with-ellipsis e >   (my-syntax a e) > > Now, this could be a result of a macro expansion and e could carry > different marks than with-syntax or my-syntax. This is why I have been > thinking that one also needs the lexical context of my-syntax and not > only the context of e. I don't see what problem would be caused by 'e' carrying different marks than 'my-syntax'. As far as I can tell, in the end, the two instances of 'e' above will effectively be compared to one another using 'bound-identifier=?'.  They must have the same name and the same marks to match.  The marks on 'my-syntax' are irrelevant here. I have been thinking of the scope in which $sc-ellipsis is bound by `with-syntax'. If `my-syntax' is within the scope of `with-ellipsis', the binding of $sc-ellipsis introduced by this `with-syntax' will be relevant; if `my-syntax' is not in the lexical scope of `with-ellipsis', the binding should be irrelevant; thus my thought that we need the lexical information of my-syntax as well. Operationally, when (with-ellipsis e (my-syntax a e)) is expanded, 'e' will be added to the macro expansion environment as the innermost binding of the ellipsis identifier, and then (my-syntax a e) will be expanded within that new expansion environment.  That is the expansion environment that will be consulted by the 'ellipsis-identifier?' predicate to find the current ellipsis identifier, which is compared with its argument (after stripping its anti-mark) using 'bound-identifier=?'. Aha, so maybe I have misunderstood the scope of `with-syntax'. Please consider the following example: (define-syntax foo   (lambda (stx)     (with-ellipsis e       (syntax-case stx ()         ((_ x e) (bar #'(x e))))))) (eval-when (expand)   (define (bar x*)     (syntax-case x* ()       ((x ...) ---)))) I would have thought that the `...' identifier in `bar' is recognized as an ellipsis, but from what you are saying it seems that the binding `with-syntax' is dynamic with respect to macro expansion (like syntax parameters). Is this really what we want? This way, as soon we use `with-ellipsis', we can never call third-party macro transformer helpers (like `bar') because they may rely on the fact that the ellipsis `...' still has its usual meaning. And circumventing the problem with (with-ellipsis e --- (with-ellipsis ... ---)) would also not work because the inner `...' is not `bound-identifier=?' to the the global ellipsis `...'. Therefore I think, we want `with-ellipsis' to be lexically scoped (in the macro transformer code). > Thanks for the explanation. I have been toying with my own > implementation of the syntax-case system. In my implementation the > (shared) lexical environments are part of the wraps (so the > identifiers are in some way self-contained). Interesting.  Are locally-bound macro transformers included in those lexical environments?  If so, how do you implement 'letrec-syntax'? My environments are lists of ribs where each rib corresponds to a lexical frame. Given the form (letrec-syntax ((var init)) body ...) I create a new rib that contains the binding of var to init and add a wrap around each expression in body ... that contains the new rib but no new marks. When the body is examined by the expander, the wraps are gradually pushed down (like in the original description of `syntax-case' by Dybvig and Hieb) so that eventually the environments stored with the identifiers in body gain another rib. > Will ellipsis? also work outside of macros? Say, what would be the > result of the following (run-time) code? > > (with-syntax e >   (ellipsis? #'e) No, this is an error.  Like 'syntax-local-binding', the 'ellipsis-identifier?' predicate must be called within the dynamic extent of a macro transformer call by the macro expander. Is this related to the question above of whether `with-syntax' has lexical or dynamic scope? In the former case I don't see a theoretical reason why it has to be restricted to the dynamic extent of a macro transformer call. > P.S.: By the way, the module (system syntax) and in particular the > procedure syntax-local-binding has already helped me a lot because I > needed to attach extra information to symbols and Guile doesn't (yet) > support Chez's define-property (well, this would be another feature > request). Hmm.  Can you tell me more specifically how you are using 'syntax-local-binding' to accomplish this?  As the Guile manual warns, those interfaces are subject to change in future versions of Guile, and therefore it is best to avoid them where possible. What I have been implementing is a pattern matcher and rewriter as a macro in Guile that works much like syntax-case/syntax. Let's call it my-syntax-case/my-syntax. When `my-syntax' is given a template, it has to check whether an identifier appearing in the template is a "my-"pattern variable or not. For that, `my-syntax-case' introduces (via `let-syntax') lexical bindings of the identifiers that are used as pattern variables. The associated syntax transformer just outputs an error (namely that the pattern variable is used outside of `my-syntax'). However, I also attach a custom property (with `make-object-property`) to this syntax transformer that holds information about the match and the nesting depth of the pattern variable. In order to retrieve this information in `my-syntax', I use `syntax-local-binding' to get hold of the associated syntax transformer. In Chez Scheme, I would have used `define-property' to define my custom property directly on the identifier standing for the pattern variable. I haven't found an equivalent feature in Guile. I don't know how to nicely code my-syntax-case/my-syntax in standard R6RS. Best regards, Marc --------------F4245CEE7348835D6CB11F8F Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8bit
Hi Mark,

> Let's assume we are writing a macro that reimplements syntax (or some
> variation thereof) and which has to check whether identifiers are
> ellipses. For example, the following could be given:
>
> (with-ellipsis e
>   (my-syntax a e)

> Now, this could be a result of a macro expansion and e could carry
> different marks than with-syntax or my-syntax. This is why I have been
> thinking that one also needs the lexical context of my-syntax and not
> only the context of e.

I don't see what problem would be caused by 'e' carrying different marks
than 'my-syntax'.

As far as I can tell, in the end, the two instances of 'e' above will
effectively be compared to one another using 'bound-identifier=?'.  They
must have the same name and the same marks to match.  The marks on
'my-syntax' are irrelevant here.

I have been thinking of the scope in which $sc-ellipsis is bound by `with-syntax'. If `my-syntax' is within the scope of `with-ellipsis', the binding of $sc-ellipsis introduced by this `with-syntax' will be relevant; if `my-syntax' is not in the lexical scope of `with-ellipsis', the binding should be irrelevant; thus my thought that we need the lexical information of my-syntax as well.
 
Operationally, when (with-ellipsis e (my-syntax a e)) is expanded, 'e'
will be added to the macro expansion environment as the innermost
binding of the ellipsis identifier, and then (my-syntax a e) will be
expanded within that new expansion environment.  That is the expansion
environment that will be consulted by the 'ellipsis-identifier?'
predicate to find the current ellipsis identifier, which is compared
with its argument (after stripping its anti-mark) using
'bound-identifier=?'.

Aha, so maybe I have misunderstood the scope of `with-syntax'. Please consider the following example:

(define-syntax foo
  (lambda (stx)
    (with-ellipsis e
      (syntax-case stx ()
        ((_ x e) (bar #'(x e)))))))

(eval-when (expand)
  (define (bar x*)
    (syntax-case x* ()
      ((x ...) ---))))

I would have thought that the `...' identifier in `bar' is recognized as an ellipsis, but from what you are saying it seems that the binding `with-syntax' is dynamic with respect to macro expansion (like syntax parameters). Is this really what we want? This way, as soon we use `with-ellipsis', we can never call third-party macro transformer helpers (like `bar') because they may rely on the fact that the ellipsis `...' still has its usual meaning. And circumventing the problem with (with-ellipsis e --- (with-ellipsis ... ---)) would also not work because the inner `...' is not `bound-identifier=?' to the the global ellipsis `...'.

Therefore I think, we want `with-ellipsis' to be lexically scoped (in the macro transformer code).

> Thanks for the explanation. I have been toying with my own
> implementation of the syntax-case system. In my implementation the
> (shared) lexical environments are part of the wraps (so the
> identifiers are in some way self-contained).

Interesting.  Are locally-bound macro transformers included in those
lexical environments?  If so, how do you implement 'letrec-syntax'?

My environments are lists of ribs where each rib corresponds to a lexical frame. Given the form

(letrec-syntax ((var init)) body ...)

I create a new rib that contains the binding of var to init and add a wrap around each expression in body ... that contains the new rib but no new marks. When the body is examined by the expander, the wraps are gradually pushed down (like in the original description of `syntax-case' by Dybvig and Hieb) so that eventually the environments stored with the identifiers in body gain another rib.
 
> Will ellipsis? also work outside of macros? Say, what would be the
> result of the following (run-time) code?
>
> (with-syntax e
>   (ellipsis? #'e)

No, this is an error.  Like 'syntax-local-binding', the
'ellipsis-identifier?' predicate must be called within the dynamic
extent of a macro transformer call by the macro expander.

Is this related to the question above of whether `with-syntax' has lexical or dynamic scope? In the former case I don't see a theoretical reason why it has to be restricted to the dynamic extent of a macro transformer call.
 
> P.S.: By the way, the module (system syntax) and in particular the
> procedure syntax-local-binding has already helped me a lot because I
> needed to attach extra information to symbols and Guile doesn't (yet)
> support Chez's define-property (well, this would be another feature
> request).

Hmm.  Can you tell me more specifically how you are using
'syntax-local-binding' to accomplish this?  As the Guile manual warns,
those interfaces are subject to change in future versions of Guile, and
therefore it is best to avoid them where possible.

What I have been implementing is a pattern matcher and rewriter as a macro in Guile that works much like syntax-case/syntax. Let's call it my-syntax-case/my-syntax. When `my-syntax' is given a template, it has to check whether an identifier appearing in the template is a "my-"pattern variable or not. For that, `my-syntax-case' introduces (via `let-syntax') lexical bindings of the identifiers that are used as pattern variables. The associated syntax transformer just outputs an error (namely that the pattern variable is used outside of `my-syntax'). However, I also attach a custom property (with `make-object-property`) to this syntax transformer that holds information about the match and the nesting depth of the pattern variable. In order to retrieve this information in `my-syntax', I use `syntax-local-binding' to get hold of the associated syntax transformer.

In Chez Scheme, I would have used `define-property' to define my custom property directly on the identifier standing for the pattern variable. I haven't found an equivalent feature in Guile. I don't know how to nicely code my-syntax-case/my-syntax in standard R6RS.

Best regards,

Marc
--------------F4245CEE7348835D6CB11F8F--