summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* bracket: bug: wrong result when function is applied.Kaz Kylheku2019-09-102-4/+18
| | | | | | | | | | | | Reported by user vapnik spaknik. * lib.c (bracket): Don't rely on the index variable to step through the arguments, because it only counts fixed arguments. The args_get function doesn't increment the index beyond args->fill; when popping arguments from args->list, index stays unmodified. * tests/016/arith.tl: Tests for bracket added.
* tests: add tests for list-builder and fix bug.Kaz Kylheku2019-09-102-1/+11
| | | | | | | * share/txr/stdlib/build.tl (list-buider pend*): Fix typo: apply should be append. Funny, this didn't propagate to ncon*. * tests/012/seq.tl: Some list-builder tests via build macro.
* tests: add tests for digits function.Kaz Kylheku2019-09-091-0/+18
| | | | * tests/016/arith.tl: Add various digits tests.
* New tests for sequence manipulation.Kaz Kylheku2019-09-092-0/+9
| | | | | | | | Just a few append cases with improper lists here to start with. * tests/012/seq.tl: New file. * tests/012/seq.expected: New file
* build: clean target should remove run.shKaz Kylheku2019-09-091-2/+2
| | | | | * Makefile (clean): If it exists, remove the temporary run.sh that is generated by the install-tests target.
* Bugfix: incorrect appending to improper lists.Kaz Kylheku2019-09-091-9/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The list building framework underlying the list_collect_decl macro has a flaw: if the current list ends in an non-nil terminating atom, and the tail pointer isn't directly aiming at that atom, then a subsequent operation to add an item or append a suffix will just overwrite the atom. The correct behavior is to execute the same logic as if the tail pointer pointed at that atom on entry into the function: switch on the type of the atom, and append to it, if possible, or else throw an error. Thus, for instance, (append '(1 2 3 . 42) '(4)) wrongly returns (1 2 3 4), instead of producing an error. The 42 atom has disappeared. The example (append '(1 2 . "ab") "c") -> (1 2 . "abc") given in the man page doesn't work; it yields (1 2 . "c"). * lib.c (list_collect, list_collect_nconc, list_collect_append, list_collect_revappend, list_collect_nreconc): In the cases when the current tail object is a CONS and LCONS, and we move the tail, we must branch backwards and process the tail atom as if the tail had been that way on entry into the function. Doing this with a tail call would be nice, but in some of the functions, we hold a local resource already, so we simulate a local tail call by updating the tailobj variable and doing a backwards goto.
* list-builder: rewrite of basic methods.Kaz Kylheku2019-09-092-49/+86
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Rewriting be addition, pending and nconcing methods of list-builder to avoid loops and rely on lower list processing functions. This cleans up the semantics and error messages. Some examples of behavioral changes: (build (pend "abc") (add #\d)) now returns "abcd", consistent with (append "abc" '(#\d)). Previously it returned '(#\d). (build (add 1) (pend 2) (pend 3)) now produces a "cannot append to 2" error. Previously it produced "copy: cannot copy object of type fixnum". * share/txr/stdlib/build.tl (list-builder add): Don't use copy-list; rather the idiom for copying a sequence in preparation for appending to it is (append x nil). This will blow up nicely if x is an atom other than nil. We use this trick twice. (list-builder add*): Simplify with append. (pend, pend*, ncon): Rewrite. (ncon*): Use nconc once on a combined argument list: this is borrowed from the rewritten pend*. * txr.1: Documentation updated with clarifications, particularly in the area of the requirements regarding destructive manipulation and substructure sharing.
* digits/digpow: recycle temporary conses.Kaz Kylheku2019-09-071-2/+3
| | | | | | | * arith.c (digcommon): Improved termination test in the second loop to avoid wasteful pop when the list of powers is empty. Use rcyc_pop to recycle these conses; they will be immediately reused for building the output list.
* digits/digpow: wrong results for radix powers.Kaz Kylheku2019-09-061-1/+1
| | | | | | * arith.c (digcommon): Fix off-by-one test causing incorrect results for radix powers like (digits 10) (digits 100) ... and analogously in other radices. Reported by vapnik spaknik.
* digits/digpow: disallow base 1.Kaz Kylheku2019-09-061-1/+1
| | | | | * arith.c (digcommon): Fix wrong test that allows base 1 to be admitted, resulting in infinitely looping behavior.
* subtypep: structs with car or length method are sequences.Kaz Kylheku2019-09-064-0/+17
| | | | | | | | | | | | | * lib.c (subtypep): For the sequence supertype, check whether the subtype is a structure that has a length or car method, returning t if so. * struct.c (get_special_slot_by_type): New function. * struct.h (get_special_slot_by_type): Declared. * txr.1: Add <structures with cars or length methods> to the type hierarchy diagram.
* seq_info: bug: nil for objects with only length method.Kaz Kylheku2019-09-061-1/+1
| | | | | | * lib.c (seq_info): Add missing else, which makes the function return nil for objects that have a length method, but not a car method.
* subtypep: remove useless eq.Kaz Kylheku2019-09-061-1/+1
| | | | | | * lib.c (subtypep): The sub and sup parameters are compared for equality early in the function; byt the time we get here, we know they are not eq, so nil can be returned.
* lib: access special methods via special slot mechanism.Kaz Kylheku2019-09-065-32/+63
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | * ffi.c (ffi_flex_struct_in): Use get_special_slot to obtain length method. * lib.c (nullify_s, from_list_s, lambda_set_s): Definitions removed from here. (seq_info, car, cdr, rplaca, rplacd, make_like, nullify, replace_obj, length, empty, sub, ref, refset, dwim_set): Use get_special_slot to obtain special method from object, rather than maybe_slot. (obj_init): Remove initializations of nullify_s, from_list_s and lambda_set_s from here. * struct.c (enum special_slot): Definition removed from here. (nullify_s, from_list_s, lambda_set_s): Definitions moved here from lib.c. (special_sym): New static array. (struct_init): Initializations of nullify_s, from_list_s and lambda_set_s moved here from lib.c. (get_special_slot): New function. * struct.h (lambda_set_s): Declared. (enum special_slot): Definition moved here. (get_special_slot): Declared. * txr.1: Added compat note, since get_special_slot behaves like maybe_slot under 224 compatibility.
* struct: remove trivial static function.Kaz Kylheku2019-09-061-6/+1
| | | | | | * struct.c (get_equal_method): Static function removed. (struct_inst_equalsub): Replace one and only call to get_equal_method with direct call to get_special_static_slot.
* structs: lazily allocate special slots array.Kaz Kylheku2019-09-041-23/+30
| | | | | | | | | | | | | | | | | | | A type which we never ask for a special slot need not waste space the array. * struct.c (struct struct_type): Change spslot from array to pointer. (make_struct_type): Initialize spslot pointer to zero. (struct_type_destroy): Free the dynamic array. (invalidate_special_slot_nonexistence): Do nothing if the spslot pointer is null. (get_special_static_slot): Dynamically allocate the array if the spslot pointer is null, and update that pointer, before doing anything else. The parameter signature changes; instead of a pointer to an element of the stslot array, we pass the index. (get_equal_method): Pass the index of the equal method special slot, rather than the address of the array entry.
* seq_info: remove redundant car slot lookup.Kaz Kylheku2019-09-041-2/+0
| | | | | | * lib.c (seq_info): Due to a copy-paste error maybe_slot is being accidentally called here twice for the same slot. Removing.
* structs: special slot generalization.Kaz Kylheku2019-09-041-13/+34
| | | | | | | | | | | | | | | | | | | | | | | This lays the groundwork for optimizing access to more special slots. Currently the equal method is handled specially; if a type has an equal method, then this is cached for fast access, so we are not doing a slot lookup each time the method needs to be called. We would like a small array of such methods, with minimal code duplication. * struct.c (enum special_slot): New enum. (struct struct_type): Scalar member eqmslot replaced by spslot array. (make_struct_type): Initialize elements of new array to null; don't initialize removed eqmslot member. (invalidate_special_slot_nonexistence): New static function. (static_slot_set, static_slot_ens_rec): Use invalidate_special_slot_nonexistence instead of open code. (get_static_special_slot): General function for obtaining and caching a special slot. Based on implementation of get_equal_method. (get_equal_method): Rewritten as a simple call to get_special-static_slot.
* structs: move SLOT_CACHE_SIZE macro.Kaz Kylheku2019-09-042-2/+1
| | | | | | | | | | Only struct.c refers to this symbol, and so only struct.c needs to be recompiled when someone experiments with different values. * lib.h (SLOT_CACHE_SIZE): Macro deleted here. * struct.c (SLOT_CACHE_SIZE): Macro moved here.
* type: lcons and string are subtypes of sequence.Kaz Kylheku2019-09-041-1/+1
| | | | | | | Omissions reported by user vapnik spaknik. * lib.c (subtypepe): The lcons type and string type must report as subtypes of sequence.
* list-builder: use copy-list, not copy.Kaz Kylheku2019-09-031-6/+6
| | | | | | | * share/txr/stdlib/build.tl (list-buider add, list-builder add*, list-builder pend, list-builder pend*): Use copy-list rather than copy. This copies terminating atoms without complaining.
* list-builder: bugfix: broken self-appending.Kaz Kylheku2019-09-031-4/+7
| | | | | | | | | | | | | | | | | | | | The list builder is failing on the documented example (build (add 1 2) (pend (get)) (pend (get))) -> (1 2 1 2 1 2 1 2) wrongly constructing an infinite list. * share/txr/stdlib/build.tl (list-builder pend): When destructively appending the next argument, check whether the current tail is a tail of that object. If so, copy the object to prevent a cycle from forming. (list-builder pend*): When appending the old head to the catenated list, do the tail check and copy the object if necessary to prevent the creation of a cycle.
* New function: tailp.Kaz Kylheku2019-09-034-0/+65
| | | | | | | | | | * eval.c (eval_init): Register tailp intrinsic. * lib.c (tailp): New function. * lib.h (tailp): Declared. * txr.1: Documented.
* struct: recycle conses used for slot lookups.Kaz Kylheku2019-09-031-0/+12
| | | | | | | | | | | | When a slot is not found in a cache, and in other situations the object system conses up a key in order to search a the global slot_hash. We should be recycling these keys for reuse via rcyc_cons. This change makes recompilation of TXR's library (make clean-tlo; make) about 1.6% faster. * struct.c (lookup_slot, lookup_static_slot_desc, static_slot_p): Recycle the hash key cons cell via rcyc_cons, so it can be reused immediately.
* doc: fixes from vapnik spaknik.Kaz Kylheku2019-09-031-43/+80
| | | | | | | | | | | | | TXR user vapnik spaknik has found a swath of errors in the documentation. * txr.1: Fixed bugs in numerous examples, copy-and-paste errors in syntax sections, and other typos, including *stdin* mistyped as *std-input* in many places. A new executable code example is provided for expand-with-free-refs to calculate the result that was previously only verbally described. Fixed *stdin* mistyped as *std-input* (a non-existent symbol that imitates the internal C variable).
* doc: hyphenation of some compound words.Kaz Kylheku2019-09-031-4/+4
| | | | * txr.1: Hyphenate "heap-allocated" and "stack-allocated".
* interpreter: trivial let goes through let* case.Kaz Kylheku2019-08-311-1/+1
| | | | | | | * eval.c (bindings_helper): If there are no bindings or just one binding, then go through the sequential case. Thus trivial let is treated like let*. This avoids the continuation-related overheads incurred in the parallel case.
* interpreter: bug between let* and continuations.Kaz Kylheku2019-08-311-11/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | This was discovered by user vapnik spaknik. If a let* form is evaluated in a top-level expression such that the incoming environment is null, and a continuation is captured in the init-form of the first variable, when that continuation is invoked, an exception is thrown: "copy-env: nil is not of type env". Short repro: 1> (block nil (let* ((x (yield 42))))) ** copy-env: nil is not of type env In fact, the bug isn't that we're trying to copy nil. the problem is we are trying to copy an environment we should not be copying at all. In fact, for sequential binding, there is no need for that logic at all; it's only parallel binding which needs it, because all of the init-forms are inserting bindings into the same environment. * eval.c (bindings_helper): Don't bother with registering a copy handler for sequential binding logic, because we don't mutate environments. All of that code is moved into the parallel case.
* 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.