diff options
author | Juan Manuel Tomás <jtomas1815@gmail.com> | 2023-02-05 04:51:32 -0300 |
---|---|---|
committer | Juan Manuel Tomás <jtomas1815@gmail.com> | 2023-02-05 04:51:32 -0300 |
commit | bb0b4c7466f5644c5fa6133814a45f4cbd99667b (patch) | |
tree | 1bdb4be2fb8d5dfa672574dd1c1af343d5ef598c | |
parent | d4233b573d81bf659e0ecf6003de8855d9521110 (diff) | |
download | cmamut-bb0b4c7466f5644c5fa6133814a45f4cbd99667b.tar.gz cmamut-bb0b4c7466f5644c5fa6133814a45f4cbd99667b.zip |
Resolve composite dependencies
Generated code finally compiles and is usable :^)
-rw-r--r-- | cmamut.lisp | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/cmamut.lisp b/cmamut.lisp index 0c5ca0d..904241e 100644 --- a/cmamut.lisp +++ b/cmamut.lisp @@ -3,9 +3,7 @@ ; Ideas: ; Generate code that creates a package and puts all definitions there. ; To avoid collisions the created package shouldn't import any symbols. -; Only define functions from the target library, but get all other definitions. -; TODO: Order composite types so that size is known on definition. ; TODO: Get constants from macro file generated by c2ffi -M ; TODO: Use c2ffi to extract the spec.json using the header file as parameter @@ -81,7 +79,7 @@ ,(let ((function-name (gethash "name" raw-function))) (if name-transformer (list function-name (funcall name-transformer function-name)) - function-name)) + (list function-name (intern function-name)))) ,(cook-type (gethash "return-type" raw-function) type-associations) ,@(queue:to-list cooked-params)))) @@ -183,14 +181,53 @@ (push def (spec-composite spec))))) spec) +(defun gather-composite-dependencies (composite) + (let ((names (make-hash-table))) + (labels ((get-deps + (def) + (dolist (param (cddr def)) + (let ((param-type (cadr param))) + (when (listp param-type) + (cond ((or (eql (car param-type) 'sb-alien:struct) + (eql (car param-type) 'sb-alien:union)) + (setf (gethash (cadr param-type) names) t) + (get-deps param-type)) + ((and (eql (car param-type) 'sb-alien:array) + (listp (cadr param-type))) + (setf (gethash (caadr param-type) names) t) + (get-deps (cadr param-type))))))))) + (get-deps composite)) + names)) + +(defun sort-composites-by-deps (composites) + (let ((comps-and-deps (mapcar (lambda (x) + (cons x (gather-composite-dependencies x))) + composites)) + (result nil)) + (labels ((filter-deps + (cnd) + (let ((new-cnd (remove-if (lambda (x) (= (hash-table-count (cdr x)) 0)) cnd))) + (if (= (length new-cnd) (length cnd)) + result + (progn + (dolist (i cnd) + (when (= (hash-table-count (cdr i)) 0) + (push (car i) result) + (dolist (j new-cnd) + (remhash (second (car i)) (cdr j))))) + (filter-deps new-cnd)))))) + (filter-deps comps-and-deps)) + (reverse result))) + (defun codegen (spec function-filter) (let ((enum-references (generate-enum-references (spec-typedefs spec))) (type-associations (generate-type-associations (spec-typedefs spec)))) (let ((enums (mapcar (lambda (x) (cook-enum x enum-references)) (spec-enums spec))) - (composite (mapcar (lambda (x) - `(sb-alien:define-alien-type nil ,(cook-composite x type-associations))) - (spec-composite spec))) + (composite (mapcar (lambda (x) `(sb-alien:define-alien-type nil ,x)) + (sort-composites-by-deps + (mapcar (lambda (x) (cook-composite x type-associations)) + (spec-composite spec))))) (functions (mapcar (lambda (x) (cook-function x type-associations)) (remove-if-not function-filter (spec-functions spec))))) (remove-duplicates (concatenate 'list enums composite functions) :test #'equal)))) |