summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* New: struct-from-plist and struct-from-args.Kaz Kylheku2017-03-123-0/+61
| | | | | | | | | * struct.c (struct_init): Register new functions. (struct_from_plist, struct_from_args): New functions. * struct.h (struct_from_plist, struct_from_args): Declared. * 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-123-6/+11
| | | | | | | | * 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-083-2/+28
| | | | | | | | | | | | | * 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.
* uref: the a.b.c syntax extended to .a.b.cKaz Kylheku2017-03-068-20/+224
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Now it is possible to use a leading dot on the referencing dot syntax. This is the is the "unbound reference dot". It expands to the uref macro, which denotes an unbound-reference: it produces a function which takes an object as the argument, and curries the reference implied by the remaining arguments. * eval.c (uref_s): New global symbol variable. (eval_init): Intern uref symbol and init uref_s. * eval.h (uref_s): Declared. * lib.c (simple_qref_args_p): A qref expression is now also not simple if it contains an embedded uref, meaning that it cannot be rendered into the dot notation without ambiguity. (obj_print_impl): Support printing (uref a b c) as .a.b.c. * lisplib.c (struct_set_entries): Add uref to the list of autoload triggers for struct.tl. * parser.l (DOTDOT): Consume any leading whitespace as part of recognizing the DOTDOT token. Otherwise the new rule for UREFDOT, which matches (mandatory) leading space will take precedence, causing " .." to be scanned wrong. (UREFDOT): Rule for new kind of dot token, which is preceded by mandatory whitespace, and isn't consing dot (which has mandatory trailing whitespace too, matched by an earlier rule). * parser.y (UREFDOT): New token type. (i_dot_expr, n_dot_expr): New grammar rules. (list): Handle a leading dot on the first element of a list as a special case. Things are done this way because trying to work a UREFDOT into the grammar otherwise causes intractable conflicts. (i_expr): The ^, ' and , punctuators are now followed by an i_dot_expr, so that the expression can be an unbound dot. (n_expr): Same change as in i_expr, but using n_dot_expr. Plus new UREFDOT n_expr production. * share/txr/stdlib/struct.tl (uref): New macro. * txr.1: Documented.
* doc: missing description of a group-reduce param.Kaz Kylheku2017-03-051-2/+16
| | | | | * txr.1: Describe the filter-fun optional argument of group-reduce.
* streamline default alg handling in group-reduce.Kaz Kylheku2017-03-051-2/+1
| | | | | | * hash.c (group_reduce): Don't pointlessly default filter_fun to identity_f, and then check for that value and not use it. Just skip the filtering code if the argument is missing.
* 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.
* Harmonize code with previous commit.Kaz Kylheku2017-03-041-2/+3
| | | | | | | * parser.y (expand_repeat_rep_args): Use a sym local variable to avoid evaluating first(arg) twice, like the previous commit does in another case of this function.
* bugfix: :vars in output repeat not registered.Kaz Kylheku2017-03-041-3/+7
| | | | | | | | | | | | | | | | Test case: @(output) @ (repeat :vars (x (y 42)) @ (list x y) @ (end) @(end) x and y are spuriously reported as unbound variables in the (list x y) form. * parser.y (expand_repeat_rep_args): Do the missing calls to match_reg_var when processing :vars list.
* doc: formatting under umeth.Kaz Kylheku2017-03-041-1/+1
| | | | * txr.1: Broken syntax markup.
* Version 170.txr-170Kaz Kylheku2017-02-286-394/+421
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* doc: give some examples of accept interaction.Kaz Kylheku2017-02-271-0/+101
| | | | | * txr.1: Example given for how @(accept) interacts with @(next) and with the function call mechanism.
* doc: horizontal trailer.Kaz Kylheku2017-02-261-0/+26
| | | | | * txr.1: Add missing documentation of the existence of horizontal @(trailer) syntax.
* doc: block syntax horizontal and vertical.Kaz Kylheku2017-02-261-0/+26
| | | | | | * txr.1: Document that block syntax can be horizontal or vertical, and likewise that the accept and fail directives can be in horizontal or vertical context.
* doc: don't refer to BLOCKS section.Kaz Kylheku2017-02-261-6/+6
| | | | | * txr.1: Multiple places were referring to a section called BLOCKS. It is called Blocks.
* doc: print methods print, not pretty-print.Kaz Kylheku2017-02-261-1/+1
| | | | | | * txr.1: Fix misleading text which says that print methods are called to pretty-print objects. They are called for all printing: regular or pretty.
* New floor-rem, ceil-rem and round-rem.Kaz Kylheku2017-02-264-18/+59
| | | | | | | | | | | | * arith.c (trunc_rem): Move function to below round function. Make second argument optional, defaulting to one. (floor_rem, ceil_rem, round_rem): New functions. * eval.c (eval_init): Registration of trunc-rem altered for optional argument. New registrations for floor-rem, ceil-rem, round=rem. * txr.1: Documented for new functions folded with trunc-rem.
* Second argument optional in trunc.Kaz Kylheku2017-02-253-75/+106
| | | | | | | | | | | | | | * arith.c (trunc1): New static function. (trunc): Detect a missing second argument and call func1. * eval.c (eval_init): Update registration of trunc intrinsic to make second arg optional. * txr.1: Describe optional argument of trunc. Trunc documentation is merged with the floor, ceil and round section. The mod and trunc-rem functions are split off into their own sections, leaving the / function described by itself. The documentation of / is substantially revised.
* doc: horizontal-vertical issues in block and accept.Kaz Kylheku2017-02-251-0/+44
| | | | | | | * txr.1: Document what happens when a vertical block catches a horizontal accept, a horizontal block catches a vertical accept, or a horizontal block catches a horizontal accept from a different line.
* doc: special interactions with accept.Kaz Kylheku2017-02-251-17/+123
| | | | | | * txr.1: Documenting all the special interactions with accept that have been recently added: next directive, functions, finally.
* Adding round function.Kaz Kylheku2017-02-255-4/+106
| | | | | | | | | | | * arith.c (round1): New static function. (roundiv): New function. * configure: New test for C99 round function. * eval.c (eval_init): Register round intrinsic. * txr.1: Documented.
* floor and ceil do division, with optional second arg.Kaz Kylheku2017-02-244-20/+228
| | | | | | | | | | | | | | | Also, with one argument, these functions handle ranges. * arith.c (floordiv, ceildiv): New functions. (floorf, ceili): Handle ranges. * eval.c (eval_init): Register floor and ceil to new functions. * lib.h (floordiv, ceildiv): Declared. * txr.1: Documentation updated.
* 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.
* Check result of seteuid and setegid.Kaz Kylheku2017-02-221-6/+10
| | | | | | * sysif.c (repress_privilege): Bail if temporarily dropping user or group privilege (in setuid operation, of course) doesn't work.
* remq/remove-if family: bugfixes in error message.Kaz Kylheku2017-02-221-9/+9
| | | | | | | | | | | | * lib.c (rem_impl): Take a name argument, so as to report correct function name. Also, serious fix here: we passed the address of the in function to the error message format job, rather than seq_in. (remove_if): Report as remove-if rather than remq in the error message. Also, same bug as in remq_impl: in used in place of seq_in. (remq, remql, remqual, keepq, keepql, keepqual): Pass function name as string into remq_impl.
* 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.
* Fix lack of robustness in struct module.Kaz Kylheku2017-02-201-6/+6
| | | | | | | | | | | | The symbolp test is too weak before calling lookup_slot, because nil satisfies it, but lookup_slot dereferences the symbol pointer to access its slot cache. One of many test cases: parsing #S(time nil nil) segfaults. * struct.c (slot, maybe_slot, slotset, uslot_fun, umethod_fun, umethod_args_fun): Check that sym isn't nil before looking it up as a slot.
* 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.
* New internal function: vec.Kaz Kylheku2017-02-152-0/+23
| | | | | | * lib.c (vec): New function. * lib.h (vec): Declared.
* Support horizontal @(block), phase 1.Kaz Kylheku2017-02-152-0/+50
| | | | | | | | | | | | 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-132-0/+15
| | | | | | | * match.c (dir_tables_init): Wire throw_s into horizontal dispatch table via hv_trampoline. * txr.1: Documented.
* Version 169.txr-169Kaz Kylheku2017-02-116-264/+288
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* Add rassoc and rassql functions.Kaz Kylheku2017-02-114-3/+82
| | | | | | | | | | | * eval.c (eval_init): Register rassoc and rassql intrinsics. * lib.c (rassoc, rassql): New functions. * lib.h (rassoc, rassql): Declared. * txr.1: Documented rassoc and rassql, with small fixes to assql and assoc.
* consistency: treat members of struct env in order.Kaz Kylheku2017-02-101-2/+2
| | | | | | | * eval.c (make_env, copy_env): Assign to vbindings, then to fbindings. The members are in that order and elsewhere, wherever we treat both bindings, we treat the variables first.
* Use non-hacky representation for deferrable warnings.Kaz Kylheku2017-02-107-46/+69
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Deferrable warnings now get their own subtype, defr-warning. The tag is a regular argument: no funny dotted argument list. * eval.c (eval_defr_warn): Throw new style deferrable warning. (me_op, no_warn_expand): Catch defr-warning rather than warning. Use uw_muffle_warning to suppress it. (gather_free_refs): Parse new representation of deferrable warning. (expand_with_free_refs): Catch defr-warning rather than warning. * lib.c (defr_warning_s): New symbol variable defined. (obj_init): Initialize defr_warning_s. * lib.h (defr_warning_s): Declared. * share/txr/stdlib/error.tl (compile-defr-warning): Throw new-style deferrable warning. * unwind.c (uw_muffle_deferrable_warning): Function removed. (uw_throw): Bugfix: handle warnings by checking by subtype rather than exactly for the warning type. Distinguish deferrable warnings by subtype rather than argument list shape. (uw_defer_warning): Take the new style args and reconstruct the (msg . tag) representation for a deferred warning, so the other functions don't have to change. (uw_late_init): Register defr-warning as exception subtype of warning. * unwind.h (uw_muffle_deferrable_warning): Decl removed. * txr.1: Adjusted all documentation touching on the subject of the representation of deferrable warnings.
* Properly default arguments in expand_with_free_refs.Kaz Kylheku2017-02-101-1/+3
| | | | | * eval.c (expand_with_free_refs): Properly handle defaulting of the two optional arguments.
* Better way for releasing deferred warnings.Kaz Kylheku2017-02-106-10/+46
| | | | | | | | | | | | | | | | | | | | We should be re-throwing deferred warnings as ordinary warnings, not dumping them to a stream. * eval.c (eval_exception): Use uw_release_deferred_warnings instead of uw_dupm_deferred_warnings. (load): Likewise. * parser.c (read_eval_ret_last): Likewise. * txr.c (txr_main): Likewise. * unwind.c (uw_release_deferred_warnings): New function. * unwind.h (uw_release_deferred_warnings): Declared. * txr.1: Documented release-deferred-warnings and updated documentation for dump-deferred-warnings.
* awk macro: warn about invalid function use in rng.Kaz Kylheku2017-02-101-11/+26
| | | | | | | | | | | | | Improving the new feature to handle functions also, and improve the diagnostic by reporting the specific to or from subform of which contains the reference. * share/txr/stdlib/awk.tl (sys:awk-code-move-check): Take a an argument indicating the kinds of bindings being checked, symbols or functions, and an extra form argument. (sys:awk-mac-let): Pass new arguments to sys:awk-code-move-check and also call it two more times to report on functions also.
* awk macro: warn about invalid var use in rng forms.Kaz Kylheku2017-02-091-30/+50
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The awk macro abruptly relocates rng forms out of their apparent scope. Therefore, code like this is wrong: (awk ((let ((x t)) (rng t x)) (action))) The rng form is transformed and relocated to a scope in which the let is not visible. This is a problem worth warning about. In the above case, there will also be a warning about the variable x being unbound, which might alerts the programmer to the problem. However, in cases where there is yet another binding of x introduced via :let or outside of awk, that warning wll not occur: the code motion will silently cause x to refer to the wrong x: (awk (:let (x nil)) ((let ((x t)) (rng 1 x)) ;; refers to the (x nil) binding!!! (action))) (let ((x nil)) (awk ((let ((x t)) (rng 1 x)) ;; refers to the (x 4) binding!!! (action)))) Now there is a warning for this situation. * share/txr/stdlib/awk.tl (sys:awk-compile-time): New slot, outer-env. (sys:awk-expander): Takes an env parameter, which is stored into the new slot of the awk-compile-time structure. (sys:awk-code-move-check): New function. (sys:awk-mac-let): Use sys:expand-with-free-refs to expand the rng forms, capturing the extra information which enables the implementation of the warning. The rng variants are refactored to pass the original form to the sys:rng expander. This allows the diagnostic to display the original rng form. (awk): Parameter e renamed to outer-env, and passed to sys:awk-expander.
* Extend functionality of sys:expand-with-free-refs.Kaz Kylheku2017-02-091-5/+71
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This function's return list now has two additional elements. The first two elements give, respectively, the free variables and functions which occur in the form: variables and functions which have no lexical binding. As before, these lists omit the variables which do have bindings in the specified environment that is passed as an argument. The two new elements give, respectively, all variable and function references emanating out of the form, regardless of whether they have bindings in the form's surrounding lexical environment or whether they are free. The function also takes a new argument: an additional environment beyond which the erasure of bindings doesn't take place. * eval.c (squash_menv_deleting_range): New static function. (gather_free_refs): Do not intercept non-deferrable warnings. (gather_free_refs_nw): New static function. (expand_with_free_refs): Expand the form twice, the second time with a collapsed environment which has been stripped of all macros and of all var shadowing entries in a specified range, using the squash_menv_deleting_range function. The second pass yields the extra variables and functions. Also take a second env argument for this purpose. (eval_init): Register sys:expand-with-free-refs as a three argument function with one optional argument.
* sys:op: don't warn about @var targets.Kaz Kylheku2017-02-091-5/+11
| | | | | | | | * eval.c (do_expand): The previous commit exposes this false warning. Basically, the (sys:var <sym>) place expander generates a (sys:setq (sys:var <sym>) <val>) form. That is valid, and the expander shoud not warn that sys:var form is an unbound variable.