mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
Add #:static-slot-allocation?
* libguile/goops.h (SCM_VTABLE_FLAG_GOOPS_STATIC): Reserve the fourth GOOPS flag to indicate that a class has static slot allocation. * libguile/goops.c (scm_init_goops_builtins): Define vtable-flag-goops-static for goops.scm. * module/oop/goops.scm (class-has-statically-allocated-slots?): New helper. (build-slots-list): Instead of the ad-hoc checks for <class> or <slot>, use the new helper. (initialize): Accept #:static-slot-allocation? keyword. * module/system/foreign-object.scm (make-foreign-object-type): Declare foreign object classes as having static slot allocation. * test-suite/tests/goops.test ("static slot allocation"): Add tests.
This commit is contained in:
parent
05d0cdf18e
commit
26350edcac
5 changed files with 60 additions and 13 deletions
|
@ -1055,6 +1055,8 @@ scm_init_goops_builtins (void *unused)
|
|||
scm_from_int (SCM_VTABLE_FLAG_GOOPS_VALID));
|
||||
scm_c_define ("vtable-flag-goops-slot",
|
||||
scm_from_int (SCM_VTABLE_FLAG_GOOPS_SLOT));
|
||||
scm_c_define ("vtable-flag-goops-static",
|
||||
scm_from_int (SCM_VTABLE_FLAG_GOOPS_STATIC));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#define SCM_VTABLE_FLAG_GOOPS_CLASS SCM_VTABLE_FLAG_GOOPS_0
|
||||
#define SCM_VTABLE_FLAG_GOOPS_VALID SCM_VTABLE_FLAG_GOOPS_1
|
||||
#define SCM_VTABLE_FLAG_GOOPS_SLOT SCM_VTABLE_FLAG_GOOPS_2
|
||||
#define SCM_VTABLE_FLAG_GOOPS_STATIC SCM_VTABLE_FLAG_GOOPS_3
|
||||
|
||||
#define SCM_CLASS_OF(x) SCM_STRUCT_VTABLE (x)
|
||||
#define SCM_CLASS_FLAGS(class) (SCM_VTABLE_FLAGS (class))
|
||||
|
|
|
@ -277,6 +277,9 @@
|
|||
(define-inlinable (instance? obj)
|
||||
(class-has-flags? (struct-vtable obj) vtable-flag-goops-class))
|
||||
|
||||
(define (class-has-statically-allocated-slots? class)
|
||||
(class-has-flags? class vtable-flag-goops-static))
|
||||
|
||||
;;;
|
||||
;;; Now that we know the slots that must be present in classes, and
|
||||
;;; their offsets, we can create the root of the class hierarchy.
|
||||
|
@ -638,10 +641,14 @@ followed by its associated value. If @var{l} does not hold a value for
|
|||
((slot . slots)
|
||||
(or (eq? (%slot-definition-name slot) name) (lp slots)))))))
|
||||
(define (check-cpl slots static-slots)
|
||||
(when (or-map (lambda (slot) (slot-memq slot slots)) static-slots)
|
||||
(scm-error 'misc-error #f
|
||||
"a predefined static inherited field cannot be redefined"
|
||||
'() '())))
|
||||
(match static-slots
|
||||
(() #t)
|
||||
((static-slot . static-slots)
|
||||
(when (slot-memq static-slot slots)
|
||||
(scm-error 'misc-error #f
|
||||
"statically allocated inherited field cannot be redefined: ~a"
|
||||
(list (%slot-definition-name static-slot)) '()))
|
||||
(check-cpl slots static-slots))))
|
||||
(define (remove-duplicate-slots slots)
|
||||
(let lp ((slots (reverse slots)) (res '()) (seen '()))
|
||||
(match slots
|
||||
|
@ -653,13 +660,13 @@ followed by its associated value. If @var{l} does not hold a value for
|
|||
(lp slots (cons slot res) (cons name seen))))))))
|
||||
;; For subclases of <class> and <slot>, we need to ensure that the
|
||||
;; <class> or <slot> slots come first.
|
||||
(let* ((static-slots (cond
|
||||
((memq <class> cpl)
|
||||
(when (memq <slot> cpl) (error "invalid class"))
|
||||
(struct-ref <class> class-index-slots))
|
||||
((memq <slot> cpl)
|
||||
(struct-ref <slot> class-index-slots))
|
||||
(else #f))))
|
||||
(let ((static-slots
|
||||
(match (filter class-has-statically-allocated-slots? (cdr cpl))
|
||||
(() #f)
|
||||
((class) (struct-ref class class-index-direct-slots))
|
||||
(classes
|
||||
(error "can't subtype multiple classes with static slot allocation"
|
||||
classes)))))
|
||||
(when static-slots
|
||||
(check-cpl dslots static-slots))
|
||||
(let lp ((cpl (cdr cpl)) (res dslots) (static-slots '()))
|
||||
|
@ -670,7 +677,7 @@ followed by its associated value. If @var{l} does not hold a value for
|
|||
(cond
|
||||
((not static-slots)
|
||||
(lp cpl (append new-slots res) static-slots))
|
||||
((or (eq? head <class>) (eq? head <slot>))
|
||||
((class-has-statically-allocated-slots? head)
|
||||
;; Move static slots to the head of the list.
|
||||
(lp cpl res new-slots))
|
||||
(else
|
||||
|
@ -912,7 +919,12 @@ slots as we go."
|
|||
(initialize-direct-slots! <class> fold-class-slots)
|
||||
|
||||
(initialize-slots! <class>)
|
||||
(initialize-slots! <slot>))
|
||||
(initialize-slots! <slot>)
|
||||
|
||||
;; Now that we're all done with that, mark <class> and <slot> as
|
||||
;; static.
|
||||
(class-add-flags! <class> vtable-flag-goops-static)
|
||||
(class-add-flags! <slot> vtable-flag-goops-static))
|
||||
|
||||
|
||||
|
||||
|
@ -2834,6 +2846,13 @@ var{initargs}."
|
|||
(struct-set! class class-index-direct-methods '())
|
||||
(struct-set! class class-index-redefined #f)
|
||||
(struct-set! class class-index-cpl (compute-cpl class))
|
||||
(when (get-keyword #:static-slot-allocation? initargs #f)
|
||||
(match (filter class-has-statically-allocated-slots?
|
||||
(class-precedence-list class))
|
||||
(()
|
||||
(class-add-flags! class vtable-flag-goops-static))
|
||||
(classes
|
||||
(error "Class has superclasses with static slot allocation" classes))))
|
||||
(struct-set! class class-index-direct-slots
|
||||
(map (lambda (slot)
|
||||
(if (slot? slot)
|
||||
|
|
|
@ -63,8 +63,10 @@
|
|||
(if finalizer
|
||||
(make-class '() dslots #:name name
|
||||
#:finalizer finalizer
|
||||
#:static-slot-allocation? #t
|
||||
#:metaclass <foreign-class-with-finalizer>)
|
||||
(make-class '() dslots #:name name
|
||||
#:static-slot-allocation? #t
|
||||
#:metaclass <foreign-class>))))
|
||||
|
||||
(define-syntax define-foreign-object-type
|
||||
|
|
|
@ -657,3 +657,26 @@
|
|||
(pass-if-equal "b accessor on ba" 'b (b-accessor ba))
|
||||
(pass-if-equal "b accessor on cab" 'b (b-accessor cab))
|
||||
(pass-if-equal "b accessor on cba" 'b (b-accessor cba))))
|
||||
|
||||
(with-test-prefix "static slot allocation"
|
||||
(let* ((<a> (class () (a) #:name '<a> #:static-slot-allocation? #t))
|
||||
(<b> (class () (b) #:name '<b> #:static-slot-allocation? #t))
|
||||
(<c> (class () (c) #:name '<c>))
|
||||
(<ac> (class (<a> <c>) #:name '<ac>))
|
||||
(<ca> (class (<c> <a>) #:name '<ca>)))
|
||||
(pass-if-equal "slots of <ac>" '(a c)
|
||||
(map slot-definition-name (class-slots <ac>)))
|
||||
(pass-if-equal "slots of <ca>" '(a c)
|
||||
(map slot-definition-name (class-slots <ca>)))
|
||||
(pass-if-exception "can't make <ab>"
|
||||
'(misc-error . "static slot")
|
||||
(class (<a> <b>) #:name '<ab>))
|
||||
;; It should be possible to create subclasses of static classes
|
||||
;; whose slots are statically allocated, as long as there is no
|
||||
;; diamond inheritance among static superclasses, but for now we
|
||||
;; don't support it at all.
|
||||
(pass-if-exception "static subclass"
|
||||
'(misc-error . "static slot")
|
||||
(class (<a>) (slot) #:name '<static-sub> #:static-slot-allocation? #t))
|
||||
(pass-if-equal "non-static subclass" '(a d)
|
||||
(map slot-definition-name (class-slots (class (<a>) (d) #:name '<ad>))))))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue