summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
...
* carray: allow t and floating 0 in sub and replace.Paul A. Patience2022-01-121-10/+15
| | | | | * ffi.c (carray_sub, carray_replace): Allow t as from or to value, and also implement the zero's end-of-range floating behavior.
* typecase: return nil from formless clauses.Paul A. Patience2022-01-121-1/+1
| | | | | * stdlib/type.tl (typecase): Return nil (as documented) instead of t when a matching clause has no clause forms.
* doc: clarify example in copy-struct description.Paul A. Patience2022-01-121-1/+6
| | | | | | * txr.1: The sample copy method given in the description of copy-struct looks like it could be a special structure function that would be taken into account by the copy function. It is not.
* New macros: each-true, some-true, each-false, some-false.Kaz Kylheku2022-01-126-52/+212
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * lisplib.c (arith_each_set_entries): Trigger autoload on new symbols. * stdilb/arith-each.tl (sys:arith-each): Generalize macro to handle short-circuiting logical operations. The op-iv parameter, which is a cons, is spread into two op and iv parameter. One new argument appears, short-circ. This specifies a code for short-circuiting behavior: t means iteration continues while the result is true; nil means it continues while it is nil, and + means iteration continues while the accumulator is nonzero. A new convention is in effect: the operator has to be specified as a list in order to request accumulating behavior, e.g (+) or (*). Otherwise the operator specifies a predicate that is applied to the forms, without taking into account the prior value. (sum-each, sum-each*, mul-each, mul-each*): Spread the op-iv arguments. Wrap the op argument in a list to request accumulation. In the case of mul-each and mul-each*, specify + for the short-circ argument, which means that iteration stops when the accumulator becomes zerop. sum-each and sum-each* specify : for the short-circ argument which is unrecognized, and so ther is no short-circuiting behavior. (each-true, some-true, each-false, some-false): New macros. * tests/016/arith.tl: New tests. * txr.1: Documented new macros and added note about possible short-circuiting in mul-each and mul-each*. * stdlib/doc-syms.tl: Updated.
* sum-each, mul-each: handle no vars case.Kaz Kylheku2022-01-114-10/+111
| | | | | | | | | | | | | | | * stdlib/arith-each.tl (sys:arith-each): If there are no vars, then just reduce to the identity element value. This is alreading happening fine for the each-prod family of operators. * tests/016/arith.tl: Test cases covering the no vars and empty iteration identity element cases for sum-each and mul-each, as well as the *-prod variants. * txr.1: Document empty iteration and empty vars behavior for arithmetic each operators as well as the each-prod family.
* Copyright year bump 2022.Kaz Kylheku2022-01-11134-136/+136
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | *LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lex.yy.c.shipped, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, psquare.h, rand.c, rand.h, regex.c, regex.h, signal.c, signal.h, socket.c, socket.h, stdlib/arith-each.tl, stdlib/asm.tl, stdlib/awk.tl, stdlib/build.tl, stdlib/cadr.tl, stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl, stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl, stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl, stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.tl, stdlib/match.tl, stdlib/op.tl, stdlib/optimize.tl, stdlib/package.tl, stdlib/param.tl, stdlib/path-test.tl, stdlib/pic.tl, stdlib/place.tl, stdlib/pmac.tl, stdlib/quips.tl, stdlib/save-exe.tl, stdlib/socket.tl, stdlib/stream-wrap.tl, stdlib/struct.tl, stdlib/tagbody.tl, stdlib/termios.tl, stdlib/trace.tl, stdlib/txr-case.tl, stdlib/type.tl, stdlib/vm-param.tl, stdlib/with-resources.tl, stdlib/with-stream.tl, stdlib/yield.tl, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, time.c, time.h, tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr, y.tab.c.shipped: Copyright year bumped to 2022.
* unwind: fix malformed #define.Kaz Kylheku2022-01-111-1/+1
| | | | | * unwind.h (uw_last_form_expanded): Add missing # token. Because of this, code won't compile without CONFIG_DEBUG_SUPPORT.
* parser: bug: carriage returns in JSON causing errors.Kaz Kylheku2022-01-102-356/+347
| | | | | | | | | | | * parser.l (NJPUNC): This inverted class lexical category must exclude the carriage return character \r, otherwise it matches it. The JSON keywords true, false and null are recognized as sequences of NJPUNC. If we don't exclude \r from NJPUNC, it looks like a symbol constituent, comprising an unrecognized JSON keyword. * lex.yy.c.shipped: Updated.
* parser: remove unreachable scanner rule.Kaz Kylheku2022-01-101-5/+0
| | | | | | | * parser.l: Remove rule matching double quote in JSON state. This follows a rule which matches . so is unreachable. The rule is necessary, but an identical copy of it already appears earlier.
* json: add tests with multi-line literals.Kaz Kylheku2022-01-101-0/+10
| | | | | | * tests/010/json.tl: New tests. These work. Odd; I'm seeing an issue whereby typing multi-line #J expressions into the listener does not work.
* Casts have crept into the code not wrapped by macros.Kaz Kylheku2022-01-0612-47/+56
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It is against TXR coding conventions to use the C cast notation. The usage creeps into the code. To find instances of this, we must compile using GNU g++, and add -Wold-style-cast via EXTRA_FLAGS. * eval.c (prof_call): Use macro instead of cast. * ffi.c (pad_retval, ffi_varray_alloc, make_ffi_type_union, carray_dup, carray_replace, uint_carray, int_carray, put_carray, fill_carray): Likewise. * itypes.c (c_i64, c_u64): Likewise. * lib.c (cyr, chk_xalloc, spilt_str_keep, vector, cobj_register): Likewise. * linenoise.c (record_undo): Likewise. Also, drop one superfluous cast: wstrdup_fn returns wchar_t *. (flash, edit_insert, edit_insert_str): Use macro instead of cast. * mpi/mpi.c (s_mp_ispow2d): Likewise. * parser.c (lino_getch): Likewise. * rand.c (make_random_state, random_buf): Likewise. * stream.c (generic_get_line, do_parse_mode): Likewise. * struct.c (get_duplicate_supers, call_initfun_chain, call_postinitfun_chain): Likewise. * sysif.c (c_time): Likewise. * tree.c (tr_insert): Likewise.
* num_ex: eliminate ill-considered cast.Kaz Kylheku2022-01-061-1/+1
| | | | | | | * lib.h (num_ex): Remove the cast to ucnum, which will cause this macro to misbehave for negative arguments. For instance, -1 > (ucnum) INT_PTR_MAX will compare as true! The -1 gets converted to the unsigned type and becomes UINT_PTR_MAX.
* quips: new one about C++ protected members.Kaz Kylheku2022-01-051-0/+1
| | | | * stdlib/quips.tl (%quips%): New entry.
* build: support CPPFLAGS.Kaz Kylheku2022-01-051-2/+2
| | | | | | | | | | | | | * Makefile (TXR_CFLAGS): Pull in $(CPPFLAGS) also. It seems some distros like Gentoo are relying on programs to interpolate CPPFLAGS, and use this variable for passing preprocessor-level options like -Dfoo=bar. This is an incredibly bad, unnecessary idea, but let's play along. Now because we are merging this into TXR_CFLAGS, it means that these preprocessor-only flags are used for linking, when nothing is being preprocessed, which makes no sense. However, GNU Make's built-in recipe for linking C code seems to do the same thing.
* configure: more nuanced time_t treatment.Kaz Kylheku2022-01-041-1/+47
| | | | | | | | | | | | | | | | | | | | I'm taking the position that on systems where time_t is 32 bits by default, but can be switched to 64 with some option that we positively detect, configure will refuse to run unless the user explicitly chooses what to do using either --big-time or --no-big-time. We neither want to ignore this situation (because Y2038 is a problem, and we don't want to contribute to it) nor do we want to force 64 bit time_t, which could be problematic in distributions where other applications and components are not being configured that way for whatever reason (like it being a system with a projected life span that is not expected to go past Y2038). * configure (big_time, big_time_given): New variables. (help): Document big-time. New logic in the test to validate the detected situation versus whether or not the big-time variable has been specified, and which way. Error out in several cases.
* lazy-str-get-trailing-list: spurious empty string issue.Kaz Kylheku2022-01-044-28/+242
| | | | | | | | | | | | | | | | | | | | | | | | | | * lib.c (lazy_str_get_trailing_list): Remove the spurious empty string caused by splitting on the terminator. Whenever the materialized prefix is not-empty, and there is a non-empty terminator, the prefix necessarily ends in the termintator. If we split on the terminator, the list of pieces ends in in an empty string, which is undesirable. This has to be subject to compat, unfortunately; it's a very visible behavior that affects the continuation of line-based matching after the @(freeform) directive. * tests/006/freeform-5.txr: With this fix, we no longer have to match the spurious blank line coming from @(freeform). * tests/015/lazy-str.tl: New file. * txr.1: Updated documentation with compat notes. There was some outright incorrect text describing lazy-str-get-trailing-list. Also, the lazy-str-force-upto and lazy-str-force were under-documented. The return value of the former was not completely described: that it returns t in the other case when not returning nil. It wasn't mentioned that the functions observe the limit-count. Moreover, the exact algorithm for forcing is now documented.
* freeform: bug: account for consumed prefix.Kaz Kylheku2022-01-043-1/+13
| | | | | | | | | | | | | | | | | | | | This was reported by user vapnik spaknik. The @(freeform), when reconstituting the unmatched trailing portion of the virtual line back into a list of lines, uses the abstract match position, neglecting to account for the fact that a prefix of the line may have been physically consumed to save memory. * match.c (v_freeform): When calling lazy_str_get_trailing_list, indicate the correct amount of prefix material, by subtracting, from the matching length, the base variable, which indicates how much of the prefix had been consumed. This consumption takes place above 4000 bytes, which is why the freeform test cases are not catching this. * tests/006/freeform-5.txr: New file. * tests/006/freeform-5.expected: New file.
* sysif: rlim constants: use signed/unsigned-agnostic macro.Kaz Kylheku2022-01-022-3/+5
| | | | | | | | | | | | * lib.h (num_ex): New macro. Uses unum if the argument is out of range for the signed type. Thus we can use this with unsigned constants that would wrap negative if passed to num. This is useful if some type in a system header file might be signed or unsigned. * sysif.c (sysif_init): Use num_ex for the RLIM_* constants. I'm observing values of -1 which should really be large, positive values in the rlim_t type, that being unsigned.
* ffi: allow enumed bitfield.Kaz Kylheku2022-01-023-22/+64
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * ffi.c (ffi_type_copy): Function moved earlier in file without change. (ffi_type_copy_new_ops): New stati function. (make_ffi_type_enum): Do not create a new type object using cobj; copy the existing base_type, and then tweak its properties, just like what is done with bool. Thus if base_type is a bitfield, the enum will be a bitfield. Add check against doign this to anything but an FFI_KIND_NUM, with the awareness that this does include floating-point types. Since tft is now a copy, we no longer have to copy a number of things from btft. We do set he kind field to FFI_KIND_ENUM. (ffi_type_compile): In the two bitfield cases, we now calculate the mask field for the bitfield type (leaving the shift at zero). The struct or union type into which the bitfield is embedded will still re-calculate this. The reason is that when an (enumed (bit ...) ...) type is defined, it constructs hash tables for converting between the symbolic and numeric values. It calls the put function of the underlying type to test whether each enumeration value can be converted (i.e. is in range). So the bitfield type must have a valid mask at that time, or else it will reject every nonzero value as being out of range for the bitfield. I'm also replacing the max_int variable with bits_int. Since bitfields are restricted to no wider than int, why pretend? * tests/017/ffi-misc.tl: New test cases. * txr.1: Documented.
* rlimit: var init problem due to large file offset.Kaz Kylheku2022-01-022-0/+17
| | | | | | | | | | | | | | | | Now that we fixed the regression in detecting whether to use -D_FILE_OFFSET_BITS=64, this has unmasked an issue in newer code. In sysif.c, the RLIM_INFINITY, and related constants, are being passed to num_fast: but they are 64 bit unsigned constants under the large file offset, which don't fit into a cnum or unum on a 32 bit system. * configure: When we detect large file offset, we deposit the tell-tale configuration constant CONFIG_LARGE_FILE_OFFSET into config.h. * sysif.c (sysif_init): Under CONFIG_LARGE_FILE_OFFSET, treat the RLIM_ constants using bignum_dbl_uipt.
* configure: support 64 bit time_t on glibc.Kaz Kylheku2021-12-301-11/+36
| | | | | | | | | | | | | | | | | There is a new feature in glibc: -D_TIME_BITS=64 makes time_t 64 bits wide, as part of a solution to Y2038. Let's detect this together with _FILE_OFFSET_BITS in the same test. I've not tested this because I need a system with a bleeding edge glibc that supports _TIME_BITS. * configure (time_bits_define): New variable. Test which searches some known command line options for 64 bit off_t expanded to also check for 64 bit time_t. This complicates the loop only slightly; it is much better than copy and pasting the code
* configure: broken file offset bits detection.Kaz Kylheku2021-12-301-1/+1
| | | | | | | | | | | | | We are not detecting the need to do -D_FILE_OFFSET_BITS=64 correct, resulting in no large file support on 32 bit platforms based on Glibc. This is a regression since TXR 244. * configure: We must pass EXTRA_FLAGS=-D$try to actually try the options we are looping over. This argument was accidentally removed in commit 3d80caccafc27ac812bbf8226eba6d8e529c63ff on October 9, 2020, when the conftest_symns command was changed to conftest_o.
* configure: file offset test: don't change config.hKaz Kylheku2021-12-301-2/+0
| | | | | | | | * configure: The file offset test has no reason to be writing anything into config.h. The SIZEOF_OFF_T symbol isn't used anywhere, and SIZEOF_BYTE already exists in the header. Because this command is in a loop, it ends up writing multiple definitions of SIZEOF_BYTE, and SIZEOF_OFF_T into config.h.
* doc: "sme" typo under :delegate.Kaz Kylheku2021-12-301-1/+1
| | | | | | * txr.1: Fix sme -> same. This creeps in because "sme" is whitelisted due to the @(sme ...) pattern notation (start/middle/end).
* configure: detect warning opts missing in older compilers.Kaz Kylheku2021-12-301-2/+16
| | | | | | | | | | | | * configure (diag_flags): Remove -Wvla and -Werror=declaration-after-statement. (diag_flags_given): New variable. New test: if diag_flags_given indicates that diag_flags were not specified by the user, then we try to add additional flags, subject to them being available, which we test by compiling the hello-world program with those flags. We rely on the hello-world program being left over by the previous compiler sanity check.
* Eliminate declaration-after-statement everywhere.Kaz Kylheku2021-12-2920-151/+215
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The use of -ansi doesn't by itself diagnose instances of some constructs we don't want in the project, like mixed declarations and statements. * configure (diag_flags): Add -Werror=declaration-after-statement. This is C only, so filter it out for C++. Also add -Werror=vla. * HACKING: Update inaccurate statements about what dialect we are using. TXR isn't pure C90: some GCC extensions are used. We even use long long if the configure script detects it as working, and some C99 library features. * buf.c (replace_buf, buf_list): Fix by reordering. * eval.c (op_dohash, op_load_time_lit): Fix by reordering. * ffi.c (ffi_simple_release): Fix by reordering. (align_sw_get): Fix empty macro to expand to dummy declaration so a semicolon after it isn't interpreted as a statement. On platforms with alignment, remove a semicolon from the macro so that it requires one. (ffi_i8_put, ffi_u8_put): Fix by reordering. * gc.c (gc_init): Fix with extra braces. * hash.c (hash_init): Fix by reordering. * lib.c (list_collect_revappend, sub_iter, replace_str, replace_vec, mapcar_listout, mappend, mapdo, window_map_list, subst): Fix by reordering. (gensym, find, rfind, pos, rpos, in, search_common): Fix by renaming optional argument and using declaration instead of assignment. * linenoise/linenoise.c (edit_in_editor): Fix by reordering. * parser.c (is_balanced_line): Fix by reordering. * regex.c (nfa_count_one, print_rec): Fix by reordering. * signal.c (sig_mask): Fix by reordering. * stream.c (get_string): Fix by renaming optional argument and using declaration instead of assignment. * struct.c (lookup_static_slot_desc): Fix by turning mutated variable into block local. (umethod_args_fun): Fix by reordering. (get_special_slot): Fix by new scope via braces. * sysif.c (usleep_wrap): Fix by new scope via braces. (setrlimit_wrap): Fix by new scope via braces. * time.c (time_string_meth, time_parse_meth): Fix by reordering. * tree.c (tr_do_delete_spec): Fix by new scope via braces. * unwind.h (uw_block_beg): New macro which doesn't define RESULTVAR but expects it to refers to an existing one. (uw_block_begin): Replace do while (0) with enum trick so that we have a declaration that requires a semicolon, rather than a statement, allowing declarations to follow. (uw_match_env_begin): Now opens a scope and features the same enum trick as in uw_block_begin. This fixes a declaration-follows-statement issue in the v_output function in match.c. (uw_match_env_end): Closes scope opened by uw_match_env_begin. * unwind.c (revive_cont): Fix by introducing variable, and using new uw_block_beg macro. * vm.c (vm_execute_closure): Fix using combination of local variable and reordering.
* Makefile: way to clean only C sources.Kaz Kylheku2021-12-291-1/+3
| | | | | | | * Makefile (clean-c): New target, complementary to clean-tlo, to only clean the C object files, executables and related materials, without touching the .tlo files. (clean): Depend on clean-c; body entirely moved into clean-c.
* help: fix preprocessor directive in macro call.Kaz Kylheku2021-12-291-3/+10
| | | | | | | * txr.c (IF_HAVE_FORK_STUFF): New macro, conditionally defined. (help): Remove #if in the middle of a lit() macro call in favor of IF_HAVE_FORK_STUFF.
* doc: spurious reference to car in search tree section.Kaz Kylheku2021-12-281-1/+0
| | | | | * txr.1: Remove spurious car place syntax from syntax section of key, left and right functions.
* Version 273.txr-273Kaz Kylheku2021-12-286-915/+1002
| | | | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date. * txr.vim, tl.vim: Regenerated.
* doc: document *struct-clause-expander*.Kaz Kylheku2021-12-272-0/+31
| | | | | | | * txr.1: New section about special variable *struct-clause-expander*. * stdlib/doc-syms.tl: Updated.
* doc: stray reference to *place-macro*.Kaz Kylheku2021-12-271-1/+1
| | | | | * txr.1: In description of *match-macro* fix stray copy-paste referring to *place-macro*.
* match: allow bound variables with regex modifier.Kaz Kylheku2021-12-273-1/+37
| | | | | | | | | * stdlib/match.tl (expand-quasi-match): Add regex cases with bound variable. * tests/011/patmatch.tl: Test cases for this. * txr.1: Documented.
* match: bad compile-error call in quasi matcher.Kaz Kylheku2021-12-271-1/+1
| | | | | * stdlib/match.tl (expand-quasi-match): Fix too few arguments to compile-error for format args.
* doc: problems in qualisiteral pattern section.Kaz Kylheku2021-12-271-4/+2
| | | | | | | | * txr.1: Fix wrong word and number agreement: the sentence is about boudn variables. Fix bungled description of bound variable substitution; this should be a .meIP to head its own section, not in line meta-typesetting; plus the syntax must refer to a {P} and show the backticks.
* txr: do not ignore regex in positive match.Kaz Kylheku2021-12-273-44/+40
| | | | | | | | | | | | | | | | | * match.c (h_var): Refactor the logic here a bit. Without regard for whether the variable has a value, we dispatch the regex, fixed field and function cases. These handle the binding against the existing value. Then before all other cases, we check for the existing value and convert that to a literal text match. The effect of this is that now the regular expression is processed even if the variable has a value. * tests/010/span-var.txr: Last two test cases hardened a bit so they cannot fall through to a successful exit, if they invoke the wrong case. This is not related to this change. New test cases for regex span. * txr.1: Updated documentation and compatibility notes.
* txr: function span variable must match existing value.Kaz Kylheku2021-12-273-22/+278
| | | | | | | | | | | | | | | | | | | | * match.c (h_var_compat): New function; verbatim copy of existing h_var prior to this commit. (h_var): If a variable has an existing binding, but is a function spanning match, do not substitute it with text. Handle it with the ordinary case, in which we now use dest_bind instead of cons. (v_var): Similarly, here, we must also use dest_bind, rather than always freshly binding the variable. (match_compat_fixup): For 272 compatibility, substitute h_var_compat for h_var in the horizontal directive table. * tests/010/span-var.txr: New test cases. * txr.1: Documentation updated and also improved overall. The behavior when a variable has an existing value is clarified for the regex and fixed field case. Also update and condense compat notes for 272.
* txr: allow variable to span vertical function.Kaz Kylheku2021-12-265-7/+95
| | | | | | | | | | | | | | | * match.c (v_var_compat, v_var): New static functions. (match_files): No longer recognize v_var specially; it is now handled via vertical table. (dir_tables_init): Register a vertical sys:var directive also via v_var function. (match_compat_fixup): New function. * txr.c (compat): Call match_compat_fixup. * tests/010/span-var.txr: New file. * txr.1: Documented.
* new feature: :mass-delegate struct clause macro.Kaz Kylheku2021-12-234-0/+213
| | | | | | | | | | | | | | | With :mass-delegate, it is possible to generate delegation methods in bulk. All of the methods of a struct type can be mirrored by delegates in another struct type just by writing a single :mass-delegate clause. * stdlib/struct.tlk (:mass-delegate): New struct clause macro. * tests/012/oop.tl: New tests. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* eval: fix optional parameter bug from 2014.Kaz Kylheku2021-12-232-4/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | This bug affects optional parameters which either have no default expression, or one that is nil. For instance x in (lambda (: (x nil))) or (lambda (: x)). When such a parameter is given the : symbol as an argument, it is not being bound, as if it weren't there. ((lambda (: x) x) :) -> ;; error: unbound variable x This issue is not a regression; it was introduced in the commit which introduced the colon convention to optionals, as well as init expressions and presence-indicating variables, commit 68c084269581f32f0a7b859446ae2efb6c6a26c0 made in February 2014. This might be the first instance of an interpreter bug being found that is not present in the compiler. * eval.c (bind_args): The idea here was that when the argument to an optional the colon keyword symbol, and the optional's initform is nil, we can skip the overhead of calling eval to get that initform's value. Unfortunately, the skip was extended over the code which binds the parameter. Only the eval can be skipped! * tests/012/lambda.tl: New test cases to cover this.
* new feature: defstruct clause macros.Kaz Kylheku2021-12-225-18/+313
| | | | | | | | | | | | | | | | | | | | | | * lisplib.c (struct_set_entries): Trigger autoload on new symbols define-struct-clause and *struct-clause-expander*. * stdlib/struct.tl (*struct-clause-expander*): New variable. (defstruct): expand-slot local function now returns list of expanded slots, not a single slot; every case in the tree-case is converted to return a list. The syntax of a slot clause is first expanded through *struct-clause-expander hash; if that works then the resulting list is further scanned for expansions. (define-struct-clause): New macro. (:delegate): New struct clause defined with define-struct-clause. Provides single-slot delegation. * tests/012/oop.tl: Tests for :delegate. * txr.1: Documented define-struct-clause and :delegate. * stdlib/doc-syms.tl: Updated.
* defstruct: refactor with local function.Kaz Kylheku2021-12-221-147/+146
| | | | | | | | * stdlib/struct.tl (defstruct): Move the large tree-case in the loop which calculates the expanded slot syntax into a local function called expand-slot. This anticipates the addition of application-defined slot expanders, which will produce output that has to be recursed upon.
* The pairlis function comes to TXR Lisp.Kaz Kylheku2021-12-226-0/+87
| | | | | | | | | | | | * eval.c (eval_init): Register pairlis intrinsic. * lib.c, lib.h (pairlis): New function. * tests/012/seq.tl: New test cases. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New functions: subq, subql, subqual and subst.Kaz Kylheku2021-12-227-5/+181
| | | | | | | | | | | | | | | * eval.c (eval_init): Register new intrinsics. * lib.c, lib.h (subq, subql, subqual, subst): New functions. * tests/012/seq.tl: New test cases. * stdlib/optimize.tl (subst): Function removed. The new subst drop-in replaces this one. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* product/arithmetic each: missing block nil.Kaz Kylheku2021-12-203-63/+91
| | | | | | | | | | | | | | | | | | | * stdlib/arith-each.tl (sys:vars-check): New function, copy and pasted from each-prod.tl. (sys:arith-each): New macro. (sum-each, sum-each*, mul-each, mul-each*): Reworked using sys:arith-each macro. This macro uses logic borrowed from a stripped-down expand-each in the compiler. * stdlib/each-prod.tl (sys:expand-each-prod, sys:expand-arith-each-prod*): Add the block nil around the mapping call, taking care that the initialization forms are evaluated outside of the block, and their values bound to gensyms that then form the function arguments. * txr.1: Document the missing requirements for all the affected macros that there must be an anonymous block around the body, which, if used, determines the return value.
* maprodo: bugfix: spurious return value.Kaz Kylheku2021-12-201-9/+7
| | | | | | | | | | | | | | | There are cases when maprodo returns a non-nil value, even though it is supposed to collect nothing. This is because though it is is collecting nothing, that nothing is sometimes converted to an alternative return type via make_like. * eval.c (prod_common): We allow the collect_fn function pointer to be null, to indicate nothing is to be collected, rather than using a stub. If collect_fn is null, we just call the mapping function without collecting its value, and at the end, we do not involve make_like and just return nil. (collect_nothing): Static function removed. (maprodo): Pass null function pointer instead of collect_nothing.
* less: bug, vectors not supported.Kaz Kylheku2021-12-202-1/+23
| | | | | | | | * lib.c (less_tab_init): Add missing initialization for VEC, with a priority above CONS: all vectors are greater than conses. The BUF priority is bumped to 7. * test/012/less.tl: New file.
* tree: new functions for priority queue operation.Kaz Kylheku2021-12-185-0/+156
| | | | | | | | | | | | | | | | * tree.c (tree_min_node, tree_min, tree_del_min_node, tree_del_min): New functions. (tree_init): tree-min-node, tree-min, tree-del-min-node, tree-del-min: New intrinsics registered. * tree.h (tree_min_node, tree_min, tree_del_min_node, tree_del_min): Declared. * txr.1: Documented. * tests/010/tree.tl: New tests. * stdlib/doc-syms.tl: Updated.
* tree: bugfix wrong tree-count.Kaz Kylheku2021-12-182-2/+14
| | | | | | | | | | | | | When duplicate keys are inserted in the default way with replacement, the tree size must not be incremented. * tree.c (tr_insert): Increment the tr->size and maintain tr->max_size here. In the case of replacing an existing node, do not touch the count. * tests/010/tree.tl: Add test cases covering duplicate insertion and tree-count. (tree_insert_node): Remove unconditional size increment.
* tree: support for duplicate keys.Kaz Kylheku2021-12-179-28/+309
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * tree.c (tr_insert): New argument for allowing duplicate. If it is true, suppresses the case of replacing a node, causing the logic to fall through to traversing right, so the duplicate key effectively looks like it is greater than the existing duplicates, and gets inserted as the rightmost duplicate. (tr_do_delete_specific, tr_delete_specific): New static functions. (tree_insert_node): New parameter, passed to tr_insert. (tree_insert): New parameter, passed to tree_insert_node. (tree_delete_specific_node): New function. (tree): New parameter to allow duplicate keys in the elements sequence. (tree_construct): Pass t to tree to allow duplicate elements. (tree_init): Update registrations of tree, tree-insert and tree-insert-node. Register tree-delete-specific-node function. * tree.h (tree, tree_insert_node, tree_insert): Declarations updated. (tree_delete_specific_node): Declared. * lib.c (seq): Pass t argument to tree_insert, allowing duplicates. * parser.c (circ_backpatch): Likewise. * parser.y (tree): Pass t to new argument of tree, so duplicates are preserved in the element list of the #T literal. * y.tab.c.shipped: Updated. * tests/010/tree.tl: Test cases for duplicate keys. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.