summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* Version 224.txr-224Kaz Kylheku2019-08-296-863/+928
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* compiler: mac params: eliminate plen variable.Kaz Kylheku2019-08-291-10/+9
| | | | | | | | * share/txr/stdlib/compiler.tl (expand-bind-mac-params): Remove the plen gensym. We don't need to store the form length in a variable, because the generated length check code references the value exactly once. Let's just propagate that the length calculating expression into that code.
* sha256/md5: allow characters and byte values.Kaz Kylheku2019-08-292-4/+48
| | | | | | | | | * chksum.c (sha256_utf8_byte_callback, md5_utf8_byte_callback): New static functions. (sha256_hash, md5_hash): Support character and integer objects. * txr.1: Documented.
* compiler: elide nil var intializaton.Kaz Kylheku2019-08-281-2/+6
| | | | | | | | | | | | Virtual machine local variables registers don't require nil initialization. In cases when a complex variable initializer is known to return nil, we can elide the move instrution which moves that nil into the register. * share/txr/stdlib/compiler.tl (null-reg): New function. (compiler comp-let): Don't move the value of the output register of the init fragment into the variable, if that register is the null register t0.
* compiler: mac params: simplify optional presence indicators.Kaz Kylheku2019-08-281-15/+21
| | | | | | | | * share/txr/stdlib/compiler.tl (expand-bind-mac-params): Generate better Lisp code when presence indicating variables on optional parameters are not used. It's possible to bind the variable directly, instead of binding to nil and assigning it. The cases are split accordingly.
* compiler: mac params: late allocation for cursors.Kaz Kylheku2019-08-281-68/+69
| | | | | | | | | | | * share/txr/stdlib/compiler.tl (expand-bind-mac-params): Allocate the curs gensym only when about to recurse over a nested parameter list, rather than unconditionally. Otherwise, we always end up allocating one more gensym than we actually use, for a lower nesting level that might not be there. Don't use unwind-protect for returning the cursor variable to the free-list; it makes no sense to be recovering that since any exception will be abandoning this function entirely.
* trace: bug: redef of traced method resurrects old.Kaz Kylheku2019-08-281-3/+3
| | | | | | | | | | | | When a method which is traced is redefined, a warning message is correctly issued and the trace is removed. But the removal is done in the wrong order and ends up restoring the old function, clobbering the new definition. * struct.c (static_slot_ensure): Move the trace_check before the call to static_slot_ens_rec, so installation of the new method takes place after the trace is removed from the old one.
* trace: bugfix: trace-redefine-check doesn't untrace.Kaz Kylheku2019-08-281-3/+3
| | | | | | | * share/txr/stdlib/trace.tl (sys:trace-redefine-check): Move the sys:untrace call before the warning throw. That throw doesn't return; it ends up transferring control to the continue catch, and so the untrace is skipped.
* compiler: bugfix: incorrect scoping in macro param binding.Kaz Kylheku2019-08-281-65/+85
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The destructuring binder binds all of the variables in the template to nil values and then assigns to them as it walks the object that is being destructured. Unfortunately, this results in incorrect treatment of init-forms, which are evaluated in the wrong scope. They are actually evaluated in completely the wrong scope due to the use of up:env, but the problem can't be fixed by removing up:env. The approach here is to generate a big let* construct that binds the variables in sequence, rather than assigning to them. * share/txr/stdlib/compiler.tl (expand-bind-mac-params): The basic structure of the code remains the same, but the details are rewritten. Instead of emitting a body of forms, we emit let* bindings. Because some of the logic requires imperative statements, like stepping pointers through the destructured object, these are mixed into the variable initializations via progn. The local functions emit-stmt and emit-var provide the interface for doing this. There is a bit of trickery in the situation that an optional parameter also has the presence-indicator variable. We must bind the parameter in an environment in which that presence-indicator variable is not yet visible. This is achieved by binding the variable to a nil value, and then binding the presence indicator to an expression which sets the variable's value as a side effect, and yields a Boolean value that initializes the indicator.
* compiler: bugfix: colon keyword bungle in macro params.Kaz Kylheku2019-08-281-9/+7
| | | | | | | | | | | | | | | When the (set arg :) form is processed by a compiled version of the set operator, it blows up with "set: arguments must be pairs". This is because the compiled destructuring code is wrongly trying to apply special treatment to a colon symbol argument to an optional parameter. It is documented that such such treatment only happens in function calls, and not in the binding of macro parameter lists. Interpreted macro param binding gets it right. * share/txr/stdlib/compiler.tl (expand-bind-mac-params): Do not treat a : element in the structure as a missing optional argument, but as an ordinary value.
* unwind: bugfix: unhandled_ex not gc-protected.Kaz Kylheku2019-08-281-1/+3
| | | | | | | | | | | | | Exception info stashed into the unhandled_ex global pseudo-frame is not protected from gc reclamation. This allows for use-after-free errors, that can reproduce if unwind-protect cleanup forms that go off during the processing of an unhandled exception trigger gc. The code which deals with unhandled exception, like error_trace, then works with exception arguments that are now objects on the free list. * unwind.c (uw_init): GC-protect the exception sym and arguments stored in unhandled_ex.
* compiler: relate mac bind error to right substructure.Kaz Kylheku2019-08-271-1/+1
| | | | | | | | * share/txr/stdlib/compiler.tl (expand-bind-mac-params): A nested destructuring error must be reported against the local parameter list, not the top-level one. The bind-mac-check call muts use the local par-syntax, not the original top-level params.
* compiler: for: bugfix: dangling label reference.Kaz Kylheku2019-08-261-1/+1
| | | | | | | | | | | An infinite for loop in which the test is explicitly given as nil rather than omitted fails to compile. A minimal repro test case for this is (compile-toplevel '(for () (nil) ()))). Spotted this while reading the compiler code. * share/txr/stdlib/compiler.tl (compiler comp-for): Test the test-p variable, not test, to determine whether or not to generate the loop skip label.
* crypt: detect and use glibc's crypt_r.Kaz Kylheku2019-08-262-2/+39
| | | | | | | | | | * configure: New test for crypt_r, depositing HAVE_CRYPT_R preprocessor symbol in config.h. * sysif.c: Conditionally include <crypt.h> header. (crypt_wrap): Use crypt_r if HAVE_CRYPT_R is nonzero. (sysif_init): Register crypt intrinsic if we HAVE_CRYPT or if we HAVE_CRYPT_R.
* build: bugfix: compiler opts duplicated; remove_flags broken.Kaz Kylheku2019-08-251-1/+1
| | | | | | * Makefile (TXR_CFLAGS): Use := operator rather than += when filtering out REMOVE_FLAGS, or else REMOVE_FLAGS are not really removed, and we duplicate all the flags.
* sha256/md5: state-based hash: handle size_t overflow.Kaz Kylheku2019-08-241-20/+20
| | | | | | | | | | | | * chksum.c (sha256_szmax_upd, md5_szmax_upd): New static functions, consisting of logic from sha256_buf and md5_buf, respectively. (sha256_buf, md5_buf): Use sha256_szmax_up and md5_szmax_upd, respectively, to handle the unlikely possiblity of the ucnum buffer length being larger than the range of size_t. (sha256_hash, md5_hash): Also use the new static functions instead of callig SHA256_update or MD5_update directly to deal with the same issue.
* sha256/md5: hash string more efficiently.Kaz Kylheku2019-08-241-4/+12
| | | | | | * chksum.c (sha256_str, md5_str): Don't construct a byte input stream for hashing a string. Just convert whole thing to temporary UTF-8, hash, and free.
* New state-object-based sha256 and md5 digesting.Kaz Kylheku2019-08-233-0/+230
| | | | | | | | | | | | | | | * chksum.c (sha256_ctx_s, md5_ctx_s): New symbol variables. (sha256_ops, md5_ops): New static structs. (sha256_begin, sha256_hash, sha256_end, md5_begin, md5_hash, md5_end): New functions. (chksum_init): New symbol variables initialized; sha256-begin, sha256-hash, sha256-end, md5-begin, md5-hash, md5-end intrinsics registered. * chksum.h (sha256_begin, sha256_hash, sha256_end, md5_begin, md5_hash, md5_end): Declared. * txr.1: Documented.
* licensing: describe RSA-MD situation.Kaz Kylheku2019-08-232-3/+15
| | | | | | | | | * LICENSE: Mention MD5 component. * METALICENSE: There are more libraries than linenoise; remove focus on linenoise and make wording generic. Add description of the RSA situation, whereby more permissive redistribution terms were granted by the Feb 23, 2000 memo.
* New: MD5 digest functions.Kaz Kylheku2019-08-236-19/+509
| | | | | | | | | | | | | | | | | * Makefile (OBJS): New object file, chksums/md5.o. * chksum.c (sha256_ensure_buf): Renamed to chksum_ensure_buf and made generic so MD5 code can borrow it. (sha256_stream, sha256): Call chksum_ensure_buf instead of sha256_ensure_buf, passing in new length and hash name parameters. (md5_stream_impl, md5_buf, md5_str): New static functions. (md5_stream, md5): New functions. (chksum_init): Register md5-stream and md5 intrinsics. * chksum.h (md5_stream, md5): Declared. * chksums/md5.c, chksums/md5.h: New files.
* New function: cptr-buf.Kaz Kylheku2019-08-214-2/+46
| | | | | | | | | | * eval.c (eval_init): Register cptr-buf intrinsic. * lib.c (cptr_buf): New function. * lib.h (cptr_buf): Declared. * txr.1: Documented.
* doc: note about cptr-obj lifetime.Kaz Kylheku2019-08-211-0/+12
| | | | | | * txr.1: Include blurb about the independent lifetime of a ctpr made by cptr-obj and the original object. If the original is garbage collected, the ctpr is junk.
* New function: intern-fb.Kaz Kylheku2019-08-204-2/+37
| | | | | | | | | | | | | | | To accompany find-symbol-fb, there is intern-fb, which is like intern, but searches the fallback list. * eval.c (eval_init): Register intern-fb intrinsic. * lib.c (intern_fallback_intrinsic): New function. Does defaulting and error checks, then calls intern_fallback, just like intern_intrinsic calls intern. * lib.h (intern_fallback_intrinsic): Declared. * txr.1: Documented.
* lib: streamline interning slightly.Kaz Kylheku2019-08-204-15/+17
| | | | | | | | | | | | | | | | | | | | | We get rid of some defaulting and error checks from interning. This saves a few cycles on startup in the large number of intern calls that are performed. * eval.c (eval_init): Wire the intern intrinsic to the new intern_intrinsic function rather than intern. * lib.c (intern): Remove package lookup and error check on str argument. (intern_intrinsic): New function, which has the package lookup and error check. (intern_fallback): Remove package lookup and error check. * lib.h (intern_intrinsic): Declared. * txr.c (txr_main): Fix one instance of an intern call that relies on defaulting of the second argument, by passing cur_package.
* lexer: no leading 0 in 2-digit hex chars in diagnostic.Kaz Kylheku2019-08-201-3/+3
| | | | | | | * parser.l (grammar): Fix incorrect format strings that are supposed to show an invalid input character in hex. For instance the character 1 comes out as #\x 1 rather than #\x01.
* parser: bugfix: uninitialized ignore flag.Kaz Kylheku2019-08-201-0/+1
| | | | | | | | | | | | | | | * parser.c (parser_common_init): Initialize the ignore flag, which was until recently called circ_suppress. When the parser is invoked via parse_once or parse_once_noerror, rather than parse, the state of the flag is indeterminate. Thus this only affects the TXR Pattern Language, not TXR Lisp. As a result of this bug, which affects releases 157 through 223, if the circle notation like #1=(foo #1#) is used in Pattern Language syntax, it may not be handled properly. I discovered this bug now because there are new behaviors connected to the flag; it doesn't just affect the processing of the circle notation, but is involved in all symbol handling in the parser.
* doc: mistake in intern arg description.Kaz Kylheku2019-08-201-2/+2
| | | | | * txr.1: name must be a string, not a symbol. The optional argument must be a package, if supplied.
* new functions: find-symbol and find-symbol-fb.Kaz Kylheku2019-08-194-9/+111
| | | | | | | | | | | | | | | | | | Turns out, there is already a find_symbol in lib.c, completely unused. * eval.c (eval_init): Register find-symbol and find-symbol-fb intrinsics. * lib.c (find_symbol): Fix this hitherto unused function to do correct defaulting of the package argument and, to accept an additional argument specifying the not-found value. (find_symbol_fb): New function. * lib.c (find_symbol): Declaration updated. (find_symbol_fb): Declared. * txr.1: Documented.
* parser: #; notation shouldn't intern symbols.Kaz Kylheku2019-08-181-2/+3
| | | | | | | | | | When #; is used to ignore an object, parsing that object shouldn't cause symbols to be interned, nor errors about unknown packages. * parser.y (ifnign): New macro. (i_expr, n_expr): For SYMTOK, don't call symhlpr when parsing under ignore flag. Just yield nil as the semantic value.
* parser: rename circ_suppress flag.Kaz Kylheku2019-08-183-16/+16
| | | | | | | | | | | * parser.h (struct parser): eof flag changed to unsigned char. circ_suppress flag renamed to ignore, changed to unsigned char and relocated next to eof to compact together. * parser.c (parser_circ_ref): Follow rename. * parser.y (hash_semi_or_n_expr, hash_semi_or_i_expr, n_exprs, parse): Likewise.
* doc: new buildn example.Kaz Kylheku2019-08-181-0/+15
| | | | | * txr.1: Adding breadth-first traversal example showing queue capability of the list-builder.
* list-builder: inserter methods return nil.Kaz Kylheku2019-08-172-24/+44
| | | | | | | | | * share/txr/stdlib/build.tl (list-builder): Methods add, add*, pend, pend*, ncon and ncon* return nil. * txr.1: Updated documentation to state that these methods return nil, rather than an unspecified return value. Improvements in build macro documentation.
* list-builder: dequeue capabilities with del/del* operators.Kaz Kylheku2019-08-173-14/+129
| | | | | | | | | | | | | | | * lisplib.c (build_set_entries): Add buildn for autload, and intern del and del* symbols. * share/txr/stdlib/build.tl (list-builder): New methods del and del*. (sys:list-builder-flets): Generate flet for del*. (sys:build-expander): New function, consisting of expansion logic previously in build function. Macrolet added for del. (build): Call sys:build-expander. (buildn): New macro. * txr.1: Documented.
* doc: expand on load-time.Kaz Kylheku2019-08-161-0/+52
| | | | | | * txr.1: Add discussion highlighting use of load-time for effect staging, rather than value. Add rationale regarding the naming difference from ANSI CL.
* compile-file: include load-time as top-level form.Kaz Kylheku2019-08-162-5/+22
| | | | | | | | | | | | * share/txr/stdlib/compiler.tl (usr:compile-file): recognize sys:load-time-lit as a top-level form and recurse through to compiling its constituent form. We check the flag whether the syntax had already been processed by the evaluator, though that currently cannot possibly happen for a form that has just been parsed from a file by compile-file itself. * txr.1: Defintion of top-level form (from compile-file POV) updated. Documentation of load-time updated.
* seq_iter: remove pointless one-member union.Kaz Kylheku2019-08-142-9/+7
| | | | | | | | * lib.h (struct seq_iter): union ul with just one member replaced by that member itself. * lib.c (seq_iter_get_vec, seq_iter_peek_vec, seq_iter_init): refer to it->len instead of it->ul.len.
* where: bugfix: doesn't work for non-list sequence.Kaz Kylheku2019-08-141-13/+7
| | | | | | | | * lib.c (lazy_where_func, where): We have a regression here due to strangely trying to smuggle the predicate function in si->inf.obj, which cannot possibly work other than for lists whose seq iterators ignore that field. We switch to the trick of using the cdr field of the lazy cons to carry that forward.
* Version 223: ten years!txr-223Kaz Kylheku2019-08-146-687/+725
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* bugfix: line number of unbound vars not reported.Kaz Kylheku2019-08-131-2/+5
| | | | | * eval.c (expand): Do not create expansion debug frames for atomic forms, only for compound forms.
* autoload: bugfix: wire in forgotten test-set and others.Kaz Kylheku2019-08-131-0/+2
| | | | | * lisplib.c (place_set_entries): Add missing entries for test-set, test-clear, compare-swap, test-inc and test-dec.
* listener: don't flush lines when writing files.Kaz Kylheku2019-08-123-7/+19
| | | | | | | | | | | | | | | | * linenoise/linenoise.h (struct lino_os): New virtual operation, puts_file_fn: like puts_fn, but not display-oriented: doesn't check for and ignore padding characters, and doesn't flush after each line. (lino_os_init): Initializer macro updated. * linenoise/linenoise.c (edit_it_editor): Use puts_file_fn to write to temporary file. (lino_hist_save): Likewise, when writing out history. * parser.c (lino_puts_file): New static function. (linenoise_txr_binding): Add lino_puts_file to initializer to wire in the operation.
* tests: add test related to recent @(collect) change.Kaz Kylheku2019-08-124-0/+35
| | | | | | | | | | | This test will misbehave on TXR without the previous fix; it will not collect columns of data which keep the corresponding rows items together. * tests/002/variant, tests/002/variant.expected, tests/002/variant.txr: New files. * Makefile (TXR_ARGS, TXR_OPTS): Override for new test.
* gc: remove #if 0 and #if 1.Kaz Kylheku2019-08-121-8/+0
| | | | | * gc.c (mark_obj): Remove material excluded by #if 1. (gc): Eliminate #if 0 block.
* @(collect): don't default vars if all required missing.Kaz Kylheku2019-08-122-60/+99
| | | | | | | | | | | | | | | | | | | | | | | | | The @(collect) directive disallows the situation when there are required vars, but some are missing (not bound by the collect body). However, the special case is allowed when none of the required variables are bound; that doesn't trigger the exception. There is a poor specification in this area: the issue is that when there are optional variables, and all variables are missing (optional and required), the optional ones are still bound to their default values. Thus, the situations is half-baked: some of the :vars are bound and some are not. This violates the all-or-nothing principle of :vars. This patch addresses the poor specification: if all variables are missing, then the optional variables are not bound to their defaults. * match.c (h_collect, h_coll): Detect the situation when at least one variable is required, and all optional variables are defaulted. In this case, don't propagate any bindings to the collected lists. * txr.1: Doc updated.
* reverse: bugfix: garbage object in error message.Kaz Kylheku2019-08-091-1/+1
| | | | | * lib.c (reverse): pointer to the C function in is being used as a value; the correct expression is seq_in.
* base-name: optionally remove suffix.Kaz Kylheku2019-08-093-5/+20
| | | | | | | | | | | | | | | | The base-name function now takes a second argument which is optional, specifying a suffix to be removed. The behavior is similar to that of the second argument of the POSIX basename command. * stream.c (base_name): Second argument added. If present, the returned value is adjusted by trimming the suffix, unless that would cause an empty string to be returned. (stream_init): Update registration of base-name intrinsic. * stream.h (base_name): Declaration updated. * txr.1: New base-name parameter documented.
* compiler: inline-lambda: optimize constant apply list.Kaz Kylheku2019-08-091-65/+75
| | | | | | | | | | | | | * share/txr/stdlib/compiler.tl (comp-inline-lambda): Pass nil to new argument of lambda-apply-transform, indicating top-level call. (lambda-apply-transform): Takes new argument indicating whether it's a recursive call. If the apply list expression is constant, then it is evaluated and treated as a list of arguments which are then turned into quoted constants individually and passed as fixed args in a recursive call. This eliminates the generation of code dealing with run-time evaluation and destructuring of the apply arguments.
* compiler: inline-lambda: optimize generated let.Kaz Kylheku2019-08-081-3/+8
| | | | | | | | | | * share/txr/stdlib/compiler.tl (lambda-apply-transform): We conditionally generate the outer let as an alet, if there are no shadowing issues. The shadowing test is very conservative: the intersection between the argument expressions and the lambda symbols must be empty. Also, we move the gensym for the apply list expression into the let*, because we need a real storage location that we can pop.
* pop: improve expansion.Kaz Kylheku2019-08-081-1/+1
| | | | | | * share/txr/stdlib/place.tl (pop): Use alet for binding the temporary rather than let, so that if (,getter) expands to a symbol, it will disappear.
* compiler: bugfix: eval order in inline lambda.Kaz Kylheku2019-08-071-52/+54
| | | | | | | | | | | | | | | * share/txr/stdlib/compiler.tl (lambda-apply-transform): The expander fails to observe left-to-right evaluation because if the trailing argument form is present, it is evaluated first, even though it is the last argument. Also, the argument evaluations are wrongly interleaved among the default expressions for optional arguments; they must be evaluated firt. We fix all this by allocating gensyms for all of the fixed argument forms, and binding these via an extra let wrapped around the output let* form. When generating the let* we refer to the gensyms instead of the original fixed arguments. This extra let needs optimizing, but it can't just be converted to an alet because of scoping issues.