diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-10-20 06:40:07 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-10-20 06:40:07 -0700 |
commit | b67f0c623feb14ff27e1c70ef192163dd31b8945 (patch) | |
tree | 1a3e609992df73a78ac88feb7c3d61ea6becf80c /struct.h | |
parent | 86523c667aceef602f80034d18edf68ee2949a11 (diff) | |
download | txr-b67f0c623feb14ff27e1c70ef192163dd31b8945.tar.gz txr-b67f0c623feb14ff27e1c70ef192163dd31b8945.tar.bz2 txr-b67f0c623feb14ff27e1c70ef192163dd31b8945.zip |
Fix struct lit problem exposed by circular syntax.
The semantics of how struct literals come to life is poorly
designed: namely, the slot-value pairs in the struct literal
are used as the plist argument in a call to make-struct.
This is wrong because the implied initializations are then
clobbered by the structure type's :init and :postinit
handlers, resulting in an object with slot values that don't
match what is in the literal. When you add circular syntax
to the mix, things get worse. Slots may be initialized with
(sys:circ-ref ...) expressions corresponding to #<n># syntax.
These expressions then get clobbered by the constructor
actions before the circ_backpatch processes the syntax.
* parser.y (struct): Use make_struct_lit rather than
make_struct to instantiate struct object.
* struct.tl (sys:struct-lit): Expand to a form which calls
sys:make-struct-lit, rather than make-struct.
* struct.c (struct_init): Register new make_struct_lit
function as sys:make-struct-lit intrinsic.
(make_struct_lit): New function.
* struct.h (make_struct_lit): Declared.
* tests/012/struct.tl: struct literal expansion test case
updated.
* txr.1: Updated documentation of struct literals.
Added compat notes.
Diffstat (limited to 'struct.h')
-rw-r--r-- | struct.h | 1 |
1 files changed, 1 insertions, 0 deletions
@@ -34,6 +34,7 @@ val struct_type_p(val obj); val super(val type); val make_struct(val type, val plist, struct args *); val make_lazy_struct(val type, val argfun); +val make_struct_lit(val type, val plist); val copy_struct(val strct); val clear_struct(val strct, val value); val replace_struct(val target, val source); |