| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (prof_call): New function, contents based on op_prof.
(struct prof_ctx): New struct type.
(op_prof_callback): New static function.
(op_prof): Reduced to call to prof_call, passing context
through to callback which performs the evaluation that is
timed.
* eval.h (prof_call): Declared.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
defsymacro via expand-defsymacro expander.
(expand-defsymacro): New function.
* eval.c (rt_defsymacro): New static function.
(eval_init): register sys:rt-defsymacro intrinsic.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (do_expand): When a defmacro or defsymacro form is
traversed, do not evaluate it, except in backward
compatibility mode. Unfortunately, this breaks some code.
* tests/011/macros-1.txr: A defmacro form has to be wrapped in
macro-time.
* tests/011/macros-2.txr: Likewise.
* tests/011/mandel.txr: Likewise.
* tests/012/man-or-boy.tl (defun-cbn): This macro generates a
progn which which expects that a defmacro form will come into
effect for the subsequent lambda in the same form. We must
wrap it in macro-time to make this happen now.
|
|
|
|
|
|
|
| |
* eval.c (rt_defun, rt_defmacro): New static functions.
(op_defun): Use static functions.
(eval_init): Register sys:rt-defun and sys:rt-defmacro
intrinsics.
|
|
|
|
|
|
| |
* eval.c (rt_defvarl): New static function.
(op_defvarl): Simplified using rt_defvarl.
(eval_init): Register sys:rt-defvarl.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is something that will be useful in compiling some forms.
At first I added it to the compiler only, but it seems wise to
have it in the interpreter also. (sys:upenv form) causes
form to be treated as if it were not in the immediately
surrounding lexical environment but its parent.
Thus (let ((a 1)) (let ((a 2)) (list a (sys:upenv a))))
yields (2 1). This operator needs no special treatment in the
expander; it is expanded as a function call. This is not 100%
correct in the face of all conceivable use. For instance
given (symacrolet ((a 1)) (let ((a 2)) (sys:upenv a))),
we probably want sys:upenv to skip the inner environment at
expansion time too so that a is replaced by 1. However, it
is not documented for application use, and will never be used
in such a situation in the compiler.
* eval.c (op_upenv): New static function.
(eval_init): Register sys:upenv special operator.
* compiler.tl (compiler compile): Implement compiled version
of sys:upenv.
|
|
|
|
|
|
|
| |
* eval.c (do_expand): The first argument of the sys:for-op
special operator isn't "vars" but a sequence of initialization
forms. Name the variable appropriately. The neglected
expansion of these forms is now performed.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Use the old ldiff function under
compatibility with 190 or lower.
* lib.c (ldiff): Rewritten.
(ldiff_old): New function, copy of previous version of ldiff.
* lib.h (ldiff_old): Declared.
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Expose raw expand function as
sys:expand*, since sys:expand squelches warnings.
* share/txr/stdlib/compiler.tl (usr:compile-toplevel): Use
expand* instead of expand.
|
|
|
|
|
|
|
|
| |
* eval.c (fmt_tostring, fmt_cat): New static functions.
(do_format_field): Replace code block with call to fmt_cat.
(fmt_simple, fmt_flex): Insert needed call to fmt_tostring.
(subst_vars): Replace blocks of code with calls to
fmt_tostring and fmt_cat.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is the second round of changes in perparation for
compiling the string quasiliterals special form.
Having split format_fields into a lower level do_format_field
and format_field, we now provide two functions which allow
Lisp code to call do_format_field.
The sys:fmt-simple function has fixed arguments for
the field width/alignment, indexing/slicing, separator
and plist. Any of them can be defaulted with nil. This
function will be useful when the quasiliteral specifies
modifiers that are simple literals or constant expressions.
The sys:fmt-flex function takes a variable number of
arguments, after the object and the plist. This function
has to scan through the arguments and classify them
by type: a string is a separator, an integer is a width
and left/right alignment and so on. The compiler will use
sys:flex when format field modifiers are present whose
arguments contain expressions that get evaluated.
* eval.c (fmt_simple, fmt_flex): New static functions.
(eval_init): sys:fmt-simple and sys:fmt-flex registered.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The objective of this work is to isolate the field-formatting
logic so we can target it in the compiler.
Currently, the sys:quasi special operator relies on calling
subst_vars, which calls format_field. Both subst_vars
and format_field perform dynamic evaluation, requiring
an environment. In the compiler, this will be replaced by
macro-generated logic; but we would like to obtain the use of
the lower-level field formatting as a pure function.
* eval.c (do_format_field): New static function. Does the
field formatting previously done in format_field. Also
performs the indexing on the object implied by the numeric
or range modifier; but the range or index is already
computed and comes in as a parameter.
(format_field): Perform the modifier parsing only, requiring
the dynamic evaluations via eval_fun, and then call
do_format_field on the extracted data. The range indexing
on the input sequence is no longer done during the parsing of
the modifiers. That unfortunately changes some behaviors that
are possible but are fortunately obscure and undocumented.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (op_defun): There is a hidden reference to the
sys:defmeth function here, which should have been
updated in commit 0ae617f463290ff4463db2e479604808f940cc76
that renamed the function to define-method!
Caught this by incidental code inspection, browsing
through special forms in the context of working on the
compiler.
|
|
|
|
|
|
|
|
|
|
|
| |
None of the statements which are conditional on eval_initing
are ever executed, because no code is interpreted during eval
init time; all intrisinc functions are C functions defined
using reg_fun.
* eval.c (eval_initing): Global variable removed.
(op_defun, op_defmacro, eval_init): References to eval_initing
and code conditional on it are removed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The test case for this is (let* (a (b a))) which raises
suspicion by diagnosing an "unbound variable a" error against
the (b a) var-init pair. The error goes away if we make it
(let* ((a nil) (b a))), a perfectly equivalent form. The
diagnostic is just a symptom; the problem is that in the case
when a doesn't have an initform, the (b a) var-init pair is
being incorrectly expanded in an environment that hasn't been
extended with the a variable.
* eval.c (expand_vars): In the sequential binding situation
(let*), we must extend the environment for each variable in
the no-init-form case exactly as we do in the with-init-form
case.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit is the start of compiler work to make TXR Lisp
execute faster. In six days of part time work, we now have a
register-style virtual machine with 32 instructions, handling
exceptions, unwind-protect, lexical closures, and global
environment access/mutation. We have a complete assembler and
disassembler for this machine. The assembler supports labels
with forward referencing with backpatching, and features
pseudo-ops: for instance the (mov ...) pseudo-instruction
chooses one of three kinds of specific move instruction based
on the operands.
* Makelfile (OBJS): Add vm.o.
* eval.c (lookup_sym_lisp1): Static function becomes external;
the virtual machine needs to use this to support that style
of lookup.
* genvmop.txr: New file. This is the generator for the
"vmop.h" header.
* lib.c (func_vm): New function.
(generic_funcall): Handle the FVM function type via new
vm_execute_closure function. In the variadic case, we want
to avoid the argument copying which we do for the sake of C
functions that get their fixed arguments directly, and then
just the trailing arguments. Thus the code is restructured a
bit in order to switch twice on the function type.
(init): Call vm_init.
* lib.h (functype_t): New enum member FVM.
(struct func): New member in the .f union: vm_desc.
(func_vm): Declared.
* lisplib.c (set_dlt_entries_impl): New static function,
formed from set_dlt_entries.
(set_dlt_entries): Reduced to wrapper for
set_dlt_entries_impl, passing in the user package.
(set_dlt_entries_sys): New static function: like
set_dlt_entries but targetting the sys package.
(asm_instantiate, asm_set_entries): New static functions.
(lisplib_init): Auto-load the sys:assembler class.
* share/txr/stdlib/asm.tl: New file.
* vm.c, vm.h, vmop.h: New files.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* args.c (args_normalize): Renamed to args_normalize_exact,
because this tries to split the arguments between an exact
array fill quantity and trailing list. Not all places using
this function actually need an exact fill, which causes
unnecessary consing when args->fill is reduced in order to
move items to args->list.
(args_normalize_least): New function. Variant of
args_normalize that can be used by functions which only
require a minimum fill.
(args_normalize_fill): Use args_normalize_least rather than
args_normalize_exact. This reduces consing in generic_funcall,
in handling variadic calls where arrayed arguments have been
supplied for trailing parameters.
* args.h (args_normalize): Renamed to args_normalize_exact.
(args_normalize_least): Declared.
(args_get_list, args_get_rest): Use args_normalize_exact.
(args_clear): Inline function removed. Was used only in one
place in generic_funcall and is no longer.
* eval.c (gather_free_refs): Use args_normalize_least.
(prod_common): Use args_normalize_exact.
* ffi.c (ffi_call_wrap): Use args_normalize_least.
* lib.c (generic_funcall): Use args_normalize_least in switch
statement that handles various callable non-function objects.
When copying args, ensure that there are ARGS_MIN.
A different strategy is used for producing the trailing args
for variadic calls, further reducing consing. Rather than
normalize the args to the fixed number, and then set
args->fill to zero so that args contains just the list, we use
args_cat_zap_from to create a copy of the args in which the
fixed ones are trimmed out. The resulting args is not
renormalized to be purely a list so no consing or list traversal
takes place. If the rebalancing is needed, the called
function will have to do it.
(dwim_set): Streamline the code that handles hashes assigned
via two or three args.
* struct.c (method_args_fun, umethod_args_fun): Use
args_normalize_exact.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_intrinsic_noerr): New function.
* eval.h (eval_intrinsic_noerr): Declared.
* parser.c (listener_greedy_eval_s): New symbol variable.
(repl): Implement greedy evaluation loop, enabled by
the *listener-greedy-eval-p* special.
(parse_init): Intern the *listener-greedy-eval-p* symbol,
storing it in the listener_greedy_eval_s variable.
Register the symbol as a special variable.
* txr.1: Documented *listener-greedy-eval-p* variable
and the greedy evaluation feature that it controls.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (load): Instead of throwing error when a .txr file
is opened, process it according to sensible requirements.
* match.c (v_load): Store bindings in the current environment
frame before evaluating Lisp, and then update afterward.
This allows .txr files loaded from Lisp to continue matching
with the current bindings and extend those bindings.
* txr.1: Update documentation of load.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This bug shows up as a spurious warning and incorrect
expansion from a from like (do set [@1 x] y).
In this situation, sys:lisp1-setq is involved in the
assignment to the place denoted by @1, because of the way the
do operator expands the (set [@1 x] y) expression. The @1
meta-variable is replaced by a gensym, but some intermediate
expansion takes place in an environment which has no binding
for the gensym, causing the place to be treated as if it were
a global variable, using sys:lisp1-setq. The subsequent real
expansion in the environment in which the gensym is now bound
then calls upon the expansion of sys:lisp1-setq, which
proceeds via the expand_lisp1_setq function. But now the
variable has a lexical binding.
This bug doesn't show up in ordinary expressions like
(set [foo x] y) which is why it went undetected for a year.
* eval.c (expand_lisp1_setq): Fix the missing symbol in
the generated code for the case when the symbol has a lexical
variable binding. We must emit (sys:setq <sym> <value>), not
(sys:setq <new-value>).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* LICENSE, LICENSE-CYG, METALICENSE, Makefile, args.c, args.h,
arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, combi.c,
combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c,
ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c,
glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c,
lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c,
parser.h, parser.l, parser.y, protsym.c, rand.c, rand.h,
regex.c, regex.h, share/txr/stdlib/awk.tl,
share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl,
share/txr/stdlib/conv.tl, share/txr/stdlib/doloop.tl,
share/txr/stdlib/error.tl, share/txr/stdlib/except.tl,
share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl,
share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl,
share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl,
share/txr/stdlib/op.tl, share/txr/stdlib/package.tl,
share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl,
share/txr/stdlib/pmac.tl, share/txr/stdlib/socket.tl,
share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl,
share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl,
share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl,
share/txr/stdlib/with-resources.tl,
share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl,
signal.c, signal.h, socket.c, socket.h, stream.c, stream.h,
struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h,
syslog.c, syslog.h, termios.c, termios.h, txr.1, txr.c, txr.h,
unwind.c, unwind.h, utf8.c, utf8.h, win/cleansvg.txr:
Extended Copyright line to 2018.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The problem is that the lop macro in op.tl generates code
that uses sys:l1-val. That requires the place.tl module.
But there is no autoload trigger for sys:l1-val. Even if
there were, it wouldn't work because op.tl is lower level
w.r.t. place.tl; place.tl uses op.tl.
Let's just rewrite sys:l1-val and sys:l1-setq in C, so they
live in the run-time core.
* eval.c (sys_l1_val_s, sys_l1_setq_s): New symbol variables.
(me_l1_val, me_l1_setq): New static functions.
(eval_init): Intern sys:l1-setq and sys:l1-val symbols,
binding these to the macro expanding functions.
* share/txr/stdlib/place.tl (sys:l1-setq, sys:l1-val): Macros
removed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (sys_lisp1_value_s): Declaration moved to be
collocated with lisp1_setq_s.
(lisp1_setq_s): Variable renamed to sys_lisp1_setq_s to
match sys_lisp1_value_s.
(do_expand): Follow rename of lisp1_setq_s.
(eval_init): Follow rename; collocate initialization of
vars.
* protsym.c (lisp1_setq_s): Manually renamed to
sys_lisp1_setq_s instead of full regeneration, which we
do at release time.
|
|
|
|
|
|
|
|
|
| |
* eval.c (term): Function here from lib.c, and changed to
static. It is used only by iapply.
* lib.c (term): Function moved to eval.c.
* lib.h (term): Declaration removed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This reduces the proliferation of car_l and cdr_l.
With this change, nreverse should work on chains of
objects that implement rplacd.
* combi.c (comb_gen_fun_common, rcomb_gen_fun_common): Use
rplaca.
* eval.c (mappendv, mapdov): Likewise
* hash.c (hash_equal_op): Likewise.
* lib.c (nreverse, acons_new, aconsql_new, sort_list): Use
rplaca and rplacd.
* match.c (dest_set, v_gather, v_collect, v_flatten, v_cat,
v_output, v_filter): Likewise
* parser.c (ensure_parser): Use sys_rplacd.
* unwind.c (uw_register_subtype): Use rplacd.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register rplaca and rplacd using new
rplaca_s and rplacd_s symbol variables.
* lib.c (rplaca_s, rplacd_s): New symbol variables.
(rplaca): Handle struct object via rplaca method, if it has
one, otherwise lambda-set, if it has that, or else error
out.
(rplacd): Handle struct object via rplacd method.
* lib.h (rplaca_s, rplacd_s): Declared.
* txr.1: Documented rplaca and rplacd methods.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Recording of source location info incurs a time and space
penalty. We don't want to impose this on programs which are
just reading large amounts of Lisp data that isn't code.
* eval.c (eval_init): Register lisp-parse and read functions
to the newly introduced nread function rather than lisp_parse.
lisp_parse continues to record source location info
unconditionally.
* parser.c (rec_source_loc_s): New symbol variable.
(parser_common_init): Set the new member of the parser
structure, rec_source_loc, according to the current value of
the special var *rec-source-loc*.
(lisp_parse_impl): New second argument, rlcp_p. If true, it
overrides the rec_source_loc member of the parser structure
to true.
(lisp_parse): Pass true argument to rlcp_p parameter of
lisp_parse_impl, so parsing via lisp_parse always records
source loc info.
(nread): New function.
(iread): Pass true argument to rlcp_p parameter of
lisp_parse_impl, so *rec-source-loc* controls whether source
location info is recorded.
(parse_init): Initilize rec_source_loc_s symbol variable,
and register the *rec-source-loc* special var.
* parser.h (struct parser): New member, rec_source_loc.
(rec_source_loc_s, nread): Declared.
* parser.y (rlcp_parser): New static function. Like rlcp but
does nothing if parser->rec_source_loc is false.
(rlc): New macro.
(grammar): Replace rlcp uses with rlc, which expands to a call
to rlcp_parser.
(rlrec): Do nothing if source loc recording is not enabled in
the parser.
(make_expr, uref_helper): Replace rlcp with rlc. This is
possible because these functions have a parser local
variable that the macro expansion can refer to.
(parse_once): Override rec_source_loc in the parser to 1, so
that source loc info is always recorded when parsing is
invoked through this function.
* txr.1: Documented *rec-source-loc* and added text under
read and iread.
|
|
|
|
|
|
|
|
|
|
| |
These easily express discontinuous ranges.
* eval.c (rlist_fun, rlist_star_fun, rlist, rlist_star): New
static functions.
(eval_init): Register rlist and rlist* intrinsics.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
| |
* eval.c (do_expand): In the function call case, check for the
operator being the rcons function. If it is called with
exactly two arguments and they are constantp in the given
environment, then evaluate them and replace with a range
literal object. Rationale: ranges often appear in constant
form like [array 1..:] and whatnot.
|
|
|
|
|
|
|
|
| |
* eval.c (op_prof): Deal with the cases when alloc_bytes_t
value cannot be converted to a val in a single call to
unum.
* lib.h (SIZEOF_ALLOC_BYTES_T): New macro.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When a form is a macro, but the macro declines to expand the
form, the form must still be code walked; we can't just return
it and be done. For instance if it is a function call, its
argument expressions have to be expanded.
This also causes undefined function warning to be generated
properly if a macro declines, and the resulting form is
a function call to a not-yet-defined function.
* eval.c (do_expand): If expand_macro yields the original
form, branch backwards to re-execute the whole if statement
again. Use the fact that the local variable macro is now
non-nil to skip the macro expansion case.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch implements a new requirement which clarifies what
happens when a macro declines to expand a form.
To decline expanding a form means to return the original form
(same object) without returning it. The expander detects this
situation with an eq comparison on the input and output.
The current behavior is that no further attempts are made to
expand the form. This is problematic for various reasons. In
code which is expanded more than once, this can lead to the
expansion being different between the expansion passes. In
the first pass, a local macro M might decline to expand a
form. In the second pass, the local macro definition no longer
exists, and the form does get expanded by a global macro M.
This kind of instability introduces a flaw into complex macros
which expand their argument material more than once.
The new requirement is that if a macro definition declines to
expand a macro, then a search takes place through the outer
lexical scopes, and global scope, for the innermost macro
definition which will expand the form. The search tries every
macro in turn, stopping if a macro is found which doesn't
decline the expansion, or after passing the global scope.
* eval.c (expand_macro): Implement new searching behavior.
* txr.1: Documented the expansion declining mechanism
under defmacro and macrolet.
* tests/011/macros-3.tl: New file.
* tests/011/macros-3.expected: New file.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Inspired by APL.
* eval.c (eval_init): Register grade intrinsic.
* lib.c (grade): New function.
* lib.h (grade): Declared.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (me_case): When a list of case keys is one
element long, reduce it to an atom. Then a simple
equality is applied whether the item is equal
to the key, rather than whether it is a member
of a list containing that one key.
This helps with the (t) case which is mandatory,
since t is ruled out as a key.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Test case: txr -t '(gun "foo")' must run in
constant memory.
* eval.c (tprint): Rewritten to iterate over lists using
open loop rather than mapdo. Classification of the sequence
is done using the new seq_info, as must be for all new
sequence functions.
* txr.c (txr_main): Implementation of -t, -p and -P captures
the result of the expression in a variable whose value is
zapped when it is passed to the function. A gc_hint is added
so that this isn't optimized away. Thus, this code won't hold
on to the original pointer to a lazy, infinite list.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c: doesn't need rand.h.
* filter.c: doesn't need gc.h.
* parser.l: doesn't need eval.h.
* parser.y: doesn't need utf8.h, stream.h, args.h or cadr.h.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (do_macroexpand_1, do_macroexpand): New static
functions; take symbol macro lookup function poiner as
argument.
(macroexpand_1): Reimplemented as wrapper around
do_macroexpand_1.
(macroexpand): Reimplemented as wrapper around
do_macroexpand.
(macroexpand_1_lisp1, macroexpand_lisp1): New static
functions.
(eval_init): Registered intrinsics macroexpand-1-lisp1
and macroexpand-lisp1.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
| |
* arith.c (inv_cum_norm): New function.
* arith.h (inv_cum_norm): Declared.
* eval.c (eval_init): Register inv-cum-norm intrinsic.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The new implementation treats the @1, @2 ... @rest
op arguments as local macros, leveraging the power of the
macro expander to perform the substitution which renames these
to gensyms.
As a result, the implementation is correct.
The old implementation blindly walks the tree
structure doing the substitution, so that @1 is substituted
even though it is in a quoted literal:
[(op list '(@1)) 42] -> ((#:arg-01-0166))
under the new implementation, '(@1) is left alone:
[(op list '(@1)) 42] -> ((@1) 42)
* eval.c (expand_quasi): Because the new op macro doesn't
rudely reach into quasi forms to substitute sys:var
elements, relying on macro expansion, we must now macro-expand
sys:var elements. The sys:var macro created by op is
smart enough to skip the compound ones that have modifiers;
they are handled via the inner expansion of the symbol.
That is to say, `@@1` contains the structure
(sys:var (sys:var 1)). The sys:var macro ignores the outer
sys:var. But existing behavior in expand_quasi expands the
inner (sys:var 1), so the substitution takes place.
(eval_init): Do not register the hacky old op and do macros,
except in compatibility mode with 184 or older.
* lisplib.c (op_set_entries, op_instantiate): New functions.
(dlt_register): Register auto-loads for op and do macros via
new functions, except when in compatibility mode with 184
or older, in which case we want the old build-in hacky op
to be used.
* share/txr/stdlib/op.tl: New file.
* txr.1: Fixed or removed no-longer-true text which hints at
special hacks implemented in the op expander. Added
compatibility notes for all new compat-switched op behaviors.
|
|
|
|
|
| |
* eval.c (builtin_reject_test): Suppress warning if
the symbol is sys:var or sys:expr.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The dot-to-apply transformation is now applied when
meta-expressions like @foo and @(bar) apparently occur in the
dot position.
This change is made in anticipation of a rewrite of the op
macro, in which the @1, @2, and @rest arguments will be
implemented as macrolets, rather than the ad-hoc, hacky code
walk currently performed in the transform_op function.
* eval.c (dot_meta_list_p): New static function.
(dot_to_apply): Detect the presence of a sys:var or
sys:expr argument in a form. If found, then turn
it and the remaining forms into a single compound
form which replaces them.
* txr.1: Update doc under Dot Position in Function Calls.
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register the same function under
length and len.
* txr.1: Documented.
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register spl and tok intrinsics.
* lib.c (spl, tok): New functions.
* txr.1: Documented.
|
|
|
|
| |
* eval.c (eval_init): Fix incorrect registration of tok-str.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): prod and sum intrinsics registered.
* lib.c (sum, prod): New functions.
* lib.h (sum, prod): Declared.
* txr.1: Documented.
|
|
|
|
|
|
| |
* eval.c (pad): Incoming sequence must be nullified, otherwise
empty vectors and strings produce a spurious nil.
This affects the weave function, which uses pad.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register set-diff under two
names: set-diff and diff. Register new isec and uni
intrinsics.
* lib.c (isec, uni): New functions.
* lib.h (isec, uni): Declared.
* txr.1: Documented new uni and isec functions, new diff
function name, and the deprecation of set-diff and its order
guarantee w.r.t the left sequence.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Just the ANSI CL nth for lists.
* eval.c (eval_init): Register nth intrinsic.
* lib.c (nth): New function.
* lib.h (nth): Declared.
* share/txr/stdlib/place.tl (nth): New place macro,
trivially takes care of making nth an accessor.
Place macros are terrific!
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register new intrinsic relate.
* lib.c (do_relate, do_relate_dfl): New static functions.
(relate): New function.
* lib.h (relate): Declared.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Repro test cases for this:
A: (progn (defun f ()) [f]).
This emits a warning against the [f] usage, even though there
is a tentative definition of f as a function.
B: (progn (defun g () [f]) (defun f ())).
Emits a warning against [f] usage which is not purged by the
evaluation of the later definition.
Both problems are related to the separation of deferred
warnings into the tag namespaces: symbols and functions. When
[f] is being expanded, the deferred warning is put into the
variable namespace. So it doesn't match a tentative def in the
function namespace which would otherwise suppress it.
A subsequent function definition only purges the warning for
the function space.
We introduce a third space, the "symbol space". Lisp-1
deferred warnings are introduced against this namespace and
both variable and function definitions purge deferred warnings
from that namespace also, in addition to their respective
proper namespace. This solves problem B. Problem A is solved
by checking, when [f] is expanded, for tentative definitions
of f in both the variable and function tag space.
Note that test case B still warns when entered into the
listener, because the listener dumps deferred warnings
prior to evaluation, thus prior to evaluating (defun f ()).
* eval.c (op_defvarl, op_defun): Purge deferred warnings from
the sym tag namespace also.
(expand_lisp1): Do not emit the deferred warning for a
nonexistent name if it has a tentative definition either as a
function or variable. When emitting the deferred warning, use
the sym namespace.
|