summaryrefslogtreecommitdiffstats
path: root/stdlib
Commit message (Collapse)AuthorAgeFilesLines
...
* compiler: recognize T0 register (nil) as constant.Kaz Kylheku2023-07-151-2/+4
| | | | | | * stdlib/optimize.tl (basic-blocks do-peephole-block): The constant folding case should fire even if some of the arguments of the call aren't D registers but T0.
* compiler: move material into constfun.tlKaz Kylheku2023-07-153-30/+32
| | | | | | | | | | | | | * stdlib/compiler.tl (%effect-free-funs%, %effect-free%, %functional-funs%, %functional%): Move variables into stdlib/constfun.tl * stdlib/constfun.tl %effect-free-funs%, %effect-free%, %functional-funs%, %functional%): Moved here. * stdlib/optimize.tl: Use load-for to express dependency on constfun module; don't depend on the compiler having loaded it.
* compiler: constant folding in optimizer.Kaz Kylheku2023-07-152-5/+43
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The compiler handles trivial constant folding over the source code, as a source to source transformation. However, there are more opportunities for constant folding after data flow optimizations of the VM code. Early constant folding will not fold, for instance, (let ((a 2) (b 3)) (* a b)) but we can reduce this to an end instruction that returns the value of a D register that holds 6. Data flow optimizations will propagate the D registers for 2 and 3 into the gcall instruction. We can then recognize that we have a gcall with nothing but D register operands, calling a constant-foldable function. We can allocate a new D register to hold the result of that calculation and just move that D register's value into the target register of the original gcall. * stdlib/compiler.tl (compiler get-dreg): When allocating a new D reg, we must invalidate the datavec slot which is calculated from the data hash. This didn't matter before, because until now, get-datavec was called after compilation, at which point no new D regs will exist. That is changing; the optimizer can allocate D regs. (compiler null-dregs, compiler null-stab): New methods. (compiler optimize): Pass self to constructor for basic-blocks. basic-blocks now references back to the compiler. At optimization level 5 or higher, constant folding can now happen, so we call the new method in the optimizer to null the unused data. This overwrites unused D registers and unused parts of the symbol vector with nil. * stdlib/optimize (basic-blocks): Boa constructor now takes a new leftmost param, the compiler. (basic-blocks do-peephole-block): New optimization case: gcall instruction invoking const-foldable function, with all arguments being dregs. (basic-blocks null-unused-data): New method.
* Math library: add numerous C99 functions.Kaz Kylheku2023-07-151-115/+159
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * configure: Detect all the new functions, with separate tests for the unary and binary ones. * arith.c (cbrt_s, erf_s, erfc_s, exp10_s, exp2_s, expm1_s, gamma_s, j0_s, j1_s, lgamma_s, log1p_s, logb_s, nearbyint_s, rint_s, significand_s, tgamma_s, y0_s, y1_s, copysign_s, drem_s, fdim_s, fmax_s, fmin_s, hypot_s, jn_s, ldexp_s, nextafter_s, remainder_s, scalb_s, scalbln_s, yn_s, r_copysign_s, r_drem_s, r_fdim_s, r_fmax_s, r_fmin_s, hypot_s, r_jn_s, r_ldexp_s, r_nextafter_s, r_remainder_s, r_scalb_s, scalbln_s, r_yn_s): New symbol variables. (not_available): New static function. (cbrt_wrap, erf_wrap, erfc_wrap, exp10_wrap, exp2_wrap, expm1_wrap, gamma_wrap, j0_wrap, j1_wrap, lgamma_wrap, log1p_wrap, logb_wrap, nearbyint_wrap, rint_wrap, significand_wrap, tgamma_wrap, y0_wrap, y1_wrap, copysign_wrap, drem_wrap, fdim_wrap, fmax_wrap, fmin_wrap, hypot_wrap, jn_wrap, ldexp_wrap, nextafter_wrap, remainder_wrap, scalb_wrap, scalbln_wrap, yn_wrap): New static functions. (arith_set_entries, arith_instantiate): New static functions. (arith_init): Initialize symbols and instantiate functions via autoload mechanism. In a program that doesn't use the functions, we suffer only the overhead of interning the symbols. * lib.h (UNUSED): New macro for GCC unused attribute. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* Fix diagnostics which call non-symbol a symbol.Kaz Kylheku2023-07-111-1/+1
| | | | | | | | | | * eval.c (me_load_for): An object which is not one of the valid clause symbols is not necessarily a symbol; don't call it one in the diagnostic. * stdlib/struct.tl (sys:check-slot): Similarly, an object that isn't the name of a struct slot isn't necessarily a symbol; don't call it one.
* doc: document SHA-1 support.Kaz Kylheku2023-07-081-4/+9
| | | | | | * txr.1: SHA-1 functions documented. * stdlib/doc-syms.tl: Updated.
* Version 289.txr-289Kaz Kylheku2023-07-021-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. * protsym.c: Regenerated.
* New cached sorting functions.Kaz Kylheku2023-06-282-0/+47
| | | | | | | | | | | | | | | | | | These functions are useful when sorting a sequence using an expensive keyfun. * autoload.c (csort_set_entries, csort_instantiate): New static functions. (autlod_init): Register autoloading of csort module via new functions. * stdlib/csort.tl: New file. * tests/012/sort.tl: csort functions included in tests. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New function: hash-map.Kaz Kylheku2023-06-281-0/+1
| | | | | | | | | | | | | | | | | | | | hash-map converts a function mapping over a sequence into a hash table. * hash.[ch] (hash_map): New function. * tests/010/hash.tl: Test case. * genman.txr: The hash-map identifier introduces a hash collision. We have to deal with that somehow now. (colli): We put the conflicting entries into a new hash called colli which maps them to an increment value. (hash-title): Increment the hash code h by the amount indicated in colli, if the title is found there. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* eval: take macro environment.Kaz Kylheku2023-06-271-131/+131
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | With this change we fix the bug that the debugger commands yield their Lisp forms rather than evaluating them. * eval.c (eval_intrinsic): Takes one more argument, the macro environment. This is passed into env_to_menv as the root macro environment. (eval_init): Update registration of eval intrinsic to have two optional arguments. * eval.h (eval_intrinsic): Declaration updated. * parser.c (read_file_common, read_eval_ret_last): Pass nil argument to new parameter of eval_intrinsic. (repl): Pass the env parameter as the new menv parameter of eval_intrinsic, rather than the existing env parameter. This fixes the command dispatch in the debugger, since the command table is consists of symbol macros, and not variables. For instance the backtrace command bt is a binding of the bt symbol to the form (sys:print-backtrace), which has to be substituted for it and executed. When that envrionment is used as the ordinary environment, bt looks like a variable whose value is the list (sys:backtrace). * parser.y (elem, check_parse_time_action): Fix eval_intrinsic calls. * txr.c (txr_main): Likewise. * txr.1: Documented. * y.tab.c.shipped: Updated. * stdlib/doc-syms.tl: Updated.
* quips: procrastination quip.Kaz Kylheku2023-06-171-0/+1
| | | | * stdlib/quips.tl (%quips%): New one.
* New macro: match-cond.Kaz Kylheku2023-06-122-0/+21
| | | | | | | | | | | | | * stdlib/match.tl (match-cond): New macro. * autoload.c (match_set_entries): match-cond triggers autoload of match module. * tests/011/patmatch.tl: Tests. * txr.1: Documented. * stdlib/doc.tl: Updated.
* New @(push) directive.Kaz Kylheku2023-06-121-8/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | @(push) is like @(output), but feeds back into input. Use carefully. * parser.y (PUSH): New token. (output_push): New nonterminal symbol. (output_clause): Handle OUTPUT or PUSH via output_push. Some logic moved to output_helper. (output_helper): New function. Transforms both @(output) and @(push) directives. Checks both for valid keywords; push has only :filter. * parser.l (grammar): Recognize @(push similarly to other directives. * lib.[ch] (push_s): New symbol variable. * match.c (v_output_keys): Internal linkage changes to external. (v_push): New function. (v_parallel): We must fix the max_line algorithm not to use an initial value of zero, because lines can go negative thanks to @(push). We end up rejecting the pushed data. (v_collect): We can no longer assert that the data line number doesn't retreat. (dir_tables_init): Register push directive in table of vertical directives. * match.h (append_k, continue_k, finish_k): Existing symbol variables declared. (v_output_keys): Declared. * y.tab.c.shipped, * y.tab.h.shipped, * lex.yy.c.shipped: Updated. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* Version 288.txr-288Kaz Kylheku2023-06-101-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.
* New functions keep-keys-if, separate-keys.Kaz Kylheku2023-06-071-0/+2
| | | | | | | | | | | * lib.[ch] (keep_keys_if, separate_keys): New functions. * eval.c (eval_init): keep-keys-if, separate-keys intrinsics registered. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New functions load-args-recurse and load-args-processKaz Kylheku2023-06-052-0/+51
| | | | | | | | | | | | * autoload.c (load_args_set_entries, load_args_instantiate): New static functions. (autoload_init): Register new auto-loaded module "load-args". * stdlib/load-args.tl: New file. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* compiler: more logging regarding compiled files.Kaz Kylheku2023-06-051-12/+23
| | | | | | | | * stdlib/compiler.tl (clean-file): Under a log-level of 1 or more, report clean-file removes a file. (compile-update-file): Under a log level of 1 or more, report when a compiled file was skipped due to being up-to-date.
* compiler: new compiler option log-levelKaz Kylheku2023-06-041-3/+15
| | | | | | | | | | | | | | | | | | With log-level, we can obtain trace messages about what file is being compiled and individual forms within that file. * autoload.c (compiler_set_entries): Intern the slot symbol log-level. * stdlib/compiler.tl (compile-opts): New slot, log-level. (%warning-syms%): Add log-level to %warning-syms%. Probably we need to rename this variable. (compile-file-conditionally): Implement the two log level messages. (with-compile-opts): Allow/recognize integer option values. * txr.1: Documented.
* compiler: new function, clean-file.Kaz Kylheku2023-06-042-0/+17
| | | | | | | | | | | | | | | | This function simplifies cleaning, by allowing a file to be cleaned to be identified in much the same way as an input file to load or compile-file. * autoload.c (compiler_set_entries): The clean-file symbol is interned and becomes an autoload trigger for the compiler module. * stdlib/compiler.tl (clean-file): New function. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* bug: compile-file can put out nil, confusing load.Kaz Kylheku2023-06-031-1/+1
| | | | | | | | | | | | | | | | | | | | The file compiler combines compiled forms into a single list as much as possible so that objects in the list can share structure (e.g. merged string literals). However, when package-manipulating forms occur, like defpackage, it has to spit these lists, since the package manipulations of an earlier form affect the processing of a later form, such as whether symbols in that form are valid. This splitting does not take care of the case that an empty piece may result when the very last form is a package manipulation form. A nil gets written to the .tlo file, which the load function does not like; load thinks that since this is not a valid list of compiled forms, it must be the version number field of a catenated .tlo file, and proceeds to find it an invalid, incompatible version. * stdlib/compiler.tl (dump-to-tlo): Use partition* rather than split*. partition* doesn't leave empty pieces.
* Version 287.txr-287Kaz Kylheku2023-06-031-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. * protsym.c: Regenerated.
* New macro: expander-let.Kaz Kylheku2023-05-282-0/+45
| | | | | | | | | | | | | * stdlib/expander-let.tl: New file. * autoload.c (expander_let_set_entries, expander_let_instantiate); New static functions. (autoload_init): Register autoloading of above new file via above new functions. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* awk: new :fun clause for local functions.Kaz Kylheku2023-05-241-25/+28
| | | | | | | | * stdlib/awk.tl (awk-compile-time): New slot, funs. (awk-expander): Gather :fun clauses info funs slot. (awk): Include a labels form which injects the functions. * txr.1: Documented.
* compiler: fbind/lbind: elide unnecessary frames.Kaz Kylheku2023-05-241-9/+15
| | | | | | | | | | | * stdlib/compiler.tl (comp-fbind): When after removing unused functions we are left with an empty list (or the list of functions was empty to begin with), let's only emit the body fragment without any frame wrapping. We can't just return bfrag because that was compiled in the environment which matches the frame. Instead of the expense of compiling the code again, we rely on eliminate-frame to move all v registers up one level.
* awk: widen scope of redirection macros.Kaz Kylheku2023-05-241-39/+44
| | | | | | | | | | | | | | | | | This change makes it possible to use the redirection macros like -> and ->> everywhere in the awk macro, including the init-forms of the :let clause. * stdlib/awk.tl (sys:awk-mac-let-outer): New macro. (sys:awk-mac-let): Move redirection macros into awk-mac-let-outer. (awk): Rearrange the order of wrapping. We split the let so the awk-retval and aws-sym are bound outermost. Then we have the outer macros that provide the redirection operators. Then the application-defined lets inside of that. * txr.1: Documented wide scope of redirection macros.
* 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.