summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* Simplify top-level macro environments also.Kaz Kylheku2023-07-172-23/+16
| | | | | | | | | | | | Like was done with the function and variable top-level environments, we simplify the macro ones. * eval.c (func_get_name, lookup_mac, lookup_symac, lookup_symac_lisp1, op_defsymacro, rt_defsymacro, rt_defmacro, op_defmacro, reg_mac, reg_symacro): Adjust to simpler representation where the hash cell itself is the binding cell, rather than holding a binding cell in its cdr.
* Simplify top-level variable and function environments.Kaz Kylheku2023-07-164-27/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Since their inception, the top_fb and top_fb hashes associated symbols with bindings cells, causing an extra cons cell to be allocated for each entry. I don't remember why this is. It might have been that way so that gethash(top_fb, sym) would return a cell when the variable exists, or else nil. This was before we had functions like gethash_e and inhash that return the hash cell itself. A hash cell is also a cons and can serve as a binding just fine by itself.Let's make it so. For now, the macro and symbol macro environments stay the way they are; I will likely convert them also. * eval.c (env_fbind, env_vbind, lookup_global_var, lookup_sym_lisp1, lookup_fun, func_get_name, rt_defv, rt_defun, set_symbol_value, reg_fun, reg_varl): Update all these functions so they treat the hash cell from top_vb or top_fb as the binding cell, rather than putting or expecting the cdr of that cell (i.e the hash value) to be a binding cell. * hash.[ch] (gethash_d): New function. Jus gethash_e without the pesky self argument, that would only be needed for error reporting if we pass an object that isn't a hash. * stdlib/place.tl (sys:get-fun-getter-setter, sys:get-vb): These two functions must be adjusted since they refer to the top-fb and top-vb variables. sys:get-vb isn't used anywhere; it continues to exist in order to provide run-time support to files that were compiled with an buggy version of the symbol-value place.
* fix self name of var defining run-time support function.Kaz Kylheku2023-07-161-1/+1
| | | | * eval.c (rt_defv): Report as sys:rt-defv, not sys:defv.
* 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-153-20/+58
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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-155-115/+822
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * 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.
* lib: avoid intern for symbol we already have.Kaz Kylheku2023-07-131-1/+1
| | | | | * eval.c (eval_init): We have a repeat_s variable; no need to call intern(lit("repeat"), user_package).
* md5: bugfix: broken on big endian.Kaz Kylheku2023-07-111-8/+8
| | | | | | * chksums/md5.c (encode, decode): Fix these functions so they actually swap the byte order of 4 byte words on big endian. Tested on PPC64.
* Fix diagnostics which call non-symbol a symbol.Kaz Kylheku2023-07-112-1/+4
| | | | | | | | | | * 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.
* unique: use sequence iterationKaz Kylheku2023-07-101-20/+8
| | | | | * lib.c (unique): Use seq_iter_t rather than dividing into list and vector cases.
* group-reduce: use sequence iteration.Kaz Kylheku2023-07-102-25/+14
| | | | | | | | * hash.c (group_reduce): Use seq_iter_t instead of obsolete vector and list iteration. * txr.1: Use 1..11 range in one group-reduce example instead of (range 1 10).
* group-by: use sequence iteration.Kaz Kylheku2023-07-102-17/+9
| | | | | | | | | | | * hash.c (group_by): Replace obsolete list/vector switching with seq_iter_t iteration. The group-by function is limited otherwise. * txr.1: Update group-by documentation not to assert that the sequence argument is required to be a list or vector. Examples for group-by and group-map now use a 0..11 range instead of (range 0 10).
* chksum: generate more with TXR.Kaz Kylheku2023-07-092-9/+64
| | | | | | | | * genchksum.txr, chksum.c: The declarations of the symbol variables, COBJ class handles, and most of the chksum_init function is also generated now. A comment is added explaining what parts of the file are generated, and what parts are scraped, and giving some advice to the maintainer.
* chksum: generate with TXR.Kaz Kylheku2023-07-092-213/+787
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | A giant macro that generates numerous functions and variables is hell for anyone who has to debug the code. The right approach is external code generation, where the result is a clean source file that is checked into the repository. * genchksum.txr: New file. * chksum.c: Now generated. (chksum_impl): Macro and its invocations removed. (sha1_stream_impl, sha1_stream, sha1_szmax_upd, sha1_buf, sha1_str, sha1, sha1_ops, sha1_begin, sha1_utf8_byte_callback, sha1_hash, sha1_end): These are directly defined again. (sha256_stream_impl, sha256_stream, sha256_szmax_upd, sha256_buf, sha256_str, sha256, sha256_ops, sha256_begin, sha256_utf8_byte_callback, sha256_hash, sha256_end): Likewise. generated by macro. md5_stream_impl, md5_stream, md5_szmax_upd, md5_buf, md5_str, md5, md5_ops, md5_begin, md5_utf8_byte_callback, md5_hash, md5_end): Likewise.
* doc: document SHA-1 support.Kaz Kylheku2023-07-082-8/+77
| | | | | | * txr.1: SHA-1 functions documented. * stdlib/doc-syms.tl: Updated.
* doc: fix SHA256.Kaz Kylheku2023-07-081-3/+3
| | | | * txr.1: SHA256 should be SHA-256 in several places.
* doc: document crc32 parameters.Kaz Kylheku2023-07-081-0/+9
| | | | | * txr.1: Specify which crc32 is implemented: which polynomial, bit direction, and complementation of the output.
* Tests for checksum functions.Kaz Kylheku2023-07-081-0/+40
| | | | * tests/013/chksum.tl: New file.
* Adding SHA-1 hash.Kaz Kylheku2023-07-087-4/+403
| | | | | | | | | | | | | | | | | | * chksums/sha1.c, chksums/sha1.h: New files. * LICENSE, METALICENSE: Mention new code. * chksum.c (sha1_ctx_s, sha1_ctx_cls): New static variables. (chksum_init): Register sha-ctx symbol, and sha_ctx_s COBJ class. Register sha1-stream, sha1, sha1-begin, sha1-hash and sha1-end intrinsics. (sha1_stream_impl, sha1_stream, sha1_szmax_upd, sha1_buf, sha1_str, sha1, sha1_ops, sha1_begin, sha1_utf8_byte_callback, sha1_hash, sha1_end): These functions and variables are generated by a call to the cksum_impl macro. * Makefile (OBJS): add chksums/sha1.o object file.
* chksum: merge SHA256 and MD5 code with macro.Kaz Kylheku2023-07-081-352/+211
| | | | | | | | | | | | | * chksum.c (chksum_impl): New macro. Two calls to this macro generate the implementations of SHA256 and MD5. The code is identical. (sha256_stream_impl, sha256_stream, sha256_szmax_upd, sha256_buf, sha256_str, sha256, sha256_ops, sha256_begin, sha256_utf8_byte_callback, sha256_hash, sha256_end): Directly written definitions removed, now generated by macro. md5_stream_impl, md5_stream, md5_szmax_upd, md5_buf, md5_str, md5, md5_ops, md5_begin, md5_utf8_byte_callback, md5_hash, md5_end): Likewise.
* crypt: handle libxcrypt failure tokens.Kaz Kylheku2023-07-041-1/+3
| | | | | | | | | | | | | | | Some OS distros have switched to a library called libxcrypt, which, instead of returning null on failure, like the Glibc crypt, returns a valid "failure token" string starting with a * character, which is guaranteed to be different from the salt argument. We should check for this so that we handle errors uniformly. Users are reporting failing crypt tests that are coming up with "*0" instead of throwing an exception. * sysif.c (crypt_wrap): Only accept a non-null result if it isn't one of the two strings "*0" and "*1".
* Version 289.txr-289Kaz Kylheku2023-07-027-803/+853
| | | | | | | | | | | | | | * 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.
* Bug: ranges not treated as iterable in some situations.Kaz Kylheku2023-06-301-1/+1
| | | | | | | | | | | | | * lib.c (seq_kind_tab): Map the RNG type to SEQ_VECLIKE rather than SEQ_NOTSEQ. This one liner change causes ranges to be rejected for iteration needlessly. For instance, we can now do (take 42 "00".."99"). Note that ranges are not literally vector-like; they don't support the ref operation. The effect of this change is simply that they are not rejected due to being SEQ_NOTSEQ. The iteration code already handles RNG specially, so the SEQ_VECLIKE classification doesn't actually matter.
* Callable integers become assignable places.Kaz Kylheku2023-06-303-31/+101
| | | | | | | | | * lib.c (dwim_set): Handle seq argument being an integer or range. * tests/012/callable.tl: A few tests. * txr.1: Documented.
* New: callable integers and ranges.Kaz Kylheku2023-06-284-2/+86
| | | | | | | | | | | | | | | | | * lib.c (do_generic_funcall): Allow integers and ranges to be function callable. They take one argument and index into it or extract a slice. In the case of ranges, this is a breaking change. Ranges can already be used in the function position in some limited ways that are not worth preserving. * tests/012/callable.tl: New file. * tests/012/iter.tl: Here we fix two instances of breakage. Using txr -C 288 will restore the behaviors previously tested here. * txr.1: Documented.
* New cached sorting functions.Kaz Kylheku2023-06-285-2/+116
| | | | | | | | | | | | | | | | | | 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-286-0/+53
| | | | | | | | | | | | | | | | | | | | 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.
* equal: bug: broken equality substitution.Kaz Kylheku2023-06-282-3/+11
| | | | | | | | | | | | | * lib.c (equal): Several cases which react to the type of the left argument have a default path which wrongly short-circuits to an early return. All these cases must break through to the logic at the end of the function which tests the right side for a possible equality substitution. * tests/012/struct.tl: One breaking test cases added. equal was found to return nil for two structures that have equal lists as their equality substitute.
* ssort: gc bug in vector case.Kaz Kylheku2023-06-283-4/+6
| | | | | | | | | | * gc.[ch] (gc_prot_array_alloc): Return the COBJ via new pointer argument. * lib.c (ssort_vec): Capture the object from gt_prot_array_alloc into a local variable, That makes it visible to the garbage collector, so it won't be prematurely reclaimed. Since we don't use or return that object, we need to use gc_hint.
* eval: take macro environment.Kaz Kylheku2023-06-278-152/+180
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* hash: rename some variables in remove algorithmsKaz Kylheku2023-06-221-7/+7
| | | | | | | | | | hash.c (hash_remove): In the algorithm that moves cells forward in the cluster in order to avoid the use of tombstones, we use slightly better variables. The cell we are looking to replace is called wipe rather than start. The cryptic varaible name k is renamed to iprobe, because it the initial probe location for the cell at position i.
* hash: support existing mutation+iteration semantics.Kaz Kylheku2023-06-203-15/+96
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The original chained hashing scheme makes certain guarantees in situation when a hash table that is being iterated is also undergoing insertions or deletions. The original scheme meets these requirements simply, by putting a freeze against hash table growth while there are outstanding iterations. Chained hashing gracefully handles load factors above 1. Load factors above 1 are not possible under open addressing (and we don't even want to approach 1) but we would like to preserve the requirements. The requirements are: 1. If an iterator has already visited an item, it will not see that item again, regardless of insertions which cause the table to be reorganized. 2. It is not specified/required that an iterator will visit newly inserted items. It may visit some of those items, but not others. 3. If an iterator has not yet visited an item, and that item is deleted, it will not see that item, regardless of any insertions that reorganize the table. In this commit, we implement a "table stack" scheme. 1. When a table is resized due to insertions, and it is being iterated (h->usecount > 0), in that situation it will push the existing small table onto a stack, the h->tblstack (table stack). 2. Iterators take a hash table's current table and its size, and work with that snapshot of the table. If the original hash table grows, existing iterators work with the original table as it existed just before the reorganization. So after that they do not see any new insertions. 3. Whenever the delete operation (hash_remove) finds the item and removes it from the current table, it also walks the table stack, searches for the item in every table in the stack and nulls it out. This search is oblivious to nil; it's a blind search that goes around the table starting at the first probe position, looking for the identical cons cell to take out. This algorithm ensures that iterators will not see a deleted item, unless they already visited it before the deletion, of course. * hash.h (struct hash_iter): New members table, and mask. * hash.c (struct hash): New member, tblstack. (hash_grow): We drop the vec argument and recreate it locally (not essential to this commit). If we find that the usecount is positive, we push the existing table onto the table stack. Otherwise, we take the opportunity to obliterate the table stack. (hash_insert): Drop the restriction that hash_grow is only called when the use count is zero. Adjust calls to hash_grow to drop the vec argument. (hash_remove): When an item is found and deleted, and the table is in use by iterators, walk the table stack and delete it from each previous table. Otherwise, if the table is not in use by iterators, obliterate the table stack. (hash_mark): Exit early also if there is a table stack, and mark that stack. (do_make_hash, make_similar_hash, copy_hash): Initialize table stack in new hash. (hash_iter_mark): Mark the iterator's table. This is likely not necessary since we also mark the hash table, which should have a pointer to that same table. That wouldn't be defensive programming, though. (hash_iter_init, us_hash_iter_init): Initialize table and mask. (hash_iter_next_impl, hash_iter_peek): These functions have to walk the table snapshot taken by the iterator, using the captured mask, and not the current table. (has_reset): If the target table's use count drops to zero, obliterate its table stack. We add a missing setcheck here; this operation potentially stores a different hash into an existing iterator. It's not being done safely with regard to generational GC. * tests/010/hash.tl: New tests.
* hash: experimental switch to open addressing.Kaz Kylheku2023-06-202-210/+227
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * hash.h (struct hash_iter): chain and cons members removed; index member added. * hash.c (struct hash_ops): acons_new_c_fun member removed. (hash_ops_init): Reduced to three arguments. (hash_grow): Function removed. (hash_find_slot, hash_lookup, hash_grow, hash_insert, hash_remove): New static functions. (hash_mark): Iterate the simple open table, which directly contains pointers to the hash entry cons cells, rather than lists of these. (hash_acons_new_c, hash_aconsql_new_c, hash_aconsq_new_c): Static functions removed. (hash_eq_ops, hash_eql_ops, hash_equal_ops): Initializer macro calls reduced to three arguments. (copy_hash_chain): Function removed. (copy_hash): copy_hash_chain logic altered to duplicate the hash cells like copy_hash_chain did. (gethash_c, gethash_e, remhash): Retargeted to the new static functions that do open addressing with linear probing. (hash_iter_mark): No cons member to mark any more. (hash_iter_init, us_hash_iter_init): Initialization updated to new representation. (hash_iter_next_impl, hash_iter_peek): Rewritten to traverse simple table. Loses second argument. (hash_iter_next, hash_next): Don't pass second argument to hash_iter_next_impl. (do_weak_tables): Adjusted to walk open table.
* hash: bug: initial hash mask miscalculation.Kaz Kylheku2023-06-191-3/+3
| | | | | | | | | | | | | | | | | | Hash tables are supposed to start with a mask of 255, which is the 256 modulus less one. However, due to a coding mistake, they get a modulus of 252. Now this still works. It just has a few zero bits in it: 1111 1100 rather than 11111111. When this grows by doubling in size, we get 1 1111 1001, 11 1111 0011 and so on. Now this still all works, because hash values AND-ed with such a mask are no greater than that mask. The table isn't accessed out of bounds. It's just inefficiently used. * hash.c (do_make_hash, make_similar_hash, clearhash): When converting the power-of-two modulus, which is a Lisp word, to the integer mask, subtract 1 from the integer value, not the original Lisp word.
* quips: procrastination quip.Kaz Kylheku2023-06-171-0/+1
| | | | * stdlib/quips.tl (%quips%): New one.
* New macro: match-cond.Kaz Kylheku2023-06-125-1/+98
| | | | | | | | | | | | | * 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-1211-6410/+6723
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | @(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-106-1341/+1377
| | | | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date. * txr.vim, tl.vim: Regenerated.
* lib: string bug spotted on Solaris.Kaz Kylheku2023-06-101-1/+1
| | | | | | | | | | * lib.c (string_finish): On platforms where we do not HAVE_MALLOC_USABLE_SIZE, there is a compiler diagnostic. The code is inappropriately using the set macro and mkloc to assign the st->st.alloc member, which is just a number (cnum type), and not a val. The set macro is only needed when mutating a gc heap object to point to another gc heap object.
* New functions keep-keys-if, separate-keys.Kaz Kylheku2023-06-076-1/+208
| | | | | | | | | | | * 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.
* clean-file: tests.Kaz Kylheku2023-06-052-0/+110
| | | | | | * tests/018/clean.tl: New file. * tests/018/clean.expected: New file.
* autoload: rename local variable.Kaz Kylheku2023-06-051-2/+2
| | | | | | | * autoload.c (expander_let_set_entries): The expander-let symbol is in the usr package, registered via autoload_set, so the array should be called name and not sys_name.
* New functions load-args-recurse and load-args-processKaz Kylheku2023-06-055-0/+352
| | | | | | | | | | | | * 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-043-7/+38
| | | | | | | | | | | | | | | | | | 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-044-1/+92
| | | | | | | | | | | | | | | | 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.
* bug: autoload issue affecting with-compilation-unitKaz Kylheku2023-06-031-0/+5
| | | | | | | | | | | | | | | When a (with-compilation-unit ...) form is compiled, it references the value of a certain special variable that is private to the compiler. This reference is correct, but the variable's symbol is not hooked up to trigger autoload. If the compiler module has not yet been loaded, and the compiled version of a with-compilation-unit form is evaluated, it will fail due to an unbound variable error. * autoload.c (compiler_set_entries): Add the sys:*in-compilation-unit* variable name to the autoload triggers for the compiler module.
* Version 287.txr-287Kaz Kylheku2023-06-037-1179/+1263
| | | | | | | | | | | | | | * 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.