diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-09-27 17:19:44 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-09-27 17:19:44 -0700 |
commit | 706d76a81618b522199f84d89101d0733c546786 (patch) | |
tree | e48fc3c291606896ddd04b07a6e6cbbacbabbb48 /stdlib/struct.tl | |
parent | 73561e855842fe75450d789ef11c5fd883f221d0 (diff) | |
download | txr-706d76a81618b522199f84d89101d0733c546786.tar.gz txr-706d76a81618b522199f84d89101d0733c546786.tar.bz2 txr-706d76a81618b522199f84d89101d0733c546786.zip |
New :postfini feature in defstruct.
The :postfini clause registers a finalizer that runs in the
ordinary order: after previously registered ones. This has
the effect of allowing a derived structure to run clean-up
actions after those of inherited structures. Either order
can be useful because the dependencies between base and
derived can go in either direction. It's a huge mistake in
C++ that it supports only derived-first destructor invocation
order.
* stdlib/struct.tl (defstruct): Recognize and translate
:postfini clause. It's exactly like :fini but omits the
t parameter in the finalize call, registering in the
natural order.
* tests/012/fini.tl (derived): Add :postfini handler.
* tests/012/fini.expected: Updated to reflect the messages
coming from the postfini handler, which are happening
in the correct order.
* txr.1: Documented.
Diffstat (limited to 'stdlib/struct.tl')
-rw-r--r-- | stdlib/struct.tl | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/stdlib/struct.tl b/stdlib/struct.tl index 4f120eef..f0806723 100644 --- a/stdlib/struct.tl +++ b/stdlib/struct.tl @@ -48,7 +48,8 @@ (compile-error form "bad syntax: dotted form")) (let ((instance-init-form nil) (instance-postinit-form nil) - (instance-fini-form nil)) + (instance-fini-form nil) + (instance-postfini-form nil)) (labels ((expand-slot (form slot) (tree-case slot ((op . args) @@ -102,6 +103,15 @@ (set instance-fini-form (cons arg body)) ^((,word nil nil))) + (:postfini + (unless (bindable arg) + (sys:bad-slot-syntax form slot)) + (when instance-postfini-form + (compile-error form + "duplicate :postfini")) + (set instance-postfini-form + (cons arg body)) + ^((,word nil nil))) (t (when body (sys:bad-slot-syntax form slot)) :))) @@ -158,12 +168,16 @@ ,*(mapcar (aret ^(when (static-slot-p ,arg-sym ',@2) (static-slot-set ,arg-sym ',@2 ,@3))) (append func-si-forms val-si-forms)))) - ,(if (or inst-si-forms instance-init-form instance-fini-form) + ,(if (or inst-si-forms instance-init-form + instance-fini-form instance-postfini-form) ^(lambda (,arg-sym) ,*(if (cdr instance-fini-form) ^((finalize ,arg-sym (lambda (,(car instance-fini-form)) ,*(cdr instance-fini-form)) t))) + ,*(if (cdr instance-postfini-form) + ^((finalize ,arg-sym (lambda (,(car instance-postfini-form)) + ,*(cdr instance-postfini-form))))) ,*(if inst-si-forms ^((let ((,type-sym (struct-type ,arg-sym))) ,*(mapcar (aret ^(unless (static-slot-p ,type-sym ',@2) |