| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
| |
* txr.1: Pattern Matching is new. Though it works, the
programmer-visible, documented requirements may have to be adjusted to
make it better, and it would be nice to do that without caring about
backward compatibility. In other words, the feature is currently in
"beta": it is expected to be reliable, but the syntax and semantics are
not written in stone.
|
| |
|
|
|
|
|
|
| |
* tests/011/patmatch.tl: Add match-case test.
* txr.1: Document when-match, if-match and match-case.
|
|
|
|
|
|
| |
* tests/011/patmatch.tl: New file.
* tests/011/patmatch.expected: Likewise.
|
|
|
|
|
| |
* test/012/seq.tl: New test with multiple lambda
arguments and variadic function.
|
| |
|
|
|
|
|
| |
* txr.1: Fix "the" mistyped as "he" in the new pattern matcher
documentation, as well as under call-finalizers.
|
| |
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (cmopile-parallel-match):
Rearrange the code and bind an all-vars local variable so that
in submatch-fun we have access to the set of symbols. When
compiling the @(or) operator, we use the list to null out all
the variables that don't belong to the matching pattern.
|
| |
|
| |
|
| |
|
|
|
|
| |
* txr.1: Fix << that should be <.
|
|
|
|
|
|
|
| |
* txr.1: The operator is struct not structure. Formalize the
heading as Pattern operator.
* checkman.txr: Recognize the new Pattern operator heading.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-struct-match):
Allow a pattern instead of a struct type name, in which
case the object can be of any struct type which has
the slots required by the pattern.
* txr.1: Documented.
|
|
|
|
|
| |
* txr.1: New Structurl Pattern Matching major section with new
subsections.
|
|
|
|
|
|
|
| |
* lisplib.c (match_set_entries): New autoload triggers.
* share/txr/stdlib/match.tl (lambda-match, defun-match): New
macros.
|
|
|
|
|
|
|
|
| |
* lisplib.c (match_set_entries): Add match-case and if-match
autoload trigger symbols.
* share/txr/stdlib/match.tl (if-match, match-case): New
macros.
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-op-match): New function.
(compile-match): Route op operator to new function.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is implemented using exactly the same code as @(or ...);
the only difference is whether the and or or operator is used
in the expression.
* share/txr/stdlib/match.tl (compiile-or-match): Renamed to
compile-or-parallel match. Some local variables are renamed to
avoid being OR-specific. The operator is extracted from the
pattern, and inserted into the guard expression. That one
insertion is the only differnce between and and or.
(compile-match): Route the or operator to the renamed
function. Rout the new and operator to it also.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-loop-match): Eliminate
repeated (op eq 'some) tests by evaluating this once into the
some-p variable. Do not wastefully generate the code that
pushes values onto accumulation lists if we are translating
the some operator; those lists are ignored. Don't generate
those accumulation variables themselves at all.
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-or-match): New function.
(compile-match): Route or operator to new function.
|
|
|
|
|
|
| |
* eval.c (maprodv, maprendv): These functions implement maprod
and maprend; the v suffix is just in the C code and must not be
part of the self name.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Observed wrong result:
(mapcar (lambda (. args) (list . args)) '#(1 2 3) '#(4 5 6))
-> #((1 4) nil nil)
Correct result:
-> #((1 4) (2 5) (3 6))
This is not specific to vector input; it's broken for
sequences of all types.
Functions affected are mapcar, mapf, mappend, mapdo,
maprod, maprend, maprodo.
* eval.c (map_common, prod_common): Because we reuse the args
structure across iterations, we must reinitialize the fill
and list members. These can be modified by the functionw which
is called. In particular, the arguments are applied, they may
be turned into a list (fill decrements to zero, and a list is
produced).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is the existential quantifier to accompany @(all).
* share/txr/stdlib/match.tl (compile-loop-match): Check for
the some symbol in a few places and adjust the output.
We don't need a local binding of the patter's variables,
only the temps. The values go directly to the outer binding of
the variables which are not shadowed now. We also don't need
the nreverse logic to set the outer variables: var-exprs
is nil at the outer level. The polarity of the loop
termination test is reversed: we quit the loop on the first
match, as is the polarity of the return value: if the loop is
aborted early t is returned instead of nil.
(compile-match): Wire in the some operator.
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is in anticipation of using the same function to compile
other patterns that involve iteration.
* share/txr/stdlib/match.tl (compile-all-match): Function
renamed to compile-loop-match. The successful match and loop
termination variables are renamed to different symbols.
Also, test for the usr:all* symbol explicitly rather than
all for making the test consp.
(compile-match): Follow function rename.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-all-match): We use a flag
to break out of the loop instead of (return). The loop's block is
thereby later eliminated by the compiler. For this we
re-purpose the same all-match-p-var symbol.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lisplib.c (match_set_entries): Ensure usr:all* is interned.
* share/txr/stdlib/match.tl (compile-all-match): When the
operator is the existing all, we must listp as a guard, not
consp, because an empty list must match vacuously by virtue of
not containing any counterexample to the pattern. For
situations when a vacuous empty match is not desired, we
support the all* alternative operator, which uses consp.
(compile-match): Wire in the all* operator.
|