(define-method/cgen 'REFERENCE
(lambda (interns expression)
- (if (variable/must-ignore? (reference/variable expression))
- (warn "Variable declared IGNORE, but was used: "
- (variable/name (reference/variable expression))))
(cgen/variable interns (reference/variable expression))))
(define-method/cgen 'SEQUENCE
;; IGNORABLE suppresses warnings about the variable not being used.
;; This is useful in macros that bind variables that the body may
-;; not actually use. Mentioning the variable in a sequence will
-;; have the effect of marking it ignorable.
+;; not actually use.
(define-declaration 'IGNORABLE
(lambda (block names)
(for-each (lambda (variable)
'()))
;; IGNORE causes warnings if an ignored variable actually ends
-;; up being used.
+;; up being used. Mentioning the variable in a sequence will
+;; have the effect of marking it IGNORED.
(define-declaration 'IGNORE
(lambda (block names)
- (for-each (lambda (variable)
- (if variable
- (variable/must-ignore! variable)))
- (block/lookup-names block names #f))
- '()))
+ (let ((variables (block/lookup-names block names #f)))
+ (for-each (lambda (variable)
+ (if variable
+ (variable/must-ignore! variable)))
+ variables)
+ (make-declarations 'IGNORE
+ variables
+ 'NO-VALUES
+ 'LOCAL))))
\f
;;;; Reductions and Expansions
;;; See "reduct.scm" for description of REDUCE-OPERATOR and REPLACE-OPERATOR.
;;; descriptive.
(define *current-block-names*)
+(define (ignored-variable-warning name)
+ (warn (string-append "Variable \""
+ (symbol->string name)
+ "\" was declared IGNORE, but used anyway.")
+ name *current-block-names*))
+
(define (integrate/top-level block expression)
(integrate/top-level* (object/scode expression) block expression))
(list (if (eq? action open-block/value-marker)
action
(integrate/expression operations environment action)))
- (cons (cond ((reference? action)
- ;; This clause lets you ignore a variable by
- ;; mentioning it in a sequence.
- (variable/may-ignore! (reference/variable action))
- action)
- ((eq? action open-block/value-marker)
+ (cons (cond ((eq? action open-block/value-marker)
action)
(else
(integrate/expression operations environment action)))
(lambda (operation info)
info ;ignore
(case operation
- ((INTEGRATE INTEGRATE-OPERATOR EXPAND)
+ ((IGNORE)
+ (ignored-variable-warning (variable/name variable)))
+ ((EXPAND INTEGRATE INTEGRATE-OPERATOR)
(warn "Attempt to assign integrated name"
(variable/name variable)))
(else (error "Unknown operation" operation))))
(operations/lookup operations variable
(lambda (operation info)
(case operation
- ((INTEGRATE-OPERATOR EXPAND)
+ ((IGNORE)
+ (ignored-variable-warning (variable/name variable))
+ (integration-failure))
+ ((EXPAND INTEGRATE-OPERATOR)
(variable/reference! variable)
expression)
((INTEGRATE)
(integrate/expression operations environment new-expression)))
(else (dont-integrate))))
+ ((IGNORE)
+ (ignored-variable-warning (variable/name variable))
+ (dont-integrate))
+
((INTEGRATE INTEGRATE-OPERATOR)
(let ((new-operator
(reassign operator
(integrate/expression operations environment new-expression))
(integration-failure))))
+ ((IGNORE)
+ (ignored-variable-warning (variable/name variable))
+ (integration-failure))
+
((INTEGRATE INTEGRATE-OPERATOR)
(let ((new-expression (integrate/name expression
operator info environment)))
(define-method/integrate-combination 'THE-ENVIRONMENT
(lambda (expression operations environment block operator operands)
(warn "(THE-ENVIRONMENT) used as an operator. Will cause a runtime error.")
- (combination/make expression block
+ (combination/make expression block
(integrate/expression operations environment operator)
operands)))
(let ((environment
(environment/bind environment
(block/bound-variables block))))
- (procedure/make
- expression block name required optional rest
- (transform/procedure-body block
- environment
- body)))))))))
+ (build-procedure expression block name required optional rest
+ (transform/procedure-body block environment body)))))))))
+
+;; If procedure body is a sequence, scan the first elements and turn variable
+;; references into IGNORE declarations.
+(define (build-procedure expression block name required optional rest body)
+ (if (sequence? body)
+ (do ((actions (sequence/actions body) (cdr actions))
+ (ignores '() (cons (variable/name (reference/variable (car actions))) ignores)))
+ ((or (null? (cdr actions))
+ (not (reference? (car actions))))
+ (let ((final-body (if (null? (cdr actions))
+ (car actions)
+ (sequence/make (object/scode body) actions))))
+ (procedure/make
+ expression block name required optional rest
+ (if (null? ignores)
+ final-body
+ (declaration/make #f (declarations/parse block `((ignore ,@ignores)))
+ final-body))))))
+ (procedure/make
+ expression block name required optional rest
+ body)))
(define (transform/procedure-body block environment expression)
(if (scode-open-block? expression)