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

How to let macros work without defining what a macro is...



    Date: 27 Mar 1985  10:19 EST (Wed)
    From: Bill Rozas <JINX%MIT-OZ@MIT-MC.ARPA>

	    This assumes that all macros work at the s-expression level,
    which is not true in our implementation.  The only way to provide both
    (especially syntax-expand) in all cases would be to fully reduce to
    s-code and then invert to s-expressions.  This would imply full
    (recursive) expansion always.

	    In our system macros translate from s-expressions to s-code.
    There are a few utilities, however, to emulate s-expression level
    macros built on top of this.  But macros like COND, LET, etc are never
    translated at the s-expression level.

No, you missed the point. You can implement these special forms however
you want. What I'm proposing is something that takes forms which may be
in an extended syntax and translates it into a standard syntax.

eg, suppose the only extended forms in some dialect are WHEN and UNLESS.
Regardless of how those are implemented (perhaps directly represented
in S-code, perhaps translated to something else in S-code, whatever),
all you have to provide is (literally) the following function:

(DEFINE (PRIMITIVE-SYNTAX-EXPAND FORM)
  (COND ((ATOM FORM) FORM)
	((EQ (CAR FORM) 'WHEN)
	 `(COND (,(CADR FORM) ,@(CDDR FORM))))
	((EQ (CAR FORM) 'UNLESS)
	 `(COND ((NOT ,(CADR FORM)) ,@(CDDR FORM))))
	(T FORM)))

You never have to call the function internally in the system. It simply
has to be available for users who want to use it. It must be the 
responsibility of system maintainers to keep it up to date so that 
code-manipulating tools can be written which assume a fixed number 
of special forms and new special forms can later be added to standard 
Scheme which do not cause a need to rewrite those tools.

Suppose that the only special forms we could agree on being standard
were LAMBDA, QUOTE, and SETQ. Suppose that someone insisted that 
 (IF X Y Z)
had to be written
 (*IF (LAMBDA () X)
      (LAMBDA () Y)
      (LAMBDA () Z))
and *IF had to be a function, etc. Assume similar rewrites were suggested
for other special forms. Now consider a user program in a particular 
dialect which had extra special forms (eg, DEFINE, COND, ...):

(DEFINE (USED-FREE-IN EXP VAR TAIL?)
  (COND ((ATOM VAR) (EQ EXP VAR))
	(FLAG
	 (COND ((NULL EXP) NIL)
	       ((USED-FREE-IN (CAR EXP) VAR NIL) T)
	       (T
		(USED-FREE-IN (CDR EXP) VAR T))))
	((EQ (CAR EXP) 'LAMBDA)
	 (COND ((MEMQ VAR (CADR EXP)) NIL)
	       (T
		(USED-FREE-IN (CDDR EXP) VAR T))))
	((EQ (CAR EXP) 'SETQ)
	 (OR (EQ EXP (CADR FORM))
	     (USED-FREE-IN (CADDR EXP) VAR NIL)))
	((EQ (CAR EXP) 'QUOTE) NIL)
	(T
	 (USED-FREE-IN EXP VAR T))))

If I didn't blow it, this program "works" on input which contains 
LAMBDA, SETQ, and QUOTE but does not work on input that contains 
COND, etc. It could, however, work on those, too, by simply making it
say:

(DEFINE (USED-FREE-IN EXP VAR TAIL?)
  (LET ((EXP (PRIMITIVE-SYNTAX-EXPAND EXP)))
    (COND ((ATOM VAR) (EQ EXP VAR))
	  (FLAG
	   (COND ((NULL EXP) NIL)
		 ((USED-FREE-IN (CAR EXP) VAR NIL) T)
		 (T
		  (USED-FREE-IN (CDR EXP) VAR T))))
	  ((EQ (CAR EXP) 'LAMBDA)
	   (COND ((MEMQ VAR (CADR EXP)) NIL)
		 (T
		  (USED-FREE-IN (CDDR EXP) VAR T))))
	  ((EQ (CAR EXP) 'SETQ)
	   (OR (EQ EXP (CADR FORM))
	       (USED-FREE-IN (CADDR EXP) VAR NIL)))
	  ((EQ (CAR EXP) 'QUOTE) NIL)
	  (T
	   (USED-FREE-IN EXP VAR T)))))

The user could write PRIMITIVE-SYNTAX-EXPAND himself, but he'd have
to:

 (a) Make sure his understanding of the syntax equivalences was
     letter perfect (the system implementors have a better chance
     of getting this right)

 (b) Update the function every time the dialect changed. ie, adding
     a special form if PRIMITIVE-SYNTAX-EXPAND is not a system primitive
     function is an incompatible change, but is a compatible change
     if PRIMITIVE-SYNTAX-EXPAND is kept in synch with available special
     forms.

It would be possible to have forms which were not translatable. They
should simply be advertised as such and PRIMITIVE-SYNTAX-EXPAND should err
when it sees them so that the user doesn't think he's winning when he's
not.

Does this make it clearer?
-kmp