blob: 28dc608cb384ef9bfd2da203f58f908c24909ea9 [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library types;
import '../common/tasks.dart' show CompilerTask;
import '../compiler.dart' show Compiler;
import '../elements/elements.dart';
import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
import '../tree/tree.dart';
import '../universe/selector.dart' show Selector;
import 'masks.dart';
export 'masks.dart';
/// API to interact with the global type-inference engine.
abstract class TypesInferrer {
void analyzeMain(Element element);
TypeMask getReturnTypeOfElement(Element element);
TypeMask getTypeOfElement(Element element);
TypeMask getTypeOfNode(Element owner, Node node);
TypeMask getTypeOfSelector(Selector selector, TypeMask mask);
void clear();
bool isCalledOnce(Element element);
bool isFixedArrayCheckedForGrowable(Node node);
}
/// Global analysis that infers concrete types.
class GlobalTypeInferenceTask extends CompilerTask {
// TODO(sigmund): rename at the same time as our benchmarking tools.
final String name = 'Type inference';
final Compiler compiler;
TypesInferrer typesInferrer;
CommonMasks masks;
GlobalTypeInferenceTask(Compiler compiler)
: masks = new CommonMasks(compiler),
compiler = compiler,
super(compiler.measurer) {
typesInferrer = new TypeGraphInferrer(compiler, masks);
}
/// Runs the global type-inference algorithm once.
void runGlobalTypeInference(Element mainElement) {
measure(() {
typesInferrer.analyzeMain(mainElement);
typesInferrer.clear();
});
}
/**
* Return the (inferred) guaranteed type of [element] or null.
*/
TypeMask getGuaranteedTypeOfElement(Element element) {
// TODO(24489): trust some JsInterop types.
if (compiler.backend.isJsInterop(element)) {
return masks.dynamicType;
}
TypeMask guaranteedType = typesInferrer.getTypeOfElement(element);
return guaranteedType;
}
TypeMask getGuaranteedReturnTypeOfElement(Element element) {
// TODO(24489): trust some JsInterop types.
if (compiler.backend.isJsInterop(element)) {
return masks.dynamicType;
}
TypeMask guaranteedType = typesInferrer.getReturnTypeOfElement(element);
return guaranteedType;
}
/// Return whether the global inference algorithm determined that [element]
/// always throws.
bool throwsAlways(Element element) {
// We know the element always throws if the return type was inferred to be
// non-null empty.
TypeMask returnType = getGuaranteedReturnTypeOfElement(element);
return returnType != null && returnType.isEmpty;
}
bool isFixedArrayCheckedForGrowable(Node send) =>
typesInferrer.isFixedArrayCheckedForGrowable(send);
bool isCalledOnce(Element element) => typesInferrer.isCalledOnce(element);
/**
* Return the (inferred) guaranteed type of [node] or null.
* [node] must be an AST node of [owner].
*/
TypeMask getGuaranteedTypeOfNode(owner, node) {
TypeMask guaranteedType = typesInferrer.getTypeOfNode(owner, node);
return guaranteedType;
}
/**
* Return the (inferred) guaranteed type of [selector] or null.
*/
TypeMask getGuaranteedTypeOfSelector(Selector selector, TypeMask mask) {
TypeMask guaranteedType = typesInferrer.getTypeOfSelector(selector, mask);
return guaranteedType;
}
}