summaryrefslogtreecommitdiffstats
path: root/stdlib
Commit message (Collapse)AuthorAgeFilesLines
...
* awk: bug: fix ->> appending redirection operator.Kaz Kylheku2023-05-231-1/+1
| | | | | | | * stdlib/awk.tl (awk-state ensure-stream): Fix missing handling for the :apf kind symbol used by appending. * tests/015/awk-redir.tl: New file.
* awk: bug: broken redirection operators.Kaz Kylheku2023-05-231-2/+2
| | | | | | | * stdlib/awk.tl (sys:awk-redir): Fix regression from April 2018. The gensym variable introduced must be parallel bound, since it is referenced by the init expression of the other variable. This breaks all awk redirection operators.
* quips: reference to Super Dave Osborne.Kaz Kylheku2023-05-171-0/+1
| | | | * stdlib/quips.tl (%quips%): New entry.
* with-compile-options: reimplement using compiler-letKaz Kylheku2023-05-161-12/+14
| | | | | | | | | | | | | | | | | | | The with-compile-opts macro is rewritten such that it cad occur inside code that is being compiled, and change compiler options for individual subexpressions. It continues to work as before in scripted build steps such as when calls to (compile-file ...) are wrapped in it. However, for the time being, that now only works in interpreted code, because with this change, when a with-compile-opts form is compiled, it no longer arranges for the binding of *compile-opts* to be visible to the subforms; the binding affects the compiler's own environment. * stdlib/compiler.tl (with-compile-opts): Rewrite. * txr.1: Documented.
* New special operator: compiler-letKaz Kylheku2023-05-162-0/+11
| | | | | | | | | | | | | | | | | | | | | | * eval.c (compiler_let_s): New symbol variable. (op_let): Recognize compiler-let for sequential binding. (do_expand): Traverse and diagnose compiler-let form. (eval_init): Initialize compiler_let_s and register the interpreted version of the operator. * stdlib/compiler.tl (compiler compile): Handle compiler-let form. (compiler comp-compiler-let): New method. (no-dvbind-eval): New function. * autoload.c (compiler-set-entries): Intern the compiler-let symbol in the user package. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New special operator: progvKaz Kylheku2023-05-152-0/+28
| | | | | | | | | | | | | | | | | | | | | | Adding a progv operator, similar to the Common Lisp one. * eval.c (progv_s): New symbol variable. (op_progv): New static function. (do_expand): Recognize and traverse the progv form. (rt_progv): New static function: run-time support for compiled progv. (eval_init): Initialize progv_s, and register the the op_progv operator interpreting function. * stdlib/compilert (compiler compile): Handle progv operator ... (compiler comp-progv): ... via this new method. * tests/019/progv.tl: New file. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* quips: piano-related quip.Kaz Kylheku2023-05-151-0/+1
| | | | * stdlib/quips.tl (%quips%): New entry.
* quips: new dad joke about the meta-object protocolKaz Kylheku2023-05-141-0/+1
| | | | * stdlib/quips.tl (%quips%): New entry.
* bug: symbol-value place always global.Kaz Kylheku2023-05-141-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | We have a problem. If v is a dynamic variable, then the form (let (v) (set (symbol-value 'v) 3)) is not behaving correctly; it's updating the top-level value of v not the rebound one. * eval.c (set_symbol_value): New static function. (eval_init): Register sys:set-symbol-value intrinsic. The top-vb variable, though no longer referenced by the symbol-value place, because existing compiled code depends on it. * stdlib/place.tl (symbol-value): Rewrite the place logic to use symbol-value to access the variable, and set-symbol-value to update it, instead of referencing sys:top-vb. (sys:get-vb): This function has to stay, because it provides run-time support for code compiled with the buggy version of the place. * tests/019/symbol-value.tl: New file.
* compiler: spelling error in diagnostic.Kaz Kylheku2023-05-121-1/+1
| | | | | * stdlib/compiler.tl (with-compile-opts): Remove stray character from "uncrecognized".
* Version 286.txr-286Kaz Kylheku2023-05-071-1/+1
| | | | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date. * txr.vim, tl.vim: Regenerated.
* defstruct: diagnostic improvement for boa args.Kaz Kylheku2023-05-051-2/+2
| | | | | | | | | | | | | | * struct.tl (defstruct): When generating the lambda that initializes slots from boa arguments, instead of we use (set (qref obj slot) val) instead of slotset. The qref macro will diagnose use of nonexistent slots.Thus warnings are produced for, say: (defstruct (point x y) nil) where x and y have not been defined, using the imperfect approach of the qref implementation, which is better than nothing.
* compiler: multiple issues in macro-parameter forms.Kaz Kylheku2023-05-051-24/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a defmacro form is compiled, the entire form is retained as a literal in the output. This is wasteful and gives away the source code. In spite of that, errors in using the macro are incorrectly reported against defmacro, because that is the first symbol in the form. These issues arise with what arguments are passed as the first two parameters of the compiler's expand-bind-mac-params function, and what exactly it does with them. We make a tweak to that, as well as some tweaks to all the calls. * stdlib/compiler.tl (expand-bind-mac-params): There is a mix-up here in that both the ctx-form and err-form arguments are ending up in the compiled output. Let's have only the first agument, ctx-form going into the compiled output. Thus that is what is inserted into the sys:bind-mach-check call that is generated. Secondly, ctx-form should not be passed to the constructor for mac-param-parser. ctx-form is a to-be-evaluated expression which might just be a gensym; we cannot use it at compile time for error reporting. Here we must use the second argument. Thus the second argument is now used only for two purposes: copying the source code info to the output code, and for error reporting in the mac-param-parser class. This second purpose is minor, because the code has been passed through the macro expander before being compiled, which has caught all the errors. Thus the argument is changed to rlcp-form, reflecting its principal use. (comp-tree-bind, comp-tree-case): Calculate a simplified version of the tree-bind or tree-case form for error reporting and pass that as argument the ctx-form argument of expand-bind-mac-params. Just pass form as the second argument. (comp-mac-param-bind, comp-mac-env-param-bind): Just pass form as the second argument of expand-bind-mac-params.
* compiler: bugfix: wrong condition in late-peephole.Kaz Kylheku2023-05-041-1/+1
| | | | | | | | | | | * stdlib/optimize.tl (basic-blocks late-peephole): The test whether lab2 is used is bogus, and will never be true. The correct test is simply whether the block has two or more rlinks. This makes no difference in the standard library images. When the bug appears, the manifestation would be that a needed label is deleted, resulting in an exception from the assembler.
* compiler: liveness bug involving closures.Kaz Kylheku2023-05-041-3/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 2022-09-13 commit 6e354e1c2d5d64d18f527d52db75e344a9223d95, subject "compiler: bugfixes in dead code elimination", introduced a problem. By allowing the closure body blocks to be included in the links of the previous basic block that ends in the close instruction, it caused liveness info to flow out out of close blocks into the close instruction, which is wrong. Thus registers used inside a closure, which are entirely private, wrongly appear live outside of the closure, interfering with optimizations like eliminating dead registers. We can't simply roll back the commit because the bug it fixes will reappear. The fix is to pair the next field with a prev field, and maintain them; don't rely on the rlinks to point to the previous block. * stdlib/optimize.tl (basic-block): New slot, prev. (back-block join-block): As we delete the next block, we must update that block's next block's prev link. (basic-blocks link-graph): Build the prev links. Fix the bug in handling the close instruction: do not list the close body code among the links, only the branch target of the close. (basic-blocks do-peephole-block): In a few cases in which we set the bl.next to nil, we also set the bl.next.prev to nil, if bl.next exists. (basic-blocks elim-dead-clode): Reset the bl.prev of every block also. (basic-block check-bypass-empty): Here, we no longer depend on rlinks containing the previous block; the prev gives it to us. So we move that fixup out of the link, and also fix up the next blocks prev pointer.
* sort: support stable sorting via ssort and snsort.Kaz Kylheku2023-05-021-2/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | For array-like objecgts, these objects use an array-based merge sort, using an auxiliary array equal in size to the original array. To provide the auxiliary array, a new kind of very simple vector-like object is introduced into the gc module: protected array. This looks like a raw dynamic C array of val type, returned as a val *. Under the hood, there is a heap object there, which makes the array traversable by the garbage collector. The whole point of this exercise is to make the new mergesort function safe even if the caller-supplied functions misbehave in such a way that the auxiliary array holds the only references to heap objects. * gc.c (struct prot_array): New struct, (prot_array_cls): New static variable. (gc_late_init): Register COBJ class, retaining in prot_array_cls. (prot_array_mark, prot_array_free): New static functions. (prot_array_ops): New static structure. (prot_array_alloc, prot_array_free): New functions. * gc.h (prot_array_alloc, prot_array_free): Declared. * lib.c (mergesort, ssort_vec): New static function. (snsort, ssort): New functions. * lib.h (snsort, ssort): Declared. * tests/010/sort.tl: Cover ssort. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* hash: new function, hash-props.Kaz Kylheku2023-05-011-0/+1
| | | | | | | | | | | | | | | | We don't have a function in the hash table module which can create a populated hash table in one step without requiring the caller to create auxiliary lists. This new function fills that gap, albeit with some limitations. * hash.c (hash_props): New function. (hash_init): Register hash-props intrinsic. * tests/010/hash.tl: New tests. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* time: improved convenience in time functions.Kaz Kylheku2023-04-301-0/+2
| | | | | | | | | | | | | | | | * time.c (time_str_local, time_str_utc): New static functions. (time_fields_local, time_fields_utc, time_struct_local, time_struct_utc): Time argument becomes optional, defaulted to current time. (time_init): Use time_s symbol instead of interning twice. Register new time-str-local and time-str-utc intrinsics. Fix registration of functions that take optional args. * txr.1: New functions documented; optional arguments documented; existing documentation revised. * stdlib/doc-syms.tl: Updated.
* match: ^#S() and ^#H(()) patterns must workKaz Kylheku2023-04-291-1/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Quasiquote patterns not containing unquotes are not working, because the parser transforms them into quoted objects. For instance ^#S(time) becomes the form (quote #S(time)) and not the form (sys:qquote (sys:struct-lit time)). The pattern matching compiler doesn't treat quote specially, only sys:qquote. * parser.y (unquotes_occur): Function removed. (vector, hash, struct, tree, json_vals, json_pairs): Remove use of unquotes_occur. Thus vector, hash, struct, tree and JSON syntax occurring within a backquote will be turned into a special literal whether or not it contains unquotes. * lib.c (obj_print_impl): Do not print the form (sys:hash-lit) as #Hnil, but #H(). * stdlib/match.tl (transform-qquote): Add a case which will handle ^#H(), as if it were ^H(()). Bugfix in the ^H(() ...) case. The use of @(coll) means it fails to match the empty syntax when no key/value pairs are specified, whereas @(all) respects vacuous truth. * test/011/patmatch.tl: A few tests. * y.tab.shipped, y.tab.h.shipped: Updated.
* compiler: simplify live-info defined set semantics.Kaz Kylheku2023-04-181-6/+4
| | | | | | | | * stdlib/optimize.tl (basic-blocks local-liveness): Just store the mask of defined registers into each live-info. Do not propagate the defined mask from the next instruction backwards. The way the defined mask is used in calc-liveness, this makes no difference, and is simpler and faster.
* compiler: bugfix: lingering funarg eval order issue.Kaz Kylheku2023-04-171-3/+1
| | | | | | | | * stdlib/compiler.tl (compiler comp-call-impl): We can no longer free the temporary registers as-we-go based on whether the argument expression frag uses them as the output register frag. Let's just put them all into the aoregs list to be freed afterward.
* compiler: propagate t-reg rename into end insn.Kaz Kylheku2023-04-171-1/+1
| | | | | | | | * stdlib/optimize.tl (basic-blocks rename): When we stop the renaming due to an end instruction and the src being a v-reg, we can still do the rename in that end instruction itself. If the v-reg becomes invalid, that doesn't happen until after the instruction.
* compiler: rewrite t-regs through defining instruction.Kaz Kylheku2023-04-171-6/+24
| | | | | | | | | | | | | * stdlib/optimize.tl (subst-preserve): Rename list param to insn for clarity. (careful-subst-preserve): New function. This is like subst-preserve, but used only for instructions that have destination registers. It performs a rewrite such that those destination positions are avoided. (basic-blocks rename): When the instruction has src or dst as a target, don't just stop before that insn. Do the substitution in the source operands using careful-subst-preserve.
* compiler: move peephole pattern and remove condition.Kaz Kylheku2023-04-171-15/+11
| | | | | | | | | | | | | | | | | * stdlib/optimize.tl (basic-blocks do-peephole-block): Remove the local function only-locally-used-treg. This is unnecessary because the optimization is valid even if the treg is used in downstream basic blocks. It was necessary previously in the old version of this optimization in which we deleted the first instruction which sets the treg's value. We are now depending on it being identified as a dead register. Also, moving the rule to the end. The reason is that there are cases when the pattern matches, but it returns insns. That causes the rewrite macro to march down to the next instruction, skipping other patterns. This could be bad, unless the pattern is the last one tried before the @else fallback.
* compiler: better handling for mutated locals in funargs.Kaz Kylheku2023-04-171-20/+49
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Instead of the conservative strategy in compiler comp-var of loading variables into t-registers, and relying on optimization to remove them, let's just go back to the old way: variables are just registers. For function calls, we can detect mutated variables and generate the conservative code. * stdlib/compiler.tl (frag): New slots vbin and alt-oreg. When a variable access is compiled, the binding is recorded in vbin, and the desired output register in alt-oreg. (simplify-var-spy): New struct type, used for detecting mutated lexical variables when we compile a function argument list. (compiler comp-var): Revert to the old compilation strategy for lexicals: the code fragment is empty, and the output register is just the v-reg. However, we record the variable binding and remember the caller's desired register in the new frag fields. (compiler comp-setq): Also revert the strategy here. Here we get our frag from a recursive compilation, so we just annotate it. (compiler comp-call-impl): Use the simplify-var-spy to obtain a list of the lexical variables that were mutated. This is used for rewriting the frags, if necessary. (handle-mutated-var-args): New function. If the mutated-vars list is non-empty, it rewrites the frag list. Every element in the frag which is a compiled reference to a lexical variable which is mutated over the evaluation of the arg list is substituted with a conservative frag which loads the variable into a temporary register. That register thus samples the value of the variable at the correct point in the left-to-right evaluation, so the function is called with the correct values.
* compiler: allow v reg source in t-reg optimizationKaz Kylheku2023-04-161-13/+15
| | | | | | | | | | | | This change is now possible due to the previous bugfix. * stdlib/optimize.tl (basic-blocks rename): If the source register is a v-reg, do not allow the propagation past an end instruction. This is a precaution because the end instruction could be the end of the frame in which the v-register is valid; we don't want to propagate it outside of that frame.
* compiler: bugfix: wrong propagation into close insn.Kaz Kylheku2023-04-161-1/+3
| | | | | | | | | * stdlib/optimize.tl (basic-blocks rename): When we encounter a close instruction, we must leave it alone. The registers named in the argument area of the instruction do not belong to the current instruction stream or basic block; they belong to the function body.
* compiler: tighten cases in liveness calculationKaz Kylheku2023-04-151-8/+8
| | | | | | | | * stdlib/optimize.tl (basic-blocks local-liveness): Handle all instructions explicitly with no catch-all behavior. Make a copy of the live-info even for instructions that have no source or destination operands, so that they don't mistakenly marked as having defs or refs.
* compiler: keep track of multiple defs in live-info.Kaz Kylheku2023-04-101-17/+22
| | | | | | | | | | | * stdlib/optimize.tl (live-info): Slot def replaced by def0 and def1. (basic-blocks local-liveness): The local function def becomes defs: it can take two defs. These become def0 and def1. In the catch instruction case, we use both arguments, capture the resulting live-info and use it to call refs. (basic-blocks rename): Check whether either def0 or def1 is the source or destination.
* compiler: streamline live-info object creation.Kaz Kylheku2023-04-101-9/+8
| | | | | | | | | | | | | | * stdlib/optimize.tl (basic-blocks local-liveness): When processing a pure def, we don't copy the live-info unconditionally, which is waseteful since if the destination register is a t-reg, we will invoke (new live-info) to make yet another live info. Instead, let's destructively mutate the incoming live info from the instruction below, and return a copy that is made before that is done. In the def-ref case, the local copy is entirely superfluous, because in all cases we return a new object. We also eliminate redundant (set [bb.li-hash insn] li) evaluations.
* compiler: bug in liveness calculation over catch insnKaz Kylheku2023-04-101-1/+4
| | | | | | | | | * stdlib/optimize.tl (basic-blocks local-liveness): The exception symbol and argument registers in the catch instruction are clobbers, not references. We must treat them as defs. Unfortunately, the instruction has two clobbers but live-info has only one def slot, which should be fixed.
* compiler: improve t-reg copy elimination.Kaz Kylheku2023-04-101-7/+18
| | | | | | | | | | | | | * optimize.tl (rename): Instead of a mapping operation, we perform the substitution only until we hit an instruction that defines either the src or dst register. (basic-blocks do-peephole-block): Drop the conditions for doing the rename: that neither register can be defined somewhere in the rest of the block. This restriction is too limiting. We have to be careful now; we cannot delete the first instruction, and must only set the recalc flag and add to the rescan list if the substitution did something, to avoid looping.
* compiler: buggy t-reg move peephole case.Kaz Kylheku2023-04-101-3/+1
| | | | | | | | | | | * stdlib/optimize.tl (basic-blocks do-peephole-block): In the unnecessary copying t-reg case, let's just stay away from doing it if the source operand is a v-reg. It breaks under the recent "eval order of variables" commit, indicating that the conditions that it uses for replacing a v-reg with the t-reg are not correct. The most likely reason is that the v-reg can be assigned, but this doesn't show up in the liveness info which tracks only t-regs.
* build: rearrange code to fix circular dependency.Kaz Kylheku2023-04-091-28/+28
| | | | | | | | | | | | | * stdlib/build.tl (sys:list-builder-flets, sys:build-expander, build, buildn): Move to top of file. This resolves a circular dependency triggered by the defstruct macro: it autoloads struct.tl which autoloads other things, some of which depend on the build macro. If we provide the build macro at the top, everything is cool. The compiled version of build.tl doesn't have this problem, because macro-time dependencies don't affect compiled code. With this change, it's possible to run the tests/012/compile.tl test case without stdlib being compiled.
* compiler: small fix in optimizer.Kaz Kylheku2023-04-081-2/+2
| | | | | | * stdlib/optimizer.tl (basic-blocks do-peephole-block): Use pushnew instead of push in one peephole case, so the block isn't pushed onto the tryjoin and rescan lists twice.
* compiler: bugfix: eval order of variables.Kaz Kylheku2023-04-081-2/+2
| | | | | | | | | | | | | | | | | | | | | We have the following problem: when function call argument expressions mutate some of the variables that are being passed as arguments, the left-to-right semantics isn't obeyed. The problem is that the funcction call simply refers to the registers that hold the variables, rather than to the evaluated values. For instance (fun a (inc a)) will translate to something like (gcall <n> (v 3) (v 3)) which is incorrect: both argument positions refer to the current value of a, whereas we need the left argument to refer to the value before the increment. * stdlib/compiler.tl (compiler comp-var): Do not assert the variable as the output register, with null code. Indicate that the value is in the caller's output register, and if necessary generate the move. (compiler comp-setq): When compiling the right-hand-side, use the original output register, so that we don't end up reporting the variable as the result location.
* compiler: discard wrongheaded discards.Kaz Kylheku2023-04-081-55/+41
| | | | | | | | | | | | | | | | | | * stdlib/compiler.tl (compiler): Remove discards slot. (compile-in-toplevel, compile-with-fresh-tregs): Do not save and restore discards. (compiler maybe-mov): Method removed. It doesn't require the compiler object so it can just be a function. (maybe-mov): New function. (compiler alloc-discard-treg): Method removed. (compiler free-treg): No need to do anything with discards. (compiler maybe-alloc-treg): No need to check discards. (compiler (comp-setq, comp-if, comp-ift, comp-switch, comp-block, comp-catch, comp-let, comp-fbind, comp-lambda-impl, comp-or, comp-tree-case, comp-load-time-lit): Use maybe-mov function instead of method. (compiler comp-progn): Use alloc-treg rather than alloc-discard-treg, and use maybe-mov function.
* compiler: iterate on level 4-5 optimizations.Kaz Kylheku2023-04-072-9/+11
| | | | | | | | | | | | | * stdlib/optimize.tl (basic-blocks num-blocks): New method. * stdlib/compiler.tl (compiler optimize): At optimization level 6, instead of performing one extra pass of jump threading, dead-code elimintation and peephole optimizations, keep iterating on these until the number of basic blocks stays the same. * txr.1: Documented.
* compiler: optimization improvementsKaz Kylheku2023-04-073-73/+85
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * stdlib/optimize.tl (basic-blocks peephole-block): Drop the code argument, and operate on bl.insns, which is stored back. Perform the renames in the rename list after the peephole pass. (basic-blocks rename): New method. (basic-blocks do-peephole-block): Implementation of peephole-block, under a new name. The local function called rename is removed; calls to it go to the new rename method. (basic-blocks peephole): Simplify code around calls to peephole-block; we no longer have to pass bl.insns to it, capture the return value and store it back into bl.insns. * stdlib/compiler.tl (*opt-level*): Initial value changes from 6 to 7. (compiler optimize): At optimization level 6, we now do another jump threading pass, and peephole, like at levels 4 and 5. The peephole optimizations at level 5 make it possible to coalesce some basic blocks in some cases, and that opens up the possibility for more reductions. The previously level 6 optimizations are moved to level 7. * txr.1: Updated documentation of optimization levels, and default value of *opt-level*. * stdlib/doc-syms.tl: Updated.
* compiler: small local refactoring in optimizer.Kaz Kylheku2023-04-061-8/+4
| | | | | | | * stdlib/optimize.tl (basic-blocks peephole-block): Move local rename function into main labels block, so other optimizations will be able to use it. Remove an unused argument, and change the recursion to a mapcar, since that's what it's doing.
* conda/condlet: fix broken scope.Kaz Kylheku2023-04-061-8/+9
| | | | | | | | | | | Contrary to the documentation, the later clauses of a condlet have the earlier clause variables in scope. * stdlib/ifa.tl (sys:if-to-cond): Change to different, non-nesting expansion strategy. We lose the cond-oper parameter. (conda, condlet): Drop second parameter from calls to if-to-cond.
* quips: new car/cdr humor.Kaz Kylheku2023-04-041-0/+2
| | | | | * stdlib/quips.tl (%quips%): Two new entries punning on carcdr.
* Version 285.txr-285Kaz Kylheku2023-03-281-1/+1
| | | | | | | | | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date. * txr.vim, tl.vim: Regenerated. * time.c (struct tm_wrap): Fix for platforms without HAVE_TM_ZONE. We still need tm_wrap defined, just not the zone member. Out of the platforms I build releases for, Solaris is the only one like this.
* doc: compiler-opts typo.Kaz Kylheku2023-03-271-1/+1
| | | | | | | * txr.1: Fix compiler-opts, *compiler-opts* and with-compiler-opts to the correct "compile". * stdlib/doc-syms.tl: Updated.
* New function: arithp.Kaz Kylheku2023-03-261-0/+1
| | | | | | | | | | | | | | | | | | | * lib.h (arithp): Declared. (plus_s): Existing symbol declared. * arith.c (arithp): New function. * struct.h (special_slot): New enum member plus_m. * struct.c (special_sym): Register plus_s together as the [plus_m] entry of the array. * tests/016/arith.tl * tests/016/ud-arith.tl: Tests for arithp. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* compiler/doc: document compiler-opts and enable unused warningKaz Kylheku2023-03-232-2/+7
| | | | | | | | | | * stdlib/compiler.tl (sys:env shadow-fun): Also diagnose if a global macro is shadowed. * txr.1: Documented compiler-opts structure, *compiler-opts* variable and with-compiler-opts macro. * stdlib/doc-syms.tl: Updated.
* match: support @nil in predicates.Kaz Kylheku2023-03-231-3/+9
| | | | | | | | | | | | | | | | | For instance @(<= 10 @nil 20) is a pattern which matches a number between 10 and 20, without binding a variable. * stdlib/match.tl (compile-predicate-match): Looks like this code was already halfway expressing the intent that the avar could be nil, because arg-var takes the value of avar if that is non-nil, otherwise a gensym is substituted. What was missing was that the gensym that replaces nil must also be substituted into the predicate. * tests/011/patmatch.tl: New tests. * txr.1: Document that the variable embedded in a predicate may be null.
* lib: address remaining unused variable warnings.Kaz Kylheku2023-03-2224-123/+142
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * stdlib/arith-each.tl (sys-arith-each): Remove :form param. * stdlib/awk.tl (awk-state :fini): Suppress unused warning in dohash form by using an uninterned symbol for this variable. This is a useful technique worth documenting. (awk-expander): Remove unused varaible in a predicate pattern. (awk-code-move-check): Lose the unused awc and aws-sym. (awk-mac-let): Don't pass the unused parameters to awk-code-move-check. * stdlib/conv.tl (conv-expand): Remove unused gensym. * stdlib/debugger.tl (fcall-frame loc, fcall-frame print-trace, expand-frame print-trace): Mark unused parameters ignored. * stdlib/defset.tl (defset-expander-simple): Remove unused parameter. (defset): Drop argument from defset-expander-simple call, and also fix unused warning in tree-case form. * stdlib/doc-lookup.tl (detached-run): Remove unused variable from a pattern matching predicate. It's not in the rightmost position so we have to revers the comparison. I will enhance the pattern matcher to support @nil in a predicate. (toplevel): Ignore a parameter of the not-implemented version of the open-url function. * stdlib/doloop.tl (expand-dooloop): Replace unused variable in a tree binding pattern with the t symbol. * stdlib/each-prod.tl (expand-each-prod*): Remove unused let variable. * stdlib/except.tl (expand-handle): Put else variable in tree bind pattern to use. * stdlib/getopts.tl (opt-desc (basic-type-p, cumul-type-p)): Replace unused catch-all variable in tree bind pattern with t symbol. (opt-processor parse-opts): Remove unused args argument. The object holds the args, prepared at construction time. (getopts, option-base getopts): Don't pass args to parse-opts. (define-option-struct): Replace unused treee pattern variable with t. * stdlib/ifa.tl (if-to-cond): Put catch-all else variable to use. * stdlib/keyparams.tl (param-expander): Mark unused parameter ignored. Replace unused variables in tree-case with t. * stdlib/match.tl (compile-struct-match, compile-predicate-match, compile-require-match, compile-as-match, compile-with-match, compile-or-match, compile-and-match, compile-not-match, compile-hash-match, compile-scan-match, compile-exprs-match): Address unused variables in mac-param-bind and tree-bind patterns. (match-case): Likewise, and also remove unused let variables. (while-match-case, while-true-match-case): Remove unused :env parameter. (expand-lambda-match): Remove unused let variable. (defun-match): Remove unused variable in tree-bind. (define-param-expander): Mark menv parameter ignored. Unused variables in tree-bind. (defmatch): Replace lambda variable with a gensym. (loosen, pat-len): Remove unused parameter. (sme, end): Fix calls to loosen and pat-len. (non-triv-pat-p): Mark parameter ignored in the temporary version of this function. (expand-quasi-match): Address unused variables in patterns, and remove unused gensyms. * stdlib/op.tl (op-rec-p): Unused variable in tree-case. (op-alpha-rename): Remove f parameter. (op-ignerr): Mark catch handler parameter ignored. (op-expand): Remove argument from calls to op-alpha-rename. * stdlib/path.test (if-windows, if-native-windows): The compiler complains here about the unused variable due to constant folding. We use the use function to indicate that the variable is not ignored, but used. * stdlib/pic.tl (expand-pic-num): Remove unused let variable. (pic): Remove unused :env parameter. * stdlib/place.tl (macroexpand-1-place): Ignore unused env parameter. (pset): Ignore some tree-bind variables. Not replacing them with t because their names help code readability. Lots of tricky code in place.tl. (shift): Replace unused variable with t in tree-case. (vecref, chr-str, ref, sub): Deal with unused expander parameters. (gethash): Deal with unused place parameter. (dwim): Remove unused env parameter, and deal with unused place parameters. (get-fun-getter-setter): Unused variables in tree-bind. (read-once, define-modify-macro): Remove unused gensyms. (placelet-1): Mark ignored a parameter of an update expander lambda. * stdlib/pmac.tl (macroexpand-params): Fix unused catch-all in tree-case. * stdlib/struct.tl (prune-missing-inits): Mark tree-bind unused variable ignored. (defstruct): Unused tree-case variable. (qref): Unused tree-case catch-all variables. (rslot): Unused parameter removed. (:delegate): Unused tree-case variables. * stdlib/tagbody.tl (tagbody): Drop unused :env param. Mark ignored the threaded-2 let variable, which cannot be removed because its init-form performs a needed side effect. * stdlib/trace.tl (trace-leave): Remove unused param. (trace): Don't pass argument to unused param of trace-leave. (untrace): Use gensym in dohash to suppress unused variable warning. * stdlib/type.tl (typecase-expander): Unused variable in tree-case. * stdlib/with-resources.tl (with-resources): Likewise. * stdlib/yield.tl (hlet-expand): Remove two unused locals. * tests/012/lambda.tl: Fix test cases that break the tests due to unused variable warnings. * tests/016/arith.tl: Add test case for each-prod*. At first I thought a bug was found in it but it turned out that the init-forms variable that was removed was really superfluous.
* compiler: dohash: source location propagationKaz Kylheku2023-03-221-8/+10
| | | | * stdlib/compiler.tl (expand-dohash): Add missing rlcp.
* compiler: forward source location for defun and defmacroKaz Kylheku2023-03-221-11/+15
| | | | | | | | | | | | | | * stdlib/compiler.tl (expand-defun): Sprinkling of rlcp to pass source location info to the generated lambda, and to the sys:define-method call. (expand-defmacro): bugfix here: in with-gensyms we shadowed the form parameter, and then passed that as both form arguments to expand-bind-mac-params. We rename the gensym to mform, and then for the error-form, we pass the original form, quoted as necessary and with source location info. Thus, now source location info flows from the original defmacro form to the generated let* which binds the destructured parameters.