class TypeInference extends DataFlowAnalysis.BranchedForwardDataFlowAnalysis<Node,FlowScope>
Modifier and Type | Class and Description |
---|---|
private class |
TypeInference.BooleanOutcomePair
When traversing short-circuiting binary operations, we need to keep track
of two sets of boolean literals:
1.
|
private static class |
TypeInference.TemplateTypeReplacer |
DataFlowAnalysis.BranchedFlowState<L extends LatticeElement>, DataFlowAnalysis.BranchedForwardDataFlowAnalysis<N,L extends LatticeElement>, DataFlowAnalysis.FlowState<L extends LatticeElement>, DataFlowAnalysis.MaxIterationsExceededException
Modifier and Type | Field and Description |
---|---|
private java.util.Map<java.lang.String,CodingConvention.AssertionFunctionSpec> |
assertionFunctionsMap |
private FlowScope |
bottomScope |
private AbstractCompiler |
compiler |
(package private) static DiagnosticType |
FUNCTION_LITERAL_UNDEFINED_THIS |
private FlowScope |
functionScope |
private JSTypeRegistry |
registry |
private ReverseAbstractInterpreter |
reverseInterpreter |
private TypedScope |
syntacticScope |
private ObjectType |
unknownType |
joinOp, MAX_STEPS, orderedWorkSet
Constructor and Description |
---|
TypeInference(AbstractCompiler compiler,
ControlFlowGraph<Node> cfg,
ReverseAbstractInterpreter reverseInterpreter,
TypedScope functionScope,
java.util.Map<java.lang.String,CodingConvention.AssertionFunctionSpec> assertionFunctionsMap) |
Modifier and Type | Method and Description |
---|---|
private void |
backwardsInferenceFromCallSite(Node n,
FunctionType fnType)
We only do forward type inference.
|
(package private) java.util.List<FlowScope> |
branchedFlowThrough(Node source,
FlowScope input)
The branched flow function maps a single lattice to a list of output
lattices.
|
private java.util.Map<java.lang.String,JSType> |
buildTypeVariables(java.util.Map<TemplateType,JSType> inferredTypes)
Build the type environment where type transformations will be evaluated.
|
(package private) FlowScope |
createEntryLattice()
Gets the incoming state of the entry node.
|
(package private) FlowScope |
createInitialEstimateLattice()
Gets the state of the initial estimation at each node.
|
private FlowScope |
dereferencePointer(Node n,
FlowScope scope)
If we access a property of a symbol, then that symbol is not
null or undefined.
|
private void |
ensurePropertyDeclared(Node getprop)
Defines a declared property if it has not been defined yet.
|
private boolean |
ensurePropertyDeclaredHelper(Node getprop,
ObjectType objectType)
Declares a property on its owner, if necessary.
|
private void |
ensurePropertyDefined(Node getprop,
JSType rightType)
Defines a property if the property has not been defined yet.
|
private java.util.Map<TemplateType,JSType> |
evaluateTypeTransformations(com.google.common.collect.ImmutableList<TemplateType> templateTypes,
java.util.Map<TemplateType,JSType> inferredTypes)
This function will evaluate the type transformations associated to the
template types
|
(package private) FlowScope |
flowThrough(Node n,
FlowScope input)
Computes the output state for a given node and input state.
|
private JSType |
getJSType(Node n)
This method gets the JSType from the Node argument and verifies that it is
present.
|
private JSType |
getNativeType(JSTypeNative typeId) |
private JSType |
getPropertyType(JSType objType,
java.lang.String propName,
Node n,
FlowScope scope) |
private void |
inferArguments(TypedScope functionScope)
Infers all of a function's arguments if their types aren't declared.
|
private static void |
inferPropertyTypesToMatchConstraint(JSType type,
JSType constraint)
Suppose X is an object with inferred properties.
|
private boolean |
inferTemplatedTypesForCall(Node n,
FunctionType fnType)
For functions with function(this: T, ...) and T as parameters, type
inference will set the type of this on a function literal argument to the
the actual type of T.
|
private java.util.Map<TemplateType,JSType> |
inferTemplateTypesFromParameters(FunctionType fnType,
Node call) |
private boolean |
isAddedAsNumber(JSType type) |
private boolean |
isUnflowable(TypedVar v) |
private static BooleanLiteralSet |
joinBooleanOutcomes(boolean isAnd,
BooleanLiteralSet left,
BooleanLiteralSet right) |
private FunctionType |
matchFunction(FunctionType expectedType,
FunctionType currentType,
boolean declared)
Take the current function type, and try to match the expected function
type.
|
private void |
maybeResolveTemplatedType(JSType paramType,
JSType argType,
java.util.Map<TemplateType,JSType> resolvedTypes,
java.util.Set<JSType> seenTypes) |
private void |
maybeResolveTemplateTypeFromNodes(java.lang.Iterable<Node> declParams,
java.lang.Iterable<Node> callParams,
java.util.Map<TemplateType,JSType> resolvedTypes,
java.util.Set<JSType> seenTypes) |
private void |
maybeResolveTemplateTypeFromNodes(java.util.Iterator<Node> declParams,
java.util.Iterator<Node> callParams,
java.util.Map<TemplateType,JSType> resolvedTypes,
java.util.Set<JSType> seenTypes) |
private FlowScope |
narrowScope(FlowScope scope,
Node node,
JSType narrowed) |
private TypeInference.BooleanOutcomePair |
newBooleanOutcomePair(JSType jsType,
FlowScope flowScope) |
private void |
redeclareSimpleVar(FlowScope scope,
Node nameNode,
JSType varType) |
private static void |
resolvedTemplateType(java.util.Map<TemplateType,JSType> map,
TemplateType template,
JSType resolved) |
private FlowScope |
tightenTypesAfterAssertions(FlowScope scope,
Node callNode) |
private FlowScope |
traverse(Node n,
FlowScope scope) |
private FlowScope |
traverseAdd(Node n,
FlowScope scope) |
private TypeInference.BooleanOutcomePair |
traverseAnd(Node n,
FlowScope scope) |
private FlowScope |
traverseArrayLiteral(Node n,
FlowScope scope)
Traverse each element of the array.
|
private FlowScope |
traverseAssign(Node n,
FlowScope scope) |
private FlowScope |
traverseCall(Node n,
FlowScope scope) |
private FlowScope |
traverseCatch(Node catchNode,
FlowScope scope)
Any value can be thrown, so it's really impossible to determine the type
of a CATCH param.
|
private FlowScope |
traverseChildren(Node n,
FlowScope scope) |
private FlowScope |
traverseGetElem(Node n,
FlowScope scope) |
private FlowScope |
traverseGetProp(Node n,
FlowScope scope) |
private FlowScope |
traverseHook(Node n,
FlowScope scope) |
private FlowScope |
traverseName(Node n,
FlowScope scope) |
private FlowScope |
traverseNew(Node n,
FlowScope scope) |
private FlowScope |
traverseObjectLiteral(Node n,
FlowScope scope) |
private TypeInference.BooleanOutcomePair |
traverseOr(Node n,
FlowScope scope) |
private FlowScope |
traverseReturn(Node n,
FlowScope scope)
Traverse a return value.
|
private TypeInference.BooleanOutcomePair |
traverseShortCircuitingBinOp(Node n,
FlowScope scope) |
private TypeInference.BooleanOutcomePair |
traverseWithinShortCircuitingBinOp(Node n,
FlowScope scope) |
private void |
updateBind(Node n)
When "bind" is called on a function, we infer the type of the returned
"bound" function by looking at the number of parameters in the call site.
|
private void |
updateScopeForTypeChange(FlowScope scope,
Node left,
JSType leftType,
JSType resultType)
Updates the scope according to the result of a type change, like
an assignment or a type cast.
|
private void |
updateTypeOfParameters(Node n,
FunctionType fnType)
For functions with function parameters, type inference will set the type of
a function literal argument from the function parameter type.
|
flow, getExitLatticeElement, initialize, isForward, joinInputs
analyze, analyze, computeEscaped, getCfg, join
static final DiagnosticType FUNCTION_LITERAL_UNDEFINED_THIS
private final AbstractCompiler compiler
private final JSTypeRegistry registry
private final ReverseAbstractInterpreter reverseInterpreter
private final TypedScope syntacticScope
private final FlowScope functionScope
private final FlowScope bottomScope
private final java.util.Map<java.lang.String,CodingConvention.AssertionFunctionSpec> assertionFunctionsMap
private final ObjectType unknownType
TypeInference(AbstractCompiler compiler, ControlFlowGraph<Node> cfg, ReverseAbstractInterpreter reverseInterpreter, TypedScope functionScope, java.util.Map<java.lang.String,CodingConvention.AssertionFunctionSpec> assertionFunctionsMap)
private void inferArguments(TypedScope functionScope)
FlowScope createInitialEstimateLattice()
DataFlowAnalysis
createInitialEstimateLattice
in class DataFlowAnalysis<Node,FlowScope>
FlowScope createEntryLattice()
DataFlowAnalysis
createEntryLattice
in class DataFlowAnalysis<Node,FlowScope>
FlowScope flowThrough(Node n, FlowScope input)
DataFlowAnalysis
flowThrough
in class DataFlowAnalysis<Node,FlowScope>
n
- The node.input
- Input lattice that should be read-only.java.util.List<FlowScope> branchedFlowThrough(Node source, FlowScope input)
DataFlowAnalysis.BranchedForwardDataFlowAnalysis
Each outgoing edge of a node will have a corresponding output lattice
in the ordered returned by
DiGraph.getOutEdges(Object)
in the returned list.
branchedFlowThrough
in class DataFlowAnalysis.BranchedForwardDataFlowAnalysis<Node,FlowScope>
private FlowScope traverseCatch(Node catchNode, FlowScope scope)
private void updateScopeForTypeChange(FlowScope scope, Node left, JSType leftType, JSType resultType)
private void ensurePropertyDefined(Node getprop, JSType rightType)
private void ensurePropertyDeclared(Node getprop)
TypedScopeCreator
.private boolean ensurePropertyDeclaredHelper(Node getprop, ObjectType objectType)
private FlowScope traverseArrayLiteral(Node n, FlowScope scope)
private boolean isAddedAsNumber(JSType type)
private FlowScope tightenTypesAfterAssertions(FlowScope scope, Node callNode)
private void backwardsInferenceFromCallSite(Node n, FunctionType fnType)
var x = f();
g(x);
a forward type-inference engine would try to figure out the type
of "x" from the return type of "f". A backwards type-inference engine
would try to figure out the type of "x" from the parameter type of "g".
However, there are a few special syntactic forms where we do some
some half-assed backwards type-inference, because programmers
expect it in this day and age. To take an example from Java,
List x = Lists.newArrayList();
The Java compiler will be able to infer the generic type of the List
returned by newArrayList().
In much the same way, we do some special-case backwards inference for
JS. Those cases are enumerated here.private void updateBind(Node n)
private void updateTypeOfParameters(Node n, FunctionType fnType)
private FunctionType matchFunction(FunctionType expectedType, FunctionType currentType, boolean declared)
private java.util.Map<TemplateType,JSType> inferTemplateTypesFromParameters(FunctionType fnType, Node call)
private void maybeResolveTemplatedType(JSType paramType, JSType argType, java.util.Map<TemplateType,JSType> resolvedTypes, java.util.Set<JSType> seenTypes)
private void maybeResolveTemplateTypeFromNodes(java.lang.Iterable<Node> declParams, java.lang.Iterable<Node> callParams, java.util.Map<TemplateType,JSType> resolvedTypes, java.util.Set<JSType> seenTypes)
private void maybeResolveTemplateTypeFromNodes(java.util.Iterator<Node> declParams, java.util.Iterator<Node> callParams, java.util.Map<TemplateType,JSType> resolvedTypes, java.util.Set<JSType> seenTypes)
private static void resolvedTemplateType(java.util.Map<TemplateType,JSType> map, TemplateType template, JSType resolved)
private java.util.Map<java.lang.String,JSType> buildTypeVariables(java.util.Map<TemplateType,JSType> inferredTypes)
private java.util.Map<TemplateType,JSType> evaluateTypeTransformations(com.google.common.collect.ImmutableList<TemplateType> templateTypes, java.util.Map<TemplateType,JSType> inferredTypes)
private boolean inferTemplatedTypesForCall(Node n, FunctionType fnType)
private TypeInference.BooleanOutcomePair traverseAnd(Node n, FlowScope scope)
private static void inferPropertyTypesToMatchConstraint(JSType type, JSType constraint)
private FlowScope dereferencePointer(Node n, FlowScope scope)
private JSType getPropertyType(JSType objType, java.lang.String propName, Node n, FlowScope scope)
private TypeInference.BooleanOutcomePair traverseOr(Node n, FlowScope scope)
private TypeInference.BooleanOutcomePair traverseShortCircuitingBinOp(Node n, FlowScope scope)
private TypeInference.BooleanOutcomePair traverseWithinShortCircuitingBinOp(Node n, FlowScope scope)
private static BooleanLiteralSet joinBooleanOutcomes(boolean isAnd, BooleanLiteralSet left, BooleanLiteralSet right)
private TypeInference.BooleanOutcomePair newBooleanOutcomePair(JSType jsType, FlowScope flowScope)
private boolean isUnflowable(TypedVar v)
private JSType getJSType(Node n)
private JSType getNativeType(JSTypeNative typeId)