X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/77d83e015f7cd280b385ad53c486e2c27ad6152f..b7fcf94152e4c1938fbca55d13b1e6a64b694bd6:/src/codegen-proto.lisp?ds=sidebyside diff --git a/src/codegen-proto.lisp b/src/codegen-proto.lisp index 264fd03..7a6be33 100644 --- a/src/codegen-proto.lisp +++ b/src/codegen-proto.lisp @@ -67,6 +67,9 @@ (defparameter *sod-tmp-val* (make-instance 'temporary-name :tag "sod__t")) +(export '*null-pointer*) +(defparameter *null-pointer* "NULL") + ;;;-------------------------------------------------------------------------- ;;; Instructions. @@ -124,8 +127,8 @@ * Instance slots named after the ARGS, with matching keyword initargs, and `inst-ARG' readers. - * A constructor `make-CODE-inst' which accepts the ARGS (in order, not - with keywords) as arguments and returns a fresh instance. + * A constructor `make-CODE-inst' which accepts the ARGS (as an ordinary + BVL) as arguments and returns a fresh instance. * A print method, which prints a diagnostic dump if `*print-escape*' is set, or invokes the BODY (with STREAMVAR bound to the output stream) @@ -135,32 +138,41 @@ If EXPORT is non-nil, then export the `CODE-inst' and `make-CODE-inst' symbols." - (let ((inst-var (gensym "INST")) - (class-name (symbolicate code '-inst)) - (constructor-name (symbolicate 'make- code '-inst)) - (keys (mapcar (lambda (arg) (intern (symbol-name arg) :keyword)) - args))) + (let* ((inst-var (gensym "INST")) + (class-name (symbolicate code '-inst)) + (constructor-name (symbolicate 'make- code '-inst)) + (slots (mapcan (lambda (arg) + (if (listp arg) (list (car arg)) + (let ((name (symbol-name arg))) + (if (and (plusp (length name)) + (char/= (char name 0) #\&)) + (list arg) + nil)))) + args)) + (keys (mapcar (lambda (arg) (intern (symbol-name arg) :keyword)) + slots))) `(progn (defclass ,class-name (inst) - ,(mapcar (lambda (arg key) - `(,arg :initarg ,key :reader ,(symbolicate 'inst- arg))) - args keys)) + ,(mapcar (lambda (slot key) + `(,slot :initarg ,key + :reader ,(symbolicate 'inst- slot))) + slots keys)) (defun ,constructor-name (,@args) - (make-instance ',class-name ,@(mappend #'list keys args))) + (make-instance ',class-name ,@(mappend #'list keys slots))) (defmethod inst-metric ((,inst-var ,class-name)) - (with-slots (,@args) ,inst-var - (+ 1 ,@(mapcar (lambda (arg) `(inst-metric ,arg)) args)))) + (with-slots (,@slots) ,inst-var + (+ 1 ,@(mapcar (lambda (slot) `(inst-metric ,slot)) slots)))) (defmethod print-object ((,inst-var ,class-name) ,streamvar) - (with-slots (,@args) ,inst-var + (with-slots (,@slots) ,inst-var (if *print-escape* (print-unreadable-object (,inst-var ,streamvar :type t) (format stream "~@<~@{~S ~@_~S~^ ~_~}~:>" - ,@(mappend #'list keys args))) + ,@(mappend #'list keys slots))) (block ,code ,@body)))) ,@(and export `((export '(,class-name ,constructor-name - ,@(mapcar (lambda (arg) - (symbolicate 'inst- arg)) - args))))) + ,@(mapcar (lambda (slot) + (symbolicate 'inst- slot)) + slots))))) ',code))) ;; Formatting utilities. @@ -204,7 +216,7 @@ ;; package or the `common-lisp' package. Use gensyms for these slot names to ;; prevent them from leaking. -(definst var (stream :export t) (name #1=#:type init) +(definst var (stream :export t) (name #1=#:type &optional init) (pprint-c-type #1# stream name) (when init (format stream " = ~A" init)) @@ -225,7 +237,7 @@ (format stream "~@<~A ~A= ~@_~2I~A;~:>" var op #1#)) ;; Special kinds of expressions. -(definst call (stream :export t) (#1=#:func args) +(definst call (stream :export t) (#1=#:func &rest args) (format stream "~A(~@<~{~A~^, ~_~}~:>)" #1# args)) ;; Simple statements. @@ -242,12 +254,19 @@ (format stream "{~:@_~@< ~2I~@[~{~A~:@_~}~:@_~]~{~A~^~:@_~}~:>~:@_}" decls body)) -(definst if (stream :export t) (#1=#:cond conseq alt) - (format-compound-statement (stream conseq alt) - (format stream "if (~A)" #1#)) - (when alt - (format-compound-statement (stream alt) - (write-string "else" stream)))) +(definst if (stream :export t) (#1=#:cond conseq &optional alt) + (let ((stmt "if")) + (loop (format-compound-statement (stream conseq (if alt t nil)) + (format stream "~A (~A)" stmt #1#)) + (typecase alt + (null (return)) + (if-inst (setf stmt "else if" + #1# (inst-cond alt) + conseq (inst-conseq alt) + alt (inst-alt alt))) + (t (format-compound-statement (stream alt) + (format stream "else")) + (return)))))) (definst while (stream :export t) (#1=#:cond body) (format-compound-statement (stream body) @@ -437,6 +456,6 @@ (export 'deliver-call) (defun deliver-call (codegen target func &rest args) "Emit a statement to call FUNC with ARGS and deliver the result to TARGET." - (deliver-expr codegen target (make-call-inst func args))) + (deliver-expr codegen target (apply #'make-call-inst func args))) ;;;----- That's all, folks --------------------------------------------------