summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmamut.lisp49
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))))