OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 dev_compiler.src.codegen.reify_coercions; | 5 library dev_compiler.src.codegen.reify_coercions; |
6 | 6 |
7 import 'package:analyzer/analyzer.dart' as analyzer; | 7 import 'package:analyzer/analyzer.dart' as analyzer; |
8 import 'package:analyzer/src/generated/ast.dart'; | 8 import 'package:analyzer/src/generated/ast.dart'; |
9 import 'package:analyzer/src/generated/element.dart'; | 9 import 'package:analyzer/src/generated/element.dart'; |
10 import 'package:analyzer/src/task/strong/rules.dart'; | 10 import 'package:analyzer/src/generated/type_system.dart' |
| 11 show StrongTypeSystemImpl; |
11 import 'package:logging/logging.dart' as logger; | 12 import 'package:logging/logging.dart' as logger; |
12 | 13 |
13 import '../info.dart'; | 14 import '../info.dart'; |
14 | 15 |
15 import 'ast_builder.dart'; | 16 import 'ast_builder.dart'; |
16 | 17 |
17 final _log = new logger.Logger('dev_compiler.reify_coercions'); | 18 final _log = new logger.Logger('dev_compiler.reify_coercions'); |
18 | 19 |
19 // TODO(leafp) Factor this out or use an existing library | 20 // TODO(leafp) Factor this out or use an existing library |
20 class Tuple2<T0, T1> { | 21 class Tuple2<T0, T1> { |
(...skipping 10 matching lines...) Expand all Loading... |
31 LibraryElement importedFrom; | 32 LibraryElement importedFrom; |
32 | 33 |
33 /// True => use/def in same library | 34 /// True => use/def in same library |
34 bool fromCurrent; | 35 bool fromCurrent; |
35 | 36 |
36 /// True => not a source variable | 37 /// True => not a source variable |
37 bool synthetic; | 38 bool synthetic; |
38 NewTypeIdDesc({this.fromCurrent, this.importedFrom, this.synthetic}); | 39 NewTypeIdDesc({this.fromCurrent, this.importedFrom, this.synthetic}); |
39 } | 40 } |
40 | 41 |
41 class _Inference extends DownwardsInference { | |
42 TypeManager _tm; | |
43 | |
44 _Inference(TypeRules rules, this._tm) : super(rules); | |
45 | |
46 @override | |
47 void annotateCastFromDynamic(Expression e, DartType t) { | |
48 var cast = Coercion.cast(e.staticType, t); | |
49 var info = new DynamicCast(rules, e, cast); | |
50 CoercionInfo.set(e, info); | |
51 } | |
52 | |
53 @override | |
54 void annotateListLiteral(ListLiteral e, List<DartType> targs) { | |
55 var tNames = targs.map(_tm.typeNameFromDartType).toList(); | |
56 e.typeArguments = AstBuilder.typeArgumentList(tNames); | |
57 var listT = rules.provider.listType.substitute4(targs); | |
58 e.staticType = listT; | |
59 } | |
60 | |
61 @override | |
62 void annotateMapLiteral(MapLiteral e, List<DartType> targs) { | |
63 var tNames = targs.map(_tm.typeNameFromDartType).toList(); | |
64 e.typeArguments = AstBuilder.typeArgumentList(tNames); | |
65 var mapT = rules.provider.mapType.substitute4(targs); | |
66 e.staticType = mapT; | |
67 } | |
68 | |
69 @override | |
70 void annotateInstanceCreationExpression( | |
71 InstanceCreationExpression e, List<DartType> targs) { | |
72 var tNames = targs.map(_tm.typeNameFromDartType).toList(); | |
73 var cName = e.constructorName; | |
74 var id = cName.type.name; | |
75 var typeName = AstBuilder.typeName(id, tNames); | |
76 cName.type = typeName; | |
77 var newType = | |
78 (e.staticType.element as ClassElement).type.substitute4(targs); | |
79 e.staticType = newType; | |
80 typeName.type = newType; | |
81 } | |
82 | |
83 @override | |
84 void annotateFunctionExpression(FunctionExpression e, DartType returnType) { | |
85 // Implicitly changes e.staticType | |
86 (e.element as ExecutableElementImpl).returnType = returnType; | |
87 } | |
88 } | |
89 | |
90 // This class implements a pass which modifies (in place) the ast replacing | 42 // This class implements a pass which modifies (in place) the ast replacing |
91 // abstract coercion nodes with their dart implementations. | 43 // abstract coercion nodes with their dart implementations. |
92 class CoercionReifier extends analyzer.GeneralizingAstVisitor<Object> { | 44 class CoercionReifier extends analyzer.GeneralizingAstVisitor<Object> { |
93 final CoercionManager _cm; | 45 final CoercionManager _cm; |
94 final TypeManager _tm; | 46 final TypeManager _tm; |
95 final VariableManager _vm; | 47 final VariableManager _vm; |
96 final LibraryUnit _library; | 48 final LibraryUnit _library; |
97 final _Inference _inferrer; | 49 final StrongTypeSystemImpl _typeSystem; |
98 | 50 |
99 CoercionReifier._( | 51 CoercionReifier._( |
100 this._cm, this._tm, this._vm, this._library, this._inferrer); | 52 this._cm, this._tm, this._vm, this._library, this._typeSystem); |
101 | 53 |
102 factory CoercionReifier(LibraryUnit library, TypeRules rules) { | 54 factory CoercionReifier( |
| 55 LibraryUnit library, StrongTypeSystemImpl typeSystem) { |
103 var vm = new VariableManager(); | 56 var vm = new VariableManager(); |
104 var tm = new TypeManager(library.library.element.enclosingElement, vm); | 57 var tm = new TypeManager(library.library.element.enclosingElement, vm); |
105 var cm = new CoercionManager(vm, tm); | 58 var cm = new CoercionManager(vm, tm); |
106 var inferrer = new _Inference(rules, tm); | 59 return new CoercionReifier._(cm, tm, vm, library, typeSystem); |
107 return new CoercionReifier._(cm, tm, vm, library, inferrer); | |
108 } | 60 } |
109 | 61 |
110 // This should be the entry point for this class. Entering via the | 62 // This should be the entry point for this class. Entering via the |
111 // visit functions directly may not do the right thing with respect | 63 // visit functions directly may not do the right thing with respect |
112 // to discharging the collected definitions. | 64 // to discharging the collected definitions. |
113 // Returns the set of new type identifiers added by the reifier | 65 // Returns the set of new type identifiers added by the reifier |
114 Map<Identifier, NewTypeIdDesc> reify() { | 66 Map<Identifier, NewTypeIdDesc> reify() { |
115 _library.partsThenLibrary.forEach(visitCompilationUnit); | 67 _library.partsThenLibrary.forEach(visitCompilationUnit); |
116 return _tm.addedTypes; | 68 return _tm.addedTypes; |
117 } | 69 } |
118 | 70 |
119 @override | 71 @override |
120 Object visitExpression(Expression node) { | 72 Object visitExpression(Expression node) { |
121 var info = CoercionInfo.get(node); | 73 var info = CoercionInfo.get(node); |
122 if (info is InferredTypeBase) { | 74 if (info is InferredTypeBase) { |
123 return _visitInferredTypeBase(info, node); | 75 return _visitInferredTypeBase(info, node); |
124 } else if (info is DownCast) { | 76 } else if (info is DownCast) { |
125 return _visitDownCast(info, node); | 77 return _visitDownCast(info, node); |
126 } | 78 } |
127 return super.visitExpression(node); | 79 return super.visitExpression(node); |
128 } | 80 } |
129 | 81 |
130 ///////////////// Private ////////////////////////////////// | 82 ///////////////// Private ////////////////////////////////// |
131 | 83 |
132 Object _visitInferredTypeBase(InferredTypeBase node, Expression expr) { | 84 Object _visitInferredTypeBase(InferredTypeBase node, Expression expr) { |
133 var success = _inferrer.inferExpression(expr, node.type, <String>[]); | 85 DartType t = node.type; |
134 assert(success); | 86 if (!_typeSystem.isSubtypeOf(_getStaticType(expr), t)) { |
| 87 if (_getStaticType(expr).isDynamic) { |
| 88 var cast = Coercion.cast(expr.staticType, t); |
| 89 var info = new DynamicCast(_typeSystem, expr, cast); |
| 90 CoercionInfo.set(expr, info); |
| 91 } |
| 92 } |
135 expr.visitChildren(this); | 93 expr.visitChildren(this); |
136 return null; | 94 return null; |
137 } | 95 } |
138 | 96 |
139 Object _visitDownCast(DownCast node, Expression expr) { | 97 Object _visitDownCast(DownCast node, Expression expr) { |
140 var parent = expr.parent; | 98 var parent = expr.parent; |
141 expr.visitChildren(this); | 99 expr.visitChildren(this); |
142 Expression newE = _cm.coerceExpression(expr, node.cast); | 100 Expression newE = _cm.coerceExpression(expr, node.cast); |
143 if (!identical(expr, newE)) { | 101 if (!identical(expr, newE)) { |
144 var replaced = parent.accept(new NodeReplacer(expr, newE)); | 102 var replaced = parent.accept(new NodeReplacer(expr, newE)); |
145 // It looks like NodeReplacer will always return true. | 103 // It looks like NodeReplacer will always return true. |
146 // It does throw IllegalArgumentException though, if child is not found. | 104 // It does throw IllegalArgumentException though, if child is not found. |
147 assert(replaced); | 105 assert(replaced); |
148 } | 106 } |
149 return null; | 107 return null; |
150 } | 108 } |
151 | 109 |
152 Object visitCompilationUnit(CompilationUnit unit) { | 110 Object visitCompilationUnit(CompilationUnit unit) { |
153 _cm.enterCompilationUnit(unit); | 111 _cm.enterCompilationUnit(unit); |
154 Object ret = super.visitCompilationUnit(unit); | 112 Object ret = super.visitCompilationUnit(unit); |
155 _cm.exitCompilationUnit(unit); | 113 _cm.exitCompilationUnit(unit); |
156 return ret; | 114 return ret; |
157 } | 115 } |
| 116 |
| 117 DartType _getStaticType(Expression expr) { |
| 118 return expr.staticType ?? DynamicTypeImpl.instance; |
| 119 } |
158 } | 120 } |
159 | 121 |
160 // This provides a placeholder variable manager. Currently it simply | 122 // This provides a placeholder variable manager. Currently it simply |
161 // mangles names in a way unlikely (but not guaranteed) to avoid | 123 // mangles names in a way unlikely (but not guaranteed) to avoid |
162 // collisions with user variables. | 124 // collisions with user variables. |
163 // TODO(leafp): Replace this with something real. | 125 // TODO(leafp): Replace this with something real. |
164 class VariableManager { | 126 class VariableManager { |
165 // TODO(leafp): Hack, not for real. | 127 // TODO(leafp): Hack, not for real. |
166 int _id = 0; | 128 int _id = 0; |
167 | 129 |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 var t = _mkNewTypeName(dType, id, args); | 455 var t = _mkNewTypeName(dType, id, args); |
494 return t; | 456 return t; |
495 } | 457 } |
496 | 458 |
497 TypeName _mkNewTypeName(DartType type, Identifier id, List<TypeName> args) { | 459 TypeName _mkNewTypeName(DartType type, Identifier id, List<TypeName> args) { |
498 var t = AstBuilder.typeName(id, args); | 460 var t = AstBuilder.typeName(id, args); |
499 t.type = type; | 461 t.type = type; |
500 return t; | 462 return t; |
501 } | 463 } |
502 } | 464 } |
OLD | NEW |