lint - Program Flow Analyzer
When you are debugging a script, just use lint instead of load
require 'debug/lint' lint 'myscript.ijs'
lint loads a script and then checks it for common errors.
Your script appears in a window like this:
lint detects the following common blunders:
- explicit definitions lacking trailing )
- undefined names, including names defined in all paths through control structures
- verbs used with invalid valences
- non-noun results at the end of condition blocks and verbs
- syntax errors
- sentences with no effect on execution (e.g. a sentence containing only verb verb).
What lint does
lint first loads the script, then extracts the explicit definitions and examines them one by one.
- Each definition is examined in the locale it's defined in
- Each line of the definition is executed in "safe mode" where verbs that have side effects, such as file operations, are not performed.
- Preassigned global variables are available to the execution, including variables assigned when the script was loaded or defined by other scripts.
- All assignments are simulated without changing the global environment.
Structuring your program for lint
- If a verb uses global variables defined in another verb, the dependent verb should follow the defining verb in the script
- Any verb named create or whose name ends with _run will automatically have its globals made available to subsequent definition
- Other verbs can use the NB.?lintsaveglobals directive to publish their global assignments for use by subsequent verbs
- Any changes to the locale must be made using the concurrent or coclass verbs. The starting locale is base.
- Conditions that are meant always to test true should be left empty. This will produce better flow analysis.
In other words, write
while. do. rather than while. 1 do.
elseif. do. rather than elseif. 1 do. in the last prong of a conditional
Lint directives are comments beginning with NB.?lint These give additional control of the checking and may appear anywhere inside an explicit definition.
Lint directives NB.?lintmsgsoff suppresses display of messages starting with the next line NB.?lintmsgson resumes display of messages starting with the next line NB.?lintonly sentence Executes sentence (in safe mode) during checking. This is useful to establish a valid value for a name during checking, to avoid a syntax error. NB.?lintsaveglobals Any global names that have been set by the current definition will be added to a list of such names that is passed in to later definitions. Use this when one verb is known to be executed before others, and creates globals that the later verbs depend on. Use in concert with NB.?lintonly to solve other problems of initialization. Note that the definitions are the ones in effect when the directive is scanned. NB.?lintloopbodyalways in the B block of for. or while., indicates that the loop body is always executed NB.?lintformnames formname the formname must be a form; variables are defined for each control that creates a name when an event is called (these variables are: controlname (the name of the control itself), controlname_select for selection controls, and controlname_scroll for scrolling controls). The names are defined with typical values if those can be found, otherwise with unknown values.
lint and form event handlers
If you conform to J's form-naming convention, lint will understand your event handlers with no prompting.
You define a form with a noun such as
GFORM =: 0 : 0 pc gform; minwh 10 10;cc name edit; <...other form definition...> )
and then you use it by writing
The key requirement is that the name of the form-definition script is an uppercase version of the name of the form on the pc command.
Events handlers for the form formname all look like
- formname is the name of the form (gform in the example above)
- childname is the name of a child control (name in the example above)
- eventname is the name of an event appropriate for that child control, such as button or select
Any verb whose name suggests it is an event handler will start off with all the form variables initialized. These are the variables described above by NB.?lintformnames, plus sysdata and sysmodifiers which are assigned suitable values based on the name of the event handler.
The x argument to lint controls whether the error messages appear in the result of lint. The default, 0, returns an empty table of messages if a grid is displayed. x=1 causes a table of error line and error text to be returned.
Using Lint from a PF key
In J6.02, pressing Ctrl+1 in a window runs lint on the file in that window.
In J8.03 or later, you can cause a PF key to run lint on the current window by including the following line into the Edit>Configure>User Keys window:
Here F4 is the key selected for Lint.