X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/sod/blobdiff_plain/d6bb2ccd1acd7d3ed72e26d7d9a2ec6f72d96e1a..2d8d81c52aded8f15e37b061971d493742f55751:/src/codegen-proto.lisp diff --git a/src/codegen-proto.lisp b/src/codegen-proto.lisp index 7a6be33..e663fb5 100644 --- a/src/codegen-proto.lisp +++ b/src/codegen-proto.lisp @@ -210,6 +210,10 @@ (defmacro format-compound-statement `(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 @@ (definst var (stream :export t) (name #1=#:type &optional init) (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))) @@ -239,6 +247,8 @@ (definst update (stream :export t) (var op #1=#:expr) ;; Special kinds of expressions. (definst call (stream :export t) (#1=#:func &rest args) (format stream "~A(~@<~{~A~^, ~_~}~:>)" #1# args)) +(definst cond (stream :export t) (#1=#:cond conseq alt) + (format stream "~@<~A ~2I~@_~@~:>" #1# conseq alt)) ;; Simple statements. (definst return (stream :export t) (#1=#:expr) @@ -250,9 +260,44 @@ (definst continue (stream :export t) () ;; 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) - (format stream "{~:@_~@< ~2I~@[~{~A~:@_~}~:@_~]~{~A~^~:@_~}~:>~:@_}" - decls body)) + (write-char #\{ stream) + (pprint-newline :mandatory stream) + (pprint-logical-block (stream nil) + (let ((newlinep nil)) + (flet ((newline () + (if newlinep + (pprint-newline :mandatory stream) + (setf newlinep t)))) + (pprint-indent :block 2 stream) + (write-string " " stream) + (when decls + (dolist (decl decls) + (newline) + (write decl :stream stream)) + (when body (newline))) + (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)) (definst if (stream :export t) (#1=#:cond conseq &optional alt) (let ((stmt "if")) @@ -277,6 +322,11 @@ (definst do-while (stream :export t) (body #1=#:cond) (write-string "do" stream)) (format stream "while (~A);" #1#)) +(definst for (stream :export t) (init #1=#:cond update body) + (format-compound-statement (stream body) + (format stream "for (~@<~@[~A~];~@[ ~_~A~];~@[ ~_~A~]~:>)" + init #1# update))) + ;;;-------------------------------------------------------------------------- ;;; Code generation. @@ -349,13 +399,15 @@ (defgeneric temporary-var (codegen type) 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) @@ -367,15 +419,17 @@ (defgeneric codegen-pop-block (codegen) (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)