| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.c (match_fun): Report self as match-fun
in error message.
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Update registration of match-fun.
* match.c (match_fun): Do defaulting on third and fourth arg.
* txr.1: Documenation updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
| |
* match.c (open_data_source): If the data source isn't
a string or stream, then error out.
|
|
|
|
|
| |
* match.c (open_data_source): do the spec_bind in just one place.
Use first_spec consistently in the debuglf calls.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
* txr.1: Describe the filter-fun optional argument of
group-reduce.
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
* txr.1: Broken syntax markup.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Likewise.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
| |
* txr.1: Example given for how @(accept) interacts with
@(next) and with the function call mechanism.
|
|
|
|
|
| |
* txr.1: Add missing documentation of the existence of
horizontal @(trailer) syntax.
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
| |
* txr.1: Multiple places were referring to a section
called BLOCKS. It is called Blocks.
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
| |
* txr.1: Documenting all the special interactions with
accept that have been recently added: next directive,
functions, finally.
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
| |
* sysif.c (repress_privilege): Bail if temporarily dropping
user or group privilege (in setuid operation, of course)
doesn't work.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
| |
* match.c (fun_resolve_bindings): New static function.
(h_fun, v_fun): Replace common code with a call to
fun_resolve_binding.
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
| |
* lib.c (vec): New function.
* lib.h (vec): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
* match.c (dir_tables_init): Wire throw_s into horizontal
dispatch table via hv_trampoline.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Likewise.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
* eval.c (expand_with_free_refs): Properly handle
defaulting of the two optional arguments.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
| |
* 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.
|