summaryrefslogtreecommitdiffstats
path: root/struct.c
Commit message (Collapse)AuthorAgeFilesLines
* We need a length-< special method.Kaz Kylheku2024-01-191-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Structure objects can be used to implement lazy structures such as sequences. It is undesirable to take the length of a lazy sequence because it forces all of its elements to exist. Moreover, if the sequence is infinite, it is impossible. There are situations in which it is only necessary to know whether the length is less than a certain bound, and for that we have the length-< function. That works on infinite sequence such as lazy lists, requiring them to be forced only so far as to determine the truth value of the test. We need objects that implement lazy sequences to work with this function. * struct.h (enum special_slot): New member length_lt_m. * lib.h (length_lt_s): Symbol variable declared. * struct.c (special_sym): New entry in this table, associating the length_lt_m enum with the length_lt_s symbol variable. * lib.c (length_lt_s): Symbol variable defined. (length_lt): Handle COBJ objects that are structures. we test whether they have a length-< method, or else length method. If they don't have either, we throw. We don't fall back on the default case for objects that don't have a length-< method, because the diagnostic won't be good if they don't have a length method either; the programmer will be informed that the length function couldn't find a length method, without mentioning that it was actually length-< that is being used. * eval.c (eval_init): Register length-< using the length_lt_s symbol variable rather than using intern. * txr.1: Documented. * tests/012/oop-seq.tl: New tests.
* Copyright year bump 2024.Kaz Kylheku2024-01-181-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h, args.c, args.h, arith.c, arith.h, autoload.c, autoload.h, buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, gzio.c, gzio.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, psquare.h, rand.c, rand.h, regex.c, regex.h, signal.c, signal.h, socket.c, socket.h, stdlib/arith-each.tl, stdlib/asm.tl, stdlib/awk.tl, stdlib/build.tl, stdlib/cadr.tl, stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl, stdlib/csort.tl, stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl, stdlib/expander-let.tl, stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl, stdlib/glob.tl, stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.tl, stdlib/load-args.tl, stdlib/match.tl, stdlib/op.tl, stdlib/optimize.tl, stdlib/package.tl, stdlib/param.tl, stdlib/path-test.tl, stdlib/pic.tl, stdlib/place.tl, stdlib/pmac.tl, stdlib/quips.tl, stdlib/save-exe.tl, stdlib/socket.tl, stdlib/stream-wrap.tl, stdlib/struct.tl, stdlib/tagbody.tl, stdlib/termios.tl, stdlib/trace.tl, stdlib/txr-case.tl, stdlib/type.tl, stdlib/vm-param.tl, stdlib/with-resources.tl, stdlib/with-stream.tl, stdlib/yield.tl, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, time.c, time.h, tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr, y.tab.c.shipped: Copyright year bumped to 2024.
* lib: review cobj calls for gc incorrectness and fix.Kaz Kylheku2024-01-061-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | I looked at all cobj calls to see if there is a potential problem, looking for situations whereby the cobj call could trigger a gc that would destroy Lisp objects that the new object either stores, or that its continued initialization depends on. * stream.c (make_strlist_input_stream): call cobj earlier, then fill in the structure. Use chk_calloc to allocate the structure so any Lisp objects in it look like nil until it is initialized. * struct.c (make_struct_impl, make_lazy_struct): Use gc_hint on the type argument, to pin down the st structure that we use in initializations after the cobj call. If the type object were to disappear, the st structure would become invalid. * tree.c (copy_search_tree, make_similar_tree): Use gc_hint on the tree argument to pin down the otr structure that we reference in initializations (copy_tree_iter): Use gc_hint on iter, for similar reasons. * vm.c (vm_copy_closure): Use gc_hint on oclosure, to pin down the environment we are copying from it.
* oop: segfault in special methods cache.Kaz Kylheku2023-11-151-11/+20
| | | | | | | | | | | | | * struct.c (invalidate_special_slots): New static function. (invalidate_special_slot_nonexistence): Move static function up in file, to be next to invalidate_special_slots. (make_struct_type, static_slot_ens_rec): Call the new invalidate_special_slots function in addition to calling static_slot_home_fixup whenever the stslots array is resized. The spslot array contains pointers to the elements of stslots, which become invalid when that is resized. * tests/012/oop-seq.tl: Repro test case added.
* Use vargs typedef instead of struct args *.Kaz Kylheku2023-09-051-15/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | The vargs typedef is underused. Let's use it consistently everywhere. * args.c, * args.h, * args.c, * args.h, * arith.c, * eval.c * ffi.c, * gc.c, * hash.c, * lib.c, * lib.h, * parser.c, * stream.c, * struct.c, * struct.h, * syslog.c, * syslog.h, * unwind.c, * vm.c, * vm.h: All "struct args * declarations replaced with existing "varg" typedef that comes from lib.h.
* New function: arithp.Kaz Kylheku2023-03-261-1/+2
| | | | | | | | | | | | | | | | | | | * lib.h (arithp): Declared. (plus_s): Existing symbol declared. * arith.c (arithp): New function. * struct.h (special_slot): New enum member plus_m. * struct.c (special_sym): Register plus_s together as the [plus_m] entry of the array. * tests/016/arith.tl * tests/016/ud-arith.tl: Tests for arithp. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* Copyright year bump 2023.Kaz Kylheku2023-01-011-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h, args.c, args.h, arith.c, arith.h, autoload.c, autoload.h, buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, gzio.c, gzio.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lex.yy.c.shipped, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, psquare.h, rand.c, rand.h, regex.c, regex.h, signal.c, signal.h, socket.c, socket.h, stdlib/arith-each.tl, stdlib/asm.tl, stdlib/awk.tl, stdlib/build.tl, stdlib/cadr.tl, stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl, stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl, stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl, stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.tl, stdlib/match.tl, stdlib/op.tl, stdlib/optimize.tl, stdlib/package.tl, stdlib/param.tl, stdlib/path-test.tl, stdlib/pic.tl, stdlib/place.tl, stdlib/pmac.tl, stdlib/quips.tl, stdlib/save-exe.tl, stdlib/socket.tl, stdlib/stream-wrap.tl, stdlib/struct.tl, stdlib/tagbody.tl, stdlib/termios.tl, stdlib/trace.tl, stdlib/txr-case.tl, stdlib/type.tl, stdlib/vm-param.tl, stdlib/with-resources.tl, stdlib/with-stream.tl, stdlib/yield.tl, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, time.c, time.h, tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr, y.tab.c.shipped: Copyright year bumped to 2023.
* structs: use type-error rather than error.Kaz Kylheku2022-11-111-5/+5
| | | | | | | * struct.c (struct_handle, stype_handle_impl, struct_handle_for_slot, umethod_fun, umethod_args_fun): Throw type-error rather than error for the situation that an argument isn't a struct.
* args: don't use alloca for const size cases.Kaz Kylheku2022-10-151-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * args.h (args_decl_list): This macro now handles only constant values of N. It declares an anonyous container struct type which juxtaposes the struc args header with exactly N values. This is simply defined as a local variable without alloca. (args_decl_constsize): Like args_decl, but requiring a constant N; implemented via args_decl_list. (args_decl_list_dyn): New name for the old args_decl_list which calls alloca. No places in the code depend on this at all, except the definition of args_decl. (args_decl): Retargeted to args_decl_list_dyn. There is some inconsistency in the macro naming in that args_decl_constsize depends on args_decl_list, and args_decl depends on arg_decl_list_dyn. This was done to minimize diffs. Most direct uses of args_decl_list have a constant size, but a large number of args_decl uses do not have a constant size. * eval.c (op_catch): Use args_decl_constsize. * ffi.c (ffi_struct_in, ffi_struct_get, union_out): Likewise. * ftw.c (ftw_callback): Likewise. * lib.c (funcall, funcall1, funcall2, funcall3, funcall4, uniq, relate): Likewise. * socket.c (sockaddr_in_unpack, sockaddr_in6_unpack, sockaddr_un_unpack): Likewise. * stream.c (formatv): Likewise. * struct.c (struct_from_plist, struct_from_args, make_struct_lit): Likewise. * sysif.c (termios_unpack): Likewise. * time.c (broken_time_struct): Likewise.
* Define bit width of NUM type in one place.Kaz Kylheku2022-09-121-1/+1
| | | | | | | | | | | | * lib.h (NUM_BIT): New preprocessor symbol. * arith.c (CNUM_BIT): Preprocessor symbol removed; this same quantity is already known as PTR_BIT in lib.h. (mul, square): Replace CNUM_BIT with PTR_BIT. (comp_trunc, logtrunc, sign_extend, ash): Replace num_bits with NUM_BIT. * struct.c (struct_inst): Replace calculation with NUM_BIT.
* Reduce proliferation of TAG_SHIFT.Kaz Kylheku2022-09-121-5/+5
| | | | | | | | | | | * arith.c (num_to_buffer, c_unum, c_dbl_num, c_dbl_unum, c_num, c_fixnum): Use c_n inline function instead of open coding exactly the same thing. * lib.c (c_chr): Likewise. * struct.c (make_struct_type, lookup_slot, lookup_static_slot_desc, static_slot_p): Likewise.
* oop: corruption bugfix.Kaz Kylheku2022-05-231-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | * struct.c (alloc_seen): Fix under-sized alloca and memset, where the size being used is the number of elements, but should be the number of bytes. This showed up as a failure in the tests/012/oop-mi.tl on PPC64, uncovered by a completely unrelated change in eval.c. The unrelated code never executes during the failed test case; it just affects some memory contents of the stack somehow. The under-allocated array is used during structure type initialization to hold a bitmask which helps to suppress the duplicate initiation of base structures which are inherited multiple times (duplicate bases). I think why this shows up on PPC64 is the big endian order. The sizes involved are small. The test case has a couple of duplicate bases only, but a full 64 bit mask needs to be allocated for that since the mask is an array of ucnum. On little endian, it doesn't matter than only a single byte is allocated: that is enough for 8 duplicate bases, and because of the byte order, those bases land into the byte that is allocated. On big endian, the bases will be on the high part of the 64 bit word, and thus over in the area we didn't allocate. To reproduce an issue on little endian, you need an inheritance hierarchy with more duplicate bases.
* listener: restore and improve method completion.Kaz Kylheku2022-02-191-40/+0
| | | | | | | | | | | | | | | | | | | | | The recent autoload changes have degraded method completion, which didn't work well in the first place. Test case: with this change you can type term.(go[Tab] to complete to term.(go-raw or term.(go-cbreak. * parser.c (find_matching_syms): Do not use the get_slot_syms function for finding method and slot symbols. Just use get_visible_syms, like for other bindings. Instead, in the switch statement in the loop, for the 'M' (method) and 'S' (slot) completion types, we use the static_slot_types and slot_types functions to inquire whether a symbol has a binding. And these two functions do something important: unlike get_slot_syms, they trigger autoload. * struct.c (get_slot_syms): Function removed. * struct.h (get_slot_syms): Declaration removed.
* lisplib: rename lisplib funtions to autoload prefix.Kaz Kylheku2022-02-181-8/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | * lisplib.c (lisplib_init): Follow rename, and rename try-load-fun to autoload-try-fun. (lisplib_try_load_fun, lisplib_try_load_var, lisplib_try_load_fun_var, lisplib_try_load_slot, lisplib_try_load_struct, lisplib_try_load_keyword): Renamed from `lisplib_try_load_@kind` to `autoload_try_@kind`. * lisplib.h (lisplib_try_load_fun, lisplib_try_load_var, lisplib_try_load_fun_var, lisplib_try_load_slot, lisplib_try_load_struct, lisplib_try_load_keyword): Declarations renamed. * eval.c (lookup_global_var, lookup_sym_lisp1, lookup_fun, lookup_mac, lookup_symac, lookup_symac_lisp1, special_var_p, expand_param_macro, rt_defvar, rt_defv, op_defsymacro, rt_defsymacro, rt_defun, rt_defmacro, makunbound, fmakunbound, mmakunbound): Follow rename. * struct.c (make_struct_type, find_struct_type, lookup_slot_load, lookup_static_slot_load, lookup_static_slot_desc_load, slot_types, static_slot_types): Follow rename. * stdlib/place.tl (get-place-macro): Follow rename of try-load-fun to autoload-try-fun.
* lisplib: split lisplib_try_load into namespaces.Kaz Kylheku2022-02-181-7/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * lisplib.c (lisplib_init): Change sys:try-load (only used by place.tl) to sys:try-load-fun, and register it to (lisplib_try_load): External function becomes static. (lisplib_try_load_fun, lisplib_try_load_var, lisplib_try_load_fun_var, lisplib_try_load_slot, lisplib_try_load_struct, lisplib_try_load_keyword): New functions. * lisplib.h (lisplib_try_load): Declaration removed. (lisplib_try_load): External function becomes static. (lisplib_try_load_fun, lisplib_try_load_var, lisplib_try_load_fun_var, lisplib_try_load_slot, lisplib_try_load_struct, lisplib_try_load_keyword): Declared. * eval.c (lookup_global_var, lookup_var, lookup_symac, lookup_symac_lisp1, rt_defvarl, rt_defv, op_defsymacro, rt_defsymacro, makunbound): Use lisplip_try_load_var. (lookup_fun, lookup_mac, rt_defun, rt_defmacro, fmakunbound, mmakunbound): Use lisplib_try_load_fun. (expand_param_macro): Use lisplib_try_load_keyword, which is a catch-all namespace for anything tied to keywords. * struct.c (make_struct_type, find_struct_type): Use lisplib_try_load_struct. (lookup_sloat_load, lookup_static_slot_load, lookup_static_slot_desc_load, slot_types, static_slot_types): Use lisplib_try_load_slot. * stdlib/place.tl (get-place-macro): Use try-load-fun, rather than try-load.
* Fix various instances of implicit conversions.Paul A. Patience2022-02-141-1/+1
| | | | | | | | | | | | | | | | | | | | | The implicit conversions were discovered with Clang's UBSan (with the -fsanitizer=implicit-conversion option). * gc.c (sweep_one): Convert only the inverted REACHABLE, since block->t.type is already of the right type. * hash.c (eql_hash, eq_hash, hash_iter_init, us_hash_iter_init): Explicitly convert to ucnum. * linenoise/linenoise.c (enable_raw_mode): Explicitly convert the inverted flag sets to tcflag_t. * mpi/mpi.c (mp_set_uintptr): Explicitly convert to uint_ptr_t. * regex.c (char_set_add): Explicitly convert to bitcell_t. * struct.c (struct_inst_hash): Correct type of hash from cnum to ucnum.
* Copyright year bump 2022.Kaz Kylheku2022-01-111-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | *LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lex.yy.c.shipped, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, psquare.h, rand.c, rand.h, regex.c, regex.h, signal.c, signal.h, socket.c, socket.h, stdlib/arith-each.tl, stdlib/asm.tl, stdlib/awk.tl, stdlib/build.tl, stdlib/cadr.tl, stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl, stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl, stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl, stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.tl, stdlib/match.tl, stdlib/op.tl, stdlib/optimize.tl, stdlib/package.tl, stdlib/param.tl, stdlib/path-test.tl, stdlib/pic.tl, stdlib/place.tl, stdlib/pmac.tl, stdlib/quips.tl, stdlib/save-exe.tl, stdlib/socket.tl, stdlib/stream-wrap.tl, stdlib/struct.tl, stdlib/tagbody.tl, stdlib/termios.tl, stdlib/trace.tl, stdlib/txr-case.tl, stdlib/type.tl, stdlib/vm-param.tl, stdlib/with-resources.tl, stdlib/with-stream.tl, stdlib/yield.tl, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, time.c, time.h, tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr, y.tab.c.shipped: Copyright year bumped to 2022.
* Casts have crept into the code not wrapped by macros.Kaz Kylheku2022-01-061-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It is against TXR coding conventions to use the C cast notation. The usage creeps into the code. To find instances of this, we must compile using GNU g++, and add -Wold-style-cast via EXTRA_FLAGS. * eval.c (prof_call): Use macro instead of cast. * ffi.c (pad_retval, ffi_varray_alloc, make_ffi_type_union, carray_dup, carray_replace, uint_carray, int_carray, put_carray, fill_carray): Likewise. * itypes.c (c_i64, c_u64): Likewise. * lib.c (cyr, chk_xalloc, spilt_str_keep, vector, cobj_register): Likewise. * linenoise.c (record_undo): Likewise. Also, drop one superfluous cast: wstrdup_fn returns wchar_t *. (flash, edit_insert, edit_insert_str): Use macro instead of cast. * mpi/mpi.c (s_mp_ispow2d): Likewise. * parser.c (lino_getch): Likewise. * rand.c (make_random_state, random_buf): Likewise. * stream.c (generic_get_line, do_parse_mode): Likewise. * struct.c (get_duplicate_supers, call_initfun_chain, call_postinitfun_chain): Likewise. * sysif.c (c_time): Likewise. * tree.c (tr_insert): Likewise.
* Eliminate declaration-after-statement everywhere.Kaz Kylheku2021-12-291-8/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The use of -ansi doesn't by itself diagnose instances of some constructs we don't want in the project, like mixed declarations and statements. * configure (diag_flags): Add -Werror=declaration-after-statement. This is C only, so filter it out for C++. Also add -Werror=vla. * HACKING: Update inaccurate statements about what dialect we are using. TXR isn't pure C90: some GCC extensions are used. We even use long long if the configure script detects it as working, and some C99 library features. * buf.c (replace_buf, buf_list): Fix by reordering. * eval.c (op_dohash, op_load_time_lit): Fix by reordering. * ffi.c (ffi_simple_release): Fix by reordering. (align_sw_get): Fix empty macro to expand to dummy declaration so a semicolon after it isn't interpreted as a statement. On platforms with alignment, remove a semicolon from the macro so that it requires one. (ffi_i8_put, ffi_u8_put): Fix by reordering. * gc.c (gc_init): Fix with extra braces. * hash.c (hash_init): Fix by reordering. * lib.c (list_collect_revappend, sub_iter, replace_str, replace_vec, mapcar_listout, mappend, mapdo, window_map_list, subst): Fix by reordering. (gensym, find, rfind, pos, rpos, in, search_common): Fix by renaming optional argument and using declaration instead of assignment. * linenoise/linenoise.c (edit_in_editor): Fix by reordering. * parser.c (is_balanced_line): Fix by reordering. * regex.c (nfa_count_one, print_rec): Fix by reordering. * signal.c (sig_mask): Fix by reordering. * stream.c (get_string): Fix by renaming optional argument and using declaration instead of assignment. * struct.c (lookup_static_slot_desc): Fix by turning mutated variable into block local. (umethod_args_fun): Fix by reordering. (get_special_slot): Fix by new scope via braces. * sysif.c (usleep_wrap): Fix by new scope via braces. (setrlimit_wrap): Fix by new scope via braces. * time.c (time_string_meth, time_parse_meth): Fix by reordering. * tree.c (tr_do_delete_spec): Fix by new scope via braces. * unwind.h (uw_block_beg): New macro which doesn't define RESULTVAR but expects it to refers to an existing one. (uw_block_begin): Replace do while (0) with enum trick so that we have a declaration that requires a semicolon, rather than a statement, allowing declarations to follow. (uw_match_env_begin): Now opens a scope and features the same enum trick as in uw_block_begin. This fixes a declaration-follows-statement issue in the v_output function in match.c. (uw_match_env_end): Closes scope opened by uw_match_env_begin. * unwind.c (revive_cont): Fix by introducing variable, and using new uw_block_beg macro. * vm.c (vm_execute_closure): Fix using combination of local variable and reordering.
* vm, structs: use FLEX_ARRAY macro.Kaz Kylheku2021-09-191-1/+1
| | | | | | | | * vm.c (struct vm_closure): Use the FLEX_ARRAY macro to define the trailing array at the end of the structure instead of hard-coding [1]. * struct.c (struct struct_inst): Likewise.
* oop: remove repeated code in slot lookup.Kaz Kylheku2021-09-091-24/+8
| | | | | | | | * struct.c (lookup_slot): Do not repeat the slot lookup logic for the case when the symbol's slot_cache must be boostrapped, which only happens exactly once in the life of a symbol. Just allocate the cache if necessary and fall through to the have-cache case.
* gcc11: warnings related to struct args allocation..Kaz Kylheku2021-09-081-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As reported by Paul A. Patience, GCC 11 warns about situations in a few places where we do args_decl(args, 0) to allocate an absolutely empty argument list object. (This by the way, is only done in places where we are absolutely sure that the function we call will not be accessing the arguments. The usual rule is that there have to be at least ARGS_MIN arguments allocated, currently 4, and code relies on that being the case! So the places which call args_decl(args, 0) are coded carefully, checking that args is not passed anywhere where ARGS_MIN space is required.) Anyway, in the 0 case, the val arg[1] member of struct args is not allocated at all, because we call alloca(offsetof (struct args, arg)). Now GCC 11 notices this and complains that accesses to the other members like args->fill or args->list are using a struct that has not been entirely allocated. This, even though those members lie entirely within the allocated area. The fix for this is two faceted. Firstly, on C99, this diagnostic goes away if we make one simple change: declare the arg array as a flexible array member: val arg[]. However, we still support C90 in maintainer mode. So in maintainer mode, we stick with the 1. But we ensure that the places which call args_decl(args, 0) will pass 1 instead of 0, so the whole structure is allocated. * lib.h (FLEX_ARRAY): New macro: empty definition in C99 or later, otherwise 1. * args.h (struct args): Declare the size of the arg member using the new FLEX_ARRAY macro from lib.h. (ARGS_ABS_MIN): New macro, the absolute args minimum: zero in C99 mode, 1 in maintainer C90 mode. * ffi.c (ffi_struct_in, ffi_struct_get, make_zstruct): Use ARGS_ABS_MIN instead of 0 when preparing dummy args for make_struct call. * struct.c (struct_from_plist, struct_from_args, make_struct_lit): Use ARGS_ABS_MIN instead of zero when preparing dummy args for make_struct_impl or make_struct call.
* license: reformat to fit 80 columns.Kaz Kylheku2021-08-161-12/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c, buf.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c, lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, rand.c, rand.h, regex.c, regex.h, signal.c, signal.h, socket.c, socket.h, stdlib/asm.tl, stdlib/awk.tl, stdlib/build.tl, stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl, stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl, stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl, stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.tl, stdlib/match.tl, stdlib/op.tl, stdlib/optimize.tl, stdlib/package.tl, stdlib/param.tl, stdlib/path-test.tl, stdlib/pic.tl, stdlib/place.tl, stdlib/pmac.tl, stdlib/quips.tl, stdlib/save-exe.tl, stdlib/socket.tl, stdlib/stream-wrap.tl, stdlib/struct.tl, stdlib/tagbody.tl, stdlib/termios.tl, stdlib/trace.tl, stdlib/txr-case.tl, stdlib/type.tl, stdlib/vm-param.tl, stdlib/with-resources.tl, stdlib/with-stream.tl, stdlib/yield.tl, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, time.c, time.h, tree.c, tree.h, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h: License reformatted. * lex.yy.c.shipped, y.tab.c.shipped, y.tab.h.shipped: Updated.
* struct: get rid of pointer typedef.Kaz Kylheku2021-07-271-5/+5
| | | | | | | | * lib.h (slot_cache_t): Typedef removed. (struct sym): Use slot_cache_set_t *. * struct.c (struct_type_finalize, lookup_slot, lookup_static_slot, lookup_static_slot_desc): Likewise.
* hash: change make_hash interface.Kaz Kylheku2021-07-221-5/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The make_hash function now takes the hash_weak_opt_t enumeration instead of a pair of flags. * hash.c (do_make_hash): Take enum argument instead of pair of flags. Just store the option; nothing to calculate. (weak_opt_from_flags): New static function. (tweak_hash): Function removed. (make_seeded_hash): Adjust to new do_make_hash interface with help from weak_opt_from_flags. (make_hash, make_eq_hash): Take enum argument instead of pair of flags. (hashv): Calculate hash_weak_opt_t enum from the extracted flags, pass down to make_eq_hash or make_hash. * hash.h (tweak_hash): Declration removed. (make_hash, make_eq_hash): Declarations updated. * eval.c (me_case, expand_switch): Update make_hash calls to new style. (eval_init): Update make_hash calls and get rid of tweak_hash calls. This renders the tweak_hash function unused. * ffi.c (make_ffi_type_enum, ffi_init): Update make_hash calls to new style. * filter.c (make_trie, trie_add, filter_init): Likewise. * lib.c (make_package_common, obj_init, obj_print): Likewise. * lisplib.c (lisplib_init): Likewise. * match.c (dir_tables_init): Likewise. * parser.c (parser_circ_def, repl, parse_init): Likewise. * parser.l (parser_l_init): Likewise. * struct.c (struct_init, get_slot_syms): Likewise. * sysif.c (get_env_hash): Likewise. * lex.yy.c.shipped, y.tab.c.shipped: Updated.
* compat: fix glaringly broken init-time handling.Kaz Kylheku2021-07-211-8/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We are doing numerous compat_ver checks in various init functions, to enact alternative symbol registrations. Only problem is, compat_ver is always zero during initialization; it is not set until the -C option is processed in txr_main. Registrations must be fixed up after initialization; that's what the compat_fixup mechanism is for. This is an long-standing problem which affects compatibility operation going back over 150 versions. * arith.c (arith_init): Move compat logic to arith_compat_fixup. (arith_compat_fixup): New function. * arith.h (arith_compat_fixup): Declared. * eval.c (eval_init): Move compat logic to eval_compat_fixup. * ffi.c (ffi_init): Move compat logic to ffi_compat_fixup. (ffi_compat_fixup): New function. * ffi.h (ffi_compat_fixup): Declared. * regex.c (regex_init): Move compat logic to regex_compat_fixup. (regex_compat_fixup): New function. * regex.h (regex_compat_fixup): Declared. * stream.c (stream_init): Move compat logic to stream_compat_fixup. (stream_compat_fixup): New function. * stream.h (stream_compat_fixup): Declared. * struct.c (struct_init): Move compat logic to struct_compat_fixup. (struct_compat_fixup): New function. * struct.h (stream_compat_fixup): Declared. * lib.c (compat_fixup): Call arith_compat_fixup, ffi_compat_fixup, regex_compat_fixup, stream_compat_fixup and struct_compat_fixup.
* defstruct: diagnose built-in type being redefined.Kaz Kylheku2021-07-091-1/+1
| | | | | | | | | | | | | | | | | | * eval.c (eval_init): Register built-in-type-p intrinsic. * lib.c (buitin_type_p): Rename to built_in_type_p since the word built-in is hyphenated. The function also tests whether the argument is a COBJ class. (cobj_class_exists): Function removed. * stdlib/doc-syms.tl: Updated. * stdlib/struct.tl (defstruct): Add built-in-type-p check. * struct.c (make_struct_type): Call only built_in_type_p; cobj_class_exists is gone. * txr.1: Document built-in-type-p.
* struct: rework stype_handle change.Kaz Kylheku2021-07-091-12/+14
| | | | | | | | | | | | | | | | | | | | | | | The change which allows stype_handle to recognize struct instances, and obtain their type, has some possibly unwanted ramifications, since the function is widely used. Let's refactor things so that, for now, only the struct_type_name function takes advantage of this flexibility. * struct.c (stype_handle_impl): New static function, copy of stype_handle, but taking an obj_ok Boolean argument to indicate whether an object instance is an acceptable argument, whose type should be fetched. (stype_handle): Now a wrapper around stype_handle_impl passing nil for the obj_ok argument. (stype_handle_obj): New static function. Passes t for the ok_obj argument of stype_handle_impl. (struct_type_name): Call stype_handle_obj instead of stype_handle. (super): Take advantage of stype_handle_obj to reduce code. * txr.1: Update documentation of struct-type-name, and improve that of super.
* type: disallow structs using built-in type names.Kaz Kylheku2021-07-081-17/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Copyright year bump 2021.Kaz Kylheku2021-01-141-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * METALICENSE: 2020 copyrights bumped to 2021. Added note about SHA-256 routines from Colin Percival. * LICENSE, LICENSE-CYG, Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lex.yy.c.shipped, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/asm.tl, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/compiler.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/copy-file.tl, share/txr/stdlib/debugger.tl, share/txr/stdlib/defset.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/each-prod.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/param.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/quips.tl, share/txr/stdlib/save-exe.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/trace.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/vm-param.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, time.c, time.h, tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr, y.tab.c.shipped: Copyright year bumped to 2021.
* struct: bad object in two diagnostics.Kaz Kylheku2020-10-161-2/+2
| | | | | | | * struct.c (umethod_fun, umethod_args_fun): The env function is being used as an object, passed to the ~a conversion specifier of the formatter. The correct argument is the sym variable.
* tags: address small issue with tag lookup.Kaz Kylheku2020-09-011-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Exuberant Ctags uses the full content of one line as the key to find a tag. A function declaration that is split into multiple lines can have a first line which is identical to the definition, as in: static int add(int a, int b); static int add(int a, int b) { return a + b; } Here, the search key which ctags uses for the add function is "static int add(int a,", taken from the definition. But it's exactly the same as a the first line of the declaration, and that is what Vim jumps to for that tag. A few function declarations in TXR have this issue. * eval.c (expand_params_rec, do_eval): Make the first line of the forward declaration different from the first line of the definition. * match.c (mf_all): Likewise. * struct.c (make_struct_type_compat): Likewise.
* OOP: use chk_calloc for objects.Kaz Kylheku2020-08-271-9/+4
| | | | | | | * struct.c (make_struct_impl, make_lazy_struct): Use chk_calloc instead of chk_malloc for allocating objects. Remove the loops that initialize slots to nil. Remove the initialization of the lazy flag to zero.
* OOP: bugfix: lazy object uninitialized dirty flag.Kaz Kylheku2020-08-271-0/+1
| | | | | | * struct.c (make_lazy_struct): Initialize dirty flag to 1, as required by the documentation, since all newly instantiated objects are dirty.
* OOP: optimization in dupe base check.Kaz Kylheku2020-08-271-7/+7
| | | | | | | | | | | | | | | | | | | | Hypothesis: the majority of struct types will not be used as inheritance bases, and most of those that are bases will not be appear as duplicate bases. If we put a flag into a type which indicates that it has been used as a duplicate base, we can check that flag to do less work when initializing an object. * struct.c (struct struct_type): New flag, dupe. (get_duplicate_supers): Each time we find a duplicate supertype, we set its dupe flag. (make_struct_type): Allocate the struct type with chk_calloc instead of chk_malloc, so the flag is initialized to zero. Remove initializations of some members to zero: those of nslots, ntslots, stslot and spslot. (call_initfun_chain, call_postinitfun_chain): Don't bother search for st in the root's array of duplicates if st is not marked with the dupe flag.
* structs: deal with initialization diamond problem.Kaz Kylheku2020-08-271-11/+112
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Until now it has been documented that if a struct type inherits a supertype two or more times, then the supertype initialization occurs that many times. This change fixes the behavior: bases are initialized once. * struct.c (struct struct_type): New members, ndsupers, dsus providing a flat array for tracking duplicate supertypes. (get_all_supers, get_duplicate_supers): New static functions. (make_struct_type): Calculate the duplicate supers, and store them in the dsus array. Under 242 or lower compat mode, pretend there are duplicates, which defeats the duplicate detecting mechanism (struct_type_destroy): Free the dsus array. (call_inittfun_chain, call_postinitfun_chain): Take new arguments: the root type from which the recursion started, and a stack-allocated bit vector indicating which duplicate bases have already been initialized. If the given type appears in the duplicate bases list of the root type, and its bit is already set, then skip all initialization for it. Otherwise set its bit and proceed. (alloc_seen, clear_seen): New macros to help with allocating the bitvector of duplicate bases. (make_struct_impl, lazy_struct_init, reset_struct): Use alloc_seen and clear_seen macros to manage the bitvector of duplicate bases for calling call_initfun_chain and call_postinitfun_chain. * txr.1: Updated doc with new paragraph about duplicated supertypes, and compat note added.
* Change noreturn to NORETURN.Kaz Kylheku2020-08-071-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The noreturn macro is respelled to harmonize with the upper-case INLINE and NOINLINE. * lib.h (noreturn): Rename to NORETURN. * arith.c (not_number, not_integer, invalid_ops, invalid_op): Declaration updated. * arith.c (do_mp_error): Likewise. * eval.c (eval_error, no_bindable_error, dotted_form_error): Likewise. * eval.h (eval_error): Likewise. * lib.c (unsup_obj, callerror, wrongargs): Likewise. * match.c (sem_error): Likewise. * stream.c (unimpl, unimpl_put_string, unimpl_put_char, unimpl_put_byte, unimpl_get_line, unimpl_get_char, unimpl_get_byte, unimpl_unget_char, unimpl_unget_byte, unimpl_put_buf, unimpl_fill_buf, unimpl_seek, unimpl_truncate, unimpl_get_sock_family, unimpl_get_sock_type, unimpl_get_sock_peer, unimpl_set_sock_peer): Likewise. * struct.c (no_such_struct, no_such_slot, no_such_static_slot): Likewise. * unwind.h (jmp_restore, uw_throw, uw_throwf, uw_errorf, uw_errorfv, type_mismatch): Likewise.
* New: protocol for iteration with structs.Kaz Kylheku2020-07-071-1/+21
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * lib.c (seq_iterable): Return t if argument is a structure supporting the iter-begin method. (seq_iter_get_oop, seq_iter_peek_oop, seq_iter_get_fast_oop, seq_iter_peek_fast_oop): New static functions. (seq_iter_init_with_info): Handle COBJ case. If the COBJ is a structure which suports the iter-begin method, then retrieve the iterator object by calling it, and then prepare the iterator structure for either the fast or the canonical protocol based on whether the iterator supports iter-more. (seq_iter_mark): Mark the iter member if the iterator is a struct object. (iter_begin): Rearrange tests here to check object type first before sequence kind. If the object is a structure supporting the iter-begin method, then call it and return its value. (iter_more, iter_step): Check for struct object with corresponding special methods and return. (iter_reset): Similar change like in iter_begin. We check for the iter-reset special method and try to use it, otherwise fall back on the regular iter_begin logic. * lib.h (struct seq_iter): New member next of the ul union for caching the result of a peek operation. * struct.c (iter_begin_s, iter_more_s, iter_item_s, iter_step_s, iter_reset_s): New symbol variables; (special_sym): Pointers to new symbol variables added to array. (struct_init): New symbol variables initialized. (get_special_required_slot): New function. * struct.h (iter_begin_s, iter_more_s, iter_item_s, iter_step_s, iter_reset_s): Declared. (enum special_slot): New enum members iter_begin_m, iter_more_m, iter_item_m, iter_step_m, iter_reset_m. (get_special_required_slot): Declared. * txr.1: Documented. * tests/012/oop-seq.expected: New file. * tests/012/oop-seq.tl: New file.
* struct: bugfix: autoload on instance slot also.Kaz Kylheku2020-07-021-1/+4
| | | | | | | | | | | | | | | | | * struct.c (slot_types): Try lisplib_try_load, just like in static_slot_types. The reason for this is that there is code like (or (sys:slot-types slot) (sys:static-slot-types slot)) which occurs in sys:check-slot, testing both hashes. This code gets fooled in the following way: the sys:slot-types slot reports nil for a particular slot being probed. It doesn't try autoloading, checking the hash just once. Next, sys:static-slot-types is called and triggers an autoload. The autoload instantiates the slot as an instance slot (but not as a static slot). Then sys:static-slot-types returns nil also because there is no such static slot. The effect is that the slot exists due to the autload, but since both functions yielded nil, the overall (or ...) expression yields nil, which is interpreted as the slot not existing.
* struct: wasteful double creation of slot_type_hash.Kaz Kylheku2020-07-021-1/+0
| | | | | * struct.c (struct_init): Delete uselessly repeated statement that generates a garbage hash object.
* c_num: now takes self argument.Kaz Kylheku2020-06-291-6/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The c_num and c_unum functions now take a self argument for identifying the calling function. This requires changes in a large number of places. In a few places, additional functions acquire a self argument. The ffi module has the most extensive example of this. Some functions mention their name in a larger string, or have scattered literals giving their name; with the introduction of the self local variable, these are replaced by references to self. In the following changelog, the notation TS stands for "take self argument", meaning that the functions acquires a new "val self" argument. The notation DS means "define self": the functions in question defines a self variable, which they pass down. The notation PS means that the functions pass down an existing self variable to functions that now require it. * args.h (args_count): TS. * arith.c (c_unum, c_num): TS. (toint, exptv): DS. * buf.c (buf_check_len, buf_check_alloc_size, buf_check_index, buf_do_set_len, replace_buf, buf_put_buf, buf_put_i8, buf_put_u8, buf_put_char, buf_put_uchar, buf_get_bytes, buf_get_i8, buf_get_u8, buf_get_cptr, buf_strm_get_byte_callback, buf_strm_unget_byte, buf_swap32, str_buf, buf_int, buf_uint, int_buf, uint_buf): PS. (make_duplicate_buf, buf_shrink, sub_buf, buf_print, buf_pprint): DS. * chskum.c (sha256_stream_impl, sha256_buf, crc32_buf, md5_stream_impl, md5_buf): TS. (chksum_ensure_buf, sha256_stream, sha256, sha256_hash, md5_stream, md5, md5_hash): PS. (crc32_stream): DS. * combi.c (perm_while_fun, perm_gen_fun_common, perm_str_gen_fun, rperm_gen_fun, comb_vec_gen_fun, comb_str_gen_fun, rcomb_vec_gen_fun, rcomb_str_gen_fun): DS. * diff.c (dbg_clear, dbg_set, dbg_restore): DS. * eval.c (do_eval, gather_free_refs, maprodv, maprendv, maprodo, do_args_apf, do_args_ipf): DS. (op_dwim, me_op, map_common): PS. (prod_common): TS. * ffi.c (struct txr_ffi_type): release member TS. (make_ffi_type_pointer): PS and release argument TS. (ffi_varray_dynsize, ffi_array_in, ffi_array_put_common, ffi_array_get_common, ffi_varray_in, ffi_varray_null_term): PS. (ffi_simple_release, ffi_ptr_in_release, ffi_struct_release, ffi_wchar_array_get, ffi_array_release_common, ffi_array_release, ffi_varray_release): TS. (ffi_float_put, double_put, ffi_be_i16_put, ffi_be_u16_put, ffi_le_i16_put, ffi_le_u16_put, ffi_be_i32_put, ffi_be_u32_put, ffi_le_i32_put, ffi_sbit_put, ffi_ubit_put, ffi_buf_d_put, make_ffi_type_array, make_ffi_type_enum, ffi_type_compile, make_ffi_type_desc, ffi_make_call_desc, ffi_call_wrap, ffi_closure_dispatch_save, ffi_put_into, ffi_in, ffi_get, ffi_put, carray_set_length, carray_blank, carray_buf, carray_buf_sync, carray_cptr, carray_refset, carray_sub, carray_replace, carray_uint, carray_int): PS. (carray_vec, carray_list): DS. * filter.c (url_encode, url_decode, base64_stream_enc_impl): DS. * ftw.c (ftw_callback, ftw_wrap): DS. * gc.c (mark_obj, gc_set_delta): DS. * glob.c (glob_wrap): DS. * hash.c (equal_hash, eql_hash, eq_hash, do_make_hash, hash_equal, set_hash_traversal_limit, gen_hash_seed): DS. * itypes.c (c_i8, c_u8, c_i16, c_u16, c_i32, c_u32, c_i64, c_u64, c_short, c_ushort, c_int, c_uint, c_long, c_ulong): PS. * lib.c (seq_iter_rewind): TS and becomes internal. (seq_iter_init_with_info, seq_setpos, replace_str, less, replace_vec, diff, isec, obj_print_impl): PS. (nthcdr, equal, mkstring, mkustring, upcase_str, downcase_str, search_str, sub_str, cat_str, scat2, scat3, fmt_join, split_str_keep, split_str_set, trim_str, int_str, chr_int, chr_str, chr_str_set, vector, vecref, vecref_l, list_vec, copy_vec, sub_vec, cat_vec, lazy_str_put, lazy_str_gt, length_str_ge, length_str_lt, length_str_le, cptr_size_hint, cptr_int, out_lazy_str, out_quasi_str, time_string_local_time, time_string_utc, time_fields_local_time, time_fields_utc, time_struct_local, time_struct_utc, make_time, time_meth, time_parse_meth): DS. (init_str, cat_str_init, cat_str_measure, cat_str_append, vscat, time_fields_to_tm, time_struct_to_tm, make_time_impl): TS. * lib.h (seq_iter_rewind): Declaration removed. (c_num, c_unum, init_str): Declarations updated. * match.c (LOG_MISMATCH, LOG_MATCH): PS. (h_skip, h_coll, do_output_line, do_output, v_skip, v_fuzz, v_collect): DS. * parser.c (parser, circ_backpatch, report_security_problem, hist_save, repl, lino_fileno, lino_getch, lineno_getl, lineno_gets, lineno_open): DS. (parser_set_lineno, lisp_parse_impl): PS. * parser.l (YY_INPUT): PS. * rand.c (make_random_state): PS. * regex.c (print_rec): DS. (search_regex): PS. * signal.c (kill_wrap, raise_wrap, get_sig_handler, getitimer_wrap, setitimer_wrap): DS. * socket.c (addrinfo_in, sockaddr_pack, fd_timeout, to_connect, open_sockfd, sock_mark_connected, sock_timeout): TS. (getaddrinfo_wrap, dgram_set_sock_peer, sock_bind, sock_connect, sock_listen, sock_accept, sock_shutdown, sock_send_timeout, sock_recv_timeout, socketpair_wrap): DS. * stream.c (generic_fill_buf, errno_to_string, stdio_truncate, string_out_put_string, open_fileno, open_command, base_name, dir-name): DS. (unget_byte, put_buf, fill_buf, fill_buf_adjust, get_line_as_buf, formatv, put_byte, test_set_indent_mode, test_neq_set_indent_mode, set_indent_mode, set_indent, inc_indent, set_max_length, set_max_depth, open_subprocess, run ): PS. (fds_subst, fds_swizzle): TS. * struct.c (make_struct_type, super, umethod_args_fun): PS. (method_args_fun): DS. * strudel.c (strudel_put_buf, strudel_fill_buf): DS. * sysif.c (errno_wrap, exit_wrap, usleep_wrap, mkdir_wrap, ensure_dir, makedev_wrap, minor_wrap, major_wrap, mknod_wrap, mkfifo_wrap, wait_wrap, wifexited, wexitstatus, wifsignaled, wtermsig, wcoredump, wifstopped, wstopsig, wifcontinued, dup_wrap, close_wrap, exit_star_wrap, umask_wrap, setuid_wrap, seteuid_wrap, setgid_wrap, setegid_wrap, simulate_setuid_setgid, getpwuid_wrap, fnmatch_wrap, dlopen_wrap): DS. (chmod_wrap, do_chown, flock_pack, do_utimes, poll_wrap, setgroups_wrap, setresuid_wrap, setresgid_wrap, getgrgid_wrap): PS. (c_time): TS. * sysif.h (c_time): Declaration updated. * syslog.c (openlog_wrap, syslog_wrap): DS. * termios.c (termios_pack): TS. (tcgetattr_wrap, tcsetattr_wrap, tcsendbreak_wrap, tcdrain_wrap, tcflush_wrap, tcflow_rap, encode_speeds, decode_speeds): DS. * txr.c (compato, array_dim, gc_delta): DS. * unwind.c (uw_find_frames_by_mask): DS. * vm.c (vm_make_desc): PS. (vm_make_closure, vm_swtch): DS.
* structs: bugfix: wrong warning about no such static slotKaz Kylheku2020-06-201-2/+5
| | | | | | | | | | | | * struct.c (static_slot_types): If a symbol is attached to an empty type list in the static slot hash, then try triggering auto-load on it. This function's result is relied on by the struct macros for generating warnings; if we don't probe the autload, we get spurious warnings about symbols not being the name of any static slot. (static_slot_type_reg): Copy and paste bug: store the type into the correct, static slot type hash instead of the instance slot type hash.
* bugfix: definitions must trigger autoload.Kaz Kylheku2020-04-131-0/+2
| | | | | | | | | | | | | | When a function, macro, variale, symbol macro or struct is being defined, we must trigger any auto-load for that symbol. If the definition is redefining a library symbol, then if the autoload is later triggered, it will surprisingly reinstate the library definition. * eval.c (rt_defvarl, op_defsymacro, rt_defsymacro, rt_defun, rt_defmacro): Insert calls to lisplib_try_load against the symbol being defined. * struct.c (make_struct_type): Likewise.
* warning cleanup: remove unused parameters.Kaz Kylheku2020-04-051-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is the second round of an effort to enable GCC's -Wextra option. All function parameters that are unused and are removable are removed. They are eliminated from the function defintions, declarations, callers, and any related function pointer variables or structure members. * arith.c (nary_simple_op): Remove unused self parameter. See lib.c: maxv, minv. * chksum.c (crc32_buf, crc32_str): Remove unused self parameter. (crc32): Don't pass self to the above functions. * eval.c (copy_env_handler, copy_bh_env_handler): Remove unused parent parameter. See unwind.c. (supplement_op_syms): Remove unused max parameter. (me_op): Don't pass max to supplement_op_syms. * lib.c (seq_iter_rewind): Remove unused self parameter. (lazy_flatten_func): Remove unused env parameter. (lazy_flatten): Use func_n1 to create non-environment-carrying funtion out of lazy_flatten_func. (maxv, minv): Don't pass self parameter to nary_simple_op. (middle_pivot): Remove unused lessfun param. (quicksort): Don't pass lessfun to middle_pivot. (diff, isec): Don't pass self to seq_iter_rewind. * lib.h (seq_iter_rewind, nary_simple_op): Declarations updated. * struct.c (get_super_slots): Remove unused self parameteer. (make_struct_type): Don't pass self to get_super_slots. * sysif.c (flock_unpack): Remove unused self parameter. (fcntl_wrap): Don't pass self to flock_unpack. * unwind.c (uw_push_cont_copy): Remove parent parameter from function pointer parameter. See eval.c: copy_env_handler. (call_copy_handlers): Remove parent parameter and don't pass that argument to the indirect call via pointer to the copy handler function. (revive_cont, capture_cont): Don't pass 0 value to removed parent parameter of call_copy_handlers. * unwind.h (struct uw_cont_copy): Function pointer member copy loses parent parameter. (uw_push_cont_copy): Declaration updated.
* warning cleanup: add casts for unused parameters.Kaz Kylheku2020-04-051-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is the first round of an effort to enable GCC's -Wextra option. All function parameters that are unused an that we cannot eliminate are treated with a cast to void in the function body. * args.c (args_key_check_store): Cast unused param to void. * combi.c (perm_list_gen_fill): Likewise. * eval.c (op_error, op_meta_error, op_quote op_qquote_error, op_unquote_error, op_load_time_lit, me_each, me_for, me_quasilist, me_flet_labels, hash_min_max, me_ignerr, me_whilet, me_iflet_whenlet, me_dotimes, me_mlet, me_load_time, me_load_for): Likewise. * ffi.c (ffi_void_put, ffi_fixed_dynsize, *ffi_fixed_alloc, ffi_noop_free, ffi_void_get, ffi_simple_release, ffi_i8_put, ffi_i8_get, ffi_u8_put, ffi_u8_get, ffi_i16_put, ffi_i16_get, ffi_u16_put, ffi_u16_get, ffi_i32_put, ffi_i32_get, ffi_u32_put, ffi_u32_get, ffi_i64_put, ffi_i64_get, ffi_u64_put, ffi_u64_get, ffi_char_put, ffi_char_get, ffi_uchar_put, ffi_uchar_get, ffi_bchar_get, ffi_short_put, ffi_short_get, ffi_ushort_put, ffi_ushort_get, ffi_int_put, ffi_int_get, ffi_uint_put, ffi_uint_get, ffi_long_put, ffi_long_get, ffi_ulong_put, ffi_ulong_get, ffi_float_put, ffi_float_get, ffi_double_put, ffi_double_get, ffi_val_put, ffi_val_get, ffi_be_i16_put, ffi_be_i16_get, ffi_be_u16_put, ffi_be_u16_get, ffi_le_i16_put, ffi_le_i16_get, ffi_le_u16_put, ffi_le_u16_get, ffi_be_i32_put, ffi_be_i32_get, ffi_be_u32_put, ffi_be_u32_get, ffi_le_i32_put, ffi_le_i32_get, ffi_le_u32_put, ffi_le_u32_get, ffi_be_i64_put, ffi_be_i64_get, ffi_be_u64_put, ffi_be_u64_get, ffi_le_i64_put, ffi_le_i64_get, ffi_le_u64_put, ffi_le_u64_get, ffi_wchar_put, ffi_wchar_get, ffi_sbit_get, ffi_ubit_get, ffi_cptr_get, ffi_str_in, ffi_str_put, ffi_str_get, ffi_str_d_get, ffi_wstr_in, ffi_wstr_get, ffi_wstr_put, ffi_wstr_d_get, ffi_bstr_in, ffi_bstr_put, ffi_bstr_get, ffi_bstr_d_get, ffi_buf_in, ffi_buf_put, ffi_buf_get, ffi_buf_d_in, ffi_buf_d_put, ffi_buf_d_get, ffi_closure_put, ffi_ptr_in_in, ffi_ptr_in_d_in, ffi_ptr_in_out, ffi_ptr_out_in, ffi_ptr_out_out, ffi_ptr_out_null_put, ffi_ptr_out_s_in, ffi_flex_struct_in, ffi_carray_get, ffi_union_get, make_ffi_type_builtin, make_ffi_type_array, ffi_closure_dispatch, ffi_closure_dispatch_safe): Likewise. * gc.c (cobj_destroy_stub_op, cobj_destroy_free_op, cobj_mark_op): Likewise. * lib.c (seq_iter_get_nil, seq_iter_peek_nil): Likewise. * linenoise/linenoise.c (sigwinch_handler): Likewise. * parser.c (repl_intr, read_eval_ret_last, repl_warning, is_balanced_line): Likewise. * parser.y (yydebug_onoff): Likewise. * socket.c (dgram_close): Likewise. * stream.c (unimpl_put_string, unimpl_put_char, unimpl_put_byte, unimpl_unget_char, unimpl_unget_byte, unimpl_put_buf, unimpl_fill_buf, unimpl_seek, unimpl_truncate, unimpl_set_sock_peer, null_put_string, null_put_char, null_put_byte, null_get_line, null_get_char, null_get_byte, null_close, null_flush, null_seek, null_set_prop, null_get_error, null_get_error_str, null_clear_error, null_get_fd, dir_close): Likewise. * struct.c (struct_type_print): Likewise. * unwind.c (me_defex): Likewise.
* method: use new dynamic args to avoid consing list.Kaz Kylheku2020-03-231-9/+10
| | | | | | | | * struct.c (method_args_fun): env parameter is now a dynamic args object. Code adjusted accordingly. (method): Duplicate args into a dyn_args object instead of a list. Because a dyn_args has a car and cdr field, we can eliminate the two conse as well.
* umethod: use new dynamic args to avoid consing list.Kaz Kylheku2020-03-231-7/+8
| | | | | | | | | | | | | * args.c (args_cat): New function. * args.h (args_cat): Declared. * struct.c (umethod_args_fun): env parameter is now a dynamic args object. Code adjusted accordingly. (umethod): Duplicate the args into a dynamic args object instead of consing up a list and also eliminate the temporary cons since we can pass the additional argument using the car field of the dynamic args.
* Copyright year bump 2020.Kaz Kylheku2019-12-311-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/asm.tl, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/compiler.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/debugger.tl, share/txr/stdlib/defset.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/param.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/save-exe.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/trace.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/vm-param.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr: Extended copyright notices to 2020.
* multiple-inheritance: super-method loose ends.Kaz Kylheku2019-12-131-26/+45
| | | | | | | | | | | | | | | | | * struct.c (do_super): New function. Now the common implementation for call_super_method, call_super_fun and super_method. (call_super_method, call_super_fun): Reduced to small wrappers around do_super. (super_method): Drill into the object to geet the struct_type handle, and then use do_super to get the method. * tests/012/oop-mi.tl: New tests for call-super-fun and call-super-method. * tests/012/oop-mi.expected: Updated. * txr.1: Updated.
* OOP: implementing multiple inheritance.Kaz Kylheku2019-12-111-60/+184
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Multiple inheritance is too useful to ignore any longer. * lib.c (subtypep): Perform subtypep calculation between two struct types via the new struct_subtype_p function. It's too complicated now to do with ad hoc code outside of struct.c. * share/txr/stdlib/struct.tl (defstruct): This macro now needs to deal with the super argument being possibly a list of base types instead of a single one. * strut.c (struct struct_type): Member super and super_handle are removed. New member nsupers, supers, and sus. (struct_init): The super function re-registered; it has an optional argument. (call_stinitfun_chain): The compat code here must now access the supertype differently. We don't bother dealing with multiple inheritance in the compat case; programs requesting compatibility with TXR 151 shoudn't be trying to use multiple inheritance. (get_struct_handles, count_super_stslots, get_super_slots, find_super_for_slot): New static functions, to off-load some new complexity from make_struct_type. (make_struct_type): Handle the increased complexity due to multiple inheritance. (super): Takes an additional argument now, to request which supertype to retrieve. Defaults to zero: the first one. (struct_type_destroy): Free the sus array. (struct_type_mark): Mark the supers slot. (call_initfun_chain): Call init functions of all bases, in right-to-left order. (call_postinitfun_chain): Likewise for postinit functions. (call_super_method, call_super_fun, super_method): Use the first base as the supertype. This requirement feels bad; it needs to be revisited. (do_struct_subtype_p): New static function. (struct_subtype_p): New function. (ancestor_with_static_slot): New static function. (method_name): Revised for multiple inheritance; now relies on ancestor_with_static_slot to find the original ancestor that has brought in a method, so we can use that type in the method name. * struct.h (super): Declaration updated. (struct_subtype_p): Declared. * tests/012/oop-mi.expected: New file. * tests/012/oop-mi.tl: New test cases. * txr.1: Revised in order to document multiple inheritance.