Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: lib/src/codegen/reify_coercions.dart

Issue 1096583002: Reifier hookup (Closed) Base URL: git@github.com:dart-lang/dart-dev-compiler.git@master
Patch Set: Tweaks Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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:logging/logging.dart' as logger; 10 import 'package:logging/logging.dart' as logger;
11 import 'package:source_span/source_span.dart' show SourceFile; 11 import 'package:source_span/source_span.dart' show SourceFile;
12 12
13 import 'package:dev_compiler/src/checker/rules.dart'; 13 import 'package:dev_compiler/src/checker/rules.dart';
14 import 'package:dev_compiler/src/info.dart'; 14 import 'package:dev_compiler/src/info.dart';
15 import 'package:dev_compiler/src/options.dart' show CompilerOptions;
15 import 'package:dev_compiler/src/utils.dart' as utils; 16 import 'package:dev_compiler/src/utils.dart' as utils;
16 17
17 import 'ast_builder.dart'; 18 import 'ast_builder.dart';
18 19
19 final _log = new logger.Logger('dev_compiler.reify_coercions'); 20 final _log = new logger.Logger('dev_compiler.reify_coercions');
20 21
21 // TODO(leafp) Factor this out or use an existing library 22 // TODO(leafp) Factor this out or use an existing library
22 class Tuple2<T0, T1> { 23 class Tuple2<T0, T1> {
23 final T0 e0; 24 final T0 e0;
24 final T1 e1; 25 final T1 e1;
(...skipping 12 matching lines...) Expand all
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 _LocatedWrapper { 42 class _LocatedWrapper {
42 final String loc; 43 final String loc;
43 final Wrapper wrapper; 44 final Wrapper wrapper;
44 _LocatedWrapper(this.wrapper, this.loc); 45 _LocatedWrapper(this.wrapper, this.loc);
45 } 46 }
46 47
48 abstract class InstrumentedRuntime {
49 Expression wrap(Expression coercion, Expression e, Expression fromType,
50 Expression toType, Expression dartIs, String kind, String location);
51 Expression cast(Expression e, Expression fromType, Expression toType,
52 Expression dartIs, String kind, String location, bool ground);
53 Expression type(Expression witnessFunction);
54 }
55
47 class _Inference extends DownwardsInference { 56 class _Inference extends DownwardsInference {
48 TypeManager _tm; 57 TypeManager _tm;
49 58
50 _Inference(TypeRules rules, this._tm) : super(rules); 59 _Inference(TypeRules rules, this._tm) : super(rules);
51 60
52 @override 61 @override
53 void annotateCastFromDynamic(Expression e, DartType t) { 62 void annotateCastFromDynamic(Expression e, DartType t) {
54 var cast = Coercion.cast(e.staticType, t); 63 var cast = Coercion.cast(e.staticType, t);
55 var node = new DynamicCast(rules, e, cast); 64 var node = new DynamicCast(rules, e, cast);
56 if (!NodeReplacer.replace(e, node)) { 65 if (!NodeReplacer.replace(e, node)) {
(...skipping 18 matching lines...) Expand all
75 } 84 }
76 85
77 @override 86 @override
78 void annotateInstanceCreationExpression( 87 void annotateInstanceCreationExpression(
79 InstanceCreationExpression e, List<DartType> targs) { 88 InstanceCreationExpression e, List<DartType> targs) {
80 var tNames = targs.map(_tm.typeNameFromDartType).toList(); 89 var tNames = targs.map(_tm.typeNameFromDartType).toList();
81 var cName = e.constructorName; 90 var cName = e.constructorName;
82 var id = cName.type.name; 91 var id = cName.type.name;
83 var typeName = AstBuilder.typeName(id, tNames); 92 var typeName = AstBuilder.typeName(id, tNames);
84 cName.type = typeName; 93 cName.type = typeName;
85 var rawType = (e.staticType.element as ClassElement).type; 94 var newType =
86 e.staticType = rawType.substitute4(targs); 95 (e.staticType.element as ClassElement).type.substitute4(targs);
96 e.staticType = newType;
97 typeName.type = newType;
87 } 98 }
88 99
89 @override 100 @override
90 void annotateFunctionExpression(FunctionExpression e, DartType returnType) { 101 void annotateFunctionExpression(FunctionExpression e, DartType returnType) {
91 // Implicitly changes e.staticType 102 // Implicitly changes e.staticType
92 (e.element as ExecutableElementImpl).returnType = returnType; 103 (e.element as ExecutableElementImpl).returnType = returnType;
93 } 104 }
94 } 105 }
95 106
96 // This class implements a pass which modifies (in place) the ast replacing 107 // This class implements a pass which modifies (in place) the ast replacing
97 // abstract coercion nodes with their dart implementations. 108 // abstract coercion nodes with their dart implementations.
98 class CoercionReifier extends analyzer.GeneralizingAstVisitor<Object> 109 class CoercionReifier extends analyzer.GeneralizingAstVisitor<Object>
99 with ConversionVisitor<Object> { 110 with ConversionVisitor<Object> {
100 final CoercionManager _cm; 111 final CoercionManager _cm;
101 final TypeManager _tm; 112 final TypeManager _tm;
102 final VariableManager _vm; 113 final VariableManager _vm;
103 final LibraryUnit _library; 114 final LibraryUnit _library;
104 SourceFile _file; 115 SourceFile _file;
105 bool _skipCoercions = false; 116 bool _skipCoercions = false;
106 final TypeRules _rules; 117 final TypeRules _rules;
107 final _Inference _inferrer; 118 final _Inference _inferrer;
119 final InstrumentedRuntime _runtime;
120 final CompilerOptions _options;
108 121
109 CoercionReifier._( 122 CoercionReifier._(this._cm, this._tm, this._vm, this._library, this._rules,
110 this._cm, this._tm, this._vm, this._library, this._rules, this._inferrer); 123 this._inferrer, this._runtime, this._options);
111 124
112 factory CoercionReifier(LibraryUnit library, TypeRules rules) { 125 factory CoercionReifier(
126 LibraryUnit library, TypeRules rules, CompilerOptions options,
127 [InstrumentedRuntime runtime]) {
113 var vm = new VariableManager(); 128 var vm = new VariableManager();
114 var tm = new TypeManager(library.library.element.enclosingElement, vm); 129 var tm =
115 var cm = new CoercionManager(vm, tm, rules); 130 new TypeManager(library.library.element.enclosingElement, vm, runtime);
131 var cm = new CoercionManager(vm, tm, rules, runtime);
116 var inferrer = new _Inference(rules, tm); 132 var inferrer = new _Inference(rules, tm);
117 return new CoercionReifier._(cm, tm, vm, library, rules, inferrer); 133 return new CoercionReifier._(
134 cm, tm, vm, library, rules, inferrer, runtime, options);
118 } 135 }
119 136
120 // This should be the entry point for this class. Entering via the 137 // This should be the entry point for this class. Entering via the
121 // visit functions directly may not do the right thing with respect 138 // visit functions directly may not do the right thing with respect
122 // to discharging the collected definitions. 139 // to discharging the collected definitions.
123 // Returns the set of new type identifiers added by the reifier 140 // Returns the set of new type identifiers added by the reifier
124 Map<Identifier, NewTypeIdDesc> reify() { 141 Map<Identifier, NewTypeIdDesc> reify() {
125 _library.partsThenLibrary.forEach(generateUnit); 142 _library.partsThenLibrary.forEach(generateUnit);
126 return _tm.addedTypes; 143 return _tm.addedTypes;
127 } 144 }
128 145
129 void generateUnit(CompilationUnit unit) { 146 void generateUnit(CompilationUnit unit) {
130 _file = new SourceFile(unit.element.source.contents.data, 147 _file = new SourceFile(unit.element.source.contents.data,
131 url: unit.element.source.uri); 148 url: unit.element.source.uri);
132 visitCompilationUnit(unit); 149 visitCompilationUnit(unit);
133 _file = null; 150 _file = null;
134 } 151 }
135 152
136 ///////////////// Private ////////////////////////////////// 153 ///////////////// Private //////////////////////////////////
137 154
138 String _locationInfo(Expression e) { 155 String _locationInfo(Expression e) {
139 if (_file != null) { 156 if (_file != null) {
140 final begin = e is AnnotatedNode 157 final begin = e is AnnotatedNode
141 ? (e as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset 158 ? (e as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset
142 : e.offset; 159 : e.offset;
143 if (begin != 0) { 160 if (begin != 0 && e.end > begin) {
144 var span = _file.span(begin, e.end); 161 var span = _file.span(begin, e.end);
145 var s = span.message("Cast"); 162 var s = span.message("Cast");
146 return s.substring(0, s.indexOf("Cast")); 163 return s.substring(0, s.indexOf("Cast"));
147 } 164 }
148 } 165 }
149 return null; 166 return null;
150 } 167 }
151 168
152 static String _conversionKind(Conversion node) { 169 static String _conversionKind(Conversion node) {
153 if (node is ClosureWrapLiteral) return "WrapLiteral"; 170 if (node is ClosureWrapLiteral) return "WrapLiteral";
154 if (node is ClosureWrap) return "Wrap"; 171 if (node is ClosureWrap) return "Wrap";
155 if (node is DynamicCast) return "DynamicCast"; 172 if (node is DynamicCast) return "DynamicCast";
156 if (node is AssignmentCast) return "AssignmentCast"; 173 if (node is AssignmentCast) return "AssignmentCast";
157 if (node is UninferredClosure) return "InferableClosure"; 174 if (node is UninferredClosure) return "InferableClosure";
158 if (node is DownCastComposite) return "CompositeCast"; 175 if (node is DownCastComposite) return "CompositeCast";
159 if (node is DownCastImplicit) return "ImplicitCast"; 176 if (node is DownCastImplicit) return "ImplicitCast";
160 assert(false); 177 assert(false);
161 return ""; 178 return "";
162 } 179 }
163 180
164 @override 181 @override
165 Object visitAsExpression(AsExpression e) { 182 Object visitAsExpression(AsExpression e) {
183 if (_runtime == null) return super.visitAsExpression(e);
166 var cast = Coercion.cast(_rules.getStaticType(e.expression), e.type.type); 184 var cast = Coercion.cast(_rules.getStaticType(e.expression), e.type.type);
167 var loc = _locationInfo(e); 185 var loc = _locationInfo(e);
168 Expression castNode = 186 Expression castNode =
169 _cm.coerceExpression(e.expression, cast, "CastUser", loc); 187 _cm.coerceExpression(e.expression, cast, "CastUser", loc);
170 if (!NodeReplacer.replace(e, castNode)) { 188 if (!NodeReplacer.replace(e, castNode)) {
171 _log.severe("Failed to replace node for DownCast"); 189 _log.severe("Failed to replace node for DownCast");
172 } 190 }
173 castNode.accept(this); 191 castNode.accept(this);
174 return null; 192 return null;
175 } 193 }
176 194
177 @override 195 @override
178 Object visitInferredTypeBase(InferredTypeBase node) { 196 Object visitInferredTypeBase(InferredTypeBase node) {
179 var expr = node.node; 197 var expr = node.node;
180 var b = _inferrer.inferExpression(expr, node.type, <String>[]); 198 var b = _inferrer.inferExpression(expr, node.type, <String>[]);
181 assert(b); 199 assert(b);
182 if (!NodeReplacer.replace(node, expr)) { 200 if (!NodeReplacer.replace(node, expr)) {
183 _log.severe("Failed to replace node for InferredType"); 201 _log.severe("Failed to replace node for InferredType");
184 } 202 }
185 expr.accept(this); 203 expr.accept(this);
186 return null; 204 return null;
187 } 205 }
188 206
189 @override 207 @override
190 Object visitDownCast(DownCast node) { 208 Object visitDownCast(DownCast node) {
191 if (_skipCoercions) { 209 if (_skipCoercions && !_options.allowConstCasts) {
192 _log.severe("Skipping runtime downcast in constant context"); 210 _log.severe("Skipping runtime downcast in constant context");
193 return null; 211 return null;
194 } 212 }
195 String kind = _conversionKind(node); 213 String kind = _conversionKind(node);
196 var loc = _locationInfo(node); 214 var loc = _locationInfo(node);
197 Expression castNode = _cm.coerceExpression(node.node, node.cast, kind, loc); 215 Expression castNode = _cm.coerceExpression(node.node, node.cast, kind, loc);
198 if (!NodeReplacer.replace(node, castNode)) { 216 if (!NodeReplacer.replace(node, castNode)) {
199 _log.severe("Failed to replace node for DownCast"); 217 _log.severe("Failed to replace node for DownCast");
200 } 218 }
201 castNode.accept(this); 219 castNode.accept(this);
202 return null; 220 return null;
203 } 221 }
204 222
205 // TODO(leafp): Bind the coercions at the top level 223 // TODO(leafp): Bind the coercions at the top level
206 @override 224 @override
207 Object visitClosureWrapBase(ClosureWrapBase node) { 225 Object visitClosureWrapBase(ClosureWrapBase node) {
208 if (_skipCoercions) { 226 if (_skipCoercions && !_options.allowConstCasts) {
209 _log.severe("Skipping coercion wrap in constant context"); 227 _log.severe("Skipping coercion wrap in constant context");
210 return null; 228 return null;
211 } 229 }
212 String kind = _conversionKind(node); 230 String kind = _conversionKind(node);
213 var loc = _locationInfo(node); 231 var loc = _locationInfo(node);
214 Expression newE = _cm.coerceExpression(node.node, node.wrapper, kind, loc); 232 Expression newE = _cm.coerceExpression(node.node, node.wrapper, kind, loc);
215 if (!NodeReplacer.replace(node, newE)) { 233 if (!NodeReplacer.replace(node, newE)) {
216 _log.severe("Failed to replace node for Closure Wrap"); 234 _log.severe("Failed to replace node for Closure Wrap");
217 } 235 }
218 newE.accept(this); 236 newE.accept(this);
(...skipping 15 matching lines...) Expand all
234 } else if (n is ConstructorDeclaration) { 252 } else if (n is ConstructorDeclaration) {
235 _skipCoercions = o || n.element.isConst; 253 _skipCoercions = o || n.element.isConst;
236 } 254 }
237 } 255 }
238 Object ret = super.visitNode(n); 256 Object ret = super.visitNode(n);
239 _skipCoercions = o; 257 _skipCoercions = o;
240 return ret; 258 return ret;
241 } 259 }
242 260
243 Object visitCompilationUnit(CompilationUnit unit) { 261 Object visitCompilationUnit(CompilationUnit unit) {
244 _cm.enterCompilationUnit(); 262 _cm.enterCompilationUnit(unit);
245 Object ret = super.visitCompilationUnit(unit); 263 Object ret = super.visitCompilationUnit(unit);
246 _cm.exitCompilationUnit(unit); 264 _cm.exitCompilationUnit(unit);
247 return ret; 265 return ret;
248 } 266 }
249 267
250 @override 268 @override
251 Object visitClassDeclaration(ClassDeclaration cl) { 269 Object visitClassDeclaration(ClassDeclaration cl) {
252 _cm.enterClass(); 270 _cm.enterClass();
253 Object ret = super.visitClassDeclaration(cl); 271 Object ret = super.visitClassDeclaration(cl);
254 _cm.exitClass(cl); 272 _cm.exitClass(cl);
255 return ret; 273 return ret;
256 } 274 }
257 } 275 }
258 276
259 // This provides a placeholder variable manager. Currently it simply 277 // This provides a placeholder variable manager. Currently it simply
260 // mangles names in a way unlikely (but not guaranteed) to avoid 278 // mangles names in a way unlikely (but not guaranteed) to avoid
261 // collisions with user variables. 279 // collisions with user variables.
262 // TODO(leafp): Replace this with something real. 280 // TODO(leafp): Replace this with something real.
263 class VariableManager { 281 class VariableManager {
264 // TODO(leafp): Hack, not for real. 282 // TODO(leafp): Hack, not for real.
265 int _id = 0; 283 int _id = 0;
266 284
267 Identifier freshIdentifier(String hint) { 285 SimpleIdentifier freshIdentifier(String hint) {
268 String n = _id.toString(); 286 String n = _id.toString();
269 _id++; 287 _id++;
270 String s = "__$hint$n"; 288 String s = "__$hint$n";
271 return AstBuilder.identifierFromString(s); 289 return AstBuilder.identifierFromString(s);
Jennifer Messerly 2015/04/16 23:31:38 it'd be worth double checking how this identifier
Leaf 2015/04/17 20:49:36 The way JS code gen currently works, I don't think
272 } 290 }
273 291
274 Identifier freshTypeIdentifier(String hint) { 292 SimpleIdentifier freshTypeIdentifier(String hint) {
275 return freshIdentifier(hint); 293 return freshIdentifier(hint);
276 } 294 }
277 } 295 }
278 296
279 // This class manages the reification of coercions as dart code. Given a 297 // This class manages the reification of coercions as dart code. Given a
280 // coercion c and an expression e it will produce an expression e' which 298 // coercion c and an expression e it will produce an expression e' which
281 // is the result of coercing e using c. For closure wrappers, it maintains 299 // is the result of coercing e using c. For closure wrappers, it maintains
282 // a table of wrapper functions to be hoisted out to either the enclosing 300 // a table of wrapper functions to be hoisted out to either the enclosing
283 // class level, or to the top level if not in a class (hoisting only to the 301 // class level, or to the top level if not in a class (hoisting only to the
284 // class level avoids having to close over type variables, which is not 302 // class level avoids having to close over type variables, which is not
285 // easily done given the lack of generic functions). Generating the coercions 303 // easily done given the lack of generic functions). Generating the coercions
286 // inline is possible as well, but is quite a bit messier and harder to read 304 // inline is possible as well, but is quite a bit messier and harder to read
287 // since in general we need to bind the coerced expression to a lambda 305 // since in general we need to bind the coerced expression to a lambda
288 // bound variable, both in order to deal with side-effects and to be 306 // bound variable, both in order to deal with side-effects and to be
289 // able to properly record the return type of the wrapper function. 307 // able to properly record the return type of the wrapper function.
290 class CoercionManager { 308 class CoercionManager {
291 VariableManager _vm; 309 VariableManager _vm;
292 TypeManager _tm; 310 TypeManager _tm;
293 bool _hoistWrappers = false; 311 bool _hoistWrappers = false;
294 TypeRules _rules; 312 TypeRules _rules;
313 InstrumentedRuntime _runtime;
295 314
296 // A map containing all of the wrappers collected but not yet discharged 315 // A map containing all of the wrappers collected but not yet discharged
297 final Map<Identifier, _LocatedWrapper> _topWrappers = 316 final Map<Identifier, _LocatedWrapper> _topWrappers =
298 <Identifier, _LocatedWrapper>{}; 317 <Identifier, _LocatedWrapper>{};
299 final Map<Identifier, _LocatedWrapper> _classWrappers = 318 final Map<Identifier, _LocatedWrapper> _classWrappers =
300 <Identifier, _LocatedWrapper>{}; 319 <Identifier, _LocatedWrapper>{};
301 Map<Identifier, _LocatedWrapper> _wrappers; 320 Map<Identifier, _LocatedWrapper> _wrappers;
302 321
303 CoercionManager(this._vm, this._tm, this._rules) { 322 CoercionManager(this._vm, this._tm, this._rules, [this._runtime]) {
304 _wrappers = _topWrappers; 323 _wrappers = _topWrappers;
305 } 324 }
306 325
307 // Call on entry to and exit from a compilation unit in order to properly 326 // Call on entry to and exit from a compilation unit in order to properly
308 // discharge the accumulated wrappers. 327 // discharge the accumulated wrappers.
309 void enterCompilationUnit() { 328 void enterCompilationUnit(CompilationUnit unit) {
310 _tm.enterCompilationUnit(); 329 _tm.enterCompilationUnit(unit);
311 _wrappers = _topWrappers; 330 _wrappers = _topWrappers;
312 } 331 }
313 void exitCompilationUnit(CompilationUnit unit) { 332 void exitCompilationUnit(CompilationUnit unit) {
314 for (Identifier i in _wrappers.keys) { 333 for (Identifier i in _wrappers.keys) {
315 FunctionDeclaration f = 334 FunctionDeclaration f =
316 _buildCoercion(i, _wrappers[i].wrapper, _wrappers[i].loc, true); 335 _buildCoercion(i, _wrappers[i].wrapper, _wrappers[i].loc, true);
317 unit.declarations.add(f); 336 unit.declarations.add(f);
318 } 337 }
319 _wrappers.clear(); 338 _wrappers.clear();
320 _wrappers = _topWrappers; 339 _wrappers = _topWrappers;
(...skipping 30 matching lines...) Expand all
351 return new Tuple2(e1, (e2) => e2); 370 return new Tuple2(e1, (e2) => e2);
352 } 371 }
353 var id = _vm.freshIdentifier(hint); 372 var id = _vm.freshIdentifier(hint);
354 var fp = AstBuilder.simpleFormal(id, null); 373 var fp = AstBuilder.simpleFormal(id, null);
355 f(e2) => AstBuilder.parenthesize(AstBuilder.letExpression(fp, e1, e2)); 374 f(e2) => AstBuilder.parenthesize(AstBuilder.letExpression(fp, e1, e2));
356 return new Tuple2(id, f); 375 return new Tuple2(id, f);
357 } 376 }
358 377
359 Expression _wrapExpression(Expression e, Wrapper w, String k, String loc) { 378 Expression _wrapExpression(Expression e, Wrapper w, String k, String loc) {
360 var q = _addWrapper(w, loc); 379 var q = _addWrapper(w, loc);
380 if (_runtime == null) {
381 var app = AstBuilder.application(q, <Expression>[e]);
382 app.staticType = w.toType;
383 return app;
384 }
361 var ttName = _tm.typeNameFromDartType(w.toType); 385 var ttName = _tm.typeNameFromDartType(w.toType);
362 var tt = _tm.typeExpression(ttName); 386 var tt = _tm.typeExpression(ttName);
363 var ft = _tm.typeExpressionFromDartType(w.fromType); 387 var ft = _tm.typeExpressionFromDartType(w.fromType);
364 if (w.fromType.element.library != null && 388 if (w.fromType.element.library != null &&
365 utils.isDartPrivateLibrary(w.fromType.element.library)) { 389 utils.isDartPrivateLibrary(w.fromType.element.library)) {
366 ft = AstBuilder.nullLiteral(); 390 ft = AstBuilder.nullLiteral();
367 } 391 }
368 var tup = _bindExpression("x", e); 392 var tup = _bindExpression("x", e);
369 var id = tup.e0; 393 var id = tup.e0;
370 var binder = tup.e1; 394 var binder = tup.e1;
371 var kind = AstBuilder.stringLiteral(k);
372 var key = AstBuilder.multiLineStringLiteral(loc);
373 var dartIs = AstBuilder.isExpression(AstBuilder.parenthesize(id), ttName); 395 var dartIs = AstBuilder.isExpression(AstBuilder.parenthesize(id), ttName);
374 var arguments = <Expression>[q, id, ft, tt, kind, key, dartIs]; 396 var oper = _runtime.wrap(q, id, ft, tt, dartIs, k, loc);
375 return binder(new RuntimeOperation("wrap", arguments)); 397 return binder(oper);
376 } 398 }
377 399
378 Expression _castExpression(Expression e, Cast c, String k, String loc) { 400 Expression _castExpression(Expression e, Cast c, String k, String loc) {
379 var ttName = _tm.typeNameFromDartType(c.toType); 401 var ttName = _tm.typeNameFromDartType(c.toType);
402 if (_runtime == null) {
403 var cast = AstBuilder.asExpression(e, ttName);
404 cast.staticType = c.toType;
405 return cast;
406 }
380 var tt = _tm.typeExpression(ttName); 407 var tt = _tm.typeExpression(ttName);
381 var ft = _tm.typeExpressionFromDartType(c.fromType); 408 var ft = _tm.typeExpressionFromDartType(c.fromType);
382 if (c.fromType.element == null) { 409 if (c.fromType.element == null) {
383 // Replace bottom with Null type. 410 // Replace bottom with Null type.
384 var ftType = _rules.provider.nullType; 411 var ftType = _rules.provider.nullType;
385 ft = _tm.typeExpressionFromDartType(ftType); 412 ft = _tm.typeExpressionFromDartType(ftType);
386 } else if (c.fromType.element.library != null && 413 } else if (c.fromType.element.library != null &&
387 utils.isDartPrivateLibrary(c.fromType.element.library)) { 414 utils.isDartPrivateLibrary(c.fromType.element.library)) {
388 ft = AstBuilder.nullLiteral(); 415 ft = AstBuilder.nullLiteral();
389 } 416 }
390 var tup = _bindExpression("x", e); 417 var tup = _bindExpression("x", e);
391 var id = tup.e0; 418 var id = tup.e0;
392 var binder = tup.e1; 419 var binder = tup.e1;
393 var kind = AstBuilder.stringLiteral(k);
394 var key = AstBuilder.multiLineStringLiteral(loc);
395 var dartIs = AstBuilder.isExpression(AstBuilder.parenthesize(id), ttName); 420 var dartIs = AstBuilder.isExpression(AstBuilder.parenthesize(id), ttName);
396 var ground = AstBuilder.booleanLiteral(_rules.isGroundType(c.toType)); 421 var ground = _rules.isGroundType(c.toType);
397 var arguments = <Expression>[id, ft, tt, kind, key, dartIs, ground]; 422 var oper = _runtime.cast(id, ft, tt, dartIs, k, loc, ground);
398 return binder(new RuntimeOperation("cast", arguments)); 423 return binder(oper);
399 } 424 }
400 425
401 Expression _coerceExpression( 426 Expression _coerceExpression(
402 Expression e, Coercion c, String kind, String loc) { 427 Expression e, Coercion c, String kind, String loc) {
403 assert(c != null); 428 assert(c != null);
404 assert(c is! CoercionError); 429 assert(c is! CoercionError);
405 if (e is NamedExpression) { 430 if (e is NamedExpression) {
406 Expression inner = _coerceExpression(e.expression, c, kind, loc); 431 Expression inner = _coerceExpression(e.expression, c, kind, loc);
407 return new NamedExpression(e.name, inner); 432 return new NamedExpression(e.name, inner);
408 } 433 }
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 // and the AST type representation. It provides utilities to translate 572 // and the AST type representation. It provides utilities to translate
548 // a DartType to AST. In order to do so, it maintains a map of typedefs 573 // a DartType to AST. In order to do so, it maintains a map of typedefs
549 // naming otherwise un-named types. These must be discharged at the top 574 // naming otherwise un-named types. These must be discharged at the top
550 // level of the compilation unit in order to produce well-formed dart code. 575 // level of the compilation unit in order to produce well-formed dart code.
551 // Note that in order to hoist the typedefs out of parameterized classes 576 // Note that in order to hoist the typedefs out of parameterized classes
552 // we must close over any type variables. 577 // we must close over any type variables.
553 class TypeManager { 578 class TypeManager {
554 final VariableManager _vm; 579 final VariableManager _vm;
555 final LibraryElement _currentLibrary; 580 final LibraryElement _currentLibrary;
556 final Map<Identifier, NewTypeIdDesc> addedTypes = {}; 581 final Map<Identifier, NewTypeIdDesc> addedTypes = {};
582 final InstrumentedRuntime _runtime;
583 CompilationUnitElement _currentUnit;
557 584
558 /// A map containing new function typedefs to be introduced at the top level 585 /// A map containing new function typedefs to be introduced at the top level
559 /// This uses LinkedHashMap to emit code in a consistent order. 586 /// This uses LinkedHashMap to emit code in a consistent order.
560 final Map<FunctionType, FunctionTypeAlias> _typedefs = {}; 587 final Map<FunctionType, FunctionTypeAlias> _typedefs = {};
561 588
562 TypeManager(this._currentLibrary, this._vm); 589 TypeManager(this._currentLibrary, this._vm, [this._runtime]);
563 590
564 void enterCompilationUnit() {} 591 void enterCompilationUnit(CompilationUnit unit) {
592 _currentUnit = unit.element;
593 }
594
565 void exitCompilationUnit(CompilationUnit unit) { 595 void exitCompilationUnit(CompilationUnit unit) {
566 unit.declarations.addAll(_typedefs.values); 596 unit.declarations.addAll(_typedefs.values);
567 _typedefs.clear(); 597 _typedefs.clear();
568 } 598 }
569 599
570 TypeName typeNameFromDartType(DartType dType) { 600 TypeName typeNameFromDartType(DartType dType) {
571 return _typeNameFromDartType(dType); 601 return _typeNameFromDartType(dType);
572 } 602 }
573 603
574 NormalFormalParameter typedFormal(Identifier v, DartType type) { 604 NormalFormalParameter typedFormal(Identifier v, DartType type) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 _ft(type); 654 _ft(type);
625 return s.toList(); 655 return s.toList();
626 } 656 }
627 657
628 List<FormalParameter> _formalParameterListForFunctionType(FunctionType type) { 658 List<FormalParameter> _formalParameterListForFunctionType(FunctionType type) {
629 var namedParameters = type.namedParameterTypes; 659 var namedParameters = type.namedParameterTypes;
630 var normalParameters = type.normalParameterTypes; 660 var normalParameters = type.normalParameterTypes;
631 var optionalParameters = type.optionalParameterTypes; 661 var optionalParameters = type.optionalParameterTypes;
632 var params = new List<FormalParameter>(); 662 var params = new List<FormalParameter>();
633 for (int i = 0; i < normalParameters.length; i++) { 663 for (int i = 0; i < normalParameters.length; i++) {
634 FormalParameter fp = _anonymousFormal(normalParameters[i]); 664 FormalParameter fp =
635 params.add(AstBuilder.requiredFormal(fp)); 665 AstBuilder.requiredFormal(_anonymousFormal(normalParameters[i]));
666 ParameterElementImpl fe = new ParameterElementImpl.forNode(fp.identifier);
667 fe.parameterKind = fp.kind;
668 fe.type = normalParameters[i];
669 fp.identifier.staticElement = fe;
670 params.add(fp);
636 } 671 }
637 for (int i = 0; i < optionalParameters.length; i++) { 672 for (int i = 0; i < optionalParameters.length; i++) {
638 FormalParameter fp = _anonymousFormal(optionalParameters[i]); 673 FormalParameter fp =
639 params.add(AstBuilder.optionalFormal(fp)); 674 AstBuilder.optionalFormal(_anonymousFormal(optionalParameters[i]));
675 ParameterElementImpl fe = new ParameterElementImpl.forNode(fp.identifier);
Jennifer Messerly 2015/04/16 23:31:38 maybe try to encapsulate this? it seems like we're
Leaf 2015/04/17 20:49:35 Done.
676 fe.parameterKind = fp.kind;
677 fe.type = optionalParameters[i];
678 fp.identifier.staticElement = fe;
679 params.add(fp);
640 } 680 }
641 for (String k in namedParameters.keys) { 681 for (String k in namedParameters.keys) {
642 FormalParameter fp = _anonymousFormal(namedParameters[k]); 682 FormalParameter fp =
643 params.add(AstBuilder.namedFormal(fp)); 683 AstBuilder.namedFormal(_anonymousFormal(namedParameters[k]));
684 ParameterElementImpl fe = new ParameterElementImpl.forNode(fp.identifier);
685 fe.parameterKind = fp.kind;
686 fe.type = namedParameters[k];
687 fp.identifier.staticElement = fe;
688 params.add(fp);
644 } 689 }
645 return params; 690 return params;
646 } 691 }
647 692
648 FormalParameter _functionTypedFormal(Identifier v, FunctionType type) { 693 FormalParameter _functionTypedFormal(Identifier v, FunctionType type) {
649 assert(v != null); 694 assert(v != null);
650 var params = _formalParameterListForFunctionType(type); 695 var params = _formalParameterListForFunctionType(type);
651 var ret = typeNameFromDartType(type.returnType); 696 var ret = typeNameFromDartType(type.returnType);
652 return AstBuilder.functionTypedFormal(ret, v, params); 697 return AstBuilder.functionTypedFormal(ret, v, params);
653 } 698 }
654 699
655 NormalFormalParameter _anonymousFormal(DartType type) { 700 NormalFormalParameter _anonymousFormal(DartType type) {
656 Identifier u = _vm.freshIdentifier("u"); 701 Identifier u = _vm.freshIdentifier("u");
657 return _typedFormal(u, type); 702 return _typedFormal(u, type);
658 } 703 }
659 704
660 NormalFormalParameter _typedFormal(Identifier v, DartType type) { 705 NormalFormalParameter _typedFormal(Identifier v, DartType type) {
661 if (type is FunctionType) { 706 if (type is FunctionType) {
662 return _functionTypedFormal(v, type); 707 return _functionTypedFormal(v, type);
663 } 708 }
664 assert(type.name != null); 709 assert(type.name != null);
665 TypeName t = typeNameFromDartType(type); 710 TypeName t = typeNameFromDartType(type);
666 return AstBuilder.simpleFormal(v, t); 711 return AstBuilder.simpleFormal(v, t);
667 } 712 }
668 713
669 Identifier freshTypeDefVariable() { 714 SimpleIdentifier freshTypeDefVariable() {
670 var t = _vm.freshTypeIdentifier("t"); 715 var t = _vm.freshTypeIdentifier("t");
671 var desc = new NewTypeIdDesc( 716 var desc = new NewTypeIdDesc(
672 fromCurrent: true, importedFrom: _currentLibrary, synthetic: true); 717 fromCurrent: true, importedFrom: _currentLibrary, synthetic: true);
673 addedTypes[t] = desc; 718 addedTypes[t] = desc;
674 return t; 719 return t;
675 } 720 }
676 721
677 Identifier typeParameterFromString(String name) => 722 SimpleIdentifier typeParameterFromString(String name) =>
678 AstBuilder.identifierFromString(name); 723 AstBuilder.identifierFromString(name);
679 724
680 Identifier freshReferenceToNamedType(DartType type) { 725 SimpleIdentifier freshReferenceToNamedType(DartType type) {
681 var name = type.name; 726 var name = type.name;
682 assert(name != null); 727 assert(name != null);
683 var id = AstBuilder.identifierFromString(name); 728 var id = AstBuilder.identifierFromString(name);
684 var element = type.element; 729 var element = type.element;
685 id.staticElement = element; 730 id.staticElement = element;
686 var library = null; 731 var library = null;
687 // This can happen for types like (e.g.) void 732 // This can happen for types like (e.g.) void
688 if (element != null) library = element.library; 733 if (element != null) library = element.library;
689 var desc = new NewTypeIdDesc( 734 var desc = new NewTypeIdDesc(
690 fromCurrent: _currentLibrary == library, 735 fromCurrent: _currentLibrary == library,
691 importedFrom: library, 736 importedFrom: library,
692 synthetic: false); 737 synthetic: false);
693 addedTypes[id] = desc; 738 addedTypes[id] = desc;
694 return id; 739 return id;
695 } 740 }
696 741
742 FunctionTypeAlias _newResolvedTypedef(
743 FunctionType type, List<TypeParameterType> ftvs) {
744
745 // The name of the typedef (unresolved at this point)
Jennifer Messerly 2015/04/16 23:31:38 maybe a TODO for now and we can fix later, but: it
Leaf 2015/04/17 20:49:36 Suggestions as to meaningful names? I made the hi
746 SimpleIdentifier t = freshTypeDefVariable();
747 // The element for the new typedef
748 var element = new FunctionTypeAliasElementImpl(t.name, 0);
749
750 // Fresh type parameter identifiers for the free type variables
751 List<Identifier> tNames =
752 ftvs.map((x) => typeParameterFromString(x.name)).toList();
753 // The type parameters themselves
754 List<TypeParameter> tps = tNames.map(AstBuilder.typeParameter).toList();
755 // Allocate the elements for the type parameters, fill in their
756 // type (which makes no sense) and link up the various elements
757 // For each type parameter identifier, make an element and a type
758 // with that element, link the two together, set the identifier element
759 // to that element, and the identifier type to that type.
760 List<TypeParameterElement> tElements = tNames.map((x) {
761 var element = new TypeParameterElementImpl(x.name, 0);
762 var type = new TypeParameterTypeImpl(element);
763 element.type = type;
764 x.staticElement = element;
765 x.staticType = type;
766 return element;
767 }).toList();
768 // Get the types out from the elements
769 List<TypeParameterType> tTypes = tElements.map((x) => x.type).toList();
770 // Take the return type from the original type, and replace the free
771 // type variables with the fresh type variables
772 element.returnType = type.returnType.substitute2(tTypes, ftvs);
773 // Set the type parameter elements
774 element.typeParameters = tElements;
775 // Set the parent element to the current compilation unit
776 element.enclosingElement = _currentUnit;
777
778 // This is the type corresponding to the typedef. Note that
779 // almost all methods on this type delegate to the element, so it
780 // cannot be safely be used for anything until the element is fully resolved
781 FunctionTypeImpl substType = new FunctionTypeImpl.con2(element);
782 element.type = substType;
783 // Link the type and the element into the identifier for the typedef
784 t.staticType = substType;
785 t.staticElement = element;
786
787 // Make the formal parameters for the typedef, using the original type
788 // with the fresh type variables substituted in.
789 List<FormalParameter> fps =
790 _formalParameterListForFunctionType(type.substitute2(tTypes, ftvs));
791 // Get the static elements out of the parameters, and use them to
792 // initialize the parameters in the element model
793 element.parameters = fps.map((x) => x.identifier.staticElement).toList();
794 // Build the return type syntax
795 TypeName ret = _typeNameFromDartType(substType.returnType);
796 // This should now be fully resolved (or at least enough so for things
797 // to work so far).
798 FunctionTypeAlias alias = AstBuilder.functionTypeAlias(ret, t, tps, fps);
799
800 return alias;
801 }
802
697 // I think we can avoid alpha-varying type parameters, since 803 // I think we can avoid alpha-varying type parameters, since
698 // the binding forms are so limited, so we just re-use the 804 // the binding forms are so limited, so we just re-use the
699 // the original names for the formals and the actuals. 805 // the original names for the formals and the actuals.
700 TypeName _typeNameFromFunctionType(FunctionType type) { 806 TypeName _typeNameFromFunctionType(FunctionType type) {
701 if (_typedefs.containsKey(type)) { 807 if (_typedefs.containsKey(type)) {
702 var alias = _typedefs[type]; 808 var alias = _typedefs[type];
703 var ts = null; 809 var ts = null;
704 var tpl = alias.typeParameters; 810 var tpl = alias.typeParameters;
705 if (tpl != null) { 811 if (tpl != null) {
706 var ltp = tpl.typeParameters; 812 var ltp = tpl.typeParameters;
707 ts = new List<TypeName>.from( 813 ts = new List<TypeName>.from(
708 ltp.map((t) => _mkNewTypeName(t.name, null))); 814 ltp.map((t) => _mkNewTypeName(null, t.name, null)));
709 } 815 }
710 var name = alias.name; 816 var name = alias.name;
711 return _mkNewTypeName(name, ts); 817 return _mkNewTypeName(type, name, ts);
712 } 818 }
713 819
714 List<TypeParameterType> ftvs = _freeTypeVariables(type); 820 List<TypeParameterType> ftvs = _freeTypeVariables(type);
715 Identifier t = freshTypeDefVariable(); 821 FunctionTypeAlias alias = _newResolvedTypedef(type, ftvs);
716
717 Iterable<Identifier> tNames =
718 ftvs.map((x) => typeParameterFromString(x.name));
719 List<TypeParameter> tps = tNames.map(AstBuilder.typeParameter).toList();
720 List<FormalParameter> fps = _formalParameterListForFunctionType(type);
721 TypeName ret = _typeNameFromDartType(type.returnType);
722 FunctionTypeAlias alias = AstBuilder.functionTypeAlias(ret, t, tps, fps);
723
724 _typedefs[type] = alias; 822 _typedefs[type] = alias;
725 823
726 List<TypeName> args = ftvs.map(_typeNameFromDartType).toList(); 824 List<TypeName> args = ftvs.map(_typeNameFromDartType).toList();
727 TypeName namedType = _mkNewTypeName(t, args); 825 TypeName namedType =
826 _mkNewTypeName(alias.name.staticType, alias.name, args);
728 827
729 return namedType; 828 return namedType;
730 } 829 }
731 830
732 TypeName _typeNameFromDartType(DartType dType) { 831 TypeName _typeNameFromDartType(DartType dType) {
733 String name = dType.name; 832 String name = dType.name;
734 if (name == null || name == "" || dType.isBottom) { 833 if (name == null || name == "" || dType.isBottom) {
735 if (dType is FunctionType) return _typeNameFromFunctionType(dType); 834 if (dType is FunctionType) return _typeNameFromFunctionType(dType);
736 _log.severe("No name for type, casting through dynamic"); 835 _log.severe("No name for type, casting through dynamic");
737 var d = AstBuilder.identifierFromString("dynamic"); 836 var d = AstBuilder.identifierFromString("dynamic");
738 var t = _mkNewTypeName(d, null); 837 var t = _mkNewTypeName(dType, d, null);
739 t.type = dType;
740 return t; 838 return t;
741 } 839 }
742 SimpleIdentifier id = freshReferenceToNamedType(dType); 840 SimpleIdentifier id = freshReferenceToNamedType(dType);
743 List<TypeName> args = null; 841 List<TypeName> args = null;
744 if (dType is ParameterizedType) { 842 if (dType is ParameterizedType) {
745 List<DartType> targs = dType.typeArguments; 843 List<DartType> targs = dType.typeArguments;
746 args = targs.map(_typeNameFromDartType).toList(); 844 args = targs.map(_typeNameFromDartType).toList();
747 } 845 }
748 var t = _mkNewTypeName(id, args); 846 var t = _mkNewTypeName(dType, id, args);
749 t.type = dType;
750 return t; 847 return t;
751 } 848 }
752 849
753 TypeName _mkNewTypeName(Identifier id, List<TypeName> args) { 850 TypeName _mkNewTypeName(DartType type, Identifier id, List<TypeName> args) {
754 var t = AstBuilder.typeName(id, args); 851 var t = AstBuilder.typeName(id, args);
852 t.type = type;
755 return t; 853 return t;
756 } 854 }
757 855
758 Expression _typeExpression(TypeName t) { 856 Expression _typeExpression(TypeName t) {
857 assert(_runtime != null);
759 if (t.typeArguments != null && t.typeArguments.length > 0) { 858 if (t.typeArguments != null && t.typeArguments.length > 0) {
760 var w = AstBuilder.identifierFromString("_"); 859 var w = AstBuilder.identifierFromString("_");
761 var fp = AstBuilder.simpleFormal(w, t); 860 var fp = AstBuilder.simpleFormal(w, t);
762 var f = AstBuilder.blockFunction(<FormalParameter>[fp], <Statement>[]); 861 var f = AstBuilder.blockFunction(<FormalParameter>[fp], <Statement>[]);
763 return new RuntimeOperation("type", <Expression>[f]); 862 return _runtime.type(f);
764 } 863 }
765 return t.name; 864 return t.name;
766 } 865 }
767 } 866 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698