| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
There has been interest in the community in a threading macro;
a triviality which which applies the opip syntax to a value.
Eschewing unusual glyph combinations like ->> and whatnot,
I've chosen the English word flow for this.
* share/txr/stdlib/op.tl (flow): New macro.
* lisplib.c (op_set_entries): Set up autoload for flow.
* txr.1: Documented.
* share/txr/stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* parser.c (repl): Set the rcfile variable to nil if
opt_noprofile is true, to suppress reading it.
* txr.c (op_noprofile): New global variable.
(help): Add help text.
(txr_main): Recognize noprofile option and set variable.
* txr.h (opt_noprofile): Declared.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/txr-case.tl (txr-case-impl): If the input
is a stream, then convert it to a lazy list of lines, so that
running multiple functions against it produces sane,
backtracking behavior, like a @(cases) construct.
* tests/011/txr-case.expected: Updated.
* tests/011/txr-case.txr: Now actually contains a test case
for txr-case.
* txr.1: Address an issue reported by Paul A. Patience: the
input to match-fun, txr-if and txr-when may be a stream. That
has always been the case in the implementation. Also document
that when the input is a single string, it is treated as a
list. Document the new requirement in txr-case that a stream
is converted into lazy list of lines.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The issue, reported by Paul A. Patience, is that
code like (< 1 "abc") is successfully producing a result.
The root cause is that 1 is an iterable object, and so
is treated as a sequence opposite to the "abc" operand.
We should allow only true sequences in this situation.
* arith.c (seq_lt_compat_check): New static function. Checks
that neither of two sequences is SEQ_NOTSEQ or SEQ_HASHLIKE.
(seq_lt, seq_le): Use seq_lt_compat_check to reject dubious
inputs.
* txr.1: Minor wording change in the related documentation,
removing a gratuitous adjective.
* tests/016/arith.tl: Inequality tests.
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (fds_subst_nosave): New static function.
(fds_clobber): New static function. Like fds_swizzle,
without the saving.
(open_subprocess, run): Use fds_clobber instead of fds_swizzle
in the child process. It makes no sense to use fds_swizzle,
which saves duplicates of the old descriptors,
if fds_restore is not going to be called.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In all cases in which we control fork and exec, we should be
doing the fds_swizzle setup in the child process. This has
several benefits. We do not disturb the file descriptor layout
of the parent. We don't have to set up a catch to do the
cleanup. We don't have to do the clean-up in the child either;
but just let it terminate.
* stream.c (struct save_fds): New members subin, subout and
suberr to hold the substitute file descriptors. The reason for
this is so that we can calculate these in the parent process
so that all the error checking is done in the parent and and
carry them over to the child somehow. This structure is the
natural place for that.
(fds_getfd): New static function: just does the job of
fetching and validating the file descriptor from the given
stream: the first part of fds_subst. This will be done in the
parent.
(fds_subst): Now just does the substitution using a given file
descriptor. Done in the child. Some variable renaming here; a
better name for fd_orig is fd_sub, the substitute descriptor.
(fds_prepare): New function: called in the parent process,
it obtains the three file descriptors from the streams.
(fds_swizzle): Just do fd_subst with the ready-made file
descriptors, not dealing with the streams. Called in the
child.
(open_command): Add fds_prepare call that is now needed.
(open_subprocess, run): Get rid of catch frame. Just call
fds_prepare where fds_swizzle was previously called, and only
call fds_swizzle in the child process.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Via macros, atoms can sneak into a quasiliteral which then
blow up because they get treated as strings without being
converted.
Example:
(defmacro two () 2)
`@(two)xyz` -> ;; error
The expansion produces the invalid form, in which the 2
is subsequently treated as a string.
(sys:quasi 2 "xyz")
On the other hand, symbol macros don't have this problem:
(defsymacro two 2)
`@{two}xyz` -> "2xyz"
The reason is that the (sys:var two) syntax will expand to
(sys:var 2), and not 2.
The straightforward, consistent fix is to ensure that the
first case will also go to (sys:var 2).
* eval.c (expand_quasi): If the expanded form is an atom which
is not a bindable symbol, wrap it in a sys:var.
* tests/012/quasi.tl: Test cases added.
Also adding a compilation test for this file, cribbed from
patmatch.tl.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is a regression that was introduced in 191. The change in
191 was trying to prevent defsymacro from being expanded
immediately by the expander except in 190 compatibility.
Unfortunately, this caused the whole defsymacro block not to
be entered unless in 190 compatibility, otherwise taking the
common exit which returns form_ex, containing the expanded
replacement form.
* eval.c (do_expand): Split up implementation of defvarl and
defsymacro. In the defsymacro block, do not do any expanding
on entry. Absent of compatibility mode, we just do some sanity
checks and pass the entire form through. In 262 compatibility,
we do the expansion to obtain form_ex. Then all the previous
compat logic is wrapped in that block.
* tests/011/macros-3.tl: Add a test case which confirms that
symbol macros are lazily expanded. Weakness in the test suite
is how these regressions creep in.
* txr.1: Improve defsymacro documentation, spelling out
clearly that the unexpanded replacement form is associated
with the symbol. Eliminate obsolescent text suggesting that
defsymacro is evaluated at macro time.
|
|
|
|
|
|
|
|
| |
* txr.1: When writing up the compatibility notes for version
190, I missed the change that defmacro and defsymacro were
switched away from instant evaluation by the macroexpander.
That change introduced a regression which I just noticed, and
this is noted also.
|
|
|
|
|
| |
* txr.1: mkstemp: fix formatting problem in heading,
and incorrect reference to mkdtemp with bad grammar.
|
|
|
|
|
|
|
|
| |
* stream.c (fds_subst): Check that stream_fd returns a
non-integer; if so, put out a more meaningful diagnostic,
rather than allowing c_num to generate a "nil is not an
integer" error. Also, let's incorporate the self string into
the existing failed dup diagnostic.
|
|
|
|
|
|
| |
* genvim.txr (bvar): Add tl_regex as a constituent.
This occurs in quasiliteral pattern matching syntax,
like `...@{a #/regex}...`.
|
|
|
|
|
|
|
|
|
|
| |
* unwind.c (uw_unwind_to_exit_point): The error reporting
relies on the *stderr* stream, but that stream may be bound in
some funny way in a context where an exception has happened,
without anything around it to restore that during unwinding.
Before diagnosing, we should reset the dynamic environment to
the top level, so that the global values of all dynamic
variables are revealed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The *stdnull* stream has been purely a stream-level
abstraction. To make it useful for redirecting real file
descriptors around the execution of external programs,
we endow it with the ability to open /dev/null when it is
asked to provide its file descriptor.
* stream.c (struct dev_null): New structure.
(dev_null_close, dev_null_get_fd, dev_null_get_prop): New
static functions.
(null_ops): Wire in the above functions instead of null_close,
null_get_fd and null_get_prop. We need new functions because
null_close and others do not belong to just the null stream;
they are base operations used by other streams as default
implementations for some kinds of unimplemented functions.
(make_null_stream): Alocate a struct dev_null instead of a
struct strm_base. Set the fd to -1.
* txr.1: Documented.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/pic.tl (expand-pic-num): format can now do
everything internally that is required of a 0####.## type
pattern; we don't have to generate the if logic with the
gensym.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/pic.tl (expand-pic-num): The ##...## string
that indicates an overflowing field can be created by the
macro and inserted into the code as a literal object, rather
than inserted as a mkstring call which calculates it run time
each time the code is executed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
There are a number of issues, such as left adjustment not
working and such. This needs a better treatment from the
requirements level, through to a set of test cases.
* stream.c (max, min): Macros macros added, in their usual
form.
(vformat_num): Implement new rules which suppress the zero and
space characters used in place of a sign if they overflow the
field width.
(formatv): Clamp integer precision field to width - 1 for
integers, for consistency with floating-point handling.
For floating-point values under ~a and ~s, do not force
the second stage precision to width - 1; only clamp it
if it is greater.
* format.tl: Numerous new tests.
* txr.1: Significant redocumenting of this area. The handling
of numbers is described as a two stage process, clarifying the
changing role of "precision" in the two stages.
|
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (formatv): The - precision option character
produces a "sign" that is a zero. If this is used with leading
zeros, it will avoid generating a space. The requirements can
use improvement here, but one step at a time.
* tests/018/format.tl: Some tests.
* txr.1: Documented.
|
|
|
|
| |
* txr.1: non-negative changed to nonnegative.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Bumped.
* txr.vim, tl.vim: Regenerated.
* protsym.c: Likewise.
* y.tab.c.shipped: Regenerated. Good catch! forgot to do this
for most recent change to parser.y.
|
|
|
|
| |
* txr.1: Examples added.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/pic.tl (pic): Refactor string compilation
code into local function which has access to the overall
argument list. Recognize the quasiliteral case and translate
by compiling all the string parts, then forming a recombined
quasiliteral where the compiled parts are substituted.
* tests/018/format.tl: test case for this.
* txr.1: Documented.
|
|
|
|
|
|
|
| |
* txr.1: The notation [ a | b | c | .. ] is used throughout
the document, but the Conventions paragraph describes only
square brackets around a single optional element. The notation
is now officially codified.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/pic.tl (expand-pic-num, expand-pic, pic):
Allow ### to be followed by a single !. This is not counted
toward the field width.
* tests/018/format.tl: Cover with some tests.
* txr.1: Doc updated.
|
|
|
|
|
|
|
|
| |
* tests/018/format.tl: Add tests which combine overflow
flagging with +/-. The space generated by - contributes to
overflow.
* txr.1: Clarify overflow issue in documentation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The recent commit 225ff2fa2fdb9e5169db5e2c06dc3b0053b775bb
titled "errors: avoid premature release of deferred warnings."
obviates the need for dealing with noise when detecting
errors from test cases.
* patmatch.tl: Remove macro-time-let around several
test cases.
* tests/012/ifa.tl: Likewise.
* tests/common.tl (macro-time-let): Macro removed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/pic.tl (expand-pic-num): Bug: when a field
overflows, the (rest ...) call truncates the leftmost digit.
A failing test case is (pic "#.#" 12) which produces "2.0"
instead of "12.0". Firstly, we only need that logic at all in
the zero padding case. When the number is positive, we stick
in the + request, so we are sure to get a + character. The
rest call then predictably chops off the + rather than a
digit.
(pic-join-opt): Fix two bugs here in the string-string combine
case: using s2 instead of s1, and not splicing in rest.
(expand-pic, pic): Implement tightening for escape sequences.
If ~ is not followed by anything, or not followed by the
documented characters for escaping, it is erroneous.
* format.tl: Battery of new tests.
|
|
|
|
|
|
|
|
| |
* tests/common.tl (error-to-sym): Catch warnings, and convert
to :warning symbol.
(vtest): Support new kinds of expected value: :warning.
The test is satisfied if it throws a warning at expansion time
or during evaluation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We don't want to be unconditionally releasing deferred
warnings when error exceptions occur in evaluation or
compilation. The reason is that the error might be handled,
for instance by a speculative expansion. Then unwanted noise
occurs, because deferred warnings have been released
prematurely.
* eval.c (eval_exception): Do not call
uw_release_deferred_warnings here.
(error_trace): But do call uw_release_deferred_warnings here,
before printing anything else. We want to preserve the
behavior that when error information is actually being
printed to a stream, any deferred warnings are dumped first
because they might pertain to the error. (I may revisit
this requirement; perhaps deferred warnings rarely, if ever,
pertain to an error).
* share/txr/stdlib/error.tl (compile-error): Do not dump
deferred warnings unconditionally. Only dump them if we
are also printing the error message to stderr. Secondly, do
not output the error message at all, unless there is no
handler for the error.
|
|
|
|
|
|
| |
* txr.1: pic macro documented.
* share/txr/stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (formatv): Do not recognize multiple leading zeros
as a single one; once the zero flag is set, if another zero is
seen, it must be treated as one of the digits specifying the
precision value. New requirement: before processing a format
specifier, check for the situation that the leading zero
has been specified, but no precision. Convert this situation
to that of a precision of zero being given, with no leading
zero.
* txr.1: Document the ambiguity around the leading zero and
how it is being handled when only the leading zero flag is
given, and no actual precision. Add a note about what happens
when zero precision is specified in ~a in conjunction with
a floating-point value. Misspelled "pas" word fixed.
|
|
|
|
|
|
|
|
|
| |
* lisplib.c (pic_instantiate, pic_set_entries): New static
functions.
(lisplib_init): Register autoloading of pic.tl module via new
functions.
* share/txr/stdlib/pic.tl: New file.
|
|
|
|
|
|
|
|
|
|
|
| |
This fixes the problem that (doc 'wh[Tab] will not
complete the macro name while.
* parser.c (find_matching_syms): Recognize the kind context
symbol 'Q', under which a which a macro or operator are
eligible for completion.
(provide_completions): Calculate kind as 'Q' if the previous
character is a ' quote or ^ backquote.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I think this is a nicer treatment of the libffi situation.
We only need the type descriptors for arrays, structs and
unions if they are ever used as return values or arguments in
a libffi call descriptor. We don't have to waste time and
memory allocating them otherwise, and in the case of arrays,
we can allocate the full descriptor that includes every
member, when that is needed.
Structures that are involved in calls, but are passed and
returned by pointer, not directly, will not have this
cruft instantiated at all.
* ffi.c (struct txr_ffi_type): New function pointer member calcft.
This specifies the lazy initialization funtion for the libffi
stuff. Only arrays, structs and unions have a non-null pointer
here. If the pointer is null, it indicates that the type
doesn't require lazy initialization: either because it was
initialized eagerly, or because lazy initialization was
already done.
(ffi_get_type): If the type has a calcft, then call it and
null it out, to ensure tffi->ft.
(ffi_struct_clone): Do not deal with ft and elements here at
all.
(ffi_union_clone): Short-lived static function removed,
because it is identical to ffi_struct_clone again.
(ffi_struct_calcft, ffi_union_calcft, ffi_array_calcft): New
static functions, implementing different strategies for
calculating the libffi elements array. For unions, I invented
this strategy: we pretend that a union is atually a structure
made of repetitions of the type which has the strictest
alignment. This is uncharted territory because libffi doesn't
support unions at all.
(make_ffi_type_struct, make_ffi_type_union,
make_ffi_type_array): Do not deal with tf or elems, except for
deleting them if we are re-initializing the object. Leave
these pointers null. Install the appropriate calcft function.
(ffi_array_clone): Function removed; the array type can use
ffi_simple_clone, since the clone function doesn't deal with
the libffi stuff. Why was that needed until several commits
ago? Because, subject to HAVE_FFI, it performed the assignment
ft->elements = copy->elements.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* arith.c (nary_op_keyfun): Static function removed.
(nary_op_seq, nary_op_seq_keyfun): New static functions.
(sumv, prodv): Static functions removed.
(sum, prod): Reimplement using nary_op_seq and
nary_op_seq_keyfun. Conversion of sequence to
list smuggled via args is gone.
* tests/016/arith.tl: new sum and prod tests.
* txr.1: Note about sum and prod taking an iterable sequence
added.
|
|
|
|
|
|
|
| |
* lib.c (reduce_left): Use sequence iteration instead of list
operations.
* txr.1: Add a note to the documentation.
|
|
|
|
|
|
|
|
|
| |
When #; is used to comment out syntax containing #S, an
attempt is made to instantiate a structure using nil as the
type, and an exception occurs.
* parser.y (hash, struct, tree): Check for parser->ignore and
produce nil instead of making any of these objects.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/ffi.c (deffi): Fix misnamed variable.
The second value coming from sys:analyze-argtypes is the number of fixed
arguments, not the number of variadic arguments. Furthermore, if this
number is equal to nargs, we were supposed to have been passing nil
instead to ffi-make-call-desc, which indicates the ordinary non-variadic
function. We were always always passing a non-nil value, so always requesting
variadic. That is fixed now thanks to the change to ffi_make_call_desc.
* ffi.c (ffi_make_call_desc): Register the function as variadic if
either nfixed is specified as nil, or if it is equal to ntotal.
* txr.1: Document the convention change for ffi-make-call-desc.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit tries to address a flaw in our use of libffi.
When we construct a structure type, we do not fill in the
"elements" array of the libffi type to describe every element.
Instead we calculate the size and alignment ourselves.
This breaks when passing small structures by value on some
platforms.
There are some areas where we are still winging it.
We allow passing of arrays by value, which are simulated using
FFI structure types. To allocate the descriptor earnestly
for such an object means allocating an array of ffi_type
pointers as large as the array, which is wasteful. So we cap
it to 20. This 20 comes form the idea that anything bigger
than a 16 byte structure is passed on the stack rather than in
registers.
For unions, we choose the largest member and inform libffi
of its type.
* ffi.c (struct txr_ffi_type): elements member changes to
from array of 1 to pointer.
(ffi_type_struct_destroy_op): Consolidate HAVE_LIBFFI code.
Don't bother setting tft->ft->elements to null.
Free tft->elements.
(ffi_struct_clone): Clone the elements array.
(ffi_union_clonse): New static function. Unions need their own
clone function now because their elements array has a size not
related to the number of members. It contains two pointers,
including the null terminating one.
(make_ffi_type_struct): Allocate the elements array, and fill
it. We wing it around bitfields, which libffi doesn't support.
This will be revisited, but it's likely a bad idea to be
passing bitfield-endowed structures by value.
(make_ffi_type_union): Allocate the elements array to a fixed
size of two pointers. Fill it in with the largest member's
type.
(ffi_array_clone): Clone the elements array, which is up two
20 pointers plus a null terminator.
(make_ffi_type_array): Allocate the elements array up to 20
elements plus null pointer, and fill it with repetitions of
the element libffi type.
|
|
|
|
|
|
|
| |
* ffi.c (make_ffi_type_struct, make_ffi_type_union): When we
are replacing the existing type, if HAVE_FFI is true, we
must free the tft->ft object before clobbering the tft with
zeros.
|
|
|
|
|
|
|
|
|
|
| |
The ffi_type_struct_destroy_op only frees
tft->ft if HAVE_FFI is true. But the object is allocated in
several places without regard for HAVE_FFI.
* ffi.c (ffi_struct_clone, make_ffi_type_struct,
make_ffi_type_union, ffi_array_clone, make_ffi_type_array): Do
not allocate a ffi_type object if HAVE_FFI is false.
|
|
|
|
|
| |
* tags.tl (process-form): Recognize deffi-struct together with
defstruct.
|
|
|
|
|
| |
* tags.tl: bind *read-unknown-structs* to t around
the file walk.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* parser.c (read_unknown_structs_s): New symbol variable.
(parser_common_init): Initialize read_unknown_structs flag
member of the parser structure from the new special variable.
(parse_init): Initialize read_unknown_struct_s variable.
Register the *read-unknown-structs* dynamic variable.
* parser.h (struct parser): New member, read_unknown_structs.
(read_unknown_structs_s): Declared.
* parser.y (struct): Generate the struct literal syntax not
only for quasiquoted structures, but for structures with an
unknown type name, if the read_unkonwn_structs flag is set.
* txr.1: Documented.
* share/txr/stdlib/doc-syms.tl: Regenerated.
* y.tab.c.shipped: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register fill-vec intrinsic.
* lib.c (fill_vec): New function.
* lib.h (fill_vec): Declared.
* tests/010/vec.tl: New file.
* txr.1: Documented.
* share/txr/stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lisplib.c (ffi_set_entries): Autoload for deffi-struct and
deffi-union symbols.
* share/txr/stdlib/ffi.tl (deffi-struct, deffi-union): New
macros.
* txr.1: Documented.
* share/txr/stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The expand function must not muffle all deferred warnings.
That causes the problem that a form like (inc var a.bar) fails
to produce a warning due to bar not being the slot of any
structure. The expand function must only muffle warnings about
undefined functions and variables.
* eval.c (muffle_unbound_warning): New static function.
(no_warn_expand): Use muffle_unbound_warning as handler,
rather than uw_muffle_warning.
* tests/012/struct.tl: Fix two test cases here which test the
expand function using a form that references a nonexistent
slot. These now generate a warning, so we use the slot name b
rather than d, which is defined.
* txr.1: Documented change to expand.
|
|
|
|
|
|
|
| |
* args.c (args_normalize_least): The bug_unless here should be
checking that minfill is not beyond argc->argc. That's the
situation that would cause the loop to overflow the fixed
argument argument storage in args indicated by args->argc.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_cptr_put): If the object is not a cptr, try it as
a carray. This requires the tft to have an eltype, requiring
a change in ffi_type_compile.
(ffi_type_compile): When compiling a parametrized cptr object,
we now look up the type symbol as a FFI type, and store the
result as the tft->eltype. If the symbol is not an FFI type,
then this lookup returns nil. If the eltype is non-nil, then
there is the possibility it can match the element type of a
carray.
* txr.1: Documented.
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_closure_put): Only diagnose a bad object if it's
not nil, otherwise let the null value of p through.
This is useful because there are sometimes C interfaces which
take an optional function pointer, whereby a null value
indicates that the pointer is not specified.
|