| 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 /// Defines static information collected by the type checker and used later by | 5 /// Defines static information collected by the type checker and used later by |
| 6 /// emitters to generate code. | 6 /// emitters to generate code. |
| 7 library dev_compiler.src.info; | 7 library dev_compiler.src.info; |
| 8 | 8 |
| 9 import 'dart:mirrors'; | 9 import 'dart:mirrors'; |
| 10 | 10 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 // The abstract type of coercions mapping one type to another. | 68 // The abstract type of coercions mapping one type to another. |
| 69 // This class also exposes static builder functions which | 69 // This class also exposes static builder functions which |
| 70 // check for errors and reduce redundant coercions to the identity. | 70 // check for errors and reduce redundant coercions to the identity. |
| 71 abstract class Coercion { | 71 abstract class Coercion { |
| 72 final DartType fromType; | 72 final DartType fromType; |
| 73 final DartType toType; | 73 final DartType toType; |
| 74 Coercion(this.fromType, this.toType); | 74 Coercion(this.fromType, this.toType); |
| 75 static Coercion cast(DartType fromT, DartType toT) => new Cast(fromT, toT); | 75 static Coercion cast(DartType fromT, DartType toT) => new Cast(fromT, toT); |
| 76 static Coercion identity(DartType type) => new Identity(type); | 76 static Coercion identity(DartType type) => new Identity(type); |
| 77 static Coercion error() => new CoercionError(); | 77 static Coercion error() => new CoercionError(); |
| 78 static Coercion wrapper(DartType fromType, DartType toType, | |
| 79 List<Coercion> normalParameters, List<Coercion> optionalParameters, | |
| 80 Map<String, Coercion> namedParameters, Coercion ret) { | |
| 81 { | |
| 82 // If any sub coercion is error, return error | |
| 83 bool isError(Coercion c) => c is CoercionError; | |
| 84 if (ret is CoercionError) return error(); | |
| 85 if (namedParameters.values.any(isError)) return error(); | |
| 86 if (normalParameters.any(isError)) return error(); | |
| 87 if (optionalParameters.any(isError)) return error(); | |
| 88 } | |
| 89 { | |
| 90 // If all sub coercions are the identity, return identity | |
| 91 bool folder(bool id, Coercion c) => id && (c is Identity); | |
| 92 bool id = (ret is CoercionError); | |
| 93 id = namedParameters.values.fold(id, folder); | |
| 94 id = normalParameters.fold(id, folder); | |
| 95 id = optionalParameters.fold(id, folder); | |
| 96 if (id) return identity(fromType); | |
| 97 } | |
| 98 return new Wrapper(fromType, toType, normalParameters, optionalParameters, | |
| 99 namedParameters, ret); | |
| 100 } | |
| 101 } | 78 } |
| 102 | 79 |
| 103 // Coercion which casts one type to another | 80 // Coercion which casts one type to another |
| 104 class Cast extends Coercion { | 81 class Cast extends Coercion { |
| 105 Cast(DartType fromType, DartType toType) : super(fromType, toType); | 82 Cast(DartType fromType, DartType toType) : super(fromType, toType); |
| 106 } | 83 } |
| 107 | 84 |
| 108 // The identity coercion | 85 // The identity coercion |
| 109 class Identity extends Coercion { | 86 class Identity extends Coercion { |
| 110 Identity(DartType fromType) : super(fromType, fromType); | 87 Identity(DartType fromType) : super(fromType, fromType); |
| 111 } | 88 } |
| 112 | 89 |
| 113 // A closure wrapper coercion. | |
| 114 // The parameter coercions are the coercions which should | |
| 115 // be applied to coerce the wrapper parameters to the | |
| 116 // appropriate type for the wrapped closure. | |
| 117 // The return coercion is appropriate to coerce the return | |
| 118 // value of the wrapped function to the type expected by the | |
| 119 // context. | |
| 120 class Wrapper extends Coercion { | |
| 121 final Map<String, Coercion> namedParameters; | |
| 122 final List<Coercion> normalParameters; | |
| 123 final List<Coercion> optionalParameters; | |
| 124 final Coercion ret; | |
| 125 Wrapper(DartType fromType, DartType toType, this.normalParameters, | |
| 126 this.optionalParameters, this.namedParameters, this.ret) | |
| 127 : super(fromType, toType); | |
| 128 } | |
| 129 | |
| 130 // The error coercion. This coercion signals that a coercion | 90 // The error coercion. This coercion signals that a coercion |
| 131 // could not be generated. The code generator should not see | 91 // could not be generated. The code generator should not see |
| 132 // these. | 92 // these. |
| 133 class CoercionError extends Coercion { | 93 class CoercionError extends Coercion { |
| 134 CoercionError() : super(null, null); | 94 CoercionError() : super(null, null); |
| 135 } | 95 } |
| 136 | 96 |
| 137 abstract class StaticInfo implements Message { | 97 abstract class StaticInfo implements Message { |
| 138 /// AST Node this info is attached to. | 98 /// AST Node this info is attached to. |
| 139 // TODO(jmesserly): this is somewhat redundant with SemanticNode. | 99 // TODO(jmesserly): this is somewhat redundant with SemanticNode. |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 InferredTypeAllocation(TypeRules rules, Expression expression, DartType type) | 366 InferredTypeAllocation(TypeRules rules, Expression expression, DartType type) |
| 407 : super._internal(rules, expression, type); | 367 : super._internal(rules, expression, type); |
| 408 } | 368 } |
| 409 | 369 |
| 410 // An inferred type for a closure expression | 370 // An inferred type for a closure expression |
| 411 class InferredTypeClosure extends InferredTypeBase { | 371 class InferredTypeClosure extends InferredTypeBase { |
| 412 InferredTypeClosure(TypeRules rules, Expression expression, DartType type) | 372 InferredTypeClosure(TypeRules rules, Expression expression, DartType type) |
| 413 : super._internal(rules, expression, type); | 373 : super._internal(rules, expression, type); |
| 414 } | 374 } |
| 415 | 375 |
| 416 // TODO(vsm): Remove these. | |
| 417 | |
| 418 // A wrapped closure coerces the underlying type to the desired type. | |
| 419 class ClosureWrapBase extends Conversion { | |
| 420 FunctionType _wrappedType; | |
| 421 Wrapper _wrapper; | |
| 422 | |
| 423 ClosureWrapBase._internal( | |
| 424 TypeRules rules, Expression expression, this._wrapper, this._wrappedType) | |
| 425 : super(rules, expression) { | |
| 426 assert(baseType is FunctionType); | |
| 427 assert(!rules.isSubTypeOf(baseType, _wrappedType)); | |
| 428 } | |
| 429 | |
| 430 DartType _getConvertedType() => _wrappedType; | |
| 431 | |
| 432 String get message => '$expression ($baseType) will need to be wrapped ' | |
| 433 'with a closure of type $convertedType'; | |
| 434 | |
| 435 Level get level => Level.WARNING; | |
| 436 | |
| 437 Wrapper get wrapper => _wrapper; | |
| 438 | |
| 439 accept(AstVisitor visitor) { | |
| 440 if (visitor is ConversionVisitor) { | |
| 441 return visitor.visitClosureWrapBase(this); | |
| 442 } else { | |
| 443 return expression.accept(visitor); | |
| 444 } | |
| 445 } | |
| 446 } | |
| 447 | |
| 448 // Standard closure wrapping. | |
| 449 class ClosureWrap extends ClosureWrapBase { | |
| 450 ClosureWrap(TypeRules rules, Expression expression, Wrapper wrapper, | |
| 451 FunctionType wrappedType) | |
| 452 : super._internal(rules, expression, wrapper, wrappedType); | |
| 453 | |
| 454 static ClosureWrapBase create(TypeRules rules, Expression expression, | |
| 455 Wrapper wrapper, FunctionType wrappedType) { | |
| 456 // Specialized wrappers: | |
| 457 if (expression is FunctionExpression) { | |
| 458 // The expression is a function literal / inline closure. | |
| 459 return new ClosureWrapLiteral(rules, expression, wrapper, wrappedType); | |
| 460 } | |
| 461 return new ClosureWrap(rules, expression, wrapper, wrappedType); | |
| 462 } | |
| 463 } | |
| 464 | |
| 465 // "Wrapping" of an inline closure. This could be optimized and / or we | |
| 466 // could propagate the types into the literal. | |
| 467 class ClosureWrapLiteral extends ClosureWrapBase { | |
| 468 ClosureWrapLiteral(TypeRules rules, Expression expression, Wrapper wrapper, | |
| 469 FunctionType wrappedType) | |
| 470 : super._internal(rules, expression, wrapper, wrappedType); | |
| 471 } | |
| 472 | |
| 473 class DynamicInvoke extends Conversion { | 376 class DynamicInvoke extends Conversion { |
| 474 DynamicInvoke(TypeRules rules, Expression expression) | 377 DynamicInvoke(TypeRules rules, Expression expression) |
| 475 : super(rules, expression); | 378 : super(rules, expression); |
| 476 | 379 |
| 477 DartType _getConvertedType() => rules.provider.dynamicType; | 380 DartType _getConvertedType() => rules.provider.dynamicType; |
| 478 | 381 |
| 479 String get message => '$expression requires dynamic invoke'; | 382 String get message => '$expression requires dynamic invoke'; |
| 480 Level get level => Level.INFO; | 383 Level get level => Level.INFO; |
| 481 | 384 |
| 482 accept(AstVisitor visitor) { | 385 accept(AstVisitor visitor) { |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 abstract class ConversionVisitor<R> implements AstVisitor<R> { | 561 abstract class ConversionVisitor<R> implements AstVisitor<R> { |
| 659 /// This method must be implemented. It is typically supplied by the base | 562 /// This method must be implemented. It is typically supplied by the base |
| 660 /// GeneralizingAstVisitor<R>. | 563 /// GeneralizingAstVisitor<R>. |
| 661 R visitNode(AstNode node); | 564 R visitNode(AstNode node); |
| 662 | 565 |
| 663 /// The catch-all for any kind of conversion | 566 /// The catch-all for any kind of conversion |
| 664 R visitConversion(Conversion node) => visitNode(node); | 567 R visitConversion(Conversion node) => visitNode(node); |
| 665 | 568 |
| 666 // Methods for conversion subtypes: | 569 // Methods for conversion subtypes: |
| 667 R visitDownCast(DownCast node) => visitConversion(node); | 570 R visitDownCast(DownCast node) => visitConversion(node); |
| 668 R visitClosureWrapBase(ClosureWrapBase node) => visitConversion(node); | |
| 669 R visitClosureWrap(ClosureWrap node) => visitClosureWrapBase(node); | |
| 670 R visitDynamicInvoke(DynamicInvoke node) => visitConversion(node); | 571 R visitDynamicInvoke(DynamicInvoke node) => visitConversion(node); |
| 671 R visitInferredTypeBase(InferredTypeBase node) => visitConversion(node); | 572 R visitInferredTypeBase(InferredTypeBase node) => visitConversion(node); |
| 672 } | 573 } |
| 673 | 574 |
| 674 /// Automatically infer list of types by scanning this library using mirrors. | 575 /// Automatically infer list of types by scanning this library using mirrors. |
| 675 final List<Type> infoTypes = () { | 576 final List<Type> infoTypes = () { |
| 676 var allTypes = new Set(); | 577 var allTypes = new Set(); |
| 677 var baseTypes = new Set(); | 578 var baseTypes = new Set(); |
| 678 var infoMirror = reflectClass(StaticInfo); | 579 var infoMirror = reflectClass(StaticInfo); |
| 679 var libMirror = infoMirror.owner as LibraryMirror; | 580 var libMirror = infoMirror.owner as LibraryMirror; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 695 var isError = severity == analyzer.ErrorSeverity.WARNING; | 596 var isError = severity == analyzer.ErrorSeverity.WARNING; |
| 696 var level = isError ? Level.SEVERE : Level.WARNING; | 597 var level = isError ? Level.SEVERE : Level.WARNING; |
| 697 int begin = error.offset; | 598 int begin = error.offset; |
| 698 int end = begin + error.length; | 599 int end = begin + error.length; |
| 699 return new AnalyzerError(error.message, level, begin, end); | 600 return new AnalyzerError(error.message, level, begin, end); |
| 700 } | 601 } |
| 701 | 602 |
| 702 const AnalyzerError(String message, Level level, int begin, int end) | 603 const AnalyzerError(String message, Level level, int begin, int end) |
| 703 : super(message, level, begin, end); | 604 : super(message, level, begin, end); |
| 704 } | 605 } |
| OLD | NEW |