Work is going on in private branches of Vicare. Slowly.
Development of the typed language’s strict-type-checking
option is on its way:
it causes a warning to be raised whenever a typed variable is set to a value that is
only compatible rather than matching. For example:
(define {O <fixnum>} (cast-signature (<integer>) 123))
will raise a warning when strict-type-checking
is enabled, because
<integer>
is only compatible with <fixnum>
and will cause further
validation at run–time.
I am unhappy with the state of the record constructors. The r6rs constructors infrastructure works like this:
(define-record-type <duo> (fields one two) (protocol (lambda (make-record) make-record))) (define-record-type <trio> (parent <duo>) (fields three) (protocol (lambda (make-duo) (lambda (x y z) ((make-duo x y) z))))) (make-<trio> 1 2 3) ⇒ #[<trio> one=1 two=2 three=3]
we specify a protocol
clause that builds and returns a closure object used
as record constructor. I like it: I find it very flexible and very Schemey.
It also has a significant impedance mismatch with the way records are built using the typed language’s extensions: it has no way to provide a type signature for the constructor and overloaded constructors are possible but only with run–time dispatching. With the code as it is now, we can do this:
(define-record-type <duo> (fields one two) (protocol (lambda (make-record) (define/overload ({make-duo <duo>} {x <real>} {y <real>}) (make-record x y)) (define/overload ({make-duo <duo>} {z <complex>}) (make-record (real-part z) (imag-part z))) make-duo)) (constructor-signature (case-lambda ((<real> <real>) => (<duo>)) ((<complex>) => (<duo>)))) (new <duo> 1 2) ⇒ #[<duo> one=1 two=2] (new <duo> 1+2i) ⇒ #[<duo> one=1 two=2]
but it is not optimal: in this code there is everything needed to select the specialised constructor at expand–time, but the selection happens at run–time.
A possible solution: introduce “named protocols”; have new
call a
constructor other than the one defined by protocol
. Something like this:
(define-record-type <duo> (fields one two) (protocol (lambda (make-record) make-record)) (named-protocol make-duo-from-complex (lambda (make-record) (lambda (z) (make-record (real-part z) (imag-part z))))) (constructor ({x <real>} {y <real>}) (make-<duo> x y)) (constructor ({z <complex>}) (make-duo-from-complex z)))
it works like this:
constructor
clauses and multiple named-protocol
clauses, in addition to the standard protocol
clause.
named-protocol
clause defines a record–constructor descriptor whose
constructor is bound to a specified name. The default protocol
clause is
just like a named-protocol
clause whose constructor is bound to the
preselected syntactic identifier make-<duo>
.
constructor
clause defines a specialisation for an overloaded
function; the overloaded function name is new-<duo>
. The body of the
specialisation can use any of the constructors defined by protocol
and
named-protocol
.
constructor
clause is used in the body of a
define-record-type
use: the syntax new
expands into a call to
new-<duo>
, rather than into a call to make-<duo>
.
The constructor
clauses expand into the overloaded function:
(define/overload ({new-<duo> <duo>} {x <real>} {y <real>}) (make-<duo> x y)) (define/overload ({new-<duo> <duo>} {z <complex>}) (make-duo-from-complex z))
Obviously we can define the constructor
clauses to use the default
constructor:
(define-record-type <duo> (fields one two) (protocol (lambda (make-record) make-record)) (constructor ({x <real>} {y <real>}) (make-<duo> x y)) (constructor ({z <complex>}) (make-<duo> (real-part z) (imag-part z))))
With this solution the clause constructor-signature
would be removed.
At some point, in one of the possible futures, I would like to split the expander and
compiler from the boot image; this means (rnrs eval (6))
, (vicare
expander)
, (vicare compiler)
become external libraries. Not an easy thing to
do.
Right now there is a single executable program installed with Vicare, but with this change there would be more of them:
vicare-repl
A precompiled Scheme program that runs the repl. It would load an external
library (vicare cafe)
, which is now an internal set of features.
vicare-compiler
A Scheme program that implements the compiler.
vicare
The run–time we have now. It would become a program that runs precompiled Scheme programs.
Things should change internally.
For example the record–type describing compiled libraries should be restructured.
To be able to run compiled programs that load compiled libraries without loading the
expander: a library’s invoke code must be loaded without loading the visit code
(which needs the expander library). This could mean that the invoke code is split
from .fasl
files into its own file; it would make it possible to install a
package holding only precompiled programs and libraries, without including the
development stuff. Cool.
The boot process would be greatly revolutionised. In addition to shipping precompiled boot images, the package would include precompiled compiler and expander libraries under the boot directory. A lot of processing that is now performed in the build script makefile.sps should be restructured.
I will think of this. I want to start by putting the repl into an external program; it will also be a test for compiled programs that is now absent from the package.