| Index: pkg/compiler/lib/src/inferrer/type_system.dart
|
| diff --git a/pkg/compiler/lib/src/inferrer/type_system.dart b/pkg/compiler/lib/src/inferrer/type_system.dart
|
| index af43cad98121ce39d63df9ec4c89bab2cc8ce74e..87a3feb49a5344954b5b89526131d2631c5043bb 100644
|
| --- a/pkg/compiler/lib/src/inferrer/type_system.dart
|
| +++ b/pkg/compiler/lib/src/inferrer/type_system.dart
|
| @@ -3,34 +3,48 @@
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| import '../common.dart';
|
| -import '../elements/elements.dart'
|
| - show
|
| - ClassElement,
|
| - ConstructorElement,
|
| - FieldElement,
|
| - FormalElement,
|
| - FunctionSignature,
|
| - FunctionTypedElement,
|
| - GetterElement,
|
| - LocalFunctionElement,
|
| - MemberElement,
|
| - MethodElement,
|
| - ParameterElement,
|
| - SetterElement;
|
| import '../elements/entities.dart';
|
| import '../elements/types.dart';
|
| -import '../tree/nodes.dart' as ast
|
| - show LiteralMap, LiteralList, Loop, Send, SwitchStatement;
|
| import '../types/masks.dart';
|
| import '../universe/selector.dart';
|
| import '../world.dart';
|
| import 'type_graph_nodes.dart';
|
|
|
| +/// Strategy for creating type information from members and parameters and type
|
| +/// information for nodes.
|
| +abstract class TypeSystemStrategy<T> {
|
| + /// Creates [MemberTypeInformation] for [member].
|
| + MemberTypeInformation createMemberTypeInformation(MemberEntity member);
|
| +
|
| + /// Creates [ParameterTypeInformation] for [parameter].
|
| + ParameterTypeInformation createParameterTypeInformation(
|
| + Local parameter, TypeSystem<T> types);
|
| +
|
| + /// Calls [f] for each parameter in [function].
|
| + void forEachParameter(FunctionEntity function, void f(Local parameter));
|
| +
|
| + /// Returns whether [node] is valid as a general phi node.
|
| + bool checkPhiNode(T node);
|
| +
|
| + /// Returns whether [node] is valid as a loop phi node.
|
| + bool checkLoopPhiNode(T node);
|
| +
|
| + /// Returns whether [node] is valid as a list allocation node.
|
| + bool checkListNode(T node);
|
| +
|
| + /// Returns whether [node] is valid as a map allocation node.
|
| + bool checkMapNode(T node);
|
| +
|
| + /// Returns whether [cls] is valid as a type mask base class.
|
| + bool checkClassEntity(ClassEntity cls);
|
| +}
|
| +
|
| /**
|
| * The class [SimpleInferrerVisitor] will use when working on types.
|
| */
|
| class TypeSystem<T> {
|
| final ClosedWorld closedWorld;
|
| + final TypeSystemStrategy<T> strategy;
|
|
|
| /// [parameterTypeInformations] and [memberTypeInformations] ordered by
|
| /// creation time. This is used as the inference enqueueing order.
|
| @@ -81,7 +95,7 @@ class TypeSystem<T> {
|
| allocatedTypes
|
| ].expand((x) => x);
|
|
|
| - TypeSystem(this.closedWorld) {
|
| + TypeSystem(this.closedWorld, this.strategy) {
|
| nonNullEmptyType = getConcreteTypeFor(commonMasks.emptyType);
|
| }
|
|
|
| @@ -348,75 +362,19 @@ class TypeSystem<T> {
|
| return newType;
|
| }
|
|
|
| - ParameterTypeInformation _createParameterTypeInformation(
|
| - ParameterElement parameter) {
|
| - FunctionTypedElement function = parameter.functionDeclaration.declaration;
|
| - if (function.isLocal) {
|
| - LocalFunctionElement localFunction = function;
|
| - MethodElement callMethod = localFunction.callMethod;
|
| - return new ParameterTypeInformation.localFunction(
|
| - getInferredTypeOfMember(callMethod),
|
| - parameter,
|
| - parameter.type,
|
| - callMethod);
|
| - } else if (function.isInstanceMember) {
|
| - MethodElement method = function;
|
| - return new ParameterTypeInformation.instanceMember(
|
| - getInferredTypeOfMember(method),
|
| - parameter,
|
| - parameter.type,
|
| - method,
|
| - new ParameterAssignments());
|
| - } else {
|
| - MethodElement method = function;
|
| - return new ParameterTypeInformation.static(
|
| - getInferredTypeOfMember(method), parameter, parameter.type, method,
|
| - // TODO(johnniwinther): Is this still valid now that initializing
|
| - // formals also introduce locals?
|
| - isInitializingFormal: parameter.isInitializingFormal);
|
| - }
|
| - }
|
| -
|
| ParameterTypeInformation getInferredTypeOfParameter(Local parameter) {
|
| - assert(!(parameter is ParameterElement && !parameter.isImplementation));
|
| -
|
| return parameterTypeInformations.putIfAbsent(parameter, () {
|
| ParameterTypeInformation typeInformation =
|
| - _createParameterTypeInformation(parameter);
|
| + strategy.createParameterTypeInformation(parameter, this);
|
| _orderedTypeInformations.add(typeInformation);
|
| return typeInformation;
|
| });
|
| }
|
|
|
| - MemberTypeInformation _createMemberTypeInformation(MemberElement member) {
|
| - if (member.isField) {
|
| - FieldElement field = member;
|
| - return new FieldTypeInformation(field, field.type);
|
| - } else if (member.isGetter) {
|
| - GetterElement getter = member;
|
| - return new GetterTypeInformation(getter, getter.type);
|
| - } else if (member.isSetter) {
|
| - SetterElement setter = member;
|
| - return new SetterTypeInformation(setter);
|
| - } else if (member.isFunction) {
|
| - MethodElement method = member;
|
| - return new MethodTypeInformation(method, method.type);
|
| - } else {
|
| - ConstructorElement constructor = member;
|
| - if (constructor.isFactoryConstructor) {
|
| - return new FactoryConstructorTypeInformation(
|
| - constructor, constructor.type);
|
| - } else {
|
| - return new GenerativeConstructorTypeInformation(constructor);
|
| - }
|
| - }
|
| - }
|
| -
|
| MemberTypeInformation getInferredTypeOfMember(MemberEntity member) {
|
| - assert(!(member is MemberElement && !member.isDeclaration));
|
| return memberTypeInformations.putIfAbsent(member, () {
|
| MemberTypeInformation typeInformation =
|
| - _createMemberTypeInformation(member);
|
| + strategy.createMemberTypeInformation(member);
|
| _orderedTypeInformations.add(typeInformation);
|
| return typeInformation;
|
| });
|
| @@ -432,19 +390,10 @@ class TypeSystem<T> {
|
| });
|
| }
|
|
|
| - void _forEachParameter(MethodElement function, void f(Local parameter)) {
|
| - MethodElement impl = function.implementation;
|
| - FunctionSignature signature = impl.functionSignature;
|
| - signature.forEachParameter((FormalElement _parameter) {
|
| - ParameterElement parameter = _parameter;
|
| - f(parameter);
|
| - });
|
| - }
|
| -
|
| String getInferredSignatureOfMethod(FunctionEntity function) {
|
| ElementTypeInformation info = getInferredTypeOfMember(function);
|
| var res = "";
|
| - _forEachParameter(function, (Local parameter) {
|
| + strategy.forEachParameter(function, (Local parameter) {
|
| TypeInformation type = getInferredTypeOfParameter(parameter);
|
| res += "${res.isEmpty ? '(' : ', '}${type.type} ${parameter.name}";
|
| });
|
| @@ -453,17 +402,17 @@ class TypeSystem<T> {
|
| }
|
|
|
| TypeInformation nonNullSubtype(ClassEntity cls) {
|
| - assert(!(cls is ClassElement && !cls.isDeclaration));
|
| + assert(strategy.checkClassEntity(cls));
|
| return getConcreteTypeFor(new TypeMask.nonNullSubtype(cls, closedWorld));
|
| }
|
|
|
| TypeInformation nonNullSubclass(ClassEntity cls) {
|
| - assert(!(cls is ClassElement && !cls.isDeclaration));
|
| + assert(strategy.checkClassEntity(cls));
|
| return getConcreteTypeFor(new TypeMask.nonNullSubclass(cls, closedWorld));
|
| }
|
|
|
| TypeInformation nonNullExact(ClassEntity cls) {
|
| - assert(!(cls is ClassElement && !cls.isDeclaration));
|
| + assert(strategy.checkClassEntity(cls));
|
| return getConcreteTypeFor(new TypeMask.nonNullExact(cls, closedWorld));
|
| }
|
|
|
| @@ -478,7 +427,7 @@ class TypeSystem<T> {
|
| TypeInformation allocateList(
|
| TypeInformation type, T node, MemberEntity enclosing,
|
| [TypeInformation elementType, int length]) {
|
| - assert(node is ast.LiteralList || node is ast.Send);
|
| + assert(strategy.checkListNode(node));
|
| ClassEntity typedDataClass = closedWorld.commonElements.typedDataClass;
|
| bool isTypedArray = typedDataClass != null &&
|
| closedWorld.isInstantiated(typedDataClass) &&
|
| @@ -514,7 +463,7 @@ class TypeSystem<T> {
|
| TypeInformation allocateMap(
|
| ConcreteTypeInformation type, T node, MemberEntity element,
|
| [List<TypeInformation> keyTypes, List<TypeInformation> valueTypes]) {
|
| - assert(node is ast.LiteralMap);
|
| + assert(strategy.checkMapNode(node));
|
| assert(keyTypes.length == valueTypes.length);
|
| bool isFixed = (type.type == commonMasks.constMapType);
|
|
|
| @@ -591,6 +540,7 @@ class TypeSystem<T> {
|
| PhiElementTypeInformation allocatePhi(
|
| T node, Local variable, TypeInformation inputType,
|
| {bool isTry}) {
|
| + assert(strategy.checkPhiNode(node));
|
| // Check if [inputType] is a phi for a local updated in
|
| // the try/catch block [node]. If it is, no need to allocate a new
|
| // phi.
|
| @@ -612,7 +562,7 @@ class TypeSystem<T> {
|
| PhiElementTypeInformation allocateLoopPhi(
|
| T node, Local variable, TypeInformation inputType,
|
| {bool isTry}) {
|
| - assert(node is ast.Loop || node is ast.SwitchStatement);
|
| + assert(strategy.checkLoopPhiNode(node));
|
| return _addPhi(node, variable, inputType, isTry);
|
| }
|
|
|
|
|