initial import --> to head
Tue Jul 13 21:17:41 CEST 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Use libsmokebase instead of libsmokeqtcore.
hunk ./src/libsmoke/CMakeLists.txt 13
-find_library(smokeqtcore_LIB smokeqtcore)
-if (smokeqtcore_LIB)
- set(smokeqtcore_FOUND TRUE)
-endif (smokeqtcore_LIB)
+find_library(smokebase_LIB smokebase)
+if (smokebase_LIB)
+ set(smokebase_FOUND TRUE)
+endif (smokebase_LIB)
hunk ./src/libsmoke/CMakeLists.txt 18
-if (smokeqtcore_FOUND)
- message(STATUS "Found smokeqtcore: ${smokeqtcore}")
-else (smokeqtcore_FOUND)
- message(FATAL_ERROR "Could not find smokeqtcore")
-endif (smokeqtcore_FOUND)
+if (smokebase_FOUND)
+ message(STATUS "Found smokebase: ${smokebase}")
+else (smokebase_FOUND)
+ message(FATAL_ERROR "Could not find smokebase")
+endif (smokebase_FOUND)
hunk ./src/libsmoke/CMakeLists.txt 27
-target_link_libraries(clsmoke ${QT_LIBRARIES} ${smokeqtcore_LIB})
+target_link_libraries(clsmoke ${QT_LIBRARIES} ${smokebase_LIB})
Sat Apr 3 21:11:26 CEST 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* slot-value access for static attributes using the class instead of an object.
hunk ./src/overload-resolution.lisp 557
+(defmethod slot-missing (meta-class (class smoke-standard-class) slot-name operation &optional new-value)
+ (let ((method (find-smoke-method class (lisp-to-cxx (string slot-name)))))
+ (if (or (not (valid-p method)) (not (static-p method)))
+ (call-next-method)
+ (ecase operation
+ (setf [_$_]
+ (handler-case (funcall (fdefinition
+ (intern
+ (concatenate 'string "SET-"
+ (string-upcase
+ (string slot-name)))
+ :cxx))
+ class new-value)
+ (undefined-function ()
+ (error "The C++ attribute ~A of ~A is read only." slot-name class))
+ (no-applicable-cxx-method (condition)
+ (if (null (viable-functions (condition-method condition)
+ (length (condition-arguments condition))
+ (condition-class condition)))
+ (error "The C++ attribute ~A of ~A is read only." slot-name class)
+ (error condition)))))
+ (slot-boundp t)
+ (slot-makunbound (error "Can not unbind the C++ attribute ~A of ~A." slot-name class))
+ (slot-value (s-call method (null-pointer)))))))
+
hunk ./src/overload-resolution.lisp 583
- (let ((method (find-smoke-method (class-of object) (lisp-to-cxx (string slot-name)))))
+ (let ((method (find-smoke-method class (lisp-to-cxx (string slot-name)))))
Sat Apr 3 14:04:39 CEST 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Make the slot-* functions work for C++ class attributes.
Allow slot-value to be used to access C++ member variables of objects.
hunk ./src/objects/stack.lisp 143
- (get-class type))
+ (get-class type))
hunk ./src/objects/stack.lisp 146
- (cerror "Remove the old object."
- "The object at pointer ~A is ~A but should be a ~A."
- object (get-object object) type)
- (remove-object object)
+ (when (stack-p type)
+ ;; The first member varible of a class can have the
+ ;; same address as its object.
+ ;; e.g.: QSharedData::ref
+ (cerror "Remove the old object."
+ "The object at pointer ~A is ~A but should be a ~A."
+ object (get-object object) type)
+ (remove-object object))
hunk ./src/overload-resolution.lisp 532
-
hunk ./src/overload-resolution.lisp 556
+
+(defmethod slot-missing ((class smoke-standard-class) object slot-name operation &optional new-value)
+ (let ((method (find-smoke-method (class-of object) (lisp-to-cxx (string slot-name)))))
+ (if (not (valid-p method))
+ (call-next-method)
+ (ecase operation
+ (setf [_$_]
+ (handler-case (funcall (fdefinition
+ (intern
+ (concatenate 'string "SET-"
+ (string-upcase
+ (string slot-name)))
+ :cxx))
+ object new-value)
+ (undefined-function ()
+ (error "The C++ attribute ~A of ~A is read only." slot-name object))
+ (no-applicable-cxx-method (condition)
+ (if (null (viable-functions (condition-method condition)
+ (length (condition-arguments condition))
+ (condition-class condition)))
+ (error "The C++ attribute ~A of ~A is read only." slot-name object)
+ (error condition)))))
+ (slot-boundp t)
+ (slot-makunbound (error "Can not unbind the C++ attribute ~A of ~A." slot-name object))
+ (slot-value (s-call method (cast object (get-class method))))))))
Sat Apr 3 14:03:07 CEST 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix attribute vs method map to same Lisp name clash.
e.g.: setWidget() and set_widget are in Lisp both #'set-widget. Prefer the method
over the attribute; the attribute will be accessible with SLOT-VALUE.
hunk ./src/smoke-to-clos.lisp 141
- (setf (gethash (lispify name "CXX") generics)
- name))
+ (let ((lisp-name (lispify name "CXX")))
+ (unless (and (gethash lisp-name generics) (attribute-p method))
+ (setf (gethash lisp-name generics) name))))
Wed Mar 10 17:38:58 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Improve missing to-lisp-translator error message.
hunk ./src/objects/stack.lisp 115
- (cerror "Return the pointer"
- "Do not know how to convert the type ~A to Lisp." type))))
+ (cerror "Return the pointer"
+ "Missing type translator to convert the type ~A to Lisp."
+ type))))
Sat Feb 20 21:56:27 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Allow passing integers as enum arguments.
hunk ./src/overload-resolution.lisp 372
-(defun coerce-enum (enum)
+(defun coerce-from-enum (enum)
hunk ./src/overload-resolution.lisp 381
+(defun coerce-to-enum (number)
+ ;; we can skip the enum type because it is not checked at this
+ ;; point.
+ (make-instance 'enum :value number))
+
hunk ./src/overload-resolution.lisp 394
- (make-match 'promotion 'coerce-enum)))
+ (make-match 'promotion 'coerce-from-enum)))
hunk ./src/overload-resolution.lisp 396
- (make-match 'promotion 'coerce-enum)))
+ (make-match 'promotion 'coerce-from-enum)))
hunk ./src/overload-resolution.lisp 400
- (make-match 'promotion 'coerce-double-float)))))
+ (make-match 'promotion 'coerce-double-float)))
+ (12 (when (object.typep '(integer 0))
+ (make-match 'promotion 'coerce-to-enum)))))
Sat Feb 20 19:01:21 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix overload resolution exact match for long and ulong.
hunk ./src/overload-resolution.lisp 343
- (8 (object.typep '(c-integer :long)))
- (9 (object.typep '(c-integer :unsigned-long)))
+ (8 (object.typep '(and (c-integer :long)
+ (not (c-integer :int)))))
+ (9 (object.typep '(and (c-integer :unsigned-long)
+ (not (c-integer :unsigned-int)))))
Sat Feb 20 18:56:48 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Faster no overload resolution method lookup.
hunk ./src/libsmoke/smoke.cpp 198
- *m = get_smoke(smoke)->findMethod(class_name, method_name);
+ Smoke::ModuleIndex id_class(get_smoke(smoke), class_index);
+
+ Smoke::ModuleIndex id_method_name = get_smoke(smoke)->findMethodName(class_name, method_name);
+ *m = get_smoke(smoke)->findMethod(id_class, id_method_name);
Sat Feb 20 18:24:36 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Cache overload resolution on sbcl
hunk ./src/clos.lisp 464
- (find-best-viable-function (constructor-name class)
- arguments
- class)
+ (#-sbcl find-best-viable-function
+ #+sbcl find-best-viable-function-cached
+ (constructor-name class)
+ arguments
+ class nil)
hunk ./src/objects/type.lisp 122
+ (declare (optimize (speed 3)))
hunk ./src/objects/type.lisp 124
- (foreign-slot-pointer [_$_]
- (mem-aref (smoke-array-pointer
- (smoke-module-types (smoke type)))
- 'smoke-type
- (the smoke-index (id type)))
- 'smoke-type 'name)
- :pointer)))
+ (foreign-slot-pointer [_$_]
+ (mem-aref (smoke-array-pointer
+ (smoke-module-types (smoke type)))
+ 'smoke-type
+ (the smoke-index (id type)))
+ 'smoke-type 'name)
+ :pointer)))
hunk ./src/overload-resolution.lisp 198
-(eval-when (:compile-toplevel :load-toplevel :execute)
- (defun conversion-function (name &optional arg)
- (if arg
- `(if (using-typep)
- `(,,name
- (find-class ',(class-name ,arg)))
- #'(lambda (object)
- (funcall (fdefinition ,name)
- object ,arg)))
- `(if (using-typep)
- ,name
- (fdefinition ,name)))))
-
hunk ./src/overload-resolution.lisp 200
- `(,(symbolicate 'make- (eval type))
- :function-name ,(conversion-function name argument)
- ,@args))
+ (flet ((conversion-function (name &optional arg)
+ (if arg
+ `(if (using-typep)
+ `(,,name
+ ,(if (typep ,arg 'class)
+ `(find-class ',(class-name ,arg))
+ `(find-smoke-method (find-class ,(class-name
+ (find-smoke-class
+ (get-class ,arg))))
+ ,(name ,arg))))
+ #'(lambda (object)
+ (funcall (fdefinition ,name)
+ object ,arg)))
+ `(if (using-typep)
+ ,name
+ (fdefinition ,name)))))
+ `(,(symbolicate 'make- (eval type))
+ :function-name ,(conversion-function name argument)
+ ,@args)))
hunk ./src/overload-resolution.lisp 310
- (subtypep type ',lisp-type)
+ (multiple-value-bind (value valid-p)
+ (subtypep type ',lisp-type)
+ (unless valid-p
+ (throw 'unspecific-type type))
+ value)
hunk ./src/overload-resolution.lisp 347
- (12 (and (object.typep 'enum) ;; FIXME enum-type using type
- (smoke-type= type (enum-type object))))
+ (12 (when (object.typep 'enum)
+ (when (using-typep)
+ (throw 'unspecific-type object))
+ (smoke-type= type (enum-type object))))
hunk ./src/overload-resolution.lisp 530
- (find-best-viable-function name
- arguments
- (smoke-class-of object-or-class)
- (when (typep object-or-class
- 'smoke-standard-object)
- (const-p object-or-class)))
+ (#-sbcl find-best-viable-function
+ #+sbcl find-best-viable-function-cached
+ name
+ arguments
+ (smoke-class-of object-or-class)
+ (when (typep object-or-class
+ 'smoke-standard-object)
+ (const-p object-or-class)))
hunk ./src/overload-resolution.lisp 543
- (if (static-p method)
- (apply #'call-sequence method (null-pointer) sequence arguments)
- (apply #'call-sequence method (cast object-or-class (get-class method)) [_$_]
- sequence arguments))))
+ (apply #'call-sequence method
+ (if (static-p method)
+ (null-pointer)
+ (cast object-or-class (get-class method)))
+ sequence arguments)))
hunk ./src/sb-optimize.lisp 95
-;;; cache ==================================================================
+;;; Cache overload resolution / method lookup
+
+;;; FIXME the cached lookup should be faster
hunk ./src/sb-optimize.lisp 99
-;;; we could replace the call to #'find-best-viable-function in
-;;; #'call-using-args with a call to
-;;; #'find-best-viable-function-cached, but it is only doubles speed.
+;;; cache return value conversion
+;;;
+;;; Using the gf symbol instead of the method name would be better,
+;;; althoug we would have to invent one for constructors.
+;;;
+;;; Since the -using-types stuff was intended for for compile time
+;;; expansion it is not that well suited for this. i.e. passing
+;;; closures would be better than the actual syntax.
+;;;
+;;; For qt.tests the uncached calls make up 30 % of all calls.
+;;; qt.examples:colliding-mice (run for ~1 min) gets 20 % uncached
+;;; calls and qt.examples:class-browser get 10 %. (20 February 2010)
hunk ./src/sb-optimize.lisp 112
-(sb-int:defun-cached (find-best-viable-function-using-types-cached
+(sb-int:defun-cached (find-best-viable-function-using-layouts-cached
hunk ./src/sb-optimize.lisp 117
- (class class)
+ (sb-c::layout class)
hunk ./src/sb-optimize.lisp 122
- (sxhash arguments)
+ (the fixnum
+ (reduce [_$_]
+ #'logxor
+ (mapcar #'sb-c::layout-clos-hash
+ arguments)))
hunk ./src/sb-optimize.lisp 135
- (find-best-viable-function-using-types name arguments class const-p)
+ (find-best-viable-function-using-types
+ name (mapcar #'sb-pcl::wrapper-class* arguments)
+ class const-p)
hunk ./src/sb-optimize.lisp 142
+ (declare (optimize (speed 3)))
hunk ./src/sb-optimize.lisp 145
- (second s)))))
+ (eval (second s))))))
hunk ./src/sb-optimize.lisp 147
- [_$_]
+
hunk ./src/sb-optimize.lisp 154
- (find-best-viable-function-using-types-cached
+ (find-best-viable-function-using-layouts-cached
hunk ./src/sb-optimize.lisp 156
- (mapcar #'(lambda (o) (class-of o)) arguments)
+ (mapcar #'(lambda (o) (sb-c::layout-of o)) arguments)
Fri Feb 19 22:22:50 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* cleanup #'delete-object & optimize #'constructor-name.
hunk ./src/clos.lisp 455
- (let ((name-start (search "::" (name class) :from-end t)))
+ (declare (optimize (speed 3)))
+ (let* ((name (the simple-string (name class)))
+ (name-start (search "::" name :from-end t)))
hunk ./src/clos.lisp 459
- (subseq (name class) (+ name-start 2))
- (name class))))
+ (subseq name (+ name-start 2))
+ name)))
hunk ./src/smoke.lisp 76
- (let ((method-name (concatenate 'string "~" (name (class-of object)))))
- (s-call
- (make-smoke-method-from-name (class-of object) method-name)
- (pointer object)))
+ (delete-pointer (pointer object) (class-of object))
Fri Feb 19 22:10:24 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* No need to construct a SmokeBinding per Smoke module.
hunk ./src/bindings.lisp 8
-
hunk ./src/bindings.lisp 10
- (binding (null-pointer) :type foreign-pointer)
- (no-dispatch-binding (null-pointer) :type foreign-pointer)
hunk ./src/clos.lisp 340
- ((binding :pointer)
- (method smoke-index)
+ ((method smoke-index)
hunk ./src/clos.lisp 351
- :smoke (gethash (pointer-address
- (smoke-get-smoke binding))
- *smoke-modules*)
+ :smoke (smoke (class-of object))
hunk ./src/libsmoke/smoke.cpp 15
-/** Returns the Smoke module of a Smoke binding.
- * @related cl_smoke::Binding
- * @param binding the Binding
- *
- * @return the Smoke module
- */
-CL_SMOKE_EXPORT void*
-cl_smoke_get_smoke(smoke_binding binding)
-{
- return static_cast<NoDispatchBinding*>(binding)->get_smoke();
-}
-
hunk ./src/libsmoke/smoke.cpp 28
-cl_smoke_construct_binding(void* smoke, void* destruct, void* dispatch)
+cl_smoke_construct_binding(void* destruct, void* dispatch)
hunk ./src/libsmoke/smoke.cpp 31
- return new NoDispatchBinding(static_cast<Smoke*>(smoke),
- reinterpret_cast<NoDispatchBinding::destructed>(destruct));
+ return new NoDispatchBinding(reinterpret_cast<NoDispatchBinding::destructed>(destruct));
hunk ./src/libsmoke/smoke.cpp 33
- return new Binding(static_cast<Smoke*>(smoke),
- reinterpret_cast<NoDispatchBinding::destructed>(destruct),
+ return new Binding(reinterpret_cast<NoDispatchBinding::destructed>(destruct),
hunk ./src/libsmoke/smoke.cpp 187
- * @param smoke the smoke binding
+ * @param smoke the smoke module
hunk ./src/libsmoke/smoke.lisp 41
- (smoke :pointer)
hunk ./src/libsmoke/smoke.lisp 53
-(declaim (inline smoke-get-smoke))
-(defcfun (smoke-get-smoke "cl_smoke_get_smoke") :pointer
- (smoke-binding smoke-binding))
-
hunk ./src/libsmoke/smokebinding.cpp 26
- * @param smoke the Smoke module
hunk ./src/libsmoke/smokebinding.cpp 28
-NoDispatchBinding::NoDispatchBinding(Smoke *smoke, destructed destruct)
- : SmokeBinding(smoke),
+NoDispatchBinding::NoDispatchBinding(destructed destruct)
+ : SmokeBinding(NULL),
hunk ./src/libsmoke/smokebinding.cpp 57
- Q_ASSERT(classId >= 0 && classId <= smoke->numClasses);
- return const_cast<char*>(smoke->classes[classId].className);
+ qFatal("className() Not implemented");
hunk ./src/libsmoke/smokebinding.cpp 83
- * @param smoke the Smoke module
hunk ./src/libsmoke/smokebinding.cpp 86
-Binding::Binding(Smoke *smoke, destructed destruct,
- dispatch_method dispatch)
- : NoDispatchBinding(smoke, destruct),
+Binding::Binding(destructed destruct, dispatch_method dispatch)
+ : NoDispatchBinding(destruct),
hunk ./src/libsmoke/smokebinding.cpp 99
- int ret = dispatch(this, method, object, stack, abstract);
+ int ret = dispatch(method, object, stack, abstract);
hunk ./src/libsmoke/smokebinding.h 14
- NoDispatchBinding(Smoke *smoke, destructed destruct);
+ NoDispatchBinding(destructed destruct);
hunk ./src/libsmoke/smokebinding.h 26
- Smoke*
- get_smoke() const
- { return smoke; }
-
hunk ./src/libsmoke/smokebinding.h 33
- typedef int (*dispatch_method)(Binding* binding, Smoke::Index method,
+ typedef int (*dispatch_method)(Smoke::Index method,
hunk ./src/libsmoke/smokebinding.h 36
- Binding(Smoke *smoke, destructed destruct, dispatch_method dispatch);
+ Binding(destructed destruct, dispatch_method dispatch);
hunk ./src/smoke.lisp 82
+(eval-startup (:load-toplevel :execute)
+ (defparameter *binding* (smoke-construct-binding
+ (callback destructed)
+ (callback dispatch-method)))
+ (defparameter *no-dispatch-binding* (smoke-construct-binding
+ (callback destructed)
+ (null-pointer))))
+
hunk ./src/smoke.lisp 98
- (smoke-module-binding (smoke class))
- (smoke-module-no-dispatch-binding (smoke class))))
+ *binding*
+ *no-dispatch-binding*))
hunk ./src/smoke.lisp 112
- (let ((no-dispatch-binding
- (smoke-construct-binding smoke (callback destructed) (null-pointer)))
- (binding (smoke-construct-binding smoke (callback destructed)
- (callback dispatch-method))))
- (setf (smoke-module-pointer module) smoke
- (smoke-module-no-dispatch-binding module) no-dispatch-binding
- (smoke-module-binding module) binding)
- (init-smoke-module module)
- (setf (gethash (pointer-address smoke) *smoke-modules*) module)
- module))
+ (setf (smoke-module-pointer module) smoke)
+ (init-smoke-module module)
+ (setf (gethash (pointer-address smoke) *smoke-modules*) module)
+ module)
Thu Feb 18 20:57:00 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Don't dispatch virtual methods for builtin classes (reduces overhead).
hunk ./src/bindings.lisp 12
+ (no-dispatch-binding (null-pointer) :type foreign-pointer)
hunk ./src/clos.lisp 350
- (when (and object (typep (class-of object) 'cxx:class))
- ;; Do not allow overwriting methods of classes the users has
- ;; not derived from (like in C++), to reduce overhead.
+ (unless (null object)
hunk ./src/libsmoke/cl_smoke.h 37
-/** Casts the void pointer smoke_binding to the Binding class.
- * @param smoke the smoke binding
- *
- * @return pointer to the Binding instance
- */
-static inline
-Binding*
-get_smoke_binding(smoke_binding binding)
-{
- return static_cast<Binding*>(binding);
-}
-
hunk ./src/libsmoke/class.lisp 8
+ (:namespace #x08)
hunk ./src/libsmoke/class.lisp 25
+(declaim (inline smoke-class-id))
hunk ./src/libsmoke/smoke.cpp 24
- return get_smoke_binding(binding)->get_smoke();
+ return static_cast<NoDispatchBinding*>(binding)->get_smoke();
hunk ./src/libsmoke/smoke.cpp 29
+ * When method dispatching is not needed, a null pointer can be passed for @a dispatch.
hunk ./src/libsmoke/smoke.cpp 31
+ * @related cl_smoke::NoDispatchBinding
+ * @related cl_smoke_destruct_binding
hunk ./src/libsmoke/smoke.cpp 40
-cl_smoke_init(void* smoke, void* destruct, void* dispatch)
+cl_smoke_construct_binding(void* smoke, void* destruct, void* dispatch)
hunk ./src/libsmoke/smoke.cpp 42
- return new Binding(static_cast<Smoke*>(smoke),
- reinterpret_cast<Binding::destructed>(destruct),
- reinterpret_cast<Binding::dispatch_method>(dispatch));
+ if (NULL == dispatch)
+ return new NoDispatchBinding(static_cast<Smoke*>(smoke),
+ reinterpret_cast<NoDispatchBinding::destructed>(destruct));
+ else
+ return new Binding(static_cast<Smoke*>(smoke),
+ reinterpret_cast<NoDispatchBinding::destructed>(destruct),
+ reinterpret_cast<Binding::dispatch_method>(dispatch));
hunk ./src/libsmoke/smoke.cpp 51
-/** Deletes the smoke binding.
- * @related cl_smoke::Binding
+/** Deletes the Smoke binding.
+ * @related cl_smoke_construct_binding
hunk ./src/libsmoke/smoke.cpp 55
-cl_smoke_destruct(smoke_binding binding)
+cl_smoke_destruct_binding(smoke_binding binding)
hunk ./src/libsmoke/smoke.cpp 57
- delete get_smoke_binding(binding)->get_smoke();
- delete get_smoke_binding(binding);
+ // Destructor is virtual; thus we can do this.
+ delete static_cast<SmokeBinding*>(binding);
hunk ./src/libsmoke/smoke.cpp 61
-/** Gets a Smoke modules name.
+/** Gets a Smoke module name.
hunk ./src/libsmoke/smoke.cpp 209
- *m = get_smoke(smoke)->findMethod(get_smoke(smoke)->className(class_index),
- method_name);
+ Q_ASSERT(class_index >= 0 && class_index <= get_smoke(smoke)->numClasses);
+
+ const char* class_name = get_smoke(smoke)->className(class_index);
+ *m = get_smoke(smoke)->findMethod(class_name, method_name);
+
hunk ./src/libsmoke/smoke.cpp 236
- * @param object the objec
+ * @param object the object
hunk ./src/libsmoke/smoke.lisp 40
-(defcfun (smoke-init "cl_smoke_init") smoke-binding
+(defcfun (smoke-construct-binding "cl_smoke_construct_binding") smoke-binding
hunk ./src/libsmoke/smoke.lisp 45
-(defcfun (smoke-destruct "cl_smoke_destruct") :void
+(defcfun (smoke-destruct-destruct "cl_smoke_destruct_binding") :void
hunk ./src/libsmoke/smokebinding.cpp 9
-/** @class Binding
- * @brief The Smoke binding.
+/** @class NoDispatchBinding
+ * @brief The Smoke binding for classes we need no dispatching.
+ * This saves some overhead, since it does not call into Lisp.
+ * Idea stolen from CommonQt ;)
+ *
+ * Dispatches for non extended classes (not of class CXX:CLASS) are between
+ * 20% - 40% (for qt.examples:colliding-mice - qt.examples:class-browser). (18 February 2010)
hunk ./src/libsmoke/smokebinding.cpp 18
-
-/** @typedef Binding::destructed
+/** @typedef NoDispatchBinding::destructed
hunk ./src/libsmoke/smokebinding.cpp 25
+/** Constructor.
+ * @param smoke the Smoke module
+ * @param destruct destruct callback
+ */
+NoDispatchBinding::NoDispatchBinding(Smoke *smoke, destructed destruct)
+ : SmokeBinding(smoke),
+ destruct(destruct)
+{
+ Q_ASSERT(destruct);
+}
+
+/** Invoked when a Smoke object is destructed. */
+void
+NoDispatchBinding::deleted(Smoke::Index, void *object)
+{
+ destruct(object);
+}
+
+/** Invoked when a Smoke method gets called. */
+bool
+NoDispatchBinding::callMethod(Smoke::Index method, void* object,
+ Smoke::Stack stack, bool abstract)
+{
+ Q_ASSERT(!abstract);
+ return false;
+}
+
+/**
+ * @todo Returning a const char* would be better
+ */
+char*
+NoDispatchBinding::className(Smoke::Index classId)
+{
+ Q_ASSERT(classId >= 0 && classId <= smoke->numClasses);
+ return const_cast<char*>(smoke->classes[classId].className);
+}
+
+/** @function NoDispatchBinding::get_smoke()
+ * Gets the Smoke instance associated with the binding.
+ * @return a pointer to the Smoke instance
+ */
+
+/** @class Binding
+ * @brief The Smoke binding.
+ */
hunk ./src/libsmoke/smokebinding.cpp 91
- : SmokeBinding(smoke),
- destruct(destruct),
+ : NoDispatchBinding(smoke, destruct),
hunk ./src/libsmoke/smokebinding.cpp 94
- Q_ASSERT(smoke);
- Q_ASSERT(destruct);
hunk ./src/libsmoke/smokebinding.cpp 97
-/** Invoked when a Smoke object is destructed. */
-void
-Binding::deleted(Smoke::Index, void *object)
-{
- destruct(object);
-}
hunk ./src/libsmoke/smokebinding.cpp 109
-/**
- * @todo Returning a const char* would be better
- */
-char*
-Binding::className(Smoke::Index classId)
-{
- return const_cast<char*>(smoke->classes[classId].className);
-}
-
-/** Gets the Smoke instance associated with the binding.
- * @return a pointer to the Smoke instance
- */
-Smoke*
-Binding::get_smoke() const
-{
- return smoke;
-}
-
hunk ./src/libsmoke/smokebinding.h 9
-class Binding : public SmokeBinding
+class NoDispatchBinding : public SmokeBinding
hunk ./src/libsmoke/smokebinding.h 14
- typedef int (*dispatch_method)(Binding* binding, Smoke::Index method,
- void* object, Smoke::Stack args, int abstract);
-
- Binding(Smoke *smoke, destructed destruct, dispatch_method dispatch);
+ NoDispatchBinding(Smoke *smoke, destructed destruct);
hunk ./src/libsmoke/smokebinding.h 27
- get_smoke() const;
+ get_smoke() const
+ { return smoke; }
hunk ./src/libsmoke/smokebinding.h 32
+};
+
+class Binding : public NoDispatchBinding
+{
+ public:
+ typedef int (*dispatch_method)(Binding* binding, Smoke::Index method,
+ void* object, Smoke::Stack args, int abstract);
+
+ Binding(Smoke *smoke, destructed destruct, dispatch_method dispatch);
+
+
+ virtual bool
+ callMethod(Smoke::Index method, void* object,
+ Smoke::Stack stack, bool abstract);
+
+
+ private:
hunk ./src/smoke.lisp 85
- (with-foreign-object (stack 'smoke-stack-item 2)
- (setf (foreign-slot-value (mem-aref stack 'smoke-stack-item 1)
- 'smoke-stack-item 'voidp)
- (smoke-module-binding (smoke (class-of object))))
- (foreign-funcall-pointer [_$_]
- (foreign-slot-value (smoke-class-pointer (class-of object))
- 'smoke-class 'class-function)
- ()
- smoke-index 0 ;; set binding method index
- :pointer (pointer object)
- smoke-stack stack
- :void)))
+ (let ((class (class-of object)))
+ (with-foreign-object (stack 'smoke-stack-item 2)
+ (setf (foreign-slot-value (mem-aref stack 'smoke-stack-item 1)
+ 'smoke-stack-item 'voidp)
+ (if (typep class 'cxx:class)
+ (smoke-module-binding (smoke class))
+ (smoke-module-no-dispatch-binding (smoke class))))
+ (foreign-funcall-pointer [_$_]
+ (foreign-slot-value (smoke-class-pointer class)
+ 'smoke-class 'class-function)
+ ()
+ smoke-index 0 ;; set binding method index
+ :pointer (pointer object)
+ smoke-stack stack
+ :void))))
hunk ./src/smoke.lisp 104
- (let* ((binding (smoke-init smoke (callback destructed)
- (callback dispatch-method))))
+ (let ((no-dispatch-binding
+ (smoke-construct-binding smoke (callback destructed) (null-pointer)))
+ (binding (smoke-construct-binding smoke (callback destructed)
+ (callback dispatch-method))))
hunk ./src/smoke.lisp 109
+ (smoke-module-no-dispatch-binding module) no-dispatch-binding
Thu Feb 18 19:31:47 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix casting across Smoke modules.
hunk ./src/clos.lisp 434
- (id (class-of object)) (id class)))
+ (id (class-of object))
+ (smoke-class-id (smoke-module-pointer (smoke (class-of object)))
+ (name-pointer class))))
hunk ./src/objects/class.lisp 33
+(defun name-pointer (class)
+ (mem-ref (foreign-slot-pointer (smoke-class-pointer class)
+ 'smoke-class 'name)
+ :pointer))
+
Wed Feb 17 18:05:35 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Remove underlinking of libclsmoke and add a darwin case to the library definitons.
Thanks to Elliott Slaughter
hunk ./src/libsmoke/CMakeLists.txt 11
+
+# FIXME look for smoke.h
+find_library(smokeqtcore_LIB smokeqtcore)
+if (smokeqtcore_LIB)
+ set(smokeqtcore_FOUND TRUE)
+endif (smokeqtcore_LIB)
+
+if (smokeqtcore_FOUND)
+ message(STATUS "Found smokeqtcore: ${smokeqtcore}")
+else (smokeqtcore_FOUND)
+ message(FATAL_ERROR "Could not find smokeqtcore")
+endif (smokeqtcore_FOUND)
+
+
hunk ./src/libsmoke/CMakeLists.txt 27
+target_link_libraries(clsmoke ${QT_LIBRARIES} ${smokeqtcore_LIB})
hunk ./src/libsmoke/CMakeLists.txt 39
-install(TARGETS clsmoke clsmokeutil
- LIBRARY DESTINATION lib)
+install(TARGETS clsmoke clsmokeutil DESTINATION lib)
hunk ./src/libsmoke/smoke.lisp 3
-;; Load the qt smoke binding to prevent undefined aliens.
hunk ./src/libsmoke/smoke.lisp 4
- (define-foreign-library libsmokeqtcore
- (:unix "libsmokeqtcore.so.3")
- (t (:default "libsmokeqtcore")))
hunk ./src/libsmoke/smoke.lisp 5
+ (:darwin "libclsmoke.dylib")
hunk ./src/libsmoke/smoke.lisp 9
+ (:darwin "libclsmokeutil.dylib")
hunk ./src/libsmoke/smoke.lisp 12
- (use-foreign-library libsmokeqtcore)
hunk ./src/libsmoke/smoke.lisp 14
-
hunk ./src/smoke.lisp 175
+ (:darwin ,(format nil "~(~A~).3.dylib" library))
Tue Feb 16 22:56:19 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Load libsmokeqtcore instead of qt in the default case of cffi:define-foreign-library.
hunk ./src/libsmoke/smoke.lisp 5
- (define-foreign-library libsmokeqt
+ (define-foreign-library libsmokeqtcore
hunk ./src/libsmoke/smoke.lisp 7
- (t (:default "libsmokeqt")))
+ (t (:default "libsmokeqtcore")))
hunk ./src/libsmoke/smoke.lisp 14
- (use-foreign-library libsmokeqt)
+ (use-foreign-library libsmokeqtcore)
Tue Feb 16 22:52:02 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix derived-p for classes that are external in every module.
hunk ./src/objects/class.lisp 110
- (handler-case (make-smoke-class (name class))
- (undefined-class () class))
+ (make-smoke-class (name class))
hunk ./src/objects/class.lisp 119
-;(defun smoke-subclassp (class base-class) TODO
hunk ./src/objects/class.lisp 121
- (values
- (derived-real-p (real-class class) (real-class base-class))
- T))
+ (handler-case (derived-real-p (real-class class) (real-class base-class))
+ ;; The class is external in every module => no derived.
+ (undefined-class () nil)))
Mon Feb 15 16:31:33 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Build a shared library not a module.
Fixes on build error on OS X as reported by Elliott Slaughter.
hunk ./src/libsmoke/CMakeLists.txt 12
-add_library(clsmoke MODULE ${SMOKE_C_SOURCES})
+add_library(clsmoke SHARED ${SMOKE_C_SOURCES})
hunk ./src/libsmoke/CMakeLists.txt 18
-add_library(clsmokeutil MODULE smoke_util.cpp)
+add_library(clsmokeutil SHARED smoke_util.cpp)
Mon Feb 8 18:14:54 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* sbcl-bundle requires posix & unix
hunk ./cl-smoke.smoke.asd 10
- #+sbcl :sb-posix)
+ #+(and sbcl unix) :sb-posix)
hunk ./cl-smoke.smoke.asd 48
- #+sbcl (:file "sbcl-bundle")
+ #+(and sbcl unix) (:file "sbcl-bundle")
Thu Feb 4 16:11:29 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Test building libclsmoke.
hunk ./test.lisp 2
+cmake ./ || exit 1
+make || exit 1
Wed Feb 3 17:20:56 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix compiling libclsmoke with asserts enabled.
smoke_get_class was not declared in this scope
Reported by:
Elliott Slaughter
hunk ./src/libsmoke/smoke.cpp 181
- Q_ASSERT(!smoke_get_class(smoke, class_index)->external);
- Q_ASSERT(!smoke_get_class(smoke_base, base_index)->external);
+ Q_ASSERT(!cl_smoke_get_class(smoke, class_index)->external);
+ Q_ASSERT(!cl_smoke_get_class(smoke_base, base_index)->external);
Wed Feb 3 07:44:09 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Add missing :sb-posix dependency.
hunk ./cl-smoke.smoke.asd 9
- (:cffi :closer-mop :alexandria :trivial-garbage :bordeaux-threads)
+ (:cffi :closer-mop :alexandria :trivial-garbage :bordeaux-threads
+ #+sbcl :sb-posix)
Sat Jan 30 15:40:08 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Do not warn on missing parent class.
hunk ./src/clos.lisp 201
- (if real-class
- (push (class-name real-class) class-symbols)
- (warn "The class ~A could not be found in any module."
- (name class))))
+ (when real-class
+ (push (class-name real-class) class-symbols)))
Tue Jan 26 17:26:09 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix for r1077826. Not instantiable parent classes are external. (QAbstractPrintDialog)
hunk ./src/clos.lisp 196
-(defun smoke-class-symbol (smoke-class)
- "Returns the Lisp class-name of SMOKE-CLASS:"
- (if (external-p smoke-class)
- (class-name (find-smoke-class smoke-class))
- (lispify (name smoke-class))))
+(defun smoke-class-symbols (classes)
+ (let ((class-symbols))
+ (dolist (class classes class-symbols)
+ (if (external-p class)
+ (let ((real-class (find-smoke-class class nil)))
+ (if real-class
+ (push (class-name real-class) class-symbols)
+ (warn "The class ~A could not be found in any module."
+ (name class))))
+ (push (lispify (name class)) class-symbols)))))
hunk ./src/clos.lisp 227
- (mapcar #'smoke-class-symbol
- (smoke-class-direct-superclasses class))
+ (smoke-class-symbols
+ (smoke-class-direct-superclasses class))
Mon Jan 25 19:47:00 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Check enum type on overload resolution
hunk ./src/overload-resolution.lisp 340
- (12 (object.typep 'enum)) ;; FIXME enum-type
+ (12 (and (object.typep 'enum) ;; FIXME enum-type using type
+ (smoke-type= type (enum-type object))))
Mon Jan 25 19:46:41 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* single-float conversion
hunk ./src/overload-resolution.lisp 366
+(defun coerce-single-float (number)
+ (float number 0f0))
+
hunk ./src/overload-resolution.lisp 380
+ (10 (when (object.typep 'real)
+ (make-match 'promotion 'coerce-single-float)))
Mon Jan 25 19:41:22 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Add :arg3 for make-instance SMOKE-CLASS.
hunk ./src/clos.lisp 478
+ (arg3 nil arg3p)
hunk ./src/clos.lisp 493
+ (arg3p (list arg0 arg1 arg2 arg3))
Sat Jan 23 20:45:41 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* class & type size (and some more exports)
hunk ./src/objects/class.lisp 33
+(defun class-size (smoke-class)
+ (class-slot-value smoke-class 'size))
+
hunk ./src/objects/class.lisp 62
+(defun copy-constructor-p (class)
+ (/= 0 (get-class-flag class :copy-constructor)))
+
hunk ./src/objects/stack.lisp 114
- (error "Do not know how to convert the type ~A to Lisp." type)))
+ (prog1 (foreign-slot-value stack-item 'smoke-stack-item 'voidp)
+ (cerror "Return the pointer"
+ "Do not know how to convert the type ~A to Lisp." type))))
hunk ./src/objects/type.lisp 142
+;; Return the cffi keyword for the type
+(defun type-foreign-keyword (smoke-type)
+ (intern (nsubstitute #\- #\ (nstring-upcase (name smoke-type)))
+ :keyword))
+
+(defun type-size (smoke-type)
+ (if (class-p smoke-type)
+ (class-size (get-class smoke-type))
+ (foreign-type-size (type-foreign-keyword smoke-type))))
+
hunk ./src/package.lisp 16
- (:export #:init
- #:get-smoke-variable-for-pointer
+ (:export #:call
+ #:c-integer
hunk ./src/package.lisp 19
- #:make-smoke-classes
- #:eval-startup
- [_$_]
- #:delete-object
- #:smoke-call
- #:call
-
- #:name
+ #:class-p
+ #:class-size
+ #:const-p
hunk ./src/package.lisp 23
- #:smoke-type=
+ #:name
+ #:pointer
+ #:pointer-p
+ #:size
+ #:smoke
+ #:stack-p
+ #:type-foreign-keyword
+ #:type-id
+ #:type-size
+ #:virtual-destructor-p
hunk ./src/package.lisp 34
+ #:convert-argument
hunk ./src/package.lisp 39
+ #:*to-lisp-translations*
+
hunk ./src/package.lisp 42
- #:make-cleanup-pointer
+ #:define-smoke-module
+
+ #:define-takes-ownership
+ #:delete-object
+ #:remove-object
+
+ #:eval-startup
+
+ #:get-smoke-variable-for-pointer
+ #:init
+ #:object-to-lisp
+
hunk ./src/package.lisp 55
+ #:make-cleanup-pointer
hunk ./src/package.lisp 57
- #:const-p
- #:pointer
- #:define-smoke-module
- #:define-takes-ownership
+ #:make-smoke-classes
+ #:make-smoke-type
+ #:no-applicable-cxx-method
+ #:smoke-call
+ #:upcast
+
+ #:smoke-standard-object
+ #:smoke-type
+ #:smoke-type=
hunk ./src/smoke-to-clos.lisp 169
- ;; FIXME when loading the Lisp image we no longer need to
- ;; call #'ensure-class, but the class-map needs still
+ ;; FIXME when loading the Lisp image we no longer need
+ ;; to call #'ensure-class, but the class-map needs still
Sun Jan 17 22:04:08 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix class-map image loading and use the new static smoke methods.
indClass() and isDerivedFrom() are now static (r1076132 and also in KDE 4.4).
hunk ./src/class-map.lisp 11
- (assert value ()
- "Unknown smoke module ~A ~A."
- smoke (smoke-get-module-name (smoke-module-pointer smoke)))
+ (assert value () "Unknown smoke module ~A." smoke)
hunk ./src/libsmoke/class.lisp 22
- (smoke :pointer)
hunk ./src/libsmoke/smoke.cpp 133
- * @param smoke the smoke module
hunk ./src/libsmoke/smoke.cpp 136
-cl_smoke_find_class(Smoke::ModuleIndex* c, void* smoke, const char* name)
+cl_smoke_find_class(Smoke::ModuleIndex* c, const char* name)
hunk ./src/libsmoke/smoke.cpp 138
- *c = get_smoke(smoke)->findClass(name);
+ *c = Smoke::findClass(name);
hunk ./src/libsmoke/smoke.cpp 184
- return get_smoke(smoke)->isDerivedFrom(get_smoke(smoke), class_index,
+ return Smoke::isDerivedFrom(get_smoke(smoke), class_index,
hunk ./src/objects/class.lisp 64
- ((smoke-name :initarg :smoke-name
- :initform nil
- :documentation "The name of the Smoke module"))
+ ()
hunk ./src/objects/class.lisp 66
- (format stream "No Smoke class named ~S in the Smoke module ~S."
- (cell-error-name condition)
- (slot-value condition 'smoke-name))))
+ (format stream "No Smoke class named ~S."
+ (cell-error-name condition))))
hunk ./src/objects/class.lisp 76
-(defun make-smoke-class (smoke name)
- "Returns the class named NAME of the smoke module SMOKE.
+(defun make-smoke-class (name)
+ "Returns the class named NAME.
hunk ./src/objects/class.lisp 81
- (smoke-find-class c (smoke-module-pointer smoke) name)
+ (smoke-find-class c name)
hunk ./src/objects/class.lisp 84
- (error (make-condition 'undefined-class :name name :smoke-name (smoke-get-module-name (smoke-module-pointer smoke))))
+ (error (make-condition 'undefined-class :name name))
hunk ./src/objects/class.lisp 104
- (handler-case (make-smoke-class (smoke class) (name class))
+ (handler-case (make-smoke-class (name class))
hunk ./src/objects/method.lisp 20
- (call-next-method)
+ (print-unreadable-object (smoke-method stream :type t)
+ (princ "no method" stream))
hunk ./src/objects/method.lisp 140
- (format nil "~A~:[~; static~]" (access method) (static-p method)))
+ (format nil "~:[~;virtual ~]~A~:[~; static~]" [_$_]
+ (virtual-p method) (access method) (static-p method)))
hunk ./src/objects/method.lisp 214
+(defun virtual-p (method)
+ "Returns T when METHOD is internal and NIL otherwise."
+ (/= 0 (get-method-flag method :virtual)))
+
hunk ./src/smoke-to-clos.lisp 168
+ (eval-startup (:compile-toplevel :load-toplevel :execute)
+ ;; FIXME when loading the Lisp image we no longer need to
+ ;; call #'ensure-class, but the class-map needs still
+ ;; to be populated by #'add-id-class-map and #'add-id;
+ ;; For now we ignore the negligible overhead.
+ (make-smoke-classes ,package ,smoke))
hunk ./src/smoke-to-clos.lisp 175
- (make-smoke-classes ,package ,smoke)
hunk ./src/smoke.lisp 55
-(defun static-call (smoke class-name method-name &rest args)
- (s-call (make-smoke-method-from-name (make-smoke-class smoke class-name)
- method-name)
- (null-pointer) args))
-
Sun Jan 10 18:31:42 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix overload resolution when a lisp smoke module is not loaded.
hunk ./cl-smoke.smoke.asd 57
-(defmethod operation-done-p ((o test-op) (c (eql (find-system :cl-smoke.smoke))))
- nil)
-
hunk ./src/objects/class.lisp 73
+(define-condition lisp-module-not-loaded (error)
+ ((class-name :initarg :class-name))
+ (:report (lambda (condition stream)
+ (format stream "The Lisp smoke module of the class ~A is not loaded."
+ (slot-value condition 'class-name)))))
+
hunk ./src/objects/class.lisp 93
- (make-instance 'smoke-class
- :id (foreign-slot-value c 'smoke-module-index 'index)
- :smoke (gethash (pointer-address (foreign-slot-value c 'smoke-module-index 'smoke)) *smoke-modules*))))
+ (let ((class (make-instance
+ 'smoke-class
+ :id (foreign-slot-value c 'smoke-module-index 'index)
+ :smoke (gethash (pointer-address (foreign-slot-value
+ c 'smoke-module-index
+ 'smoke))
+ *smoke-modules*))))
+ (unless (smoke class)
+ (error (make-condition 'lisp-module-not-loaded :class-name name)))
+ class)))
hunk ./src/overload-resolution.lisp 466
- (let ((to-class (find-smoke-class (get-class type) nil)))
- (when (and to-class
- (call-using-types find-best-viable-function2
- (if (using-typep)
- #'standard-conversion-sequence-using-types
- #'standard-conversion-sequence)
- (constructor-name (get-class type))
- (list object) to-class))
- (make-match 'user-conversion
- 'coerce-to-class
- to-class)))))
+ (handler-case
+ (let ((to-class (find-smoke-class (get-class type) nil)))
+ (when (and to-class
+ (call-using-types find-best-viable-function2
+ (if (using-typep)
+ #'standard-conversion-sequence-using-types
+ #'standard-conversion-sequence)
+ (constructor-name (get-class type))
+ (list object) to-class))
+ (make-match 'user-conversion
+ 'coerce-to-class
+ to-class)))
+ ;; When the correspoinding Lisp module is not loaded, we ignore
+ ;; the overload.
+ (lisp-module-not-loaded ()))))
Sun Jan 10 18:30:48 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Auto-recompile when the smoke module has changed.
hunk ./src/smoke-to-clos.lisp 90
- "Raises an error when the fasl of the DEFINE-METHOS was not compiled against
-the current smoke module."
- `(eval-when (:load-toplevel :execute)
- (unless (sizes= (,smoke)
- smoke-module-methods
- smoke-module-method-names
- smoke-module-method-maps
- smoke-module-classes
- smoke-module-types)
- (error "The smoke module ~A changed, you need to recompile the lisp file."
- (smoke-get-module-name (smoke-module-pointer ,smoke))))))
+ "Raises an error or tries to recompile when the fasl of the define-classes-and-gfs
+was not compiled against the current smoke module."
+ (with-unique-names (restart)
+ `(eval-when (:load-toplevel :execute)
+ (unless (sizes= (,smoke)
+ smoke-module-methods
+ smoke-module-method-names
+ smoke-module-method-maps
+ smoke-module-classes
+ smoke-module-types)
+ (let ((,restart (find-restart 'asdf:try-recompiling)))
+ (if ,restart
+ (invoke-restart ,restart)
+ (error "The smoke module ~A changed, you need to recompile the lisp file."
+ (smoke-get-module-name (smoke-module-pointer ,smoke)))))))))
Sun Jan 10 09:49:36 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Support modular smoke & cleanup.
move ./smoke.asd ./cl-smoke.smoke.asd
move ./src/smoke-c/csmokebinding.cpp ./src/smoke-c/smokebinding.cpp
move ./src/smoke-c/csmokebinding.h ./src/smoke-c/smokebinding.h
move ./src/smoke-c/smoke-c-util.cpp ./src/smoke-c/smoke_util.cpp
move ./src/smoke-c/smoke-c.cpp ./src/smoke-c/smoke.cpp
move ./src/smoke-c/smoke-c.lisp ./src/smoke-c/smoke.lisp
move ./src/smoke-c ./src/libsmoke
hunk ./cl-smoke.smoke.asd 1
-(defpackage smoke-system
- (:use :cl :asdf))
-
-(in-package smoke-system)
-
-(asdf:defsystem :smoke
- :name :smoke
+(defsystem :cl-smoke.smoke
+ :name :cl-smoke.smoke
hunk ./cl-smoke.smoke.asd 17
- (:file "smoke" :depends-on (:smoke-c :objects "clos"))
+ (:file "smoke" :depends-on (:libsmoke :objects "clos"))
hunk ./cl-smoke.smoke.asd 20
- (:file "bindings" :depends-on ("package"))
+ (:file "bindings" :depends-on ("package" :utils))
hunk ./cl-smoke.smoke.asd 22
- (:file "clos" :depends-on
- (:smoke-c "cxx-method" :objects "object-map" "class-map" "bindings"))
+ (:file "clos" :depends-on (:libsmoke "cxx-method" :objects
+ "object-map" "class-map" "bindings"))
hunk ./cl-smoke.smoke.asd 27
- :depends-on (:smoke-c :utils "bindings")
+ :depends-on (:libsmoke :utils "bindings")
hunk ./cl-smoke.smoke.asd 35
- (:module :smoke-c
+ (:module :libsmoke
hunk ./cl-smoke.smoke.asd 38
- ((:file "smoke-c") (:file "class" :depends-on ("smoke-c"))
+ ((:file "smoke")
+ (:file "class" :depends-on ("smoke"))
hunk ./cl-smoke.smoke.asd 57
-(defmethod asdf:perform ((operation test-op) (c (eql (find-system :smoke))))
- (operate 'asdf:load-op :qt)
- (operate 'asdf:test-op :qt))
+(defmethod operation-done-p ((o test-op) (c (eql (find-system :cl-smoke.smoke))))
+ nil)
+
+(defmethod perform ((operation test-op) (c (eql (find-system :cl-smoke.smoke))))
+ (operate 'asdf:load-op :cl-smoke.qt.tests)
+ (operate 'asdf:test-op :cl-smoke.qt.tests))
hunk ./src/CMakeLists.txt 1
-add_subdirectory(smoke-c)
+add_subdirectory(libsmoke)
hunk ./src/bindings.lisp 3
-(defvar *bindings* (make-hash-table)
- "The Smoke C++ binding classes to which virtual method calls are dispatched.")
-
-;; FIXME is this lock needed? (The user may not have to
-;; load additional modules while threads are running.
-(defvar *bindings-lock* (make-lock "bindings-lock"))
-
-(defun binding (smoke)
- "Returns the Smoke binding for the Smoke module SMOKE."
- (with-lock-held (*bindings-lock*)
- (multiple-value-bind (value present-p)
- (gethash (pointer-address smoke) *bindings*)
- (assert (eql t present-p)
- ()
- "No binding for ~A." smoke)
- value)))
-
-(defun (setf binding) (binding smoke)
- (with-lock-held (*bindings-lock*)
- (setf (gethash (pointer-address smoke) *bindings*)
- binding)))
-
hunk ./src/bindings.lisp 26
+(eval-on-save ()
+ (clrhash *smoke-modules*))
+
hunk ./src/clos.lisp 205
- (let ((*package* (find-package package)))
+ (let ((impl-package *package*)
+ (*package* (find-package package)))
hunk ./src/clos.lisp 210
- (unless (or (external-p class)
- (and (eq package :cl-smoke.qt)
- (string/= (smoke-get-module-name [_$_]
- (smoke-module-pointer smoke))
- "qt")
- (string= (name class) "QGlobalSpace")))
+ (unless (external-p class)
hunk ./src/clos.lisp 212
- (add-id class
- (closer-mop:ensure-class (lispify (name class))
- :direct-superclasses
- (mapcar #'smoke-class-symbol
- (smoke-class-direct-superclasses class))
- :id (id class)
- :smoke (smoke class)
- :metaclass 'smoke-standard-class))
- (export (lispify (name class))))))
+ (let ((class-name [_$_]
+ ;; There is a QGlobalSpace class per Smoke module.
+ ;; Put it in *package* and not PACKAGE to avoid
+ ;; clashes between multiple modules.
+ (if (string= "QGlobalSpace" (name class))
+ (lispify "QGlobalSpace" impl-package)
+ (lispify (name class)))))
+ (add-id class
+ (closer-mop:ensure-class class-name
+ :direct-superclasses
+ (mapcar #'smoke-class-symbol
+ (smoke-class-direct-superclasses class))
+ :id (id class)
+ :smoke (smoke class)
+ :metaclass 'smoke-standard-class))
+ (when (eql (symbol-package class-name) *package*)
+ (export class-name))))))
hunk ./src/libsmoke/CMakeLists.txt 11
-set(SMOKE_C_SOURCES smoke-c.cpp csmokebinding.cpp)
-add_library(smoke-c MODULE ${SMOKE_C_SOURCES})
-set_target_properties(smoke-c
+set(SMOKE_C_SOURCES smoke.cpp smokebinding.cpp)
+add_library(clsmoke MODULE ${SMOKE_C_SOURCES})
+set_target_properties(clsmoke
hunk ./src/libsmoke/CMakeLists.txt 18
-add_library(smoke-c-util MODULE smoke-c-util.cpp)
-set_target_properties(smoke-c-util
+add_library(clsmokeutil MODULE smoke_util.cpp)
+set_target_properties(clsmokeutil
hunk ./src/libsmoke/CMakeLists.txt 24
-install(TARGETS smoke-c smoke-c-util
+install(TARGETS clsmoke clsmokeutil
hunk ./src/libsmoke/cl_smoke.h 16
-/** @brief Common Lisp Smoke binding namespace. */
+/** @brief cl-smoke binding namespace. */
hunk ./src/libsmoke/class.lisp 20
-(defcfun smoke-find-class :void
+(defcfun (smoke-find-class "cl_smoke_find_class") :void
hunk ./src/libsmoke/class.lisp 25
-(defcfun smoke-class-id smoke-index
+(defcfun (smoke-class-id "cl_smoke_class_id") smoke-index
hunk ./src/libsmoke/class.lisp 29
-(defcfun smoke-get-class (:pointer smoke-class)
+(defcfun (smoke-get-class "cl_smoke_get_class") (:pointer smoke-class)
hunk ./src/libsmoke/class.lisp 33
-(defcfun smoke-is-derived-from :boolean
+(defcfun (smoke-is-derived-from "cl_smoke_is_derived_from") :boolean
hunk ./src/libsmoke/class.lisp 39
-(defcfun smoke-cast :pointer
+(defcfun (smoke-cast "cl_smoke_cast") :pointer
hunk ./src/libsmoke/method.lisp 37
-(defcfun smoke-find-method :void
+(defcfun (smoke-find-method "cl_smoke_find_method") :void
hunk ./src/libsmoke/smoke.cpp 1
-#include "csmokebinding.h"
hunk ./src/libsmoke/smoke.cpp 2
+#include "smokebinding.h"
hunk ./src/libsmoke/smoke.cpp 5
-
hunk ./src/libsmoke/smoke.cpp 22
-smoke_get_smoke(smoke_binding binding)
+cl_smoke_get_smoke(smoke_binding binding)
hunk ./src/libsmoke/smoke.cpp 37
-smoke_init(void* smoke, void* destruct, void* dispatch)
+cl_smoke_init(void* smoke, void* destruct, void* dispatch)
hunk ./src/libsmoke/smoke.cpp 48
-smoke_destruct(smoke_binding binding)
+cl_smoke_destruct(smoke_binding binding)
hunk ./src/libsmoke/smoke.cpp 60
-smoke_get_module_name(void* smoke)
+cl_smoke_get_module_name(void* smoke)
hunk ./src/libsmoke/smoke.cpp 137
-smoke_find_class(Smoke::ModuleIndex* c, void* smoke, const char* name)
+cl_smoke_find_class(Smoke::ModuleIndex* c, void* smoke, const char* name)
hunk ./src/libsmoke/smoke.cpp 149
-smoke_class_id(void* smoke, const char* name)
+cl_smoke_class_id(void* smoke, const char* name)
hunk ./src/libsmoke/smoke.cpp 164
-smoke_get_class(void* smoke, Smoke::Index class_index)
+cl_smoke_get_class(void* smoke, Smoke::Index class_index)
hunk ./src/libsmoke/smoke.cpp 179
-smoke_is_derived_from(void* smoke, Smoke::Index class_index, void* smoke_base, Smoke::Index base_index)
+cl_smoke_is_derived_from(void* smoke, Smoke::Index class_index, void* smoke_base,
+ Smoke::Index base_index)
hunk ./src/libsmoke/smoke.cpp 186
- get_smoke(smoke_base), base_index);
+ get_smoke(smoke_base), base_index);
hunk ./src/libsmoke/smoke.cpp 200
-smoke_find_method(Smoke::ModuleIndex* m, void* smoke,
+cl_smoke_find_method(Smoke::ModuleIndex* m, void* smoke,
hunk ./src/libsmoke/smoke.cpp 220
-smoke_find_type(void* smoke, const char* name)
+cl_smoke_find_type(void* smoke, const char* name)
hunk ./src/libsmoke/smoke.cpp 234
-smoke_cast(void* smoke, void* object, Smoke::Index from, Smoke::Index to)
+cl_smoke_cast(void* smoke, void* object, Smoke::Index from, Smoke::Index to)
hunk ./src/libsmoke/smoke.lisp 6
- (:unix "libsmokeqt.so.3")
+ (:unix "libsmokeqtcore.so.3")
hunk ./src/libsmoke/smoke.lisp 8
- (define-foreign-library libsmoke-c
- (:unix "libsmoke-c.so")
- (t (:default "libsmoke-c")))
- (define-foreign-library libsmoke-c-util
- (:unix "libsmoke-c-util.so")
- (t (:default "libsmoke-c-util")))
+ (define-foreign-library libclsmoke
+ (:unix "libclsmoke.so")
+ (t (:default "libclsmoke")))
+ (define-foreign-library libclsmokeutil
+ (:unix "libclsmokeutil.so")
+ (t (:default "libclsmokeutil")))
hunk ./src/libsmoke/smoke.lisp 15
- (use-foreign-library libsmoke-c))
+ (use-foreign-library libclsmoke))
hunk ./src/libsmoke/smoke.lisp 19
- (use-foreign-library libsmoke-c-util)
- (defcfun smoke-sizeof-bool :int)
+ (use-foreign-library libclsmokeutil)
+ (defcfun (smoke-sizeof-bool "cl_smoke_sizeof_bool") :int)
hunk ./src/libsmoke/smoke.lisp 23
- (load-foreign-library 'libsmoke-c-util)
+ (load-foreign-library 'libclsmokeutil)
hunk ./src/libsmoke/smoke.lisp 32
-;(close-foreign-library 'libsmoke-c-util)
+;(close-foreign-library 'libclsmokeutil)
hunk ./src/libsmoke/smoke.lisp 44
-(defcfun smoke-init smoke-binding
+(defcfun (smoke-init "cl_smoke_init") smoke-binding
hunk ./src/libsmoke/smoke.lisp 49
-(defcfun smoke-destruct :void
+(defcfun (smoke-destruct "cl_smoke_destruct") :void
hunk ./src/libsmoke/smoke.lisp 59
-(defcfun smoke-get-smoke :pointer
+(defcfun (smoke-get-smoke "cl_smoke_get_smoke") :pointer
hunk ./src/libsmoke/smoke.lisp 62
-(defcfun smoke-get-module-name :string
+(defcfun (smoke-get-module-name "cl_smoke_get_module_name") :string
hunk ./src/libsmoke/smoke_util.cpp 22
-smoke_sizeof_bool()
+cl_smoke_sizeof_bool()
hunk ./src/libsmoke/smokebinding.cpp 1
-#include "csmokebinding.h"
+#include "smokebinding.h"
hunk ./src/libsmoke/smokebinding.h 1
-#ifndef CSMOKEBINDING_H
-#define CSMOKEBINDING_H
+#ifndef SMOKEBINDING_H
+#define SMOKEBINDING_H
hunk ./src/libsmoke/smokebinding.h 39
-#endif // CSMOKEBINDING_H
+#endif // SMOKEBINDING_H
hunk ./src/libsmoke/type.lisp 18
-(defcfun smoke-find-type smoke-index
+(defcfun (smoke-find-type "cl_smoke_find_type") smoke-index
hunk ./src/object-map.lisp 41
+ (tg:gc :full t) ;; Try to get all #'smoke::make-auto-pointer
hunk ./src/object-map.lisp 43
- (warn "life object ~A" object)
+ (warn "life object ~A ~A" object (pointer object))
hunk ./src/smoke-to-clos.lisp 21
- `(define-constant ,symbol ;; a long not really an enum.
+ `(define-constant ,symbol ;; a long, not really an enum.
hunk ./src/smoke-to-clos.lisp 55
- (call-using-args (find-class (quote ,(lispify (name class) package)))
- ,method-name
- ,(if (< argument-count 0)
- 'args
- `(list ,@(make-lambda argument-count)))))
+ (call-using-args
+ (find-class (quote ,(lispify (name class) [_$_]
+ (if (string= (name class)
+ "QGlobalSpace")
+ *package* ;; See #'MAKE-SMOKE-CLASSES
+ package))))
+ ,method-name
+ ,(if (< argument-count 0)
+ 'args
+ `(list ,@(make-lambda argument-count)))))
hunk ./src/smoke-to-clos.lisp 116
- (when (enum-p method)
+ (when (and (enum-p method)
+ ;; qt.network has QIODevice::NotOpen(), but the
+ ;; class is external (workaround).
+ (not (external-p (get-class method))))
hunk ./src/smoke-to-clos.lisp 142
- (setf (gethash function-symbol function-symbols)
- (if methods (- (id method)) (id method)))))))
+ (unless (fboundp function-symbol) ;; do not overwrite
+ ;; existing functions e.g. qInstallMsgHandler of
+ ;; qt.core with that of qt.gui which causes a
+ ;; segfault when loading from an saved image.
+ (setf (gethash function-symbol function-symbols)
+ (if methods (- (id method)) (id method))))))))
hunk ./src/smoke-to-clos.lisp 164
- (eval-startup (:load-toplevel :execute)
- ;; eval on startup for class map.
- (make-smoke-classes ,package ,smoke))
hunk ./src/smoke-to-clos.lisp 165
+ (make-smoke-classes ,package ,smoke)
hunk ./src/smoke.lisp 1
-;;; Copyright (C) 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
+;;; Copyright (C) 2009, 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
hunk ./src/smoke.lisp 105
- (use-foreign-library libsmoke-c)
+ (use-foreign-library libclsmoke)
hunk ./src/smoke.lisp 108
- (setf (binding smoke) binding
- (smoke-module-pointer module) smoke
+ (setf (smoke-module-pointer module) smoke
hunk ./src/smoke.lisp 115
+ ;; Used by make-load-form for enums to reference the smoke module.
hunk ./src/smoke.lisp 148
- ;;FIXME speed this up, needed by (mb:document :smoke).
hunk ./test-bundle.sh 8
-MALLOC_CHECK_=3 sbcl --eval '(require :qt.tests)' \
+MALLOC_CHECK_=3 sbcl --eval '(require :cl-smoke.qt.tests)' \
hunk ./test.lisp 11
-sh ./test-bundle.sh || exit 2
+ sh ./test-bundle.sh || exit 2
hunk ./test.lisp 21
-(asdf:operate 'asdf:load-op :smoke)
-(asdf:operate 'asdf:test-op :smoke)
+(require :asdf)
+(asdf:operate 'asdf:load-op :cl-smoke.smoke)
+(asdf:operate 'asdf:test-op :cl-smoke.smoke)
changepref test
sh test.lisp
Sun Dec 13 13:43:58 CET 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Support ASDF instead of Mudballs.
addfile ./smoke.asd
hunk ./smoke.asd 1
+(defpackage smoke-system
+ (:use :cl :asdf))
+
+(in-package smoke-system)
+
+(asdf:defsystem :smoke
+ :name :smoke
+ :version (0 0 1)
+ :author "Tobias Rautenkranz"
+ :license "GPL with linking exception"
+ :description "Smoke bindings. Provides the base functionality to
+implement bindings using the various Smoke modules."
+ :depends-on
+ (:cffi :closer-mop :alexandria :trivial-garbage :bordeaux-threads)
+
+ :components
+ ((:module :src :components
+ ((:file "package")
+ (:file "using-type" :depends-on ("package"))
+ (:file "overload-resolution" :depends-on ("package" "smoke" "using-type"))
+ #+sbcl (:file "sb-optimize" :depends-on ("overload-resolution"))
+ (:file "smoke" :depends-on (:smoke-c :objects "clos"))
+ (:file "object-map" :depends-on (:objects :utils))
+ (:file "class-map" :depends-on ("package"))
+ (:file "bindings" :depends-on ("package"))
+ (:file "cxx-method" :depends-on ("package"))
+ (:file "clos" :depends-on
+ (:smoke-c "cxx-method" :objects "object-map" "class-map" "bindings"))
+ (:file "smoke-to-clos" :depends-on ("clos" "overload-resolution"))
+ (:module :objects
+ :serial t
+ :depends-on (:smoke-c :utils "bindings")
+ :components
+ ((:file "object") (:file "enum" :depends-on ("object"))
+ (:file "type" :depends-on ("enum"))
+ (:file "method" :depends-on ("type"))
+ (:file "class" :depends-on ("method"))
+ (:file "instance" :depends-on ("class"))
+ (:file "stack" :depends-on ("instance"))))
+ (:module :smoke-c
+ :depends-on ("package")
+ :components
+ ((:file "smoke-c") (:file "class" :depends-on ("smoke-c"))
+ (:file "stack" :depends-on ("class"))
+ (:file "method" :depends-on ("stack"))
+ (:file "type" :depends-on ("method"))))
+ (:module :utils
+ :depends-on ("package")
+ :components
+ ((:file "get-value")
+ #+sbcl (:file "sbcl-bundle")
+ (:module :image :components
+ ((:file "image" :depends-on (:impl))
+ (:module :impl
+ :components
+ (#+sbcl (:file "sbcl")
+ #+openmcl (:file "ccl")
+ #+(not (or sbcl openmcl))
+ (:file "not-implemented")))))))))))
+
+(defmethod asdf:perform ((operation test-op) (c (eql (find-system :smoke))))
+ (operate 'asdf:load-op :qt)
+ (operate 'asdf:test-op :qt))
hunk ./smoke.mbd 1
-;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
-
-;;; Allow this file to compile even when sysdef.cmake is not loaded.
-;;; You can not add a (MB:LOAD :SYSDEF.CMAKE) on top since when Mudballs
-;;; loads this file it might not know yet about :SYSDEF.CMAKE.
-(defpackage :sysdef.cmake
- (:use :cl :sysdef)
- (:export :cmake-file :cmake-library))
-(in-package :sysdef.cmake)
-
-(defclass sysdef.cmake:cmake-file (source-file)
- ()
- (:default-initargs :type "txt"))
-
-(defclass sysdef.cmake:cmake-library (component)
- ((package :initarg :package)))
-;;; end SYDDEF.CMAKE
-
-(in-package :sysdef-user)
-(eval-when (:compile-toplevel :load-toplevel :execute)
- (use-package :sysdef.cmake))
-
-(define-system :smoke ()
- (:version 0 0 1)
- (:documentation "Smoke bindings. Provides the base functionality to
-implement bindings using the various Smoke modules.")
- (:author "Tobias Rautenkranz")
- (:license "GPL with linking exception")
- (:components
- ("CMakeLists" cmake-file)
- (:src module
- (:needs "CMakeLists")
- (:components
- "package"
- ("using-type" (:needs "package"))
- ("overload-resolution" (:needs "package" "smoke" "using-type"))
- ("sb-optimize" (:for :sbcl) (:needs "overload-resolution"))
- ("smoke" (:needs "smoke-c" "objects" "clos"))
- ("object-map" (:needs "objects" :utils))
- ("class-map" (:needs "package"))
- ("bindings" (:needs "package"))
- ("cxx-method" (:needs "package"))
- ("clos" (:needs "smoke-c" "cxx-method" "objects" "object-map" "class-map" "bindings"))
- ("smoke-to-clos" (:needs "clos" "overload-resolution"))
- (:objects module
- (:needs "smoke-c" "utils" "bindings")
- (:serial t)
- (:components "object" "enum" "type" "method" "class"
- "instance" "stack"))
- (:smoke-c module
- (:needs "package")
- (:components ("libsmoke-c" cmake-library)
- ("libsmoke-c-util" cmake-library)
-
- ("smoke-c" (:needs "libsmoke-c"
- "libsmoke-c-util"))
- ("class" (:needs "smoke-c"))
- ("stack" (:needs "class"))
- ("method" (:needs "stack"))
- ("type" (:needs "method"))))
-
- (:utils module
- (:needs "package")
- (:requires (:sb-posix (:for :sbcl)))
- (:components
- "get-value"
- ("sbcl-bundle" (:for :sbcl))
- (:image module
- (:components [_$_]
- ("image" (:needs "impl"))
- (:impl module
- (:components
- ("sbcl" (:for :sbcl))
- ("ccl" (:for :openmcl))
- ("not-implemented" (:for (:not
- (:or :sbcl :openmcl)))))))))))))
- (:needs :sysdef.cmake :cffi :closer-mop
- :alexandria :trivial-garbage :bordeaux-threads))
rmfile ./smoke.mbd
hunk ./src/smoke-c/smoke-c.lisp 8
- #-mudballs
hunk ./src/smoke-c/smoke-c.lisp 11
- #-mudballs
hunk ./test-bundle.sh 8
-MALLOC_CHECK_=3 sbcl --eval '(mb:load :qt.tests)' \
+MALLOC_CHECK_=3 sbcl --eval '(require :qt.tests)' \
hunk ./test.lisp 18
-# do not use --script to allow loading mudballs with ${HOME}/.sbclrc
hunk ./test.lisp 21
-
-(in-package :sysdef-user)
-
-(defun load-sysdef (pathname system)
- (load pathname)
- (setf (mb.sysdef::pathname-of (find-system system)) pathname))
-
-(defun load-sysdef-file (system-name)
- "Loads a mbd file in the current directory."
- (load-sysdef (make-pathname :defaults *default-pathname-defaults*
- :name (string-downcase system-name)
- :type "mbd")
- system-name))
-
-(load-sysdef-file :smoke)
-;(mb:load :FiveAm)
-;(setf 5am:*debug-on-failure* t)
-;(setf 5am:*debug-on-error* t)
-(mb:test :smoke)
+(asdf:operate 'asdf:load-op :smoke)
+(asdf:operate 'asdf:test-op :smoke)
changepref test
sh ./test.lisp
Sun Dec 13 11:17:08 CET 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Update to the new Smoke ABI (v.3)
hunk ./src/objects/method.lisp 184
+(defun attribute-p (method)
+ "Returns T when METHOD accesses C++ member/static variables."
+ (/= 0 (get-method-flag method :attribute)))
+
+(defun property-p (method)
+ "Returns T when METHOD accesses a Q_PROPERTY."
+ (/= 0 (get-method-flag method :property)))
+
hunk ./src/smoke-c/class.lisp 17
- (flags :unsigned-short))
+ (flags :unsigned-short)
+ (size :unsigned-int))
hunk ./src/smoke-c/method.lisp 12
- (:protected #x80))
+ (:protected #x80)
+ (:attribute #x100)
+ (:property #x200)
+ (:virtual #x400)
+ (:purevirtual #x800)
+ (:signal #x1000)
+ (:slot #x2000))
hunk ./src/smoke-c/method.lisp 26
- (flags :unsigned-char)
+ (flags :unsigned-short)
hunk ./src/smoke-c/smoke-c.lisp 6
- (:unix "libsmokeqt.so.2")
+ (:unix "libsmokeqt.so.3")
hunk ./src/smoke-c/smoke-c.lisp 54
+;; Smoke::ModuleIndex is a POD-struct.
+;; Thus we can treat it as a C struct.
hunk ./src/smoke.lisp 181
- (:unix ,(format nil "~(~A~).so.2.0" library))
+ (:unix ,(format nil "~(~A~).so.3" library))
hunk ./src/smoke.lisp 189
- (defcfun (,init-function ,(format nil "_Z~A~Av"
- (length function-name)
- function-name)
- :library ,library)
+ (defcfun (,init-function ,function-name :library ,library)
hunk ./test-bundle.sh 8
-sbcl --eval '(mb:load :qt.tests)' \
+MALLOC_CHECK_=3 sbcl --eval '(mb:load :qt.tests)' \
hunk ./test-bundle.sh 12
-echo "(progn (5am:run!) (quit))" | ./qt.test.run [_$_]
+echo "(progn (in-package :qt.tests) (5am:run!) (quit))" | MALLOC_CHECK_=3 ./qt.test.run [_$_]
Fri Nov 6 20:27:56 CET 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Explicitly use old ABI (pre r1045709)
hunk ./src/smoke.lisp 181
- (:unix ,(format nil "~(~A~).so.2" library))
+ (:unix ,(format nil "~(~A~).so.2.0" library))
Wed Sep 9 21:25:37 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Template types are no longer t_class.
hunk ./src/objects/stack.lisp 108
- ((0 13) (if-let ((translation (gethash (name type) *to-lisp-translations*)))
- (let ((pointer (foreign-slot-value stack-item 'smoke-stack-item
- 'voidp)))
- (prog1 (funcall (car translation) pointer)
- (when (stack-p type)
- (funcall (cdr translation) pointer))))
- (error "Do not know how to convert the type ~A to Lisp." type)))
+ (0 (if-let ((translation (gethash (name type) *to-lisp-translations*)))
+ (let ((pointer (foreign-slot-value stack-item 'smoke-stack-item
+ 'voidp)))
+ (prog1 (funcall (car translation) pointer)
+ (when (stack-p type)
+ (funcall (cdr translation) pointer))))
+ (error "Do not know how to convert the type ~A to Lisp." type)))
hunk ./src/overload-resolution.lisp 341
- (13 (if (class-p type)
- (and (object.typep 'smoke-standard-object)
- (smoke-type= (get-class type) (object.type-of)))
- (when-let (test (gethash (name type) *from-lisp-translations*))
- (funcall test object (using-typep)))))))
+ (13 (and (object.typep 'smoke-standard-object)
+ (smoke-type= (get-class type) (object.type-of))))))
Wed Sep 9 15:22:32 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Smoke::t_class is now also used for classes not wrapped by Smoke & remove global-space part from enum symbols.
hunk ./src/objects/stack.lisp 108
- (0 (if-let ((translation (gethash (name type) *to-lisp-translations*)))
- (let ((pointer (foreign-slot-value stack-item 'smoke-stack-item
- 'voidp)))
- (prog1 (funcall (car translation) pointer)
- (when (stack-p type)
- (funcall (cdr translation) pointer))))
- (error "Do not know how to convert the type ~A to Lisp." type)))
+ ((0 13) (if-let ((translation (gethash (name type) *to-lisp-translations*)))
+ (let ((pointer (foreign-slot-value stack-item 'smoke-stack-item
+ 'voidp)))
+ (prog1 (funcall (car translation) pointer)
+ (when (stack-p type)
+ (funcall (cdr translation) pointer))))
+ (error "Do not know how to convert the type ~A to Lisp." type)))
hunk ./src/objects/type.lisp 107
- (/= -1 (type-slot-value type 'class))))
+ (not (zerop (type-slot-value type 'class)))))
hunk ./src/overload-resolution.lisp 341
- (13 (and (object.typep 'smoke-standard-object)
- (smoke-type= (get-class type) (object.type-of))))))
+ (13 (if (class-p type)
+ (and (object.typep 'smoke-standard-object)
+ (smoke-type= (get-class type) (object.type-of)))
+ (when-let (test (gethash (name type) *from-lisp-translations*))
+ (funcall test object (using-typep)))))))
hunk ./src/overload-resolution.lisp 510
- (declare (optimize (speed 3)))
+ (declare (optimize (speed 3))
+ (type (or smoke-standard-class smoke-standard-object)
+ object-or-class))
hunk ./src/smoke-to-clos.lisp 7
- (if (string= (name (get-class method))
- "Qt")
+ (if (or (string= (name (get-class method))
+ "Qt")
+ (string= (name (get-class method))
+ "QGlobalSpace"))
Wed Sep 2 13:49:34 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Various fixes:
* Allow user conversions for return values
* fix destruction of objects with multiple C++ superclasses
* Fix list to QList conversion dispatch
hunk ./src/clos.lisp 270
+ (when (typep object 'smoke-multi-superclass-mixin)
+ (dolist (extra-object (extra-objects object))
+ (unless (null-pointer-p (pointer extra-object))
+ (remove-object (pointer extra-object))
+ (delete-object extra-object))))
hunk ./src/clos.lisp 297
-(defun convert-argument (argument type &optional (user t))
- "Returns ARGUMENT converted to TYPE. If USER is true, user defined
-conversion sequences are considered."
- (let ((rank (get-conversion-sequence argument type user)))
- (if (null rank)
- (error "Can not convert the argument ~S to ~A."
- argument (name type))
- (funcall (conversion-function-name rank)
- argument))))
+(defun convert-argument (argument type &optional disown)
+ "Returns ARGUMENT converted to TYPE and removes the ownership when
+it is passed on the stack."
+ (flet ((disown (object)
+ (remove-finalizer object)
+ (when (typep object 'smoke-standard-object)
+ (remove-object (pointer object)))))
+ (let ((rank (get-conversion-sequence argument type nil)))
+ (if (null rank)
+ (let ((rank (get-conversion-sequence argument type t)))
+ (if (null rank)
+ (error "Can not convert the argument ~S to ~A."
+ argument (name type))
+ (let ((ret (funcall (conversion-function-name rank)
+ argument)))
+ (when (and disown (stack-p type))
+ (disown ret))
+ ret)))
+ (prog1 (funcall (conversion-function-name rank) argument)
+ (when (and disown (stack-p type))
+ (disown argument)))))))
hunk ./src/clos.lisp 323
- ;; FIXME support user conversions.
- ;;
- ;; We need to determine which of value and converted-value is
- ;; passed on the stack. E.g. converted-value can be something
- ;; like (cxx:operator-variant value).
- (let ((converted-value (convert-argument value type nil)))
- (push-smoke-stack stack converted-value (type-id type))
- (when (stack-p type) ;; Pass by value => smoke deletes the object.
- (remove-finalizer converted-value)
- (when (typep value 'smoke-standard-object)
- (remove-object (pointer value))))))))
- ; (transfer-ownership-to value object)))))))
+ (let ((converted-value (convert-argument value type t)))
+ (push-smoke-stack stack converted-value (type-id type))))))
hunk ./src/object-map.lisp 115
- (assert (not (has-pointer-p (pointer object))) ()
- "There exists already a object ~A for the pointer of ~A."
- (get-object (pointer object)) object)
+ (when (has-pointer-p (pointer object))
+ (cerror "Overwrite the old object."
+ "There exists already a object ~A for the pointer of ~A."
+ (get-object (pointer object)) object))
hunk ./src/overload-resolution.lisp 305
- #'(lambda (type)
- (and (subtypep type ',lisp-type)
+ #'(lambda (type type-p)
+ (and (if type-p
+ (subtypep type ',lisp-type)
+ (typep type ',lisp-type))
hunk ./src/overload-resolution.lisp 328
- (funcall test (object.type-of))))
+ (funcall test object (using-typep))))
Tue Sep 1 13:44:21 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix overload resolution using types and test caching the overload resolution.
hunk ./src/overload-resolution.lisp 143
- (function-name nil :type (or symbol function) :read-only t)
+ (function-name nil :type (or symbol list function) :read-only t)
hunk ./src/overload-resolution.lisp 211
-(defmacro make-match (type &optional (name ''identity)
- (argument nil)
+(defmacro make-match (type &optional (name ''identity) (argument nil)
hunk ./src/overload-resolution.lisp 214
- :function-name ,(conversion-function name argument)
- ,@args))
+ :function-name ,(conversion-function name argument)
+ ,@args))
hunk ./src/overload-resolution.lisp 501
- [_$_]
+
+
hunk ./src/sb-optimize.lisp 94
+
+;;; cache ==================================================================
+;;;
+;;; we could replace the call to #'find-best-viable-function in
+;;; #'call-using-args with a call to
+;;; #'find-best-viable-function-cached, but it is only doubles speed.
+
+(sb-int:defun-cached (find-best-viable-function-using-types-cached
+ :hash-function (lambda (name arguments
+ class const-p)
+ (declare (string name)
+ (list arguments)
+ (class class)
+ (boolean const-p))
+ (logand [_$_]
+ (logxor
+ (sxhash name)
+ (sxhash arguments)
+ (sxhash class)
+ (sxhash const-p))
+ #x1FF))
+ :hash-bits 9)
+ ((name equal) (arguments equal) (class eq) (const-p eq))
+ (declare (optimize (speed 3))
+ (inline find-best-viable-function-using-types))
+ (multiple-value-bind (method conversion-sequence)
+ (find-best-viable-function-using-types name arguments class const-p)
+ (list method (mapcar #'(lambda (s)
+ (if (symbolp s)
+ (fdefinition s)
+ #'(lambda (x)
+ (funcall (fdefinition (first s))
+ x
+ (second s)))))
+ conversion-sequence))))
+ [_$_]
+(declaim (inline find-best-viable-function-cached))
+(defun find-best-viable-function-cached (name arguments class const-p)
+ (declare (optimize (speed 3)))
+ (catch 'unspecific-type
+ (return-from find-best-viable-function-cached
+ (values-list
+ (find-best-viable-function-using-types-cached
+ name
+ (mapcar #'(lambda (o) (class-of o)) arguments)
+ class
+ const-p))))
+ (find-best-viable-function name arguments class const-p))
+
hunk ./src/using-type.lisp 16
- ,@body))
+ ,@body))
Sun Aug 30 16:12:44 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Allow deriving from multiple C++ classes.
hunk ./src/clos.lisp 124
+(defclass smoke-multi-superclass-mixin ()
+ ((extra-objects :reader extra-objects
+ :initarg :extra-objects)))
+
hunk ./src/clos.lisp 154
- &allow-other-keys)
+ direct-default-initargs &allow-other-keys)
hunk ./src/clos.lisp 157
- "No superclass sup-lied for class ~A" class)
- (let ((superclass (first direct-superclasses)))
- (assert (subtypep (class-of superclass) (find-class 'smoke-standard-class))
+ "No superclass supplied for class ~A" class)
+ (let ((superclass (first direct-superclasses))
+ (extra-superclasses (remove-if-not #'(lambda (class)
+ (typep class 'smoke-standard-class))
+ (rest direct-superclasses))))
+ (assert (typep superclass 'smoke-standard-class)
hunk ./src/clos.lisp 164
- "The first superclass must be an subclass of an smoke class.")
+ "The first superclass ~A must be an subclass of an Smoke class."
+ class)
hunk ./src/clos.lisp 168
- "The class ~A has a non virtual destructor." superclass)
+ "The superclass ~A of ~A has a non virtual destructor."
+ superclass class)
+ (when extra-superclasses
+ (dolist (superclass extra-superclasses)
+ (unless (virtual-destructor-p superclass)
+ (cerror "Continue anyway"
+ "The superclass ~A of ~A has a non virtual destructor."
+ superclass class)))
+ (setf direct-superclasses
+ (append direct-superclasses
+ (list (find-class 'smoke-multi-superclass-mixin))))
+ (push `(:extra-objects ,extra-superclasses ,#'(lambda ()
+ extra-superclasses))
+ direct-default-initargs))
hunk ./src/clos.lisp 187
+ :direct-default-initargs direct-default-initargs
hunk ./src/clos.lisp 202
-
hunk ./src/clos.lisp 324
-;; Receive virutal function calls.
+;; Receive virtual function calls.
hunk ./src/clos.lisp 410
-(defun cast (object class)
- "Returns a pointer of type CLASS to the C++ object of OBJECT."
+(defgeneric cast (object class)
hunk ./src/clos.lisp 412
- (assert (derived-p (class-of object) class)
- ()
- "Can not cast object ~A of class ~A to class ~A."
- object (name (class-of object)) (name class))
- (smoke-cast (smoke-module-pointer (smoke (class-of object))) (pointer object)
- (id (class-of object)) (id class)))
-
+ (:documentation "Returns a pointer of type CLASS to the C++ object of OBJECT.")
+ (:method (object class)
+ (declare (optimize (speed 3)))
+ (assert (derived-p (class-of object) class)
+ ()
+ "Can not cast object ~A of class ~A to class ~A."
+ object (name (class-of object)) (name class))
+ (smoke-cast (smoke-module-pointer (smoke (class-of object))) (pointer object)
+ (id (class-of object)) (id class)))
+ (:method ((object smoke-multi-superclass-mixin) class)
+ (if (derived-p (class-of object) class)
+ (call-next-method)
+ (let ((extra-object (find-if #'(lambda (o)
+ (derived-p (class-of o) class))
+ (extra-objects object))))
+ (assert extra-object
+ ()
+ "Can not cast object ~A to class ~A."
+ object (name class))
+ (cast extra-object class)))))
hunk ./src/clos.lisp 449
-(defun call-constructor (object arguments)
- (if (null arguments)
- (let ((method (find-smoke-method (class-of object)
- (constructor-name (class-of object)))))
- (assert (valid-p method)
- (method)
- "No constructor for ~A." object)
- (pointer-call method (null-pointer)))
- (multiple-value-bind (method sequence)
- (find-best-viable-function (constructor-name (class-of object))
- arguments
- (class-of object))
- (when (null method)
- (error "No constructor for object ~A with
-the arguments ~S." object arguments))
- (pointer-call method (null-pointer)
- (mapcar #'(lambda (conversion argument)
- (funcall conversion argument))
- sequence arguments)))))
+(defun call-constructor (class arguments)
+ (multiple-value-bind (method sequence)
+ (find-best-viable-function (constructor-name class)
+ arguments
+ class)
+ (when (null method)
+ (error "No constructor for class ~A with
+the arguments ~S." class arguments))
+ (pointer-call method (null-pointer)
+ (mapcar #'(lambda (conversion argument)
+ (funcall conversion argument))
+ sequence arguments))))
hunk ./src/clos.lisp 479
- (call-constructor object [_$_]
+ (call-constructor (class-of object)
hunk ./src/clos.lisp 484
- (setf (slot-value object 'pointer) (call-constructor object args)))
+ (setf (slot-value object 'pointer)
+ (call-constructor (class-of object) args)))
hunk ./src/clos.lisp 490
+(defun construct-extra-objects (object extra-objects)
+ (loop for class in extra-objects
+ collect (let ((extra-object (make-instance (first extra-objects)
+ :pointer (call-constructor (first extra-objects)
+ nil))))
+ (set-binding extra-object)
+ (setf (get-object (pointer extra-object)) object)
+ extra-object)))
+ [_$_]
+(defmethod initialize-instance :after ((object smoke-multi-superclass-mixin) [_$_]
+ &key args)
+ (setf (slot-value object 'extra-objects)
+ (construct-extra-objects object (extra-objects object))))
+
+(defmethod make-finalize ((object smoke-multi-superclass-mixin))
+ (let ((pointer (pointer object))
+ (extra-objects (extra-objects object))
+ (class (class-of object)))
+ #'(lambda ()
+ (declare (optimize (speed 3)))
+ (handler-case (progn
+ (delete-pointer pointer class)
+ (dolist (object extra-objects)
+ (delete-object object)))
+ (error (condition)
+ (report-finalize-error condition 't (name class) pointer))))))
hunk ./src/clos.lisp 531
- (cerror "ignore" "~A has already been added to ~A."
+ (cerror "Ignore" "~A has already been added to ~A."
hunk ./src/object-map.lisp 95
+ ;; #'remove-object is called in the destructed callback. This
+ ;; happens even for objects without an virtual destructor.
hunk ./src/overload-resolution.lisp 121
-(defun all-smoke-superclasses (class)
- "Returns a list of all super-classes of CLASS and CLASS itself."
- (declare (optimize (speed 3)))
- (let ((classes (list class)))
- (dolist (class (closer-mop:class-direct-superclasses class) classes)
- (when (typep class 'smoke-standard-class)
- (setf classes (append (all-smoke-superclasses class) classes))))))
- [_$_]
hunk ./test.lisp 2
+echo \
+"################
+## Testing sbcl
+################"
hunk ./test.lisp 7
+echo \
+"###############
+## Testing sbcl image
+################"
hunk ./test.lisp 12
+echo \
+"###############
+## Testing ccl [_$_]
+################"
Sun Aug 30 15:51:40 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Make integer constants return an integer instead of an enum (e,g.: qt:graphics-item.+user-type+).
hunk ./src/smoke-to-clos.lisp 11
- package)
+ package)
hunk ./src/smoke-to-clos.lisp 16
- package))))
+ package))))
hunk ./src/smoke-to-clos.lisp 18
- `(define-constant ,symbol
- (make-instance 'enum
- :value ,(enum-call method)
- :type (make-instance 'smoke-type
- :id ,(id (return-type method))
- :smoke ,smoke))
- :test #'enum=)
+ (if (= 8 (type-id (return-type method)))
+ `(define-constant ,symbol ;; a long not really an enum.
+ ,(enum-call method))
+ `(define-constant ,symbol
+ (make-instance 'enum
+ :value ,(enum-call method)
+ :type (make-instance 'smoke-type
+ :id ,(id (return-type method))
+ :smoke ,smoke))
+ :test #'enum=))
Thu Aug 27 13:43:13 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Support the new smokegenerator (r1015073).
* support const correctness
* remove workarounds for the old smoke
The old smoke is no longer supported.
Thanks to Arno Rehn for making the smokegenerator work with cl-smoke.
hunk ./src/bindings.lisp 48
+(defmethod print-object ((smoke-module smoke-module) stream)
+ (if (null-pointer-p (smoke-module-pointer smoke-module))
+ (call-next-method)
+ (print-unreadable-object (smoke-module stream :type t :identity t)
+ (princ (smoke-get-module-name (smoke-module-pointer smoke-module))
+ stream))))
+
hunk ./src/class-map.lisp 29
-(defun find-smoke-class (class)
+(defun find-smoke-class (class &optional (error-p t))
hunk ./src/class-map.lisp 31
- (let* ((class (real-class class))
- (ret (gethash (id class) (id-class-map (smoke class)))))
- (assert (not (null ret))
- ()
- "The class ~A was not found." (name class))
+ (let* ((class (handler-case (real-class class)
+ (undefined-class (e) (when error-p (error e)))))
+ (ret (when class (gethash (id class) (id-class-map (smoke class))))))
+ (when error-p
+ (assert (not (null ret))
+ ()
+ "The class ~A was not found." (name class)))
hunk ./src/clos.lisp 111
+ (when (const-p object)
+ (princ "CONST " stream))
hunk ./src/clos.lisp 188
- (unless (external-p class)
- (add-id class
- (closer-mop:ensure-class (lispify (name class))
- :direct-superclasses
- (mapcar #'smoke-class-symbol
- (smoke-class-direct-superclasses class))
- :id (id class)
- :smoke (smoke class)
- :metaclass 'smoke-standard-class))
- (export (lispify (name class)))))
+ (unless (or (external-p class)
+ (and (eq package :cl-smoke.qt)
+ (string/= (smoke-get-module-name [_$_]
+ (smoke-module-pointer smoke))
+ "qt")
+ (string= (name class) "QGlobalSpace")))
+ (with-simple-restart (skip "Skip generating class ~A" (name class)) [_$_]
+ (add-id class
+ (closer-mop:ensure-class (lispify (name class))
+ :direct-superclasses
+ (mapcar #'smoke-class-symbol
+ (smoke-class-direct-superclasses class))
+ :id (id class)
+ :smoke (smoke class)
+ :metaclass 'smoke-standard-class))
+ (export (lispify (name class))))))
hunk ./src/clos.lisp 267
- (push (argument-to-lisp (mem-ref stack 'smoke-stack-item)
+ (cons (argument-to-lisp (mem-ref stack 'smoke-stack-item)
hunk ./src/clos.lisp 467
- (let ((ret (make-instance class :pointer pointer)))
+ (let ((ret (make-instance class :pointer pointer
+ :const-p (const-p type))))
hunk ./src/objects/class.lisp 94
- (make-smoke-class (smoke class) (name class))
+ (handler-case (make-smoke-class (smoke class) (name class))
+ (undefined-class () class))
hunk ./src/objects/enum.lisp 47
- (let ((type (enum-type (eval (first (first cases))))))
+ (flet ((first-key (keys)
+ (if (listp keys)
+ (first keys)
+ keys)))
+ (let ((type (enum-type (eval (first-key (first (first cases)))))))
hunk ./src/objects/enum.lisp 53
- (check-enum-type (eval (first case))
+ (check-enum-type (eval (first-key (first case)))
hunk ./src/objects/enum.lisp 56
- ; (check-enum-type (enum-type ,keyform)
- ; (enum-type ,(first (first cases))))
+ ;; (check-enum-type (enum-type ,keyform)
+ ;; (enum-type ,(first (first cases))))
hunk ./src/objects/enum.lisp 60
- collect `(,(value (eval (first case)))
- ,@(rest case))))))
+ collect `(,(if (listp (first case))
+ (mapcar #'(lambda (c)
+ (print c)
+ (value (eval c)))
+ (first case))
+ (value (eval (first case))))
+ ,@(rest case)))))))
hunk ./src/objects/stack.lisp 36
- [_$_]
hunk ./src/objects/stack.lisp 42
+ (const-p :reader const-p
+ :initarg :const-p
+ :initform nil
+ :documentation "Returns true when the object is const and nil otherwise.")
hunk ./src/objects/stack.lisp 102
+(defvar *to-lisp-translations* (make-hash-table :test 'equal))
+
hunk ./src/objects/stack.lisp 166
-(defvar *to-lisp-translations* (make-hash-table :test 'equal))
hunk ./src/objects/type.lisp 61
- (and t ;(pointer-eq (smoke type1)
- ; (smoke type2))
- (= (id type1)
- (id type2))))
+ (if (eq (smoke type1) (smoke type2))
+ (= (id type1) (id type2))
+ (string= (name type1) (name type2))))
hunk ./src/objects/type.lisp 122
- (declare (optimize (speed 3)))
- (zerop (mem-ref (mem-aref (smoke-array-pointer
- (smoke-module-types (smoke type)))
- 'smoke-type
- (the smoke-index (id type)))
- :char)))
+ (null-pointer-p (mem-ref
+ (foreign-slot-pointer [_$_]
+ (mem-aref (smoke-array-pointer
+ (smoke-module-types (smoke type)))
+ 'smoke-type
+ (the smoke-index (id type)))
+ 'smoke-type 'name)
+ :pointer)))
hunk ./src/overload-resolution.lisp 3
+;;;
+;;; We handle only the most common cases. Stuff like virtual inheritance
+;;; that is not needed is not implemented.
hunk ./src/overload-resolution.lisp 81
-(defmacro push-candidate-method (index name argument-count class methods)
+(defmacro push-candidate-method (index name argument-count class methods
+ const-p)
hunk ./src/overload-resolution.lisp 112
- (incf ,ambig-index)
- (push (make-smoke-method :smoke ,smoke
- :id ,i)
- ,methods)))
- (push ,method ,methods))) [_$_]
+ (incf ,ambig-index)
+ (let ((,method (make-smoke-method :smoke ,smoke
+ :id ,i)))
+ (unless (and ,const-p (not (const-p ,method)))
+ (push ,method ,methods)))))
+ (unless (and ,const-p (not (const-p ,method)))
+ (push ,method ,methods))))
hunk ./src/overload-resolution.lisp 129
-(defun viable-functions (name argument-count class)
- "Returns a list of methods named NAME that take ARGUMENT-COUNT methods."
- ;; 13.3.2
- ;;
- ;; FIXME make a lazy map-viable-functions to allow returning early,
- ;; when an exact match is found.
+(defun viable-functions (name argument-count class &optional const-p)
hunk ./src/overload-resolution.lisp 133
- (dolist (class (all-smoke-superclasses class))
- (let ((smoke (smoke class)))
- (let ((start-index (find-method-for-class name class)))
- (declare (type smoke-index start-index))
- (when (>= start-index 0)
- (loop for index from start-index downto 1
- while (push-candidate-method index name argument-count class
- methods))
- (loop for index from (1+ start-index)
- to (the smoke-index (smoke-array-length
- (smoke-module-method-maps smoke)))
- while (push-candidate-method index name argument-count class
- methods))))))
+ (let ((smoke (smoke class)))
+ (let ((start-index (find-method-for-class name class)))
+ (declare (type smoke-index start-index))
+ (when (>= start-index 0)
+ (loop for index from start-index downto 1
+ while (push-candidate-method index name argument-count class
+ methods const-p))
+ (loop for index from (1+ start-index)
+ to (the smoke-index (smoke-array-length
+ (smoke-module-method-maps smoke)))
+ while (push-candidate-method index name argument-count class
+ methods const-p)))))
hunk ./src/overload-resolution.lisp 168
-(defgeneric conversion< (conversion1 conversion2)
- (:documentation
- "Returns true when CONVERSION1 is better than CONVERSION2.")
+(defgeneric conversion<= (conversion1 conversion2)
hunk ./src/overload-resolution.lisp 173
- (or (null conversion2)
- (< (the fixnum (conversion-rank conversion1))
- (the fixnum (conversion-rank conversion2)))))
+ (and (not (null conversion1))
+ (or (null conversion2)
+ (<= (the fixnum (conversion-rank conversion1))
+ (the fixnum (conversion-rank conversion2))))))
hunk ./src/overload-resolution.lisp 192
- (:documentation
- "Returns true when the standard conversion sequence CONVERSION1
- is indistinguishable from CONVERSION2.")
hunk ./src/overload-resolution.lisp 193
- (= (conversion-rank conversion1) (conversion-rank conversion2)))
+ (and (conversion<= conversion1 conversion2)
+ (conversion<= conversion2 conversion1)))
hunk ./src/overload-resolution.lisp 202
- (if (conversion< conversion1 conversion2)
+ (if (conversion<= conversion1 conversion2)
hunk ./src/overload-resolution.lisp 241
- (let ((max-rank)
- (conversions))
- (loop for type in (arguments method)
- for class in classes do
- (let ((rank (call-using-type get-conversion-sequence class type user)))
- (when (null rank)
- (setf max-rank nil)
- (return nil))
- (setf max-rank (max-conversion rank max-rank))
- (push (conversion-function-name rank) conversions)))
- (values max-rank (reverse conversions))))
+ (if (null classes)
+ (values (make-match 'exact-match) nil)
+ (let ((max-rank)
+ (conversions))
+ (loop for type in (arguments method)
+ for class in classes do
+ (let ((rank (call-using-type get-conversion-sequence class type user)))
+ (when (null rank)
+ (setf max-rank nil)
+ (return nil))
+ (setf max-rank (max-conversion rank max-rank))
+ (push (conversion-function-name rank) conversions)))
+ (values max-rank (reverse conversions)))))
hunk ./src/overload-resolution.lisp 258
-(defun+using-types find-best-viable-function (name arguments class)
+(defun+using-types find-best-viable-function (name arguments class
+ &optional const-p)
hunk ./src/overload-resolution.lisp 264
- name arguments class))
+ name arguments class const-p))
hunk ./src/overload-resolution.lisp 266
-(defun+using-types find-best-viable-function2 (get-sequence name objects class)
- (declare (type (function (t list) (values t function)) get-sequence))
+(defun+using-types find-best-viable-function2 (get-sequence name objects class
+ &optional const-p)
hunk ./src/overload-resolution.lisp 272
- class))
+ class const-p))
hunk ./src/overload-resolution.lisp 276
- (loop for method in viable-functions do
- (multiple-value-bind (rank method-conversions)
- (funcall get-sequence method objects)
- ;; FIXME test for ambiguous overload #'conversion=
- (when (and rank (conversion< rank best-rank))
- (setf best-rank rank)
- (setf best-method method)
- (setf conversions method-conversions)
- (when (conversion= rank (make-match 'exact-match))
- (return)))))
- (values best-method conversions)))
+ (if (null viable-functions)
+ (dolist (class (closer-mop:class-direct-superclasses class)
+ (values best-method nil))
+ (when (typep class 'smoke-standard-class)
+ (multiple-value-bind (method conversions)
+ (call-using-types find-best-viable-function2 get-sequence name objects class const-p)
+ (when method
+ (return (values method conversions))))))
+ (loop for method in viable-functions
+ finally (return (values best-method conversions)) do
+ (block next
+ (multiple-value-bind (rank method-conversions)
+ (funcall get-sequence method objects)
+ (when (and rank (conversion<= rank best-rank))
+ (when (conversion= rank best-rank)
+ ;; FIXME catch all ambigious overloads
+ (if const-p
+ (error "Ambigious overload ~A." method)
+ (when (const-p method)
+ ;; assume that the previous method is a non
+ ;; const one and thus more specific.
+ (return-from next))))
+ (setf best-rank rank)
+ (setf best-method method)
+ (setf conversions method-conversions)
+ (when (and (conversion= rank (make-match 'exact-match))
+ (not (xor const-p (const-p method))))
+ (return (values method conversions))))))))))
hunk ./src/overload-resolution.lisp 397
- (derived-p (object.type-of) (get-class type)))
+ (derived-p (object.type-of) (get-class type))
+ (find-smoke-class (get-class type)))
hunk ./src/overload-resolution.lisp 449
- (if (pointer-p to-type)
- ;; Insert a space before the #\*
- (let ((name (name to-type)))
- (concatenate 'string
- (subseq name 0 (1- (length name)))
- " *"))
- (name to-type)))))
+ (name to-type))))
hunk ./src/overload-resolution.lisp 459
- (assert (not (void-p type))
- ()
- "Conversion operators not supported by Smoke.
-Update to Smoke >= r955426.")
hunk ./src/overload-resolution.lisp 473
- (let ((to-class (find-smoke-class (get-class type))))
- (when (call-using-types find-best-viable-function2
- (if (using-typep)
- #'standard-conversion-sequence-using-types
- #'standard-conversion-sequence)
- (constructor-name (get-class type))
- (list object) to-class)
+ (let ((to-class (find-smoke-class (get-class type) nil)))
+ (when (and to-class
+ (call-using-types find-best-viable-function2
+ (if (using-typep)
+ #'standard-conversion-sequence-using-types
+ #'standard-conversion-sequence)
+ (constructor-name (get-class type))
+ (list object) to-class))
hunk ./src/overload-resolution.lisp 514
- (if (null arguments)
- (let ((method (find-smoke-method (smoke-class-of object-or-class)
- name)))
- (unless (valid-p method)
- (error (make-condition 'no-applicable-cxx-method
- :method name
- :class object-or-class
- :arguments arguments)))
- (if (static-p method)
- (s-call method (null-pointer))
- (s-call method (cast object-or-class (get-class method)))))
- (multiple-value-bind (method sequence)
- (find-best-viable-function name
- arguments
- (smoke-class-of object-or-class))
- (when (null method)
- (error (make-condition 'no-applicable-cxx-method
- :method name
- :class object-or-class
- :arguments arguments)))
- (if (static-p method)
- (apply #'call-sequence method (null-pointer) sequence arguments)
- (apply #'call-sequence method (cast object-or-class (get-class method)) [_$_]
- sequence arguments)))))
+ (multiple-value-bind (method sequence)
+ (find-best-viable-function name
+ arguments
+ (smoke-class-of object-or-class)
+ (when (typep object-or-class
+ 'smoke-standard-object)
+ (const-p object-or-class)))
+ (when (null method)
+ (error (make-condition 'no-applicable-cxx-method
+ :method name
+ :class object-or-class
+ :arguments arguments)))
+ (if (static-p method)
+ (apply #'call-sequence method (null-pointer) sequence arguments)
+ (apply #'call-sequence method (cast object-or-class (get-class method)) [_$_]
+ sequence arguments))))
hunk ./src/package.lisp 38
+ #:const-p
hunk ./src/smoke-to-clos.lisp 106
- (when (and (enum-p method)
- ;; FIXME workaround for
- ;; http://lists.kde.org/?l=kde-bindings&m=123464781307375
- (not (string= (name (get-class method))
- "KGlobalSettings")))
+ (when (enum-p method)
Sun Aug 2 12:12:41 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Cleanup C++ to Lisp translation
move ./src/method.lisp ./src/smoke-to-clos.lisp
hunk ./smoke.mbd 35
- ("translate" (:needs "package"))
hunk ./smoke.mbd 44
- ("method" (:needs "clos" "overload-resolution"))
+ ("smoke-to-clos" (:needs "clos" "overload-resolution"))
hunk ./smoke.mbd 46
- (:needs "smoke-c" "utils")
+ (:needs "smoke-c" "utils" "bindings")
hunk ./smoke.mbd 51
- (:needs "package" "translate")
+ (:needs "package")
hunk ./src/bindings.lisp 3
-(defvar *bindings* (make-hash-table))
+(defvar *bindings* (make-hash-table)
+ "The Smoke C++ binding classes to which virtual method calls are dispatched.")
hunk ./src/bindings.lisp 26
+ "A C array."
hunk ./src/bindings.lisp 45
-(defvar *smoke-modules* (make-hash-table))
+(defvar *smoke-modules* (make-hash-table)
+ "All loaded Smoke modules.")
hunk ./src/class-map.lisp 8
-
hunk ./src/class-map.lisp 11
- (assert value [_$_]
- ()
+ (assert value ()
hunk ./src/class-map.lisp 17
- (setf (gethash (pointer-address (smoke-module-pointer smoke)) *smoke-id-class-map*)
+ (setf (gethash (pointer-address (smoke-module-pointer smoke))
+ *smoke-id-class-map*)
hunk ./src/class-map.lisp 22
- (setf (id-class-map smoke)
- (make-hash-table)))
+ (setf (id-class-map smoke) (make-hash-table)))
hunk ./src/class-map.lisp 26
- (setf (gethash (id smoke-class)
- (id-class-map (smoke smoke-class)))
+ (setf (gethash (id smoke-class) (id-class-map (smoke smoke-class)))
hunk ./src/class-map.lisp 32
- (ret (gethash (id class)
- (id-class-map (smoke class)))))
+ (ret (gethash (id class) (id-class-map (smoke class)))))
hunk ./src/clos.lisp 12
-
hunk ./src/clos.lisp 122
-(defmethod closer-mop:validate-superclass ((class smoke-standard-class) (superclass standard-class))
+(defmethod closer-mop:validate-superclass ((class smoke-standard-class)
+ (superclass standard-class))
hunk ./src/clos.lisp 126
-(defmethod closer-mop:validate-superclass ((class cxx:class) (superclass smoke-standard-class))
+(defmethod closer-mop:validate-superclass ((class cxx:class)
+ (superclass smoke-standard-class))
hunk ./src/clos.lisp 130
-(defmethod reinitialize-instance :around
- ((class smoke-standard-class)
- &rest args &key direct-superclasses &allow-other-keys)
- (apply
- #'call-next-method class
- :direct-superclasses (or direct-superclasses
- (list (find-class
- 'smoke-standard-object))) args))
+;; Sets NIL superclass to SMOKE-STANDARD-OBJECT instead of the default
+;; STANDARD-OBJECT.
+(defun init-smoke-standard-class (class next-method
+ &rest args &key direct-superclasses
+ &allow-other-keys)
+ (apply next-method class
+ :direct-superclasses (or direct-superclasses
+ (list (find-class 'smoke-standard-object)))
+ args))
hunk ./src/clos.lisp 140
-(defmethod initialize-instance :around
- ((class smoke-standard-class)
- &rest args &key direct-superclasses &allow-other-keys)
- "Sets NIL superclass to SMOKE-STANDARD-OBJECT instead of the default STANDARD-OBJECT."
- (apply
- #'call-next-method class
- :direct-superclasses (or direct-superclasses
- (list (find-class 'smoke-standard-object)))
- args))
+(defmethod initialize-instance :around ((class smoke-standard-class) &rest args)
+ (apply #'init-smoke-standard-class class #'call-next-method args))
+
+(defmethod reinitialize-instance :around ((class smoke-standard-class) &rest args)
+ (apply #'init-smoke-standard-class class #'call-next-method args))
hunk ./src/clos.lisp 146
-(defmethod reinitialize-instance :around
- ((class cxx:class)
- &rest args &key direct-superclasses &allow-other-keys)
- (assert (not (null direct-superclasses))
- (direct-superclasses)
- "No superclass supplied for class ~A" class)
- (let ((superclass (first direct-superclasses)))
- (assert (subtypep (class-of superclass) (find-class 'smoke-standard-class))
- ((first direct-superclasses))
- "The first superclass must be an subclass of an smoke class.")
- (apply
- #'call-next-method class
- :id (id superclass)
- :smoke (smoke superclass)
- :direct-superclasses direct-superclasses
- args)))
hunk ./src/clos.lisp 147
-(defmethod initialize-instance :around
- ((class cxx:class)
- &rest args &key direct-superclasses &allow-other-keys)
+(defun init-cxx-class (class next-method &rest args &key direct-superclasses
+ &allow-other-keys)
hunk ./src/clos.lisp 159
- [_$_]
hunk ./src/clos.lisp 160
- #'call-next-method class
+ next-method class
hunk ./src/clos.lisp 166
+(defmethod reinitialize-instance :around ((class cxx:class) &rest args)
+ (apply #'init-cxx-class class #'call-next-method args))
+ [_$_]
+(defmethod initialize-instance :around ((class cxx:class) &rest args)
+ (apply #'init-cxx-class class #'call-next-method args))
+
hunk ./src/clos.lisp 237
+ ;; The destructed callback can be the result of deleting the object
+ ;; in a finalizer. In that case the object is already removed from
+ ;; *object-map* when the callback is invoked. Thus OBJECT can be NIL.
hunk ./src/clos.lisp 248
+ ;; It looks like there is no stack allocation in Qt virtual method signatures.
hunk ./src/clos.lisp 259
- (push (argument-to-lisp (mem-ref stack
- 'smoke-stack-item)
+ (push (argument-to-lisp (mem-ref stack 'smoke-stack-item)
hunk ./src/clos.lisp 287
- (transfer-ownership-to value object)))))))
+ (remove-object (pointer value))))))))
+ ; (transfer-ownership-to value object)))))))
hunk ./src/clos.lisp 295
+;; Receive virutal function calls.
hunk ./src/clos.lisp 304
- ;; FIXME:
- ;;(assert object
- ;; (object)
- ;; "No object for ~A to call ~A." object-ptr method)
- (if (and object (typep (class-of object) 'cxx:class))
- ;; Do not allow overwriting methods of classes the users has
- ;; not derived from (like in C++), to reduce overhead.
- (let* ((method (make-smoke-method
- :smoke (gethash (pointer-address
- (smoke-get-smoke binding))
- *smoke-modules*)
- :id method)))
- (loop
- (restart-case
- (return-from dispatch-method
- (let ((gf (get-gf-for-method method)))
- (declare (function gf))
- (if (null (gf-methods gf))
- (progn
- (when abstract
- (error "Abstract method ~A called."
- (method-declaration method)))
- nil)
- (if object
- (progn
- (put-returnvalue stack
- (apply gf object
- (stack-to-args
- (inc-pointer stack [_$_]
- (foreign-type-size
- 'smoke-stack-item))
- (get-first-argument method)))
- (return-type method)
- object)
- t)
- nil))))
- ;; Restarts to prevent stack unwinding across the C++ stack.
- (call-default ()
- :report (lambda (stream)
- (declare (stream stream))
- (format stream "Call default implementation ~A instead."
- method))
- :test (lambda (condition)
- (declare (ignore condition))
- (not abstract))
- (return-from dispatch-method nil))
- (use-returnvalue (return-value)
- :report (lambda (stream)
- (declare (stream stream))
- (format stream "Supply a return value for ~A."
- (method-declaration method)))
- :test (lambda (condition)
- (declare (ignore condition))
- (not (void-p (return-type method))))
- :interactive (lambda ()
- (format *query-io* "~&Enter a new return value: ")
- (multiple-value-list (eval (read *query-io*))))
- (put-returnvalue stack return-value [_$_]
- (return-type method)
- (get-object object-ptr))
- (return-from dispatch-method t))
- (return ()
- :report (lambda (stream)
- (declare (stream stream))
- (format stream "Return void for ~A."
- (method-declaration method)))
- :test (lambda (condition)
- (declare (ignore condition))
- (void-p (return-type method)))
- (return-from dispatch-method (values)))
- (retry ()
- :report (lambda (stream)
- (declare (stream stream))
- (format stream "Try again calling ~A." [_$_]
- (method-declaration method))))))
- nil))))
+ ;; The Lisp OBJECT can be gc'ed but we might still receive a
+ ;; QObject destructed event when the C++ instance is deleted in
+ ;; the finalizer. Thus OBJECT might be NIL.
+ (when (and object (typep (class-of object) 'cxx:class))
+ ;; Do not allow overwriting methods of classes the users has
+ ;; not derived from (like in C++), to reduce overhead.
+ (let* ((method (make-smoke-method
+ :smoke (gethash (pointer-address
+ (smoke-get-smoke binding))
+ *smoke-modules*)
+ :id method)))
+ (loop
+ (restart-case
+ (return-from dispatch-method
+ (let ((gf (get-gf-for-method method)))
+ (declare (function gf))
+ (if (null (gf-methods gf))
+ (progn
+ (when abstract
+ (error "Abstract method ~A of ~A called."
+ (method-declaration method) object))
+ nil)
+ (if object
+ (progn
+ (put-returnvalue
+ stack
+ (apply gf object
+ (stack-to-args
+ (inc-pointer stack (foreign-type-size
+ 'smoke-stack-item))
+ (get-first-argument method)))
+ (return-type method) object)
+ t)
+ nil))))
+ ;; Restarts to prevent stack unwinding across the C++ stack.
+ (call-default ()
+ :report (lambda (stream)
+ (declare (stream stream))
+ (format stream
+ "Call default implementation ~A instead."
+ method))
+ :test (lambda (condition)
+ (declare (ignore condition))
+ (not abstract))
+ (return-from dispatch-method nil))
+ (use-returnvalue (return-value)
+ :report (lambda (stream)
+ (declare (stream stream))
+ (format stream "Supply a return value for ~A."
+ (method-declaration method)))
+ :test (lambda (condition)
+ (declare (ignore condition))
+ (not (void-p (return-type method))))
+ :interactive (lambda ()
+ (format *query-io* "~&Enter a new return value: ")
+ (multiple-value-list (eval (read *query-io*))))
+ (put-returnvalue stack return-value [_$_]
+ (return-type method)
+ (get-object object-ptr))
+ (return-from dispatch-method t))
+ (return ()
+ :report (lambda (stream)
+ (declare (stream stream))
+ (format stream "Return void for ~A."
+ (method-declaration method)))
+ :test (lambda (condition)
+ (declare (ignore condition))
+ (void-p (return-type method)))
+ (return-from dispatch-method (values)))
+ (retry ()
+ :report (lambda (stream)
+ (declare (stream stream))
+ (format stream "Try again calling ~A." [_$_]
+ (method-declaration method))))))
+ nil))))
hunk ./src/clos.lisp 401
-(defmethod convert-to-class (smoke-class (object smoke-standard-object))
- (cast object smoke-class))
-
+;; The constructor name is the name of the class minus any namespace parts.
hunk ./src/clos.lisp 469
- (cerror "ignore" "~A has already been called for ~A."
- #'keep-wrapper object))
+ (cerror "ignore" "~A has already been added to ~A."
+ object new-owner))
hunk ./src/cxx-method.lisp 4
- ((gf-methods :initform nil
+ ((gf-methods :initform nil :type list
hunk ./src/cxx-method.lisp 6
- :type list
- :documentation "Generic functions for different argument counts."))
+ :documentation "gf for different argument counts."))
hunk ./src/cxx-method.lisp 8
- (:documentation
- "A generic function that can be overloaded by argument count."))
+ (:documentation "gf that can be overloaded by argument count."))
hunk ./src/cxx-method.lisp 37
- (= argument-count
- (argument-count gf)))
+ (= argument-count (argument-count gf)))
hunk ./src/cxx-method.lisp 80
- (let ((generic-function (ensure-gf-by-argument-count cxx-generic-function
- (method-argument-count method))))
+ (let ((generic-function (ensure-gf-by-argument-count
+ cxx-generic-function
+ (method-argument-count method))))
hunk ./src/object-map.lisp 9
-
hunk ./src/object-map.lisp 37
-except object with a non virtual destructor which had their ownership transferred
-to C++.")
+except object with a non virtual destructor which had their ownership
+transferred to C++.")
hunk ./src/object-map.lisp 61
-(defun remove-if-exists (pointer)
- (remhash (pointer-address pointer) *object-map*))
-
hunk ./src/object-map.lisp 62
- (declare (optimize (speed 3)))
hunk ./src/object-map.lisp 109
- [_$_]
+ [_$_]
hunk ./src/object-map.lisp 113
- (assert (not (has-pointer-p (pointer object)))
- ()
+ (assert (not (has-pointer-p (pointer object))) ()
hunk ./src/objects/class.lisp 4
- ((id :initform 0 :type smoke-index :reader id :initarg :id)
- (smoke :type smoke-module :reader smoke :initarg :smoke)))
+ ((id :initform 0 :type smoke-index
+ :reader id :initarg :id)
+ (smoke :type smoke-module
+ :reader smoke :initarg :smoke)))
hunk ./src/objects/class.lisp 12
-
hunk ./src/objects/class.lisp 14
- (mem-aref (the foreign-pointer (smoke-array-pointer (smoke-module-classes
- (smoke class))))
+ (mem-aref (the foreign-pointer
+ (smoke-array-pointer (smoke-module-classes (smoke class))))
hunk ./src/objects/class.lisp 46
- (declare (optimize (speed 3)))
+ (declare (type smoke-class class)
+ (optimize (speed 3)))
hunk ./src/objects/class.lisp 73
-;smoke-find-class
hunk ./src/objects/class.lisp 111
- (smoke-is-derived-from (smoke-module-pointer (smoke class)) (id class)
- (smoke-module-pointer (smoke base-class)) (id base-class)))
+ (smoke-is-derived-from (smoke-module-pointer (smoke class)) [_$_]
+ (id class)
+ (smoke-module-pointer (smoke base-class))
+ (id base-class)))
hunk ./src/objects/class.lisp 130
- class (append classes
- (list
- (make-smoke-class-from-id (smoke class)
- class-index)))
+ class
+ (append classes
+ (list (make-smoke-class-from-id (smoke class) class-index)))
hunk ./src/objects/enum.lisp 6
-;;;
hunk ./src/objects/enum.lisp 33
- enum-type)
+ enum-type)
hunk ./src/objects/enum.lisp 41
- (enum-type enum2))
+ (enum-type enum2))
hunk ./src/objects/enum.lisp 69
- collect `(,(value (eval (first case)))
- ,@(rest case)))))
+ collect `(,(value (eval (first case)))
+ ,@(rest case)))))
hunk ./src/objects/method.lisp 17
- (if (or (null-pointer-p (smoke-module-pointer (smoke-method-smoke smoke-method)))
+ (if (or (null-pointer-p (smoke-module-pointer
+ (smoke-method-smoke smoke-method)))
hunk ./src/objects/method.lisp 56
- (the (smoke-index 0)
- (method-slot-value method 'name))))
+ (the (smoke-index 0) (method-slot-value method 'name))))
hunk ./src/objects/method.lisp 139
- (format nil "~A~:[~; static~]" (access method)
- (static-p method)))
+ (format nil "~A~:[~; static~]" (access method) (static-p method)))
hunk ./src/objects/method.lisp 255
-
hunk ./src/objects/stack.lisp 20
- :top (inc-pointer smoke-stack
- #.(foreign-type-size 'smoke-stack-item))))
+ :top (inc-pointer smoke-stack #.(foreign-type-size 'smoke-stack-item))))
hunk ./src/objects/stack.lisp 23
- (setf (foreign-slot-value (call-stack-top stack)
- 'smoke-stack-item type) value)
+ (setf (foreign-slot-value (call-stack-top stack) 'smoke-stack-item type)
+ value)
hunk ./src/objects/stack.lisp 31
- 'smoke-stack-item ,type) ,value)
+ 'smoke-stack-item ,type)
+ ,value)
hunk ./src/objects/stack.lisp 103
- (0 (let ((cffi-type (get-type (name type))))
- (if (null cffi-type)
- (progn [_$_]
- ;; FIXME warn but not on void**
- ;;(warn "Unknown translation from ~A to lisp." (name type))
- (foreign-slot-value stack-item 'smoke-stack-item 'voidp))
- (let* ((pointer (foreign-slot-value stack-item
- 'smoke-stack-item
- 'voidp))
- (value (convert-from-foreign pointer cffi-type)))
- (when (stack-p type)
- ;; FIXME free-translated-object is not intended for this;
- ;; param is NIL for now.
- (cffi:free-translated-object pointer cffi-type nil))
- value
- ))))
+ (0 (if-let ((translation (gethash (name type) *to-lisp-translations*)))
+ (let ((pointer (foreign-slot-value stack-item 'smoke-stack-item
+ 'voidp)))
+ (prog1 (funcall (car translation) pointer)
+ (when (stack-p type)
+ (funcall (cdr translation) pointer))))
+ (error "Do not know how to convert the type ~A to Lisp." type)))
hunk ./src/objects/stack.lisp 122
- :value (foreign-slot-value stack-item 'smoke-stack-item 'enum-value)
+ :value (foreign-slot-value stack-item 'smoke-stack-item
+ 'enum-value)
hunk ./src/objects/stack.lisp 132
- (if (class-p type)
- (let ((class (get-class type)))
- (if (has-pointer-p object)
+ (let ((class (get-class type)))
+ (if (has-pointer-p object)
+ (if (derived-p (class-of (get-object object))
+ (get-class type))
hunk ./src/objects/stack.lisp 137
- (instance-to-lisp object (find-smoke-class class) type)))
- nil))
+ (progn
+ (cerror "Remove the old object."
+ "The object at pointer ~A is ~A but should be a ~A."
+ object (get-object object) type)
+ (remove-object object)
+ (instance-to-lisp object (find-smoke-class class) type)))
+ (instance-to-lisp object (find-smoke-class class) type))))
hunk ./src/objects/stack.lisp 149
- (object-to-lisp (foreign-slot-value stack-item
- 'smoke-stack-item
+ (object-to-lisp (foreign-slot-value stack-item 'smoke-stack-item
hunk ./src/objects/stack.lisp 157
- ((void-p type)
- (values))
- ((class-p type)
- (class-to-lisp stack-item type))
- (t
- (enum-to-lisp stack-item type))))
+ ((void-p type) (values))
+ ((class-p type) (class-to-lisp stack-item type))
+ (t (enum-to-lisp stack-item type))))
+
+(defvar *to-lisp-translations* (make-hash-table :test 'equal))
+
+(defun error-no-free (object)
+ (error "Can not free object at ~A." object))
+
+(defmacro define-to-lisp-translation (type-names &optional
+ (conversion-function-name 'identity)
+ (free-function-name 'error-no-free))
+ `(progn ,@(loop for type-name in (ensure-list type-names)
+ collect `(setf (gethash ,type-name *to-lisp-translations*)
+ (cons ',conversion-function-name
+ ',free-function-name)))))
+
+(defmacro define-pointer-typedef (type-names lisp-type)
+ (declare (ignore lisp-type))
+ `(progn [_$_]
+ (define-to-lisp-translation ,type-names identity identity)))
+ ;; not needed
+ ;;(define-from-lisp-translation ,type-names ,lisp-type)))
+
+(define-to-lisp-translation ("void*" "const void*" "void**"))
+
+(define-to-lisp-translation ("char*" "const char*") foreign-string-to-lisp)
hunk ./src/objects/type.lisp 80
- ;; Can't just use #'get-type-flag since it
- ;; can only be one of :stack, :reference and :pointer.
+ ;; Can't just use #'get-type-flag since it can only be one of
+ ;; :stack, :reference and :pointer.
hunk ./src/objects/type.lisp 124
- (= 0 (mem-ref (mem-aref (smoke-array-pointer
- (smoke-module-types (smoke type)))
- 'smoke-type
- (the smoke-index (id type)))
- :char)))
+ (zerop (mem-ref (mem-aref (smoke-array-pointer
+ (smoke-module-types (smoke type)))
+ 'smoke-type
+ (the smoke-index (id type)))
+ :char)))
hunk ./src/objects/type.lisp 136
- (assert (/= -1 (type-slot-value type 'class))
+ (assert (class-p type)
hunk ./src/objects/type.lisp 138
- "The type ~S is not a smoke class." (name type))
- (make-smoke-class-from-id
- (smoke type)
- (type-slot-value type 'class)))
+ "The type ~S is not a smoke class." type)
+ (make-smoke-class-from-id (smoke type) (type-slot-value type 'class)))
hunk ./src/overload-resolution.lisp 407
+ ;;
+ ;; But it is needed for passing the int pointer in QApplication(int&, char**).
hunk ./src/overload-resolution.lisp 413
- :from (find-class 't)
- :to (find-class 't)))) ;; FIXME get the class when applicable
+ :from (find-class 't)
+ :to (find-class 't)))) ;; FIXME get the class when applicable
hunk ./src/package.lisp 33
+ #:define-to-lisp-translation
+ #:define-pointer-typedef
hunk ./src/smoke-c/csmokebinding.cpp 4
+#include <QDebug>
hunk ./src/smoke-c/csmokebinding.cpp 17
+ * @param class_index Index of the object's class.
hunk ./src/smoke-c/smoke-c.lisp 16
-
hunk ./src/smoke-c/smoke-c.lisp 17
-
hunk ./src/smoke.lisp 34
- 'smoke-class
- 'class-function)
+ 'smoke-class 'class-function)
hunk ./src/smoke.lisp 37
- 'smoke-method
- 'method)
+ 'smoke-method 'method)
hunk ./src/smoke.lisp 52
-
hunk ./src/smoke.lisp 53
- (s-call
- (make-smoke-method-from-name class method-name)
- pointer args))
+ (s-call (make-smoke-method-from-name class method-name) pointer args))
hunk ./src/smoke.lisp 56
- (s-call
- (make-smoke-method-from-name (make-smoke-class smoke class-name)
- method-name)
- (null-pointer) args))
+ (s-call (make-smoke-method-from-name (make-smoke-class smoke class-name)
+ method-name)
+ (null-pointer) args))
hunk ./src/smoke.lisp 63
+ ;;
hunk ./src/smoke.lisp 66
- ;; and confuses it with the member function type() ??
- ;; (27.2.09)
+ ;; and confuses it with the member function type() ?? (27.2.09)
hunk ./src/smoke.lisp 78
- (s-call
- (make-smoke-method-from-name class method-name)
- pointer)))
+ (s-call (make-smoke-method-from-name class method-name) pointer)))
hunk ./src/smoke.lisp 83
- (make-smoke-method-from-name (class-of object) method-name)
- (pointer object)))
+ (make-smoke-method-from-name (class-of object) method-name)
+ (pointer object)))
hunk ./src/smoke.lisp 91
- (setf (foreign-slot-value (mem-aref stack
- 'smoke-stack-item
- 1)
- 'smoke-stack-item
- 'voidp)
+ (setf (foreign-slot-value (mem-aref stack 'smoke-stack-item 1)
+ 'smoke-stack-item 'voidp)
hunk ./src/smoke.lisp 96
- 'smoke-class
- 'class-function)
+ 'smoke-class 'class-function)
hunk ./src/smoke.lisp 99
- :pointer (pointer object) smoke-stack stack
+ :pointer (pointer object)
+ smoke-stack stack
hunk ./src/smoke.lisp 106
- (let* ((binding (smoke-init smoke
- (callback destructed)
+ (let* ((binding (smoke-init smoke (callback destructed)
hunk ./src/smoke.lisp 118
- (setf (gethash (pointer-address (smoke-module-pointer (eval symbol))) pointer-symbol-map)
+ (setf (gethash (pointer-address (smoke-module-pointer (eval symbol)))
+ pointer-symbol-map)
hunk ./src/smoke.lisp 126
- (smoke-call (class-of object)
- (pointer object)
- method-name
- args))
+ (smoke-call (class-of object) (pointer object)
+ method-name args))
hunk ./src/smoke.lisp 140
-
hunk ./src/smoke.lisp 185
+
hunk ./src/smoke.lisp 187
- (defcvar (,variable ,variable-name
- :read-only t
- :library ,library) :pointer)
+ (defcvar (,variable ,variable-name :read-only t :library ,library)
+ :pointer)
hunk ./src/smoke.lisp 202
-
hunk ./src/translate.lisp 1
-(in-package :smoke)
-
-(defvar *type-map* (make-hash-table :test 'equal))
-
-(defun get-type (name)
- "Return the CFFI type for NAME."
- (gethash name *type-map*))
-
-(defun add-type (name type)
- "Registers the CFFI type TYPE with NAME."
- (setf (gethash name *type-map*) type))
-
-(defun setup-type-map ()
- "Setup C string <-> Lisp string translation."
- (add-type "char*" :string)
- (add-type "const char*" :string))
-
-(eval-when (:load-toplevel :execute)
- (setup-type-map))
-
-(defgeneric convert-to-class (smoke-class object))
-
-;(defmethod convert-to-class (smoke-class (pointer cffi:foreign-pointer))
-(defmethod convert-to-class (smoke-class pointer)
- (declare (ignore smoke-class))
- (assert (cffi:pointerp pointer))
- pointer)
rmfile ./src/translate.lisp
Fri Jul 24 15:32:23 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix conversion sequence from QByteArray to const char*.
hunk ./src/overload-resolution.lisp 424
+(defun conversion-operator-name (to-type)
+ (concatenate 'string
+ "operator "
+ (if (class-p to-type)
+ (name (get-class to-type))
+ (if (pointer-p to-type)
+ ;; Insert a space before the #\*
+ (let ((name (name to-type)))
+ (concatenate 'string
+ (subseq name 0 (1- (length name)))
+ " *"))
+ (name to-type)))))
+
+(defun coerce-to-type (object method)
+ (pointer-call method (pointer object)))
+ [_$_]
hunk ./src/overload-resolution.lisp 443
- (format nil "operator ~A" [_$_]
- (if (class-p type)
- (name (get-class type))
- (name type))))))
+ (conversion-operator-name type))))
hunk ./src/overload-resolution.lisp 449
- (make-match 'user-conversion
- (lispify (name method) :cxx))))))
+ (if (pointer-p type)
+ (make-match 'user-conversion
+ 'coerce-to-type
+ method)
+ (make-match 'user-conversion
+ (lispify (name method) :cxx)))))))
Thu Jul 23 00:26:05 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Use strcmp, fix constructor & destrucor calling for classes witn namespace (phonon::MediaPlayer) and add :arg0 to :arg2 initargs
hunk ./TODO 1
-Methods:
- * C++ overload resolution & argument promotion
- => no more writing (make-instance 'qt:byte-array :args ("foo"))
- * Test for null pointer in this and for references
- * default arguments
- * fetch name of arguments
-
-* const correctness
-
-* keyword arguments for make-instance
-
-* QApplication and KCmdLineArgs.init call exit() on e.g. "--help"
-
-Testsuite:
- * Fix segfaults when lots of qt:applictions are created & deleted
- * Test condition & restarts
-
-finalization:
- * get rid of owned-p
- * use QObject::deleteLater ?
-
-* Exceptions
rmfile ./TODO
hunk ./src/clos.lisp 22
- ;; At least on sbcl 1.0.25.debian CONCATENATE is faster
- ;; than VECTOR-PUSH-EXTEND
+ ;; At least on sbcl 1.0.25.debian CONCATENATE is faster than
+ ;; VECTOR-PUSH-EXTEND.
hunk ./src/clos.lisp 124
- T)
+ t)
hunk ./src/clos.lisp 127
- T)
+ t)
hunk ./src/clos.lisp 248
- ((object-pointer :pointer))
+ ((object-pointer :pointer))
hunk ./src/clos.lisp 270
- 'smoke-stack-item)
- arg)
+ 'smoke-stack-item)
+ arg)
hunk ./src/clos.lisp 289
+ ;;
hunk ./src/clos.lisp 291
- ;; passed on the stack. E.g. converted-value can be something like
- ;; (cxx:operator-variant value).
+ ;; passed on the stack. E.g. converted-value can be something
+ ;; like (cxx:operator-variant value).
hunk ./src/clos.lisp 318
- ;; Do not allow overwriting methods of classes the users has not derived from (like in C++),
- ;; to reduce overhead.
+ ;; Do not allow overwriting methods of classes the users has
+ ;; not derived from (like in C++), to reduce overhead.
hunk ./src/clos.lisp 321
- :smoke (gethash (pointer-address (smoke-get-smoke binding))
+ :smoke (gethash (pointer-address
+ (smoke-get-smoke binding))
hunk ./src/clos.lisp 414
+(defun constructor-name (class)
+ (let ((name-start (search "::" (name class) :from-end t)))
+ (if name-start
+ (subseq (name class) (+ name-start 2))
+ (name class))))
+
hunk ./src/clos.lisp 423
- (name (class-of object)))))
+ (constructor-name (class-of object)))))
+ (assert (valid-p method)
+ (method)
+ "No constructor for ~A." object)
hunk ./src/clos.lisp 429
- (find-best-viable-function (name (class-of object))
+ (find-best-viable-function (constructor-name (class-of object))
hunk ./src/clos.lisp 433
- (error "No constructor ~A for ~S"
- object arguments))
+ (error "No constructor for object ~A with
+the arguments ~S." object arguments))
hunk ./src/clos.lisp 441
- &key args &allow-other-keys)
+ &key args
+ (arg0 nil arg0p)
+ (arg1 nil arg1p)
+ (arg2 nil arg2p)
+ &allow-other-keys)
hunk ./src/clos.lisp 455
- (setf (slot-value object 'pointer) (call-constructor object args))
+ (if arg0p
+ (setf (slot-value object 'pointer) [_$_]
+ (call-constructor object [_$_]
+ (cond
+ (arg2p (list arg0 arg1 arg2))
+ (arg1p (list arg0 arg1))
+ (t (list arg0)))))
+ (setf (slot-value object 'pointer) (call-constructor object args)))
hunk ./src/object-map.lisp 67
- (assert (has-pointer-p pointer)
- (pointer)
- "No object to remove for pointer ~A." pointer)
- (remhash (pointer-address pointer) *object-map*))
+ (unless (remhash (pointer-address pointer) *object-map*)
+ (cerror "ignore" "No object to remove for pointer ~A." pointer)))
hunk ./src/object-map.lisp 103
+
+(defun debug-finalize ()
+ (eval '(defmethod make-finalize :around (object)
+ (let ((pointer (pointer object))
+ (class (class-of object))
+ (next (call-next-method)))
+ #'(lambda ()
+ (format *debug-io* "cl-smoke: finalizing: ~A..."
+ (make-instance class :pointer pointer))
+ (funcall next)
+ (format *debug-io* "done~%"))))))
hunk ./src/objects/class.lisp 122
- (assert (<= class-index
- (smoke-array-length
- (smoke-module-classes (smoke class)))))
+ (assert (<= class-index (smoke-array-length
+ (smoke-module-classes (smoke class)))))
hunk ./src/objects/class.lisp 126
- (smoke-add-superclass class (append classes
- (list
- (make-smoke-class-from-id (smoke class)
- class-index)))
- (1+ index)))))
+ (smoke-add-superclass
+ class (append classes
+ (list
+ (make-smoke-class-from-id (smoke class)
+ class-index)))
+ (1+ index)))))
hunk ./src/objects/method.lisp 50
+(declaim (inline smoke-method-name))
+(defun smoke-method-name (method)
+ (mem-aref (smoke-array-pointer (smoke-module-method-names [_$_]
+ (smoke-method-smoke method)))
+ :pointer
+ (the (smoke-index 0)
+ (method-slot-value method 'name))))
+
hunk ./src/objects/stack.lisp 11
- (/ [_$_]
- (- (pointer-address (call-stack-top stack))
- (pointer-address (call-stack-pointer stack)))
- (foreign-type-size 'smoke-stack-item)))
+ (/ (- (pointer-address (call-stack-top stack))
+ (pointer-address (call-stack-pointer stack)))
+ (foreign-type-size 'smoke-stack-item)))
hunk ./src/overload-resolution.lisp 6
-(defun cstring= (string1 string2)
- "Returns T when the C strings STRING1 and STRING2 are equal
- and NIL otherwise."
- (declare (optimize (speed 3) (safety 0)))
- (dotimes (i array-total-size-limit)
- (let ((char1 (mem-aref string1 :char i))
- (char2 (mem-aref string2 :char i)))
- (when (/= char1 char2)
- (return-from cstring= nil))
- (when (or (= 0 char1)
- (= 0 char2))
- (return-from cstring= (= char1 char2))))))
-
hunk ./src/overload-resolution.lisp 8
- "Returns -1 if a < b; 0 if a = b and 1 if a > b"
- (declare (values (integer -1 1)))
- (if (< a b)
- -1
- (if (> a b)
- 1
- 0)))
+ (- a b))
hunk ./src/overload-resolution.lisp 10
-(declaim (inline cstring-cmp))
-(defun cstring-cmp (string1 string2)
- "Compares the C strings STRING1 and STRING2."
- (declare (foreign-pointer string1 string2)
- (values (integer -1 1))
- (optimize (speed 3)))
- (dotimes (i array-total-size-limit (error "omg"))
- (let ((char1 (mem-aref string1 :char i))
- (char2 (mem-aref string2 :char i)))
- (when (/= char1 char2)
- (return-from cstring-cmp (if (< char1 char2) -1 1)))
- (when (= 0 char1) ;; <=> (= 0 char2)
- (return-from cstring-cmp 0)))))
+(declaim (inline strcmp))
+(defcfun strcmp :int (s1 :pointer) (s2 :pointer))
hunk ./src/overload-resolution.lisp 13
+(declaim (inline cstring/=))
hunk ./src/overload-resolution.lisp 17
- (declare (optimize (speed 3)))
- (dotimes (i array-total-size-limit)
- (let ((char1 (mem-aref string1 :char i))
- (char2 (mem-aref string2 :char i)))
- (when (/= char1 char2)
- (return-from cstring/= i))
- (when (= 0 char1)
- (return-from cstring/= nil)))))
-
-(declaim (inline smoke-method-name))
-(defun smoke-method-name (method)
- (mem-aref (smoke-array-pointer (smoke-module-method-names [_$_]
- (smoke-method-smoke method)))
- :pointer
- (the (smoke-index 0)
- (method-slot-value method 'name))))
+ (not (zerop (strcmp string1 string2))))
hunk ./src/overload-resolution.lisp 24
- (values (integer -1 1))
hunk ./src/overload-resolution.lisp 27
- (declare (type (integer -1 1) id-cmp)
- (dynamic-extent id-cmp))
+ (declare (type smoke-index id-cmp))
hunk ./src/overload-resolution.lisp 30
- (cstring-cmp (smoke-method-name method)
+ (strcmp (smoke-method-name method)
hunk ./src/overload-resolution.lisp 33
-;;; INLINE OPTIMIZE
hunk ./src/overload-resolution.lisp 68
- (cmp (the (integer -1 1) (method-cmp method class-id name))))
- (declare (type (integer -1 1) cmp)
+ (cmp (the smoke-index (method-cmp method class-id name))))
+ (declare (type smoke-index cmp)
hunk ./src/overload-resolution.lisp 71
- (ecase cmp
- (-1 (setf start (1+ index)))
- (0 (return-from find-method-for-class index))
- (1 (setf end (1- index)))))))
+ (if (< cmp 0)
+ (setf start (1+ index))
+ (if (> cmp 0)
+ (setf end (1- index))
+ (return-from find-method-for-class index))))))
hunk ./src/overload-resolution.lisp 85
- ,index))
+ (the smoke-index ,index)))
hunk ./src/overload-resolution.lisp 126
+ ;;
hunk ./src/overload-resolution.lisp 131
- (let ((methods)
- (smoke (smoke class)))
+ (let ((methods))
hunk ./src/overload-resolution.lisp 133
- (let ((start-index (find-method-for-class name class)))
- (declare (type smoke-index start-index))
- (loop for index from start-index downto 1
- while (push-candidate-method index name argument-count class
- methods))
- (loop for index from (1+ start-index)
- to (the smoke-index (smoke-array-length
- (smoke-module-method-maps smoke)))
- while (push-candidate-method index name argument-count class
- methods))))
+ (let ((smoke (smoke class)))
+ (let ((start-index (find-method-for-class name class)))
+ (declare (type smoke-index start-index))
+ (when (>= start-index 0)
+ (loop for index from start-index downto 1
+ while (push-candidate-method index name argument-count class
+ methods))
+ (loop for index from (1+ start-index)
+ to (the smoke-index (smoke-array-length
+ (smoke-module-method-maps smoke)))
+ while (push-candidate-method index name argument-count class
+ methods))))))
hunk ./src/overload-resolution.lisp 147
-(eval-when (:compile-toplevel :load-toplevel :execute)
-(defconstant +exact-match+ 0)
-(defconstant +promotion+ 1)
-(defconstant +conversion+ 2))
-
hunk ./src/overload-resolution.lisp 154
-(defstruct (exact-match (:include conversion (rank +exact-match+))))
+(defstruct (exact-match (:include conversion (rank 0))))
hunk ./src/overload-resolution.lisp 156
-(defstruct (promotion (:include conversion (rank +promotion+))))
+(defstruct (promotion (:include conversion (rank 1))))
hunk ./src/overload-resolution.lisp 158
-(defstruct (number-conversion (:include conversion (rank +conversion+))))
+(defstruct (number-conversion (:include conversion (rank 2))))
hunk ./src/overload-resolution.lisp 160
-(defstruct (pointer-conversion (:include conversion (rank (1+ +conversion+))))
+(defstruct (pointer-conversion (:include conversion (rank 3)))
hunk ./src/overload-resolution.lisp 164
-(defstruct (boolean-conversion (:include conversion (rank (+ 2 +conversion+)))))
+(defstruct (boolean-conversion (:include conversion (rank 4))))
hunk ./src/overload-resolution.lisp 166
-(defstruct (user-conversion (:include conversion (rank (+ 3 +conversion+)))))
+(defstruct (user-conversion (:include conversion (rank 5))))
hunk ./src/overload-resolution.lisp 199
- t)
- (:method ((conversion1 pointer-conversion) (conversion2 pointer-conversion))
- (and (not (conversion< conversion1 conversion2))
- (not (conversion< conversion2 conversion1)))))
+ t))
hunk ./src/overload-resolution.lisp 326
+ (8 (object.typep '(c-integer :long)))
+ (9 (object.typep '(c-integer :unsigned-long)))
hunk ./src/overload-resolution.lisp 397
- ;; Not using pointer-p to allow passing a raw pointer for
- ;; objects on the stack and references
+ ;; Not using pointer-p to allow passing a raw pointer for objects on
+ ;; the stack and references.
hunk ./src/overload-resolution.lisp 401
- ;; FIXME this breaks passing pointers to references
- ;; e.g.: calling the function foo(QByteArray& foo)
- ;; with (foo pointer) assumes pointer to point to a QByteArray,
- ;; but actually the conversion sequence QByteArray(pointer) should be used.
- ;; When pointer is a null pointer it fails horribly!.
+ ;; FIXME this breaks passing pointers to references.
+ ;; [_$_]
+ ;; e.g.: calling the function foo(QByteArray& foo) with
+ ;; (foo pointer) assumes pointer to point to a QByteArray, but
+ ;; actually the conversion sequence QByteArray(pointer) should be
+ ;; used. When pointer is a null pointer it fails horribly!.
hunk ./src/overload-resolution.lisp 451
- (format nil "~A" (name (get-class type)))
+ (constructor-name (get-class type))
hunk ./src/package.lisp 34
+ #:make-auto-pointer
hunk ./src/smoke.lisp 83
- (let ((method-name (concatenate 'string "~" (name class))))
+ (let ((method-name (concatenate 'string "~" (constructor-name class))))
hunk ./src/smoke.lisp 86
- pointer))
- (setf pointer (null-pointer)))
+ pointer)))
hunk ./src/smoke.lisp 146
-;; No eql T since all-methods is to slow to be used in conjunction with
-;; mb:document
-(defmethod documentation ((gf smoke-gf) (doc-type (eql 'cxx-function)))
+(defmethod documentation ((gf smoke-gf) (doc-type (eql 't)))
hunk ./src/smoke.lisp 153
+
+(declaim (inline cstring=))
+(defun cstring= (string1 string2)
+ "Returns T when the C strings STRING1 and STRING2 are equal
+ and NIL otherwise."
+ (zerop (strcmp string1 string2)))
+
hunk ./src/smoke.lisp 163
- (declare (string name)
- (optimize (speed 3)))
+ (declare (optimize (speed 3)))
+ (with-foreign-string (name name)
hunk ./src/smoke.lisp 167
- #'(lambda (address value)
- (declare (ignore value))
- (let ((smoke (make-pointer address)))
- (map-methods #'(lambda (method)
- (when (and (string= name (name method))
- (not (enum-p method)))
- (push (make-instance 'smoke-method
- :id (smoke-method-id method)
- :smoke (smoke method))
- methods)))
- smoke)))
- *smoke-id-class-map*)
- methods))
+ #'(lambda (address module)
+ (declare (ignore address))
+ (map-methods #'(lambda (method)
+ (when (and (cstring= name (smoke-method-name method))
+ (not (enum-p method)))
+ (push (make-smoke-method
+ :id (smoke-method-id method)
+ :smoke (smoke-method-smoke method))
+ methods)))
+ module))
+ *smoke-modules*)
+ methods)))
hunk ./src/smoke.lisp 193
- (eval-when (:compile-toplevel :load-toplevel :execute)
- (define-foreign-library ,library
- (:unix ,(format nil "~(~A~).so.2" library))
- (t (:default ,(format nil "~(~A~)" library)))))
+ (eval-when (:compile-toplevel :load-toplevel :execute)
+ (define-foreign-library ,library
+ (:unix ,(format nil "~(~A~).so.2" library))
+ (t (:default ,(format nil "~(~A~)" library)))))
hunk ./src/smoke.lisp 198
- (load-foreign-library ',library))
+ (load-foreign-library ',library))
hunk ./src/smoke.lisp 200
-; (eval-when (:compile-toplevel :load-toplevel :execute)
-; (define-foreign-library ,library
-; (:unix ,(format nil "~(~A~).so.2" library))
-; (t (:default ,(format nil "~(~A~)" library))))
-; (load-foreign-library ',library))
Wed Jul 8 22:41:19 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Speedup overload resolution and some other stuff for faster C++ method calling.
hunk ./src/clos.lisp 120
- ((pointer :type smoke-standard-class))
+ ()
hunk ./src/clos.lisp 123
-(defmethod pointer ((class cxx:class))
- (pointer (slot-value class 'pointer)))
-
hunk ./src/clos.lisp 160
- :pointer superclass
+ :id (id superclass)
hunk ./src/clos.lisp 181
- :pointer superclass
+ :id (id superclass)
hunk ./src/clos.lisp 206
- :pointer [_$_]
- (pointer class)
- ;(mem-aref (smoke-array-pointer [_$_]
- ; (smoke-module-classes
- ; (smoke class)))
- ; 'smoke-class
- ; (id class))
+ :id (id class)
hunk ./src/clos.lisp 287
- (setf (top stack) (pointer stack))
+ (setf (call-stack-top stack) (call-stack-pointer stack))
hunk ./src/clos.lisp 391
+ (declare (optimize (speed 3)))
hunk ./src/clos.lisp 397
- ;(id (class-of object)) (id (real-class class))))
hunk ./src/method.lisp 68
-
hunk ./src/method.lisp 151
- (eval-startup (:execute)
- (make-smoke-classes ,package ,smoke)
+ (eval-startup (:load-toplevel :execute)
+ ;; eval on startup for class map.
+ (make-smoke-classes ,package ,smoke))
+ (eval-when (:load-toplevel :execute)
hunk ./src/objects/class.lisp 4
- ;; FXIME maybe change back to id
- ((pointer ;:type foreign-pointer
- :initarg :pointer
- :reader pointer)
- (smoke :type smoke-module
- :initarg :smoke
- :reader smoke))
- (:documentation "A class"))
+ ((id :initform 0 :type smoke-index :reader id :initarg :id)
+ (smoke :type smoke-module :reader smoke :initarg :smoke)))
hunk ./src/objects/class.lisp 8
- (make-instance 'smoke-class
- :pointer (mem-aref (smoke-array-pointer (smoke-module-classes
- smoke))
- 'smoke-class
- id)
- :smoke smoke))
+ (make-instance 'smoke-class :id id :smoke smoke))
hunk ./src/objects/class.lisp 10
-(defmethod id ((class smoke-class))
- (declare (values (smoke-index 0))
- (optimize (speed 3)))
- (values
- (floor
- (the (integer 0)
- (- (pointer-address (pointer class))
- (pointer-address (smoke-array-pointer (smoke-module-classes
- (smoke class))))))
- #.(cffi:foreign-type-size 'smoke-class))))
+
+(declaim (inline smoke-class-pointer))
+(defun smoke-class-pointer (class)
+ (mem-aref (the foreign-pointer (smoke-array-pointer (smoke-module-classes
+ (smoke class))))
+ 'smoke-class
+ (the smoke-index (id class))))
hunk ./src/objects/class.lisp 20
- (foreign-slot-value (pointer class)
+ (foreign-slot-value (smoke-class-pointer class)
hunk ./src/objects/class.lisp 25
- `(foreign-slot-value (pointer ,class)
+ `(foreign-slot-value (smoke-class-pointer ,class)
hunk ./src/objects/class.lisp 39
- (setf (slot-value class 'pointer)
- (mem-aref (smoke-array-pointer (smoke-module-classes smoke))
- 'smoke-class
- id))
+ (setf (slot-value class 'id)
+ id)
hunk ./src/objects/class.lisp 87
- :pointer (smoke-get-class [_$_]
- (foreign-slot-value c 'smoke-module-index 'smoke)
- (foreign-slot-value c 'smoke-module-index 'index))
+ :id (foreign-slot-value c 'smoke-module-index 'index)
hunk ./src/objects/method.lisp 136
+ (declare (optimize (speed 3)))
hunk ./src/objects/method.lisp 210
- (call-next-method)))
+ (the smoke-index (call-next-method))))
hunk ./src/objects/stack.lisp 3
-(defclass call-stack ()
- ((pointer :reader pointer :initarg :pointer
- :initform (null-pointer)
- :type foreign-pointer
- :documentation "Pointer to the Smoke stack")
- (top :accessor top :initarg :top
- :initform (null-pointer)
- :type foreign-pointer
- :documentation "Pointer to push the next argument to."))
- (:documentation "Contains the argument passed to a Smoke method."))
+(declaim (inline %make-call-stack))
+(defstruct (call-stack (:constructor %make-call-stack))
+ (pointer (null-pointer) :type foreign-pointer)
+ (top (null-pointer) :type foreign-pointer))
hunk ./src/objects/stack.lisp 12
- (- (pointer-address (top stack))
- (pointer-address (pointer stack)))
+ (- (pointer-address (call-stack-top stack))
+ (pointer-address (call-stack-pointer stack)))
hunk ./src/objects/stack.lisp 17
- (declare (optimize (speed 3)))
- (make-instance 'call-stack
- :pointer smoke-stack
- :top (inc-pointer smoke-stack (foreign-type-size 'smoke-stack-item))))
+ (declare (type foreign-pointer smoke-stack)
+ (optimize (speed 3)))
+ (%make-call-stack
+ :pointer smoke-stack
+ :top (inc-pointer smoke-stack
+ #.(foreign-type-size 'smoke-stack-item))))
hunk ./src/objects/stack.lisp 25
- (setf (foreign-slot-value (top stack)
+ (setf (foreign-slot-value (call-stack-top stack)
hunk ./src/objects/stack.lisp 27
- (incf-pointer (top stack) #.(foreign-type-size 'smoke-stack-item)))
+ (incf-pointer (call-stack-top stack) #.(foreign-type-size 'smoke-stack-item)))
hunk ./src/objects/stack.lisp 32
- (setf (foreign-slot-value (top ,stack)
+ (setf (foreign-slot-value (call-stack-top ,stack)
hunk ./src/objects/stack.lisp 34
- (incf-pointer (top ,stack) ,(foreign-type-size 'smoke-stack-item)))
+ (incf-pointer (call-stack-top ,stack)
+ ,(foreign-type-size 'smoke-stack-item)))
hunk ./src/objects/stack.lisp 41
+ :type foreign-pointer
hunk ./src/objects/type.lisp 123
+ (declare (optimize (speed 3)))
hunk ./src/objects/type.lisp 127
- (id type))
+ (the smoke-index (id type)))
hunk ./src/overload-resolution.lisp 79
+;;; INLINE OPTIMIZE
+(declaim (inline first-unabigious-index))
hunk ./src/overload-resolution.lisp 99
- (declare (type (smoke-index 0) start end))
+ (declare (type (smoke-index 0) start end)
+ (dynamic-extent start))
hunk ./src/overload-resolution.lisp 117
- (dynamic-extent method index cmp))
+ (dynamic-extent method))
hunk ./src/overload-resolution.lisp 196
-(defclass std-conversion ()
- ((function-name :accessor conversion-function-name
- :initarg :conversion-function-name))
- (:documentation "A conversion"))
+(declaim (inline make-conversion make-exact-match make-promotion
+ make-number-conversion make-pointer-conversion
+ make-boolean-conversion make-user-conversion))
+(defstruct conversion
+ (function-name nil :type (or symbol function) :read-only t)
+ (rank -1 :type fixnum :read-only t))
hunk ./src/overload-resolution.lisp 203
-(defclass exact-match (std-conversion)
- ((rank :reader rank
- :allocation :class
- :type fixnum
- :initform +exact-match+)))
+(defstruct (exact-match (:include conversion (rank +exact-match+))))
hunk ./src/overload-resolution.lisp 205
-(defclass promotion (std-conversion)
- ((rank :reader rank
- :allocation :class
- :type fixnum
- :initform +promotion+)))
+(defstruct (promotion (:include conversion (rank +promotion+))))
hunk ./src/overload-resolution.lisp 207
-(defclass number-conversion (std-conversion)
- ((rank :reader rank
- :allocation :class
- :type fixnum
- :initform +conversion+)))
+(defstruct (number-conversion (:include conversion (rank +conversion+))))
hunk ./src/overload-resolution.lisp 209
-(defclass pointer-conversion (std-conversion)
- ((rank :reader rank
- :allocation :class
- :type fixnum
- :initform (1+ +conversion+))
- (from :reader from
- :initarg :from)
- (to :reader to
- :initarg :to)))
+(defstruct (pointer-conversion (:include conversion (rank (1+ +conversion+))))
+ (from (find-class t) :type class :read-only t)
+ (to (find-class t) :type class :read-only t))
hunk ./src/overload-resolution.lisp 213
-(defclass boolean-conversion (std-conversion)
- ((rank :reader rank
- :allocation :class
- :type fixnum
- :initform (+ 2 +conversion+))))
+(defstruct (boolean-conversion (:include conversion (rank (+ 2 +conversion+)))))
hunk ./src/overload-resolution.lisp 215
-(defclass user-conversion (std-conversion)
- ((rank :reader rank
- :allocation :class
- :type fixnum
- :initform (+ 3 +conversion+))))
+(defstruct (user-conversion (:include conversion (rank (+ 3 +conversion+)))))
hunk ./src/overload-resolution.lisp 225
- (< (the fixnum (rank conversion1))
- (the fixnum (rank conversion2)))))
+ (< (the fixnum (conversion-rank conversion1))
+ (the fixnum (conversion-rank conversion2)))))
hunk ./src/overload-resolution.lisp 229
- (if (eq (from conversion1) (from conversion2))
+ (if (eq (pointer-conversion-from conversion1)
+ (pointer-conversion-from conversion2))
hunk ./src/overload-resolution.lisp 232
- (subtypep (to conversion1) (to conversion2))
- (if (eq (to conversion1) (to conversion2))
+ (subtypep (pointer-conversion-to conversion1)
+ (pointer-conversion-to conversion2))
+ (if (eq (pointer-conversion-to conversion1)
+ (pointer-conversion-to conversion2))
hunk ./src/overload-resolution.lisp 237
- (subtypep (from conversion1) (from conversion2))
+ (subtypep (pointer-conversion-from conversion1)
+ (pointer-conversion-from conversion2))
hunk ./src/overload-resolution.lisp 246
- (= (rank conversion1) (rank conversion2)))
+ (= (conversion-rank conversion1) (conversion-rank conversion2)))
hunk ./src/overload-resolution.lisp 277
- `(make-instance ,type
- :conversion-function-name ,(conversion-function name argument)
- [_$_]
+ `(,(symbolicate 'make- (eval type))
+ :function-name ,(conversion-function name argument)
hunk ./src/sb-optimize.lisp 84
- ;; FIXME only cast when needed.
- (cast object
- (find-class (quote ,(class-name [_$_]
- (find-smoke-class
- (get-class method))))))
+ ,(if (eql (type-specifier object)
+ (find-smoke-class (get-class method)))
+ `(pointer object)
+ `(cast object
+ (find-class (quote ,(class-name [_$_]
+ (find-smoke-class
+ (get-class method)))))))
hunk ./src/smoke.lisp 33
- (foreign-slot-value (pointer (get-class method))
+ (foreign-slot-value (smoke-class-pointer (get-class method))
hunk ./src/smoke.lisp 46
- (call-s-method method object-pointer (pointer stack))
- (type-to-lisp (pointer stack) (return-type method))))
+ (call-s-method method object-pointer (call-stack-pointer stack))
+ (type-to-lisp (call-stack-pointer stack) (return-type method))))
hunk ./src/smoke.lisp 51
- (call-s-method method object-pointer (pointer stack))
- (foreign-slot-value (pointer stack) 'smoke-stack-item 'class)))
+ (call-s-method method object-pointer (call-stack-pointer stack))
+ (foreign-slot-value (call-stack-pointer stack) 'smoke-stack-item 'class)))
hunk ./src/smoke.lisp 76
- (call-s-method method (null-pointer) (pointer stack))
- (foreign-slot-value (pointer stack) 'smoke-stack-item 'long)))
+ (call-s-method method (null-pointer) (call-stack-pointer stack))
+ (foreign-slot-value (call-stack-pointer stack) 'smoke-stack-item 'long)))
hunk ./src/smoke.lisp 107
- (foreign-slot-value (pointer (class-of object))
+ (foreign-slot-value (smoke-class-pointer (class-of object))
Wed Jul 8 16:56:52 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* SBCL: compile time overload resolution
hunk ./smoke.mbd 38
+ ("sb-optimize" (:for :sbcl) (:needs "overload-resolution"))
hunk ./src/overload-resolution.lisp 302
- (if-let
- (match (call-using-type exact-match object type))
- (if (eql t match)
- (make-match 'exact-match)
- (make-match 'exact-match match))
- (or (call-using-type promotion object type)
- (call-using-type conversion object type)
- (and user
- (call-using-type user-conversion object type)))))
+ (if-let (match (call-using-type exact-match object type))
+ (if (eql t match)
+ (make-match 'exact-match)
+ (make-match 'exact-match match))
+ (or (call-using-type promotion object type)
+ (call-using-type conversion object type)
+ (and user
+ (call-using-type user-conversion object type)))))
addfile ./src/sb-optimize.lisp
hunk ./src/sb-optimize.lisp 1
+(in-package :smoke)
+
+(declaim (optimize (debug 3)))
+
+(defmacro catch-try ((tag &optional catch-result) catch-form &body body)
+ "Catch TAG in the BODY forms. When TAG is throw CATCH-RESULT is bound
+to the thrown values and result of CATCH-FORM is returned. Otherwise
+the result of BODY is returned and CATCH-FORM is not evaluated."
+ (flet ((catch-block (tag return-block body)
+ `(catch ,tag
+ (return-from ,return-block
+ ,@body))))
+ (let ((return-block (gensym)))
+ `(block ,return-block [_$_]
+ ,(if catch-result
+ `(let ((,catch-result ,(catch-block tag return-block body)))
+ ,catch-form)
+ `(progn ,(catch-block tag return-block body)
+ ,catch-form))))))
+
+(defun type-specifier (lvar)
+ (let ((type (sb-kernel:type-specifier (sb-c::lvar-type lvar))))
+ (if (subtypep type 'smoke-standard-object)
+ (find-class type)
+ type)))
+ [_$_]
+
+(defun give-up-transform (&rest args)
+ (apply #'sb-c::give-up-ir1-transform args))
+
+(defmacro define-transform (name lambda-list &body body)
+ `(sb-c:deftransform ,name (,lambda-list)
+ ,@body))
+
+(defmacro define-known (name)
+ `(sb-c:defknown ,name * *))
+
+(defun method-form (method)
+ `(make-smoke-method
+ :id ,(id method)
+ :smoke (eval ,(get-smoke-variable-for-pointer
+ (smoke method)))))
+ [_$_]
+(defun sequence-form (sequence arguments)
+ (mapcar #'(lambda (sequence argument)
+ (if (symbolp sequence)
+ `(,sequence ,argument)
+ `(,(first sequence) ,argument ,@(rest sequence))))
+ sequence arguments))
+
+
+(defmacro define-resolve-at-compile-time (gf-name)
+ `(eval-when (:compile-toplevel :load-toplevel :execute)
+ (define-known ,gf-name)
+ (sb-c:defoptimizer (,gf-name derive-type) ((object &rest args))
+ (catch-try ('unspecific-type) sb-c::*wild-type*
+ (let ((method (find-best-viable-function-using-types
+ ,(name (fdefinition gf-name))
+ (mapcar #'type-specifier args) (type-specifier object))))
+ (if (and method (class-p (return-type method)))
+ (sb-kernel:single-value-specifier-type
+ (find-smoke-class (get-class (return-type method))))
+ sb-c::*wild-type*))))
+ (define-transform ,gf-name (object &rest args)
+ (when (null args)
+ (give-up-transform "No arguments."))
+ (catch-try ('unspecific-type reason)
+ (give-up-transform "Could not resolve overload at compile time: ~A" reason)
+ (multiple-value-bind (method sequence)
+ (find-best-viable-function-using-types
+ ,(name (fdefinition gf-name))
+ (mapcar #'type-specifier args)
+ (type-specifier object))
+ (let ((argument-names (make-gensym-list (length args))))
+ (when (null method)
+ (give-up-transform "No applicable method."))
+ (if (static-p method)
+ `(s-call ,(method-form method)
+ (null-pointer)
+ (list ,@(sequence-form
+ sequence args)))
+ `(lambda (object ,@argument-names)
+ (s-call ,(method-form method)
+ ;; FIXME only cast when needed.
+ (cast object
+ (find-class (quote ,(class-name [_$_]
+ (find-smoke-class
+ (get-class method))))))
+ (list ,@(sequence-form
+ sequence argument-names)))))))))))
hunk ./src/using-type.lisp 20
-false when it is not; and :MAYBE when the relationship
-could not be determined."
+false when it is not."
hunk ./src/using-type.lisp 32
- nil
+ (if (and (subtypep type 'integer)
+ (not (integer-types-disjunct-p object-type type)))
+ (throw 'unspecific-type (values object-type type))
+ nil)
hunk ./src/using-type.lisp 62
- #+nil [_$_]
hunk ./src/using-type.lisp 76
- #+nil
hunk ./src/using-type.lisp 87
+
+(defun integer-types-disjunct-p (type1 type2)
+ ;; FIXME implement this
+ (declare (ignore type1 type2))
+ nil)
Fri Jul 3 11:50:05 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix methods and method-maps bounds.
hunk ./src/object-map.lisp 43
- (warn "life object ~A" (class-of object))
+ (warn "life object ~A" object)
hunk ./src/objects/method.lisp 88
- (loop for id from 1 to length do
+ (loop for id from 0 below length do ;; exception: methods is < lenght
hunk ./src/overload-resolution.lisp 96
- (end (smoke-array-length (smoke-module-method-maps smoke))))
+ (end (1+ (smoke-array-length (smoke-module-method-maps smoke)))))
Thu Jul 2 23:51:50 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Promption real to double-float
hunk ./src/overload-resolution.lisp 422
+(defun coerce-double-float (number)
+ (float number 0d0))
+
+;; FIXME incomplete
hunk ./src/overload-resolution.lisp 435
- (make-match 'promotion 'coerce-enum)))))
+ (make-match 'promotion 'coerce-enum)))
+ (11 (when (object.typep 'real)
+ (make-match 'promotion 'coerce-double-float)))))
Thu Jul 2 23:51:14 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix infinite loop when showing candidate functions.
hunk ./src/overload-resolution.lisp 528
-Candidates are:~{~T~%~}."
+Candidates are:~{~T~A~%~}."
Thu Jul 2 21:08:40 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix undefine init_smoke* C function & cleanup finalizers when a image is saved.
hunk ./smoke.mbd 39
- ("object-map" (:needs "objects"))
+ ("object-map" (:needs "objects" :utils))
hunk ./smoke.mbd 77
- (:supports (:os :linux) (:implementation :sbcl :openmcl))
hunk ./src/object-map.lisp 41
+(eval-on-save ()
+ (loop for object being the hash-value of *object-map* do
+ (warn "life object ~A" (class-of object))
+ (remove-finalizer object)
+ (setf (slot-value object 'pointer) (null-pointer)))
+ (clrhash *object-map*))
+
hunk ./src/smoke.lisp 190
- (eval-startup (:compile-toplevel :execute)
hunk ./src/smoke.lisp 193
- (t (:default ,(format nil "~(~A~)" library))))
- (use-foreign-library ,library))
- (defcvar (,variable ,variable-name :read-only t) :pointer)
+ (t (:default ,(format nil "~(~A~)" library)))))
+ (eval-startup (:compile-toplevel :execute)
+ (load-foreign-library ',library))
+ (eval-startup (:compile-toplevel :execute)
+; (eval-when (:compile-toplevel :load-toplevel :execute)
+; (define-foreign-library ,library
+; (:unix ,(format nil "~(~A~).so.2" library))
+; (t (:default ,(format nil "~(~A~)" library))))
+; (load-foreign-library ',library))
+ (defcvar (,variable ,variable-name
+ :read-only t
+ :library ,library) :pointer)
hunk ./src/smoke.lisp 207
- function-name))
+ function-name)
+ :library ,library)
hunk ./src/utils/image/impl/ccl.lisp 6
+(defmacro eval-on-save (() &body body)
+ `(eval-when (:load-toplevel)
+ (push #'(lambda ()
+ (let ((*package* ,*package*))
+ ,@body))
+ ccl:*save-exit-functions*)))
+
hunk ./src/utils/image/impl/sbcl.lisp 15
+(defmacro eval-on-save (() &body body)
+ `(eval-when (:load-toplevel)
+ (push #'(lambda ()
+ (let ((*package* ,*package*))
+ ,@body))
+ sb-ext:*save-hooks*)))
+
Wed Jul 1 12:54:01 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Spellcheck
hunk ./src/clos.lisp 55
-Note that (LISP-TO-CXX (CXX-TO-LIST SOME-STRING)) will not neccessarily return
-a string equal to SMOME-STRING."
+Note that (LISP-TO-CXX (CXX-TO-LIST SOME-STRING)) will not necessarily return
+a string equal to SOME-STRING."
hunk ./src/clos.lisp 58
- "Downcase, convert _ and dispatch."
+ "Down case, convert _ and dispatch."
hunk ./src/clos.lisp 77
- "Strip leadind Q or K."
+ "Strip leading Q or K."
hunk ./src/clos.lisp 83
- "Upcase, convert _ and dispatch."
+ "Up case, convert _ and dispatch."
hunk ./src/clos.lisp 156
- "No superclass suplied for class ~A" class)
+ "No superclass supplied for class ~A" class)
hunk ./src/clos.lisp 173
- "No superclass suplied for class ~A" class)
+ "No superclass sup-lied for class ~A" class)
hunk ./src/clos.lisp 197
- "Construts a lisp class in PACKAGE for each one in the Smoke module SMOKE."
+ "Constructs a lisp class in PACKAGE for each one in the Smoke module SMOKE."
hunk ./src/clos.lisp 230
- "Returns the class of OBJECT or OBJECT iff it alread is a class."
+ "Returns the class of OBJECT or OBJECT iff it already is a class."
hunk ./src/clos.lisp 431
- (error "No construtor ~A for ~S"
+ (error "No constructor ~A for ~S"
hunk ./src/cxx-method.lisp 78
- "The method ~A must not contatin lambda list keywords." method))
+ "The method ~A must not contain lambda list keywords." method))
hunk ./src/cxx-method.lisp 108
- ;; on startup and the eval stuff is slower.
+ ;; on start up and the eval stuff is slower.
hunk ./src/cxx-method.lisp 123
- ;; -using-classes only cares abount the number of arguments;
+ ;; -using-classes only cares about the number of arguments;
hunk ./src/cxx-method.lisp 155
- "Retruns a compiler-macro form for CXX-GENERIC-FUNCTION that
+ "Returns a compiler-macro form for CXX-GENERIC-FUNCTION that
hunk ./src/method.lisp 98
-;;; mulitiple definiton of a function with the same name.
+;;; multiple definition of a function with the same name.
hunk ./src/method.lisp 120
- (string/= (name method) "tr")) ;; we have a custom qt:tr funciton
+ (string/= (name method) "tr")) ;; we have a custom qt:tr function
hunk ./src/object-map.lisp 29
-;; CLISP has problems with weak hashtables and finalizers.
+;; CLISP has problems with weak hash tables and finalizers.
hunk ./src/object-map.lisp 38
-except object with a non virtual destuctor which had their ownership transfered
+except object with a non virtual destructor which had their ownership transferred
hunk ./src/object-map.lisp 100
- "Adds OBJECT to the pointer -> object map. It can later be retrived
+ "Adds OBJECT to the pointer -> object map. It can later be retrieved
hunk ./src/objects/class.lisp 47
- "Applys FUNCTION to the classes of SMOKE."
+ "Applies FUNCTION to the classes of SMOKE."
hunk ./src/objects/method.lisp 54
-Signals an error when the method is ambigious."
+Signals an error when the method is ambiguous."
hunk ./src/objects/method.lisp 74
- (error "The method ~S of ~S is ambigious" name (name class))) ;;TODO
+ (error "The method ~S of ~S is ambiguous" name (name class))) ;;TODO
hunk ./src/objects/method.lisp 82
- "Applys FUNCTION to the methods of SMOKE.
+ "Applies FUNCTION to the methods of SMOKE.
hunk ./src/objects/method.lisp 169
- "Retruns T when METHOD is static and NIL otherwise."
+ "Returns T when METHOD is static and NIL otherwise."
hunk ./src/objects/method.lisp 185
- "Returns T when METHOD is ambigious and NIL otherwise."
+ "Returns T when METHOD is ambiguous and NIL otherwise."
hunk ./src/objects/stack.lisp 48
- ;; since then they would be alway reacable from Lisp and thus
+ ;; since then they would be always reachable from Lisp and thus
hunk ./src/objects/stack.lisp 53
- :documentation "Objecsts owned by the C++ instance."))
+ :documentation "Objects owned by the C++ instance."))
hunk ./src/objects/stack.lisp 88
- "To many arguments suppliend (Arguments ~A)." args)
+ "To many arguments supplied (Arguments ~A)." args)
hunk ./src/objects/stack.lisp 139
- (:documentation "Returns a clos instance for POINTER."))
+ (:documentation "Returns a CLOS instance for POINTER."))
hunk ./src/objects/type.lisp 120
- ;; For efficency just check if the first byte is a null byte;
+ ;; For efficiency just check if the first byte is a null byte;
hunk ./src/overload-resolution.lisp 159
- "Returns a list of all superclasses of CLASS and CLASS itself."
+ "Returns a list of all super-classes of CLASS and CLASS itself."
hunk ./src/overload-resolution.lisp 240
- "Retruns true when CONVERSION1 is better than CONVERSION2.")
+ "Returns true when CONVERSION1 is better than CONVERSION2.")
hunk ./src/overload-resolution.lisp 300
- "Retruns a conversion sequence to convert a instance of type CLASS
+ "Retrains a conversion sequence to convert a instance of type CLASS
hunk ./src/overload-resolution.lisp 350
- ;; FIXME test for ambigious overload #'conversion=
+ ;; FIXME test for ambiguous overload #'conversion=
hunk ./src/overload-resolution.lisp 528
-Candidtes are:~{~T~%~}."
+Candidates are:~{~T~%~}."
hunk ./src/smoke.lisp 81
-Calls the destrutor and frees the memory."
+Calls the destructor and frees the memory."
hunk ./src/utils/sbcl-bundle.lisp 21
- "could not remove temponary directory ~A"
+ "could not remove temporary directory ~A"
Wed Jul 1 00:47:39 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix for Clozure CL
hunk ./src/clos.lisp 314
- ((binding :pointer)
- (method smoke-index)
- (object-ptr :pointer)
- (stack smoke-stack)
- (abstract :boolean))
+ ((binding :pointer)
+ (method smoke-index)
+ (object-ptr :pointer)
+ (stack smoke-stack)
+ (abstract :boolean))
hunk ./src/clos.lisp 320
- (let* ((method (make-smoke-method
- :smoke (gethash (pointer-address (smoke-get-smoke binding))
- *smoke-modules*)
- :id method)))
- (loop
- (restart-case
- (return-from dispatch-method
- (let ((gf (get-gf-for-method method)))
- (declare (function gf))
- (if (null (gf-methods gf))
- (progn
- (when abstract
- (error "Abstract method ~A called."
- (method-declaration method)))
- nil)
- (let ((object (get-object object-ptr)))
- ;; FIXME:
- ;;(assert object
- ;; (object)
- ;; "No object for ~A to call ~A." object-ptr method)
- (if object
+ (let ((object (get-object object-ptr)))
+ ;; FIXME:
+ ;;(assert object
+ ;; (object)
+ ;; "No object for ~A to call ~A." object-ptr method)
+ (if (and object (typep (class-of object) 'cxx:class))
+ ;; Do not allow overwriting methods of classes the users has not derived from (like in C++),
+ ;; to reduce overhead.
+ (let* ((method (make-smoke-method
+ :smoke (gethash (pointer-address (smoke-get-smoke binding))
+ *smoke-modules*)
+ :id method)))
+ (loop
+ (restart-case
+ (return-from dispatch-method
+ (let ((gf (get-gf-for-method method)))
+ (declare (function gf))
+ (if (null (gf-methods gf))
hunk ./src/clos.lisp 339
- (put-returnvalue stack
- (apply gf object
- (stack-to-args
- (inc-pointer stack [_$_]
- (foreign-type-size
- 'smoke-stack-item))
- (get-first-argument method)))
- (return-type method)
- object)
- t)
- nil)))))
- ;; Restarts to prevent stack unwinding across the C++ stack.
- (call-default ()
- :report (lambda (stream)
- (declare (stream stream))
- (format stream "Call default implementation ~A instead."
- method))
- :test (lambda (condition)
- (declare (ignore condition))
- (not abstract))
- (return-from dispatch-method nil))
- (use-returnvalue (return-value)
- :report (lambda (stream)
- (declare (stream stream))
- (format stream "Supply a return value for ~A."
- (method-declaration method)))
- :test (lambda (condition)
- (declare (ignore condition))
- (not (void-p (return-type method))))
- :interactive (lambda ()
- (format *query-io* "~&Enter a new return value: ")
- (multiple-value-list (eval (read *query-io*))))
- (put-returnvalue stack return-value [_$_]
- (return-type method)
- (get-object object-ptr))
- (return-from dispatch-method t))
- (return ()
+ (when abstract
+ (error "Abstract method ~A called."
+ (method-declaration method)))
+ nil)
+ (if object
+ (progn
+ (put-returnvalue stack
+ (apply gf object
+ (stack-to-args
+ (inc-pointer stack [_$_]
+ (foreign-type-size
+ 'smoke-stack-item))
+ (get-first-argument method)))
+ (return-type method)
+ object)
+ t)
+ nil))))
+ ;; Restarts to prevent stack unwinding across the C++ stack.
+ (call-default ()
hunk ./src/clos.lisp 360
- (format stream "Return void for ~A."
+ (format stream "Call default implementation ~A instead."
+ method))
+ :test (lambda (condition)
+ (declare (ignore condition))
+ (not abstract))
+ (return-from dispatch-method nil))
+ (use-returnvalue (return-value)
+ :report (lambda (stream)
+ (declare (stream stream))
+ (format stream "Supply a return value for ~A."
hunk ./src/clos.lisp 373
- (void-p (return-type method)))
- (return-from dispatch-method (values)))
- (retry ()
- :report (lambda (stream)
- (declare (stream stream))
- (format stream "Try again calling ~A." [_$_]
- (method-declaration method))))))))
+ (not (void-p (return-type method))))
+ :interactive (lambda ()
+ (format *query-io* "~&Enter a new return value: ")
+ (multiple-value-list (eval (read *query-io*))))
+ (put-returnvalue stack return-value [_$_]
+ (return-type method)
+ (get-object object-ptr))
+ (return-from dispatch-method t))
+ (return ()
+ :report (lambda (stream)
+ (declare (stream stream))
+ (format stream "Return void for ~A."
+ (method-declaration method)))
+ :test (lambda (condition)
+ (declare (ignore condition))
+ (void-p (return-type method)))
+ (return-from dispatch-method (values)))
+ (retry ()
+ :report (lambda (stream)
+ (declare (stream stream))
+ (format stream "Try again calling ~A." [_$_]
+ (method-declaration method))))))
+ nil))))
hunk ./src/method.lisp 21
- :type (make-instance 'smoke-lazy-type
+ :type (make-instance 'smoke-type
hunk ./src/method.lisp 153
- (register-smoke-module-var (quote ,smoke))
hunk ./src/objects/class.lisp 5
- ((pointer :type foreign-pointer
+ ((pointer ;:type foreign-pointer
hunk ./src/objects/enum.lisp 20
+;; for the constants (e.g.: QT:+ALT+)
hunk ./src/objects/enum.lisp 22
- (declare (ignore environment))
hunk ./src/objects/enum.lisp 24
- :type (make-instance 'smoke::smoke-lazy-type
- :id ,(id (enum-type enum))
- :smoke ',(smoke::get-smoke-variable-for-pointer
- (smoke::smoke (enum-type enum))))))
+ :type ,(make-load-form (enum-type enum) environment)))
hunk ./src/objects/type.lisp 21
-(defclass smoke-lazy-type (smoke-type)
- ())
+;; Clozure CL needs this
+(defmethod make-load-form ((type smoke-type) &optional environment)
+ (declare (ignore environment))
+ `(make-instance 'smoke-type
+ :id ,(id type)
+ :smoke (eval ,(get-smoke-variable-for-pointer
+ (smoke-module-pointer (smoke type))))))
hunk ./src/overload-resolution.lisp 94
- (class-id (id class))
- (smoke (smoke class))
- (end (smoke-array-length (smoke-module-method-maps smoke))))
+ (class-id (id class))
+ (smoke (smoke class))
+ (end (smoke-array-length (smoke-module-method-maps smoke))))
hunk ./src/smoke.lisp 30
-(declaim (inline call-s-method) (optimize (debug 3)))
+(declaim (inline call-s-method))
hunk ./src/smoke.lisp 82
-; (declare (optimize (speed 3)))
+ (declare (optimize (speed 3)))
hunk ./src/smoke.lisp 191
- (eval-when (:compile-toplevel :load-toplevel :execute)
- (define-foreign-library ,library
- (:unix ,(format nil "~(~A~).so.2" library))
- (t (:default ,(format nil "~(~A~)" library))))
- (use-foreign-library ,library))
- (defcvar (,variable ,variable-name :read-only t) :pointer)
- (defcfun (,init-function ,(format nil "_Z~A~Av"
- (length function-name)
- function-name))
- :void))
+ (eval-when (:compile-toplevel :load-toplevel :execute)
+ (define-foreign-library ,library
+ (:unix ,(format nil "~(~A~).so.2" library))
+ (t (:default ,(format nil "~(~A~)" library))))
+ (use-foreign-library ,library))
+ (defcvar (,variable ,variable-name :read-only t) :pointer)
+ (defcfun (,init-function ,(format nil "_Z~A~Av"
+ (length function-name)
+ function-name))
+ :void))
hunk ./src/smoke.lisp 204
- (,init-function)
- (init ,variable ,smoke-module))
+ (,init-function)
+ (init ,variable ,smoke-module)
+ (register-smoke-module-var ',smoke-module))
hunk ./src/smoke.lisp 220
+ (declare (ignorable ,@(loop for arg in (rest lambda-list) collect
+ (if (consp arg)
+ (first arg)
+ arg))))
hunk ./test.lisp 4
+ccl --batch --quiet --load $0 || exit 3
hunk ./test.lisp 30
-(sb-ext:quit)
+#+sbcl (sb-ext:quit)
+#+ccl (ccl:quit)
Tue Jun 30 22:54:49 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* CLISP workaround finalizer for objects in weak hash table crash.
hunk ./src/clos.lisp 261
- (cancel-finalization object)
+ (remove-finalizer object)
hunk ./src/clos.lisp 304
- (cancel-finalization converted-value)
+ (remove-finalizer converted-value)
hunk ./src/clos.lisp 475
- (cancel-finalization object)
+ (remove-finalizer object)
hunk ./src/clos.lisp 485
- (let ((finalizer (make-finalize object)))
- (finalize object finalizer)))
+ (set-finalizer object))
hunk ./src/object-map.lisp 24
- #-cmucl (make-weak-hash-table :weakness #-clisp weakness
- ;; CLISP crash with weak hash table
- ;; leak memory (see also: #'keep-wrapper)
- #+clisp nil)
+ #-cmucl (make-weak-hash-table :weakness weakness)
hunk ./src/object-map.lisp 72
+(declaim (inline remove-finalizer))
+(defun remove-finalizer (object)
+ #-clisp
+ (cancel-finalization object)
+ #+clisp
+ (when (typep object 'smoke-standard-object)
+ (cancel-finalization (slot-value object 'finalizer))))
+
+(declaim (inline set-finalizer))
+(defun set-finalizer (object)
+ #-clisp
+ (finalize object (make-finalize object))
+ #+clisp
+ (finalize (slot-value object 'finalizer) (make-finalize object)))
+
hunk ./src/objects/stack.lisp 46
+ #+clisp (finalizer :type list :initform (list nil))
Mon Jun 22 14:18:08 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Speedup overload resolution by calling less into C, more efficient finding of the viable methods
and various optimizations.
This breaks Clozure CL -- fix it later.
hunk ./examples/CMakeLists.txt 1
-
-find_package(Qt4)
-set(QT_DONT_USE_QTGUI true)
-include(${QT_USE_FILE})
-
-find_library(SMOKE_KDE_LIBRARY smokekde)
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(smokekde DEFAULT_MSG SMOKE_KDE_LIBRARY)
-
-## kde-hello-world
-if(SMOKE_KDE_LIBRARY)
- include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../src/smoke-c/")
-
- add_executable(kde-hello-world kde-hello-world.cpp ../src/smoke-c/csmokebinding.cpp)
- target_link_libraries(kde-hello-world ${SMOKE_KDE_LIBRARY})
-endif(SMOKE_KDE_LIBRARY)
rmfile ./examples/CMakeLists.txt
hunk ./examples/kde-hello-world.cpp 1
-/*
- * Copyright 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * Hello world example using libsmoke-c.
- * Display an KDE Window. */
-
-#include <smoke/qt_smoke.h>
-#include <smoke/kde_smoke.h>
-
-#include "smoke-c.cpp"
-
-#include <iostream>
-
-using namespace std;
-using namespace cl_smoke;
-
-static void
-destructed(Binding* binding, Smoke::Index class_id,
- void* object)
-{
- cout << "destructed: " << binding->className(class_id) << endl;
-}
-
-/** No method dispatch in this example. */
-static int
-dispatch(Binding* binding, Smoke::Index method,
- void* object, Smoke::Stack args, int abstract)
-{
- return false;
-}
-
-int
-main(int argc, char** argv)
-{
- init_kde_Smoke(); // calls also init_qt_Smoke();
- smoke_binding kde = smoke_init(kde_Smoke, reinterpret_cast<void*>(&destructed),
- reinterpret_cast<void*>(&dispatch));
- smoke_binding qt = smoke_init(qt_Smoke, reinterpret_cast<void*>(&destructed),
- reinterpret_cast<void*>(&dispatch));
-
- Smoke::StackItem stack[5];
- Smoke::ModuleIndex m;
- Smoke::ModuleIndex c;
-
- // bytearray = new QByteArray("foo");
- {
- char str[] = "foo";
-
- smoke_find_class(&c, qt_Smoke, "QByteArray");
- smoke_find_method(&m, qt_Smoke, c.index, "QByteArray$");
-
- stack[1].s_class = str;
-
- smoke_call_method(qt_Smoke, m.index, NULL, stack);
- }
- void* bytearray = stack[0].s_class;
-
-
- // l10n = ki18n(bar);
- {
- char str[] = "hello world";
- smoke_find_class(&c, kde_Smoke, "QGlobalSpace");
- smoke_find_method(&m, kde_Smoke, c.index, "ki18n$");
-
- stack[1].s_class = str;
-
- smoke_call_method(kde_Smoke, m.index, NULL, stack);
- }
- void* l10n = stack[0].s_class;
-
- // about = KAboutData(bytearray, bytearray, l10n, bytearray);
- {
- smoke_find_class(&c, kde_Smoke, "KAboutData");
- smoke_find_method(&m, kde_Smoke, c.index, "KAboutData####");
-
- stack[1].s_class = bytearray;
- stack[2].s_class = bytearray;
- stack[3].s_class = l10n;
- stack[4].s_class = bytearray;
-
- smoke_call_method(kde_Smoke, m.index, NULL, stack);
- }
- void* about = stack[0].s_class;
-
-
- // KCmdLineArgs::init(argc, argv, about);
- {
- smoke_find_class(&c, kde_Smoke, "KCmdLineArgs");
- smoke_find_method(&m, kde_Smoke, c.index, "init$?#");
-
- stack[1].s_int = argc;
- stack[2].s_class = argv;
- stack[3].s_class = about;
-
- smoke_call_method(kde_Smoke, m.index, NULL, stack);
- }
-
- // app = new KApplication();
- void* app;
- {
- smoke_find_class(&c, kde_Smoke, "KApplication");
- smoke_find_method(&m, kde_Smoke, c.index, "KApplication");
-
- smoke_call_method(kde_Smoke, m.index, NULL, stack);
- app = stack[0].s_class;
-
- smoke_set_binding(c.smoke, kde, c.index, app);
- }
-
- {
- smoke_find_class(&c, kde_Smoke, "KGlobalSettings");
- smoke_find_method(&m, kde_Smoke, c.index, "Disable");
- smoke_call_method(kde_Smoke, m.index, NULL, stack);
- }
-
- // widget = new KXmlGuiWindow();
- // widget->setupGUI();
- // widget->show();
- // return app->exec();
- void* widget;
- {
- smoke_find_class(&c, kde_Smoke, "KXmlGuiWindow");
- smoke_find_method(&m, kde_Smoke, c.index, "KXmlGuiWindow");
-
- smoke_call_method(m.smoke, m.index, NULL, stack);
- widget = stack[0].s_class;
- smoke_set_binding(c.smoke, kde, c.index, widget);
-
- smoke_find_method(&m, c.smoke, c.index, "setupGUI");
- smoke_call_method(m.smoke, m.index, widget, stack);
-
- smoke_find_method(&m, c.smoke, c.index, "show");
- smoke_call_method(m.smoke, m.index, widget, stack);
-
- smoke_find_class(&c, kde_Smoke, "KApplication");
- smoke_find_method(&m, c.smoke, c.index, "exec");
- smoke_call_method(m.smoke, m.index, NULL, stack);
-
- return stack[0].s_int;
- }
-}
rmfile ./examples/kde-hello-world.cpp
rmdir ./examples
hunk ./CMakeLists.txt 6
-add_subdirectory(examples)
hunk ./src/bindings.lisp 24
+(defstruct smoke-array
+ (pointer (null-pointer) :type foreign-pointer)
+ (length 0 :type (smoke-index 0)))
+
+
+(defstruct smoke-module
+ (pointer (null-pointer) :type foreign-pointer)
+ (binding (null-pointer) :type foreign-pointer)
+
+ (classes (make-smoke-array) :type smoke-array)
+ (methods (make-smoke-array) :type smoke-array)
+ (method-maps (make-smoke-array) :type smoke-array)
+ (method-names (make-smoke-array) :type smoke-array)
+ (types (make-smoke-array) :type smoke-array)
+
+ (inheritance-list (null-pointer) :type foreign-pointer)
+ (argument-list (null-pointer) :type foreign-pointer)
+ (ambiguous-method-list (null-pointer) :type foreign-pointer))
+ [_$_]
+(defvar *smoke-modules* (make-hash-table))
+
+(defun init-smoke-module (module)
+ (let ((smoke (smoke-module-pointer module)))
+ (setf (gethash (pointer-address smoke) *smoke-modules*)
+ module)
+ (flet ((mk-array (array)
+ (make-smoke-array :pointer (cl-smoke-array smoke array)
+ :length (cl-smoke-array-size smoke array))))
+ (setf (smoke-module-classes module) (mk-array :classes)
+ (smoke-module-methods module) (mk-array :methods)
+ (smoke-module-method-maps module) (mk-array :method-maps)
+ (smoke-module-method-names module) (mk-array :method-names)
+ (smoke-module-types module) (mk-array :types)
+
+ (smoke-module-inheritance-list module)
+ (cl-smoke-array smoke :inheritance-list)
+
+ (smoke-module-argument-list module)
+ (cl-smoke-array smoke :argument-list)
+
+ (smoke-module-ambiguous-method-list module)
+ (cl-smoke-array smoke :ambiguous-method-list)))))
+
hunk ./src/class-map.lisp 10
- (let ((value (gethash (pointer-address smoke)
+ (let ((value (gethash (pointer-address (smoke-module-pointer smoke))
hunk ./src/class-map.lisp 15
- smoke (smoke-get-module-name smoke))
+ smoke (smoke-get-module-name (smoke-module-pointer smoke)))
hunk ./src/class-map.lisp 19
- (setf (gethash (pointer-address smoke) *smoke-id-class-map*)
+ (setf (gethash (pointer-address (smoke-module-pointer smoke)) *smoke-id-class-map*)
hunk ./src/clos.lisp 95
- "Convert camelCase to lisp-style."
+ "C++ namespace separator"
hunk ./src/clos.lisp 120
- ((smoke :reader smoke-symbol :initarg :smoke-symbol
- :type symbol))
+ ((pointer :type smoke-standard-class))
hunk ./src/clos.lisp 123
-(defmethod smoke ((class cxx:class))
- (eval (smoke-symbol class)))
-
+(defmethod pointer ((class cxx:class))
+ (pointer (slot-value class 'pointer)))
hunk ./src/clos.lisp 163
- :id (id superclass)
- :smoke (get-smoke-variable-for-pointer (smoke superclass))
+ :pointer superclass
+ :smoke (smoke superclass)
hunk ./src/clos.lisp 184
- :id (id superclass)
- :smoke (get-smoke-variable-for-pointer (smoke superclass))
+ :pointer superclass
+ :smoke (smoke superclass)
hunk ./src/clos.lisp 198
- (declare (foreign-pointer smoke)
- (optimize (speed 3)))
- (let ((*package* (find-package package)))
- (add-id-class-map smoke)
+ (declare (optimize (speed 3)))
+ (let ((*package* (find-package package)))
+ (add-id-class-map smoke)
hunk ./src/clos.lisp 209
- :id (id class)
+ :pointer [_$_]
+ (pointer class)
+ ;(mem-aref (smoke-array-pointer [_$_]
+ ; (smoke-module-classes
+ ; (smoke class)))
+ ; 'smoke-class
+ ; (id class))
hunk ./src/clos.lisp 228
+(declaim (inline smoke-class-of))
hunk ./src/clos.lisp 231
- (if (subtypep (class-of object) (find-class 'smoke-class))
+ (declare (optimize (speed 3)))
+ (if (typep object 'smoke-class)
hunk ./src/clos.lisp 240
- (declare (optimize (speed 3)))
+ (declare (dynamic-extent args)
+ (optimize (speed 3)))
hunk ./src/clos.lisp 257
- ((binding :pointer)
- (id smoke-index)
- (object-pointer :pointer))
- (declare (ignore binding id)
- (optimize (speed 3)))
+ ((object-pointer :pointer))
+ (declare (optimize (speed 3)))
hunk ./src/clos.lisp 265
+(declaim (inline argument-to-lisp))
+(defun argument-to-lisp (stack-item type)
+ ;; FIXME do not take ownership of stack allocated objects.
+ (type-to-lisp stack-item type))
+
hunk ./src/clos.lisp 274
- args
- (stack-to-args (cffi:inc-pointer stack
- (cffi:foreign-type-size 'smoke-stack-item))
+ (reverse args)
+ (stack-to-args (inc-pointer stack
+ (foreign-type-size 'smoke-stack-item))
hunk ./src/clos.lisp 278
- (append args (list
- (type-to-lisp (cffi:mem-ref stack 'smoke-stack-item)
- arg))))))
+ (push (argument-to-lisp (mem-ref stack
+ 'smoke-stack-item)
+ arg)
+ args))))
hunk ./src/clos.lisp 316
- (object :pointer)
+ (object-ptr :pointer)
hunk ./src/clos.lisp 320
- (let* ((method (make-instance 'smoke-method
- :id method
- :smoke (smoke-get-smoke binding))))
+ (let* ((method (make-smoke-method
+ :smoke (gethash (pointer-address (smoke-get-smoke binding))
+ *smoke-modules*)
+ :id method)))
hunk ./src/clos.lisp 328
+ (declare (function gf))
hunk ./src/clos.lisp 335
- (let ((object (get-object object)))
+ (let ((object (get-object object-ptr)))
+ ;; FIXME:
+ ;;(assert object
+ ;; (object)
+ ;; "No object for ~A to call ~A." object-ptr method)
hunk ./src/clos.lisp 342
- (put-returnvalue
- stack
- (apply gf object
- (stack-to-args
- (cffi:inc-pointer stack [_$_]
- (cffi:foreign-type-size
- 'smoke-stack-item))
- (get-first-argument method)))
- (return-type method)
- object)
- t)
+ (put-returnvalue stack
+ (apply gf object
+ (stack-to-args
+ (inc-pointer stack [_$_]
+ (foreign-type-size
+ 'smoke-stack-item))
+ (get-first-argument method)))
+ (return-type method)
+ object)
+ t)
hunk ./src/clos.lisp 353
+ ;; Restarts to prevent stack unwinding across the C++ stack.
hunk ./src/clos.lisp 356
+ (declare (stream stream))
hunk ./src/clos.lisp 365
+ (declare (stream stream))
hunk ./src/clos.lisp 376
- (get-object object))
+ (get-object object-ptr))
hunk ./src/clos.lisp 380
+ (declare (stream stream))
hunk ./src/clos.lisp 389
- (format stream "Try again calling ~A" [_$_]
+ (declare (stream stream))
+ (format stream "Try again calling ~A." [_$_]
hunk ./src/clos.lisp 400
- (smoke-cast (smoke (class-of object)) (pointer object)
+ (smoke-cast (smoke-module-pointer (smoke (class-of object))) (pointer object)
hunk ./src/clos.lisp 402
- (id (class-of object)) (class-id (smoke (class-of object))
- class)))
+ (id (class-of object)) (id class)))
hunk ./src/clos.lisp 410
- (smoke-cast (smoke class) (pointer object)
+ (smoke-cast (smoke-module-pointer (smoke class)) (pointer object)
hunk ./src/clos.lisp 438
+ (declare (optimize (speed 3)))
hunk ./src/clos.lisp 446
- (set-binding object (binding (smoke (class-of object))))
+ (set-binding object)
hunk ./src/clos.lisp 452
- (let ((ret (make-instance class
- :pointer pointer)))
+ (declare (type smoke-standard-class class)
+ (optimize (speed 3)))
+ (let ((ret (make-instance class :pointer pointer)))
hunk ./src/clos.lisp 461
- #-clisp
+ (declare (type smoke-standard-object object)
+ (optimize (speed 3)))
hunk ./src/clos.lisp 468
+(declaim (inline remove-wrapper-object))
hunk ./src/clos.lisp 474
+ (declare (optimize (speed 3)))
hunk ./src/method.lisp 2
-(declaim (optimize (debug 3)))
hunk ./src/method.lisp 23
- :smoke ',smoke))
+ :smoke ,smoke))
hunk ./src/method.lisp 74
+(defmacro sizes= ((smoke)&rest arrays)
+ `(and ,@(loop for array in arrays collect
+ `(= (smoke-array-length (,array ,smoke))
+ ,(smoke-array-length (funcall (fdefinition array)
+ (eval smoke)))))))
+
hunk ./src/method.lisp 84
- (unless (and (= (smoke-methods-size ,smoke)
- ,(smoke-methods-size (eval smoke)))
- (= (smoke-method-name-size ,smoke)
- ,(smoke-method-name-size (eval smoke)))
- (= (smoke-types-size ,smoke)
- ,(smoke-types-size (eval smoke)))
- (= (smoke-classes-size ,smoke)
- ,(smoke-classes-size (eval smoke))))
+ (unless (sizes= (,smoke)
+ smoke-module-methods
+ smoke-module-method-names
+ smoke-module-method-maps
+ smoke-module-classes
+ smoke-module-types)
hunk ./src/method.lisp 91
- (smoke-get-module-name ,smoke)))))
+ (smoke-get-module-name (smoke-module-pointer ,smoke))))))
hunk ./src/method.lisp 138
- (let ((method (make-instance 'smoke-method
- :id (abs id)
- :smoke (eval smoke))))
+ (let ((method (make-smoke-method
+ :smoke (eval smoke)
+ :id (abs id))))
hunk ./src/object-map.lisp 44
-(declaim (inline ptr -address))
-(defun ptr-address (pointer)
- ;; CLISP returns NIL for a null pointer
- #+clisp
- (if pointer
- (pointer-address pointer)
- 0)
- #-clisp
- (pointer-address pointer))
-
hunk ./src/object-map.lisp 46
- (gethash (ptr-address pointer) *object-map*))
+ (gethash (pointer-address pointer) *object-map*))
hunk ./src/object-map.lisp 50
- (setf (gethash (ptr-address pointer) *object-map*)
+ (setf (gethash (pointer-address pointer) *object-map*)
hunk ./src/object-map.lisp 53
+(declaim (inline has-pointer-p))
hunk ./src/object-map.lisp 56
- (nth-value 1 (gethash (ptr-address pointer) *object-map*)))
+ (nth-value 1 (gethash (pointer-address pointer) *object-map*)))
hunk ./src/object-map.lisp 59
- (remhash (ptr-address pointer) *object-map*))
+ (remhash (pointer-address pointer) *object-map*))
hunk ./src/object-map.lisp 62
+ (declare (optimize (speed 3)))
hunk ./src/object-map.lisp 66
- (remhash (ptr-address pointer) *object-map*))
+ (remhash (pointer-address pointer) *object-map*))
hunk ./src/object-map.lisp 72
- function class pointer condition))
+ function class pointer condition)
+ #+sbcl (sb-debug:backtrace 10))
hunk ./src/object-map.lisp 82
+ (declare (optimize (speed 3)))
hunk ./src/objects/class.lisp 3
-;;;
-;;; find-class
-;;; ensure-class
-;;; make-instance
-;;; class-name
-;;; class-slots
-;;; class-direct-subclasses
-;;; class-direct-superclasses
-;;; class-of
-;;; subclassp / subtypep
+(defclass smoke-class ()
+ ;; FXIME maybe change back to id
+ ((pointer :type foreign-pointer
+ :initarg :pointer
+ :reader pointer)
+ (smoke :type smoke-module
+ :initarg :smoke
+ :reader smoke))
+ (:documentation "A class"))
hunk ./src/objects/class.lisp 13
+(defun make-smoke-class-from-id (smoke id)
+ (make-instance 'smoke-class
+ :pointer (mem-aref (smoke-array-pointer (smoke-module-classes
+ smoke))
+ 'smoke-class
+ id)
+ :smoke smoke))
hunk ./src/objects/class.lisp 21
-(defclass smoke-class (smoke-symbol)
- ()
- (:documentation "A class"))
+(defmethod id ((class smoke-class))
+ (declare (values (smoke-index 0))
+ (optimize (speed 3)))
+ (values
+ (floor
+ (the (integer 0)
+ (- (pointer-address (pointer class))
+ (pointer-address (smoke-array-pointer (smoke-module-classes
+ (smoke class))))))
+ #.(cffi:foreign-type-size 'smoke-class))))
hunk ./src/objects/class.lisp 34
- (foreign-slot-value (smoke-get-class (smoke class) (id class))
+ (foreign-slot-value (pointer class)
hunk ./src/objects/class.lisp 37
+(define-compiler-macro class-slot-value (&whole form class slot-name)
+ (if (constantp slot-name)
+ `(foreign-slot-value (pointer ,class)
+ 'smoke-class ,slot-name)
+ form))
+
hunk ./src/objects/class.lisp 49
- (foreign-pointer smoke)
hunk ./src/objects/class.lisp 51
- :id 0
hunk ./src/objects/class.lisp 52
- (loop for id from 1 to (1- (the fixnum (smoke-classes-size smoke))) do
- (setf (slot-value class 'id) id)
+ (loop for id from 1 to (smoke-array-length (smoke-module-classes smoke)) do
+ (setf (slot-value class 'pointer)
+ (mem-aref (smoke-array-pointer (smoke-module-classes smoke))
+ 'smoke-class
+ id))
hunk ./src/objects/class.lisp 61
+ (declare (optimize (speed 3)))
hunk ./src/objects/class.lisp 64
-(defmethod get-flag ((class smoke-class) flag)
- (boole boole-and (class-slot-value class 'flags)
- (foreign-enum-value 'smoke-class-flags flag)))
+(defun get-class-flag (class flag)
+ (declare (optimize (speed 3)))
+ (logand (class-slot-value class 'flags)
+ (the fixnum (foreign-enum-value 'smoke-class-flags flag))))
hunk ./src/objects/class.lisp 71
- (/= 0 (get-flag class :constructor)))
+ (/= 0 (get-class-flag class :constructor)))
hunk ./src/objects/class.lisp 75
- (/= 0 (get-flag class :virtual-destructor)))
+ (/= 0 (get-class-flag class :virtual-destructor)))
hunk ./src/objects/class.lisp 93
- (smoke-find-class c smoke name)
+ (smoke-find-class c (smoke-module-pointer smoke) name)
hunk ./src/objects/class.lisp 96
- (error (make-condition 'undefined-class :name name :smoke-name (smoke-get-module-name smoke)))
+ (error (make-condition 'undefined-class :name name :smoke-name (smoke-get-module-name (smoke-module-pointer smoke))))
hunk ./src/objects/class.lisp 103
- :id (foreign-slot-value c 'smoke-module-index 'index)
- :smoke (foreign-slot-value c 'smoke-module-index 'smoke))))
+ :pointer (smoke-get-class [_$_]
+ (foreign-slot-value c 'smoke-module-index 'smoke)
+ (foreign-slot-value c 'smoke-module-index 'index))
+ :smoke (gethash (pointer-address (foreign-slot-value c 'smoke-module-index 'smoke)) *smoke-modules*))))
hunk ./src/objects/class.lisp 128
- (smoke-is-derived-from (smoke class) (id class)
- (smoke base-class) (id base-class)))
+ (smoke-is-derived-from (smoke-module-pointer (smoke class)) (id class)
+ (smoke-module-pointer (smoke base-class)) (id base-class)))
hunk ./src/objects/class.lisp 136
- (let ((class-index (smoke-get-parent-index (smoke class) index)))
- (assert (< class-index (smoke-classes-size (smoke class))))
+ (let ((class-index (mem-aref (smoke-module-inheritance-list [_$_]
+ (smoke class))
+ 'smoke-index
+ index)))
+ (assert (<= class-index
+ (smoke-array-length
+ (smoke-module-classes (smoke class)))))
hunk ./src/objects/class.lisp 147
- (make-instance 'smoke-class
- :id class-index
- :smoke (smoke class))))
+ (make-smoke-class-from-id (smoke class)
+ class-index)))
hunk ./src/objects/method.lisp 3
-(defclass smoke-method (smoke-symbol)
- ()
- (:documentation "A C++ method"))
+(declaim (inline make-smoke-method))
+(defstruct smoke-method
+ (id 0 :type smoke-index)
+ (smoke (make-smoke-module) :type smoke-module))
+
+(declaim (inline smoke-method-pointer))
+(defun smoke-method-pointer (method)
+ (declare (optimize (speed 3)))
+ (mem-aref (smoke-array-pointer (smoke-module-methods
+ (smoke-method-smoke method)))
+ 'smoke-method
+ (smoke-method-id method)))
hunk ./src/objects/method.lisp 17
- (if (null-pointer-p (smoke smoke-method))
+ (if (or (null-pointer-p (smoke-module-pointer (smoke-method-smoke smoke-method)))
+ (null-pointer-p (smoke-method-pointer smoke-method)))
hunk ./src/objects/method.lisp 23
+(defmethod smoke ((method smoke-method))
+ (smoke-module-pointer (smoke-method-smoke method)))
+
+(defmethod id ((method smoke-method))
+ (declare (optimize (speed 3)))
+ (smoke-method-id method))
+
hunk ./src/objects/method.lisp 39
-(defun valid-p (method)
- "Returns T when METHOD is valid and NIL otherwise."
- (/= 0 (id method)))
-
-(defun unambigous-p (method)
- "Returns T when METHOD is valid and not ambiguous."
- (< 0 (id method)))
-
-(defun ambiguous-p (method)
- "Returns T when METHOD is ambiguous and NIL otherwise."
- (> 0 (id method)))
-
-(defun make-smoke-method-munged (class munged-name-id)
- "Returns the method for the MUNGED-NAME-ID of SMOKE."
- (with-foreign-object (module 'smoke-module-index)
- (smoke-find-method-for-id module (smoke class) (id class) munged-name-id)
- (make-instance 'smoke-method
- :id (foreign-slot-value module 'smoke-module-index 'index)
- :smoke (foreign-slot-value module 'smoke-module-index 'smoke))))
-
hunk ./src/objects/method.lisp 42
- (smoke-find-method m (smoke class) (id class) name)
- (make-instance 'smoke-method
- :id (foreign-slot-value m 'smoke-module-index 'index)
- :smoke (foreign-slot-value m 'smoke-module-index 'smoke))))
+ (smoke-find-method m (smoke-module-pointer (smoke class)) (id class) name)
+ (let ((smoke (foreign-slot-value m 'smoke-module-index 'smoke)))
+ (make-smoke-method
+ :smoke (if (null-pointer-p smoke)
+ (make-smoke-module)
+ (gethash (pointer-address smoke) *smoke-modules*))
+ :id (foreign-slot-value m 'smoke-module-index 'index)))))
hunk ./src/objects/method.lisp 51
-(defun make-smoke-method (class name)
+(defun make-smoke-method-from-name (class name)
hunk ./src/objects/method.lisp 57
- (smoke-find-method m (smoke class) (id class) name)
+ (smoke-find-method m (smoke-module-pointer (smoke class)) (id class) name)
hunk ./src/objects/method.lisp 67
- (loop as i = (smoke-ambiguous-method (smoke class)
- (- (foreign-slot-value m 'smoke-module-index 'index)))
- while (> i 0)
+ (loop as i = (mem-aref (smoke-module-ambiguous-method-list (smoke class))
+ 'smoke-index
+ (- (foreign-slot-value m 'smoke-module-index 'index)))
+ while (> i 0)
hunk ./src/objects/method.lisp 72
- (let ((m (make-instance 'smoke-method :id i :smoke (smoke class))))
- (format t " ~A ~A~%" (name m) (signature m))))
- (error "The method ~S of ~S is ambigious" name (name class)));;TODO
- (make-instance 'smoke-method
- :id (foreign-slot-value m 'smoke-module-index 'index)
- :smoke (foreign-slot-value m 'smoke-module-index 'smoke))))
+ (let ((m (make-smoke-method :smoke (smoke class) :id i)))
+ (format t " ~A ~A~%" (name m) (signature m))))
+ (error "The method ~S of ~S is ambigious" name (name class))) ;;TODO
+ (make-smoke-method
+ :smoke (gethash (pointer-address
+ (foreign-slot-value m 'smoke-module-index 'smoke))
+ *smoke-modules*)
+ :id (foreign-slot-value m 'smoke-module-index 'index))))
hunk ./src/objects/method.lisp 85
- (cffi:foreign-pointer smoke)
hunk ./src/objects/method.lisp 86
- (let ((method (make-instance 'smoke-method
- :id 0
- :smoke smoke))
- (length (1- (the fixnum (smoke-methods-size smoke)))))
+ (let ((method (make-smoke-method :smoke smoke :id 0))
+ (length (smoke-array-length (smoke-module-methods smoke))))
hunk ./src/objects/method.lisp 89
- (setf (slot-value method 'id) id)
+ (setf (smoke-method-id method) id)
hunk ./src/objects/method.lisp 97
- (foreign-slot-value (smoke-get-method (smoke method) (id method))
+ (foreign-slot-value (smoke-method-pointer method)
hunk ./src/objects/method.lisp 100
+(define-compiler-macro method-slot-value (&whole form method slot-name)
+ "Optimize constant slot-names."
+ ;; declaring the function inline calls the compiler macro of
+ ;; foreign-slot-value with 'SLOT-NAME instead of its value an thus
+ ;; has no effect; thus the compiler macro.
+ (if (constantp slot-name)
+ `(foreign-slot-value (smoke-method-pointer ,method)
+ 'smoke-method ,slot-name)
+ form))
+ [_$_]
+
hunk ./src/objects/method.lisp 112
- (smoke-get-method-name (smoke method)
- (method-slot-value method 'name)))
+ (mem-aref (smoke-array-pointer (smoke-module-method-names
+ (smoke-method-smoke method)))
+ :string
+ (method-slot-value method 'name)))
hunk ./src/objects/method.lisp 138
- :smoke (smoke method)))
+ :smoke (smoke-method-smoke method)))
hunk ./src/objects/method.lisp 147
-(defmethod get-flag ((method smoke-method) flag)
+(defun get-method-flag (method flag)
hunk ./src/objects/method.lisp 151
+(define-compiler-macro get-method-flag (&whole form method flag)
+ (if (constantp flag)
+ `(logand (method-slot-value ,method 'flags)
+ ;; Resolve flag value at compile time
+ ,(foreign-enum-value 'smoke-method-flags flag)) [_$_]
+ form))
+
hunk ./src/objects/method.lisp 162
- (/= 0 (get-flag method :constructor)))
+ (/= 0 (get-method-flag method :constructor)))
hunk ./src/objects/method.lisp 166
- (/= 0 (get-flag method :destructor)))
+ (/= 0 (get-method-flag method :destructor)))
hunk ./src/objects/method.lisp 170
- (/= 0 (get-flag method :static)))
+ (/= 0 (get-method-flag method :static)))
hunk ./src/objects/method.lisp 174
- (/= 0 (get-flag method :protected)))
+ (/= 0 (get-method-flag method :protected)))
hunk ./src/objects/method.lisp 178
- (/= 0 (get-flag method :const)))
+ (/= 0 (get-method-flag method :const)))
+
+(defun valid-p (method)
+ "Returns T when METHOD is valid and NIL otherwise."
+ (/= 0 (smoke-method-id method)))
hunk ./src/objects/method.lisp 186
- (< 0 (id method)))
+ (< 0 (smoke-method-id method)))
hunk ./src/objects/method.lisp 190
- (/= 0 (get-flag method :enum)))
+ (/= 0 (get-method-flag method :enum)))
hunk ./src/objects/method.lisp 194
- (/= 0 (get-flag method :internal)))
+ (/= 0 (get-method-flag method :internal)))
hunk ./src/objects/method.lisp 197
- (make-instance 'smoke-class
- :id (method-slot-value method 'class)
- :smoke (smoke method)))
-
- [_$_]
+ (make-smoke-class-from-id
+ (smoke-method-smoke method)
+ (method-slot-value method 'class)))
hunk ./src/objects/method.lisp 206
- (smoke-get-argument (smoke argument) (slot-value argument 'id)))
+ (declare (optimize (speed 3)))
+ (mem-aref (smoke-module-argument-list (smoke argument))
+ 'smoke-index
+ (call-next-method)))
hunk ./src/objects/method.lisp 213
- (= 0 (smoke-get-argument (smoke argument) (1+ (slot-value argument 'id)))))
+ (= 0 (mem-aref (smoke-module-argument-list (smoke argument))
+ 'smoke-index
+ (1+ (slot-value argument 'id)))))
hunk ./src/objects/method.lisp 236
+ (declare (optimize (speed 3)))
hunk ./src/objects/method.lisp 239
- :smoke (smoke method)))
+ :smoke (smoke-method-smoke method)))
hunk ./src/objects/method.lisp 245
- :smoke (smoke method)))
+ :smoke (smoke-method-smoke method)))
hunk ./src/objects/object.lisp 2
-
-(defclass smoke-symbol ()
- ((id :reader id :initarg :id
- :type smoke-index
- :documentation "The objects index.")
- (smoke :reader smoke :initarg :smoke
- :initform (null-pointer)
- :documentation "Pointer to the Smoke module."))
- (:documentation "A method or class in a Smoke module."))
-
-(defmethod print-object ((smoke-symbol smoke-symbol) stream)
- (if (null-pointer-p (smoke smoke-symbol))
- (call-next-method)
- (print-unreadable-object (smoke-symbol stream :type t)
- (princ (name smoke-symbol) stream))))
-
-(defgeneric name (smoke-symbol)
- (:documentation "Returns the name of SMOKE-SYMBOL."))
-
-(defgeneric get-struct-slot-value (smoke-symbol slot-name)
- (:documentation "Returns the slot value of SLOT-NAME of
-the SMOKE-SYMBOLs struct."))
+ [_$_]
+(declaim (inline id))
hunk ./src/objects/stack.lisp 23
+ (declare (optimize (speed 3)))
hunk ./src/objects/stack.lisp 31
- (incf-pointer (top stack) (foreign-type-size 'smoke-stack-item)))
+ (incf-pointer (top stack) #.(foreign-type-size 'smoke-stack-item)))
+
+(define-compiler-macro push-stack (&whole form stack value type)
+ (if (constantp type)
+ `(progn [_$_]
+ (setf (foreign-slot-value (top ,stack)
+ 'smoke-stack-item ,type) ,value)
+ (incf-pointer (top ,stack) ,(foreign-type-size 'smoke-stack-item)))
+ form))
+ [_$_]
hunk ./src/objects/stack.lisp 56
+ (declare (type (smoke-index 0) type-id)
+ (type call-stack stack)
+ (optimize (speed 3)))
hunk ./src/objects/stack.lisp 103
+ (declare (optimize (speed 3)))
hunk ./src/objects/stack.lisp 137
+ (declare (optimize (speed 3)))
hunk ./src/objects/stack.lisp 141
+ (declare (optimize (speed 3)))
hunk ./src/objects/stack.lisp 153
- (let ((object (object-to-lisp (foreign-slot-value stack-item
- 'smoke-stack-item
- 'class)
- type)))
- object))
+ (object-to-lisp (foreign-slot-value stack-item
+ 'smoke-stack-item
+ 'class)
+ type))
hunk ./src/objects/stack.lisp 160
+ (declare (optimize (speed 3)))
hunk ./src/objects/type.lisp 3
-(defclass smoke-type (smoke-symbol)
- ()
+(declaim (inline smoke))
+
+(defclass smoke-type ()
+ ((id :reader id :initarg :id
+ :type smoke-index
+ :documentation "The objects index.")
+ (smoke :reader smoke :initarg :smoke
+ :type smoke-module
+ :documentation "Pointer to the Smoke module."))
hunk ./src/objects/type.lisp 14
-(defclass smoke-lazy-type (smoke::smoke-type)
- ((id :reader smoke::id
- :initarg :id)
- (smoke :initarg :smoke
- :reader smoke-symbol)))
+(defmethod print-object ((type smoke-type) stream)
+ (if (or (<= (id type) 0)
+ (null-pointer-p (smoke-module-pointer (smoke type))))
+ (call-next-method)
+ (print-unreadable-object (type stream :type t)
+ (princ (name type) stream))))
hunk ./src/objects/type.lisp 21
-(defmethod smoke::smoke ((type smoke-lazy-type))
- (eval (smoke-symbol type)))
+(defclass smoke-lazy-type (smoke-type)
+ ())
hunk ./src/objects/type.lisp 29
- (foreign-slot-value (smoke-get-type (smoke type) (id type))
+ (foreign-slot-value (mem-aref (smoke-array-pointer
+ (smoke-module-types (smoke type)))
+ 'smoke-type
+ (the smoke-index (id type)))
hunk ./src/objects/type.lisp 35
+(define-compiler-macro type-slot-value (&whole form type slot-name)
+ (if (constantp slot-name)
+ `(foreign-slot-value (mem-aref (smoke-array-pointer
+ (smoke-module-types (smoke ,type)))
+ 'smoke-type
+ (the smoke-index (id ,type)))
+ 'smoke-type ,slot-name)
+ form))
+ [_$_]
+
hunk ./src/objects/type.lisp 48
- :id (smoke-find-type smoke name)
+ :id (smoke-find-type (smoke-module-pointer smoke) name)
hunk ./src/objects/type.lisp 52
+ (declare (optimize (speed 3)))
hunk ./src/objects/type.lisp 61
-(defgeneric get-flag (object flag)
- (:documentation "Returns the value for FLAG of OBJECT."))
-
-(defmethod get-flag ((type smoke-type) flag)
+(defun get-type-flag (type flag)
+ (declare (optimize (speed 3)))
hunk ./src/objects/type.lisp 64
- #xF0 ;; = ! 0x0F
- (foreign-enum-value 'smoke-type-flags flag)))
+ #xF0 ;; = !0x0F
+ (the fixnum (foreign-enum-value 'smoke-type-flags flag))))
hunk ./src/objects/type.lisp 67
-(defun get-allocation-flag (type)
- (logand (type-slot-value type 'flags)
- #x30))
+(define-compiler-macro get-type-flag (&whole form type flag)
+ (if (constantp flag)
+ `(logand (type-slot-value ,type 'flags)
+ #xF0
+ ,(foreign-enum-value 'smoke-type-flags flag))
+ form))
+ [_$_]
+(defmacro allocation-flag-p (type flag)
+ ;; Can't just use #'get-type-flag since it
+ ;; can only be one of :stack, :reference and :pointer.
+ ;; (:stack + :pointer = :reference) <=> (#x10 + #x20 = #x30)
+ `(= ,(foreign-enum-value 'smoke-type-flags flag)
+ (logand #x30
+ (type-slot-value ,type 'flags))))
hunk ./src/objects/type.lisp 82
+(declaim (inline stack-p))
hunk ./src/objects/type.lisp 85
- (= (get-allocation-flag type) (get-flag type :stack)))
+ (allocation-flag-p type :stack))
hunk ./src/objects/type.lisp 89
- (= (get-allocation-flag type) (get-flag type :reference)))
+ (allocation-flag-p type :reference))
hunk ./src/objects/type.lisp 93
- (= (get-allocation-flag type) (get-flag type :pointer)))
+ (allocation-flag-p type :pointer))
hunk ./src/objects/type.lisp 98
- (/= 0 (get-flag type :const))))
+ (/= 0 (get-type-flag type :const))))
hunk ./src/objects/type.lisp 107
- (logand (type-slot-value type 'flags)
- (foreign-enum-value 'smoke-type-flags :type-id)))
+ (declare (smoke-type type)
+ (optimize (speed 3) (safety 0)))
+ (logand (the (c-integer :unsigned-short) (type-slot-value type 'flags))
+ #.(foreign-enum-value 'smoke-type-flags :type-id)))
hunk ./src/objects/type.lisp 118
- (= 0 (mem-ref (smoke-get-type (smoke type) (id type))
+ (= 0 (mem-ref (mem-aref (smoke-array-pointer
+ (smoke-module-types (smoke type)))
+ 'smoke-type
+ (id type))
hunk ./src/objects/type.lisp 133
- (make-instance 'smoke-class
- :id (type-slot-value type 'class)
- :smoke (smoke type)))
-
-
-;; FIXME why macro?
-(defmacro smoke-type-p (type smoke type-name)
- (let ((t2 (smoke-find-type smoke type-name)))
- `(and (= (id ,type) ,(id t2))
- (pointer-eq (smoke ,type) ,(smoke t2)))))
+ (make-smoke-class-from-id
+ (smoke type)
+ (type-slot-value type 'class)))
hunk ./src/overload-resolution.lisp 6
-(defun mung-char-p (character)
- "Returns true when CHARACTER is used for munging and false otherwise."
- (declare (character character))
- (case character
- ((#\$ #\? #\#) t)))
+(defun cstring= (string1 string2)
+ "Returns T when the C strings STRING1 and STRING2 are equal
+ and NIL otherwise."
+ (declare (optimize (speed 3) (safety 0)))
+ (dotimes (i array-total-size-limit)
+ (let ((char1 (mem-aref string1 :char i))
+ (char2 (mem-aref string2 :char i)))
+ (when (/= char1 char2)
+ (return-from cstring= nil))
+ (when (or (= 0 char1)
+ (= 0 char2))
+ (return-from cstring= (= char1 char2))))))
hunk ./src/overload-resolution.lisp 19
-(defun binary-search-method-names (name smoke start end)
- "Returns the index of NAME for the Smoke module SMOKE and 0 when
-NAME is not found."
- ;; FIXME search methods instead of methodMaps, since we are not
- ;; interrested in the munging.
- (declare ((smoke-index 1) start end)
- (string name)
+(declaim (inline cmp))
+(defun cmp (a b)
+ "Returns -1 if a < b; 0 if a = b and 1 if a > b"
+ (declare (values (integer -1 1)))
+ (if (< a b)
+ -1
+ (if (> a b)
+ 1
+ 0)))
+
+(declaim (inline cstring-cmp))
+(defun cstring-cmp (string1 string2)
+ "Compares the C strings STRING1 and STRING2."
+ (declare (foreign-pointer string1 string2)
+ (values (integer -1 1))
hunk ./src/overload-resolution.lisp 35
- (if (> start end)
- 0
- (let* ((index (floor (+ end start) 2))
- (method-name (smoke-get-method-name smoke index))
- (diff (string/= method-name name)))
- (if diff
- (if (and (>= diff (length name))
- (mung-char-p (char method-name diff)))
- index
- (if (and (< diff (length name))
- (or (>= diff (length method-name))
- (char< (char method-name diff) (char name diff))))
- (binary-search-method-names name smoke (1+ index) end)
- (binary-search-method-names name smoke start (1- index))))
- index))))
+ (dotimes (i array-total-size-limit (error "omg"))
+ (let ((char1 (mem-aref string1 :char i))
+ (char2 (mem-aref string2 :char i)))
+ (when (/= char1 char2)
+ (return-from cstring-cmp (if (< char1 char2) -1 1)))
+ (when (= 0 char1) ;; <=> (= 0 char2)
+ (return-from cstring-cmp 0)))))
hunk ./src/overload-resolution.lisp 43
-(defun method-name= (name munged)
- "Returns true when the name of the munged method name MUNGED is NAME."
- (let ((diff (string/= name munged)))
- (not (and diff
- (or (< diff (length name))
- (not (mung-char-p (char munged diff))))))))
+(defun cstring/= (string1 string2)
+ "Returns T when the C strings STRING1 and STRING2 are not equal
+ and NIL otherwise."
+ (declare (optimize (speed 3)))
+ (dotimes (i array-total-size-limit)
+ (let ((char1 (mem-aref string1 :char i))
+ (char2 (mem-aref string2 :char i)))
+ (when (/= char1 char2)
+ (return-from cstring/= i))
+ (when (= 0 char1)
+ (return-from cstring/= nil)))))
hunk ./src/overload-resolution.lisp 55
-(defun munged-method-argument-count (munged-name)
- "Returns the number of arguments the method MUNGED-NAME uses."
- (- (1- (length munged-name))
- (position-if-not #'mung-char-p munged-name :from-end t)))
- [_$_]
-(defun method-argument-count= (name munged-name argument-count)
- (declare ((integer 1 #.call-arguments-limit) argument-count))
- (and (= (length munged-name) (+ (length name) argument-count))
- (mung-char-p (char munged-name (length name)))))
+(declaim (inline smoke-method-name))
+(defun smoke-method-name (method)
+ (mem-aref (smoke-array-pointer (smoke-module-method-names [_$_]
+ (smoke-method-smoke method)))
+ :pointer
+ (the (smoke-index 0)
+ (method-slot-value method 'name))))
hunk ./src/overload-resolution.lisp 63
-(defun position-method-names (name argument-count smoke start end)
- "Returns a list of the method indices with name NAME
-that accept ARGUMENT-COUNT arguments."
- (declare (string name)
- ((smoke-index 1) start end)
+(defun method-cmp (method class-id name)
+ "Compares METHOD to the method with NAME of class CLASS-ID."
+ (declare (foreign-pointer name)
+ (type (smoke-index 0) class-id)
+ (smoke-method method)
+ (values (integer -1 1))
+ (optimize (speed 3) (debug 0) (safety 0)))
+ (let ((id-cmp (cmp (the (smoke-index 0) (method-slot-value method 'class))
+ (the (smoke-index 0) class-id))))
+ (declare (type (integer -1 1) id-cmp)
+ (dynamic-extent id-cmp))
+ (if (/= 0 id-cmp)
+ id-cmp
+ (cstring-cmp (smoke-method-name method)
+ name))))
+ [_$_]
+(defun first-unabigious-index (smoke index)
+ (declare (type smoke-index index)
hunk ./src/overload-resolution.lisp 82
- (let ((positions (loop for i from start to end
- while (method-name= name (smoke-get-method-name smoke i))
- when (method-argument-count= name (smoke-get-method-name smoke i)
- argument-count)
- collect i)))
- (loop for i from (1- start) downto 1
- while (method-name= name (smoke-get-method-name smoke i))
- do (when (method-argument-count= name (smoke-get-method-name smoke i)
- argument-count)
- (push i positions)))
- positions))
+ (if (>= index 0)
+ index
+ (mem-aref (smoke-module-ambiguous-method-list smoke)
+ 'smoke-index
+ (- index))))
hunk ./src/overload-resolution.lisp 88
-(defun smoke-modules (class)
- "Returns a list of super classes of CLASS; one or every smoke module
-that can be reached by super classes of CLASS. The returned super classes
-are as specific as possible."
- (let ((modules (list class)))
- (dolist (super-class (closer-mop:class-direct-superclasses class) modules)
- (when (and (typep super-class 'smoke-standard-class)
- (not (eql super-class (find-class 'smoke-standard-object))))
- (dolist (c (smoke-modules super-class))
- (setf modules (adjoin c modules :key #'smoke)))))))
+(defun find-method-for-class (name class)
+ "Returns the index of a method with name NAME for class CLASS."
+ (declare (type foreign-pointer name)
+ (type smoke-class class)
+ (optimize (speed 3)))
+ (let* ((start 1) ;; 0 is "no method"
+ (class-id (id class))
+ (smoke (smoke class))
+ (end (smoke-array-length (smoke-module-method-maps smoke))))
+ (declare (type (smoke-index 0) start end))
+ (loop until (> start end) do
+ (let* ((index (the smoke-index (floor (+ end start) 2)))
+ (method (make-smoke-method [_$_]
+ :smoke smoke [_$_]
+ :id (the (smoke-index 0)
+ (first-unabigious-index
+ smoke
+ (foreign-slot-value
+ (mem-aref (smoke-array-pointer
+ (smoke-module-method-maps
+ smoke))
+ 'smoke-method-map index)
+ 'smoke-method-map
+ 'method)))))
+ (cmp (the (integer -1 1) (method-cmp method class-id name))))
+ (declare (type (integer -1 1) cmp)
+ (dynamic-extent method index cmp))
+ (ecase cmp
+ (-1 (setf start (1+ index)))
+ (0 (return-from find-method-for-class index))
+ (1 (setf end (1- index)))))))
+ -1)
hunk ./src/overload-resolution.lisp 121
+(defmacro push-candidate-method (index name argument-count class methods)
+ (with-gensyms (method-map method-index method ambig-index i smoke)
+ `(let* ((,smoke (smoke ,class))
+ (,method-map (mem-aref
+ (smoke-array-pointer
+ (smoke-module-method-maps ,smoke))
+ 'smoke-method-map
+ ,index))
+ (,method-index (foreign-slot-value ,method-map 'smoke-method-map 'method))
+ (,method (make-smoke-method
+ :smoke ,smoke
+ :id (first-unabigious-index
+ ,smoke
+ ,method-index))))
+ (declare (type smoke-index ,method-index))
+ (if (cstring/= ,name
+ (smoke-method-name ,method))
+ nil
+ (progn
+ (when (= (the smoke-index ,argument-count)
+ (the smoke-index (get-arguments-length ,method)))
+ (if (< ,method-index 0)
+ (let ((,ambig-index (- ,method-index)))
+ (declare (type smoke-index ,ambig-index))
+ (loop as ,i = (the smoke-index
+ (mem-aref (smoke-module-ambiguous-method-list
+ ,smoke)
+ 'smoke-index
+ ,ambig-index))
+ while (> (the smoke-index ,i) 0) do
+ (incf ,ambig-index)
+ (push (make-smoke-method :smoke ,smoke
+ :id ,i)
+ ,methods)))
+ (push ,method ,methods))) [_$_]
+ t)))))
hunk ./src/overload-resolution.lisp 158
-(defun viable-functions (name argument-count class2)
+(defun all-smoke-superclasses (class)
+ "Returns a list of all superclasses of CLASS and CLASS itself."
+ (declare (optimize (speed 3)))
+ (let ((classes (list class)))
+ (dolist (class (closer-mop:class-direct-superclasses class) classes)
+ (when (typep class 'smoke-standard-class)
+ (setf classes (append (all-smoke-superclasses class) classes))))))
+ [_$_]
+(defun viable-functions (name argument-count class)
hunk ./src/overload-resolution.lisp 169
- (let ((methods))
- (dolist (class (smoke-modules class2))
- (let ((index (binary-search-method-names
- name (smoke class) 1
- (smoke-method-name-size (smoke class)))))
- (loop for i in (position-method-names name argument-count (smoke class)
- index
- (smoke-method-name-size [_$_]
- (smoke class)))
- do [_$_]
- (let ((method (make-smoke-method-munged class i)))
- (if (unambigous-p method)
- (push method methods)
- (when (ambiguous-p method)
- (let ((index (- (id method))))
- (loop as i = (smoke-ambiguous-method (smoke method)
- index)
- while (> i 0) do
- (incf index)
- (push (make-instance 'smoke-method
- :smoke (smoke method)
- :id i)
- methods)))))))))
- methods))
- [_$_]
+ ;; FIXME make a lazy map-viable-functions to allow returning early,
+ ;; when an exact match is found.
+ (declare (optimize (speed 3)))
+ (with-foreign-string (name name)
+ (let ((methods)
+ (smoke (smoke class)))
+ (dolist (class (all-smoke-superclasses class))
+ (let ((start-index (find-method-for-class name class)))
+ (declare (type smoke-index start-index))
+ (loop for index from start-index downto 1
+ while (push-candidate-method index name argument-count class
+ methods))
+ (loop for index from (1+ start-index)
+ to (the smoke-index (smoke-array-length
+ (smoke-module-method-maps smoke)))
+ while (push-candidate-method index name argument-count class
+ methods))))
+ methods)))
+ [_$_]
hunk ./src/overload-resolution.lisp 244
+ (declare (optimize (speed 3)))
hunk ./src/overload-resolution.lisp 246
- (< (rank conversion1) (rank conversion2))))
+ (< (the fixnum (rank conversion1))
+ (the fixnum (rank conversion2)))))
hunk ./src/overload-resolution.lisp 249
+ (declare (optimize (speed 3)))
hunk ./src/overload-resolution.lisp 350
+ ;; FIXME test for ambigious overload #'conversion=
hunk ./src/overload-resolution.lisp 359
-(defmacro string-case ((keyform) &body clauses)
- ;; FIXME this is horribly inefficient
- `(cond ,@(mapcar #'(lambda (clause)
- `((string= ,keyform ,(first clause))
- ,@(rest clause)))
- clauses)))
-
-(defmacro smoke-type-case ((keyform class) &body clauses)
- `(string-case ((name ,keyform))
- ,@(mapcar (curry #'apply
- #'(lambda (type-name lisp-type)
- `(,type-name (typep-using-type ,class (quote ,lisp-type)))))
- clauses)))
-
hunk ./src/overload-resolution.lisp 388
- (0 [_$_]
- (when-let (test (gethash (name type) *from-lisp-translations*))
- (funcall test (object.type-of))))
+ (0 (when-let (test (gethash (name type) *from-lisp-translations*))
+ (funcall test (object.type-of))))
hunk ./src/overload-resolution.lisp 546
+ "Calls the method NAME of OBJECT-OR-CLASS with ARGUMENTS."
hunk ./src/overload-resolution.lisp 551
- (assert (valid-p method)
- ()
- "No applicable method ~A() for ~A." name object-or-class)
+ (unless (valid-p method)
+ (error (make-condition 'no-applicable-cxx-method
+ :method name
+ :class object-or-class
+ :arguments arguments)))
hunk ./src/package.lisp 22
- #:new-object
hunk ./src/smoke-c/cl_smoke.h 16
-/** @brief Common Lisp smoke binding namespace. */
+/** @brief Common Lisp Smoke binding namespace. */
hunk ./src/smoke-c/cl_smoke.h 21
+/** The arrays of the Smoke module */
+enum cl_smoke_module_array
+{
+ classes,
+ methods,
+ method_maps,
+ method_names,
+ types,
+ inheritance_list,
+ argument_list,
+ ambiguous_method_list
+};
+
hunk ./src/smoke-c/class.lisp 28
-(defcfun smoke-classes-size smoke-index
- (smoke :pointer))
-
hunk ./src/smoke-c/class.lisp 32
-(defcfun smoke-get-parent-index smoke-index
- (smoke :pointer)
- (class smoke-index))
-
hunk ./src/smoke-c/csmokebinding.cpp 16
- * @param binding Smoke binding of the object
- * @param class_id class id
- * @param object the object
+ * @param object pointer to the object
hunk ./src/smoke-c/csmokebinding.cpp 30
- *when the default method shall be invoked.
+ * when the default method shall be invoked.
hunk ./src/smoke-c/csmokebinding.cpp 51
-Binding::deleted(Smoke::Index classId, void *obj)
+Binding::deleted(Smoke::Index, void *object)
hunk ./src/smoke-c/csmokebinding.cpp 53
- destruct(this, classId, obj);
+ destruct(object);
hunk ./src/smoke-c/csmokebinding.h 12
- typedef void (*destructed)(Binding* binding, Smoke::Index class_id,
- void* object);
+ typedef void (*destructed)(void* object);
hunk ./src/smoke-c/csmokebinding.h 20
- deleted(Smoke::Index classId, void *obj);
+ deleted(Smoke::Index classId, void *object);
hunk ./src/smoke-c/method.lisp 3
-(declaim (optimize (debug 3)))
-
hunk ./src/smoke-c/method.lisp 30
-(defcfun smoke-get-method-map (:pointer smoke-method-map)
- (smoke :pointer)
- (index smoke-index))
-
-(defcfun smoke-find-method-for-id :void
- (m :pointer smoke-module-index)
- (smoke :pointer)
- (class-index smoke-index)
- (method-name smoke-index))
-
+(declaim (inline smoke-find-method))
hunk ./src/smoke-c/method.lisp 36
-
-(defcfun smoke-methods-size smoke-index
- (smoke :pointer))
-
-(defcfun smoke-get-method (:pointer smoke-method)
- (smoke :pointer)
- (method smoke-index))
-
-(defcfun smoke-get-method-name :string
- (smoke :pointer)
- (method-index smoke-index))
-
-(defcfun smoke-method-name-size smoke-index
- (smoke :pointer))
-
-(defcfun smoke-call-method :void
- (smoke :pointer)
- (method smoke-index)
- (object :pointer)
- (stack smoke-stack))
-
-(defcfun smoke-get-argument smoke-index
- (smoke :pointer)
- (argument smoke-index))
-
-(defcfun smoke-ambiguous-method smoke-index
- (smoke :pointer)
- (ambiguous smoke-index))
hunk ./src/smoke-c/smoke-c.cpp 10
- *
- * @example examples/kde-hello-world.cpp
- * This KDE example creates a KXmlGuiWindow.
- * Note that C++ is only used to make the example shorter
- * (by allowing to directly include smoke-c.cpp), but it could also
- * be implemented in C using \c dlsym.
- *
- * @image html doc/images/kde-hello-world.png "Screenshot"
- * @image latex doc/images/kde-hello-world.png "Screenshot" width=5cm
hunk ./src/smoke-c/smoke-c.cpp 66
+
+/** Returns the pointer to the array @a array of @a smoke.
+ * @param smoke the Smoke module
+ * @param array the array type
+ * [_$_]
+ * @return a pointer to the array
+ */
+CL_SMOKE_EXPORT void*
+cl_smoke_array(void* smoke, cl_smoke_module_array array)
+{
+ switch (array)
+ {
+ case classes:
+ return get_smoke(smoke)->classes;
+ case methods:
+ return get_smoke(smoke)->methods;
+ case method_maps:
+ return get_smoke(smoke)->methodMaps;
+ case method_names:
+ return get_smoke(smoke)->methodNames;
+ case types:
+ return get_smoke(smoke)->types;
+ case inheritance_list:
+ return get_smoke(smoke)->inheritanceList;
+ case argument_list:
+ return get_smoke(smoke)->argumentList;
+ case ambiguous_method_list:
+ return get_smoke(smoke)->ambiguousMethodList;
+ }
+ qFatal("cl_smoke_array(): Unknown smoke_array %d", array);
+}
+
+/** Returns the size of the array @a array of @a smoke.
+ * The size if inclusive the bound.
+ * @param smoke the Smoke module
+ * @param array the array type
+ *
+ * @return the size
+ */
+CL_SMOKE_EXPORT Smoke::Index
+cl_smoke_array_size(void* smoke, cl_smoke_module_array array)
+{
+ switch (array)
+ {
+ case classes:
+ return get_smoke(smoke)->numClasses;
+ case methods:
+ return get_smoke(smoke)->numMethods;
+ case method_maps:
+ return get_smoke(smoke)->numMethodMaps;
+ case method_names:
+ return get_smoke(smoke)->numMethodNames;
+ case types:
+ return get_smoke(smoke)->numTypes;
+ case inheritance_list:
+ case argument_list:
+ case ambiguous_method_list:
+ qFatal("cl_smoke_array_size(): size of %d not known.", array);
+ }
+ qFatal("cl_smoke_array_size(): Unknown smoke_array %d.", array);
+}
+
hunk ./src/smoke-c/smoke-c.cpp 158
-
-
-/** Gets the number of classes.
- *
- * @return the number of classes
- */
-CL_SMOKE_EXPORT Smoke::Index
-smoke_classes_size(void* smoke)
-{
- return get_smoke(smoke)->numClasses;
-}
-
-/** Sets the binding for an newly constructed instance.
- * @param smoke the Smoke module
- * @param binding the Smoke binding
- * @param class_index the index of the instances class
- * @param object pointer to the class instance.
- */
-CL_SMOKE_EXPORT void
-smoke_set_binding(void* smoke, smoke_binding binding, Smoke::Index class_index, void* object)
-{
- Q_ASSERT(object != NULL);
- Q_ASSERT(binding != NULL);
- Q_ASSERT(class_index > 0 && class_index <= smoke_classes_size(smoke));
-
- const Smoke::Class* klass = &get_smoke(smoke)->classes[class_index];[_^I_][_$_]
-
- Smoke::StackItem stack[2];
- stack[1].s_voidp = get_smoke_binding(binding);
-
- (*klass->classFn)(0, object, stack);
-}
-
hunk ./src/smoke-c/smoke-c.cpp 167
- Q_ASSERT(class_index >= 0 && class_index <= smoke_classes_size(smoke));
+ Q_ASSERT(class_index >= 0 && class_index <= get_smoke(smoke)->numClasses);
hunk ./src/smoke-c/smoke-c.cpp 189
-/** Returns the index of a base class.
- * @param smoke the Smoke module
- * @param class_index the class index
- * [_$_]
- * @return the index of a parent
- */
-CL_SMOKE_EXPORT Smoke::Index
-smoke_get_parent_index(void* smoke, Smoke::Index class_index)
-{
- Q_ASSERT(class_index >= 0);
-
- return get_smoke(smoke)->inheritanceList[class_index];
-}
-
hunk ./src/smoke-c/smoke-c.cpp 193
-/** Gets the method map.
- * @param smoke the Smoke module
- * @param method the index of the method
- *
- * @return a pointer to the @c MethodMap entry.
- */
-CL_SMOKE_EXPORT const Smoke::MethodMap*
-smoke_get_method_map(void* smoke, Smoke::Index method)
-{
- Q_ASSERT(method >= 0 && method <= get_smoke(smoke)->numMethodMaps);
-
- return &get_smoke(smoke)->methodMaps[method];
-}
-
-/** Gets a methods name.
- * @param smoke the Smoke module
- * @param method_name the method name index
- *
- * @return the method name
- */
-CL_SMOKE_EXPORT const char*
-smoke_get_method_name(void* smoke, Smoke::Index method_name)
-{
- Q_ASSERT(method_name >= 0 && method_name <= get_smoke(smoke)->numMethodNames);
-
- return get_smoke(smoke)->methodNames[method_name];
-}
-
-/** Gets the number of method names.
- * @param smoke the Smoke module
- *
- * @return the number of method names
- */
-CL_SMOKE_EXPORT Smoke::Index
-smoke_method_name_size(void *smoke)
-{
- return get_smoke(smoke)->numMethodNames;
-}
-
-/** Gets the number of methods.
- * @param smoke the Smoke module
- *
- * @return the number of methods
- */
-CL_SMOKE_EXPORT Smoke::Index
-smoke_methods_size(void* smoke)
-{
- return get_smoke(smoke)->numMethods;
-}
-
-/** Gets a method.
- * @param smoke the smoke binding
- * @param method the index of the method
- *
- * @return a pointer to the method struct
- */
-CL_SMOKE_EXPORT const struct Smoke::Method*
-smoke_get_method(void* smoke, Smoke::Index method)
-{
- Q_ASSERT(method >= 0 && method <= smoke_methods_size(smoke));
-
- return &get_smoke(smoke)->methods[method];
-}
-
hunk ./src/smoke-c/smoke-c.cpp 206
- m->index = smoke_get_method_map(m->smoke, m->index)->method;
-}
-
-/** Finds a method for a class and a munged name.
- * @param m pointer where the result is stored.
- * @param smoke the Smoke binding
- * @param class_index index of the class
- * @param method_name index of the munged method name
- */
-CL_SMOKE_EXPORT void
-smoke_find_method_for_id(Smoke::ModuleIndex* m, void* smoke,
- Smoke::Index class_index, Smoke::Index method_name)
-{
- *m = get_smoke(smoke)->findMethod((Smoke::ModuleIndex){get_smoke(smoke), class_index},
- (Smoke::ModuleIndex){get_smoke(smoke), method_name});
-
- if(m->index > 0)
- m->index = smoke_get_method_map(m->smoke, m->index)->method;
-}
-
-/** Gets the type index of an argument.
- * @param smoke the smoke binding
- * @param argument the argument index
- *
- * @return the type index
- */
-CL_SMOKE_EXPORT Smoke::Index
-smoke_get_argument(void* smoke, Smoke::Index argument)
-{
- Q_ASSERT(argument >= 0);
-
- return get_smoke(smoke)->argumentList[argument];
-}
-
-/** Calls a method.
- * The methods return value is stored in the first element of the stack.
- * @param smoke the smoke binding
- * @param method the index of the method
- * @param object A pointer to the class instance, or NULL for static and constructor calls
- * @param stack The stack with the methods arguments.
- */
-CL_SMOKE_EXPORT void
-smoke_call_method(void* smoke, Smoke::Index method, void* object,
- Smoke::Stack stack)
-{
- Smoke::Method meth = *smoke_get_method(smoke, method);
- Q_ASSERT(!(meth.flags & Smoke::mf_internal));
- Q_ASSERT_X((NULL == object
- && (meth.flags & (Smoke::mf_static
- | Smoke::mf_enum
- | Smoke::mf_copyctor
- | Smoke::mf_ctor)))
- || object,
- __func__, "object is NULL");
- Q_ASSERT(meth.flags & Smoke::mf_ctor ? NULL == object : true);
- const Smoke::Class* klass = smoke_get_class(smoke, meth.classId);
-
- try
- {
- Q_ASSERT(klass->classFn != NULL);
- (*klass->classFn)(meth.method, object, stack);
- } [_$_]
- // This catch is mostly useless:
- // Qt / KDElibs do not use exceptions and since they are often built with -fno-exceptions
- // the catch will have no effect and the terminate handler is called instead.
- catch (const std::exception& e) [_$_]
- {
- qFatal(e.what());
- }
- catch (...)
- {
- qFatal("exception in C++ code.");
- }
+ m->index = m->smoke->methodMaps[m->index].method;
hunk ./src/smoke-c/smoke-c.cpp 213
-/** Gets the number of types.
- * @param smoke the Smoke module
- *
- * @return the number of types
- */
-CL_SMOKE_EXPORT Smoke::Index
-smoke_types_size(void* smoke)
-{
- return get_smoke(smoke)->numTypes;
-}
-
-/** Gets a type.
- * @param smoke the Smoke module
- * @param type the index of the type
- *
- * @return a pointer to the type struct
- */
-CL_SMOKE_EXPORT const struct Smoke::Type*
-smoke_get_type(void* smoke, Smoke::Index type)
-{
- Q_ASSERT(type >= 0 && type <= smoke_types_size(smoke));
-
- return &get_smoke(smoke)->types[type];
-}
-
hunk ./src/smoke-c/smoke-c.cpp 236
- Q_ASSERT(from > 0 && from <= smoke_classes_size(smoke));
- Q_ASSERT(to > 0 && to <= smoke_classes_size(smoke));
+ Q_ASSERT(from > 0 && from <= get_smoke(smoke)->numClasses);
+ Q_ASSERT(to > 0 && to <= get_smoke(smoke)->numClasses);
hunk ./src/smoke-c/smoke-c.cpp 242
-/** Gets an ambiguous method.
- * @param smoke the Smoke module
- * @param ambiguous the index
- *
- * @return the index of a method
- */
-CL_SMOKE_EXPORT Smoke::Index
-smoke_ambiguous_method(void* smoke, Smoke::Index ambiguous)
-{
- Q_ASSERT(ambiguous >= 0);
-
- return get_smoke(smoke)->ambiguousMethodList[ambiguous];
-}
-
hunk ./src/smoke-c/smoke-c.lisp 60
-(defcfun smoke-set-binding :void
- "Sets the binding for an newly constructed instance."
- (smoke :pointer)
- (smoke-binding smoke-binding)
- (class smoke-index)
- (object :pointer))
-
+(declaim (inline smoke-get-smoke))
hunk ./src/smoke-c/smoke-c.lisp 66
+
+(defcenum cl-smoke-array
+ :classes
+ :methods
+ :method-maps
+ :method-names
+ :types
+ :inheritance-list
+ :argument-list
+ :ambiguous-method-list)
+
+(defcfun cl-smoke-array :pointer
+ (smoke :pointer)
+ (array cl-smoke-array))
+
+(defcfun cl-smoke-array-size smoke-index
+ (smoke :pointer)
+ (array cl-smoke-array))
hunk ./src/smoke-c/type.lisp 14
- "A type"
hunk ./src/smoke-c/type.lisp 21
-
-(defcfun smoke-types-size smoke-index
- (smoke :pointer))
-
-(defcfun smoke-get-type (:pointer smoke-type)
- (smoke :pointer)
- (type smoke-index))
hunk ./src/smoke.lisp 30
-(defun s-call (method object &optional (args nil))
+(declaim (inline call-s-method) (optimize (debug 3)))
+(defun call-s-method (method object-pointer stack-pointer)
+ (foreign-funcall-pointer [_$_]
+ (foreign-slot-value (pointer (get-class method))
+ 'smoke-class
+ 'class-function)
+ ()
+ smoke-index (foreign-slot-value (smoke-method-pointer method)
+ 'smoke-method
+ 'method)
+ :pointer object-pointer
+ smoke-stack stack-pointer
+ :void))
+
+(defun s-call (method object-pointer &optional (args nil))
hunk ./src/smoke.lisp 46
- (smoke-call-method (smoke method) (id method)
- object (pointer stack))
+ (call-s-method method object-pointer (pointer stack))
hunk ./src/smoke.lisp 49
-(defun pointer-call (method object &optional (args nil))
+(defun pointer-call (method object-pointer &optional (args nil))
hunk ./src/smoke.lisp 51
- (smoke-call-method (smoke method) (id method)
- object (pointer stack))
+ (call-s-method method object-pointer (pointer stack))
hunk ./src/smoke.lisp 57
- (make-smoke-method class method-name)
+ (make-smoke-method-from-name class method-name)
hunk ./src/smoke.lisp 62
- (make-smoke-method (make-smoke-class smoke class-name)
- method-name)
+ (make-smoke-method-from-name (make-smoke-class smoke class-name)
+ method-name)
hunk ./src/smoke.lisp 76
- (smoke-call-method (smoke method) (id method)
- (null-pointer) (pointer stack))
+ (call-s-method method (null-pointer) (pointer stack))
hunk ./src/smoke.lisp 79
-(defun new-object (binding class-name method-name &rest args)
- (let* ((smoke (smoke-get-smoke binding))
- (method (make-smoke-method (make-smoke-class smoke class-name)
- method-name))
- (pointer
- (pointer-call method (null-pointer) args))
- (object (instance-to-lisp pointer [_$_]
- (find-smoke-class (get-class (return-type method)))
- (return-type method))))
- (set-binding object (binding (smoke (class-of object))))
- (add-object object)
- object))
- [_$_]
-
hunk ./src/smoke.lisp 82
+; (declare (optimize (speed 3)))
hunk ./src/smoke.lisp 85
- (make-smoke-method class method-name)
+ (make-smoke-method-from-name class method-name)
hunk ./src/smoke.lisp 92
- (make-smoke-method (class-of object) method-name)
+ (make-smoke-method-from-name (class-of object) method-name)
hunk ./src/smoke.lisp 96
-(defun set-binding (object binding)
- (smoke-set-binding (smoke (class-of object)) binding (id (class-of object)) (pointer object)))
+(defun set-binding (object)
+ "Sets the Smoke binding for OBJECT, that receives its callbacks."
+ (declare (optimize (speed 3)))
+ (with-foreign-object (stack 'smoke-stack-item 2)
+ (setf (foreign-slot-value (mem-aref stack
+ 'smoke-stack-item
+ 1)
+ 'smoke-stack-item
+ 'voidp)
+ (smoke-module-binding (smoke (class-of object))))
+ (foreign-funcall-pointer [_$_]
+ (foreign-slot-value (pointer (class-of object))
+ 'smoke-class
+ 'class-function)
+ ()
+ smoke-index 0 ;; set binding method index
+ :pointer (pointer object) smoke-stack stack
+ :void)))
hunk ./src/smoke.lisp 115
-(defun init (smoke)
+(defun init (smoke module)
hunk ./src/smoke.lisp 118
- (let ((binding (smoke-init smoke
- (callback destructed)
- (callback dispatch-method))))
- (setf (binding smoke) binding)
- binding))
+ (let* ((binding (smoke-init smoke
+ (callback destructed)
+ (callback dispatch-method))))
+ (setf (binding smoke) binding
+ (smoke-module-pointer module) smoke
+ (smoke-module-binding module) binding)
+ (init-smoke-module module)
+ (setf (gethash (pointer-address smoke) *smoke-modules*) module)
+ module))
hunk ./src/smoke.lisp 131
- (setf (gethash (pointer-address (eval symbol)) pointer-symbol-map)
+ (setf (gethash (pointer-address (smoke-module-pointer (eval symbol))) pointer-symbol-map)
hunk ./src/smoke.lisp 162
- (maphash #'(lambda (address value)
- (declare (ignore value))
- (let ((smoke (make-pointer address)))
- (map-methods #'(lambda (method)
- (when (and (string= name (name method))
- (not (enum-p method)))
- (push (make-instance 'smoke-method
- :id (id method)
- :smoke (smoke method))
- methods)))
- smoke)))
- *smoke-id-class-map*)
+ (maphash
+ #'(lambda (address value)
+ (declare (ignore value))
+ (let ((smoke (make-pointer address)))
+ (map-methods #'(lambda (method)
+ (when (and (string= name (name method))
+ (not (enum-p method)))
+ (push (make-instance 'smoke-method
+ :id (smoke-method-id method)
+ :smoke (smoke method))
+ methods)))
+ smoke)))
+ *smoke-id-class-map*)
hunk ./src/smoke.lisp 179
- (when (search str (name method))
- (format t "~A::~A~%" (name (get-class method))
- (signature method))))
+ (when (search str (name method))
+ (princ (method-declaration method))
+ (terpri)))
hunk ./src/smoke.lisp 188
- `(progn
- (eval-startup (:compile-toplevel :execute)
+ (let ((smoke-module (intern "*SMOKE-MODULE*")))
+ `(progn
+ (eval-startup (:compile-toplevel :execute)
+ (eval-when (:compile-toplevel :load-toplevel :execute)
+ (define-foreign-library ,library
+ (:unix ,(format nil "~(~A~).so.2" library))
+ (t (:default ,(format nil "~(~A~)" library))))
+ (use-foreign-library ,library))
+ (defcvar (,variable ,variable-name :read-only t) :pointer)
+ (defcfun (,init-function ,(format nil "_Z~A~Av"
+ (length function-name)
+ function-name))
+ :void))
hunk ./src/smoke.lisp 202
- (define-foreign-library ,library
- (:unix ,(format nil "~(~A~).so.2" library))
- (t (:default ,(format nil "~(~A~)" library))))
- (use-foreign-library ,library))
- (defcvar (,variable ,variable-name :read-only t) :pointer)
- (defcfun (,init-function ,(format nil "_Z~A~Av" (length function-name)
- function-name))
- :void))
- (eval-startup (:compile-toplevel :execute)
- (,init-function)
- (init ,variable))
- (define-classes-and-gfs ,package ,variable)))
+ (defparameter ,smoke-module (make-smoke-module)))
+ (eval-startup (:compile-toplevel :execute)
+ (,init-function)
+ (init ,variable ,smoke-module))
+ (define-classes-and-gfs ,package ,smoke-module))))
hunk ./src/using-type.lisp 1
+;;; NOTE -using-type is disabled for now, since it is not used.
+
hunk ./src/using-type.lisp 20
-false when it is not"; and :MAYBE when the relationship
-;could not be determined."
+false when it is not; and :MAYBE when the relationship
+could not be determined."
hunk ./src/using-type.lisp 60
+ #+nil [_$_]
hunk ./src/using-type.lisp 75
+ #+nil
hunk ./test.lisp 2
-sbcl --noinform --noprint --disable-debugger --load $0 --end-toplevel-options "$@" || exit 1
+MALLOC_CHECK_=3 sbcl --noinform --disable-debugger --noprint --load $0 --end-toplevel-options "$@" || exit 1
hunk ./test.lisp 24
-(mb:clean :smoke)
+;(mb:load :FiveAm)
+;(setf 5am:*debug-on-failure* t)
+;(setf 5am:*debug-on-error* t)
Fri Jun 12 14:21:44 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Load Smoke libraries at compile time.
hunk ./src/clos.lisp 109
-(defclass smoke-standard-object ()
- ((pointer :reader pointer
- :initarg :pointer
- :documentation "Pointer to the C++ object.")
- ;; We can not have a global table of objects owned by C++,
- ;; since then they would be alway reacable from Lisp and thus
- ;; cycles would never be garbage collected.
- (owned-objects :accessor owned-objects
- :initform nil
- :type list
- :documentation "Objecsts owned by the C++ instance."))
- (:documentation "The standard superclass for Smoke classes."))
-
hunk ./src/objects/stack.lisp 31
+
+(defclass smoke-standard-object ()
+ ((pointer :reader pointer
+ :initarg :pointer
+ :documentation "Pointer to the C++ object.")
+ ;; We can not have a global table of objects owned by C++,
+ ;; since then they would be alway reacable from Lisp and thus
+ ;; cycles would never be garbage collected.
+ (owned-objects :accessor owned-objects
+ :initform nil
+ :type list
+ :documentation "Objecsts owned by the C++ instance."))
+ (:documentation "The standard superclass for Smoke classes."))
hunk ./src/smoke.lisp 171
+ (eval-when (:compile-toplevel :load-toplevel :execute)
hunk ./src/smoke.lisp 175
- (use-foreign-library ,library)
+ (use-foreign-library ,library))
Thu Jun 11 20:45:05 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* futile CLISP fixes
hunk ./src/clos.lisp 454
+ #-clisp
hunk ./src/object-map.lisp 24
- #-cmucl (make-weak-hash-table :weakness weakness)
+ #-cmucl (make-weak-hash-table :weakness #-clisp weakness
+ ;; CLISP crash with weak hash table
+ ;; leak memory (see also: #'keep-wrapper)
+ #+clisp nil)
hunk ./src/object-map.lisp 30
+
+;; FIXME
+;; CLISP has problems with weak hashtables and finalizers.
+;; trivial-garbage has a workaround!?
+;; http://sourceforge.net/tracker/index.php?func=detail&aid=1472478&group_id=1355&atid=101355
+;; crashes 2.47 and 2.44.1
+;; Works when not using a weak hash table, but now we are leaking memory!
hunk ./src/object-map.lisp 44
+(declaim (inline ptr -address))
+(defun ptr-address (pointer)
+ ;; CLISP returns NIL for a null pointer
+ #+clisp
+ (if pointer
+ (pointer-address pointer)
+ 0)
+ #-clisp
+ (pointer-address pointer))
+
hunk ./src/object-map.lisp 56
- (gethash (pointer-address pointer) *object-map*))
+ (gethash (ptr-address pointer) *object-map*))
hunk ./src/object-map.lisp 60
- (setf (gethash (pointer-address pointer) *object-map*)
+ (setf (gethash (ptr-address pointer) *object-map*)
hunk ./src/object-map.lisp 65
- (nth-value 1 (gethash (pointer-address pointer) *object-map*)))
+ (nth-value 1 (gethash (ptr-address pointer) *object-map*)))
hunk ./src/object-map.lisp 68
- (remhash (pointer-address pointer) *object-map*))
+ (remhash (ptr-address pointer) *object-map*))
hunk ./src/object-map.lisp 74
- (remhash (pointer-address pointer) *object-map*))
+ (remhash (ptr-address pointer) *object-map*))
Thu Jun 11 16:35:40 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Modules can specify the package to place the classes, static methods and constants in.
hunk ./smoke.mbd 16
- ())
+ ((package :initarg :package)))
hunk ./src/clos.lisp 211
-(defun make-smoke-classes (smoke)
- "Construts a lisp class for each one in the Smoke module SMOKE."
+(defun make-smoke-classes (package smoke)
+ "Construts a lisp class in PACKAGE for each one in the Smoke module SMOKE."
hunk ./src/clos.lisp 215
+ (let ((*package* (find-package package)))
hunk ./src/clos.lisp 229
- smoke))
+ smoke)))
hunk ./src/method.lisp 4
-(defun constant-definition (method smoke)
+(defun constant-definition (package method smoke)
hunk ./src/method.lisp 11
- "+"))
+ "+")
+ package)
hunk ./src/method.lisp 16
- (name method) "+")))))
+ (name method) "+")
+ package))))
hunk ./src/method.lisp 28
-(defun static-method-symbol (method)
+(defun static-method-symbol (package method)
hunk ./src/method.lisp 38
- (name method)))))
+ (name method))
+ package)))
hunk ./src/method.lisp 41
-(defun static-method-definition (method &optional (argument-count -1))
+(defun static-method-definition (package method &optional (argument-count -1))
hunk ./src/method.lisp 46
- (name (static-method-symbol method)))
+ (name (static-method-symbol package method)))
hunk ./src/method.lisp 51
- (call-using-args (find-class (quote ,(lispify (name class))))
+ (call-using-args (find-class (quote ,(lispify (name class) package)))
hunk ./src/method.lisp 90
-(defmacro define-methods (smoke)
+(defmacro define-classes-and-gfs (package smoke)
hunk ./src/method.lisp 109
- (multiple-value-bind (def export) (constant-definition method smoke)
+ (multiple-value-bind (def export) (constant-definition package method smoke)
hunk ./src/method.lisp 129
- (let* ((function-symbol (static-method-symbol method))
+ (let* ((function-symbol (static-method-symbol package method))
hunk ./src/method.lisp 140
+ package
hunk ./src/method.lisp 151
- (make-smoke-classes ,smoke)
+ (make-smoke-classes ,package ,smoke)
hunk ./src/method.lisp 155
- (export (quote ,exports))))))
+ (export (quote ,exports) ,package)))))
hunk ./src/smoke-c/smoke-c.lisp 57
- "asdf"
hunk ./src/smoke.lisp 165
-(defmacro define-smoke-module (library (variable variable-name)
+(defmacro define-smoke-module (package library [_$_]
+ (variable variable-name)
hunk ./src/smoke.lisp 182
- (define-methods ,variable)))
+ (define-classes-and-gfs ,package ,variable)))
Wed Jun 10 14:01:10 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* No need for a synchronized hash table when threads are not supported.
hunk ./src/object-map.lisp 19
- (cerror "Use unsynchronized hash-table"
- "Synchronized hash table not implemented.")
+ (when *supports-threads-p*
+ (cerror "Use unsynchronized hash-table"
+ "Synchronized hash table not implemented."))
Wed Jun 10 13:55:55 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix ownership transfer for non cxx:class objects.
hunk ./src/clos.lisp 193
+ (assert (virtual-destructor-p superclass)
+ ()
+ "The class ~A has a non virtual destructor." superclass)
+ [_$_]
hunk ./src/clos.lisp 308
- (transfer-ownership-to value object))))))
+ (when (typep value 'smoke-standard-object)
+ (transfer-ownership-to value object)))))))
hunk ./src/clos.lisp 453
- (assert (not (member object (owned-objects new-owner)))
- ()
- "~A has already been called for ~A." #'keep-wrapper object)
+ (when (member object (owned-objects new-owner))
+ (cerror "ignore" "~A has already been called for ~A."
+ #'keep-wrapper object))
hunk ./src/clos.lisp 464
- (if (typep (class-of object) 'cxx:class)
- (progn
- (assert (virtual-destructor-p (class-of object))
- ()
- "The ownership of the object ~A is transfered to C++, but
-it has a nonvirtual destructor." object)
- (keep-wrapper object new-owner))
- (when (and (typep object 'smoke-standard-object)
- (not (virtual-destructor-p (class-of object))))
- (remove-object (pointer object)))))
+ (if (virtual-destructor-p (class-of object))
+ (keep-wrapper object new-owner)
+ (remove-object (pointer object))))
hunk ./src/clos.lisp 468
-
Mon Jun 8 11:20:54 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Make unreadable cycles garbage collectable.
hunk ./src/clos.lisp 110
- ((pointer :reader pointer :initarg :pointer
- :documentation "Pointer to the C++ object."))
+ ((pointer :reader pointer
+ :initarg :pointer
+ :documentation "Pointer to the C++ object.")
+ ;; We can not have a global table of objects owned by C++,
+ ;; since then they would be alway reacable from Lisp and thus
+ ;; cycles would never be garbage collected.
+ (owned-objects :accessor owned-objects
+ :initform nil
+ :type list
+ :documentation "Objecsts owned by the C++ instance."))
hunk ./src/clos.lisp 267
- (remove-wrapper-object object)
hunk ./src/clos.lisp 292
-(defun put-returnvalue (stack value type)
+(defun put-returnvalue (stack value type object)
hunk ./src/clos.lisp 304
- (disown-object value))))))
+ (transfer-ownership-to value object))))))
hunk ./src/clos.lisp 342
- (return-type method))
+ (return-type method)
+ object)
hunk ./src/clos.lisp 364
- (put-returnvalue stack return-value (return-type method))
+ (put-returnvalue stack return-value [_$_]
+ (return-type method)
+ (get-object object))
hunk ./src/clos.lisp 447
-(defvar *cxx-wrapper-objects* (make-synchronized-hash-table))
-
-(defun keep-wrapper (object)
- (assert (not (gethash object *cxx-wrapper-objects*)))
- (setf (gethash object *cxx-wrapper-objects*) object))
+(defun keep-wrapper (object new-owner)
+ (assert (not (member object (owned-objects new-owner)))
+ ()
+ "~A has already been called for ~A." #'keep-wrapper object)
+ (push object (owned-objects new-owner)))
hunk ./src/clos.lisp 453
-(defun remove-wrapper-object (object)
- (remhash object *cxx-wrapper-objects*))
+(defun remove-wrapper-object (object owner)
+ (remove object (owned-objects owner)))
hunk ./src/clos.lisp 456
-(defun disown-object (object)
+(defun transfer-ownership-to (object new-owner)
hunk ./src/clos.lisp 465
- (keep-wrapper object))
+ (keep-wrapper object new-owner))
hunk ./src/clos.lisp 471
-
-(defun take-ownership (object)
+(defun take-ownership (object &optional current-owner)
hunk ./src/clos.lisp 474
- (remove-wrapper-object object)
+ (when current-owner
+ (remove-wrapper-object object current-owner))
hunk ./src/clos.lisp 478
-
-;(eval-when (:load-toplevel)
-; (trace disown-object
-; keep-wrapper
-; remove-wrapper-object [_$_]
-;take-ownership
-;put-returnvalue
-;))
hunk ./src/objects/enum.lisp 79
+(defun enum-logior (&rest enums)
+ (apply #'logior (mapcar #'value enums)))
+
hunk ./src/package.lisp 6
+ #:enum-logior
hunk ./src/smoke.lisp 191
- "Declares METHOD transfers the ownership of OBJECT to C++."
+ "Declares METHOD transfers the ownership of OBJECT to the
+first argument of LAMBDA-LIST."
hunk ./src/smoke.lisp 194
- (disown-object ,object)))
+ (transfer-ownership-to ,object ,(if (consp (first lambda-list))
+ (first (first lambda-list))
+ (first lambda-list)))))
Wed Jun 3 23:55:26 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Added restarts to method dispatch callback.
hunk ./src/clos.lisp 311
- (let ((method (make-instance 'smoke-method
- :id method
- :smoke (smoke-get-smoke binding))))
- (let ((gf (get-gf-for-method method)))
- (if (null (gf-methods gf))
- (progn
- (when abstract
- (error "Abstract method ~S called." (name method)))
- nil)
- (let ((object (get-object object)))
- (if object
- (progn
- (put-returnvalue
- stack
- (apply gf object
- (stack-to-args
- (cffi:inc-pointer stack [_$_]
- (cffi:foreign-type-size
- 'smoke-stack-item))
- (get-first-argument method)))
- (return-type method))
- t)
- nil))))))
+ (let* ((method (make-instance 'smoke-method
+ :id method
+ :smoke (smoke-get-smoke binding))))
+ (loop
+ (restart-case
+ (return-from dispatch-method
+ (let ((gf (get-gf-for-method method)))
+ (if (null (gf-methods gf))
+ (progn
+ (when abstract
+ (error "Abstract method ~A called."
+ (method-declaration method)))
+ nil)
+ (let ((object (get-object object)))
+ (if object
+ (progn
+ (put-returnvalue
+ stack
+ (apply gf object
+ (stack-to-args
+ (cffi:inc-pointer stack [_$_]
+ (cffi:foreign-type-size
+ 'smoke-stack-item))
+ (get-first-argument method)))
+ (return-type method))
+ t)
+ nil)))))
+ (call-default ()
+ :report (lambda (stream)
+ (format stream "Call default implementation ~A instead."
+ method))
+ :test (lambda (condition)
+ (declare (ignore condition))
+ (not abstract))
+ (return-from dispatch-method nil))
+ (use-returnvalue (return-value)
+ :report (lambda (stream)
+ (format stream "Supply a return value for ~A."
+ (method-declaration method)))
+ :test (lambda (condition)
+ (declare (ignore condition))
+ (not (void-p (return-type method))))
+ :interactive (lambda ()
+ (format *query-io* "~&Enter a new return value: ")
+ (multiple-value-list (eval (read *query-io*))))
+ (put-returnvalue stack return-value (return-type method))
+ (return-from dispatch-method t))
+ (return ()
+ :report (lambda (stream)
+ (format stream "Return void for ~A."
+ (method-declaration method)))
+ :test (lambda (condition)
+ (declare (ignore condition))
+ (void-p (return-type method)))
+ (return-from dispatch-method (values)))
+ (retry ()
+ :report (lambda (stream)
+ (format stream "Try again calling ~A" [_$_]
+ (method-declaration method))))))))
hunk ./src/object-map.lisp 55
-(defun report-finalize-error (condition function object pointer)
- (warn "error calling finalizer ~A for ~A ~A:~%~5T~A"
- function object pointer condition))
+(defun report-finalize-error (condition function class pointer)
+ "Report the error CONDITION it the finalizer FUNCTION for the
+object at POINTER of class CLASS."
+ (warn "error calling finalizer ~A for ~A ~A:~%~5T~A~%"
+ function class pointer condition))
hunk ./src/objects/method.lisp 230
-
hunk ./src/smoke-c/csmokebinding.cpp 58
-/** Invoked whne a Smoke method gets called. */
+/** Invoked when a Smoke method gets called. */
hunk ./src/smoke-c/csmokebinding.cpp 63
- return dispatch(this, method, object, stack, abstract);
+ int ret = dispatch(this, method, object, stack, abstract);
+ Q_ASSERT( !abstract || ret );
+
+ return ret;
hunk ./src/smoke-c/smoke-c.cpp 6
-#include <stdexcept>
hunk ./src/smoke-c/smoke-c.cpp 325
- }
- catch (std::exception& e)
+ } [_$_]
+ // This catch is mostly useless:
+ // Qt / KDElibs do not use exceptions and since they are often built with -fno-exceptions
+ // the catch will have no effect and the terminate handler is called instead.
+ catch (const std::exception& e) [_$_]
hunk ./src/smoke-c/smoke-c.cpp 332
- return;
hunk ./src/smoke-c/smoke-c.lisp 61
-
Mon Jun 1 00:22:05 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* fix define-takes-ownership return value
hunk ./src/smoke.lisp 192
- `(defmethod ,method ,lambda-list
- (cancel-finalization ,object)
- (remove-object ,object)))
+ `(defmethod ,method :before ,lambda-list
+ (disown-object ,object)))
Sun May 31 19:41:26 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Ownership for return values on the stack
hunk ./src/clos.lisp 124
-(defclass smoke-wrapper-class (smoke-standard-class)
+(defclass cxx:class (smoke-standard-class)
hunk ./src/clos.lisp 126
- :type symbol)))
+ :type symbol))
+ (:documentation "Metaclass to extend Smoke Objects."))
hunk ./src/clos.lisp 129
-(defmethod smoke ((class smoke-wrapper-class))
+(defmethod smoke ((class cxx:class))
hunk ./src/clos.lisp 132
-(defclass cxx:class (smoke-wrapper-class)
- ()
- (:documentation "Metaclass to extend Smoke Objects."))
-
hunk ./src/clos.lisp 136
-(defmethod closer-mop:validate-superclass ((class smoke-wrapper-class) (superclass smoke-standard-class))
+(defmethod closer-mop:validate-superclass ((class cxx:class) (superclass smoke-standard-class))
hunk ./src/clos.lisp 159
- ((class smoke-wrapper-class)
+ ((class cxx:class)
hunk ./src/clos.lisp 176
- ((class smoke-wrapper-class)
+ ((class cxx:class)
hunk ./src/clos.lisp 259
+ (remove-wrapper-object object)
hunk ./src/clos.lisp 276
+ "Returns ARGUMENT converted to TYPE. If USER is true, user defined
+conversion sequences are considered."
hunk ./src/clos.lisp 296
- (cancel-finalization converted-value) [_$_]
- (when (and (class-p type)
- (not (virtual-destructor-p (get-class type))))
- (if (pointerp converted-value)
- (remove-object converted-value)
- (progn
- (cancel-finalization value)
- (remove-object (pointer value))))))))))
+ (cancel-finalization converted-value)
+ (disown-object value))))))
hunk ./src/clos.lisp 400
+
+(defvar *cxx-wrapper-objects* (make-synchronized-hash-table))
+
+(defun keep-wrapper (object)
+ (assert (not (gethash object *cxx-wrapper-objects*)))
+ (setf (gethash object *cxx-wrapper-objects*) object))
+
+(defun remove-wrapper-object (object)
+ (remhash object *cxx-wrapper-objects*))
+
+(defun disown-object (object)
+ "Transfers the ownership of OBJECT to C++."
+ (cancel-finalization object)
+ (if (typep (class-of object) 'cxx:class)
+ (progn
+ (assert (virtual-destructor-p (class-of object))
+ ()
+ "The ownership of the object ~A is transfered to C++, but
+it has a nonvirtual destructor." object)
+ (keep-wrapper object))
+ (when (and (typep object 'smoke-standard-object)
+ (not (virtual-destructor-p (class-of object))))
+ (remove-object (pointer object)))))
+ [_$_]
+
+
+(defun take-ownership (object)
+ "Assigns the ownership of OBJECT to Lisp. i.e.:
+cl-smoke is responsible for deleting the object."
+ (remove-wrapper-object object)
+ (let ((finalizer (make-finalize object)))
+ (finalize object finalizer)))
+
+;(eval-when (:load-toplevel)
+; (trace disown-object
+; keep-wrapper
+; remove-wrapper-object [_$_]
+;take-ownership
+;put-returnvalue
+;))
hunk ./src/object-map.lisp 4
-(defun make-weak-synchronized-hash-table (&key weakness)
- (make-weak-hash-table :weakness weakness :synchronized t))
+(defun make-synchronized-hash-table (&key weakness)
+ (if weakness
+ (make-weak-hash-table :weakness weakness :synchronized t)
+ (make-weak-hash-table :synchronized t)))
hunk ./src/object-map.lisp 12
- (defun make-weak-synchronized-hash-table (&key weakness)
- (make-weak-hash-table :weakness weakness)))
+ (defun make-synchronized-hash-table (&key weakness)
+ (if weakness
+ (make-weak-hash-table :weakness weakness)
+ (make-weak-hash-table))))
hunk ./src/object-map.lisp 19
-(cerror "Use unsynchronized hash-table"
- "Synchronized hash table not implemented.")
-(defun make-weak-synchronized-hash-table (&key weakness)
- #-cmucl (make-weak-hash-table :weakness weakness)
- #+cmucl (make-hash-table :weak-p weakness)
- ))
+ (cerror "Use unsynchronized hash-table"
+ "Synchronized hash table not implemented.")
+ (defun make-synchronized-hash-table (&key weakness)
+ (if weakness
+ #-cmucl (make-weak-hash-table :weakness weakness)
+ #+cmucl (make-hash-table :weak-p weakness)
+ (make-hash-table))))
hunk ./src/object-map.lisp 28
-(defvar *object-map* (make-weak-synchronized-hash-table :weakness :value))
+(defvar *object-map* (make-synchronized-hash-table :weakness :value)
+ "Contains all objects constructed by Smoke, that are not yet destructed;
+except object with a non virtual destuctor which had their ownership transfered
+to C++.")
hunk ./src/object-map.lisp 55
+(defun report-finalize-error (condition function object pointer)
+ (warn "error calling finalizer ~A for ~A ~A:~%~5T~A"
+ function object pointer condition))
hunk ./src/object-map.lisp 67
- (condition (condition)
- (format *debug-io* "error finalize ~A ~A~%" (name class)
- condition))))))
- [_$_]
-
-(defun take-ownership (object)
- "Assigns the ownership of OBJECT to Lisp. i.e.:
-cl-smoke is responsible for deleting the object."
- (let ((finalizer (make-finalize object)))
- (finalize object finalizer)))
+ (error (condition)
+ (report-finalize-error condition 't (name class) pointer))))))
hunk ./src/overload-resolution.lisp 484
+ (assert (valid-p method)
+ ()
+ "No applicable method ~A() for ~A." name object-or-class)
hunk ./src/smoke.lisp 196
-
Sat May 30 14:12:25 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* soversion for wrappers
hunk ./src/smoke-c/CMakeLists.txt 13
+set_target_properties(smoke-c
+ PROPERTIES
+ SOVERSION "0.0"
+ VERSION "0.0.1")
hunk ./src/smoke-c/CMakeLists.txt 19
+set_target_properties(smoke-c-util
+ PROPERTIES
+ SOVERSION "0.0"
+ VERSION "0.0.1")
Thu May 28 15:43:36 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix CCL and allow ASDF
hunk ./src/class-map.lisp 28
- (declare (smoke-class smoke-class))
hunk ./src/objects/enum.lisp 13
- :type (integer 0)
+ :type integer
hunk ./src/objects/object.lisp 8
- :type foreign-pointer
hunk ./src/package.lisp 37
+ #:define-takes-ownership
hunk ./src/smoke-c/smoke-c.lisp 8
+ #-mudballs
+ (define-foreign-library libsmoke-c
+ (:unix "libsmoke-c.so")
+ (t (:default "libsmoke-c")))
+ #-mudballs
+ (define-foreign-library libsmoke-c-util
+ (:unix "libsmoke-c-util.so")
+ (t (:default "libsmoke-c-util")))
hunk ./src/smoke.lisp 190
+(defmacro define-takes-ownership (method lambda-list object)
+ "Declares METHOD transfers the ownership of OBJECT to C++."
+ `(defmethod ,method ,lambda-list
+ (cancel-finalization ,object)
+ (remove-object ,object)))
+
+
Wed May 27 19:47:28 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Condition NO-APPLICABLE-CXX-METHOD
hunk ./src/objects/stack.lisp 81
+ ;; FIXME warn but not on void**
hunk ./src/overload-resolution.lisp 458
+
+(defun format-no-applicable-cxx-method (stream name class arguments)
+ (format stream
+ "No applicable method ~S of ~A for ~S.
+Candidtes are:~{~T~%~}."
+ name class arguments
+ (mapcar #'signature
+ (viable-functions name
+ (length arguments)
+ (smoke-class-of class)))))
+
+(define-condition no-applicable-cxx-method (error)
+ ((method :initarg :method :reader condition-method)
+ (class :initarg :class :reader condition-class)
+ (arguments :initarg :arguments :reader condition-arguments))
+ (:report (lambda (condition stream)
+ (format-no-applicable-cxx-method stream
+ (condition-method condition)
+ (condition-class condition)
+ (condition-arguments condition)))))
hunk ./src/overload-resolution.lisp 492
- (error "No applicable method ~S of ~A for ~S.
-Candidates are:~{~T~A~%~}."
- name object-or-class arguments
- (mapcar #'signature
- (viable-functions name
- (length arguments)
- (smoke-class-of object-or-class)))))
+ (error (make-condition 'no-applicable-cxx-method
+ :method name
+ :class object-or-class
+ :arguments arguments)))
Wed May 27 19:22:08 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix error when printing a SMOKE-OBJECT with an unbound pointer slot.
hunk ./src/clos.lisp 115
- (print-unreadable-object (object stream :type t)
- (princ (pointer object) stream)))
+ (if (slot-boundp object 'pointer)
+ (print-unreadable-object (object stream :type t)
+ (princ (pointer object) stream))
+ (call-next-method)))
Wed May 27 14:20:30 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix some warnings
hunk ./smoke.mbd 48
- (:components "object" "enum" "method" "class"
- "type" "instance" "stack"))
+ (:components "object" "enum" "type" "method" "class"
+ "instance" "stack"))
hunk ./src/class-map.lisp 28
- (declare (smoke-class smoke-class)
- (smoke-standard-class class))
+ (declare (smoke-class smoke-class))
hunk ./src/objects/method.lisp 134
-(defgeneric get-flag (object flag)
- (:documentation "Returns the value for FLAG of OBJECT."))
-
hunk ./src/objects/stack.lisp 14
+(defgeneric size (object))
hunk ./src/objects/type.lisp 39
+(defgeneric get-flag (object flag)
+ (:documentation "Returns the value for FLAG of OBJECT."))
+
hunk ./src/objects/type.lisp 63
-(defmethod const-p ((type smoke-type))
- "Returns T when TYPE is const; NIL otherwise."
- (/= 0 (get-flag type :const)))
+(defgeneric const-p (object)
+ (:method ((type smoke-type))
+ "Returns T when TYPE is const; NIL otherwise."
+ (/= 0 (get-flag type :const))))
hunk ./src/overload-resolution.lisp 443
- (multiple-value-bind (method sequence)
- (call-using-types find-best-viable-function2
- (if (using-typep)
- #'standard-conversion-sequence-using-types
- #'standard-conversion-sequence)
- (format nil "~A" (name (get-class type)))
- (list object) to-class)
- (when method
+ (when (call-using-types find-best-viable-function2
+ (if (using-typep)
+ #'standard-conversion-sequence-using-types
+ #'standard-conversion-sequence)
+ (format nil "~A" (name (get-class type)))
+ (list object) to-class)
hunk ./src/overload-resolution.lisp 450
- 'coerce-to-class
- to-class))))))
+ 'coerce-to-class
+ to-class)))))
hunk ./src/smoke.lisp 92
- (let ((method-name (concatenate 'string "~" (name object))))
+ (let ((method-name (concatenate 'string "~" (name (class-of object)))))
hunk ./src/smoke.lisp 94
- (make-smoke-method object method-name)
+ (make-smoke-method (class-of object) method-name)
hunk ./src/translate.lisp 25
+ (declare (ignore smoke-class))
Tue May 26 11:54:47 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Cleanup Lisp -> C++ conversion
hunk ./src/clos.lisp 3
-(declaim (optimize (speed 0) (debug 3)))
-
hunk ./src/clos.lisp 275
-(defgeneric set-returnvalue (stack value type))
-(defmethod set-returnvalue (stack (value smoke-standard-object) type)
- (assert (class-p type)
- (type)
- "The type ~A of the value ~A is not a class."
- (name type) value)
- (setf (foreign-slot-value stack 'smoke-stack-item 'class)
- (cast value (find-smoke-class (get-class type))))
- ;(pointer value))
- (when (stack-p type) ;; Pass by value => smoke deletes the object.
- (cancel-finalization value) [_$_]
- (unless (virtual-destructor-p (class-of value))
- (remove-object (pointer value))))) ;; Fixme mark object as invalid or copy it
-
-
-(defmethod set-returnvalue (stack (value integer) type)
- (setf (foreign-slot-value stack 'smoke-stack-item 'int)
- value))
-
-(defmethod set-returnvalue (stack (value (eql t)) type)
- (setf (foreign-slot-value stack 'smoke-stack-item 'bool)
- value))
+(defun convert-argument (argument type &optional (user t))
+ (let ((rank (get-conversion-sequence argument type user)))
+ (if (null rank)
+ (error "Can not convert the argument ~S to ~A."
+ argument (name type))
+ (funcall (conversion-function-name rank)
+ argument))))
hunk ./src/clos.lisp 285
- (set-returnvalue stack value type)))
+ (let ((stack (make-call-stack stack)))
+ (setf (top stack) (pointer stack))
+ ;; FIXME support user conversions.
+ ;; We need to determine which of value and converted-value is
+ ;; passed on the stack. E.g. converted-value can be something like
+ ;; (cxx:operator-variant value).
+ (let ((converted-value (convert-argument value type nil)))
+ (push-smoke-stack stack converted-value (type-id type))
+ (when (stack-p type) ;; Pass by value => smoke deletes the object.
+ (cancel-finalization converted-value) [_$_]
+ (when (and (class-p type)
+ (not (virtual-destructor-p (get-class type))))
+ (if (pointerp converted-value)
+ (remove-object converted-value)
+ (progn
+ (cancel-finalization value)
+ (remove-object (pointer value))))))))))
hunk ./src/clos.lisp 309
- ((binding :pointer)
- (method smoke-index)
- (object :pointer)
- (stack smoke-stack)
- (abstract :boolean))
+ ((binding :pointer)
+ (method smoke-index)
+ (object :pointer)
+ (stack smoke-stack)
+ (abstract :boolean))
hunk ./src/clos.lisp 327
- (put-returnvalue stack
- (apply gf object
- (stack-to-args (cffi:inc-pointer stack (cffi:foreign-type-size 'smoke-stack-item))
- (get-first-argument method)))
- (return-type method))
+ (put-returnvalue
+ stack
+ (apply gf object
+ (stack-to-args
+ (cffi:inc-pointer stack [_$_]
+ (cffi:foreign-type-size
+ 'smoke-stack-item))
+ (get-first-argument method)))
+ (return-type method))
hunk ./src/objects/class.lisp 19
-(defmethod get-struct-slot-value ((class smoke-class) slot-name)
+(declaim (inline class-slot-value))
+(defun class-slot-value (class slot-name)
hunk ./src/objects/class.lisp 25
- (get-struct-slot-value class 'name))
+ (class-slot-value class 'name))
hunk ./src/objects/class.lisp 41
- (get-struct-slot-value class 'external))
+ (class-slot-value class 'external))
hunk ./src/objects/class.lisp 44
- (boole boole-and (get-struct-slot-value class 'flags)
+ (boole boole-and (class-slot-value class 'flags)
hunk ./src/objects/class.lisp 109
- (smoke-add-superclass class nil (get-struct-slot-value class 'parents)))
+ (smoke-add-superclass class nil (class-slot-value class 'parents)))
hunk ./src/objects/enum.lisp 13
+ :type (integer 0)
hunk ./src/objects/method.lisp 2
-(declaim (optimize (debug 3)))
hunk ./src/objects/method.lisp 92
+(declaim (inline method-slot-value))
hunk ./src/objects/object.lisp 5
+ :type smoke-index
hunk ./src/objects/object.lisp 8
+ :type foreign-pointer
hunk ./src/objects/stack.lisp 3
-(declaim (optimize (debug 3)))
hunk ./src/objects/stack.lisp 6
+ :type foreign-pointer
hunk ./src/objects/stack.lisp 10
- :documentation "Pointer to push the next argument to.")
- (cleanup-stack :accessor cleanup-stack
- :initform nil
- :documentation "Cleanup functions"))
+ :type foreign-pointer
+ :documentation "Pointer to push the next argument to."))
hunk ./src/objects/stack.lisp 31
-(defun push-cleanup (stack function)
- "Adds the cleanup function FUNCTION to STACK"
- (push function (cleanup-stack stack)))
-
-(defun push-stack2 (stack value type-id)
+(defun push-smoke-stack (stack value type-id)
hunk ./src/objects/stack.lisp 46
- (13 (push-stack stack value 'class))))
-
-(defun push-smoke-stack (stack lisp-value smoke-type)
- (typecase smoke-type
- (smoke-type
- (cond
- ((cffi:pointerp lisp-value)
- (push-stack2 stack lisp-value (type-id smoke-type)))
- ((class-p smoke-type)
- (push-stack2 stack
- (convert-to-class (get-class smoke-type) lisp-value)
- (type-id smoke-type)))
-; ((pointer-p smoke-type)
- (t
- (let ((cffi-type (get-type (name smoke-type))))
- (if (null cffi-type)
- (progn
- ; (assert (typep lisp-value 'foreign-pointer)
- ; (lisp-value)
- ; "The lisp-value ~S is not a foreign-pointer."
- ; lisp-value)
- (push-stack2 stack
- lisp-value
- (type-id smoke-type)))
- (multiple-value-bind (pointer args) (convert-to-foreign lisp-value
- cffi-type)
- (push-cleanup stack
- #'(lambda ()
- (free-converted-object pointer
- cffi-type
- args)))
- (push-stack2 stack
- pointer
- (type-id smoke-type))))))))
-; (t (push-stack2 stack lisp-value (type-id smoke-type)))))
- (t (push-lisp-object stack lisp-value smoke-type))))
-
-(defgeneric push-lisp-object (stack object class)
- (:documentation "Push the OBJECT on STACK."))
+ (13 (if (typep value 'smoke-standard-object)
+ ;; FIXME call pointer in overload resolution
+ (push-stack stack (pointer value) 'class)
+ (push-stack stack value 'class)))))
hunk ./src/objects/stack.lisp 61
- (push-smoke-stack stack (first args) (first arguments))
- (set-smoke-stack stack (rest args) (rest arguments))))
+ (if (typep (first arguments) 'smoke-type)
+ (push-smoke-stack stack (first args) (type-id (first arguments)))
+ (push-stack stack (first args) 'class)) ;; Used for :qt lisp-object
+ (set-smoke-stack stack (rest args) (rest arguments))))
hunk ./src/objects/stack.lisp 70
- (unwind-protect
- (progn
hunk ./src/objects/stack.lisp 72
- ,@body)
- (mapcar #'funcall (cleanup-stack ,stack)))))))
+ ,@body))))
hunk ./src/objects/stack.lisp 137
-
- [_$_]
hunk ./src/objects/type.lisp 16
+(declaim (inline type-slot-value))
hunk ./src/objects/type.lisp 76
- (null (name type)))
+ ;; void is an empty string.
+ ;; For efficency just check if the first byte is a null byte;
+ ;; No need to convert the entire C string to lisp like in:
+ ;; (null (name type)))
+ (= 0 (mem-ref (smoke-get-type (smoke type) (id type))
+ :char)))
+ [_$_]
hunk ./src/overload-resolution.lisp 5
-(declaim (optimize (debug 3)))
hunk ./src/overload-resolution.lisp 124
+ :type fixnum
hunk ./src/overload-resolution.lisp 130
+ :type fixnum
hunk ./src/overload-resolution.lisp 136
+ :type fixnum
hunk ./src/overload-resolution.lisp 142
+ :type fixnum
hunk ./src/overload-resolution.lisp 152
+ :type fixnum
hunk ./src/overload-resolution.lisp 158
+ :type fixnum
hunk ./src/overload-resolution.lisp 334
- (13 (and (object.typep (find-class 'smoke-standard-object))
- (smoke-type= type (object.type-of))))))
+ (13 (and (object.typep 'smoke-standard-object)
+ (smoke-type= (get-class type) (object.type-of))))))
hunk ./src/overload-resolution.lisp 339
- "Returns a pointer that calls CLEANUP-FUNCTION when it is finalized."
+ "Returns a pointer that calls CLEANUP-FUNCTION with pointer as argument
+when it is finalized."
hunk ./src/overload-resolution.lisp 348
- (let ((address (pointer-address pointer)))
- (tg:finalize pointer #'(lambda ()
- (foreign-free (make-pointer address))))))
+ (make-cleanup-pointer pointer #'foreign-free))
hunk ./src/overload-resolution.lisp 367
+(declaim (inline coerce-to-class))
hunk ./src/overload-resolution.lisp 435
+(declaim (inline coerce-to-class))
hunk ./src/overload-resolution.lisp 462
+ (declare (optimize (speed 3)))
Mon May 25 20:39:33 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* speed up get-struct-slot-value & cleanup
hunk ./src/clos.lisp 361
-(defun make-smoke-constructor (class args)
- (find-method-using-args class
- (name class)
- args))
-
hunk ./src/marshall.lisp 1
-(in-package :smoke)
-
-(declaim (optimize (debug 3)))
-
-(defmacro average (&rest args)
- `(floor (+ ,@args) ,(length args)))
- [_$_]
-
-(defun binary-find (lower upper < =)
- (let ((mid (average lower upper)))
- (if (= mid lower)
- nil
- (if (funcall = mid)
- mid
- (if (funcall < mid)
- (binary-find lower mid < =)
- (binary-find mid upper < =))))))
-
-(defun serach-method (smoke name)
- (binary-find 1 (smoke-method-name-size smoke)
- #'(lambda (index)
- (string< name
- (smoke-get-method-name smoke index)))
- #'(lambda (index)
- (string= name
- (smoke-get-method-name smoke index)))))
-
-(defun find-last (lower upper =)
- (if (or (>= lower upper)
- (not (funcall = (1+ lower))))
- lower
- (find-last (1+ lower) upper =)))
- [_$_]
- [_$_]
-(defun find-methods (smoke name)
- (let* ((index (serach-method smoke name))
- (= #'(lambda (index)
- (string= name
- (smoke-get-method-name smoke index)
- :end2 (length name))))
- (upper (find-last index (smoke-method-name-size smoke) =))
- (methods nil))
- (loop for i from index to upper do
- (push (smoke-get-method-name smoke i)
- methods))
- methods))
- [_$_]
- [_$_]
-
-;(defmethod exact-match ((object singl-float) type))
-(defun type-equal (type type-name)
- (equal (name type) type-name))
-
-(defun exact-match (object type)
- (format t "~A ~A~%" object (name type))
- (ctypecase object [_$_]
- (smoke-standard-object
- (and (class-p type)
- (derived-p (class-of object)
- (get-class type))))
- (double-float (type-equal type "double"))
- (single-float (type-equal type "float"))
- (integer (type-equal type "int"))
- (string (or (type-equal type "const char*")
- (type-equal type "const QString&")))
- (character (type-equal type "char"))))
-
-(defun exact-match-p (arguments types)
- (if (or (null arguments) (null types))
- (and (null arguments)
- (null types))
- (if (not (exact-match (first arguments)
- (first types)))
- nil
- (exact-match-p (rest arguments)
- (rest types)))))
- [_$_]
-(defun promotion-match (object type)
- (ctypecase object
- (character (type-equal type "int"))
- (float (type-equal type "double"))
- (boolean (type-equal type "int"))))
-
-(defun standard-conversion-match (object type)
- (ctypecase object
- (number (or (type-equal type "short")
- (type-equal type "int")
- (type-equal type "long")))))
-
-(defun constructor-match (object type)
- (if (class-p type)
- (let ((constructor (make-smoke-constructor (get-class type)
- (mung-arg object))))
- (exact-match object (get-first-argument constructor)))
- nil))
- [_$_]
-(defun find-ambiguous-method (predicate method)
- (let ((index (- (id method))))
- (loop as i = (smoke-ambiguous-method (smoke method)
- index)
- while (> i 0) do
- (incf index)
- (let ((ambiguous-method (make-instance 'smoke-method
- :smoke (smoke method)
- :id i)))
- (when (funcall predicate ambiguous-method)
- (return ambiguous-method))))))
-
-(defun find-method-using-args (class name arguments)
- (with-foreign-object (m 'smoke-module-index)
- (smoke-find-method m (smoke class) (id class)
- (concatenate 'string name
- (munged-args arguments)))
- (let ((method (make-instance 'smoke-method
- :smoke (foreign-slot-value m
- 'smoke-module-index
- 'smoke)
- :id (foreign-slot-value m
- 'smoke-module-index
- 'index))))
- (when (< (id method) 0)
- (setf method
- (find-ambiguous-method #'(lambda (method)
- (exact-match-p arguments (arguments method)))
- method))
- (assert (not (null method)) (method)
- "No method ~A::~A for the arguments ~A"
- (name class) name arguments))
- method)))
-
-
-(defgeneric get-convert-function (to from))
-(defmethod get-convert-function ((to eql 'int) (from eql 'char)))
-(defmethod get-convert-function ((to cxx::int) (from string)))
-
-(get-convert-function 'int 'char)
-
-;'const int 'char:
-(get-convert-function 'int 'char)
-&& (convert-const-p 'char)
-
-;'int 'const char:
-(get-convert-function 'int 'char)
-&& (not (const-p 'char))
-
-
-(defclass int ()
- ((const-p)))
-
-(defun get-convert-function (to from))
-
- [_$_]
rmfile ./src/marshall.lisp
hunk ./src/objects/method.lisp 79
-(defun type-equal (type type-name)
- "Returns true when TYPE is of the type named TYPE-NAME and false otherwise."
- (equal (name type) type-name))
-
-(defun exact-match (object type)
- "Returns true when the type of OBJECT is exactly the same as TYPE and
-false otherwise."
- (ctypecase object [_$_]
- (smoke-standard-object
- (and (class-p type)
- (derived-p (class-of object)
- (get-class type))))
- (double-float (type-equal type "double"))
- (single-float (type-equal type "float"))
- (integer (type-equal type "int"))
- ;; int is also enum
- ;; FIXME remove magic number 12
- ;;(= (type-id type) 12)))
- (string (or (type-equal type "const char*")
- (type-equal type "const QString&")))
- (enum (smoke-type= (enum-type object)
- type))
- (sequence (type-equal type "const QStringList&"))
- (character (type-equal type "char"))))
-
-(defun exact-match-p (arguments types)
- "Returns true when all the type of ARGUMENTS is the same as the
-corresponing type of TYPES and the length of the ARGUMENTS and TYPES list
-is equal."
- (if (or (null arguments) (null types))
- (and (null arguments)
- (null types))
- (if (not (exact-match (first arguments)
- (first types)))
- nil
- (exact-match-p (rest arguments)
- (rest types)))))
-
-(defun mung-arg (argument)
- "Returns the mung char for ARUGMENT."
- ;; FIXME void* is #\$ but void[] is #\?
- ;; FIXME Get rid of the mugging stuff and compute the applicable methods
- ;; including argument promotion
- (case argument
- ((t nil) #\$) ;; Booleans
- (otherwise
- (ctypecase argument
- (number #\$)
- (character #\$)
- (string #\$)
- (foreign-pointer #\?)
- (sequence #\?)
- (enum #\$)
- (smoke-standard-object #\#)))))
-
-(defun munged-args (arguments &optional (string nil))
- "Maps the type of every item of ARGUMENTS to a char;
-Returns the list of the chars."
- (if (null arguments)
- string
- (munged-args (rest arguments)
- (append string (list (mung-arg (first arguments)))))))
-
-(defun find-ambiguous-method (predicate method)
- "Returns a method of the ambiguous method METHOD such that
-PREDICATE is true. NIL is returned when no matching method is found."
- (assert (ambiguous-p method)
- (method)
- "The method is not ambiguous.")
- (let ((index (- (id method))))
- (loop as i = (smoke-ambiguous-method (smoke method)
- index)
- while (> i 0) do
- (incf index)
- (let ((ambiguous-method (make-instance 'smoke-method
- :smoke (smoke method)
- :id i)))
- (when (funcall predicate ambiguous-method)
- (return ambiguous-method))))))
-
-(defun find-method-using-args (class name arguments)
- "Returns the method of class CLASS with the name NAME
-for the arguments ARGUMENTS."
- (with-foreign-object (m 'smoke-module-index)
- (smoke-find-method m (smoke class) (id class)
- (concatenate 'string name
- (munged-args arguments)))
- (let ((method (make-instance 'smoke-method
- :smoke (foreign-slot-value m
- 'smoke-module-index
- 'smoke)
- :id (foreign-slot-value m
- 'smoke-module-index
- 'index))))
- (assert (valid-p method)
- (method)
- "No method ~A::~A for the arguments ~A" (name class) name arguments)
- (when (ambiguous-p method)
- (setf method
- (find-ambiguous-method #'(lambda (method)
- (exact-match-p arguments (arguments method)))
- method))
- (assert (not (null method)) (method)
- "No method ~A::~A for the arguments ~A"
- (name class) name arguments))
- method)))
-
-
hunk ./src/objects/method.lisp 93
-(defmethod get-struct-slot-value ((method smoke-method) slot-name)
+(defun method-slot-value (method slot-name)
+ (declare (smoke-method method)
+ (symbol slot-name)
+ (optimize (speed 3)))
hunk ./src/objects/method.lisp 102
- (get-struct-slot-value method 'name)))
+ (method-slot-value method 'name)))
hunk ./src/objects/method.lisp 124
- :id (get-struct-slot-value method 'return-type)
+ :id (method-slot-value method 'return-type)
hunk ./src/objects/method.lisp 138
- (logand (get-struct-slot-value method 'flags)
+ (logand (method-slot-value method 'flags)
hunk ./src/objects/method.lisp 177
- :id (get-struct-slot-value method 'class)
+ :id (method-slot-value method 'class)
hunk ./src/objects/method.lisp 208
- (get-struct-slot-value method 'num-args))
+ (method-slot-value method 'num-args))
hunk ./src/objects/method.lisp 213
- :id (get-struct-slot-value method 'arguments)
+ :id (method-slot-value method 'arguments)
hunk ./src/objects/method.lisp 219
- :id (+ (get-struct-slot-value method 'arguments) index)
+ :id (+ (method-slot-value method 'arguments) index)
hunk ./src/objects/type.lisp 16
-(defmethod get-struct-slot-value ((type smoke-type) slot-name)
+(defun type-slot-value (type slot-name)
+ (declare (smoke-type type)
+ (symbol slot-name)
+ (optimize (speed 3)))
hunk ./src/objects/type.lisp 30
- (get-struct-slot-value type 'name))
+ (type-slot-value type 'name))
hunk ./src/objects/type.lisp 39
- (logand (get-struct-slot-value type 'flags)
+ (logand (type-slot-value type 'flags)
hunk ./src/objects/type.lisp 44
- (logand (get-struct-slot-value type 'flags)
+ (logand (type-slot-value type 'flags)
hunk ./src/objects/type.lisp 66
- (/= -1 (get-struct-slot-value type 'class))))
+ (/= -1 (type-slot-value type 'class))))
hunk ./src/objects/type.lisp 70
- (logand (get-struct-slot-value type 'flags)
+ (logand (type-slot-value type 'flags)
hunk ./src/objects/type.lisp 82
- (assert (/= -1 (get-struct-slot-value type 'class))
+ (assert (/= -1 (type-slot-value type 'class))
hunk ./src/objects/type.lisp 86
- :id (get-struct-slot-value type 'class)
+ :id (type-slot-value type 'class)
Sun May 24 23:28:44 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Allow passing a raw pointer for an argument of type class
hunk ./src/overload-resolution.lisp 389
- (when (and (= 0 (type-id type))
+ ;; Not using pointer-p to allow passing a raw pointer for
+ ;; objects on the stack and references
+ ;; (e.g.: for qInstallMsgHandler(QtMsgHandler) )
+ ;;
+ ;; FIXME this breaks passing pointers to references
+ ;; e.g.: calling the function foo(QByteArray& foo)
+ ;; with (foo pointer) assumes pointer to point to a QByteArray,
+ ;; but actually the conversion sequence QByteArray(pointer) should be used.
+ ;; When pointer is a null pointer it fails horribly!.
+ (when (and (or (= 0 (type-id type)) ; voidp
+ (= 13 (type-id type))) ; class
hunk ./src/overload-resolution.lisp 402
- :from (object.type-of)
- :to (find-class 't))))
+ :from (find-class 't)
+ :to (find-class 't)))) ;; FIXME get the class when applicable
Sun May 24 13:30:05 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* cleanup finalization stuff
hunk ./src/clos.lisp 113
- :documentation "Pointer to the C++ object.")
- (owned-p :accessor owned-p :initarg :owned-p
- :initform t
- :documentation "T when the object is owned by Lisp and
-NIL when C++ is the owner.")
- (const-p :reader const-p :initarg :const-p
- :initform nil
- :documentation "T when the object is const and NIL otherwise."))
+ :documentation "Pointer to the C++ object."))
hunk ./src/clos.lisp 121
- ((enumerations :initform (make-hash-table)
- :initarg :enumerations
- :reader enumerations
- :documentation "The enumerations of the class.
-Maps the type-id of the enumeration to a hash-table that
-maps an enum value to a symbol."))
+ ()
hunk ./src/clos.lisp 195
-(defun smoke-class-symbol (class)
- (if (external-p class)
- (class-name (find-smoke-class class))
- (lispify (name class))))
+(defun smoke-class-symbol (smoke-class)
+ "Returns the Lisp class-name of SMOKE-CLASS:"
+ (if (external-p smoke-class)
+ (class-name (find-smoke-class smoke-class))
+ (lispify (name smoke-class))))
hunk ./src/clos.lisp 284
- (pointer value))
+ (cast value (find-smoke-class (get-class type))))
+ ;(pointer value))
hunk ./src/clos.lisp 287
- (cancel-finalization value) ;; Fixme mark object as invalid or copy it
- ;(remove-object (pointer value))
- (remove-if-exists (pointer value));;FIXME!
- (setf (slot-value value 'pointer) (null-pointer))))
+ (cancel-finalization value) [_$_]
+ (unless (virtual-destructor-p (class-of value))
+ (remove-object (pointer value))))) ;; Fixme mark object as invalid or copy it
+
hunk ./src/clos.lisp 309
-;(eval-startup (:execute)
-; (memoize:memoize-function 'get-gf-for-method)
-; (memoize:clear-memoized-function 'get-gf-for-method))
-
hunk ./src/clos.lisp 395
- (setf (slot-value object 'owned-p) t)
+ (take-ownership object)
hunk ./src/clos.lisp 401
- :owned-p (stack-p type)
hunk ./src/clos.lisp 402
+ (when (stack-p type)
+ (take-ownership ret)
+ (add-object ret))
hunk ./src/object-map.lisp 61
+(defun take-ownership (object)
+ "Assigns the ownership of OBJECT to Lisp. i.e.:
+cl-smoke is responsible for deleting the object."
+ (let ((finalizer (make-finalize object)))
+ (finalize object finalizer)))
+ [_$_]
hunk ./src/object-map.lisp 68
+ "Adds OBJECT to the pointer -> object map. It can later be retrived
+with GET-OBJECT."
hunk ./src/object-map.lisp 74
- (when (owned-p object)
- (let ((finalizer (make-finalize object)))
- (finalize object finalizer)))
hunk ./src/objects/class.lisp 50
+(defun virtual-destructor-p (class)
+ "Returns T when CLASS has a virtual destructor and NIL otherwise."
+ (/= 0 (get-flag class :virtual-destructor)))
+
hunk ./src/objects/stack.lisp 164
- (object-to-lisp (foreign-slot-value stack-item
- 'smoke-stack-item
- 'class)
- type))
+ (let ((object (object-to-lisp (foreign-slot-value stack-item
+ 'smoke-stack-item
+ 'class)
+ type)))
+ object))
hunk ./src/objects/type.lisp 36
- (boole boole-and (get-struct-slot-value type 'flags)
- (foreign-enum-value 'smoke-type-flags flag)))
+ (logand (get-struct-slot-value type 'flags)
+ #xF0 ;; = ! 0x0F
+ (foreign-enum-value 'smoke-type-flags flag)))
+
+(defun get-allocation-flag (type)
+ (logand (get-struct-slot-value type 'flags)
+ #x30))
hunk ./src/objects/type.lisp 46
- (/= 0 (get-flag type :stack)))
+ (= (get-allocation-flag type) (get-flag type :stack)))
hunk ./src/objects/type.lisp 50
- (/= 0 (get-flag type :reference)))
+ (= (get-allocation-flag type) (get-flag type :reference)))
hunk ./src/objects/type.lisp 54
- (/= 0 (get-flag type :pointer)))
+ (= (get-allocation-flag type) (get-flag type :pointer)))
hunk ./src/objects/type.lisp 67
- (boole boole-and (get-struct-slot-value type 'flags)
- (foreign-enum-value 'smoke-type-flags :type-id)))
+ (logand (get-struct-slot-value type 'flags)
+ (foreign-enum-value 'smoke-type-flags :type-id)))
hunk ./src/smoke.lisp 81
+
Fri May 22 16:57:59 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Use synchronized object-map
hunk ./src/object-map.lisp 3
-(defvar *object-map* [_$_]
- #-cmucl (make-weak-hash-table :weakness :value)
- #+cmucl (make-hash-table :weak-p :value)
- [_$_]
- "Maps a lisp object to Smoke C++ object.")
+#+sbcl [_$_]
+(defun make-weak-synchronized-hash-table (&key weakness)
+ (make-weak-hash-table :weakness weakness :synchronized t))
hunk ./src/object-map.lisp 7
-;; FIXME This probably does not scale well. A per thread object-map
-;; or at least a read-write lock should be used.
-;; => use :synchronized of sbcl hash-table
-(defvar *object-map-mutex* (make-lock "object-map lock"))
hunk ./src/object-map.lisp 8
+#+openmcl
+(let ((ccl::*shared-hash-table-default* t))
+ (defun make-weak-synchronized-hash-table (&key weakness)
+ (make-weak-hash-table :weakness weakness)))
+
+#-(or sbcl openmcl)
+(progn
+(cerror "Use unsynchronized hash-table"
+ "Synchronized hash table not implemented.")
+(defun make-weak-synchronized-hash-table (&key weakness)
+ #-cmucl (make-weak-hash-table :weakness weakness)
+ #+cmucl (make-hash-table :weak-p weakness)
+ ))
+ [_$_]
+
+(defvar *object-map* (make-weak-synchronized-hash-table :weakness :value))
+
+(declaim (inline get-object))
hunk ./src/object-map.lisp 27
- (with-lock-held (*object-map-mutex*)
- (gethash (pointer-address pointer) *object-map*)))
+ (gethash (pointer-address pointer) *object-map*))
hunk ./src/object-map.lisp 29
+(declaim (inline (setf get-object)))
hunk ./src/object-map.lisp 31
- (with-lock-held (*object-map-mutex*)
- (setf (gethash (pointer-address pointer) *object-map*)
- value)))
- [_$_]
+ (setf (gethash (pointer-address pointer) *object-map*)
+ value))
hunk ./src/object-map.lisp 36
- (with-lock-held (*object-map-mutex*)
- (nth-value 1 (gethash (pointer-address pointer) *object-map*))))
+ (nth-value 1 (gethash (pointer-address pointer) *object-map*)))
+
+(defun remove-if-exists (pointer)
+ (remhash (pointer-address pointer) *object-map*))
+
+(defun remove-object (pointer)
+ (assert (has-pointer-p pointer)
+ (pointer)
+ "No object to remove for pointer ~A." pointer)
+ (remhash (pointer-address pointer) *object-map*))
hunk ./src/object-map.lisp 70
-
-(defun remove-if-exists (pointer)
- (with-lock-held (*object-map-mutex*)
- (remhash (pointer-address pointer) *object-map*)))
-
-(defun remove-object (pointer)
- (assert (has-pointer-p pointer)
- (pointer)
- "No object to remove for pointer ~A." pointer)
- (with-lock-held (*object-map-mutex*)
- (remhash (pointer-address pointer) *object-map*)))
-
-(defun print-garbage ()
- (with-lock-held (*object-map-mutex*)
- (maphash #'(lambda (pointer object)
- (format t "~A of type: ~S~%"
- (make-pointer pointer)
- (class-name (class-of object))))
- *object-map*)))
Tue May 19 15:59:22 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Clozure CL save image
hunk ./smoke.mbd 65
- (:components "get-value"
- ("image" (:for (:not :sbcl)))
- ("image-sbcl" (:for :sbcl)))))))
+ (:components
+ "get-value"
+ ("sbcl-bundle" (:for :sbcl))
+ (:image module
+ (:components [_$_]
+ ("image" (:needs "impl"))
+ (:impl module
+ (:components
+ ("sbcl" (:for :sbcl))
+ ("ccl" (:for :openmcl))
+ ("not-implemented" (:for (:not
+ (:or :sbcl :openmcl)))))))))))))
+ (:supports (:os :linux) (:implementation :sbcl :openmcl))
hunk ./smoke.mbd 79
- :alexandria
- :trivial-garbage :bordeaux-threads))
+ :alexandria :trivial-garbage :bordeaux-threads))
hunk ./src/clos.lisp 318
-;(memoize:memoize-function 'get-gf-for-method)
+
+;(eval-startup (:execute)
+; (memoize:memoize-function 'get-gf-for-method)
+; (memoize:clear-memoized-function 'get-gf-for-method))
adddir ./src/utils/image
hunk ./src/utils/image-sbcl.lisp 1
-(in-package :smoke)
-
-(eval-when (:compile-toplevel :load-toplevel :execute)
- (defvar *startup-functions* nil
- "Functions to run (in order) on startup.")
-
- (defun add-startup-function (function)
- (setf *startup-functions*
- (nconc *startup-functions* (list function))))
-
- (defun add-and-run-startup-function (function)
- (add-startup-function function)
- (funcall function))
-
- (defun run-startup-functions ()
- (mapcar #'funcall *startup-functions*)))
-
-(eval-when (:load-toplevel :execute)
- (push #'run-startup-functions sb-ext:*init-hooks*))
-
-(defmacro eval-startup ((&rest situations) &body body)
- "Runs BODY when it is loaded."
- `(eval-when (,@situations :load-toplevel)
- (add-and-run-startup-function #'(lambda ()
- (let ((*package* ,*package*))
- ,@body)))))
-
-(defun strip-foreign-libraries-path ()
- (dolist (library sb-alien::*shared-objects*)
- (setf (slot-value library 'namestring)
- (file-namestring (slot-value library 'pathname)))))
-
-(defun make-temporary-directory ()
- (pathname (concatenate 'string (sb-posix:mkdtemp "/tmp/cl-smokeXXXXXX")
- "/")))
-
-(defmacro with-temporary-directory ((directory) &body body)
- "Binds DIRECTORY to the pathname of a temporary directory and executes body:"
- `(let ((,directory (make-temporary-directory)))
- (unwind-protect (progn ,@body)
- (unless (zerop
- (sb-ext:process-exit-code
- (sb-ext:run-program "/bin/rm"
- (list "-r" (namestring ,directory)))))
- (cerror "ignore"
- "could not remove temponary directory ~A"
- ,directory)))))
- [_$_]
-(defun save-image (file-name &rest options &key &allow-other-keys)
- "Save the lisp image in FILE-NAME."
- (let ((pid (sb-posix:fork)))
- (if (= 0 pid)
- (progn
- (strip-foreign-libraries-path)
- (apply #'sb-ext:save-lisp-and-die file-name :executable t
- options))
- (sb-posix:waitpid pid 0))))
-
-(defun write-shell-wrapper (pathname core-name)
- (with-open-file (stream pathname :direction :output)
- (format stream "#!/bin/sh
-cd `dirname \"$0\"`
-LD_LIBRARY_PATH=./ exec -a \"$0\" ./~A $@
-" core-name))
- (sb-posix:chmod pathname #o0755))
-
-(defun make-tarball (run-directory tarball-pathname &rest pathnames)
- (flet ((arguments (&rest args)
- (format nil "~{~A ~}" args)))
- (unless (zerop
- (sb-ext:process-exit-code
- (sb-ext:run-program
- "/bin/sh"
- (list "-c"
- (apply #'arguments
- "cd " (namestring run-directory) " && "
- "tar -cvjf " (namestring tarball-pathname)
- " --strip 2 "
- (mapcar #'namestring pathnames))))))
- (error "Create tarball ~A failed." tarball-pathname))))
-
-(defun makeself (run-directory directory-name file-name label [_$_]
- &optional (startup-script "") &rest args)
- "Make self-extractable archives on Unix
-http://megastep.org/makeself/"
- ;; make an absolute pathname sine we change the directory.
- (let ((file-name (merge-pathnames file-name)))
- (flet ((arguments (&rest args)
- (format nil "~{~A ~}" args)))
- (unless (zerop
- (sb-ext:process-exit-code
- (sb-ext:run-program
- "/bin/sh"
- (list "-c"
- (apply #'arguments
- "cd " (namestring run-directory) " && "
- "makeself --nox11" (namestring directory-name)
- (namestring file-name) label
- startup-script args)))))
- (error "Create ~A failed." file-name)))))
-
-(defun save-bundle (file-name &optional extra-files &rest options &key &allow-other-keys)
- "Creates a FILE-NAME.tar.bz2 in the current directory.
-This bundle contains a dumped image, the wrapper libraries and a
-script to run in. OPTIONS is passed to SB-EXT:SAVE-LISP-AND-DIE."
- (with-temporary-directory (dir)
- (let ((bundle-dir (merge-pathnames (make-pathname :directory
- (list :relative file-name))
- dir)))
- (sb-posix:mkdir bundle-dir #o0755)
- (dolist (library sb-alien::*shared-objects*)
- (sb-ext:run-program
- "/bin/cp" (list (namestring (slot-value library 'pathname))
- (namestring bundle-dir))))
- (apply #'save-image (namestring (make-pathname :name "sbcl-core"
- :defaults bundle-dir))
- options)
- (write-shell-wrapper (make-pathname :defaults bundle-dir
- :name "run"
- :type "sh")
- "sbcl-core")
-;; (make-tarball dir (concatenate 'string file-name ".tar.bz2")
-;; file-name)
- (dolist (file extra-files)
- (copy-file file (merge-pathnames bundle-dir file)))
- (makeself dir bundle-dir file-name "sbcl-bundle"
- "./run.sh"))))
-;; (copy-file (make-pathname :defaults dir
-;; :name (concatenate 'string file-name ".tar")
-;; :type "bz2")
-; (concatenate 'string file-name ".tar.bz2")))))
rmfile ./src/utils/image-sbcl.lisp
hunk ./src/utils/image.lisp 1
-(in-package :smoke)
-
-(defmacro eval-startup ((&rest situations) &body body)
- "Runs BODY when it is loaded."
- `(eval-when (,@situations :load-toplevel)
- ,@body))
rmfile ./src/utils/image.lisp
addfile ./src/utils/image/image.lisp
hunk ./src/utils/image/image.lisp 1
+(in-package :smoke)
+
+(declaim (inline add-and-run-startup-function))
+(defun add-and-run-startup-function (function)
+ (add-startup-function function)
+ (funcall function))
+
+(defmacro eval-startup ((&rest situations) &body body)
+ "Runs BODY when it is loaded (when the source is loaded and also
+when the Lisp image is loaded)."
+ `(eval-when (,@situations :load-toplevel)
+ (add-and-run-startup-function #'(lambda ()
+ (let ((*package* ,*package*))
+ ,@body)))))
adddir ./src/utils/image/impl
addfile ./src/utils/image/impl/ccl.lisp
hunk ./src/utils/image/impl/ccl.lisp 1
+(in-package :smoke)
+
+(defun add-startup-function (function)
+ (push function ccl:*lisp-startup-functions*))
addfile ./src/utils/image/impl/sbcl.lisp
hunk ./src/utils/image/impl/sbcl.lisp 1
+(in-package :smoke)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defvar *startup-functions* nil
+ "Functions to run (in order) on startup.")
+(defun add-startup-function (function)
+ (setf *startup-functions*
+ (nconc *startup-functions* (list function))))
+(defun run-startup-functions ()
+ (mapcar #'funcall *startup-functions*)))
+
+(eval-when (:load-toplevel :execute)
+ (push #'run-startup-functions sb-ext:*init-hooks*))
addfile ./src/utils/sbcl-bundle.lisp
hunk ./src/utils/sbcl-bundle.lisp 1
+(in-package :smoke)
+
+(defun strip-foreign-libraries-path ()
+ (dolist (library sb-alien::*shared-objects*)
+ (setf (slot-value library 'namestring)
+ (file-namestring (slot-value library 'pathname)))))
+
+(defun make-temporary-directory ()
+ (pathname (concatenate 'string (sb-posix:mkdtemp "/tmp/cl-smokeXXXXXX")
+ "/")))
+
+(defmacro with-temporary-directory ((directory) &body body)
+ "Binds DIRECTORY to the pathname of a temporary directory and executes body:"
+ `(let ((,directory (make-temporary-directory)))
+ (unwind-protect (progn ,@body)
+ (unless (zerop
+ (sb-ext:process-exit-code
+ (sb-ext:run-program "/bin/rm"
+ (list "-r" (namestring ,directory)))))
+ (cerror "ignore"
+ "could not remove temponary directory ~A"
+ ,directory)))))
+ [_$_]
+(defun save-image (file-name &rest options &key &allow-other-keys)
+ "Save the lisp image in FILE-NAME."
+ (let ((pid (sb-posix:fork)))
+ (if (= 0 pid)
+ (progn
+ (strip-foreign-libraries-path)
+ (apply #'sb-ext:save-lisp-and-die file-name :executable t
+ options))
+ (sb-posix:waitpid pid 0))))
+
+(defun write-shell-wrapper (pathname core-name)
+ (with-open-file (stream pathname :direction :output)
+ (format stream "#!/bin/sh
+cd `dirname \"$0\"`
+LD_LIBRARY_PATH=./ exec -a \"$0\" ./~A $@
+" core-name))
+ (sb-posix:chmod pathname #o0755))
+
+(defun makeself (run-directory directory-name file-name label [_$_]
+ &optional (startup-script "") &rest args)
+ "Make self-extractable archives on Unix
+http://megastep.org/makeself/"
+ ;; make an absolute pathname sine we change the directory.
+ (let ((file-name (merge-pathnames file-name)))
+ (flet ((arguments (&rest args)
+ (format nil "~{~A ~}" args)))
+ (unless (zerop
+ (sb-ext:process-exit-code
+ (sb-ext:run-program
+ "/bin/sh"
+ (list "-c"
+ (apply #'arguments
+ "cd " (namestring run-directory) " && "
+ "makeself --nox11" (namestring directory-name)
+ (namestring file-name) label
+ startup-script args)))))
+ (error "Create ~A failed." file-name)))))
+
+(defun save-bundle (file-name &optional extra-files &rest options &key &allow-other-keys)
+ "Creates a FILE-NAME.tar.bz2 in the current directory.
+This bundle contains a dumped image, the wrapper libraries and a
+script to run in. OPTIONS is passed to SB-EXT:SAVE-LISP-AND-DIE."
+ (with-temporary-directory (dir)
+ (let ((bundle-dir (merge-pathnames (make-pathname :directory
+ (list :relative file-name))
+ dir)))
+ (sb-posix:mkdir bundle-dir #o0755)
+ (dolist (library sb-alien::*shared-objects*)
+ (sb-ext:run-program
+ "/bin/cp" (list (namestring (slot-value library 'pathname))
+ (namestring bundle-dir))))
+ (apply #'save-image (namestring (make-pathname :name "sbcl-core"
+ :defaults bundle-dir))
+ options)
+ (write-shell-wrapper (make-pathname :defaults bundle-dir
+ :name "run"
+ :type "sh")
+ "sbcl-core")
+ (dolist (file extra-files)
+ (copy-file file (merge-pathnames bundle-dir file)))
+ (makeself dir bundle-dir file-name "sbcl-bundle"
+ "./run.sh"))))
Tue May 19 13:09:12 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix loading with Clozure CL
hunk ./src/clos.lisp 14
+
hunk ./src/clos.lisp 314
+(defun get-gf-for-method (smoke-method)
+ (declare (smoke-method smoke-method)
+ (optimize (speed 3)))
+ (symbol-function (lispify (name smoke-method) "CXX")))
+;(memoize:memoize-function 'get-gf-for-method)
+
hunk ./src/clos.lisp 330
- (let ((gf (symbol-function (lispify (name method) "CXX"))))
+ (let ((gf (get-gf-for-method method)))
hunk ./src/cxx-method.lisp 3
-(defclass cxx-method-generic-function (standard-generic-function)
- ((generic-function :accessor cxx-generic-function
- :initarg :cxx-generic-function
- :type cxx-generic-function
- :documentation "Contains the generic function."))
- (:metaclass closer-mop:funcallable-standard-class)
- (:documentation "Generic function of a specify argument count."))
-
hunk ./src/cxx-method.lisp 12
+(defclass cxx-method-generic-function (standard-generic-function)
+ ((generic-function :accessor cxx-generic-function
+ :initarg :cxx-generic-function
+ :type cxx-generic-function
+ :documentation "Contains the generic function."))
+ (:metaclass closer-mop:funcallable-standard-class)
+ (:documentation "Generic function of a specify argument count."))
+
+
+
hunk ./src/method.lisp 55
-(defun generic-method-definition (name cxx-name)
- (values [_$_]
- `(ensure-generic-function (quote ,name)
- :cxx-name ,cxx-name
+(defun ensure-generic-methods (symbols-names)
+ "Ensures the generic functions for SYMBOLS-NAMES."
+ (declare (list symbols-names)
+ (optimize (speed 3)))
+ (dolist (symbol-name symbols-names)
+ (ensure-generic-function (first symbol-name)
+ :cxx-name (rest symbol-name)
hunk ./src/method.lisp 64
- name))
+ (export (first symbol-name) :cxx)))
+
hunk ./src/method.lisp 96
- (ensure-generics)
hunk ./src/method.lisp 98
- (cxx-exports)
hunk ./src/method.lisp 143
- (loop for name being the hash-key of generics
- for cxx-name being the hash-value of generics do
- (multiple-value-bind (definition export)
- (generic-method-definition name cxx-name)
- (push definition ensure-generics)
- (push export cxx-exports)))
hunk ./src/method.lisp 147
- (make-smoke-classes ,smoke))
- (eval-when (:load-toplevel :execute)
- ,@ensure-generics)
- (export (quote ,cxx-exports) :cxx)
+ (make-smoke-classes ,smoke)
+ (ensure-generic-methods ',(hash-table-alist generics)))
hunk ./src/method.lisp 150
- (export (quote ,exports)))))
+ (eval-when (:load-toplevel :execute)
+ (export (quote ,exports))))))
hunk ./src/overload-resolution.lisp 112
+(eval-when (:compile-toplevel :load-toplevel :execute)
hunk ./src/overload-resolution.lisp 115
-(defconstant +conversion+ 2)
+(defconstant +conversion+ 2))
hunk ./src/package.lisp 30
- #:define-methods
-
Thu May 14 14:07:00 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Dump Lisp image & make bundle with C wrapper libraries.
hunk ./smoke.mbd 34
- ("CMakeLists.txt" static-file)
hunk ./smoke.mbd 55
- ;; Make release-action add this files
- ("CMakeLists.txt" static-file)
- ("csmokebinding.h" static-file)
- ("csmokebinding.cpp" static-file)
- ("smoke-c.cpp" static-file)
-
hunk ./smoke.mbd 64
- (:components "get-value")))))
+ (:requires (:sb-posix (:for :sbcl)))
+ (:components "get-value"
+ ("image" (:for (:not :sbcl)))
+ ("image-sbcl" (:for :sbcl)))))))
hunk ./src/class-map.lisp 8
-(defmacro id-class-map (smoke)
- `(gethash (pointer-address ,smoke)
- *smoke-id-class-map*))
+
+(defun id-class-map (smoke)
+ (let ((value (gethash (pointer-address smoke)
+ *smoke-id-class-map*)))
+ (assert value [_$_]
+ ()
+ "Unknown smoke module ~A ~A."
+ smoke (smoke-get-module-name smoke))
+ value))
+
+(defun (setf id-class-map) (new-value smoke)
+ (setf (gethash (pointer-address smoke) *smoke-id-class-map*)
+ new-value))
hunk ./src/class-map.lisp 23
- (unless (nth-value 1 (id-class-map smoke))
- (setf (id-class-map smoke)
- (make-hash-table))))
+ (setf (id-class-map smoke)
+ (make-hash-table)))
hunk ./src/class-map.lisp 28
+ (declare (smoke-class smoke-class)
+ (smoke-standard-class class))
hunk ./src/clos.lisp 136
- ())
+ ((smoke :reader smoke-symbol :initarg :smoke-symbol
+ :type symbol)))
+
+(defmethod smoke ((class smoke-wrapper-class))
+ (eval (smoke-symbol class)))
hunk ./src/clos.lisp 185
- :smoke (smoke superclass)
+ :smoke (get-smoke-variable-for-pointer (smoke superclass))
hunk ./src/clos.lisp 202
- :smoke (smoke superclass)
+ :smoke (get-smoke-variable-for-pointer (smoke superclass))
hunk ./src/clos.lisp 214
- (declare (optimize (speed 3))
- (cffi:foreign-pointer smoke))
+ (declare (foreign-pointer smoke)
+ (optimize (speed 3)))
hunk ./src/cxx-method.lisp 89
- (remove-method (closer-mop:method-generic-function) method))))
+ (remove-method generic-function method))))
hunk ./src/method.lisp 20
- :type (make-instance 'smoke-type
+ :type (make-instance 'smoke-lazy-type
hunk ./src/method.lisp 22
- :smoke ,smoke))
+ :smoke ',smoke))
hunk ./src/method.lisp 24
- `(export (quote ,symbol)))))
+ symbol)))
hunk ./src/method.lisp 53
- `(export (quote ,name)))))
+ name)))
hunk ./src/method.lisp 55
-(defun ensure-generic-methods (symbols-names)
- "Ensures the generic functions for SYMBOLS-NAMES."
- (declare (list symbols-names)
- (optimize (speed 3)))
- (dolist (symbol-name symbols-names)
- (ensure-generic-function (first symbol-name)
- :cxx-name (rest symbol-name)
+(defun generic-method-definition (name cxx-name)
+ (values [_$_]
+ `(ensure-generic-function (quote ,name)
+ :cxx-name ,cxx-name
hunk ./src/method.lisp 61
- (export (first symbol-name) :CXX)))
+ name))
hunk ./src/method.lisp 92
+ (ensure-generics)
hunk ./src/method.lisp 95
+ (cxx-exports)
hunk ./src/method.lisp 141
+ (loop for name being the hash-key of generics
+ for cxx-name being the hash-value of generics do
+ (multiple-value-bind (definition export)
+ (generic-method-definition name cxx-name)
+ (push definition ensure-generics)
+ (push export cxx-exports)))
hunk ./src/method.lisp 149
- (eval-when (:load-toplevel :execute)
+ (eval-startup (:execute)
hunk ./src/method.lisp 151
- (ensure-generic-methods ',(hash-table-alist generics))
hunk ./src/method.lisp 152
+ (eval-when (:load-toplevel :execute)
+ ,@ensure-generics)
+ (export (quote ,cxx-exports) :cxx)
hunk ./src/method.lisp 156
- ,@exports)))
+ (export (quote ,exports)))))
hunk ./src/objects/class.lisp 28
+ (declare (function function)
+ (foreign-pointer smoke)
+ (optimize (speed 3)))
hunk ./src/objects/class.lisp 32
- :id 0
- :smoke smoke)))
- (loop for id from 1 to (1- (smoke-classes-size smoke)) do
+ :id 0
+ :smoke smoke)))
+ (loop for id from 1 to (1- (the fixnum (smoke-classes-size smoke))) do
hunk ./src/objects/enum.lisp 23
- :type (make-instance 'smoke::smoke-type
+ :type (make-instance 'smoke::smoke-lazy-type
hunk ./src/objects/enum.lisp 25
- :smoke ,(smoke::get-smoke-variable-for-pointer
+ :smoke ',(smoke::get-smoke-variable-for-pointer
hunk ./src/objects/type.lisp 7
+(defclass smoke-lazy-type (smoke::smoke-type)
+ ((id :reader smoke::id
+ :initarg :id)
+ (smoke :initarg :smoke
+ :reader smoke-symbol)))
+
+(defmethod smoke::smoke ((type smoke-lazy-type))
+ (eval (smoke-symbol type)))
hunk ./src/package.lisp 19
+ #:eval-startup
hunk ./src/package.lisp 37
- #:pointer))
+ #:pointer
+ #:define-smoke-module
+
+ #+sbcl #:save-bundle))
hunk ./src/package.lisp 60
-
-
-
-(in-package #:smoke)
hunk ./src/smoke.lisp 164
+(defmacro define-smoke-module (library (variable variable-name)
+ (init-function function-name))
+ "Define a Smoke module."
+ `(progn
+ (eval-startup (:compile-toplevel :execute)
+ (define-foreign-library ,library
+ (:unix ,(format nil "~(~A~).so.2" library))
+ (t (:default ,(format nil "~(~A~)" library))))
+ (use-foreign-library ,library)
+ (defcvar (,variable ,variable-name :read-only t) :pointer)
+ (defcfun (,init-function ,(format nil "_Z~A~Av" (length function-name)
+ function-name))
+ :void))
+ (eval-startup (:compile-toplevel :execute)
+ (,init-function)
+ (init ,variable))
+ (define-methods ,variable)))
+ [_$_]
+
addfile ./src/utils/image-sbcl.lisp
hunk ./src/utils/image-sbcl.lisp 1
+(in-package :smoke)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (defvar *startup-functions* nil
+ "Functions to run (in order) on startup.")
+
+ (defun add-startup-function (function)
+ (setf *startup-functions*
+ (nconc *startup-functions* (list function))))
+
+ (defun add-and-run-startup-function (function)
+ (add-startup-function function)
+ (funcall function))
+
+ (defun run-startup-functions ()
+ (mapcar #'funcall *startup-functions*)))
+
+(eval-when (:load-toplevel :execute)
+ (push #'run-startup-functions sb-ext:*init-hooks*))
+
+(defmacro eval-startup ((&rest situations) &body body)
+ "Runs BODY when it is loaded."
+ `(eval-when (,@situations :load-toplevel)
+ (add-and-run-startup-function #'(lambda ()
+ (let ((*package* ,*package*))
+ ,@body)))))
+
+(defun strip-foreign-libraries-path ()
+ (dolist (library sb-alien::*shared-objects*)
+ (setf (slot-value library 'namestring)
+ (file-namestring (slot-value library 'pathname)))))
+
+(defun make-temporary-directory ()
+ (pathname (concatenate 'string (sb-posix:mkdtemp "/tmp/cl-smokeXXXXXX")
+ "/")))
+
+(defmacro with-temporary-directory ((directory) &body body)
+ "Binds DIRECTORY to the pathname of a temporary directory and executes body:"
+ `(let ((,directory (make-temporary-directory)))
+ (unwind-protect (progn ,@body)
+ (unless (zerop
+ (sb-ext:process-exit-code
+ (sb-ext:run-program "/bin/rm"
+ (list "-r" (namestring ,directory)))))
+ (cerror "ignore"
+ "could not remove temponary directory ~A"
+ ,directory)))))
+ [_$_]
+(defun save-image (file-name &rest options &key &allow-other-keys)
+ "Save the lisp image in FILE-NAME."
+ (let ((pid (sb-posix:fork)))
+ (if (= 0 pid)
+ (progn
+ (strip-foreign-libraries-path)
+ (apply #'sb-ext:save-lisp-and-die file-name :executable t
+ options))
+ (sb-posix:waitpid pid 0))))
+
+(defun write-shell-wrapper (pathname core-name)
+ (with-open-file (stream pathname :direction :output)
+ (format stream "#!/bin/sh
+cd `dirname \"$0\"`
+LD_LIBRARY_PATH=./ exec -a \"$0\" ./~A $@
+" core-name))
+ (sb-posix:chmod pathname #o0755))
+
+(defun make-tarball (run-directory tarball-pathname &rest pathnames)
+ (flet ((arguments (&rest args)
+ (format nil "~{~A ~}" args)))
+ (unless (zerop
+ (sb-ext:process-exit-code
+ (sb-ext:run-program
+ "/bin/sh"
+ (list "-c"
+ (apply #'arguments
+ "cd " (namestring run-directory) " && "
+ "tar -cvjf " (namestring tarball-pathname)
+ " --strip 2 "
+ (mapcar #'namestring pathnames))))))
+ (error "Create tarball ~A failed." tarball-pathname))))
+
+(defun makeself (run-directory directory-name file-name label [_$_]
+ &optional (startup-script "") &rest args)
+ "Make self-extractable archives on Unix
+http://megastep.org/makeself/"
+ ;; make an absolute pathname sine we change the directory.
+ (let ((file-name (merge-pathnames file-name)))
+ (flet ((arguments (&rest args)
+ (format nil "~{~A ~}" args)))
+ (unless (zerop
+ (sb-ext:process-exit-code
+ (sb-ext:run-program
+ "/bin/sh"
+ (list "-c"
+ (apply #'arguments
+ "cd " (namestring run-directory) " && "
+ "makeself --nox11" (namestring directory-name)
+ (namestring file-name) label
+ startup-script args)))))
+ (error "Create ~A failed." file-name)))))
+
+(defun save-bundle (file-name &optional extra-files &rest options &key &allow-other-keys)
+ "Creates a FILE-NAME.tar.bz2 in the current directory.
+This bundle contains a dumped image, the wrapper libraries and a
+script to run in. OPTIONS is passed to SB-EXT:SAVE-LISP-AND-DIE."
+ (with-temporary-directory (dir)
+ (let ((bundle-dir (merge-pathnames (make-pathname :directory
+ (list :relative file-name))
+ dir)))
+ (sb-posix:mkdir bundle-dir #o0755)
+ (dolist (library sb-alien::*shared-objects*)
+ (sb-ext:run-program
+ "/bin/cp" (list (namestring (slot-value library 'pathname))
+ (namestring bundle-dir))))
+ (apply #'save-image (namestring (make-pathname :name "sbcl-core"
+ :defaults bundle-dir))
+ options)
+ (write-shell-wrapper (make-pathname :defaults bundle-dir
+ :name "run"
+ :type "sh")
+ "sbcl-core")
+;; (make-tarball dir (concatenate 'string file-name ".tar.bz2")
+;; file-name)
+ (dolist (file extra-files)
+ (copy-file file (merge-pathnames bundle-dir file)))
+ (makeself dir bundle-dir file-name "sbcl-bundle"
+ "./run.sh"))))
+;; (copy-file (make-pathname :defaults dir
+;; :name (concatenate 'string file-name ".tar")
+;; :type "bz2")
+; (concatenate 'string file-name ".tar.bz2")))))
addfile ./src/utils/image.lisp
hunk ./src/utils/image.lisp 1
+(in-package :smoke)
+
+(defmacro eval-startup ((&rest situations) &body body)
+ "Runs BODY when it is loaded."
+ `(eval-when (,@situations :load-toplevel)
+ ,@body))
addfile ./test-bundle.sh
hunk ./test-bundle.sh 1
+#!/bin/sh
+if [[ $# -ne 0 ]]; then
+ echo "Test cl-smoke bundle creation."
+ echo "Usage: $0"
+ exit 1
+fi
+
+sbcl --eval '(mb:load :qt.tests)' \
+ --eval '(smoke:save-bundle "qt.test.run")' \
+ --eval '(quit)' || exit 1
+
+echo "(progn (5am:run!) (quit))" | ./qt.test.run [_$_]
hunk ./test.lisp 2
-exec -a "$0" sbcl --noinform --noprint --disable-debugger --load $0 --end-toplevel-options "$@"
+sbcl --noinform --noprint --disable-debugger --load $0 --end-toplevel-options "$@" || exit 1
+sh ./test-bundle.sh || exit 2
+exit 0
Tue May 12 15:54:46 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Support Clozure CL
hunk ./src/cxx-method.lisp 96
+#+sbcl
hunk ./src/cxx-method.lisp 119
+#+sbcl
hunk ./src/method.lisp 145
+ (register-smoke-module-var (quote ,smoke))
hunk ./src/objects/enum.lisp 8
-;;; an use thouse as enums, but C++ enums may have several symbols for
+;;; an use those as enums, but C++ enums may have several symbols for
hunk ./src/objects/enum.lisp 18
+;; Clozure CL needs this
+(defmethod make-load-form ((enum enum) &optional environment)
+ (declare (ignore environment))
+ `(make-instance 'enum
+ :value ,(value enum)
+ :type (make-instance 'smoke::smoke-type
+ :id ,(id (enum-type enum))
+ :smoke ,(smoke::get-smoke-variable-for-pointer
+ (smoke::smoke (enum-type enum))))))
+
hunk ./src/overload-resolution.lisp 208
- (format t "~S: ~S~%" type name)
hunk ./src/overload-resolution.lisp 255
- (format t "ERROR TYPE~%")
hunk ./src/package.lisp 16
+ #:get-smoke-variable-for-pointer
hunk ./src/smoke-c/smoke-c.lisp 3
-#|
+;; Load the qt smoke binding to prevent undefined aliens.
hunk ./src/smoke-c/smoke-c.lisp 11
- (use-foreign-library libsmoke-c)
-)
-|#
+ (use-foreign-library libsmoke-c))
hunk ./src/smoke-c/smoke-c.lisp 14
-
hunk ./src/smoke.lisp 109
+(let ((pointer-symbol-map (make-hash-table)))
+ (defun register-smoke-module-var (symbol)
+ "Registers SYMBOL of a variable containing a pointer to a Smoke module."
+ (setf (gethash (pointer-address (eval symbol)) pointer-symbol-map)
+ symbol))
+ (defun get-smoke-variable-for-pointer (pointer)
+ "Returns the SYMBOL of the variable whose value is POINTER."
+ (gethash (pointer-address pointer) pointer-symbol-map)))
+ [_$_]
Mon May 11 22:18:23 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Make &rest lambda list for static methods only when necessary.
hunk ./src/method.lisp 2
+(declaim (optimize (debug 3)))
hunk ./src/method.lisp 38
-(defun static-method-definition (method)
+(defun static-method-definition (method &optional (argument-count -1))
hunk ./src/method.lisp 45
- `(defun ,name (&rest args)
+ `(defun ,name ,(if (< argument-count 0)
+ '(&rest args)
+ (make-lambda argument-count))
hunk ./src/method.lisp 49
- ,method-name args))
+ ,method-name
+ ,(if (< argument-count 0)
+ 'args
+ `(list ,@(make-lambda argument-count)))))
hunk ./src/method.lisp 125
- (let ((function-symbol (static-method-symbol method)))
- (unless (nth-value 1 (gethash function-symbol function-symbols))
- (setf (gethash function-symbol function-symbols) t)
- (multiple-value-bind (def export) (static-method-definition method)
- (push def functions)
- (push export exports)))))))
+ (let* ((function-symbol (static-method-symbol method))
+ (methods (gethash function-symbol function-symbols)))
+ (setf (gethash function-symbol function-symbols)
+ (if methods (- (id method)) (id method)))))))
hunk ./src/method.lisp 130
+ (loop for id being the hash-values of function-symbols do
+ (let ((method (make-instance 'smoke-method
+ :id (abs id)
+ :smoke (eval smoke))))
+ (multiple-value-bind (definition export)
+ (static-method-definition
+ method
+ (if (< 0 id)
+ (get-arguments-length method)
+ -1))
+ (push definition functions)
+ (push export exports))))
hunk ./src/overload-resolution.lisp 83
-(defun candidate-functions (name argument-count class2)
+
+(defun viable-functions (name argument-count class2)
hunk ./src/overload-resolution.lisp 86
- (let (methods)
+ ;; 13.3.2
+ (let ((methods))
hunk ./src/overload-resolution.lisp 112
- [_$_]
-
hunk ./src/overload-resolution.lisp 258
- (let ((candidate-functions (candidate-functions name (length objects)
+ (let ((viable-functions (viable-functions name (length objects)
hunk ./src/overload-resolution.lisp 263
- (loop for method in candidate-functions do
+ (loop for method in viable-functions do
hunk ./src/overload-resolution.lisp 462
- (candidate-functions name
- (length arguments)
- (smoke-class-of object-or-class)))))
+ (viable-functions name
+ (length arguments)
+ (smoke-class-of object-or-class)))))
Mon May 11 19:55:42 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Support (setf (getter-method) value) for C++ set* methods.
hunk ./src/clos.lisp 232
- (:documentation "Smoke generic function"))
+ (:documentation "Smoke generic function."))
hunk ./src/clos.lisp 255
- (call-using-args ,(first lambda-list) (name ,(cxx-generic-function gf))
+ (call-using-args ,(first lambda-list)
+ (name ,(cxx-generic-function gf))
hunk ./src/clos.lisp 258
-#|
- (let ((method (find-method-using-args (smoke-class-of ,(first lambda-list))
- (name ,(cxx-generic-function gf))
- (list ,@(rest lambda-list)))))
- (if (static-p method)
- (s-call method (null-pointer) (list ,@lambda-list))
- (s-call method (cast ,(first lambda-list) (get-class method))
- (list ,@(rest lambda-list))))))))))
-|#
hunk ./src/clos.lisp 260
- ((binding :pointer)
- (id smoke-index)
- (object-pointer :pointer))
- (declare (optimize (speed 3)))
+ ((binding :pointer)
+ (id smoke-index)
+ (object-pointer :pointer))
+ (declare (ignore binding id)
+ (optimize (speed 3)))
hunk ./src/method.lisp 42
- (name (lispify (concatenate 'string
- (if (string= (name class)
- "QGlobalSpace")
- nil
- (concatenate 'string
- (name class)
- "."))
- (name method)))))
+ (name (static-method-symbol method)))
hunk ./src/method.lisp 60
+(defun setf-method-definition (method)
+ `(defun (setf ,(lispify (subseq (name method) 3) :cxx)) (new-value object)
+ (,(lispify (name method) :cxx) object new-value)
+ new-value))
+
hunk ./src/method.lisp 80
-
hunk ./src/method.lisp 90
+ (setf-function-symbols (make-hash-table))
hunk ./src/method.lisp 108
- (setf (gethash (lispify (name method) "CXX") generics)
- (name method))
+ (let ((name (name method)))
+ (when (and (starts-with-subseq "set" name)
+ (> (length name) 3)
+ (upper-case-p (char name 3))
+ (= 1 (get-arguments-length method)))
+ (unless (nth-value 1 (gethash (lispify name :cxx) setf-function-symbols))
+ (setf (gethash (lispify name :cxx) setf-function-symbols) t)
+ (push (setf-method-definition method) functions)))
+ (setf (gethash (lispify name "CXX") generics)
+ name))
Mon May 11 16:11:35 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Export Lisp -> C++ API.
hunk ./src/overload-resolution.lisp 293
+ "Defines a translation from LISP-TYPE to the C++ types TYPE-NAMES using
+the function CONVERSION-FUNCTION-NAME."
hunk ./src/overload-resolution.lisp 314
-;(defun exact-match-using-type (object-type type)
hunk ./src/overload-resolution.lisp 316
- ;(declare (values boolean))
hunk ./src/overload-resolution.lisp 335
+ "Returns a pointer that calls CLEANUP-FUNCTION when it is finalized."
hunk ./src/package.lisp 32
+ #:define-from-lisp-translation
+ #:make-cleanup-pointer
+
Mon May 11 15:35:40 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Fix enum to int promotion.
hunk ./src/overload-resolution.lisp 359
- (make-match 'promotion 'cocere-enum)))))
+ (make-match 'promotion 'coerce-enum)))
+ (7 (when (object.typep 'enum)
+ (make-match 'promotion 'coerce-enum)))))
Mon May 11 14:30:33 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* cleanup: use package alexandria.
hunk ./src/cxx-method.lisp 43
- (alexandria:symbolicate (closer-mop:generic-function-name cxx-generic-function)
- #\/ (write-to-string argument-count))))
+ (symbolicate (closer-mop:generic-function-name cxx-generic-function)
+ #\/ (write-to-string argument-count))))
hunk ./src/method.lisp 16
- ; `(defconstant ,symbol
- ; ,(enum-call method))
- `(alexandria:define-constant ,symbol
+ `(define-constant ,symbol
hunk ./src/method.lisp 37
-(defun static-method-definition (method smoke)
+(defun static-method-definition (method)
hunk ./src/method.lisp 116
- (multiple-value-bind (def export) (static-method-definition method smoke)
+ (multiple-value-bind (def export) (static-method-definition method)
hunk ./src/method.lisp 123
- (ensure-generic-methods ',(alexandria:hash-table-alist generics))
+ (ensure-generic-methods ',(hash-table-alist generics))
hunk ./src/overload-resolution.lisp 32
- (char< (char method-name diff) (char name diff))))
+ (char< (char method-name diff) (char name diff))))
hunk ./src/overload-resolution.lisp 217
- (alexandria:if-let
+ (if-let
hunk ./src/overload-resolution.lisp 283
- ,@(mapcar (alexandria:curry #'apply
+ ,@(mapcar (curry #'apply
hunk ./src/overload-resolution.lisp 293
- `(progn ,@(loop for type-name in (alexandria:ensure-list type-names)
+ `(progn ,@(loop for type-name in (ensure-list type-names)
hunk ./src/overload-resolution.lisp 305
- (if (alexandria:starts-with-subseq
+ (if (starts-with-subseq
hunk ./src/overload-resolution.lisp 308
- ;`(integer 0 ,(1- (expt 2 bits)))
hunk ./src/overload-resolution.lisp 310
- ;`(integer ,(- (expt 2 (1- bits)))
- ; ,(1- (expt 2 (1- bits)))))))
hunk ./src/overload-resolution.lisp 318
- (alexandria:when-let (test (gethash (name type) *from-lisp-translations*))
+ (when-let (test (gethash (name type) *from-lisp-translations*))
hunk ./src/overload-resolution.lisp 466
-
-
-(defun cxx-coerce-p-using-type (type result-type)
- "Returns true when an object of type TYPE can be convertet to an object
-of smoke type RESULT-TYPE."
-)
- [_$_]
-
-(defun cxx-coerce (object result-type)
-)
hunk ./src/package.lisp 13
- (:use #:cl #:cffi #:trivial-garbage #:bordeaux-threads #:cxx-support)
+ (:use #:cl #:cffi #:trivial-garbage #:bordeaux-threads #:cxx-support
+ #:alexandria)
hunk ./src/using-type.lisp 4
- `(macrolet ((,(alexandria:symbolicate object '.typep)
+ `(macrolet ((,(symbolicate object '.typep)
hunk ./src/using-type.lisp 7
- (,(alexandria:symbolicate object '.type-of) ()
+ (,(symbolicate object '.type-of) ()
hunk ./src/using-type.lisp 36
- `(macrolet ((,(alexandria:symbolicate object-type '.typep)
+ `(macrolet ((,(symbolicate object-type '.typep)
hunk ./src/using-type.lisp 39
- (,(alexandria:symbolicate object-type '.type-of) ()
+ (,(symbolicate object-type '.type-of) ()
hunk ./src/using-type.lisp 43
- `(,(alexandria:symbolicate function-name '-using-types)
+ `(,(symbolicate function-name '-using-types)
hunk ./src/using-type.lisp 46
- `(,(alexandria:symbolicate function-name '-using-type)
+ `(,(symbolicate function-name '-using-type)
hunk ./src/using-type.lisp 59
- (defun ,(alexandria:symbolicate name '-using-type) ,lambda-list
+ (defun ,(symbolicate name '-using-type) ,lambda-list
hunk ./src/using-type.lisp 73
- `(,(alexandria:symbolicate function-name '-using-types)
+ `(,(symbolicate function-name '-using-types)
hunk ./src/using-type.lisp 76
- `(,(alexandria:symbolicate function-name '-using-type)
+ `(,(symbolicate function-name '-using-type)
hunk ./src/using-type.lisp 80
- `(function ,(alexandria:symbolicate name '-using-types))))
- (defun ,(alexandria:symbolicate name '-using-types) ,lambda-list
+ `(function ,(symbolicate name '-using-types))))
+ (defun ,(symbolicate name '-using-types) ,lambda-list
Mon May 11 14:21:24 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* cleanup: rename type= to smoke-type=.
hunk ./src/objects/enum.lisp 25
- (assert (type= (enum-type enum)
+ (assert (smoke-type= (enum-type enum)
hunk ./src/objects/enum.lisp 33
- (assert (type= (enum-type enum1)
+ (assert (smoke-type= (enum-type enum1)
hunk ./src/objects/method.lisp 99
- (enum (type= (enum-type object)
+ (enum (smoke-type= (enum-type object)
hunk ./src/objects/type.lisp 21
-(defun type= (type1 type2)
+(defun smoke-type= (type1 type2)
hunk ./src/overload-resolution.lisp 334
- (type= type (object.type-of))))))
+ (smoke-type= type (object.type-of))))))
hunk ./src/package.lisp 25
- #:type=
+ #:smoke-type=
Mon May 11 14:05:00 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Visibility for C wrappers
hunk ./src/smoke-c/CMakeLists.txt 5
+include(CheckCXXCompilerFlag)
+check_cxx_compiler_flag("-fvisibility=hidden" CXX_VISIBILITY)
+if(CXX_VISIBILITY)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden")
+endif(CXX_VISIBILITY)
+
hunk ./src/smoke-c/cl_smoke.h 1
+#ifndef CL_SMOKE_H
+#define CL_SMOKE_H
+
hunk ./src/smoke-c/cl_smoke.h 6
+#if defined _WIN32 || defined __CYGWIN__
+ #define CL_SMOKE_EXPORT __declspec(dllexport)
+#else
+ #if __GNUC__ >= 4
+ #define CL_SMOKE_EXPORT __attribute__((visibility("default")))
+ #else
+ #define CL_SMOKE_EXPORT
+ #endif
+#endif
hunk ./src/smoke-c/cl_smoke.h 48
+
+#endif // CL_SMOKE_H
hunk ./src/smoke-c/smoke-c-util.cpp 1
+#if defined _WIN32 || defined __CYGWIN__
+ #define CL_SMOKE_EXPORT __declspec(dllexport)
+#else
+ #if __GNUC__ >= 4
+ #define CL_SMOKE_EXPORT __attribute__((visibility("default")))
+ #else
+ #define CL_SMOKE_EXPORT
+ #endif
+#endif
hunk ./src/smoke-c/smoke-c-util.cpp 21
-int
+CL_SMOKE_EXPORT int
hunk ./src/smoke-c/smoke-c.cpp 32
-void*
+CL_SMOKE_EXPORT void*
hunk ./src/smoke-c/smoke-c.cpp 47
-smoke_binding
+CL_SMOKE_EXPORT smoke_binding
hunk ./src/smoke-c/smoke-c.cpp 58
-void
+CL_SMOKE_EXPORT void
hunk ./src/smoke-c/smoke-c.cpp 70
-const char*
+CL_SMOKE_EXPORT const char*
hunk ./src/smoke-c/smoke-c.cpp 85
-void
+CL_SMOKE_EXPORT void
hunk ./src/smoke-c/smoke-c.cpp 97
-Smoke::Index
+CL_SMOKE_EXPORT Smoke::Index
hunk ./src/smoke-c/smoke-c.cpp 112
-Smoke::Index
+CL_SMOKE_EXPORT Smoke::Index
hunk ./src/smoke-c/smoke-c.cpp 124
-void
+CL_SMOKE_EXPORT void
hunk ./src/smoke-c/smoke-c.cpp 145
-const struct Smoke::Class*
+CL_SMOKE_EXPORT const struct Smoke::Class*
hunk ./src/smoke-c/smoke-c.cpp 160
-int
+CL_SMOKE_EXPORT int
hunk ./src/smoke-c/smoke-c.cpp 176
-Smoke::Index
+CL_SMOKE_EXPORT Smoke::Index
hunk ./src/smoke-c/smoke-c.cpp 194
-const Smoke::MethodMap*
+CL_SMOKE_EXPORT const Smoke::MethodMap*
hunk ./src/smoke-c/smoke-c.cpp 208
-const char*
+CL_SMOKE_EXPORT const char*
hunk ./src/smoke-c/smoke-c.cpp 221
-Smoke::Index
+CL_SMOKE_EXPORT Smoke::Index
hunk ./src/smoke-c/smoke-c.cpp 232
-Smoke::Index
+CL_SMOKE_EXPORT Smoke::Index
hunk ./src/smoke-c/smoke-c.cpp 244
-const struct Smoke::Method*
+CL_SMOKE_EXPORT const struct Smoke::Method*
hunk ./src/smoke-c/smoke-c.cpp 258
-void
+CL_SMOKE_EXPORT void
hunk ./src/smoke-c/smoke-c.cpp 274
-void
+CL_SMOKE_EXPORT void
hunk ./src/smoke-c/smoke-c.cpp 291
-Smoke::Index
+CL_SMOKE_EXPORT Smoke::Index
hunk ./src/smoke-c/smoke-c.cpp 306
-void
+CL_SMOKE_EXPORT void
hunk ./src/smoke-c/smoke-c.cpp 347
-Smoke::Index
+CL_SMOKE_EXPORT Smoke::Index
hunk ./src/smoke-c/smoke-c.cpp 359
-const struct Smoke::Type*
+CL_SMOKE_EXPORT const struct Smoke::Type*
hunk ./src/smoke-c/smoke-c.cpp 373
-Smoke::Index
+CL_SMOKE_EXPORT Smoke::Index
hunk ./src/smoke-c/smoke-c.cpp 387
-void*
+CL_SMOKE_EXPORT void*
hunk ./src/smoke-c/smoke-c.cpp 402
-Smoke::Index
+CL_SMOKE_EXPORT Smoke::Index
Mon May 11 14:02:40 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Cleanup: unpush does not need second argument.
hunk ./src/cxx-method.lisp 85
-(defun unpush-method (method cxx-generic-function)
+(defun unpush-method (method)
hunk ./src/cxx-method.lisp 146
- (unpush-method method gf)
+ (unpush-method method)
Mon May 11 13:07:39 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Prepare for overload resolution at compile time
hunk ./smoke.mbd 37
- ("overload-resolution" (:needs "package" "smoke"))
+ ("using-type" (:needs "package"))
+ ("overload-resolution" (:needs "package" "smoke" "using-type"))
hunk ./smoke.mbd 73
+ :alexandria
hunk ./src/clos.lisp 208
- [_$_]
-
hunk ./src/clos.lisp 229
- :type string))
+ :type string
+ :documentation "The C++ name of the method."))
hunk ./src/clos.lisp 246
-#|
- (let ((method (find-method-using-args (smoke-class-of (first args))
- (name gf) (rest args))))
- (if (static-p method)
- (s-call method (null-pointer) (rest args))
- (s-call method (cast (first args) (get-class method)) (rest args)))))
-|#
hunk ./src/clos.lisp 255
+ (call-using-args ,(first lambda-list) (name ,(cxx-generic-function gf))
+ (list ,@(rest lambda-list))))))))
+#|
hunk ./src/clos.lisp 265
+|#
hunk ./src/clos.lisp 378
- (multiple-value-bind (rank method sequence)
+ (multiple-value-bind (method sequence)
hunk ./src/clos.lisp 380
- (mapcar #'(lambda (a)
- (let ((type (type-of a)))
- (if (subtypep type 'smoke-standard-object)
- (class-of a)
- type)))
- arguments)
+ arguments
hunk ./src/clos.lisp 386
- (mapcar #'funcall sequence arguments)))))
-; (pointer-call (make-smoke-constructor (class-of object)
-; args)
-; (null-pointer)
-; args))
+ (mapcar #'(lambda (conversion argument)
+ (funcall conversion argument))
+ sequence arguments)))))
hunk ./src/clos.lisp 410
-; (when (stack-p type)
-; (add-object ret))
-; (set-binding ret (binding (smoke (class-of ret)))))
hunk ./src/cxx-method.lisp 41
+(defun cxx-method-generic-function-name (cxx-generic-function argument-count)
+ (let ((*package* (find-package :cxx)))
+ (alexandria:symbolicate (closer-mop:generic-function-name cxx-generic-function)
+ #\/ (write-to-string argument-count))))
+
hunk ./src/cxx-method.lisp 53
- (let ((gf (make-instance 'cxx-method-generic-function
- :cxx-generic-function cxx-generic-function
- :lambda-list (make-lambda argument-count))))
+ (let* ((name (cxx-method-generic-function-name cxx-generic-function
+ argument-count))
+ (gf (make-instance 'cxx-method-generic-function
+ :name name
+ :cxx-generic-function cxx-generic-function
+ :lambda-list (make-lambda argument-count))))
+ (setf (fdefinition name) gf)
hunk ./src/cxx-method.lisp 148
+
+#|
+(defun cxx-dispatch-compiler-macro (cxx-generic-function)
+ "Retruns a compiler-macro form for CXX-GENERIC-FUNCTION that
+precomputes the dispatching for the argument count, if possible."
+ ;; FIXME only applies when a defmethod with the right argument count
+ ;; has been defined, which is almost never.
+ `(define-compiler-macro ,(closer-mop:generic-function-name cxx-generic-function)
+ (&whole form object &rest args)
+ (let ((name (cxx-method-generic-function-name (fdefinition (first form))
+ (1+ (length args)))))
+ (if (fboundp name)
+ `(,name ,object ,@args)
+ form))))
+
+(defmethod initialize-instance :after ((gf cxx-generic-function) &key &allow-other-keys)
+ (eval (cxx-dispatch-compiler-macro gf)))
+|#
hunk ./src/method.lisp 3
-(declaim (optimize (debug 3)))
-
-(defun enum-class-symbol (enum-type)
- (let ((class-name (name (get-class enum-type))))
- (if (null class-name)
- 'global-enum-class
- (lispify class-name))))
- [_$_]
hunk ./src/method.lisp 56
- ;(let ((method (find-method-using-args (make-instance 'smoke-class
- ; :id ,(id class)
- ; :smoke ,smoke)
- ; ,method-name args)))
- ; (s-call method (null-pointer) args)))
hunk ./src/method.lisp 58
-(defun hash-table-key-values (hash-table)
- "Returns a list containing all key-value pairs as CONS of HASH-TABLE."
- (let ((list))
- (maphash #'(lambda (key value)
- (push (cons key value) list))
- hash-table)
- list))
-
hunk ./src/method.lisp 73
- (unless (= (smoke-methods-size ,smoke)
- ,(smoke-methods-size (eval smoke)))
+ (unless (and (= (smoke-methods-size ,smoke)
+ ,(smoke-methods-size (eval smoke)))
+ (= (smoke-method-name-size ,smoke)
+ ,(smoke-method-name-size (eval smoke)))
+ (= (smoke-types-size ,smoke)
+ ,(smoke-types-size (eval smoke)))
+ (= (smoke-classes-size ,smoke)
+ ,(smoke-classes-size (eval smoke))))
hunk ./src/method.lisp 125
- (ensure-generic-methods ',(hash-table-key-values generics))
+ (ensure-generic-methods ',(alexandria:hash-table-alist generics))
hunk ./src/object-map.lisp 11
+;; => use :synchronized of sbcl hash-table
hunk ./src/objects/method.lisp 276
+(defun internal-p (method)
+ "Returns T when METHOD is internal and NIL otherwise."
+ (/= 0 (get-flag method :internal)))
+
hunk ./src/objects/stack.lisp 58
+ ((cffi:pointerp lisp-value)
+ (push-stack2 stack lisp-value (type-id smoke-type)))
hunk ./src/overload-resolution.lisp 7
-(deftype smoke-index (&optional (lower -32768) (upper 32767))
- `(integer ,lower ,upper))
-
hunk ./src/overload-resolution.lisp 8
+ "Returns true when CHARACTER is used for munging and false otherwise."
hunk ./src/overload-resolution.lisp 14
+ "Returns the index of NAME for the Smoke module SMOKE and 0 when
+NAME is not found."
+ ;; FIXME search methods instead of methodMaps, since we are not
+ ;; interrested in the munging.
hunk ./src/overload-resolution.lisp 45
+ "Returns the number of arguments the method MUNGED-NAME uses."
hunk ./src/overload-resolution.lisp 55
+ "Returns a list of the method indices with name NAME
+that accept ARGUMENT-COUNT arguments."
hunk ./src/overload-resolution.lisp 73
- "Returns a list if super classes of CLASS; one or every smoke module
-that can be reaced by CLASS super classes. The returned super classes
-are as secific as possible."
+ "Returns a list of super classes of CLASS; one or every smoke module
+that can be reached by super classes of CLASS. The returned super classes
+are as specific as possible."
hunk ./src/overload-resolution.lisp 112
-(defconstant +no-match+ most-positive-fixnum)
hunk ./src/overload-resolution.lisp 117
- ()
+ ((function-name :accessor conversion-function-name
+ :initarg :conversion-function-name))
hunk ./src/overload-resolution.lisp 121
-(defclass no-match (std-conversion)
- ((rank :reader rank
- :allocation :class
- :initform +no-match+)))
hunk ./src/overload-resolution.lisp 148
- :initform (1+ +conversion+))))
+ :initform (+ 2 +conversion+))))
hunk ./src/overload-resolution.lisp 153
- :initform (1+ +conversion+))))
+ :initform (+ 3 +conversion+))))
hunk ./src/overload-resolution.lisp 178
+ (:method ((conversion1 (eql nil)) (conversion2 (eql nil)))
+ t)
hunk ./src/overload-resolution.lisp 185
+ "Returns the greater conversion of CONVERSION1 and CONVERSION2."
hunk ./src/overload-resolution.lisp 191
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (defun conversion-function (name &optional arg)
+ (if arg
+ `(if (using-typep)
+ `(,,name
+ (find-class ',(class-name ,arg)))
+ #'(lambda (object)
+ (funcall (fdefinition ,name)
+ object ,arg)))
+ `(if (using-typep)
+ ,name
+ (fdefinition ,name)))))
+
+(defmacro make-match (type &optional (name ''identity)
+ (argument nil)
+ &rest args)
+ (format t "~S: ~S~%" type name)
+ `(make-instance ,type
+ :conversion-function-name ,(conversion-function name argument)
+ [_$_]
+ ,@args))
hunk ./src/overload-resolution.lisp 214
-(defun conversion-sequence-for-type (class type &optional user)
- (if (exact-match-using-class class type)
- (values (make-instance 'exact-match) #'identity)
- (multiple-value-bind (match function)
- (promotion-using-class class type)
- (if match
- (values (make-instance 'promotion) function)
- (multiple-value-bind (m2 function2)
- (conversion-using-class class type)
- (if m2
- (values m2 function2)
- (if user
- (user-conversion-using-class class type)
- (values nil nil))))))))
+(defun+using-type get-conversion-sequence object (object type &optional user)
+ "Retruns a conversion sequence to convert a instance of type CLASS
+to an instance of type TYPE. When USER is true user conversions are considered."
+ (alexandria:if-let
+ (match (call-using-type exact-match object type))
+ (if (eql t match)
+ (make-match 'exact-match)
+ (make-match 'exact-match match))
+ (or (call-using-type promotion object type)
+ (call-using-type conversion object type)
+ (and user
+ (call-using-type user-conversion object type)))))
hunk ./src/overload-resolution.lisp 227
-(defun standard-conversion-sequence-using-classes (method classes &optional user)
+(defun+using-types standard-conversion-sequence (method classes &optional user)
+ "Returns the conversion sequences to convert the arguments of types CLASSES
+to the types required by METHOD."
hunk ./src/overload-resolution.lisp 232
- ;(format t "~A~%~3T~A~%" method classes)
hunk ./src/overload-resolution.lisp 234
- ;(format t "~%C ~A ~A~%" type class)
- (multiple-value-bind (rank function)
- (conversion-sequence-for-type class type user)
+ (let ((rank (call-using-type get-conversion-sequence class type user)))
hunk ./src/overload-resolution.lisp 239
- (push function conversions)))
+ (push (conversion-function-name rank) conversions)))
hunk ./src/overload-resolution.lisp 242
-(defun conversion-sequence-using-classes (method classes)
- (standard-conversion-sequence-using-classes method classes t))
+(defun+using-types conversion-sequence (method classes)
+ (call-using-types standard-conversion-sequence method classes t))
hunk ./src/overload-resolution.lisp 245
-(defun find-best-viable-function (name classes class)
- (find-best-viable-function2 #'conversion-sequence-using-classes
- name classes class))
+(defun+using-types find-best-viable-function (name arguments class)
+ "Returns the method named NAME of class CLASS that can be called
+using arguments of types TYPES with the lowest conversion sequence."
+ (call-using-types find-best-viable-function2
+ (function-using-types conversion-sequence)
+ name arguments class))
hunk ./src/overload-resolution.lisp 252
-(defun find-best-viable-function2 (get-sequence name classes class)
+(defun+using-types find-best-viable-function2 (get-sequence name objects class)
hunk ./src/overload-resolution.lisp 254
- (let ((candidate-functions (candidate-functions name (length classes)
+ (when (and (using-typep)
+ (not (typep class 'smoke-standard-class)))
+ (format t "ERROR TYPE~%")
+ (throw 'unspecific-type class))
+ (let ((candidate-functions (candidate-functions name (length objects)
hunk ./src/overload-resolution.lisp 260
- (best-rank (make-instance 'no-match))
+ (best-rank)
hunk ./src/overload-resolution.lisp 265
- (funcall get-sequence method classes)
+ (funcall get-sequence method objects)
hunk ./src/overload-resolution.lisp 270
- (when (conversion= rank (make-instance 'exact-match))
+ (when (conversion= rank (make-match 'exact-match))
hunk ./src/overload-resolution.lisp 272
- (values best-rank best-method conversions)))
+ (values best-method conversions)))
hunk ./src/overload-resolution.lisp 285
- `(,type-name (subtypep ,class (quote ,lisp-type)))))
+ `(,type-name (typep-using-type ,class (quote ,lisp-type)))))
hunk ./src/overload-resolution.lisp 287
- [_$_]
-(defun exact-match-using-class (class type)
- (declare (values boolean))
+
+(defvar *from-lisp-translations* (make-hash-table :test 'equal))
+
+(defmacro define-from-lisp-translation (type-names lisp-type
+ &optional
+ (conversion-function-name 'identity))
+ `(progn ,@(loop for type-name in (alexandria:ensure-list type-names)
+ collect `(setf (gethash ,type-name *from-lisp-translations*)
+ #'(lambda (type)
+ (and (subtypep type ',lisp-type)
+ ',conversion-function-name))))))
+
+(define-from-lisp-translation ("void*" "const void*" "void**" "const void**")
+ foreign-pointer)
+
+;; FIXME grovel this?
+(deftype c-integer (ctype)
+ (let ((bits (* 8 (foreign-type-size ctype))))
+ (if (alexandria:starts-with-subseq
+ (symbol-name :unsigned)
+ (symbol-name ctype))
+ ;`(integer 0 ,(1- (expt 2 bits)))
+ `(unsigned-byte ,bits)
+ `(signed-byte ,bits))))
+ ;`(integer ,(- (expt 2 (1- bits)))
+ ; ,(1- (expt 2 (1- bits)))))))
+ [_$_]
+ [_$_]
+;(defun exact-match-using-type (object-type type)
+(defun+using-type exact-match object (object type)
+ "Test for an exact match."
+ ;(declare (values boolean))
hunk ./src/overload-resolution.lisp 320
- (0 (smoke-type-case (type class)
- ("const QString&" string)
- ("const char*" string)
- ("void*" cffi:foreign-pointer)
- ("const void*" cffi:foreign-pointer)
- ("void**" cffi:foreign-pointer)))
- (1 (subtypep class 'boolean))
- (2 (subtypep class 'character))
- (6 (subtypep class 'integer))
- (7 (subtypep class '(integer 0)))
- (10 (subtypep class 'single-float))
- (11 (subtypep class 'double-float))
- (12 (subtypep class 'enum)) ;; FIXME enum-type
- (13 (and (subtypep class (find-class 'smoke-standard-object))
- (type= type class)))))
- [_$_]
+ (0 [_$_]
+ (alexandria:when-let (test (gethash (name type) *from-lisp-translations*))
+ (funcall test (object.type-of))))
+ (1 (object.typep 'boolean))
+ (2 (object.typep 'standard-char))
+ (3 (object.typep '(c-integer :unsigned-char)))
+ (4 (object.typep '(c-integer :short)))
+ (5 (object.typep '(c-integer :unsigned-short)))
+ (6 (object.typep '(c-integer :int)))
+ (7 (object.typep '(c-integer :unsigned-int)))
+ (10 (object.typep 'single-float))
+ (11 (object.typep 'double-float))
+ (12 (object.typep 'enum)) ;; FIXME enum-type
+ (13 (and (object.typep (find-class 'smoke-standard-object))
+ (type= type (object.type-of))))))
+
+
+(defun make-cleanup-pointer (pointer cleanup-function)
+ (let ((address (pointer-address pointer)))
+ (tg:finalize pointer #'(lambda ()
+ (funcall cleanup-function
+ (make-pointer address))))))
+
hunk ./src/overload-resolution.lisp 349
-(defun promotion-using-class (class type)
+(defun coerce-c-string (string)
+ (make-auto-pointer (foreign-string-alloc string)))
+
+(defun coerce-enum (enum)
+ (cxx-support:value enum))
+
+(defun+using-type promotion object (object type)
hunk ./src/overload-resolution.lisp 357
- ;(values boolean (or nil function)))
hunk ./src/overload-resolution.lisp 358
- (0
- (if (and (string= (name type)
- "const char*")
- ; (subtypep class '(simple-array character *)))
- (subtypep class 'string))
- (values t #'(lambda (string)
- (make-auto-pointer (foreign-string-alloc string))))
- (values nil nil)))
- (6 (and (subtypep class 'enum)
- (values t #'cxx-support:value)))))
+ (0 (when (and (string= (name type) "const char*")
+ (object.typep 'string))
+ (make-match 'promotion 'coerce-c-string)))
+ (6 (when (object.typep 'enum)
+ (make-match 'promotion 'cocere-enum)))))
hunk ./src/overload-resolution.lisp 364
-; (smoke-type-case (type class)
-; ("double" single-float)))
+(defun coerce-cast (object to-class)
+ (cast object to-class))
hunk ./src/overload-resolution.lisp 367
-(defun conversion-using-class (class type)
- (if (and (class-p type)
- (subtypep class 'smoke-standard-object)
- (derived-p class
- (get-class type)))
- (values (make-instance 'pointer-conversion
- :from class :to (find-smoke-class (get-class type)))
- #'(lambda (o) (cast o (find-smoke-class (get-class type)))))
- (if (and (string= (name type)
- "void*")
- (subtypep class (find-class 'smoke-standard-object)))
- (values (make-instance 'pointer-conversion
- :from class :to (find-class 't))
- #'identity)
- (if (= 0 (type-id type))
- (values (make-instance 'pointer-conversion
- :from class :to (find-class 't))
- #'identity)
- (values nil nil)))))
+(defun coerce-to-void (object)
+ object)
hunk ./src/overload-resolution.lisp 370
-(defun user-conversion-using-class (class type)
- ;; (or (and (subtypep class 'smoke-standard-object)
- ;; [_$_]
- ;; (fboundp (intern (format nil "OPERATOR-~@:(~A~)" (name type))
- ;; :cxx)))))
- (if (subtypep class 'smoke-standard-object)
- (let ((method (find-smoke-method class
- (format nil "operator ~A" [_$_]
- (if (class-p type)
- (name (get-class type))
- (name type))))))
- (when (valid-p method)
- (if (void-p type)
- (warn "Conversion operators not supported by Smoke. Update Smoke.")
- (values (make-instance 'user-conversion)
- #'(lambda (o)
- (format t "CALL ~A~%" o)
- (s-call method (pointer o)))))))
- (if (class-p type)
- (multiple-value-bind (rank method sequence)
- (find-best-viable-function2 #'standard-conversion-sequence-using-classes
- (format nil "~A" (name (get-class type)))
- (list class) (find-smoke-class
- (get-class type)))
- (if (conversion= rank (make-instance 'no-match))
- (values nil nil)
- (values (make-instance 'user-conversion)
- #'(lambda (o)
- (make-instance (find-smoke-class (get-class type))
- :args (list o)))))))))
- [_$_]
-#|
-(defun test-foo ()
- (values
- (multiple-value-list
- (find-best-viable-function "setPen" (list 'string)
- (find-class 'qt:painter)))
- (multiple-value-list
- (find-best-viable-function "QVariant" (list (find-class 'qt:color))
- (find-class 'qt:variant)))))
- [_$_]
-|#
+(defun+using-type conversion-cast object (object type)
+ (when (and (class-p type)
+ (object.typep 'smoke-standard-object)
+ (derived-p (object.type-of) (get-class type)))
+ (make-match 'pointer-conversion
+ 'coerce-cast [_$_]
+ (find-smoke-class (get-class type))
+ :from (object.type-of)
+ :to (find-smoke-class (get-class type)))))
+
+(defun+using-type conversion-void object (object type)
+ (when (and (string= (name type) "void*")
+ (object.typep 'smoke-standard-object))
+ (make-match 'pointer-conversion
+ 'coerce-void
+ nil
+ :from (object.type-of)
+ :to (find-class 't))))
+
+(defun+using-type conversion-pointer object (object type)
+ (when (and (= 0 (type-id type))
+ (object.typep 'foreign-pointer))
+ (make-match 'pointer-conversion 'identity nil
+ :from (object.type-of)
+ :to (find-class 't))))
+ [_$_]
+
+(defun+using-type conversion object (object type)
+ (or (call-using-type conversion-cast object type)
+ (call-using-type conversion-void object type)
+ (call-using-type conversion-pointer object type)))
+
+(defun+using-type user-conversion object (object type)
+ (or (call-using-type operator-conversion object type)
+ (call-using-type constructor-conversion object type)))
+
+(defun+using-type operator-conversion object (object type)
+ (when (object.typep 'smoke-standard-object)
+ (let ((method (find-smoke-method (object.type-of)
+ (format nil "operator ~A" [_$_]
+ (if (class-p type)
+ (name (get-class type))
+ (name type))))))
+ (when (valid-p method)
+ (assert (not (void-p type))
+ ()
+ "Conversion operators not supported by Smoke.
+Update to Smoke >= r955426.")
+ (make-match 'user-conversion
+ (lispify (name method) :cxx))))))
+
+(defun coerce-to-class (object to-class)
+ (make-instance to-class
+ :args (list object)))
+
+(defun+using-type constructor-conversion object (object type)
+ (when (class-p type)
+ (let ((to-class (find-smoke-class (get-class type))))
+ (multiple-value-bind (method sequence)
+ (call-using-types find-best-viable-function2
+ (if (using-typep)
+ #'standard-conversion-sequence-using-types
+ #'standard-conversion-sequence)
+ (format nil "~A" (name (get-class type)))
+ (list object) to-class)
+ (when method
+ (make-match 'user-conversion
+ 'coerce-to-class
+ to-class))))))
hunk ./src/overload-resolution.lisp 442
- (mapcar #'funcall sequence args)))
+ (mapcar #'(lambda (conversion argument)
+ (funcall conversion argument))
+ sequence args)))
hunk ./src/overload-resolution.lisp 453
- (multiple-value-bind (rank method sequence)
+ (multiple-value-bind (method sequence)
hunk ./src/overload-resolution.lisp 455
- (mapcar #'(lambda (a)
- (let ((type (type-of a)))
- (if (subtypep type 'smoke-standard-object)
- (class-of a)
- type)))
- arguments)
+ arguments
hunk ./src/overload-resolution.lisp 458
- (error "No applicable method ~A of ~A for ~S.
+ (error "No applicable method ~S of ~A for ~S.
hunk ./src/overload-resolution.lisp 469
+
+
+(defun cxx-coerce-p-using-type (type result-type)
+ "Returns true when an object of type TYPE can be convertet to an object
+of smoke type RESULT-TYPE."
+)
+ [_$_]
+
+(defun cxx-coerce (object result-type)
+)
hunk ./src/smoke-c/class.lisp 10
-
hunk ./src/smoke-c/smoke-c.lisp 23
- (intern (format nil "UINT~A" (* 8
- (smoke-sizeof-bool)))
- ; (foreign-funcall smoke-sizeof-bool :int)))
+ (intern (format nil "UINT~A" (* 8 (smoke-sizeof-bool)))
hunk ./src/smoke-c/smoke-c.lisp 39
+(deftype smoke-index (&optional (lower -32768) (upper 32767))
+ "Smoke index."
+ `(integer ,lower ,upper))
+
hunk ./src/smoke.lisp 68
-#|
-(defun new-object (binding class-name method-name &rest args)
- (let* ((smoke (smoke-get-smoke binding))
- (pointer
- (pointer-call
- (make-smoke-method (make-smoke-class smoke class-name)
- method-name)
- (null-pointer) args)))
- (let ((object (instance-to-lisp object (find-smoke-class class)
- (return-type)))
-|#
addfile ./src/using-type.lisp
hunk ./src/using-type.lisp 1
+(in-package :smoke)
+
+(defmacro with-object-as-object (object &body body)
+ `(macrolet ((,(alexandria:symbolicate object '.typep)
+ (type)
+ `(typep ,',object ,type))
+ (,(alexandria:symbolicate object '.type-of) ()
+ `(class-of ,',object))
+ (using-typep () nil)
+ (call-using-types (function-name &rest args)
+ `(,function-name ,@args))
+ (call-using-type (function-name &rest args)
+ `(,function-name ,@args)))
+ ,@body))
+
+(defun typep-using-type (object-type type)
+ "Returns true when OBJECT-TYPE is a subtype of TYPE,
+false when it is not"; and :MAYBE when the relationship
+;could not be determined."
+ (declare (values (member t nil :maybe)))
+ (multiple-value-bind (subtype-p valid-p)
+ (subtypep object-type type)
+ (if subtype-p
+ t
+ (if valid-p
+ (multiple-value-bind (subtype-p valid-p)
+ (subtypep type object-type)
+ (if subtype-p [_$_]
+ (throw 'unspecific-type (values object-type type))
+ (if valid-p
+ nil
+ (throw 'unspecific-type (values object-type type)))))
+ (throw 'unspecific-type (values object-type))))))
+
+(defmacro with-object-as-type (object-type &body body)
+ `(macrolet ((,(alexandria:symbolicate object-type '.typep)
+ (type)
+ `(typep-using-type ,',object-type ,type))
+ (,(alexandria:symbolicate object-type '.type-of) ()
+ (quote ,object-type))
+ (using-typep () t)
+ (call-using-types (function-name &rest args)
+ `(,(alexandria:symbolicate function-name '-using-types)
+ ,@args))
+ (call-using-type (function-name &rest args)
+ `(,(alexandria:symbolicate function-name '-using-type)
+ ,@args)))
+ ,@body))
+
+(defmacro defun+using-type (name object lambda-list &body body)
+ "Defines the functions NAME and NAME-using-type where the argument
+OBJECT of LAMBDA-LIST is an object respective its type.
+For OBJECT the functions OBJECT.typep and OBJECT.type-of can be used."
+ `(progn
+ (with-object-as-object ,object
+ (defun ,name ,lambda-list
+ ,@body))
+ (with-object-as-type ,object
+ (defun ,(alexandria:symbolicate name '-using-type) ,lambda-list
+ ,@body))))
+
+(defmacro defun+using-types (name lambda-list &body body)
+ `(progn (macrolet ((call-using-types (function-name &rest args)
+ `(,function-name ,@args))
+ (call-using-type (function-name &rest args)
+ `(,function-name ,@args))
+ (using-typep () nil)
+ (function-using-types (name)
+ `(function ,name)))
+ (defun ,name ,lambda-list
+ ,@body))
+ (macrolet ((call-using-types (function-name &rest args)
+ `(,(alexandria:symbolicate function-name '-using-types)
+ ,@args))
+ (call-using-type (function-name &rest args)
+ `(,(alexandria:symbolicate function-name '-using-type)
+ ,@args))
+ (using-typep () t)
+ (function-using-types (name)
+ `(function ,(alexandria:symbolicate name '-using-types))))
+ (defun ,(alexandria:symbolicate name '-using-types) ,lambda-list
+ ,@body))))
Fri Apr 17 17:26:55 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Experimental C++ style overload resolution.
hunk ./smoke.mbd 37
+ ("overload-resolution" (:needs "package" "smoke"))
hunk ./smoke.mbd 44
- ("method" (:needs "clos"))
+ ("method" (:needs "clos" "overload-resolution"))
hunk ./src/clos.lisp 76
- "Returns camelCase STRING in lisp-style."
+ "Returns camelCase STRING in lisp-style."
hunk ./src/clos.lisp 89
+ (#\ (append-char #\-) ;; space (cast operators)
+ (go-next default))
hunk ./src/clos.lisp 246
+ (call-using-args (first args) (name gf) (rest args)))
+#|
hunk ./src/clos.lisp 253
+|#
hunk ./src/clos.lisp 377
-(defun call-constructor (object args)
- (pointer-call (make-smoke-constructor (class-of object)
- args)
- (null-pointer)
- args))
+(defun call-constructor (object arguments)
+ (if (null arguments)
+ (let ((method (find-smoke-method (class-of object)
+ (name (class-of object)))))
+ (pointer-call method (null-pointer)))
+ (multiple-value-bind (rank method sequence)
+ (find-best-viable-function (name (class-of object))
+ (mapcar #'(lambda (a)
+ (let ((type (type-of a)))
+ (if (subtypep type 'smoke-standard-object)
+ (class-of a)
+ type)))
+ arguments)
+ (class-of object))
+ (when (null method)
+ (error "No construtor ~A for ~S"
+ object arguments))
+ (pointer-call method (null-pointer)
+ (mapcar #'funcall sequence arguments)))))
+; (pointer-call (make-smoke-constructor (class-of object)
+; args)
+; (null-pointer)
+; args))
hunk ./src/method.lisp 62
- (let ((method (find-method-using-args (make-instance 'smoke-class
- :id ,(id class)
- :smoke ,smoke)
- ,method-name args)))
- (s-call method (null-pointer) args)))
+ (call-using-args (find-class (quote ,(lispify (name class))))
+ ,method-name args))
+ ;(let ((method (find-method-using-args (make-instance 'smoke-class
+ ; :id ,(id class)
+ ; :smoke ,smoke)
+ ; ,method-name args)))
+ ; (s-call method (null-pointer) args)))
hunk ./src/objects/method.lisp 27
+(defun unambigous-p (method)
+ "Returns T when METHOD is valid and not ambiguous."
+ (< 0 (id method)))
+
hunk ./src/objects/method.lisp 35
+(defun make-smoke-method-munged (class munged-name-id)
+ "Returns the method for the MUNGED-NAME-ID of SMOKE."
+ (with-foreign-object (module 'smoke-module-index)
+ (smoke-find-method-for-id module (smoke class) (id class) munged-name-id)
+ (make-instance 'smoke-method
+ :id (foreign-slot-value module 'smoke-module-index 'index)
+ :smoke (foreign-slot-value module 'smoke-module-index 'smoke))))
+
+(defun find-smoke-method (class name)
+ "Returns the method NAME of CLASS."
+ (with-foreign-object (m 'smoke-module-index)
+ (smoke-find-method m (smoke class) (id class) name)
+ (make-instance 'smoke-method
+ :id (foreign-slot-value m 'smoke-module-index 'index)
+ :smoke (foreign-slot-value m 'smoke-module-index 'smoke))))
+
hunk ./src/objects/method.lisp 53
- "Returns the method called NAME of CLASS.
-Signals a undefined-method condition when no method was found."
+ "Returns the method NAME of CLASS.
+Signals a undefined-method condition when no method was found.
+Signals an error when the method is ambigious."
addfile ./src/overload-resolution.lisp
hunk ./src/overload-resolution.lisp 1
+;;; C++ overload resolution
+;;; See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf
+
+(in-package :smoke)
+(declaim (optimize (debug 3)))
+
+(deftype smoke-index (&optional (lower -32768) (upper 32767))
+ `(integer ,lower ,upper))
+
+(defun mung-char-p (character)
+ (declare (character character))
+ (case character
+ ((#\$ #\? #\#) t)))
+
+(defun binary-search-method-names (name smoke start end)
+ (declare ((smoke-index 1) start end)
+ (string name)
+ (optimize (speed 3)))
+ (if (> start end)
+ 0
+ (let* ((index (floor (+ end start) 2))
+ (method-name (smoke-get-method-name smoke index))
+ (diff (string/= method-name name)))
+ (if diff
+ (if (and (>= diff (length name))
+ (mung-char-p (char method-name diff)))
+ index
+ (if (and (< diff (length name))
+ (or (>= diff (length method-name))
+ (char< (char method-name diff) (char name diff))))
+ (binary-search-method-names name smoke (1+ index) end)
+ (binary-search-method-names name smoke start (1- index))))
+ index))))
+
+(defun method-name= (name munged)
+ "Returns true when the name of the munged method name MUNGED is NAME."
+ (let ((diff (string/= name munged)))
+ (not (and diff
+ (or (< diff (length name))
+ (not (mung-char-p (char munged diff))))))))
+
+(defun munged-method-argument-count (munged-name)
+ (- (1- (length munged-name))
+ (position-if-not #'mung-char-p munged-name :from-end t)))
+ [_$_]
+(defun method-argument-count= (name munged-name argument-count)
+ (declare ((integer 1 #.call-arguments-limit) argument-count))
+ (and (= (length munged-name) (+ (length name) argument-count))
+ (mung-char-p (char munged-name (length name)))))
+
+(defun position-method-names (name argument-count smoke start end)
+ (declare (string name)
+ ((smoke-index 1) start end)
+ (optimize (speed 3)))
+ (let ((positions (loop for i from start to end
+ while (method-name= name (smoke-get-method-name smoke i))
+ when (method-argument-count= name (smoke-get-method-name smoke i)
+ argument-count)
+ collect i)))
+ (loop for i from (1- start) downto 1
+ while (method-name= name (smoke-get-method-name smoke i))
+ do (when (method-argument-count= name (smoke-get-method-name smoke i)
+ argument-count)
+ (push i positions)))
+ positions))
+
+(defun smoke-modules (class)
+ "Returns a list if super classes of CLASS; one or every smoke module
+that can be reaced by CLASS super classes. The returned super classes
+are as secific as possible."
+ (let ((modules (list class)))
+ (dolist (super-class (closer-mop:class-direct-superclasses class) modules)
+ (when (and (typep super-class 'smoke-standard-class)
+ (not (eql super-class (find-class 'smoke-standard-object))))
+ (dolist (c (smoke-modules super-class))
+ (setf modules (adjoin c modules :key #'smoke)))))))
+
+(defun candidate-functions (name argument-count class2)
+ "Returns a list of methods named NAME that take ARGUMENT-COUNT methods."
+ (let (methods)
+ (dolist (class (smoke-modules class2))
+ (let ((index (binary-search-method-names
+ name (smoke class) 1
+ (smoke-method-name-size (smoke class)))))
+ (loop for i in (position-method-names name argument-count (smoke class)
+ index
+ (smoke-method-name-size [_$_]
+ (smoke class)))
+ do [_$_]
+ (let ((method (make-smoke-method-munged class i)))
+ (if (unambigous-p method)
+ (push method methods)
+ (when (ambiguous-p method)
+ (let ((index (- (id method))))
+ (loop as i = (smoke-ambiguous-method (smoke method)
+ index)
+ while (> i 0) do
+ (incf index)
+ (push (make-instance 'smoke-method
+ :smoke (smoke method)
+ :id i)
+ methods)))))))))
+ methods))
+ [_$_]
+ [_$_]
+
+(defconstant +no-match+ most-positive-fixnum)
+(defconstant +exact-match+ 0)
+(defconstant +promotion+ 1)
+(defconstant +conversion+ 2)
+
+(defclass std-conversion ()
+ ()
+ (:documentation "A conversion"))
+
+(defclass no-match (std-conversion)
+ ((rank :reader rank
+ :allocation :class
+ :initform +no-match+)))
+(defclass exact-match (std-conversion)
+ ((rank :reader rank
+ :allocation :class
+ :initform +exact-match+)))
+
+(defclass promotion (std-conversion)
+ ((rank :reader rank
+ :allocation :class
+ :initform +promotion+)))
+
+(defclass number-conversion (std-conversion)
+ ((rank :reader rank
+ :allocation :class
+ :initform +conversion+)))
+
+(defclass pointer-conversion (std-conversion)
+ ((rank :reader rank
+ :allocation :class
+ :initform (1+ +conversion+))
+ (from :reader from
+ :initarg :from)
+ (to :reader to
+ :initarg :to)))
+
+(defclass boolean-conversion (std-conversion)
+ ((rank :reader rank
+ :allocation :class
+ :initform (1+ +conversion+))))
+
+(defclass user-conversion (std-conversion)
+ ((rank :reader rank
+ :allocation :class
+ :initform (1+ +conversion+))))
+
+(defgeneric conversion< (conversion1 conversion2)
+ (:documentation
+ "Retruns true when CONVERSION1 is better than CONVERSION2.")
+ ;; 13.3.3.2 Ranking implicit conversion sequences
+ ;; 4
+ (:method (conversion1 conversion2)
+ (or (null conversion2)
+ (< (rank conversion1) (rank conversion2))))
+ (:method ((conversion1 pointer-conversion) (conversion2 pointer-conversion))
+ (if (eq (from conversion1) (from conversion2))
+ ;; A->B < A->C <=> B subclass of C
+ (subtypep (to conversion1) (to conversion2))
+ (if (eq (to conversion1) (to conversion2))
+ ;; B->A < C->A <=> B subclass of C
+ (subtypep (from conversion1) (from conversion2))
+ nil))))
+
+(defgeneric conversion= (conversion1 conversion2)
+ (:documentation
+ "Returns true when the standard conversion sequence CONVERSION1
+ is indistinguishable from CONVERSION2.")
+ (:method (conversion1 conversion2)
+ (= (rank conversion1) (rank conversion2)))
+ (:method ((conversion1 pointer-conversion) (conversion2 pointer-conversion))
+ (and (not (conversion< conversion1 conversion2))
+ (not (conversion< conversion2 conversion1)))))
+
+(defun max-conversion (conversion1 conversion2)
+ (if (null conversion2)
+ conversion1
+ (if (conversion< conversion1 conversion2)
+ conversion2
+ conversion1)))
+ [_$_]
+(defun conversion-sequence-for-type (class type &optional user)
+ (if (exact-match-using-class class type)
+ (values (make-instance 'exact-match) #'identity)
+ (multiple-value-bind (match function)
+ (promotion-using-class class type)
+ (if match
+ (values (make-instance 'promotion) function)
+ (multiple-value-bind (m2 function2)
+ (conversion-using-class class type)
+ (if m2
+ (values m2 function2)
+ (if user
+ (user-conversion-using-class class type)
+ (values nil nil))))))))
+
+(defun standard-conversion-sequence-using-classes (method classes &optional user)
+ (let ((max-rank)
+ (conversions))
+ ;(format t "~A~%~3T~A~%" method classes)
+ (loop for type in (arguments method)
+ for class in classes do
+ ;(format t "~%C ~A ~A~%" type class)
+ (multiple-value-bind (rank function)
+ (conversion-sequence-for-type class type user)
+ (when (null rank)
+ (setf max-rank nil)
+ (return nil))
+ (setf max-rank (max-conversion rank max-rank))
+ (push function conversions)))
+ (values max-rank (reverse conversions))))
+
+(defun conversion-sequence-using-classes (method classes)
+ (standard-conversion-sequence-using-classes method classes t))
+
+(defun find-best-viable-function (name classes class)
+ (find-best-viable-function2 #'conversion-sequence-using-classes
+ name classes class))
+
+(defun find-best-viable-function2 (get-sequence name classes class)
+ (declare (type (function (t list) (values t function)) get-sequence))
+ (let ((candidate-functions (candidate-functions name (length classes)
+ class))
+ (best-rank (make-instance 'no-match))
+ (best-method)
+ (conversions))
+ (loop for method in candidate-functions do
+ (multiple-value-bind (rank method-conversions)
+ (funcall get-sequence method classes)
+ (when (and rank (conversion< rank best-rank))
+ (setf best-rank rank)
+ (setf best-method method)
+ (setf conversions method-conversions)
+ (when (conversion= rank (make-instance 'exact-match))
+ (return)))))
+ (values best-rank best-method conversions)))
+
+(defmacro string-case ((keyform) &body clauses)
+ ;; FIXME this is horribly inefficient
+ `(cond ,@(mapcar #'(lambda (clause)
+ `((string= ,keyform ,(first clause))
+ ,@(rest clause)))
+ clauses)))
+
+(defmacro smoke-type-case ((keyform class) &body clauses)
+ `(string-case ((name ,keyform))
+ ,@(mapcar (alexandria:curry #'apply
+ #'(lambda (type-name lisp-type)
+ `(,type-name (subtypep ,class (quote ,lisp-type)))))
+ clauses)))
+ [_$_]
+(defun exact-match-using-class (class type)
+ (declare (values boolean))
+ (case (type-id type)
+ (0 (smoke-type-case (type class)
+ ("const QString&" string)
+ ("const char*" string)
+ ("void*" cffi:foreign-pointer)
+ ("const void*" cffi:foreign-pointer)
+ ("void**" cffi:foreign-pointer)))
+ (1 (subtypep class 'boolean))
+ (2 (subtypep class 'character))
+ (6 (subtypep class 'integer))
+ (7 (subtypep class '(integer 0)))
+ (10 (subtypep class 'single-float))
+ (11 (subtypep class 'double-float))
+ (12 (subtypep class 'enum)) ;; FIXME enum-type
+ (13 (and (subtypep class (find-class 'smoke-standard-object))
+ (type= type class)))))
+ [_$_]
+(defun make-auto-pointer (pointer)
+ "Returns a pointer that frees the memory at POINTER when it is finalized."
+ (let ((address (pointer-address pointer)))
+ (tg:finalize pointer #'(lambda ()
+ (foreign-free (make-pointer address))))))
+
+(defun promotion-using-class (class type)
+ (declare (smoke-type type))
+ ;(values boolean (or nil function)))
+ (case (type-id type)
+ (0
+ (if (and (string= (name type)
+ "const char*")
+ ; (subtypep class '(simple-array character *)))
+ (subtypep class 'string))
+ (values t #'(lambda (string)
+ (make-auto-pointer (foreign-string-alloc string))))
+ (values nil nil)))
+ (6 (and (subtypep class 'enum)
+ (values t #'cxx-support:value)))))
+ [_$_]
+; (smoke-type-case (type class)
+; ("double" single-float)))
+
+(defun conversion-using-class (class type)
+ (if (and (class-p type)
+ (subtypep class 'smoke-standard-object)
+ (derived-p class
+ (get-class type)))
+ (values (make-instance 'pointer-conversion
+ :from class :to (find-smoke-class (get-class type)))
+ #'(lambda (o) (cast o (find-smoke-class (get-class type)))))
+ (if (and (string= (name type)
+ "void*")
+ (subtypep class (find-class 'smoke-standard-object)))
+ (values (make-instance 'pointer-conversion
+ :from class :to (find-class 't))
+ #'identity)
+ (if (= 0 (type-id type))
+ (values (make-instance 'pointer-conversion
+ :from class :to (find-class 't))
+ #'identity)
+ (values nil nil)))))
+
+(defun user-conversion-using-class (class type)
+ ;; (or (and (subtypep class 'smoke-standard-object)
+ ;; [_$_]
+ ;; (fboundp (intern (format nil "OPERATOR-~@:(~A~)" (name type))
+ ;; :cxx)))))
+ (if (subtypep class 'smoke-standard-object)
+ (let ((method (find-smoke-method class
+ (format nil "operator ~A" [_$_]
+ (if (class-p type)
+ (name (get-class type))
+ (name type))))))
+ (when (valid-p method)
+ (if (void-p type)
+ (warn "Conversion operators not supported by Smoke. Update Smoke.")
+ (values (make-instance 'user-conversion)
+ #'(lambda (o)
+ (format t "CALL ~A~%" o)
+ (s-call method (pointer o)))))))
+ (if (class-p type)
+ (multiple-value-bind (rank method sequence)
+ (find-best-viable-function2 #'standard-conversion-sequence-using-classes
+ (format nil "~A" (name (get-class type)))
+ (list class) (find-smoke-class
+ (get-class type)))
+ (if (conversion= rank (make-instance 'no-match))
+ (values nil nil)
+ (values (make-instance 'user-conversion)
+ #'(lambda (o)
+ (make-instance (find-smoke-class (get-class type))
+ :args (list o)))))))))
+ [_$_]
+#|
+(defun test-foo ()
+ (values
+ (multiple-value-list
+ (find-best-viable-function "setPen" (list 'string)
+ (find-class 'qt:painter)))
+ (multiple-value-list
+ (find-best-viable-function "QVariant" (list (find-class 'qt:color))
+ (find-class 'qt:variant)))))
+ [_$_]
+|#
+
+(defun call-sequence (method object sequence &rest args)
+ (s-call method object
+ (mapcar #'funcall sequence args)))
+ [_$_]
+(defun call-using-args (object-or-class name arguments)
+ (if (null arguments)
+ (let ((method (find-smoke-method (smoke-class-of object-or-class)
+ name)))
+ (if (static-p method)
+ (s-call method (null-pointer))
+ (s-call method (cast object-or-class (get-class method)))))
+ (multiple-value-bind (rank method sequence)
+ (find-best-viable-function name
+ (mapcar #'(lambda (a)
+ (let ((type (type-of a)))
+ (if (subtypep type 'smoke-standard-object)
+ (class-of a)
+ type)))
+ arguments)
+ (smoke-class-of object-or-class))
+ (when (null method)
+ (error "No applicable method ~A of ~A for ~S.
+Candidates are:~{~T~A~%~}."
+ name object-or-class arguments
+ (mapcar #'signature
+ (candidate-functions name
+ (length arguments)
+ (smoke-class-of object-or-class)))))
+ (if (static-p method)
+ (apply #'call-sequence method (null-pointer) sequence arguments)
+ (apply #'call-sequence method (cast object-or-class (get-class method)) [_$_]
+ sequence arguments)))))
addfile ./src/smoke-c/cl_smoke.h
hunk ./src/smoke-c/cl_smoke.h 1
+#include <smoke.h>
+
+
+/** @brief Common Lisp smoke binding namespace. */
+namespace cl_smoke
+{
+class Binding;
+
+/** A Binding */
+typedef void* smoke_binding;
+
+/** Casts the void pointer smoke_binding to the Binding class.
+ * @param smoke the smoke binding
+ *
+ * @return pointer to the Binding instance
+ */
+static inline
+Binding*
+get_smoke_binding(smoke_binding binding)
+{
+ return static_cast<Binding*>(binding);
+}
+
+/** Casts the void pointer smoke to the Smoke class.
+ * @param smoke the Smoke module
+ *
+ * @return pointer to the Smoke module.
+ */
+static inline
+Smoke*
+get_smoke(void* smoke)
+{
+ return static_cast<Smoke*>(smoke);
+}
+} // namespace cl_smoke
hunk ./src/smoke-c/method.lisp 26
+(defcstruct smoke-method-map
+ "Maps a munged method."
+ (class-id smoke-index)
+ (name smoke-index)
+ (method smoke-index))
+
+(defcfun smoke-get-method-map (:pointer smoke-method-map)
+ (smoke :pointer)
+ (index smoke-index))
+
+(defcfun smoke-find-method-for-id :void
+ (m :pointer smoke-module-index)
+ (smoke :pointer)
+ (class-index smoke-index)
+ (method-name smoke-index))
+
hunk ./src/smoke-c/method.lisp 62
-(defcfun smoke-call-method :string
+(defcfun smoke-call-method :void
hunk ./src/smoke-c/smoke-c.cpp 2
+#include "cl_smoke.h"
hunk ./src/smoke-c/smoke-c.cpp 10
- * \@brief C wrapper the Smoke bindings.
+ * @brief C wrapper the Smoke bindings.
hunk ./src/smoke-c/smoke-c.cpp 12
- * \example examples/kde-hello-world.cpp
+ * @example examples/kde-hello-world.cpp
hunk ./src/smoke-c/smoke-c.cpp 18
- * \image html doc/images/kde-hello-world.png "Screenshot"
- * \image latex doc/images/kde-hello-world.png "Screenshot" width=5cm
+ * @image html doc/images/kde-hello-world.png "Screenshot"
+ * @image latex doc/images/kde-hello-world.png "Screenshot" width=5cm
hunk ./src/smoke-c/smoke-c.cpp 22
-
-/** @brief Common Lisp smoke binding namespace. */
-namespace cl_smoke
-{
-
-/** A Binding */
-typedef void* smoke_binding;
-
-/** Casts the void pointer smoke_binding to the Binding class.
- * @param smoke the smoke binding
- *
- * @return pointer to the Binding instance
- */
-static inline
-Binding*
-get_smoke_binding(smoke_binding binding)
-{
- return static_cast<Binding*>(binding);
-}
-
-/** Casts the void pointer smoke to the Smoke class.
- * @param smoke the Smoke module
- *
- * @return pointer to the Smoke module.
- */
-static inline
-Smoke*
-get_smoke(void* smoke)
-{
- return static_cast<Smoke*>(smoke);
-}
-} // namespace cl_smoke
-
hunk ./src/smoke-c/smoke-c.cpp 268
+/** Finds a method for a class and a munged name.
+ * @param m pointer where the result is stored.
+ * @param smoke the Smoke binding
+ * @param class_index index of the class
+ * @param method_name index of the munged method name
+ */
+void
+smoke_find_method_for_id(Smoke::ModuleIndex* m, void* smoke,
+ Smoke::Index class_index, Smoke::Index method_name)
+{
+ *m = get_smoke(smoke)->findMethod((Smoke::ModuleIndex){get_smoke(smoke), class_index},
+ (Smoke::ModuleIndex){get_smoke(smoke), method_name});
+
+ if(m->index > 0)
+ m->index = smoke_get_method_map(m->smoke, m->index)->method;
+}
+
hunk ./src/smoke-c/smoke-c.cpp 305
- *
- * @return NULL on success or a description of the exception that occurred.
hunk ./src/smoke-c/smoke-c.cpp 306
-const char*
+void
hunk ./src/smoke-c/smoke-c.cpp 330
- return e.what();
+ return;
hunk ./src/smoke-c/smoke-c.cpp 334
- qFatal("exception");
- return NULL;
+ qFatal("exception in C++ code.");
hunk ./src/smoke-c/smoke-c.cpp 336
-
- return NULL;
hunk ./src/smoke-c/smoke-c.lisp 3
+#|
hunk ./src/smoke-c/smoke-c.lisp 13
+|#
hunk ./src/smoke-c/smoke-c.lisp 33
-(close-foreign-library 'libsmoke-c-util)
+;(close-foreign-library 'libsmoke-c-util)
Tue Apr 14 16:23:24 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* License
addfile ./COPYING
hunk ./COPYING 1
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+ [_$_]
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+ [_$_]
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
addfile ./LICENSE
hunk ./LICENSE 1
+The software in this package is distributed under the GNU General Public
+License (with a special exception described below).
+
+A copy of GNU General Public License (GPL) is included in this distribution,
+in the file COPYING. [_$_]
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+ [_$_]
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version.
hunk ./smoke.mbd 28
+ (:license "GPL with linking exception")
hunk ./src/smoke.lisp 1
-(in-package #:smoke)
+;;; Copyright (C) 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
+;;;
+;;; This program is free software: you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation, either version 3 of the License, or
+;;; (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+;;;
+;;; As a special exception, the copyright holders of this library give you
+;;; permission to link this library with independent modules to produce an
+;;; executable, regardless of the license terms of these independent
+;;; modules, and to copy and distribute the resulting executable under
+;;; terms of your choice, provided that you also meet, for each linked
+;;; independent module, the terms and conditions of the license of that
+;;; module. An independent module is a module which is not derived from or
+;;; based on this library. If you modify this library, you may extend this
+;;; exception to your version of the library, but you are not obligated to
+;;; do so. If you do not wish to do so, delete this exception statement
+;;; from your version.
hunk ./src/smoke.lisp 28
-(declaim (optimize (debug 3)))
+(in-package #:smoke)
Tue Apr 14 11:12:10 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Do not use :asdf in :smoke package
hunk ./src/package.lisp 13
- (:use #:cl #:asdf #:cffi #:trivial-garbage #:bordeaux-threads #:cxx-support)
+ (:use #:cl #:cffi #:trivial-garbage #:bordeaux-threads #:cxx-support)
Sun Apr 12 22:25:47 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* fix cxx generic function documentation generation
hunk ./src/objects/method.lisp 169
+ (declare (function function)
+ (cffi:foreign-pointer smoke)
+ (optimize (speed 3)))
hunk ./src/objects/method.lisp 174
- :smoke smoke)))
- (loop for id from 1 to (1- (smoke-methods-size smoke)) do
- (when (= (mod id (floor (smoke-methods-size smoke) 10)) 0)
- (format t "[ ~A ]~%" (* 10
- (floor (* 10 id)
- (smoke-methods-size smoke)))))
+ :smoke smoke))
+ (length (1- (the fixnum (smoke-methods-size smoke)))))
+ (loop for id from 1 to length do
hunk ./src/smoke.lisp 101
-(defmethod documentation ((class smoke-standard-class) (doc-type t))
+(defmethod documentation ((class smoke-standard-class) (doc-type (eql 't)))
+ (declare (optimize (speed 3)))
hunk ./src/smoke.lisp 105
-(defmethod documentation ((gf smoke-gf) (doc-type t))
+;; No eql T since all-methods is to slow to be used in conjunction with
+;; mb:document
+(defmethod documentation ((gf smoke-gf) (doc-type (eql 'cxx-function)))
+ (declare (optimize (speed 3)))
hunk ./src/smoke.lisp 116
+ ;;FIXME speed this up, needed by (mb:document :smoke).
+ (declare (string name)
+ (optimize (speed 3)))
Sun Apr 12 21:53:53 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Export cxx operator functions.
hunk ./src/package.lisp 35
- (:export #:class))
+ (:export #:class
+ [_$_]
+ #:= ;; These are defined in :qt since we need QGlobalSpace
+ #:/=
+ #:< #:<=
+ #:> #:>=
+ #:incf
+ #:decf
+ #:+
+ #:-
+ #:*
+ #:/
+ #:1+
+ #:1-
+ [_$_]
+ #:aref))
Sun Apr 12 21:53:26 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Support passing character arguments
hunk ./src/objects/method.lisp 106
+ (character #\$)
hunk ./src/objects/stack.lisp 41
- (2 (push-stack stack value 'char))
+ (2 (push-stack stack (char-code value) 'char))
Sun Apr 12 16:43:33 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Support overloading by argument count for cxx: generic functions.
hunk ./smoke.mbd 40
- ("clos" (:needs "smoke-c" "objects" "object-map" "class-map" "bindings"))
+ ("cxx-method" (:needs "package"))
+ ("clos" (:needs "smoke-c" "cxx-method" "objects" "object-map" "class-map" "bindings"))
hunk ./src/clos.lisp 75
-
- [_$_]
-
hunk ./src/clos.lisp 210
- (declare (optimize (speed 3)))
+ (declare (optimize (speed 3))
+ (cffi:foreign-pointer smoke))
hunk ./src/clos.lisp 227
-(defun generic-lambda-list (method)
- "Returns the lisp lambda list for METHOD."
- (if (static-p method)
- '(class &rest args)
- '(object &rest args)))
-
-(defclass smoke-gf (standard-generic-function)
- ((cxx-name :reader name :initarg :cxx-name))
+(defclass smoke-gf (cxx-generic-function)
+ ((cxx-name :reader name :initarg :cxx-name
+ :type string))
hunk ./src/clos.lisp 239
-;;; To speed up the startup (MAKE-SMOKE-METHODS)
+;;; To speed up the startup
hunk ./src/clos.lisp 243
+ (declare (optimize (speed 3)))
hunk ./src/clos.lisp 250
-(defmethod add-method :after ((gf smoke-gf) method)
+(defmethod add-method :after ((gf cxx-method-generic-function) method)
hunk ./src/clos.lisp 253
- (closer-mop:ensure-method gf
- `(lambda (object &rest args)
- (let ((method (find-method-using-args (smoke-class-of object)
- (name ,gf)
- args)))
- (if (static-p method)
- (s-call method (null-pointer) args)
- (s-call method (cast object (get-class method)) args)))))))
+ (let ((lambda-list (closer-mop:method-lambda-list method)))
+ (closer-mop:ensure-method
+ gf
+ `(lambda ,lambda-list
+ (declare (optimize (speed 3)))
+ (let ((method (find-method-using-args (smoke-class-of ,(first lambda-list))
+ (name ,(cxx-generic-function gf))
+ (list ,@(rest lambda-list)))))
+ (if (static-p method)
+ (s-call method (null-pointer) (list ,@lambda-list))
+ (s-call method (cast ,(first lambda-list) (get-class method))
+ (list ,@(rest lambda-list))))))))))
hunk ./src/clos.lisp 326
- (if (null (closer-mop:generic-function-methods gf))
+ (if (null (gf-methods gf))
addfile ./src/cxx-method.lisp
hunk ./src/cxx-method.lisp 1
+(in-package :smoke)
+
+(defclass cxx-method-generic-function (standard-generic-function)
+ ((generic-function :accessor cxx-generic-function
+ :initarg :cxx-generic-function
+ :type cxx-generic-function
+ :documentation "Contains the generic function."))
+ (:metaclass closer-mop:funcallable-standard-class)
+ (:documentation "Generic function of a specify argument count."))
+
+(defclass cxx-generic-function (standard-generic-function)
+ ((gf-methods :initform nil
+ :accessor gf-methods
+ :type list
+ :documentation "Generic functions for different argument counts."))
+ (:metaclass closer-mop:funcallable-standard-class)
+ (:documentation
+ "A generic function that can be overloaded by argument count."))
+
+(defun make-lambda (argument-count)
+ "Returns a lambda expression for ARGUMENT-COUNT arguments."
+ (declare ((integer 0) argument-count))
+ (loop for i from 0 below argument-count
+ collect (intern (format nil "A~A" i))))
+
+(defun argument-count (generic-function)
+ "Returns the number of arguments to GENERIC-FUNCTION."
+ (length (closer-mop:generic-function-lambda-list generic-function)))
+
+(defun find-generic-function-by-argument-count (cxx-generic-function argument-count)
+ "Returns the generic function of CXX-GENERIC-FUNCTION that takes
+ARGUMENT-COUNT arguments, or false when no such function exists."
+ (declare (cxx-generic-function cxx-generic-function)
+ ((integer 0) argument-count)
+ (values (or cxx-method-generic-function null)))
+ (find-if #'(lambda (gf)
+ (= argument-count
+ (argument-count gf)))
+ (gf-methods cxx-generic-function)))
+
+(defun ensure-gf-by-argument-count (cxx-generic-function argument-count)
+ "Returns the generic-function of CXX-GENERIC-FUNCTION that takes
+ARGUMENT-COUNT arguments. When none exists, one is created."
+ (declare (cxx-generic-function cxx-generic-function)
+ ((integer 0) argument-count))
+ (or (find-generic-function-by-argument-count cxx-generic-function
+ argument-count)
+ (let ((gf (make-instance 'cxx-method-generic-function
+ :cxx-generic-function cxx-generic-function
+ :lambda-list (make-lambda argument-count))))
+ (push gf (gf-methods cxx-generic-function))
+ gf)))
+
+(defun method-argument-count (method)
+ "Returns the number of arguments of METHOD."
+ (length (closer-mop:method-lambda-list method)))
+ [_$_]
+(defun lambda-list-keywords-p (lambda-list)
+ "Returns true when LAMBDA-LIST contains a lambda list keyword
+and false otherwise."
+ (not (null (intersection lambda-list-keywords lambda-list))))
+
+(defun check-cxx-method-argument-list (method)
+ "Signals an error when METHOD contains lambda list keywords."
+ (assert (not (lambda-list-keywords-p (closer-mop:method-lambda-list method)))
+ ()
+ "The method ~A must not contatin lambda list keywords." method))
+
+(defun push-method (method cxx-generic-function)
+ "Adds METHOD to a cxx-method-generic-function of CXX-GENERIC-FUNCTION."
+ (declare (optimize (speed 3)))
+ (let ((generic-function (ensure-gf-by-argument-count cxx-generic-function
+ (method-argument-count method))))
+ (add-method generic-function method)))
+
+(defun unpush-method (method cxx-generic-function)
+ "Removes METHOD from its generic-function."
+ (let ((generic-function (closer-mop:method-generic-function method)))
+ (when generic-function
+ (remove-method (closer-mop:method-generic-function) method))))
+ ;(when (null (closer-mop:generic-function-methods generic-function))
+ ; TODO
+ [_$_]
+(defmethod no-applicable-method ((gf cxx-method-generic-function) &rest args)
+ (apply #'no-applicable-method (cxx-generic-function gf) args))
+
+(defmethod closer-mop:compute-applicable-methods-using-classes ((gf cxx-generic-function) classes)
+ (let ((gf2 (find-generic-function-by-argument-count gf (length classes))))
+ (if gf2
+ (values (list gf2) t)
+ (values nil t))))
+
+(defmethod closer-mop:compute-discriminating-function ((cxx-generic-function cxx-generic-function))
+ (declare (optimize (speed 3)))
+ ;; Special case no methods, since it will apply to all cxx generic functions
+ ;; on startup and the eval stuff is slower.
+ (if (null (gf-methods cxx-generic-function))
+ #'(lambda (&rest args)
+ (apply #'no-applicable-method cxx-generic-function args))
+ (eval [_$_]
+ `#'(lambda (&rest args)
+ (case (length args)
+ ,@(loop for gf in (gf-methods cxx-generic-function)
+ collect `(,(argument-count gf)
+ (apply ,gf args)))
+ (t (apply #'no-applicable-method ,cxx-generic-function args)))))))
+
+
+(defmethod compute-applicable-methods ((gf cxx-generic-function) arguments)
+ ;; -using-classes only cares abount the number of arguments;
+ ;; thus no the to actually pass the classes.
+ (closer-mop:compute-applicable-methods-using-classes gf arguments))
+ [_$_]
+(defun update-method (generic-function action method)
+ "Updates GENERIC-FUNCTION when METHOD has been added or removed;
+and updates the dependents."
+ (declare (generic-function generic-function)
+ ((member add-method remove-method) action)
+ (standard-method method)
+ (optimize (speed 3)))
+ (closer-mop:set-funcallable-instance-function
+ generic-function
+ (closer-mop:compute-discriminating-function generic-function))
+ (closer-mop:map-dependents
+ (class-of generic-function)
+ #'(lambda (dependent)
+ (closer-mop:update-dependent (class-of generic-function)
+ dependent
+ action method))))
+
+(defmethod add-method ((gf cxx-generic-function) method)
+ (declare (optimize (speed 3)))
+ (push-method method gf)
+ (update-method gf 'add-method method))
+
+(defmethod remove-method ((gf cxx-generic-function) method)
+ (unpush-method method gf)
+ (update-method gf 'remove-method method))
hunk ./src/method.lisp 79
+ (declare (list symbols-names)
+ (optimize (speed 3)))
hunk ./src/method.lisp 83
- :cxx-name (rest symbol-name)
- :generic-function-class 'smoke-gf
- :lambda-list '(object &rest args))
-
+ :cxx-name (rest symbol-name)
+ :generic-function-class 'smoke-gf
+ :lambda-list '(object &rest args))
hunk ./src/method.lisp 137
- (eval-when (:load-toplevel)
+ (eval-when (:load-toplevel :execute)
hunk ./src/method.lisp 139
- (make-smoke-classes ,smoke)
- )
+ (make-smoke-classes ,smoke))
hunk ./src/object-map.lisp 7
- "Maps eisp object to Smoke C++ object of a class.")
+ "Maps a lisp object to Smoke C++ object.")
hunk ./src/smoke.lisp 72
- (make-smoke-method class method-name)
- pointer))
+ (make-smoke-method class method-name)
+ pointer))
Wed Apr 8 17:18:53 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Free translated return values (fix memleak)
hunk ./src/objects/stack.lisp 120
- ;(warn "Unknown translation from ~A to lisp." (name type))
+ ;;(warn "Unknown translation from ~A to lisp." (name type))
hunk ./src/objects/stack.lisp 122
- (convert-from-foreign (foreign-slot-value stack-item
- 'smoke-stack-item
- 'voidp)
- cffi-type))))
+ (let* ((pointer (foreign-slot-value stack-item
+ 'smoke-stack-item
+ 'voidp))
+ (value (convert-from-foreign pointer cffi-type)))
+ (when (stack-p type)
+ ;; FIXME free-translated-object is not intended for this;
+ ;; param is NIL for now.
+ (cffi:free-translated-object pointer cffi-type nil))
+ value
+ ))))
Wed Apr 8 17:18:07 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* assert that binding exists
hunk ./src/bindings.lisp 12
- (gethash (pointer-address smoke) *bindings*)))
+ (multiple-value-bind (value present-p)
+ (gethash (pointer-address smoke) *bindings*)
+ (assert (eql t present-p)
+ ()
+ "No binding for ~A." smoke)
+ value)))
Tue Apr 7 11:49:04 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* cmucl support
hunk ./src/clos.lisp 235
-(defclass smoke-gf (standard-generic-function smoke-method)
- ()
+(defclass smoke-gf (standard-generic-function)
+ ((cxx-name :reader name :initarg :cxx-name))
hunk ./src/method.lisp 77
-(defun ensure-generic-methods (names-and-ids smoke)
- "Ensures the generic functions in NAMES-AND-IDS for the Smoke module SMOKE."
- (dolist (name-id names-and-ids)
- (ensure-generic-function (first name-id)
- :id (rest name-id)
- :smoke smoke
+(defun ensure-generic-methods (symbols-names)
+ "Ensures the generic functions for SYMBOLS-NAMES."
+ (dolist (symbol-name symbols-names)
+ (ensure-generic-function (first symbol-name)
+ :cxx-name (rest symbol-name)
hunk ./src/method.lisp 85
- (export (first name-id) :CXX)))
+ (export (first symbol-name) :CXX)))
hunk ./src/method.lisp 125
- (id method))
+ (name method))
hunk ./src/method.lisp 137
- (ensure-generic-methods ',(hash-table-key-values generics) ,smoke)
+ (ensure-generic-methods ',(hash-table-key-values generics))
Mon Apr 6 13:48:20 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Tests on darcs record
addfile ./test.lisp
hunk ./test.lisp 1
+#|
+exec -a "$0" sbcl --noinform --noprint --disable-debugger --load $0 --end-toplevel-options "$@"
+# do not use --script to allow loading mudballs with ${HOME}/.sbclrc
+# Used for testing on darcs record.
+|#
+
+
+(in-package :sysdef-user)
+
+(defun load-sysdef (pathname system)
+ (load pathname)
+ (setf (mb.sysdef::pathname-of (find-system system)) pathname))
+
+(defun load-sysdef-file (system-name)
+ "Loads a mbd file in the current directory."
+ (load-sysdef (make-pathname :defaults *default-pathname-defaults*
+ :name (string-downcase system-name)
+ :type "mbd")
+ system-name))
+
+(load-sysdef-file :smoke)
+(mb:clean :smoke)
+(mb:test :smoke)
+
+(sb-ext:quit)
adddir ./tests
addfile ./tests/test.lisp
hunk ./tests/test.lisp 1
+;;; :smoke has no test suite, but since :qt depends on :smoke we can use its.
+
+(mb:test :qt)
changepref test
sh ./test.lisp
Sun Apr 5 17:36:29 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* initial import
addfile ./CMakeLists.txt
hunk ./CMakeLists.txt 1
+cmake_minimum_required(VERSION 2.6)
+
+project(smoke)
+
+add_subdirectory(src)
+add_subdirectory(examples)
+
+include(UseDoxygen OPTIONAL)
addfile ./TODO
hunk ./TODO 1
+Methods:
+ * C++ overload resolution & argument promotion
+ => no more writing (make-instance 'qt:byte-array :args ("foo"))
+ * Test for null pointer in this and for references
+ * default arguments
+ * fetch name of arguments
+
+* const correctness
+
+* keyword arguments for make-instance
+
+* QApplication and KCmdLineArgs.init call exit() on e.g. "--help"
+
+Testsuite:
+ * Fix segfaults when lots of qt:applictions are created & deleted
+ * Test condition & restarts
+
+finalization:
+ * get rid of owned-p
+ * use QObject::deleteLater ?
+
+* Exceptions
adddir ./examples
addfile ./examples/CMakeLists.txt
hunk ./examples/CMakeLists.txt 1
+
+find_package(Qt4)
+set(QT_DONT_USE_QTGUI true)
+include(${QT_USE_FILE})
+
+find_library(SMOKE_KDE_LIBRARY smokekde)
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(smokekde DEFAULT_MSG SMOKE_KDE_LIBRARY)
+
+## kde-hello-world
+if(SMOKE_KDE_LIBRARY)
+ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../src/smoke-c/")
+
+ add_executable(kde-hello-world kde-hello-world.cpp ../src/smoke-c/csmokebinding.cpp)
+ target_link_libraries(kde-hello-world ${SMOKE_KDE_LIBRARY})
+endif(SMOKE_KDE_LIBRARY)
addfile ./examples/kde-hello-world.cpp
hunk ./examples/kde-hello-world.cpp 1
+/*
+ * Copyright 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Hello world example using libsmoke-c.
+ * Display an KDE Window. */
+
+#include <smoke/qt_smoke.h>
+#include <smoke/kde_smoke.h>
+
+#include "smoke-c.cpp"
+
+#include <iostream>
+
+using namespace std;
+using namespace cl_smoke;
+
+static void
+destructed(Binding* binding, Smoke::Index class_id,
+ void* object)
+{
+ cout << "destructed: " << binding->className(class_id) << endl;
+}
+
+/** No method dispatch in this example. */
+static int
+dispatch(Binding* binding, Smoke::Index method,
+ void* object, Smoke::Stack args, int abstract)
+{
+ return false;
+}
+
+int
+main(int argc, char** argv)
+{
+ init_kde_Smoke(); // calls also init_qt_Smoke();
+ smoke_binding kde = smoke_init(kde_Smoke, reinterpret_cast<void*>(&destructed),
+ reinterpret_cast<void*>(&dispatch));
+ smoke_binding qt = smoke_init(qt_Smoke, reinterpret_cast<void*>(&destructed),
+ reinterpret_cast<void*>(&dispatch));
+
+ Smoke::StackItem stack[5];
+ Smoke::ModuleIndex m;
+ Smoke::ModuleIndex c;
+
+ // bytearray = new QByteArray("foo");
+ {
+ char str[] = "foo";
+
+ smoke_find_class(&c, qt_Smoke, "QByteArray");
+ smoke_find_method(&m, qt_Smoke, c.index, "QByteArray$");
+
+ stack[1].s_class = str;
+
+ smoke_call_method(qt_Smoke, m.index, NULL, stack);
+ }
+ void* bytearray = stack[0].s_class;
+
+
+ // l10n = ki18n(bar);
+ {
+ char str[] = "hello world";
+ smoke_find_class(&c, kde_Smoke, "QGlobalSpace");
+ smoke_find_method(&m, kde_Smoke, c.index, "ki18n$");
+
+ stack[1].s_class = str;
+
+ smoke_call_method(kde_Smoke, m.index, NULL, stack);
+ }
+ void* l10n = stack[0].s_class;
+
+ // about = KAboutData(bytearray, bytearray, l10n, bytearray);
+ {
+ smoke_find_class(&c, kde_Smoke, "KAboutData");
+ smoke_find_method(&m, kde_Smoke, c.index, "KAboutData####");
+
+ stack[1].s_class = bytearray;
+ stack[2].s_class = bytearray;
+ stack[3].s_class = l10n;
+ stack[4].s_class = bytearray;
+
+ smoke_call_method(kde_Smoke, m.index, NULL, stack);
+ }
+ void* about = stack[0].s_class;
+
+
+ // KCmdLineArgs::init(argc, argv, about);
+ {
+ smoke_find_class(&c, kde_Smoke, "KCmdLineArgs");
+ smoke_find_method(&m, kde_Smoke, c.index, "init$?#");
+
+ stack[1].s_int = argc;
+ stack[2].s_class = argv;
+ stack[3].s_class = about;
+
+ smoke_call_method(kde_Smoke, m.index, NULL, stack);
+ }
+
+ // app = new KApplication();
+ void* app;
+ {
+ smoke_find_class(&c, kde_Smoke, "KApplication");
+ smoke_find_method(&m, kde_Smoke, c.index, "KApplication");
+
+ smoke_call_method(kde_Smoke, m.index, NULL, stack);
+ app = stack[0].s_class;
+
+ smoke_set_binding(c.smoke, kde, c.index, app);
+ }
+
+ {
+ smoke_find_class(&c, kde_Smoke, "KGlobalSettings");
+ smoke_find_method(&m, kde_Smoke, c.index, "Disable");
+ smoke_call_method(kde_Smoke, m.index, NULL, stack);
+ }
+
+ // widget = new KXmlGuiWindow();
+ // widget->setupGUI();
+ // widget->show();
+ // return app->exec();
+ void* widget;
+ {
+ smoke_find_class(&c, kde_Smoke, "KXmlGuiWindow");
+ smoke_find_method(&m, kde_Smoke, c.index, "KXmlGuiWindow");
+
+ smoke_call_method(m.smoke, m.index, NULL, stack);
+ widget = stack[0].s_class;
+ smoke_set_binding(c.smoke, kde, c.index, widget);
+
+ smoke_find_method(&m, c.smoke, c.index, "setupGUI");
+ smoke_call_method(m.smoke, m.index, widget, stack);
+
+ smoke_find_method(&m, c.smoke, c.index, "show");
+ smoke_call_method(m.smoke, m.index, widget, stack);
+
+ smoke_find_class(&c, kde_Smoke, "KApplication");
+ smoke_find_method(&m, c.smoke, c.index, "exec");
+ smoke_call_method(m.smoke, m.index, NULL, stack);
+
+ return stack[0].s_int;
+ }
+}
addfile ./smoke.mbd
hunk ./smoke.mbd 1
+;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
+
+;;; Allow this file to compile even when sysdef.cmake is not loaded.
+;;; You can not add a (MB:LOAD :SYSDEF.CMAKE) on top since when Mudballs
+;;; loads this file it might not know yet about :SYSDEF.CMAKE.
+(defpackage :sysdef.cmake
+ (:use :cl :sysdef)
+ (:export :cmake-file :cmake-library))
+(in-package :sysdef.cmake)
+
+(defclass sysdef.cmake:cmake-file (source-file)
+ ()
+ (:default-initargs :type "txt"))
+
+(defclass sysdef.cmake:cmake-library (component)
+ ())
+;;; end SYDDEF.CMAKE
+
+(in-package :sysdef-user)
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (use-package :sysdef.cmake))
+
+(define-system :smoke ()
+ (:version 0 0 1)
+ (:documentation "Smoke bindings. Provides the base functionality to
+implement bindings using the various Smoke modules.")
+ (:author "Tobias Rautenkranz")
+ (:components
+ ("CMakeLists" cmake-file)
+ (:src module
+ (:needs "CMakeLists")
+ (:components
+ ("CMakeLists.txt" static-file)
+ "package"
+ ("translate" (:needs "package"))
+ ("smoke" (:needs "smoke-c" "objects" "clos"))
+ ("object-map" (:needs "objects"))
+ ("class-map" (:needs "package"))
+ ("bindings" (:needs "package"))
+ ("clos" (:needs "smoke-c" "objects" "object-map" "class-map" "bindings"))
+ ("method" (:needs "clos"))
+ (:objects module
+ (:needs "smoke-c" "utils")
+ (:serial t)
+ (:components "object" "enum" "method" "class"
+ "type" "instance" "stack"))
+ (:smoke-c module
+ (:needs "package" "translate")
+ (:components ("libsmoke-c" cmake-library)
+ ("libsmoke-c-util" cmake-library)
+
+ ;; Make release-action add this files
+ ("CMakeLists.txt" static-file)
+ ("csmokebinding.h" static-file)
+ ("csmokebinding.cpp" static-file)
+ ("smoke-c.cpp" static-file)
+
+ ("smoke-c" (:needs "libsmoke-c"
+ "libsmoke-c-util"))
+ ("class" (:needs "smoke-c"))
+ ("stack" (:needs "class"))
+ ("method" (:needs "stack"))
+ ("type" (:needs "method"))))
+
+ (:utils module
+ (:needs "package")
+ (:components "get-value")))))
+ (:needs :sysdef.cmake :cffi :closer-mop
+ :trivial-garbage :bordeaux-threads))
adddir ./src
addfile ./src/CMakeLists.txt
hunk ./src/CMakeLists.txt 1
+add_subdirectory(smoke-c)
addfile ./src/bindings.lisp
hunk ./src/bindings.lisp 1
+(in-package :smoke)
+
+(defvar *bindings* (make-hash-table))
+
+;; FIXME is this lock needed? (The user may not have to
+;; load additional modules while threads are running.
+(defvar *bindings-lock* (make-lock "bindings-lock"))
+
+(defun binding (smoke)
+ "Returns the Smoke binding for the Smoke module SMOKE."
+ (with-lock-held (*bindings-lock*)
+ (gethash (pointer-address smoke) *bindings*)))
+
+(defun (setf binding) (binding smoke)
+ (with-lock-held (*bindings-lock*)
+ (setf (gethash (pointer-address smoke) *bindings*)
+ binding)))
addfile ./src/class-map.lisp
hunk ./src/class-map.lisp 1
+(in-package :smoke)
+
+(defvar *smoke-id-class-map*
+ (make-hash-table)
+ "Maps a Smoke module pointer - id pair to a class.")
+;; FIXME disallow adding a class when threads are running or add a lock.
+
+(defmacro id-class-map (smoke)
+ `(gethash (pointer-address ,smoke)
+ *smoke-id-class-map*))
+
+(defun add-id-class-map (smoke)
+ (unless (nth-value 1 (id-class-map smoke))
+ (setf (id-class-map smoke)
+ (make-hash-table))))
+
+(defun add-id (smoke-class class)
+ "Associates the CLOS class CLASS with SMOKE-CLASS."
+ (setf (gethash (id smoke-class)
+ (id-class-map (smoke smoke-class)))
+ class))
+
+(defun find-smoke-class (class)
+ "Returns the CLOS class for smoke-class CLASS."
+ (let* ((class (real-class class))
+ (ret (gethash (id class)
+ (id-class-map (smoke class)))))
+ (assert (not (null ret))
+ ()
+ "The class ~A was not found." (name class))
+ ret))
addfile ./src/clos-types.lisp
hunk ./src/clos-types.lisp 1
+(in-package :smoke)
+
+(defclass cxx::number () ())
+
+(defclass cxx::rational (cxx::number) ())
+
+(defclass cxx::int (cxx::rational) ())
+(defclass cxx::short (cxx::rational) ())
+
+
+(defclass cxx::real (cxx::number) ())
+
+(defclass cxx::float (cxx::real) ())
+(defclass cxx::double (cxx::real) ())
+
+
+(defclass cxx::char () ())
+(defclass cxx::pointer ()
+ ((next)))
+(defclass cxx::const ()
+ ((next)))
+ [_$_]
+
+(defgeneric convert (from to))
+
+(defmethod convert (from to)
+ (values nil nil))
+
+(defun char->int (c)
+ (char-code c))
+
+(defmethod convert ((from character) (to cxx::int))
+ (values #'char->int 1))
+
+(defmethod convert (from (to cxx::const))
+ (call-next-method (const from) to))
+
+(defmethod convert ((from cxx::const) (to cxx::const))
+ (call-next-method (next from) (next to)))
+
+(defun float->int (f)
+ (round f))
+
+(defmethod convert ((from float) (to cxx::int))
+ (values #'float->int 1))
+
+(defmethod convert ((from string) (to cxx::char)))
+;(defmethod convert ((from string) (to qstring)))
addfile ./src/clos.lisp
hunk ./src/clos.lisp 1
+(in-package #:smoke)
+
+(declaim (optimize (speed 0) (debug 3)))
+
+(declaim (inline lispify))
+(defun lispify (name &optional (package nil))
+ "Returns the interned symbol for name in Lisp style."
+ (declare (string name)
+ (optimize (speed 3)))
+ (if (null package)
+ (values (intern (cxx-to-lisp name)))
+ (values (intern (cxx-to-lisp name) package))))
+
+(defmacro define-string-transform (name documentation &body states)
+ "Defines a function to transform a string."
+ (let ((output (gensym))
+ (index (gensym))
+ (length (gensym)))
+ `(defun ,name (input)
+ ,documentation
+ (declare (simple-string input)
+ (optimize (speed 3)))
+ ;; At least on sbcl 1.0.25.debian CONCATENATE is faster
+ ;; than VECTOR-PUSH-EXTEND
+ (let ((,output "")
+ (,index 0)
+ (,length (length input))
+ (char #\Null))
+ (declare (base-char char))
+ (macrolet ((next-char ()
+ `(if (>= ,',index ,',length)
+ (return-from transform ,',output)
+ (progn
+ (setf char (aref input ,',index))
+ (incf ,',index))))
+ (go-next (tag)
+ `(progn (next-char)
+ (go ,tag)))
+ (append-char (char)
+ `(setf ,',output (concatenate 'string
+ ,',output
+ (string ,char)))))
+ (block transform
+ (tagbody
+ (next-char) ;; Get first char
+ ,@(reduce #'append
+ (mapcar #'(lambda (state)
+ (if (stringp (second state))
+ `(,(first state) . ,(cddr state))
+ state))
+ states)))))))))
+
+
+(define-string-transform lisp-to-cxx
+ "Converts LISP-STYLE to camelCase.
+Note that (LISP-TO-CXX (CXX-TO-LIST SOME-STRING)) will not neccessarily return
+a string equal to SMOME-STRING."
+ (default [_$_]
+ "Downcase, convert _ and dispatch."
+ (case char
+ (#\- (go-next camel-upcase))
+ (#\. (go-next namespace))
+ (t (append-char (char-downcase char))
+ (go-next default))))
+ (camel-upcase
+ "Convert camelCase to lisp-style."
+ (append-char char)
+ (go-next default))
+ (namespace
+ "Convert . to ::"
+ (append-char #\:)
+ (append-char #\:)
+ (go default)))
+
+
+ [_$_]
+
+(define-string-transform cxx-to-lisp [_$_]
+ "Returns camelCase STRING in lisp-style."
+ (begin
+ "Strip leadind Q or K."
+ (case char
+ (#\K (go-next default))
+ (#\Q (go-next default))
+ (t (go default))))
+ (default
+ "Upcase, convert _ and dispatch."
+ (case char
+ (#\: (go-next namespace))
+ (#\_ (append-char #\-)
+ (go-next default))
+ (t (append-char (char-upcase char))
+ (if (lower-case-p char)
+ (go-next camel-case)
+ (go-next default)))))
+ (namespace
+ "Convert camelCase to lisp-style."
+ (assert (eql #\: char))
+ (append-char #\.)
+ (go-next default))
+ (camel-case
+ "Convert camelCase to lisp-style."
+ (if (upper-case-p char)
+ (progn [_$_]
+ (append-char #\-)
+ (append-char char)
+ (go-next default))
+ (go default))))
+ [_$_]
+
+(defclass smoke-standard-object ()
+ ((pointer :reader pointer :initarg :pointer
+ :documentation "Pointer to the C++ object.")
+ (owned-p :accessor owned-p :initarg :owned-p
+ :initform t
+ :documentation "T when the object is owned by Lisp and
+NIL when C++ is the owner.")
+ (const-p :reader const-p :initarg :const-p
+ :initform nil
+ :documentation "T when the object is const and NIL otherwise."))
+ (:documentation "The standard superclass for Smoke classes."))
+
+(defmethod print-object ((object smoke-standard-object) stream)
+ (print-unreadable-object (object stream :type t)
+ (princ (pointer object) stream)))
+
+(defclass smoke-standard-class (standard-class smoke-class)
+ ((enumerations :initform (make-hash-table)
+ :initarg :enumerations
+ :reader enumerations
+ :documentation "The enumerations of the class.
+Maps the type-id of the enumeration to a hash-table that
+maps an enum value to a symbol."))
+ (:documentation "A Smoke C++ class"))
+
+(defclass smoke-wrapper-class (smoke-standard-class)
+ ())
+
+(defclass cxx:class (smoke-wrapper-class)
+ ()
+ (:documentation "Metaclass to extend Smoke Objects."))
+
+
+(defmethod closer-mop:validate-superclass ((class smoke-standard-class) (superclass standard-class))
+ T)
+
+(defmethod closer-mop:validate-superclass ((class smoke-wrapper-class) (superclass smoke-standard-class))
+ T)
+
+(defmethod reinitialize-instance :around
+ ((class smoke-standard-class)
+ &rest args &key direct-superclasses &allow-other-keys)
+ (apply
+ #'call-next-method class
+ :direct-superclasses (or direct-superclasses
+ (list (find-class
+ 'smoke-standard-object))) args))
+
+(defmethod initialize-instance :around
+ ((class smoke-standard-class)
+ &rest args &key direct-superclasses &allow-other-keys)
+ "Sets NIL superclass to SMOKE-STANDARD-OBJECT instead of the default STANDARD-OBJECT."
+ (apply
+ #'call-next-method class
+ :direct-superclasses (or direct-superclasses
+ (list (find-class 'smoke-standard-object)))
+ args))
+
+(defmethod reinitialize-instance :around
+ ((class smoke-wrapper-class)
+ &rest args &key direct-superclasses &allow-other-keys)
+ (assert (not (null direct-superclasses))
+ (direct-superclasses)
+ "No superclass suplied for class ~A" class)
+ (let ((superclass (first direct-superclasses)))
+ (assert (subtypep (class-of superclass) (find-class 'smoke-standard-class))
+ ((first direct-superclasses))
+ "The first superclass must be an subclass of an smoke class.")
+ (apply
+ #'call-next-method class
+ :id (id superclass)
+ :smoke (smoke superclass)
+ :direct-superclasses direct-superclasses
+ args)))
+
+(defmethod initialize-instance :around
+ ((class smoke-wrapper-class)
+ &rest args &key direct-superclasses &allow-other-keys)
+ (assert (not (null direct-superclasses))
+ (direct-superclasses)
+ "No superclass suplied for class ~A" class)
+ (let ((superclass (first direct-superclasses)))
+ (assert (subtypep (class-of superclass) (find-class 'smoke-standard-class))
+ ((first direct-superclasses))
+ "The first superclass must be an subclass of an smoke class.")
+ (apply
+ #'call-next-method class
+ :id (id superclass)
+ :smoke (smoke superclass)
+ :direct-superclasses direct-superclasses
+ args)))
+
+(defun smoke-class-symbol (class)
+ (if (external-p class)
+ (class-name (find-smoke-class class))
+ (lispify (name class))))
+
+
+ [_$_]
+
+(defun make-smoke-classes (smoke)
+ "Construts a lisp class for each one in the Smoke module SMOKE."
+ (declare (optimize (speed 3)))
+ (add-id-class-map smoke)
+ (map-classes [_$_]
+ #'(lambda (class)
+ (unless (external-p class)
+ (add-id class
+ (closer-mop:ensure-class (lispify (name class))
+ :direct-superclasses
+ (mapcar #'smoke-class-symbol
+ (smoke-class-direct-superclasses class))
+ :id (id class)
+ :smoke (smoke class)
+ :metaclass 'smoke-standard-class))
+ (export (lispify (name class)))))
+ smoke))
+
+(defun generic-lambda-list (method)
+ "Returns the lisp lambda list for METHOD."
+ (if (static-p method)
+ '(class &rest args)
+ '(object &rest args)))
+
+(defclass smoke-gf (standard-generic-function smoke-method)
+ ()
+ (:metaclass closer-mop:funcallable-standard-class)
+ (:documentation "Smoke generic function"))
+
+(defun smoke-class-of (object)
+ "Returns the class of OBJECT or OBJECT iff it alread is a class."
+ (if (subtypep (class-of object) (find-class 'smoke-class))
+ object
+ (class-of object)))
+ [_$_]
+;;; To speed up the startup (MAKE-SMOKE-METHODS)
+;;; ENSURE-METHOD is only called as needed.
+(defmethod no-applicable-method ((gf smoke-gf) &rest args)
+ "Calls the smoke method."
+ (let ((method (find-method-using-args (smoke-class-of (first args))
+ (name gf) (rest args))))
+ (if (static-p method)
+ (s-call method (null-pointer) (rest args))
+ (s-call method (cast (first args) (get-class method)) (rest args)))))
+
+(defmethod add-method :after ((gf smoke-gf) method)
+ "Adds a method which calls the smoke method, to make call-next-method work."
+ (when (null (rest (closer-mop:generic-function-methods gf)))
+ (closer-mop:ensure-method gf
+ `(lambda (object &rest args)
+ (let ((method (find-method-using-args (smoke-class-of object)
+ (name ,gf)
+ args)))
+ (if (static-p method)
+ (s-call method (null-pointer) args)
+ (s-call method (cast object (get-class method)) args)))))))
+
+(defcallback destructed :void
+ ((binding :pointer)
+ (id smoke-index)
+ (object-pointer :pointer))
+ (declare (optimize (speed 3)))
+ (let ((object (get-object object-pointer)))
+ (when object
+ (cancel-finalization object)
+ (remove-object object-pointer)
+ (setf (slot-value object 'pointer) (null-pointer)))))
+
+(defun stack-to-args (stack arg &optional (args nil))
+ "Returns the arguments in STACK, where ARG is the type
+of the first argument, as an list of Lisp objects."
+ (if (end-p arg)
+ args
+ (stack-to-args (cffi:inc-pointer stack
+ (cffi:foreign-type-size 'smoke-stack-item))
+ (next arg)
+ (append args (list
+ (type-to-lisp (cffi:mem-ref stack 'smoke-stack-item)
+ arg))))))
+
+(defgeneric set-returnvalue (stack value type))
+(defmethod set-returnvalue (stack (value smoke-standard-object) type)
+ (assert (class-p type)
+ (type)
+ "The type ~A of the value ~A is not a class."
+ (name type) value)
+ (setf (foreign-slot-value stack 'smoke-stack-item 'class)
+ (pointer value))
+ (when (stack-p type) ;; Pass by value => smoke deletes the object.
+ (cancel-finalization value) ;; Fixme mark object as invalid or copy it
+ ;(remove-object (pointer value))
+ (remove-if-exists (pointer value));;FIXME!
+ (setf (slot-value value 'pointer) (null-pointer))))
+
+(defmethod set-returnvalue (stack (value integer) type)
+ (setf (foreign-slot-value stack 'smoke-stack-item 'int)
+ value))
+
+(defmethod set-returnvalue (stack (value (eql t)) type)
+ (setf (foreign-slot-value stack 'smoke-stack-item 'bool)
+ value))
+
+(defun put-returnvalue (stack value type)
+ (unless (void-p type)
+ (set-returnvalue stack value type)))
+
+(defcallback dispatch-method :boolean
+ ((binding :pointer)
+ (method smoke-index)
+ (object :pointer)
+ (stack smoke-stack)
+ (abstract :boolean))
+ (declare (optimize (speed 3)))
+ (let ((method (make-instance 'smoke-method
+ :id method
+ :smoke (smoke-get-smoke binding))))
+ (let ((gf (symbol-function (lispify (name method) "CXX"))))
+ (if (null (closer-mop:generic-function-methods gf))
+ (progn
+ (when abstract
+ (error "Abstract method ~S called." (name method)))
+ nil)
+ (let ((object (get-object object)))
+ (if object
+ (progn
+ (put-returnvalue stack
+ (apply gf object
+ (stack-to-args (cffi:inc-pointer stack (cffi:foreign-type-size 'smoke-stack-item))
+ (get-first-argument method)))
+ (return-type method))
+ t)
+ nil))))))
+
+;;FIXME use CHANGE-CLASS instead?
+(defun cast (object class)
+ "Returns a pointer of type CLASS to the C++ object of OBJECT."
+ (assert (derived-p (class-of object) class)
+ ()
+ "Can not cast object ~A of class ~A to class ~A."
+ object (name (class-of object)) (name class))
+ (smoke-cast (smoke (class-of object)) (pointer object)
+ ;(id (class-of object)) (id (real-class class))))
+ (id (class-of object)) (class-id (smoke (class-of object))
+ class)))
+
+
+(defun upcast (object class)
+ (assert (derived-p class (class-of object))
+ ()
+ "Can not upcast object ~A of class ~A to class ~A."
+ object (name (class-of object)) (name class))
+ (smoke-cast (smoke class) (pointer object)
+ (id (class-of object)) (id (real-class class))))
+
+
+(defmethod convert-to-class (smoke-class (object smoke-standard-object))
+ (cast object smoke-class))
+
+(defun make-smoke-constructor (class args)
+ (find-method-using-args class
+ (name class)
+ args))
+
+(defun call-constructor (object args)
+ (pointer-call (make-smoke-constructor (class-of object)
+ args)
+ (null-pointer)
+ args))
+
+(defmethod initialize-instance :after ((object smoke-standard-object) [_$_]
+ &key args &allow-other-keys)
+ "Initializes a Smoke object. Calls its constructor with the arguments supplied
+by the key :ARGS and sets the smoke binding."
+ (assert (not (and (slot-boundp object 'pointer)
+ (not (null args))))
+ ((slot-value object 'pointer) args)
+ "Pointer ~A bound and constructor argument :ARGS ~S supplied."
+ (slot-value object 'pointer) args)
+ (unless (slot-boundp object 'pointer)
+ (setf (slot-value object 'pointer) (call-constructor object args))
+ (set-binding object (binding (smoke (class-of object))))
+ (setf (slot-value object 'owned-p) t)
+ (add-object object)))
+
+
+(defmethod instance-to-lisp (pointer class type)
+ (let ((ret (make-instance class
+ :owned-p (stack-p type)
+ :pointer pointer)))
+; (when (stack-p type)
+; (add-object ret))
+; (set-binding ret (binding (smoke (class-of ret)))))
+ ret))
addfile ./src/marshall.lisp
hunk ./src/marshall.lisp 1
+(in-package :smoke)
+
+(declaim (optimize (debug 3)))
+
+(defmacro average (&rest args)
+ `(floor (+ ,@args) ,(length args)))
+ [_$_]
+
+(defun binary-find (lower upper < =)
+ (let ((mid (average lower upper)))
+ (if (= mid lower)
+ nil
+ (if (funcall = mid)
+ mid
+ (if (funcall < mid)
+ (binary-find lower mid < =)
+ (binary-find mid upper < =))))))
+
+(defun serach-method (smoke name)
+ (binary-find 1 (smoke-method-name-size smoke)
+ #'(lambda (index)
+ (string< name
+ (smoke-get-method-name smoke index)))
+ #'(lambda (index)
+ (string= name
+ (smoke-get-method-name smoke index)))))
+
+(defun find-last (lower upper =)
+ (if (or (>= lower upper)
+ (not (funcall = (1+ lower))))
+ lower
+ (find-last (1+ lower) upper =)))
+ [_$_]
+ [_$_]
+(defun find-methods (smoke name)
+ (let* ((index (serach-method smoke name))
+ (= #'(lambda (index)
+ (string= name
+ (smoke-get-method-name smoke index)
+ :end2 (length name))))
+ (upper (find-last index (smoke-method-name-size smoke) =))
+ (methods nil))
+ (loop for i from index to upper do
+ (push (smoke-get-method-name smoke i)
+ methods))
+ methods))
+ [_$_]
+ [_$_]
+
+;(defmethod exact-match ((object singl-float) type))
+(defun type-equal (type type-name)
+ (equal (name type) type-name))
+
+(defun exact-match (object type)
+ (format t "~A ~A~%" object (name type))
+ (ctypecase object [_$_]
+ (smoke-standard-object
+ (and (class-p type)
+ (derived-p (class-of object)
+ (get-class type))))
+ (double-float (type-equal type "double"))
+ (single-float (type-equal type "float"))
+ (integer (type-equal type "int"))
+ (string (or (type-equal type "const char*")
+ (type-equal type "const QString&")))
+ (character (type-equal type "char"))))
+
+(defun exact-match-p (arguments types)
+ (if (or (null arguments) (null types))
+ (and (null arguments)
+ (null types))
+ (if (not (exact-match (first arguments)
+ (first types)))
+ nil
+ (exact-match-p (rest arguments)
+ (rest types)))))
+ [_$_]
+(defun promotion-match (object type)
+ (ctypecase object
+ (character (type-equal type "int"))
+ (float (type-equal type "double"))
+ (boolean (type-equal type "int"))))
+
+(defun standard-conversion-match (object type)
+ (ctypecase object
+ (number (or (type-equal type "short")
+ (type-equal type "int")
+ (type-equal type "long")))))
+
+(defun constructor-match (object type)
+ (if (class-p type)
+ (let ((constructor (make-smoke-constructor (get-class type)
+ (mung-arg object))))
+ (exact-match object (get-first-argument constructor)))
+ nil))
+ [_$_]
+(defun find-ambiguous-method (predicate method)
+ (let ((index (- (id method))))
+ (loop as i = (smoke-ambiguous-method (smoke method)
+ index)
+ while (> i 0) do
+ (incf index)
+ (let ((ambiguous-method (make-instance 'smoke-method
+ :smoke (smoke method)
+ :id i)))
+ (when (funcall predicate ambiguous-method)
+ (return ambiguous-method))))))
+
+(defun find-method-using-args (class name arguments)
+ (with-foreign-object (m 'smoke-module-index)
+ (smoke-find-method m (smoke class) (id class)
+ (concatenate 'string name
+ (munged-args arguments)))
+ (let ((method (make-instance 'smoke-method
+ :smoke (foreign-slot-value m
+ 'smoke-module-index
+ 'smoke)
+ :id (foreign-slot-value m
+ 'smoke-module-index
+ 'index))))
+ (when (< (id method) 0)
+ (setf method
+ (find-ambiguous-method #'(lambda (method)
+ (exact-match-p arguments (arguments method)))
+ method))
+ (assert (not (null method)) (method)
+ "No method ~A::~A for the arguments ~A"
+ (name class) name arguments))
+ method)))
+
+
+(defgeneric get-convert-function (to from))
+(defmethod get-convert-function ((to eql 'int) (from eql 'char)))
+(defmethod get-convert-function ((to cxx::int) (from string)))
+
+(get-convert-function 'int 'char)
+
+;'const int 'char:
+(get-convert-function 'int 'char)
+&& (convert-const-p 'char)
+
+;'int 'const char:
+(get-convert-function 'int 'char)
+&& (not (const-p 'char))
+
+
+(defclass int ()
+ ((const-p)))
+
+(defun get-convert-function (to from))
+
+ [_$_]
addfile ./src/method.lisp
hunk ./src/method.lisp 1
+(in-package :smoke)
+
+(declaim (optimize (debug 3)))
+
+(defun enum-class-symbol (enum-type)
+ (let ((class-name (name (get-class enum-type))))
+ (if (null class-name)
+ 'global-enum-class
+ (lispify class-name))))
+ [_$_]
+(defun constant-definition (method smoke)
+ "Returns an expression that defines a constant for the enum METHOD.
+The second return value is the expression to export the constant."
+ (let ((symbol [_$_]
+ (if (string= (name (get-class method))
+ "Qt")
+ (lispify (concatenate 'string "+" (name method)
+ "+"))
+ (lispify (concatenate 'string
+ (name (get-class method))
+ ".+"
+ (name method) "+")))))
+ (values
+ ; `(defconstant ,symbol
+ ; ,(enum-call method))
+ `(alexandria:define-constant ,symbol
+ (make-instance 'enum
+ :value ,(enum-call method)
+ :type (make-instance 'smoke-type
+ :id ,(id (return-type method))
+ :smoke ,smoke))
+ :test #'enum=)
+ `(export (quote ,symbol)))))
+
+(defun static-method-symbol (method)
+ "Returns the lisp symbol for the static method METHOD."
+ (let ((class (get-class method)))
+ (lispify (concatenate 'string
+ (if (string= (name class)
+ "QGlobalSpace")
+ nil
+ (concatenate 'string
+ (name class)
+ "."))
+ (name method)))))
+
+(defun static-method-definition (method smoke)
+ "Returns an expression to define a function for the static METHOD.
+The second return value is the expression to export the function."
+ (let* ((class (get-class method))
+ (method-name (name method))
+ (name (lispify (concatenate 'string
+ (if (string= (name class)
+ "QGlobalSpace")
+ nil
+ (concatenate 'string
+ (name class)
+ "."))
+ (name method)))))
+ (values
+ `(defun ,name (&rest args)
+ (let ((method (find-method-using-args (make-instance 'smoke-class
+ :id ,(id class)
+ :smoke ,smoke)
+ ,method-name args)))
+ (s-call method (null-pointer) args)))
+ `(export (quote ,name)))))
+
+(defun hash-table-key-values (hash-table)
+ "Returns a list containing all key-value pairs as CONS of HASH-TABLE."
+ (let ((list))
+ (maphash #'(lambda (key value)
+ (push (cons key value) list))
+ hash-table)
+ list))
+
+(defun ensure-generic-methods (names-and-ids smoke)
+ "Ensures the generic functions in NAMES-AND-IDS for the Smoke module SMOKE."
+ (dolist (name-id names-and-ids)
+ (ensure-generic-function (first name-id)
+ :id (rest name-id)
+ :smoke smoke
+ :generic-function-class 'smoke-gf
+ :lambda-list '(object &rest args))
+
+ (export (first name-id) :CXX)))
+
+(defmacro check-recompile (smoke)
+ "Raises an error when the fasl of the DEFINE-METHOS was not compiled against
+the current smoke module."
+ `(eval-when (:load-toplevel :execute)
+ (unless (= (smoke-methods-size ,smoke)
+ ,(smoke-methods-size (eval smoke)))
+ (error "The smoke module ~A changed, you need to recompile the lisp file."
+ (smoke-get-module-name ,smoke)))))
+
+
+(defmacro define-methods (smoke)
+ "Process the C++ methods of the Smoke module SMOKE.
+Expands to DEFUNs for static methods, DEFINE-CONSTANTs for enum methods
+and a function do define the generic methods a load-time."
+;;; symbol - id pairs are stored in the hash-tables to prevent the
+;;; mulitiple definiton of a function with the same name.
+ (let ((generics (make-hash-table))
+ (constants)
+ (functions)
+ (function-symbols (make-hash-table))
+ (exports))
+ (map-methods [_$_]
+ #'(lambda (method)
+ (when (and (enum-p method)
+ ;; FIXME workaround for
+ ;; http://lists.kde.org/?l=kde-bindings&m=123464781307375
+ (not (string= (name (get-class method))
+ "KGlobalSettings")))
+ (multiple-value-bind (def export) (constant-definition method smoke)
+ (push def
+ constants)
+ (push export exports)))
+ (when (and (not (destructor-p method))
+ (not (constructor-p method))
+ (not (enum-p method))
+ (not (eql nil (name method)))
+ (string/= (name method) "tr")) ;; we have a custom qt:tr funciton
+ (setf (gethash (lispify (name method) "CXX") generics)
+ (id method))
+ (when (static-p method)
+ (let ((function-symbol (static-method-symbol method)))
+ (unless (nth-value 1 (gethash function-symbol function-symbols))
+ (setf (gethash function-symbol function-symbols) t)
+ (multiple-value-bind (def export) (static-method-definition method smoke)
+ (push def functions)
+ (push export exports)))))))
+ (eval smoke))
+ `(progn (check-recompile ,smoke)
+ ,@functions
+ (eval-when (:load-toplevel)
+ (ensure-generic-methods ',(hash-table-key-values generics) ,smoke)
+ (make-smoke-classes ,smoke)
+ )
+ ,@constants
+ ,@exports)))
+
addfile ./src/object-map.lisp
hunk ./src/object-map.lisp 1
+(in-package :smoke)
+
+(defvar *object-map* [_$_]
+ #-cmucl (make-weak-hash-table :weakness :value)
+ #+cmucl (make-hash-table :weak-p :value)
+ [_$_]
+ "Maps eisp object to Smoke C++ object of a class.")
+
+;; FIXME This probably does not scale well. A per thread object-map
+;; or at least a read-write lock should be used.
+(defvar *object-map-mutex* (make-lock "object-map lock"))
+
+(defun get-object (pointer)
+ (with-lock-held (*object-map-mutex*)
+ (gethash (pointer-address pointer) *object-map*)))
+
+(defun (setf get-object) (value pointer)
+ (with-lock-held (*object-map-mutex*)
+ (setf (gethash (pointer-address pointer) *object-map*)
+ value)))
+ [_$_]
+
+(defun has-pointer-p (pointer)
+ "Returns T when there is an object for POINTER in the map and NIL otherwise."
+ (with-lock-held (*object-map-mutex*)
+ (nth-value 1 (gethash (pointer-address pointer) *object-map*))))
+
+
+(defgeneric make-finalize (object)
+ (:documentation "Returns a function to be called when OBJECT is finalized."))
+
+(defmethod make-finalize (object)
+ (let ((pointer (pointer object))
+ (class (class-of object)))
+ #'(lambda ()
+ (handler-case (delete-pointer pointer class)
+ (condition (condition)
+ (format *debug-io* "error finalize ~A ~A~%" (name class)
+ condition))))))
+ [_$_]
+
+(defun add-object (object)
+ (assert (not (has-pointer-p (pointer object)))
+ ()
+ "There exists already a object ~A for the pointer of ~A."
+ (get-object (pointer object)) object)
+ (when (owned-p object)
+ (let ((finalizer (make-finalize object)))
+ (finalize object finalizer)))
+ (setf (get-object (pointer object)) object))
+
+(defun remove-if-exists (pointer)
+ (with-lock-held (*object-map-mutex*)
+ (remhash (pointer-address pointer) *object-map*)))
+
+(defun remove-object (pointer)
+ (assert (has-pointer-p pointer)
+ (pointer)
+ "No object to remove for pointer ~A." pointer)
+ (with-lock-held (*object-map-mutex*)
+ (remhash (pointer-address pointer) *object-map*)))
+
+(defun print-garbage ()
+ (with-lock-held (*object-map-mutex*)
+ (maphash #'(lambda (pointer object)
+ (format t "~A of type: ~S~%"
+ (make-pointer pointer)
+ (class-name (class-of object))))
+ *object-map*)))
adddir ./src/objects
addfile ./src/objects/class.lisp
hunk ./src/objects/class.lisp 1
+(in-package #:smoke)
+
+;;;
+;;; find-class
+;;; ensure-class
+;;; make-instance
+;;; class-name
+;;; class-slots
+;;; class-direct-subclasses
+;;; class-direct-superclasses
+;;; class-of
+;;; subclassp / subtypep
+
+
+(defclass smoke-class (smoke-symbol)
+ ()
+ (:documentation "A class"))
+
+(defmethod get-struct-slot-value ((class smoke-class) slot-name)
+ (foreign-slot-value (smoke-get-class (smoke class) (id class))
+ 'smoke-class slot-name))
+
+(defmethod name ((class smoke-class))
+ (get-struct-slot-value class 'name))
+
+(defun map-classes (function smoke)
+ "Applys FUNCTION to the classes of SMOKE."
+ (let ((class (make-instance 'smoke-class
+ :id 0
+ :smoke smoke)))
+ (loop for id from 1 to (1- (smoke-classes-size smoke)) do
+ (setf (slot-value class 'id) id)
+ (funcall function class))))
+
+(defun external-p (class)
+ "Returns T when CLASS is external in its module; NIL otherwise."
+ (get-struct-slot-value class 'external))
+
+(defmethod get-flag ((class smoke-class) flag)
+ (boole boole-and (get-struct-slot-value class 'flags)
+ (foreign-enum-value 'smoke-class-flags flag)))
+
+(defmethod constructor-p ((class smoke-class))
+ "Returns T when CLASS has a constructor; NIL otherwise."
+ (/= 0 (get-flag class :constructor)))
+
+(define-condition undefined-class (cell-error)
+ ((smoke-name :initarg :smoke-name
+ :initform nil
+ :documentation "The name of the Smoke module"))
+ (:report (lambda (condition stream)
+ (format stream "No Smoke class named ~S in the Smoke module ~S."
+ (cell-error-name condition)
+ (slot-value condition 'smoke-name))))
+ (:documentation "A undefined Smoke class"))
+
+;smoke-find-class
+(defun make-smoke-class (smoke name)
+ "Returns the class named NAME of the smoke module SMOKE.
+Signals an undefined-class condition when there is no class for NAME."
+ (with-foreign-object (c 'smoke-module-index)
+ (do () (nil)
+ (smoke-find-class c smoke name)
+ (restart-case
+ (if (null-pointer-p (foreign-slot-value c 'smoke-module-index 'smoke))
+ (error (make-condition 'undefined-class :name name :smoke-name (smoke-get-module-name smoke)))
+ (return))
+ (supply (new-name)
+ :report "Supply a new class name"
+ :interactive read-new-value
+ (setf name new-name))))
+ (make-instance 'smoke-class
+ :id (foreign-slot-value c 'smoke-module-index 'index)
+ :smoke (foreign-slot-value c 'smoke-module-index 'smoke))))
+
+(defun real-class (class)
+ "Returns the same class like CLASS, but such that EXTERNAL-P returns NIL."
+ (if (external-p class)
+ (make-smoke-class (smoke class) (name class))
+ class))
+
+(defun class-id (module class)
+ "Returns the class id of CLASS for the Smoke module MODULE."
+ (if (eq (smoke class) module)
+ (id class)
+ (smoke-class-id module (name class))))
+
+;(defun smoke-subclassp (class base-class) TODO
+(defun derived-p (class base-class)
+ "Returns T when CLASS is derived from BASE-CLASS and NIL when not."
+ (values
+ (derived-real-p (real-class class) (real-class base-class))
+ T))
+
+(defun derived-real-p (class base-class)
+ (smoke-is-derived-from (smoke class) (id class)
+ (smoke base-class) (id base-class)))
+ [_$_]
+
+(defun smoke-class-direct-superclasses (class)
+ (smoke-add-superclass class nil (get-struct-slot-value class 'parents)))
+
+(defun smoke-add-superclass (class classes index)
+ (let ((class-index (smoke-get-parent-index (smoke class) index)))
+ (assert (< class-index (smoke-classes-size (smoke class))))
+ (if (= 0 class-index)
+ classes
+ (smoke-add-superclass class (append classes
+ (list
+ (make-instance 'smoke-class
+ :id class-index
+ :smoke (smoke class))))
+ (1+ index)))))
addfile ./src/objects/enum.lisp
hunk ./src/objects/enum.lisp 1
+(in-package :cxx-support)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (use-package :smoke :cxx-support))
+
+;;;
+;;; One could map enum-values to lisp symbols, store the type in the plist
+;;; an use thouse as enums, but C++ enums may have several symbols for
+;;; the same value and thus lisp symbols can not be used.
+
+(defclass enum ()
+ ((value :reader value
+ :initarg :value)
+ (type :reader enum-type
+ :initarg :type))
+ (:documentation "Holds the integer value and type of an C++ enum value."))
+
+(defmethod print-object ((enum enum) stream)
+ (print-unreadable-object (enum stream :type t)
+ (format stream "~A ~A" (name (enum-type enum))
+ (value enum))))
+ [_$_]
+
+(defun check-enum-type (enum enum-type)
+ (assert (type= (enum-type enum)
+ enum-type)
+ (enum enum-type)
+ "The enums ~A is not of type ~A." enum (name enum-type)))
+
+(defun enum= (enum1 enum2)
+ "Returns true when ENUM1 and ENUM2 are equal and false otherwise."
+ (declare (enum enum1 enum2))
+ (assert (type= (enum-type enum1)
+ (enum-type enum2))
+ (enum1 enum2)
+ "The enums ~A and ~A have a different type." enum1 enum2)
+ (= (value enum1) (value enum2)))
+
+(defmacro enum-xcase (case keyform &body cases)
+ (let ((type (enum-type (eval (first (first cases))))))
+ (loop for case in cases do
+ (check-enum-type (eval (first case))
+ type)))
+ `(progn
+ ; (check-enum-type (enum-type ,keyform)
+ ; (enum-type ,(first (first cases))))
+ (,case (value ,keyform)
+ ,@(loop for case in cases
+ collect `(,(value (eval (first case)))
+ ,@(rest case))))))
+
+(defmacro enum-case (keyform &body cases)
+ `(enum-xcase case ,keyform ,@cases))
+
+(defmacro enum-ecase (keyform &body cases)
+ `(enum-xcase ecase ,keyform ,@cases))
+
+(defmacro enum-cases (keyform &body cases)
+ "Keyform returns a number; cases are enums."
+ `(case ,keyform
+ ,@(loop for case in cases
+ collect `(,(value (eval (first case)))
+ ,@(rest case)))))
+
+(defun enum-logand (&rest enums)
+ (apply #'logand (mapcar #'value enums)))
addfile ./src/objects/instance.lisp
hunk ./src/objects/instance.lisp 1
+(in-package #:smoke)
+
+(defclass object (smoke-class)
+ ((pointer :reader pointer :initarg :pointer
+ :initform (null-pointer)
+ :documentation "Pointer to the C++ object."))
+ (:documentation "A Smoke CPP object"))
addfile ./src/objects/method.lisp
hunk ./src/objects/method.lisp 1
+(in-package #:smoke)
+(declaim (optimize (debug 3)))
+
+(defclass smoke-method (smoke-symbol)
+ ()
+ (:documentation "A C++ method"))
+
+(defmethod print-object ((smoke-method smoke-method) stream)
+ (if (null-pointer-p (smoke smoke-method))
+ (call-next-method)
+ (print-unreadable-object (smoke-method stream :type t)
+ (princ (method-declaration smoke-method) stream))))
+
+(define-condition undefined-method (undefined-function)
+ ((class-name :initarg :class-name
+ :initform nil))
+ (:report (lambda (condition stream)
+ (format stream "No Smoke method ~S for class ~S."
+ (cell-error-name condition)
+ (slot-value condition 'class-name)))) [_$_]
+ (:documentation "A undefined Smoke method"))
+ [_$_]
+(defun valid-p (method)
+ "Returns T when METHOD is valid and NIL otherwise."
+ (/= 0 (id method)))
+
+(defun ambiguous-p (method)
+ "Returns T when METHOD is ambiguous and NIL otherwise."
+ (> 0 (id method)))
+
+;smoke-find-method
+(defun make-smoke-method (class name)
+ "Returns the method called NAME of CLASS.
+Signals a undefined-method condition when no method was found."
+ (with-foreign-object (m 'smoke-module-index)
+ (do () (nil)
+ (smoke-find-method m (smoke class) (id class) name)
+ (restart-case
+ (if (null-pointer-p (foreign-slot-value m 'smoke-module-index 'smoke))
+ (error (make-condition 'undefined-method :name name :class-name (name class)))
+ (return))
+ (supply (new-name)
+ :report "Supply a new method name"
+ :interactive read-new-value
+ (setf name new-name))))
+ (when (> 0 (foreign-slot-value m 'smoke-module-index 'index))
+ (loop as i = (smoke-ambiguous-method (smoke class)
+ (- (foreign-slot-value m 'smoke-module-index 'index)))
+ while (> i 0)
+ do (decf (foreign-slot-value m 'smoke-module-index 'index))
+ (let ((m (make-instance 'smoke-method :id i :smoke (smoke class))))
+ (format t " ~A ~A~%" (name m) (signature m))))
+ (error "The method ~S of ~S is ambigious" name (name class)));;TODO
+ (make-instance 'smoke-method
+ :id (foreign-slot-value m 'smoke-module-index 'index)
+ :smoke (foreign-slot-value m 'smoke-module-index 'smoke))))
+
+(defun type-equal (type type-name)
+ "Returns true when TYPE is of the type named TYPE-NAME and false otherwise."
+ (equal (name type) type-name))
+
+(defun exact-match (object type)
+ "Returns true when the type of OBJECT is exactly the same as TYPE and
+false otherwise."
+ (ctypecase object [_$_]
+ (smoke-standard-object
+ (and (class-p type)
+ (derived-p (class-of object)
+ (get-class type))))
+ (double-float (type-equal type "double"))
+ (single-float (type-equal type "float"))
+ (integer (type-equal type "int"))
+ ;; int is also enum
+ ;; FIXME remove magic number 12
+ ;;(= (type-id type) 12)))
+ (string (or (type-equal type "const char*")
+ (type-equal type "const QString&")))
+ (enum (type= (enum-type object)
+ type))
+ (sequence (type-equal type "const QStringList&"))
+ (character (type-equal type "char"))))
+
+(defun exact-match-p (arguments types)
+ "Returns true when all the type of ARGUMENTS is the same as the
+corresponing type of TYPES and the length of the ARGUMENTS and TYPES list
+is equal."
+ (if (or (null arguments) (null types))
+ (and (null arguments)
+ (null types))
+ (if (not (exact-match (first arguments)
+ (first types)))
+ nil
+ (exact-match-p (rest arguments)
+ (rest types)))))
+
+(defun mung-arg (argument)
+ "Returns the mung char for ARUGMENT."
+ ;; FIXME void* is #\$ but void[] is #\?
+ ;; FIXME Get rid of the mugging stuff and compute the applicable methods
+ ;; including argument promotion
+ (case argument
+ ((t nil) #\$) ;; Booleans
+ (otherwise
+ (ctypecase argument
+ (number #\$)
+ (string #\$)
+ (foreign-pointer #\?)
+ (sequence #\?)
+ (enum #\$)
+ (smoke-standard-object #\#)))))
+
+(defun munged-args (arguments &optional (string nil))
+ "Maps the type of every item of ARGUMENTS to a char;
+Returns the list of the chars."
+ (if (null arguments)
+ string
+ (munged-args (rest arguments)
+ (append string (list (mung-arg (first arguments)))))))
+
+(defun find-ambiguous-method (predicate method)
+ "Returns a method of the ambiguous method METHOD such that
+PREDICATE is true. NIL is returned when no matching method is found."
+ (assert (ambiguous-p method)
+ (method)
+ "The method is not ambiguous.")
+ (let ((index (- (id method))))
+ (loop as i = (smoke-ambiguous-method (smoke method)
+ index)
+ while (> i 0) do
+ (incf index)
+ (let ((ambiguous-method (make-instance 'smoke-method
+ :smoke (smoke method)
+ :id i)))
+ (when (funcall predicate ambiguous-method)
+ (return ambiguous-method))))))
+
+(defun find-method-using-args (class name arguments)
+ "Returns the method of class CLASS with the name NAME
+for the arguments ARGUMENTS."
+ (with-foreign-object (m 'smoke-module-index)
+ (smoke-find-method m (smoke class) (id class)
+ (concatenate 'string name
+ (munged-args arguments)))
+ (let ((method (make-instance 'smoke-method
+ :smoke (foreign-slot-value m
+ 'smoke-module-index
+ 'smoke)
+ :id (foreign-slot-value m
+ 'smoke-module-index
+ 'index))))
+ (assert (valid-p method)
+ (method)
+ "No method ~A::~A for the arguments ~A" (name class) name arguments)
+ (when (ambiguous-p method)
+ (setf method
+ (find-ambiguous-method #'(lambda (method)
+ (exact-match-p arguments (arguments method)))
+ method))
+ (assert (not (null method)) (method)
+ "No method ~A::~A for the arguments ~A"
+ (name class) name arguments))
+ method)))
+
+
+(defun map-methods (function smoke)
+ "Applys FUNCTION to the methods of SMOKE.
+The method argument to function must not be modified."
+ (let ((method (make-instance 'smoke-method
+ :id 0
+ :smoke smoke)))
+ (loop for id from 1 to (1- (smoke-methods-size smoke)) do
+ (when (= (mod id (floor (smoke-methods-size smoke) 10)) 0)
+ (format t "[ ~A ]~%" (* 10
+ (floor (* 10 id)
+ (smoke-methods-size smoke)))))
+ (setf (slot-value method 'id) id)
+ (funcall function method))))
+
+(defmethod get-struct-slot-value ((method smoke-method) slot-name)
+ (foreign-slot-value (smoke-get-method (smoke method) (id method))
+ 'smoke-method slot-name))
+
+(defmethod name ((method smoke-method))
+ (smoke-get-method-name (smoke method)
+ (get-struct-slot-value method 'name)))
+
+(defun signature (method)
+ "Returns the signature of METHOD."
+ (format nil "~A(~{~A~^, ~}) ~:[~;const~]"
+ (name method)
+ (mapcar #'name (arguments method))
+ (const-p method)))
+
+(defun access (method)
+ "Returns the access for METHOD. (public or protected)"
+ (if (protected-p method)
+ "protected"
+ "public"))
+
+(defun modifiers (method)
+ (format nil "~A~:[~; static~]" (access method)
+ (static-p method)))
+
+(defun return-type (method)
+ "Returns the return type of METHOD."
+ (make-instance 'smoke-type
+ :id (get-struct-slot-value method 'return-type)
+ :smoke (smoke method)))
+
+(defun method-declaration (method)
+ (format nil "~A~:[ void~; ~1:*~A~] ~A::~A"
+ (modifiers method)
+ (name (return-type method))
+ (name (get-class method))
+ (signature method)))
+
+(defgeneric get-flag (object flag)
+ (:documentation "Returns the value for FLAG of OBJECT."))
+
+(defmethod get-flag ((method smoke-method) flag)
+ (logand (get-struct-slot-value method 'flags)
+ (foreign-enum-value 'smoke-method-flags flag)))
+
+(defgeneric constructor-p (object)
+ (:documentation "Returns T when OBJECT is a constructor."))
+
+(defmethod constructor-p ((method smoke-method))
+ (/= 0 (get-flag method :constructor)))
+
+(defun destructor-p (method)
+ "Returns T when METHOD is a destructor; NIL otherwise."
+ (/= 0 (get-flag method :destructor)))
+
+(defun static-p (method)
+ "Retruns T when METHOD is static and NIL otherwise."
+ (/= 0 (get-flag method :static)))
+
+(defun protected-p (method)
+ "Returns T when METHOD is protected; NIL otherwise."
+ (/= 0 (get-flag method :protected)))
+
+(defmethod const-p ((method smoke-method))
+ "Returns T when METHOD is a const method and NIL otherwise."
+ (/= 0 (get-flag method :const)))
+
+(defun ambigious-p (method)
+ "Returns T when METHOD is ambigious and NIL otherwise."
+ (< 0 (id method)))
+
+(defun enum-p (method)
+ "Returns T when METHOD is enum value and NIL otherwise."
+ (/= 0 (get-flag method :enum)))
+
+(defmethod get-class ((method smoke-method))
+ (make-instance 'smoke-class
+ :id (get-struct-slot-value method 'class)
+ :smoke (smoke method)))
+
+ [_$_]
+
+(defclass smoke-argument (smoke-type)
+ ()
+ (:documentation "A argument to a method"))
+
+(defmethod id ((argument smoke-argument))
+ (smoke-get-argument (smoke argument) (slot-value argument 'id)))
+
+(defun last-p (argument)
+ "Returns T when ARGUMENT is the last argument and NIL otherwise."
+ (= 0 (smoke-get-argument (smoke argument) (1+ (slot-value argument 'id)))))
+
+(defun end-p (argument)
+ "Returns T when ARGUMENT is the after last element and NIL otherwise."
+ (= 0 (id argument)))
+
+(defun next (argument)
+ "Returns the argument following ARGUMENT."
+ (assert (not (end-p argument))
+ (argument)
+ "Access after end element")
+ (make-instance 'smoke-argument
+ :id (1+ (slot-value argument 'id))
+ :smoke (smoke argument)))
+
+(defun get-arguments-length (method)
+ "Returns the number of arguments for METHOD."
+ (get-struct-slot-value method 'num-args))
+ [_$_]
+(defun get-first-argument (method)
+ "Returns the first argument of METHOD"
+ (make-instance 'smoke-argument
+ :id (get-struct-slot-value method 'arguments)
+ :smoke (smoke method)))
+
+(defun get-argument (method index)
+ "Returns the type of METHODs argument with number INDEX."
+ (make-instance 'smoke-argument
+ :id (+ (get-struct-slot-value method 'arguments) index)
+ :smoke (smoke method)))
+
+
+(defun build-argument-list (list argument)
+ (if (end-p argument)
+ list
+ (build-argument-list (append list (list argument))
+ (next argument))))
+
+(defun arguments (method)
+ "Returns a list of the arguments of METHOD."
+ (build-argument-list nil (get-first-argument method)))
+
addfile ./src/objects/object.lisp
hunk ./src/objects/object.lisp 1
+(in-package #:smoke)
+
+(defclass smoke-symbol ()
+ ((id :reader id :initarg :id
+ :documentation "The objects index.")
+ (smoke :reader smoke :initarg :smoke
+ :initform (null-pointer)
+ :documentation "Pointer to the Smoke module."))
+ (:documentation "A method or class in a Smoke module."))
+
+(defmethod print-object ((smoke-symbol smoke-symbol) stream)
+ (if (null-pointer-p (smoke smoke-symbol))
+ (call-next-method)
+ (print-unreadable-object (smoke-symbol stream :type t)
+ (princ (name smoke-symbol) stream))))
+
+(defgeneric name (smoke-symbol)
+ (:documentation "Returns the name of SMOKE-SYMBOL."))
+
+(defgeneric get-struct-slot-value (smoke-symbol slot-name)
+ (:documentation "Returns the slot value of SLOT-NAME of
+the SMOKE-SYMBOLs struct."))
addfile ./src/objects/stack.lisp
hunk ./src/objects/stack.lisp 1
+(in-package #:smoke)
+
+(declaim (optimize (debug 3)))
+(defclass call-stack ()
+ ((pointer :reader pointer :initarg :pointer
+ :initform (null-pointer)
+ :documentation "Pointer to the Smoke stack")
+ (top :accessor top :initarg :top
+ :initform (null-pointer)
+ :documentation "Pointer to push the next argument to.")
+ (cleanup-stack :accessor cleanup-stack
+ :initform nil
+ :documentation "Cleanup functions"))
+ (:documentation "Contains the argument passed to a Smoke method."))
+
+(defmethod size ((stack call-stack))
+ "Returns the size (number of arguments) of STACK."
+ (/ [_$_]
+ (- (pointer-address (top stack))
+ (pointer-address (pointer stack)))
+ (foreign-type-size 'smoke-stack-item)))
+
+(defun make-call-stack (smoke-stack)
+ (make-instance 'call-stack
+ :pointer smoke-stack
+ :top (inc-pointer smoke-stack (foreign-type-size 'smoke-stack-item))))
+
+(defun push-stack (stack value type)
+ (setf (foreign-slot-value (top stack)
+ 'smoke-stack-item type) value)
+ (incf-pointer (top stack) (foreign-type-size 'smoke-stack-item)))
+ [_$_]
+(defun push-cleanup (stack function)
+ "Adds the cleanup function FUNCTION to STACK"
+ (push function (cleanup-stack stack)))
+
+(defun push-stack2 (stack value type-id)
+ (ecase type-id
+ (0 (push-stack stack value 'voidp))
+ (1 (push-stack stack value 'bool))
+ (2 (push-stack stack value 'char))
+ (3 (push-stack stack value 'uchar))
+ (4 (push-stack stack value 'short))
+ (5 (push-stack stack value 'ushort))
+ (6 (push-stack stack value 'int))
+ (7 (push-stack stack value 'uint))
+ (8 (push-stack stack value 'long))
+ (9 (push-stack stack value 'ulong))
+ (10 (push-stack stack value 'float))
+ (11 (push-stack stack value 'double))
+ (12 (push-stack stack (value value) 'enum-value))
+ (13 (push-stack stack value 'class))))
+
+(defun push-smoke-stack (stack lisp-value smoke-type)
+ (typecase smoke-type
+ (smoke-type
+ (cond
+ ((class-p smoke-type)
+ (push-stack2 stack
+ (convert-to-class (get-class smoke-type) lisp-value)
+ (type-id smoke-type)))
+; ((pointer-p smoke-type)
+ (t
+ (let ((cffi-type (get-type (name smoke-type))))
+ (if (null cffi-type)
+ (progn
+ ; (assert (typep lisp-value 'foreign-pointer)
+ ; (lisp-value)
+ ; "The lisp-value ~S is not a foreign-pointer."
+ ; lisp-value)
+ (push-stack2 stack
+ lisp-value
+ (type-id smoke-type)))
+ (multiple-value-bind (pointer args) (convert-to-foreign lisp-value
+ cffi-type)
+ (push-cleanup stack
+ #'(lambda ()
+ (free-converted-object pointer
+ cffi-type
+ args)))
+ (push-stack2 stack
+ pointer
+ (type-id smoke-type))))))))
+; (t (push-stack2 stack lisp-value (type-id smoke-type)))))
+ (t (push-lisp-object stack lisp-value smoke-type))))
+
+(defgeneric push-lisp-object (stack object class)
+ (:documentation "Push the OBJECT on STACK."))
+
+(defun set-smoke-stack (stack args arguments)
+ "Pushes the arguments ARGS onto the Smoke stack STACK."
+ (when (null args)
+ (assert (null arguments)
+ ()
+ "To few arguments supplied. Missing: ~A" arguments))
+ (unless (null args)
+ (assert (not (null arguments))
+ ()
+ "To many arguments suppliend (Arguments ~A)." args)
+ (push-smoke-stack stack (first args) (first arguments))
+ (set-smoke-stack stack (rest args) (rest arguments))))
+
+(defmacro with-stack ((stack args types) &body body)
+ (let ((smoke-stack (gensym "STACK")))
+ `(with-foreign-object (,smoke-stack 'smoke-stack-item (1+ (length ,args)))
+ (let ((,stack (make-call-stack ,smoke-stack)))
+ (unwind-protect
+ (progn
+ (set-smoke-stack ,stack ,args
+ ,types)
+ ,@body)
+ (mapcar #'funcall (cleanup-stack ,stack)))))))
+
+(defun enum-to-lisp (stack-item type)
+ "Returns the Lisp representation for STACK-ITEM of the basic C type TYPE."
+ (ecase (type-id type)
+ (0 (let ((cffi-type (get-type (name type))))
+ (if (null cffi-type)
+ (progn [_$_]
+ ;(warn "Unknown translation from ~A to lisp." (name type))
+ (foreign-slot-value stack-item 'smoke-stack-item 'voidp))
+ (convert-from-foreign (foreign-slot-value stack-item
+ 'smoke-stack-item
+ 'voidp)
+ cffi-type))))
+ (1 (foreign-slot-value stack-item 'smoke-stack-item 'bool))
+ (2 (code-char (foreign-slot-value stack-item 'smoke-stack-item 'char)))
+ (3 (code-char (foreign-slot-value stack-item 'smoke-stack-item 'uchar)))
+ (4 (code-char (foreign-slot-value stack-item 'smoke-stack-item 'short)))
+ (5 (code-char (foreign-slot-value stack-item 'smoke-stack-item 'ushort)))
+ (6 (foreign-slot-value stack-item 'smoke-stack-item 'int))
+ (7 (foreign-slot-value stack-item 'smoke-stack-item 'uint))
+ (8 (foreign-slot-value stack-item 'smoke-stack-item 'long))
+ (9 (foreign-slot-value stack-item 'smoke-stack-item 'ulong))
+ (10 (foreign-slot-value stack-item 'smoke-stack-item 'float))
+ (11 (foreign-slot-value stack-item 'smoke-stack-item 'double))
+ (12 (make-instance 'enum
+ :value (foreign-slot-value stack-item 'smoke-stack-item 'enum-value)
+ :type type))))
+
+(defgeneric instance-to-lisp (pointer class type)
+ (:documentation "Returns a clos instance for POINTER."))
+
+(defun object-to-lisp (object type)
+ (if (class-p type)
+ (let ((class (get-class type)))
+ (if (has-pointer-p object)
+ (get-object object)
+ (instance-to-lisp object (find-smoke-class class) type)))
+ nil))
+
+
+
+(defun class-to-lisp (stack-item type)
+ "Returns the Lisp representation for STACK-ITEM of type C++ class."
+ (object-to-lisp (foreign-slot-value stack-item
+ 'smoke-stack-item
+ 'class)
+ type))
+
+(defun type-to-lisp (stack-item type)
+ "Returns the Lisp representation of STACK-ITEM"
+ (cond
+ ((void-p type)
+ (values))
+ ((class-p type)
+ (class-to-lisp stack-item type))
+ (t
+ (enum-to-lisp stack-item type))))
+
+ [_$_]
addfile ./src/objects/type.lisp
hunk ./src/objects/type.lisp 1
+(in-package #:smoke)
+
+(defclass smoke-type (smoke-symbol)
+ ()
+ (:documentation "A type"))
+
+
+(defmethod get-struct-slot-value ((type smoke-type) slot-name)
+ (foreign-slot-value (smoke-get-type (smoke type) (id type))
+ 'smoke-type slot-name))
+
+(defun make-smoke-type (smoke name)
+ "Returns the type in the Smoke module SMOKE named NAME."
+ (make-instance 'smoke-type
+ :id (smoke-find-type smoke name)
+ :smoke smoke))
+
+(defmethod name ((type smoke-type))
+ (get-struct-slot-value type 'name))
+
+(defun type= (type1 type2)
+ (and t ;(pointer-eq (smoke type1)
+ ; (smoke type2))
+ (= (id type1)
+ (id type2))))
+
+(defmethod get-flag ((type smoke-type) flag)
+ (boole boole-and (get-struct-slot-value type 'flags)
+ (foreign-enum-value 'smoke-type-flags flag)))
+
+(defun stack-p (type)
+ "Returns T when TYPE is stored on the stack; NIL otherwise."
+ (/= 0 (get-flag type :stack)))
+
+(defun reference-p (type)
+ "Returns T when TYPE is a reference ('type&'); NIL otherwise."
+ (/= 0 (get-flag type :reference)))
+
+(defun pointer-p (type)
+ "Returns T when TYPE is a pointer ('type*'); NIL otherwise."
+ (/= 0 (get-flag type :pointer)))
+
+(defmethod const-p ((type smoke-type))
+ "Returns T when TYPE is const; NIL otherwise."
+ (/= 0 (get-flag type :const)))
+
+(defun class-p (type)
+ "Returns T when TYPE is a smoke class"
+ (and (eql (type-id type) 13)
+ (/= -1 (get-struct-slot-value type 'class))))
+
+(defun type-id (type)
+ "Returns the ID of TYPE."
+ (boole boole-and (get-struct-slot-value type 'flags)
+ (foreign-enum-value 'smoke-type-flags :type-id)))
+
+(defun void-p (type)
+ "Return T when TYPE is a void type (no value)."
+ (null (name type)))
+
+(defgeneric get-class (smoke-symbol)
+ (:documentation "Returns the smoke-class associated with SMOKE-SYMBOL."))
+
+(defmethod get-class ((type smoke-type))
+ "Return the smoke-class of TYPE."
+ (assert (/= -1 (get-struct-slot-value type 'class))
+ (type)
+ "The type ~S is not a smoke class." (name type))
+ (make-instance 'smoke-class
+ :id (get-struct-slot-value type 'class)
+ :smoke (smoke type)))
+
+
+;; FIXME why macro?
+(defmacro smoke-type-p (type smoke type-name)
+ (let ((t2 (smoke-find-type smoke type-name)))
+ `(and (= (id ,type) ,(id t2))
+ (pointer-eq (smoke ,type) ,(smoke t2)))))
addfile ./src/package.lisp
hunk ./src/package.lisp 1
+(defpackage #:cxx-support
+ (:use #:cl)
+ (:export #:enum
+ #:enum=
+ #:enum-logand
+ #:value
+ #:enum-type
+ #:enum-case
+ #:enum-cases
+ #:enum-ecase))
+
+(defpackage #:smoke
+ (:use #:cl #:asdf #:cffi #:trivial-garbage #:bordeaux-threads #:cxx-support)
+ (:export #:init
+
+ #:make-smoke-classes
+ [_$_]
+ #:new-object
+ #:delete-object
+ #:smoke-call
+ #:call
+
+ #:name
+ #:id
+ #:type=
+
+ #:define-methods
+
+ #:cxx-bool
+
+ #:pointer))
+
+(defpackage #:cxx
+ (:use) ;; do not use #:cl
+ (:export #:class))
+
+
+
+(in-package #:smoke)
addfile ./src/run-test.lisp
hunk ./src/run-test.lisp 1
+#|
+exec sbcl --noinform --noprint --disable-debugger --load $0 --end-toplevel-options "$@"
+|#
+
+;(asdf:operate 'asdf:load-op 'smoke :verbose nil)
+;(require :sb-cover)
+;(declaim (optimize sb-cover:store-coverage-data))
+;(asdf:oos 'asdf:load-op :smoke :force t)
+(require :smoke-tests)
+(in-package :smoke-tests)
+(setup)
+(5am:run!)
+;(smoke-destruct *kde-binding*)
+;(smoke-destruct *qt-binding*)
+;(sb-cover:report "./report/")
+(sb-ext:quit)
adddir ./src/smoke-c
addfile ./src/smoke-c/CMakeLists.txt
hunk ./src/smoke-c/CMakeLists.txt 1
+find_package(Qt4 REQUIRED)
+set(QT_DONT_USE_QTGUI true)
+include(${QT_USE_FILE})
+
+set(SMOKE_C_SOURCES smoke-c.cpp csmokebinding.cpp)
+add_library(smoke-c MODULE ${SMOKE_C_SOURCES})
+
+add_library(smoke-c-util MODULE smoke-c-util.cpp)
+
+install(TARGETS smoke-c smoke-c-util
+ LIBRARY DESTINATION lib)
addfile ./src/smoke-c/class.lisp
hunk ./src/smoke-c/class.lisp 1
+(in-package #:smoke)
+
+(defcenum smoke-class-flags
+ "Class properties"
+ (:constructor #x01)
+ (:copy-constructor #x02)
+ (:virtual-destructor #x04)
+ (:undefined #x10))
+
+
+(defcstruct smoke-class
+ "Describe a class"
+ (name :string)
+ (external cxx-bool)
+ (parents smoke-index)
+ (class-function :pointer)
+ (enum-function :pointer)
+ (flags :unsigned-short))
+
+(defcfun smoke-find-class :void
+ (m :pointer smoke-module-index)
+ (smoke :pointer)
+ (name :string))
+
+(defcfun smoke-class-id smoke-index
+ (smoke :pointer)
+ (name :string))
+
+(defcfun smoke-classes-size smoke-index
+ (smoke :pointer))
+
+(defcfun smoke-get-class (:pointer smoke-class)
+ (smoke :pointer)
+ (class smoke-index))
+
+(defcfun smoke-get-parent-index smoke-index
+ (smoke :pointer)
+ (class smoke-index))
+
+(defcfun smoke-is-derived-from :boolean
+ (smoke :pointer)
+ (class smoke-index)
+ (smoke-base :pointer)
+ (base-class smoke-index))
+
+(defcfun smoke-cast :pointer
+ (smoke :pointer)
+ (object :pointer)
+ (from smoke-index)
+ (to smoke-index))
addfile ./src/smoke-c/csmokebinding.cpp
hunk ./src/smoke-c/csmokebinding.cpp 1
+#include "csmokebinding.h"
+
+#include <QtGlobal>
+
+namespace cl_smoke
+{
+
+/** @class Binding
+ * @brief The Smoke binding.
+ */
+
+
+/** @typedef Binding::destructed
+ * Callback when a Smoke object is destructed.
+ *
+ * @param binding Smoke binding of the object
+ * @param class_id class id
+ * @param object the object
+ */
+
+
+/** @typedef Binding::dispatch_method
+ * Callback when a Smoke method gets called.
+ *
+ * @param binding Smoke binding of @a object
+ * @param method index of the method
+ * @param object the object for which the method is called
+ * @param args the arguments to the method
+ * @param abstract @c true when the method is abstract and @c false otherwise
+ *
+ * @return @c true when the method call was handled and @c false
+ *when the default method shall be invoked.
+ */
+
+/** Constructor.
+ * @param smoke the Smoke module
+ * @param destruct destruct callback
+ * @param dispatch method dispatch callback
+ */
+Binding::Binding(Smoke *smoke, destructed destruct,
+ dispatch_method dispatch)
+ : SmokeBinding(smoke),
+ destruct(destruct),
+ dispatch(dispatch)
+{
+ Q_ASSERT(smoke);
+ Q_ASSERT(destruct);
+ Q_ASSERT(dispatch);
+}
+
+/** Invoked when a Smoke object is destructed. */
+void
+Binding::deleted(Smoke::Index classId, void *obj)
+{
+ destruct(this, classId, obj);
+}
+
+/** Invoked whne a Smoke method gets called. */
+bool
+Binding::callMethod(Smoke::Index method, void* object,
+ Smoke::Stack stack, bool abstract)
+{
+ return dispatch(this, method, object, stack, abstract);
+}
+
+/**
+ * @todo Returning a const char* would be better
+ */
+char*
+Binding::className(Smoke::Index classId)
+{
+ return const_cast<char*>(smoke->classes[classId].className);
+}
+
+/** Gets the Smoke instance associated with the binding.
+ * @return a pointer to the Smoke instance
+ */
+Smoke*
+Binding::get_smoke() const
+{
+ return smoke;
+}
+
+} // namespace cl_smoke
addfile ./src/smoke-c/csmokebinding.h
hunk ./src/smoke-c/csmokebinding.h 1
+#ifndef CSMOKEBINDING_H
+#define CSMOKEBINDING_H
+
+#include <smoke.h>
+
+namespace cl_smoke
+{
+
+class Binding : public SmokeBinding
+{
+ public:
+ typedef void (*destructed)(Binding* binding, Smoke::Index class_id,
+ void* object);
+
+ typedef int (*dispatch_method)(Binding* binding, Smoke::Index method,
+ void* object, Smoke::Stack args, int abstract);
+
+ Binding(Smoke *smoke, destructed destruct, dispatch_method dispatch);
+
+ virtual void
+ deleted(Smoke::Index classId, void *obj);
+
+ virtual bool
+ callMethod(Smoke::Index method, void* object,
+ Smoke::Stack stack, bool abstract);
+
+ virtual char* [_$_]
+ className(Smoke::Index classId);
+
+ Smoke*
+ get_smoke() const;
+
+ private:
+ const destructed destruct;
+ const dispatch_method dispatch;
+};
+
+} // namespace cl_smoke
+
+#endif // CSMOKEBINDING_H
addfile ./src/smoke-c/method.lisp
hunk ./src/smoke-c/method.lisp 1
+(in-package #:smoke)
+
+(declaim (optimize (debug 3)))
+
+(defcenum smoke-method-flags
+ "Method flags"
+ (:static #x01)
+ (:const #x02)
+ (:copy-constructor #x04)
+ (:internal #x08)
+ (:enum #x10)
+ (:constructor #x20)
+ (:destructor #x40)
+ (:protected #x80))
+
+(defcstruct smoke-method
+ "Describe a method"
+ (class smoke-index)
+ (name smoke-index)
+ (arguments smoke-index)
+ (num-args :unsigned-char)
+ (flags :unsigned-char)
+ (return-type smoke-index)
+ (method smoke-index))
+
+(defcfun smoke-find-method :void
+ (m :pointer smoke-module-index)
+ (smoke :pointer)
+ (class smoke-index)
+ (method :string))
+
+(defcfun smoke-methods-size smoke-index
+ (smoke :pointer))
+
+(defcfun smoke-get-method (:pointer smoke-method)
+ (smoke :pointer)
+ (method smoke-index))
+
+(defcfun smoke-get-method-name :string
+ (smoke :pointer)
+ (method-index smoke-index))
+
+(defcfun smoke-method-name-size smoke-index
+ (smoke :pointer))
+
+(defcfun smoke-call-method :string
+ (smoke :pointer)
+ (method smoke-index)
+ (object :pointer)
+ (stack smoke-stack))
+
+(defcfun smoke-get-argument smoke-index
+ (smoke :pointer)
+ (argument smoke-index))
+
+(defcfun smoke-ambiguous-method smoke-index
+ (smoke :pointer)
+ (ambiguous smoke-index))
addfile ./src/smoke-c/smoke-c-util.cpp
hunk ./src/smoke-c/smoke-c-util.cpp 1
+
+/** @file
+ * \@brief Utility functions
+ */
+
+extern "C" {
+
+/** Gets the size of the C++ bool type in bytes.
+ *
+ * @return the size of bool
+ */
+int
+smoke_sizeof_bool()
+{
+ return sizeof(bool);
+}
+
+} // extern "C"
addfile ./src/smoke-c/smoke-c.cpp
hunk ./src/smoke-c/smoke-c.cpp 1
+#include "csmokebinding.h"
+
+#include <smoke.h>
+
+#include <stdexcept>
+#include <QtGlobal>
+
+/** @file [_$_]
+ * \@brief C wrapper the Smoke bindings.
+ *
+ * \example examples/kde-hello-world.cpp
+ * This KDE example creates a KXmlGuiWindow.
+ * Note that C++ is only used to make the example shorter
+ * (by allowing to directly include smoke-c.cpp), but it could also
+ * be implemented in C using \c dlsym.
+ *
+ * \image html doc/images/kde-hello-world.png "Screenshot"
+ * \image latex doc/images/kde-hello-world.png "Screenshot" width=5cm
+ */
+
+
+/** @brief Common Lisp smoke binding namespace. */
+namespace cl_smoke
+{
+
+/** A Binding */
+typedef void* smoke_binding;
+
+/** Casts the void pointer smoke_binding to the Binding class.
+ * @param smoke the smoke binding
+ *
+ * @return pointer to the Binding instance
+ */
+static inline
+Binding*
+get_smoke_binding(smoke_binding binding)
+{
+ return static_cast<Binding*>(binding);
+}
+
+/** Casts the void pointer smoke to the Smoke class.
+ * @param smoke the Smoke module
+ *
+ * @return pointer to the Smoke module.
+ */
+static inline
+Smoke*
+get_smoke(void* smoke)
+{
+ return static_cast<Smoke*>(smoke);
+}
+} // namespace cl_smoke
+
+using namespace cl_smoke;
+
+extern "C" {
+
+/** Returns the Smoke module of a Smoke binding.
+ * @related cl_smoke::Binding
+ * @param binding the Binding
+ *
+ * @return the Smoke module
+ */
+void*
+smoke_get_smoke(smoke_binding binding)
+{
+ return get_smoke_binding(binding)->get_smoke();
+}
+
+/** Creates a new Smoke binding.
+ * The binding is allocated on the heap an can be freed with smoke_destruct().
+ * @related cl_smoke::Binding
+ * @param smoke pointer to a Smoke module instance
+ * @param destruct callback for object destruction
+ * @param dispatch method dispatch callback
+ *
+ * @return a pointer to a new Smoke binding.
+ */
+smoke_binding
+smoke_init(void* smoke, void* destruct, void* dispatch)
+{
+ return new Binding(static_cast<Smoke*>(smoke),
+ reinterpret_cast<Binding::destructed>(destruct),
+ reinterpret_cast<Binding::dispatch_method>(dispatch));
+}
+
+/** Deletes the smoke binding.
+ * @related cl_smoke::Binding
+ */
+void
+smoke_destruct(smoke_binding binding)
+{
+ delete get_smoke_binding(binding)->get_smoke();
+ delete get_smoke_binding(binding);
+}
+
+/** Gets a Smoke modules name.
+ * @param smoke the Smoke module
+ *
+ * @return the module name
+ */
+const char*
+smoke_get_module_name(void* smoke)
+{
+ return get_smoke(smoke)->moduleName();
+}
+
+///////////////////////////
+/// Class
+///////////////////////////
+
+/** Finds a class.
+ * @param c pointer to write the result to
+ * @param smoke the smoke module
+ * @param name the name of the class
+ */
+void
+smoke_find_class(Smoke::ModuleIndex* c, void* smoke, const char* name)
+{
+ *c = get_smoke(smoke)->findClass(name);
+}
+
+/** Gets the class ID for a Smoke module.
+ * @param smoke the Smoke module
+ * @param name the class name
+ *
+ * @return the class ID in the supplied Smoke module
+ */
+Smoke::Index
+smoke_class_id(void* smoke, const char* name)
+{
+ Smoke::ModuleIndex m = get_smoke(smoke)->idClass(name, true);
+ Q_ASSERT(m.smoke == smoke);
+
+ return m.index;
+}
+
+
+
+/** Gets the number of classes.
+ *
+ * @return the number of classes
+ */
+Smoke::Index
+smoke_classes_size(void* smoke)
+{
+ return get_smoke(smoke)->numClasses;
+}
+
+/** Sets the binding for an newly constructed instance.
+ * @param smoke the Smoke module
+ * @param binding the Smoke binding
+ * @param class_index the index of the instances class
+ * @param object pointer to the class instance.
+ */
+void
+smoke_set_binding(void* smoke, smoke_binding binding, Smoke::Index class_index, void* object)
+{
+ Q_ASSERT(object != NULL);
+ Q_ASSERT(binding != NULL);
+ Q_ASSERT(class_index > 0 && class_index <= smoke_classes_size(smoke));
+
+ const Smoke::Class* klass = &get_smoke(smoke)->classes[class_index];[_^I_][_$_]
+
+ Smoke::StackItem stack[2];
+ stack[1].s_voidp = get_smoke_binding(binding);
+
+ (*klass->classFn)(0, object, stack);
+}
+
+/** Gets a class
+ * @param smoke the smoke binding
+ * @param class_index the index of the class
+ *
+ * @return A pointer to the class into the array of class structs
+ */
+const struct Smoke::Class*
+smoke_get_class(void* smoke, Smoke::Index class_index)
+{
+ Q_ASSERT(class_index >= 0 && class_index <= smoke_classes_size(smoke));
+ return &get_smoke(smoke)->classes[class_index];
+}
+
+/** Determines werter a class is from a base class.
+ * @param smoke the Smoke module of @a class_index
+ * @param class_index the class index
+ * @param smoke_base the Smoke module of the base class @a base_index
+ * @param base_index the index of the base class
+ *
+ * @return Returns 0 when the class is not derived from the base class and nonzero value otherwise.
+ */
+int
+smoke_is_derived_from(void* smoke, Smoke::Index class_index, void* smoke_base, Smoke::Index base_index)
+{
+ Q_ASSERT(!smoke_get_class(smoke, class_index)->external);
+ Q_ASSERT(!smoke_get_class(smoke_base, base_index)->external);
+
+ return get_smoke(smoke)->isDerivedFrom(get_smoke(smoke), class_index,
+ get_smoke(smoke_base), base_index);
+}
+
+/** Returns the index of a base class.
+ * @param smoke the Smoke module
+ * @param class_index the class index
+ * [_$_]
+ * @return the index of a parent
+ */
+Smoke::Index
+smoke_get_parent_index(void* smoke, Smoke::Index class_index)
+{
+ Q_ASSERT(class_index >= 0);
+
+ return get_smoke(smoke)->inheritanceList[class_index];
+}
+
+//////////////////////////////
+/// Method
+//////////////////////////////
+
+/** Gets the method map.
+ * @param smoke the Smoke module
+ * @param method the index of the method
+ *
+ * @return a pointer to the @c MethodMap entry.
+ */
+const Smoke::MethodMap*
+smoke_get_method_map(void* smoke, Smoke::Index method)
+{
+ Q_ASSERT(method >= 0 && method <= get_smoke(smoke)->numMethodMaps);
+
+ return &get_smoke(smoke)->methodMaps[method];
+}
+
+/** Gets a methods name.
+ * @param smoke the Smoke module
+ * @param method_name the method name index
+ *
+ * @return the method name
+ */
+const char*
+smoke_get_method_name(void* smoke, Smoke::Index method_name)
+{
+ Q_ASSERT(method_name >= 0 && method_name <= get_smoke(smoke)->numMethodNames);
+
+ return get_smoke(smoke)->methodNames[method_name];
+}
+
+/** Gets the number of method names.
+ * @param smoke the Smoke module
+ *
+ * @return the number of method names
+ */
+Smoke::Index
+smoke_method_name_size(void *smoke)
+{
+ return get_smoke(smoke)->numMethodNames;
+}
+
+/** Gets the number of methods.
+ * @param smoke the Smoke module
+ *
+ * @return the number of methods
+ */
+Smoke::Index
+smoke_methods_size(void* smoke)
+{
+ return get_smoke(smoke)->numMethods;
+}
+
+/** Gets a method.
+ * @param smoke the smoke binding
+ * @param method the index of the method
+ *
+ * @return a pointer to the method struct
+ */
+const struct Smoke::Method*
+smoke_get_method(void* smoke, Smoke::Index method)
+{
+ Q_ASSERT(method >= 0 && method <= smoke_methods_size(smoke));
+
+ return &get_smoke(smoke)->methods[method];
+}
+
+/** Finds a method of a class.
+ * @param m pointer to write the result to
+ * @param smoke the smoke binding
+ * @param class_index index of the class
+ * @param method_name method name
+ */
+void
+smoke_find_method(Smoke::ModuleIndex* m, void* smoke,
+ Smoke::Index class_index, const char* method_name)
+{
+ *m = get_smoke(smoke)->findMethod(get_smoke(smoke)->className(class_index),
+ method_name);
+ if(m->index > 0)
+ m->index = smoke_get_method_map(m->smoke, m->index)->method;
+}
+
+/** Gets the type index of an argument.
+ * @param smoke the smoke binding
+ * @param argument the argument index
+ *
+ * @return the type index
+ */
+Smoke::Index
+smoke_get_argument(void* smoke, Smoke::Index argument)
+{
+ Q_ASSERT(argument >= 0);
+
+ return get_smoke(smoke)->argumentList[argument];
+}
+
+/** Calls a method.
+ * The methods return value is stored in the first element of the stack.
+ * @param smoke the smoke binding
+ * @param method the index of the method
+ * @param object A pointer to the class instance, or NULL for static and constructor calls
+ * @param stack The stack with the methods arguments.
+ *
+ * @return NULL on success or a description of the exception that occurred.
+ */
+const char*
+smoke_call_method(void* smoke, Smoke::Index method, void* object,
+ Smoke::Stack stack)
+{
+ Smoke::Method meth = *smoke_get_method(smoke, method);
+ Q_ASSERT(!(meth.flags & Smoke::mf_internal));
+ Q_ASSERT_X((NULL == object
+ && (meth.flags & (Smoke::mf_static
+ | Smoke::mf_enum
+ | Smoke::mf_copyctor
+ | Smoke::mf_ctor)))
+ || object,
+ __func__, "object is NULL");
+ Q_ASSERT(meth.flags & Smoke::mf_ctor ? NULL == object : true);
+ const Smoke::Class* klass = smoke_get_class(smoke, meth.classId);
+
+ try
+ {
+ Q_ASSERT(klass->classFn != NULL);
+ (*klass->classFn)(meth.method, object, stack);
+ }
+ catch (std::exception& e)
+ {
+ qFatal(e.what());
+ return e.what();
+ }
+ catch (...)
+ {
+ qFatal("exception");
+ return NULL;
+ }
+
+ return NULL;
+}
+
+///////////////////////////
+/// Type
+//////////////////////////
+
+/** Gets the number of types.
+ * @param smoke the Smoke module
+ *
+ * @return the number of types
+ */
+Smoke::Index
+smoke_types_size(void* smoke)
+{
+ return get_smoke(smoke)->numTypes;
+}
+
+/** Gets a type.
+ * @param smoke the Smoke module
+ * @param type the index of the type
+ *
+ * @return a pointer to the type struct
+ */
+const struct Smoke::Type*
+smoke_get_type(void* smoke, Smoke::Index type)
+{
+ Q_ASSERT(type >= 0 && type <= smoke_types_size(smoke));
+
+ return &get_smoke(smoke)->types[type];
+}
+
+/** Gets the index of a type.
+ * @param smoke the Smoke module
+ * @param name the types name
+ *
+ * @return the index of the type
+ */
+Smoke::Index
+smoke_find_type(void* smoke, const char* name)
+{
+ return get_smoke(smoke)->idType(name);
+}
+
+/** Casts an object.
+ * @param smoke the Smoke module
+ * @param object the objec
+ * @param from the class index of @a object
+ * @param to the class index to cast to
+ *
+ * @return the casted object
+ */
+void*
+smoke_cast(void* smoke, void* object, Smoke::Index from, Smoke::Index to)
+{
+ Q_ASSERT(from > 0 && from <= smoke_classes_size(smoke));
+ Q_ASSERT(to > 0 && to <= smoke_classes_size(smoke));
+
+ return get_smoke(smoke)->cast(object, from, to);
+}
+
+/** Gets an ambiguous method.
+ * @param smoke the Smoke module
+ * @param ambiguous the index
+ *
+ * @return the index of a method
+ */
+Smoke::Index
+smoke_ambiguous_method(void* smoke, Smoke::Index ambiguous)
+{
+ Q_ASSERT(ambiguous >= 0);
+
+ return get_smoke(smoke)->ambiguousMethodList[ambiguous];
+}
+
+} // extern "C"
addfile ./src/smoke-c/smoke-c.lisp
hunk ./src/smoke-c/smoke-c.lisp 1
+(in-package #:smoke)
+
+(eval-when (:load-toplevel :compile-toplevel :execute)
+ (define-foreign-library libsmokeqt
+ (:unix "libsmokeqt.so.2")
+ (t (:default "libsmokeqt")))
+
+ (use-foreign-library libsmokeqt)
+
+ (use-foreign-library libsmoke-c)
+)
+ [_$_]
+
+
+(eval-when (:load-toplevel :compile-toplevel :execute)
+ (use-foreign-library libsmoke-c-util)
+ (defcfun smoke-sizeof-bool :int)
+ (defun cffi-bool-type ()
+ "Returns a cffi unsigned int type with the same size as a C++ bool."
+ (load-foreign-library 'libsmoke-c-util)
+ (intern (format nil "UINT~A" (* 8
+ (smoke-sizeof-bool)))
+ ; (foreign-funcall smoke-sizeof-bool :int)))
+ (find-package :keyword)))
+
+ (defmacro defcxxbool ()
+ `(defctype cxx-bool (:boolean ,(cffi-bool-type)))))
+
+(defcxxbool)
+
+(close-foreign-library 'libsmoke-c-util)
+
+(defctype smoke-binding :pointer
+ "A Smoke binding")
+
+(defctype smoke-index :short
+ "An index")
+
+(defcfun smoke-init smoke-binding
+ (smoke :pointer)
+ (destruct :pointer)
+ (dispatch :pointer))
+
+(defcfun smoke-destruct :void
+ (smoke smoke-binding))
+
+(defcstruct smoke-module-index
+ "asdf"
+ (smoke :pointer)
+ (index smoke-index))
+
+
+(defcfun smoke-set-binding :void
+ "Sets the binding for an newly constructed instance."
+ (smoke :pointer)
+ (smoke-binding smoke-binding)
+ (class smoke-index)
+ (object :pointer))
+
+(defcfun smoke-get-smoke :pointer
+ (smoke-binding smoke-binding))
+
+(defcfun smoke-get-module-name :string
+ (smoke :pointer))
addfile ./src/smoke-c/stack.lisp
hunk ./src/smoke-c/stack.lisp 1
+(in-package #:smoke)
+
+(defcunion smoke-stack-item
+ "A variable on the Smoke stack"
+ (voidp :pointer)
+ (bool cxx-bool)
+ (char :char)
+ (uchar :unsigned-char)
+ (short :short)
+ (ushort :unsigned-short)
+ (int :int)
+ (uint :unsigned-int)
+ (long :long)
+ (ulong :unsigned-long)
+ (float :float)
+ (double :double)
+ (enum-value :long)
+ (class :pointer))
+
+(defctype smoke-stack (:pointer smoke-stack-item)
+ "A Smoke call stack.")
addfile ./src/smoke-c/type.lisp
hunk ./src/smoke-c/type.lisp 1
+(in-package #:smoke)
+
+(defcenum smoke-type-flags
+ "Type properties"
+ (:type-id #x0F)
+
+ (:stack #x10)
+ (:pointer #x20)
+ (:reference #x30)
+
+ (:const #x40))
+
+(defcstruct smoke-type
+ "A type"
+ (name :string)
+ (class smoke-index)
+ (flags :unsigned-short))
+
+(defcfun smoke-find-type smoke-index
+ (smoke :pointer)
+ (name :string))
+
+(defcfun smoke-types-size smoke-index
+ (smoke :pointer))
+
+(defcfun smoke-get-type (:pointer smoke-type)
+ (smoke :pointer)
+ (type smoke-index))
addfile ./src/smoke.lisp
hunk ./src/smoke.lisp 1
+(in-package #:smoke)
+
+(declaim (optimize (debug 3)))
+
+(defun s-call (method object &optional (args nil))
+ (with-stack (stack args (arguments method) )
+ (smoke-call-method (smoke method) (id method)
+ object (pointer stack))
+ (type-to-lisp (pointer stack) (return-type method))))
+
+(defun pointer-call (method object &optional (args nil))
+ (with-stack (stack args (arguments method) )
+ (smoke-call-method (smoke method) (id method)
+ object (pointer stack))
+ (foreign-slot-value (pointer stack) 'smoke-stack-item 'class)))
+
+
+(defun smoke-call (class pointer method-name &optional (args nil))
+ (s-call
+ (make-smoke-method class method-name)
+ pointer args))
+
+(defun static-call (smoke class-name method-name &rest args)
+ (s-call
+ (make-smoke-method (make-smoke-class smoke class-name)
+ method-name)
+ (null-pointer) args))
+
+(defun enum-call (method)
+ "Return the enum value for METHOD."
+ ;; FIXME:
+ ;; we could use static call, but QGraphicsEllipseItem::Type has
+ ;; wrongly QGraphicsGridLayout as return type. Smoke ignores case
+ ;; and confuses it with the member function type() ??
+ ;; (27.2.09)
+ ;; [_$_]
+ (assert (enum-p method))
+ (with-stack (stack nil nil)
+ (smoke-call-method (smoke method) (id method)
+ (null-pointer) (pointer stack))
+ (foreign-slot-value (pointer stack) 'smoke-stack-item 'long)))
+
+#|
+(defun new-object (binding class-name method-name &rest args)
+ (let* ((smoke (smoke-get-smoke binding))
+ (pointer
+ (pointer-call
+ (make-smoke-method (make-smoke-class smoke class-name)
+ method-name)
+ (null-pointer) args)))
+ (let ((object (instance-to-lisp object (find-smoke-class class)
+ (return-type)))
+|#
+(defun new-object (binding class-name method-name &rest args)
+ (let* ((smoke (smoke-get-smoke binding))
+ (method (make-smoke-method (make-smoke-class smoke class-name)
+ method-name))
+ (pointer
+ (pointer-call method (null-pointer) args))
+ (object (instance-to-lisp pointer [_$_]
+ (find-smoke-class (get-class (return-type method)))
+ (return-type method))))
+ (set-binding object (binding (smoke (class-of object))))
+ (add-object object)
+ object))
+ [_$_]
+(defun delete-pointer (pointer class)
+ "Destructs the object at POINTER of type CLASS.
+Calls the destrutor and frees the memory."
+ (let ((method-name (concatenate 'string "~" (name class))))
+ (s-call
+ (make-smoke-method class method-name)
+ pointer))
+ (setf pointer (null-pointer)))
+
+(defun delete-object (object)
+ (let ((method-name (concatenate 'string "~" (name object))))
+ (s-call
+ (make-smoke-method object method-name)
+ (pointer object)))
+ (setf (slot-value object 'pointer) (null-pointer)))
+
+(defun set-binding (object binding)
+ (smoke-set-binding (smoke (class-of object)) binding (id (class-of object)) (pointer object)))
+
+(defun init (smoke)
+ "Returns the a new Smoke binding for the Smoke module SMOKE."
+ (use-foreign-library libsmoke-c)
+ (let ((binding (smoke-init smoke
+ (callback destructed)
+ (callback dispatch-method))))
+ (setf (binding smoke) binding)
+ binding))
+
+(defun call (object method-name &rest args)
+ (smoke-call (class-of object)
+ (pointer object)
+ method-name
+ args))
+
+(defmethod documentation ((class smoke-standard-class) (doc-type t))
+ (format nil "~@[~A~%~]C++ name: ~A" (call-next-method) (name class)))
+
+(defmethod documentation ((gf smoke-gf) (doc-type t))
+ (let ((methods (all-methods (name gf))))
+ (format nil "~@[~A~%~]~{~T~A~%~}"
+ (call-next-method)
+ (sort (mapcar #'method-declaration methods) #'string<=))))
+
+(defun all-methods (name)
+ "Returns a list of all methods named NAME."
+ (let ((methods))
+ (maphash #'(lambda (address value)
+ (declare (ignore value))
+ (let ((smoke (make-pointer address)))
+ (map-methods #'(lambda (method)
+ (when (and (string= name (name method))
+ (not (enum-p method)))
+ (push (make-instance 'smoke-method
+ :id (id method)
+ :smoke (smoke method))
+ methods)))
+ smoke)))
+ *smoke-id-class-map*)
+ methods))
+
+(defun fgrep-methods (smoke str)
+ (map-methods #'(lambda (method)
+ (when (search str (name method))
+ (format t "~A::~A~%" (name (get-class method))
+ (signature method))))
+ smoke))
+
+(defun fgrep-classes (smoke str)
+ (map-classes #'(lambda (class)
+ (when (search str (name class))
+ (format t "~A~%" (name class))))
+ smoke))
addfile ./src/test.lisp
hunk ./src/test.lisp 1
+#|
+exec sbcl --noinform --load $0 --end-toplevel-options "$@"
+|#
+
+(sb-ext:disable-debugger)
+(require :smoke)
+(in-package :smoke)
+(setup)
+(test)
+(sb-ext:quit)
addfile ./src/tests.lisp
hunk ./src/tests.lisp 1
+(in-package :smoke)
+
+(5am:def-suite smoke-suite)
+(5am:in-suite smoke-suite)
+
addfile ./src/translate.lisp
hunk ./src/translate.lisp 1
+(in-package :smoke)
+
+(defvar *type-map* (make-hash-table :test 'equal))
+
+(defun get-type (name)
+ "Return the CFFI type for NAME."
+ (gethash name *type-map*))
+
+(defun add-type (name type)
+ "Registers the CFFI type TYPE with NAME."
+ (setf (gethash name *type-map*) type))
+
+(defun setup-type-map ()
+ "Setup C string <-> Lisp string translation."
+ (add-type "char*" :string)
+ (add-type "const char*" :string))
+
+(eval-when (:load-toplevel :execute)
+ (setup-type-map))
+
+(defgeneric convert-to-class (smoke-class object))
+
+;(defmethod convert-to-class (smoke-class (pointer cffi:foreign-pointer))
+(defmethod convert-to-class (smoke-class pointer)
+ (assert (cffi:pointerp pointer))
+ pointer)
adddir ./src/utils
addfile ./src/utils/get-value.lisp
hunk ./src/utils/get-value.lisp 1
+(in-package #:smoke)
+
+ (defun read-new-value ()
+ (format *query-io* "Enter a new value: ")
+ (multiple-value-list (eval (read *query-io*))))
changepref test
chmod +x ./test.lisp && ./test.lisp