mirror of https://github.com/flutter/samples.git
deploy: 423663d24c
parent
54548429f4
commit
1cb16f8d44
File diff suppressed because one or more lines are too long
@ -0,0 +1,81 @@
|
||||
# Wolf Analysis
|
||||
|
||||
The code in this directory is __experimental__ and not yet ready for public
|
||||
consumption. This file briefly describes its design and intended use.
|
||||
|
||||
## Intention
|
||||
|
||||
Wolf analysis is intended as a broader, more extensible version of flow analysis
|
||||
for use in the analyzer package and the linter. If it proves useful, we may
|
||||
expand it to be usable by clients of the analyzer such as code generators.
|
||||
|
||||
The reason for making a new type of analysis, rather than extending flow
|
||||
analysis, is because the design of flow analysis is heavily constrained in ways
|
||||
that make it expensive to modify, maintain, and extend:
|
||||
|
||||
- It has to operate in parallel with type inference. This means that it can only
|
||||
make a single pass through the source code, and any time it "looks ahead", the
|
||||
code it is looking at doesn't yet have types. This forces it to make some
|
||||
conservative assumptions when analyzing loops and closures--for example, on
|
||||
entry to a loop, flow analysis knows which variables are written inside the
|
||||
loop body, but it doesn't know the types of the values that are written to
|
||||
those variables; so it has to discard type promotions for all of them. If
|
||||
later analysis shows that the values that were written are compatible with the
|
||||
promoted type, it's too late to go back and update the analysis.
|
||||
|
||||
- It can't be improved without bumping the language version (or it will break
|
||||
existing programs).
|
||||
|
||||
- All of its analyses must be 100% sound, because they are relied on by later
|
||||
compilation stages. This severly limits its ability to account for human
|
||||
intent, which we would sometimes like to do in lints.
|
||||
|
||||
- It has to be shared between the analyzer and the common front end, which means
|
||||
that all of the data structures it acts on must be abstract.
|
||||
|
||||
Additionally, flow analysis doesn't understand special behavioral guarantees of
|
||||
methods and types declared outside the SDK, and it never looks outside of a
|
||||
single method body.
|
||||
|
||||
## Design
|
||||
|
||||
The design consists of multiple analysis stages:
|
||||
|
||||
- AST-to-IR. The analyzer's AST is converted to a stack-based IR (intermediate
|
||||
representation). The proposed IR and the approach for converting to it are
|
||||
described in http://flutter.dev/go/dart-static-analysis-ir.
|
||||
|
||||
- Scope analysis. A pass is made through the IR, identifying all the state
|
||||
variables of interest. This includes local variables as well as any other
|
||||
pieces of state that are needed for whatever lints are enabled. This stage
|
||||
records the set of state variables that could potentially be changed inside
|
||||
each loop, block, closure, etc., for use in later analysis stages.
|
||||
|
||||
- SSA (single static assignment) analysis. A pass is made through the IR to
|
||||
assign SSA node ids to each state variable and stack value. Queries are
|
||||
generated at points that are of interest to whatever lints are enabled (e.g. a
|
||||
lint that verifies that certain kinds of values are never null will generate
|
||||
queries that ask "is the value represented by this SSA node null?").
|
||||
|
||||
- Query solver. Each query generated by SSA analysis is resolved by working
|
||||
backwards through the IR, rewriting it in terms of previous SSA nodes, until a
|
||||
point in the code is reached where the query either can or can't be
|
||||
definitively answered. The mechanism for rewriting queries is inspired by
|
||||
Prolog. Depending on the result of the query, a lint output might be
|
||||
generated.
|
||||
|
||||
Other analysis stages might be added in the future. For example, if we find that
|
||||
some lints can't be easily expressed in terms of queries, but can still benefit
|
||||
from the SSA representation, we may add other analysis stages after SSA
|
||||
analysis, to support those lints.
|
||||
|
||||
## Support structure
|
||||
|
||||
In addition to the pieces above, there is a simple interpreter that executes the
|
||||
IR. The interpreter is not intended for production use; it is just sophisticated
|
||||
enough to serve as the basis for unit testing the other stages. For example, we
|
||||
use it in the unit tests of the AST-to-IR conversion stage, to make sure that
|
||||
the output of this stage properly reflects Dart semantics. (If, instead, our
|
||||
unit tests simply compared the output of AST-to-IR conversion to an expected
|
||||
sequence of instructions, the unit tests would be much more brittle, and there
|
||||
would be a much greater risk of human error in reviewing them.)
|
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue