summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* doc: grammar under pattern matching.Kaz Kylheku2022-05-171-1/+1
| | | | * txr.1: agreement between "body" and "consist".
* ffi: bugfix: null terminated string as flexible member.Kaz Kylheku2022-05-172-38/+34
| | | | | | | | | | | | * ffi.c (ffi_char_array_get, ffi_zchar_array_get, ffi_wchar_array_get, ffi_bchar_array_get): Rearrange so that we test for tft->null_term first, and not nelem == 0. If nelem happens to be zero, but we are supposed to decode a null-terminated string, we will do the wrong thing and return the null string. (ffi_varray_in): The body can't be conditional on vec being non-nil, because then we do nothing if we don't have a Lisp object, which means we skip the cases when we should decode a null-terminated array. Now if vec is nil, we must guard against calling ffi_varray_dynsize.
* ffi: bugfix: unions are not unconditionally incomplete.Kaz Kylheku2022-05-171-1/+1
|
* New options: --in-package and --compile.Kaz Kylheku2022-05-123-3/+98
| | | | | | | | | * txr.c (help): Mention new options. (do_compile_opt, do_in_package_opt): New static functions. (txr_main): Implement options. * Makefile (COMPILE_TL): Use the options instead of -e. * txr.1: Document.
* expander: new rule for macro-produced function callsKaz Kylheku2022-05-122-1/+136
| | | | | | | | | | | | | | * eval.c (do_expand): When a function call's arguments are expanded and produce a transformation, then if that function call had been produced by a macro, the transformed function call is tried again as a macro. This is necessary because TXR Lisp allows a symbol to be both a function and macro. When a macro-produced function call's arguments are expanded, the macro version of that function may, as a result of the argument transformations, have more opportunities for expansion. * txr.1: New section outlining how macro expansion generally works, with a special focus on this unusual new rule.
* Print ([...] . @var) and ([...] . @(expr)) notation.Kaz Kylheku2022-05-111-2/+11
| | | | | | | | | | | This change fixes objects like (@a @b . @c) being printed as (@a @b sys:var c). This is piggybacked into the logic which renders dotted unquotes. In other words, we are already printing (x . ,y) in that from rather than (x sys:unquote y); we just recognize sys:var, and sys:expr in the same code. * lib.c (obj_print_impl): Recognize dotted metavariables and metaexpressions similarly to dotted unquotes.
* lambda-match: bug: over-strict match in variadic pattern.Kaz Kylheku2022-05-112-1/+15
| | | | | | | | | | | | * stdlib/match.tl (expand-lambda-match): A pattern that is shorter than the maximum number of arguments is augmented with a check ensuring that no fixed arguments are present beyond those that the pattern requires. However, this check must be omitted if the pattern is variadic, because those excess arguments match its tail pattern. * tests/011/patmatch.tl: Cases added.
* Version 275.txr-275Kaz Kylheku2022-05-107-1585/+1632
| | | | | | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date. * txr.vim, tl.vim: Regenerated. * protsym.c: Likewise.
* tests: Cygwin fixes.Kaz Kylheku2022-05-103-14/+18
| | | | | | | | | | | * tests/017/str-s.tl: Use (libc) not nil in with-dyn-lib. * tests/018/forkflush.tl: On Cygwin, produce canned output for first test case, because the real test case produces some DOS line endings that cause a mismatch. * tests/019/load-search.tl: Skip test case involving a directory with bad permissions being in the load search path.
* Support Loongarch.Kaz Kylheku2022-05-102-0/+81
| | | | | | * jmp.S (jmp_save, jmp_restore): Define for Loongarch. * unwind.h (struct jmp): Likewise.
* ffi: fix broken on RISC-V.Kaz Kylheku2022-05-101-1/+1
| | | | | | | | | | | | | | * ffi.c (pad_retval): Remove the special case of zero mapping to zero, which occurs when the return type is void. It's not clear whether this is correct at all, on any platform. It hasn't showed up as a problem until now, but on RISC-V, we have hit a situation in which ffi_call writes a value into that zero-byte space for the void return value, causing that to overwrite values[0]: the first element of the argument array. For reasons not understood, this happens in the qsort test cases in which which the callback function performs a block return. It is strange because the block return is handled entirely in the closure dispatching function.
* Support RISC-V: conditionally.Kaz Kylheku2022-05-102-0/+105
| | | | | | | | | | | | | | | | | | | | | | Everything compiles, and most tests pass. Failing test are: - tests/014/dgram-stream.tl: - tests/017/glob-carray.tl: - tests/017/qsort.tl: The datagram test is not able to bind a UDP socket to a port. On the gcc402 machine of the GCC Compile Farm, attempts bind a UDP socket to any of the ports 1024-65535 all fail with errno 99 (EADDRNOTAVAIL). The FFI test cases are segfaulting. The qosrt.tl case has the problem in the test cases which abort the callback with a return-from. * unwind.h (struct jmp): Define for RISC-V. * jmp.S (DEFUN): Define macro for RISC-V. (jmp_save, jmp_restore): Define for RISC-V.
* linenoise: Ctrl-Z: send SIGTSTP to group, not self.Kaz Kylheku2022-04-281-3/+3
| | | | | | | | | | | | | | | | | | | I realized this issue while implementing Ctrl-Z for the pw (Pipe Watch) program. Sending the SIGTSTP signal just to the calling process is not enough. Only that process gets suspended, which results in a weird behavior. It can be tested like this, for instance: txr | tee file Ctrl-Z must be issued twice: once to sort of suspend txr, and then again to send it to the tee program. Then the job actually suspends and the shell prompt appears. With this fix, the above situation requires only one Ctrl-Z, as expected. * linenoise/linenoise.c (history_search, show_help, edit): Don't raise(SIGTSTP), but kill(0, SIGTSTP) to send the suspend signal to all processes in the process group.
* doc: FFI string types map null pointer to nil.Kaz Kylheku2022-04-261-3/+7
| | | | | | * txr.1: Document the existing behavior that the various FFI string types map between the null pointer and the nil object.
* doc: ffi: document the array-of-1 trick.Kaz Kylheku2022-04-261-0/+62
| | | | | * txr.1: Document the (ptr (array 1 <type>)) trick needed for out or in-out parameters.
* load/@(load): use path_cat.Kaz Kylheku2022-04-252-6/+2
| | | | | | | * eval.c (load): Use path_cat and dir_name instead of ad hoc path munging. * match.c (v_load): Likewise.
* *load-search-dir*: Some tests.Kaz Kylheku2022-04-251-0/+33
| | | | | * tests/019/load-search.tl: Add some cases that explore the load search path.
* New: load can search multiple directories.Kaz Kylheku2022-04-258-19/+131
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (load_search_dirs_s): New symbol variable. (load): Initialize the name variable whose address is passed as the third argument of open_txr_file, which is now an in-out parameter. Pass t for the new search_dirs parameter, so that load benefits from the searching. (eval_init): Initialize load_search_dirs_s and register the *load-search-dirs* special variable. * eval.h (load_search_dirs_s): Declared. (load_search_dirs): New macro. * match.c (v_load): Initialize the variable passed as third argument of open_txr_file. * parser.c (open_txr_file): Take a new argument, search_dirs. If this is t, it tells the function "if the path is not found, then recurse on the *load-search-dirs* variable. Otherwise, if the value is not t, it is a list of the remaining directories to try. The existing parameter orig_in_resolved_out must now point to a location which is initialized. It is assumed to hold the original target that was passed to the load function. The first_try_path is a the path to actually try, derived from that one. Thus, the caller of open_txr_file gets to determine the initial try path using its own algorithm. Then any recursive calls that go through *load-search-dirs* will pass a first argument which is made of the original name, combined with a search dir. (load_rcfile): Pass pointer to initialized location as third argument of open-txr_file, and pass a nil value for search_dirs: no search takes place when looking for that file, which is at a single, fixed location. * parser.h (open_txr_file): Declaration updated. * txr.c (sysroot_init): Initialize *load-search-dirs*. (txr_main): Ensure third argument in all calls to open_txr_file points to initialized variable, with the correct value, and pass t for the search_dirs argument. * txr.1: Documented. * stdlib/doc-syms.tl: Updated. New: load can search multiple directories. * eval.c (load_search_dirs_s): New symbol variable. (load): Initialize the name variable whose address is passed as the third argument of open_txr_file, which is now an in-out parameter. Pass t for the new search_dirs parameter, so that load benefits from the searching. (eval_init): Initialize load_search_dirs_s and register the *load-search-dirs* special variable. * eval.h (load_search_dirs_s): Declared. (load_search_dirs): New macro. * match.c (v_load): Initialize the variable passed as third * argument of open_txr_file. * parser.c (open_txr_file): Take a new argument, search_dirs. If this is t, it tells the function "if the path is not found, then recurse on the *load-search-dirs* variable. Otherwise, if the value is not t, it is a list of the remaining directories to try. The existing parameter orig_in_resolved_out must now point to a location which is initialized. It is assumed to hold the original target that was passed to the load function. The first_try_path is a the path to actually try, derived from that one. Thus, the caller of open_txr_file gets to determine the initial try path using its own algorithm. Then any recursive calls that go through *load-search-dirs* will pass a first argument which is made of the original name, combined with a search dir. (load_rcfile): Pass pointer to initialized location as third argument of open-txr_file, and pass a nil value for search_dirs: no search takes place when looking for that file, which is at a single, fixed location. * parser.h (open_txr_file): Declaration updated. * txr.c (sysroot_init): Initialize *load-search-dirs*. (txr_main): Ensure third argument in all calls to open_txr_file points to initialized variable, with the correct value, and pass t for the search_dirs argument. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* open_txr_file: rename parameters.Kaz Kylheku2022-04-242-20/+20
| | | | | | * parser.[ch] (open_txr_file): spec_file is now called first_try_path. The name parameter is called orig_in_resolved_out. Currently it has just the resolved_out semantics, but that is about to change.
* subprocesses: don't unnecessarily flush *stdout*.Kaz Kylheku2022-04-241-2/+4
| | | | | | * stream.c (open_subprocess, open_commad): Only flush standard output for non-input pipes. If we are capturing the output of the process, then it is unrelated to our standard output.
* subprocesses: flush *stdout*.Kaz Kylheku2022-04-231-0/+8
| | | | | | * stream.c (open-subprocess, open_command, run): Flush the standard output stream before forking or spawning the child process. This gets tests/018/forkflush.tl to pass.
* fork/streams: new failing test.Kaz Kylheku2022-04-232-0/+43
| | | | | | | | | | | | | | | | This test case exemplifies code that will work as expected when *stdout* is a TTY device, such that line buffering is in effect, but then break when standard output is redirected to a file. The issue is that the controlling process is not flushing its standard output when calling the external script, so the script's output gets placed ahead of the process' own earlier output. * tests/018/forkflush.tl: New file. * tests/018/forkflush.expected: New file.
* doc: cross reference eval and file compilation.Kaz Kylheku2022-04-011-2/+33
| | | | | | | * txr.1: The Top-Level Forms and File Compilation Model sections now reference back to eval, noting its similar treatment of top-level forms. Without this, it looks like top-level forms are just a compilation concept.
* loading: bugfix: try specified path before suffixes.Kaz Kylheku2022-03-312-61/+99
| | | | | | | | | | | | | | | | | | | | This is a partial revert of the May 1, 2019 commit 065dde19dfbe50e91e313e5b3ccc033cfbe47f74, titled "loading: try unsuffixed files directly last". Test cases added in prior commit now pass. * parser.c (open_txr_file); Like before the 2019 commit, we try the exact path that is specified first. Only if that is not found do we try adding suffixes to a file which has no recognizable suffix. This does mean that (load "foo") will probe the filesystem twice in order to find "foo.tl" or "foo.tlo" there is no obvious way around that that doesn't cause a problem. * txr.1: Update documentation that is outdated, incomplete, incorrect, or that is has become incorrect because of this fix.
* Add test for loading issue.Kaz Kylheku2022-03-3110-0/+55
| | | | | | | | | | | | | | | | | This test currently fails because when we execute an unsuffixed file like test/019/a, which exists, another file is executed instead, like test/019/a.txr. * tests/019/data/a, * tests/019/data/a.tl, * tests/019/data/a.tlo, * tests/019/data/a.txr * tests/019/data/b.tl * tests/019/data/b.tlo * tests/019/data/b.txr * tests/019/data/c.tl * tests/019/data/c.txr * tests/019/load-search.tl: New files.
* compiler: package-manipulating top-level forms bug.Kaz Kylheku2022-03-311-1/+2
| | | | | | | | | | | | | | * stdlib/compiler.tl (compile-file-conditionally): Recognize a potential package-manipulating form not checking whether its main operator is in %pakage-manip% list, but whether any global functions that its compiled image references are in that list. This is the same approach that is used in dump-compiled-objects. This fix is needed for correctly recognizing defpackage as a package-manipulating form. defpackage macro-expands to a let form which contains a call to make-package. Testing whether let is in %package-manip% is useless; of course it isn't, and the test overlooks make-package.
* New function: isecp.Kaz Kylheku2022-03-306-7/+52
| | | | | | | | | | | | | | | | | * eval.c (eval_init): Register isecp intrinsic. * lib.c (isecp): New function. * lib.h (isecp): Declared. * stdlib/compiler.tl (lambda-apply-transform, dump-compiled-objects): Use isecp instead of isec, since the actual intersection of symbols isn't needed, only whether it exists. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* Test of a package-related file compilation problem.Kaz Kylheku2022-03-302-0/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This test currently fails. This problem was reported by Paul Patience, with a repro test case. The issue is that when compile-file is processing a (defpackage x ...) form, and the package x already exists, it fails to recognize the form as a package-manipulating form, and therefore fails to introduce a "fence" in the output so that subsequent material is placed into a new top-level object. The compiled image fo the (defun foo:fun ()) form in program.tl causes an error: the foo package does not exist. This is because the symbol foo:fun is being read as part of the same object which holds the compiled image of the defpackage form which defines the package. It's essentially the same problem as this (let () (defpackage :foo) foo:bar) The (defpackage ...) cannot execute until the entire form is read, but that form contains foo:bar which requires the foo package to exist. * tests/019/compile-package.tl: New file. * tests/019/data/program.tl: Likewise.
* New FFI types str-s, bstr-s and wstr-s.Kaz Kylheku2022-03-214-54/+143
| | | | | | | | | | | | | | | | | These types actually make it possible to receive a string by pointer from a C function, without trying to free it. It is now possible to write a FFI wrapper for strtol or wcstol, which is done in the new test case. * ffi.c (str_s_s, bstr_s_s, wstr_s_s): New symbol variables. (ffi_init_types): Register the types str-s, bstr-s and wstr-s. (ffi_init): Intern the new symbols. * tests/017/str-s.tl: New file. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* ffi: minor code reordering in initialization.Kaz Kylheku2022-03-201-4/+6
| | | | | * ffi.c (ffi_init_types): Move initialization of str-d type from just before wstr to after, for consistency.
* configure: bugfix in shell escaping codeKaz Kylheku2022-03-181-1/+1
| | | | | | | | | | | * configure: in the case when the argument contains single quotes, we try to identify the subcase that cannot use double quotes instead. That subcase is not correctly identified: it occurs when there are double quotes, dollar signs **or backslashes**. For instance the data '\ cannot be put into double quotes as "'\" on account of the backslash, which is an active character in double quotes. We also simplify the pattern by using a character class.
* configure: missing tab in shell escaping code.Kaz Kylheku2022-03-181-1/+1
| | | | | | * configure: a certain ' ' (four spaces between single quotes is actually supposed to be a tab; it must have been expanded by the editor.
* ffi: after call, process args in reverse order.Kaz Kylheku2022-03-171-11/+10
| | | | | | | | | | | | | | | | | | | | | | | | | In FFI foreign function and closure calls, it behooves us to iterate over the arguments in the opposite order after the call is done. By doing that, any freeing of memory that will be done will be in the opposite order. And that is necessary if some left argument allocates a pointer that is shared with a right argument. An example of this occurs in the strtol function: long int strtol(const char *nptr, char **endptr, int base); Here, the function sets *endptr to a value derived by displacing ptr. If we call this function via FFI, then FFI will allocate memory for nptr. When the function returns, if we destroy that memory before processing *endptr then *endptr contains an invalid pointer. * ffi.c (ffi_call_wrap): In the in pass, iterate arguments in reverse. (ffi_closure_dispatch, ffi_closure_dispatch_safe): Stack-allocate an array for the argument types, so we don't have to pop the list twice, and to allow access in reverse order. In the out pass, iterate arguments in reverse.
* doc: sort-group: unnecessary copyKaz Kylheku2022-03-161-1/+1
| | | | | * txr.1: Remove copy operation partition-by expression; this was needed when sort was destructive.
* ffi: support intmax-t and uintmax-t types.Kaz Kylheku2022-03-154-9/+62
| | | | | | | | | | | | | * configure: detect intmax_t and place HAVE_INTMAX_T into config.h. * ffi.c (ffi_init_extra_types): register intmax-t and uintmax-t types. If HAVE_INTMAX_T is missing, then make them aliases for longlong and ulonglong. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New GNU-themed quip.Kaz Kylheku2022-03-081-0/+1
| | | | | | * stdlib/quips.tl (%quips%): Samsung spelled backwards is gnusmaS. In December, don't wish Merry GNUsmas in a GNU mailing list.
* New function: group-map.Kaz Kylheku2022-03-025-9/+51
| | | | | | | | | | | | * hash.c (group_map): New function. (hash_init): group-map intrinsic registered. * hash.h (group_map): Declared. * tests/010/hash.tl: New test case. * txr.1: Documented together with group-by. Extra paren removed from group-by example.
* hash: add tests for group-by, group-reduce.Kaz Kylheku2022-03-021-0/+16
| | | | * tests/010/hash.tl: New tests.
* hash: group-reduce calls hash-update.Kaz Kylheku2022-03-021-9/+3
| | | | | | | * hash.c (group_reduce): Replace loop with call to hash_update which is exactly the same logic, and even more efficient because it avoids calling us_rplacd. (hash_update): Fix incorrect self name.
* Version 274.txr-274Kaz Kylheku2022-02-247-859/+1003
| | | | | | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date. * txr.vim, tl.vim: Regenerated. * protsym.c: Likewise.
* opip: pass through forms in the op family.Kaz Kylheku2022-02-243-5/+28
| | | | | | | | | | | | | | * stdlib/op.tl (sys:opip-expand): Add op, do, lop, ldo, ap, ip, ado, ido, ret and aret to the operators whose forms are passed through untransformed. This is important because it lets us override the implicit (op ...) and (do ...) chosen by the expander. When a pipeline element produces a list, for instance, we want to be able to use (ap ...) in the next element to spread the list into arguments. * tests/012/op.tl: Add bellied numbers test case. * txr.1: Documented.
* doc: revisit partition-ifKaz Kylheku2022-02-231-7/+26
| | | | | * txr.1: Add introductory paragraph, and fine-tune the rest of the documentation.
* doc: make-like can take an iterators.Kaz Kylheku2022-02-231-0/+10
| | | | | | * txr.1: A December 2021 change that went into TXR 273 allows iterators from iter-begin to be the object argument to the make-like function. This is now documented.
* New list-builder method: oust.Kaz Kylheku2022-02-235-6/+70
| | | | | | | | | | | | | | | | * autoload.c (build_set_entries): Add oust symbol. * stdlib/build.tl (list-builder postinit): Call the self argument self instead of bc, for consistency with other methods. (list-builder oust): New method. (list-builder-flets): Add local function oust. * tests/012/seq.tl: New tests. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New function: partition-if.Kaz Kylheku2022-02-236-0/+199
| | | | | | | | | | | | | | | | * eval.c (eval_init): Register partition-if intrinsic. * lib.c (partition_if_countdown_funv, partition_if_func): New functions. (partition_if): New function. * lib.h (partition_if): Declared. * tests/012/seq.tl: New test cases. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* find-max: convert to seq_info iteration.Kaz Kylheku2022-02-223-87/+36
| | | | | | | | | | | | * lib.c (find_max): Simplify into a single loop rather than handling various sequence types specially. This means it works for all iterable objects now. * txr.1: find-max documentation updated; discussion of hash tables removed, since the described behavior is the one expected for hash tables as iterables. * tests/012/seq.tl: Add some test coverage.
* gc: c++ fix in type_t conversion.Kaz Kylheku2022-02-222-3/+3
| | | | | | | | | | | | | | * gc.c (sweep_one): The recent fix to address the clang diagnostic from -fsanitize=implicit-conversion broke C++ compatibility, due to enums being type safe. We revert the expression to the original, before that fix, and address the clang diagnostic differently. * gc.h (REACHABLE, FREE): Add a U suffix to the constants to make them unsigned. The implicit conversion issue in the expression convert(type_t, block->t.type & ~REACHABLE) is that ~REACHABLE is -257, and is being converted to unsigned.
* termios: overflow in initialization on 32 bits.Kaz Kylheku2022-02-221-2/+2
| | | | | | | * termios.c (termios_init): The CMSPAR and CRTSCTS constants cannot be passed to num_fast; they are out of range, and so the corresponding cmspar and crtscts variables will end up with garbage values.
* New functions: find-max-key and find-min-key.Kaz Kylheku2022-02-215-0/+76
| | | | | | | | | | | | | * eval.c (eval_init): Register find-max-key and find-min-key intrinsics. * lib.c (find_max_key, find_min_key): New functions. * lib.h (find_max_key, find_min_key): Declared. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* listener: restore and improve method completion.Kaz Kylheku2022-02-193-44/+7
| | | | | | | | | | | | | | | | | | | | | The recent autoload changes have degraded method completion, which didn't work well in the first place. Test case: with this change you can type term.(go[Tab] to complete to term.(go-raw or term.(go-cbreak. * parser.c (find_matching_syms): Do not use the get_slot_syms function for finding method and slot symbols. Just use get_visible_syms, like for other bindings. Instead, in the switch statement in the loop, for the 'M' (method) and 'S' (slot) completion types, we use the static_slot_types and slot_types functions to inquire whether a symbol has a binding. And these two functions do something important: unlike get_slot_syms, they trigger autoload. * struct.c (get_slot_syms): Function removed. * struct.h (get_slot_syms): Declaration removed.