summaryrefslogtreecommitdiffstats
path: root/lib.c
Commit message (Collapse)AuthorAgeFilesLines
* Adding mismatch function.Kaz Kylheku2016-12-121-0/+112
| | | | | | | | | | * eval.c (eval_init): Register mismatch intrinsic. * lib.c (mismatch): New function. * lib.c (mismatch): Declared. * txr.1: Documented mismatch.
* bugfix: find-max doesn't handle internal literals.Kaz Kylheku2016-12-121-1/+2
| | | | | * lib.c (find_max): Handle LIT case in switch. Also, fix nonsensical, typo-ridden error message.
* New function: endp.Kaz Kylheku2016-12-101-0/+10
| | | | | | | | | | | | | This improves compatibility with other Lisp dialects in a small way. * eval.c (eval_init): Register endp intrinsic. * lib.c (endp): New function. * lib.h (endp): Declared. * txr.1: Documented endp.
* C++ regression in printer.Kaz Kylheku2016-12-071-21/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * lib.c (obj_print_impl): The recent change for unquote-related read/print consistency introduced initializing declarations which are crossed by a label. They are not actually used past the label, so we can put in a block to delimit their scope to get rid of the compiler error. diff --git a/lib.c b/lib.c index dd599d2..1ca1790 100644 --- a/lib.c +++ b/lib.c @@ -9663,29 +9663,31 @@ val obj_print_impl(val obj, val out, val pretty, struct strm_ctx *ctx) for (iter = obj; consp(iter); iter = cdr(iter)) { val d; - val a = car(iter); - val unq = nil; - - if (a == sys_unquote_s) - unq = lit(". ,"); - else if (a == sys_splice_s) - unq = lit(". ,*"); - - if (unq) { - val d = cdr(iter); - val ad = car(d); - - if (consp(d) && !cdr(d)) { - put_string(unq, out); - if (a == sys_unquote_s && unquote_star_check(ad, pretty)) - put_char(chr(' '), out); - obj_print_impl(ad, out, pretty, ctx); - put_char(closepar, out); - break; + { + val a = car(iter); + val unq = nil; + + if (a == sys_unquote_s) + unq = lit(". ,"); + else if (a == sys_splice_s) + unq = lit(". ,*"); + + if (unq) { + val d = cdr(iter); + val ad = car(d); + + if (consp(d) && !cdr(d)) { + put_string(unq, out); + if (a == sys_unquote_s && unquote_star_check(ad, pretty)) + put_char(chr(' '), out); + obj_print_impl(ad, out, pretty, ctx); + put_char(closepar, out); + break; + } } - } - obj_print_impl(a, out, pretty, ctx); + obj_print_impl(a, out, pretty, ctx); + } finish: d = cdr(iter); if (nilp(d)) {
* bugfix: , *sym printed as ,*sym.Kaz Kylheku2016-12-061-2/+18
| | | | | | | | | | | | | | We are lacking read/print consistency in the handling of unquotes applied to symbols whose names begin with a star. * lib.c (unquote_star_check): New static function. (obj_print_impl): Use unquote_star check when printing an unquote to determine whether a space is needed so that the result doesn't read back as a ,* splice. * txr.1: Change "should" to "must": the whitespace is absolutely required in , *x*. Adding more discussion as a dialect note.
* bugfix: print unquote/splice in dot position.Kaz Kylheku2016-12-051-1/+19
| | | | | | * lib.c (obj_print_impl): Properly print objects like ^(... . ,expr) and (... . ,*expr) rather than ^(... sys:unquote expr) or ^(... sys:splice expr).
* Adding curry_1234_1 function.Kaz Kylheku2016-12-011-0/+15
| | | | | | | * lib.c (do_curry_1234_1): New static function. (curry_1234_1): New function * lib.h: (curry_1234_1): Declared.
* Don't throw when printing (sys:quasi . atom).Kaz Kylheku2016-11-271-2/+2
| | | | | | | | | | | | | | | | | | | We do not have perfect read/print consistency for quasiliterals. Programs can construct quasiliterals which cause the printer to throw exceptions, or which don't print such that the same object is read back. However, at least we can handle some trivial cases. In particular, the object (sys:quasi . #<function>) occurs in the system, as the top-level binding of the quasi operator. With this change, we can print that instead of throwing. * lib.c (obj_print_impl): Check that a quasiliteral or quasi-list-literal is a list with at least one argument. Don't print (sys:quasi) or (sys:quasi . non-nil-atom) in the notation.
* bugfix: read-print consistency for @(expr).Kaz Kylheku2016-11-271-1/+1
| | | | | | | | * lib.c (obj_print_impl): Only print (sys:expr x . rest) as @x if rest is nil, and x is a cons. Otherwise we create read-print problems: (sys:expr x y) prints as @x, concealing y. And (sys:expr sym) prints as @sym which reads as (sys:var sym).
* Expander warns about unbound variables.Kaz Kylheku2016-11-261-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (eval_exception): New static function. (eval_error): Reduced to wrapper around eval_exception. (eval_warn): New function. (me_op): Bind the rest symbol in a shadowing env to suppress watnings about unbound rest. (do_expand): Throw a warning when a bindable symbol is traversed that has no binding. (expand): Don't install atoms as last_form_expanded. * lib.c (warning_s, restart_s, continue_s): New symbol variables. (obj_init): Initialize new symbol variables. * lib.h (warning_s, restart_s, continue_s): Declared. * lisplib.c (except_set_entries): New entries for ignwarn and macro-time-ignwarn. * parser.c (repl_warning): New static function. (repl): Use repl_warning function as a handler for warning exceptions: to print their message and then continue by throwing a continue exception. * parser.y (warning_continue): New static function. (parse_once): Use warning_continue to ignore warnings. In other words, we suppress warnings from Lisp that is mixed into TXR pattern language code, because this produces too many false positives. * share/txr/stdlib/except.tl (ignwarn, macro-time-ignwarn): New macros. * share/txr/stdlib/place.tl (call-update-expander, call-clobber-expander, call-delete-expander): Ignore warnings around calls to sys:expand, because of some gensym-related false positives (we expand code into which we inserted some gensyms, without having inserted the constructs which bind them. * tests/011/macros-2.txr: Suppress unbound variable warnings from a test case. * tests/012/ifa.tl: Bind unbound x y variables in one test case. * tests/012/struct.tl: Suppress unbound variable warnings in some test cases. * uwind.c (uw_throw): If a warning is unhandled, then print its message with a "warning" prefix and then throw a continue exception. (uw_register_subtype): Eliminate the check for sub already being a subtype of sup. This allows us to officially register new types against t. (uw_late_init): Register continue exception type as a subtype of the restart type. Formally register warning type. * txr.1: Documented ignwarn.
* bugfix: quasilit read/print consistency, part 2.Kaz Kylheku2016-11-261-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In this patch commit I'm addressing the issue introduced in part 1 that expressions in @(output) blocks are still using (sys:expr ...) wrapping, but are passed down to an evaluator which now expects unwrapped expressions now. As part of this change, I'm changing the representation of @expr from (sys:expr . expr) to (sys:expr expr). * eval.c (format_field): Adjust access to sys:expr expression based on new representation. (transform_op): Likewise. * lib.c (obj_print_impl): Likewise. * match.c (dest_bind): Likewise. (do_txeval): Likewise. (do_output_line): Likewise, in some compat code. Here is the fix for the issue: when calling tx_subst_vars, we pass a list of one element containing the expression, not wrapped in sys:expr. Previously, we passed a one-element list containing the sys:expr. * parser.y (o_elem): If a list occurs in the syntax, represent it as (sys:expr list) rather than (sys:expr . list). (list): Do the same for @ n_expr syntax. (expand_meta, make_expr): Harmonize with the representation change.
* bugfix: quasilit read/print consistency, part 1.Kaz Kylheku2016-11-261-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The bug is that `@@@a` prints as `@@a` which reads as a different object. In this patch we simplify how quasiliterals are represented. Embedded expressions are no longer (sys:expr E), just E. Meta-numbers N and variables V are still (sys:var N). However `@@a` and `@a` remain equivalent. * eval.c (subst_vars): No need to look for expr_s; just evaluate a compound form. The recursive nested case is unnecessary and is removed. (expand_quasi): Do nothandle expr_s; it is not part of the quasi syntax any more. * lib.c (out_quasi_str): Do not look for expr_s in the quasi syntax; just print any expression with a @ the fallback case. * match.c (tx_subst_vars): Analogous changes to those done in subst_vars in eval.c. * parser.y (quasi_meta_helper): Static function removed. This was responsible for the issue due to stripping a level of meta from expressions already having a meta on them. (quasi_item): In the `@` n_expr syntax case, no longer call quasi_meta_helper. The remaining logic is simple enough to put in line. Symbols and integers get wrapped with (sys:var ...); other expressions are integrated into the syntax as-is.
* Completion of fallback list implementation.Kaz Kylheku2016-11-161-1/+26
| | | | | | | | | | | | | | | | | | | | | | | | * lib.c (find_symbol): New function. (symbol_present): Search the fallback list also to determine whether the symbol is visible. * lib.h (find_symbol): Declared. * parser.y (sym_helper): Implement a new behavior for qualified symbols. Interning new symbols is only allowed for packages that have an empty fallback list. * parser.c (get_visible_syms): New static function. (find_matching_syms): Use get_visible_syms to get the list of eligible symbols. This way the fallback list of the package is included if it is the current package. * share/txr/stdlib/package.tl (defpackage): Do not insert a default (:use usr) if there is no :usr clause. Since defpackage is very new, no need for backward compatibility; the amount of code depending on this is likely zero. * txr.1: Documented fallback list feature.
* Start of fallback package list implementation.Kaz Kylheku2016-11-161-0/+53
| | | | | | | | | | | | | | | | | | | | * eval.c (eval_init): Register package-fallback-list and set-package-fallback-list intrinsics. * lib.c (package_fallback_list, set_package_fallback_list, intern_fallback): New functions * lib.h (package_fallback_list, set_package_fallback_list, intern_fallback): Declared. * parser.y (sym_helper): Slightly restructure function so that the symbol interning is done separately in the various cases. In the unqualified symbol case, use intern_fallback to search the fallback list of the current package. * share/txr/stdlib/package.tl (defpackage): Implement :fallback clause.
* Fix circular printing issue for package objects.Kaz Kylheku2016-11-101-1/+1
| | | | | | * lib.c (obj_print_impl): Print package name using ~a rather than ~s. Otherwise if the string object occurs elsewhere in the structure being printed, we have a problem.
* Handle interpreted functions in circle printing.Kaz Kylheku2016-11-101-0/+7
| | | | | | | | | | | | | | | | | | | Interpreted functions print as #<interpreted fun: name args>, thus repeating some list structure in their notation. This means we must traverse them when populating the object hash during printing, and also when backpatching after parsing. Test case: evaluate and print (let ((s '(lambda (a b c) d))) (list s (eval s))) with *print-circle* enabled. * lib.c (populate_obj_hash): Handle FUN objects of functype FINTERP. * parser.c (circ_backpatch): Likewise.
* Fix some gc-unsafe mutations found by inspection.Kaz Kylheku2016-11-101-2/+2
| | | | | | | | | | | | | | | | | | * eval.c (force): When replacing the promise by a forced value, we must use the set macro. Only the deref assignments which store symbols are safe, not the one storing ret. * lib.c (alist_nremove, alist_nremove1): We must use the set macro here instead of assigning through deref. Even though these assignments preserve the direction of the list (they just splice out nodes), it's possible that the list already contains a "wrong-way" reference (old generation to new) and that the node making this reference is appropriately marked to be processed properly in the next GC cycle. If we remove *that* node, we then cause its predecessor to point to the new generation node and that predecessor could be old generation.
* Check for non-package value in *package*.Kaz Kylheku2016-11-101-1/+9
| | | | | | * lib.c (get_current_package): If *package* contains nonsense, then reset it to a sane value and throw an exception.
* Implementing package foreign symbol concept.Kaz Kylheku2016-11-101-38/+238
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (eval_init): Register new intrinsics: package-local-symbols, package-foreign-symbols, use-sym, unuse-sym, use-package, unuse-package, unintern. * gc.c (mark_obj): Mark new hidhash member of struct package. * lib.c (make_package): Initialize new hidhash member of struct package. (lookup_package): New static function. (find_package): Allow string or symbol argument. (get_package): New static function. (delete_package, package_symbols): Use get_package for flexible package argument; delete_package removes symbols from other packages via unuse_package. (package_local_symbols, package_foreign_symbols): New functions. (use_sym, unuse_sym): New functions. (resolve_package_designators): New static function. (use_package, unuse_package): New functions. (symbol_present): New static function. (intern): Revised with get_package for flexible package argument. (unintern): New function. (rehome_sym): Use get_package. Semantics revised. (obj_print_impl): Use symbol_present function to determine whether object is visible in *package* and can be printed without a prefix, rather than naive home package test. * lib.h (struct package): New member, hidhash. (package_local_symbols, package_foreign_symbols, use_sym, unuse_sym, use_package, unuse_package, unintern): Declared. * txr.1: Documentation updated. Extended section introducing the design of packages, and argument conventions. New functions described. Existing function descriptions revised, particularly rehome-sym. Missing description of delete-package added.
* Check that name is stringp in some sym functions.Kaz Kylheku2016-11-081-6/+18
| | | | | * lib.c (make_sym, make_package, intern): Check that the name argument is a string.
* Implement *package* special var; package overhaul.Kaz Kylheku2016-11-081-26/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (load): Rebind *package* in the local dynamic environment already established for the sake of *load-path*. By doing this we cause *package* to be restored to its prior value, which allows the loaded file to alter it. Common Lisp works this way. (eval_init): Register *package* variable, with the user package as its default value. * lib.c (package_s): New symbol variable. (intern, rehome_sym): Default the package argument to the current package, not to user_package. (get_user_package, get_system_package, get_keyword_package): Functions removed. (get_current_package): New function. (obj_print_impl): Revise symbol printing. Keyword and uninterned symbols are printed with : and #: prefixes. The remainder are printed with a package prefix if their home package isn't the current package. * lib.h (keyword_package, user_package, system_package): These macros are just straight aliases for the global variables, not going through the lookup mechanism, which was pointless. (cur_package): New macro. (package_s): Declared. (get_current_package): Declared. * lisplib.c (lisplib_try_load): Establish a local dynamic environment, and bind the *package* variable to the user package which the library modules expect. * parser.c (find_matching_syms, provide_completions): Treat unqualified symbols in the current package rather than user package. * parser.y (sym_helper): Intern unqualified symbols in the current package, not user package. * txr.1: Document that the variables user-package, system-package and keyword-package should not be modified. Document the *package* special variable, and that intern and rehome-sym default their package argument to its value. (Here we get rid of wrong references to the undocumented variable *user-package*).
* Don't access *print-circle* in early init.Kaz Kylheku2016-11-081-1/+1
| | | | | | | | * lib.c (obj_print): Check that print_circle_s has been interned before trying to look it up as a variable. Otherwise the auto-load code will be triggered, and try to use a hash table that doesn't exist yet. This can happen when this code is called during early initialization.
* Circ print: fix recursion from print methods.Kaz Kylheku2016-11-011-12/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Two issues addressed here, both occurring when *print-circle* is enabled and an object has struct components which have a custom print method that re-enters the object printer. One issue is that the children of these components which occur just once print with spurious labels: like #3=, when no matching #3# occurs. The other bug is a wrong "unexpected duplicate object" exception caused by mismanagement of the child object's label hash table and its merging with the parent. * stream.h (struct stream_ctx): New member, obj_hash_prev. Makes the parent hash table known to populate_obj_hash, if there is a table, otherwise nil. * lib.c (populate_obj_hash): If there is a parent table, check each object in it. If it occurs, then bail. I.e. don't add objects to the child table which occur in the parent. This fixes both issues. Also, we do the unexpected duplicate object check right here now: if we traverse an object that already printed without a label (because it is not known to be duplicate), that means that a custom print method is inappropriately introducing new references to existing objects, contrary to the rules. (obj_hash_merge): The logic here is now simplified. All entries in the child table are simply moved to the parent. If anything already exists, that is an unexpected stuation indicating an internal problem, turned into a variant of the unexpected duplicate object message. * tests/012/circ.tl: New file, giving tests for the bugs. * tests/012/circ.expected: New file.
* Don't enter symbols into cycle-identifying hash.Kaz Kylheku2016-10-311-2/+7
| | | | | | | | | * lib.c (circle_print_eligible): New inline function. (obj_print_impl): Do not bother with hash lookup for interned objects that don't participate in circle notation. (populate_obj_hash): Replace open-coded test with call to circle_print_eligible.
* Relax restrictions on dwim places.Kaz Kylheku2016-10-311-9/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | No longer require the leftmost expression in a dwim place to itself be a place, except when the expression evaluates to a list, and the list is subject to an element deletion or a range operation. * eval.c (eval_init): Register dwim-set and dwim-del with one additional argument that the C functions now take. * lib.c (dwim_set, dwim_del): Take a new place_p argument which informs these functions whether the object they are operating on came from a syntactic place. The forbidden situations are diagnosed based on this flag: modification of the subrange of a list, or deletion of a list ref. Some error messages reworded. * lib.h (dwim_set, dwim_del): Declarations updated. * share/txr/stdlib/place.tl (defplace dwim): Produce a different update, clobber and delete expansion when the obj-place form isn't a place. In the non-place case, do not assign the result of the sys:dwim-set or sys:dwim-del operation back obj-place. Furthermore, pass a Boolean flag to sys:dwim-set and sys:dwim-del indicating which situation is the case: did the object argument come from a place or non-place. * txr.1: Documentation updated.
* lambda-set method: treat [struct ...] as place.Kaz Kylheku2016-10-301-19/+51
| | | | | | | | | | | | | | | | | | | | | | | | * eval.c (eval_init): Change registration of dwim-set to only one required argument, with the rest variadic. * lib.c (lambda_set_s): New symbol variable. (dwim_set): Change to variadic function that takes all arguments other than the object/sequence being operated on as struct args *. Rewrite to do a test on the object type first, handling hashes and structs specially. (obj_init): Initialize lambda_set_s. * share/txr/stdlib/place.tl (defplace dwim): Rewritten for more generic syntax. The only argument required is obj-place; the other arguments are treated as a variable argument list, all treated uniformly. This eliminates the special handling of the default value for hash lookups. * args.h (args_count): New inline function. * txr.1: Updated documentation for dwim operator, which neglects to mention use over objects thanks to the lambda function. Documented lambda-set.
* Same fix in tok-where as tok-str.Kaz Kylheku2016-10-261-1/+23
| | | | | | | | lib.c (tok_where) Implement new loop which suppresses empty tokens immediately matching after non-empty tokens. Old loop available under compatibility. No documentation update needed since tok-where is already documented as working like tok-str.
* Don't bother with numeq comparison in tok_where.Kaz Kylheku2016-10-261-1/+1
| | | | * lib.c (tok_where): Just compare match_end == match_start.
* Fix regression: broken tok_where.Kaz Kylheku2016-10-261-7/+10
| | | | | | * lib.c (tok_where): Check that the regex match succeeded before destructuring the result with range_bind.
* Fix tok-str semantics once again.Kaz Kylheku2016-10-261-1/+26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The problem is that when the regular expression is capable of matching empty strings, tok-str will extract an empty token immediately following a non-empty token. For instance (tok-str "a,b" /[^,]*/) extracts ("a" "" "b") instead of just ("a" "b"). This is a poor behavior and the way to fix it is to impose a rule that an empty token must not be extracted immediately at the ending position of a previous token. Only a non-empty token can be consecutive to a token. * lib.c (tok_str): Rewrite the logic of the loop, using the prev_empty flag to suppress empty tokens which immediately follow non-empty tokens. The addition of 1 to the position when the token is empty to skip a character is done at the bottom of the loop and a new last_end variable keeps track of the end position of the last extracted token for the purposes of extracting the keep-between area if keep_sep is true. The old loop is preserved intact and enabled by compatibility. * tests/015/split.tl: Multiple empty-regex test cases for tok-str updated. * txr.1: Updated tok-str documentation and also added a note between the conditions under which split-str and tok-str, invoked with keep-sep true, produce equivalent output. Added compatibility notes.
* obj_print: uw guard frame only when circ printing.Kaz Kylheku2016-10-261-2/+4
| | | | | | * lib.c (obj_print): Only set up and tear down the continuation-blocking unwind frame when doing circle printing.
* Let guard frames optionally pass through unwinding.Kaz Kylheku2016-10-261-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | We have a bug in that when an exception occurs in a context called from obj_print, the guard for stopping continuation captures across obj_print also unintentially blocks the unwinding. Let's make the unwinding blockage optional * unwind.c (uw_unwind_to_exit_point): If a UW_GUARD is encountered, do not abort if the uw_ok flag is set; keep unwinding. (uw_push_guard): New uw_ok argument, initializes the uw_ok member of a guard frame. * unwind.h (struct uw_guard): New struct type. (union uw_frame): New member gu of type struct uw_guard. (uw_push_guard): Declaration updated. * ftw.c (ftw_callback): Pass zero as new uw_push_guard argument: no unwinding across the POSIX library function ftw. * glob.c (errfunc_thunk): Likewise, no unwinding across the library function glob. * lib.c (obj_print): Pass 1 as new uw_push_guard argument: continuations can't be captured, but unwinding is okay.
* last, butlast: become accessors, get optional arg.Kaz Kylheku2016-10-261-7/+20
| | | | | | | | | | | | | | | | | | | | * eval.c (optimize_qquote_form): Pass nil to default new argument of butlast. (me_whilet, me_iflet_whenlet): Likewise for last. (eval_init): Add optional argument to registration of last and butlast intrinsics. * lib.c (last, butlast): Support optional numeric argument, like in Common Lisp. * lib.h (last, butlast): Declarations updated. * share/txr/stdlib/place.tl (last, butlast): New place macros. * txr.1: Updated documentation. The description of last is now moved into the sequence functions section.
* New accessors nthlast and butlastn.Kaz Kylheku2016-10-251-0/+31
| | | | | | | | | | | | | | * eval.c (eval_init): register nthlast and butlastn intrinsicis. * lib.c (nthlast, butlastn): New function. * lib.h (nthlast, butlastn): Declared. * share/txr/stdlib/place.tl (defplace nthlast, defplace butlastn): New places. * txr.1: Documented nthlast and butlastn.
* Default to epoch time in time-parse.Kaz Kylheku2016-10-231-1/+9
| | | | | | | * lib.c (epoch_time): New static function. (time_parse): Default the struct tm to epoch. * txr.1: Documented.
* Block continuation capture across printer.Kaz Kylheku2016-10-211-0/+5
| | | | | * lib.c (obj_print): Applying a continuation guard around the body of the function. This seems prudent.
* Another fix to print method circular printing.Kaz Kylheku2016-10-211-8/+21
| | | | | | | | | | | | | | | | | | | | | | | Continuing on the theme of the previous patch, we now properly detect the situation when the recursive call is re-introducing duplicate references to objects that have already been sent to the stream without at #<num>= label. It's too late to print those objects, so we throw an exception. * lib.c (obj_print_impl): When we print an object that doesn't have duplicates (its hash entry has a nil value), we replace that value with the : symbol to indicate that the object has already been printed. (obj_hash_merge): New function, factoring out the hash merging logic from obj_print, introduced in parent commit. Here, we detect the case that the recursive print call has submitted to us an object which was already printed without a label: because it is associated with the : symbol in the parent hash. This situation is a show-stopper so we throw. We cannot attempt to print the object in any manner because we can get into runaway recursion. (obj_print): Hash merging logic replaced with call to new static function.
* Fix circular printing across print methods.Kaz Kylheku2016-10-211-0/+10
| | | | | | | | | * lib.c (obj_print): When invoked recursively in circular printing mode, collect the nodes of the new object into a separate hash table. Then merge these entries into to the previous hash table. If the newly visited object visits objects we have already seen, suppress those entries.
* Changes to the printing framework.Kaz Kylheku2016-10-201-39/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The print function now takes an optional boolean for pretty printing. The print method is also called with a third argument; hence structures can customize both standard printing and pretty printing. * lib.c (obj_print): Take pretty argument, and pass it down to obj_print_impl. This makes obj_pprint redundant. (obj_pprint): Function removed: it was identical to obj_print except for passing t down to obj_print_impl for the pretty argument. These two wrappers had started small and got bigger with identical changes done in parallel. (pprint): New function. (tostring, dump): Pass nil for pretty argument of obj_print. (tostringp): Use pprint instead of obj_pprint. * lib.h (obj_print): Declaration updated. (obj_pprint): Declaration removed. (print, pprint): Declared. * eval.c (prinl): Pass nil for pretty_p argument of obj_print. Do the stream defaulting here; obj_print doesn't do it. (pprinl): Pass t for pretty_p argument of obj_print, and do stream argument defaulting. (eval_init): Register print to new print function rather than directly to obj_print. Register pprint to new pprint function rather than obj_pprint. * hash.c (hash_print_op): Call obj_print_impl to print the :equal-based keyword, rather than obj_print. Pass down the pretty flag. All the other keywords are treated this way; this fixes an inconsistency. * match.c (dump_var): Call pprint instead of obj_pprint. * stream.c (formatv): Call obj_print, with a calculated pretty argument instead of switching between obj_pprint and obj_print. * struct.c (struct_inst_print): Except when in backward compatibility mode, call the object's print method in both pretty and regular printing mode, passing the mode as a third argument. * tests/012/oop.tl (defstruct animal): Support third argument in print method. Make it optional because there are some explicit calls which don't pass the argument. * txr.1: Documentation updated for print method and the print function. Revised text for some of the related functions. Added compat notes.
* obj_print: use of volatile.Kaz Kylheku2016-10-201-3/+5
| | | | | | | | * lib.c (obj_print): The ret variable doesn't have to be volatile qualified, because it is never modified after setting an exception handler, and then accessed in the cleanup. On the other hand, the ctx variable is manipulated this way and must be volatile.
* Implement *print-circle* for sharing and cycles.Kaz Kylheku2016-10-201-5/+122
| | | | | | | | | | | | | | | | | | | | | | | * lib.c (obj_print_impl): On entry, ctx being non-null indicates that cycle and substructure detecting is enabled via *print-circle* for this print job. In this case, check whether this is the first request to print a multiply-referenced object, in which case we print the #<n>= label definition, or whether it is a second or additional reference, in which case we render the object as #<n>#. Special handling must also be introduced into the loop which prints list elements. At any point in a list, the rest of the list could be shared substructure or a cyclic link that must be rendered with the appropriate notation. (populate_obj_hash): New static function. Enters all objects in the substructure that are eligible for the circle notation into the hash that is stored in the print context. Any object that appears two or more times is associated with a t value. (obj_print, obj_pprint): Unless circle printing is already in effect, check *print-circle* and turn it on if necessary and prepare the context, associating it with the stream. Either way, if circle printing is enabled, call populate_obj_hash to walk the object and add its components to the hash.
* Add stream printing context.Kaz Kylheku2016-10-201-32/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is some infrastructure which will support *print-circle*. * lib.h (struct strm_ctx): Forward declared. (struct cobj_ops): Add context parameter to print function pointer. (cobj_print_op, obj_print_impl): Add context parameter to declarations. * hash.c (hash_print_op): Take context argument and pass it down in obj_print_impl calls. * lib.c (cobj_print_op, out_quasi_str): Likewise (obj_print_impl): Likewise, and also pass to COBJ print method. (obj_print, obj_pprint): Pass null pointer as context argument to obj_print_impl. * regex.c (regex_print): Take context parameter and ignore it. * socket.c (dgram_print): Likewise. * stream.h (struct strm_ctx): New struct type. (struct strm_base): New ctx member, pointer to struct strm_ctx. (stream_print_op): Add context parameter to declaration. (get_set_ctx, get_ctx): Declared. * stream.c (strm_base_init): Add null pointer to initializer. (strm_base_cleanup): Add assertion against context pointer being non-null: that indicates that some stream operation installed a context pointer and neglected to restore it to null before returning, which is bad because context will be stack allocated. (stream_print_op, stdio_stream_print, cat_stream_print): Take context parameter and ignore it. (get_set_ctx, get_ctx): New functions. * struct.c (struct_type_print): Take context parameter and ignore it. (struct_inst_print): Take context parameter and pass down to obj_print_impl.
* reduce-left bugfix: bad init val with key-func.Kaz Kylheku2016-10-181-1/+1
| | | | | * lib.c (reduce_left): init value pulled from list itself must be passed through the key function.
* Provide functions to alter range objects.Kaz Kylheku2016-10-171-0/+14
| | | | | | | | | | Ranges continue to be immutable; but a backdoor is needed for upcoming support for circular notation. * lib.c (set_from, set_to): New functions. * lib.h (set_from, set_to): Declared.
* Bugfix: sub and length on abstract sequences.Kaz Kylheku2016-10-131-1/+30
| | | | | | | | | | * lib.c (length_proper_list): New static function. (length): Use length_proper_list for objects. (sub): Call nullify on COBJ object before passing to sub_list. * tests/012/aseq.tl, tests/012/aseq.expected: New files.
* Overhaul where funtion.Kaz Kylheku2016-10-131-14/+43
| | | | | * lib.c (where): Implement faster ref-based access for vectors and strings. Support abstract sequence structs.
* Let some sequence functions work on structs.Kaz Kylheku2016-10-131-28/+32
| | | | | | * lib.c (in, sub, ref, search, rsearch, sel): These functions now accept struct objects that have the nullify, car and cdr methods.
* find-max and find-min support hashes.Kaz Kylheku2016-10-121-13/+55
| | | | | | | * lib.c (find_max): Restructured to implement separately for vectors and lists. Support hash tables. * txr.1: Document find-min and find-max for hashes.
* Support gmtoff and zone in time struct.Kaz Kylheku2016-10-121-2/+18
| | | | | | | | | | | | | | * lib.c (gmtoff_s, zone_s): New symbol variables. (tm_to_time_struct): Copy tm_gmtoff and tm_zone into Lisp struct from struct tm, if the platform has these. (time_fields_to_tm): Zero/null-out the tm_gmtoff and tm_zone fields of the target structure, if the platform has them. (time_init): Intern the gmtoff and zone symbols, initializing the gmtoff_s and zone_s variables. Add the gmtoff and zone slots to the time struct. * txr.1: Documented new slots.
* length and empty functions support ranges.Kaz Kylheku2016-10-041-0/+4
| | | | | | * lib.c (length, empty): Handle RNG in switch. * txr.1: Documented.