2009-07-19 Doug Evans <dje@sebabeach.org>
+ Fix binding of nested pmacro parameters.
+ * pmacros.scm (-pmacro-env-make): New arg prev-env.
+ All callers updated.
+ (-pmacro-bulid-lambda): Ditto.
+ * doc/pmacros.texi: Update.
+
* ifield.scm (-multi-ifield-make-default-insert): Fix shifts
calculation.
(-multi-ifield-make-default-extract): Ditto.
(load-op uh OP2_11 HI (.pmacro (mode expr) (zext mode expr)))
@end smallexample
-.pmacro's don't bind the way Scheme lambda expressions do.
-In the following example, arg2 in the second pmacro is not bound
-to the arg2 argument of the first pmacro.
-@c FIXME: Feels like a bug rather than a feechure.
+.pmacro's bind the same way Scheme lambda expressions do.
+In the following example, arg2 in the second pmacro is bound
+to the arg2 argument of the outer pmacro.
@smallexample
(define-pmacro (foo arg1 arg2) ((.pmacro (bar) (+ arg2 bar)) arg1))
-(foo 3 4) ==> (+ arg2 3)
+(foo 3 4) ==> (+ 4 3)
@end smallexample
@node Passing macros as arguments
; .sym and .str convert numbers to symbols/strings as necessary (base 10).
;
; .pmacro is for constructing pmacros on-the-fly, like lambda, and is currently
-; only valid as arguments to other macros.
-; ??? Nested pmacros don't bind their arguments the way nested lambda's do.
-; Should they?
+; only valid as arguments to other macros or assigned to a local in a {.let}.
;
; ??? Methinks .foo isn't a valid R5RS symbol. May need to change
; to something else.
; Cover functions to manage an "environment" in case a need or desire for
; another method arises.
-(define (-pmacro-env-make names values) (map cons names values))
+(define (-pmacro-env-make prev-env names values)
+ (append! (map cons names values) prev-env)
+)
(define (-pmacro-env-ref env name) (assq name env))
; Error message generator.
; Build a procedure that performs a pmacro expansion.
-(define (-pmacro-build-lambda params expansion)
+(define (-pmacro-build-lambda prev-env params expansion)
(eval1 `(lambda ,params
(-pmacro-expand ',expansion
- (-pmacro-env-make ',params (list ,@params)))))
+ (-pmacro-env-make ',prev-env
+ ',params (list ,@params)))))
)
; ??? I'd prefer to use `define-macro', but boot-9.scm uses it and
; name).
; ??? The goal here is to follow Scheme's define/lambda, but not all variants
; are supported yet. There's also the difference that we treat undefined
-; symbols as being themselves.
+; symbols as being themselves (i.e. "self quoting" so-to-speak).
;
; ??? We may want user-definable "syntactic" macros some day. Later.
(-pmacro-set! name (-pmacro-make name #f #f #f expansion comment)))
(-pmacro-set! name
(-pmacro-make name arg-spec default-values #f
- (-pmacro-build-lambda arg-spec expansion)
+ (-pmacro-build-lambda nil
+ arg-spec expansion)
comment))))
*UNSPECIFIED*
)
;; e.g. (define (foo bar . baz) ...)
(if (not (list? params))
(-pmacro-error ".pmacro parameter-spec is not a list" params))
- (-pmacro-make '.anonymous params #f #f (-pmacro-build-lambda params expansion) "")
+ (-pmacro-make '.anonymous params #f #f
+ (-pmacro-build-lambda env params expansion) "")
)
; (.let (var-list) expr1 . expr-rest)