diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-07-08 19:17:39 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-07-08 19:17:39 -0700 |
commit | fc22de3079459193253522efccdd7519879e34b7 (patch) | |
tree | 6c665cc9b800b81827a2a5214ed1125cb0dd49f3 /tree.c | |
parent | c0a9036d15d9f0a910aab82905e6b5e7d6ce71da (diff) | |
download | txr-fc22de3079459193253522efccdd7519879e34b7.tar.gz txr-fc22de3079459193253522efccdd7519879e34b7.tar.bz2 txr-fc22de3079459193253522efccdd7519879e34b7.zip |
type: disallow structs using built-in type names.
This is a big commit motivated by the need to clean up the
situation with built-in type symbols, COBJ objects and
structs.
The struct type system allows struct types to be defined
for symbols like regex or str, which are used by built-in
or cobj types. This is a bad thing.
What is worse, structure instances are COBJ types which
identify their type using the COBJ class symbol mechanism.
There are places in the C implementation which assume
that when a COBJ has a certain class symbol, it is of
a certain expected type, which is totally different from
and incompatible form a struct instance. User code can
define a structure object which will fool that code.
There are multiple things going on in this patch.
The major theme is that the COBJ representation is changing.
Instead of a class symbol, COBJ instances now carry a
"struct cobj_class *" pointer. This pointer is obtained
by registration via the cobj_register function. All modules
must register their class symbols to obtain these class
handles, which are then used in cobj() calls for
instantiation.
The CPTR type was identical to COBJ until now, except for the
type tag. This is changing; CPTR objects will keep the old
representation with the class symbol.
commit 20fdfc6008297001491308849c17498c006fe7b4
Author: Kaz Kylheku <kaz@kylheku.com>
Date: Thu Jul 8 19:17:39 2021 -0700
* ffi.h (carray_cls): Declared.
* hash.h (hash_cls): Declared.
(hash_early_init): Declared.
* lib.h (struct cobj_class): New struct.
(struct cobj): cls member changing to struct cobj_class *.
(struct cptr): New struct, same as previous struct cobj.
(union obj): New member cp of type struct cptr, for CPTR.
(builtin_type): Declared.
(class_check): Declaration moved closer to COBJ-related
functions and updated.
(cobj_register, cobj_register_super, cobj_class_exists): New
functions declared.
(cobjclassp, cobj_handle, cobj_ops): Declarations updated.
* parser.h (parser_cls): Declared.
* rand.h (random_state_cls): Declared.
* regex.h (regex_cls): Declared.
* stream.h (stream_cls, stdio_stream_cls): Declared.
* struct.h (struct_cls): Declared.
* tree.h (tree_cls, tree_iter_cls): Declared.
* vm.h (vm_desc_cls): Declared.
* buf.c (buf_strm, make_buf_stream): Pass stream_cls
functions instead of stream_s class symbol.
* chksum.c (sha256_ctx_cls, md5_ctx_cls): New static class
handles.
(sha256_begin, sha256_hash, sha256_end, md5_begin, md5_hash,
md5_end): Pass class handles to instead of class symbols.
(chksum_init): Initialize class handle variables.
* ffi.c (ffi_type_cls, ffi_call_desc_cls, ffi_closure_cls,
union_cls): New static class handles.
(carray_cls): New global variable.
(ffi_type_struct_checked, ffi_type_print_op,
ffi_closure_struct_checked, ffi_closure_print_op,
make_ffi_type_builtin, make_ffi_type_pointer,
make_ffi_type_struct, make_ffi_type_union,
make_ffi_type_array, make_ffi_type_enum,
ffi_call_desc_checked, ffi_call_desc_print_op,
ffi_make_call_desc, ffi_make_closure, carray_struct_checked,
carray_print_op, make_carray, cptr_getobj, cptr_out,
uni_struct_checked, make_union_common): Pass class handles
instead of class symbols.
(ffi_init): Initialize class handle variables.
* filter.c (regex_from_trie): Use hash_cls class handle
instead of hash_s.
* gc.c (mark_obj): Split COBJ and CPTR cases since the
representation is different.
* hash.c (hash_cls, hash_iter_cls): New class handles.
(make_similar_hash, copy_hash, gethash_c, gethash_e, remhash,
clearhash, hash_count, get_hash_userdata, set_hash_userdata,
hashp, hash_iter_init, hash_begin, hash_next, hash_peek,
hash_reset, hash_reset, hash_uni, hash_diff, hash_symdiff,
hash_isec): Pass class handles instead of class symbols.
(hash_early_init): New function.
(hash_init): Set the class symbols in the class handles that
were created in hash_early_init at a time when these symbols
did not exist.
* lib.c (nelem): New macro.
(cobj_class): New static array.
(cobj_ptr): New static pointer.
(cobj_hash): New static hash.
(seq_iter_cls): New static class handle.
(builtin_type_p): New function.
(typeof): Struct instances now all carry the same symbol,
struct, as their COBJ class symbol. To get their type, we must
call struct_type_name.
(subtypep): Rearrangement of two cases: let's make the
reflexive case first. Adjust code for different location
of COBJ class symbol.
(seq_iter_init_with_info, seq_begin, seq_next, seq_reset,
iter_begin, iter_more, iter_item, iter_step, iter_reset,
make_like, list_collect, do_generic_funcall): Use class
handles instead of class symbols.
(class_check, cobj, cobjclassp, cobj_handle, cobj_ops): Take
class handle argument instead of class symbol.
(cobj_register, cobj_register_super, cobj_class_exists): New
functions.
(cobj_populate_hash): New static function.
(cobj_print_op): Adjust for different location of class
(cptr_print_op, cptr_typed, cptr_type, cptr_handle,
cptr_get): cptr functions now refer to obj->cp rather than
obj->co.
(copy, length, sub, ref, refset, replace, dwim_set, dwim_del,
obj_print): Use class handles for various COBJ types rather
than class symbols.
(obj_init): gc-protect cobj_hash. Initialize seq_iter_cls
class symbol and cobj_hash. Populate cobj_hash as the last
initialization step.
(init): Call hash_early_init immediately after gc_init.
diff --git a/lib.c b/lib.c
* match.c (do_match_line): Refer to regex_cls class handle
instead of regex_s..
* parser.c (parser_cls): New global class handle.
(parse, parser_get_impl, lisp_parse_impl, txr_parse,
parser_errors): Use class handles instead of class symbols.
(parse_init): Initialize parser_cls.
* rand.c (random_state_cls): New global class handle.
(make_state, random_state_p, make_random_state,
random_state_get_vec, random_fixnum, random_float, random):
Use class handles instead of class symbols.
(rand_init): Initialize random_state_cls.
* regex.c (regex_cls): New global class handle.
(chset_cls): New static class handle.
(reg_compile_csets, reg_derivative, regex_compile, regexp,
regex_source, regex_print, regex_run, regex_machine_init): Use
class handles instead of class symbols.
(regex_init): Initialize regex_cls and chset_cls.
* socket.c (make_dgram_sock_stream): Use stream_cls class
symbol instead of stream_s.
* stream.c (stream_cls, stdio_stream_cls): New class handles.
(make_null_stream, stdio_get_fd, make_stdio_stream_common,
stream_fd, sock_family, sock_type, sock_peer, sock_set_peer,
make_dir_stream, make_string_input_stream,
make_string_byte_input_stream, make_strlist_input_stream,
make_string_output_stream, make_strlist_output_stream,
get_list_from_stream, make_catenated_stream,
make_delegate_stream, make_delegate_stream, stream_set_prop,
stream_get_prop, close_stream, get_error, get_error_str,
clear_error, get_line, get_char, get_byte, get_bytes,
unget_char, unget_byte, put_buf, fill_buf, fill_buf_adjust,
get_line_as_buf, format, put_string, put_char, put_byte,
flush_stream, seek_stream, truncate_stream, get_indent_mode,
test_set_indent_mode, test_neq_set_indent_mode,
set_indent_mode, get_indent, set_indent, inc_indent,
width_check, force_break, set_max_length, set_max_depth): Use
class handle instead of symbol.
(stream_init): Initialize stream_cls and stdio_stream_cls.
* struct.c (struct_type_cls, struct_cls): New class handles.
(struct_init): Initialize struct_type_cls and struct_cls.
(struct_handle): Static function moved to avoid forward
declaration.
(stype_handle): Refer to struct_type_cls class handle instead
of struct_type_s symbol. Handle instance objects in addition
to types.
(make_struct_type): Throw error if a built-in type is being
defined as a struct type. Refer to class handle instead of
class symbol.
(find_struct_type, allocate_struct, make_struct_impl,
make_lazy_struct, copy_struct): Refer to class handle instead of
class symbol.
* strudel.c (make_struct_delegate_stream): Refer to stream_cls
class handle instead of stream_s symbol.
* sysif.c (dir_cls): New class handle.
(poll_wrap): Use typep instead of subtypep, eliminating access
to class symbol.
(opendir_wrap, closedir_wrap, readdir_wrap): Use class handles
instead of class symbols.
(sysif_init): Initialize dir_cls.
* syslog.c (make_syslog_stream): Refer to stream_cls class
handle instead of stream_s symbol.
* tree.c (tree_cls, tree_iter_cls): New class handles.
(tree_insert_node, tree_lookup_node, tree_delete_node,
tree_root, tree_equal_op, tree, copy_search_tree,
make_similar_tree, treep, tree_begin, copy_tree_iter,
replace_tree_iter, tree_reset, tree_next, tree_peek,
tree_clear): Use class handle instead of class symbol.
(tree_init): Initialize tree_cls and tree_iter_cls.
* unwind.c (sys_cont_cls): New static class handle.
(revive_cont, capture_cont): Use class handle instead of class
symbol.
(uw_late_init): Initialize sys_cont_cls.
* vm.c (vm_desc_cls): New global class handle.
(vm_closure_cls): New static class handle.
(vm_desc_struct, vm_make_desc, vm_closure_struct,
vm_make_closure, vm_copy_closure): Use class handle instead of
class symbol.
(vm_init): Initialize vm_desc_cls and vm_closure_cls.
Diffstat (limited to 'tree.c')
-rw-r--r-- | tree.c | 56 |
1 files changed, 31 insertions, 25 deletions
@@ -82,6 +82,8 @@ struct tree_diter { val tree_s, tree_iter_s, tree_fun_whitelist_s; +struct cobj_class *tree_cls, *tree_iter_cls; + val tnode(val key, val left, val right) { val obj = make_obj(); @@ -501,7 +503,7 @@ static val tr_delete(val tree, struct tree *tr, val key) val tree_insert_node(val tree, val node) { val self = lit("tree-insert-node"); - struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_s)); + struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_cls)); type_check(self, node, TNOD); @@ -530,7 +532,7 @@ val tree_insert(val tree, val key) val tree_lookup_node(val tree, val key) { val self = lit("tree-lookup-node"); - struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_s)); + struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_cls)); return tr_lookup(tr, key); } @@ -543,7 +545,7 @@ val tree_lookup(val tree, val key) val tree_delete_node(val tree, val key) { val self = lit("tree-delete-node"); - struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_s)); + struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_cls)); return tr_delete(tree, tr, key); } @@ -556,15 +558,15 @@ val tree_delete(val tree, val key) static val tree_root(val tree) { val self = lit("tree-root"); - struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_s)); + struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_cls)); return tr->root; } static val tree_equal_op(val left, val right) { val self = lit("equal"); - struct tree *ltr = coerce(struct tree *, cobj_handle(self, left, tree_s)); - struct tree *rtr = coerce(struct tree *, cobj_handle(self, right, tree_s)); + struct tree *ltr = coerce(struct tree *, cobj_handle(self, left, tree_cls)); + struct tree *rtr = coerce(struct tree *, cobj_handle(self, right, tree_cls)); if (ltr->size != rtr->size) return nil; @@ -683,7 +685,7 @@ val tree(val keys_in, val key_fn, val less_fn, val equal_fn) { struct tree *tr = coerce(struct tree *, chk_calloc(1, sizeof *tr)); val keys = default_null_arg(keys_in), key; - val tree = cobj(coerce(mem_t *, tr), tree_s, &tree_ops); + val tree = cobj(coerce(mem_t *, tr), tree_cls, &tree_ops); seq_iter_t ki; uses_or2; @@ -743,9 +745,9 @@ val copy_search_tree(val tree) { val self = lit("copy-search-tree"); struct tree *ntr = coerce(struct tree *, malloc(sizeof *ntr)); - struct tree *otr = coerce(struct tree *, cobj_handle(self, tree, tree_s)); + struct tree *otr = coerce(struct tree *, cobj_handle(self, tree, tree_cls)); val nroot = deep_copy_tnode(otr->root); - val ntree = cobj(coerce(mem_t *, ntr), tree_s, &tree_ops); + val ntree = cobj(coerce(mem_t *, ntr), tree_cls, &tree_ops); *ntr = *otr; ntr->root = nroot; return ntree; @@ -755,8 +757,8 @@ val make_similar_tree(val tree) { val self = lit("make-similar-tree"); struct tree *ntr = coerce(struct tree *, malloc(sizeof *ntr)); - struct tree *otr = coerce(struct tree *, cobj_handle(self, tree, tree_s)); - val ntree = cobj(coerce(mem_t *, ntr), tree_s, &tree_ops); + struct tree *otr = coerce(struct tree *, cobj_handle(self, tree, tree_cls)); + val ntree = cobj(coerce(mem_t *, ntr), tree_cls, &tree_ops); *ntr = *otr; ntr->root = nil; ntr->size = ntr->max_size = 0; @@ -765,7 +767,7 @@ val make_similar_tree(val tree) val treep(val obj) { - return tnil(type(obj) == COBJ && obj->co.cls == tree_s); + return tnil(type(obj) == COBJ && obj->co.cls == tree_cls); } static void tree_iter_mark(val tree_iter) @@ -790,10 +792,10 @@ static struct cobj_ops tree_iter_ops = cobj_ops_init(eq, val tree_begin(val tree, val lowkey, val highkey) { val self = lit("tree-begin"); - struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_s)); + struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_cls)); struct tree_diter *tdi = coerce(struct tree_diter *, chk_calloc(1, sizeof *tdi)); - val iter = cobj(coerce(mem_t *, tdi), tree_iter_s, &tree_iter_ops); + val iter = cobj(coerce(mem_t *, tdi), tree_iter_cls, &tree_iter_ops); tdi->ti.self = iter; tdi->tree = tree; @@ -815,10 +817,10 @@ val copy_tree_iter(val iter) { val self = lit("copy-tree-iter"); struct tree_diter *tdis = coerce(struct tree_diter *, - cobj_handle(self, iter, tree_iter_s)); + cobj_handle(self, iter, tree_iter_cls)); struct tree_diter *tdid = coerce(struct tree_diter *, chk_calloc(1, sizeof *tdid)); - val iter_copy = cobj(coerce(mem_t *, tdid), tree_iter_s, &tree_iter_ops); + val iter_copy = cobj(coerce(mem_t *, tdid), tree_iter_cls, &tree_iter_ops); int depth = tdis->ti.depth; tdid->ti.self = iter_copy; @@ -841,9 +843,9 @@ val replace_tree_iter(val diter, val siter) { val self = lit("replace-tree-iter"); struct tree_diter *tdid = coerce(struct tree_diter *, - cobj_handle(self, diter, tree_iter_s)); + cobj_handle(self, diter, tree_iter_cls)); struct tree_diter *tdis = coerce(struct tree_diter *, - cobj_handle(self, siter, tree_iter_s)); + cobj_handle(self, siter, tree_iter_cls)); int depth = tdis->ti.depth; tdid->ti.depth = depth; @@ -866,9 +868,9 @@ val replace_tree_iter(val diter, val siter) val tree_reset(val iter, val tree, val lowkey, val highkey) { val self = lit("tree-reset"); - struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_s)); + struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_cls)); struct tree_diter *tdi = coerce(struct tree_diter *, - cobj_handle(self, iter, tree_iter_s)); + cobj_handle(self, iter, tree_iter_cls)); const struct tree_iter it = tree_iter_init(0); tdi->ti = it; @@ -894,8 +896,8 @@ val tree_next(val iter) { val self = lit("tree-next"); struct tree_diter *tdi = coerce(struct tree_diter *, - cobj_handle(self, iter, tree_iter_s)); - struct tree *tr = coerce(struct tree *, cobj_handle(self, tdi->tree, tree_s)); + cobj_handle(self, iter, tree_iter_cls)); + struct tree *tr = coerce(struct tree *, cobj_handle(self, tdi->tree, tree_cls)); if (tdi->lastnode) { val node = tn_find_next(tdi->lastnode, &tdi->ti); @@ -923,8 +925,8 @@ val tree_peek(val iter) { val self = lit("tree-peek"); struct tree_diter *tdi = coerce(struct tree_diter *, - cobj_handle(self, iter, tree_iter_s)); - struct tree *tr = coerce(struct tree *, cobj_handle(self, tdi->tree, tree_s)); + cobj_handle(self, iter, tree_iter_cls)); + struct tree *tr = coerce(struct tree *, cobj_handle(self, tdi->tree, tree_cls)); if (tdi->lastnode) { val node = tn_peek_next(tdi->lastnode, &tdi->ti); @@ -948,7 +950,7 @@ val tree_peek(val iter) val tree_clear(val tree) { val self = lit("tree-clear"); - struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_s)); + struct tree *tr = coerce(struct tree *, cobj_handle(self, tree, tree_cls)); cnum oldsize = tr->size; tr->root = nil; tr->size = tr->max_size = 0; @@ -972,6 +974,10 @@ void tree_init(void) tree_s = intern(lit("tree"), user_package); tree_iter_s = intern(lit("tree-iter"), user_package); tree_fun_whitelist_s = intern(lit("*tree-fun-whitelist*"), user_package); + + tree_cls = cobj_register(tree_s); + tree_iter_cls = cobj_register(tree_iter_s); + reg_fun(tnode_s, func_n3(tnode)); reg_fun(intern(lit("left"), user_package), func_n1(left)); reg_fun(intern(lit("right"), user_package), func_n1(right)); |