OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library simple_types_inferrer; | 5 library simple_types_inferrer; |
6 | 6 |
7 import '../closure.dart' show ClosureRepresentationInfo; | 7 import '../closure.dart' show ClosureRepresentationInfo; |
8 import '../common.dart'; | 8 import '../common.dart'; |
9 import '../common/names.dart' show Identifiers, Selectors; | 9 import '../common/names.dart' show Identifiers, Selectors; |
10 import '../compiler.dart' show Compiler; | 10 import '../compiler.dart' show Compiler; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 MemberElement analyzedElement, | 81 MemberElement analyzedElement, |
82 this.resolvedAst, | 82 this.resolvedAst, |
83 this.outermostElement, | 83 this.outermostElement, |
84 InferrerEngine inferrer, | 84 InferrerEngine inferrer, |
85 this.compiler, | 85 this.compiler, |
86 this.locals) | 86 this.locals) |
87 : this.analyzedElement = analyzedElement, | 87 : this.analyzedElement = analyzedElement, |
88 this.inferrer = inferrer, | 88 this.inferrer = inferrer, |
89 this.types = inferrer.types, | 89 this.types = inferrer.types, |
90 this.memberData = inferrer.dataOfMember(analyzedElement.memberContext) { | 90 this.memberData = inferrer.dataOfMember(analyzedElement.memberContext) { |
| 91 assert(analyzedElement.isDeclaration); |
91 assert(outermostElement != null); | 92 assert(outermostElement != null); |
| 93 assert(outermostElement.isDeclaration); |
92 if (locals != null) return; | 94 if (locals != null) return; |
93 ast.Node node; | 95 ast.Node node; |
94 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 96 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
95 node = resolvedAst.node; | 97 node = resolvedAst.node; |
96 } | 98 } |
97 FieldInitializationScope fieldScope = | 99 FieldInitializationScope fieldScope = |
98 analyzedElement.isGenerativeConstructor | 100 analyzedElement.isGenerativeConstructor |
99 ? new FieldInitializationScope(types) | 101 ? new FieldInitializationScope(types) |
100 : null; | 102 : null; |
101 locals = | 103 locals = |
102 new LocalsHandler(inferrer, types, compiler.options, node, fieldScope); | 104 new LocalsHandler(inferrer, types, compiler.options, node, fieldScope); |
103 } | 105 } |
104 | 106 |
105 ElementGraphBuilder(MemberElement element, ResolvedAst resolvedAst, | 107 ElementGraphBuilder(MemberElement element, ResolvedAst resolvedAst, |
106 Compiler compiler, InferrerEngine inferrer, [LocalsHandler handler]) | 108 Compiler compiler, InferrerEngine inferrer, [LocalsHandler handler]) |
107 : this.internal(element, resolvedAst, element.memberContext, inferrer, | 109 : this.internal(element, resolvedAst, element.memberContext.declaration, |
108 compiler, handler); | 110 inferrer, compiler, handler); |
109 | 111 |
110 TreeElements get elements => resolvedAst.elements; | 112 TreeElements get elements => resolvedAst.elements; |
111 | 113 |
112 bool accumulateIsChecks = false; | 114 bool accumulateIsChecks = false; |
113 bool conditionIsSimple = false; | 115 bool conditionIsSimple = false; |
114 List<ast.Send> isChecks; | 116 List<ast.Send> isChecks; |
115 int loopLevel = 0; | 117 int loopLevel = 0; |
116 | 118 |
117 bool get inLoop => loopLevel > 0; | 119 bool get inLoop => loopLevel > 0; |
118 bool get isThisExposed { | 120 bool get isThisExposed { |
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
916 closureData.forEachCapturedVariable((variable, field) { | 918 closureData.forEachCapturedVariable((variable, field) { |
917 locals.setCaptured(variable, field); | 919 locals.setCaptured(variable, field); |
918 }); | 920 }); |
919 closureData.forEachBoxedVariable((variable, field) { | 921 closureData.forEachBoxedVariable((variable, field) { |
920 locals.setCapturedAndBoxed(variable, field); | 922 locals.setCapturedAndBoxed(variable, field); |
921 }); | 923 }); |
922 if (analyzedElement.isField) { | 924 if (analyzedElement.isField) { |
923 return visit(initializer); | 925 return visit(initializer); |
924 } | 926 } |
925 | 927 |
926 MethodElement function = analyzedElement; | 928 MethodElement function = analyzedElement.implementation; |
927 FunctionSignature signature = function.functionSignature; | 929 FunctionSignature signature = function.functionSignature; |
928 signature.forEachOptionalParameter((FormalElement _element) { | 930 signature.forEachOptionalParameter((FormalElement _element) { |
929 ParameterElement element = _element; | 931 ParameterElement parameter = _element; |
930 ast.Expression defaultValue = element.initializer; | 932 ast.Expression defaultValue = parameter.initializer; |
931 // TODO(25566): The default value of a parameter of a redirecting factory | 933 // TODO(25566): The default value of a parameter of a redirecting factory |
932 // constructor comes from the corresponding parameter of the target. | 934 // constructor comes from the corresponding parameter of the target. |
933 | 935 |
934 // If this is a default value from a different context (because | 936 // If this is a default value from a different context (because |
935 // the current function is synthetic, e.g., a constructor from | 937 // the current function is synthetic, e.g., a constructor from |
936 // a mixin application), we have to start a new inferrer visitor | 938 // a mixin application), we have to start a new inferrer visitor |
937 // with the correct context. | 939 // with the correct context. |
938 // TODO(johnniwinther): Remove once function signatures are fixed. | 940 // TODO(johnniwinther): Remove once function signatures are fixed. |
939 ElementGraphBuilder visitor = this; | 941 ElementGraphBuilder visitor = this; |
940 if (inferrer.hasAlreadyComputedTypeOfParameterDefault(element)) return; | 942 if (inferrer.hasAlreadyComputedTypeOfParameterDefault(parameter)) return; |
941 | 943 |
942 FunctionElement declaration = element.functionDeclaration; | 944 FunctionElement declaration = parameter.functionDeclaration.declaration; |
943 MethodElement declarationMethod = declaration is LocalFunctionElement | 945 MethodElement declarationMethod = declaration is LocalFunctionElement |
944 ? declaration.callMethod | 946 ? declaration.callMethod |
945 : declaration; | 947 : declaration; |
946 bool needNewContext = declarationMethod != analyzedElement; | 948 bool needNewContext = declarationMethod != analyzedElement; |
947 if (needNewContext) { | 949 if (needNewContext) { |
948 assert( | 950 assert( |
949 declarationMethod is ConstructorElement, | 951 declarationMethod is ConstructorElement, |
950 failedAt( | 952 failedAt( |
951 element, | 953 parameter, |
952 "Unexpected function declaration " | 954 "Unexpected function declaration " |
953 "${declarationMethod}, expected ${analyzedElement}.")); | 955 "${declarationMethod}, expected ${analyzedElement}.")); |
954 visitor = new ElementGraphBuilder(declarationMethod, | 956 visitor = new ElementGraphBuilder(declarationMethod, |
955 element.functionDeclaration.resolvedAst, compiler, inferrer); | 957 parameter.functionDeclaration.resolvedAst, compiler, inferrer); |
956 } | 958 } |
957 TypeInformation type = | 959 TypeInformation type = |
958 (defaultValue == null) ? types.nullType : visitor.visit(defaultValue); | 960 (defaultValue == null) ? types.nullType : visitor.visit(defaultValue); |
959 inferrer.setDefaultTypeOfParameter(element, type); | 961 inferrer.setDefaultTypeOfParameter(parameter, type); |
960 }); | 962 }); |
961 | 963 |
962 if (closedWorld.nativeData.isNativeMember(analyzedElement)) { | 964 if (closedWorld.nativeData.isNativeMember(analyzedElement)) { |
963 // Native methods do not have a body, and we currently just say | 965 // Native methods do not have a body, and we currently just say |
964 // they return dynamic. | 966 // they return dynamic. |
965 return types.dynamicType; | 967 return types.dynamicType; |
966 } | 968 } |
967 | 969 |
968 if (analyzedElement.isGenerativeConstructor) { | 970 if (analyzedElement.isGenerativeConstructor) { |
969 isThisExposed = false; | 971 isThisExposed = false; |
(...skipping 1338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2308 analyzeSuperConstructorCall(constructor, arguments); | 2310 analyzeSuperConstructorCall(constructor, arguments); |
2309 } | 2311 } |
2310 } | 2312 } |
2311 // If we are looking at a new expression on a forwarding factory, we have to | 2313 // If we are looking at a new expression on a forwarding factory, we have to |
2312 // forward the call to the effective target of the factory. | 2314 // forward the call to the effective target of the factory. |
2313 // TODO(herhut): Remove the loop once effectiveTarget forwards to patches. | 2315 // TODO(herhut): Remove the loop once effectiveTarget forwards to patches. |
2314 while (target.isFactoryConstructor) { | 2316 while (target.isFactoryConstructor) { |
2315 if (!target.isRedirectingFactory) break; | 2317 if (!target.isRedirectingFactory) break; |
2316 target = target.effectiveTarget.implementation; | 2318 target = target.effectiveTarget.implementation; |
2317 } | 2319 } |
2318 if (compiler.backend.isForeign(closedWorld.commonElements, target)) { | 2320 if (closedWorld.commonElements.isForeign(target)) { |
2319 return handleForeignSend(node, target); | 2321 return handleForeignSend(node, target); |
2320 } | 2322 } |
2321 Selector selector = elements.getSelector(node); | 2323 Selector selector = elements.getSelector(node); |
2322 CallStructure callStructure = selector.callStructure; | 2324 CallStructure callStructure = selector.callStructure; |
2323 TypeMask mask = memberData.typeOfSend(node); | 2325 TypeMask mask = memberData.typeOfSend(node); |
2324 // In erroneous code the number of arguments in the selector might not | 2326 // In erroneous code the number of arguments in the selector might not |
2325 // match the function element. | 2327 // match the function element. |
2326 // TODO(polux): return nonNullEmpty and check it doesn'TypeInformation break
anything | 2328 // TODO(polux): return nonNullEmpty and check it doesn'TypeInformation break
anything |
2327 if (target.isMalformed || | 2329 if (target.isMalformed || |
2328 !callStructure.signatureApplies(target.parameterStructure)) { | 2330 !callStructure.signatureApplies(target.parameterStructure)) { |
2329 return types.dynamicType; | 2331 return types.dynamicType; |
2330 } | 2332 } |
2331 | 2333 |
2332 TypeInformation returnType = | 2334 TypeInformation returnType = |
2333 handleStaticSend(node, selector, mask, target, arguments); | 2335 handleStaticSend(node, selector, mask, target.declaration, arguments); |
2334 if (Elements.isGrowableListConstructorCall( | 2336 if (Elements.isGrowableListConstructorCall( |
2335 constructor, node, closedWorld.commonElements)) { | 2337 constructor, node, closedWorld.commonElements)) { |
2336 return inferrer.concreteTypes.putIfAbsent( | 2338 return inferrer.concreteTypes.putIfAbsent( |
2337 node, | 2339 node, |
2338 () => types.allocateList(types.growableListType, node, | 2340 () => types.allocateList(types.growableListType, node, |
2339 outermostElement, types.nonNullEmpty(), 0)); | 2341 outermostElement, types.nonNullEmpty(), 0)); |
2340 } else if (Elements.isFixedListConstructorCall( | 2342 } else if (Elements.isFixedListConstructorCall( |
2341 constructor, node, closedWorld.commonElements) || | 2343 constructor, node, closedWorld.commonElements) || |
2342 Elements.isFilledListConstructorCall( | 2344 Elements.isFilledListConstructorCall( |
2343 constructor, node, closedWorld.commonElements)) { | 2345 constructor, node, closedWorld.commonElements)) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2396 inferrer.typeOfMember(element), | 2398 inferrer.typeOfMember(element), |
2397 outermostElement, | 2399 outermostElement, |
2398 arguments, | 2400 arguments, |
2399 sideEffects, | 2401 sideEffects, |
2400 inLoop); | 2402 inLoop); |
2401 } | 2403 } |
2402 | 2404 |
2403 /// Handle invocation of a top level or static [function]. | 2405 /// Handle invocation of a top level or static [function]. |
2404 TypeInformation handleStaticFunctionInvoke( | 2406 TypeInformation handleStaticFunctionInvoke( |
2405 ast.Send node, MethodElement function) { | 2407 ast.Send node, MethodElement function) { |
2406 if (compiler.backend.isForeign(closedWorld.commonElements, function)) { | 2408 if (closedWorld.commonElements.isForeign(function)) { |
2407 return handleForeignSend(node, function); | 2409 return handleForeignSend(node, function); |
2408 } | 2410 } |
2409 ArgumentsTypes arguments = analyzeArguments(node.arguments); | 2411 ArgumentsTypes arguments = analyzeArguments(node.arguments); |
2410 Selector selector = elements.getSelector(node); | 2412 Selector selector = elements.getSelector(node); |
2411 TypeMask mask = memberData.typeOfSend(node); | 2413 TypeMask mask = memberData.typeOfSend(node); |
2412 return handleStaticSend(node, selector, mask, function, arguments); | 2414 return handleStaticSend(node, selector, mask, function, arguments); |
2413 } | 2415 } |
2414 | 2416 |
2415 /// Handle an static invocation of an unresolved target or with incompatible | 2417 /// Handle an static invocation of an unresolved target or with incompatible |
2416 /// arguments to a resolved target. | 2418 /// arguments to a resolved target. |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2716 LocalFunctionElement function, | 2718 LocalFunctionElement function, |
2717 ast.NodeList arguments, | 2719 ast.NodeList arguments, |
2718 CallStructure callStructure, | 2720 CallStructure callStructure, |
2719 _) { | 2721 _) { |
2720 analyzeArguments(node.arguments); | 2722 analyzeArguments(node.arguments); |
2721 return types.dynamicType; | 2723 return types.dynamicType; |
2722 } | 2724 } |
2723 | 2725 |
2724 TypeInformation handleStaticSend(ast.Node node, Selector selector, | 2726 TypeInformation handleStaticSend(ast.Node node, Selector selector, |
2725 TypeMask mask, MemberElement element, ArgumentsTypes arguments) { | 2727 TypeMask mask, MemberElement element, ArgumentsTypes arguments) { |
| 2728 assert(element.isDeclaration); |
2726 assert(!element.isFactoryConstructor || | 2729 assert(!element.isFactoryConstructor || |
2727 !(element as ConstructorElement).isRedirectingFactory); | 2730 !(element as ConstructorElement).isRedirectingFactory); |
2728 // Erroneous elements may be unresolved, for example missing getters. | 2731 // Erroneous elements may be unresolved, for example missing getters. |
2729 if (Elements.isUnresolved(element)) return types.dynamicType; | 2732 if (Elements.isUnresolved(element)) return types.dynamicType; |
2730 // TODO(herhut): should we follow redirecting constructors here? We would | 2733 // TODO(herhut): should we follow redirecting constructors here? We would |
2731 // need to pay attention if the constructor is pointing to an erroneous | 2734 // need to pay attention if the constructor is pointing to an erroneous |
2732 // element. | 2735 // element. |
2733 return inferrer.registerCalledMember(node, selector, mask, outermostElement, | 2736 return inferrer.registerCalledMember(node, selector, mask, outermostElement, |
2734 element, arguments, sideEffects, inLoop); | 2737 element, arguments, sideEffects, inLoop); |
2735 } | 2738 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2807 return handleDynamicSend(node, selector, mask, receiverType, arguments); | 2810 return handleDynamicSend(node, selector, mask, receiverType, arguments); |
2808 } | 2811 } |
2809 | 2812 |
2810 void recordReturnType(TypeInformation type) { | 2813 void recordReturnType(TypeInformation type) { |
2811 returnType = | 2814 returnType = |
2812 inferrer.addReturnTypeForMethod(analyzedElement, returnType, type); | 2815 inferrer.addReturnTypeForMethod(analyzedElement, returnType, type); |
2813 } | 2816 } |
2814 | 2817 |
2815 TypeInformation synthesizeForwardingCall( | 2818 TypeInformation synthesizeForwardingCall( |
2816 Spannable node, ConstructorElement element) { | 2819 Spannable node, ConstructorElement element) { |
2817 element = element.implementation; | 2820 assert(element.isDeclaration); |
2818 MethodElement function = analyzedElement; | 2821 MethodElement function = analyzedElement.implementation; |
2819 FunctionSignature signature = function.functionSignature; | 2822 FunctionSignature signature = function.functionSignature; |
2820 FunctionSignature calleeSignature = element.functionSignature; | 2823 FunctionSignature calleeSignature = element.functionSignature; |
2821 if (!calleeSignature.isCompatibleWith(signature)) { | 2824 if (!calleeSignature.isCompatibleWith(signature)) { |
2822 return types.nonNullEmpty(); | 2825 return types.nonNullEmpty(); |
2823 } | 2826 } |
2824 | 2827 |
2825 List<TypeInformation> unnamed = <TypeInformation>[]; | 2828 List<TypeInformation> unnamed = <TypeInformation>[]; |
2826 signature.forEachRequiredParameter((FormalElement _element) { | 2829 signature.forEachRequiredParameter((FormalElement _element) { |
2827 ParameterElement element = _element; | 2830 ParameterElement element = _element; |
2828 assert(locals.use(element) != null); | 2831 assert(locals.use(element) != null); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2939 Selector moveNextSelector = Selectors.moveNext; | 2942 Selector moveNextSelector = Selectors.moveNext; |
2940 TypeMask moveNextMask = memberData.typeOfIteratorMoveNext(node); | 2943 TypeMask moveNextMask = memberData.typeOfIteratorMoveNext(node); |
2941 | 2944 |
2942 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, | 2945 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, |
2943 iteratorMask, expressionType, new ArgumentsTypes.empty()); | 2946 iteratorMask, expressionType, new ArgumentsTypes.empty()); |
2944 | 2947 |
2945 return handleForInLoop(node, iteratorType, currentSelector, currentMask, | 2948 return handleForInLoop(node, iteratorType, currentSelector, currentMask, |
2946 moveNextSelector, moveNextMask); | 2949 moveNextSelector, moveNextMask); |
2947 } | 2950 } |
2948 } | 2951 } |
OLD | NEW |