summaryrefslogtreecommitdiffstats
path: root/match.c
Commit message (Collapse)AuthorAgeFilesLines
* parser: always use stream-associated parser for parse_once.Kaz Kylheku2019-04-211-5/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This refactoring is needed for fixing the off-by-one line number bug when the hash bang line is processed. * eval.c (load): Don't define parser locally; ensure there is one in the stream and use it. * match.c (v_load): Likewise. * parser.c (get_parser_impl): Renamed to parser_get_impl and changed from internal to external linkage. (ensure_parser): Changed to external linkage. (lisp_parser_impl, read_file_common): Follow rename of get_parser_impl. * parser.h (parse_once): Declaration updated. (parser_get_impl, ensure_parser): Declared. * parser.y (parse_once): Take self parameter; drop parser parameter. Ensure a parser to the stream, rather than declaring one locally. Don't clean up the parser when done, just let the stream clean it up. * txr.c (parse_once_noerr): Parser argument is dropped and not passed to parse_once. Program name is passed as self argument to parse_once. (txr_main): When parsing the TXR pattern query, don't define a parser locally; ensure there is one in the stream and use it, like in load and v_load.
* debug support: crude debugger removed.Kaz Kylheku2019-04-091-38/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * debug.c (debug_depth, debug_quit_s): Variables removed. (step_mode, next_depth, breakpoints, last_command, cols): Static variables removed. (debug_check): C99 inline instantiation removed. (help, show_bindings): Static functions removed. (debug): Function removed. (debug_set_state): Now takes one int argument, returns int. It's anticipated that the new debug system will have a simple on-off switch; there won't be a debug_depth hack. (debug_restore_state): Function removed. (debug_init): Emptied. * debug.h (debug_depth, debug_state_t): Declarations removed. (debug_enter, debug_leave, debug_return): Macros removed. (debug_check): Inline function removed. (debug_set_state): Declaration updated. (debug_restore_state): Declaration removed. (debug_frame, debug_end): Macros removed. * eval.c (do_eval, me_interp_macro): Debugging support scrubbed. * lisplib.c (lisplib_try_load): Adapt to debug_set_state interface change. * match.c (h_fun, do_match_line, v_fun, match_files, match_fun): Debugging support scrubbed. * parser.y (parse_once): Adapt to debug_set_state interface change. * protsym.c: Regenerated. * signal.h (debug_depth): Declaration removed. (EJ_DBG_MEMB, EJ_DBG_SAVE, EJ_DBG_REST): Macros removed. (EJ_OPT_MEMB, EJ_OPT_SAVE, EJ_OPT_REST): Reduced to unconditionally empty definitions for future use. * unwind.c (uw_push_debug): Function removed. * unwind.h (uw_frtype_t): UW_DBG enum member removed. (struct uw_debug): struct declaration removed. (union uw_frame): db member removed. (uw_push_debug): Declaration removed. * txr.1: Debugger doc removed.
* unwind: rename env frames.Kaz Kylheku2019-04-061-16/+16
| | | | | | | | | | | | | | | | | | | | | | Unwind frames of type ENV exist for the sake of the pattern language. Let's rename them accordingly. * match.c (tleval, tleval_progn, h_fun, tx_subst_vars, v_bind, v_output, v_filter, v_fun): Occurrences of the macros uw_env_begin and uw_env_end are renamed. * unwind.c (uw_env_stack): Renamed to uw_menv_stack. (uw_unwind_to_exit_point, uw_abscond_to_exit_point, uw_find_env, uw_pop_frame, revive_cont): Follow rename of UW_ENV to UW_MENV and uw_env_stack to uw_menv_stack. (uw_push_env): Renamed to uw_push_match_env, and updated to follow renames. * unwind.h (enum uw_frtype, uw_frtype_t): UW_ENV renamed to UW_MENV. (uw_push_env): Renamed to uw_push_match_env. (uw_env_begin, uw_env_end): Renamed to uw_match_env_begin an uw_match_env_end.
* @(output): bugfix: lazy evaluation doesn't work.Kaz Kylheku2019-04-051-4/+15
| | | | | | | | | | | | | | | In an @(output), if we reference a variable bound to a lazy list, and the generation of that logic references TXR pattern variables, things break: the lazy list's code doesn't see the binding. This is because the lazy list is forced by some logic that doesn't establish the proper environment for that evaluation. Inside a @(repeat), the do_output function measures the lengths of lists emanating from variables, and that has the effect of forcing the lazy lists. * match.c (v_output): Just set up the dynamic environment around the entire function, so that any Lisp evaluation that occurs is happening as if it were via tleval.
* c++ maintenance: multiple defs of mod_s and bit_s.Kaz Kylheku2019-03-301-1/+2
| | | | | | | | | * arith.h (mod_s, bit_s): Add extern declarations. * ffi.c (bit_s): Remove definition. * match.c (mod_s): Remove definition. Include "arith.h" to obtain declaration of mod_s.
* pattern lang: diagnose undefined function facing EOF.Kaz Kylheku2019-02-011-3/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | This addresses the following issue. Suppose the query is something like this: @abc @(nonexistent) and there is one line of data. In this case, there is no error about a nonexistent function. The function lookup fails in vertical mode, so horizontal mode fallback takes place. But that just concludes that there is no data, and reports a failed match. But the programmer might have intended to invoke some function or directive that doesn't need to match anything, but rather has an important effect. In this patch we fix that. As part of the change, we disallow functions from shadowing horizontal directives. * match.c (match_files): Do not look up sys:var and sys:text through the directive table, but check for these. If the directive is not found in the vertical table, check the horizontal table; if found there, don't try it as a function but go to horizontal processing. Then if the function lookup fails, we diagnose a failed lookup; don't fall through to horizontal processing.
* style: convert assignment to initialization.Kaz Kylheku2019-02-011-3/+1
| | | | | | * match.c (match_files): Change pointless two-step initialization of a variable by assignment into straight initialization.
* @(next): Cover Lisp expressions with :nothrow.Kaz Kylheku2019-01-281-10/+57
| | | | | | | | | | | | | | We would like @(next (open-directory "nonexistent") :nothrow) to act as a failed match, rather than for the exception to propagate (and likely terminate TXR). The problem is that only file sources are treated with :nothrow. * match.c (tleval_nothrow, tleval_144_nothrow): New static functions. (v_next_impl): Use tleval_nothrow for all Lisp evaluation. If nothrow is requested and Lisp evaluation returns the colon symbol (which tleval_nothrow produces in the case of an exception), then treat the situation as a failed match.
* @(next): Diagnose source combined with source-giving option.Kaz Kylheku2019-01-281-3/+3
| | | | | | | | * match.c (v_next_impl): The check against the presence of multiple of source-specifying keyword options must also consider the base source as part of the mutual exclusion, so that syntax like @(next "file" :string "str") is also ruled out.
* @(next): bugfix: nothrow not causing failed match.Kaz Kylheku2019-01-281-6/+14
| | | | | | | | | | * match.c (v_next_impl): Contrary to the documentation and to "classic" TXR behavior exhibited in compatibility mode, when @(next "file" :nothrow) fails to open "file", it treats the situation as a cue to read from standard input, rather than to treat the situation as a failed match. This is because complex_open returns nil, and when that is passed to lazy_stream_cons, that function defaults to standard input.
* Copyright year bump 2019.Kaz Kylheku2019-01-161-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c, lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/asm.tl, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/compiler.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/trace.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/vm-param.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr: Extended Copyright line to 2018.
* Eliminate ALLOCA_H.Kaz Kylheku2018-12-311-1/+1
| | | | | | | | | | | | | * configure: Instead of generating a definition of ALLOCA_H, generate the variable HAVE_ALLOCA_<name> with a value of 1, where <name> is one of stdlib, alloca or malloc. * alloca.h: New header. * args.c, eval.c, ffi.c ffi.c, ftw.c, hash.c, lib.c, match.c, parser.c, parser.y, regex.c, socket.c, stream.c, struct.c, sysif.c, syslog.c, termios.c, unwind.c, vm.c: Include "alloca.h" instead of ALLOCA_H.
* Drastically reduce inclusion of <dirent.h>.Kaz Kylheku2018-12-111-1/+0
| | | | | | | | | | | | | | | | | | | The <dirent.h> header is included all over the place because it is needed by a single declaration in stream.h. That declaration is for a function that is only called within stream.c, so we make it internal. Now only stream.c has to include <dirent.h>. * buf.c, debug.c, eval.c, ffi.c, filter.c, gc.c, gencadr.txr, hash.c, lib.c, lisplib.c, match.c, parser.c, regex.c, socket.c, struct.c, strudel.c, sysif.c, syslog.c, termios.c, txr.c, unwind.c, vm.c: Remove #include <dirent.h>. * cadr.c: Regenerated. * stream.c (make_dir_stream): Make external function static. * stream.h (make_dir_stream): Declaration updated.
* Better identify functions that misuse COBJ-s and hashes.Kaz Kylheku2018-11-071-2/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In this patch, the cobj_handle, cobj_ops and variants of gethash get an additional argument to identify the caller. Many functions are updated to pass this down. * buf.c (buf_strm): Pass self name to cobj_handle. * eval.c (env_fbind, env_vbind, rt_defvarl, me_case): Pass self name to gethash_c or gethash_e. (load): Pass self name to read_eval_stream and read_compiled_file. (reg_symacro): Pass situation-identifying string to gethash_c. * ffi.c (ffi_type_struct_checked, ffi_closure_struct_checked, ffi_call_desc_checked, uni_struct_checked): Take self name parameter, and pass down to cobj_handle. (ffi_get_type, ffi_get_lisp_type): Take self name and pass down to ffi_type_struct_checked. (union_get_ptr): Take self name and pass to uni_struct_checked. (ffi_union_in, ffi_union_put): Pass self name to union_get_ptr. (ffi_type_compile): Pass self name to ffi_get_lisp_type. (ffi_make_call_desc): Pass self name to ffi_type_struct_checked, ffi_get_type and ffi_call_desc_checked. (ffi_make_closure): Pass self name to ffi_call_desc_checked. (ffi_closure_get_fptr): Take self name, pass to ffi_closure_struct_checked. (ffi_typedef, ffi_size, ffi_alignof, ffi_offsetof, ffi_arraysize, ffi_elemsize, ffi_elemtype, ffi_put_into, ffi_put, ffi_in, ffi_get, ffi_out, make_carray): Pass self name to ffi_closure_struct_checked. (carray_struct_checked): Take self name, pass to cobj_handle. (carray_set_length, carray_dup, carray_own, carray_free, carray_type, length_carray, copy_carray, carray_ptr, buf_carray, vec_carray, list_carray, carray_ref, carray_refset, carray_sub, carray_replace, carray_get_common, carray_put_common, unum_carray, num_carray, put_carray, fill_carray): Pass self name to carray_struct_checked. (carray_blank, carray_buf, carray_cptr): Pass self name ffi_type_struct_checked. (carray_pun): Pass self name to carray_struct_checked and ffi_type_struct_checked. (make_union): Pass self name to ffi_type_struct_checked. (union_members, union_get, union_put, union_in, union_out): Pass self name to uni_struct_checked. (make_zstruct, zero_fill, put_obj, get_obj, fill_obj): Pass self-name to ffi_type_struct_checked. * ffi.h (ffi_closure_get_fptr, union_get_ptr): Declarations updated. * filter.c (trie_add): Pass self-name to gethash_l. * hash.c (make_similar_hash, copy_hash, hash_count, get_hash_userdata, set_hash_userdata, hash_begin, hash_next, hash_uni, hash_diff, hash_isec): Pass self name to cobj_handle. (gethash_c, gethash_e): Take self name parameter and pass down to cobj_handle. (gethash_f): Take self parameter and pass down to gethash_e. (gethash, inhash, gethash_n, sethash, pushhash, remhash, clearhash, hash_update_1): Pass self name to gethash_e or gethash_c. * hash.h (gethash_c, gethash_e, gethash_f): Declarations updated. (gethash_l): Take self name, and pass down to gethash_c. * lib.c (class_check): Take self name parameter and use in type mismatch diagnostic. (use_sym, unuse_sym, symbol_needs_prefix, find_symbol, intern, unintern, intern_fallback, unique, in, sel, obj_print_impl, populate_obj_hash, obj_hash_merge): Pass self name to gethash_f or gethash_l. (symbol_visible, obj_init): Pass situation-identifying string to gethash_e. (cobj_handle, cobj_ops): Take self name parameter and pass down to class_check. * lib.h (class_check, cobj_handle, cobj_ops): Declarations updated. * match.c (v_load): Pass self name to read_compiled_file and read_eval_stream. * parser.c (get_parser_impl): Take self name and pass to cobj_handle. (ensure_parser): Pass situation-identifying string to gethash_c. (parser_circ_def): Pass self-name to gethash_c. (lisp_parser_impl): Pass self name to get_parser_impl and class_check. (lisp_parse, nread, iread): Pass self-name to lisp_parser_impl. (read_file_common): Take self name parameter and pass down to get_parser_impl. (read_eval_stream, read_compiled_file): Take self name and pass down to read_file_common. (load_rcfile): Pass situation-identifying string to read_eval_streem. (get_visible_syms): Pass situation-identifying string to gethash_c. (parser_errors, parser_eof): Pass self name to cobj_handle. * parser.h (read_eval_stream, read_compiled_file): Declarations updated. * parser.y (rlset): Pass self name to gethash_c. * rand.c (make_random_state, random_state_get_vec,l random_fixnum, random_float): Pass self name to cobj_handle. * regex.c (regex_source, regex_print, regex_run): Pass self-name to cobj_handle. (regex_machine_init): Take self name param and pass to cobj_handle. (search_regex, match_regex, match_regex_right, regex_prefix_match, read_until_match): Pass self-name to regex_machine_init. * stream.c (stdio_get_fd): Pass self name to cobj_handle. (generic_get_line): Get COBJ operations via unsafe, diret object access rather than cobj_ops. (set_mode_props): Get object handle via unsafe, direct object access. (stream_fd, sock_family, sock_type, sock_peer, set_sock_peer, get_string_from_stream, get_list_from_stream, stream_set_prop, stream_get_prop, close_stream, get_error, get_error_str, clear_error, get_line, get_char, get_byte, unget_char, unget_byte, put_buf, fill_buf, put_string, put_char, put_byte, flush_stream, seek_stream, truncate_stream, get_indent_mode, test_set_indent_mode, set_indent_mode, get_indent, set_indent, inc_indent, width_check, force_break, get_set_ctx, get_ctx): Pass self name to cobj_ops. (make_delegate_stream): Take self name parameter, pass down to cobj_ops. (record_adapter): Pass self name down to make_delegate_stream. (format): Pass self name to class_check. * struct.c (stype_handle): Pass self name to cobj_handle. (make_struct_type): Pass self name to class_check. * txr.c (read_eval_stream_noerr): Take self name parameter, pass to read_eval_stream. (txr_main): Pass istuation-identifying string to read_compiled_file and read_eval_stream_noerr. * unwind.c (revive_cont): Pass self-name to cobj_handle. * vm.c (vm_desc_struct): Take self name parameter, pass to cobj_handle. (vm_desc_nlevels, vm_desc_nregs, vm_desc_bytecode, vm_desc_datavec, vm_desc_symvec, vm_execute_toplevel, vm_execute_closure, vm_closure_entry): Pass self name to vm_desc_struct. (vm_closure_struct): Take self name parameter, pass to cobj_handle.
* txr: support variable in postive match.Kaz Kylheku2018-05-221-0/+5
| | | | | | | | | | | | | In the @{var mod} syntax in the pattern language, allow mod to be a variable which contains a regex or integer, not just an integer or regex literal. * match.c (h_var): Check for modifier being a variable, and resolve it. * parser.y (modifiers): Allow a SYMTOK phrase. * txr.1: Documented.
* parser: @(if) hack in output must use usr package.Kaz Kylheku2018-04-101-0/+3
| | | | | | | | | | | * match.c (else_s, elif_s): New symbol variables. (syms_init): Initialize new variable with interned symbols. * match.h (else_s, elif_s): Declared. * parser.y (not_a_clause): Refer to if_s, else_s and elif_s, which are symbols in the usr package, instead of intering symbols in whatever package is current.
* Implement compiled file loading.Kaz Kylheku2018-04-041-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (load): If open_txr_file indicates compiled file by setting txr_lisp_p to character #\o, use read_compiled_file. * match.c (v_load): Likewise. * parser.c (open_txr_file): Recognize the .tlo suffix, and also try to open a .tlo version of an unsuffixed file before trying it as .tl. Indicate a .tlo file by setting txr_lisp_p to the character #\o rather than t. (read_file_common): New static function, made from contents of read_eval_stream. Will either evaluate forms or load compiled code by instantiating virtual machine descriptions and performing their top-level execution. (read_eval_stream): Now a wrapper for read_file_common. (read_compiled_file): New function. * parser.h (read_compiled_file): Declared. * txr.c (help): List new --compiled option. (txr_main): If --compiled is specified, set txr_lisp_p to #\o to load as compiled code. Update error message that -c is not compatible with --lisp or --compiled. If txr_lisp_p is #\o, then use read_compiled_file.
* Lisp load function supports .txr files.Kaz Kylheku2018-02-161-0/+4
| | | | | | | | | | | | * eval.c (load): Instead of throwing error when a .txr file is opened, process it according to sensible requirements. * match.c (v_load): Store bindings in the current environment frame before evaluating Lisp, and then update afterward. This allows .txr files loaded from Lisp to continue matching with the current bindings and extend those bindings. * txr.1: Update documentation of load.
* Copyright year bump 2018.Kaz Kylheku2018-02-151-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.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, lib.c, lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, win/cleansvg.txr: Extended Copyright line to 2018.
* Use rplaca and rplacd instead of set over car_l/cdr_l.Kaz Kylheku2018-01-011-8/+8
| | | | | | | | | | | | | | | | | | | | | | | This reduces the proliferation of car_l and cdr_l. With this change, nreverse should work on chains of objects that implement rplacd. * combi.c (comb_gen_fun_common, rcomb_gen_fun_common): Use rplaca. * eval.c (mappendv, mapdov): Likewise * hash.c (hash_equal_op): Likewise. * lib.c (nreverse, acons_new, aconsql_new, sort_list): Use rplaca and rplacd. * match.c (dest_set, v_gather, v_collect, v_flatten, v_cat, v_output, v_filter): Likewise * parser.c (ensure_parser): Use sys_rplacd. * unwind.c (uw_register_subtype): Use rplacd.
* Bi-directional string tree match for non-vars.Kaz Kylheku2017-08-021-2/+12
| | | | | | | | | | | | | | | | | | There is an inconsistency in @(bind) in that given @(bind x y) where x is a variable, both directions are tried for a string tree match. x could be tree of strings and y a string atom, or vice versa. But if x is just an atom, or a Lisp evaluation, then only one direction is tried. @(bind @(list "a" "b") "a") succeeds, but @(bind "a" @(list "a" "b")) fails. * match.c (dest_bind): Test both directions in the scalar and Lisp evaluated cases of the left hand side. Subject to compatibility, just in case. * txr.1: Compat note added.
* bugfix: pattern language undefined warning system.Kaz Kylheku2017-07-161-2/+3
| | | | | | | | * match.c (match_reg_var): The uw_tentative_def_exists check is being made against a symbol rather than the tag. This check will always fail. There is no ill consequence. Just that uw_register_tentative_def will be called redundantly when it doesn't have to be.
* New :lists feature in @(collect)/@(coll).Kaz Kylheku2017-07-111-5/+28
| | | | | | | | | | | | | | | | | | | This is for those situations when multiple lists are being collected, and must all be bound even if empty. Yet, the lists are independent rather than parallel, so the discipline of :vars is too rigid. * match.c (lists_k): New keyword symbol variable. (h_coll, v_collect): Extract :lists argument as local variable lists, validate that :lists is not used on @(repeat)/@(rep) and implement logic. (match_expand_keyword_args): Treat expansion of :lists the same way as :vars. (syms_init): Initialize lists_k. * match.c (lists_k): Declared. * txr.1: Documented.
* bugfix: regression in horizontal @(trailer)Kaz Kylheku2017-06-191-3/+3
| | | | | | | * match.c (h_trailer): Prevent LOG_MATCH call from being evaluated in failed case, when the position is nil. This situation triggers an exception, because LOG_MATCH prints the position as an integer using ~d.
* Refactoring hash bang support; hash bang null hack.Kaz Kylheku2017-05-301-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The hash bang mechanism is handled in one place, and disentangled from all parsing logic. It is also endowed with special powers. * eval.c (load): Pass one less argument to read_eval_stream. * match.c (v_load): Likewise. * parser.c (read_eval_stream): hash_bang_support Boolean argument removed. Hash bang logic removed. (load_rcfile): Pass only two arguments to read_eval_stream. * parser.h (read_eval_stream): Declaration updated. * txr.c (remove_hash_bang_line): Function removed. (check_hash_bang): New static function. (txr_main): Recognize the script file name while still inside the argument processing loop. Open the file, and check for a hash bang line, doing the special processing which can generate more arguments from material after a null byte in the hash bang line. The parse_stream variable is now initialized to nil and doubles as a Boolean indicating whether a stream has been opened. After the loop, we remove the script file from the arguments, if we have an open stream and the spec_file_str matches. read_eval_stream is called only with two arguments. * txr.1: Revised existing documentation and described new features.
* Bugfix: missing usr:end and usr:single symbols.Kaz Kylheku2017-04-111-0/+6
| | | | | | | | | | | | | | When TXR pattern language code is canned in the context of an alternative *package* which uses the usr package, the scanner will throw false errors on @(end) and @(single). This is because these symbols don't exist in the usr package and will get interned in the current package. The scanner will then complain that they are not in the usr package. * match.c (syms_init): Intern end and single in the usr package, but don't store the return value in any variable.
* Indexing in variable subst applies to any sequence.Kaz Kylheku2017-04-051-5/+12
| | | | | | | | | | | | | | | | | | | | The @{a [3]} syntax in quasiliterals and @(output) now indexes into the original object a if it is any sequence kind, not specifically a list. Otherwise it indexes into its string representation. * eval.c (format_field): Combine the elements of the object with the separator if it is any sequence type other than a string. Subject to compat option. (subst_vars): Avoid converting any kind of sequence to string, rather than just lists. After any field formatting is applied, if the object is any sequence (not just alist), combine the elements with a space. All subect to compat option. * match.c (tx_subst_vars): Same treatment as subst_vars. * txr.1: Compatibility notes added.
* Bind variable during directive delimited match.Kaz Kylheku2017-03-221-1/+37
| | | | | | | | | | | | | | | | | | | | | | | | | | The existing behavior is: when a situation like @a@(foo) performs a search for the match for @(foo) in order to determine the extent of the text matched by variable a, the variable a is not bound. That is to say, @(foo) is tried in an environment in which a doesn't exist. The variable is only bound when the search succeeds, and then @(foo) is processed again, with the variable now available. The new behavior is that @(foo) is tested in an environment in which a is bound. The variable's value is bound to the range of text between the original position and the tested position where @(foo) is tried. This is subject to the copatibility option. * match.c (ml_bindings_specline_pos): New static function. (search_match_binding_var): New static function, variant of search_match. (h_var): In the var-delimited-by-directive case, perform the search using search_match_binding_var, unless <= 172 compatibility is requested. * txr.1: Compatibility note added.
* Remove useless consume_prefix call.Kaz Kylheku2017-03-221-2/+0
| | | | | | | | | * match.c (search_match): Calling consume_prefix from this function does nothing because it does not advance c->pos, and so it is hereby removed. This was introduced in commit fce7c87fa0099e5414607676fc73c9dfa9d7649c on 2012-02-11, at the same time when consume_prefix was introduced.
* Bugfix: missing warnings when main file is .txr.Kaz Kylheku2017-03-221-0/+3
| | | | | | | | | | | | | | | | | | | If the main file of an application is a .txr file, unbound function and variable warnings are not being generated. * match.c (v_load): For consistency with the load function in eval.c, release deferred warnings in the normal return case, if we are not a recursive load. However, this doesn't fix anything because a load or include is always recursive being invoked from a .txr file that is being loaded. The problem is in fact that the recursive flag is nil when it shouldn't be, and then the uw_unwind block obliterates the warnings. * txr.c (txr_main): We must bind *load-recursive* to t around not just the loading of Lisp, but also of TXR. Otherwise the individual loads will release warnings, raising false positives for forward references.
* Rename badly named default_bool_argKaz Kylheku2017-03-171-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * lib.h (default_bool_arg): Inline function renamed to default_null_arg. * eval.c (if_fun, pad, ginterate, giterate, range_star, range, constantp, macroexpand_1, macro_form_p, expand_with_free_refs, do_expand, eval_intrinsic, func_get_name, make_env_intrinsic): Follow rename. * arith.c (lognot): Likewise. * gc.c (gc_finalize): Likewise. * glob.c (glob_wrap): Likewise. * hash.c (group_reduce, gethash_n): Likewise. * lib.c (print, multi_sort, lazy_str, vector, iff, tok_str, split_str_keep, search_str, remove_if, val): Likewise. * match.c (match_fun): Likewise. * parser.c (lisp_parse_impl, regex_parse): Likewise. * rand.c (make_random_state): Likewise. * regex.c (read_until_match, search_regex, regex_compile): Likewise. * socket.c (sock_accept, sock_connect): Likewise. * stream.c (open_files_star, open_files, run, open_process, open_tail, get_string, record_adapter): Likewise. * struct.c (static_slot_ensure, static_slot_ens_rec, clear_struct, make_struct_type): Likewise. * sysif.c (exec_wrap, errno_wrap, cobj_ops_init): Likewise. * unwind.c (uw_capture_cont, uw_find_frames_impl): Likewise.
* Add in-package directive.Kaz Kylheku2017-03-131-1/+2
| | | | | | | | | | | | * match.c (in_package_s): New symbol variable. (syms_init): Initialize in_package_s. * match.h (in_package_s): Declared. * parser.y (check_parse_time_action): Add case for in-package. Evaluate just with eval, as a case of the in-package macro. * txr.1: Documented.
* New directive: mdo.Kaz Kylheku2017-03-121-1/+2
| | | | | | | | | | | | | | | * eval.h (progn_s): Declarationa added. * match.c (mdo_s): New symbol variable. (syms_init): Initialize mdo_s. * match.h (mdo_s): Declared. * parser.y (check_for_include): Renamed to check_parse_time_action and implements mdo, not only include. (clauses_rev): Follow rename of function. * txr.1: Documented.
* bugfix: @(next) in function called with match-fun.Kaz Kylheku2017-03-121-2/+6
| | | | | | | | | | | | | | | | | | | | The match-fun function must augment the input list with the current input source, because @(next) pops the first item from the files list and tries to open the second. We want it so that if we invoke (match-fun 'f arglist input '("abc")) then if the pattern function f invokes @(next), it will open "abc". * match.c (match_fun): Calculate a value for the curfile property of the match context and pass it to mf_all. If the input is a stream, we get its name. We also push this curfile onto the files list, satisfying the expectation that curfile and the first element of files refer to the same thing.
* match-fun: report error using external name.Kaz Kylheku2017-03-121-1/+1
| | | | | * match.c (match_fun): Report self as match-fun in error message.
* match-fun: make last two args optional.Kaz Kylheku2017-03-121-1/+3
| | | | | | | | * eval.c (eval_init): Update registration of match-fun. * match.c (match_fun): Do defaulting on third and fourth arg. * txr.1: Documenation updated.
* Don't open streams or stdin on non-matching directives.Kaz Kylheku2017-03-091-22/+25
| | | | | | | | | | | | | * match.c (open_data_source): The logic of not opening the data source for a non-matching directive must be applied to streams also, because the lazy list mechanism will read ahead from an underlying non-interactive stream. We must also apply it in the case when we open standard input by default. If standard input is non-interactive such that the lazy list unconditionally tries to read a line from it upon construction, we misbehave. The program could block on the read. Even if it doesn't block, the input action is an unwanted externally visible event.
* Don't sweep bad data source under the rug.Kaz Kylheku2017-03-081-1/+1
| | | | | * match.c (open_data_source): If the data source isn't a string or stream, then error out.
* clean up open_data_source function.Kaz Kylheku2017-03-081-7/+5
| | | | | * match.c (open_data_source): do the spec_bind in just one place. Use first_spec consistently in the debuglf calls.
* Drop the annoying need for - for standard input.Kaz Kylheku2017-03-081-1/+9
| | | | | | | | | | | | | * match.c (open_data_source): If there is nothing in the files array and data is t (indicating a request to open a data source), then use standard input. Subject to the compatibility option. * Makefile (txr-manpage.html): Drop use of the txr - argument in rule recipe. * txr.1: Document that - isn't necessary. Added to compatibility notes.
* bugfix: :counter var not registered tentative.Kaz Kylheku2017-03-041-0/+4
| | | | | | | | | | | | | | | This test case suffers a spurious unbound variable warning: @(collect :counter x) @(bind y @x) @(end) * match.c (match_expand_keyword_args): Register the :counter variable as a tentative definition with match_reg_var. We don't do this for :vars because they are not newly introduced: the :vars construct doesn't bind. The :counter feature is the only keyword feature in collect which binds a new variable.
* bugfix: expand :counter property in @(collect).Kaz Kylheku2017-03-041-1/+10
| | | | | | | * match.c (match_expand_keyword_args): counter is wrongly lumped with things like :times here, which fails to handle the syntax with an initialized like :counter (a (+ 2 2)). We move it to a separate case.
* bugfix: integrate finally clause with accept.Kaz Kylheku2017-02-231-20/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The test case for this issue is: @(next :list '#"the quick brown fox jumped") @(block b) @(try) @the @(accept b) @(finally) @quick @(end) @(end) Inside the try-protected clause, we bind the variable the to the string "the". Then we initiate an accept whose exit point is the block b. There are two problems: the finally clause executes against the input stream beginning with "the", even though "the" was consumed in the protected block. Secondly, the binding captures by finally is thrown away; the accept control transfer continues and only one variable emerges from the block: the variable the. In this patch we obtain a different behavior. The processing of the finally clause detects that an accept transfer is passing through. The clause is executed against the input stream that is being communicated by the accept, in this case the stream which beings with the second line "quick", so the quick variable gets bound to this string. Secondly, the bindings being communicated by the accept are hijacked and replaced with the new environment captured by the finally clause. Thus, in this case, the quick variable emerges out of the block. Lastly, if the finally block fails to match, the accept transfer is converted to a @(fail) transfer and continues to the block. * match.c (v_take_accept): New static function. (v_block); Use v_take_accept function to update the match_files_ctx state from a caught accept. That is to say, the code to do this moves into that function, and is just called. This way we can share that logic with the finally processing in v_try. (v_try): Detect an accept transfer by checking the exit point. If one is going on, then accept the input and bindings into the current context and process the clause in that context. Afterward, update the accept result object with the new position and bindings or convert to a failure.
* bugfix: data stream escape in accept transfers.Kaz Kylheku2017-02-201-1/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This fixes a bug in the same category as the parent commit. The issue of concern here is that if an @(accept) control transfer terminates a @(next) directive, the data stream to which the @(next) directive switched escapes out of that scope. Example: @(block b) @(next :list '("line")) @(accept b) @(end) @var Here, var captures "line" because the stream set up by @(next) is carried by the @(accept) to the destination block, and then taken as the current data source going forward. The overwhelmingly preferrable behavior is for the accept to honor the input source controlling dynamic scope of the @(next) directive. When the control transfer crosses a @(next) boundary by terminating a next directive, the transfer's data must be replaced by the original data stream just prior the @(next). However, the bindings are carried through untouched. This is basically opposite to pattern function invocations. Pattern functions freely advance the data position in the same stream, but carefully control what bindings emerge. Whereas @(next) carefully scopes the input source, but freely allows bindings to emerge. The @(accept) control transfers must be in accord with these behaviors. And, in the existing case of @(trailer) which properly interacts with accept, the same holds. That directive allows bindings to escape but prevents the advancement of the input within the current stream. If it is terminated by @(accept), these hold. * match.c (v_next_impl): New static function, identical to previous v_next. (v_next): Reduced to wrapper around v_next_impl which intercepts @(accept) control transfers and fixes up their data position to match the position coming into the @(next).
* bugfix: accept allowing binding escape.Kaz Kylheku2017-02-201-0/+33
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The issue is that if @(accept) traverses a pattern function call boundary, the rules for resolving bindings when terminating a function are being ignored. For instance, this test case ends with a and x being bound to "y" and "x": @(define fun (a)) @(bind x "x") @(accept a) @(end) @(block a) @(fun "y") @(end) the right behavior is that there are no bindings at all. When the accept control transfer terminates (fun "y"), binding resolution must take place as if the function terminated normally. This resolution, in this particular case, suppresses the a and x bindings which are local, so that the test case terminates with no bindings. * match.c (fun_intercept_accept): New static function. (h_fun, v_fun): Set up an unwind handler which calls fun_intercept_accept to catch accepts and fix-up their bindings.
* Eliminate common code: pattern fun binding resolution.Kaz Kylheku2017-02-201-36/+37
| | | | | | * match.c (fun_resolve_bindings): New static function. (h_fun, v_fun): Replace common code with a call to fun_resolve_binding.
* Bugfix: h_trailer has to intercept accept.Kaz Kylheku2017-02-161-8/+26
| | | | | | | * match.c (h_trailer): Add the unwind handling for intercepting the block return driven by @(accept) and fixing up the position, so the semantics of trailer isn't violated, similarly to how it is done in v_trailer.
* Support horizontal @(block), phase 2.Kaz Kylheku2017-02-151-12/+62
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Accepts produce a return value which is a vector object carrying both vertical (data pointer + line number) and horizontal context (position within line). Both a vertical and horizontal @(block) construct look at this and behave in some intelligent way. * match.c (match_line_ctx): New member, data. Thus, horizontal contexts now know the vertical list from whcih they are derived. (ml_all): Take data argument, and initialize new member. (h_block): If a vector object emerges from the block, that means the block terminated due to an accept. If the accept is from a different line, or from vertical context, then just keep whatever horizontal position is current in the horizontal context. (We have no way of knowing how far we advanced between the start of the block and the elem which triggered the accept.) If the accept is from the same line then advance to the indicated position. (h_accept_fail): Produce a three-element vector object for the accept long return value. This carries the bindings, the vertical-style result value, and the horizontal position. (freeform_prepare): Update ml_all call to include c->data. (v_block): Like in h_block, handle a vector result value. An accept emanating from horizontal context for the current line causes the vertical context to advance to the next line. Horizontal accept from a different line doesn't advance the data. Accept from a vertical context behaves as before. (v_accept_fail): Produce vector object for accept. (v_trailer): When intercepting accept, patch new vector representation of accept value. (match_files): Pass c.data to ml_all.
* Support horizontal @(block), phase 1.Kaz Kylheku2017-02-151-0/+45
| | | | | | | | | | | | Unresolved issue: horizontal @(accept) terminating in a vertical @(block) or horizontal @(block) in a different line, or vertical @(accept) caught in horizontal context. * match.c (h_block, h_accept_fail): New functions. (dir_tables_init): Register horizontal @(block), @(accept) and @(fail). * parser.y (elem): Support BLOCK syntax.
* Support horizontal form of @(throw).Kaz Kylheku2017-02-131-0/+1
| | | | | | | * match.c (dir_tables_init): Wire throw_s into horizontal dispatch table via hv_trampoline. * txr.1: Documented.