| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It looks like I neglected to treat dynamically scoped
variables in destructuring; all parameters are treated as
lexical. This is only true in interpreted code; compiled
destructuring treats dynamics properly because it generates a
let to bind all the variables which occur, and then uses
assignment to populate them.
* eval.c (bind_macro_params): Instead of env_vbind, use the
newly introduced lex_or_dyn_bind helper function.
(op_tree_bind, op_mac_param_bind): Save and restore dyn_env
around bind_macro_params and the evaluation of the associated
body. In op_defmacro, this is already done.
|
|
|
|
|
|
|
|
| |
* eval.c (lex_or_dyn_bind_seq, lex_or_dyn_bind): New static
functions.
(bind_args): Eliminate repeated code using new helper
functions. One wrong repetitions is thereby fixed also: a
a neglected check of dyn_env_made.
|
|
|
|
|
|
|
|
|
| |
* eval.c (expand_opt_params_rec, expand_params_rec): Remove
pspecials argument, and accumulation of the special
variables. The caller doesn't use this list any more.
(expand_params): Remove unused specials local variable whose
address was passed as the pspecials argument to
expand_params_rec.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In this patch we eliminate the special operator
sys:with-dyn-rebinds, and implement correct semantics for
dynamically scoped variables that occur in argument
lists.
* eval.c (with_dyn_rebinds_s): Symbol variable removed.
(bind_args): Handle special variables dynamically:
for each symbol that appears, check whether it is a special
and treat accordingly by allocating a new dynamic environment
if necessary, and binding in that environment.
This adds overhead, which is why I moved away from this
approach in the past. But now that there is a compiler,
overhead in the interpreter matters less. Correct semantics
is more important.
(expand_params): Greatly simplified for not having to wrap the
sys:with-dyn-rebinds operator around the body.
(funcall_interp): Since bind_args can now extend the dynamic
environment, it is necessary to save and restore dyn_env
around it. Another call to bind_args occurs in op_catch;
that already saves and restores dyn_env.
(op_with_dyn_rebinds): Static function removed.
(do_expand): with-dyn-rebinds-s case removed.
(eval_init): Removed interning of sys:with-dyn-rebinds
symbol and registration of special op.
* protsym.c: Regenerated.
* compiler.tl (compiler compile): Remove case which handles
sys:with-dyn-rebinds.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Change ca6199a that went into TXR 191 was over-zealous in suppressing
expand_param_rec calls for non-macro argument processing. The recursive
calls are needed in order to detect parameters that are special
variables and add them to pspecials. The upshot is that usage such as
the following broke: (lambda (*stdout*) ...) because expand_param_rec
isn't called on the *stdout* symbol and *stdout* is thus not noted as a
special variable, and thus the expander then neglects to produce
(sys:with-dyn-rebinds (*stdout*) ...) around the body of the lambda.
The new compiler introduced at the same time made this harder
to find. Why? Because the compiler ignores the
sys:with-dyn-rebinds special form; it implements its own
handling for specials in lambda and let! So compiled code is
unaffected by this regression.
* eval.c (expand_opt_params_rec): Call expand_params_rec on the
car of the optional var-init pair, whether or not expanding a macro
style parameter.
(expand_params_rec): Call expand_params_rec recursively on any parameter
that is bindable whether or not in macro mode. The two cases fold
together again, and so here we see that the recent fix d934a3e was also
a regression caused by ca6199a.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When compile-file writes emits the file, it does so with
*package* bound to a temporary package named "$" so that all
the symbols get fully qualified. Problem is, this is a valid
package name and is added to the package list. While the
package exists, symbols such as $:a could be interned. If such
symbols occur in code being compiled, they get emitted using
unqualified names. Let's introduce an internal interface for
making an anonymous package which isn't on the list of
package, and which has a name that results in bad syntax if it
occurs in print.
* eval.c (eval_init): Register sys:make-anon-package
intrinsic.
* lib.c (make_package_common): New static function.
(make_package): Package construction and initialization
code moved into make_package_common.
(make_anon_package): New function.
* lib.h (make_anon_package): Declared.
* share/txr/stdlib/compiler.tl (usr:compile-file): When
writing out translation, bind *package* to anonymous
package from sys:make-anon-package.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is similar to the ANSI CL load-time-value.
* eval.c (load_time_s, load_time_lit_s): New symbol variables.
(op_load_time_lit, me_load_time): New static functions.
(eval_init): Intern load-time symbol and sys:load-time-lit.
Register the sys:load-time-lit special operator and load-time
macro.
* share/txr/stdlib/asm.tl (assembler parse-args): We must
now allow the d registers to be the targets of a mov
instruction, because load-time depends on being able to mutate
the data vector, in order to turn the result of a calculation
into a de facto literal.
* share/txr/stdlib/compiler.tl (compiler): New member,
lt-frags.
(compile-in-toplevel): New macro.
(compiler alloc-dreg): New method.
(compiler compile): Handle sys:load-time-lit special form
via comp-load-time-lit method.
(compiler comp-load-time-lit): New method.
(usr:compile-toplevel): Prepend the load-time assembly code
fragments to the compiled assembly code.
* vm.c (vm_set, vm_sm_set): Do not reject an attempt to modify
the static data, since load-time now generates mov
instructions targetting the d registers.
* txr.1: Document load-time.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Give the sys:fmt-simple function argument defaulting so the
generated code doesn't have to call it with all five arguments
present, four of them nil being much of the time.
* eval.c (fmt_simple): Default all but the first four
arguments.
(eval_init): Re-register sys:fmt-simple as having only one
required argument.
* parser.c (read_file_common): Load version 1 or 2 files.
We are bumping the object file version to 2 because
now when we compile files, they won't work with older
TXR in which all five arguments to sys:fmt-simple are
required.
* share/txr/stdlib/compiler.tl (expand-quasi-mods):
Generate the sys:fmt-simple call with just enough
arguments to express the modifiers that were decoded.
(sexpand-quasi-args): Reduce the trivial modifier-less
sys:fmt-simple calls to just one argument.
(%tlo-ver%): Bump major version to 2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When a dotted form like (call x ... . z) is subject to the
dot-to-apply transformation, this results in
(apply (fun call) x ... . z). The (fun call) is useless
and can be removed. Therefore, what we do is remove
occurrences of call from the original form.
* eval.c (dot_to_apply): Remove leading occurrences of call.
Since this promotes the second or subsequent form into
the operator position, we must be careful; if we are
doing a Lisp-2 form, only the first element requires
wrapping in (fun ...) when turned into an apply argument.
The second and subsequent arguments are subject to ordinary
evaluation and so if any of those becomes the operator,
it doesn't need (fun ...) wrapping.
|
|
|
|
|
|
|
|
|
| |
* eval.c (apply_intrinsic): Function removed.
(to_apf): Use applyv instead of apply_intrinsic.
* eval.h (apply_intrinsic): Declaration removed.
* vm.c (vm_gapply): Use applyv instead of apply_intrinsic.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Now (pprof (apply '+ 1 2 3 4 5 '(6 7))) shows zero
bytes consed. Previously 176 (on 32 bit). This is
the same whether the expression is compiled or
interpreted.
* eval.c (applyv): Rewritten to efficiently manipulate the
args and call generic_funcall directly. The consing
funcction apply_intrinsic_frob_args is only used when
args contains a trailing list (args->list) and is only
used on that trailing list, not the entire arg list.
Also, changing the static function to external.
* eval.h (applyv): Declared.
* vm.c (vm_apply): Use applyv instead of wastefully
converting the arguments to a consed list and going through
apply_intrinsic.
|
|
|
|
|
|
|
|
| |
The <trailing-args> argument is required in apply and iapply;
and that is documented.
* eval.c (apply_intrinsic_frob_args): Check for args being
empty and throw.
|
|
|
|
|
|
|
|
| |
* eval.c (hash_min_max): New static function.
(me_case): Check for keys being all integers or all characters
in a dense range (> 75% full). Generate code for switching
directly on the displacement of the tested value into the key
range.
|
|
|
|
|
|
|
|
| |
* eval.c (do_expand): Do not convert (op arg ... . dot)
to (sys:apply (fun op) (sys:l1-value arg) ... dot) if op is
a special operator; this is only valid for functions.
This issue has been uncovered by new diagnosis of undefined
functions in the fun operator.
|
|
|
|
|
|
|
| |
* eval.c (dotted_form_error): New static function.
(expand_forms, expand_forms_ss, expand_forms_lisp1): Call
dotted_form_error instead of repeated open coded uw_throwf
calls.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (me_case): Correct the condition. We want to generate
for all the case comparison types. The only situation we want
to avoid is when the keys do not use eq equality, but caseq
is used. The reason is that the underlying hash table is
eql-based, not eq-based: it's not the right kind of hash
table for caseql/caseql*. We can only use it if two keys
might be eql that are not eq.
|
|
|
|
|
|
|
| |
* eval.c (compares_with_eq): New static function.
(me_case): Instead of check_fun, call compares_with_eq
directly. For the case when we map over check fun,
allocate the function just once, outside the loop.
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): vm-fun-p intrinsic registered.
* lib.c (vm_fun_p): New function.
* lib.h (vm_fun_p): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (public_package): New variable.
(obj_init): Protect public_package from gc. Initialize
it with a package called "pub" which has the user
package in its fallback list.
* lib.h (public_package): Declared.
* eval.c (eval_init): Initialize package_s to public_package
rather than user_package, except in compat <= 190 mode.
* txr.c (txr_main): Bind *package* to public_package
rather than user_package, except in compat <= 190 mode.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The identifiers user_package, system_package and
keyword_package are preprocessor symbols that expand to other
preprocessor symbols for no good reason. Time to get rid of
this.
* lib.c (system_package_var, keyword_package_var,
user_package_var): Variables renamed to system_package,
keyword_package and user_package.
(symbol_package, keywordp, obj_init): Fix variable
references to follow rename.
* lib.h (keyword_package, user_package, system_package):
Macros removed.
(system_package_var, keyword_package_var,
user_package_var): Variables renamed.
* eval.c (eval_init): Fix variable references to
follow rename.
* parser.y (sym_helper): Likewise.
|
|
|
|
|
|
|
|
|
|
|
| |
append is too generic, and produces nil sometimes. Let's use a
custom run-time support function sys:fmt-join.
* eval.c (fmt_join): New function.
(eval_init): Intern sys:fmt-join.
* share/txr/stdlib/compiler.tl (expand-quasi): Generate a
sys:fmt-join call to combine the pieces rather than append.
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): The existing variable
sys:*load-recursive* is formally defined. This is necessary if
a form is evaluated from the command line using -p or -e,
which somewhere accesses this variable. txr_main sets up the
variable dynamicaly, but later. It should have an entry for it
in the global environment.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (load): If open_txr_file indicates compiled file by
setting txr_lisp_p to character #\o, use read_compiled_file.
* match.c (v_load): Likewise.
* parser.c (open_txr_file): Recognize the .tlo suffix, and
also try to open a .tlo version of an unsuffixed file before
trying it as .tl. Indicate a .tlo file by setting txr_lisp_p
to the character #\o rather than t.
(read_file_common): New static function, made from contents of
read_eval_stream. Will either evaluate forms or load compiled
code by instantiating virtual machine descriptions and
performing their top-level execution.
(read_eval_stream): Now a wrapper for read_file_common.
(read_compiled_file): New function.
* parser.h (read_compiled_file): Declared.
* txr.c (help): List new --compiled option.
(txr_main): If --compiled is specified, set txr_lisp_p to #\o
to load as compiled code. Update error message that -c is
not compatible with --lisp or --compiled.
If txr_lisp_p is #\o, then use read_compiled_file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Going forward, when : appears as the argument of an optional
parameter in destructuring, it is treated as an ordinary
object, and not as "this argument is missing". That is now a
feature of function calls only.
Rationale: interferes with macros. For instance, the pattern
(test : then else) doesn't correctly express the arguments
of if, because (if x y :) eats the semicolon.
The defaulting behavior is not useful because usually there
is no default value for optional structure, other than nil.
* eval.c (bind_macro_params): Only implement the colon hack
under compatibility with 190.
* share/txr/stdlib/place.tl (defplace gethash, defplace fun,
defplace symbol-function, defplace symbol-macro, defplace
symbol-value): Remove uses of : for defaulting the ssetter
argument. This illustrates how useless the feature is for
macro destructuring; all these just replace with nil.
* txr.1: Clarify that macro parameter lists don't implement
the colon trick. It was never explicitly specified that this
is the case, but could have been inferred from the statements
which indicate that macro parameter lists copy the features of
function parameter lists. Added compat notes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
These forms will be specially recognized by the file compiler
when they appear as top-level forms. eval-only will mean this:
only execute this form (possibly after compiling it);
do not emit any compiled code into the output file.
compile-only will mean: only emit the compiled code into the
output file; do not execute it.
* eval.c (eval_init): Register special operators compile-only
and eval-only. In the interpreter, these are equivalent to
progn and so route to op_progn.
* share/txr/stdlib/compiler.tl (compiler compile): Similarly
to interpreter, handle compile-only and eval-only as progn.
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (expand_params_rec): Add the parameter to the macro-time
environment before processing rest of parameter list. This is
already done for all the symbols of a macro-style
destructuring; just not for a simple parameter. This is
necessary, because the init forms of optional parameters occur
in a lexical environment in which prior parameters are
visible. The test case for this is that (lambda (x : (y x)))
must not produce a warning about unbound x.
|
|
|
|
|
|
| |
* eval.c (do_expand): When traversing (fun ...)
operator, warn if the function isn't defined or if it is being
applied to a special operator.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Currently, the case macros (caseq, caseql, casequal,
caseq*, caseql* and casequal*) all translate to a cond
statement which tries the cases one by one.
With this change, larger cases are translated to
a lookup through a hash table, which produces an
integer value. The integer value is then used as the
index in an op:switch form for table lookup dispatch.
If the hash lookup fails, then the else-clause is
evaluated.
op:switch is handled efficiently in the interpreter, and
turned into an efficient swtch VM instruction by the new
compiler.
* eval.c (me_case): Add variables and logic to the function
such that while it gathers the materials for the cond-based
translation, it also builds materials for a hash-switch-based
translation. Then, at the end, a decision is made by looking
at how many keys there are and other factors.
Because we don't have hash tables based on the eq function,
but only eql, we must be careful not to turn caseq into
hash lookup, unless we verify that the keys which occur
are fixnum integers, characters or symbols.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Due to a number of changes since December 2016, we have two
problems in the evaluator: (lambda (nil)) is accepted rather
than complaining that nil is not bindable; and
(tree-bind (()) '(3)) silently proceeds rather than
diagnosing that the atom 3 doesn't match the empty pattern ().
* eval.c (expand_opt_params_rec, expand_params_rec): When not
expandin macro-style params, check for a parameter not being
bindable, and also avoid recursion entirely when not doing
macro style.
(bind_macro_params): Don't assume that an atom parameter is
a variable, but rather tha a non-list parameter is
a variable. Otherwise we bind nil rather than treating it
as an empty sub-pattern. Before the December 2016 change
(744340ab), we were checking bindablep here; the idea was to
hoist the detailed checking to expansion time. But then the
pattern versus variable distinction was bungled here.
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|