[plt-scheme] Updated version of no-brainer tool available to detect unused bindings

From: John Clements (clements at brinckerhoff.org)
Date: Mon Sep 8 14:27:06 EDT 2003

More foolish errors on my part prompted me to update my tiny static 
checker, 'no-brainer.plt'.

In particular, no-brainer now detects unused bindings, helping you to 
identify another category of stupid programming errors.

Also, the output format has improved (slightly) to supply source 
positions for the errors that it detects.

No-Brainer is a free download for DrScheme from 
<http://www.cs.utah.edu/plt/develop/>

As always, I would be glad for any feedback.

john clements


Here's the text of No-Brainer's doc.txt:



The _No-Brainer_ Tool

The No-Brainer Tool, performs a static check for arity errors
and unused bindings on the program in the definitions window.

ARITY ERRORS

No-Brainer operates on any sequence of top-level definitions, but
makes a weak soundness claim ONLY for code contained in top-level
module expressions.

No-Brainer makes the following soundness-like claim: if No-Brainer
identifies a piece of code as containing an arity error, then that code 
(if
evaluated) will raise an exception[*].

No-Brainer makes no specific completeness-like claim. No-Brainer makes
two passes; the first to associate identifiers with arity
specifications, the second to identify arity errors.  No-Brainer will
correctly associate lambda expressions with definitions (both lexical
and top-level) when the lambda expression is directly contained by the
definition or is the only possible evaluation result of the expression
directly contained in the definition.  Any mutation of the identifier
causes No-Brainer to remove this identifier from its table (and hence
to make no claims about its applications).  No-Brainer will identify
arity errors only in applications where the function position is
directly an identifier.

UNUSED BINDINGS

No-Brainer also reports unused bindings in the user's program. In
particular, No-Brainer reports an error for each let, letrec, or
lambda which meets the following criteria:

1. It binds an identifier which is not referred to anywhere in
that identifier's scope.
2. The unused identifier has a source position.

The second of these is intended to filter out bindings introduced
by macro expansion, as these are less likely to be errors in
the user's program.  Note that the position check is applied to
the identifier, and not to the let, letrec, or lambda, so that
macro-based special forms which bind identifiers specified by
the user will be treated like ordinary binding forms.

Since unused bindings are less likely to be errors than arity
mismatches, they are reported in a later section of the output.
Also, since unused lambda bindings are less likely to be errors
than unused let/rec bindings, the unused bindings error messages
are separated into these two categories

USING THE TOOL

To use No-Brainer, simply click the "No Brain" button.  No-Brainer
will print a series of errors detected, and will finish by displaying
"all done."  All output is confined to a window entitled "Here's
what's wrong with your stupid program."  Users are encouraged not to
be insulted by this mildly provocative and preliminary window title.

The user's interface to no-brainer is primitive, in that references to
source-code positions are accomplished by mzscheme's native format
ability to represent syntax objects.  That is, a syntax object which
refers to line and line position within the current file will be
printed so as to reveal that information.

Example:

...
bindings (end-selection) (from (#<syntax:2487:22>)) unused in 
expression #<syntax:2484:14>
...

RUNNING TIME

No-Brainer makes two passes over the code, and visits each expression 
once
during each pass. In theory, it could be quadratic in running time, as 
it must
perform a set-union operation on lists of identifiers at each step, but 
this
should never dominate the running time.  No-Brainer is observed to take
roughly ten seconds on files of roughly two thousand lines.

Useful? You decide.

[*] Note that the exception may not be an arity error, but instead
an undefined/uninitialized error. This can happen because the 
application
precedes the definition, or because the evaluation of the definition
raised an exception.
  



Posted on the users mailing list.