Chromium Code Reviews| 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: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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |