OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
; | 5 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
; |
6 import 'package:kernel/ast.dart'; | 6 import 'package:kernel/ast.dart'; |
7 | 7 |
8 /// Type inference listener that records inferred types and file offsets for | 8 /// Type inference listener that records inferred types and file offsets for |
9 /// later use by [ValidatingResolutionApplier]. | 9 /// later use by [ValidatingResolutionApplier]. |
10 class InstrumentedResolutionStorer extends ResolutionStorer { | 10 class InstrumentedResolutionStorer extends ResolutionStorer { |
11 /// Indicates whether debug messages should be printed. | 11 /// Indicates whether debug messages should be printed. |
12 static const bool _debug = false; | 12 static const bool _debug = false; |
13 | 13 |
14 final List<int> _typeOffsets; | 14 final List<int> _typeOffsets; |
15 | 15 |
16 InstrumentedResolutionStorer(List<DartType> types, this._typeOffsets) | 16 InstrumentedResolutionStorer(List<DartType> types, this._typeOffsets) |
17 : super(types); | 17 : super(types); |
18 | 18 |
19 @override | 19 @override |
20 void _recordType(DartType type, int offset) { | 20 int _recordType(DartType type, int offset) { |
21 if (_debug) { | 21 if (_debug) { |
22 print('Recording type $type for offset $offset'); | 22 print('Recording type $type for offset $offset'); |
23 } | 23 } |
24 assert(_types.length == _typeOffsets.length); | 24 assert(_types.length == _typeOffsets.length); |
25 _typeOffsets.add(offset); | 25 _typeOffsets.add(offset); |
26 super._recordType(type, offset); | 26 return super._recordType(type, offset); |
27 } | 27 } |
28 } | 28 } |
29 | 29 |
30 /// Type inference listener that records inferred types for later use by | 30 /// Type inference listener that records inferred types for later use by |
31 /// [ResolutionApplier]. | 31 /// [ResolutionApplier]. |
32 class ResolutionStorer extends TypeInferenceListener { | 32 class ResolutionStorer extends TypeInferenceListener { |
33 final List<DartType> _types; | 33 final List<DartType> _types; |
34 | 34 |
| 35 /// Indices into [_types] which need to be filled in later. |
| 36 final _deferredTypeSlots = <int>[]; |
| 37 |
35 ResolutionStorer(this._types); | 38 ResolutionStorer(this._types); |
36 | 39 |
| 40 /// Verifies that all deferred work has been completed. |
| 41 void finished() { |
| 42 assert(_deferredTypeSlots.isEmpty); |
| 43 } |
| 44 |
37 @override | 45 @override |
38 bool genericExpressionEnter( | 46 bool genericExpressionEnter( |
39 String expressionType, Expression expression, DartType typeContext) { | 47 String expressionType, Expression expression, DartType typeContext) { |
40 super.genericExpressionEnter(expressionType, expression, typeContext); | 48 super.genericExpressionEnter(expressionType, expression, typeContext); |
41 return true; | 49 return true; |
42 } | 50 } |
43 | 51 |
44 @override | 52 @override |
45 void genericExpressionExit( | 53 void genericExpressionExit( |
46 String expressionType, Expression expression, DartType inferredType) { | 54 String expressionType, Expression expression, DartType inferredType) { |
47 _recordType(inferredType, expression.fileOffset); | 55 _recordType(inferredType, expression.fileOffset); |
48 super.genericExpressionExit(expressionType, expression, inferredType); | 56 super.genericExpressionExit(expressionType, expression, inferredType); |
49 } | 57 } |
50 | 58 |
51 @override | 59 @override |
| 60 void methodInvocationBeforeArgs(Expression expression, bool isImplicitCall) { |
| 61 if (!isImplicitCall) { |
| 62 // We are visiting a method invocation like: a.f(args). We have visited a |
| 63 // but we haven't visited the args yet. |
| 64 // |
| 65 // The analyzer AST will expect a type for f at this point. (It can't |
| 66 // wait until later, because for all it knows, a.f might be a property |
| 67 // access, in which case the appropriate time for the type is now). But |
| 68 // the type isn't known yet (because it may depend on type inference based |
| 69 // on arguments). |
| 70 // |
| 71 // So we add a `null` to our list of types; we'll update it with the |
| 72 // actual type later. |
| 73 _deferredTypeSlots.add(_recordType(null, expression.fileOffset)); |
| 74 } |
| 75 super.methodInvocationBeforeArgs(expression, isImplicitCall); |
| 76 } |
| 77 |
| 78 @override |
| 79 void methodInvocationExit(Expression expression, Arguments arguments, |
| 80 bool isImplicitCall, DartType inferredType) { |
| 81 if (!isImplicitCall) { |
| 82 // TODO(paulberry): get the actual callee function type from the inference |
| 83 // engine |
| 84 var calleeType = const DynamicType(); |
| 85 _types[_deferredTypeSlots.removeLast()] = calleeType; |
| 86 } |
| 87 _recordType(inferredType, arguments.fileOffset); |
| 88 super.genericExpressionExit("methodInvocation", expression, inferredType); |
| 89 } |
| 90 |
| 91 @override |
| 92 bool staticInvocationEnter( |
| 93 StaticInvocation expression, DartType typeContext) { |
| 94 // We are visiting a static invocation like: f(args), and we haven't visited |
| 95 // args yet. |
| 96 // |
| 97 // The analyzer AST will expect a type for f at this point. (It can't wait |
| 98 // until later, because for all it knows, f is a method on `this`, and |
| 99 // methods need a type for f at this point--see comments in |
| 100 // [methodInvocationBeforeArgs]). But the type isn't known yet (because it |
| 101 // may depend on type inference based on arguments). |
| 102 // |
| 103 // So we add a `null` to our list of types; we'll update it with the actual |
| 104 // type later. |
| 105 _deferredTypeSlots.add(_recordType(null, expression.fileOffset)); |
| 106 return super.staticInvocationEnter(expression, typeContext); |
| 107 } |
| 108 |
| 109 @override |
| 110 void staticInvocationExit( |
| 111 StaticInvocation expression, DartType inferredType) { |
| 112 // TODO(paulberry): get the actual callee function type from the inference |
| 113 // engine |
| 114 var calleeType = const DynamicType(); |
| 115 _types[_deferredTypeSlots.removeLast()] = calleeType; |
| 116 _recordType(inferredType, expression.arguments.fileOffset); |
| 117 super.genericExpressionExit("staticInvocation", expression, inferredType); |
| 118 } |
| 119 |
| 120 @override |
52 void variableDeclarationEnter(VariableDeclaration statement) { | 121 void variableDeclarationEnter(VariableDeclaration statement) { |
53 _recordType(statement.type, statement.fileOffset); | 122 _recordType(statement.type, statement.fileOffset); |
54 super.variableDeclarationEnter(statement); | 123 super.variableDeclarationEnter(statement); |
55 } | 124 } |
56 | 125 |
57 void _recordType(DartType type, int offset) { | 126 int _recordType(DartType type, int offset) { |
| 127 int slot = _types.length; |
58 _types.add(type); | 128 _types.add(type); |
| 129 return slot; |
59 } | 130 } |
60 } | 131 } |
OLD | NEW |