summaryrefslogtreecommitdiffstats
path: root/tests
Commit message (Collapse)AuthorAgeFilesLines
...
* path-components-safe: repel /proc symlink attacksKaz Kylheku2022-07-291-0/+25
| | | | | | | | | | | | | | | | | | | | | | In a Linux system, it's possible for an unprivileged user to create a root symlink pointing to any directory, simply by changing to that directory and running a setuid executable like "su". That executable will get a process whose /proc/<pid> directory is root owned, and contains a symlink named cwd pointing to the current directory. Other symlinks under /proc look exploitable in this way. * stdlib/path-test.tl (safe-abs-path): New function. Here is where we are going to check for unsafe paths. We use some pattern matching to recognize various unsafe symlinks under /proc. (path-components-safe): Simplify code around recognition of absolute paths. When an absolute path is read from a symlink, remove the first empty component. Pass every absolute path through safe-abs-path to check for known unsafe paths. * tests/018/path-safe.tl: New tests.
* gcd: rewrite for better efficiency.Kaz Kylheku2022-07-271-0/+29
| | | | | | | | | | | * arith.c (gcd): New implementation which uses arithmetic in the unsigned type ucnum if both operands are in that type's range. This uses Stein's algorithm a.k.a. binary GCD. The mpi_gcd function is used only if at least one argument is a bignum whose value doesn't fit into a ucnum. * tests/016/arith.tl: gcd test cases added.
* New function: path-components-safe.Kaz Kylheku2022-07-251-0/+89
| | | | | | | | | | | | | | | | * autoload.c (path_test_set_entries): Autoload on path-components-safe symbol. * stdlib/path-test.tl (if-windows, if-native-windows): New system macros. (path-safe-sticky-dir): New system function. (path-components-safe): New function. * tests/018/path-safe.tl: New file.' * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New function: count.Kaz Kylheku2022-07-181-0/+10
| | | | | | | | | | | | | | | | The general count function, with keyfun and testfun, is noticeably absent. Let's implement it. * lib.[ch] (count): New function. * eval.c (eval_init): Register count intrinsic. * tests/012/seq.tl: Some tests for count. * txr.1: Add count to count-if section. Revise documentation based on pos/pos-if. * stdlib/doc-syms.tl: Updated.
* bugfix: missing gzip support in open-command.Kaz Kylheku2022-06-211-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * stream.c (pipe_close_status_helper): New function, factored out of pipe_close and used by it, and also by gzio_close. (pipe_close): Call pipe_close, which now contains the classification of process wait status codes. (open_fileno): Now takes optional pid argument. If this specified, then make_pipevp_stream is used. (open_subprocess): Use the open_fileno function, rather than fopen. This simplifies things too, except that we have to catch exception. Pass pid to the newly added parameter of open_fileno so that we obtain a proper pipe stream that will wait for the process to terminate when closed. (mkstemp_wrap): Pass nil for pid argument of open_fileno. (stream_init): Update registration of open-fileno. * gzio.c (struct gzio_handle): New member, pid. (gzio_close): If there is a nonzero pid, wait for the process to terminate. (make_gzio_stream): Initialize h->pid to zero. (make_gzio_pipe_stream): New function. * parser.c (lino_fdopen): Pass nil for pid argument of open_fileno. * gzio.h (make_gzio_pipe_stream): Declared. * tests/018/gzip.tl: New test.
* New function: strKaz Kylheku2022-06-121-0/+28
| | | | | | | | | | | | | | | The str function is like mkstring but allows a fill pattern to be specified. * eval.c (eval_init): str intrinsic registered. * lib.[ch[ (str): New function. * tests/015/str.tl: New file. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* cygwin: bug: sh always uses cmd.exe.Kaz Kylheku2022-05-311-9/+3
| | | | | | | | | | * stream.c (sh): Use a single definition for this function, which uses the shell and shell_arg variables to use either /bin/sh -c or cmd.exe /c. We only want to use cmd.exe when running as a Windows native program on Cygnal. * tests/018/process.tl: Remove workaround from test case. This is what was causing the weirdness.
* buf: compression tests.Kaz Kylheku2022-05-301-0/+18
| | | | | | | | | | * buf.c (buf_compress): Let's use the level value of -1 if not specified, so Zlib defaults it to 6, or whatever. * tests/012/buf.tl: New tests. * txr.1: Note that -1 is a valid level value and that is the default.
* gzio: some tests.Kaz Kylheku2022-05-301-0/+53
| | | | * tests/018/gzip.tl: New file.
* New: spln and tokn functions.Kaz Kylheku2022-05-301-0/+27
| | | | | | | | | | | | | | | Instead of trying to work the new count parameter into the spl and tok functions, it's better to make new ones. * eval.c (eval_init): spln and tokn intrinsics registered. * lib.[ch] (spln, tokn): New functions. * tests/015/split.tl: New test cases. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* tok-str: takes count argument.Kaz Kylheku2022-05-281-0/+15
| | | | | | | | | | | | | | * eval.c (eval_init): Update registration of tok-str. * lib.c (tok_str): New argument, count_opt. Implemented in the compat 155 case; what the heck. (tok): Pass nil to new parameter of tok_str. * lib.h (tok_str): Declaration updated. * tests/015/split.tl: New tests. * txr.1: Documented.
* tests: fix failing load-search test.Kaz Kylheku2022-05-261-1/+2
| | | | | | * tests/019/load-search.tl: skip a certain test if it is run as superuser; it fails because superuser is not affected by denied directory search and execute permissions.
* ffi: reproduce odd GNU C behavior for aligned bitfields.Kaz Kylheku2022-05-241-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | We've already taken care of imitating the situation that GNU C allows __attribute__((aligned(n))) to weaken the alignment of a bitfield, contrary to it being documented that align only strengthens alignment. Even a value of n == 1 is meaningful in that it can cause the bitfield to start allocating from a new byte. This patch corrects a newly discovered nuance: when a bitfield is attributed with a weaker alignment than its underlying type (e.g. uint32_t field marked with 2 byte alignment), the original type's alignment is still in effect for calculating the alignment of the structure, and the padding. * ffi.c (struct txr_ffi_type): New member oalign, for keeping track of the type's original alignment, prior to adjustment. (make_ffi_type_struct): For a named bitfield, take the oalign value into account when determining the most strict member alignment. (ffi_type_compile): When marking a type as aligned, the we remember the original alignment in atft->oalign. * tests/017/bitfields.tl: New test case, struct s16. * txr.1: Documented.
* fixup! ffi: couple of tests; assertion.Kaz Kylheku2022-05-241-5/+5
|
* ffi: couple of tests; assertion.Kaz Kylheku2022-05-241-0/+13
| | | | | | | | | | | | | * ffi.c (make_ffi_type_struct): Add check for impossible condition. The bits_alloc variable could only exceed bits_type (and thus cause the room variable to have a nonsensical, large value) if the bitfield allocation tried to continue allocating bits into an aligned unit, whose alignment exceeds the size of the underlying type. But in that case, tft->aligned would have to be true, and so the offset would have been aligned prior to this code, rendering bits_alloc zero. * tests/017/bitfields.tl: New tests.
* ffi: bitfield tests and fixes.Kaz Kylheku2022-05-231-0/+587
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The bitfield allocation rules are wrong. Some of it is due to the recent changes which are based on incorrect analysis, but reverting things doesn't fix it. The idea that we compare the current member's alignment with the previous is wrong; it is not borne out by empirical tests with gcc. So we do a straight revert of that. In GNU C, an __attribute__((aligned (N))) attribute applied to a bitfield member will perform the requested alignment if, evidently, the bit field is already being placed into a new byte. (If the bit field is about to be packed into an existing byte, then there is a warning about the align attribute being ignored). Because we don't have alignment as a member attribute, but only as a type attribute, we must implement a flag which indicates that a type has had align applied to it (even if the alignment didn't change) so we can then honor this in the right place in the bitfield allocation code. * ffi.c (struct txr_ffi_type): New attribute flag, aligned. (make_ffi_type_struct): Remove the prev_align variable and all related logic. Consolidate all alignment into one place, which is done before we allocate the bitfield or regular member. We align if the new member isn't a bitfield, or even if it is a bitfield if it has the aligned attribute, or if the bitfield is changing endian compared to the previous member (our local rule, not from GNU C). (ffi_type_compile): The align and pack operators now set the aligned attribute, except in the (pack 1 ...) case which semantically denotes lack of alignment. * tests/017/bitfields.tl: New file. * txr.1: Documented.
* tests: add forgotten test for new expansion rule.Kaz Kylheku2022-05-211-0/+11
| | | | | | | | This was developed together with what became the May 12 commit 1162a735b61c1c5086fb6055471ee35cc8ed62a4; I just forgot to git add the file. * tests/011/macros-4.tl
* ffi: flex structs: minor refactor.Kaz Kylheku2022-05-211-0/+9
| | | | | | | | | | | | * ffi.c (ffi_flex_struct_in): Function renamed to ffi_flex_array_len, because its responsibility is determining the length of a flexible array that is not null terminated. We don't pass in the structure's type's descriptor any more, but the member descriptor. (ffi_struct_in, ffi_struct_get): Follow rename and changed parameter conventions. * tests/017/flexstruct.tl: Added test case with nested flexible structure.
* ffi: testing and fixing flexible arrays.Kaz Kylheku2022-05-201-0/+64
| | | | | | | | | | | | | | | * ffi.c (ffi_flex_struct_in): Check for the last member being an array, and not null-terminated. We now check the character conversion disposition of the array. If it has character conversion, then we store the length right into the slot that will become the string. In the no-conversion case, we assume that if the member exists, it's a vector we can resize. Otherwise we plant a vector of the required size. (ffi_varray_put): Only call ffi_varray_dynsize if the Lisp object is a vector. If the Lisp objecct is a number, then use that as the size. Otherwise the size is zero. * tests/017/flexstruct.tl: New file.
* utf8: bugfix: trailing char fragment ignored.Kaz Kylheku2022-05-201-0/+6
| | | | | | | | | | | | | | | | | | | | After "years of trouble-free operation" a bug in the UTF-8 decoder was found, which violates its property that any sequence of bytes will decode to some kind of string, which will encode to the original bytes. When the UTF-8 data prematurely ends in the middle of a valid character, the decoder just drops that data as if it didn't exist. So for instance the two-byte sequence E6 BC should decode to "\xDCE6\xDCBC", since it is a fragment of a three-byte UTF-8 sequence. It actually decodes to the empty string. * utf8.c (utf8_bfom_buffer): When the buffer is exhausted, if we are not in the utf8_init state, it means we were in the middle of a UTF-8 sequence. Walk the bytes from the backtrack point to the end of the buffer and store them into the string as U+DCxx codes. * tests/012/buf.tl: Tests added for this via buf-str, str-buf.
* ffi: pack bugfix and tests.Kaz Kylheku2022-05-201-0/+112
| | | | | | | | | | | | | | * ffi.c (ffi_transform_pack): Fix: return the original syntax in the situation when no cases are recognized, rather than the cdr of the syntax. When the struct/union syntax has no members, return the original syntax to indicate no transformation took place. * txr.1: Document the feature that pack on a typedef name or struct name with no members will do the alignment adjustment only, without the syntactic transformation. * tests/017/pack-align.tl: New file.
* New function: trim-path-sepsKaz Kylheku2022-05-201-0/+38
| | | | | | | | | | | | | * stream.c (trim_path_seps): New function. (stream_init): trim-path-seps intrinsic registered. * stream.c (trim_path_seps): Declared. * tests/018/path.tl: New tests. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* ffi: bugfix: empty structs/unions have alignment of 1.Kaz Kylheku2022-05-191-0/+4
| | | | | | | | * ffi.c (make_ffi_type_struct, make_ffi_type_union): Initialize most_align local variable to 1, so the lower bound of alignment is that, rather than zero. * tests/017/ffi-misc.tl: Tests added.
* ffi: support 64 bit bitfields.Kaz Kylheku2022-05-191-0/+15
| | | | | | | | | | | | | | | | | | | | | | | | | * ffi.c (struct txr_ffi_type): Replace unsigned mask member with a union m which holds unsigned mask and 64-bit fmask (fat mask). (ffi_sbit_put, ffi_sbit_get, ffi_ubit_put, ffi_ubit_get): Refer to m.mask. (ffi_fat_sbit_put, ffi_fat_sbit_get, ffi_fat_ubit_put, ffi_fat_ubit_get): New static functions. (ffi_generic_fat_sbit_put, ffi_generic_fat_sbit_get, ffi_generic_fat_ubit_put, ffi_generic_fat_ubit_get): Likewise. (make_ffi_type_struct, make_ffi_type_union): Set up fat mask for bitfields that are wider than int. (ffi_type_compile): Refer to m.mask for the int and unsigned int based bitfields declared with sbit and ubit that don't mention a type. The bit operator now allows int64 and uint64 to be valid types for a bitfield. In this case, the "fat" get and put functions are selected which use 64 bit operations. Thus there is no efficiency impact on non-fat bitfields which continue to use code with 32 bit operands. (ffi_offsetof): Use the bitfield flag in the member's type structure to detect bitfields, rather than the mask.
* ffi: alignment bug in undimensioned arrays.Kaz Kylheku2022-05-181-2/+2
| | | | | | | | | | | | | | | | | | | | | | Because the varray behavior for undimensioned arrays was introduced in dubious commit 7880c9b565ab438e1bf0250a967acdbf8d04cb42 in 2017, which used make_ffi_type_pointer to register the type, claiming that the C representation is pointer (which was not true in that commit, nor ever since). As a result, though, undimensioned arrays received the alignment of pointers, rather than deriving it from the element type. Thus (array char) has 4 or 8 byte alignment whereas (array 4 char) correctly has 1 byte alignment. * ffi.c (ffi_type_compile): Use make_ffi_type_array for the two-element array syntax, just like for the dimensioned case with three elements. Then override some of the functions with the varray versions. * tests/017/ffi-misc.tl: Fix the test case which exposed this. In the type (struct flex (a char) (b (zarray char)), the array b must be at offset 1. I didn't notice that the offset of 4 being confirmed by the test case was wrong, but this showed up when running the test case on a platform with 8 byte pointers.
* ffi: fix broken test.Kaz Kylheku2022-05-181-2/+2
| | | | | | | * tests/017/ffi-misc.tl: Fix incorrect test whose loop body does not execute. A remaining issue here is why the diagnostics about unbound functions and variables in the loop body get swept under the rug.
* split-str: new count parameter.Kaz Kylheku2022-05-171-0/+39
| | | | | | | | | | | | | | | | | | * eval.c (eval_init): Fix up registration of split-str to account for new parameter. * lib.c (split_str_keep): Implement new optional count argument. (spl): Pass nil value to split_str_keep for new argument. I'd like this function to benefit from this argument also, but the design isn't settled. (split_str): Pass nil argument to split_str_keep. * lib.h (split_str_keep): Declaration updated. * tests/015/split.tl: New tests. * txr.1: Documented.
* ffi: bugfix: null terminated string as flexible member.Kaz Kylheku2022-05-171-0/+6
| | | | | | | | | | | | * 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.
* lambda-match: bug: over-strict match in variadic pattern.Kaz Kylheku2022-05-111-0/+14
| | | | | | | | | | | | * 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.
* 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.
* *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.
* 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.
* 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.
* 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-211-0/+11
| | | | | | | | | | | | | | | | | 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.
* New function: group-map.Kaz Kylheku2022-03-021-2/+2
| | | | | | | | | | | | * 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.
* opip: pass through forms in the op family.Kaz Kylheku2022-02-241-0/+6
| | | | | | | | | | | | | | * 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.
* New list-builder method: oust.Kaz Kylheku2022-02-231-0/+5
| | | | | | | | | | | | | | | | * 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-231-0/+26
| | | | | | | | | | | | | | | | * 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-221-0/+13
| | | | | | | | | | | | * 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.
* tests: test case for combining .tlo files.Kaz Kylheku2022-02-141-0/+27
| | | | * tests/018/combine-tlo.tl: New file.
* matcher: test case for `@{nil #/regex/}`.Kaz Kylheku2022-02-091-0/+2
| | | | * tests/011/patmatch.tl: New tests for recently fixed issue.
* matcher: bug: quasiliteral allowing prefix matches.Kaz Kylheku2022-02-041-1/+4
| | | | | | | | * stdlib/match.tl (expand-quasi-match): When matching `text` or `@var`, which are matching in the final position of the specimen, it is not good enough that match-str returns true; we must check that the entire string was matched. Reported by Paul A. Patience.
* New function: copy-cptr.Kaz Kylheku2022-01-281-0/+5
| | | | | | | | | | | | | | | * eval.c (eval_init): copy-cptr intrinsic registered. * lib.c (copy_cptr): New function. (copy): Use copy_cptr for CPTR objects. * lib.h (copy_cptr): Declared. * tests/017/ffi-misc.tl: New test cases. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* typecase: merge with etypecase, handle t differnetly.Kaz Kylheku2022-01-212-1/+19
| | | | | | | | | | | | | | | | | * stdlib/type.tl (sys:typecase-expander): New function, formed from body of typecase. Bad clause syntax now handled with compile-error rather than (throwf 'eval-error). The t symbol is handled specially: it turns into a t conditon in the resulting cond rather than a typep test. The compiler will nicely eliminate dead code after that. Now etypecase is handled here also: if we are expanding etypecase, we just emit the extra clause. (typecase, etypecase): Reduced to sys:typecase-expander calls. * tests/012/typecase.tl: New file. * tests/012/compile.tl: Add type.tl to list of compile-tested files.
* quasiquote: make new @,expr work in dot position.Kaz Kylheku2022-01-181-0/+12
| | | | | | | | | | | | | | | Bugfix: the newly introduced @.expr fails in the dotted position because ^(a . @,expr) turns into (list 'a 'let ...). * eval.c (is_meta_unquote): New static function. (expand_qquote_rec): Replace existing shape test with is_meta_unquote. We must also use this test in one more place: whenever the cdr of a list has the meta unquote shape, we must treat the result similarly to a dotted atom, by converting to append format. * tests/010/qquote.tl: Test cases to cover this.
* quasiquote: support @,expr hack.Kaz Kylheku2022-01-181-0/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | For better or worse, TXR Lisp has a dichotomy of representation that @<atom> produces sys:var syntax, whereas @<compound> produces sys:expr. This can cause an issue in backquoting. Suppose you want to use backquote to generate sytax like (a @b) where the b comes from a variable. The problem is that (let ((x 'b)) ^(a @,x)) doesn't do what you might expect: it produces (sys:expr b) rather than (sys:var b). This patch adds a hack into the quasiquote expander which causes it to generate code to do what you expect. Old behavior: 1> (expand '^(a @,x)) (list 'a (list 'sys:expr x)) New behavior: 1> (expand '^(a @,x)) (list 'a (let ((#:g0012 x)) (if (atom #:g0012) (list 'sys:var #:g0012) (list 'sys:expr #:g0012)))) In other words, x will be evaluted, and the based on the type of the object which emerges, either sys:var or sys:expr syntax is generated. * eval.c (expand_qquote_rec): Implement the above hack. We are careful to only do this when this exact shape occurs in the syntax: (sys:expr (sys:unquote item)). * tests/010/qquote.tl: New file. * txr.1: Documented.
* New function: match-fboundp.Kaz Kylheku2022-01-171-1/+6
| | | | | | | | | | | | | | | | | | User vapnik spaknik was asking in the mailing list whether there is an existence test for TXR pattern functions. Now there is. * eval.c (eval_init): Register match-fboundp intrinsic. * match.c (match_fbound): New function. * match.h (match_fbound): Declared. * tests/011/txr-case.txr: New test cases. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* keyparams: fix broken.Kaz Kylheku2022-01-171-0/+38
| | | | | | | | | | | | | | | | | | | Issues reported by user vapnik spaknik. The evaluation of init forms is incorrect. Init forms like '(x) evaluate to '(x) rather than (x), Also, init forms are evaluated even when the argument is present, so the entire current approach is wrong. * stdlib/keyparams.tl (extract-keys, extract-keys-p, build-key-list-expr): Functions removed. (stuff-key-params): New function. (:key): Rework using simplified approach, with just the stuff-key-params helper. All variables from the keyword parameter list are bound with let. Generated code searches the keyword parameters for values and assigns the variables as needed, evaluating default init forms in the not-found cases. * tests/011/keyparams.tl: New file.