summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
...
* matcher: fix broken @(let @a @(some @a)) test case.Kaz Kylheku2021-01-212-8/+8
| | | | | | | | | | | | | | | | | | | | | 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.
* matcher: add failing circular backreferencing test.Kaz Kylheku2021-01-211-0/+4
| | | | | | * 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.
* matcher: cleaner @(let) implementation.Kaz Kylheku2021-01-211-12/+11
| | | | | | | | * 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.
* iter-step: don't step through improper list terminators.Kaz Kylheku2021-01-211-1/+20
| | | | | | | | | | | | | | | | 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.
* matcher: allow variables to back-reference.Kaz Kylheku2021-01-202-54/+101
| | | | | | | | | | | | | | | | | | | | | | | | 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.
* match-case: eliminate useless initial flag test.Kaz Kylheku2021-01-201-2/+3
| | | | | | | | | | | | * 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.
* doc: another .code typo.Kaz Kylheku2021-01-201-1/+1
| | | | txr.1: Again under the @(not) operator, .cond instead of .code.
* matcher: bugfix and interface change in @(require).Kaz Kylheku2021-01-202-12/+29
| | | | | | | | | | | | | | * 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.
* Version 248txr-248Kaz Kylheku2021-01-203-4/+20
| | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise.
* compiler: bug in new and expansion.Kaz Kylheku2021-01-201-3/+2
| | | | | | | | | | | | | | | * /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.
* New function: hash-keys-of.Kaz Kylheku2021-01-203-1/+32
| | | | | | | | | * hash.c (hash_keys_of): New function. (hash_init): Register hash-keys-of intrinsic * hash.h (hash_keys_of): Declared. * txr.1: Documented.
* doc: misspelled .code macro.Kaz Kylheku2021-01-201-1/+1
| | | | * txr.1: Under @(not) operator, .cond instead of .code.
* Version 247txr-247Kaz Kylheku2021-01-195-89/+118
| | | | | | | | | | | | * 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.
* doc: clarification about finalization.Kaz Kylheku2021-01-191-1/+9
| | | | | * txr.1: GC-driven finalization will not iterate on new finalizer registrations.
* matcher: use mac-param-bind, not tree-bind.Kaz Kylheku2021-01-191-9/+9
| | | | | | | | | * 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.
* matcher: fix broken @(some) test case.Kaz Kylheku2021-01-191-10/+14
| | | | | | | | | * 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.
* matcher: add another broken test case.Kaz Kylheku2021-01-191-0/+2
| | | | | * tests/011/patmatch.tl: Breaking test case added. The @(some) pattern match has the same vars misalignment problem.
* matcher: fix broken test case.Kaz Kylheku2021-01-191-5/+7
| | | | | | | | | | | * 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.
* matcher: add failing test case.Kaz Kylheku2021-01-191-0/+2
| | | | | | * 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.
* doc: fix defmacro exampleKaz Kylheku2021-01-191-4/+4
| | | | | * txr.1: Fix the bungled dolist macro definition, as well as the incorrect example illustrating its usage.
* compiler: improve code for and/or.Kaz Kylheku2021-01-181-9/+36
| | | | | | | | | | | | | | | | | | | | | 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.
* matcher: add @(not) operator.Kaz Kylheku2021-01-182-0/+51
| | | | | | | * share/txr/stdlib/match.tl (compile-not-match): New function. (compile-match): Hook in not operator. * txr.1: Documented.
* doc: add warning to Pattern Matching section.Kaz Kylheku2021-01-181-0/+9
| | | | | | | | | * 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.
* doc: document lambda-match and defun-match.Kaz Kylheku2021-01-181-0/+86
|
* doc: document when-match, if-match and match-case.Kaz Kylheku2021-01-182-0/+132
| | | | | | * tests/011/patmatch.tl: Add match-case test. * txr.1: Document when-match, if-match and match-case.
* matcher: add tests from documentation.Kaz Kylheku2021-01-182-0/+68
| | | | | | * tests/011/patmatch.tl: New file. * tests/011/patmatch.expected: Likewise.
* mapcar: add test covering recent regression.Kaz Kylheku2021-01-181-0/+3
| | | | | * test/012/seq.tl: New test with multiple lambda arguments and variadic function.
* doc: document @(op) and predicate operator.Kaz Kylheku2021-01-181-0/+81
|
* doc: fix "he" typos.Kaz Kylheku2021-01-171-2/+2
| | | | | * txr.1: Fix "the" mistyped as "he" in the new pattern matcher documentation, as well as under call-finalizers.
* doc: document @(and)/@(or) pattern operators.Kaz Kylheku2021-01-171-0/+55
|
* matcher: fix semantics of variables in @(or)Kaz Kylheku2021-01-171-14/+19
| | | | | | | | * 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.
* doc: document @(some) pattern operator.Kaz Kylheku2021-01-171-0/+28
|
* doc: document @(all)/@(all*) pattern operators.Kaz Kylheku2021-01-171-0/+48
|
* doc: document @(let) and @(require) pattern ops.Kaz Kylheku2021-01-171-0/+88
|
* doc: bad syntax in FFI type struct.Kaz Kylheku2021-01-171-1/+1
| | | | * txr.1: Fix << that should be <.
* doc: fix doc for @(struct ...) pattern operator.Kaz Kylheku2021-01-172-5/+5
| | | | | | | * txr.1: The operator is struct not structure. Formalize the heading as Pattern operator. * checkman.txr: Recognize the new Pattern operator heading.
* matcher: support loose mode for structures.Kaz Kylheku2021-01-172-26/+113
| | | | | | | | | * 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.
* doc: start of pattern matching documentation.Kaz Kylheku2021-01-161-0/+270
| | | | | * txr.1: New Structurl Pattern Matching major section with new subsections.
* matcher: add lambda-match and defun-matchKaz Kylheku2021-01-162-0/+11
| | | | | | | * lisplib.c (match_set_entries): New autoload triggers. * share/txr/stdlib/match.tl (lambda-match, defun-match): New macros.
* matcher: add if-match and match-case.Kaz Kylheku2021-01-152-1/+35
| | | | | | | | * 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.
* matcher: add support for @(op ...) predicate syntax.Kaz Kylheku2021-01-151-0/+6
| | | | | * share/txr/stdlib/match.tl (compile-op-match): New function. (compile-match): Route op operator to new function.
* matcher: support @(and pats ...) operator.Kaz Kylheku2021-01-151-16/+18
| | | | | | | | | | | | | | 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.
* matcher: remove useless code from @(some ...)Kaz Kylheku2021-01-151-8/+11
| | | | | | | | | * 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.
* matcher: support @(or pats ..) operator.Kaz Kylheku2021-01-151-0/+17
| | | | | * share/txr/stdlib/match.tl (compile-or-match): New function. (compile-match): Route or operator to new function.
* maprod, maprend: correct self name.Kaz Kylheku2021-01-151-2/+2
| | | | | | * 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.
* mapcar/maprod: show-stopper bug.Kaz Kylheku2021-01-151-2/+6
| | | | | | | | | | | | | | | | | | | | | | | | 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).
* matcher: support @(some pat) operator.Kaz Kylheku2021-01-151-4/+8
| | | | | | | | | | | | | | | | 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.
* matcher: some renaming in all match.Kaz Kylheku2021-01-151-10/+12
| | | | | | | | | | | | 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.
* matcher: use flag to eliminate block.Kaz Kylheku2021-01-151-3/+4
| | | | | | | * 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.
* matcher: fix semantics of empty @(all ...) match.Kaz Kylheku2021-01-152-2/+10
| | | | | | | | | | | | * 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.