[plt-scheme] srfi-0 cond-expand

From: MJ Ray (markj at cloaked.freeserve.co.uk)
Date: Fri Oct 4 10:15:15 EDT 2002

[WARNING: Longish post (for me) containing half-baked program code.  Those
with a sensitive nature may wish to go get the indigestion tablets now.]

OK, I've started looking at this and its relationship to the module system. 
I think it can be implemented as a layer over the PLT module system, which
is fine if we're just trying to write portable code and don't really care
how it happens.  Here's my first cut at the code.

The first file is catalogue.scm and is basically taken from the reference
implementation of srfi-0:

(define-syntax cond-expand
    (and or not else srfi-0)
    ((cond-expand) (syntax-error "Unfulfilled cond-expand"))
    ((cond-expand (else body ...))
     (begin body ...))
    ((cond-expand ((and) body ...) more-clauses ...)
     (begin body ...))
    ((cond-expand ((and req1 req2 ...) body ...) more-clauses ...)
     (cond-expand (req1 (cond-expand ((and req2 ...) body ...) more-clauses ...))
       more-clauses ...))
    ((cond-expand ((or) body ...) more-clauses ...)
     (cond-expand more-clauses ...))
    ((cond-expand ((or req1 req2 ...) body ...) more-clauses ...)
     (cond-expand (req1 (begin body ...)) (else (cond-expand ((or req2 ...) body ...) more-clauses ...))))
    ((cond-expand ((not req) body ...) more-clauses ...)
     (cond-expand (req (cond-expand more-clauses ...)) (else body ...)))
    ((cond-expand (srfi-0 body ...) more-clauses ...)
     (begin body ...))
    ((cond-expand (feature-id body ...) more-clauses ...)
     (cond-expand more-clauses ...))))

The other file will hopefully become a PLT module, called 0.ss for me for

(define (syntax-error args)
  (error 'syntax-error args))

(load "catalogue.scm")

Finally, the following file allows me to update catalogue.scm with new
feature symbols and their require statements:-

(define (matcher sym)
  `(cond-expand (,sym body ...) more-clauses ...))

(define (expander clause)
  `(begin ,clause body ...))

(define (add-package sym clause)
  (let ((catalogue (call-with-input-file "catalogue.scm"
                     (lambda (in)
                       (read in)))))
    (call-with-output-file "catalogue.scm"
      (lambda (out)
            (lambda (ds ce c2)
              (list ds ce
                  (list (car c2) (cons sym (cadr c2))
                    (list (matcher sym) (expander clause)))
                  (cddr c2))))

Now, the idea is that when new packages are installed, we call add-package
with something like:

  (add-package 'srfi-13 '(require (lib "13.ss" "srfi")))

and the catalogue.scm file is updated accordingly, with srfi-13 added to the
list of symbols and it is expanded to the require statement in any
cond-expand.  User programs can be written using cond-expand to access
portable features and run with -M0 on the mzscheme commmand line.

I realise that the finer details of the above "proof of concept" need to be
worked out (eg locating catalogue.scm in each call above), but are there
problems with the basic implementation that I've proposed?  If so, please
tell me how to address them ;-)

If no-one finds a fatal bug, I'll package this up into a module, beg Noel to
accept it at schematics and start on the next layer I want.  All the
function names apart from cond-expand will probably change...


Posted on the users mailing list.