Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SRFI 38 read does not use immutable pairs #877

Open
dpk opened this issue Dec 17, 2022 · 11 comments
Open

SRFI 38 read does not use immutable pairs #877

dpk opened this issue Dec 17, 2022 · 11 comments

Comments

@dpk
Copy link
Contributor

dpk commented Dec 17, 2022

chibi-scheme/sexp.c

Lines 3336 to 3338 in e93b719

if (sexp_port_sourcep(in))
for (tmp=res; sexp_pairp(tmp); tmp=sexp_cdr(tmp))
sexp_immutablep(tmp) = 1;

I see that there are circumstances in which literal pairs become immutable, but I can’t work out when. Specifically, nothing I can think of like this works as expected at the REPL:

> (define mypair '(1 . 2))
> mypair
(1 . 2)
> (set-car! mypair 2)
;; expected: error because mypair is a literal
;; actual: works:
> mypair
(2 . 2)

This includes changing the definition of mypair to any combination of read with a port (even having done an explicit port-source?-set! to #t on that port).

I’m trying to implement an optimization of immutable lists in Chibi and am very confused by this.

@ashinn
Copy link
Owner

ashinn commented Dec 17, 2022

I can't reproduce this - I consistently get an error calling set-car! on a literal:

> (define mypair '(1 . 2))
> mypair
(1 . 2)
> (set-car! mypair 2)
ERROR on line 3: set-car!: immutable pair: (1 . 2)

@dpk
Copy link
Contributor Author

dpk commented Dec 18, 2022

Ahhhh, it’s immutable for me only if chibi-scheme is started without -R. The ‘smart’ REPL with line editing causes literals to be mutable. Can you confirm?

@dpk dpk changed the title Under what circumstances does Chibi enforce immutability of literals (especially pairs)? Literals sometimes mutable Dec 18, 2022
@ashinn ashinn changed the title Literals sometimes mutable SRFI 38 read does not use immutable pairs Dec 18, 2022
@ashinn
Copy link
Owner

ashinn commented Dec 18, 2022

This is the SRFI 38 implementation. It's a little tedious to fix, in part because it's fully portable, and in part because it actually needs to use set-c*r! to support shared structures.

@mnieper
Copy link
Collaborator

mnieper commented Dec 18, 2022

What about a procedure (immutable <datum>) that maps a datum into an immutable version of it? The SRFI 38 implementation could then use this.

@ashinn
Copy link
Owner

ashinn commented Dec 19, 2022

Sure, we could add that. Since it has to duplicate the shared structure detection of SRFI 38 it would be more work, but at the same time be generally useful.

@APIPLM
Copy link

APIPLM commented Dec 21, 2022

set-car! procedure is part of the scheme module, and as well for the portable code is nature.
SRFI-38 is like a custom reader for the circle list, more generically for a shared structure. which is a special implementation.
REPL should be between both them. Sound like we can not embed SRFI-38 into REPL directly.

@ashinn
Copy link
Owner

ashinn commented Dec 21, 2022

I'm not sure I follow. Are you suggesting a circular dependency? This doesn't really apply since the repl itself is not part of the standard. The SRFI 38 read/ss is imported and reexported as read by (scheme read), which imports (scheme base) containing set-car!.

@APIPLM
Copy link

APIPLM commented Dec 21, 2022

I have not had a suggestion yet. I mean from code portable point view, there are no issue at all. In REPL, read/ss and write/ss can read and write the shared structure from a port. and read/ss and write/ss are imported and reexported to(scheme base)for the user script after it import srfi-38 implementation. But from the system point view, without srfi-38. the shared structure, such like circle list still in the scheme as well. I mean we need to have a way to serialize the circle list ,which is a shared structure like the literal representation for it without srfi-38. Because Chibi live in the C language implementation sexp-reader as well, I supposed that the shared structure like circle list is a part of the standard scheme

@dpk
Copy link
Contributor Author

dpk commented Mar 8, 2023

Could fixing this be an opportunity to generally clean up the situation around reading and reader/writer extensions in Chibi?

At the moment there are at least three implementations of a reader for S-expressions in the Chibi libraries, two of which have corresponding writers: one reader/writer in C in sexp.c, one reader/writer in Scheme in the SRFI 38 implementation, and a third reader in Scheme in the (chibi scribble) library.

Could an approach comparable to the readtables of Common Lisp or Racket be used, so that e.g. (chibi scribble) can simply extend an existing reader for the bits where it has to read an S-expression, instead of implementing one from scratch?

@ashinn
Copy link
Owner

ashinn commented Mar 9, 2023

Chibi is intentionally built in layers. The C reader/writer is fast and simple and handles all standard syntax but only reads, not writes, shared structures.

The Scheme reader is actually the fully portable (srfi 38) implementation, adding support for shared structures. It relies on the underlying read from (chibi) for non-structural data. There's not much duplicate logic and it's building on the core so I think this is a good split.

The Scribble reader is a <100 line implementation of a subset of Scheme, which allows interleaving Scribble code in with Scheme. I don't remember why it doesn't use (scheme read) which would allow making it smaller and improving the supported syntax. It's so small I don't worry about it much.

A possible factoring would be a (chibi read) module, optionally layered on (chibi)'s read, with a customizable read table. (srfi 38) and (chibi scribble) could then be customized versions of this. Personally I've had no need to customize the reader table (I actually prefer keeping everything portable) so it's not been a high priority.

@dpk
Copy link
Contributor Author

dpk commented Mar 11, 2023

The Scribble reader is a <100 line implementation of a subset of Scheme, which allows interleaving Scribble code in with Scheme. I don't remember why it doesn't use (scheme read) which would allow making it smaller and improving the supported syntax. It's so small I don't worry about it much.

Scribble syntax allows @-expressions to be embedded in S-expressions and vice versa: @command{this is some text, and @(this is an s expression @with{some text inside it})}. (Substitute \ for @ for the Chibi version of Scribble as appropriate.) In other words, at least for Racket-style Scribble syntax, there has to be an entry point from the regular Scheme reader into the @-expression reader as well as the @-expression reader being able to read normal Scheme expressions.

A possible factoring would be a (chibi read) module, optionally layered on (chibi)'s read, with a customizable read table. (srfi 38) and (chibi scribble) could then be customized versions of this. Personally I've had no need to customize the reader table (I actually prefer keeping everything portable) so it's not been a high priority.

One inconsistency I just noticed which would be evened out by the universal use of character-based dispatch tables: the basic read in (chibi) supports R6RS-style bytevector literals; the SRFI 38 implementation used by the REPL with line-editing doesn’t.

But I appreciate this would be a big change so I’m happy to drop it for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants