| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/asm.tl (oc-base backpatch, (backpatch-low-16
backpatch, backpatch-high16 backpatch, op-label (asm, dis),
op-noop dis, op-frame dis, op-end dis, op-movrs dis,
op-movsr dis, op-movrr dis, op-jmp (backpatch,dis),
op-if (backpatch, dis), op-ifq backpatch, op-block backpatch,
op-retsr dis, op-retrs dis, op-retrr dis,
op-catch (backpatch, dis), op-handle dis, op-getv dis,
op-setv dis, op-close (backpatch, dis), op-getlx dis,
op-setlx dis): Suppress warnings about unused variables
using ignore and other approaches.
(assembler dis-listing): The unused stream parameter here
is a real bug: it was intended to be the output destination,
rather than standard output being hard-coded.
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/compiler.tl (compiler (comp-atom, comp-dwim),
safe-const-reduce, igno-notfound): Use ignore
rather than use for marking unused variable.
* stdlib/copy-file.tl (copy-files, copy-path-rec,
remove-path-rec, chmod-rec, chown-rec): Likewise.
* stdlib/optimize.tl (basic-block print): Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We want the ignore function to go away; but if variables
are mentioned, to suppress unused warnings on them.
* stdlib/compiler.tl (%functional-funs%): Remove nilf
from list since we are handling it specially.
(compiler comp-fun-form): Recognize (ignore ...)
and (nilf ...) forms, transforming
them into (progn .... nil). In the case of ignore,
walk the arguments: if any look like variables, mark
them used.
Also, add the use function to the pattern which handles
identity, since it is a synonym.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This will be an official mechanism for indicating
deliberately unused variables.
* eval.c (eval_init): Register ignore intrinsic,
binding to the same function object as nilf.
* stdlib/compiler.tl (%const-foldable-funs%): Mention
ignore function, next to its nilf synonym.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
| |
* stdlib/copy-file.tl (copy-files, copy-path-rec,
remove-path-rec, chmod-rec, chown-rec): Fix instances
of unused parameters.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/optimizer.tl (basic-block print): Suppress
warning for pretty-p parameter using the use function.
(basic-blocks (local-liveness, calc-liveness,
thread-jumps-block, peephole-block, late-peephole,
fill-treg-compacting-map), (basic-block
apply-treg-compacting-map), dedup-labels): Fix
unused variables in pattern, mostly by replacing
them by @nil.
(basic-blocks check-bypass-empty): Method moved,
turned into (basic-block check-bypass-empty),
losing the unused basic-blocks parameter.
(basic-blocks elim-next-jump): Likewise moved
into basic-block class.
(basic-blocks elim-dead-code): Calls to check-bypass-empty
and elim-next-jump adjusted.
|
|
|
|
|
|
|
|
|
|
|
| |
This was uncovered by unused variable warnings.
* stdlib/optimize.tl (basic-blocks peephole-block):
The pattern trying to detect wasteful register moves
is incorrect; the reg1 term is intended to be the
@reg1 variable. It is matched literally and so will
not match because the symbol reg1 does not literally
occur in the VM code.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Now that we have the t convention in macro parameters,
we can use it to suppress many cases of unused variables
in the compiler.
* stdlib/compiler.tl (compiler (comp-setq, comp-lisp1-setq,
comp-setqf, comp-cond, comp-ift, comp-switch,
comp-unwind-protect, comp-return, comp-handler-bind,
comp-catch, eliminate-frame, comp-lambda-impl,
comp-fun, comp-or, comp-prog1, comp-arith-form,
comp-arith-neg-form, comp-fun-form, comp-apply-call,
comp-for, comp-tree-bind, comp-mac-param-bind,
comp-mac-env-param-bind, comp-tree-case, comp-lisp1-value,
comp-dwim, comp-prof, comp-load-time-lit), expand-quasi-mods,
expand-dohash, expand-each, expand-defvar, expand-defun,
expand-defmacro, expand-defsymacro, lambda-apply-transform,
usr:compile): Fix unused variable warnings mostly by using
the t mechanism in tree-case or mac-param-bind. In
some cases, (use var) is used where it would be detrimental
to diagnostic quality to replace identifiers in the
pattern with t. A few unused "else" variables were renamed
and used.
(safe-const-reduce, ign-notfound): Fix unused exception
clause unused parameters using (use param).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (expand_params_rec, bind_macro_params): Handle t
specially everywhere a parameter can occur. Expansion
allows the syntax through without extending the
environment with a t variable; binding walks over
the structure without binding a variable.
* stdlib/compiler.tl (expand-bind-mac-params): Likewise,
handle occurrences of t, suppressing the generation of
and assignment to variables, while ensuring that
initializing expressions are evaluated.
* tests/011/tree-bind.tl: New file.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We fix numerous unused variable situations uncovered
by the new diagnostic. Most of those occurring inside
tree-bind or mac-param-bind forms remain unfixed.
These are caused by the idiom of binding a dummy variable
as a placeholder in the structure. I am instead going to
introduce a mechanism into tree-bind/mac-param-bind
for indicating an ignored piece of structure.
* stdlib/compiler.tl (compiler (comp-if, eliminate-frame,
comp-lambda-impl, comp-typep, comp-fun-form, expand-and,
reduce-or, compiler-emit-warnings, usr:compile
with-compile-opts): Eliminate unused variables in structural
pattern matches in various ways: eliminating predicate
argument variables, replacing place holder variables by
@nil, or just using the variables when possible.
(compiler compile-in-toplevel): Remove unused saved-nlev variable.
(compiler comp-atom): Use (use oreg) form to suppress
unused parameter warning.
(compiler comp-return-form): Eliminate unused binfo variable.
The lookup-block method is called for the side effect of
marking the block used, so we keep that call.
(compiler comp-let): Unused variable specials is gone.
(compiler comp-or): Unused variable lastfrag is gone,
as is the assignment to it. There is a reason assignment
isn't use!
(compiler comp-inline-lambda): Get rid of the two variables
called dummy by folding the associated calculation into
an adjacent initform using progn and prog1.
(comp-tree-case): Remove unused ncases, lerrtest and lnext
variables.
(safe-const-eval): Remove unused reduced-form variable,
and simplify code, eliminating another local.
|
|
|
|
|
| |
* stdlib/compiler.tl (opt-controlled-diag): If a the compiler
option's value is t, treat it as :warn.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Unused variables in tree-bind forms are not generating
diagnostics with source location info. We are missing
some rlcp calls.
* stdlib/compiler.tl (compiler comp-catch): The generated
lambda here ends up transformed to a let by the
lambda-apply-transfom function. We must propagate source
info to it, otherwise unused catch clause parameters
get diagnosed without it.
(compiler (comp-for, comp-mac-param-bind,
comp-mac-env-param-bind, comp-tree-case): Confer source
location info onto the err-form argument of
expand-bind-mac-params.
(expand-bind-mac-params): Pass source location info
from err-form onto the generated let* form.
Thus, diagnostics related to variables in that let*
get reported against that form's location.
(lambda-apply-transform): Pass source location info
from the lambda expression to the generated let.
* stdlib/except.tl (usr:catch): Pass source loc info
from each clause source code to the transformed
clause. The transformed clause will turn into a lambda
which will turn into a let in comp-catch, and then
into a let in lambda-apply-transform.
|
|
|
|
|
| |
* stdlib/constfun.tl (%const-foldable-funs%): use is a synonym
of identity, which is listed; now use is also listed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autoload.c (compiler_set_entries): Register slot symbol
"unused".
* stdlib/compiler.tl (compile-opts): New slot, unused.
(%warning-syms%): List unused symbol.
(env lookup-var): Support optional mark-used parameter,
just like lookup-fun.
(env unused-check): New method.
(compiler comp-var): Pass t to mark-used parameter of
lookup-var to register the use.
(compiler (comp-let, comp-var)): Call unused-check
method after sub-compilations are done to dump
diagnostics about unused variables.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Introducing a compiler options system, so we can
control diagnostics and such. We begin with
three options for diagnosing shadowing.
* autoload.c (compiler_set_entries): Register a
structure name compiler-opts, a with-compile-opts
function name, *compile-opts* variable name, and
slots shadow-fun, shadow-var and shadow-cross.
* stdlib/compiler.tl (compile-opts): New struct.
(%warning-syms%): New macro.
(*compile-opts*): New special variable.
(when-opt, with-compile-opts): New macros.
(opt-controlled-diag): New function.
(env extend-var): Call extend-var* method instead of
repeating code.
(env extend-var*): Implement shadow-var and shadow-cross
diagnostic options.
(env extend-fun): Implement shadow-fun and shadow-cross
diagnostic options.
|
|
|
|
|
|
| |
* stdlib/quips.tl (%quips%): New entry: what if we apply
the concept of channel separation to audiophiles who
hate each other's guts?
|
|
|
|
| |
* stdlib/quips.tl (%quips%): New entry.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* txr.1: The functions -, + and * are documented together,
but the section heading only mentions + and -.
This was introduced when these functions were documented
for the first time in March 2012, in commit
6363875356bc050ef81d40553e573fc47aca2e28, and
then went unnoticed for almost eleven years in spite
of the heading undergoing relocation and reformatting.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h,
args.c, args.h, arith.c, arith.h, autoload.c, autoload.h,
buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h,
chksums/crc32.c, chksums/crc32.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, gzio.c,
gzio.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S,
lex.yy.c.shipped, lib.c, lib.h, linenoise/linenoise.c,
linenoise/linenoise.h, match.c, match.h, parser.c, parser.h,
parser.l, parser.y, protsym.c, psquare.h, rand.c, rand.h,
regex.c, regex.h, signal.c, signal.h, socket.c, socket.h,
stdlib/arith-each.tl, stdlib/asm.tl, stdlib/awk.tl,
stdlib/build.tl, stdlib/cadr.tl, stdlib/compiler.tl,
stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl,
stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl,
stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl,
stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl,
stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.tl,
stdlib/match.tl, stdlib/op.tl, stdlib/optimize.tl,
stdlib/package.tl, stdlib/param.tl, stdlib/path-test.tl,
stdlib/pic.tl, stdlib/place.tl, stdlib/pmac.tl,
stdlib/quips.tl, stdlib/save-exe.tl, stdlib/socket.tl,
stdlib/stream-wrap.tl, stdlib/struct.tl, stdlib/tagbody.tl,
stdlib/termios.tl, stdlib/trace.tl, stdlib/txr-case.tl,
stdlib/type.tl, stdlib/vm-param.tl, stdlib/with-resources.tl,
stdlib/with-stream.tl, stdlib/yield.tl, stream.c, stream.h,
struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h,
syslog.c, syslog.h, termios.c, termios.h, time.c, time.h,
tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h,
utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr,
y.tab.c.shipped: Copyright year bumped to 2023.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
* txr.vim, tl.vim: Regenerated.
* protsym.c: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The res variable captures the specific value of the
condition expression, making it available to the action.
* autoload.c (awk_set_entries): Intern the res symbol
* stdlib/awk.tl (awk): Instead of generating the condition-action
into a simple when, we use whenlet to also bind the res variable.
* tests/015/awk-res.tl: New file.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
| |
* txr.1: *define-struct-prelude* should of course be
define-struct-prelude.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
| |
* stdlib/quips.tl (%quips%): New one about personality.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When an invalid call expression is constant folded, such
as (call 'abs 1 2), runaway recursion occurs. This is
because due to the wrong number of arguments being passed
to abs, the safe-const-reduce function returns the
expression unmodified. The comp-apply-call method then
passes it to compile, wrongly assuming a reduction had
taken place, and so everything repeats.
* stdlib/compiler.tl (comp-apply-call): Detect when
safe-const-reduce has hit a fixed point by returning
the input form. In that case, we don't call the compiler
top-level entry point, but the comp-fun-form method
directly; the wrong function call will be compiled without
constant folding and throw an error at run-time.
|
|
|
|
|
|
|
|
| |
* stdlib/constfun.tl (%const-foldable-syms%): Removing
the following functions, which cannot be constant folded
because maybe are relied upon to produce fresh objects:
cons, sub-list, conses, ldiff, uniq, tostring, tostringp,
join, join-with.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When a global variable v is wrapped with (read-once v),
multiple accesses to the place still generate
multiple accesses of the global through getv or getlx
instructions. The reason is that the alet and slet
macros optimize away a temporary bound to the value of
a variable regardless of whether the variable is lexical.
Let's fix that.
* stdlib/place.tl (slet, alet): Replace the bindable test
with lexical-var-p, in the given environment. A binding
to a variable is only alias-like if the variable is
lexical, otherwise we need a real temporary.
* tests/012/struct.tl (get-current-menv): New macro.
(menv): New global variable. Fix a number of tests which
use expand, whose expansion has changed because the
expressions refer to free variables. We introduce an
environment parameter which binds all the variables, so
that the optimized expansion is produced, as before.
* txr.1: Updated documentation. slet gets examples.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A struct prelude definition associates one or more
future defstruct (by struct name) with clauses which
are implicitly inserted into the defstruct.
It is purely a macro-time construct, customizing the
expansion behavior of defstruct.
* stdlib/struct.tl (*struct-prelude, *struct-prelude-alists*):
New special variables holding hash tables.
(defstruct): Before processing slot-specs, augment it with
the contents of the prelude definitions associated with
this struct name.
(define-struct-prelude): New macro.
* autoload.c (struct_set_entries): define-struct-prelude
is interned and triggers autoload of struct module.
* tests/012/oop-prelude.tl: New file.
* tests/012/oop-prelude.expected: Likewise.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/compiler.tl (comp-catch): Under an optimization level
of at least 1, if no symbols are being caught, or if the
try expression is a safe constant expression, then just
compile the try expression. Furthermore, if there is only one
exception symbol being caught, and a catch clause is for a
subtype of that symbol, we eliminate the run-time
exception-subtype-p test. This will always be true if the catch
macros are being used, because the list of symbols is derived
from the clauses. Lastly, if there is only one exception symbol
being caught, any clause which doesn't match that symbol is
now eliminated as dead code. That shouldn't happen unless
the sys:catch operator is used directly.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The :inherit clause allows custom struct clauses to
inject inherited bases.
* stdlib/struct.tl (defstruct): Recognize :inherit clause,
adding symbol arguments to extra list of supers that
get appended to the list coming from defstruct's
seconda rgument.
(define-struct-clause): Disallow :inherit clause name.
* tests/012/oop-dsc.tl: New tests.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date. Also mention that separator
commas in integer tokens are new in 283 and have a different
interpretation in older versions.
* txr.vim, tl.vim: Regenerated.
* protsym.c: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/struct.tl (macroexpand-struct-clause): New function.
* autoload.c (struct_set_entries): Autoload struct module
on macroexpand-struct-clause.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/match.tl (macroexpand-match): New function.
* autoload.c (match_set_entries): Autoload match
module on macroexpand-match.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/place.tl (sys:pl-expand): Function renamed to
macroexpand-place; env parameter becomes optional.
(macroexpand-1-place): New function.
(place-form-p, call-update-expander, call-clobber-expander,
call-delete-expander): Follow rename.
* autoload.c (place_set_entries): Register symbols
macroexpand-place and macroexpand-1-place for autoload.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/pmac.tl (macroexpand-params): New function,
implemented using newly exposed sys:expand-param-macro.
* autoload.c (pmac_set_entries): Trigger pmac.tl autload
on macroexpand-params symbol.
* eval.c (eval_init): Register existing expand_param_macro
function as sys:expand-param-macro.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/struct.tl (:delegate): Handle the two-element
form of the optional parameter, which specifies the
usual initializing expression for the default value.
This is just passed through as-is to the generated
method. Diagnose if the three-element form occurs.
* tests/012/oop.tl: Some new tests.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (standard_k, print_json_format_s):
New symbol variables.
(stream_init): New variables initialized.
* stream.h (enum json_fmt): New enum.
(standard_k, print_json_format_s): Declared.
* lib.c (out_json_rec): Take enum json_fmt param,
and pass it recursively. Printing for vector and
dictionaries reacts to argument value.
(out_json, put_json): Examine value of special
var *print-json-format* and calculate enum json_fmt
value from this. Pass to out_json_rec.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (inc_indent_abs): New function.
(stream_init): inc-init-abs intrinsic registered.
* stream.h (inc_indent_abs): Declared.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
| |
* stdlib/quips.tl (%quips%): New entry.
|
|
|
|
|
|
|
|
| |
* stdlib/struct.tl (defstruct): Don't generate a separate finalizer
registration for each :fini or :postfini; roll them into a single
lambda in the correct order. Their object argument turns into a
let block around each piece of code to bind that argument, like
had been done for :init and :postinit.
|
|
|
|
|
|
|
|
| |
* stdlib/struct.tl (defstruct): When an :init, :fini,
:postinit or :postfini has an empty body, do not push
it onto its corresponding list. Then later we don't
have to check for empty items when generating the code;
we know only non-empty items are on the lists.
|
|
|
|
|
|
|
| |
* stdlib/struct.tl (define-struct-clause): Disallow
the :postfini keyword as clause name.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The motivation is that struct clause macros defined
using define-struct-clause may want to introduce
their own initializers and finalizers for the specific
stuff they add to the struct. The uniqueness restrictions
on these initializing and finalizing clauses makes
it impossible to use two clause macros which both want
to inject a definition of the same initializer or finalizer
type.
* stdlib/struct.tl (defstruct): Don't enforce that there
be at most one clause in the category of :init,
:postinit, :fini or :postini. Multiple are allowed.
They all execute left-to-right except for :fini.
* tests/012/fini.tl: New tests.
* tests/012/fini.expected: Updated.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (pct_fun_s): New symbol variable, holding
the usr:%fun% symbol.
(fun_macro_env): New static function.
(do_expand): For defun and defmacro, use fun_macro_env
to establish an environment binding the %fun% symbol
macro, and expand everything in that environment.
(eval_init): Intern the %fun% symbol, initializing
pct_fun_s, and also register a global symbol macro in
that name so that we can freely use %fun% everywhere
without worrying that the code will blow up.
E.g. a logging macro can use it to get the function name,
but still be useful in a top-level form outside of
a named function.
* stdlib/struct.tl (sys:meth-lambda): New macro.
(defstruct, defmeth): Use sys:meth-lambda as a replacement
for lambda to set up the %fun% symbol macro. In the :init
case which doesn't use a lambda, an open-coded symacrolet
does the job.
* tests/019/pct-fun.tl: New file.
* tests/019/pct-fun.expected: Likewise.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* socket.c (sock_set_entries): Intern str-addr symbol.
There is no autoload on this because the struct types of
which this is a method don't exist if the socket
module has not been loaded.
* stdlib/socket.tl ((sockaddr-in str-addr), (sockaddr-in6
str-addr), (sockaddr-un str-addr)): New methods.
* tests/014/str-addr.tl: New file. This provides
coverage not just for the str-addr method, but the
hitherto untested address to text functions.
This is why the bug was found, that was addressed
in the previous commit. The test case which produces
"8000::1" was actually producing "800:1".
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/socket.c (sys:in6addr-condensed-text): The
regular expression used in calculating zr is incorrect;
the zero in it can match the trailing zero of
a nonzero quad, when the intent is only to match
zero quads. Hack: we represent zero quads by the
character Z and use that for the matching and removal
of the longest range of zero quads. Then we filter
the Z back to 0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This function "intelligently" constructs an
address object of the right type from a string.
* socket.c (sock_set_entries): Autoload socket.tl
on sockaddr-str function being accessed.
* stdlib/socket.tl (sockaddr-str): New function.
* tests/014/sockaddr-str.tl: New file.
* txr.1: Documented.
* stdlib.doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The :postfini clause registers a finalizer that runs in the
ordinary order: after previously registered ones. This has
the effect of allowing a derived structure to run clean-up
actions after those of inherited structures. Either order
can be useful because the dependencies between base and
derived can go in either direction. It's a huge mistake in
C++ that it supports only derived-first destructor invocation
order.
* stdlib/struct.tl (defstruct): Recognize and translate
:postfini clause. It's exactly like :fini but omits the
t parameter in the finalize call, registering in the
natural order.
* tests/012/fini.tl (derived): Add :postfini handler.
* tests/012/fini.expected: Updated to reflect the messages
coming from the postfini handler, which are happening
in the correct order.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The bad situation reproduced as a miscompilation of some prof
forms at *opt-level* 5 or above.
The basic idea is that there is a situation like this
prof t2
... profiled code here producing value in t8
mov t2 t8
end t2
end t2
The code block produces a value in t8, which is copied into
t2, and executes the end instruction. This instruction does not
fall through to the next one but passes control back to the
prof instruction. The prof instruction then stores the result
value, which came from t2, back into the t2 register and
resumes the program at the end t2.
The first bad thing that happens is that the end instructions
get merged together into one basic block. The optimizer then
treats them without regard for the prof instruction, as if
they were a linear sequence. It looks like the register move
mov t2 t8
is wasteful and so it eliminates it, rewriting the end instruction
to:
end t8
end t8
Of course, the second instruction is now wrong because prof is
still producing the result in t2.
To fix this without changing the instruction set, I'm introducing
another pseudo-op that represents end, called xend. This is
similar to jend, except that jend is regarded as an unconditional
branch whereas xend isn't. The special thing about xend is
that a basic block in which it occcurs is marked as non-joinable.
It will not be joined with the following basic block.
* stdlib/asm.tl (xend): New alias opcode for end.
* stdlib/compiler.tl (comp-prof): Use xend to end prof fragment,
rather than plain end.
* stdlib/optimize.tl (basic-block): New slot, nojoin.
If true, block cannot be joined with next one.
(basic-blocks jump-ops): Add xend to list of jump ops,
so that a basic block will terminate on xend.
(basic-blocks link-graph): Set the nojoin flag on a
basic block which contains (and thus ends with) xend.
(basic-blocks local-liveness): Add xend to the case
in def-ref that handles end.
(basic-blocks (peephole, join-blocks)): Refuse to join
blocks marked nojoin.
* tests/019/comp-bugs.tl: New file with miscompiled
test case that was returning 42 instead of (42 0 0 0)
as a result of the wrong register's value being returned.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The scoping is not behind handled correctly for optional
variables. The init-forms are being evaluated in a scope
in which all the variables are already visible, instead
of sequentially. Thus, for instance, variable rebinding
doesn't work, as in (lambda (: (x x)) ...). When the
argument is missing, x ends up with the value : because
the expression refers to the new x, rather than the
outer x.
* stdlib/compiler.tl (compiler comp-lambda-impl):
Perform the compilation of the init-forms earlier.
Use the same new trick that is used for let*:
the target for the code fragment is a locaton obtained
from get-loc, which is then attached to a variable
afterward. The spec-sub helper is extended with a loc
parameter to help with this case.
* tests/012/lambda.tl: New test case that fails without
this fix.
|