summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
...
* 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.
* infix: more test cases.Kaz Kylheku2025-04-182-0/+60
| | | | | | | | * tests/012/infix.tl: New tests providing some coverage of ifx, and its phony infix also. Big test case with FFT function. * tests/common.tl (msstest): New macro.
* autoload: reset expand hook while loading.Kaz Kylheku2025-04-171-0/+1
| | | | | | | | | * autoload.c (autload_try): Just like we set *package* and *package-alist* to sane values before loading, we must also reset *expand-hook* to nil. We would not want autoloads to be processed with some custome expansion that breaks them. This matters in the rare case when they are being loaded from .tl sources rather than .tlo.
* listener: auto infix mode.Kaz Kylheku2025-04-172-7/+50
| | | | | | | | | | * parser.c (listener_auto_infix_s): New symbol variable for *listener-auto-infix-s* special. (repl): After potentially transforming the input line via auto compound mode, check for auto infix mode. If turned on, wrap the expression in ifx. (parse_init): Initialize listener_auto_infix_s. Register the special variable named by the symbol.
* Rebind *expand-hook* in load and compile-file.Kaz Kylheku2025-04-174-4/+41
| | | | | | | | | | | | * eval.c (loadv): Rebind *expand-hook* to its current value, like we do with *package*. * match.c (v_load): Likewise. * stdlib/compiler.tl (compile-file-conditionally): Likewise. * txr.1: Documented.
* New: HMAC functions.Kaz Kylheku2025-04-164-0/+137
| | | | | | | | | | | | * autoload.c (hmac_set_entries, hmac_instantiate): New static functions. (autoload_init): Register autoload of hmac module. * stdlib/hmac.tl: New file. * tests/013/chksum.tl: New tests. * txr.1: Documented.
* chksum: support stream arguments in more places.Kaz Kylheku2025-04-154-39/+136
| | | | | | | | | | | | | | | | | | | | | | * chksum.c (sha1_stream_read, sha256_stream_read, md5_stream_read): New static function. (sha1_stream_impl, sha256_stream_impl, md5_stream_impl): Logic moved into new functions. (sha1, sha256, md5): Support stream argument, via corresponding stream_impl function, passing nil as the size to snarf the whole stream. This could have been implemented without the above refactoring. In other words, the _stream functions only need to be used now when a limit on the number of bytes must be specified. (sha1_hash, sha256_hash, md5_hash): Support a stream argument. * gencksum.txr: All above chksum.c changes actually generated from here. * tests/013/chksum.tl: New tests. * txr.1: Documentation updated.
* special-operator-p: don't report error entries as t.Kaz Kylheku2025-04-142-2/+46
| | | | | | | | | | | * eval.c (special_operator_p): Do not return t for certain symbols that are wired to error-throwing functions in the table, whose purpose it is to detect certain unexpanded syntax that is handled internally by the expander. * txr.1: Documentation udpated in several places to clarify that certain operators are not special operators. Also expander-let is reclassified from Macro to Ooerator.
* expander-let: rewrite in C.Kaz Kylheku2025-04-143-62/+35
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The expander-let mechanism wants to be more tightly integrated into the expander than a macro. The reason is that the macro makes an explicit call to the expander. But the expansion it returns will be processed again by the expander. In the tightly integrated expander-let, we can avoid this; the expander can assume that the function which processes expander-let completely processes it and consequently can be tail called. All in all, since the expander is written in C, a utility which is this close to the heart of the expander should be implemented together with it in C. * eval.c (expander_let_s): New symbol variable. (expand_expander_let): New function. (do_expand): Tail call expand_expander_let when encountering a form headed by the expander-let symbol. (eval_init): Initialize expander_let_s variable with interned symbol. Also wire it into the special op table as an error entry, similarly to macrolet and a few others. * autoload.c (expander_let_set_entries, expander_let_instantiate): Static functions removed. (autoload_init): Autoload registration for expander-let module removed. * stdlib/expander-let.tl: File removed. Also, it should be noted that the the expander-let macro in this file has a a tiny bug: it refers to a sys:dv-bind symbol which should have been sys:dvbind. That means it is evaluating the (sys:dvbind ...) forms, which means it binds special variables twice: once in that evaluation, and then again in progv.
* doc: infix: document precedence demotion rule.Kaz Kylheku2025-04-141-0/+145
| | | | | | | * txr.1: Add a subsection to Infix Syntax titled Precedence Demotion Rule which describes our infix parser's enhancement to operator precedence parsing, possibly not found anywhere else.
* infix: revise auto-detection and parsing.Kaz Kylheku2025-04-093-42/+203
| | | | | | | | | | | | | | * stdlib/infix.tl (parse-infix): Change how we treat fn (arg ...) and elem [arg ...] forms. These now translate to (fn (arg ...)) and [elem (arg ...)] rather than (fn arg ...) and [elem arg ...]. (detect-infix): detect certain op [arg ...] forms as infix. (infix-expand-hook): Revise detection logic to handle bracket expression forms, and parenthesized single terms. The latter are needed to reduce [elem (atom)] to [elem atom]. * tests/012/infix.tl: Fix up some tests. * txr.1: Documented.
* expand-hook: implement in macroexpand-1.Kaz Kylheku2025-04-081-8/+35
| | | | | | | | | | | | | | | | | | | When expanding a form with macroexpand-1 or macroexpand, and an expand hook is in effect, we must call the hook. Otherwise macrology that relies on macroexpand or macroexpand-1 might not work with expander-driven syntax. I'm running into not being able to, for instance, use the swap macro on a pair of infix expressions because of this. macroexpand-1 must behave like the real macro expander. eval.c (do_macroexpand_1): After looking up whether the form is a macro, pass it through the hook if it is defined. If the hook transforms the code, then iterate on this. We pass the form through the expand hook even if it is not a macro call, and classify it based on whether is a function call, dwim brackets form or other, careful not to pass down special operators.
* expand-hook: process DWIM brackets forms.Kaz Kylheku2025-04-082-12/+27
| | | | | | | | | | | It turns out we need this for infix. * eval.c (do_expand): Call the expand hook for forms headed by the dwim operator, passing that operator symbol as the type indicator. * txr.1: Document this and also that the expand hook doesn't receive symbol macros.
* expand-hook: don't process symbol macros.Kaz Kylheku2025-04-081-10/+0
| | | | | | | | | | There isn't an obvious use for calling the expander hook for symbolic forms that are macros. (Especially while not calling it for symbolic forms that are not macros.) * eval.c (do_expand): Do not call the expand hook for symbol macro forms.
* infix: new operators, revise precedence.Kaz Kylheku2025-04-083-29/+148
| | | | | | | | | | | | | | | | * autoload.c (infix_set_entries): Intern new symbols ||, &&, !, !=, &=, |=, &&=, ||=, >>=, <<=, ~=, %=, *=, %=, <<, >>, &, |, ~, % and //. * stdlib/infix.tl: revise precedence of calculating assignment operators. Add shifts, bitwise operators, modulo, C-like synonyms for some operators, numerous new calculating assignments. (sys:mod-set, sys:and-set, sys:or-set, sys:logand-set, sys:logxor-set, sys:logior-set, sys:ash-set, sys:asr-set, sys:asr): New macros to provide the implementation of operation combinations that will only be available via infix.
* New macros: mul and div.Kaz Kylheku2025-04-083-1/+33
| | | | | | | | | * autoload.c (place_set_entries): Add mul and div symbols as autoload triggers. * stdlib/place.tl (mul, div): New macros. * txr.1: Documented.
* bident/lident: allow | character.Kaz Kylheku2025-04-086-4126/+4119
| | | | | | | | | | | | | | | | We allow the | character to be an identifier or constituent of identifers. This is going to be immediately useful in infix syntax to provide the C-like operators. * parser.l (BSCHR, NSCHR, ID_END): Add | character. * genvim.txr (glyph, iskeyword): Add | character. * lex.yy.c.shipped, * tl.vim, * txr.vim: Regenerated. * txr.1: Documented.
* place: move set-mask, get-mask out of defset.Kaz Kylheku2025-04-073-9/+9
| | | | | | | | | | * autoload.c (place_set_entries, defset_set_entries): Move the set-mask and clear-mask symbols from def_set_entries to place_set_entries. * stdlib/defset.tl (set-mask, clear-mask): Functions removed from here. * stdlib/place.tl (set-mask, clear-mask): Functions moved here.
* infix: add quadratic-roots testKaz Kylheku2025-04-062-0/+24
| | | | | | | * tests/012/infix.tl (quadractic-roots): New function. Add couple of tests. * txr.1: Add quadratic-roots as example to ifx macro.
* doc: mention whitespace issue in infixKaz Kylheku2025-04-061-0/+13
| | | | | | * txr.1: Make it clear that whitespace is required between atoms in infix expressions most of the time, so certain compact notations from C-like syntax are not achieved.
* infix: document.Kaz Kylheku2025-04-061-0/+355
| | | | * txr.1: New major section Infix Syntax.
* infix: remove unnecessary rewrite ruleKaz Kylheku2025-04-061-2/+0
| | | | | | | * stdlib/infix.tl (parse-infix): We don't need to recognize consecutive [...][...], because the rule which reduces any element followed by [...] does the job.
* infix: add tests.Kaz Kylheku2025-04-062-1/+68
| | | | | | * tests/012/infix.tl: New file. * tests/012/compile.tl: Add infix to compiled tests.