summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-01-03 11:16:48 -0800
committerKaz Kylheku <kaz@kylheku.com>2016-01-03 11:16:48 -0800
commit11ac283d7eda2bac2f19d62d014043f66c8de84c (patch)
tree2b0289573ae6c8337c94734aa58b46b282e916e9
parent629c448f272fe23cefe6eb2b2b90dc8dfb3bbf86 (diff)
downloadtxr-11ac283d7eda2bac2f19d62d014043f66c8de84c.tar.gz
txr-11ac283d7eda2bac2f19d62d014043f66c8de84c.tar.bz2
txr-11ac283d7eda2bac2f19d62d014043f66c8de84c.zip
defstruct: order function slots before other static slots.
This allows the initializer expressions for static slots to instantiate objects, and those instances can rely on methods being set up. * share/txr/stdlib/struct.tl (sys:prune-nil-inits): Recognize :function keyword as denoting a static slot. (defstruct): Represent methods and functions as (:function ...) items rather than (:static ...) so they can be distinguished. Function slots appear before other static slots in the static slot list, and their initializing code is placed into the the static-initfun lambda of the sys:make-struct-type call in this order. * txr.1: Documented.
-rw-r--r--share/txr/stdlib/struct.tl32
-rw-r--r--txr.131
2 files changed, 48 insertions, 15 deletions
diff --git a/share/txr/stdlib/struct.tl b/share/txr/stdlib/struct.tl
index 7e0d2af1..ee4bfd18 100644
--- a/share/txr/stdlib/struct.tl
+++ b/share/txr/stdlib/struct.tl
@@ -29,7 +29,7 @@
(defun sys:prune-nil-inits (slot-init-forms super-type)
(remove-if (tb ((kind name init-form))
- (and (member kind '(:static :instance))
+ (and (member kind '(:static :instance :function))
(null init-form)
(or (not super-type)
(not (slotp super-type name)))))
@@ -56,13 +56,13 @@
"~s: method ~s needs \
\ at least one parameter"
'defstruct name))
- ^(:static ,name
- (lambda ,args
- (block ,name ,*body))))
- (:function ^(:static ,name
- (lambda ,args
- (block ,name
- ,*body))))
+ ^(:function ,name
+ (lambda ,args
+ (block ,name ,*body))))
+ (:function ^(,word ,name
+ (lambda ,args
+ (block ,name
+ ,*body))))
((:static :instance)
(when body
(sys:bad-slot-syntax slot))
@@ -112,11 +112,15 @@
^(:instance ,name nil))
(name
^(:instance ,name nil)))))
- (stat-si-forms [keep-if (op eq :static) slot-init-forms car])
+ (super-type (find-struct-type super))
+ (stat-si-forms [keep-if (op member @1 '(:static :function))
+ slot-init-forms car])
+ (pruned-si-forms (sys:prune-nil-inits stat-si-forms super-type))
+ (func-si-forms [keep-if (op eq :function) pruned-si-forms car])
+ (val-si-forms [keep-if (op eq :static) pruned-si-forms car])
(inst-si-forms [keep-if (op eq :instance) slot-init-forms car])
(stat-slots [mapcar second stat-si-forms])
- (inst-slots [mapcar second inst-si-forms])
- (super-type (find-struct-type super)))
+ (inst-slots [mapcar second inst-si-forms]))
(whenlet ((bad [find-if [notf bindable]
(append stat-slots inst-slots)]))
(throwf 'eval-error
@@ -124,17 +128,15 @@
"~s: slot name ~s isn't a bindable symbol"
"~s: invalid slot specifier syntax: ~s")
'defstruct bad))
- (set stat-si-forms (sys:prune-nil-inits stat-si-forms super-type))
- (set inst-si-forms (sys:prune-nil-inits inst-si-forms super-type))
(let ((arg-sym (gensym))
(type-sym (gensym)))
^(sys:make-struct-type
',name ',super ',stat-slots ',inst-slots
- ,(if stat-si-forms
+ ,(if (or func-si-forms val-si-forms)
^(lambda (,arg-sym)
,*(mapcar (aret ^(when (static-slot-p ,arg-sym ',@2)
(static-slot-set ,arg-sym ',@2 ,@3)))
- stat-si-forms)))
+ (append func-si-forms val-si-forms))))
,(if (or inst-si-forms instance-init-form instance-fini-form)
^(lambda (,arg-sym)
,*(if (cdr instance-fini-form)
diff --git a/txr.1 b/txr.1
index c997d177..fb2a91a6 100644
--- a/txr.1
+++ b/txr.1
@@ -19094,6 +19094,37 @@ type doesn't have. When an instance of the structure is created, then the
instance initializations are performed on that slot from all of the ancestor
structure types in which that slot is also an instance slot.
+The initialization for slots which are specified using the
+.code :method
+or
+.code :function
+specifiers is re-ordered with regard to
+.code :static
+slots. Regardless of their placement in the
+.code defstruct
+form,
+.code :method
+and
+.code :function
+slots are initialized before
+.code :static
+slots. This ordering is useful, because it means that when the initialization
+expression for a given static slot constructs an instance of the struct type,
+any instance initialization code executing for that instance can use
+all functions and methods of the struct type.
+However, note the static slots which follow that slot in the
+.code defstruct
+syntax are not yet initialized. If it is necessary for a structure's
+initialization code to have access to all static slots, even when the
+structure is instantiated during the initialization of a static slot,
+a possible solution may be to use lazy instantiation using the
+.code lnew
+operator, rather than ordinary eager instantiation via
+.codn new .
+It is also necessary to ensure that that the instance isn't accessed until all
+static initializations are complete, since access to the instance slots of a
+lazily instantiated structure triggers its initialization.
+
The structure name is specified using two forms, plain
.meta name
or the syntax