summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* doc: *print-flo-format*: show string value in quotes.Kaz Kylheku2025-01-251-1/+1
| | | | | * txr.1: The example possible value "~3,4f" should be shown as a string literal in quotes.
* get-csv: bugfix: return nil on EOF.Kaz Kylheku2025-01-243-5/+40
| | | | | | | | | | | | | | | | | * stream.c (get_csv): Let's add a new state init. If get_char returns nil and we are in the init state, let's bail to a nil return. While we are at it, let's not allocate the record or string until we read at least one character. If we read a character in the init state, let's allocate those two objects, and then change to the rfield state and fall through to it to handle the character. * tests/010/csv.tl: Fix one incorrect test: (tocsv "") now returns nil, as it should. Add tests for multiple record extraction, also covering missing line termination on the last record as well as CR-LF termination. * txr.1: Documented nil return conditions.
* New functions for producing CSV.Kaz Kylheku2025-01-244-0/+111
| | | | | | | | | | | | * stream.c (put_csv, tocsv): New functions. (stream_init): put-csv and tocsv intrinsics registered. * stream.h (put_csv, tocsv): Declared. * tests/010/csv.tl (mtest-pcsv): New macro. New test cases. * txr.1: Documented.
* doc: split Data Interchange Support section.Kaz Kylheku2025-01-241-1/+3
| | | | * txr.1: Split Data Interchange Support into JSON and CSV.
* get-csv: refactor into switches.Kaz Kylheku2025-01-211-19/+26
| | | | | | | * stream.c (get_csv): All cases handle end-of-stream the same way, so we check for nil outside of the case switch. Then only characters need to be handled, so we can call c_chr(ch) and switch on it.
* get-csv: rewrite in C.Kaz Kylheku2025-01-214-91/+79
| | | | | | | | | | | | | | * autload.c (csv_set_entries, csv_instantiate): Functions removed. (autoload_init): Autoload registration for stdlib/csv removed. * stdlib/csv.tl: File removed. * stream.c (get_csv): New function. (stream_init): Register get-csv intrinsic. * stream.h (get_csv): Declared.
* get-csv: use symbols for states.Kaz Kylheku2025-01-211-45/+44
| | | | | | * csv.tl (get-csv): Since there are only three states, there is no jump table optimization. We might as well use keyword symbols for the states rather than integers.
* get-csv: simplify implementation by CR-LF folding.Kaz Kylheku2025-01-211-30/+7
| | | | | | | | | * stdlib/csv.tl (get-csv): Pre-process the input by a small state machine that maps CR-LF sequences to LF. Then we don't have to recognize #\return anywhere in the state machine and can delete the cr and qcr states, as well as all the code recognizing #\return and branching to those states.
* New function: get-csv.Kaz Kylheku2025-01-214-0/+373
| | | | | | | | | | | | | * autloload.c (csv_set_entries, csv_instantiate): New static funtions. (autoload_init): Register autoload of stdlib/csv module via new functions. * stdlib/csv.tl: New file. * tests/010/csv.tl: Likewise. * txr.1: Documented.
* New macros for enumerated constants.Kaz Kylheku2025-01-204-0/+174
| | | | | | | | | | | | | * autoload.c (enum_set_entries, enum_instantiate): New static functions. (autoload_init): Register autoload of stdlib/enum module via new functions. * stdlib/enum.tl: New file. * tests/016/enum.tl: Likewise. * txr.1: Documented.
* Makefile: tidy up clean targets.Kaz Kylheku2025-01-171-3/+12
| | | | | | | | | | | | | * Makefile (clean): Do not remove the run.sh file here. That is a temporary file that install-tests should be cleaning away when done, which we can remove in distclean. (clean-doc, clean-tests): New targets, which let us clean up generated documentation files and the test-generated state information in tst. (distclean): Do not remove the documentation stuff here; rely on clean-doc. Also depend on clean-tests. Do remove run.sh here. (install-tests): Add missing .PHONY. Remove run.sh.
* lflow/lopip: optimize one argument situations via lop1.Kaz Kylheku2025-01-171-21/+25
| | | | | | | | | | | | | | | | | | | | | | | In an opip pipeline, only the first pipeline element can receive multiple arguments. The subsequent elements receive the single return value from the previous element. Therefore if it is a left-inserting pipeline created by lopip, only the first element needs to use lop. The others can use lop1, resulting in an optimization. Furthermore in the flow/lflow macros, even the first function in the pipeline is called with one argument: the result of the input expression. So the case of lflow, every element of the pipe that would translate to lop can go to lop1 instead. * stdlib/opt.tl (sys:opip-expand): Calculate a local variable called opsym-rest which determines which op symbol we use for the recursive call. This is the same as the incoming opsym, except in the case when opsym is lop, in which case we substitute lop1. (sys:lopip1): New macro, like lopip but uses lop1 for the first element also. (lflow): Expand to sys:lopip1 rather than lopip.
* New macro: lop1.Kaz Kylheku2025-01-174-3/+66
| | | | | | | | | | | | | * autoload.c (op_set_entries): Autoload on lop1 symbol. * stldlib/op.tl (sys:op-expand): Add lop1 case. (sys:opip-expand): Add lop1 to the list of operators that are recgonized and specially treated. (lop1): New macro. * tests/012/op.tl: New tests. * txr.1: Documented.
* json: flat must override all effects of :standardKaz Kylheku2025-01-163-14/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | * stream.h (struct json_opts): Member flat removed. I noticed that !jo.flat was always being tested together with jo.fmt == json_fmt_standard. Except for a few places where the code only tested for json_fmt_standard, resulting in flat output, but some extra spaces. What distiguishes flat mode now is simply that we disable stream indentation. * lib.c (out_json_rec): Remove tests for !jo.flat. (out_json): Remove initialization of jo.flat member. In this function we set up indentation on the stream resulting in multi-line mode (existing behavior). (put_json): Remove initialization of jo.flat member. If flat mode is requested, then it overrides the format to json_fmt_default. I.e. json_fmt_standard coresponding to :standard is only in effect if flat is not requested. In this function we set up indentation on the stream if flat mode isn't requested, otherwise we disable indentation (existing behavior, enough to make flat work). * tests/010/json.tl: Tests for flat mode, :standard formatting, and combinaton of both.
* put_json: bug: incorrect defaulting of flat argument.Kaz Kylheku2025-01-151-2/+3
| | | | | | | | | | this also affects put_jsonl and tojson. * lib.c (put_json): The flat argument must be properly defaulted. Without this we are treating it as true when it is missing due to the convention that missing args are signaled by the : symbol. This bugs breaks the ability to use the :standard value for *print-json-format*.
* lop: don't insert args when metas present.Kaz Kylheku2025-01-083-26/+114
| | | | | | | | | | | | | | | | | | | | | The lop macro is inconsistent from op in that it inserts the trailing function arguments on the left even if arguments are explicitly given in the form via @1, @2, ... or @rest. This change makes lop is equivalent to op in all situations when these metas are given. * stdlib/op.tl (compat-225, compat-298): New top-level variables. (op-expand): local variable compat replaced by references to compat-225. If compat-298 is *not* in effect, then metas are checked for first in the cond, preventing the lop transformation from taking place. * tests/012/op.tl: Test cases for lop, combinations of do with lop and a few for op also. * txr.1: Redocumented, added compat notes.
* Copyright year bump 2025.Kaz Kylheku2025-01-01141-143/+143
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h, args.c, args.h, arith.c, arith.h, autoload.c, autoload.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, gzio.c, gzio.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, 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/comp-opts.tl, stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl, stdlib/csort.tl, stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl, stdlib/expander-let.tl, stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl, stdlib/glob.tl, stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.tl, stdlib/load-args.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 bumped to 2025.
* match-case: bugfix in conversion to casequal.Kaz Kylheku2024-12-202-2/+3
| | | | | | | | | | | | | * stdlib/match.tl (match-case-to-casequal): the (do inc dfl-cnt) action has a problem: it inserts an implicit extra parameter to the invocation of inc, which crashes the + addition due to that parameter being the matching @nil object. We don't need this entire case because it handles @nil, which also matches the following case for (sys:var ...), since @nil is (sys:var nil). That case ahs the same action of incrementing dfl-cnt. * tests/011/patmatch.tl: Test case added.
* Version 298.txr-298Kaz Kylheku2024-12-174-5/+17
| | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date.
* listener: regression: txr bails when .txr-profile missing.Kaz Kylheku2024-12-161-0/+3
| | | | | * parser.c (load_rcfile): When neither ~/.txr-profile nor ~/.txr_profile exist, then bail. Do not pass nil to abs-path-p and other functions.
* Version 297.txr-297Kaz Kylheku2024-12-166-735/+771
| | | | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date. * txr.vim, tl.vim: Regenerated.
* bug: string range length signed/unsigned.Kaz Kylheku2024-12-161-1/+2
| | | | | | | | * lib.c (length_str_range): On platforms where wchar_t is unsigned, we calculate bogus values for reversed ranges. On Android, gcc warns about the code, and the recently added tests fail. Let's cast the characters to long before doing the subtraction, which is the argument type of labs.
* string ranges: bug: ranges of length 1.Kaz Kylheku2024-12-153-2/+24
| | | | | | | | | * lib.c (seq_iter_init_with_info): String ranges are inclusive. We must not assume at a range whose endpoints are the same is empty; we must check that case for the endpoints being strings. * tests/012/seq.tl: New tests.
* tests for string range length.Kaz Kylheku2024-12-151-0/+12
| | | | * tests/012/seq.tl: New tests.
* lib: fix g++ warning in map_common.Kaz Kylheku2024-12-111-1/+1
| | | | | | * eval.c (map_common): use the all_zero_init macro, defined differently for C and C++ for initializing a struct to all zero.
* quips: jab at Weller.Kaz Kylheku2024-12-081-0/+1
| | | | * stdlib/quips.tl (%quips%): New one.
* switch to .txr-profile and .txr-historyKaz Kylheku2024-11-143-19/+74
| | | | | | | | | | | | | | | | | | | | The profile and history files should have used hyphens from the beginning. Let's switch to that but continue to work with the old files if present, as an obsolescent feature. * parser.c (open_txr_file): Treat files with .txr-profile suffix as Lisp. (load_rcfile): Arguments rearranged. This function now needs the home directory and the existence test function, but does not need the profile file name. It tries .txr-profile first, then .txr-profile. (repl): Call load_rcfile in the new way. Try two history files: first .txr-history and then .txr_history. Remember which one was used so the same one is saved. If neither file existed at startup, then save new history into .txr-history. * txr.1: Documented.
* ffi: bug: flexible structure size calculation.Kaz Kylheku2024-10-071-3/+2
| | | | | | | | | | | * ffi.c (make_ffi_type_struct): We must calculate the size of a flexible structure the way GCC does it. We cannot simply truncate it at the offset of the member. Rather, the size is calculated in the usual way. The alignment of the array is taken into account for the purpose of determining what is the most aligned member of the structure, and then padding is added, if required. Thus, the size may exceed the offset of that member.
* copy: now handles range objects.Kaz Kylheku2024-10-014-22/+20
| | | | | | | | | | | | | | | | Ranges are iterable, denoting abstract sequences. The copy function now copies a range by constructing the array. This is useful when copy is used for the purpose of obtaining a mutable copy. For example, (shuffle 0..100) will now work, returning a shuffled vector of the integers from 0 to 99. * lib.c (copy): Handle RNG case via vec_seq. * tests/012/seq.tl, * tests/012/sort.tl: New test cases. * txr.1: Documented. Documentation for the copy function improved.
* refset, replace: adjust diagnostic for unsupported object.Kaz Kylheku2024-09-301-2/+2
| | | | | | | * lib.c (refset, replace): Word the bad object diagnostic in terms of it not being a modifiable sequence. This covers cases when the object is something abstractly iterable, like a range. We don't want to say that it's not a sequence.
* regex: closure operations don't output epsilon states.Kaz Kylheku2024-09-151-6/+12
| | | | | | | | | | | | * regex.c (nfa_closure, nfa_move_closure): Do not add epsilon states to the output array. We only need to add them to the stack for the spanning traversal. Epsilon states are not real states; they are just a representation of the concept of transitioning to multiple states at the same time. When we add them to the output, they just end up being ignored when nfa_move_closure is called again on that set, since it only cares about states that have real transitions for a character.
* regex: bugfix: not taking full advantage of REGM_MATCH_DONE.Kaz Kylheku2024-09-151-2/+2
| | | | | | | | | | | | * regex.c (nfa_has_transitions): The logical disjunction here is wrong. We would like to test whether a state has transitions if it is not an epsilon state. The code which uses this macro doesn't care about epsilon states, even though they have transitions; those are squeezed out by transitively closure. The wrong condition here makes the code think that a NFA set has transitions when it does not, preventing the result code REGM_MATCH_DONE to be produced which can spare a character from being consumed from a stream.
* regex: misleading comment.Kaz Kylheku2024-09-151-1/+2
| | | | | | * regex.c (mfa_move_closure): Fix misleading wording in comment. The state which matches the character (has a transition for it) is not the one added to the move set.
* read-until-match: fix regression.Kaz Kylheku2024-09-143-2/+21
| | | | | | | | | | | | | | | | | | | | | | | | | Commit 9aa751c8a4f845ef2d2bba091c81ffeded941afd broke things. This fix affects the function read-until-match, scan-until-match and count-until-match which share implementation. * regex.c (scan_until_common): In the REGM_MATCH_DONE and REGM_MATCH cases, we must push the character onto the local stack, before doing the match = stack assignment. Otherwise, it's possible that the stack is empty and so no match is recorded. The REGM_FAIL case will then behave as if no match was found, consuming a character and continuing. * txr.1: Codify an existing behavior: only non-empty matches for the regex are considered by read-until-match. * tests/015/regex.tl: New file. I am amazed to discover that we don't seem to have a test suite for regexes at all. Putting the tests here which confirm this fix and provide coverage for some edge cases in read-until-match.
* quips: new one.Kaz Kylheku2024-09-031-0/+1
| | | | * stdlib/quips.tl (%quips%): New entry.
* mapcar: introduce map as a synonym.Kaz Kylheku2024-08-142-2/+14
| | | | | | | * eval.c (eval_init): Bind new map symbol to the same function as mapcar. * txr.1: Documented.
* loongarch64: fix assembler warning.Kaz Kylheku2024-08-111-2/+2
| | | | | | | | | | This issue was spotted by Alpine Linux people; I'm upstreaming their patch (originally authored by a user named huajingyun01). * jmp.S (jmp_save, jmp_restore): Use recommended register names on loongarch64: a0 and a1 rather than v0 and v1.
* genman: change to new PayPal button code.Kaz Kylheku2024-08-091-6/+4
| | | | * genman.txr: PayPay form replaced.
* Version 296.txr-296Kaz Kylheku2024-08-077-1067/+1149
| | | | | | | | | | | | | | * 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.
* keep-if, remove-if, keep-keys-if: mapfun argument.Kaz Kylheku2024-07-305-52/+90
| | | | | | | | | | | | | | | | | | | | | | | | | | | | We introduce a mapfun argument to these functions so that they can additionally transform the accumulated values. The keep-keys-if function is now implemented through the same helper function as keep-if but with the mapfun argument defaulting to a copy of the keyfun argument. * eval.c (eval_init): Update registrations of remove-if, keep-if and keep-keys-if to new arities of C functions. * lib.c (rem_if_impl): Implement new optional mapfun parameter. (remove_if, keep_if): Add mapfun parameter. (keep_keys_if): Implement via rem_if_impl, and add mapfun argument. We do the defaulting of keyfun here, so that we can then use that argument's value to default mapfun. * lib.h (remove_if, keep_if, keep_keys_if): Declarations updated. * tests/012/seq.tl: Couple of test cases exercising mapfun argument of keep-if and remove-if. * txr.1: Documented.
* doc: touch up description of trivial patterns.Kaz Kylheku2024-07-271-5/+9
| | | | | | | * txr.1: patterns are also nontrivial if they contain quasiquotes that contain nontrivial patterns, and quasiliterals that contain operators. Also, we italicize the term trivial pattern as well as nontrivial.
* doc: missing subject in @(hash ...) pattern section.Kaz Kylheku2024-07-271-1/+1
| | | | * txr.1: Fix sentence which needs a subject, "the operator".
* doc: avoid quasiliteral in reference to non-strings.Kaz Kylheku2024-07-271-6/+6
| | | | | | | * txr.1: Fix a number of places that use quasiliteral in reference to a structural quasiquote. In the TXR manual, quasiliteral syntax is the `...` that produces strings, short for quasistring literal. ^(...) is a quasiquote.
* lib: get rid of internal rewindable iter nonsense.Kaz Kylheku2024-07-253-82/+19
| | | | | | | | | | | | | | | | | | | | Iterator rewinding is only used by the three functions isec, isecp and diff, which can easily just re-initialize the iterator. * lib.c (seq_iter_rewind): Static function removed. (seq_iter_init_with_info): Remove support_rewind argument, and adjust all code referencing it on the assumption that it's zero. (seq_iter_init_with_rewind): Static function removed. (seq_iter_init, iter_begin, iter_reset, nullify, find, rfind): Drop last argument from seq_iter_init_with_info. (diff, isec, iescp): Use seq_iter_init rather than seq_iter_init_with_rewind. Instead of seq_iter_rewind, just reinitialize the iterator. * lib.h (seq_iter_init_with_info): Declaration updated. * eval.c (tprint): Drop last argument from seq_iter_init_with_info.
* zip: more permissive implementation.Kaz Kylheku2024-07-245-22/+58
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | zip and transpose should allow non-character data when the leftmost column is a string, falling back on making lists, like seq_build. We can't use seq_build as-is because of the special semantics of transpose/zip with regard to strings. We introduce a "strcat" variant of seq_build for this purpose. * lib.c (seq_build_strcat_add): New static function. (sb_strcat_ops): New static structure like sb_str_ops, but with seq_build_strcat_add as the add operation, which allows string arguments to be appended to the string rather than switching to a list. (seq_build_strcat_init): New function. * lib.h (seq_build_strcat_init): Declared. * eval.c (zip_strcat): New static function; uses seq_build_strcat_init. (zipv): Only recognize strings specially; all else goes through the existing default case. Strings use zip_strcat. * tests/012/seq.tl: New test case. * txr.1: Describe special semantics of zip/tranpose; previously only documented in one example. Clarify that the rows are only sequences of the same kind as the leftmost column if possible, otherwise lists. Remove text which says that it's an error for the other columns to contain non-string, non-character objects if the leftmost column is a string.
* make-like: use seq_build.Kaz Kylheku2024-07-233-50/+31
| | | | | | | | | | | * lib.c (make_like): Simplify implementation using seq_build, which also lets it handle more cases. * tests/012/seq.tl: New tests. Some existing test fixed, including one for tuples*. * txr.1: Documentation updated: mainly that make-like doesn't strictly require a list argument.
* New function: seq-like.Kaz Kylheku2024-07-233-5/+49
| | | | | | | | | | | | * eval.c (zip_fun): Renamed to seq_like. (zipv): Follow rename of zip_fun. (eval_init): Register seq-like intrinsic. * tests/seq.tl: Some tests for make-like and seq-like, revealing a difference: make-like needs to be rewritten to use seq_build. * txr.1: Documented.
* doc: certain JSON-related variables are specials.Kaz Kylheku2024-07-221-3/+3
| | | | | | | * txr.1: The *print-json-format*, *read-bad-json* and *read-json-int* variables are special (i.e. dynamically scoped) variables, and so reaquire the Special Variable heading, not Variable.
* json: new *read-json-int* variable.Kaz Kylheku2024-07-226-18/+74
| | | | | | | | | | | | | | | | | | | | | * parser.h (struct parser): New member, read_json_int. * parser.c (read_json_int_s): New symbol variable for *read-json-int* symbol. (parser_common_init): Look up value of *read-json-int* and store in read_json_int struct member. (parse_init): Initialize read_json_int_s with interned symbol and also register the dynamic variable. * parser.l (grammar): Extend the {JNUM} rule to check the read_json_int flag and produce an integer value if the lexeme does not contain a decimal point, e or E. * tests/010/json.tl: New tests. * txr.1: Documented. * lex.yy.c.shipped: Regenerated.
* parser: remove some wasteful string object allocations.Kaz Kylheku2024-07-224-211/+236
| | | | | | | | | | | | | | | | * lib.c (int_str_wc): New function, made out of int_str. This can be used by the parser to work with a wchar_t * string without having to create a string object. (int_str): Implemented in terms of int_str_wc. * parser.l (grammar): Remove string_own calls from numerous rule bodies that use int_str to return a number. These rules now capture the wchar_t string, pass it to int_str_wc and then immediately free it. Whereas string_own allocates an extra object and leaves it to the garbage collector. * lex.yy.c.shipped: Regenerated.