| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (expand-quasi-match): Don't
extract substrings with sub-str; use match-str to match
in-place.
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (expand-quasi-match): Calculate
npos correctly relative to current pos. Use match-str rather
than starts-with.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (expand-quasi-match): Close the
gap in the expander by diagnosing all unhandled syntax.
There is now enough useful functionality and stability to
start documenting the feature.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (expand-quasi-match): Add case fo
r unbound var followed by var, followed by nothing.
* tests/011/patmatch.tl: New tests.
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (expand-quasi-match): Instead of
accessing args with car and cadr, capture that part in the
match using @(as) and refer to the variable.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (expan-quasi-match): Use rest
variable consistently instead of (cdr args). Two instances of
(cdr rest) should just be rest. New case added for variable
with no modifiers followed by text being the last item.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (expand-quasi-match): The return
value of search-str isn't a length but an absolute position.
We not only fix a bug, but lose a useless calculation.
* tests/011/patmatch.tl: New test cases for quasiliteral
patterns, starting with the most rudimentary.
Last one broke, due to the above issue.
|
|
|
|
|
|
|
|
|
|
|
| |
* match.tl (compile-cons-structure): Recognize quasi in the
middle of cons structure and compile appropriately.
(parse-lambda-match-clause): Recognize quasi in dot
position properly.
(check, check-end): Treat quasi as atom pattern.
(pat-len): Recognize quasi in dotted position.
(non-triv-pat-p): Handle quasi case. Any quasi containing
elements that are lists is nontrivial.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This not only gets rid of the @ from @`...`, but allows the ``
empty pattern `` to work. A bug is also fixed.
* share/txr/stdlib/match.tl (compile-match): Recognize
list headed by sys:quasi and feed to expand-quasi-match.
(sys:quasi): defmatch removed.
(expand-quasi-match): Function formed from sys:quasi defmatch.
Instead of :form argument, we access *match-form*, like all
the other internal functions. Instead of the :env parameter,
we use the vars-list object. Using that object's exists method
fixed a bug: failing to check for existing variables using
boundp.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (sys:quasi): New defmatch.
This is a macro for now, which makes it require the @ prefix:
e.g. @`@a-@b-@c`. The plain is to integrate this into the
matcher to eliminate that @ prefix. The first priority
are test cases and documentation.
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-quasi): Do not emit
sys:fmt-join call unconditionally. If expand-quasi yields
a list of one expression, we can just yield that expression.
If the list is empty, we can yield a mutable empty string.
(That case will not arise via `` because that converts to ""
at read time, but code that generates quasiliteral syntax
might have an empty case, and expect a mutable string in
all cases).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Log message correction superseding original commit
65213f5f7f6a204886a02c32f259ae2617d1dfb6.
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Bumped.
* txr.vim, tl.vim: Regenerated.
* protsymc.: Likewise
* share/txr/stdlib/doc-syms.tl: Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In eliminate-frame, our stategy of replacing vregs with tregs
assumes that the newly minted tregs are initialized to nil.
This is true if the block is executed only once, but not true
if it's in the middle of a loop, where the previous
iteration's treg values can be present. This results in
miscompilation of code like
(when-match (@x @(all @x)) '(1 (1 2)) x)
which wrongly returns 1 instead of nil starting at
optimization level 2.
* share/txr/stdlib/compiler.tl (struct compiler): New slot,
loop-nest, indicating the loop nesting level.
(compiler eliminate-frame): add instructions to the start of
the block of code to null out all the tregs that we allocated
for replacing vregs. We do this only when compiling the
repeated parts of a loop, as indicated by a positive value
of loop-nest.
(comp-for): Increment loop-nest before compiling the repeated
parts of the loop; decrement it afterward.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/optimize.tl (basic-blocks join-block): When
we merge a block N with its physical predecessor P, we must
iterate over the jump targets of N, and update their reverse
list to point to P instead of N. A full call to link-graph
would fix it also, but we don't call link-graph anywhere in
the optimization pipeline after this point. The reverse
links are relied on to be correct elsewhere, such
merge-jump-tunks, which needs to walk the blocks which jump
to a removed duplicate block, to retarget them to go to
another copy of that block.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (comp-apply-call): When a call
expression is evaluated at compile time, we must quote the
result, because it could be a non-self-evaluating symbol,
or list.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-match): Pattern macro
expanders now have an environment parameter. We turn the list
of variables that have been bound so far into a fake
macro-time lexical environment, the parent of which is the
surrounding environment. The pattern macro can query this
using the lexical-var-p function to determine whether a given
variable already has a binding, either in the pattern, or
in the surrounding lexical environment.
(defmatch): Generate a two-argument lambda, and use the new
mac-env-param-bind to make the environment object available
to the user-defined expansion.
* tests/011/patmatch.tl: New test cases for this environment
mechanism, and also for defmatch itself.
* txr.1: Document role of :env under defmatch.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
mac-env-param-bind is like mac-param-bind but also allows
the value for the :env parameter to be specified.
* eval.c (op_mac_env_param_bind_s): New sy mbol variable.
(op_mac_env_param_bind): New static function.
(do_expand): Handle mac_env_param_bind_s.
(eval_init): Initialize symbol variable and register macro.
* share/txr/stdlib/compiler.tl (compiler compile): Add case
for mac-env-param-bind.
(compiler comp-mac-env-param-bind): New method.
* share/txr/stdlib/doc-syms.tl: Updated with new hashes for
tree-bind and mac-param-bind, and inclusion of
mac-env-param-bind.
* tests/012/binding.tl: New file.
* txr.1: Documented.
|
|
|
|
|
| |
* share/txr/stdlib/quips.tl (%quips%): Song lyric parody
of あなたに夢中 by キャンディーズ.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/doc-syms.tl: New entry for end.
* share/txr/stdlib/match.tl (check, check-end, check-sym,
loosen, pat-len): New functions, taken from original local
functions of sme macro.
(sme): Refactored by hoisting local functions out. Some
local variable renaming.
(end): New pattern macro.
* tests/011/patmatch.tl: New test for end.
* txr.1: Documented.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (open-compile-streams): When
the output file cannot be opened, the diagnostic message
wrongly refers to the input stream object rather than the
output file path.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lisplib.c (match_instantiate): Intern sme symbol.
* share/txr/stdlib/doc-syms.tl: Update with sme entry.
* share/txr/stdlib/match.tl (sme): New defmatch macro.
* tests/011/patmatch.tl: New tests for sme.
* txr.1: Documented.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (defmatch): Pass *match-form* to
mac-param-bind so that the context is available to defmatch
macros via the :form parameter.
* txr.1: Documented use of :form in defmatch.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/error.tl (compile-error): Print the
error message on *stderr*, like we do with warnings.
This allows the programming environment to pick up the
error message and navigate to that line accordingly.
The error message is also output by the unhandled exception
logic but with a prefix that prevents parsing by the tooling.
To avoid sending double error messages to the interactive
user, we only issue the *stderr* message if *load-recursive*
is true.
* tests/common.tl (macro-time-let): New macro. This lets us
bind special variables around the macro-expansion of the body,
which is useful when expansion-time logic reacts to values
of special variables.
* tests/012/ifa.tl: Use macro-time-let to suppress *stderr*
around the expansion of the erroneous ifa form.
We now needs this because the error situation spits out a
message on *stderr*, in addition to throwing.
|
|
|
|
|
| |
* share/txr/stdlib/struct.tl (new-expander): Don't format
prefix into error message; compile-error does that.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/match.tl (compile-scan-match): New
function.
(compile-match): Hook scan operator into compiler.
* lisplib.c (match_set_entries): Ensure scan is interned in
usr package.
* txr.1: Documented.
* share/txr/stdlib/doc-syms.tl: Updated with new entry for
scan.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lisplib.c (match_set_entries): Register defmatch
and *match-symbol* to autoload match.tl.
* share/txr/stdlib/doc-syms.tl: Updated with entries for
defmatch and *match-macro*.
* share/txr/stdlib/match.tl (*match-macro*): New special
variable holding hash.
(compile-match): Handle macros via *match-macro* hash.
(defmatch): New macro.
* txr.1: Documented.
* tags.tl: Recognize defmatch forms.
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (lambda-apply-transform): Do
not take all of the fixed arguments and rest expression to be
the trailing list. Rather, skip as many elements from these
as the function has fixed parameters. E.g. if there
are two fixed parameters as in (lambda (a b . c)) and the
call specifies four fixed parameters and a trailing x
(1 2 3 4 . x) then the rest argument c must be (list* 3 4 . x)
and not (list* 1 2 3 4 . x).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This bug causes forms like (call (fun 'foo) ...) not to
register foo as a free reference in the function space,
leading to inappropriate lambda lifting optimizations. The
compiler thinks that a lambda is safe to move because that
lambda doesn't reference any surrounding lexical functions,
which is incorrect.
A failing test case for this is
(compile-file "tests/012/man-or-boy.tl")
at *opt-level* 3 or higher. A bogus error occurs similar
to "function #:g0144 is not defined", due to that function
being referenced from a lifted lambda, and not being in
its scope.
* share/txr/stdlib/compiler.tl (compiler (comp-fun-form,
comp-apply-call)): Pass the function symbol as an extra
argument to comp-fun-form so that it's added to ffuns.
(compiler comp-call-impl): Take new optional argument: a
symbol to be added to the ffuns slot of the returned fragment,
indicating that a function symbol is referenced.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Bumped.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
| |
* share/txr/stdlib/doc-lookup.tl (open-url): Define for
android, which has xdg-open in the termux environment.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/awk.tl (awk-state loop): When rs contains a
string, do not pass it directly to regex-compile, because that
function calls regex-parse when the argument is a string.
Wrap it it a (compound ...) tree node to get it to be treated
as sequence of characters to match.
|
|
|
|
|
| |
* share/txr/stdlib/struct.tl (qref): Do not assume that (b) is
the name of a slot to be looked up. Use qref to handle it.
|
|
|
|
|
|
|
|
|
| |
The expression a.?b is not being treated hygienically;
a is evaluated twice. This is only if the null-safe object
is the left most; a.b.?c is hygienic.
* share/txr/stdlib/struct.tl (qref): Add the necessary gensym
use to fix the broken case.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (struct env): The mark-used
optional parameter of lookup-var is not used anywhere, and so
always nil. Let's remove it.
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/awk.tl (sys:awk-expander): Do not impose
stricter restrictions on :name than the block mechanism
itself.
* txr.1: Documentation updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* genman.txr: dump contents of symhash into a doc-syms.tl
library file, as a defvarl form.
* lisplib.c (doc_instantiate, doc_set_entries): New static
functions.
(lisplib_init): Register autoload for doc-lookup module
to symbols doc and *doc-url*.
* share/txr/stdlib/doc-lookup.tl: New file.
* share/txr/stdlib/doc-syms.tl: Likewise.
* txr.1: Documented.
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler (pop-closure-spy,
pop-access-spy)): The stack underflow checkt must be done by
checking top, not the incoming spy argument.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (%param-info%): New global
variable.
(compiler comp-fun-form): Use get-param-info function to get
param-info object.
(get-param-info): Retrieve object from cache, using the
function as the key. If not found, create the entry.
(compiler-emit-warning): Use get-param-info.
* share/txr/stdlib/param.tl (struct param-info): Remove symbol
slot, replacing it with the function.
(param-info :postinit): No need to do symbol-function lookup;
the function is given.
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (reduce-lisp, reduce-constant):
Propagate source location to rewritten forms.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch eliminates parentheses from the error messages,
as well as a leading ./ being added to relative paths.
The word "warning: " is moved into the error message, so that
it does not appear before the location.
Example, when doing (compile-file "path/to/foo.tl").
Before patch:
warning: (./path/to/foo.tl:37): unbound function foo
After:
path/to/foo.tl:37: warning: unbound function foo
Now when I compile out of Vim, it nicely jumps to errors in
Lisp code.
* eval.c (eval_exception): Drop parentheses from error
location, add colon.
(eval_warn): Prepend "warning: " to format string.
(eval_defr_warn): Drop parentheses from location, and
prepend "warning: " to format string.
* parser.c (repl-warning): Drop "warning:" prefix.
* share/txr/stdlib/compiler.tl (open-compile-streams): Do not
do parent substitution for relative paths if the parent path
is the empty string "", to avoid inserting ./ onto relative
paths in that case.
* share/txr/stdlib/error.tl (sys:loc): Drop parentheses and
space from location.
(compile-error) Separate location with colon and space.
(compile-warning, compile-defr-warning): Likewise and add
"warning: " prefix.
* unwind.c (uw_rthrow): Drop "warning: " prefix.
(uw_warningf): Add "warning: " prefix.
(uw_dump_deferred_warnings): Drop "warning: " prefix.
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (expand-quasi-args): Here,
expand-quasi-mods is being called with the wrong number of
arguments. This was likely intended to be a recursive call to
expand-quasi-args. Let's convert it to that. Removing this
case also works, but it is nicer not to generate the
sys:fmt-simple call.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We implement rudimentary compile-time checking beween function
calls and function definitions.
* share/txr/stdlib/compiler.tl (dstruct frag): We add one more
optional BOA parameter, corresponding to a new slot.
This is used when compiling a lambda. A lambda fragment is
annotated with the parameter parser object which gives
information about its arguments.
(struct fbinding): New slot, pars. When processing a sys:fbind
or sys:lbind form, we decorate the lexical function bindings
with the parameter object pulled from the lambda fragment
that is compiled for each function binding.
(*unchecked-calls*): New special variable. This is used for
checking, at the end of the compilation unit, the arguments of
calls to functions that were not defined at the time of the
call.
(compiler comp-fbind): When processing the lambda expressions,
propagate the parameter object from the compiled lambda
fragment to the function binding.
(compiler comp-fun-form): On entry, look up the function being
called and if it is lexical or has a global definition, check
the arguments. If it has no definition, push information into
the *unchecked-calls* list to do the check later, if possible.
Also, there is a behavior change here now: optimizations are
now applied here only to functions that don't have a lexical
binding. Thus if the application lexically redefines a
standard function, and calls it, we won't try to optimize it.
(param-check): New function.
* share/txr/stdlib/param.tl (param-info): New struct. This
presents information about a global function in a similar way
to param-parser, using some of the same fields. With this
object we can check the call to a lexical function or global
function in a uniform way, using the same code.
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (compiler comp-apply-call): The
conditions for constant-folding a call expressions are too
weak. The first argument could be a quoted symbol, which is a
constant expression, and so we end up wrongly evaluating
an expression like (call 'print '3) at compile time.
We can constant-fold if the first expression evaluates to a
symbol, which names a constant-foldable function, or else
if it evaluates to something which is not a bindable symbol.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Bumped.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ifq tN t0 label0 ifq tN t0 label1
... ...
label0: --> ...
if tN label2
label1: label1:
... ...
* share/txr/stdlib/optimize.tl (basic-blocks
thread-jumps-block): Implement case. There are there are 56
"hits" for this in the standard library.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The float type promotes to double when passed as
a variadic argument.
This patch adds internal FFI types which models that
promotion. It uses double for its C type, while still
performing the range checks for float.
Also, the types be-float and le-float are rejected from
being variadic arguments.
* share/txr/stdlib/ffi.tl (analyze-argtypes): Rewrite
function, adding validation and substitution for the
variadic part of the argument type list. Map float type to
double, and reject be-float and le-float.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When a jmp instruction is replaced by the end instruction
that it jumps to, or possibly by a two-instruction sequence
ending in end, there can be more opportunities to optimize.
For instance, the second reduction in a sequence like this:
mov t3, t5 mov t3, t5
jmp label --> end t3 --> end t5
...
label:
end t3
* share/txr/stdlib/optimize.tl (basic-blocks peephole-block):
If the end-propagation is done, we change the linkage of the
current block to indicate that it has no next blocks. We
add it to the rescan list and set the recalc flag so the
liveness information is updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
If a function has nothing but parameters that are not captured
in lexical closures, they can be converted registers. The
function then doesn't need a variable frame for its
parameters. This is similar to the eliminate-frame
optimization, and borrows the same code and logic.
* share/txr/stdlib/compiler.tl (compiler eliminate-frame): We
no longer assume that the code coming in starts with a frame
instruction we can eliminate using (cdr code) and an end
insruction we can eliminate with a trailing pattern.
This is because when this function is used for a lambda, this
is not the case; a lambda's variable frame is implicit,
created by the VM for any lambda with a nonzero frame size,
rather than by a frame instruction.
(compiler comp-let): In the call to eliminate-frame, we now
trim away the first and last instruction, to get rid of
the (frame ...) and (end ...).
(compiler comp-lambda-impl): Install a closure spy against the
variable frame to detect which variables are captured in
closures, similarly to in comp-let. Under the right
conditions, pass the code through eliminate-frame to turn
the variables into registers. The close instruction has to be
rewritten, because the frame size is now zero, and the number
of t registers has changed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We have the situation that there are effectively two kinds of
spies: let constructs plant spies only in order to learn about
what variables are being captured, whereas lambdas plant spies
in order to intercept variable accesses (and to inform the
spies that are interested in what is captured). Let us split
these up into two separate types, with different methods,
in different stacks.
* share/txr/stdlib/compiler.tl (struct var-spy): Renamed to
closure-spy.
(var-spy accessed, var-spy assigned): Methods removed: the
closure-spy type has only the captured method.
(struct capture-var-spy): Renamed to accesss-spy.
(capture-var-spy var-spies): Renamed to access-spy
closure-spies.
(capture-var-spy captured): Method removed; the access spy is
doesn't receive captured calls.
(struct compiler): Slot var-spies removed, replaced with
closure-spies and access-spies.
(with-var-spy): Macro removed.
(with-spy): New function.
(with-closure-spy, with-access-spy): New macros.
(compiler push-var-spy, compiler pop-var-spy): Methods
removed.
(compiler push-closure-spy, compiler pop-closure-spy,
compiler push-access-spy, compiler pop-access-spy): New
methods.
(compiler comp-var, compiler comp-setq, compiler
comp-lisp1-setq, compiler comp-lisp1-value): Walk new
access-spies list rather than var-spies to report about
accesses and assignments.
(compiler comp-let): Use with-closure-spy macro rather than
with var-spy. The spy object is now a closure-spy type,
and the variable is cspy rather than vspy.
(compiler comp-lambda-impl): Use with-access-spy instead of
with-var-spy. The spy object is now of type access-spy.
It refers to the current me.closure-spies from the compiler.
|
|
|
|
|
|
|
|
|
|
|
| |
The var-spy structure is only being used for detecting
captured variables, not assigned or accessed variables.
So the information about accessed and assigned is being
wastefully accumulated, never used.
* share/txr/stdlib/compiler.tl (struct var-spy): Remove slots
acc-vars and set-vars.
(var-spy accessed, var-spy assigned): Methods become no-ops.
|