The No-Brainer Tool

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.


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.


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


To use No-Brainer, simply click the "No Brain" button.  No-Brainer
will print a series of errors detected.  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.


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


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.