summaryrefslogtreecommitdiffstats
path: root/eval.c
Commit message (Collapse)AuthorAgeFilesLines
* tree: allow quasiquoting into #T syntax.Kaz Kylheku2019-09-281-1/+7
| | | | | | | | | | | | | | | | | * eval.c (tree_lit_s, tree_construct_s): New symbol variables. (expand_qquote_rec): Handle sys:tree-lit syntax generated by quasi-quoted #T notaton by expanding and converting to sys:tree-constuct call. (eval_init): Initialize tree_lit_s and tree_construct_s. * eval.h (tree_lit_s, tree_construct_s): Declared. * parser.y (tree): Produce sys:tree-lit syntax when #T is quasi-quoted, and unquotes occur inside it. * tree.c (tree_construct_fname, tree_construct): New static functions. (tree_init): Register sys:tree-construct intrinsic function.
* symbol-function: support lambda expressions.Kaz Kylheku2019-09-271-7/+3
| | | | | | | | | | | | | | | | | * eval.c (lookup_fun): Check for a lambda expression and return a faked binding containing the interpreted function. (do_eval, op_fun): Remove checks for lambda that are now being done in lookup_fun. In many other places where lookup_fun is used, we still need lambda checks, like in the expander. * share/txr/stdlib/place.tl (sys:get-fun-getter-setter): Take form argument. Diagnose assignments to lambda, and to unknown function place syntax. (defplace symbol-function): Pass sys:*pl-form* to sys:get-fun-getter-setter as form argument. * txr.1: fboundp and symbol-function doc updated.
* fun operator: don't cons binding when handling lambda.Kaz Kylheku2019-09-261-4/+4
| | | | | | * eval.c (op_fun): Don't cons up a fake fbinding when processing lambda; just return result of func_interp. Test for null fbinding consolidated, too.
* lookup_fun: eliminate recursion.Kaz Kylheku2019-09-261-24/+24
| | | | | | | | * eval.c (lookup_fun); Use iteration to search the nested environments. Put this code ahead of the global search so we fall back on it. Also, let's check for a compound function name first, so we don't search the environments for this.
* func-get-name: fix bogus return for nil argument.Kaz Kylheku2019-09-261-10/+15
| | | | | | | | | | | | * eval.c (func_get_name): when func_get_name has a nil function argument and nil env, it falls back on method_name, which naively searches its space and finds some static slots with a nil value which is then returned as a method name. Let's put in a type check that the argument must be a function. Also, let's drop the recursion in the nested environment search and switch to iteration, so we don't do these wasteful sanity checks on multiple re-entries of the function.
* New data structure: binary search trees.Kaz Kylheku2019-09-251-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Adding binary search trees based on the new tnode cell. The scapegoat algorithm is used, which requires no additional storage in a cell. In the future we may go to something else, like red-black trees, and carve out a bit in the tag field of the cell for the red/black color. Tree cells store only single key objects, not key/value pairs. However, which part of the key object is compared is determined by a custom key function stored in the tree container. For instance, tree nodes can be cons cells, and car can be used as the key function; the cdr then stores an associated value. Trees have a printed notation #T(<props> <key>*) where <props> is a list of up to three items: <props> ::= ([<key-fn> [<less-fn> [<equal-fn>]]]) key-fn, less-fn and equal-fn are function names. If they are missing or nil, they default, respectively, to identity, less and equal. For security, the printed notation is machine-readable only if these options are symbols, not lambda expressions. Furthermore, the symbols must be listed in the special variable *tree-fun-whitelist*. * eval.c (less_s): New symbol variable. (eval_init): Initialize less_s. * eval.h (less_s): Declard. * parser.h (grammar): New #T token recognized, mapped to HASH_T. * parser.y (HASH_T): New terminal symbol. (tree): New non-terminal symbol. (i_expr, n_expr): Add tree to productions. (fname_helper): New static function. (yybadtoken): Map HASH_T to "#T". * protsym.c: Tweaked accidentally; remove. * tree.c (TREE_DEPTH_MAX): New macro. (struct tree): New struct type. (enum tree_iter_state): New enumeration. (struct tree_iter): New struct type. (tree_iter_init): New macro. (tree_s, tree_fun_whitelist_s): New symbol variables. (tn_size, tn_size_one_child, tn_lookup, tn_find_next, tn_flatten, tn_build_tree, tr_rebuild, tr_find_rebuild_scapegoat, tr_insert, tr_lookup, tr_do_delete, tr_delete, tree_insert_node, tree_insert, tree_lookup_node, tree_lookup, tree_delete, tree_root, tree_equal_op, tree_print_op, tree_mark, tree_hash_op): New static functions. (tree_ops): New static struct. (tree): New function. (tree_init): Initialize tree_s and tree_fun_whitelist_s symbol variables. Register intrinsic functions tree, tree-insert-node, tree-insert, tree-lookup-node, tree-lookup, tree-delete, tree-root. Register special variable *tree-fun-whitelist*. * tree.h (tree_s, tree_fun_whitelist_s, tree): Declared. (tree_fun_whitelist): New macro.
* New data type: tnode.Kaz Kylheku2019-09-221-0/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Binary search tree nodes are being added as a basic heap data type. The C type tag is TNOD, and the Lisp type is tnode. Binary search tree nodes have three elements: a key, a left child and a right child. The printed notation is #N(key left right). Quasiquoting is supported: ^#N(,foo ,bar) but not splicing. Because tnodes have three elements, they they fit into TXR's four-word heap cell, not requiring any additional memory allocation. These nodes are going to be the basis for a binary search tree container, which will use the scapegoat tree algorithm for maintaining balance. * tree.c, tree.h: New files. * Makefile (OBJS): Adding tree.o. * eval.c (expand_qquote_rec): Recurse through tnode cells, so unquotes work inside #N syntax. * gc.c (finalize): Add TNOD to no-op case in switch; tnodes don't require finalization. (mark_obj): Traverse tnode cell. * hash.c (equal_hash): Add TNOD case. * lib.c (tnode_s): New symbol variable. (seq_kind_tab): New entry for TNOD, mapping to SEQ_NOTSEQ. (code2type, equal): Handle TNOD. (obj_init): Initialize tnode_s variable. (obj_print_impl, populate_obj_hash): Handle TNOD. (init): Call tree_init function in tree.c. * lib.h (enum type, type_t): New enumeration TNOD. (struct tnod): New struct type. (union obj, obj_t): New union member tn of type struct tnod. (tnode_s): Declard. * parserc.c (circ_backpatch): Handle TNOD, so circular notation works through tnode cells. * parser.l (grammar): Recognize #N prefix, mapping to HASH_N token. * parser.y (HASH_N): New grammar terminal symbol. (tnode): New nonterminal symbol. (i_expr, n_expr): Add tnode cases to productions. (yybadtoken): Map HASH_N to "#N" string.
* New function: tailp.Kaz Kylheku2019-09-031-0/+1
| | | | | | | | | | * eval.c (eval_init): Register tailp intrinsic. * lib.c (tailp): New function. * lib.h (tailp): Declared. * txr.1: Documented.
* interpreter: trivial let goes through let* case.Kaz Kylheku2019-08-311-1/+1
| | | | | | | * eval.c (bindings_helper): If there are no bindings or just one binding, then go through the sequential case. Thus trivial let is treated like let*. This avoids the continuation-related overheads incurred in the parallel case.
* interpreter: bug between let* and continuations.Kaz Kylheku2019-08-311-11/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | This was discovered by user vapnik spaknik. If a let* form is evaluated in a top-level expression such that the incoming environment is null, and a continuation is captured in the init-form of the first variable, when that continuation is invoked, an exception is thrown: "copy-env: nil is not of type env". Short repro: 1> (block nil (let* ((x (yield 42))))) ** copy-env: nil is not of type env In fact, the bug isn't that we're trying to copy nil. the problem is we are trying to copy an environment we should not be copying at all. In fact, for sequential binding, there is no need for that logic at all; it's only parallel binding which needs it, because all of the init-forms are inserting bindings into the same environment. * eval.c (bindings_helper): Don't bother with registering a copy handler for sequential binding logic, because we don't mutate environments. All of that code is moved into the parallel case.
* New function: cptr-buf.Kaz Kylheku2019-08-211-0/+1
| | | | | | | | | | * eval.c (eval_init): Register cptr-buf intrinsic. * lib.c (cptr_buf): New function. * lib.h (cptr_buf): Declared. * txr.1: Documented.
* New function: intern-fb.Kaz Kylheku2019-08-201-0/+1
| | | | | | | | | | | | | | | To accompany find-symbol-fb, there is intern-fb, which is like intern, but searches the fallback list. * eval.c (eval_init): Register intern-fb intrinsic. * lib.c (intern_fallback_intrinsic): New function. Does defaulting and error checks, then calls intern_fallback, just like intern_intrinsic calls intern. * lib.h (intern_fallback_intrinsic): Declared. * txr.1: Documented.
* lib: streamline interning slightly.Kaz Kylheku2019-08-201-1/+1
| | | | | | | | | | | | | | | | | | | | | We get rid of some defaulting and error checks from interning. This saves a few cycles on startup in the large number of intern calls that are performed. * eval.c (eval_init): Wire the intern intrinsic to the new intern_intrinsic function rather than intern. * lib.c (intern): Remove package lookup and error check on str argument. (intern_intrinsic): New function, which has the package lookup and error check. (intern_fallback): Remove package lookup and error check. * lib.h (intern_intrinsic): Declared. * txr.c (txr_main): Fix one instance of an intern call that relies on defaulting of the second argument, by passing cur_package.
* new functions: find-symbol and find-symbol-fb.Kaz Kylheku2019-08-191-0/+2
| | | | | | | | | | | | | | | | | | Turns out, there is already a find_symbol in lib.c, completely unused. * eval.c (eval_init): Register find-symbol and find-symbol-fb intrinsics. * lib.c (find_symbol): Fix this hitherto unused function to do correct defaulting of the package argument and, to accept an additional argument specifying the not-found value. (find_symbol_fb): New function. * lib.c (find_symbol): Declaration updated. (find_symbol_fb): Declared. * txr.1: Documented.
* bugfix: line number of unbound vars not reported.Kaz Kylheku2019-08-131-2/+5
| | | | | * eval.c (expand): Do not create expansion debug frames for atomic forms, only for compound forms.
* expander: bugfix: spurious lambda form warning.Kaz Kylheku2019-08-071-5/+5
| | | | | | | | | | * eval.c (do_expand): In the expansion logic for function calls, after we have done the dot-to-apply transform, we must thereafter consistently refer to the new front element of the form insym, and not the original element sym. The first element may be a lambda form moved into the second position by dot-to-apply. We then falsely warn about that being in the operator position. Test case: ((lambda ()) . 3).
* txr: regression: lack of file name in error messages.Kaz Kylheku2019-07-221-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This was broken on April 21, 2019 in commit 2e36e0feae8d1dd75c8410b365d7dc33b30ce66b (April 21, 2019) which changed parse_once in such a way that the name being passed down was no longer stored in the parser. The ensure_parser function being relied upon doesn't take on the responsibility of propagating the name from the stream to the parser, so the parser ends up with a nil name. Let's just smooth this over by having ensure_parser take a name parameter. If ensure_parser creates a new parser, it puts in the name. If the name is nil, then it is taken from the stream. * eval.c (load): Pass name to ensure_parser. * match.c (v_load): Likewise. * parser.c (parser): Take name parameter, and plant into newly constructed parser. (ensure_parser): Take name parameter. When creating a parser, give it that name, or if name is specified as nil, then give it the name taken from the stream. (parser_set_lineno): Pass nil name to ensure_parser. (lisp_parse_impl, read_file_common): Pass name to ensure_parser. * parser.h (parser, ensure_parser): Declarations updated. * parser.y (parse_once): Pass name to ensure_parser. * txr.c (txr_main): Pass spec_file_str to ensure_parser.
* expander: relax sys:setq and lisp-1 stringency.Kaz Kylheku2019-06-171-23/+21
| | | | | | | | | | | | | | | | | | | | | | | | The motivation here is that there are behaviors in the expander which hinder symbol-macro-based renaming techniques. For instance (expand '(symacrolet ((x y)) (sys:setq x x))) throws. The right hand side of the setq is fine, but the left hand one is a forbidden symbol macro. Yet, we would just like this to expand to (sys:setq y y). The original idea was that sys:setq occurs as a result of macro-expansion. Therefore, if its argument is a symbol macro, something must be wrong; it didn't get expanded. That reasoning is wrong in the face of explicit expansion techniques that make multiple expansion passes. For instance (set a b) can become something like (sys:setq #:g0005 #:g0007) when the intent that in another round of renaming these gensyms will be defined as symbol macros which perform one more renaming. * eval.c (expand_lisp1_value, expand_lisp1_setq): Macro-expand the symbol and work with the expanded one. We still keep the check for a symbol macro; these situations can arise if a symbol macro cannot expand due to circularity. (do_expand): When checking sys:setq for a bad symbol or symbol macro, work with the expanded argument.
* Replace lt(x, zero) pattern.Kaz Kylheku2019-06-151-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | This slight inefficiency occurs in some 37 places in the code. In most places we replace lt(x, zero) with minusp(x). In a few places, !plusp(x) is used and surrounding logic is simplified. In one case, the silly pattern lt(x, zero) ? t : nil is replaced with just minusp(x). * buf.c (sub_buf, replace_buf): Replace lt. * combi.c (perm, rperm, comb, rcomb): Likewise. * eval.c (do_format_field): Likewise. * lib.c (listref, sub_list, replace_list, split_func, split_star_func, match_str, lazy_sub-str, sub_str, replace_str, sub_vec, replace_vec): Likewise. * match.c (weird_merge): Likewise. * regex.c (match_regex, match_regex_right_old, match_regex_right, regex_prefix_match, regex_range_left, regex_range_right): Likewise.
* load: always bind *load-path* to actual path.Kaz Kylheku2019-05-201-1/+3
| | | | | | | | | | | * eval.c (load): Bind *load-path* to the real path that was used to open the file, not to the tentative path to which the .tl suffix was added, subject to compatibility option. * txr.1: Documentation for load revised for better wording and to document the above change. Fixed *load-path* being wrongly called a macro, and also load being called a macro. Compat note added.
* interpreter: small code tidying in me_interp_macro.Kaz Kylheku2019-05-021-2/+1
| | | | | | * eval.c (me_interp_macro): Combine initialization and assignment into one. There was previously code between the two that got removed when the old debugger was scrubbed.
* interpreter: don't bother with dot position.Kaz Kylheku2019-05-021-6/+1
| | | | | | * eval.c (do_eval_args): Since function call expressions all undergo the dot-to-apply transform, there is no need look for a form in the dot position.
* bugfix: apply regression.Kaz Kylheku2019-05-021-1/+1
| | | | | | | | | | | | | | | | | | | | | | Refactorings to apply released TXR 192 broke it, causing apply to fail to treat non-list sequences as individual arguments, as documented. This affects dotted application as well. ;; wrong (list . "abc") -> "abc" ;; correct (list . "abc") -> (#\a #\b #\c) With some misgivings, I'm not making the behavior subject to the -C compat option. * eval.c (applyv): Two things are wrong here: we moved the last fixed argument into args->list without turning it into a one-element list. Secondly, we didn't pass this list through apply_intrinsic_frob_args. We can combine both actions into just calling tolist, which is what apply_intrinsic_frob_args will do with the car of a one-element list.
* debugger: expand frames.Kaz Kylheku2019-04-291-33/+38
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch adds special unwind frames for backtracing expansions. With this, we can get rid of the global variable last_form_expanded, since to get the last form expanded, we just search for the most enclosing expand frame. * eval.c (last_form_expanded): Global variable removed. (error_trace): Use uw_last_form_expanded() instead of last_form_expanded. (expand_eval): No need to save and restore last_form_expanded any more. (expand_lisp_setq, expand_setqf, expand_lisp1, do_expand): Use uw_last_form_expanded(). (expand, do_macroexpand_1): Push and pop expand frame. This fixes a bug: do_macroexpand_1 was not recording last_form_expanded. Evaluation of top-level forms uses explicit macroexpansion, therefore top-level evaluation was neglecting to set last_form_expanded. This explains weird behavior I saw in the listener from time to time, when errors would report against the expansion of the wrong form. (eval_init): Remove reference to last_form_expanded variable. * eval.h (last_form_expanded): Declaration removed. * share/txr/stdlib/debug.tl (expand-frame print-trace, expand-frame loc): New methods. (print-backtrace): Include uw-expand frames in the backtrace. * unwind.c (expand_frame_type): New static variable. (uw_find_frames_by_mask): Handle UW_EXPAND. (uw_last_form_expanded, uw_push_expand): New functions. (uw_late_init): Register expand-frame struct type. * unwind.h (enum uw_frtype): New enum member, UW_EXPAND. (uw_last_form_expanded, uw_push_expand): Declared.
* bugfix: source lineno off by one under hash bang.Kaz Kylheku2019-04-211-1/+3
| | | | | | | | | | | | | | * eval.c (load): When we read and discard a hash bang line, we must set the parser line number to two. * parser.c (parser_set_lineno): New function. * parser.h (parser_set_lineno): Declared. * txr.c (check_hash_bang): New argument, occurs. (txr_main): Track whether hash bang has occurred in a new local variable hb_occurs. Then, before parsing, if hash bang has occurred, set the line number to two.
* parser: always use stream-associated parser for parse_once.Kaz Kylheku2019-04-211-4/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* New function: window-mapdo.Kaz Kylheku2019-04-211-0/+1
| | | | | | | | | | | | | | | | * lib.c (enum wmap_op): New enum type. (window_map_list): Use enum wmap_op for last argument instead of Boolean flag. If the argument is WMAP_MAPDO, do not accumulate. (window_map_vec, window_map, window_mapped): Adjust to new enum argument. (window_mapdo): New function. * lib.h (window_mapdo): Declared. * eval.c (eval_init): window-mapdo intrinsic registered. * txr.1: Documented.
* debugger: eval frames.Kaz Kylheku2019-04-211-14/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We introduce evaluation tracking frames. The backtrace function can use these to deduce the line from which a function is called (if called from interpreted code). Eventually we will have analogous virtual machine frames to do this for compiled code. * eval.c (do_eval): If backtraces are enabled, then push and pop an eval frame, which holds the two key pieces: the form and environment. * share/txr/stdlib/debug.tl ((fcall-frame loc), (fcall-frame print-trace), (eval-frame loc), (eval-frame print-trace)): New methods. (print-backtrace): Loop reduced to just dispatching frame-specific print-trace methods. It gives the previous and next frame to each method. The (fcall-frame print-trace) method prints function frames, using the previous form to deduce the location from which the function is called. The (eval-frame print-trace) method mostly suppresses the printing of eval frames. We print an eval frame if it is the parent of an internal function frame, and if it is the topmost frame (to identify the toplevel form at the root of the backtrace). * unwind.c (form_s): New symbol variable. (eval_frame_type): New static variable. (uw_find_frames_by_mask): Handle UW_EVAL case, producing eval-frame struct. (uw_push_eval): New function. (uw_late_init): Allocate eval-frame struct type, storing it in eval_frame_type, and gc-protect that new variable. Register uw-eval variable evaluating to a one bit mask with the UW_EVAL-th bit set. * unwind.h (enum uw_frtype): New enum constant UW_EVAL. (struct uw_eval): New struct type. (union uw_frame): New member, el. (uw_push_eval): Declared.
* defun: record source loc info.Kaz Kylheku2019-04-201-4/+4
| | | | | | | | | | | | The interpreted defun should tag the function form that is obtainable with func-get-form with source location info. * eval.c (op_defun): In all cases, propagate source loc info from the form to the function form that is bound to the function name. (op_defmacro): Propagate the source location info in the same manner: not from the body (which could be empty) but from the form.
* debugger: initial backtrace support.Kaz Kylheku2019-04-161-0/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * debug.c (debug_state): Switch to unsigned, since this is now a bitmask. (sys_print_backtrace_s): New symbol variable. (dbg_clear, dbg_set, dbg_restore): New static functions. (debug_init): Initialize sys_print_backtrace_s. Register dbg-clear, dbg-set, dbg-restore intrinsics. Register dbg-enable, dbg-step, dbg-backtrace and dbg-all bitmask variables, Lisp equivalents of DBG_ENABLE, DBG_SETP, DBG_BACKTRACE and DBG_ALL. (debug_dump_backtrace): New function. * debug.h (opt_debugger): Declaration removed. (debug_state): Declaration updated. (DBG_ENABLE, DBG_STEP, DBG_BACKTRACE, DBG_ALL): New preprocessor symbols. (debug_set_state): Inline function removed. (debug_clear, debug_set, debug_restore): New inline functions. (dbg_backtrace, dbg_fcall_begin, dbg_fcall_end): New macros. (debug_dump_backtrace): Declared. * eval.c (error_trace): Invoke debug_dump_backtrace if support is compiled in and backtraces are enabled. * lib.c (do_generic_funcall): New function, copy of generic_funcall. (generic_funcall): Now a wrapper for do_generic_funcall which registers fcall frames if backtrace support is enabled. (funcall, funcall1, funcall2, funcall3, funcall4): Route to slow generic_funcall path if backtraces are enabled. * lisplib.c (debugger_instantiate, debugger_set_entries): New static functions. (lisplib_init): Autload support for debug module via above new functions. (lisplib_try_load): Save and restore debugger state in new way using debug_set and debug_restore, with specific mask values. * parser.y (parse_once): Disable debugging in new way. * share/txr/stdlib/debug.tl New file. * sighal.h (EJ_DBG_MEMB, EJ_DBG_SAVE, EJ_DBG_REST): New macros for saving/restoring debug state. (EJ_OPT_MEMB, EJ_OPT_SAVE, EJ_OPT_REST): Reference the above macros to include debug state in extended jump context. * txr.c (help): Document --backtrace and that that -d implies --backtrace. (txr_main): Enable debugger using debug_set. Provide new --backtrace option to enable backtraces only. * unwind.c (args_s): New symbol variable. (fcall_frame_type): New static variable. (unwind_to_exit_point): Save pointer to original frame stack and restore it when calling error_trace. This is so that error_trace can walk the stack to collect a backtrace. (uw_find_frames_by_mask, uw_push_fcall): New functions. (uw_late_init): Initialize args_s and fcall_frame_type. gc-protect fcall_frame_type. Register uw-* variables corresponding to the UW_* frame types. * unwind.h (uw_frtype_t): New enum constant UW_FCALL. (struct uw_fcall): New frame structure. (union uw_frame): New member fc. (uw_push_fcall, uw_find_frames_by_mask): Declared.
* exceptions: allow description field in catch frames.Kaz Kylheku2019-04-101-6/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (op_catch): Extra argument in sys:catch syntax specifies an expression that evaluates to a description field. (expand_catch): Expand the desc expression in sys:catch syntax. * parser.c (read_file_common): Increase acceptance of compiled files from versions 1-4 to 1-5, since we are now marking compiled files with version 5.0 rather than 4.0. * share/txr/stdlib/asm.tl (op-catch catch): Support new argument in the opcode syntax. Turns out we have a spare field in the instruction format which was previously set to zero We can use that for the description. Thus, the instruction set and VM remain backward compatible: old code works. * share/txr/stdlib/compiler.tl (compiler comp-catch): Handle the desc argument introduced into the sys:catch form. We must compile it as an expression, then inject the code into the instruction template, and reference the output register of that code block in the catch instruction. (%tlo-ver%): Bump up the compiled file version to 5.0. * share/txr/stdlib/except.tl (usr:catch, catch*): Add desc argument to generated sys:catch form, specifying it as nil. * unwind.c (desc_s): New symbol variable. (uw_find_frames_impl): Set the desc member of the extracted catch structure from the corresponding field in the catch frame. (uw_late_init): Initialize desc_s with interned symbol. Add desc slot to catch-frame type. * unwind.h (struct uw_catch): New member, desc. (uw_catch_begin_w_desc): New macro. * vm.c (vm_catch): Extract the desc field from the catch instruction, and use uw_catch_begin_w_desc to propagate that to the catch frame.
* debug support: crude debugger removed.Kaz Kylheku2019-04-091-21/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * 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.
* New function: cptr-size-hint.Kaz Kylheku2019-04-061-0/+1
| | | | | | | | | | * eval.c (eval_init): Register cptr-size-hint intrinsic. * lib.c (cptr_size_hint): New function. * lib.h (cptr_size_hint): Declared. * txr.1: Documented.
* tagbody: code replication bug.Kaz Kylheku2019-04-051-20/+14
| | | | | | | | | | | | | | | tagbody translates to a loop around a sys:switch special form. The compiler recognizes substructure sharing among the branches of the the sys:switch code and de-duplicates the generated assembly code accordingly. Unfortunately, the expander for sys:switch has a bug which spoils the substructure sharing. * eval.c (expand_forms_ss): We must process the incoming form list itself into the hash, not just that list's cdr. Onthe other hand, there is no need to hash the cars of the forms list (the forms themselves), so the code simplifies quite a bit.
* Move numeric functions from lib.c to arith.cKaz Kylheku2019-03-251-31/+0
| | | | | | | | | | | | | | | * arith.c, lib.c (num, c_num, c_fixnum, bad_float, flo, c_flo, fixnump, bignump, integerp, floatp, numberp nary_op, nary_simple_op, plusv, minusv, mulv, divv, logandv, logiorv, gtv, ltv, gev, lev, numeqv, numneqv, sumv, prod, exptv, gcdv, lcmv): Function definitions moved from lib.c to arith.c. (nary_op_keyfun, unary_num, unary_arith, unary_int, sumv, prodv, rexpt, abso_self): Static functions moved from libmoved from lib.c to arith.c. (max): New macro in arith.c. (arith_init): Registrations moved from eval.c. * eval.c (eval_init): Registrations moved to arith.c
* Register arithmetic functions in arith module.Kaz Kylheku2019-03-251-47/+1
| | | | | | | | * arith.c (plus_s): Definition moved here. (arith_init): Register numerous math intrinsics here. * eval.c (plus_s): Definition removed. (eval_init): Numerous math function registrations removed.
* lazy conses: support state in car and cdr.Kaz Kylheku2019-03-131-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Here we allow application code to take advantage of a trick already used internally. When a lazy cons cell is created, we can temporarily put state information into its car and cdr fields. When these fields are accessed normally, by the car and cdr function, the lazy cons' update function will be invoked, which will populate these fields. If we have a way for that function to retrieve the existing values of those fields, then the function can treat those fields as state information: it can retrieve the values into temporary local variables, overwrite the original values, and then propagate the state information into the car and cdr into the next lazy cons cell being added. Thus lazy list generation that needs two cells of state or less does not require the allocation of a context object. * eval.c (eval_init): make-lazy-cons becomes a three-argument function with two optional parameters. New functions lcons-car and lcons-cdr are registered. * lib.c (make_lazy_cons_pub): New function, wrapping make_lazy_cons_car_cdr with argument defaulting. (lcons_car, lcons_cdr): New functions. * lib.h (make_lazy_cons_pu, lcons_car, lcons_cdr): Declared. * txr.1: Updated doc of make-lazy-cons regarding new arguments. Documented lcons-car and lcons-cdr.
* lib: optimize lazy functions with unchecked accesses.Kaz Kylheku2019-03-121-61/+61
| | | | | | | | | | | | | | | | | | * lib.h (us_lcons_fun): New inline function. (us_cons_bind): New macro. * eval.c (lazy_mapcar_func, lazy_mapcarv_func, range_func, range_star_func, generate_func, giterate_func, ginterate_func, expand_right_fun, repeat_infinite_func, repeat_times_func, pad_func): Use us_cons_bind, us_car, us_cdr, us_rplaca, us_rplacd and us_lazy_cons_func, which skip the type check. * lib.c (lazy_conses_func, lazy_appendv_func, rem_lazy_func, lazy_flatten_func, lazy_flatcar_fund, tuples_func, partition_by_func, partition_func, split_func, split_star_func, partition_star_func, lazy_interpose_fun, take_list_fun, take_while_list_fun, take_until_list_fun, lazy_where_has_func): Likewise.
* New sequence iterator object and functions.Kaz Kylheku2019-03-111-0/+3
| | | | | | | | | | | | | | | | | * eval.c (eval_init): Register seq-begin, seq-next and seq-reset. * lib.c (seq_iter_s): New symbol variable. (seq_iter_mark): New static function. (seq_iter_ops): New static structure. (seq_begin, seq_next, seq_reset): New functions. (obj_init): Intern seq-iter symbol, used as class name for iterators. * lib.h (seq_iter_s, seq_begin, seq_next, seq_reset): Declared. * txr.1: Documented.
* expander: tree-bind: fix incorrect param env.Kaz Kylheku2019-03-081-2/+2
| | | | | | | | | | | | * eval.c (do_expand): A wrong thing is being done here: the macro is extended using the original parameter syntax, that has not been processed by expand_params. The body is then expanded using that environment. This subtly breaks support for parameter macros in tree-bind. They work, but there are spurious warnings about undefined variables during expansion, and the wrong scope handling can introduce bugs. The right thing is to derive new_menv by pulling the parameter symbols from params_ex.
* lambda expressions aren't fboundp.Kaz Kylheku2019-03-031-5/+11
| | | | | | | | | | | | | | | | | | We don't want (fboundp '(lambda ...)) to be true, or (symbol-function '(lambda ...)) to yield a function. This also fixes funny print formatting of lambda expressions. * eval.c (lookup_fun): Do not recognize lambda expressions. Also, return nil for unknown syntax; don't bother looking it up in the hashes. (do_eval): We now have to check for a lambda expression in the car position to evaluate it; lookup_fun will no longer do that. (op_fun): The interpreted fun oprator must also check for lambda itself. (do_expand): A small code change is required here to avoid spuriously warning about a lambda in the car position.
* Fix use of comma operator as statement terminator.Kaz Kylheku2019-03-031-2/+2
| | | | | | * eval.c (fmakunbound, mmakunbound): Replace comma operator with statement terminator, an unintentional stylistic oddness. No behavior change.
* New macro: load-for.Kaz Kylheku2019-03-021-0/+78
| | | | | | | | | * eval.c (me_load_for): New function. (rt_load_for): New static function. (eval_init): Register load-for macro and sys:rt-load-for intrinsic function. * txr.1: Documented.
* eval: introduce variable for usr:var symbol.Kaz Kylheku2019-03-021-1/+2
| | | | | | * eval.c (usr_var_c): New symbol variable. The existing var_s hold sys:var, not usr:var. (eval_init): var symbol interned in usr package.
* ffi, eval: move struct_s.Kaz Kylheku2019-03-021-1/+2
| | | | | | | | | | * eval.c (struct_s): Now defined here. (eval_init): struct now interned here. * eval.h (struct_s): Declared. * ffi.c (struct_s): Definition removed. (ffi_init) struct no longer interned here.
* bracket: new function.Kaz Kylheku2019-02-241-0/+1
| | | | | | | | | | * eval.c (eval_init): Register bracket intrinsic. * lib.c (bracket): New function. * lib.h (bracket): Declared. * txr.1: Documented.
* pprof: generate much smaller expansion.Kaz Kylheku2019-02-191-17/+21
| | | | | | | | | * eval.c (me_pprof): Instead of emitting open code which destructures the output of pprof and prints a diagnostic, let's do that inside a run-time support function called sys:rt-pprof, so (pprof x) now expands to (rt:pprof (prof x)). (rt_pprof): New function. (eval_init): Register sys:rt-pprof intrinsic.
* Optimize hash operation with unsafe car/cdr.Kaz Kylheku2019-02-141-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The associative lists that make up the chains of a hash table are guaranteed to be made of conses. We can use unsafe versions of car, cdr, rplaca and rplacd to speed up hash operations. * eval.c (op_dohash): Use unsafe operations on hash cell. * filter.c (trie_compress, regex_from_trie): Likewise. * hash.c (hash_equal_op, hash_print_op, hash_mark, hash_grow, hash_assoc, hash_assql, copy_hash_chain, gethash, inhash, gethash_n, sethash, remhash, hash_next, maphash, do_weak_tables, group_by, group_reduce, hash_keys_lazy, hash_keys, hash_values_lazy, hash_values, hash_pairs_lazy, hash_pairs, hash_alist_lazy, hash_uni, hash_diff, hash_symdiff, hash_isec, hash_subset, hash_update, hash_update_1, hash_revget): Likewise. * lib.c (us_rplaca, us_rplacd): New functions. (package_local_symbols, package_foreign_symbols, where, populate_obj_hash, obj_hash_merge): Use unsafe operations on hash cell * lib.h (us_rplaca, us_rplacd): Declared. * parser.c (circ_backpatch, get_visible_syms): Use unsafe operations on hash cell. * struct.c (method_name, get_slot_syms): Likewise.
* gethash_c: review uses and improve or replace.Kaz Kylheku2019-02-141-9/+9
| | | | | | | | | | | | | | | | | | | | * eval.c (env_fbind, env_vbind, reg_symacro): Use gethash_l instead of gethash_c to eliminate repeated cdr operations on the same cell. * hash.c (sethash): Since new_p is never used, eliminated it and use nulloc. (group_reduce): Use gethash_l instead of gethash_c. * lib.c (obj_init): Replace rplacd(gethash_c(...)) pattern whose return value is not used with with sethash. We lose some diagnosability here since sethash doesn't take a "self" argument. (obj_print_impl, obj_hash_merge): Use gethash_l instead of gethash_c. * parser.y (ensure_parser, parser_circ_def, get_visible_syms, rlset): Use gethash_l instead of gethash_c.
* symdiff: new function.Kaz Kylheku2019-02-141-0/+1
| | | | | | | | | | | | * eval.c (eval_init): Register symdiff intrinsic. * lib.c (symdiff): New function. * lib.h (us_car_p, us_cdr_p): New inline functions. (symdiff): Declared. * txr.1: Documented, also fixing issues not related to symdiff doc.