summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* matcher: test for dotted variable in predicate.Kaz Kylheku2021-02-081-0/+4
| | | | * tests/011/patmatch.tl: New test case.
* compiler: frame optimizations apply to dframe too.Kaz Kylheku2021-02-081-2/+2
| | | | | * share/txr/stdlib/optimize.tl (basic-blocks peephole): Use or pattern to look for dframe as well as frame.
* doc: document feature of multi-sort.Kaz Kylheku2021-02-081-0/+4
| | | | | | * txr.1: Document that multi-sort takes a single function in place of a list of one function. This has been a feature of the implementation from the beginning.
* compiler: jump skid optimization.Kaz Kylheku2021-02-071-0/+8
| | | | | | | | | | | | | | | | | | If an (if reg label0) target branches due to reg being nil, and the target of the branch is another branch instrution of the form (ifq reg nil label1), we know that that branch is not taken: the code following that instruction is executed. THus can jump right to that code. (if reg label0) (if reg xlabel) ... ... label0 label0 (ifq reg nil label1) --> (ifq reg nil label1) ... xlabel ... * share/txr/stdlib/optimize.tl (basic-blocks peephole): New sub-case under (jmp @reg @jlabel).
* compiler: frame reduction optimizations.Kaz Kylheku2021-02-071-1/+36
| | | | | | | | | | | | | | These optimizations have to do with moving a (frame x y) instruction past the next instruction. The goal is to move the frame past a conditional branch, under the right circumstances, so that the frame is eliminated when the branch is taken. * share/txr/stdlib/optimize.tl (basic-blocks (cut-block, next-block)): New methods. (basic-block peephole): Add two patterns: one to move a frame past a mov, call or gcall. Another more complicated one to move it past an if which jumps to an end.
* matcher: exprs-syntax: process trivial matches first.Kaz Kylheku2021-02-071-12/+15
| | | | | | | * share/txr/stdlib/match.tl (compile-exprs-match): Sort the expressions and patterns so trivial matches are processed first. The original order is used for evaluating the expressions.
* multi-sort: bug: always return list of lists.Kaz Kylheku2021-02-071-6/+13
| | | | | | | * lib.c (multi_sort): If any of the input lists is empty, then there is an empty list of tuples to sort, producing a an empty list that doesn't transpose back to a list of empty lists. We code this as a special case.
* matcher: eliminate use of flags.Kaz Kylheku2021-02-071-27/+18
| | | | | | | | | * share/txr/stdlib/match.tl (if-match, match-case, lambda-match): Instead of returning the result from the case(s), which gets stored in a result variable, and setting a flag to t, set the result variable inside the case, and return t. This eliminates the flag. In match-case and lambda-match, the cases can then be combined into an or form.
* matcher: predicate: document dot position of @avar.Kaz Kylheku2021-02-061-5/+9
| | | | | * txr.1: The @avar variable may be in the dot position of the form, denoting application.
* matcher: remove @(op ...) pattern.Kaz Kylheku2021-02-063-41/+2
| | | | | | | | | | | | | | | All he typical uses of this are better served by the new predicate match. If op is really needed, it can be used with the DWIM form of the predicate, as in @[(op ...) ...]. * share/txr/stdlib/match.tl (compile-op-match): Function removed. (compile-match): Remove op case. * tests/011/patmatch.tl: Keep op test cases by converting them to predicate test cases. * txr.1: Documentation removed.
* matcher: redesign predicate pattern.Kaz Kylheku2021-02-065-110/+142
| | | | | | | | | | | | | | | | | | | | | | | | * share/txr/stdlib/match.tl (compile-dwim-predicate-match): Function removed. There is no more special @(dwim ...) or @[...] pattern. (compile-predicate-match): Function rewritten, providing different syntax and semantics. (compile-match): dwim dispatch removed. (non-triv-pat-p): Replaced @(op ...) calls with new-style predicate syntax. (var-pat-p): Likewise, and upgraded one instance of old-style predicate syntax to new. * share/txr/stdlib/compiler.tl (reduce-or): Adjust predicate pattern to new style. * share/txr/stdlib/optimize.tl (dedup-labels): Likewise. * tests/011/patmatch.tl: All test cases with predicate syntax are updated to new style. One test case removed; some added. * txr.1: Predicate patterns re-documented. All examples involving predicate patterns updated.
* matcher: left-to-right scoping for @(and).Kaz Kylheku2021-02-062-26/+33
| | | | | | | | | | | | | | And binds left to right now; only or is parallel. * share/txr/stdlib/match.tl (compile-and-mach): Do not compile the patterns with copies of the var list, but with he one and only incoming var-list. Consequently, there are not var lists to merge. par-pat parameter renamed to and-pat. * txr.1: Improve and/or documentation, clarifying scope rules. Also, clarify that variables in non-matching patterns of an or are no set to nil, if they are existing bindings from before the or.
* matcher: @(as) must always bind fresh variable.Kaz Kylheku2021-02-062-13/+47
| | | | | | | | | | | | | | It is documented that as binds a new variable. Furthermore, it used to be called let. Yet, it back-references. Let's fix it. * share/txr/stdlib/match.tl (compile-new-var-match): New function: like compile-var-match but binds new variable, as if back-referencing didn't exist. (compile-as-match): Use compile-new-var-match. * txr.1: Improve as documentation. Clarify that it binds a fresh variable, and that pattern is processed in its scope. Include an example with circular structure.
* matcher: clean up var match.Kaz Kylheku2021-02-051-4/+6
| | | | | | * share/txr/stdlib/match.tl (compile-var-match): Pull symbol check into the cond. In null sym case, don't call var-list.record.
* compiler: take advantage of new scoping in optimizer.Kaz Kylheku2021-02-051-14/+14
| | | | | | * share/txr/stdlib/optimize.tl (basic-blocks peephole): Get rid of @(op ...) and @(require ...) operators in favor of direct backreferencing.
* matcher: back-reference Lisp variables.Kaz Kylheku2021-02-053-9/+64
| | | | | | | | | | | | | | | | * share/txr/stdlib/match.tl (struct var-list): New slot, menv. (var-list exists): Method now falls back on lexical scope and dynamic variables. (get-var-list): New function. (when-match, if-match, match-case, when-exprs-match): Capture macro environment and use get-vars-list to convert to a vars object which carries it as the menv slot. With this, the compiler framework has access to the lexical environment. * tests/011/patmatch.tl: Test cases of back-referencing with Lisp lexicals. * txr.1: Documented.
* compiler: rewrite one peephole patern using @(with ...).Kaz Kylheku2021-02-051-8/+6
| | | | | | | * share/txr/stdlib/optimize.tl (basic-blocks peephole): Rewrite the recently added jump hreading optimization as a single pattern, doing the matching into the other basic block through the hash table using @(with ...).
* matcher: rearrange match order of @(with).Kaz Kylheku2021-02-053-28/+49
| | | | | | | | | | | | | | | | | The @(with side-pat expr main-pat) syntax becomes @(with main-pat side-pat expr), which is more useful. Also, the main-pat can be omitted. * share/txr/stdlib/match.tl (compile-with-match): Recognize two forms of the syntax: two argument form with main-pat omitted and the full form. In the full form, main-pat is on the left now and processed first, so we have to rearrange the compilation and integration order. * tests/011/patmatch.tl: Existing tests updated. Two-argument test added. * txr.1: Updated.
* matcher: don't set flag in last case.Kaz Kylheku2021-02-051-12/+18
| | | | | | | | | | | The last case in a match-case or lambda-match does not need to set the matched flag, since nothing tests it. * share/txr/stdlib/match.tl (match-case): Rename some local variables for consistency with lambda-match. Change the counter from 1, so we can then compare the index of the last case to the length and avoid emitting the set. (expand-lambda-match): Same optimization.
* compiler: new jump threading optimization case.Kaz Kylheku2021-02-051-0/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This opportunity now exists due to the previous commit which eliminates discarded register moves. The idea is to recognize code like if Txxx label0 jmp label1 ;; jump if Txx is not nil label1: if Txxx ... ;; Txxx is not nil jmp label2 ;; jump taken and rewrite the jmp in the first block to: if Txxx label0 jmp label2 The leading if Txx label0 is then susceptible to further threading via label0, as before. Before the previous compiler commit, there were dead register moves between the if and jmp that would be too complicated to analyze in the peephole. The motivation is that this pattern occurs in match-case and lambda-match due to the way the cases update a matched-p variable which is used to skip subsequent cases: case0 (unless matched-p case1) ;; sets matched-p if it matches (unless matched-p) case2) ;; sets matched-p if it matches ... and so on. Those successive matched-p tests now thread; if matched-p is true, the control flow will short-circuit past the subsequent tests. * share/txr/stdlib/optimize.tl (basic-blocks peephole): Add new case for recognizing aforementioned pattern.
* compiler: optimize away discard register.Kaz Kylheku2021-02-051-33/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When compiling the procedural special forms prog and prog1, there are subforms whose values are discarded. The compilation of those forms still requires an output register, which is passed down. In certain cases, wasteful moves of data into that register are generated, which we can eliminate. * share/txr/stdlib/compiler.tl (struct compiler): New slot, discards. Holds t-registers that are marked as discard. (compiler alloc-discard-treg): New method. (compiler free-treg): Remove freed treg from discard list. (compiler maybe-alloc-treg): If the given register is a discard, we must allocate. (compiler maybe-mov): New method, replacing maybe-mov function. (compiler comp-if): Replace maybe-mov function calls with method. In the (if test then) case, avoid referencing oreg register after a maybe-mov since it may be a discard such that the maybe-mov produced no code; reference the original register. (comp-progn): Allocate oreg-discard with alloc-discard-treg method instead of alloc-treg. (comp-prog1): Same thing with igreg. (comp-for): For compiling the test expression, use the same output register as what was used for the init block. Do not borrow oreg for this, which may be a discard that will be removed by the maybe-mov. (compiler (comp-setq, comp-ift, comp-switch, comp-block, comp-catch, comp-let, comp-fbind, comp-lambda-impl, comp-or, comp-tree-case, comp-load-time-lit): Replace maybe-mov function calls with method. (maybe-mov): Function removed, replaced by method.
* matcher: lambda-match: bug: wrong variable tested.Kaz Kylheku2021-02-041-1/+1
| | | | | | * share/txr/stdlib/match.tl (expand-lambda-match): The matched-p-temp variable must be tested for each clause, not result-temp. The result of a matching clause could be nil.
* matcher: lambda-match: error diagnostics.Kaz Kylheku2021-02-041-14/+20
| | | | | | | | | * share/txr/stdlib/match.tl (when-exprs-match): Bind the *match-form* special to macro form. (lambda-match, defun-match, :match): Likewise. (expand-lambda-match): Set the macro ancestor for the when-exprs-match form to the be clause syntax it was derived from.
* matcher: misleading diagnostics.Kaz Kylheku2021-02-041-2/+2
| | | | | | | * share/txr/stdlib/match.tl (compile-var-match, compile-predicate-match): Replace "is not a symbol" with "is not a bindable symbol". I had this message come up claiming that a :keyword is not a symbol.
* error: improve compiler error location reporting.Kaz Kylheku2021-02-041-8/+18
| | | | | | | | | | | * share/txr/stdlib/error.tl (sys:dig): New function. If the form has no source location, but has macro ancestry, thens try to search through that. (sys:loc): Don't bother with the conditional; source-loc-str always returns something. When there is no source location there is a "source loc n/a" string. (compile-error, compile-warning, compile-defr-warning): Use sys:dig to take advanage of macro ancestry information.
* doc: misspelled dump-deferred-warningsKaz Kylheku2021-02-041-1/+1
| | | | * txr.1: pluralize identifier in syntax section.
* matcher: add :match parameter macro.Kaz Kylheku2021-02-043-4/+252
| | | | | | | | | | | | | With this, we can do matching anywhere we are able to specify a function parameter list and a body, and we can specify ordinary arguments, which are inserted to the left of the implicit match. Plus, it specialy integrates with :key. * lisplib.c (match_set_entries): Autoload on :match. * share/txr/stdlib/match.tl (:match): New parameter macro. * txr.1: Documented.
* doc: param macros: missing return value requirements.Kaz Kylheku2021-02-041-0/+14
| | | | | | * txr.1: Document return value convention of parameter list transformers, without which it can only be deduced from the example.
* matcher: lambda-match: redoc, bugfix, test-casesKaz Kylheku2021-02-043-37/+205
| | | | | | | | | | | | | | | * share/txr/stdlib/match.tl (expand-lambda-match): In a case that takes the maximum number of fixed args and no dotted pattern, in a function that is variadic, we must assert that the rest parameter is nil: there are no additional arguments. In the lambda args, we must generate the colon that separates the optional arguments. * tests/011/patmatch.tl: basic test cases for lambda-match and defun-match. * txr.1: lambda-match and defun-match redocumented, with examples.
* matcher: reimplementation of lambda-match.Kaz Kylheku2021-02-031-6/+98
| | | | | | | | | | | | | | | | | | | | | | This patch replaces the argument-list-based lambda match with one that matches fixed arguments without consing. Instead of generating a variadic function with zero fixed arguments, it generates a function with required, optional and rest argument based on considering the arity of all the matches. * share/txr/stdlib/match.tl (compile-exprs-match): New function. (compile-match): Wire a new pattern operator called sys:exprs, for internal use. This matches a list-like pattern against the values of multiple expressions, rather than a single expression. (when-exprs-mach): New internal macro for matching a sequence of patterns against a sequence of expressions of the same arity. (lambda-clause): New structure. (parse-lambda-match-clause, expand-lambda-match): New functions. (lambda-match, defun-match): Redefine using expand-lambda-match.
* matcher: bugfix: bad hygiene in match-case.Kaz Kylheku2021-02-031-4/+6
| | | | | | | * share/txr/stdlib/match.tl (match-case): Use a gensym for evaluating the obj expression, rather than passing that expression itself into the sub-compile jobs, where it is subject to multiple evaluation.
* lib: code review of get_special_slot uses.Kaz Kylheku2021-02-021-24/+23
| | | | | | | | | | | | | * lib.c (seq_info): Streamline code. Initialize ret.kind to SEQ_NOTSEQ to avoid repeating that in multiple else clauses. Make sure that if the nullify method returns nil, we also return in that case, and don't call get_special_slot on nil. (rplaca, rplacd): Change the default case to COBJ, so that the obj_struct_p inline can be used instead of structp. Put the default: label on the error case which the struct check falls through to; NIL now goes there. (sub): Use obj_struct_p, not structp, in a case where we already know we have a COBJ.
* lib: fix crash in iterable and nullify.Kaz Kylheku2021-02-021-1/+1
| | | | | | | * lib.c (seq_iterable): In the COBJ case, we must check whether the object is a structure before accessing get_special_slot. For instance (nullify #/a/) crashes because a regex is a COBJ but not a struct.
* matcher: fix @(and/or) backreferencing issue.Kaz Kylheku2021-02-021-1/+6
| | | | | | | | * share/txr/stdlib/match.tl (var-list merge): New method. (compile-or-match, compile-and-match): After compiling the sub-patterns, merge all of their new variables produced in their isolated var-list copies back into var-list, so they are visible to subsequent compilation.
* matcher: new failing backreferencing test case.Kaz Kylheku2021-02-021-0/+4
| | | | | | | | | | * tests/011/patmatch.tl: New test cases that break. The (copy var-list) logic in the handling of and and or is incomplete. The bifurcated vars must be merged together into the original vars. Without this, it looks as if the operator didn't bind any variables, and they can be repeated again without backreferencing. In the broken examples, variable a is taking on the value 2 instead of mismatching the previous value of 1.
* matcher: new @(with) operator.Kaz Kylheku2021-02-014-1/+74
| | | | | | | | | | | | * lisplib.c (match_instantiate): Ensure usr:with is interned. * share/txr/stdlib/match.tl (compile-with-match): New function. (compile-match): Wire in with operator. * tests/011/patmatch.tl: Test cases. * txr.1: Documented.
* matcher: rename @(let) to @(as).Kaz Kylheku2021-02-014-17/+17
| | | | | | | | | | | | | * lisplib.c (match_instantiate): Ensure usr:as is interned. * share/txr/stdlib/match.tl (compile-let-match): Rename to compile-as-match. (compile-match): Remove handling of let symbol; route as symbol to compile-as-match. * tests/011/patmatch.tl: Update all uses of let to as. * txr.1: Updated.
* matcher: restore nulling out of vars in @(or).Kaz Kylheku2021-02-011-12/+23
| | | | | | | | | | | | | * share/txr/stdlib/match.tl (compiled-match get-vars): Local function here becomes stand-alone defun, because we need it elsewhere. (compiled-mach wrap-guards): When processing the guard-disjunction object to produce the or branches, we calculate, for each branch, its own variables, and the variables of the preceding clauses. We generate code to set the previous variables to nil. Not all the previous variables, just those that are not also in the current clause. (get-vars): New function.
* matcher: adding test case for @(or) regression.Kaz Kylheku2021-02-011-0/+3
| | | | | | | * tests/011/patmatch.tl: New test case showing that @(or) no longer nulls out the variables from previous clauses like it used to. (2 2 nil) is returned, showing a is not set to nil when b matches.
* matcher: struct: move type test before slot tests.Kaz Kylheku2021-02-011-4/+2
| | | | | | | | | | | | | | | In the loose form of the @(struct ...) match, the struct type is matched by a pattern. This pattern should execute before the object is tested for the presence of the required slots by by guard1. It should not come between testing for the presence of slots, and then testing their contents. * share/txr/stdlib/match.tl (compile-struct-match): Do not lump together the type-match and slot-matches into a single all-matches list. Emit type-match's guard before guard1, and the slot-matches guards after. The order is basic test (guard0), struct type pattern match (type-match), slots-present (guard1) and then slot contents (slot-matches).
* matcher: struct: make guards lists; eliminate backquote.Kaz Kylheku2021-02-011-13/+15
| | | | | | * share/txr/stdlib/match.tl (compile-struct-match): make guard0 and guard1 lists match-guard items. Replace backquote with straight append.
* doc: mistake in example for @[...] pattern.Kaz Kylheku2021-02-011-3/+3
| | | | | | | * txr.1: Fix use of nonexistent odd function which should be oddp. The same example occurs in the test suite, but without this error. Also fix indentation in this and the two related examples above.
* matcher: bugfix: bad stray code in @[...] matcher.Kaz Kylheku2021-02-012-2/+5
| | | | | | | | | | * share/txr/stdlib/match.tl (compile-dwim-predicate-match): In he one-argument case, there is stray code referencing var-match.test-expr, which blows up. This is hit by exactly the one example in the documentation that was not added as a test case. * tests/011/patmatch.tl: Add test case from doc.
* doc: mistake in when-match rcons example.Kaz Kylheku2021-02-011-1/+1
| | | | | * txr.1: The de-sugared (rcons @a @b) example is missing a quote on the object, and so returns nil and not (1 2).
* Version 250txr-250Kaz Kylheku2021-01-316-249/+295
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* lib: get rid of alist_remove1 function.Kaz Kylheku2021-01-311-6/+1
| | | | | | | * lib.c (delete_package): This is the only user of alist_remove1. It can use remqual with a car_f key, which is more efficient. (alist_remove1): Function removed.
* @(rebind): bugfix: don't clobber right side variable.Kaz Kylheku2021-01-305-11/+79
| | | | | | | | | | | | | | | | | | | | | * Makefile (tst/tests/000/binding.ok): Pass -B to txr for this new test. * match.c (v_rebind): Fix gaping copy-and-paste bug here, which causes rebind to take on the behavior of local/forget; it takes all symbols that appear as its arguments from the environment and produces an environment in which they don't exist. What we want is to remove the left variables from the environment, and since that is a nested pattern, the right way to do that is to flatten it. Bug reported by Frank Schwidom. * tests/000/binding.txr: New file. * tests/000/binding.expected: New file. * txr.1: Improve documentation of @(rebind), also making improvements in @(set) documentation.
* doc: bad syntax formatting: partition and split.Kaz Kylheku2021-01-291-4/+4
| | | | | | * txr.1: Fix issues in the formatting of the index-list, index and function arguments of partition, partition*, split and split* functions.
* matcher: prune @nil in cons and vector matches.Kaz Kylheku2021-01-291-9/+19
| | | | | | | | | | | | | | | | | | Elimination of unused temporaries is really the job of the compiler, but we can do some simple things to get better code from the matcher in the meanwhile. In list and vector matches, @nil gets used just for placeholding. We can avoid generating the code which binds the corresponding value to an unused gensym. share/txr/stdlib/match.tl (compile-var-match): When the variable is nil, then do not generate a match-guard with empty content. Just generate an empty guard-chain. The higher level compiler can then check for this empty guard chain and prune its own material away. (compile-vec-match, compile-cons-structure): Eliminate every gensym and its initializing expression, whose corresponding compiled sub-match has an empty guard chain.
* matcher: bugfix: @nil isn't trivial.Kaz Kylheku2021-01-292-1/+2
| | | | | | | | | | | | | * share/txr/stdlib/match.tl (non-triv-pat-p): Extend sys:var match so (sys:var nil) is identified as trivial. * tests/011/patmatch.tl: Add broken test case fixed by this. This doesn't show up when @nil is used as the only match. It also doesn't show up if @nil is used in a vector or list in a mixture with other operators, because those other ones identify the overall list pattern as non-trivial. None of the occurrences of @nil in the existing test suite, like (@nil @nil @x) tickle the bug.