summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* matcher: rescind support for @(rcons ...) patterns.Kaz Kylheku2021-01-243-41/+31
| | | | | | | | | | | | | | | | | | | | | 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.
* printer: do not render @(rcons ...) in .. notation.Kaz Kylheku2021-01-241-2/+11
| | | | | | | | | | | | | | | | | | | | | | | 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.
* printer: do some streamlining.Kaz Kylheku2021-01-241-26/+27
| | | | | | * 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.
* parser: fix bad precedence of @ token.Kaz Kylheku2021-01-246-1778/+1876
| | | | | | | | | | | | | | | | | | | | | | | 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.
* build: add rule for updating .shipped material.Kaz Kylheku2021-01-241-0/+3
| | | | * Makefile (%.shipped): New pattern rule.
* matcher: bind some temporaries with let.Kaz Kylheku2021-01-231-30/+34
| | | | | | | | | | | | | | * 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.
* places: fix runaway recursion bug.Kaz Kylheku2021-01-231-6/+7
| | | | | | | | | | | | | | 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.
* place: bug: call-delete-expander not in usr package.Kaz Kylheku2021-01-231-1/+1
| | | | | * lisplib.c (place_set_entries): Fix misspelling of call-delete-expander entry: stray parenthesis.
* matcher: add support for range objects.Kaz Kylheku2021-01-232-0/+122
| | | | | | | | | | | * 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.
* doc: fix remove double word.Kaz Kylheku2021-01-231-2/+1
| | | | | * txr.1: Under Structural Pattern Matching, fix "instance instance".
* matcher: bugfix: boostrapping chicken-egg-problem.Kaz Kylheku2021-01-221-0/+2
| | | | | | | | | | | | | | | | | 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.
* matcher: match trivial patterns as atoms.Kaz Kylheku2021-01-221-7/+13
| | | | | | | | | | | | * 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.
* matcher: add optimized special case to hash pattern.Kaz Kylheku2021-01-223-4/+55
| | | | | | | | | | | | | | | | | | 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.
* matcher: fix null value ambiguity in hash match.Kaz Kylheku2021-01-221-1/+6
| | | | | | | | | | | 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.
* doc: he -> the fix.Kaz Kylheku2021-01-221-1/+1
| | | | * txr.1: fix typoo under if-match.
* matcher: document hash and some fixes.Kaz Kylheku2021-01-223-7/+131
| | | | | | | | | | | | | * 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: hash-revget now defaults to equal.Kaz Kylheku2021-01-222-3/+16
| | | | | | | | | * 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.
* matcher: existing variables in @(all) now backref.Kaz Kylheku2021-01-223-8/+37
| | | | | | | | | | | | | | | | | | 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.
* matcher: default guard-expr to t in match-guard.Kaz Kylheku2021-01-211-4/+1
| | | | | | | | | * 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.
* doc: fix wrong year in document date.Kaz Kylheku2021-01-211-1/+1
| | | | * txr.1: 2020 -> 2021.
* bugfix: several predicates return 1 instead of t.Kaz Kylheku2021-01-211-13/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* matcher: first cut at @(hash ...) operator.Kaz Kylheku2021-01-211-0/+54
| | | | | | | | | * 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.
* matcher: new @(coll) operator.Kaz Kylheku2021-01-213-9/+43
| | | | | | | | | | | | | * 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.
* matcher: when-match incorrect body treatment.Kaz Kylheku2021-01-211-1/+1
| | | | | * share/txr/stdlib/match.tl (when-match): Replace incorrect if with when.
* matcher: @(some) and @(all) work with sequences.Kaz Kylheku2021-01-212-16/+23
| | | | | | | | | | 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.
* doc: document new check in iter-step.Kaz Kylheku2021-01-211-1/+36
| | | | | | * txr.1: Document recently introduced check against crossing over into infinite iteration on the terminator of an improper list.
* matcher: more test cases.Kaz Kylheku2021-01-211-0/+29
| | | | | | * 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.
* matcher: matcher: fix broken @(let @a @(some @a)).Kaz Kylheku2021-01-212-7/+7
| | | | | | | | | | | | * 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.
* 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.