| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (window_map_common): New static function formed
from window_map_list.
(window_map_list, window_map_vec): Function removed.
(window_map, window_mappend, window_mapdo): Simplify
to wrappers around window_map_common.
* txr.1: Some wording improved in the window-map
documentation.
|
|
|
|
|
|
| |
* lib.c (rfind): We combine the default case with
SEQ_LISTLIKE and use the seq_iter abstraction rather
than car/cdr.
|
|
|
|
|
|
|
| |
* lib.c (find): We retain the optimization for strings when
the comparison is regular equality (eq, eql, equal). The
other cases are handled by seq_iter rather than separate
list-like and vector-like cases.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
* lib.c (list_vec): use ucnum rather than int
for the index and length variables.
|
|
|
|
|
|
| |
* lib.c (unique): Build output using seq_build_t, rather
than consing up a list which is then converted to the desired
sequence type.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (partition_func, split_func, split_star_func):
Indices passed through lazy cons are now iterator,
rather than a sequence accessed via car and cdr,
which is inefficient for nonlists.
(partition-split-common): Use iter-begin to convert
indices to iterator, which becomes the cdr field of
the lazy cons.
* txr.1: Update documentation for these functions to clarify
that the second argument is a sequence. The inaccurate
text claiming that "if the second argument is an atom
other than a function" is rewritten. This doesn't describe
the behavior that is implemented, where the test applied
is seqp, not atom. The indices can be a vector of integers,
which is an atom.
|
|
|
|
|
| |
* lib.c (partition_if_func): Instead of list_collect_decl
and make_like, use seq_build.
|
|
|
|
|
|
|
|
| |
* lib.c (partition_by_func): The seq object is now
an iter object: use iter_more, iter_item and iter_step
rather than non-null test, car and cdr.
(partition_by): Obtain iterator for sequence using
iter_begin, and use that in its place.
|
|
|
|
|
| |
* lib.c (partition_by_func): Use seq_build instead of
list_collect_decl and make_like.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
* lib.c (sb_vec_ops): fix indentation.
|
|
|
|
|
|
| |
* lib.c (seq_build_struct_finish, seq_build_carray_finish):
Do not call seq_build_convert_to_finished, since
seq_build_list_finish has already done that.
|
|
|
|
|
|
|
|
| |
* lib.c (seq_build_improper_finish): Function removed.
(sb_improper_ops): Replace seq_build_improper_finish
with null pointer. The seq_finish function checks for
null and avoids calling, so we don't need the noop
implementation.
|
|
|
|
|
|
|
|
| |
* lib.c (seq_build_convert_to_finished): New function.
(seq_build_list_finish): call seq_build_convert_to_finished.
(sb_finished_ops): New static struct. All operations
except mark are null pointers so this will crash if
used.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (mapcar): Implement with seq_iter and seq_build,
rather than relying on mapcar_listout and make_like.
(mappend): Replace list_collect_decl and make_like
with seq_build.
* eval.c (map_common): Replace list_collect_decl and
make_like with seq_build. The collect_fn is now a pointer
to either seq_add or seq_pend rather than list_collect
or list_collect_append.
(mapcarv, mappendv): Pass seq_add and seq_pend to
map_common, rather than list_collect and list_collect_append.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
To be useful for some operations, the seq_build framework
must handle the pend operation on lists specially.
The appended piece must only be treated as a sequence if
it is a cons. Moreover, if it is an atom, or of it is
an improper list, then the list terminates. Subsequent
add and pend operations must fail. The atom must appear
as the terminator. We meet these objectives by switching
the object's operations, sb_list_ops, to a new set of
operations, sb_improper_ops.
* lib.c (seq_build_list_pend): New static function.
This individually adds all items from the input
list, until it hits a terminating atom. If the
atom isn't nil, it converts the seq_build_t object
to improper operations.
(seq_build_improper_add, seq_build_improper_pend):
New static functions. These throw an error:
adding anything to an improper list is impossible.
(seq_build_improper_finish): New function, which
does nothing: the improper list is finished already.
(sb_list_ops): Use the seq_build_list_pend operation
rather than the generic one.
(sb_improper_ops): New static structure.
(seq_build_convert_to_improper): New static function.
Finishes the list, giving it the specified terminating
atom, and then switches to sb_improper_ops so that
adding is no longer possible.
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (tuples_func): Replace list accumulation
with make_like with seq_build.
* tests/012/seq.tl: Fix one test case here which no
longer errors out. It produces a tuple which is not
a string, due to the inclusion of a non-character
object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In the make_like function, the list is converted to
string or buffer if the first element of the list
is a character, or integer. We need similar logic in
seq_build. We can make it better. When any item is
added which is incompatible, we can convert what we
have so far to a list, change the seq_build type
to list, and keep going.
* lib.c (seq_build_convert_to_list): New static
function.
(seq_build_str_add, seq_build_buf_add): If the item
is incompatible, convert the string or buffer to
a list and pass to seq_build_convert_to_list.
Then call bu->ops->add to add the item, now as a list.
(seq_build_buf_pend): Function removed.
(sb_buf_ops): Use the seq_build_generic_pend function
for the pend operation. This is because we have to
check each item one by one; we cannot use replace_buf.
|
|
|
|
|
|
|
| |
* lib.c (seq_build_struct_finish, seq_build_carray_finish):
These functions are still wrongly assuming that the list
is finished by nreverse. We intead call seq_build_list_finish
for that, which puts the list back into bu->obj.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (seq_build_list_add, seq_build_list_finish):
We use the trick that bu->obj (if not nil) points
to the tail cons cell of the list being built, and
the cdr of that tail always points back to the head.
To finish the list, all we do is nil out that head
pointer, so the list is properly terminated, and then
plan the head as bu->obj.
|
|
|
|
| |
* lib.c (separate_keys): Rewrite using seq_info and seq_build.
|
|
|
|
|
| |
* lib.c (separate): switch statement with type-specific
coding replaced with generic sequence iteration and building.
|
|
|
|
|
|
| |
* lib.c (seq_build_init): Replicate a feature of make_like:
if the reference object is an iterator, then we recurse: we
initialize according to the object it is iterating.
|
|
|
|
|
| |
* lib.c (keep_keys_if): Replace with generic sequence
iteration and building.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
* lib.c (rem_if_impl): New static function, based on renaming
remove_if, and adding a self parameter.
(remove_if): Now wrapper around rem_if_impl.
(keep_if): Retarget to rem_if_impl, passing "keep-if" name.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I spotted in the N3096 draft of ISO C (April 2023) that
a zero size in realloc is no longer defined behavior,
like it used to be. I don't know exactly when it changed;
in C99 it is not mentioned. We call realloc only in
one place, so we can defend agains this.
* lib.c (chk_realloc): If the new size is zero, we
implement the C99 and older semantics: deallocate the
object, and then behave like malloc(0). In other
cases, we use realloc.
|
|
|
|
|
|
|
|
|
|
|
| |
This showed up as an intermittent segfault on OpenBSD
of the test case tests/006/freeform-5.txr, reproducible
quite often, around 30% to 60%. This was with gcc 4.2.1.
* lib.c (lazy_sub_str): We need a gc_hint here on the
prefix hend in pfxcopy. The garbage collector is
scavenging that object, not seeing that we planted
it into a malloced structure.
|
|
|
|
|
|
|
|
|
|
| |
Also affects seq_begin.
* lib.c (seq_begin, iter_begin): We must gc_protect the
incoming obj also, not only the iter. Both these pointers
are in the seq_info_t structure which is no longer used
at the time the iterator is being allocated by the call
to cobj, and so may be prematurely garbage collected.
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (obj_print_impl): Do not print (rcons X Y)
as X..Y if X looks like (rcons ...). This
causes the problem that (rcons (rcons 1 2) 3)
prints as 1..2..3, a notation which unambiguously
means (rcons 1 (rcons 2 3)).
* tests/012/syntax.tl: New test cases.
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (dwim_del): Remove check against structures from
OBJ case; we just let this pass through to the logic that
invokes replace.
* tests/012/aseq.tl: New test cases.
* txr.1: Document how del works on a [obj index] place.
|
|
|
|
|
|
|
| |
* lib.c (dwim_set): The "not a place" diagnostic applies
not only in situations when the object is a list;
the diagnostic should not imply that the argument is a list
when it isn't.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (lazy_flatten_scan): Fix a problem which results
in cases like (()), ((())) ... to incorrectly flatten
to (nil). The do loop in this function which iteratively
descends into a nested left-nesting of a list does not handle
all cases, and therefore the function may not return at that
point. Removing the return fixes the problem, but so does
removing the loop so that in that case we just descend one
level into the nested list, and continue in the main loop.
What is incorrect is that when the consp(a) test fails and the
do loop terminates, we need to distinguish the cases off
a being an atom versus nil. Continuing in the loop does that.
This bug was spotted by a reviewer in the comp.lang.c
Usenet newsgroup.
(lazy_flatten): We neglect to handle the case here that
the input is an empty list, resulting in (flatten* nil)
returning (nil) rather than nil. The flatten function
is correct.
* tests/012/seq.tl: New tests.
* txr.1: Documentation improved. In particular, these
functions don't handle improper lists. Also, it needs
to be documented that the argument may be an atom.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (out_json_rec): Handle NUM and BGNUM cases same as FLNUM
so integers get printed. The restriction against integers has
been largely unhelpful and bothersome. Handle LCONS together with
CONS. Lists that are not special notation fall through to the VEC
case, which now uses seq_iter_t iteration to handle vectors and lists.
* tests/010/json.tl: New tests.
* txr.1: Documented support for printing integers and lists.
|
|
|
|
|
|
|
|
|
|
| |
* lib.[ch] (str_esc): New function.
* eval.c (eval_init): str-esc intrinsic registered.
* tests/015/esc.tl: New file.
* txr.1: Documented.
|