| 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 |