| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.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.
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
| |
* autoload.c (place_set_entries): Add mul and div
symbols as autoload triggers.
* stdlib/place.tl (mul, div): New macros.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
| |
* stdlib/infix.tl (parse-infix): We don't need to
recognize consecutive [...][...], because the
rule which reduces any element followed by [...]
does the job.
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/infix.tl (parse-infix): Drop usr: package
prefix; autoload.c interns this symbol in the usr
package.
(detect-infix): New function, whose single
responsibility is determining whether the argument
expression should be treated via parse-infix.
(infix-expand-hook): Simplified by using detect-infix
function.
|
|
|
|
|
| |
* stdlib/infix.tl (infix-error): Remove
trailing whitespace.
|
|
|
|
|
|
|
|
| |
* stdlib/infix.tl (toplevel): New prefix operator =
at 0 precedence. This is useful for specifying an
infix formula that is not being autodetected by ifx
nicely. For instance an expression containing
only array references can be obtained as (= a[i][j]).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We implement a dynamic precedence algorithm whereby
when an infix operator is immediately followed by
a clump of one or more consecutive prefix operators,
the infix operator's precedence is lowered to one
less than the lowest one of the prefix operators.
This creates nice handling for situations like
(sqrt x + y - sqrt z + w) whose visual symmetry
parses into (- (sqrt (+ x y)) (sqrt (+ z w)))
rather than subordinating the second sqrt to the
first one.
* stdlib/infix.tl (parse-infix): Before processing
an infix operator, calculate the prefix of the rest
of the input that consists of nothing but consecutive
prefix operators, and if it is nonempty, then use it
to adjust the effective precedence used for the infix
operator. This algorithm must only ever lower the
precedence, never raise it.
|
|
|
|
|
|
| |
* stdlib/infix.tl (toplevel): The := operator must
be assoc :right so a := b := c becomes (set a (set b c))
and not (set (set a b) c).
|
|
|
|
|
|
|
|
|
| |
* stdlib/infix.tl (parse-infix): The operator expected
diagnostic can occur not just before an an operand,
but before an prefix operator. For instance "a cos b".
An operator is expected between a and cos.
We don't want to say "before operand cos" because
cos is an operator.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The infix module provides a macro called ifx. Forms
(evaluated expressions) enclosed inside ifx at any nesting
level, which are not special operator or macro forms, are
subject to automatic detection of an infix notation, which is
transformed into regular Lisp. The notation is based on Lisp
atoms; no read syntax is introduced. Infix may be freely mixed
with ordinary Lisp.
* autoload.c (infix_set_entries, infix_instantiate):
New static functions.
(autoload_init): Register new infix module for autoload.
* stdlib/infix.tl: New file.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autolod.c (match_set_entries): Autoload match module on
match-tuple-case.
* match.tl (match-tuple-case): New macro.
* tests/011/patmatch.tl: New tests.
The macro is trivial; if lambda-match works, the
macro works.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register keep intrinsic.
* lib.[ch] (keep): New function.
* stdlib/compiler.tl (compiler comp-fun-form): Transform
two argument keep to keepqual.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/compiler.tl (compiler comp-fun-form): Recognize
two-argument forms of remove, count, pos, member and subst.
When these don't specify test, key or map functions, they are
equivalent to remqual, countqual, posqual, memqual and
subqual. These functions are a bit faster because they have
no arguments to default and some of their C implementations
call the equal function either directly or via a pointer,
rather than via going via funcall. The exceptions are posqual
and subqual which actually call pos; but even for these it is
still slightly advantageous to convert to to the fixed arity
function, because funcall2 doesn't have to default the
optional arguments with colon_k.
|
|
|
|
|
|
| |
* stdlib/place.tl (sys:placelet-1): Fix a misindented
call-update-expander function call. Also indent its
arguments in function style.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autoload.c (glob_set_entries): Remove autoload on
sys:brace-expand. Add usr:exp.
* stdlib/glob.tl (brace-expand): Renamed to usr:bexp.
(glob*): Call bexp rather than brace-expand.
* tests/018/glob.tl: Rename references to sys:brace
expand to bexp.
* txr.1: Add section describing the bexp function.
Move brace expansion documentation from glob* to this
new section, adjusting the wording a little bit, mainly
to avoid referring to "patterns". Point glob* documentation
to bexp, which also in turn references glob*.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlb/glob.tl (bexp-parse): Recognize .. as a token.
(bexp-parse-brace): If a brace expansion doesn't contain
commas, then check whether it contains .. and that its elements
are all strings. In that case it is a possible range expansion
and we thus transform it to a (- ...) node, subject to
more validation in bexp-expand.
(bexp-expand): Add casees to handle range expansion,
taking care that invalid forms translate to verbatim
syntax.
* tests/018/glob.tl: New tests.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/awk (awk-state upd-rec-to-f): Handle a new case
of fs being the keyword symbol :csv, producing a
field-splitting lambda that calls get-csv.
* tests/015/awk-basic.tl: Several new test cases for
this CSV feature.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Handle field separations with lambdas, similarly to record
separation. The idea is that we replace the rec-to-f method,
which contains a cond statement checking the variables for
which field separation discipline applies, with a lambda which
is updated whenever any of those ariables change.
* awk.tl (awk-state): New instance slot, rec-to-f.
(awk-state :postinit): Call new upd-rec-to-f method
so that rec-to-f is populated with the default field
separating lambda.
(awk-state rec-to-f): Method removed.
(awk-state upd-rec-to-f): New method, based on rec-to-f.
This doesn't perform the field separation, but returns
a lambda which will perform it.
(awk-state loop): We must call upd-rec-to-f whenever
we change par-mode, because it influences field separation.
(awk-mac-let): Replace the symbol macros fs, ft, fw and
kfs with new implementations that use the reactive slot
mechanism provided by rslot. Whenever the awk macro assigns
any of these, the upd-rec-to-f method will be called.
* tests/015/awk-basic.tl: New file. These basic tests of
field separation pass before and after this change.
* tests/common.tl (otest, motest): New macros.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autload.c (csv_set_entries, csv_instantiate): Functions
removed.
(autoload_init): Autoload registration for stdlib/csv
removed.
* stdlib/csv.tl: File removed.
* stream.c (get_csv): New function.
(stream_init): Register get-csv intrinsic.
* stream.h (get_csv): Declared.
|
|
|
|
|
|
| |
* csv.tl (get-csv): Since there are only three states, there
is no jump table optimization. We might as well use keyword
symbols for the states rather than integers.
|
|
|
|
|
|
|
|
|
| |
* stdlib/csv.tl (get-csv): Pre-process the input by a small
state machine that maps CR-LF sequences to LF. Then
we don't have to recognize #\return anywhere in the state
machine and can delete the cr and qcr states, as well
as all the code recognizing #\return and branching to those
states.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autloload.c (csv_set_entries, csv_instantiate): New
static funtions.
(autoload_init): Register autoload of stdlib/csv
module via new functions.
* stdlib/csv.tl: New file.
* tests/010/csv.tl: Likewise.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autoload.c (enum_set_entries, enum_instantiate): New static
functions.
(autoload_init): Register autoload of stdlib/enum module
via new functions.
* stdlib/enum.tl: New file.
* tests/016/enum.tl: Likewise.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In an opip pipeline, only the first pipeline element can
receive multiple arguments. The subsequent elements
receive the single return value from the previous element.
Therefore if it is a left-inserting pipeline created
by lopip, only the first element needs to use lop.
The others can use lop1, resulting in an optimization.
Furthermore in the flow/lflow macros, even the first
function in the pipeline is called with one argument:
the result of the input expression. So the case of lflow,
every element of the pipe that would translate to lop
can go to lop1 instead.
* stdlib/opt.tl (sys:opip-expand): Calculate a local
variable called opsym-rest which determines which op
symbol we use for the recursive call. This is the
same as the incoming opsym, except in the case when
opsym is lop, in which case we substitute lop1.
(sys:lopip1): New macro, like lopip but uses lop1
for the first element also.
(lflow): Expand to sys:lopip1 rather than lopip.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autoload.c (op_set_entries): Autoload on lop1 symbol.
* stldlib/op.tl (sys:op-expand): Add lop1 case.
(sys:opip-expand): Add lop1 to the list of operators
that are recgonized and specially treated.
(lop1): New macro.
* tests/012/op.tl: New tests.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The lop macro is inconsistent from op in that it
inserts the trailing function arguments on the
left even if arguments are explicitly given in the
form via @1, @2, ... or @rest. This change makes
lop is equivalent to op in all situations when these
metas are given.
* stdlib/op.tl (compat-225, compat-298): New top-level
variables.
(op-expand): local variable compat replaced by references to
compat-225. If compat-298 is *not* in effect, then metas
are checked for first in the cond, preventing the lop
transformation from taking place.
* tests/012/op.tl: Test cases for lop, combinations of
do with lop and a few for op also.
* txr.1: Redocumented, added compat notes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h,
args.c, args.h, arith.c, arith.h, autoload.c, autoload.h,
buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h,
chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure,
debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c,
filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, gzio.c,
gzio.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S,
lex.yy.c.shipped, lib.c, lib.h, linenoise/linenoise.c,
linenoise/linenoise.h, match.c, match.h, parser.c, parser.h,
parser.l, parser.y, protsym.c, psquare.h, rand.c, rand.h,
regex.c, regex.h, signal.c, signal.h, socket.c, socket.h,
stdlib/arith-each.tl, stdlib/asm.tl, stdlib/awk.tl,
stdlib/build.tl, stdlib/cadr.tl, stdlib/comp-opts.tl,
stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl,
stdlib/copy-file.tl, stdlib/csort.tl, stdlib/debugger.tl,
stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl,
stdlib/error.tl, stdlib/except.tl, stdlib/expander-let.tl,
stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl,
stdlib/glob.tl, stdlib/hash.tl, stdlib/ifa.tl,
stdlib/keyparams.tl, stdlib/load-args.tl, stdlib/match.tl,
stdlib/op.tl, stdlib/optimize.tl, stdlib/package.tl,
stdlib/param.tl, stdlib/path-test.tl, stdlib/pic.tl,
stdlib/place.tl, stdlib/pmac.tl, stdlib/quips.tl,
stdlib/save-exe.tl, stdlib/socket.tl, stdlib/stream-wrap.tl,
stdlib/struct.tl, stdlib/tagbody.tl, stdlib/termios.tl,
stdlib/trace.tl, stdlib/txr-case.tl, stdlib/type.tl,
stdlib/vm-param.tl, stdlib/with-resources.tl,
stdlib/with-stream.tl, stdlib/yield.tl, stream.c, stream.h,
struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h,
syslog.c, syslog.h, termios.c, termios.h, time.c, time.h,
tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h,
utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr,
y.tab.c.shipped: Copyright bumped to 2025.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/match.tl (match-case-to-casequal): the (do inc
dfl-cnt) action has a problem: it inserts an implicit extra
parameter to the invocation of inc, which crashes the +
addition due to that parameter being the matching @nil object.
We don't need this entire case because it handles @nil,
which also matches the following case for (sys:var ...),
since @nil is (sys:var nil). That case ahs the same action
of incrementing dfl-cnt.
* tests/011/patmatch.tl: Test case added.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
| |
* stdlib/quips.tl (%quips%): New one.
|
|
|
|
| |
* stdlib/quips.tl (%quips%): New entry.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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: Regenerated.
|
|
|
|
|
|
| |
* stdlib/struct.tl (sys:check-slot): Don't issue the
diagnostic "<obj> isn't the name of a struct slot"
for slots that are not bindable symbols like obj."abc".
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is like @(scan) but collects all matches over the
suffixes of the list.
* autoload.c (match_set_entries): Intern scan-all symbol.
* stdlib/match.tl (compile-scan-all-match): New function.
(compile-match): Dispatch compile-scan-all-match on scan-all
symbol.
* tests/011/patmatch.tl: Tests for scanall and also missing
tests for scan.
* txr.1: Documented.
|
|
|
|
|
| |
* stdlib/match.tl (compile-scan-match): Fix wrong indentation
of let* body.
|
|
|
|
|
| |
* stdlib/quips.tl (%quips%): Remove quip about lecithin;
it does not wear well.
|