summaryrefslogtreecommitdiffstats
path: root/struct.c
Commit message (Collapse)AuthorAgeFilesLines
* cobj: rename poorly named default operation.Kaz Kylheku2017-05-151-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Renaming cobj_hash_op to cobj_eq_hash_op. This function is only appropriate to use with COBJ objects which use eq as their equal funtion. I've spotted one instance of an inappropriate use which have to be addressed by a different commit: the equal function is other than eq, but cobj_hash_op is used for the equal hash. * lib.h (cobj_hash_op): Declaration renamed to cobj_eq_hash_op. * hash.c (cobj_hash_op): Renamed to cobj_eq_hash_op. (hash_iter_ops): Refer to renamed cobj_hash_eq_op. * ffi.c (ffi_type_builtin_ops, ffi_type_struct_ops, ffi_type_ptr_ops, ffi-closure_ops, ffi_call_desc_ops): Likewise. * lib.c (cptr_ops): Likewise. * parser.c (parser_ops): Likewise. * rand.c (random_state_ops): Likewise. * regex.c (char_set_ops, regex_obj_ops): Likewise. * socket.c (dgram_strm_ops): Likewise. * stream.c (null_ops, stdio_ops, tail_ops, pipe_ops, dir_ops, string_in_ops, byte_in_ops, strlist_in_ops, string_out_ops, strlist_out_ops, cat_stream_ops, record_adapter_ops): Likewise. * struct.c (struct_type_ops): Likewise. * sysif.c (cptr_dl_ops): Likewise. * syslog.c (syslog_strm_ops): Likewise. * unwind.c (cont_ops): Likewise.
* Warn when a nonexistent slot is referenced.Kaz Kylheku2017-03-231-1/+50
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Implementing warning for the situaton when the qref, uref, usl and umeth macro operators are asked to refer to a slot that doesn't exist in any struct type. This won't catch errors referencing a slot on the wrong type, but it will catch slots that are misspelled in such a way that the typo doesn't land on any slot. * share/txr/stdlib/struct.tl (defstruct): Register tenative slot definitions for all slots to nuke warnings. (sys:check-slot): New function. (qref, usl, umeth): Check slots with sys:check-slot. (uref): Drop :whole argument, which is unused. (defmeth): Register tentative definition for slot. * struct.c (slot_s, static_slot_s): New symbol variables. (slot_type_hash, static_slot_type_hash): New hash tables, associating symbols with lists of struct type names in which they are defined. (struct_init): Initialize and gc-protect hashes. Initialize new symbols, interning in system package. Register new intrinsic funtions sys:slot-types and sys:static-slot-types. (make_struct_type): Register slots in new hashes. (static_slot_ens_rec): Register new slow in static slot hash. (slot_types, static_slot_types): New functions, registered as intrinsics. (slot_type_reg, static_slot_type_reg): New functions. * struct.h (print_s): Declared. (slot_s, static_slot_s): Declared. (slot_types, static_slot_types, slot_type_reg, static_slot_type_reg): Declared.
* listener: completion sensitive for slots and methods.Kaz Kylheku2017-03-211-0/+38
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When completing .prefix[TAB], .(prefix[TAB] or .[prefix[TAB], restrict identifiers to the appropriate namespace. The former will report only symbols from the relevant package which are struct slots; the latter further restricts it to those which are static slots defined as functions. * lib.c (symbol_visible): Static function becomes extern. * lib.h (symbol_visible): Declared. * parser.c (find_matching_syms): par parameter is renamed kind and can hold additional values 'S' (slots) and 'M' (methods). New get_slot_syms function is used to fetch the slots, as necessary, instead of the visible syms, if the kind is 'S' or 'M'. The same loop as before (with the minor change of recognizing 'S' and 'M' also) performs the prefix matching. (provide_completions): Recognize . .( and .[ prefix, calculating the kind argument of find_matching_syms in a new way. * struct.c (get_slot_syms): New function. * struct.h (get_slot_syms): Declared. * txr.1: Add some notes about this under the description of completion. The full rules are not given though; let the user discover.
* Rename badly named default_bool_argKaz Kylheku2017-03-171-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * lib.h (default_bool_arg): Inline function renamed to default_null_arg. * eval.c (if_fun, pad, ginterate, giterate, range_star, range, constantp, macroexpand_1, macro_form_p, expand_with_free_refs, do_expand, eval_intrinsic, func_get_name, make_env_intrinsic): Follow rename. * arith.c (lognot): Likewise. * gc.c (gc_finalize): Likewise. * glob.c (glob_wrap): Likewise. * hash.c (group_reduce, gethash_n): Likewise. * lib.c (print, multi_sort, lazy_str, vector, iff, tok_str, split_str_keep, search_str, remove_if, val): Likewise. * match.c (match_fun): Likewise. * parser.c (lisp_parse_impl, regex_parse): Likewise. * rand.c (make_random_state): Likewise. * regex.c (read_until_match, search_regex, regex_compile): Likewise. * socket.c (sock_accept, sock_connect): Likewise. * stream.c (open_files_star, open_files, run, open_process, open_tail, get_string, record_adapter): Likewise. * struct.c (static_slot_ensure, static_slot_ens_rec, clear_struct, make_struct_type): Likewise. * sysif.c (exec_wrap, errno_wrap, cobj_ops_init): Likewise. * unwind.c (uw_capture_cont, uw_find_frames_impl): Likewise.
* trace: implement redefinition checks.Kaz Kylheku2017-03-171-0/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The tracing module should warn when traced functions or methods are being redefined, and stop tracing the original methods. * eval.c (trace_check): New function. Calls sys:trace-redefined-check if the trace module has been loaded, otherwise does nothing. (op_defun, op_defmacro): Call trace_check to have a warning issued for a redefined traced function or macro. * eval.h (trace_check): Declared. * lisplib.c (trace_loaded): New global variable. (trace_instantiate): Flip trace_loaded to t. * lisplib.h (trace_loaded): Declared. * share/txr/stdlib/trace.tl (sys:trace-redefine-check): New function. Checks two situations: traced function or method is redefined (neither old nor new is traced any longer), and traced method is overridden (base method continues to be traced, override is not traced). * struct.c (static_slot_ensure): Do a trace check here, taking care of defmeth.
* New function: static-slot-home.Kaz Kylheku2017-03-161-0/+26
| | | | | | | | | | | * struct.c (struct_init): Register intrinsic function static-slot-home. (lookup_static_slot_desc_load): New static function. (static_slot_home): New function. * struct.h (static_slot_home): Declared. * txr.1: Documented.
* structs: remove unused param from some functions.Kaz Kylheku2017-03-161-20/+19
| | | | | | | | | | * struct.c (lookup_static_slot_desc, lookup_static_slot, lookup_static_slot_load, get_equal_method): Remove stype argument; it is only passed down through the calls and not used at the leaf level. (static_slot, static_slot_set, static_slot_ens_rec, struct_inst_print, struct_inst_equalsub, method_name): Don't pass stype to slot lookup functions that no longer take it.
* Fix misleading "no such slot" for static slot lookup.Kaz Kylheku2017-03-161-2/+8
| | | | | | | * struct.c (no_such_static_slot): New static function. (static_slot, static_slot_set): Use no_such_static_slot when reporting error. The struct type might have an instance slot of that name.
* Print method can return : to decline printing.Kaz Kylheku2017-03-131-3/+2
| | | | | | | | * struct.c (struct_inst_print): Check return value of print method call. If it is the colon keyword, then do not return but rather continue to the regular struct printing code. * txr.1: Documented.
* New: struct-from-plist and struct-from-args.Kaz Kylheku2017-03-121-0/+14
| | | | | | | | | * struct.c (struct_init): Register new functions. (struct_from_plist, struct_from_args): New functions. * struct.h (struct_from_plist, struct_from_args): Declared. * txr.1: Documented.
* Fix lack of robustness in struct module.Kaz Kylheku2017-02-201-6/+6
| | | | | | | | | | | | The symbolp test is too weak before calling lookup_slot, because nil satisfies it, but lookup_slot dereferences the symbol pointer to access its slot cache. One of many test cases: parsing #S(time nil nil) segfaults. * struct.c (slot, maybe_slot, slotset, uslot_fun, umethod_fun, umethod_args_fun): Check that sym isn't nil before looking it up as a slot.
* Bump copyright year to 2017.Kaz Kylheku2017-01-231-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, args.c, args.h, arith.c, arith.h, cadr.c, cadr.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.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, stream.c, stream.h, struct.c, struct.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/except.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/package.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl: Add 2017 to all copyright headers and strings.
* bugfix: supertype check in make-struct-type.Kaz Kylheku2017-01-161-1/+1
| | | | | | * struct.c (make_struct_type): Fix test of incorrect variable which renders the supertype test useless, causing the type to be created with no supertype.
* Functions for error reporting out of macros.Kaz Kylheku2017-01-151-0/+2
| | | | | | | | | | | | | | | | | * eval.c (eval_init): Register sys:ctx-form and sys:ctx-name intrinsics. * lisplib.c (error_set_entries, error_instantiate): New static functions. (lisplib_init): Register autoloading of error.tl via new functions. * share/txr/stdlib/error.tl: New file. * struct.c (make_struct_type): Purge deferred warnings. * unwind.c (uw_late_init): Register purge-deferred-warning intrinsic.
* Fix some C style casts to use casting macros.Kaz Kylheku2016-12-071-4/+4
| | | | | | | | | | | | | | | | | | | | This is uncovered by compiling with g++ using -Wold-style-cast. * mpi/mpi.c (mp_get_intptr): Use convert macro. Also in one of the rules producing REGCHAR. * parser.l (num_esc): Likewise. * struct.c (static_slot_set, static_slot_ens_rec, get_equal_method): Use coerce macro for int to pointer conversion. * sysif.c (setgroups_wrap): Use convert macro. * termios.c (termios_unpack, termios_pack): Likewise. * txr.c (sysroot_init): Likewise.
* Introducing struct instance dirty flags.Kaz Kylheku2016-11-141-1/+38
| | | | | | | | | | | | | | | | * struct.c (struct struct_inst): New bitfield member, dirty. (struct_init): Register test-dirty, test-clear-dirty and clear-dirty intrinsics. (make_struct): Initialize dirty flag to 1. (slotset): If the object is clean, then determine whether the slot being set is an instance slot. If so, then set the dirty flag. (test_dirty, test_clear_dirty, clear_dirty): New functions. * struct.h (test_dirty, test_clear_dirty, clear_dirty): Declared. * txr.1: Documented dirty flags concept and new functions.
* Expose slots function.Kaz Kylheku2016-11-051-1/+2
| | | | | | | * struct.c (struct_init): Register slots intrinsic. (slots): Pass correct name string to stype_handle. * txr.1: Slots function documented.
* Fix non-working quasiquote over struct literals.Kaz Kylheku2016-10-241-2/+3
| | | | | | | | | | | | | | | | | | | | Turns out that there is missing support for quasiquoting over structs. Code analogous to the way vector and hash literals are handled is missing for structs. * eval.c (expand_qquote_rec): Handle struct_lit_s forms specially, like hash_lit_s and vector_lit_s. commit 1e5bc5708d5763f20a7774f9348e825304a51adc * struct.c (make_struct_lit_s): New symbol variable. (struct_init): Store interned sys:make-struct-lit symbol into make_struct_lit_s, and use that to register the function. * struct.h (make_struct_lit_s): Declared. * tests/012/struct.tl: Update struct literal quasiquote test cases to reflect fixed behavior.
* struct bug: mismanagement of static slot store.Kaz Kylheku2016-10-211-1/+4
| | | | | | | | | | | | | | | | | The bug_unless statement was found to go off, indicating an internal problem. Indeed, the store of inherited static slots were being set to non-nil by incorrect copying in two places. This is harmless in and of itself; it's just a way of being tidy. If a slot's value is located elsewhere, then the local store must be nil. * struct.c (static_slot_home_fixup): After fetching a fresh copy of the home type's stslot entry, clear the store to nil. (make_struct_type): Likewise. (struct_type_mark): Use assert for this rather than bug_unless, because it happens in the middle of garbage collection. Throwing an exception out of the middle of gc is a nonstarter.
* Changes to the printing framework.Kaz Kylheku2016-10-201-2/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The print function now takes an optional boolean for pretty printing. The print method is also called with a third argument; hence structures can customize both standard printing and pretty printing. * lib.c (obj_print): Take pretty argument, and pass it down to obj_print_impl. This makes obj_pprint redundant. (obj_pprint): Function removed: it was identical to obj_print except for passing t down to obj_print_impl for the pretty argument. These two wrappers had started small and got bigger with identical changes done in parallel. (pprint): New function. (tostring, dump): Pass nil for pretty argument of obj_print. (tostringp): Use pprint instead of obj_pprint. * lib.h (obj_print): Declaration updated. (obj_pprint): Declaration removed. (print, pprint): Declared. * eval.c (prinl): Pass nil for pretty_p argument of obj_print. Do the stream defaulting here; obj_print doesn't do it. (pprinl): Pass t for pretty_p argument of obj_print, and do stream argument defaulting. (eval_init): Register print to new print function rather than directly to obj_print. Register pprint to new pprint function rather than obj_pprint. * hash.c (hash_print_op): Call obj_print_impl to print the :equal-based keyword, rather than obj_print. Pass down the pretty flag. All the other keywords are treated this way; this fixes an inconsistency. * match.c (dump_var): Call pprint instead of obj_pprint. * stream.c (formatv): Call obj_print, with a calculated pretty argument instead of switching between obj_pprint and obj_print. * struct.c (struct_inst_print): Except when in backward compatibility mode, call the object's print method in both pretty and regular printing mode, passing the mode as a third argument. * tests/012/oop.tl (defstruct animal): Support third argument in print method. Make it optional because there are some explicit calls which don't pass the argument. * txr.1: Documentation updated for print method and the print function. Revised text for some of the related functions. Added compat notes.
* Fix struct lit problem exposed by circular syntax.Kaz Kylheku2016-10-201-0/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Add stream printing context.Kaz Kylheku2016-10-201-5/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is some infrastructure which will support *print-circle*. * lib.h (struct strm_ctx): Forward declared. (struct cobj_ops): Add context parameter to print function pointer. (cobj_print_op, obj_print_impl): Add context parameter to declarations. * hash.c (hash_print_op): Take context argument and pass it down in obj_print_impl calls. * lib.c (cobj_print_op, out_quasi_str): Likewise (obj_print_impl): Likewise, and also pass to COBJ print method. (obj_print, obj_pprint): Pass null pointer as context argument to obj_print_impl. * regex.c (regex_print): Take context parameter and ignore it. * socket.c (dgram_print): Likewise. * stream.h (struct strm_ctx): New struct type. (struct strm_base): New ctx member, pointer to struct strm_ctx. (stream_print_op): Add context parameter to declaration. (get_set_ctx, get_ctx): Declared. * stream.c (strm_base_init): Add null pointer to initializer. (strm_base_cleanup): Add assertion against context pointer being non-null: that indicates that some stream operation installed a context pointer and neglected to restore it to null before returning, which is bad because context will be stack allocated. (stream_print_op, stdio_stream_print, cat_stream_print): Take context parameter and ignore it. (get_set_ctx, get_ctx): New functions. * struct.c (struct_type_print): Take context parameter and ignore it. (struct_inst_print): Take context parameter and pass down to obj_print_impl.
* New function to access slot list of struct type.Kaz Kylheku2016-10-181-0/+6
| | | | | | * struct.c (slots): New function. * struct.h (slots): Declared.
* Support curried args in method and meth.Kaz Kylheku2016-10-091-1/+24
| | | | | | | | | | | | | | | | | | | | | * share/txr/stdlib/struct.tl (meth): Take trailing arguments and pass them down to method, which now accepts them. * struct.c (struct_init): Register method intrinsic to the function method_args instead of the method function. (method_args_fun): New static function. (method_args): New function. Behaves like method function if args is empty, otherwise creates a function by means of method_args_fun. * struct.h (method_args_fun): Declared. * tests/012/oop.tl: New test case. * tests/012/oop.expected: Updated. * txr.1: Documented new features in method and meth, revising the documentation in the process.
* Support curried arguments in umethod and umeth.Kaz Kylheku2016-10-091-3/+36
| | | | | | | | | | | | | | | | | | | | | | | | * share/txr/stdlib/struct.tl (umeth): accept variadic arguments. Evaluate them using the dwim brackets and pass to umethod. The (fun umethod) trick is used to refer to the umethod in the function namespace even if it is shadowed by a variable. * struct.c (struct_init): Update registration of umethod to reflect its new variadic argument signature. (umethod_args_fun): New static function. (umethod): Return a function based on umethod_fun, as before, if there are no variadic args. Otherwise, use umethod_args_fun which deals with them. * struct.h (umethod): Declaration updated. * tests/012/oop.tl: Modest testcase for umeth with curried argument. * tests/012/oop.expected: Updated. * txr.1: Updated documentation of umeth and umethod.
* gc issues in clear_struct and replace_struct.Kaz Kylheku2016-10-071-0/+3
| | | | | | | * struct.c (clear_struct, reset_struct): Inform the garbage collector that the structure has been mutate, using the mut macro. This is required for correctness because the structure may be a mature object receiving young generation values.
* Check for self-assignment in replace_struct.Kaz Kylheku2016-10-071-12/+16
| | | | | | | | | * struct.c (replace_struct): If target and source are the same object, just do nothing and return target. * txr.1: Document self-assignment and return value of replace-struct.
* bug: heap backpointer assignment in static-slot-ensure.Kaz Kylheku2016-10-071-1/+1
| | | | | | | | * struct.c (static_slot_ens_rec): Neglected use of set macro to store newval in freshly allocated slot, which means we corrupt garbage collection if this causes an old generation objet to point to a new generation object.
* bug: wrong way assert in static slot gc marking.Kaz Kylheku2016-10-071-1/+1
| | | | | | * struct.c (struct_type_mark): We must assert that sl->store is nil if we are not marking it, not that it is non-nil.
* Synchronize license comments with LICENSE.Kaz Kylheku2016-10-011-16/+17
| | | | | | | | | | | | | | | | | | | | * Makefile, args.c, args.h, arith.c, arith.h, cadr.c, cadr.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.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, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/except.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.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, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h: Revert to verbatim 2-Clause BSD.
* Check for overflow in static slot counter.Kaz Kylheku2016-10-011-1/+8
| | | | | * struct.c (make_struct_type, static_slot_ens_rec): Throw an error if there are too many static slots.
* Revision of static slot inheritance.Kaz Kylheku2016-09-301-53/+205
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fixing the broken static slot handling in TXR Lisp's "OOP structs" object system. Inherited static slots are now shared with the base type; only static slots explicitly defined in a derived type have a distinct global instance in that type. * share/txr/stdlib/struct.tl (sys:prune-nil-inits): Function removed. (sys:prune-missing-inits): New function. We now handle static slot forms with missing inits specially, not those with nil or missing inits. (defstruct): Translate a (word name) form to (word name) rather than (word name nil) if word is :static, because we need this nuance for non-shared static slots, so they can inherit the value from the base struct. For the purposes of generating the static init function, prune away all the static slot forms that do not have an initializer; we let those default. * struct.c (struct stslot): New struct for representing a static slot. (stslot_loc, stslot_place): New macros. (struct struct_type): Member eqmslot changes to a pointer to a struct stslot. The stslot dynamic array is no longer an array of val, but an array of stslot structs. (call_stinitfun_chain): The superclass chain of static init functions is now called only in compatibility mode. Otherwise only the type's own static init fun is called, which defclass uses to initialize just the new or repeated static slots. Inherited static slots are completely left alone; they do not require initialization. (static_slot_home_fixup): New static function; needed to fix some internal pointers within the static slot arrays if they are realloc'ed. (make_struct_type): Considerably revised to implement new scheme, while providing backward compatibility switching. New slots live in the struct stslot in which they are allocated. Inherited slots have home pointers to within the array in the base. (struct_type_mark): When walking the static slots, mark only the store cells of those which live in this array. Those that live elsewhere should have store cells that are nil; let's assert on it. (lookup_slot): Static slot lookup code has to retrieve slots in the new way, indirecting through the home pointer, which is hidden behind the stslot_loc macro. (lookup_static_slot_desc): New function, like lookup_static_slot, but returning a pointer to the struct stslot. Formed from the guts of lookup_static_slot. (lookup_static_slot): Gutted and turned into a wrappar around lookup_static_slot_desc. (static_slot_set): Simple change here: add cast because of the pointer type of eqmslot. (static_slot_home_fixup_rec): New static function. Fixes up the cached home in slot arrays in an entire type hierarchy rooted at a given type, which has to be done when its static slot has been reallocated, so all those inherited static slot pointers in the derived types are invalid. (static_slot_rewrite_rec): New static function: rewrites a particular inherited static slot in an inheritance hierarchy to point to a different slot. (static_slot_ens_rec): New static function: factored out recursive logic of static_slot_ensure. Substantially rewritten to handle new static slot scheme, plus support backward compatibility. There is a bug fixed here: if an instance slot is encountered in the no_error_p mode, it looks like we were dereferencing through an invalid ptr through the set(ptr, newval) line. (static_slot_ensure): A wrapper now for static_slot_ens_rec. (get_equal_method): Rework the logic related to the eqmslot member of the struct_type structure, in terms of it being a pointer now rather than an integer. The value -1 cast to a pointer serves the previous -1 sentinel value which indicates that it is confirmed (for the time being) that this type doesn't have an equal method. * txr.1: All documentation related to static slots updated, and compatibility notes added. * tests/012/oop.tl, tests/012/oop.expected: New files.
* Fix poorly chosen :postinit order.Kaz Kylheku2016-09-071-1/+5
| | | | | | | | | * struct.c (call_postinitfun_chain): call base handlers before derived ones, except in backward compatibility mode. * txr.1: Updated documentation of :postinit, and added compatibility note.
* Fix runaway recursion in lazy struct initialization.Kaz Kylheku2016-08-281-2/+3
| | | | | | | | | | | | | | | | | | | | | Staci-blowing test case: (defstruct foo nil bar) (mlet ((f (lnew foo bar (not f.bar)))) (prinl f.bar)) * struct.c (lazy_struct_init): Do not flip the lazy flag to zero here. The problem is that it's being done after the funcall(so->slot[0]), and so the struct is still marked for lazy initialization while that function is running. We could detect the circularity (as done in the force function) but that would create inflexibilities in lazy struct initialization. (check_init_lazy_struct): Flip the lazy flag to zero in this function before calling lazy_struct_init. * txr.1: Document behavior of struct being freely accessible during lazy initialization.
* Methods for turning objects into sequences.Kaz Kylheku2016-06-011-0/+14
| | | | | | | | | | | | | | | | | | | | | | | | Struct objects can now define methods car, cdr and nullify. With these, they can participate in operations on sequences. * eval.h (car_s, cdr_s): Declared. * lib.c (nullify_s): New symbol variable. (car, cdr): Implement for struct objects via, respectively, their car and cdr methods. (tolist): Handle objects by mapping through identity. (nullify): Implement for objects optionally: if an object is a struct with a nullify method, use it, otherwise go through default case of just returning the object. (empty): Implement for objects that have nullify method. (obj_init): Initialize nullify_s. * struct.c (maybe_slot): New function. * struct.h (maybe_slot): Declared. * txr.1: Documented car, cdr and nullify method convention.
* Print method on objects.Kaz Kylheku2016-06-011-1/+10
| | | | | | | | | * struct.c (print_s): New symbol variable. (struct_init): Initialize print_s. (struct_inst_print): If pretty-printing, try to look up object's print method and use it. * txr.1: Documented pretty-printing via print method.
* Reduce work done by hashing.Kaz Kylheku2016-05-271-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Curtail traversal of objects and strings. * hash.c (struct hash): hash_fun member takes int * parameter now. (HASH_STR_LIMIT, HASH_REC_LIMIT): New macros. (hash_c_str): Hash only HASH_STR_LIMIT characters. (equal_hash): Becomes extern function. Takes pointer-to-int count argument, which is decremented. Function stops recursing and returns zero when this hits zero. (eql_hash): Also takes int * param, for compatibility with function pointer in struct hash. This parameter is not used, though. (cobj_hash_op): Take pointer-to-count parameter, but ignore it. (hash_hash_op): Take pointer-to-count parameter, decrement and check that it has not hit zero, pass down to equal hash. (hash_grow, gethash_c, gethash, gethash_f, gethash_n, remhash): Initialize a counter to HASH_REC_LIMIT and pass down to hashing function. (hash_eql): Pass down a pointer to a dummy counter to eql_hash. (hash_equal): Initialize a counter to HASH_REC_LIMIT and pass down to hash_equal. * hash.h (equal_hash): Declared. * lib.h (cobj_ops): hash member takes int * parameter. (cobj_hash_op): Declaration updated with new param. * struct.c (struct_inst_hash): Takes new int * parameter for count. Calls equal_hash instead of hash_equal, eliminating c_num calls; pointer to count is passed to equal_hash.
* Fix generational-GC bug in struct code.Kaz Kylheku2016-05-141-3/+5
| | | | | | | | | * struct.c (static_slot_ensure): In the case when we grow the array of static slots, we were allowing chk_manage_vec to initialize the newly added element. This is wrong, because it is just a plain assignment, which causes a mature object to point to a baby object. This bug caused static slots to contain junk.
* Support autoloading for methods.Kaz Kylheku2016-05-131-2/+22
| | | | | | | * struct.c (lookup_slot_load, lookup_static_slot_load): New functions. (slot, static_slot): Use auto-load wrappers for lower-level slot lookup functions.
* Broken argument handling in umethod.Kaz Kylheku2016-04-131-2/+3
| | | | | | * struct.c (umethod_fun): Use proper args interfaces to check whether there is an object argument, and to extract it.
* Support lazy loading of stdlib struct definitions.Kaz Kylheku2016-01-311-2/+6
| | | | | | | * struct.c (make_struct_type): Use find_struct_type rather than direct lookup in struct_type_hash. (find_struct_type): Use lisplib_try_load if a type is not found to trigger autoloading on the symbol.
* Static slots mustn't trigger instantiation.Kaz Kylheku2016-01-041-2/+3
| | | | | | | | | It is already documented that accessing the instance slots (not static slots) of a lazy struct forces it to instantiate, thus this is a doc conformance bug. * struct.c (lookup_slot): Only call check_init_lazy_structs in the code paths where we calculate the location of an instance slot.
* Copyright year bump.Kaz Kylheku2015-12-311-1/+1
| | | | | | | | | | | | | | | | | | | | | | | * LICENSE, METALICENSE, Makefile, args.c, args.h, arith.c, arith.h, cadr.c, cadr.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, filter.c, filter.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.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, share/txr/stdlib/cadr.tl, share/txr/stdlib/except.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, stream.c, stream.h, struct.c, struct.h, sysif.c, sysif.h, syslog.c, syslog.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h: Add 2016 copyright. * linenoise/LICENSE, linenoise/linenoise.c, linenoise/linenoise.h: Bump one principal author's copyright from 2014 to 2015. The code is based on a snapshot of 2015 upstream work.
* Useful feature: object post-initialization.Kaz Kylheku2015-12-161-4/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Structs can now have code which executes after an object is initialized, which is useful for doing work like registering objects in global lists and whatever, when those actions need access to the initialized slots of the object. * share/txr/stdlib/struct.tl (defstruct): Handle :posinit syntax, by generating lambda as eighth argument of sys:make-struct call. * struct.c (struct struct_type): New member, postinitfun. (struct_init): Adjust registrations of make_struct_type to account for new parameter. The user visible make-struct-type is registered as having one optional argument, for backward compat. (make_struct_type): New argument, postinitfun. Store this in the structure. For backward compatibility, the argument is defaulted. (struct_type_mark): Mark the new postinitfun member. (call_postinitfun_chain): New static function. (make_struct, lazy_struct_init): Call call_postinitfun_chain after slots are initialized, and after the boa function is called. * struct.h (make_struct_type): Declaration updated. * lib.c (time_init): Pass eighth argument to make_struct type. * sysif.c (sysif_init): Likewise. * unwind.c (uw_late_init): Likewise. * tests/012/struct.tl: Update defstruct expansion test case. * txr.1: Document new argument of make-struct-type, and clarify ordering of initfun with regard to other actions. Likewise, document :postinit, and clarify ordering of :init actions with regard to other actions.
* static-slot-ensure always processes subtypes.Kaz Kylheku2015-12-011-16/+17
| | | | | | | | | | | * struct.c (static_slot_ensure): Restructured function so that the subtypes of stype are processed even if stype already has the static slot. This way static-slot-ensure can be used to overwrite a static slot value, not only establish one. And thus defmeth can redefine methods. * txr.1: Revamped static-slot-ensure doc, and added notes about redefining to defmeth.
* Bugfix: structs not inheriting late static slot values.Kaz Kylheku2015-12-011-1/+3
| | | | | | | | | | | | | | | | | | | | | | This bug doesn't affect static slots that are defined in defstruct, because those get initialized in the new type by the static init function. The bug is that the values of static slots added later with static_slot_ensure are not inherited by subtypes that are created later still. (Since static_slot_ensure propagates a slot to subtypes which already exist, those types get the slot value.) * struct.c (make_struct_type): Copy the contents of the static slot array of the supertype into the new type, so that static slot values are inherited. We can just use memcpy because the ordering of static slots is the same in the new type, and the inherited ones precede the new ones, due to the way the all_slots list is combined. * txr.1: Clarify inheritance of static slots.
* Resolve method name to supertype.Kaz Kylheku2015-12-011-1/+17
| | | | | | * struct.c (method_name): Don't return first match. Resolve to most ancestral superclass which has that function in the same slot.
* func-get-name calculates a name for methods.Kaz Kylheku2015-11-301-1/+25
| | | | | | | | | | | | | | * eval.c (func_get_name): Use try to use new method_name function, if unable to get name from the lexical or global environment for functions. * struct.c (meth_s): New symbol variable. (struct_init): Initialize meth_s variable. (method_name): New function. * struct.h (method_name): Declared. * txr.1: Re-documented func-get-name.
* Bugfix: super returning type rather than supertype.Kaz Kylheku2015-11-231-1/+1
| | | | | | * struct.c (super): Fix regression from Oct 17. When the argument is a struct instance, we must return the supertype, not the type.
* Struct instances now point directly to low level type.Kaz Kylheku2015-11-231-35/+35
| | | | | | | | | | | | | | | | | | | | | | | This change eliminates numerous cast expressions and a pointer chase from some operations, though some, like the struct_type function, end up chasing an extra pointer. * struct.c (struct struct_type): New member, self. (struct struct_inst): Type member changed from val to struct struct_type *. (make_struct_type): Initialize new self member. (super): Obtain type from si->type->self rather than si->type. There appears to be a bug here. (make_struct, lazy_struct_init): Initialize type field with struct pointer rather than type object. Add an assertion which references the type parameter, to prevent the cobj call from garbage collecting type. (copy_struct, clear_struct, replace_struct, reset_struct, (lookup_slot, slot, slotset, struct_type, uslot_fun, umethod_fun, struct_inst_print, struct_inst_mark, struct_inst_equal, struct_inst_hash, struct_inst_equalsub): All updated to new way of referencing type structure and type object.