((in-use-p :initarg :in-use-p :initform nil
:type boolean :accessor var-in-use-p)))
+(define-module-var *temporary-index* 0
+ "Index for temporary name generation.
+
+ This is automatically reset to zero before the output functions are
+ invoked to write a file. This way, we can ensure that the same output
+ file is always produced from the same input.")
+
+(define-clear-the-decks reset-codegen-index
+ (setf *temporary-index* 0))
+
(defmethod commentify-argument-name ((name temporary-name))
nil)
-(export 'temporary-function)
(defun temporary-function ()
"Return a temporary function name."
(make-instance 'temporary-function
;; Compound statements.
-(definst if (stream :export t) (condition consequent alternative)
+;; HACK: use gensyms for the `condition' slots to avoid leaking the slot
+;; names, since the symbol `condition' actually comes from the `common-lisp'
+;; package. The `definst' machinery will symbolicate the various associated
+;; methods correctly despite this subterfuge.
+
+(definst if (stream :export t) (#1=#:condition consequent alternative)
(format-compound-statement (stream consequent alternative)
- (format stream "if (~A)" condition))
+ (format stream "if (~A)" #1#))
(when alternative
(format-compound-statement (stream alternative)
(write-string "else" stream))))
-(definst while (stream :export t) (condition body)
+(definst while (stream :export t) (#1=#:condition body)
(format-compound-statement (stream body)
- (format stream "while (~A)" condition)))
+ (format stream "while (~A)" #1#)))
-(definst do-while (stream :export t) (body condition)
+(definst do-while (stream :export t) (body #1=#:condition)
(format-compound-statement (stream body :space)
(write-string "do" stream))
- (format stream "while (~A);" condition))
+ (format stream "while (~A);" #1#))
;; Special varargs hacks.
;; Expressions.
-(definst call (stream :export t) (func args)
- (format stream "~A(~@<~{~A~^, ~_~}~:>)" func args))
+;; HACK: use a gensym for the `func' slot to avoid leaking the slot name,
+;; since the symbol `func' is exported from our package.
+(definst call (stream :export t) (#1=#:func args)
+ (format stream "~A(~@<~{~A~^, ~_~}~:>)" #1# args))
;;;--------------------------------------------------------------------------
;;; Code generator objects.
(defmethod emit-insts ((codegen basic-codegen) insts)
(asetf (codegen-insts codegen) (revappend insts it)))
+(defmethod emit-decl ((codegen basic-codegen) inst)
+ (push inst (codegen-vars codegen)))
+
+(defmethod emit-decls ((codegen basic-codegen) insts)
+ (asetf (codegen-vars codegen) (revappend insts it)))
+
(defmethod ensure-var ((codegen basic-codegen) name type &optional init)
(let* ((vars (codegen-vars codegen))
- (var (find name vars :key #'inst-name :test #'equal)))
+ (var (find name
+ (remove-if-not (lambda (var) (typep var 'var-inst)) vars)
+ :key #'inst-name :test #'equal)))
(cond ((not var)
(setf (codegen-vars codegen)
(cons (make-var-inst name type init) vars)))
(c-type-equal-p type (inst-type var)))
name
nil)))
- vars)
+ (remove-if-not (lambda (var) (typep var 'var-inst)) vars))
(let* ((name (make-instance 'temporary-variable
:in-use-p t
:tag (prog1 temp-index