summaryrefslogtreecommitdiffstats
path: root/lib.h
Commit message (Collapse)AuthorAgeFilesLines
* bugfix: several seq_iter kinds need clone operation.Kaz Kylheku2024-06-181-0/+2
| | | | | | | | | | | | | | Several seq_iter_t kinds of objects cannot be correctly bitwise copied, because they point to an iterator object that cannot be shared. * lib.c (seq_iter_clone_op): New static function. (si_hash_ops, si_tree_ops, si_oop_ops, si_fast_oop_ops): Use seq_iter_clone_op, which uses the copy function to duplicate it->ui.iter after doing a bitwise copy of the structure. * lib.h (seq_iter_ops_init_full): New macro.
* cobj: clone method streamlines copy; structs get copy method.Kaz Kylheku2024-06-171-4/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * lib.h (struct cobj_ops): New function pointer, clone. (cobj_ops_init, cobj_ops_init_ex): Add clone argument to macros. * lib.c (seq_iter_cobj_ops): Use copy_iter as the clone operation. (cptr_ops): Use copy_cptr as clone operation. (copy): Replace if statements by check whether COBJ has a clone operation. If so, we use it to copy the object. * struct.h (enum special_slot): New member, copy_m. * struct.c (copy_s): New symbol variable. (special_sym): Associate copy_m enum value with copy symbol. (struct_init): Initialize copy_s with interned symbol. (struct_inst_clone): New static function. (struct_type_ops): Specify no clone operation via null pointer. (struct_inst_ops): Specify struct_inst_clone as clone operation. * arith.c (psq_ops): Indicate no clone operation via null pointer. * buf.c (buf_strm_ops): Likewise. * chksum.c (sha1_ops, sha256_ops, md5_ops): Likewise. * ffi.c (ffi_type_builtin_ops, ffi_type_struct_ops, ffi_type_ptr_ops, ffi_type_enum_ops, ffi_closure_ops, union_ops): Likewise. (carray_borrowed_ops, carry_owned_ops, carray_mmap_ops): Specify copy_carray as clone operation. * gc.c (prot_array_ops): Indicate no clone operation via null pointer. * gzip.c (gzio_ops_rd, gzip_ops_wr): Likewise. * hash.c (hash_iter_ops): Likewise. (hash_ops): Specify copy_hash as clone operation. * parser.c (parser_ops): Indicate no clone operation via null pointer. * rand.c (random_state_clone): New static function. (random_state_ops): Use random_state_clone as clone function. * regex.c (char_set_obj_ops, regex_obj_ops): Indicate no clone operation via null pointer. * 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. * strudel.c (strudel_ops): Likewise. * sysif.c (cptr_dl_ops, opendir_ops): Likewise. * syslog.c (syslog_strm_ops): Likewise. * unwind.c (cont_ops): Likewise. * vm.c (vm_desc_ops, vm_closure_ops): Likewise. * tree.c (tree_ops): Use copy_search_tree for clone operation. (tree_iter_ops): Use copy_tree_iter for clone operation. * genchksum.txr: Changes in chksum.c specified in one place here. * tests/012/oop.tl: Couple of new tests. * txr.1: Documented.
* New function: copy-iter.Kaz Kylheku2024-06-151-0/+1
| | | | | | * eval.c (eval_init): Register copy-iter intrinsic. * lib.[ch] (copy_iter): New function.
* seq_iter: fix inadequate gc marking for some types.Kaz Kylheku2024-06-151-0/+1
| | | | | | | | | | | | * lib.c (seq_iter_mark_oop, seq_iter_mark_cat): New static functions. (si_oop_ops, si_fast_oop_ops): Use seq_iter_mark_oop instead of the generic one, because we need to mark the next field, not only the iter. (si_cat_ops): Use seq_iter_mark_cat, since we need to mark only the second field, dargs. * lib.h (seq_iter_ops_init_mark): New macro.
* New permi: iterator version of perm.Kaz Kylheku2024-06-151-2/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (eval_init): Register permi intrinsic. * combi.c (permi_get, permi_peek, permi_clone): New static functions. (permi_ops): New static structure. (permi_iter): New static function. (permi): New function. * combi.h (permi): Declared. * lib.h (struct seq_iter_ops): New function pointer, clone. (seq_iter_ops_init, seq_iter_ops_init_nomark): Initialize new member. (seq_iter_ops_init_clone): New macro. (seq_iter_cls): Existing external name declared. (seq_iter_cobj_ops, seq_iter_mark_op): Previously internal names declared external. * lib.c (seq_iter_mark_op, seq_iter_cobj_ops): Static variables become extern. (seq_iter_clone): New static function. (seq_iter_init_with_info): Use seq_iter_clone instead of assuming we can trivially clone an iterator state bitwise.
* quasiliterals: buffers in hex, separation for strings and buffers.Kaz Kylheku2024-05-271-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | In this commit, output variables in the TXR Pattern language and in TXR Lisp quasiliterals now support separator strings for values that are strings and buffers. Values which are buffers appear differently: they are rendered as a sequence of lower case hex digit pairs. When a string-valued variable specifies a separator, the separator appears between characters of the string value. Previously, the separator was ignored. When a buffer-valued variable specifies a separator. the separator appears between pairs of digits, not between digits. For instance if ethaddr is a variable holding #b'08:00:27:79:c7:f5', then the quasiliteral `@ethaddr` produces "08002779c7f" whereas `@{ethaddr ":"}` produces "08:00:27:79:c7:f5". * buf.[ch] (buf_str_sep): New function. * lib.[ch] (fmt_str_sep): New function. * eval.c (fmt_cat): If the argument is a string, and a separator is present, replace the value with the result of calling fmt_str_sep. If the argument is a buffer, and a separator is present, use buf_str_sep to convert to a string, otherwise use tostringp. * txr.1: Section on Output Variables updated. * tests/012/readprint.tl: New tests.
* New function: iter-cat.Kaz Kylheku2024-04-161-0/+2
| | | | | | | | | | | | | | | | * eval.c (eval_init): Register iter-cat intrinsic. * lib.h (struct seq_iter): New union member dargs. (iter_catv): Declared. * lib.c (seq_iter_get_cat, seq_iter_peek_cat): New static functions. (si_cat_ops): New static structure. (iter_catv): New function. * tests/012/iter.tl: New tests. * txr.1: Documented.
* New function: lcons-force.Kaz Kylheku2024-04-041-0/+1
| | | | | | | | * lib.[ch] (lcons_force): New function. * eval.c (eval_init): Register lcons-force intrinsic. * txr.1: Documented.
* append, nconc; replace implementation with seq_build.Kaz Kylheku2024-03-101-0/+4
| | | | | | | | | | * lib.c (seq_append2, seq_appendv, seq_nconc2, seq_nconcv): New functions. (append2, appendv, nappend2, nconcv): Now implemented using new functions. * lib.h (seq_append2, seq_appendv, seq_nconc2, seq_nconcv): Declared.
* New function: rangeref.Kaz Kylheku2024-03-071-0/+1
| | | | | | | | | | | | | | | | | | | | | Because ranges can be iterated like sequences, and are identified as vector-like, they have to support indexing. However, ranges already have semantics as a function: with a sequence argument, they slice it. Let's put the semantics into a function called rangeref, so it can be coherently documented. * eval.c (eval_init): Register rangeref intrinsic. * lib.c (generic_funcall): Range as a function works in terms of rangeref. (ref): Handle RNG case via rangeref. (rangeref): New function. * lib.h (rangeref): Declared. * tests/012/seq.tl: New tests.
* zip: make more generic.Kaz Kylheku2024-03-011-2/+0
| | | | | | | | | | | | | | | | * lib.c (do_pa_12_1_v, pa_12_1_v): Static functions removed. (transposev, transpose): Functions removed. * lib.c (transposev, transpose): Declarations removed. * eval.c (join_f): New global variable. (zip_fun, zipv, transpose): New static functions. (eval_init): gc-protect join_f, and initialize it. Registration of zip intrinsic goes to zipv rather than transposev. sys:fmt-join and join registered with help of global join_f rather than local. * tests/012/seq.tl: New zip test cases.
* seq_build: seq_pend must be nondestructive for lists.Kaz Kylheku2024-02-281-2/+4
| | | | | | | | | | | | | | | | | | | | Let's have both a seq_pend and seq_nconc, where seq_nconc can reuse the pieces of list passed to it. * lib.h (struct seq_build_ops): New member, nconc. (seq_build_ops_init): Add nconc parameter and initializer. (seq_nconc): Function declared. * lib.c (seq_build_list_pend): Switch to list_collect_append, otherwise mappend behaves destructively. (seq_build_list_nconc): New function. (sb_vec_ops, sb_str_ops, sb_buf_ops, sb_struct_ops, sb_carray_ops): Use seq_build_generic_pend for nconc operation. (sb_list_ops): Use new seq_build_list_nconc for nconc operation. (sb_finished_ops): Use null pointer for nconc operation. (seq_nconc): New function.
* seq_build: convert list buiding to list_collect.Kaz Kylheku2024-02-281-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | We want to use the list_collect functions for consistency. For instance, these functions allow an atom to be added to an improper list if the terminating atom is a sequence. (append '(1 . "abc") "d") yields (1 . "abcd"). * lib.h (struct seq_build): New member, tail. * lib.c (seq_build_list_add): Use list_collect. (seq_build_list_pend): Use list_collect_nconc. (seq_build_list_finish): Nothing to do here, except call seq_build_convert_to_finished since bu->obj is the head of the list at all times now. (seq_build_improper_add, seq_build_improper_pend): Functions removed. (sb_improper_ops): Structure removed. (seq_build_convert_to_improper): Function removed. (seq_build_convert_to_list): Different strategy needed here now. The list just goes into bu->obj, and we have to set up the tail to either point to the last cons cell's cdr, or else to bu->obj if the list is empty. (seq_build_init): Initialize bu->tail in the three cases that set up list collection.
* seq_build: put self name into structure.Kaz Kylheku2024-02-271-3/+4
| | | | | | | | | | | | | | | * lib.h (struct seq_build): New member, self. (struct seq_build_ops): Remove self parameter from pend function. (seq_build_init, seq_pend): Declarations updated. * lib.c (seq_build_generic_pend): Drop self parameter, take the value from structure. (seq_build_buf_pend): Drop self parameter. (seq_build_init): New self parameter. Pass recursively. (seq_pend): Self parameter dropped. (rem_impl, rem_if_impl, keep_keys_if, separate, separate_keys): Pass self to seq_build_init.
* seq_build: remove unused struct member.Kaz Kylheku2024-02-271-1/+0
| | | | * lib.h (struct seq_build): Remove inf member.
* New sequence building framework.Kaz Kylheku2024-02-261-0/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Just as the "seq_iter" iterators help to condense the code for iterating any kind of sequence, "seq_builder" objects solve the problem of producing a sequence of the same kind as an input sequence. Until now, two approaches have been taken for this. One was to have separately coded cases: code iterating over a string building up a string, and so on. The other has been to produce a list, which is then coerced to the right sequence type using make_like. The approach introduced here is similar to using make_like, but without wastefully consing up a temporary list. The remove-if, remqual, remql, remq and keep-if functions are retargetted to this new abstraction. * lib.h (struct seq_build, seq_build_t): New struct type. (struct seq_build_ops): New struct type. (seq_build_ops_init): New macro. (seq_build_init, seq_add, seq_pend, seq_finish): Functions declared. * lib.c (seq_build_generic_pend, seq_build_obj_mark, seq_build_struct_mark, seq_build_carray_mark, seq_build_vec_add, seq_build_str_add, seq_build_buf_add, seq_build_buf_pend, seq_build_buf_finish, seq_build_list_add, seq_build_list_finish, seq_build_struct_finish, seq_build_carray_finish): New static functions. (sb_vec_ops, sb_str_ops, sb_buf_ops, sb_struct_ops, sb_carray_ops, sb_list_ops): New static structs. (seq_build_init, seq_add, seq_pend, seq_finish): New functions. (rem_impl, rem_if_impl): Reworked in terms of seq_iter and seq_build, becoming much shorter, and handling all iterable objects.
* New function: cons-count.Kaz Kylheku2024-02-091-0/+1
| | | | | | | | | | | | | * eval.c (eval_init): Register cons-count intrinsic. * lib.c (cons_count_rec): New static function. (cons_count): New function. * lib.h (cons_count): Declared. * tests/012/cons.tl: New tests. * txr.1: Documented.
* New function: cons-find.Kaz Kylheku2024-02-091-0/+1
| | | | | | | | | | | | | | | | | * eval.c (cons_find): Static function removed; a new one is implemented in lib.c. (eval_init): Register cons-find intrinsic. * lib.c (cons_find_rec): New static function. (cons_find): New function. * lib.h (cons_find): Declared. * tests/012/cons.tl: New file. * txr.1: Documented cons-find together with tree-find. Document that tree-find's test-fun argument is optional, defaulting to equal.
* New function: hist-sort-by.Kaz Kylheku2024-02-021-0/+1
| | | | | | | | | | | | | * eval.c (eval_init): Register hist-sort-by intrinsic. * lib.c (hist_sort_by): New function. (hist_sort): Wrapper for hist_sort_by now. * lib.h (hist_sort_by): Declared. * tests/012/sort.tl: Tests. * txr.1: Documented.
* 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.
* New accessor: mref.Kaz Kylheku2023-11-151-0/+1
| | | | | | | | | | | | | | * eval.c (eval_init): Register mref intrinsic. * lib.[ch] (mref): New function. * stdlib/place.tl (sys:mref1): New place. (mref): New place macro, defined in terms of sys:merf1, ref place and mref function. * tests/012/seq.tl: New tests. * txr.1: Documented.
* New: length-list-<, length-<Kaz Kylheku2023-10-051-0/+2
| | | | | | | | | | | | | | | | | | | | | | These are functions for testing whether a list or sequence is shorter than a given integer. This is cheaper than calculating the length of lists, which is in some cases impossible if they are infinite. A length-str-< function already exists, useful with lazy strings. length-< uses length-list-< or length-str-< as appropriate * lib.[ch] (length_list_lt, length_lt): New functions. * eval.c (eval_init): length-list-< and length-< intrinsics registered. * tests/012/seq.tl: New tests. * txr.1: Documented.
* New hist-sort function.Kaz Kylheku2023-09-251-1/+2
| | | | | | | | | | | | | | | * eval.c (eval_init): Register hist-sort intrinsic. * lib.c (gt_f): New global variable. (hist_succ_f): New static variable. (hist_succ): New static function. (hist_sort): New function. * lib.h (gt_f, hist_sort): Declared. * tests/012/sort.tl: New tests. * txr.1: Documented.
* New functions: nested-vec-of and nested-vec.Kaz Kylheku2023-09-211-0/+2
| | | | | | | | | | | | | | | * eval.c (eval_init): Register nestd-vec-of and nested-vec intrinsics. * lib.[ch] (vec_allocate, vec_own, vec_init): New static functions. (vector, copy_vec): Expressed in terms of new functions. (nested_vec_of_v, nested_vec_v): New functions. * args.[ch] (args_cat_from): New function. * tests/010/vec.tl: New tests. * txr.1: Documented.
* Use vargs typedef instead of struct args *.Kaz Kylheku2023-09-051-46/+46
| | | | | | | | | | | | | | | | | | | | | | | | | | | 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: str-esc.Kaz Kylheku2023-09-011-0/+1
| | | | | | | | | | * lib.[ch] (str_esc): New function. * eval.c (eval_init): str-esc intrinsic registered. * tests/015/esc.tl: New file. * txr.1: Documented.
* New feature: local symbol renaming.Kaz Kylheku2023-08-101-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The new function use-sym-as can bring a foreign symbol into a package under a different name, which is not that symbol's name. This is also featured in a new defpackage clause, :use-syms-as. With this simple relaxation in the package system, we don't require package local nicknames, which is more complicated to implement and less ergonomic, because it doesn't actually vanquish the use of ugly package prefixes on clashing symbols. * eval.c (eval_init): Register use-syms-as. * lib.c (use_sym_as): New function, made out of use_sym. (use_sym): Now a wrapper for use_sym_as. * lib.h (use_sym_as): Declared. * stdlib/package.tl (defpackage): Implement :use-syms-as clause. * tests/012/use-as.tl: New file. * txr.1: Documented, * stdlib/doc-syms.tl: Updated.
* Math library: add numerous C99 functions.Kaz Kylheku2023-07-151-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * configure: Detect all the new functions, with separate tests for the unary and binary ones. * arith.c (cbrt_s, erf_s, erfc_s, exp10_s, exp2_s, expm1_s, gamma_s, j0_s, j1_s, lgamma_s, log1p_s, logb_s, nearbyint_s, rint_s, significand_s, tgamma_s, y0_s, y1_s, copysign_s, drem_s, fdim_s, fmax_s, fmin_s, hypot_s, jn_s, ldexp_s, nextafter_s, remainder_s, scalb_s, scalbln_s, yn_s, r_copysign_s, r_drem_s, r_fdim_s, r_fmax_s, r_fmin_s, hypot_s, r_jn_s, r_ldexp_s, r_nextafter_s, r_remainder_s, r_scalb_s, scalbln_s, r_yn_s): New symbol variables. (not_available): New static function. (cbrt_wrap, erf_wrap, erfc_wrap, exp10_wrap, exp2_wrap, expm1_wrap, gamma_wrap, j0_wrap, j1_wrap, lgamma_wrap, log1p_wrap, logb_wrap, nearbyint_wrap, rint_wrap, significand_wrap, tgamma_wrap, y0_wrap, y1_wrap, copysign_wrap, drem_wrap, fdim_wrap, fmax_wrap, fmin_wrap, hypot_wrap, jn_wrap, ldexp_wrap, nextafter_wrap, remainder_wrap, scalb_wrap, scalbln_wrap, yn_wrap): New static functions. (arith_set_entries, arith_instantiate): New static functions. (arith_init): Initialize symbols and instantiate functions via autoload mechanism. In a program that doesn't use the functions, we suffer only the overhead of interning the symbols. * lib.h (UNUSED): New macro for GCC unused attribute. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New @(push) directive.Kaz Kylheku2023-06-121-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | @(push) is like @(output), but feeds back into input. Use carefully. * parser.y (PUSH): New token. (output_push): New nonterminal symbol. (output_clause): Handle OUTPUT or PUSH via output_push. Some logic moved to output_helper. (output_helper): New function. Transforms both @(output) and @(push) directives. Checks both for valid keywords; push has only :filter. * parser.l (grammar): Recognize @(push similarly to other directives. * lib.[ch] (push_s): New symbol variable. * match.c (v_output_keys): Internal linkage changes to external. (v_push): New function. (v_parallel): We must fix the max_line algorithm not to use an initial value of zero, because lines can go negative thanks to @(push). We end up rejecting the pushed data. (v_collect): We can no longer assert that the data line number doesn't retreat. (dir_tables_init): Register push directive in table of vertical directives. * match.h (append_k, continue_k, finish_k): Existing symbol variables declared. (v_output_keys): Declared. * y.tab.c.shipped, * y.tab.h.shipped, * lex.yy.c.shipped: Updated. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New functions keep-keys-if, separate-keys.Kaz Kylheku2023-06-071-0/+2
| | | | | | | | | | | * lib.[ch] (keep_keys_if, separate_keys): New functions. * eval.c (eval_init): keep-keys-if, separate-keys intrinsics registered. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* gc: fix bad c++ casts.Kaz Kylheku2023-06-031-2/+2
| | | | | | | | | | This C++ regression snuck into in Version 286; I didn't check C++ compilation. * lib.h (container): Macro must use coerce not convert because mem_t * isn't void *. * gc.c (gc_prot_array_alloc): Likewise.
* gc: use single allocation for prot_array.Kaz Kylheku2023-05-021-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | * gc.c (prot_array): Add self pointer; arr member becomes flexible array. (prot_array_mark): We now check the handle itself for null, because the whole thing is freed. (prot_array_free): Function removed. (prot_array_ops): Wire cobj_destroy_free_op in place of prot_array_free. This fixes a memory leak because prot_array_free was not freeing the handle, only the array. (gc_prot_array_alloc): Fix to allocate everything in one swoop and store the self-pointer in the named member rather than arr[-1]. The self argument is not required; we drop it. The size argument cannot be anywhere near INT_PTR_MAX, because such an array wouldn't fit into virtual memory, so it is always safe to add a small value to the size. (prot_array_free): Obtain the self-pointer, and free the handle, replacing it with a null pointer. * gc.h (gc_prot_array_alloc): Declaration updated. * lib.c (ssort_vec): Don't pass self to gc_prot_array_alloc. * lib.h (container): New macro.
* sort: support stable sorting via ssort and snsort.Kaz Kylheku2023-05-021-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | For array-like objecgts, these objects use an array-based merge sort, using an auxiliary array equal in size to the original array. To provide the auxiliary array, a new kind of very simple vector-like object is introduced into the gc module: protected array. This looks like a raw dynamic C array of val type, returned as a val *. Under the hood, there is a heap object there, which makes the array traversable by the garbage collector. The whole point of this exercise is to make the new mergesort function safe even if the caller-supplied functions misbehave in such a way that the auxiliary array holds the only references to heap objects. * gc.c (struct prot_array): New struct, (prot_array_cls): New static variable. (gc_late_init): Register COBJ class, retaining in prot_array_cls. (prot_array_mark, prot_array_free): New static functions. (prot_array_ops): New static structure. (prot_array_alloc, prot_array_free): New functions. * gc.h (prot_array_alloc, prot_array_free): Declared. * lib.c (mergesort, ssort_vec): New static function. (snsort, ssort): New functions. * lib.h (snsort, ssort): Declared. * tests/010/sort.tl: Cover ssort. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New function: arithp.Kaz Kylheku2023-03-261-0/+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.
* fix --no-gen-gc configuration.Kaz Kylheku2023-01-201-3/+3
| | | | | | | | | | | | | | | | | | | This fixes only the build. I'm getting a crash in one test case, namely tests/010/json.tl. * lib.h (mut): Remove stray semicolon from definition. This semicolon compensates for the lack of a semicolon in txr.c, which becomes a syntax errror under no-gen-gc, when the other definition of mut is active. (mkloc, setcheck): Let's add casts of the object argument to void. This gets rid of a number of unused parameter errors in various functions that take an object parameter that is only used in the case of generational GC. * txr.c (txr_main): Add missing semicolon after mut call. * gc.c (gc_wrap): In the no CONFIG_GEN_GC case, cast argument full to void, since it is unused.
* 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.
* lib: or2: define in GCC-specific way.Kaz Kylheku2022-10-261-1/+5
| | | | | | | | | * lib.h (or2): Define simply using the ?: operator from GNU C, eliminating the explicit temporary variable. (uses_or2): For GNU C, we make this a dummy, harmless declaration. If memory serves me, one of the few good ways to do that it without eliciting unused warnings is to declare an enum.
* strings: revert caching of hash value.Kaz Kylheku2022-10-081-3/+1
| | | | | | | | | | | | | | | Research indicates that this is something useful in languages that abuse strings for implementing symbols. We have interned symbols. * lib.h (struct string): Remove hash member. * lib.c (string_own, string, string_utf8, mkustring, string_extend, replace_str, chr_str_set): Remove all initializations and updates of the removed hash member. * hash.c (equal_hash): Do not cache string hash value.
* strings: take advantage of malloc_usable_sizeKaz Kylheku2022-10-061-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On platforms which have the malloc_usable_size function, we don't have to store the allocated size of an object; malloc provides us the allocated size (which may be larger than we requested). Here we take advantage of this for strings. And since we don't have to store the string allocated size any more, we use that field for something else: storing the hash code (for seed zero). This can speed up some hashing operations. * configure (have_malloc_usable_size): New variable. Configure test for have_malloc_usable size. We have to try several header files, too. We set the configure variable HAVE_MALLOC_USABLE_SIZE, and possibly HAVE_MALLOC_H or HAVE_MALLOC_NP_H. * lib.h (struct string): If HAVE_MALLOC_USABLE_SIZE is true, we define a member called hash insetad of alloc. Also, we change alloc to cnum. * lib.c: Include <malloc_np.h> if HAVE_MALLOC_NP_H is defined. (string_own, string, string_utf8, mkstring, mkustring, init_str, string_extend, string_finish, string_set_code, string_get_code, length_str, replace_str, chr_str_set): Fix code for both cases. On platforms with malloc_usable_size, we have the allocated size from malloc, so we don't have to retrieve it from the object or store it. Any operations which mutate the string must reset the hash field to zero; zero means "hash has not been calculated". * hash.c (equal_hash): Just retrive a string's hash value, if it is nonzero, otherwise calculate, cache it and return it. * gc.c (mark_obj): The alloc member of struct string is a machine integer now; no need to mark it.
* nan-boxing: warning fix for gcc 12.Kaz Kylheku2022-09-161-0/+2
| | | | | | | | | | gcc 12.2.0, targetting RISC-V, emitted a warning for the c_f function that the &u expression uses an uninitialized u, even though u is declared with an initializer. Code builds otherwise and tests pass. * lib.h (c_f): Also suppress and re-enable the -Wuninitialized option.
* nan-boxing: build on older gcc.Kaz Kylheku2022-09-161-7/+8
| | | | | | | | | | | | Older GCC 4.x versions do not support diagnostic pragmas in functions and don't have push pragmas for diagnostics. * arith.c (flo): Put the diagnostic disabling pragma stuff outside of the function. Instead saving and restoring the status with push and pop, we just disable the aliasing warning and re-instate it as a warning. * lib.h (c_f): Likewise.
* nan-boxing: use GCC pragmas to disable aliasing warnings.Kaz Kylheku2022-09-141-0/+7
| | | | | | | | | | | * arith.c (flo): The line of code which triggers the aliasing diagnostic is wrapped with GNU-C-specific pramgas that disable the diagnostic just for that line. * lib.h (c_f): Likewise. * configure: Drop the test which adds -Wno-strict-aliasing to the DIAG_FLAGS;
* Implement NaN boxing.Kaz Kylheku2022-09-131-17/+137
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On platforms with 64 bit pointers, and therefore 64-bit-wide TXR values, we can use a representation technique which allows double floating-point values to be unboxed. Fixnum integers are reduced from 62 bits to 50, and there is a little more complexity in the run-time type checking and dispatch which costs extra cycles. The support is currently off by default; it must be explicitly enabled with ./configure --nan-boxing. * lib.h (NUM_MAX, NUM_MIN, NUM_BIT): Define separately for NaN boxing. (TAG_FLNUM, TAG_WIDTH, NAN_TAG_BIT, NAN_TAG_MASK, TAG_BIGMASK, TAG_BIGSHIFT, NAN_FLNUM_DELTA): New preprocessor symbols. (enum type, type_t): The FLNUM enumeration constant moves to just after LIT, so that its value is the same as TAG_FLNUM. (struct flonum): Does not exist under NaN boxing. (union obj): No fl member under NaN boxing. (tag, is_ptr): Separately defined for NaN boxing. (is_flo): New function under NaN boxing. (tag_ex): New function. It's like tag, but identifies floating-point values as TAG_FLNUM. The tag function continues to map them to TAG_PTR, which is wrong under NaN boxing, but needed in order not to separately write tons of cases in the arith.c module. (type): Use tag_ex, so TAG_FLNUM is handled, if it exists. (auto_str, static_str, litptr, num_fast, chr, c_n, c_u): Different definition for NaN boxing. (c_ch, c_f): New function. (throw_mismatch): Attribute with NORETURN. (nao): Separate definition for NaN boxing. * lib.c (seq_kind_tab): Reorder initializer to follow enum reordering. (seq_iter_rewind): use c_n and c_ch functions, since type checking has been done in those cases. The self parameter is no longer needed. (iter_more): use c_ch on CHR object. (equal): Use c_f accessor to get double value rather than assuming there is a struct flonum representation. (stringp): Use tag_ex, otherwise a floating-point number is identified as TAG_PTR. (diff, isec, isecp): Don't pass removed self parameter to seq_iter_rewind. * arith.c (c_unum, c_dbl_num, c_dbl_unum, plus, minus, signum, gt, lt, ge, le, numeq, logand, logior, logxor, logxor_old, bit, bitset, tofloat, toint, width, c_num, c_fixnum): Extract floating-point value using c_f accessor. Handle CHR type separately from NUM because the storage representation is no longer identical; CHR values have a two bit tag over bits where NUM has ordinary value bits. NUM is tagged at the NaN level with the upper 14 bits being 0xFFFC. The remaining 50 bits are the value. (flo): Construct unboxed float under NaN boxing by taking image of double as a 64 bit value, and adding the delta offset, then casting to the val pointer type. (c_flo): Separate implementation for NaN boxing. (integerp, numberp): Use tag_ex. * buf.c (str_buf, buf_int): Separate CHR and NUM cases, like in numerous arith.c functions. * chksum.c (sha256_hash, md5_hash): Use c_ch accessor for CHR value. * hash.c (equal_hash, eql_hash): Handle CHR separately. Use c_f accessor for floating-point value. (eq_hash): Use tag_ex and handle TAG_FLNUM value under NaN boxing. Handle CHR separately from NUM. * ffi.c (ffi_float_put, ffi_double_put, carray_uint, carray_int): Handle CHR and NUM separately. * stream.c (formatv): Use c_f accessor. * configure: disable automatic selection of NaN boxing on 64 bit platforms, for now. Add test whether -Wno-strict-aliasing is supported by the compiler, performed only if NaN boxing is enabled. We need to disable this warning because it goes off on the code that reinterprets an integer as a double and vice versa.
* Define bit width of NUM type in one place.Kaz Kylheku2022-09-121-0/+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.
* New macro: close-lazy-streams.Kaz Kylheku2022-08-281-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | * lib.c (lazy_stream_s): New symbol variable. (lazy_streams_binding): New static variable. (lazy_stream_register): New static function (lazy_stream_cons): If the stream is associated with a lazy cons, register it with lazy_stream_register. (obj_init): gc-protect lazy_streams_binding variable. Intern the sys:*lazy-streams* symbol. * lib.h (lazy_streams_s): Declared. * eval.c (eval_init): Register sys:*lazy-streams* special variable. * stdlib/getput.tl (close-lazy-streams): New macro. * autoload.c (getput_set_entries): Trigger autload on close-lazy-streams symbol. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New function: search-allKaz Kylheku2022-08-171-0/+1
| | | | | | | | | | | | | | | | | | | | | | | * eval.c (eval_init): search-all intrinsic registered. * lib.c (search_common): New Boolean argument all, indicating whether all positions are to be returned. We must handle this in the two places where empty key and sequence are handled, and also in the main loop. A trick is used: the found variable is now bound by list_collect_decl, but not used for collecting unless all is true. (search, rsearch, contains): Pass 0 for all argument of search_common. (search_all): New function. * lib.h (search_all): Declared. * tests/012/seq.tl: New tests. * txr.1: Documented. * stdlib/doc-syms.tl: Regenerated.
* New function: count.Kaz Kylheku2022-07-181-0/+1
| | | | | | | | | | | | | | | | The general count function, with keyfun and testfun, is noticeably absent. Let's implement it. * lib.[ch] (count): New function. * eval.c (eval_init): Register count intrinsic. * tests/012/seq.tl: Some tests for count. * txr.1: Add count to count-if section. Revise documentation based on pos/pos-if. * stdlib/doc-syms.tl: Updated.
* New function: strKaz Kylheku2022-06-121-0/+1
| | | | | | | | | | | | | | | The str function is like mkstring but allows a fill pattern to be specified. * eval.c (eval_init): str intrinsic registered. * lib.[ch[ (str): New function. * tests/015/str.tl: New file. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New: spln and tokn functions.Kaz Kylheku2022-05-301-0/+2
| | | | | | | | | | | | | | | Instead of trying to work the new count parameter into the spl and tok functions, it's better to make new ones. * eval.c (eval_init): spln and tokn intrinsics registered. * lib.[ch] (spln, tokn): New functions. * tests/015/split.tl: New test cases. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.