| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Another part of the preparation for an upcoming change.
All library code is now read in the sys package, so any
symbols that are interned (local variables and whatnot)
are in sys and will not be exposed to user code.
We have to overcome some annoyances to achieve this:
- We have to stay away from the symbols exp or var,
because they are now sys:exp and sys:var with their
special meaning.
- Instances in which a symbol of the same name exists
in both sys and usr present a problem; the plain
symbol now is the usr one. For instance rplaca
will refer to sys:rplaca, so a small amount of
code has to explicitly use usr:rplaca.
* Makefile (COMPILE_TL): Change to the sys package before
compiling library code.
* lisplib.c (lisplib_try_load): Bind *package* to the system
package.
* share/txr/stdlib/asm.tl, share/txr/stdlib/compiler.tl:
Remove in-package macro invocation; we don't need this since
all files are loaded or compiled in the sys package.
* 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/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/trace.tl
share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl,
share/txr/stdlib/ver.tl, share/txr/stdlib/with-resources.tl,
share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl:
Deal with the various usr versus sys symbol issues.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/struct.tl (defstruct, sys:check-slot,
defmeth): Use slot rather than sys:slot as indicator in
tentative defs.
* struct.c (static_slot_s): Variable removed.
(struct_init): slot_s initialized with symbol in user package,
rather than system package. Initialization of static_slot_s
removed. Existing slot function now registered using slot_s.
(static_slot_type_reg): Remove reference to static_slot_s.
This was a dud all along; nothing publishes deferred warnings
against this symbol.
* protsym.c (protected_sym): Remove static_slot_s.
|
|
|
|
| |
* trace.tl: File was introduced in 2016, so 2016-2018.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* parser.c (read_file_common): The entire compiled
representation is now one big list. We must walk the list to
visit the individual compiled top-level forms.
* share/txr/stdlib/compiler.tl (compile-file): Collect all the
compiled top-level forms into one list, and emit it as one
object. This way, gensym references among the items will
resolve; for instance tests/012/man-or-boy.tl now compiles.
That file defines a function named by a gensym, and a macro
which expands to calls to that function. These end up in
separate top-level forms and have to resolve.
Because we are emitting everything as one big object, we
cannot rely on (in-package ...) forms influencing the reading
of the symbols. So we create a dummy package and switch to
that during the writing, which forces all symbols to be fully
qualified.
|
|
|
|
|
|
|
|
|
|
| |
* parser.c (read_file_common): Treat first form in file as a
version number of the form (major minor), where major nad
minor are non-negative integers. If the major number is
greater than zero, reject the file as incompatible.
* share/txr/stdlib/compiler.tl (usr:compile-file): Emit version
number (0 0) as the first item in a compiled file.
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
| |
The compiler barfed on hash.tl, reporting an if form with too
many arguments in the with-hash-iter macro, indicating that
it's basically broken.
* share/txr/stdlib/hash.tl (with-hash-iter): Repair the macro.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-quasi-args): When the
element of the quasiquote is a compound form, we can't just
return it. Firstly, because we are appending, we must wrap
each returned item in a list. Secondly, we must wrap the form
in code which formats it into a string consistently.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
These top-level macro-time forms are preventing code from
being compiled.
* share/txr/stdlib/ifa.tl: Remove macro-time around
sys:if-to-cond function.
* share/txr/stdlib/package.tl: Remove macro-time around
sys:name-str.
* share/txr/stdlib/struct.tl: Remove macro-time around
sys:bad-slot-syntax and sys:prune-missing-inits.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The sys:bind-mac-error function is a run-time support function
for the compiler-generated code for destructuring. But the
compiler.tl source file is a bad place for it. It means that
compiled modules which need sys:bind-mac-error auto-load the
entire compiler. That easily creates an irresolveable cycle,
because the compiler is on top of the foodchain.
No, sys:bind-mac-error belongs in error.tl; the light-weight
module of low-dependency run-time support routines for error
reporting.
* lisplib.c (error_set_entries): Add sys:bind-mac-error symbol
here.
(compiler_set_entries): Remove it from here.
* share/txr/stdlib/compiler.tl (sys:bind-mac-error): Function
removed.
* share/txr/stdlib/error.tl (sys:bind-mac-error): Function
moved here.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/asm.tl (assembler): Wrap with compile-only
so we don't redefine this struct while we are compiling
the assembler.
(%oc-code%): Use defparml so this is reset to zero, so that
the opcodes are numbered from zero instead of the most
recent value left in the variable.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl: Skip top-level forms which are
just constants. Their value is discarded and they have no
effect.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-tree-case): The
block name isn't a lexical variable; do not add it to nenv via
extend-var. Just bind to gensym directly and insert where
needed. This reduces the run-time frame size by one entry.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Uses of the macro-time form are not useful in this module, and
will hinder compilation, since forms evaluated by macro-time
are not seen by the compiler and thus cannot be emitted in
compiled form into a compiled file.
* share/txr/stdlib/place.tl: Remove all top-level occurrences
of macro-time.
(defplace): Remove macro-time emitted in expansion, replacing
it by progn.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-defmacro): We cannot
simply generate a mac-param-bind form because that has no
means to pass through the all-important macro environment
parameter; its expansion is carried out by
expand-bind-mac-params with an nil environment parameter.
Instead, we retarget to use expand-bind-mac-params directly,
and supply the parameter gensym.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lisplib.c (compiler_set_entries): Autoload on compile-file.
* parser.c (parse_init): Expose get-parser, parser-errors and
parser-eof intrinsics in system package.
* share/txr/stdlib/compiler.tl (compiler): Wrap defstruct form
in compile-only. What this means is that when we invoke
comile-file on compiler.tl, the compiler will only compile
this defstruct and not evaluate it. I.e. it will not try to
redefine the structure. Redefining the core structure of the
compiler while it is compiling itself wreaks havoc on the
compilation.
(%fille-suff-rx%, *emit*, *eval*): New variables.
(open-compile-streams, list-from-vm-desc, usr:compile-file):
New functions.
* vm.c (vm_desc_nlevels, vm_desc_nregs): New static functions.
(vm_init): Register new intrinsics vm-desc-nlevels and
vn-desc-nregs in system package.
|
|
|
|
|
| |
* share/txr/stdlib/asm.tl, share/txr/stdlib/compiler.tl: Just
use (in-package sys) rather than (in-package :sys).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-cond): Add
handling for the case when the cond clause contains only a
test form, and no additional forms. In that case, if the
value is true, then cond terminates with that value. We can
nicely achieve this by using or. This was uncovered while
compiling share/txr/stdlib/awk.tl, which contains such a
case in (sys:awk-state loop) that handles opening the
input source.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (comp-block): Our output frag
indicates that oreg is the output register, and in the case
when the block is terminated by the dynamic return, that's
where it stores the result value before branching to the skip
address. In the ordinary termination case, we have neglected
to move the output of the block's code from bfrag.oreg to
the output register oreg.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (comp-unwind-protect): The
output register of the compiled unwind-protect is that
of the protected forms compiled in pfrag, not of the
compiled code for the cleanup forms in cfrag.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (comp-switch): When compiling
the shared case of switch (generated by tagbody), we must
identify the last fragment's output register and move that to
oreg.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (comp-switch): Emit the code
for evaluating the switch index. This has been working by
fluke, because when the index is a variable, the assembly
code for ifrag is nil; the swtch instruction accesses the
variable directly and all is cool.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
There is a smattering of incorrect logic affecting a number of
the compiler's special form sub-compilers. Basically the issue
is that a compiler routine cannot arbitrarily use the oreg
that it is given. If it generates multiple instructions which
clobber a destination, only the last clobber may target oreg.
The reason is that oreg is not necessarily a fresh temporary
that can be used arbitrarily. It can be a variable which is
evaluated by the forms that are compiled by the sub-compiler.
Prematurely storing a value into oreg can affect the behavior
and result value of not-yet executed code. The recent
"indirect function calls" fix addressed just one case of this;
the problem is more wide-spread.
* share/txr/stdlib/compiler.tl
(compiler (maybe-alloc-treg, maybe-free-treg)): New methods.
(compiler (comp-if, comp-switch, comp-unwind-protect,
comp-block, comp-handler-bind, comp-catch, comp-let,
comp-progn, comp-and-or, comp-prog1, comp-for, comp-call,
comp-tree-case): Do not carelessly use oreg for intermediate
computations; allocate one or more temporary registers for
that purpose, and either only move the final value into oreg,
or else indicate a temporary register as the returned frag's
output register.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-lambda): We must
not deduce the frame size from the nenv v-counter, because in
the case when no frame is needed (the function has no
arguments), nenv is just env. Our need-frame variable
indicates whether or not a frame is needed; if not, we must
use size zero. This is crucial because the VM otherwise ends
up throwing an exception due to the frame level mismatch.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (comp-return-from,
comp-return): The value expression is optional in all the
return operators.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (comp-call): We must not use
the output register oreg for compiling the expression which
calculates the function because it could be one of the
arguments. In that case, we clobber an argument before we
have called the function.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-bind-mac-params): When
the strict parameter is the keyword symbol : we are
mis-translating the length check. We are ignoring the presence
of the rest-par, and checking for an exact length.
When rest-par is present, we must check only for a minimum
number of fixed parameters.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (comp-catch): The emitted code
doesn't handle the normal non-exception path. It assumes that
only the frame established with the earlier frame instruction
needs to be terminated; but in fact the catch intruction's
frame has to be ended also. Thus we don't need the frame-end
label; all exit cases jump too the handler-end label in front
of the two end instructions.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (comp-lambda): The init-forms
for optional parameters in a lambda must be compiled in the
environment in which prior arguments are visible.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): All
special forms are handled, so "not handled yet" wording is
inappropriate. Going forward, no special form will be added
without compiler support.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-call-impl):
Instead of allocating N temporary registers for N arguments,
some (or even none) of which may actually be used, we
do this one argument at a time: allocate just one register,
compile the argument expression, and then free the register
immediately if that fragment specifies its own output location
instead of the register. Otherwise keep the register and push
it on a stack. This strategy lowers maximum register use.
Also, since we are pushing the used registers on a stack,
when we call free-tregs, they get liberated in reverse
order of allocation, which keeps things tidy.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler check-treg-leak): New
method.
(usr:compile-toplevel): Free the top-level output register,
then call check-treg-leak to verify all were returned.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-bind-mac-params): The
listp function identifies a recursive parameter, not consp,
because nil is an empty pattern, and not a variable name,
in macro-style parameter lists.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We use the ifq instruction for compiling (if (eq x y) ...)
and (if (neq x y ...) rather than emitting a call to
eq or neq.
* share/txr/stdlib/compiler.tl (%test-funs-pos%,
%test-funs-neg%, %test-funs%, %test-inv%): New global
%variables.
(comp-if): Recognize when test expression is one of the tests
in %test-funs% and transform into (sys:ift ...) syntax.
Also, minor unrelated change here: (if test) optimized away to
nil if test is a constant expression.
(compiler comp-ift): New method.
(compiler comp-fun-form): Recognize sys:ift in operator
position; hand off to comp-ift.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Pass form
to comp-fun-form rather than sym and (cdr form).
(compile comp-fun-form): Take just a form argument.
Internally destructure to sym and args with tree-bind.
This will allow some special cases added in the future
to have access to the original form.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-cond): Replace
pointlessly verbose cond implementation compact implementation
that rewrites cond to combinations of if, progn and smaller
cond. This generates pretty much the same code, and will
automatically benefit from special case translations
applied in if.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler): Remove gcallop and
callop static members.
(%gcall-op%, %call-op%): New global variables.
(compiler comp-fun-form): Use new globals instead of old
static members.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-if): Remove a
trailing maybe-mov from the instruction template that
serves no purpose and can potentially generate an instruction.
|
|
|
|
|
|
| |
* share/txr/stdlib/asm.tl (disassemble-c-d): When printing the
data table, use capital hexadecimal for the dregs, consistent
with the instruction listing.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Very similar issue to the sys:fbind issue fixed some commits
ago. When we are setting up parallel bindings, we don't want
to compile initforms in the original env, because then they
get the same frame level as the new env we are compiling. Thus
(let ((x (let (...)))) ...) is mistranslated. Both lets,
have environments which are siblings of the same parent env,
which puts them on the same level. But their lifetimes at
run-time are nested, so they cannot share the same level.
The VM caught this since frame instructions declare their
absolute level and it must be one higher than the current
level. (I had the foresight to predict this might be a source
of problems and put in the checks.)
* share/txr/stdlib/compiler.tl (compiler comp-let): Same trick
as in sys:fbind case: set up an empty environment above the
initforms, so when an initform creates an environment, it is a
granddaughter of env, and thus a niece rather than sister of
of nenv, consequenty one frame level higher.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler get-dreg): If the
input atom is nil, return the t0 register that always
holds nil.
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler get-dreg):
Restructure code. Don't increment dreg-cntr past 255.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler): new slot,
treg-cntr; slot nregs removed; tregs stack initialized to
empty list.
(compiler alloc-treg): Take from stack if possible,
otherwise create new treg using counter, up to 255.
(usr:compile-toplevel): Referenceco.treg-cntr for register
count, rather than removed co.nreg.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-progn): Since
oreg-discard is conditionally allocated, it must be
only be freed if it had been allocated.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
prof via comp-prof method.
(comp-prof): New method.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/asm.tl (prof): New opcode.
(op-prof): New opcode class.
* vm.c (vm_prof_callback, vm_prof): New static functions.
(vm_execute): Handle PROF opcode via vm_prof.
* vmop.h: Regenerated.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
sys:switch via comp-switch method.
(comp-switch): New method.
|
|
|
|
|
|
|
|
|
|
|
|
| |
When a (flet ...) form is compiled, the function arguments of
the lambda are being bound in the same frame and clashing
against the variables being bound by the construct.
* share/txr/stdlib/compiler.tl (compiler comp-fbind): For the
non-recursive case, insert the dummy empty environment eenv,
and compile the forms in that environment. This raises them
up to the appropriate display level without affecting what
is visible in their scope.
|