| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler): New slots, gcallop
and callop.
(compiler comp-fun-form): Restructured to handle apply and
call forms, turning them into better code, exploiting the
call, gcall, apply and gapply instructions.
(compiler comp-call): Take opcode argument so apply calls can
be handled.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
commit 87caead8269055b4791de53be0e03afab01f1dd4, subject
"macros: expand declined form in outer env" broke tagbody.
The tagbody implementation uses a dubious trick of setting up
local macros which return the original form, as a way of
prevening an outer scoped macro from expanding the form. The
above commit specifically changes the behavior in such a way
that this strategy is nullified.
However, the macro fallback feature introduced by the above
commit is exactly what tagbody needs!
* share/txr/stdlib/tagbody.tl (tagbody): Simplify the
treatment of (go label) thanks to new behavior in macro
expander. We no longer need an extra sys:expand pass to
allow inner tagbodies to expand their go forms, and intercept
any unexpanded ones. We have a simple go macrolet which
performs the expansiion when the label is recognized, or else
returns the form to decline expansion. The macro expander
will then fall back by trying the macro in the next outer
scope. Thus, every (go label) is resolved in the tagbody
to which label belongs, or else lands into the top-level
go macro which diagnoses undefined labels.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
sys:catch via comp-catch method.
(comp-catch): New method.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/asm.tl (backpatch-low16, backpatch-high16):
New struct types.
(%backpatch-low16%, %backpatch-high16%): New global variables.
(swtch): New opcode.
(op-swtch): New opcode class.
* vm.c (vm_swtch): New static function.
(vm_execute): Handle SWTCH opcode via vm_swtch.
* vmop.h: Regenerated.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
defmacro via comp-handler-bind method.
(comp-handler-bind): New method.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/asm.tl (abscsr): New instruction.
(op-abscsr): New opcode class, derived from op-retsr.
* share/txr/stdlib/compiler.tl: Handle sys:abscond-from via
comp-return-from method.
(compiler comp-return-from): Handle sys:abscond-from by
switching to abscsr opcode instead of ret pseudo-op.
* vm.c (vm_abscsr): New static function.
(vm_execute): Dispatch ABSCSR opcode.
* vmop.h: Regenerated.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Route
block* to same helper method as block.
(compiler comp-block): Handle block* also by compiling the
name form and using the resulting value as the name
operand in the block instruction.
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
defmacro via expand-defmacro expander.
(expand-defmacro): New function.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
defun via expand-defun expander.
(expand-defun): New function.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
defvarl via expand-defvarl expander.
(expand-defvarl): New function.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
sys:setqf via comp-setqf.
(compiler comp-setqf): New method.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-setq): The
output register of the returned frag must be that of the value
calculating frag, not vloc, because in the dynamic variable
case, vloc holds the d-reg with the variable's name, not the
v-reg that receives its value.
(compiler compl-lisp1-setq): Fix same bug which got propagated
by copy-and-paste coding.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
sys:lisp1-setq via comp-lisp1-setq.
(compiler comp-lisp1-setq): New method.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle dwim
case via comp-dwim.
(compiler comp-dwim): New method.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (vbinding, fbinding): New
structs subtyping binding.
(sys:env lookup-lisp1): New method.
(sys:env extend-var, sys:env extend-var*, sys:env extend-fun):
Instantiate a vbinding or fbinding as appropriate.
This lets us tell whether we have a function or variable
binding after doing a successful lookup-lisp1.
(compiler compile): Add sys:lisp1-value case.
(compiler comp-lisp1-value): New method.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-fun-form): Add a
caseq form to handle certain top-level functions specially.
Add a case for the call function, handled by comp-call.
(compiler comp-call): New method.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Call
comp-fun-form instead of comp-call.
(compiler comp-call): Rename to comp-fun-form.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Route fun
to comp-fun.
(compiler comp-fun): New method.
|
|
|
|
|
|
|
|
| |
This supports labels and flet.
* share/txr/stdlib/compiler.tl (compiler compile): Route fbind
and lbind to comp-fbind method.
(compiler comp-fbind): New method.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (sys:env extend-fun): The
v register's level is two less than the frame level.
Add missing ppred call; extend-var has it already.
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-call): Pass the
location, not the binding itself, to comp-call-impl.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Wire in
unwind-protect case via comp-unwind-protect method.
(compiler comp-unwind-protect): New method.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Wire in
tree-bind case via comp-mac-param-bind method.
(compiler comp-mac-param-bind): New method.
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-bind-mac-params): Take
the context form and error forms as separate arguments instead
of calculating one from the other. Moreover, they are no
longer assumed to be objects to be quoted and inserted but
rather expressions to be substituted into the code directly.
This gives the caller flexibility to make them calculated.
(compiler comp-tree-bind, compiler comp-tree-case): Make the
compensating adjustments to preserve the behavior.
|
|
|
|
|
|
| |
* share/txr/stdlib/asm.tl (assembler dis-listing): Return the
number of instructions that were traversed.
(disassemble-c-d): Print count after instruction listing.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-bind-mac-params): We
don't need the full form for error reporting, because only the
leading symbol is reported in diagnostics. We do need the full
form if the :form parameter is used. If :form is not used,
then a compiled function need not carry the entire form in its
data table.
|
|
|
|
|
|
|
|
|
| |
var is sys:var when we're working in the system package.
This sometimes confuses the code walker, because
(sys:var X) is the implementation of the @X notation.
* share/txr/stdlib/compiler.tl (expand-bind-mac-params): Use
sym instead of var.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-prog1): prog1
already uses progn. When using progn, though, it should append
the nil form to the tail, otherwise progn will spare the last
from from being eliminated, leaving an unused constant in the
data table.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-progn):
Eliminate any form which is a constant or a symbol,
unless it appears in the last position.
|
|
|
|
|
|
|
|
|
|
|
|
| |
We optimize based on test being constant expressions.
* share/txr/stdlib/compiler.tl (compiler comp-cond): Whenever
a test is a constant null, we need not evaluate the forms in that case;
the entire case basically disappears so we compile it to nil.
We also need not consider any cases after the first case whose
test is a constant true.
(compiler comp-if): Optimize all situations when the test is
constant.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-cond): Don't
generate the jmp instruction at the end of the last case.
Why do I bother; a simple peephole optimizer will eliminate
these. I want a little better code, now! That's why.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In most compiler uses of bindv, getv and setv,
the operand which names the dynamic symbol is the data table:
a d0-dff register. The source or destination register of the
transfer could be anything. Therefore, the existing encoding
is suboptimal: the symbol is being put into the full sized
operand field of the instruction, and the source or
destination register into the small, ten-bit extra field
in the upper half. This breaks on cases like (set x y)
where x is a deeply nested lexical variable and y is
a dynamic variable. Let's reverse the encoding.
* share/txr/stdlib/asm.tl (op-getv, op-setv): Reverse the
operands. All derived opcodes follow this since they
reuse the code via inheritance.
* vm.c (vm_get_binding): Fetch the symbol from the small
operand field rather than the main operand field.
(vm_getsym, vm_getbind, vm_setsym, vm_bindv): Pull the
destination or source from the main operand of the instruction
rather than the small opreand.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The setting of an error variable upon destructuring mismatch
is not useful; it just takes extra instructions to check for a
colon return out of the body or that variable being set.
Let's have expand-bind-mac-params generate code which
returns that symbol itself of assigning to it. The
caller can then specify : for the strict parameter. A
destructuring mismatch turns into a : return value, exactly
the same as the value which indicates "fall through to next
case".
* share/txr/stdlib/compiler.tl (compiler comp-tree-case):
Don't generate the err-var; remove all references to it.
Pass : to expand-bind-mac-params as the strict parameter,
rather than err-var.sym. Generate much simplified code
after the cfrag: just test for a colon and continue
through to the next case or else branch to the end.
In the last case, the fall through path precipiates to the
end, so we insert an instruction to clobber the : in the
return register with a nil.
(expand-bind-mac-params): Eliminate assignments to strict;
it doesn't function as a variable any longer. Return
that symbol in the return-from forms.
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-setq): Fix
reversed setv instruction operands.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Add
tree-case case, handled via comp-tree-case method.
(compiler comp-tree-case): New method.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Wire in
tree-bind case via comp-tree-bind method.
(compiler comp-tree-bind): New method.
(expand-bind-mac-parse-params, expand-bind-mac-params): New
functions.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
return and return-from special forms.
(compiler comp-return-from, compiler comp-return): New
methods.
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-setq): Fix
reversed mov instruction arguments in lexical case.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl: If a non-list sequence like a
string or vector is being accumulated, we must have an append
call, because the accumulation cell is never extended with new
cells. After we replace the cdr of ,accum with a string or
vector atom, (last ,accum) just finds ,accum and so then the
cdr will be clobbered on the next iteration.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (sys:env extend-var*):
New method.
(compiler comp-let): When doing sequential bindings, we must
still add the variable to the environment even if there is no
init-form. Oops! Since we're not doing any gensym renaming
trick in this case but binding the real symbol directly, we
need a binding method that allows duplicates.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We want to diagnose (let (a a)) and (lambda (a a)), as well as
the analogous situations for function bindings. This is
certainly ambiguous: if the code accesses a, which one was
intended? The choice is undocumented and so this is a
likely programming error; nobody will write code this
deliberately, investigate what the implementation actually
does, and then rely on that.
However, multiple bindings of special variables are allowed.
Duplicates are also allowed in sequential binding.
Handling duplicates in let* binding creates the following
problem: (a a) means that a should be initialized from the
previous a. We would like to compile the init form in the
environment in which the second a doesn't exist, yet indicate
the destination location of the new a. Since we are clobbering
one environment as we go by adding bindings to it, this is not
possible. The solution is a rename hack: we introduce the new
a as a gensym, so that it is invisible. We indicate the
gensym's location as the destination register for the
init-form code fragment. Then immediately after compiling the
init-form, we rename the gensym variable.
* share/txr/stdlib/compiler.tl (sys:env extend-var, sys:env
extend-fun): Diagnose duplicates.
(sys:env rename-var): New methods.
* share/txr/stdlib/compiler.tl (compile comp-let): Bind to a
gensym instead of the real symbol when binding sequentially.
Then rename the symbol.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
sys:each-op with help of expand-each.
(expand-each): New function.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle and
and or cases via comp-and-or method.
(compiler comp-and-or): New method. This is based on
comp-progn.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Handle
dohash by rewriting the form via expand-dohash, then compiling
result.
(expand-dohash): New function.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-lambda): To
determine whether the argument is missing, we must
test it for equivalence to the : symbol. What we're
testing here is the wrong thing: the register which
will hold the output of the default initform.
That fragment would even be executed yet at this spot
in the code, never mind being the wrong value to test.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-progn): If the
suggested output register is a variable, progn should not use
it for the discarded values of the leading forms, only for
the last form. Writes to the variable space of the display
are costly because in closures, the underlying vector of
a given level has to be passed to gc_mutated. We use a new
temp register for the discarded forms.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler compile): Fix
nonsensical fourth argument expression in
comp-progn call.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-let): The
returned fragment must specify boreg not oreg, because
the output is either in oreg or bfrag.oreg.
|