| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
| |
* txr.1: New section comparing TXR Lisp exceptions
with CL conditions, with a contrasting example.
|
|
|
|
|
|
|
|
| |
* eval.c (me_iflet_whenlet): Allow the last binding
to be (init-form) instead of (sym init-form), for
situations in which sym is never used.
* txr.1: Documented.
|
|
|
|
|
|
|
| |
* Makefile (clean): Remove txr-win an txr-win-dbg
executables if they exist. Because of this issue,
stale txr-win executables got packaged in some
Windows installer releases.
|
|
|
|
|
|
| |
* txr.1: The List Sorting section looks as if it describes all
the support there is for sorting. Add references pointing to
sort under Sequence Manipulation.
|
|
|
|
|
| |
* txr.1: Address \*(TL not followed by whitespace in
HTML version.
|
|
|
|
|
| |
* txr.1: The "Rule 7" example is actually triggering Rule 6.
Fix comment and add a Rule 7 example.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Likewise.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
| |
* eval.c (do_expand): Fix outdated comment about what
forms are expanded like function calls.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This addresses a problem with the new scheme for handling
specials. If we let specials be bound in the lexical
environment and then do the swizzle into the dynamic
environment using sys:with-dyn-rebinds, that only works
correctly for parallel bindings (and thus also for lambda and
macro parameters). For sequential bindings, it exposes the
possibility that a closure is created during the sequential
binding which captures a would-be special variable while it is
still in the lexical stage. That closure can be thrown out of
there, so the sys:with-dyn-rebinds is never reached which
swizzles the variable.
The new scheme is very simple. When expanding a let, we
tranform (s init) to (s (sys:dvbind s init)) if s is a special
variable. This new sys:dvbind operator binds s to the value of
the init expression in a newly created dynamic environment,
and returns the #:unbound symbol, which is received by the
lexical s. Problem solved. The only thing remains is that the
let special operator must save and restore the dynamic
environment.
There is no need for sys:with-dyn-rebinds around the body
of a let, but we keep that mechanism and approach for handling
specials in argument lists.
* eval.c (dvbind_s): New symbol variale.
(bindings_helper): Lose the env_out argument; return the new
environment. No caller uses the returned bindings any more.
(op_let): Call bindings_helper in initializing expression of
new_env. Save the dyn_env, and restore it after evaluating
the body.
(op_dvbind): New static function.
(expand_vars): Lose the pspecials argument. Perform
the insertion of sys:dvbind.
(do_expand): Simplify the let expander: expand_vars no longer
outputs a list of specials and there is no need to insert
with_dyn_rebinds_s. Add a case for sys:dvbind: assume it
requires no expansion.
(eval_init): Intern sys:dvbind, and bind it as an operator
to the new op_dvbind function.
|
|
|
|
|
|
| |
* share/txr/stdlib/tagbody.tl (tagbody): When calling
sys:expand, env was left out due to wrong parenthesis
placement.
|
|
|
|
|
|
|
|
|
|
|
| |
The genvim.txr program iterates over package symbols
and encounters sys:unbound. It binds that to a local
variable, creating a problem due to the special hack.
Let's turn sys:unbound into a gensym.
* eval.c (eval_init): Protect unbound_s from gc.
Initialize unbound_s with an uninterned symbol
created by make_sym.
|
|
|
|
|
|
|
|
| |
* eval.c (struct bindings_helper_vars): Remove de member.
(copy_bh_env_handler): Remove copying of dynamic environment.
(bindings_helper): Remove all code dealing with de.
The sequential binding will no longer introduce a dynamic
environment.
|
|
|
|
| |
* txr.1: Describe *place-expander* variable.
|
|
|
|
|
| |
* txr.1: Document *place-update-expander*,
*place-clobber-expander* and *place-delete-expander*.
|
|
|
|
|
| |
* txr.1: with-gensyms moves from User-Defined Places
to macros.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* unwind.c (uw_find_frames_impl): New static function, made
from uw_find_frame.
(uw_find_frame): Reduced to wrapper around
uw_find_frames_impl.
(uw_find_frames): New function.
(uw_late_init): Register find-frames intrinsic.
* unwind.h (uw_find_frames): Declared.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/awk.tl (sys:awk-mac-let): Local macro
sys:rng generalized to support code generation for ranges that
exclude either endpoint. Local rng macro adjusted to target
this new form. Local macros rng-, -rng, and -rng- added.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Removing code which handles the special function
argument (sys:special ...) which can occur ahead
of the other arguments, indicating the names of
arguments which require special binding.
Removing code which handles (sys:special init-form var)
bindings in let/let*.
* eval.c (env_vbind_special): Function removed.
(bind_args): Do not look for special list; no such
thing occurs. Use env_vbind directly rather than
env_vbind special.
(bind_macro_params): Likewise.
(funcall_interp): Streamlined by not having to
check for presence of specials list and setting up
the dynamic environment frame for it.
(bindings_helper): Don't look for the (sys:special
initform sym) syntax among the bindings.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The old way: process, at expansion time, bindings in lambda
lists and all binding constructs to find special variables
(symbols marked special). Replace these bindings with
an annotation. Then when the interpreter performs binding,
the binding helper functions process these annotations.
Also, if specials occur, wrap the construct in
sys:with-save-specials to set up the necessary dynamic
environment frame.
The new way: process, at expansion time, bindings in
lambda lists and binding constructs (which have been reduced
to just let and let*). If special variables occur, then
wrap the body in in sys:with-dyn-rebinds which re-binds
specific symbols in the dynamic namespace, copying their
value from their lexical binding. The lexical bindings are
then replaced with the value sys:unbound, which indicates that
the value should be resolved in the dynamic environment.
* eval.c (with_saved_vars_s): Symbol variable removed.
(with_dyn_rebinds_s): New symbol variable.
(lookup_var, lookup_sym_lisp1): If a lexical binding contains
the value sys:unbound, then continue the search through the
dynamic environment; ignore the remaining lexical
environments.
(expand_params_rec): Bugfix: neglected collect of
special variable in fallback case.
(expand_params): Takes body environment, and returns two
values as a cons cell. The additional return value is a body
that is either the original body, or else is wrapped with
sys:with-dyn-rebinds. Removed is the special variable
hack inserted into the syntax.
(expand_macrolet, expand_tree_cases): Adjust to new
expand_params interface.
(op_with_saved_vars): Static function removed.
(op_with_dyn_rebinds): New static function.
(expand_vars): Return list of special variables via pointer
argument, rather than just a Boolean which indicates that
specials are present. Transformation to special representation
is removed.
(expand_catch_clause): Adjust to new expand_params interface.
(expand_save_specials): Static function removed.
(do_expand): Adjust let/let* expansion to new expand_vars
interface. Generate the sys:with-dyn-rebinds wrapping around
the body. Adjust the defun, lambda and mac-param-bind
expanders to the new expand_params interface.
Recognize sys:with-dyn-rebinds and don't expand it;
all places which generate this form have to expand the
internals themselves.
(eval_init): Remove initialization of with_saved_var_s,
and its registration as an operator.
Initialize with_dyn_rebinds_s with interned symbol,
and register as operator.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
NOTE: The socket test cases do not pass under this commit:
this is expected.
The for and each family of operators will now be macros which
expand to let/let* binding construct wrapping a lower level
special operator.
This is in preparation for a change to how special variable
binding is implemented.
This change reduces the number of special forms which bind
variables.
There is a single low-level operator for for loops called
sys:for-op. Its syntax is a lot like the C89 for loop:
(sys:for-op init-forms test step-forms body). The init-forms
do not bind anything; it is just forms.
There is a sys:each operator for implementing each,
each*, append-each and all those operators. Its syntax is
(sys:each-op type-sym optional-vars . body).
The type-sym is one of each, append-each or collect-each.
If optional-vars is nil, then the operator looks at the
immediate lexical environment, and assumes all the bindings
there are the each iteration variables and it works with
those bindings, like its predecessor did. Otherwise
optional-vars is a list of symbols: the operator walks the
list and resolves each element to a binding. This is
used in two situations: when some of the variables are
special (dynamically scoped) or when the variables are
bound sequentially with let* and are thus scattered in
multiple levels of environment.
* eval.c (for_op_s, each_op_s): New symbol variables.
(get_bindings): New static function.
(op_each): Now implements sys:each-op.
(op_for): Now implements sys:for-op.
(get_var_syms): New static function.
(me_each, me_for): New static functions.
(do_expand): Do not expand the each operator family under the
same rule. New case handling sys:each-op is introduced
due to the different syntax.
The for case restructured to handle for_op_s.
(eval_init): Intern sys:each-op and sys:for-op symbols.
Register the corresponding operators. Move registrations of
the public symbols each, each*, for, for* and all the other
each variants to be macros.
* tests/011/macros-2.expected: Updated with different
macro expansion which is now produced for a while
loop.
|
|
|
|
|
|
|
|
|
| |
* lisplib.c (tagbody_set_entries): Add prog and prog* to
autoload list.
* share/txr/stdlib/tagbody.tl (prog, prog*): New macros.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
If a signal goes off in the middle of gc that is
routed to an async lambda handler, we should cancel
gc, so the handler finds the heap in a good state.
Of course, the handler must not return in this
case, or else the interrupted gc will try to resume.
* gc.c (inprogress): New static flag.
(gc): Increment and decrement inprogress variable.
Abort if re-entered.
(gc_inprogress): New function.
(unmark): Do not clear FREE flags, only REACHABLE.
(gc_cancel): New function.
* gc.h (gc_inprogress, gc_cancel): Declared.
* signal.c (sig_handler): In the async lambda
case, check for an in-progress gc and cancel it.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register mismatch intrinsic.
* lib.c (mismatch): New function.
* lib.c (mismatch): Declared.
* txr.1: Documented mismatch.
|
|
|
|
|
| |
* lib.c (find_max): Handle LIT case in switch.
Also, fix nonsensical, typo-ridden error message.
|
|
|
|
|
|
| |
* eval.c (do_expand): Do not use the "unbound function"
warning if the operator position isn't a symbol which
can have a function binding.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (lookup_fun): When looking up (meth ...) syntax,
avoid calling static_slot with a slot argument which isn't
a static slot of the given type, otherwise an exception
is thrown. The situation is turned instead into a nil
return which just indicates "no binding". This allows,
for instance, (fboundp '(meth foo bar)) to be safe.
It makes no sense for that to return nil if foo
doesn't name a struct type, but to throw an error if
bar isn't a static slot in foo.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
* txr.1: adding a few pointless weasel words.
|
|
|
|
|
|
|
| |
* eval.c (me_equot): New static function.
(eval_init): Register equot intrinsic macro.
* txr.1: Documented equot.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Likewise.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is uncovered by compiling with g++ using
-Wold-style-cast.
* mpi/mpi.c (mp_get_intptr): Use convert macro.
Also in one of the rules producing REGCHAR.
* parser.l (num_esc): Likewise.
* struct.c (static_slot_set, static_slot_ens_rec,
get_equal_method): Use coerce macro for int to pointer
conversion.
* sysif.c (setgroups_wrap): Use convert macro.
* termios.c (termios_unpack, termios_pack): Likewise.
* txr.c (sysroot_init): Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch addresses a problem whereby if a TXR Lisp file ends
with an erased object notation such as #;(a b c), there is a
syntax error.
The strategy is to simplify the grammar so that a single
yyparse primed with SECRET_ESCAPE_E or SECRET_ESCAPE_I will
read either an object, or just one instance of the #;
notation. If #;OBJ is read, then the parse tree is returned as
the nao value. The caller knows that #;OBJ must have occurred
because there are no errors and the parser isn't at EOF, yet
there is no parse tree. Then in lisp_parse we can loop on this
situation, and make adjustments elsewhere also.
So that iread continues to work, we must separate the
parser_eof condition from the lookahead token. Under iread,
we were clearing the token in prime_parser_post, but that
was having the side effect of making the parser look like
it is in EOF. We now preserve the EOF indication in a flag,
so we can manipulate the token.
* parser.h (struct parser): new member, eof.
* parser.c (parser_common_init): Initialize new eof flag
in parser structure to zero.
(prime_parser_post): Set the eof flag if the parser's most
recent token is zero.
(lisp_parse_impl): Call the parser repeatedly while there
are no errors, and no EOF, yet no object has been produced.
This indicates that a #; erasure has been processed.
(read_eval_stream): Restructure the logic here for
clarity. Do not break the loop if error_val was returned
from the parser, but there are no errors, and the parser isn't
at EOF. This is behavior is probably redundant with respect
to the loop in lisp_parse_impl.
(read_eval_ret_last): Bugfixes here. Pass an error indicating
value down to lisp_parse, like in read_eval_stream and
make the logic similar.
(parser_eof): Just return an indication based no the
eof flag.
* parser.y (hash_semis_n_expr, hash_semis_i_expr,
ignored_i_exprs, ignored_n_exprs): Grammar rules removed.
(hash_semi_or_n_expr, hash_semi_or_i_expr): New grammar
rules.
(spec): Retarget SECRET_ESCAPE_E and SECRET_ESCAPE_I
cases to new rules.
(parse): Clear eof flag to zero.
|
|
|
|
|
| |
* txr.1: Document that unquoting and splicing forms
may appear outside of unquote syntax.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
| |
* lib.c (obj_print_impl): Properly print objects
like ^(... . ,expr) and (... . ,*expr) rather
than ^(... sys:unquote expr) or ^(... sys:splice expr).
|
|
|
|
|
|
| |
* parser.l: A stray printf was committed in November 2015.
The spurious output only occurs when certain invalid
floating-point syntax is encountered.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Weakness uncovered by fuzzing with AFL (fast) 2.30b.
The failing test case is regex syntax like
[\1111111...111abc], where the bad character escape
allows an invalid, negatively valued character object to
escape out of the parser into the system leading to an an
out-of-bounds array access in the char set code in the regex
compiler.
* parser.l (num_esc): Make sure that an out-of-range
character is mapped to zero. Set up a default value of
zero for the return variable. If the character token has
too many digits, don't pass them through strtol at all,
which will produce a garbage value. Then in the final
range check, actually replace the value with zero if it
is out of range: issuing a diagnostic is not enough.
|
|
|
|
|
|
|
|
| |
* regex.c (regex_range_full_fun, regex_range_left_fun,
regex_range_right_fun, regex_range_search_fun): New functions.
(regex_init): Register fr^$, fr^, fr$ and frr intrinsics.
* txr.1: Documented.
|
|
|
|
|
|
|
| |
* lib.c (do_curry_1234_1): New static function.
(curry_1234_1): New function
* lib.h: (curry_1234_1): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/awk.tl (sys:awk-let): Renamed to
sys:awk-mac-let. Macrolet prn removed from here.
(sys:awk-fun-let): New macro, provides awk functions.
The prn function removed from sys:awk-mac-let is generated
here.
(sys:awk-fun-shadowing-env): New function.
(awk): Follow rename of sys:awk-let. When expanding p-action
forms, use only sys:awk-mac-let; do not include the awk
functions, which do not "vaporize" unlike local macros. To
compensate for not including the functions, extend the macro
environment with one that shadows the functions, so that
during this expansion, any global macros of the same name as
awk local functions are properlly hidden. In the final
expansion, include the awk functions.
* txr.1: Updated documentation to consistently call
prn an awk function everywhere.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/awk.tl (awk): We must generate the
code to bind the awk-fun under the same conditions that
control whether the loop call is generated to which it
is an argument. Otherwise we end up with an unbound var
reference: the loop isn't elided because begin/end
actions are present, but the call refers to a nonexistent
variable.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This problem happens when awk is issued from the command line
followed by one or more arguments as exemplified by the usage
txr -e '(awk ...) arg ... . In this case, after awk processes
the args as input sources and completes, TXR resumes
processing the command line arguments and wants to open arg
as a script file! To address this problem, when awk defaults
on using *args* as input sources, it consumes *args* by
clearing the variable to nil. TXR's command line processing
already reacts to changes in *args* by evaluated forms.
Code that wants *args* to be left alone by awk can explicitly
pass them in using (awk (:inputs *args*) ...).
* share/txr/stdlib/awk.tl (sys:awk-state): Move
default initialization of inputs into :postinit.
If there are no inputs by :postinit time, then
take *args* or *stdin*. If *args* is used in this
default manner, then consume *args*.
* txr.1: Documented.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/awk.tl (awk): The macro must not
elide the processing loop if there are :begin-file,
:end-file or :end actions. All these actions must
be missing, not only the, cond-actions for that elision
to be valid.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Contrary to the documentation, handle doesn't in fact have the
same syntax as catch. It passes the exception symbol to
clauses as the leftmost argument, followed by the exception
arguments, whereas catch passes only the exception arguments.
* share/txr/stdlib/except.tl (handle): Do not pass the
exception sybmol as the leftmost argument, unless operating
in TXR 161 or earlier compatibility.
* tests/012/except.tl: drop exception symbol argument from
handle clause.
* txr.1: Compatibility note added.
|
|
|
|
|
|
|
| |
* txr.c (compat): Update sys:compat variable with
actual value.
(txr_main): Register sys:compat variable with
default zero value.
|
|
|
|
|
|
| |
* share/txr/stdlib/struct.tl (sys:rslotset): Return the new
value that comes out of slotset, rather than the value of the
method call. Also, we don't need macro-time wrapping.
|
|
|
|
| |
* txr.1: slotset returns the stored value.
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (warning_continue): Static function removed.
(no_warn_expand): Use uw_muffle_warning instead of
removed function.
* parser.y (warning_continue): Static function removed.
(parse_once): Use uw_muffle_warning instead of
removed function.
* unwind.c (uw_muffle_warning): New function.
* unwind.h (uw_muffle_warning): Declared.
|