| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
| |
* lib.c (equal): Since we have switched on the type of the
left and right argument, we can access the object directly
instead of going through car and cdr. Except that for a lazy
conses, we need at least one such access to force the object
first.
|
|
|
|
|
|
|
|
| |
* lib.c (less_tab_init): Assign category 6 to BUF type, so
buffers are sorted after other types.
(less): Add BUF case.
* txr.1: Documented.
|
|
|
|
| |
* txr.1: Fix "a eval-only" in definition of top-level form.
|
|
|
|
|
| |
* share/txr/stdlib/op.tl (sys:op-expand): Replace ^(,*args)
with just args.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In this commit, we ensure that objects in the heap are aligned
to at east eight byte boundaries (the minimum alignment from
most malloc implementations on 32 and 64 bit systems). If
possible, we align objects to a multiple of their size, sizeof
(obj_t), which is 16 bytes on 32 bit platforms and 32 bytes
on 64 bit platforms. We do this by making the object array the
first field of the heap structure, and by allocating it with
an aligned allocator function, if possible.
* configure: detect memory alignment function: either
memalign (preferred) or else posix_memalign (ugly duckling).
We conditionally add either HAVE_MEMALIGN or
HAVE_POSIX_MEMALIGN into config.h.
* gc.c (OBJ_ALIGN): New macro.
(struct heap, heap_t): Put the block member first, so objects
are aligned with the containing heap.
(in_heap): If the pointer is not aligned to a multiple of
OBJ_ALIGN, it can't be a heap object; return zero.
If allocations of the heap are aligned, then we don't need the
additional alignment check in the loop body; if the pointer
lands in the array, then the earlier OBJ_ALIGN check assures
us it must be aligned. If we have only malloc alignment, we
must do the check; the pointer could be to an address
divisible by 8 which is in the middle of an obj_t.
* lib.c: If HAVE_MEMALIGN is true, then include <malloc.h> so
we have it declared.
(memalign): If HAVE_POSIX_MEMALIGN is true,
this static function is defined; it's compatible with the
Glibc memalign. If HAVE_MEMALIGN and HAVE_POSIX_MEMALIGN are
false, then memalign is defined as a malloc wrapper which
doesn't align.
(chk_malloc_gc_more): Use memalign instead of malloc. If
aligned allocation is available, this will cause the heap to
be aligned to a multiple of the object size.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* configure: In several config tests, test HAVE_SUPERLONG_T,
HAVE_LONGLONG_T and HAVE_SYS_WAIT with #if.
* lib.c: Test HAVE_GETENVIRONMENTSTRINGS with #if.
* lib.h: Test HAVE_DOUBLE_INTPTR_T with #if.
* mpi/mpi.c: Likewise.
* mpi/mpi.h: Likewise.
* socket.c: Test HAVE_GETADDRINFO with #if in three places.
* stream.c: Test HAVE_SYS_WAIT and HAVE_SOCKETS with #if.
|
|
|
|
|
|
|
|
| |
* gc.c (more): The heap_max_bound and heap_min_bound variables
are initialized to null. We must update them unconditionally
if they are in that state. What's happening otherwise is that
heap_min_bound stays null and so we unnecessarily process
false positives in the in_heap function.
|
|
|
|
|
|
|
|
| |
* lib.c (cat_str, vscat): Use size_t type for the total, so
that the wrapping behavior we depend on for overflow detection
is well-defined. Also, there was an overflow check missing for
the total + 1 beign passed to chk_wmalloc. Instead of adding
that overflow check, let's just start the total at 1.
|
|
|
|
|
|
|
|
|
|
|
|
| |
I had this file locally for the better part of a year!
Commit 5e4c74dfd5927b3829b4f5e04a7964dbac6a4f34 made on
December 31, 2018 claims that alloca.h was added.
In fact, it was not. Things work without it because
the #include "alloca.h" directives in the code end up
resolving to <alloca.h>. This is widely available so nobody
has seen a problem.
* alloca.h: New file.
|
|
|
|
| |
* linenoise.c: due to extensive changes, asserting own copyright.
|
|
|
|
| |
* ftw.c: Bump copyright to 2019.
|
|
|
|
| |
* md5.c (encode): Remove unused op variable.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Likewise.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/build.tl (list-builder add,
list-builder pend, list-builder pend): Refer to previously
cached variable holding self.head or self.tail, instead of
re-accessing the slot.
|
|
|
|
|
| |
* share/txr/stdlib/build.tl (list-builder pend): Use tailp
instead of last and eq.
|
|
|
|
|
|
|
|
|
| |
* lib.c (obj_print_impl): The Unicode BOM is also a zero width
non-breaking space, which causes it to look like the
incomplete #\ syntax. Let's instead render it as #\xFEFF.
A few other hex cases are moved up into the surrounding
switch, and a little goto takes care of avoiding code
duplication.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Reported by user vapnik spaknik.
* lib.c (bracket): Don't rely on the index variable to step
through the arguments, because it only counts fixed arguments.
The args_get function doesn't increment the index beyond
args->fill; when popping arguments from args->list, index
stays unmodified.
* tests/016/arith.tl: Tests for bracket added.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/build.tl (list-buider pend*): Fix typo:
apply should be append. Funny, this didn't propagate to ncon*.
* tests/012/seq.tl: Some list-builder tests via build macro.
|
|
|
|
| |
* tests/016/arith.tl: Add various digits tests.
|
|
|
|
|
|
|
|
| |
Just a few append cases with improper lists here to start with.
* tests/012/seq.tl: New file.
* tests/012/seq.expected: New file
|
|
|
|
|
| |
* Makefile (clean): If it exists, remove the temporary run.sh
that is generated by the install-tests target.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The list building framework underlying the list_collect_decl
macro has a flaw: if the current list ends in an non-nil
terminating atom, and the tail pointer isn't directly aiming
at that atom, then a subsequent operation to add an item or
append a suffix will just overwrite the atom.
The correct behavior is to execute the same logic as if the
tail pointer pointed at that atom on entry into the function:
switch on the type of the atom, and append to it, if possible,
or else throw an error.
Thus, for instance, (append '(1 2 3 . 42) '(4)) wrongly
returns (1 2 3 4), instead of producing an error. The 42
atom has disappeared.
The example (append '(1 2 . "ab") "c") -> (1 2 . "abc")
given in the man page doesn't work; it yields (1 2 . "c").
* lib.c (list_collect, list_collect_nconc,
list_collect_append, list_collect_revappend,
list_collect_nreconc): In the cases when the current tail
object is a CONS and LCONS, and we move the tail, we must
branch backwards and process the tail atom as if the tail had
been that way on entry into the function. Doing this with a
tail call would be nice, but in some of the functions, we hold
a local resource already, so we simulate a local tail call
by updating the tailobj variable and doing a backwards goto.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Rewriting be addition, pending and nconcing methods of
list-builder to avoid loops and rely on lower list processing
functions. This cleans up the semantics and error messages.
Some examples of behavioral changes:
(build (pend "abc") (add #\d)) now returns "abcd",
consistent with (append "abc" '(#\d)).
Previously it returned '(#\d).
(build (add 1) (pend 2) (pend 3)) now produces a "cannot
append to 2" error.
Previously it produced "copy: cannot copy object of type fixnum".
* share/txr/stdlib/build.tl (list-builder add): Don't use
copy-list; rather the idiom for copying a sequence in
preparation for appending to it is (append x nil). This will
blow up nicely if x is an atom other than nil. We use
this trick twice.
(list-builder add*): Simplify with append.
(pend, pend*, ncon): Rewrite.
(ncon*): Use nconc once on a combined argument list: this is
borrowed from the rewritten pend*.
* txr.1: Documentation updated with clarifications,
particularly in the area of the requirements regarding
destructive manipulation and substructure sharing.
|
|
|
|
|
|
|
| |
* arith.c (digcommon): Improved termination test in the second
loop to avoid wasteful pop when the list of powers is empty.
Use rcyc_pop to recycle these conses; they will be immediately
reused for building the output list.
|
|
|
|
|
|
| |
* arith.c (digcommon): Fix off-by-one test causing incorrect
results for radix powers like (digits 10) (digits 100) ...
and analogously in other radices. Reported by vapnik spaknik.
|
|
|
|
|
| |
* arith.c (digcommon): Fix wrong test that allows base 1 to be
admitted, resulting in infinitely looping behavior.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (subtypep): For the sequence supertype, check
whether the subtype is a structure that has a length or
car method, returning t if so.
* struct.c (get_special_slot_by_type): New function.
* struct.h (get_special_slot_by_type): Declared.
* txr.1: Add <structures with cars or length methods> to the
type hierarchy diagram.
|
|
|
|
|
|
| |
* lib.c (seq_info): Add missing else, which makes the function
return nil for objects that have a length method, but not a
car method.
|
|
|
|
|
|
| |
* lib.c (subtypep): The sub and sup parameters are compared
for equality early in the function; byt the time we get
here, we know they are not eq, so nil can be returned.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_flex_struct_in): Use get_special_slot to obtain
length method.
* lib.c (nullify_s, from_list_s, lambda_set_s): Definitions
removed from here.
(seq_info, car, cdr, rplaca, rplacd, make_like, nullify,
replace_obj, length, empty, sub, ref, refset, dwim_set): Use
get_special_slot to obtain special method from object,
rather than maybe_slot.
(obj_init): Remove initializations of nullify_s, from_list_s
and lambda_set_s from here.
* struct.c (enum special_slot): Definition removed from here.
(nullify_s, from_list_s, lambda_set_s): Definitions moved here
from lib.c.
(special_sym): New static array.
(struct_init): Initializations of nullify_s, from_list_s
and lambda_set_s moved here from lib.c.
(get_special_slot): New function.
* struct.h (lambda_set_s): Declared.
(enum special_slot): Definition moved here.
(get_special_slot): Declared.
* txr.1: Added compat note, since get_special_slot behaves
like maybe_slot under 224 compatibility.
|
|
|
|
|
|
| |
* struct.c (get_equal_method): Static function removed.
(struct_inst_equalsub): Replace one and only call to
get_equal_method with direct call to get_special_static_slot.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A type which we never ask for a special slot need not
waste space the array.
* struct.c (struct struct_type): Change spslot from array to
pointer.
(make_struct_type): Initialize spslot pointer to zero.
(struct_type_destroy): Free the dynamic array.
(invalidate_special_slot_nonexistence): Do nothing if the
spslot pointer is null.
(get_special_static_slot): Dynamically allocate the array
if the spslot pointer is null, and update that pointer,
before doing anything else. The parameter signature changes;
instead of a pointer to an element of the stslot array, we
pass the index.
(get_equal_method): Pass the index of the equal method special
slot, rather than the address of the array entry.
|
|
|
|
|
|
| |
* lib.c (seq_info): Due to a copy-paste error maybe_slot is
being accidentally called here twice for the same slot.
Removing.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This lays the groundwork for optimizing access to more special
slots. Currently the equal method is handled specially; if a
type has an equal method, then this is cached for fast access,
so we are not doing a slot lookup each time the method needs
to be called. We would like a small array of such methods,
with minimal code duplication.
* struct.c (enum special_slot): New enum.
(struct struct_type): Scalar member eqmslot replaced by
spslot array.
(make_struct_type): Initialize elements of new array to null;
don't initialize removed eqmslot member.
(invalidate_special_slot_nonexistence): New static function.
(static_slot_set, static_slot_ens_rec): Use
invalidate_special_slot_nonexistence instead of open code.
(get_static_special_slot): General function for obtaining and
caching a special slot. Based on implementation of
get_equal_method.
(get_equal_method): Rewritten as a simple call to
get_special-static_slot.
|
|
|
|
|
|
|
|
|
|
| |
Only struct.c refers to this symbol, and so only struct.c
needs to be recompiled when someone experiments with different
values.
* lib.h (SLOT_CACHE_SIZE): Macro deleted here.
* struct.c (SLOT_CACHE_SIZE): Macro moved here.
|
|
|
|
|
|
|
| |
Omissions reported by user vapnik spaknik.
* lib.c (subtypepe): The lcons type and string type must
report as subtypes of sequence.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/build.tl (list-buider add,
list-builder add*, list-builder pend, list-builder pend*):
Use copy-list rather than copy. This copies terminating
atoms without complaining.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The list builder is failing on the documented example
(build
(add 1 2)
(pend (get))
(pend (get)))
-> (1 2 1 2 1 2 1 2)
wrongly constructing an infinite list.
* share/txr/stdlib/build.tl (list-builder pend): When
destructively appending the next argument, check whether
the current tail is a tail of that object. If so, copy
the object to prevent a cycle from forming.
(list-builder pend*): When appending the old head to the
catenated list, do the tail check and copy the object if
necessary to prevent the creation of a cycle.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register tailp intrinsic.
* lib.c (tailp): New function.
* lib.h (tailp): Declared.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
| |
When a slot is not found in a cache, and in other situations
the object system conses up a key in order to search a the
global slot_hash. We should be recycling these keys
for reuse via rcyc_cons. This change makes recompilation of
TXR's library (make clean-tlo; make) about 1.6% faster.
* struct.c (lookup_slot, lookup_static_slot_desc, static_slot_p):
Recycle the hash key cons cell via rcyc_cons, so it can be
reused immediately.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
TXR user vapnik spaknik has found a swath of errors in the
documentation.
* txr.1: Fixed bugs in numerous examples, copy-and-paste
errors in syntax sections, and other typos, including *stdin*
mistyped as *std-input* in many places. A new executable code
example is provided for expand-with-free-refs to calculate the
result that was previously only verbally described. Fixed
*stdin* mistyped as *std-input* (a non-existent symbol that
imitates the internal C variable).
|
|
|
|
| |
* txr.1: Hyphenate "heap-allocated" and "stack-allocated".
|
|
|
|
|
|
|
| |
* eval.c (bindings_helper): If there are no bindings or just
one binding, then go through the sequential case. Thus trivial
let is treated like let*. This avoids the continuation-related
overheads incurred in the parallel case.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This was discovered by user vapnik spaknik. If a let* form is
evaluated in a top-level expression such that the incoming
environment is null, and a continuation is captured in the
init-form of the first variable, when that continuation is
invoked, an exception is thrown: "copy-env: nil is not of type
env".
Short repro:
1> (block nil (let* ((x (yield 42)))))
** copy-env: nil is not of type env
In fact, the bug isn't that we're trying to copy nil.
the problem is we are trying to copy an environment we should
not be copying at all. In fact, for sequential binding,
there is no need for that logic at all; it's only parallel
binding which needs it, because all of the init-forms are
inserting bindings into the same environment.
* eval.c (bindings_helper): Don't bother with registering a
copy handler for sequential binding logic, because we
don't mutate environments. All of that code is moved into the
parallel case.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Likewise.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-bind-mac-params):
Remove the plen gensym. We don't need to store the form length
in a variable, because the generated length check code
references the value exactly once. Let's just propagate that
the length calculating expression into that code.
|
|
|
|
|
|
|
|
|
| |
* chksum.c (sha256_utf8_byte_callback, md5_utf8_byte_callback):
New static functions.
(sha256_hash, md5_hash): Support character and integer
objects.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Virtual machine local variables registers don't require
nil initialization. In cases when a complex variable
initializer is known to return nil, we can elide the move
instrution which moves that nil into the register.
* share/txr/stdlib/compiler.tl (null-reg): New function.
(compiler comp-let): Don't move the value of the output
register of the init fragment into the variable, if that
register is the null register t0.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-bind-mac-params):
Generate better Lisp code when presence indicating variables
on optional parameters are not used. It's possible to bind the
variable directly, instead of binding to nil and assigning it.
The cases are split accordingly.
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-bind-mac-params):
Allocate the curs gensym only when about to recurse over a
nested parameter list, rather than unconditionally. Otherwise,
we always end up allocating one more gensym than we actually
use, for a lower nesting level that might not be there.
Don't use unwind-protect for returning the cursor variable to
the free-list; it makes no sense to be recovering that since
any exception will be abandoning this function entirely.
|