summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
...
* trace: need autoload on sys:*trace-level*.Kaz Kylheku2025-05-091-0/+5
| | | | | | | | * autoload.c (trace_set_entries): Add sys:*trace-level* symbol as autoload trigger. Compiled code which uses the :trace parameter macro references this variable (and some other internal trace symbols, but that one first).
* compiler: improvements in reporting form in diagnostics.Kaz Kylheku2025-05-093-13/+27
| | | | | | | | | | | | | | | | | | | | * 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.
* buf-count-ones: optimize for common cases.Kaz Kylheku2025-05-091-14/+31
| | | | | | | * buf.c (buf_count_ones): Short-circuit loop iteration if word or byte is zero. If the word/byte is a power of two (1 bit set) or if it has all bits set, then skip the bit trick.
* trace: new parameter macro :trace for simple static tracingKaz Kylheku2025-05-093-1/+76
| | | | | | | | | | | | Just add :trace to the head of the parameter list, and the function is traced. No dynamic turning on and off though. * autoload.c (trace_set_entries): Trigger autoload on :trace keyword. * stdlib/trace.tl (:trace): New parameter list expander. * txr.1: Documented.
* flet/labels: generate macro ancestor form,Kaz Kylheku2025-05-091-0/+4
| | | | | | | | | * 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.
* dig: don't stop at form that has source location.Kaz Kylheku2025-05-091-2/+1
| | | | | | | | | | * stdlib/error.tl (sys:dig): Do not stop tracing the macro ancestry of a form upon finding source location info. This can be counterproductive because there are situations in which intermediate forms receive the info via rlcp or rlcp_tree. We would like to get to the form that actually exists in that file at that line number.
* autoload: load error module for sys:dig.Kaz Kylheku2025-05-091-1/+1
| | | | | | * autoload.c (error_set_entries): Add dig to system package names that trigger autoload of stdlib/error.
* quips; Unicode quip.Kaz Kylheku2025-05-081-0/+1
| | | | * stdlib/quips.tl (%quips%): New one about grapheme clusters.
* match: new macros in the "each" family.Kaz Kylheku2025-05-084-1/+250
| | | | | | | | | | | | | | | | | * autoload.c (match_set_entries): Trigger autoload on new symbols in function namespace: each-match-case, collect-match-cases, append-match-cases, keep-match-cases, each-match-case-product, collect-match-case-products, append-match-case-products, keep-match-case-products. * stdlib/match.tl (each-match-case, collect-match-cases, append-match-cases, keep-match-cases, each-match-case-product, collect-match-case-products, append-match-case-products, keep-match-case-products): New macros. * tests/011/patmatch.tl: New tests. * txr.1: Documented.
* args: type check uses of dargs in places.Kaz Kylheku2025-05-072-5/+5
| | | | | | | | | | | | | | 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.
* infix: expose and document finish-infix.Kaz Kylheku2025-05-072-1/+47
| | | | | | | * autoload.c (infix_set_entries): intern finish-infix in the usr package, and trigger autoload on it. * txr.1: Documented existence and purpose of finish-infix.
* infix: bug: non-infix expressions conflated with infix.Kaz Kylheku2025-05-073-15/+29
| | | | | | | | | | | | | | | | | | | The problem is that (parse-infix '(x < y < z)) and (parse-infix '(x < (< y z)) produce exactly the same parse and will be treated the same way. But we would like (< y z) to be left alone. The fix is to annotate all compound terms such that finish-infix will not recurse into them. * stdlib/infix.tl (parse-infix): When an operand is seen that is a compound expression X it is turned into @X, in other words (sys:expr X). (finish-infix): Recognize (sys:expr X) and convert it into X without recursing into it. * tests/012/infix.tl: Update a number of test cases. * txr.1: Documented.
* buf: int-buf: unsigned multiplication overflow.Kaz Kylheku2025-05-071-2/+1
| | | | | | | * buf.c (int_buf): Do not multiply the buffer length by 8 as a built-in unsigned integer. Use the mul function instead on the original Lisp integer length. sign-extend handles bignum values for the bit width.
* mpi: remove signed_bin stuff we don't use.Kaz Kylheku2025-05-072-42/+0
| | | | | | | | | * mpi/mpi.c (mp_read_signed_bin, mp_signed_bin_size, mp_to_signed_bin): Functions removed. * mpi/mpi.h (mp_read_signed_bin, mp_signed_bin_size, mp_to_signed_bin): Declarations removed. (mp_read_raw, mp_raw_size, mp_toraw): Macros removed.
* arith: logtrunc, lognot, bit, sign-extend: handle bits <= 0.Kaz Kylheku2025-05-072-22/+29
| | | | | | | | | | | | | | | This fixes an exception in (int-buf #b''). * arith.c (comp_trunc, lognot): Do not throw on negative bits, just return zero. (bit): Return nil if bit is negative rather than throwing. (sign_extend): Fix instance of bad indentation. Renumber goto labels. Otherwise, nothing needs to be done here since bit is where it was blowing up on a zero or negative bits value. * txr.1: Document that logtrunc, lognot, sign-extend and bit handle nonpositive bit widths, and negative bit positions.
* mpi: allow conversion of zero-sized buffer.Kaz Kylheku2025-05-071-1/+1
| | | | | | | | | This causes assertions in uint-buf and int-buf on an empty buffer argument. * mpi.c (mp_read_unsigned_bin): Remove len > 0 assertion, because the code works fine for len == 0, returning the zero mp_int produced by mp_zero.
* New function: buf-binary-width.Kaz Kylheku2025-05-074-0/+164
| | | | | | | | | | | * buf.c (buf_binary_width): New function. (buf_init): Register buf-binary-width intrinsic. * buf.h (buf_binary_width): Declared. * tests/012/buf.tl: New tests. * txr.1: Documented.
* New function: buf-count-ones.Kaz Kylheku2025-05-064-0/+201
| | | | | | | | | | | * buf.c (buf_count_ones): New function. (buf_init): Register buf-count-ones intrinsic. * buf.h (buf_count_ones): Declared. * tests/012/buf.h: New tests. * txr.1: Documented.
* buf: buf_ash: fix buffer overrrun.Kaz Kylheku2025-05-061-1/+1
| | | | | * buf.c (buf_ash): Loop must be clamped the smaller length of the result, cnlen.
* buf: remove array size checks from bit ops.Kaz Kylheku2025-05-061-15/+1
| | | | | | | | | | | | | | | | The length of a buffer is capped by the range of cnum, which is a subrange of ucnum. A buffer can never be so big that it can't be iterated by a for (i = 0; i < len; i++) loop, where i and len are of type ucnum. * buf.c (buf_ash): In this function, we potentially create a longer buffer than the input, and so here it makes sense to check for the new length being out of the range of cnum; i.e. beyond INT_PTR_MAX. We keep the check but change the threshold. (buf_and, buf_test, buf_or, buf_xor, buf_not): Remove checks on existing length.
* New function: buf-test.Kaz Kylheku2025-05-064-3/+77
| | | | | | | | | | | * buf.c (buf_test): New function. (buf_init): Register buf-test intrinsic. * buf.h (buf_test): Declared. * tests/012/buf.tl: New tests. * txr.1: Documented.
* New function: buf-zero-p.Kaz Kylheku2025-05-064-0/+59
| | | | | | | | | | | * buf.c (buf_zero_p): New function. (buf_init): Register buf-zero-p intrinsic. * buf.h (buf_zero_p): Declared. * tests/012/buf.tl: New tests. * txr.1: Documented.
* New function: buf-bit.Kaz Kylheku2025-05-054-0/+54
| | | | | | | | | | | * buf.c (buf_bit): New function. (buf_init): Register buf_bit intrinsic. * buf.h (buf_bit): Declared. * tests/012/buf.h: New tests. * txr.1: Documented.
* New function: buf-bitset.Kaz Kylheku2025-05-054-0/+73
| | | | | | | | | | | * buf.c (buf_bitset): New function. (buf_init): Register buf-bitset intrinsic. * buf.h (buf_bitset): Declared. * tests/012/buf.tl: New tests. * txr.1: Documented.
* New functions: buf-not and buf-trunc.Kaz Kylheku2025-05-054-0/+166
| | | | | | | | | | | * buf.c (buf_not, buf_trunc): New functions. (buf_init): Register buf-not and buf-trunc intrinsics. * buf.h (buf_not, buf_trunc): Declared. * tests/012/buf.h: New tests. * txr.1: Documented.
* New functions: buf-and, buf-or, buf-xor.Kaz Kylheku2025-05-054-0/+215
| | | | | | | | | | | * buf.c (buf_and, buf_or, buf_xor): New functions. (buf_init): buf-and, buf-or and buf-xor intrinsics registered. * buf.h (buf_and, buf_or, buf_xor): Declared. * tests/012/buf.tl: New tests. * txr.1: Documented.
* New function: buf-fash.Kaz Kylheku2025-05-054-0/+193
| | | | | | | | | | | * buf.c (buf_fash): New function. (buf_init): buf-fash intrinsic registered. * buf.h (buf_fash): Declared. * tests/012/buf.tl: New tests. * txr.1: Documented.
* New function; buf-ash.Kaz Kylheku2025-05-054-1/+296
| | | | | | | | | | | | | * buf.c (err_oflow): New static function. (buf_compress): Use err_oflow. (buf_ash): New function. (buf_init): Register buf-ash intrinsic. * buf.h (buf_ash): Declared. * tests/012/buf.tl: New tests. * txr.1: Documented.
* buf: buf-put-buf: wrong argument order.Kaz Kylheku2025-05-033-2/+51
| | | | | | | | | | | | | | | * buf.c (buf_put_buf): Fix incorrect argument order, contrary to documentation and inconsistent with other buf-put-* functions. (compat_buf_put_buf): New static function. Detects wrong argument order and swaps. (buf_init): Register buf-put-buf intrinsic to new static function. Thus buf-put-buf conforms to the documentation, but also works if called with the incorect old argument order. * test/012/buf.tl: New tests. * txr.1: Documentation added to clarify behaviors when put operation is out of the range of the destination buffer.
* New function: progf.Kaz Kylheku2025-05-023-0/+43
| | | | | | | | | * eval.c (do_progf, progf): New static functions. (eva_init): Register progf intrinsic. * tests/012/callable.tl: New test. * txr.1: Documented.
* callf, juxt: rewrite.Kaz Kylheku2025-05-023-15/+27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | * 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.
* infix: use superfix in fft test case.Kaz Kylheku2025-05-021-1/+1
| | | | | * tests/012/infix.tl (fft): express loop condition more succinctly as a relational compound.
* infix: do not process square bracket forms.Kaz Kylheku2025-05-022-61/+42
| | | | | | | | | * stdlib/infix.tl (infix-expand-hook): Do not process the interior of square bracket forms; jsut pass them through. Of course, square brackets continue to denote postfix array indexing. * txr.1: Updated and revised.
* sysif: check setenv for error.Kaz Kylheku2025-05-011-1/+4
| | | | | | * sysif.c (setenv_wrap): Throw an error if setenv returns negative, rather than sweeping the error under the carpet and adding the variable to our hash.
* infix: phony infix requires 3 or more elements.Kaz Kylheku2025-05-012-1/+8
| | | | | | | | | | | | | | | | | | | It is undesirable to translate (1 fun) into (fun 1). Only cases similar to these patterns, using list as an example: (1 list 2) -> (list 1 2) (1 list 2 3) -> (list 1 2 3) (1 list 2 + 3) -> (list 1 (+ 2 3)) (list 2 3) -> (list 2 3) (list 2 + 3) -> (list (+ 2 3)) * stdlib/infix.tl (infix-expand-hook): Restrict the phony infix case to three or more elements. * txr.1: Update phony infix case 1 as requiring three or more elements. Also add (1 list) example emphasizing that it's not recognized.
* infix: superfix relational operators; better code.Kaz Kylheku2025-05-013-33/+240
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit extends infix with a post-processing step applied to the output of parse-infix which improves the code, and also implements math-like semantics for relational operators, which I'm calling superfix. Improving the code means that expressions like a + b + c, which turn into (+ (+ a b) c) are cleaned up into (+ a b c). This is done for all n-ary operators. superfix means that clumps of certain operators behave as a compound. For instance a < b <= c means (and (< a b) (<= b c)), where b is evaluated only once. Some relational operators are n-ary; for those we generate the n-ary expression, so that a = b = c < d becomes (and (= a b c) (< c d)). * stdlib/infix.tl (*ifx-env*): New special variable. We use this for communicating the macro environment down into the new finish-infix function, without having to pass a parameter through all the recursion. (eq, eql, equal, neq, neql, nequal, /=, <, >, <=, >=, less, greater, lequal, gequal): These operators become right associative, and are merged into a single precedence level. (finish-infix): New function which coalesces compounds of n-ary operations and converts the postfix chains of relational operators into the correct translation of superfix semantics. (infix-expand-hook): Call finish-infix on the output of parse-infix, taking care to bind the *ifx-env* variable to the environment we are given. * tests/012/infix.tl: New tests. * txr.1: Documented.
* infix: bug: (a = b) not parsing.Kaz Kylheku2025-04-292-9/+18
| | | | | | | | | * stdlib.tl (detect-infix): Do not detect a prefix operator followed by argument, followed by anything whatsoever as being infix. The pair must be followed by nothing, or by a non-argument. * txr.1: Documented.
* build: config cache: don't touch config when no change.Kaz Kylheku2025-04-281-9/+15
| | | | | | | | | | | * config-cache-hook.tl (try-save-curent-config, try-restore-new-config): These functions now take the cache key as the argument again. The caller has to obtain that. Diagnostics are not issued in these functions. (mainline): Convert git hashes to cache keys. If they are the same, indicate current config is valid. Also diagnose when a configuration has not been retrieved, recommending ./configure being run.
* build: config cache: use hash of config inputs as cache keysKaz Kylheku2025-04-281-3/+17
| | | | | | | | | | | * config-cache-hook.tl (hash-config-inputs): New function. Hashes the configure script and the configure-related portions at the end of the Makefile, starting with the conftest: targets. We use git cat-file to get the correct versions of these files at the specified git hash. (try-save-current-config, try-restore-new-config): Convert the incoming sha to a cache key. (toplevel): Add debugging hash command.
* build: config cache: preserve perms.Kaz Kylheku2025-04-281-2/+2
| | | | | | * config-cache-hook.tl (try-save-current-config, try-restore-current-config): Preserve permissions when copying files, so ./reconfigure remains executable.
* infix: bug: handle dotted function calls.Kaz Kylheku2025-04-281-1/+1
| | | | | | * stdlib/infix.tl (infix-expand-hook): In the phony prefix case, require rest to be a cons, rather than non-nil in order to invoke cdr.
* build: new utility for caching build configs.Kaz Kylheku2025-04-271-0/+34
| | | | | | | | * config-cache-hook.tl: New file. If this is is installed as a git post-checkout hook, it will save and restore the configuration materials, associated with commit hash, under a directory called .config-cache. A cache of configs covering a wide range of commits helps with git bisecting.
* infix: test cases for prefix phony.Kaz Kylheku2025-04-231-2/+19
| | | | | | | | | | * test/012/infix.tl: New tests. (*compiling*) New variable. (unless-compiling): New macro. One :error test elicits a warning during the compiled version of the test that is hard to squelch, so we just remove it from the compiled test case. (fft): Remove unused variable i; all for loops locally bind i.
* infix: phony infix for prefix funtion call expressions too.Kaz Kylheku2025-04-222-13/+42
| | | | | | | | | | | | | | * stdlib/infix.tl (infix-expand-hook): In addition to the phony infix rule which swaps a function from second to first place, and then transforms the arguments, if possible, we add a case which is essentially like the above, but with the leading argument before the function being absent: the expression begins with a function and has two or more arguments. If those arguments transform as infix, we take the result as one argument. Otherwise if no transformation takes place, we return the original expression. * txr.1: Documented.
* infix: support function power operators.Kaz Kylheku2025-04-212-6/+41
| | | | | | | | | | | | | | | | | | | | * infix.tl (ifx-oper): New slot, power. When we detect a prefix operator that is followed by a power symbol and operand, we clone the operator and store the operand here. (parse-infix): If the operator has the power slot, the add-local function, add an extra node for the exponentiation operation over the function result. When about to add a prefix operator to the operator stack, we check whether it is a function, and whether it is followed by ** and an operand. If so, we clone the operator and store the operand into the power slot then remoe those two arguments from the rest of the input; effectively, we recognize this as a phrase structure. (detect-infix): We need a couple of rules here to detect infix expressions which use function power operators. * txr.1: Document function power operators as well as the new auto-detection rules.
* infix: autodetection takes lexical functions into account.Kaz Kylheku2025-04-212-21/+24
| | | | | | | | | | * stdlib/infix.tl (funp): New macro. (detect-infix): Take environment argument and test with funp rather than fboundp. (infix-expand-hook): Pass environment to detect-infix. Also use funp in the phony infix argument test. * txr.1: Documented.
* infix: revise auto-detection algorithm.Kaz Kylheku2025-04-213-50/+95
| | | | | | | | | | | | | | | * stdlib/infix.tl (detect-infix): Redesign. New algorithm looks only at the first two or three elements. Arguments that are not operators are only considered operands if they don't have function bindings. This is important because sometimes the logic is applied to the arguments in a DWIM bracket form, like [apply / args], which we don't want to treat as (/ apply args). * tests/012/infix.tl: New test. * txr.1: Redocumented.
* infix: phony infix: try arguments as infix.Kaz Kylheku2025-04-212-7/+32
| | | | | | | | | | | | * stdlib/infix.tl (infix-expand-hook): In the phony infix logic that swaps the first two arguments, we also try the remaining arguments as a stand-alone expression, passing that through the hook. If the hook recognizes and transforms them as infix, we keep the result as one argument. Otherwise, we just take the original arguments. I already committed some test cases for this which are failing. * txr.1: Documented.
* op: reduce and mitigate multiple expansion.Kaz Kylheku2025-04-191-4/+6
| | | | | | | | | * stdlib/op.tl (sys:op-expand): Bind *expand-hook* to nil in several places so that the unavoidable multiple expansions we perform do not re-invoke hooks. Finally, when we interpolate the calculated lambda-interior into the output templates, we mark it noexpand since the material already underwent several expansions.
* expander: noexpand mechanism.Kaz Kylheku2025-04-192-1/+70
| | | | | | | | | | | | | * 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.