X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/e5573634ce3668f2a4eac74be125262d28a5cb8a..7de8c6661211bce3a2b2739b461f33a370294979:/src/codegen-proto.lisp?ds=sidebyside diff --git a/src/codegen-proto.lisp b/src/codegen-proto.lisp index 767f35b..186f225 100644 --- a/src/codegen-proto.lisp +++ b/src/codegen-proto.lisp @@ -210,6 +210,10 @@ `(format-compound-statement* ,stream ,child ,morep (lambda (,stream) ,@body))) +(export 'format-banner-comment) +(defun format-banner-comment (stream control &rest args) + (format stream "~@~_ */~:>" control args)) + ;; Important instruction classes. ;; HACK: Some of the slot names we'd like to use are external symbols in our @@ -222,8 +226,12 @@ (format stream " = ~A" init)) (write-char #\; stream)) -(definst function (stream :export t) (name #1=#:type body) +(definst function (stream :export t) + (name #1=#:type body &optional #2=#:banner &rest banner-args) (pprint-logical-block (stream nil) + (when #2# + (apply #'format-banner-comment stream #2# banner-args) + (pprint-newline :mandatory stream)) (princ "static " stream) (pprint-c-type #1# stream name) (format stream "~:@_~A~:@_~:@_" body))) @@ -250,6 +258,21 @@ ;; Compound statements. +(defvar *first-statement-p* t + "True if this is the first statement in a block. + + This is used to communicate between `block-inst' and `banner-inst' so that + they get the formatting right between them.") + +(definst banner (stream :export t) (control &rest args) + (pprint-logical-block (stream nil) + (unless *first-statement-p* (pprint-newline :mandatory stream)) + (apply #'format-banner-comment stream control args))) + +(export 'emit-banner) +(defun emit-banner (codegen control &rest args) + (emit-inst codegen (apply #'make-banner-inst control args))) + (definst block (stream :export t) (decls body) (write-char #\{ stream) (pprint-newline :mandatory stream) @@ -266,9 +289,11 @@ (newline) (write decl :stream stream)) (when body (newline))) - (dolist (inst body) - (newline) - (write inst :stream stream))))) + (let ((*first-statement-p* t)) + (dolist (inst body) + (newline) + (write inst :stream stream) + (setf *first-statement-p* nil)))))) (pprint-newline :mandatory stream) (write-char #\} stream)) @@ -367,13 +392,15 @@ cleanup automatically.")) (export 'codegen-build-function) -(defun codegen-build-function (codegen name type vars insts) +(defun codegen-build-function + (codegen name type vars insts &optional banner &rest banner-args) "Build a function and add it to CODEGEN's list. Returns the function's name." (codegen-add-function codegen - (make-function-inst name type - (make-block-inst vars insts))) + (apply #'make-function-inst name type + (make-block-inst vars insts) + banner banner-args)) name) (export 'codegen-pop-block) @@ -385,15 +412,17 @@ (make-block-inst vars insts)))) (export 'codegen-pop-function) -(defgeneric codegen-pop-function (codegen name type) +(defgeneric codegen-pop-function + (codegen name type &optional banner &rest banner-args) (:documentation "Makes a function out of the completed code in CODEGEN. The NAME can be any object you like. The TYPE should be a function type object which includes argument names. The return value is the NAME.") - (:method (codegen name type) + (:method (codegen name type &optional banner &rest banner-args) (multiple-value-bind (vars insts) (codegen-pop codegen) - (codegen-build-function codegen name type vars insts)))) + (apply #'codegen-build-function codegen name type vars insts + banner banner-args)))) (export 'with-temporary-var) (defmacro with-temporary-var ((codegen var type) &body body)