; main declaration generator for CFFI binding (in-package "VERRAZANO-CFFI") ; the state of the backend as it processes tree fragments (defstruct cffi-state symbols) ; generate a package containing declarations for dq (defun cffi-generate-package (dq cfg) (let* ((bst (make-cffi-state :symbols (make-hash-table :test #'equal))) (decls (generate-declarations dq bst)) (stripped (strip-nils decls))) (write-declarations stripped cfg bst))) ; generate the declarations corresponding to dq (defun generate-declarations (dq bst) (map 'list #'(lambda (def) (output (car def) (cadr def) (caddr def) bst)) dq)) ; macro to ease writing matchers (defmacro generate-for ((par edg (tgtn &rest tgtl)) &rest body) (let ((st (gensym))) `(progn ,@(mapcar #'(lambda (tp) `(defmethod output (,par ,edg (,tgtn ,tp) ,st) (declare (ignorable ,st)) (macrolet ((symbol-table () `,',st) (define-symbol (n tp) `(define-symbol-full ,n ,tp nil ,',st)) (collect-output (tgt &optional kd) `(collect-output-full ,tgt ,',st ,kd))) ,@body))) tgtl)))) ; output Lisp declarations for pattern in IR (defgeneric output (par edg tgt bst)) ; by default, output nothing (generate-for ((par node) (edg edge) (tgt node)) nil) ; collect the output of edges from node (defun collect-output-full (tgt bst &optional kind) (mapcar #'(lambda (e) (when (match-optional (type-of e) kind) (output tgt e (edge-target e) bst))) (node-edges tgt))) ; add a symbol to the symbol table (defun define-symbol-full (symname symtype symval bstate) (when (not (gethash symtype (cffi-state-symbols bstate))) (setf (gethash symtype (cffi-state-symbols bstate)) (make-hash-table :test #'equal))) (setf (gethash symname (gethash symtype (cffi-state-symbols bstate))) symval))