How to make DrRacket interactions window use the same reader as the definitions window?

162 views
Skip to first unread message

Thomas Dickerson

unread,
May 27, 2020, 2:01:26 PM5/27/20
to Racket Users
I'm working on #lang with a custom reader (via read-table extension), that among other things, defines custom syntax for duodecimal numbers.

My reader is working great in the definitions window / when I hut "Run" in DrRacket, and the top of the interaction window shows the name of my #lang, but my custom literal syntax is being read as an (undefined) identifier.

Any thoughts on what I'm missing?

Thanks!

Thomas Dickerson

unread,
May 29, 2020, 10:35:03 AM5/29/20
to Racket Users
On an apparently related note:

I have modified Racket to allow parameterized control over how numbers are written/printed/displayed ( cf. https://github.com/racket/racket/pull/3222 ).
This works fine from command-line racket, but DrRacket (installed using `raco pkg install -i drracket` of my modified racket) is merrily doing its own thing and printing numbers without invoking my parameterized routine.

It doesn't appear to be a case of DrRacket using a separate binary, because I can still read and set the parameter, it just has no effect.

Thoughts?

Matthew Flatt

unread,
May 29, 2020, 11:29:38 AM5/29/20
to Thomas Dickerson, Racket Users
DrRacket uses `pretty-print`, which will print numbers using
`number->string`, and so (I think) won't go through your parameter.

I think there may be problems with parametering the core printer,
partly because printing is is sometimes used where `read` is supposed
to work on the result, but I think there may be other issues and I
haven't thought through them enough.

Just to make sure, does using the pretty printer and its hooks
(especially `pretty-print-print-hook`) work for your goals?
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/6f260d7e-68e0-454c-9d81-04d74cb7
> 8b9a%40googlegroups.com.

Thomas Dickerson

unread,
May 29, 2020, 12:25:58 PM5/29/20
to Racket Users


On Friday, May 29, 2020 at 11:29:38 AM UTC-4, Matthew Flatt wrote:
DrRacket uses `pretty-print`, which will print numbers using
`number->string`, and so (I think) won't go through your parameter.

This sounds like a good lead - curious if this also applies to `write` and `display` as well?
I was having trouble with all three.
 
I think there may be problems with parametering the core printer,
partly because printing is is sometimes used where `read` is supposed
to work on the result, but I think there may be other issues and I
haven't thought through them enough.

The intended use is in a setting where `read` has already been extended (cf. my original question in this thread, which is that the DrRacket interactions window appears to ignore any `read` extensions provided by a #lang)
 
Just to make sure, does using the pretty printer and its hooks
(especially `pretty-print-print-hook`) work for your goals?

It sounds like that may be useful for fixing this particular issue with DrRacket, but I don't think it will meet my goals for the overall project.
One question - to what extent are pretty-print-print-hooks expected to cooperate with the current value of that parameter when printing compound or recursive values?
It would be great to install a hook that delegates to the existing hook for everything but numbers, but that approach not working with port-print-handler et al. is what led me to parameterizing over all of print et al.

For example, if for some reason I want numbers to be printed as Roman numerals, I don't want to reimplement printing lists for `(print '(7))` to result in `'(VII)`

Thomas Dickerson

unread,
May 29, 2020, 4:24:18 PM5/29/20
to Racket Users
Quick follow-up:
It looks like I may somehow be able to change DrRacket's printing and reading behavior on a per-language basis somehow using the classes here https://docs.racket-lang.org/tools/drracket_language.html?q=drracket%3Alanguage%3Asimple-settings-printing-style but the documentation on actually doing anything with it is quite sparse (I only found it by searching "pretty-print-print-hook" on the DrRacket GitHub repo and reading backward).

My #lang currently has:
- a `main.rkt`
- a `lang/reader.rkt` using `#lang s-exp syntax/module-reader` with `#:read`, `#:read-syntax`, and `#:info` set.

As far as I can tell, `get-info` is never actually queried for the sorts of configuration which is relevant here, and the "support for #lang-based languages" page doesn't mention any other mechanisms for providing more configuration.
The "Adding module-based languages to DrRacket" begins with a paragraph that looks like it was chopped out of other documentation and is missing a bunch of context:
For backwards compatibility, DrRacket also supports and info.rkt file-based method for specifying such languages. Include these definitions:
(the listed definitions all mention "drscheme").

The most promising paragraph is here:

With some additional work, any language that can be compiled to Racket is supported by the tools interface, not just those that use standard configurations and module.

Each language is a class that implement the drracket:language:language<%> interface. DrRacket also provides two simpler interfaces: drracket:language:module-based-language<%> and drracket:language:simple-module-based-language<%>, and mixins drracket:language:simple-module-based-language->module-based-language-mixin and drracket:language:module-based-language->language-mixin that build implementations of drracket:language:language<%>s from these simpler interfaces.

Once you have an implementation of the drracket:language:language<%> interface, call drracket:language-configuration:add-language to add the language to DrRacket.

Each language comes with its own type, called settings. This can be any type the language designer chooses, but to aid documentation, we call it settings here. The settings type is expected to contain parameters of the language, such as case sensitivity, etc. The implementor of the language provides a GUI so the user can configure the settings and all of the language’s operations accept a setting. DrRacket maintains the current settings for each language.


But it doesn't actually say where any of the relevant code is supposed to go.


Any guidance from someone who knows their way around these systems (as they relate to my queries above) would be immensely helpful (and should probably also just be added to the documentation pages).

Jens Axel Søgaard

unread,
May 29, 2020, 4:51:25 PM5/29/20
to Thomas Dickerson, Racket Users
There may be other solutions, but one way to control the evaluation of expressions entered in the REPL
is to provide an   #%top-interaction, which sets the appropriate parameters.

/Jens Axel

Thomas Dickerson

unread,
May 29, 2020, 5:06:32 PM5/29/20
to Jens Axel Søgaard, Racket Users
Jens -

Interesting - does the default #%top-interaction behave differently from #%module-begin w.r.t. to a #lang's read?
Right now my main.rkt is providing the standard #%module-begin, #%top-interaction, #%app, #%datum, and #%top, in addition to my language's functions + macros.

Thanks!

Matthew Flatt

unread,
Jun 3, 2020, 2:17:05 PM6/3/20
to Thomas Dickerson, Racket Users
At Fri, 29 May 2020 09:25:58 -0700 (PDT), Thomas Dickerson wrote:
> On Friday, May 29, 2020 at 11:29:38 AM UTC-4, Matthew Flatt wrote:
> > DrRacket uses `pretty-print`, which will print numbers using
> > `number->string`, and so (I think) won't go through your parameter.
>
> This sounds like a good lead - curious if this also applies to
> `write` and `display` as well? I was having trouble with all three.

The pretty print hooks apply only to `pretty-print`, `pretty-write`,
and `pretty-display`. They may be most useful when implementing a
printer by calling `pretty-print`, etc., instead of setting the hooks
globally and expecting that pretty-print` is used.

> > I think there may be problems with parametering the core printer,
> > partly because printing is is sometimes used where `read` is supposed
> > to work on the result, but I think there may be other issues and I
> > haven't thought through them enough.
> >
>
> The intended use is in a setting where `read` has already been extended
> (cf. my original question in this thread, which is that the DrRacket
> interactions window appears to ignore any `read` extensions provided by a
> #lang)

It's possible to globally extend `read` via a readtable, but there's
also `call-with-default-reading-parameterization`, which various
libraries use to make sure they have the default reader settings (e.g.,
when reading a preferences file). There's not currently anything that
libraries can use like `call-with-default-writing-parameterization`,
which means that globally changing `write` could break libraries.

Meanwhile, it's possible to change the `print` function more globally
through `global-port-print-handler`.

Finally, there's `display`. I think `display` in principle should be
more configurable, because it's meant to about how things are displayed
for humans to read.

These different approaches, with a relatively flexible reader and and a
relatively inflexible writer, evolved as a result of various pressures.
I think the write side is a little closer to right idea with its
distinction between `write` for serialization, `print` for displaying
values, and `display` for showing things for humans. (On the read,
side, we could have done better by making a cleaner separation between
`read` and `read-syntax`. Still, it's complicated.)

I think a variant of your PR that just affects `display` may be ok, and
it would be worth exploring if that solves a problem. Given that
`print` and `display` seem safely configurable, the question is whether
you want to modify `write` just because that's a third printing
function or because it's important in your target use.

If, for example, your language wants to provide a `write` that isn't
the Racket serialization write, it can always provide a different
function as `write`. That won't affect other libraries that may be
called by programs in your language, but my point is that it generally
shouldn't; those libraries should be using `write` for
serialization-type purposes.

At Fri, 29 May 2020 13:24:17 -0700 (PDT), Thomas Dickerson wrote:
> Quick follow-up:
> It looks like I may somehow be able to change DrRacket's printing and
> reading behavior on a per-language basis somehow using the classes here

I don't think you want that layer of tools. At the DrRacket layer, you
want to stay in the `#lang` world --- so, don't do anything
DrRacket-specific.

At the level of the `#lang`/module system, a language can parameterize
run-time functionality, such as the reader and printer, through a
`configure-runtime` submodule. See

https://docs.racket-lang.org/guide/module-runtime-config.html

and

https://docs.racket-lang.org/reference/running-sa.html#%28part._configure-runtime%29

So, that's the place where you'd update the reader, printer, and
displayer.

> One question - to what extent are pretty-print-print-hooks expected to
> cooperate with the current value of that parameter when printing compound
> or recursive values?
> It would be great to install a hook that delegates to the existing hook for
> everything but numbers, but that approach not working with
> port-print-handler et al. is what led me to parameterizing over all of
> print et al.

From a language implementation perspective where you're setting the
global print handler to use `pretty-print`, your language gets to set
the starting point, and libraries as used by programs in your language
can cooperate with it by extending (instead of replacing) the printer.

So, I think you'd want to make the language use `pretty-print` and
recur as needed (which is not at all for just changing numbers) to
allow library-based extensions.

At Fri, 29 May 2020 17:06:14 -0400, Thomas Dickerson wrote:
> Interesting - does the default #%top-interaction behave differently from
> #%module-begin w.r.t. to a #lang's read?
> Right now my main.rkt is providing the standard #%module-begin,
> #%top-interaction, #%app, #%datum, and #%top, in addition to my language's
> functions + macros.

Yes, those are at the macro layer, and they don't have anything to do
with the reader. (Although it may be possible to make
`#%top-interaction` have a useful side effect on the printer, it's not
the direction to go.)

Reply all
Reply to author
Forward
0 new messages