unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Philip McGrath <philip@philipmcgrath.com>
To: guile-devel@gnu.org
Cc: "Marc Nieper-Wißkirchen" <marc@nieper-wisskirchen.de>
Subject: Re: [PATCH] add language/wisp to Guile?
Date: Sun, 26 Feb 2023 18:22:39 -0500	[thread overview]
Message-ID: <3517394.V25eIC5XRa@bastet> (raw)
In-Reply-To: <CAEYrNrSa+U4ZCwa5G_vkR1WJH17H_-QBcnPnOrM7FafjP7gJPQ@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 8726 bytes --]

Hi,

On Sunday, February 26, 2023 6:02:04 AM EST Marc Nieper-Wißkirchen wrote:
> Am So., 26. Feb. 2023 um 08:46 Uhr schrieb <guile-devel-request@gnu.org>:
> > Message: 1
> > Date: Sun, 26 Feb 2023 02:45:12 -0500
> > From: "Philip McGrath" <philip@philipmcgrath.com>
> > To: "Maxime Devos" <maximedevos@telenet.be>, Ludovic Courtès
> > 
> >         <ludo@gnu.org>, "Matt Wette" <matt.wette@gmail.com>,
> >         guile-devel@gnu.org
> > 
> > Cc: "Christine Lemmer-Webber" <cwebber@dustycloud.org>
> > Subject: Re: [PATCH] add language/wisp to Guile?
> > Message-ID: <981b0e74-96c0-4430-b693-7fc8026e3ead@app.fastmail.com>
> > Content-Type: text/plain;charset=utf-8
> 
> [...]
> 
> I would like to make two remarks, which I think are essential to get
> the semantics right.
> 
> The R6RS comments of the form "#!r6rs" are defined to modify the
> lexical syntax of the reader; possibly, they don't change the language
> semantics (after reading).  In particular, "#!r6rs" also applies to
> data files but does not affect the interpretation of the data after it
> is read. It cannot because the reader otherwise ignores and does not
> report comments.
> 
> Thus a comment of the form "#!r6rs" may be suitable for Wisp, but it
> is not a substitute for Racket's "#lang" (or a similar mechanism).
> Guile shouldn't confuse these two different levels of meaning.
> 

I agree that it's important to distinguish between lexical syntax (`read`) and 
the semantics of what is read.

However, Racket's `#lang` in fact operates entirely at the level of `read`. 
(Racketeers contribute to confusion on this point by using `#lang` as a 
shorthand for Racket's entire language-creation infrastructure, when in fact 
`#lang` specifically has a fairly small, though important, role.) When `read` 
encounters `#lang something`, it looks up a reader extension procedure in the 
module indicated by `something` and uses that procedure to continue parsing 
the input stream into data. Importantly, while syntax objects may be used to 
attach source location information, there is no "lexical context" or binding 
information at this stage, as one familiar with syntax objects from macro 
writing might expect: those semantics come after `read` has finished parsing 
the input stream from bytes to values.

Nonetheless, because the reader extension procedure has complete control over 
what data is read, a `#lang` language's reader can produce data with the 
semantics the language's author intends.

Before I go on to give some examples, I would note that of course R6RS gives 
implementations great freedom in how they use `#!implementation-specific` to 
extend the lexical syntax, and some ways that some implementations use it 
would be awkward at best to express by treating `#!` as an alternate spelling 
for `#lang `: Chez Scheme's `#!base-rtd` and `#!bwp` come to mind in that 
category. 

Now some examples, where `with-module-reading-parameterization` configures 
`read` to the right state for reading a module. (When reading generic data, 
reader extension procedures are turned off by default.)

```
philip@bastet:~$ racket 
Welcome to Racket v8.8 [cs].
-> (require syntax/modread)
-> (define (read-module str)              
     (with-module-reading-parameterization
       (lambda ()                         
         (read (open-input-string str)))))
-> (read-module "#lang racket (eqv? 1.5 (/ 3 2))")
'(module anonymous-module racket (#%module-begin (eqv? 1.5 (/ 3 2))))
-> (read-module "#lang exact-decimal racket (eqv? 1.5 (/ 3 2))")
'(module anonymous-module racket (#%module-begin (eqv? 3/2 (/ 3 2))))
```

Here the `exact-decimal` meta-language parameterizes the call to the base 
language's reader, changing lexical syntax like "1.5" to be read as an exact 
number instead of an inexact number. Chez Scheme's `#!fold-case` and `#!no-
fold-case` directives are somewhat similar in spirit.

Most Racket `#lang` languages are more like this example:

```
-> (read-module "#lang racket (lambda (x) (+ 1 x))")
'(module anonymous-module racket (#%module-begin (lambda (x) (+ 1 x))))
-> (read-module "#lang typed/racket (lambda (x) (+ 1 x))")
'(module anonymous-module typed/racket (#%module-begin (lambda (x) (+ 1 x))))
```

Here, the lexical syntax is the same: the only difference is whether the 
resulting `module` form has `racket` or `typed/racket` as its "initial import" 
or "language". However, the semantics are starkly different: the `#lang racket` 
example is a perfectly good program, but attempting to macro-expand the `#lang 
typed/racket` program fails with the following error:

```
Type Checker: type mismatch
  expected: Number
  given: Any in: x
```

Much of the power of Racket's language infrastructure comes from the each 
`module` form specifying its "language"/"initial import", which dates from 
"Composable and Compilable Macros: You Want it When?" (ICFP 2002) [1], long 
before the addition of `#lang`. You can write a `module` form explicitly, 
without using a `#lang`-based reader extension.

Doing this sort of thing is less elegant and convenient with R6RS `library` 
forms, but it's certainly possible to produce an R6RS library form where 
`lambda` and `+` have semantics different than the versions exported from the 
`(rnrs)` library.

For a variation on the theme, consider:

```
-> (read-module "#lang web-server
    (require racket/serialize)
    (serialize (λ (x) x))")
'(module anonymous-module web-server/lang
   (#%module-begin (require racket/serialize) (serialize (λ (x) x))))
```

First, note that the resulting datum refers to `web-server/lang`, not `web-
server`: in this particular case, the mismatch is a historical accident that 
confused me once (so I remember it), but it does illustrate how `#lang` 
maintains the distinction between the reader and the expander.

The example also illustrates semantic change. The `#%module-begin` form from 
the web server language performs a whole-module transformation on its subforms 
to make continuations serializable, thus producing "Automatically RESTful Web 
Applications" [2]. Likewise, it's `lambda` form, unlike the version from 
`racket/base`, creates serializable closures.

Finally, here's a more dramatic example:

```
-> (define (read-module* str)
     (with-module-reading-parameterization
       (lambda ()
         ;; avoid a bug
         (syntax->datum (read-syntax #f (open-input-string str))))))
-> (read-module* "#lang datalog
   parent(creusa, ascanius).  
   parent(anchises, aeneas).
   parent(aeneas, ascanius).
   parent(hecuba, creusa).  
   parent(priam, creusa). 
   ancestor(A, B) :- parent(A, B).
   ancestor(A, B) :- parent(A, C), ancestor(C, B).
   ancestor(A, ascanius)?")
'(module anonymous-module datalog/sexp/lang
   (#%module-begin
    (! (parent creusa ascanius))
    (! (parent anchises aeneas))
    (! (parent aeneas ascanius))
    (! (parent hecuba creusa))
    (! (parent priam creusa))
    (! (:- (ancestor A B) (parent A B)))
    (! (:- (ancestor A B) (parent A C) (ancestor C B)))
    (? (ancestor A ascanius))))
```

Even when `#lang` is working at the fullest extent of its powers, its job is 
merely to `read` the input byte stream and produce an S-expression.

> The second comment concerns the shebang line in R6RS scripts (as
> described in the non-normative appendices).  The shebang line is not a
> comment in the R6RS lexical syntax; it does not even reach the reader
> - at least, conceptionally.  The Scheme reader only sees the lines
> following the shebang line.
> 
> For example, a conforming R6RS implementation must raise an exception
> when trying to read (using get-datum, for example) a file that begins
> with a shebang line.
> 
> Thus, the shebang line doesn't need to be considered when discussing
> comment formats in lexical syntax.
> 

This is a very persuasive account of the R6RS appendices. I just find the 
approach somewhat unsatisfying. An R6RS implementation with script support 
must have a procedure `not-quite-read` that handles a potential shebang line 
before calling `read`. I wish this `not-quite-read` procedure were made 
available from some Scheme library (and perhaps somewhat more explicitly 
specified), and I'd probably find it most beautiful for this `not-quite-read` to 
be unified with `read`. But that's not really relevant per se.

> 
> Best,
> 
> Marc

Thank you for these thought-provoking remarks!

Philip

[1]: https://www-old.cs.utah.edu/plt/publications/macromod.pdf
[2]: https://jeapostrophe.github.io/home/static/icfp065-mccarthy.pdf

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2023-02-26 23:22 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <mailman.886.1677397547.13386.guile-devel@gnu.org>
2023-02-26 11:02 ` [PATCH] add language/wisp to Guile? Marc Nieper-Wißkirchen
2023-02-26 23:22   ` Philip McGrath [this message]
2023-02-27  5:00     ` Dr. Arne Babenhauserheide
2023-02-27  7:26     ` Marc Nieper-Wißkirchen
2023-02-28  4:27       ` Philip McGrath
2023-02-28  6:57         ` Marc Nieper-Wißkirchen
2023-02-03 21:26 Dr. Arne Babenhauserheide
2023-02-04 15:08 ` Maxime Devos
2023-02-04 15:46   ` Dr. Arne Babenhauserheide
2023-02-04 19:09     ` Maxime Devos
2023-02-04 21:35       ` Dr. Arne Babenhauserheide
2023-02-05 15:08         ` Maxime Devos
2023-02-14  8:32           ` Dr. Arne Babenhauserheide
2023-02-14 21:24             ` Dr. Arne Babenhauserheide
2023-02-14 23:01               ` Maxime Devos
2023-02-15  1:46                 ` Matt Wette
2023-02-16 21:38                   ` Dr. Arne Babenhauserheide
2023-02-17  1:26                     ` Matt Wette
2023-02-23 11:36                       ` Ludovic Courtès
2023-02-23 17:48                         ` Dr. Arne Babenhauserheide
2023-02-23 18:42                         ` Maxime Devos
2023-02-24 15:45                           ` Ludovic Courtès
2023-02-24 16:34                             ` Dr. Arne Babenhauserheide
2023-03-08 10:34                               ` Dr. Arne Babenhauserheide
2023-02-24 23:48                             ` Maxime Devos
2023-02-24 23:51                               ` Maxime Devos
2023-02-25  0:15                                 ` Matt Wette
2023-02-25 10:42                                   ` Maxime Devos
2023-02-17 23:06                     ` Maxime Devos
2023-02-18  3:50                       ` Philip McGrath
2023-02-18 15:58                         ` Maxime Devos
2023-02-18 19:56                           ` Matt Wette
2023-02-21 12:09                             ` Dr. Arne Babenhauserheide
2023-02-26  7:45                           ` Philip McGrath
2023-02-26 15:42                             ` Maxime Devos
2023-02-26 16:14                               ` Dr. Arne Babenhauserheide
2023-02-26 17:58                               ` Matt Wette
2023-02-26 18:03                                 ` Dr. Arne Babenhauserheide
2023-02-26 18:20                                   ` Matt Wette
2023-02-26 21:39                                     ` Dr. Arne Babenhauserheide
2023-10-02 14:59                             ` Christine Lemmer-Webber
2023-02-23  7:59                         ` Maxime Devos
2023-02-23  8:51                           ` Dr. Arne Babenhauserheide
2023-02-23 18:04                             ` Maxime Devos
2023-02-23 18:22                               ` Maxime Devos
2023-02-23 18:36                               ` Maxime Devos
2023-02-23 18:37                               ` Maxime Devos
2023-02-15  8:36                 ` Dr. Arne Babenhauserheide
2023-02-15 20:13                   ` Maxime Devos
2023-02-16  7:01                     ` Dr. Arne Babenhauserheide
2023-02-16  8:03   ` Dr. Arne Babenhauserheide
2023-02-16 11:30     ` Maxime Devos
2023-02-16 21:35       ` Dr. Arne Babenhauserheide
2023-09-30 13:17 ` Christine Lemmer-Webber
2023-09-30 20:09   ` Maxime Devos
2023-10-02 14:48     ` Christine Lemmer-Webber

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3517394.V25eIC5XRa@bastet \
    --to=philip@philipmcgrath.com \
    --cc=guile-devel@gnu.org \
    --cc=marc@nieper-wisskirchen.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).