| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Using Lisp types for lengths, indices and buffer sizes
has been awkward due to all the conversions. The
code in buf.c and other code elsewhere that touches
buffers, overall improves when we revise this
decision. Mostly there are fewer conversion from
Lisp to C which require a type check and self symbol
for error diagnsotis, like c_unum(len, self).
In a few places, there are conversions in the other
direction that were not needed before, like
unum(b->len). These are simpler and faster.
* lib.h (struct buf): Members len and size change
from val to ucnum (pointer-sized unsigned integer).
* gc.c (mark_obj): No need to do anything with BUF any
more; it has no Lisp object references.
* buf.c (BUR_BORROWED): New preprocessor symbol. Because
the allocation size can no longer be nil to indicate that
the buffer is borrowed (the buffer object doesn't own
the memory) we use this value instead: the highest value
of the ucnum type.
(buf_check_alloc_size): len parameter changes from cnum
to ucnum. Defends against the BUF_BORROWED value.
(buf_check_index): Returns ucnum rather than cnum.
(err_oflow): NORETURN attribute added to prevent some spurious
compiler warnings.
(prepare_pattern): Drop c_unum conversion of len.
(make_buf): Some locals change from cnum to ucnum.
We lose an unnecessary conversion.
(init_borrowed_buf): Take len as ucnum rather than val.
Use BUF_BORROWED value for allocated size to indicate
borrowed status.
(make_borrowed_buf): Take len as ucnum.
(make_duplicate_buf, make_owned_buf): Take len as ucnum,
and take a self argument. Check for the size being
BUF_BORROWED and reject.
(make_ubuf): Parameter renamed. Lose a conversion from
ucnum to val.
(copy_buf): Check for allocated size being BUF_BORROWED
to distinguish the two cases, rather than it being nil
or not.
(buf_shrink): Simplifies: loses a C to Lisp integer
conversion, and no longer needs the local variable self.
(buf_trim): Reject borrowed buffers by noticing the
BUF_BORROWED value.
(buf_do_set_len): len param becomes ucnum. Two Lisp-to-C
integer conversiond disappear; one C-to-Lisp moves
elsewhere in the code.
(buf_set_length): Use buf_check_len to check and
convert incoming len to ucnum. This is an improvement
over the previous approach of letting buf_do_set_len
to just rely on c_num conversions and their generic
diagnostics.
(buf_free): Check for borrowed buffer by comparing
allocated size to BUF_BORROWED constant.
(length_buf): ucnum to Lisp conversion now required here.
(buf_alloc_size): Check for alloc_size being BUF_BORROWED
and convert that to a nil return value. When returning
an integer size, we need a conversion to a Lisp integer.
(sub_buf): Use self symbol rather than lit("sub") when
obtaining buffer handle. Use buf_check_len to validate
the length and convert to C type.
(replace_buf): Some cnum local variables become ucnum.
We need a very careful comparison of w and l because
w remains signed while l is unsigned.
(buf_list): Substantially rewritten. We don't calculate
the length of the sequence upfront, but extend the
buffer as we add the elements to it.
(buf_move_bytes): size parameter changes from cnum
to ucnum. Lisp arithmetic replaced with C arithmetic;
conversions eliminated.
(buf_put_buf): Conversion eliminated in call to buf_move_bytes.
(buf_put_bytes): Function reduced to wrapper for
but_move_bytes, since it is almost identical. The only
difference is that it performs memcpy rather than memmove
which is not worth a separate function.
(buf_put_i8, buf_put_u8, buf_put_char, buf_put_uchar,
buf_get_i8, buf_get_u8): Simplified with C arithmetic
and fewer conversions; cnum use replaced with ucnum.
(buf_get_bytes): size parameter goes from cnum to ucnum.
Overflow check for p + size addition added.
(buf_print): Two conversions removed.
(buf_str_sep): Conversion removed.
(struct buf_strm): pos member changes from val to ucnum.
(buf_strm_mark): Do not mark p->pos, no longer a Lisp object.
(buf_strm_put_byte_callback): Lisp arithmetic removed,
but a unum conversion is needed now in calling buf_put_uchar.
That could be eliminated by not using the public interface.
(buf_strm_get_byte_callback): Eliminate buf_check_index to
validate the stream position; we simply check it against
b->len. Becomes simple one liner.
(buf_strm_get_char): Local variable index renamd to pos.
Two conversions from and to Lisp eliminated, leaving
no conversions.
(buf_strm_unget_byte): Local variable p renamed to pos and
changes from cnum to ucnum. Two conversions eliminated
leaving no conversions.
(buf_strm_fill_buf): Conversions eliminated. Check for the
allocated size being BUF_BORROWED, in which case we
fall back on using the length. Lisp arithmetic eliminated.
(buf_strm_seek): Offset calculation done with C arithmetic
and bounds checks.
(buf_strm_truncate): Check incoming len with buf_check_len
and convert to ucnum. Lisp arithmetic and conversions
eliminated; buf_do_set_len used instead of public interface
buf_set_length.
(buf_strm_get_error): Use C comparison rather than ge
function, and convert to t or nil result.
(buf_strm_get_error_str): Bug: do not call errno_to_string
since buffers don't talk to an operating system API that
uses errno. The only error condition is eof. Thus,
return either "eof" or "no error".
(make_buf_stream): Initialize pos to 0 rather than Lisp zero.
(swap32, buf_str, str_buf, buf_int, buf_uint, int_buf,
uint_buf): Conversions eliminated; int_buf and uint_buf use
C multiplication by 8. We know this doesn't overflow because
the MPI bignums restrict the number of bits to something
countable by a word.
(buf_compress, buf_decompress, str_compress, str_decompress):
Conversions eliminated.
(buf_ash, buf_fash, buf_and, buf_test, buf_or, buf_xor,
buf_not, buf_trunc, buf_bitset, buf_bit, buf_zero_p,
buf_count_ones, binary_width, buf_xor_pattern): Make
necessary adjustments, adding and/or elimiating conversions.
* buf.h (make_borrowed_buf, init_borrowed_buf, make_owned_buf,
make_duplicate_buf, buf_put_bytes): Declarations updated.
* lib.c (equal, less): Conversions eliminated in BUF cases.
* eval.c (map_common): Add self argument to make_owned_buf call.
* chksum.c (chksum_ensure_buf): len param changes from cnum
to ucnum. Conversions eliminated and use of lt() switches
to C less-than operator.
(sha1_stream, sha1_buf, sha1, sha1_hash, sha1_end,
sha256_stream, sha256_buf, sha256, sha256_hash, sha256_end,
md5_stream, md5_buf, md5, md5_hash, md5_end): Adjustments:
conversions eliminated.
(crc32_buf): Conversion eliminated.
* genchksum.txr: Changes to chksum.c actually made here.
* ffi.c (ffi_buf_in, ffi_buf_get, ffi_buf_d_in,
ffi_buf_d_get, buf_carray, put_carray, fill_carray,
put_obj, get_obj): Simplified with removal of
conversions.
(fill_obj): Necessary adjustments, leaving same
number of conversions.
* hash.c (equal_hash): Remove conversion from BUF case.
* rand.c (make_random_state): Remove conversion of seed
to Lisp integer.
(random_buf): Pass self to make_owned_buf.
* strudel.c (strudel_unget_byte, strudel_fill_buf):
Coversions removed, streamlining code.
* stream.c (iobuf_get, iobuf_put): We cannot overload
the len field with serving as a linked list since it's
no longer a pointer. We instead use the struct any
union member, which has a next pointer for this purpose.
Because "t.next" overlaps with "b.size", and we must not
clobber the size field, we save "b.size" by copying it
into "b.len". When pulling buffers from the iobuf_free_list,
we restore b.size from b.len. For good measure, We
add a bug_unless assertion that the size is the expected
one. I ran into a test case failure while working on this
due to the size being clobbered to zero, and subsequent
I/O with that zero-sized buffer being interpreted as EOF.
|
|
|
|
|
|
|
|
| |
* eval.c (expand_quasi): Quasiliteral sys:var items
now have a format string, which we have to propagate
to the expansion.
* tests/012/quasi.tl: New tests.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch adds support to quasiliterals to have the inserted
items formatted via a format conversion specifier, for example
@~3,3a:abc is @abc modified by ~3,3a format conversion.
When the inserted value is a list, the conversion is distributed
over the elements individually. Otherwise it applies to the
entire item.
* eval.c (fmt_tostring, fmt_cat): Take additional format
string argument. If it isn't nil, then do the string
conversion via the fmt1 function rather than tostring.
(do_format_field): Take format string argument, and
pass down to fmt_cat.
(format_field); Take format string argument and pass down
to do_format_field.
(fmt_simple, fmt_flex): Pass nil format string argument to
fmt_tostring.
(fmt_simple_fmstr, fmt_flex_fmstr): New static functions,
like fmt_simple and fmt_flex but with format string arg.
Used as run-time support for compiler-generated quasilit code
for cases when format conversion specifier is present.
(subst_vars): Extract the new format string frome each
variable item. Pass it down to fmt_tostring, format_field
and fmt_cat.
(eval_init): Register sys:fmt-simple-fmstr and sys:flex-fmstr
intrinsics.
* eval.h (format_field): Declaration updated.
* lib.c (out_quasi_str_sym): Take format string argument.
If it is present, output it after the @, followed by
a colon, to reproduce the read notation.
(out_quasi_str): Pass down the format string, taken
from the fourth element of a sys:var item of the quasiliteral.
For simple symbolic items, pass down nil.
* match.c (tx_subst_vars): Pass nil as new argument of
format_field. The output variables of the TXR Pattern
language do not exhibit this feature.
* parser.l (FMT): New pattern for matching the format
string part.
(grammar): The rule which recognizes @ in quasiliterals
optionally scans the format notation, and turns it
into a string attached to the token's semantic value,
which is now of type val (see parser.y remarks).
* parser.y (tokens): The '@' token's %type changed
from lineno to val so it can carry the format string.
(q_var): If format string is present in the @ symbol,
then include it as the fourth element of the sys:var
form. This rule handles braced items.
(meta): We can no longer get the line number from the @
item, so we get it from n_expr.
(quasi_item): Similar to q_var change here. This handles
@ followed by unbraced items: symbols and other expressions.
* stdlib/compiler.tl (expand-quasi-mods): Take format
string argument. When the format string is present,
then generate code which uses the new alternative
run-time support functions, and passes them the format
string as an argument.
(expand-quasi-args): Extend the sys:var match to extract
the format string if it is present. Pass it down to
expand-quasi-mods.
* stdlib/match.tl (expand-quasi-match): Add an error case
diagnosing the situation when the program tries to use
a format-conversion-endowed item in a quasilit pattern.
* stream.[ch] (fmt1): New function.
* tests/012/quasi.tl: New tests.
* txr.1: Documented.
* lex.yy.c.shipped, y.tab.c.shipped: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (ctx_name): Do not report just the car
of the form. If the form starts with three symbols,
list those; if two, list those.
* stdlib/compiler.tl (expand-defun): Set the
defun form as the macro ancestor of the lambda,
rather than propagating source location info.
Then diagnostics that previously refer to a
lambda will correctly refer to the defun and
thank to the above change in eval.c, include
its name.
* stdlib/pmac.t (define-param-expander):
A similar change here. We make the define-param-expander
form the macro ancestor of the lambda, so that
diagnostics agains tthe lambda will show that
form.
|
|
|
|
|
|
|
|
|
| |
* eval.c (me_flet_labels): Create a synthetic
macro ancestor form which is (labels <name>)
or (flet <name>) so the function name, location
and type of binding can be traced from the
lambda expression. This will be useful to the
:trace parameter macro that is coming.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The DARG object type (dynamic args) is used in a few places.
It has no safe accessors that do type checks and is
directly accessed for efficiency. We need some modicum of
safety when is is planted into the environment of functions,
because those are mutable.
* eval.c (do_args_apf, do_args_ipf, do_callf): type check
the dargs object from the function to be DARG before
accessing it.
* struct.c (method_args_fun, umethod_args_fun): Likewise.
|
|
|
|
|
|
|
|
|
| |
* eval.c (do_progf, progf): New static functions.
(eva_init): Register progf intrinsic.
* tests/012/callable.tl: New test.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.[ch] (do_juxt, juxtv): Functions removed.
* eval.c (do_callf): New static function.
Implements callf without consing up an
argument list with juxt which is then applied
to the function. It's all done with a loop
which builds args on the stack.
(callf): Rewritten to use do_callf. We have
to convert the function list to dynamic
args, but that is more compact than all the
consing done by the removed juxt implementation.
(juxt): New static function: implemented trivially
using callf and list_f.
(eval_init): Change registration from removed juxtv
to juxt. Going forward, I won't be using the v
suffix on functions. That should only be used when
two versions of a function exist: one which takes
vargs, and one which takes C variable arguments
or something else like a list. Example: format
is a variadic C function with a ... in its
argument list. formatv takes a varg and is the
main implementation. vformat takes a va_list.
Leading v is the standard C convention, like
vsprintf. trailing v is the TXR convention for
a function that takes vargs, but only if it is
an alternative to one which doesn't.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (noexpand_s): New symbol variable, holding
sys:noexpand symbol.
(do_expand): When a (sys:noexpand X) form is seen, then
produce the expansion X without recursing into it; in other
words, sys:noexpand is like quote, but against expansion.
(noexpand): Static function.
(eval_init): Initialize noexpand_s. Register noexpand
as intrinsic function.
* txr.1: Document noexpand function.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (loadv): Rebind *expand-hook* to its current
value, like we do with *package*.
* match.c (v_load): Likewise.
* stdlib/compiler.tl (compile-file-conditionally):
Likewise.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (special_operator_p): Do not return t for certain
symbols that are wired to error-throwing functions in the
table, whose purpose it is to detect certain unexpanded
syntax that is handled internally by the expander.
* txr.1: Documentation udpated in several places to clarify
that certain operators are not special operators.
Also expander-let is reclassified from Macro to Ooerator.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The expander-let mechanism wants to be more tightly integrated
into the expander than a macro. The reason is that the macro
makes an explicit call to the expander. But the expansion it
returns will be processed again by the expander.
In the tightly integrated expander-let, we can avoid this;
the expander can assume that the function which processes
expander-let completely processes it and consequently can
be tail called. All in all, since the expander is written in
C, a utility which is this close to the heart of the expander
should be implemented together with it in C.
* eval.c (expander_let_s): New symbol variable.
(expand_expander_let): New function.
(do_expand): Tail call expand_expander_let when encountering
a form headed by the expander-let symbol.
(eval_init): Initialize expander_let_s variable with interned
symbol. Also wire it into the special op table as an error
entry, similarly to macrolet and a few others.
* autoload.c (expander_let_set_entries,
expander_let_instantiate): Static functions removed.
(autoload_init): Autoload registration for expander-let module removed.
* stdlib/expander-let.tl: File removed.
Also, it should be noted that the the expander-let macro
in this file has a a tiny bug: it refers to a sys:dv-bind
symbol which should have been sys:dvbind. That means it is
evaluating the (sys:dvbind ...) forms, which means it
binds special variables twice: once in that evaluation,
and then again in progv.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When expanding a form with macroexpand-1 or macroexpand,
and an expand hook is in effect, we must call the hook.
Otherwise macrology that relies on macroexpand or
macroexpand-1 might not work with expander-driven syntax.
I'm running into not being able to, for instance, use
the swap macro on a pair of infix expressions because
of this. macroexpand-1 must behave like the real macro
expander.
eval.c (do_macroexpand_1): After looking up whether the
form is a macro, pass it through the hook if it is
defined. If the hook transforms the code, then iterate
on this. We pass the form through the expand hook even
if it is not a macro call, and classify it based on
whether is a function call, dwim brackets form or other,
careful not to pass down special operators.
|
|
|
|
|
|
|
|
|
|
|
| |
It turns out we need this for infix.
* eval.c (do_expand): Call the expand hook for
forms headed by the dwim operator, passing that
operator symbol as the type indicator.
* txr.1: Document this and also that the
expand hook doesn't receive symbol macros.
|
|
|
|
|
|
|
|
|
|
| |
There isn't an obvious use for calling the
expander hook for symbolic forms that are
macros. (Especially while not calling it
for symbolic forms that are not macros.)
* eval.c (do_expand): Do not call the expand
hook for symbol macro forms.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (do_expand): Do not expand the arguments of a
function call prior to checking for and dispatching
the expand hook. The expand hook may rewrite the
entire form and the arguments, so that those expansions
are then thrown away. Not only is it wasteful to
calculate them but possibly wrong. A form that is
rewritten by a hook may have strange syntax, such that
the hook itself will get confused if it is unleashed
recursively on the constituent fragments of the syntax.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Here we fix bugs in expand-hook-combine, imrprove the tests
and make different recommendations in the manual about hook
order.
* eval.c (expand_hook_combine_fun): Fix incorrect tests
which cause the next function to be ignored.
* tests/011/exphook.tl: (pico-style-expand-hook): Needs tweak
to evaluate constantp using standard expansion (without
pico-style), so that pico-style can nest with ifx in either
order.
(pico-style): Now when we call expand-hook-combine
we give the new hook first, and the existing one next.
This behavior makes more sense as a default go-to strategy
because it gives priority to the innermost hook-based macro,
closest to the code.
(infix-expand-hook, ifx): Add test cases which test nesting of
hook-based macros.
* txr.1: Opposite recommendation made about chaining of
expand hooks: new first, fall back on old.
Example adjusted.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This fixes nuisance diagnostics from constantp, such as when
invalid forms are given. An example is (constantp '(1)).
* eval.c (no_ub_warn_expand): New name for previous
no_warn_expand function.
(no_warn_expand): Rewritten to muffle all warnings, and
call no_ub_warn_expand. The constantp function continues
to call no_warn_expand.
(eval_init): Retarget expand intrinsic to no_ub_warn_expand,
to preserve its documented behavior. The only function which
currently uses no_warn_expand is constantp.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This function provides a functional combinator that takes
the responsibility of combining expand hooks.
* eval.c (expand_hook_combine_fun, expand_hook_combine):
New static functions.
(eval_init): Register expand-hook-combine intrinsic.
* tests/011/exphook.tl: New file.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (expand_hook_s): New symbol variable.
(do_expand): Check for expand hook in several places and
call it: symbol macros, macros, functions, and
forms that not confirmed function calls.
(eval_init): Initialize new symbol, and
register the *expand-hook* special variable.
* eval.h (expand_hook_s): Declared.
(expand_hook): New macro.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register keep intrinsic.
* lib.[ch] (keep): New function.
* stdlib/compiler.tl (compiler comp-fun-form): Transform
two argument keep to keepqual.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We need a remove function that doesn't have an equality
suffix, analogous to member, pos, count.
* eval.c (eval_init): Register remove intrinsic.
* lib.[ch] (remov): New function.
Named this way to avoid clashing with the ISO C remove
function in <stdlib.h>.
* tests/012/seq.tl: New tests.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
There is a general trend in TXR Lisp to use a nice name for
the variant of a function which uses equal equality.
With the case macros, we have to use casequal, ecasequal,
ecasequal or ecasequal*. Let's introduce synonyms for these:
case, case*, ecase and ecase*.
* eval.c (case_s, case_star_s): New symbol variables.
(me_case): Check for case_star_s also to determine whether
we have a "star" macro.
(eval_init): Initialize symbol variables, and register
case, case*, ecase and ecase* intrinsics.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
| |
* eval.c (me_letrec): New function.
(eval_init): Register letrec intrinsic macro.
* tests/012/let.tl: New file.
* txr.1: Documented, and also referenced from mlet.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register iterp intrinsic.
* lib.[ch] (iterp): New function.
* tests/012/iter.tl: New tests.
* txr.1: Document iterp. Update documentation for iter-more,
iter-item and iter-step to more precisely identify which
objects are valid arguments in terms of iterp and additional
conditions, and that other objects throw a type-error
exception. Fix wrong references to iter-more under
documentation for iter-item. Removed obsolete text specifying
that iter-step uses car on list-like sequences, a dubious
behavior removed in the previous commit.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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/comp-opts.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 bumped to 2025.
|
|
|
|
| |
* eval.c (map_common): use the all_zero_init macro, defined
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Bind new map symbol to the same function
as mapcar.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We introduce a mapfun argument to these functions so that they
can additionally transform the accumulated values.
The keep-keys-if function is now implemented through the same
helper function as keep-if but with the mapfun argument
defaulting to a copy of the keyfun argument.
* eval.c (eval_init): Update registrations of remove-if,
keep-if and keep-keys-if to new arities of C functions.
* lib.c (rem_if_impl): Implement new optional mapfun
parameter.
(remove_if, keep_if): Add mapfun parameter.
(keep_keys_if): Implement via rem_if_impl, and add
mapfun argument. We do the defaulting of keyfun here,
so that we can then use that argument's value to default
mapfun.
* lib.h (remove_if, keep_if, keep_keys_if): Declarations
updated.
* tests/012/seq.tl: Couple of test cases exercising mapfun
argument of keep-if and remove-if.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Iterator rewinding is only used by the three functions isec,
isecp and diff, which can easily just re-initialize the
iterator.
* lib.c (seq_iter_rewind): Static function removed.
(seq_iter_init_with_info): Remove support_rewind argument, and
adjust all code referencing it on the assumption that it's zero.
(seq_iter_init_with_rewind): Static function removed.
(seq_iter_init, iter_begin, iter_reset, nullify, find, rfind):
Drop last argument from seq_iter_init_with_info.
(diff, isec, iescp): Use seq_iter_init rather than
seq_iter_init_with_rewind. Instead of seq_iter_rewind, just
reinitialize the iterator.
* lib.h (seq_iter_init_with_info): Declaration updated.
* eval.c (tprint): Drop last argument from seq_iter_init_with_info.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
zip and transpose should allow non-character data
when the leftmost column is a string, falling back
on making lists, like seq_build.
We can't use seq_build as-is because of the special
semantics of transpose/zip with regard to strings.
We introduce a "strcat" variant of seq_build
for this purpose.
* lib.c (seq_build_strcat_add): New static function.
(sb_strcat_ops): New static structure like sb_str_ops,
but with seq_build_strcat_add as the add operation,
which allows string arguments to be appended to the
string rather than switching to a list.
(seq_build_strcat_init): New function.
* lib.h (seq_build_strcat_init): Declared.
* eval.c (zip_strcat): New static function; uses
seq_build_strcat_init.
(zipv): Only recognize strings specially; all else goes
through the existing default case.
Strings use zip_strcat.
* tests/012/seq.tl: New test case.
* txr.1: Describe special semantics of zip/tranpose;
previously only documented in one example.
Clarify that the rows are only sequences of the
same kind as the leftmost column if possible,
otherwise lists. Remove text which says that it's an error
for the other columns to contain non-string, non-character
objects if the leftmost column is a string.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (zip_fun): Renamed to seq_like.
(zipv): Follow rename of zip_fun.
(eval_init): Register seq-like intrinsic.
* tests/seq.tl: Some tests for make-like and seq-like,
revealing a difference: make-like needs to be
rewritten to use seq_build.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): New intrinsic functions find-maxes and
find-mins.
* lib.[ch] (find_maxes, find_mins): New function.
* tests/012/seq.tl: New tests.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): register intrinsics wheref, whereq,
whereql and wherequal.
* lib.c (wheref_fun): New static function.
(wheref, whereq, whereql, wherequal): New functions.
* lib.h (wheref, whereq, whereql, wherequal): Declared.
* tests/012/seq.tl: New tests.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
These functions find random cyclic permutations.
* eval.c (eval_init): Register cshuffle and cnshuffle
intrinsics.
* lib.c (nshuffle_impl): New static function, formed out of
nshuffle.
(nhuffle): Now wrapper around nshuffle_impl.
(shuffle): Also wraps nshuffle_impl rather than nshuffle.
(cnshuffle, cshuffle): New funtions.
* lib.h (cnshuffle, cshuffle): Declared.
* txr.1: Documented new functions. Also added warning
about limitations on permutation reachability in relation
to PRNG state size.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* combi.c (permi_get, permi_peek): Fix algorithm.
(permi_mark): New static function.
(permi_ops): Reference permi_mark for mark operation.
(permi): Initialize it->ul.next to nao as required by
new get/peek algorithm.
(rpermi_get, rpermi_peek): Fix algorithm.
(rpermi_mark): New static function.
(rpermi_ops): Reference permi_mark for mark operation.
(rpermi): Initialize it->ul.next to nao as required
by new get/peek algorithm.
(combi_get, combi_peek, combi_mark, combi_clone): New static
functions.
(combi_ops): New static structure.
(combi): New function.
(rcombi_get, rcombi_peek, rcombi_mark, rcombi_clone): New
static functions.
(rcombi_ops): New static structure.
(rcombi): New function.
* combi.h (combi, rcombi): Declared.
* tests/015/comb.tl: New tests.
|
|
|
|
|
|
|
|
|
|
|
| |
* combi.c (rpermi_get, rpermi_peek, rpermi_clone): New static
functions.
(rpermi_ops): New static structure.
(rpermi): New function.
* combi.h (rpermi): Declared.
* eval.c (eval_init): Register rpermi intrinsic.
|
|
|
|
|
|
| |
* eval.c (eval_init): Register copy-iter intrinsic.
* lib.[ch] (copy_iter): New function.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
| |
In a recent commit, the defaulting of the separator in quasiliteral
variable formatting was moved down into the fmt_cat routine.
One stray case remains in subst_vars.
* eval.c (subst_vars): A call to fmt_cat is specifying a separator
value consisting of a single space. This is wrong, preventing
fmt_cat from defaulting it in different ways according to type.
|
|
|
|
|
|
| |
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The motivation here is an upcoming change in which
we will support the separator modifier for buffers
and strings. Currently, it does nothing. If we write
`@{a ":"}`, and a is a buffer or string, the separator
is ignored. We don't fix that in this commit, but
we fix the problem that some higher level formatting
functions are defaulting the separator to " " (single
space) and passing it down. We want to control the
defaulting based on the type of the object in one place.
* eval.c (fmt_cat): Do not assume here that sep has been
defaulted; do the defaulting to space here.
(format_field, fmt_flex): Initialize the separator to nil,
not space. If no separator occurs among the modifiers,
it gets passed down as nil through to fmt_cat.
(fmt_simple): Don't default the sep argument to space;
pass it through to do_format_field which will pass it down
to fmt_cat.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The pprint semantics of buffers is that the
raw bytes are dumped into the stream. This is poor.
It was hastily designed based on analogy with
strings, which pprint by just sending their contents
to the stream; but for strings this is justified
because they represent text.
We also fix the semantics of buffer values being
rendered by quasiliteral notation. Currently, the
are treated as sequences, and so they explode into
individual decimal integers.
* buf.c (buf_pprint): Print the bytes as pairs of
lower-case hex digits, with no line breaks.
In 294 compatibility or lower, put out bytes as before.
* eval.c (fmt_cat): When not in 294 compatibility
mode, treat a buffer object via tostringp, which
will render it to hexadecimal via buf_pprintf.
In compatibility mode, treat it as before, which is
as a sequence: the individual values of the buffer
are converted to text, thus decimal values in the
range 0 to 255, catenated using the given separator.
* tests/012/readprint.tl: New tests.
* txr.1: Documented. Also expanding on what pretty printing
means in TXR.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
| |
* lib.[ch] (lcons_force): New function.
* eval.c (eval_init): Register lcons-force intrinsic.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (MAP_ALLOCA_LIMIT): New preprocessor symbol.
(map_common): If the number of args is greater than
MAP_ALLOCA_LIMIT, then allocate the array of seq_iter_t
structures from chk_malloc rather than alloca.
In case an exception might be thrown during the execution
of this function, we bind that memory to a buf object.
If we return normally, we call the new function buf_free
to release it. Otherwise we rely on the garbage collector.
* buf.[ch] (buf_free): New function.
* tests/012/seq.tl: Test case which hits this behavior.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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 (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.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|