Feature/unused vars (#1)
* TypeChecker - Adding new chapter `Variable referencing counting` * TypeChecker - Added missing method table - Added code usage * Markdown transform - Updated * Configuration - Documented `typecheck:warnUnusedVars` * Command line - Added compiler flags documentation * MK - Built * Command line - Formatting fixed * MK - Built
This commit is contained in:
parent
99c10d4953
commit
be9ed17d99
|
@ -207,3 +207,68 @@ This is a sanity check, as if the type coercion failed then an exception
|
|||
would be thrown and the assertion would not be reached, however if the
|
||||
types were an exact match **or** if they were not but could be coerced
|
||||
as such then the two types should match.
|
||||
|
||||
### Variable referencing counting
|
||||
|
||||
Firstly let me make it clear that this has nothing to do with
|
||||
**runtime** reference counting but rather a simple mechanism used to
|
||||
maintain a count or *number of* references to variables after their
|
||||
declaration.
|
||||
|
||||
Below is a method table of the methods of concern:
|
||||
|
||||
| Method | Description | Return |
|
||||
|------------------------|-----------------------------------------------------------------------------------------------|--------------|
|
||||
| `touch(Variable)` | Increments the count by 1 for the given variable, creates a mapping if one does not yet exist | `void` |
|
||||
| `getUnusedVariables()` | Returns an array of all `Variable`s which have a reference count above `1` | `Variable[]` |
|
||||
|
||||
This aids us in implementing a single feature *unused variable
|
||||
detection*. It’s rather simple, reference counts are incremented by
|
||||
using a `touch(Variable)` method defined in the `TypeChecker` and this
|
||||
is called whilst doing dependency generation in the dependency
|
||||
generator.
|
||||
|
||||
The first time a variable is encountered, such as even its declaration,
|
||||
we will then `touch(...)`-it. At the end of type checking we then call
|
||||
the `getUnusedVariables()` method which returns a list of the undeclared
|
||||
variables. These are variables with a reference count higher than `1`.
|
||||
We then print these out so the user can see which are unused.
|
||||
|
||||
#### Usage
|
||||
|
||||
Example usage below shows us `touch`-ing a variable when we process them
|
||||
in expressions such as a `VariableExpression` in the dependency module:
|
||||
|
||||
``` d
|
||||
...
|
||||
|
||||
/* Get the entity as a Variable */
|
||||
Variable variable = cast(Variable)namedEntity;
|
||||
|
||||
/* Variable reference count must increase */
|
||||
tc.touch(variable);
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
We then, after typechecking, run the following in the type checker
|
||||
module’s `doPostChecks()` method:
|
||||
|
||||
``` d
|
||||
/**
|
||||
* Find the variables which were declared but never used
|
||||
*/
|
||||
if(this.config.hasConfig("typecheck:warnUnusedVars") & this.config.getConfig("typecheck:warnUnusedVars").getBoolean())
|
||||
{
|
||||
Variable[] unusedVariables = getUnusedVariables();
|
||||
gprintln("There are "~to!(string)(unusedVariables.length)~" unused variables");
|
||||
if(unusedVariables.length)
|
||||
{
|
||||
foreach(Variable unusedVariable; unusedVariables)
|
||||
{
|
||||
// TODO: Get a nicer name, full path-based
|
||||
gprintln("Variable '"~to!(string)(unusedVariable.getName())~"' is declared but never");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -62,7 +62,7 @@ before adding them here
|
|||
### Statements
|
||||
|
||||
Statements are inevitably the building blocks of a program and make use
|
||||
of all the former defined sections of the grammar and more of themsleves
|
||||
of all the former defined sections of the grammar and more of themselves
|
||||
in some cases as well.
|
||||
|
||||
module ::= "module", ident, ";", {decl, ";"};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## Configuration
|
||||
|
||||
The T compiler can have various variables tweaked to control the
|
||||
bahviour of the compiler
|
||||
behavior of the compiler
|
||||
|
||||
### `types`
|
||||
|
||||
|
@ -9,10 +9,10 @@ Anything regarding the type system (this includes the type checker and
|
|||
the meta processor).
|
||||
|
||||
1. `types:max_width`
|
||||
- This entry holds an integrak value
|
||||
- This entry holds an integral value
|
||||
- This sets the maximum bit-width of a machine (in bytes)
|
||||
- This can either be `1`, `2`, `4` or `8`
|
||||
- It affects how alises such as `size_t` and `ssize_t` behave in
|
||||
- It affects how aliases such as `size_t` and `ssize_t` behave in
|
||||
terms of what the resolve to
|
||||
|
||||
### `dgen`
|
||||
|
@ -57,3 +57,13 @@ This controls aspects of the `CodeEmitter` API, meaning irrespective of
|
|||
which emitter (such as `dgen`) is used.
|
||||
|
||||
TODO: Move `dgen_emit_entrypoint_test` and `dgen:pretty_code` here.
|
||||
|
||||
### `typecheck`
|
||||
|
||||
This controls the aspects of the `TypeChecker`.
|
||||
|
||||
1. `typecheck:warnUnusedVars`
|
||||
- If this is set to `true` then at the end of the typechecking
|
||||
process a scan for all variables will be done and any variable
|
||||
that is unused will be printed out
|
||||
- Default: `true`
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
## Command-line
|
||||
|
||||
This documents the full set of available command-line flags one can use.
|
||||
|
||||
### `--unusedVars <boolean>`
|
||||
|
||||
- **What**: Allows one to toggle whether or not warnings about unused
|
||||
variables should be printed out or not.
|
||||
- **Where**: Can be used with the `typecheck`, `emit` and `compile`
|
||||
commands.
|
||||
- **How**: This toggles the compiler configuration entry
|
||||
`typecheck:warnUnusedVars`
|
|
@ -285,4 +285,56 @@ assert(isSameType(
|
|||
); // Sanity check
|
||||
```
|
||||
|
||||
This is a sanity check, as if the type coercion failed then an exception would be thrown and the assertion would not be reached, however if the types were an exact match **or** if they were not but could be coerced as such then the two types should match.
|
||||
This is a sanity check, as if the type coercion failed then an exception would be thrown and the assertion would not be reached, however if the types were an exact match **or** if they were not but could be coerced as such then the two types should match.
|
||||
|
||||
### Variable referencing counting
|
||||
|
||||
Firstly let me make it clear that this has nothing to do with **runtime** reference counting but rather a simple mechanism used to maintain a count or _number of_ references to variables after their declaration.
|
||||
|
||||
Below is a method table of the methods of concern:
|
||||
|
||||
| Method | Description | Return |
|
||||
|--------|-------------|--------|
|
||||
| `touch(Variable)` | Increments the count by 1 for the given variable, creates a mapping if one does not yet exist | `void` |
|
||||
| `getUnusedVariables()` | Returns an array of all `Variable`s which have a reference count above `1` | `Variable[]` |
|
||||
|
||||
This aids us in implementing a single feature _unused variable detection_. It's rather simple, reference counts are incremented by using a `touch(Variable)` method defined in the `TypeChecker` and this is called whilst doing dependency generation in the dependency generator.
|
||||
|
||||
The first time a variable is encountered, such as even its declaration, we will then `touch(...)`-it. At the end of type checking we then call the `getUnusedVariables()` method which returns a list of the undeclared variables. These are variables with a reference count higher than `1`. We then print these out so the user can see which are unused.
|
||||
|
||||
#### Usage
|
||||
|
||||
Example usage below shows us `touch`-ing a variable when we process them in expressions such as a `VariableExpression` in the dependency module:
|
||||
|
||||
```{.d .numberLines}
|
||||
...
|
||||
|
||||
/* Get the entity as a Variable */
|
||||
Variable variable = cast(Variable)namedEntity;
|
||||
|
||||
/* Variable reference count must increase */
|
||||
tc.touch(variable);
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
We then, after typechecking, run the following in the type checker module's `doPostChecks()` method:
|
||||
|
||||
```{.d .numberLines}
|
||||
/**
|
||||
* Find the variables which were declared but never used
|
||||
*/
|
||||
if(this.config.hasConfig("typecheck:warnUnusedVars") & this.config.getConfig("typecheck:warnUnusedVars").getBoolean())
|
||||
{
|
||||
Variable[] unusedVariables = getUnusedVariables();
|
||||
gprintln("There are "~to!(string)(unusedVariables.length)~" unused variables");
|
||||
if(unusedVariables.length)
|
||||
{
|
||||
foreach(Variable unusedVariable; unusedVariables)
|
||||
{
|
||||
// TODO: Get a nicer name, full path-based
|
||||
gprintln("Variable '"~to!(string)(unusedVariable.getName())~"' is declared but never");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
|
@ -47,3 +47,10 @@ This controls aspects of the `CodeEmitter` API, meaning irrespective of which em
|
|||
|
||||
TODO: Move `dgen_emit_entrypoint_test` and `dgen:pretty_code` here.
|
||||
|
||||
### `typecheck`
|
||||
|
||||
This controls the aspects of the `TypeChecker`.
|
||||
|
||||
1. `typecheck:warnUnusedVars`
|
||||
* If this is set to `true` then at the end of the typechecking process a scan for all variables will be done and any variable that is unused will be printed out
|
||||
* Default: `true`
|
|
@ -0,0 +1,10 @@
|
|||
## Command-line
|
||||
|
||||
This documents the full set of available command-line flags one can use.
|
||||
|
||||
### `--unusedVars <boolean>`
|
||||
|
||||
* **What**: Allows one to toggle whether or not warnings about unused variables should be printed out or not.
|
||||
* **Where**: Can be used with the `typecheck`, `emit` and `compile` commands.
|
||||
* **How**: This toggles the compiler configuration entry `typecheck:warnUnusedVars`
|
||||
|
Loading…
Reference in New Issue