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

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

Issue 1169873002: dead code elimination in reify_coercions (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 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
« no previous file with comments | « no previous file | lib/src/info.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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:analyzer/src/generated/engine.dart' show AnalysisContext;
11 import 'package:logging/logging.dart' as logger; 10 import 'package:logging/logging.dart' as logger;
12 11
13 import 'package:dev_compiler/devc.dart' show AbstractCompiler; 12 import 'package:dev_compiler/devc.dart' show AbstractCompiler;
14 import 'package:dev_compiler/src/checker/rules.dart'; 13 import 'package:dev_compiler/src/checker/rules.dart';
15 import 'package:dev_compiler/src/info.dart'; 14 import 'package:dev_compiler/src/info.dart';
16 import 'package:dev_compiler/src/options.dart' show CompilerOptions; 15 import 'package:dev_compiler/src/options.dart' show CompilerOptions;
17 import 'package:dev_compiler/src/utils.dart' as utils;
18 16
19 import 'ast_builder.dart'; 17 import 'ast_builder.dart';
20 18
21 final _log = new logger.Logger('dev_compiler.reify_coercions'); 19 final _log = new logger.Logger('dev_compiler.reify_coercions');
22 20
23 // TODO(leafp) Factor this out or use an existing library 21 // TODO(leafp) Factor this out or use an existing library
24 class Tuple2<T0, T1> { 22 class Tuple2<T0, T1> {
25 final T0 e0; 23 final T0 e0;
26 final T1 e1; 24 final T1 e1;
27 Tuple2(this.e0, this.e1); 25 Tuple2(this.e0, this.e1);
28 } 26 }
29 27
30 typedef T Function1<S, T>(S _); 28 typedef T Function1<S, T>(S _);
31 29
32 class NewTypeIdDesc { 30 class NewTypeIdDesc {
33 /// If null, then this is not a library level identifier (i.e. it's 31 /// If null, then this is not a library level identifier (i.e. it's
34 /// a type parameter, or a special type like void, dynamic, etc) 32 /// a type parameter, or a special type like void, dynamic, etc)
35 LibraryElement importedFrom; 33 LibraryElement importedFrom;
36 /// True => use/def in same library 34 /// True => use/def in same library
37 bool fromCurrent; 35 bool fromCurrent;
38 /// True => not a source variable 36 /// True => not a source variable
39 bool synthetic; 37 bool synthetic;
40 NewTypeIdDesc({this.fromCurrent, this.importedFrom, this.synthetic}); 38 NewTypeIdDesc({this.fromCurrent, this.importedFrom, this.synthetic});
41 } 39 }
42 40
43 class _LocatedWrapper {
44 final String loc;
45 final Wrapper wrapper;
46 _LocatedWrapper(this.wrapper, this.loc);
47 }
48
49 abstract class InstrumentedRuntime {
50 Expression wrap(Expression coercion, Expression e, Expression fromType,
51 Expression toType, Expression dartIs, String kind, String location);
52 Expression cast(Expression e, Expression fromType, Expression toType,
53 Expression dartIs, String kind, String location, bool ground);
54 Expression type(Expression witnessFunction);
55 }
56
57 class _Inference extends DownwardsInference { 41 class _Inference extends DownwardsInference {
58 TypeManager _tm; 42 TypeManager _tm;
59 43
60 _Inference(TypeRules rules, this._tm) : super(rules); 44 _Inference(TypeRules rules, this._tm) : super(rules);
61 45
62 @override 46 @override
63 void annotateCastFromDynamic(Expression e, DartType t) { 47 void annotateCastFromDynamic(Expression e, DartType t) {
64 var cast = Coercion.cast(e.staticType, t); 48 var cast = Coercion.cast(e.staticType, t);
65 var node = new DynamicCast(rules, e, cast); 49 var node = new DynamicCast(rules, e, cast);
66 if (!NodeReplacer.replace(e, node)) { 50 if (!NodeReplacer.replace(e, node)) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 void annotateFunctionExpression(FunctionExpression e, DartType returnType) { 86 void annotateFunctionExpression(FunctionExpression e, DartType returnType) {
103 // Implicitly changes e.staticType 87 // Implicitly changes e.staticType
104 (e.element as ExecutableElementImpl).returnType = returnType; 88 (e.element as ExecutableElementImpl).returnType = returnType;
105 } 89 }
106 } 90 }
107 91
108 // This class implements a pass which modifies (in place) the ast replacing 92 // This class implements a pass which modifies (in place) the ast replacing
109 // abstract coercion nodes with their dart implementations. 93 // abstract coercion nodes with their dart implementations.
110 class CoercionReifier extends analyzer.GeneralizingAstVisitor<Object> 94 class CoercionReifier extends analyzer.GeneralizingAstVisitor<Object>
111 with ConversionVisitor<Object> { 95 with ConversionVisitor<Object> {
112 final AnalysisContext _context;
113 final CoercionManager _cm; 96 final CoercionManager _cm;
114 final TypeManager _tm; 97 final TypeManager _tm;
115 final VariableManager _vm; 98 final VariableManager _vm;
116 final LibraryUnit _library; 99 final LibraryUnit _library;
117 bool _skipCoercions = false; 100 bool _skipCoercions = false;
118 final TypeRules _rules;
119 final _Inference _inferrer; 101 final _Inference _inferrer;
120 final InstrumentedRuntime _runtime;
121 final CompilerOptions _options; 102 final CompilerOptions _options;
122 103
123 CompilationUnit _unit; 104 CoercionReifier._(this._cm, this._tm, this._vm, this._library, this._inferrer,
105 this._options);
124 106
125 CoercionReifier._(this._cm, this._tm, this._vm, this._library, this._rules, 107 factory CoercionReifier(LibraryUnit library, AbstractCompiler compiler) {
126 this._inferrer, this._runtime, this._context, this._options);
127
128 factory CoercionReifier(LibraryUnit library, AbstractCompiler compiler,
129 [InstrumentedRuntime runtime]) {
130 var vm = new VariableManager(); 108 var vm = new VariableManager();
131 var tm = 109 var tm = new TypeManager(library.library.element.enclosingElement, vm);
132 new TypeManager(library.library.element.enclosingElement, vm, runtime); 110 var cm = new CoercionManager(vm, tm);
133 var rules = compiler.rules; 111 var inferrer = new _Inference(compiler.rules, tm);
134 var cm = new CoercionManager(vm, tm, rules, runtime);
135 var inferrer = new _Inference(rules, tm);
136 var context = compiler.context;
137 var options = compiler.options; 112 var options = compiler.options;
138 return new CoercionReifier._( 113 return new CoercionReifier._(cm, tm, vm, library, inferrer, options);
139 cm, tm, vm, library, rules, inferrer, runtime, context, options);
140 } 114 }
141 115
142 // This should be the entry point for this class. Entering via the 116 // This should be the entry point for this class. Entering via the
143 // visit functions directly may not do the right thing with respect 117 // visit functions directly may not do the right thing with respect
144 // to discharging the collected definitions. 118 // to discharging the collected definitions.
145 // Returns the set of new type identifiers added by the reifier 119 // Returns the set of new type identifiers added by the reifier
146 Map<Identifier, NewTypeIdDesc> reify() { 120 Map<Identifier, NewTypeIdDesc> reify() {
147 _library.partsThenLibrary.forEach(generateUnit); 121 _library.partsThenLibrary.forEach(generateUnit);
148 return _tm.addedTypes; 122 return _tm.addedTypes;
149 } 123 }
150 124
151 void generateUnit(CompilationUnit unit) { 125 void generateUnit(CompilationUnit unit) {
152 _unit = unit;
153 visitCompilationUnit(unit); 126 visitCompilationUnit(unit);
154 _unit = null;
155 } 127 }
156 128
157 ///////////////// Private ////////////////////////////////// 129 ///////////////// Private //////////////////////////////////
158 130
159 String _locationInfo(Expression e) {
160 if (_unit != null) {
161 final begin = e is AnnotatedNode
162 ? (e as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset
163 : e.offset;
164 if (begin != 0 && e.end > begin) {
165 var span = utils.createSpan(_context, _unit, begin, e.end);
166 var s = span.message("Cast");
167 return s.substring(0, s.indexOf("Cast"));
168 }
169 }
170 return null;
171 }
172
173 static String _conversionKind(Conversion node) {
174 if (node is ClosureWrapLiteral) return "WrapLiteral";
175 if (node is ClosureWrap) return "Wrap";
176 if (node is DynamicCast) return "DynamicCast";
177 if (node is AssignmentCast) return "AssignmentCast";
178 if (node is UninferredClosure) return "InferableClosure";
179 if (node is DownCastComposite) return "CompositeCast";
180 if (node is DownCastImplicit) return "ImplicitCast";
181 assert(false);
182 return "";
183 }
184
185 @override
186 Object visitAsExpression(AsExpression e) {
187 if (_runtime == null) return super.visitAsExpression(e);
188 var cast = Coercion.cast(_rules.getStaticType(e.expression), e.type.type);
189 var loc = _locationInfo(e);
190 Expression castNode =
191 _cm.coerceExpression(e.expression, cast, "CastUser", loc);
192 if (!NodeReplacer.replace(e, castNode)) {
193 _log.severe("Failed to replace node for DownCast");
194 }
195 castNode.accept(this);
196 return null;
197 }
198
199 @override 131 @override
200 Object visitInferredTypeBase(InferredTypeBase node) { 132 Object visitInferredTypeBase(InferredTypeBase node) {
201 var expr = node.node; 133 var expr = node.node;
202 var b = _inferrer.inferExpression(expr, node.type, <String>[]); 134 var b = _inferrer.inferExpression(expr, node.type, <String>[]);
203 assert(b); 135 assert(b);
204 if (!NodeReplacer.replace(node, expr)) { 136 if (!NodeReplacer.replace(node, expr)) {
205 _log.severe("Failed to replace node for InferredType"); 137 _log.severe("Failed to replace node for InferredType");
206 } 138 }
207 expr.accept(this); 139 expr.accept(this);
208 return null; 140 return null;
209 } 141 }
210 142
211 @override 143 @override
212 Object visitDownCast(DownCast node) { 144 Object visitDownCast(DownCast node) {
213 if (_skipCoercions && !_options.allowConstCasts) { 145 if (_skipCoercions && !_options.allowConstCasts) {
214 _log.severe("Skipping runtime downcast in constant context"); 146 _log.severe("Skipping runtime downcast in constant context");
215 return null; 147 return null;
216 } 148 }
217 String kind = _conversionKind(node); 149 Expression castNode = _cm.coerceExpression(node.node, node.cast);
218 var loc = _locationInfo(node);
219 Expression castNode = _cm.coerceExpression(node.node, node.cast, kind, loc);
220 if (!NodeReplacer.replace(node, castNode)) { 150 if (!NodeReplacer.replace(node, castNode)) {
221 _log.severe("Failed to replace node for DownCast"); 151 _log.severe("Failed to replace node for DownCast");
222 } 152 }
223 castNode.accept(this); 153 castNode.accept(this);
224 return null; 154 return null;
225 } 155 }
226 156
227 // TODO(leafp): Bind the coercions at the top level 157 // TODO(leafp): Bind the coercions at the top level
228 @override 158 @override
229 Object visitClosureWrapBase(ClosureWrapBase node) { 159 Object visitClosureWrapBase(ClosureWrapBase node) {
230 if (_skipCoercions && !_options.allowConstCasts) { 160 if (_skipCoercions && !_options.allowConstCasts) {
231 _log.severe("Skipping coercion wrap in constant context"); 161 _log.severe("Skipping coercion wrap in constant context");
232 return null; 162 return null;
233 } 163 }
234 String kind = _conversionKind(node); 164 Expression newE = _cm.coerceExpression(node.node, node.wrapper);
235 var loc = _locationInfo(node);
236 Expression newE = _cm.coerceExpression(node.node, node.wrapper, kind, loc);
237 if (!NodeReplacer.replace(node, newE)) { 165 if (!NodeReplacer.replace(node, newE)) {
238 _log.severe("Failed to replace node for Closure Wrap"); 166 _log.severe("Failed to replace node for Closure Wrap");
239 } 167 }
240 newE.accept(this); 168 newE.accept(this);
241 return null; 169 return null;
242 } 170 }
243 171
244 @override 172 @override
245 Object visitNode(AstNode n) { 173 Object visitNode(AstNode n) {
246 var o = _skipCoercions; 174 var o = _skipCoercions;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 // class level avoids having to close over type variables, which is not 234 // class level avoids having to close over type variables, which is not
307 // easily done given the lack of generic functions). Generating the coercions 235 // easily done given the lack of generic functions). Generating the coercions
308 // inline is possible as well, but is quite a bit messier and harder to read 236 // inline is possible as well, but is quite a bit messier and harder to read
309 // since in general we need to bind the coerced expression to a lambda 237 // since in general we need to bind the coerced expression to a lambda
310 // bound variable, both in order to deal with side-effects and to be 238 // bound variable, both in order to deal with side-effects and to be
311 // able to properly record the return type of the wrapper function. 239 // able to properly record the return type of the wrapper function.
312 class CoercionManager { 240 class CoercionManager {
313 VariableManager _vm; 241 VariableManager _vm;
314 TypeManager _tm; 242 TypeManager _tm;
315 bool _hoistWrappers = false; 243 bool _hoistWrappers = false;
316 TypeRules _rules;
317 InstrumentedRuntime _runtime;
318 244
319 // A map containing all of the wrappers collected but not yet discharged 245 // A map containing all of the wrappers collected but not yet discharged
320 final Map<Identifier, _LocatedWrapper> _topWrappers = 246 final Map<Identifier, Wrapper> _topWrappers = <Identifier, Wrapper>{};
321 <Identifier, _LocatedWrapper>{}; 247 final Map<Identifier, Wrapper> _classWrappers = <Identifier, Wrapper>{};
322 final Map<Identifier, _LocatedWrapper> _classWrappers = 248 Map<Identifier, Wrapper> _wrappers;
323 <Identifier, _LocatedWrapper>{};
324 Map<Identifier, _LocatedWrapper> _wrappers;
325 249
326 CoercionManager(this._vm, this._tm, this._rules, [this._runtime]) { 250 CoercionManager(this._vm, this._tm) {
327 _wrappers = _topWrappers; 251 _wrappers = _topWrappers;
328 } 252 }
329 253
330 // Call on entry to and exit from a compilation unit in order to properly 254 // Call on entry to and exit from a compilation unit in order to properly
331 // discharge the accumulated wrappers. 255 // discharge the accumulated wrappers.
332 void enterCompilationUnit(CompilationUnit unit) { 256 void enterCompilationUnit(CompilationUnit unit) {
333 _tm.enterCompilationUnit(unit); 257 _tm.enterCompilationUnit(unit);
334 _wrappers = _topWrappers; 258 _wrappers = _topWrappers;
335 } 259 }
336 void exitCompilationUnit(CompilationUnit unit) { 260 void exitCompilationUnit(CompilationUnit unit) {
337 for (Identifier i in _wrappers.keys) { 261 for (Identifier i in _wrappers.keys) {
338 FunctionDeclaration f = 262 FunctionDeclaration f = _buildCoercion(i, _wrappers[i], true);
339 _buildCoercion(i, _wrappers[i].wrapper, _wrappers[i].loc, true);
340 unit.declarations.add(f); 263 unit.declarations.add(f);
341 } 264 }
342 _wrappers.clear(); 265 _wrappers.clear();
343 _wrappers = _topWrappers; 266 _wrappers = _topWrappers;
344 _tm.exitCompilationUnit(unit); 267 _tm.exitCompilationUnit(unit);
345 } 268 }
346 269
347 // Call on entry to and exit from a class in order to properly 270 // Call on entry to and exit from a class in order to properly
348 // discharge the accumulated wrappers. 271 // discharge the accumulated wrappers.
349 void enterClass() { 272 void enterClass() {
350 _wrappers = _classWrappers; 273 _wrappers = _classWrappers;
351 } 274 }
352 void exitClass(ClassDeclaration cl) { 275 void exitClass(ClassDeclaration cl) {
353 for (Identifier i in _wrappers.keys) { 276 for (Identifier i in _wrappers.keys) {
354 ClassMember f = 277 ClassMember f = _buildCoercion(i, _wrappers[i], false);
355 _buildCoercion(i, _wrappers[i].wrapper, _wrappers[i].loc, false);
356 cl.members.add(f); 278 cl.members.add(f);
357 } 279 }
358 _wrappers.clear(); 280 _wrappers.clear();
359 _wrappers = _topWrappers; 281 _wrappers = _topWrappers;
360 } 282 }
361 283
362 // The main entry point. Coerce e using c, returning a new expression, 284 // The main entry point. Coerce e using c, returning a new expression,
363 // possibly recording additional coercions functions and typedefs to 285 // possibly recording additional coercions functions and typedefs to
364 // be discharged at a higher level. 286 // be discharged at a higher level.
365 Expression coerceExpression( 287 Expression coerceExpression(Expression e, Coercion c) {
366 Expression e, Coercion c, String kind, String loc) {
367 return _coerceExpression(e, c, kind, loc);
368 }
369
370 ///////////////// Private //////////////////////////////////
371 Tuple2<Identifier, Function1<Expression, Expression>> _bindExpression(
372 String hint, Expression e1) {
373 if (e1 is Identifier) {
374 return new Tuple2(e1, (e2) => e2);
375 }
376 var id = _vm.freshIdentifier(hint);
377 var fp = AstBuilder.simpleFormal(id, null);
378 Expression f(Expression e2) =>
379 AstBuilder.parenthesize(AstBuilder.letExpression(fp, e1, e2));
380 return new Tuple2(id, f);
381 }
382
383 Expression _wrapExpression(Expression e, Wrapper w, String k, String loc) {
384 var q = _addWrapper(w, loc);
385 if (_runtime == null) {
386 var app = AstBuilder.application(q, <Expression>[e]);
387 app.staticType = w.toType;
388 return app;
389 }
390 var ttName = _tm.typeNameFromDartType(w.toType);
391 var tt = _tm.typeExpression(ttName);
392 var ft = _tm.typeExpressionFromDartType(w.fromType);
393 if (w.fromType.element.library != null &&
394 utils.isDartPrivateLibrary(w.fromType.element.library)) {
395 ft = AstBuilder.nullLiteral();
396 }
397 var tup = _bindExpression("x", e);
398 var id = tup.e0;
399 var binder = tup.e1;
400 var dartIs = AstBuilder.isExpression(AstBuilder.parenthesize(id), ttName);
401 var oper = _runtime.wrap(q, id, ft, tt, dartIs, k, loc);
402 return binder(oper);
403 }
404
405 Expression _castExpression(Expression e, Cast c, String k, String loc) {
406 var ttName = _tm.typeNameFromDartType(c.toType);
407 if (_runtime == null) {
408 var cast = AstBuilder.asExpression(e, ttName);
409 cast.staticType = c.toType;
410 return cast;
411 }
412 var tt = _tm.typeExpression(ttName);
413 var ft = _tm.typeExpressionFromDartType(c.fromType);
414 if (c.fromType.element == null) {
415 // Replace bottom with Null type.
416 var ftType = _rules.provider.nullType;
417 ft = _tm.typeExpressionFromDartType(ftType);
418 } else if (c.fromType.element.library != null &&
419 utils.isDartPrivateLibrary(c.fromType.element.library)) {
420 ft = AstBuilder.nullLiteral();
421 }
422 var tup = _bindExpression("x", e);
423 var id = tup.e0;
424 var binder = tup.e1;
425 var dartIs = AstBuilder.isExpression(AstBuilder.parenthesize(id), ttName);
426 var ground = _rules.isGroundType(c.toType);
427 var oper = _runtime.cast(id, ft, tt, dartIs, k, loc, ground);
428 return binder(oper);
429 }
430
431 Expression _coerceExpression(
432 Expression e, Coercion c, String kind, String loc) {
433 assert(c != null); 288 assert(c != null);
434 assert(c is! CoercionError); 289 assert(c is! CoercionError);
435 if (e is NamedExpression) { 290 if (e is NamedExpression) {
436 Expression inner = _coerceExpression(e.expression, c, kind, loc); 291 Expression inner = coerceExpression(e.expression, c);
437 return new NamedExpression(e.name, inner); 292 return new NamedExpression(e.name, inner);
438 } 293 }
439 if (c is Cast) return _castExpression(e, c, kind, loc); 294 if (c is Cast) return _castExpression(e, c);
440 if (c is Wrapper) return _wrapExpression(e, c, kind, loc); 295 if (c is Wrapper) return _wrapExpression(e, c);
441 assert(c is Identity); 296 assert(c is Identity);
442 return e; 297 return e;
443 } 298 }
444 299
445 Expression _addWrapper(Wrapper w, String loc) { 300 ///////////////// Private //////////////////////////////////
301
302 Expression _wrapExpression(Expression e, Wrapper w) {
303 var q = _addWrapper(w);
304 var app = AstBuilder.application(q, <Expression>[e]);
305 app.staticType = w.toType;
306 return app;
307 }
308
309 Expression _castExpression(Expression e, Cast c) {
310 var ttName = _tm.typeNameFromDartType(c.toType);
311 var cast = AstBuilder.asExpression(e, ttName);
312 cast.staticType = c.toType;
313 return cast;
314 }
315
316 Expression _addWrapper(Wrapper w) {
446 if (_hoistWrappers) { 317 if (_hoistWrappers) {
447 var q = _vm.freshIdentifier("q"); 318 var q = _vm.freshIdentifier("q");
448 _wrappers[q] = new _LocatedWrapper(w, loc); 319 _wrappers[q] = w;
449 return q; 320 return q;
450 } else { 321 } else {
451 return _buildCoercionExpression(w, loc); 322 return _buildCoercionExpression(w);
452 } 323 }
453 } 324 }
454 325
455 // Choose a canonical name for the ith coercion parameter 326 // Choose a canonical name for the ith coercion parameter
456 // with name "name". 327 // with name "name".
457 Identifier _coercionParameter(String name, int index) { 328 Identifier _coercionParameter(String name, int index) {
458 String s = name + index.toString(); 329 String s = name + index.toString();
459 return AstBuilder.identifierFromString(s); 330 return AstBuilder.identifierFromString(s);
460 } 331 }
461 332
(...skipping 17 matching lines...) Expand all
479 for (String k in namedParameters.keys) { 350 for (String k in namedParameters.keys) {
480 // TODO(leafp): These could collide with the generated names. 351 // TODO(leafp): These could collide with the generated names.
481 Identifier z = AstBuilder.identifierFromString(k); 352 Identifier z = AstBuilder.identifierFromString(k);
482 // We use the toType to avoid changing the reified type 353 // We use the toType to avoid changing the reified type
483 FormalParameter fp = _tm.typedFormal(z, namedParameters[k].toType); 354 FormalParameter fp = _tm.typedFormal(z, namedParameters[k].toType);
484 params.add(AstBuilder.namedFormal(fp)); 355 params.add(AstBuilder.namedFormal(fp));
485 } 356 }
486 return params; 357 return params;
487 } 358 }
488 359
489 List<Expression> _wrapperCoercedArguments(Wrapper wrapper, String loc) { 360 List<Expression> _wrapperCoercedArguments(Wrapper wrapper) {
490 var namedParameters = wrapper.namedParameters; 361 var namedParameters = wrapper.namedParameters;
491 var normalParameters = wrapper.normalParameters; 362 var normalParameters = wrapper.normalParameters;
492 var optionalParameters = wrapper.optionalParameters; 363 var optionalParameters = wrapper.optionalParameters;
493 var args = new List<Expression>(); 364 var args = new List<Expression>();
494 for (int i = 0; i < normalParameters.length; i++) { 365 for (int i = 0; i < normalParameters.length; i++) {
495 Identifier x = _coercionParameter("x", i); 366 Identifier x = _coercionParameter("x", i);
496 Expression e = 367 Expression e = coerceExpression(x, normalParameters[i]);
497 _coerceExpression(x, normalParameters[i], "CastParam", loc);
498 args.add(e); 368 args.add(e);
499 } 369 }
500 for (int i = 0; i < optionalParameters.length; i++) { 370 for (int i = 0; i < optionalParameters.length; i++) {
501 Identifier y = _coercionParameter("y", i); 371 Identifier y = _coercionParameter("y", i);
502 Expression e = 372 Expression e = coerceExpression(y, optionalParameters[i]);
503 _coerceExpression(y, optionalParameters[i], "CastParam", loc);
504 args.add(e); 373 args.add(e);
505 } 374 }
506 for (String k in namedParameters.keys) { 375 for (String k in namedParameters.keys) {
507 // TODO(leafp): These could collide with the generated names. 376 // TODO(leafp): These could collide with the generated names.
508 Identifier z = AstBuilder.identifierFromString(k); 377 Identifier z = AstBuilder.identifierFromString(k);
509 Expression e = _coerceExpression(z, namedParameters[k], "CastParam", loc); 378 Expression e = coerceExpression(z, namedParameters[k]);
510 args.add(AstBuilder.namedParameter(k, e)); 379 args.add(AstBuilder.namedParameter(k, e));
511 } 380 }
512 return args; 381 return args;
513 } 382 }
514 383
515 // Given an identifier c, a value f and a coercion q : T0 -> T1 => S0 -> S1 384 // Given an identifier c, a value f and a coercion q : T0 -> T1 => S0 -> S1
516 // wrap f using q and bind it to variable c 385 // wrap f using q and bind it to variable c
517 // T1 c(T0 x) => (f(x as T0) as S1) 386 // T1 c(T0 x) => (f(x as T0) as S1)
518 // Note that we use the "fromType" to decorate the wrapper 387 // Note that we use the "fromType" to decorate the wrapper
519 // rather than the "toType" to avoid changing the reified type 388 // rather than the "toType" to avoid changing the reified type
520 // TODO(leafp): If we wrap non-function literals, we can still 389 // TODO(leafp): If we wrap non-function literals, we can still
521 // end up changing the runtime reified type, since we build a function 390 // end up changing the runtime reified type, since we build a function
522 // literal based on the static type. 391 // literal based on the static type.
523 FunctionDeclarationStatement _wrapperMkInner( 392 FunctionDeclarationStatement _wrapperMkInner(
524 Identifier c, Expression f, Wrapper wrapper, String loc) { 393 Identifier c, Expression f, Wrapper wrapper) {
525 List<FormalParameter> params = _wrapperFormalParameters(wrapper); 394 List<FormalParameter> params = _wrapperFormalParameters(wrapper);
526 List<Expression> args = _wrapperCoercedArguments(wrapper, loc); 395 List<Expression> args = _wrapperCoercedArguments(wrapper);
527 Expression app = AstBuilder.application(f, args); 396 Expression app = AstBuilder.application(f, args);
528 Expression body = _coerceExpression(app, wrapper.ret, "CastResult", loc); 397 Expression body = coerceExpression(app, wrapper.ret);
529 FunctionExpression ce = AstBuilder.expressionFunction(params, body, true); 398 FunctionExpression ce = AstBuilder.expressionFunction(params, body, true);
530 TypeName rt = 399 TypeName rt =
531 _tm.typeNameFromDartType((wrapper.fromType as FunctionType).returnType); 400 _tm.typeNameFromDartType((wrapper.fromType as FunctionType).returnType);
532 Statement cDec = AstBuilder.functionDeclarationStatement(rt, c, ce); 401 Statement cDec = AstBuilder.functionDeclarationStatement(rt, c, ce);
533 return cDec; 402 return cDec;
534 } 403 }
535 404
536 Tuple2<List<FormalParameter>, List<Statement>> _buildCoercionBody( 405 Tuple2<List<FormalParameter>, List<Statement>> _buildCoercionBody(
537 Wrapper wrapper, String loc) { 406 Wrapper wrapper) {
538 var f = AstBuilder.identifierFromString("f"); 407 var f = AstBuilder.identifierFromString("f");
539 var c = AstBuilder.identifierFromString("c"); 408 var c = AstBuilder.identifierFromString("c");
540 var cDec = _wrapperMkInner(c, f, wrapper, loc); 409 var cDec = _wrapperMkInner(c, f, wrapper);
541 var comp = AstBuilder.binaryExpression(f, "==", AstBuilder.nullLiteral()); 410 var comp = AstBuilder.binaryExpression(f, "==", AstBuilder.nullLiteral());
542 var n = AstBuilder.nullLiteral(); 411 var n = AstBuilder.nullLiteral();
543 var cond = AstBuilder.conditionalExpression(comp, n, c); 412 var cond = AstBuilder.conditionalExpression(comp, n, c);
544 var stmts = <Statement>[cDec, AstBuilder.returnExpression(cond)]; 413 var stmts = <Statement>[cDec, AstBuilder.returnExpression(cond)];
545 var fp = _tm.typedFormal(f, wrapper.fromType); 414 var fp = _tm.typedFormal(f, wrapper.fromType);
546 var params = <FormalParameter>[fp]; 415 var params = <FormalParameter>[fp];
547 return new Tuple2<List<FormalParameter>, List<Statement>>(params, stmts); 416 return new Tuple2<List<FormalParameter>, List<Statement>>(params, stmts);
548 } 417 }
549 418
550 Expression _buildCoercionExpression(Wrapper wrapper, String loc) { 419 Expression _buildCoercionExpression(Wrapper wrapper) {
551 var tup = _buildCoercionBody(wrapper, loc); 420 var tup = _buildCoercionBody(wrapper);
552 return AstBuilder.blockFunction(tup.e0, tup.e1); 421 return AstBuilder.blockFunction(tup.e0, tup.e1);
553 } 422 }
554 423
555 // Given a name g and coercion q : T0 -> T1 => S0 -> S1 424 // Given a name g and coercion q : T0 -> T1 => S0 -> S1
556 // Bind g to a function or static method which maps 425 // Bind g to a function or static method which maps
557 // T0 -> T1 functions to S0 -> S1 functions. 426 // T0 -> T1 functions to S0 -> S1 functions.
558 // T0 -> T1 g(S1 f(S0)) { 427 // T0 -> T1 g(S1 f(S0)) {
559 // T1 c(T0 x) => (f(x as T0) as S1); 428 // T1 c(T0 x) => (f(x as T0) as S1);
560 // return (f == null) ? null : c; 429 // return (f == null) ? null : c;
561 // } 430 // }
562 Declaration _buildCoercion( 431 Declaration _buildCoercion(Identifier q, Wrapper wrapper, bool top) {
563 Identifier q, Wrapper wrapper, String loc, bool top) { 432 var tup = _buildCoercionBody(wrapper);
564 var tup = _buildCoercionBody(wrapper, loc);
565 var params = tup.e0; 433 var params = tup.e0;
566 var stmts = tup.e1; 434 var stmts = tup.e1;
567 TypeName rt = _tm.typeNameFromDartType(wrapper.toType); 435 TypeName rt = _tm.typeNameFromDartType(wrapper.toType);
568 if (top) { 436 if (top) {
569 return AstBuilder.blockFunctionDeclaration(rt, q, params, stmts); 437 return AstBuilder.blockFunctionDeclaration(rt, q, params, stmts);
570 } else { 438 } else {
571 return AstBuilder.blockMethodDeclaration(rt, q, params, stmts); 439 return AstBuilder.blockMethodDeclaration(rt, q, params, stmts);
572 } 440 }
573 } 441 }
574 } 442 }
575 443
576 // A class for managing the interaction between the DartType hierarchy 444 // A class for managing the interaction between the DartType hierarchy
577 // and the AST type representation. It provides utilities to translate 445 // and the AST type representation. It provides utilities to translate
578 // a DartType to AST. In order to do so, it maintains a map of typedefs 446 // a DartType to AST. In order to do so, it maintains a map of typedefs
579 // naming otherwise un-named types. These must be discharged at the top 447 // naming otherwise un-named types. These must be discharged at the top
580 // level of the compilation unit in order to produce well-formed dart code. 448 // level of the compilation unit in order to produce well-formed dart code.
581 // Note that in order to hoist the typedefs out of parameterized classes 449 // Note that in order to hoist the typedefs out of parameterized classes
582 // we must close over any type variables. 450 // we must close over any type variables.
583 class TypeManager { 451 class TypeManager {
584 final VariableManager _vm; 452 final VariableManager _vm;
585 final LibraryElement _currentLibrary; 453 final LibraryElement _currentLibrary;
586 final Map<Identifier, NewTypeIdDesc> addedTypes = {}; 454 final Map<Identifier, NewTypeIdDesc> addedTypes = {};
587 final InstrumentedRuntime _runtime;
588 CompilationUnitElement _currentUnit; 455 CompilationUnitElement _currentUnit;
589 456
590 /// A map containing new function typedefs to be introduced at the top level 457 /// A map containing new function typedefs to be introduced at the top level
591 /// This uses LinkedHashMap to emit code in a consistent order. 458 /// This uses LinkedHashMap to emit code in a consistent order.
592 final Map<FunctionType, FunctionTypeAlias> _typedefs = {}; 459 final Map<FunctionType, FunctionTypeAlias> _typedefs = {};
593 460
594 TypeManager(this._currentLibrary, this._vm, [this._runtime]); 461 TypeManager(this._currentLibrary, this._vm);
595 462
596 void enterCompilationUnit(CompilationUnit unit) { 463 void enterCompilationUnit(CompilationUnit unit) {
597 _currentUnit = unit.element; 464 _currentUnit = unit.element;
598 } 465 }
599 466
600 void exitCompilationUnit(CompilationUnit unit) { 467 void exitCompilationUnit(CompilationUnit unit) {
601 unit.declarations.addAll(_typedefs.values); 468 unit.declarations.addAll(_typedefs.values);
602 _typedefs.clear(); 469 _typedefs.clear();
603 } 470 }
604 471
605 TypeName typeNameFromDartType(DartType dType) { 472 TypeName typeNameFromDartType(DartType dType) {
606 return _typeNameFromDartType(dType); 473 return _typeNameFromDartType(dType);
607 } 474 }
608 475
609 NormalFormalParameter typedFormal(Identifier v, DartType type) { 476 NormalFormalParameter typedFormal(Identifier v, DartType type) {
610 return _typedFormal(v, type); 477 return _typedFormal(v, type);
611 } 478 }
612 479
613 Expression typeExpressionFromDartType(DartType t) =>
614 typeExpression(typeNameFromDartType(t));
615
616 Expression typeExpression(TypeName t) => _typeExpression(t);
617
618 ///////////////// Private ////////////////////////////////// 480 ///////////////// Private //////////////////////////////////
619 List<TypeParameterType> _freeTypeVariables(DartType type) { 481 List<TypeParameterType> _freeTypeVariables(DartType type) {
620 var s = new Set<TypeParameterType>(); 482 var s = new Set<TypeParameterType>();
621 483
622 void _ft(DartType type) { 484 void _ft(DartType type) {
623 void _ftMap(Map<String, DartType> m) { 485 void _ftMap(Map<String, DartType> m) {
624 if (m == null) return; 486 if (m == null) return;
625 for (var k in m.keys) _ft(m[k]); 487 for (var k in m.keys) _ft(m[k]);
626 } 488 }
627 void _ftList(List<DartType> l) { 489 void _ftList(List<DartType> l) {
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 } 713 }
852 var t = _mkNewTypeName(dType, id, args); 714 var t = _mkNewTypeName(dType, id, args);
853 return t; 715 return t;
854 } 716 }
855 717
856 TypeName _mkNewTypeName(DartType type, Identifier id, List<TypeName> args) { 718 TypeName _mkNewTypeName(DartType type, Identifier id, List<TypeName> args) {
857 var t = AstBuilder.typeName(id, args); 719 var t = AstBuilder.typeName(id, args);
858 t.type = type; 720 t.type = type;
859 return t; 721 return t;
860 } 722 }
861
862 Expression _typeExpression(TypeName t) {
863 assert(_runtime != null);
864 if (t.typeArguments != null && t.typeArguments.length > 0) {
865 var w = AstBuilder.identifierFromString("_");
866 var fp = AstBuilder.simpleFormal(w, t);
867 var f = AstBuilder.blockFunction(<FormalParameter>[fp], <Statement>[]);
868 return _runtime.type(f);
869 }
870 return t.name;
871 }
872 } 723 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/info.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698