240 lines
8.3 KiB
Org Mode
240 lines
8.3 KiB
Org Mode
#+TITLE: Where next for guile-prescheme?
|
|
|
|
* TODO guile repl integration
|
|
|
|
Currently the "prescheme" language definition is just scheme with a different
|
|
default environment (aka. the "prelude", the stuff that's imported by default).
|
|
|
|
In the Guile REPL you can =,L prescheme= to switch language, but it's not very
|
|
useful because you stay in the guile-user module, which is Guile's default
|
|
environment, not Pre-Scheme's!
|
|
|
|
You can create a Pre-Scheme module and switch into it with some effort:
|
|
|
|
#+BEGIN_SRC scheme
|
|
(use-modules (system base language))
|
|
(set-current-module (default-environment 'prescheme))
|
|
,language prescheme
|
|
#+END_SRC
|
|
|
|
We need to make the process of "give me a Pre-Scheme REPL" easier. Maybe just
|
|
ship a REPL launcher script which starts up in Pre-Scheme instead of Guile?
|
|
|
|
* TODO script to build each module
|
|
|
|
We can use ~guile compile~ to get useful warnings:
|
|
|
|
#+BEGIN_SRC shell
|
|
find -name '*.scm' | xargs -n1 guild compile -W1 -O0 | grep -v '^wrote'
|
|
#+END_SRC
|
|
|
|
* STRT port ps-compiler
|
|
|
|
Above is just the emulation layer. The real work is the ps-compiler itself,
|
|
which is written in Scheme 48 (and also Common Lisp apparently). This will
|
|
involve:
|
|
|
|
- rewrite s48 interfaces as guile modules
|
|
- rewrite macros from explicit renaming to syntax-case
|
|
- ... and many more unforeseen challenges...
|
|
|
|
** ps-compiler/package-defs.scm [28/30]
|
|
*** [X] node
|
|
*** [X] variable
|
|
*** [X] primop
|
|
*** [X] pp-cps
|
|
*** [X] let-nodes
|
|
*** [X] check-nodes
|
|
*** [X] parameters
|
|
*** [X] set-parameters
|
|
*** [X] arch
|
|
*** [X] node-vector
|
|
*** [X] front
|
|
*** [X] front-debug
|
|
*** [X] cps-util
|
|
*** [X] jump
|
|
*** [X] simplify
|
|
*** [-] simplify-internal
|
|
*** [X] simplify-let
|
|
*** [X] simplify-join
|
|
*** [X] simp-patterns
|
|
*** [X] remove-cells
|
|
*** [X] flow-values
|
|
*** [X] comp-util
|
|
*** [X] expanding-vectors
|
|
*** [X] transitive
|
|
*** [X] integer-sets
|
|
*** [X] strongly-connected
|
|
*** [X] dominators
|
|
*** [X] ssa
|
|
*** [X] compiler-byte-vectors
|
|
*** [?] annotated-read
|
|
- the implementation of this package is missing from s48
|
|
|
|
** ps-compiler/prescheme/package-defs.scm [22/27]
|
|
*** [X] prescheme-compiler
|
|
*** [-] prescheme-display
|
|
*** [X] protocol
|
|
*** [-] prescheme-front-end
|
|
*** [X] forms
|
|
*** [X] expand
|
|
*** [X] ps-primitives
|
|
*** [-] primitive-data
|
|
*** [X] eval-node
|
|
*** [X] flatten
|
|
*** [X] flatten-internal
|
|
*** [X] to-cps
|
|
*** [-] linking
|
|
*** [X] ps-types
|
|
*** [X] type-variables
|
|
*** [X] record-types
|
|
*** [-] expand-define-record-type
|
|
*** [X] inference
|
|
*** [X] inference-internal
|
|
*** [X] node-types
|
|
*** [X] ps-primops
|
|
*** [X] ps-c-primops
|
|
*** [X] primop-data
|
|
*** [X] c-primop-data
|
|
*** [X] external-values
|
|
*** [X] c
|
|
*** [X] c-internal
|
|
|
|
** DONE port scheme/bcomp/node.scm
|
|
** DONE port scheme/bcomp/schemify.scm
|
|
** DONE port scheme/bcomp/package.scm
|
|
** TODO port write-one-line from scheme/big/more-port.scm
|
|
|
|
** TODO port the scheme48 reader & expander
|
|
*** [-] prescheme/bcomp/read-form.scm
|
|
*** [X] ps-compiler/prescheme/expand.scm
|
|
*** [X] ps-compiler/prescheme/flatten.scm
|
|
*** [X] ps-compiler/prescheme/front-end.scm
|
|
*** [-] ps-compiler/prescheme/linking.scm
|
|
|
|
** TODO port the primitive-data package
|
|
*** [ ] ps-compiler/prescheme/primop/scm-scheme.scm
|
|
*** [ ] ps-compiler/prescheme/primop/scm-arith.scm
|
|
*** [ ] ps-compiler/prescheme/primop/scm-memory.scm
|
|
*** [ ] ps-compiler/prescheme/primop/scm-record.scm
|
|
|
|
** TODO review bcomp node vs. ps-compiler node usage
|
|
|
|
Scheme48 has two different "node" implementations; one is part of the
|
|
byte-compiler (bcomp) and one is part of the prescheme compiler (ps-compiler).
|
|
To compile prescheme code, it is first run through the Scheme48 expander,
|
|
producing bcomp nodes which are then converted to ps-compiler nodes.
|
|
|
|
The trouble is that both types of record are called "node", and a number of
|
|
utility functions share the same name. These differences are handled in the
|
|
Scheme48 package definitions, but it's possible I've made some errors during
|
|
porting.
|
|
|
|
Carefuly review package definitions referencing "nodes" vs "node" interfaces.
|
|
|
|
* TODO prepare some compatibility tests
|
|
|
|
We need to find collect all the "real-world" Pre-Scheme we can get our hands on,
|
|
and test that our Guile Pre-Scheme produces identical output to Scheme 48
|
|
Pre-Scheme.
|
|
|
|
Exhibit A is the "hello world" from the manual:
|
|
|
|
#+BEGIN_SRC scheme
|
|
;; https://thintz.com/resources/prescheme-documentation#Example-Pre_002dScheme-compiler-usage
|
|
(define (main argc argv)
|
|
(if (= argc 2)
|
|
(let ((out (current-output-port)))
|
|
(write-string "Hello, world, " out)
|
|
(write-string (vector-ref argv 1) out)
|
|
(write-char #\! out)
|
|
(newline out)
|
|
0)
|
|
(let ((out (current-error-port)))
|
|
(write-string "Usage: " out)
|
|
(write-string (vector-ref argv 0) out)
|
|
(write-string " <user>" out)
|
|
(newline out)
|
|
(write-string " Greets the world & <user>." out)
|
|
(newline out)
|
|
-1)))
|
|
#+END_SRC
|
|
|
|
A bunch of tests are included in scheme48-1.9.2/ps-compiler/prescheme/test.
|
|
Nice!
|
|
|
|
** TODO test infrastucture (SRFI-64?)
|
|
** TODO test coverage of let-nodes
|
|
|
|
* TODO replace s48 utilities with rnrs/srfi where possible
|
|
|
|
The initial port of ps-compiler tries to minimise changes from the original
|
|
source, this has meant porting a decent collection of supporting utility
|
|
functions and macros from Scheme 48. After the initial port is complete, we
|
|
should replace these utilities with standardised equivalents.
|
|
|
|
This will reduce the amount of code we need to maintain, make it easier for
|
|
people with experience in other contemporary scheme projects to contribute, and
|
|
ease future work to port ps-compiler to other scheme implementations.
|
|
|
|
* IDEA replace the s48 expander to support modern standard scheme
|
|
|
|
Pre-Scheme relies on the Scheme 48 macro expander to pre-process source code
|
|
before translating it into the intermediate representation used by the compiler.
|
|
|
|
John Cowan has suggested replacing the Scheme 48 expander with Unsyntax
|
|
(https://www.unsyntax.org/). Unsyntax supports R7RS with a number of extensions
|
|
(including a variety of macro systems), expanding to a minimal dialect of
|
|
R7RS-small. It's also implemented in R7RS-small, so is easily portable across
|
|
scheme implementations.
|
|
|
|
To integrate the new expander, additional work will be required to resolve
|
|
mismatches between Unsyntax's minimal dialect and Pre-Scheme's minimal dialect.
|
|
|
|
This would significantly reduce the amount of code we need to maintain, go a
|
|
long way towards modernising the Pre-Scheme language, and ease future work to
|
|
port ps-compiler to other scheme implementations.
|
|
|
|
This would also probably be a backwards-incompatible change to Pre-Scheme, going
|
|
beyond the scope implied by calling this project a "port". We should discuss
|
|
this with Richard Kelsey, Jonathan Rees, and Michael Sperber and get their
|
|
permission to continue under the Pre-Scheme name, or possibly rename the
|
|
project.
|
|
|
|
* IDEA provide an optional Pre-Scheme "standard library"
|
|
|
|
Pre-Scheme supports a very minimal dialect of scheme, which is basically the
|
|
subset of scheme features that can be directly translated to C. This excludes
|
|
many features that a scheme programmer would expect, such as lists.
|
|
|
|
This minimalism is necessary to satisfy Pre-Scheme's goal of offering a
|
|
low-level, zero-overhead, zero-runtime scheme-like language, and that purity
|
|
shouldn't be compromised. It should always be possible to write in a minimal
|
|
dialect that compiles directly to standard portable C.
|
|
|
|
However, to make Pre-Scheme more attractive and useful to a wider variety of
|
|
programmers, we should provide a completely optional set of standard libraries,
|
|
written in Pre-Scheme, to extend the base language with commonly-used
|
|
functionality. These libraries should offer APIs as close to standard scheme as
|
|
possible (ie. based on RNRS/SRFI documents), but be implemented in a way that's
|
|
familiar to C programmers, with unsurprising runtime characteristics.
|
|
|
|
The libraries should cover things like:
|
|
- POSIX processes, threads, mutexes, shared memory, etc.
|
|
- lists
|
|
- hash-tables
|
|
- CLOS-alike
|
|
- ...?
|
|
|
|
One challenge will be to decide how to support generic data-structures. Will it
|
|
be sufficient to offer a set of macros which expand into concrete definitions,
|
|
like the C++ STL but in scheme?
|
|
|
|
We should discuss this with Richard Kelsey, Jonathan Rees, and Michael Sperber
|
|
to investigate whether there were any previous efforts in this direction. We
|
|
should also look at other scheme-likes and low-level lisps for inspiration on
|
|
what functionality could be included, and consult with the wider scheme
|
|
community to learn about as much prior art as possible.
|
|
|
|
* TODO write more TODOs
|