Updated srfis and other stuff (2015 March 20)

I have assimilated into Vicare the srfis 113, 114. Quite some work was needed because, for example, srfi-114 has no test suite; also, they are written thinking to r7rs implementations and CHICKEN in particular. To assimilate the code to Vicare’s style, I had to touch almost all the procedures definitions.

While doing this work: I have pushed, in parallel, other development tasks.

Fixed Issue 49

While working on srfi-114 assimilation I think I fixed Issue 49. I feel a bit ashamed for taking so long to fix this, because it was a very simple mistake in the compiler; but the cause of error just did not pop up into my mind until now.

It goes like this, when the source optimiser sees code like:

(let ((a 1))
  (set! a (do-something))
  2)

it recognises that the binding a is referenced only in the assignment form, so to mutate the binding is useless; the code is transformed to the equivalent:

(let ((a 1))
  (do-something)
  2)

now further optimisations are possible but they do not matter here. Everything is fine with local bindings, but what about top level bindings? If the code is:

(library (demo)
  (export
    ;... some bindings ...
    a)
  (import (vicare))
  ;;... some definitions ...
  (define a 1)
  (set! a (do-something)))

the binding a is referenced in the library body only in the assignment form, but we cannot transform the code to:

(library (demo)
  (export
    ;... some bindings ...
    a)
  (import (vicare))
  ;;... some definitions ...
  (define a 1)
  (do-something))

because the binding is exported. Even if the code is:

(library (demo)
  (export
    ;... some bindings ...
    )
  (export)
  (import (vicare))
  ;;... some definitions ...
  (define a 1)
  (set! a (do-something)))

where a is not exported, we cannot transform the code because some macro might create a non–hygienic reference to the binding.

In general, Vicare’s compiler has no way to detect when a top level binding is referenced in the code or not, so top level bindings can be neither removed nor subject to this kind of source optimisation. But this is exactly what was happening.

When code like the following is expanded:

(library (demo)
  (export make-record record?)
  (import (vicare))
  (define-record-type record))

a definition for make-record is created:

(define make-record ...)

then the compiler processes the library body and transforms the top level binding definitions according to the selected letrec and letrec* optimisation policy; the code is transformed to an equivalent of:

(letrec* ((make-record (void))
          ...)
  (set! make-record ...))

where the letrec* bindings are top level; then the source optimiser is applied to it. If make-record is never used in the body other than in the assignment form: the assignment cannot be removed, but this was happening. Hence the error.

More vector core primitives

Some of the “fold left” and “fold right” functions from the library (vicare containers vectors) have been moved into the boot image, becoming core primitives; some other primitives were added. In the boot image we now have:

vector-map
vector-for-each
vector-find
vector-for-all
vector-exists
vector-fold-left
vector-fold-right

which constitute a decent base for vector iteration.

More hash tables primitives

Inspired by the functions in srfi-113 I have added the following core primitives to (vicare):

hashtable-for-each-key
hashtable-for-each-entry
hashtable-for-all-keys
hashtable-for-all-entries
hashtable-exists-key
hashtable-exists-entry
hashtable-find-key
hashtable-find-entry
hashtable-fold-keys
hashtable-fold-entries
hashtable->alist
alist->hashtable!

and inspired by the functions in srfi-114 I have extended the suite of hash functions to:

string-hash             string-ci-hash
symbol-hash             bytevector-hash
equal-hash
fixnum-hash             exact-integer-hash
flonum-hash             number-hash
char-hash               char-ci-hash
boolean-hash            void-hash
eof-object-hash         would-block-hash
struct-hash             record-hash
object-hash

not all of these are quality functions.

No more “last revision” identifier

For some time, when starting the repl, the identifier of the last commit was included in the greetings screen:

$ vicare
Vicare Scheme version 0.4d0, 64-bit
Revision master/84506e3ba00414bd689a87e4890076e4fedd9f56
Build 2015-03-06

Copyright (c) 2006-2010 Abdulaziz Ghuloum and contributors
Copyright (c) 2011-2015 Marco Maggi

vicare>

now I have removed it:

$ vicare
Vicare Scheme version 0.4d0, 64-bit
Build 2015-03-11

Copyright (c) 2006-2010 Abdulaziz Ghuloum and contributors
Copyright (c) 2011-2015 Marco Maggi and contributors

vicare>

To include the “last revision” identifier: after every commit and every branch merge the branch and commit checksum were saved into a file included in the next Vicare build. This meant that after every commit and merge everything needed to be rebuilt, even when no actual code was modified. This annoyed me.

Also, I failed multiple times in keeping in sync the registered revision with the build distributed in tarballs.

For this reasons I nuked this feature. We can live without.