The static code analyzer
Yacas has some tools to assess the quality of the scripts.
The code checking tools are never finished, as new bugs
are found, and guards against them added.
The idea behind the static code checkers is to check that
coding standards are upheld, and to mark code that is dangerous
and thus is likely to be buggy.
The following sections each describe one specific type of test.
The static code analysis code can be found in codecheck.rep .
Interface check
As described in an essay elsewhere, files should be careful with
what they expose to the environment. the def file mechanism
and the LocalSymbols routine should be used for this. The
interface check verifies that no global resources are accidentally
The rules that should be upheld are:
- global variables should not be accessible to the outside
world. They should be made local to the module by using LocalSymbols.
- functions can be global, exposed to the outside world,
iff they are declared in the corresponding def file. Otherwise,
they should be made local to the module with LocalSymbols.
- files should not be loaded with Load or Use,
explicitly. Rather, the module should depend on the system automatically
loading the right file through the def file mechanism.
- scripts in the standard library should just contain simple
function definitions, transformation rules, and initializations of
global variables local to that module.
The interface check also assumes the code to consist of simple
function definitions. It is meant to be used for the scripts in the
standard scripts library. Exposing functionality to the outside
world is usually less of a problem in one-off scripts to do
specific calculations, for instance.
General rules
The following rules are general guide lines.
- the static code analyzer should be able to recognize,
when possible, if variables or functions are defined but not used.
- functions or variables that are not declared anywhere
should be reported, as it might be a typing error. Yacas evaluation just
skips the function call, or lets the variable evaluate to itself.
- platform-specific code is not allowed, in general, and thus
use of SystemCall or PlatformOS or related variables or functions
should be reported.
- macro-like functions with local variables, which use
Eval, or Map or related functions that re-evaluate an expression,
should be flagged if the variables are not made unique through
LocalSymbols.
- the tools could discover if a variable is masked by another
local variable with the same name.
Transformation rule checks
- ideally there should be a way to determine that type
changes are made. For instance, 0*{a,b,c} should return
a list, {0,0,0} , and not zero.
- rules that are completely masked by other rules, and
can never be reached, should be flagged.
- rules with the same precedence, but which are ambiguous,
should be reported, as the order in which they are tried might have
impact on the result of application of the transformation rules.
- some form of type checking might be possible, by declaring
input types of various functions, and then examining the surrounding
code to detect when incorrect types might be passed in. It seems to happen
a lot that functions don't verify their input.
Coverage checks
Next to checking if functions are declared in the associated
def file, the analyzer could also detect if:
- there is no test code for the function
- there is no or incorrect documentation for the function