| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The opip syntax often generates lambdas that have a trailing
parameter and use [sys:apply ...]. This is wasteful in the
second and subsequent argument positions of a chain, because we
know that only a single value is coming from the previous
function. We can pattern match these lambdas and convert
the trailing argument to a single fixed parameter.
* stdlib/compiler.tl (simplify-variadic-lambda): New function.
(inline-chain-rec): Try to simplify every function through
simplify-variadic-lambda. The leftmost function is treated in
inline-chain, so these are all second and subsequent
functions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The opip syntax and its variants transforms into
chain expressions. Currently, we emit actual chain
function calls, and so all the chain arguments
that are lambda expressions have become closures.
In this commit, an inlining optimization is introduced
which turns some chain function calls into chained
expressions. The lambdas are then immediately called,
and so succumb to the lambda-eliminating optimization.
* stdlib/compiler.tl (compiler comp-fun-form): Handle
chain forms. At optimization level 6 or higher, if
the form is eligible for the transform, perform it.
(inline-chain-rec, can-inline-chain, inline-chain):
New functions.
* txr.1: Mention that *opt-level* 6 does this chain
optimization.
|
|
|
|
|
| |
* stdlib/compiler (lambda-apply-transform): Fix
misleading indentation.
|
|
|
|
|
| |
* txr.1: Under Pattern-Matching Notation: subject-verb
agreement.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
| |
* hash.c (hash_eql): Use hash_traversal_limit for
the initial value of the limit rather than zero.
Commit 84e9903c27ede099e2361e15b16a05c6aa4dc819 in October
2019 fixed eql_hash to actually make use of the limit, which
broke the assumption that we could use zero.
* tests/010/hash.tl: Add a few tests for hash-equal and
hash-eql.
|
|
|
|
| |
* stdlib/quips.tl (%quips%): New entry.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
* ffi.c (mmap_wrap): Make the diagnostic depend on the actual
condition that it's wording is about. If the element type is
nonzero, but the length is too low for the array to have any
elements, that is not strictly an error; we can let that pass.
|
|
|
|
|
|
| |
* txr.1: The source argument of mmap is not adequately
documented. It can be an integer descriptor, stream or
filename string.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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 fixes crashes in the test cases when TXR is built with
clang on little-endian PPC64. Clang uses vector instructions,
but our jmp.S does not save any vector registers. In some
places this causes a problem.
I've noticed much of the code just uses vrs0, vrs1 and vrs63
for doing small things, like initializing small structures
with a single instruction. The functions that use more of these
registers don't call anything that saves and restores a
context.
In this patch we just save/restore vrs63, which maps to vr31.
The vrs0 and vrs1 don't have to be saved and restored; the
setjmp function doesn't do it. Everything is conditional on
__ALTIVEC__.
* unwind.h (jmp): We add vr31 to the PPC64 version of
struct jmp. The instructions which load and store this
requires 32 byte alignment, so we assert that. Note that the
alignment leaves 8 bytes of padding at the end of the structure
since there are 23 other registers to save.
* jmp.S (jmp_save, jmp_restore): We save and restore v31 first
and then move the pointer past it by 32 bytes to do the rest
of the registers exactly as before. In jmp_save, we save
an extra copy of the r11 register into the padding so that
it is initialized. We don't like to encourage padding in the
stack because in light of our GC's conservative scan of
the stack, it promotes spurious retention of objects.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I looked at all cobj calls to see if there is a potential
problem, looking for situations whereby the cobj call could
trigger a gc that would destroy Lisp objects that the
new object either stores, or that its continued initialization
depends on.
* stream.c (make_strlist_input_stream): call cobj earlier,
then fill in the structure. Use chk_calloc to allocate
the structure so any Lisp objects in it look like nil
until it is initialized.
* struct.c (make_struct_impl, make_lazy_struct):
Use gc_hint on the type argument, to pin down the
st structure that we use in initializations after
the cobj call. If the type object were to disappear,
the st structure would become invalid.
* tree.c (copy_search_tree, make_similar_tree):
Use gc_hint on the tree argument to pin down the otr
structure that we reference in initializations
(copy_tree_iter): Use gc_hint on iter, for similar
reasons.
* vm.c (vm_copy_closure): Use gc_hint on oclosure,
to pin down the environment we are copying from it.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (reparent_env): This function is used in bindings
helper, when special variables are involved. It makes a new
environment the parent of an existing one, just by assigning
the pointer. This is wrong under generational GC if it makes
a mature object point to a new object. We fix it with the set
macro. I've not seen a crash because of this; I caught it by
inspection.
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
* sysif.c (link_wrap_common): Cast the follow_link
argument to void in the #else case to suppress warning.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* tests/007/except-4.txr: The portable way to get a shell
command that exits with a signal is to execute kill -KILL $$.
If we use a signal that the shell catch like SIGTERM or
SIGINT, we get nonportable behaviors. Some shells seem to
catch the signal and then raise it again so they terminate
with that signal. Some shells terminate normally, but create
an exit status by OR-ing 0x80 with the caught signal.
Let's use kill -KILL here and drop the tests for BSD and
Solaris.
* tests/007/except-3.txr: Fix the kill command here also.
While this test wasn't failing on those platforms, it succeeds
vacuously, since the exception being ignored by :nothrow
is not actually thrown.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* tests/014/socket-basic.tl: Test for :openbsd also
were we test for :bsd.
* tests/014/glob-carray.tl: Likewise.
* tests/017/glob-zarray.tl: Likewise.
* tests/017/mmap.tl: Likewise.
* tests/018/chmod.tl: Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The STDLIB_EARLY_TLOS are not being built in the intended
order for several reasons. Firstly, the list is built by
filtering STDLIB_TLOS which are in an order pulled by the
wildcard command. Secondly, the order-only rule isn't
preserving the order among the early tlos, only ensuring
that those members of STDLIB_TLOS which occur in
STDLIB_EARLY_TLOS are built before the others.
* Makefile (STDLIB_EARLY_PATS): Variable removed.
(STDLIB_EARLY_TLOS): Specified directly rather than via
filtering.
(all): Don't depend on $(STDLIB_TLOS) but rather on
$(STDLIB_EARLY_TLOS) and $(STDLIB_LATE_TLOS) in that order.
($(STDLIB_LATE_TLOS):): Ordering rule removed.
|
|
|
|
|
|
|
|
| |
* tests/common.tl (os-symbol): Add :openbsd.
* tests/007/except-4.txr: Skip.
* tests/018/crypt.tl: Skip unsupported salts, i.e., without leading "$".
* tests/018/gzip.tl: Add -f to gzip command to force compression even if
it does not make the file smaller.
|
|
|
|
|
|
|
| |
OpenBSD is missing RLIMIT_AS.
* sysif.c (sysif_init): Register rlimit-as variable only if RLIMIT_AS is
defined.
|
|
|
|
| |
* txr.1: Fix markup of syntax, invalid due to missing space.
|
|
|
|
|
| |
* txr.1: Clarify that both sort and nsort are not stable
for vectors and strings.
|
|
|
|
| |
* configure: Capitalize first word "detecting" of diagnostic line.
|
|
|
|
|
| |
* configure: Add space after ellipses where missing, and prefer putting
the space in the initial printf.
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
* configure: Pipe output of strings into grep in endianness test, like
is done for ubsan.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
|
|
|
| |
* Makefile (shipped): Copy the shipped materials unconditionally,
rather than checking if they are different. If a patch exists
for a shipped file, then apply it.
* lex.yy.c.shipped, y.tab.c.shipped: Updated.
* lex.yy.c.patch, y.tab.c.patch: New files.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This was prompted by a misleading indentation warning.
* parser.c (read_objects_common): The indented statment
"return error_return_val;" belongs with the if. This works
anyway because if lisp_parse_impl returned unique_s, it
means that either pi->syntax_tree is nao, or pi->errors
is positive. So, let's take advantage of that and don't
bother checking for pi->syntax_tree == nao. If unique_s
was returned and there are no errors, we hit EOF and
so break out of the loop.
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (run): On Cygwin, the spawnvp function is
returning a 16 bit termination status word where the upper
8 bits is the termination status if the termination is normal,
otherwise the lower 8 bits holds a termination signal.
Let's massage it so that the function returns an integer
termnation status, or nil if the termination was abnormal,
same as we do on POSIX platforms with fork/wait.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
perm doesn't generate items of the right type. We need
to add the original sequence to the state vector and
use make_like.
The new generic sequence support in rperm is broken, too.
* combi.c (perm_while_fun, perm_gen_fun_common): Rename p
variable to vec.
(perm_init_common): Rename to perm_init. Take one more
argument and store in new fourth element of state vector.
(perm_vec, perm_list, perm_str): Pass nil to new parameter
of perm_init.
(perm_seq_gen_fun): Use perm_list_gen_fun to get list
permutations, and coerce each one to the same type as
the sequence with make_like.
(rcomb_seq_gen_fun): Remove redundant call to
rcomb_gen_fun_common. The rcomb_list_gen_fun function
is called, which does this already, so we lose every
other sequence element.
* tests/015/comb.tl: New tests.
|
|
|
|
|
|
| |
* combi.c (rcomb_seq_gen_fun, rcomb_seq): New static functions.
(rcomb): Replace error throw in default case with call to
rcomb_seq.
|
|
|
|
|
|
|
| |
* combi.c (comb_seq_gen_fun, comb_seq): New static
functions.
(comb): Call comb_seq in default case rather than
throwing error.
|
|
|
|
|
|
|
|
| |
* combi.c (comb_hash_while_fun): Function removed.
(comb_hash): For the while function, use the
unwrapped state, and just comb_while_fun.
The augmented state with hash is used only with
comb_hash_gen_fun.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* combi.c (rperm_init): Take one more parameter.
Allocate the state vector to three elements and
put the extra value there.
(rperm_list, rperm_vec, rperm_str): Pass nil
for the extra value to rperm_init; these do not
use it.
(rperm_seq_gen_fun, rperm_seq): New functions.
These use the extra value to store the original
seq in the state, so that the elements of the
output sequence can be converted to the same type
of sequence as the input.
(rperm): Replace error throw in default case with
call to rperm_seq.
|
|
|
|
|
|
|
|
| |
* combi.c (rperm_init): New static function.
(rperm_while_fun, rperm_gen_fun): Retrieve state
info from vector-based state rather than cons.
(rperm_list, rperm_vec, rperm_str): Call rperm_init to
allocate state.
|
|
|
|
| |
* tests/015/comb.tl: New tests.
|
|
|
|
|
| |
* txr.1: Section describing rcomb function wrongly
refers to comb.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The comb function is broken; some combinations of items
are missing in the output. This is because the iteration
reset step in comb_gen_fun_common handles only one
column of the state, neglecting to reset the other
columns: what is now done by the for (j = i ...
loop. I'm changing the representation of the state from
a list of lists to a vector of lists. Moreover, it is not
reversed. This allows the loop in comb_gen_fun_common
to perform random access.
* combi.c (k_conses): Return a vector, that is not
reversed.
(comb_init): New helper function to slightly abstract
the use of k_conses.
(comb_while_fun): Termination now occurs if the state
vector is nil (degenerate case, like k items chosen
from n, when k > n), or if the vector has nil in
element zero (special flag situation).
(comb_gen_fun_common): Rewritten, with correction.
The logic is similar. Since we have random access,
we don't need the "prev" variable. When we reset
a column iterator, we now also populate all the
columns to the right of it. For instance, if a
given column resets to (a b c), the one to the right
must reset to (b c), and so on. In the broken function,
this is what was not done, resulting in missing
items due to, say, a column resetting to (a b c)
but the one next to it remaining at (c).
(comb_list_gen_fun): Drop nreverse.
(comb_vec_gen_fun, comb_str_gen_fun, comb_hash_gen_fun):
Use the same i iterator for the state and the output object,
accessing the vector directly.
(comb_list, comb_vec, comb_str, comb_hash): Use comb_init.
* tests/015/comb.tl: New file.
|
|
|
|
|
|
| |
* combi.c (perm_seq_gen_fun, perm_seq): New functions.
(perm): Call perm_seq in default case to handle more
sequence kinds.
|
|
|
|
|
|
|
|
|
| |
* txr.1: The Math Library is documented in a way that is
oblivious to User-Defined Arithmetic. This is now clarified.
When some of the argument types of a math function are
user-defined arithmetic structures, the stated conversions
and restrictions don't apply, since it defers all semantics
to the method invoked.
|
|
|
|
|
|
| |
* Makefile (shipped): This rule works correctly but
shows, for instance, COPY lex.yy.c.shipped -> lex.yy.c.
which is backwards. Let's fix it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I've run into situations in which I wanted a comment in a
big JSON quasiliteral to explain some embedded piece of code.
We support only semicolon comments, and no #; ignore notation.
* parser.l (grammar): Recognize Lisp comments in the JSON
state also. That does it.
* tests/010/json.tl: One modest little test.
* txr.1: Documented.
* lex.yy.c.shipped: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We have these issues, which are regressions:
1> (compile-toplevel '(/ 1 0))
** expr-1:1: warning: sys:b/: constant expression (sys:b/ 1 0) throws
** /: division by zero
** during evaluation at expr-1:1 of form (sys:b/ 1 0)
1> (compile-toplevel '(let ((a 1) (b 0)) (/ a b)))
** /: division by zero
** during evaluation at expr-1:1 of form (compile-toplevel [...])
While the compiler's early pass constant folding is careful
to detect constant expressions that throw, care was not taken
in the optimizer's later constant folding which takes place
after constant values are propagated around.
After the fix:
1> (compile-toplevel '(let ((a 1) (b 0) (c t)) (if c (/ a b))))
** expr-1:1: warning: let: function sys:b/ with arguments (1 0) throws
#<sys:vm-desc: 9aceb20>
2> (compile-toplevel '(let ((a 1) (b 0) (c nil)) (if c (/ a b))))
#<sys:vm-desc: 9aef9f0>
* stdlib/compiler.tl (compiler): New slot top-form.
(compile-toplevel): Initialize the top-form slot of the
compiler. The optimizer uses this to issue a warning now.
Since the warning is based on analyzing generated code, we
cannot trace it to the code more precisely than to the top-level
form.
* stdlib/optimize.tl (basic-blocks): New slot, warned-insns.
List of instructions that have been warned about.
(basic-blocks do-peephole-block): Rearrange the constant folding
case so that as part of the pattern match condition, we include
the fact that the function will not throw when called with those
constant arguments. Only in that case do we do the optimization.
We warn in the case when the function call does throw.
A function rejected due to throwing could be processed through
this rule multiple times, under multiple peephole passes, so
for that reason we use the warned-insns list to suppress duplicate
warnings.
|
|
|
|
|
|
| |
* stdlib/compiler.tl (compiler compile): Don't store form
into me.last-form if it's an atom; it won't be useful
or error reporting.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* parser.c (read_objects_common): New static function, formed
from read_objects_from-string.
(read_objects_from_string): Now wrapper for read_objects_common.
(read_objects): New function.
* parser.h (read_objects): Declared.
* eval.c (eval_init): Register read-objects intrinsic.
* autoload.c (getput_set_entries): Add three new symbols:
file-get-objects, file-put-objects and file-append-objects.
* stdlib/getput.tl (put-objects): New system function.
(file-get-objects, file-put-objects, file-append-objects):
New functions.
* txr.1: Documented.
* tests/018/getput.tl: New file.
|
|
|
|
|
|
|
|
|
|
|
| |
* hash.c (hash_join): New function.
(hash_init): hash-join intrinsic registered.
* hash.h (hash_join): Declared.
* tests/010/hash.tl: New tests.
* txr.1: Documented.
|
|
|
|
|
|
|
| |
* tests/010/hash.tl: Add test cases for the hash set operations.
* txr.1: Clarify that in hash-uni, the mapping functions are
used on all items, not just ones subject to joinfun.
|