blob: e19da52e159269c3e531c0ce8284eddbac7a2a53 [file] [log] [blame]
// Copyright (c) 2015, 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 dart2js.abstract_value_domain;
import '../constants/values.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../universe/selector.dart' show Selector;
enum AbstractBool { True, False, Maybe, Nothing }
/// A value in an abstraction of runtime values.
abstract class AbstractValue {}
/// A system that implements an abstraction over runtime values and provides
/// access to interprocedural analysis results.
// TODO(johnniwinther): Consider extracting the inference result access from
// this interface.
abstract class AbstractValueDomain {
AbstractValue get dynamicType;
AbstractValue get typeType;
AbstractValue get functionType;
AbstractValue get boolType;
AbstractValue get intType;
AbstractValue get doubleType;
AbstractValue get numType;
AbstractValue get stringType;
AbstractValue get listType;
AbstractValue get mapType;
AbstractValue get nonNullType;
AbstractValue get nullType;
AbstractValue get extendableArrayType;
AbstractValue get fixedArrayType;
AbstractValue get arrayType;
AbstractValue get uint31Type;
AbstractValue get uint32Type;
AbstractValue get uintType;
AbstractValue get numStringBoolType;
AbstractValue get fixedLengthType;
AbstractValue get interceptorType;
AbstractValue get interceptedTypes;
/// If true, [function] ignores its explicit receiver argument and will use
/// its `this` value instead.
bool methodIgnoresReceiverArgument(FunctionElement function);
/// If true, the explicit receiver argument can be ignored when invoking
/// [selector] on a value of [type].
bool targetIgnoresReceiverArgument(AbstractValue type, Selector selector);
Element locateSingleElement(AbstractValue mask, Selector selector);
ClassElement singleClass(AbstractValue mask);
bool needsNoSuchMethodHandling(AbstractValue mask, Selector selector);
AbstractValue getReceiverType(MethodElement method);
AbstractValue getParameterType(ParameterElement parameter);
AbstractValue getReturnType(FunctionElement function);
AbstractValue getInvokeReturnType(Selector selector, AbstractValue mask);
AbstractValue getFieldType(FieldElement field);
AbstractValue join(AbstractValue a, AbstractValue b);
AbstractValue intersection(AbstractValue a, AbstractValue b);
AbstractValue getTypeOf(ConstantValue constant);
/// Returns the constant value if the [AbstractValue] represents a single
/// constant value. Returns `null` if [value] is not a constant.
ConstantValue getConstantOf(AbstractValue value);
AbstractValue nonNullExact(ClassElement element);
AbstractValue nonNullSubclass(ClassElement element);
AbstractValue nonNullSubtype(ClassElement element);
bool isDefinitelyBool(AbstractValue t, {bool allowNull: false});
bool isDefinitelyNum(AbstractValue t, {bool allowNull: false});
bool isDefinitelyString(AbstractValue t, {bool allowNull: false});
bool isDefinitelyNumStringBool(AbstractValue t, {bool allowNull: false});
bool isDefinitelyNotNumStringBool(AbstractValue t);
/// True if all values of [t] are either integers or not numbers at all.
///
/// This does not imply that the value is an integer, since most other values
/// such as null are also not a non-integer double.
bool isDefinitelyNotNonIntegerDouble(AbstractValue t);
bool isDefinitelyNonNegativeInt(AbstractValue t, {bool allowNull: false});
bool isDefinitelyInt(AbstractValue t, {bool allowNull: false});
bool isDefinitelyUint31(AbstractValue t, {bool allowNull: false});
bool isDefinitelyUint32(AbstractValue t, {bool allowNull: false});
bool isDefinitelyUint(AbstractValue t, {bool allowNull: false});
bool isDefinitelyArray(AbstractValue t, {bool allowNull: false});
bool isDefinitelyMutableArray(AbstractValue t, {bool allowNull: false});
bool isDefinitelyFixedArray(AbstractValue t, {bool allowNull: false});
bool isDefinitelyExtendableArray(AbstractValue t, {bool allowNull: false});
bool isDefinitelyIndexable(AbstractValue t, {bool allowNull: false});
bool isDefinitelyMutableIndexable(AbstractValue t, {bool allowNull: false});
bool isDefinitelyFixedLengthIndexable(AbstractValue t,
{bool allowNull: false});
bool isDefinitelyIntercepted(AbstractValue t, {bool allowNull});
bool isDefinitelySelfInterceptor(AbstractValue t, {bool allowNull: false});
/// Given a class from the interceptor hierarchy, returns an [AbstractValue]
/// matching all values with that interceptor (or a subtype thereof).
AbstractValue getInterceptorSubtypes(ClassElement class_);
bool areDisjoint(AbstractValue leftType, AbstractValue rightType);
bool isMorePreciseOrEqual(AbstractValue t1, AbstractValue t2);
AbstractBool isSubtypeOf(AbstractValue value, DartType type,
{bool allowNull});
/// Returns whether [value] is one of the falsy values: false, 0, -0, NaN,
/// the empty string, or null.
AbstractBool boolify(AbstractValue value);
AbstractBool strictBoolify(AbstractValue type);
/// Create a type mask containing at least all subtypes of [type].
AbstractValue subtypesOf(DartType type);
/// Returns a subset of [receiver] containing at least the types
/// that can respond to [selector] without throwing.
AbstractValue receiverTypeFor(Selector selector, AbstractValue receiver);
/// The result of an index operation on [value], or the dynamic type if
/// unknown.
AbstractValue elementTypeOfIndexable(AbstractValue value);
/// The length property of [value], or `null` if unknown.
int getContainerLength(AbstractValue value);
/// Returns the type of the entry of [container] at a given index.
/// Returns `null` if unknown.
AbstractValue indexWithConstant(
AbstractValue container, ConstantValue indexValue);
}