| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
There is no longer any way to write a @(rcons ...)
pattern using the range syntax, so there is no point in
supporting that operator. The silly syntax @@a..@b
which previously worked was actually due to a mistaken
requirement in the parser.
* share/txr/stdlib/match.tl (compile-range-match): Function
moved closer to compile-atom-match, below compile-vec-match.
The argument is now a range object containing patterns, so we
pull it apart with from and to.
(compile-atom-match): Pass range directly to
compile-range-match; no need to construct (rcons ...) syntax.
* tests/011/patmatch.tl: Add range tests from documentation
and a few others.
* txr.1: References to @(rcons ...) pattern scrubbed.
One wrong #R pattern example corrected.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This fixes the following print-read consistency issue.
Both of these objects print as @a..@b.
1> '@(rcons a b)
@a..b
2> '(rcons @a b)
@a..b
We want only the second case. After the this fix:
1> '(rcons @a b)
@a..b
2> '@(rcons a b)
@(rcons a b)
* lib.c (obj_print_impl): In the sys:expr case, we check
whether the head of the argument is rcons. If so, we adjust a
few local variables and branch directly to the generic list
case via goto to print the argument as (rcons ...) without
conversion to dotdot range notation.
|
|
|
|
|
|
| |
* lib.c (obj_print_impl): Capture some values into local
variables to avoid repeating the type-checked accesses.
Many of the cases access the first argument, and such.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Whereas @a..@b parses and transforms to (rcons @a @a),
@(a)..@(a) goes to @(rcons a @(a)).
* parser.l (grammar): Under 248 compatibility or lower, the @
character now produces the OLD_AT token. Otherwise it produces
the '@' character, as before.
* parser.y (OLD_AT): New token replaces the '@' at the old
low precedence position. '@' is now at the highest precedence,
together with OLD_DOTDOT. (We don't care about interactions
between '@' and OLD_DOTDOT, because OLD_DOTDOT only exists in
185 compatibility, in which '@' is OLD_AT).
(meta): The two rules have to be unfortunately duplicated for
OLD_AT, since there is no BNF OR operator in Yacc.
* txr.1: Compat note added.
* lex.yy.c.shipped: Updated.
* y.tab.c.shipped, y.tab.h.shipped: Likewise.
|
|
|
|
| |
* Makefile (%.shipped): New pattern rule.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (match-vars): New slots, pure-vars
and pure-var-exprs.
(match-vars lets): New method.
(compiled-match wrap-guards): Generate an alet that binds the
temporaries, and then does the assignments of the regular
variables.
(compile-vec-match, compile-cons-structure,
compile-hash-match, compile-range-match): Use the pure-vars
for match-guard temporaries that are bound and not assigned,
rather than vars.
(when-match, if-match): Use alet for obj-var.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The following form fails to expand:
(let (a) (set a '#1=(#1#)))
This is due to macro ancestor propagation which wants to
traverse the entire (set ...) form in order to indicate its
macro ancestor.
* share/txr/stdlib/place.tl (sys:propagate-ancestor): We check
whether to-tree already has a macro ancestor, and only recurse
if it doesn't.
|
|
|
|
|
| |
* lisplib.c (place_set_entries): Fix misspelling of
call-delete-expander entry: stray parenthesis.
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-atom-match): Handle range
type, via transformation to rcons operator and
compile-range-mach.
(compile-range-match): New function.
(compile-match): Hook in compile-range-match for @(rcons).
(non-triv-pat-p): Handle range case.
* txr.1: Documented.
|
|
|
|
|
| |
* txr.1: Under Structural Pattern Matching, fix "instance
instance".
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The previous commit made the general pattern matcher dependent
on calling non-triv-pat-p function. But that function needs
the matcher to work in order to be defined. This has left the
code base uncompilable.
* share/txr/stdlib/match.tl (non-triv-pat-p): Precede the
real definition of non-triv-pat-p with a temporary one which
returns a conservative t value, which suspects all syntx to
be non-trivial. This means that the real non-triv-pat-p can
use match-case, because match-case's expander will be using
the temporary version of the function. non-triv-pat-p won't
benefit from the optimizations arising from identifying
trivial patterns: but since it doesn't have any such patterns,
so it makes no difference.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-atom-match): Test whether
a vector is really a non-trivial pattern, or a trivial
piece of datum. If it is trivial, then compile it
as an atom, which is matched by a simple call to equal,
which is way less code bloat, and implemented in C.
(compile-match): Similarly, check whether the cons structure
case is nontrivial and only then treat it as a cons
pattern, otherwise compile it as an atom, which will
just match it with equal.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This change causes a key-value pattern like (@a @b)
to be treated specially when @a already has a binding from a
previous pattern. In this case, it behaves like the
trivial key case: the value of @a is looked up to try to find
a single value. If @a is not bound, then the exhaustive
search takes place, using equal equality.
* share/txr/stdlib/match.tl (compile-hash-match): Implement
special case.
(var-pat-p): New function.
* tests/011/patmatch.tl: Existing test case now changes
value. New test case added.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
| |
Hash pattern matching must not assume that if gethash returns
nil, the item is not found. That's just a convenience that can
be coded in some situations, not in a general mechanism.
* share/txr/stdlib/match.tl (compile-hash-match): Allocate a
gensym that serves as a unique object. Pass this to gethash
as the alt argument, and then check whether gethash has
returned this value to indicate failure.
|
|
|
|
| |
* txr.1: fix typoo under if-match.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-hash-match): Follow
rename of is-pattern function to non-triv-pat-p.
(is-pattern): Renamed to non-triv-pat-p, to follow terminology
in the reference manual. A bug is fixed here: we must
recognize cons patterns with operators and variables in the
dotted position as non-trivial.
* tests/011/patmatch.tl: New hash test case, from doc.
* txr.1: Documented hash pattern operator.
|
|
|
|
|
|
|
|
|
| |
* hash.c (hash_revget): Default to equal, except in
compatibility mode.
(hash_keys_of): Also default to equal. This function is too
new to bother with compatibility switching.
* txr.1: Documented, with compat notes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit fixes the inadequacy that all variables occurring
in a pattern under @(all ...) or @(coll ...) are blindly
collated into lists, ignoring the fact that they may be
previously bound variables that must back-reference and not be
colleced into lists (just like in the TXR Pattern language!)
* share/txr/stdlib/match.tl (compile-loop-match): Calculate
the subset of variables in the pattern that have been freshly
bound. Only generate the collection gensyms for those
variables and only collect and nreverse those variables.
* tests/011/patmatch.tl: Some test cases that backreference
into an @(all).
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (struct match-guard): guard-expr
slot defaults to t, so the guard defauls open.
Guards are sometimes used just for binding temporaries and not
imposing any condition.
(compile-parallel-match, compile-hash-match): Omit
initial value of t for guard-expr.
|
|
|
|
| |
* txr.1: 2020 -> 2021.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Firstly, I'm fixing an odd bug here: cobjclassp returns 1
instead of t to represent true. This affects: carrayp, hashp,
random-state-p, regexp and struct-type-p, all of which
return 1 when the test is true. For some bizarre reason, I
chose this weird solution back in 2019 because this function
has some calls at init time when t is not yet available;
simply returning t causes a segfault.
Secondly, I'm fixing the way we deal with t at initialization
time. We simply give it a temporary value of 1 until it is
replaced with the real symbol. This fixes all the original
problems with t being nil until initialized. Now, we cannot
do this:
val t = one;
because one is not a constant expression due to the cast,
even though one is a de-facto constant. That's probably what
distraced me away from the obvious second-best solution of
just assigning it at some early point in the execution.
* lib.c (cobjclassp): Fix odd bug here: returning one to
indicate true instead of t. (make_sym): Don't test value of t here any more.
(make_package_common): Don't use lit("t") instead of t any
more in the make_hash calls.
(make_package): Don't test value of t here.
(obj_init): t can now be initialized using the straightforward
expression t = intern(lit("t"), user_package), similarly
to other symbols.
(init): set t to the integer 1 before making any init calls.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-hash-match): New
function.
(compile-match): Hook in hash operator.
(is-pattern): New function: uses match-case, and is used in
the implementation of the hash operator. This works because
the function doesn't use @(hash ...) anywhere.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-loop-match): Implement
coll semantics. coll fails if it collects nothing, which
uses common logic with all*. We just have to move the
flipping of the loop-iterated-var into the match, and not
do it unconditionally for every iteration.
(compile-match): Hook in the coll operator.
* tests/011/patmatch.tl: Test case copied from doc example.
* txr.1: Documented.
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (when-match): Replace incorrect if
with when.
|
|
|
|
|
|
|
|
|
|
| |
Relax the restrictions in these operators so they work with
sequences rather than specifically lists.
* share/txr/stdlib/match.tl (compile-loop-match): Make the
necessary adjustments so that abstract iteration is used.
* txr.1: Documented.
|
|
|
|
|
|
| |
* txr.1: Document recently introduced check against crossing
over into infinite iteration on the terminator of an improper
list.
|
|
|
|
|
|
| |
* tests/011/patmatch.tl: Add test case matching with two
structures in circular relationship, and a loop around
match case for various cases involving backreference.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-parallel-match): Just
like what was done in compile-loop-match in the prior commit,
we fix the situation here. guard1's guard-expr, in which the
matching logic actually happens, becomes the main test-expr.
Thus guard1 disappears and guard0 is renamed to the one and
only guard.
* tests/011/patmatch.tl: Added test case which is fixed
by this.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is caused by the way the loop match compiler moves the
matching logic into a guard, which causes a re-ordering of the
variable assignments which interferes with backreferencing
when @(some) is embedded into a @(let), and probably other
situations. The issues is that the backreferencing equal
tests can be reordered to occur before the assignment which
sets the intial value of the backreferenced variable:
cart before the horse kind of thing.
* share/txr/stdlib/match.tl (compile-loop-match): Do not add
the submatch into the guard sequence. Thus guard1's vars and
var-exprs, move into into the main compiled-match,
and guard1's guard-expr moves into guard0. Thus guard1
disappears, guard0 becomes guard.
* tests/011/patmatch.tl: New test case that is also fixed,
and which was not fixed by a different approach to the problem
that I scrapped.
|
|
|
|
|
|
| |
* tests/011/patmatch.tl: New test showing breakage whereby
a variable inside the @(some ...) operator is not able
to unify against a surrounding let variable.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-let-match): Reimplement
cleanly in terms of compiling a variable match and a pattern
match against the same object and integrating the two.
Also, do not reject nil as a variable name; the documentation
clearly says it is allowed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The issue is that iter-step will traverse (1 2 . 3)
into the 3, and then that is valid iterator which
continues via 4, 5, 6, ...
This affects the each operator family which use
iter-step.
* lib.c (iter_step): Handle CONS and LCONS specially now. If
the next object pulled via cdr is not a cons, and not nil,
then throw an error. The default case now only possibly
handles list-like sequences. Here we do something more generic
and expensive: we enforce that the next iterator must
be nil, or else a list-like sequence.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Multiple occurrences of variables unify using equal.
* share/txr/stdlib/match.tl (var-list): New struct type.
Used for tracking what variables have been defined.
(compile-struct-match, compile-vec-match, compile-atom-match,
compile-op-match, compile-cons-structure,
compile-require-match, compile-let-match, compile-loop-match,
compile-parallel-match, compile-not-match): Take var-match
argument and pass it down.
(compile-parallel-match): Take var-match argument and pass
copies of it down to the compile jobs of the branches, since
they do not unify.
(compile-var-match, comiple-let-match, compile-op-match):
Handle variables carefully: check for variable already
being defined and generate a backreference instead of
a new binding match.
(compile-match): Take optional var-list argument,
instantiating the object if it is missing, pass down to all
recursive compile unctions.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (match-case): The first case
should not test the flag variable, the variable is false.
This compiles to a useless if instruction and unreachable code.
I tried writing a peephole rule against that instruction
sequence in an experimental peephole optimizer, but across the
entire code, it only matched in code in compiler.tl arising
out of match-case, so it is better to squash this at the
source. I won't commit the peephole optimizer until it comes
up with something that isn't better fixed elsewhere.
|
|
|
|
| |
txr.1: Again under the @(not) operator, .cond instead of .code.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-require-match): The bug
here is that the condition is placed before the
match.test-expr, which is incorrect. The conditions can only
be evaluated if match.test-expr has succeeded, because
otherwise the variables are not validated to have the
correctly matching value. Also, in the documentation,
the synax insinuates there can be more than one expression. So
let's just make it work: require takes multiple expressions
and combines them with an implicit and.
* txr.1: Documentation updated.
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* /share/txr/stdlib/compiler.tl (expand-and): The case with
@(true-const-p) is wrongly ordered with respect to (and @a).
The problem is that @rest can match a null terminator, and
then we wrongly consume the constant; i.e. (and 42)
calls (expand-and ^(and)) yielding t.
Also, we eliminate the (and @a @b) case, because it is
redundant with respect to (and @a . @rest).
We adjust the latter to just output (if ...).
And, lo and behold, now the function's cases map 1:1 to the
ones in reduce-or. In fact reduce-or was originally produced
from expand-and. I debugged it thoroughly, but neglected to
backport to expand-and.
|
|
|
|
|
|
|
|
|
| |
* hash.c (hash_keys_of): New function.
(hash_init): Register hash-keys-of intrinsic
* hash.h (hash_keys_of): Declared.
* txr.1: Documented.
|
|
|
|
| |
* txr.1: Under @(not) operator, .cond instead of .code.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Bumped from incorrect 245 to 247.
* txr.vim, tl.vim: Regenerated.
* protsym.c: Regenerated.
|
|
|
|
|
| |
* txr.1: GC-driven finalization will not iterate on new
finalizer registrations.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-struct-match,
compile-predicate-match, compile-cons-structure,
compile-require-match, compile-let-match, compile-loop-match,
compile-parallel-match, compile-not-match, match-case): Use
mac-param-bind for better error reporting against the original
form when inner tree patterns don't match.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-loop-match): Introduce a
new guard, and bind the pattern's variables there. The main
compiled match now has an empty list of vars and var-exprs,
so there is no length mismatch. The nreversing of the
accumulated lists (only done in the @(and) case) is part of
the test-expr now.
|
|
|
|
|
| |
* tests/011/patmatch.tl: Breaking test case added. The @(some)
pattern match has the same vars misalignment problem.
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-parallel-match): The
problem here is that vars in the new compiled-match being
returned is not a list of the same length as var-exprs (that
being empty). When this is embedded in other expressions, and
the vars/var-exprs are appended together, this causes a
mismatch, causing assignments to go to the wrong variables.
The solution is to move the binding of all-vars into a new
guard. Guards are not blindly combined by appending.
|
|
|
|
|
|
| |
* tests/011/patmatch.tl: New weirdly failing test case. The
@(and @a @b) is important; if that term is replaced by a
simple @a, then the correct datum is bound to c.
|
|
|
|
|
| |
* txr.1: Fix the bungled dolist macro definition, as well as
the incorrect example illustrating its usage.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Squeeze the constant and unreachable cases out of (and ...)
and (or ...) forms, producing a more streamlined translation.
This is the first appearance of structural pattern matching in
the compiler!
* share/txr/stdlib/compiler.tl (compiler compile): Handle and
using new expand-and function, which translates it to if
forms. Handle or via the renamed method comp-or.
(compiler comp-and-or): Renamed to comp-or, since it handles
only or. All the switching between or/and is eliminated.
The or form is first reduced using simplify-or.
We retain this function because one case in cond relies on or;
or is a useful primitive because (or a b) evaluates a only
once; whereas (if a a b) requires common-subexpression
elimination to generate the same code as (or a b).
(true-const-p, expand-and, flatten-or, reduce-or,
simplify-or): New functions.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-not-match): New function.
(compile-match): Hook in not operator.
* txr.1: Documented.
|