summaryrefslogtreecommitdiffstats
path: root/stdlib/struct.tl
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-09-27 17:19:44 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-09-27 17:19:44 -0700
commit706d76a81618b522199f84d89101d0733c546786 (patch)
treee48fc3c291606896ddd04b07a6e6cbbacbabbb48 /stdlib/struct.tl
parent73561e855842fe75450d789ef11c5fd883f221d0 (diff)
downloadtxr-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.tl18
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)