| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/names.dart'; | 8 import '../common/names.dart'; |
| 9 import '../compiler.dart'; | 9 import '../compiler.dart'; |
| 10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| 11 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
| 12 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
| 13 import '../js_backend/backend_helpers.dart'; | |
| 14 import '../js_backend/js_backend.dart'; | 13 import '../js_backend/js_backend.dart'; |
| 15 import '../kernel/kernel.dart'; | 14 import '../kernel/kernel.dart'; |
| 16 import '../kernel/kernel_debug.dart'; | |
| 17 import '../native/native.dart' show NativeBehavior; | |
| 18 import '../resolution/tree_elements.dart'; | 15 import '../resolution/tree_elements.dart'; |
| 19 import '../tree/tree.dart' as ast; | 16 import '../tree/tree.dart' as ast; |
| 20 import '../types/masks.dart'; | 17 import '../types/masks.dart'; |
| 21 import '../types/types.dart'; | 18 import '../types/types.dart'; |
| 22 import '../universe/call_structure.dart'; | 19 import '../universe/call_structure.dart'; |
| 23 import '../universe/selector.dart'; | 20 import '../universe/selector.dart'; |
| 24 import '../universe/side_effects.dart'; | 21 import '../universe/side_effects.dart'; |
| 25 import '../world.dart'; | 22 import '../world.dart'; |
| 26 import 'locals_handler.dart'; | 23 import 'locals_handler.dart'; |
| 27 import 'types.dart'; | 24 import 'types.dart'; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 57 for (LocalFunctionElement localFunction in kernel.localFunctions.keys) { | 54 for (LocalFunctionElement localFunction in kernel.localFunctions.keys) { |
| 58 _nodeToElement[kernel.localFunctions[localFunction]] = localFunction; | 55 _nodeToElement[kernel.localFunctions[localFunction]] = localFunction; |
| 59 } | 56 } |
| 60 _typeConverter = new DartTypeConverter(this); | 57 _typeConverter = new DartTypeConverter(this); |
| 61 } | 58 } |
| 62 | 59 |
| 63 Compiler get _compiler => _backend.compiler; | 60 Compiler get _compiler => _backend.compiler; |
| 64 TreeElements get elements => _resolvedAst.elements; | 61 TreeElements get elements => _resolvedAst.elements; |
| 65 GlobalTypeInferenceResults get _inferenceResults => | 62 GlobalTypeInferenceResults get _inferenceResults => |
| 66 _compiler.globalInference.results; | 63 _compiler.globalInference.results; |
| 67 DiagnosticReporter get reporter => _compiler.reporter; | |
| 68 | 64 |
| 69 ConstantValue getConstantForSymbol(ir.SymbolLiteral node) { | 65 ConstantValue getConstantForSymbol(ir.SymbolLiteral node) { |
| 70 ast.Node astNode = getNode(node); | 66 ast.Node astNode = getNode(node); |
| 71 ConstantValue constantValue = _backend.constants | 67 ConstantValue constantValue = _backend.constants |
| 72 .getConstantValueForNode(astNode, _resolvedAst.elements); | 68 .getConstantValueForNode(astNode, _resolvedAst.elements); |
| 73 assert(invariant(astNode, constantValue != null, | 69 assert(invariant(astNode, constantValue != null, |
| 74 message: 'No constant computed for $node')); | 70 message: 'No constant computed for $node')); |
| 75 return constantValue; | 71 return constantValue; |
| 76 } | 72 } |
| 77 | 73 |
| 78 Element getElement(ir.Node node) { | 74 Element getElement(ir.Node node) { |
| 79 Element result = _nodeToElement[node]; | 75 Element result = _nodeToElement[node]; |
| 80 assert(invariant(CURRENT_ELEMENT_SPANNABLE, result != null, | 76 assert(result != null); |
| 81 message: "No element found for $node.")); | |
| 82 return result; | 77 return result; |
| 83 } | 78 } |
| 84 | 79 |
| 85 ast.Node getNode(ir.Node node) { | 80 ast.Node getNode(ir.Node node) { |
| 86 ast.Node result = _nodeToAst[node]; | 81 ast.Node result = _nodeToAst[node]; |
| 87 assert(result != null); | 82 assert(result != null); |
| 88 return result; | 83 return result; |
| 89 } | 84 } |
| 90 | 85 |
| 91 Local getLocal(ir.VariableDeclaration variable) { | 86 Local getLocal(ir.VariableDeclaration variable) { |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 TypeMask get assertThrowReturnType => TypeMaskFactory | 272 TypeMask get assertThrowReturnType => TypeMaskFactory |
| 278 .inferredReturnTypeForElement(_backend.helpers.assertThrow, _compiler); | 273 .inferredReturnTypeForElement(_backend.helpers.assertThrow, _compiler); |
| 279 | 274 |
| 280 DartType getDartType(ir.DartType type) { | 275 DartType getDartType(ir.DartType type) { |
| 281 return type.accept(_typeConverter); | 276 return type.accept(_typeConverter); |
| 282 } | 277 } |
| 283 | 278 |
| 284 List<DartType> getDartTypes(List<ir.DartType> types) { | 279 List<DartType> getDartTypes(List<ir.DartType> types) { |
| 285 return types.map(getDartType).toList(); | 280 return types.map(getDartType).toList(); |
| 286 } | 281 } |
| 287 | |
| 288 @override | |
| 289 ForeignKind getForeignKind(ir.StaticInvocation node) { | |
| 290 if (isForeignLibrary(node.target.enclosingLibrary)) { | |
| 291 switch (node.target.name.name) { | |
| 292 case BackendHelpers.JS: | |
| 293 return ForeignKind.JS; | |
| 294 case BackendHelpers.JS_BUILTIN: | |
| 295 return ForeignKind.JS_BUILTIN; | |
| 296 case BackendHelpers.JS_EMBEDDED_GLOBAL: | |
| 297 return ForeignKind.JS_EMBEDDED_GLOBAL; | |
| 298 case BackendHelpers.JS_INTERCEPTOR_CONSTANT: | |
| 299 return ForeignKind.JS_INTERCEPTOR_CONSTANT; | |
| 300 } | |
| 301 } | |
| 302 return ForeignKind.NONE; | |
| 303 } | |
| 304 | |
| 305 bool isForeignLibrary(ir.Library node) { | |
| 306 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER; | |
| 307 } | |
| 308 | |
| 309 DartType _typeLookup(String typeName) { | |
| 310 DartType findIn(Uri uri) { | |
| 311 LibraryElement library = _compiler.libraryLoader.lookupLibrary(uri); | |
| 312 if (library != null) { | |
| 313 Element element = library.find(typeName); | |
| 314 if (element != null && element.isClass) { | |
| 315 ClassElement cls = element; | |
| 316 return cls.rawType; | |
| 317 } | |
| 318 } | |
| 319 return null; | |
| 320 } | |
| 321 | |
| 322 DartType type = findIn(Uris.dart_core); | |
| 323 type ??= findIn(BackendHelpers.DART_JS_HELPER); | |
| 324 type ??= findIn(BackendHelpers.DART_INTERCEPTORS); | |
| 325 type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER); | |
| 326 type ??= findIn(Uris.dart_collection); | |
| 327 type ??= findIn(Uris.dart_html); | |
| 328 return type; | |
| 329 } | |
| 330 | |
| 331 String _getStringArgument(ir.StaticInvocation node, int index) { | |
| 332 return node.arguments.positional[index].accept(new Stringifier()); | |
| 333 } | |
| 334 | |
| 335 NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) { | |
| 336 if (node.arguments.positional.length < 2 || | |
| 337 node.arguments.named.isNotEmpty) { | |
| 338 reporter.reportErrorMessage( | |
| 339 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS); | |
| 340 return new NativeBehavior(); | |
| 341 } | |
| 342 String specString = _getStringArgument(node, 0); | |
| 343 if (specString == null) { | |
| 344 reporter.reportErrorMessage( | |
| 345 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST); | |
| 346 return new NativeBehavior(); | |
| 347 } | |
| 348 | |
| 349 String codeString = _getStringArgument(node, 1); | |
| 350 if (codeString == null) { | |
| 351 reporter.reportErrorMessage( | |
| 352 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND); | |
| 353 return new NativeBehavior(); | |
| 354 } | |
| 355 | |
| 356 return NativeBehavior.ofJsCall(specString, codeString, _typeLookup, | |
| 357 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes); | |
| 358 } | |
| 359 | |
| 360 NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) { | |
| 361 if (node.arguments.positional.length < 1) { | |
| 362 reporter.internalError( | |
| 363 CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type."); | |
| 364 return new NativeBehavior(); | |
| 365 } | |
| 366 if (node.arguments.positional.length < 2) { | |
| 367 reporter.internalError( | |
| 368 CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name."); | |
| 369 return new NativeBehavior(); | |
| 370 } | |
| 371 String specString = _getStringArgument(node, 0); | |
| 372 if (specString == null) { | |
| 373 reporter.internalError( | |
| 374 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); | |
| 375 return new NativeBehavior(); | |
| 376 } | |
| 377 return NativeBehavior.ofJsBuiltinCall(specString, _typeLookup, | |
| 378 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes); | |
| 379 } | |
| 380 | |
| 381 NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall( | |
| 382 ir.StaticInvocation node) { | |
| 383 if (node.arguments.positional.length < 1) { | |
| 384 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, | |
| 385 "JS embedded global expression has no type."); | |
| 386 return new NativeBehavior(); | |
| 387 } | |
| 388 if (node.arguments.positional.length < 2) { | |
| 389 reporter.internalError( | |
| 390 CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name."); | |
| 391 return new NativeBehavior(); | |
| 392 } | |
| 393 if (node.arguments.positional.length > 2 || | |
| 394 node.arguments.named.isNotEmpty) { | |
| 395 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, | |
| 396 "JS embedded global has more than 2 arguments."); | |
| 397 return new NativeBehavior(); | |
| 398 } | |
| 399 String specString = _getStringArgument(node, 0); | |
| 400 if (specString == null) { | |
| 401 reporter.internalError( | |
| 402 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); | |
| 403 return new NativeBehavior(); | |
| 404 } | |
| 405 return NativeBehavior.ofJsEmbeddedGlobalCall(specString, _typeLookup, | |
| 406 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes); | |
| 407 } | |
| 408 } | |
| 409 | |
| 410 enum ForeignKind { | |
| 411 JS, | |
| 412 JS_BUILTIN, | |
| 413 JS_EMBEDDED_GLOBAL, | |
| 414 JS_INTERCEPTOR_CONSTANT, | |
| 415 NONE, | |
| 416 } | 282 } |
| 417 | 283 |
| 418 class DartTypeConverter extends ir.DartTypeVisitor<DartType> { | 284 class DartTypeConverter extends ir.DartTypeVisitor<DartType> { |
| 419 final KernelAstAdapter astAdapter; | 285 final KernelAstAdapter astAdapter; |
| 420 | 286 |
| 421 DartTypeConverter(this.astAdapter); | 287 DartTypeConverter(this.astAdapter); |
| 422 | 288 |
| 423 DartType visitType(ir.DartType type) => type.accept(this); | 289 DartType visitType(ir.DartType type) => type.accept(this); |
| 424 | 290 |
| 425 List<DartType> visitTypes(List<ir.DartType> types) { | 291 List<DartType> visitTypes(List<ir.DartType> types) { |
| 426 return new List.generate( | 292 return new List.generate( |
| 427 types.length, (int index) => types[index].accept(this)); | 293 types.length, (int index) => types[index].accept(this)); |
| 428 } | 294 } |
| 429 | 295 |
| 430 @override | 296 @override |
| 431 DartType visitTypeParameterType(ir.TypeParameterType node) { | 297 DartType visitTypeParameterType(ir.TypeParameterType node) { |
| 432 if (node.parameter.parent is ir.Class) { | 298 return new TypeVariableType(astAdapter.getElement(node.parameter)); |
| 433 ir.Class cls = node.parameter.parent; | |
| 434 int index = cls.typeParameters.indexOf(node.parameter); | |
| 435 ClassElement classElement = astAdapter.getElement(cls); | |
| 436 return classElement.typeVariables[index]; | |
| 437 } else if (node.parameter.parent is ir.FunctionNode) { | |
| 438 ir.FunctionNode func = node.parameter.parent; | |
| 439 int index = func.typeParameters.indexOf(node.parameter); | |
| 440 ConstructorElement constructorElement = astAdapter.getElement(func); | |
| 441 ClassElement classElement = constructorElement.enclosingClass; | |
| 442 return classElement.typeVariables[index]; | |
| 443 } | |
| 444 throw new UnsupportedError('Unsupported type parameter type node $node.'); | |
| 445 } | 299 } |
| 446 | 300 |
| 447 @override | 301 @override |
| 448 DartType visitFunctionType(ir.FunctionType node) { | 302 DartType visitFunctionType(ir.FunctionType node) { |
| 449 return new FunctionType.synthesized( | 303 return new FunctionType.synthesized( |
| 450 visitType(node.returnType), | 304 visitType(node.returnType), |
| 451 visitTypes(node.positionalParameters | 305 visitTypes(node.positionalParameters |
| 452 .take(node.requiredParameterCount) | 306 .take(node.requiredParameterCount) |
| 453 .toList()), | 307 .toList()), |
| 454 visitTypes(node.positionalParameters | 308 visitTypes(node.positionalParameters |
| (...skipping 17 matching lines...) Expand all Loading... |
| 472 @override | 326 @override |
| 473 DartType visitDynamicType(ir.DynamicType node) { | 327 DartType visitDynamicType(ir.DynamicType node) { |
| 474 return const DynamicType(); | 328 return const DynamicType(); |
| 475 } | 329 } |
| 476 | 330 |
| 477 @override | 331 @override |
| 478 DartType visitInvalidType(ir.InvalidType node) { | 332 DartType visitInvalidType(ir.InvalidType node) { |
| 479 throw new UnimplementedError("Invalid types not currently supported"); | 333 throw new UnimplementedError("Invalid types not currently supported"); |
| 480 } | 334 } |
| 481 } | 335 } |
| 482 | |
| 483 /// Visitor that converts string literals and concatenations of string literals | |
| 484 /// into the string value. | |
| 485 class Stringifier extends ir.ExpressionVisitor<String> { | |
| 486 @override | |
| 487 String visitStringLiteral(ir.StringLiteral node) => node.value; | |
| 488 | |
| 489 @override | |
| 490 String visitStringConcatenation(ir.StringConcatenation node) { | |
| 491 StringBuffer sb = new StringBuffer(); | |
| 492 for (ir.Expression expression in node.expressions) { | |
| 493 String value = expression.accept(this); | |
| 494 if (value == null) return null; | |
| 495 sb.write(value); | |
| 496 } | |
| 497 return sb.toString(); | |
| 498 } | |
| 499 } | |
| OLD | NEW |