[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

begin-for-syntax, begin-for-load should be in this SRFI



Hidden away in the reference implementation, and in
an unannounced SRFI are the keywords
  (begin-for-syntax ...)
and
  (begin-for-import ...).

These are part of the module system, but I think they should be
part of the macro system (srfi-72).

Even if you have no module system, or a different one, these
are needed to control macro expansion, to prevent big computations
from being done at expansion time, and to prevent the
compiled program from bloating up with macro expansion
helper procedures.

I have been using (load <file>) alone to get my code in, and
have implemented a version of the expander that writes
expanded code to a file to be loaded later.  It seems to work.

Along with this I have changed the name of begin-for-import
to begin-for-load, since I have no import.  I think that
would be a fine name even when/if the module system is in
use.  Scheme calls fetching a bunch of code and executing
it "load".  I don't really love this name, and the operation
is underspecified by RRRS (the Repeatedly Revised Report), but
I rather stick with the name I know than make fruitless
innovation.  It seems to me that import is just a fancy
kind of load.

Here is some of the code.

Procedure expand-toplevel has an extra argument to indicate
whether to execute the expanded form.  This is because the stand-alone
expander needs to execute definitions in case they are used by macros,
but in the repl you don't want things done twice.

(define expand-toplevel
  (let ((source-rename (make-renaming-procedure source-colour scheme-env #f)))
    (lambda (exp execute?)
      (*source-stack*        '())
      (*current-module-name* (string->symbol ""))
      (*inside-quasisyntax*  #f)
      (set! source-rename
            (make-renaming-procedure source-colour 
                                     (close-environment (source-rename 'dummy))
                                     #f))
      (let ((expanded (expand (datum->syntax-object0 source-rename exp))))
         (cond ((begin-for-syntax? expanded)
		 (eval `(begin . ,(cdr expanded)))
	          '(void))
	       ((begin-for-load? expanded)
	         `(begin . ,(cdr expanded)))
	       (else 
                 (if execute? (eval expanded))
                 expanded))))))

Procedure compile reads a file with macros and makes one without

(define (compile filename)
  (let ((scm (open-input-file  (string-append filename ".scm")))
        (obj (open-output-file  (string-append filename ".obj"))))
     (let loop ((e (read scm)))
	  (if (eof-object? e)
	      'done
	      (begin
                (write (expand-toplevel e #t) obj)
                (newline obj)
                (loop (read scm)))))))

The repl calls
   (eval (expand-toplevel exp #f)))

By the way, I do not understand why the local variable
|source-rename| is initialized and immediately overwriten,
only to turn to garbage by the end of the procedure,
but that's the way I found it and I left it so, in case
there is deep magic unkent.

-- 
     -- Keith Wright

Programmer in Chief, Free Computer Shop
 ---  Food, Shelter, Source code.  ---