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:js_runtime/shared/embedded_names.dart'; |
5 import 'package:kernel/ast.dart' as ir; | 6 import 'package:kernel/ast.dart' as ir; |
6 | 7 |
7 import '../constants/expressions.dart'; | 8 import '../constants/expressions.dart'; |
8 import '../common.dart'; | 9 import '../common.dart'; |
9 import '../common/names.dart'; | 10 import '../common/names.dart'; |
10 import '../compiler.dart'; | 11 import '../compiler.dart'; |
11 import '../constants/values.dart'; | 12 import '../constants/values.dart'; |
12 import '../dart_types.dart'; | 13 import '../dart_types.dart'; |
13 import '../elements/elements.dart'; | 14 import '../elements/elements.dart'; |
| 15 import '../js/js.dart' as js; |
14 import '../js_backend/backend_helpers.dart'; | 16 import '../js_backend/backend_helpers.dart'; |
15 import '../js_backend/js_backend.dart'; | 17 import '../js_backend/js_backend.dart'; |
16 import '../kernel/kernel.dart'; | 18 import '../kernel/kernel.dart'; |
17 import '../kernel/kernel_debug.dart'; | 19 import '../kernel/kernel_debug.dart'; |
18 import '../native/native.dart' show NativeBehavior, TypeLookup; | 20 import '../native/native.dart' as native; |
19 import '../resolution/tree_elements.dart'; | 21 import '../resolution/tree_elements.dart'; |
20 import '../tree/tree.dart' as ast; | 22 import '../tree/tree.dart' as ast; |
21 import '../types/masks.dart'; | 23 import '../types/masks.dart'; |
22 import '../types/types.dart'; | 24 import '../types/types.dart'; |
23 import '../universe/call_structure.dart'; | 25 import '../universe/call_structure.dart'; |
24 import '../universe/selector.dart'; | 26 import '../universe/selector.dart'; |
25 import '../universe/side_effects.dart'; | 27 import '../universe/side_effects.dart'; |
26 import '../world.dart'; | 28 import '../world.dart'; |
27 import 'locals_handler.dart'; | 29 import 'locals_handler.dart'; |
28 import 'types.dart'; | 30 import 'types.dart'; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 } | 236 } |
235 | 237 |
236 TypeMask inferredTypeOf(ir.Member node) { | 238 TypeMask inferredTypeOf(ir.Member node) { |
237 return TypeMaskFactory.inferredTypeForElement(getElement(node), _compiler); | 239 return TypeMaskFactory.inferredTypeForElement(getElement(node), _compiler); |
238 } | 240 } |
239 | 241 |
240 TypeMask selectorTypeOf(Selector selector, TypeMask mask) { | 242 TypeMask selectorTypeOf(Selector selector, TypeMask mask) { |
241 return TypeMaskFactory.inferredTypeForSelector(selector, mask, _compiler); | 243 return TypeMaskFactory.inferredTypeForSelector(selector, mask, _compiler); |
242 } | 244 } |
243 | 245 |
| 246 TypeMask typeFromNativeBehavior(native.NativeBehavior nativeBehavior) { |
| 247 return TypeMaskFactory.fromNativeBehavior(nativeBehavior, _compiler); |
| 248 } |
| 249 |
244 ConstantValue getConstantFor(ir.Node node) { | 250 ConstantValue getConstantFor(ir.Node node) { |
245 ConstantValue constantValue = | 251 ConstantValue constantValue = |
246 _backend.constants.getConstantValueForNode(getNode(node), elements); | 252 _backend.constants.getConstantValueForNode(getNode(node), elements); |
247 assert(invariant(getNode(node), constantValue != null, | 253 assert(invariant(getNode(node), constantValue != null, |
248 message: 'No constant computed for $node')); | 254 message: 'No constant computed for $node')); |
249 return constantValue; | 255 return constantValue; |
250 } | 256 } |
251 | 257 |
252 bool isIntercepted(ir.Node node) { | 258 bool isIntercepted(ir.Node node) { |
253 Selector selector = getSelector(node); | 259 Selector selector = getSelector(node); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 kernel.functions[_backend.helpers.assertThrow]; | 308 kernel.functions[_backend.helpers.assertThrow]; |
303 | 309 |
304 ir.Procedure get setRuntimeTypeInfo => | 310 ir.Procedure get setRuntimeTypeInfo => |
305 kernel.functions[_backend.helpers.setRuntimeTypeInfo]; | 311 kernel.functions[_backend.helpers.setRuntimeTypeInfo]; |
306 | 312 |
307 TypeMask get assertThrowReturnType => TypeMaskFactory | 313 TypeMask get assertThrowReturnType => TypeMaskFactory |
308 .inferredReturnTypeForElement(_backend.helpers.assertThrow, _compiler); | 314 .inferredReturnTypeForElement(_backend.helpers.assertThrow, _compiler); |
309 | 315 |
310 ir.Class get objectClass => kernel.classes[_compiler.coreClasses.objectClass]; | 316 ir.Class get objectClass => kernel.classes[_compiler.coreClasses.objectClass]; |
311 | 317 |
| 318 ir.Procedure get currentIsolate => |
| 319 kernel.functions[_backend.helpers.currentIsolate]; |
| 320 |
| 321 bool isInForeignLibrary(ir.Member member) => |
| 322 _backend.isForeign(getElement(member)); |
| 323 |
| 324 native.NativeBehavior getNativeBehavior(ir.Node node) { |
| 325 return elements.getNativeData(getNode(node)); |
| 326 } |
| 327 |
| 328 js.Name getNameForJsGetName(ir.Node argument, ConstantValue constant) { |
| 329 int index = _extractEnumIndexFromConstantValue( |
| 330 constant, _backend.helpers.jsGetNameEnum); |
| 331 if (index == null) return null; |
| 332 return _backend.namer |
| 333 .getNameForJsGetName(getNode(argument), JsGetName.values[index]); |
| 334 } |
| 335 |
| 336 js.Template getJsBuiltinTemplate(ConstantValue constant) { |
| 337 int index = _extractEnumIndexFromConstantValue( |
| 338 constant, _backend.helpers.jsBuiltinEnum); |
| 339 if (index == null) return null; |
| 340 return _backend.emitter.builtinTemplateFor(JsBuiltin.values[index]); |
| 341 } |
| 342 |
| 343 int _extractEnumIndexFromConstantValue( |
| 344 ConstantValue constant, Element classElement) { |
| 345 if (constant is ConstructedConstantValue) { |
| 346 if (constant.type.element == classElement) { |
| 347 assert(constant.fields.length == 1); |
| 348 ConstantValue indexConstant = constant.fields.values.single; |
| 349 if (indexConstant is IntConstantValue) { |
| 350 return indexConstant.primitiveValue; |
| 351 } |
| 352 } |
| 353 } |
| 354 return null; |
| 355 } |
| 356 |
312 DartType getDartType(ir.DartType type) { | 357 DartType getDartType(ir.DartType type) { |
313 return type.accept(_typeConverter); | 358 return type.accept(_typeConverter); |
314 } | 359 } |
315 | 360 |
316 List<DartType> getDartTypes(List<ir.DartType> types) { | 361 List<DartType> getDartTypes(List<ir.DartType> types) { |
317 return types.map(getDartType).toList(); | 362 return types.map(getDartType).toList(); |
318 } | 363 } |
319 | 364 |
320 DartType getFunctionReturnType(ir.FunctionNode node) { | 365 DartType getFunctionReturnType(ir.FunctionNode node) { |
321 return getDartType(node.returnType); | 366 return getDartType(node.returnType); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 } | 420 } |
376 return ForeignKind.NONE; | 421 return ForeignKind.NONE; |
377 } | 422 } |
378 | 423 |
379 /// Return `true` if [node] is the `dart:_foreign_helper` library. | 424 /// Return `true` if [node] is the `dart:_foreign_helper` library. |
380 bool isForeignLibrary(ir.Library node) { | 425 bool isForeignLibrary(ir.Library node) { |
381 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER; | 426 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER; |
382 } | 427 } |
383 | 428 |
384 /// Looks up [typeName] for use in the spec-string of a `JS` called. | 429 /// Looks up [typeName] for use in the spec-string of a `JS` called. |
385 // TODO(johnniwinther): Use this in [NativeBehavior] instead of calling the | 430 // TODO(johnniwinther): Use this in [native.NativeBehavior] instead of calling
the |
386 // `ForeignResolver`. | 431 // `ForeignResolver`. |
387 // TODO(johnniwinther): Cache the result to avoid redundant lookups? | 432 // TODO(johnniwinther): Cache the result to avoid redundant lookups? |
388 TypeLookup _typeLookup({bool resolveAsRaw: true}) { | 433 native.TypeLookup _typeLookup({bool resolveAsRaw: true}) { |
389 return (String typeName) { | 434 return (String typeName) { |
390 DartType findIn(Uri uri) { | 435 DartType findIn(Uri uri) { |
391 LibraryElement library = _compiler.libraryLoader.lookupLibrary(uri); | 436 LibraryElement library = _compiler.libraryLoader.lookupLibrary(uri); |
392 if (library != null) { | 437 if (library != null) { |
393 Element element = library.find(typeName); | 438 Element element = library.find(typeName); |
394 if (element != null && element.isClass) { | 439 if (element != null && element.isClass) { |
395 ClassElement cls = element; | 440 ClassElement cls = element; |
396 // TODO(johnniwinther): Align semantics. | 441 // TODO(johnniwinther): Align semantics. |
397 return resolveAsRaw ? cls.rawType : cls.thisType; | 442 return resolveAsRaw ? cls.rawType : cls.thisType; |
398 } | 443 } |
(...skipping 11 matching lines...) Expand all Loading... |
410 type ??= findIn(Uris.dart_web_audio); | 455 type ??= findIn(Uris.dart_web_audio); |
411 type ??= findIn(Uris.dart_web_gl); | 456 type ??= findIn(Uris.dart_web_gl); |
412 return type; | 457 return type; |
413 }; | 458 }; |
414 } | 459 } |
415 | 460 |
416 String _getStringArgument(ir.StaticInvocation node, int index) { | 461 String _getStringArgument(ir.StaticInvocation node, int index) { |
417 return node.arguments.positional[index].accept(new Stringifier()); | 462 return node.arguments.positional[index].accept(new Stringifier()); |
418 } | 463 } |
419 | 464 |
420 /// Computes the [NativeBehavior] for a call to the [JS] function. | 465 /// Computes the [native.NativeBehavior] for a call to the [JS] function. |
421 // TODO(johnniwinther): Cache this for later use. | 466 // TODO(johnniwinther): Cache this for later use. |
422 NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) { | 467 native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) { |
423 if (node.arguments.positional.length < 2 || | 468 if (node.arguments.positional.length < 2 || |
424 node.arguments.named.isNotEmpty) { | 469 node.arguments.named.isNotEmpty) { |
425 reporter.reportErrorMessage( | 470 reporter.reportErrorMessage( |
426 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS); | 471 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS); |
427 return new NativeBehavior(); | 472 return new native.NativeBehavior(); |
428 } | 473 } |
429 String specString = _getStringArgument(node, 0); | 474 String specString = _getStringArgument(node, 0); |
430 if (specString == null) { | 475 if (specString == null) { |
431 reporter.reportErrorMessage( | 476 reporter.reportErrorMessage( |
432 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST); | 477 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST); |
433 return new NativeBehavior(); | 478 return new native.NativeBehavior(); |
434 } | 479 } |
435 | 480 |
436 String codeString = _getStringArgument(node, 1); | 481 String codeString = _getStringArgument(node, 1); |
437 if (codeString == null) { | 482 if (codeString == null) { |
438 reporter.reportErrorMessage( | 483 reporter.reportErrorMessage( |
439 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND); | 484 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND); |
440 return new NativeBehavior(); | 485 return new native.NativeBehavior(); |
441 } | 486 } |
442 | 487 |
443 return NativeBehavior.ofJsCall( | 488 return native.NativeBehavior.ofJsCall( |
444 specString, | 489 specString, |
445 codeString, | 490 codeString, |
446 _typeLookup(resolveAsRaw: true), | 491 _typeLookup(resolveAsRaw: true), |
447 CURRENT_ELEMENT_SPANNABLE, | 492 CURRENT_ELEMENT_SPANNABLE, |
448 reporter, | 493 reporter, |
449 _compiler.coreTypes); | 494 _compiler.coreTypes); |
450 } | 495 } |
451 | 496 |
452 /// Computes the [NativeBehavior] for a call to the [JS_BUILTIN] function. | 497 /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN] functi
on. |
453 // TODO(johnniwinther): Cache this for later use. | 498 // TODO(johnniwinther): Cache this for later use. |
454 NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) { | 499 native.NativeBehavior getNativeBehaviorForJsBuiltinCall( |
| 500 ir.StaticInvocation node) { |
455 if (node.arguments.positional.length < 1) { | 501 if (node.arguments.positional.length < 1) { |
456 reporter.internalError( | 502 reporter.internalError( |
457 CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type."); | 503 CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type."); |
458 return new NativeBehavior(); | 504 return new native.NativeBehavior(); |
459 } | 505 } |
460 if (node.arguments.positional.length < 2) { | 506 if (node.arguments.positional.length < 2) { |
461 reporter.internalError( | 507 reporter.internalError( |
462 CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name."); | 508 CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name."); |
463 return new NativeBehavior(); | 509 return new native.NativeBehavior(); |
464 } | 510 } |
465 String specString = _getStringArgument(node, 0); | 511 String specString = _getStringArgument(node, 0); |
466 if (specString == null) { | 512 if (specString == null) { |
467 reporter.internalError( | 513 reporter.internalError( |
468 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); | 514 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); |
469 return new NativeBehavior(); | 515 return new native.NativeBehavior(); |
470 } | 516 } |
471 return NativeBehavior.ofJsBuiltinCall( | 517 return native.NativeBehavior.ofJsBuiltinCall( |
472 specString, | 518 specString, |
473 _typeLookup(resolveAsRaw: true), | 519 _typeLookup(resolveAsRaw: true), |
474 CURRENT_ELEMENT_SPANNABLE, | 520 CURRENT_ELEMENT_SPANNABLE, |
475 reporter, | 521 reporter, |
476 _compiler.coreTypes); | 522 _compiler.coreTypes); |
477 } | 523 } |
478 | 524 |
479 /// Computes the [NativeBehavior] for a call to the [JS_EMBEDDED_GLOBAL] | 525 /// Computes the [native.NativeBehavior] for a call to the [JS_EMBEDDED_GLOBAL
] |
480 /// function. | 526 /// function. |
481 // TODO(johnniwinther): Cache this for later use. | 527 // TODO(johnniwinther): Cache this for later use. |
482 NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall( | 528 native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall( |
483 ir.StaticInvocation node) { | 529 ir.StaticInvocation node) { |
484 if (node.arguments.positional.length < 1) { | 530 if (node.arguments.positional.length < 1) { |
485 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, | 531 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, |
486 "JS embedded global expression has no type."); | 532 "JS embedded global expression has no type."); |
487 return new NativeBehavior(); | 533 return new native.NativeBehavior(); |
488 } | 534 } |
489 if (node.arguments.positional.length < 2) { | 535 if (node.arguments.positional.length < 2) { |
490 reporter.internalError( | 536 reporter.internalError( |
491 CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name."); | 537 CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name."); |
492 return new NativeBehavior(); | 538 return new native.NativeBehavior(); |
493 } | 539 } |
494 if (node.arguments.positional.length > 2 || | 540 if (node.arguments.positional.length > 2 || |
495 node.arguments.named.isNotEmpty) { | 541 node.arguments.named.isNotEmpty) { |
496 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, | 542 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, |
497 "JS embedded global has more than 2 arguments."); | 543 "JS embedded global has more than 2 arguments."); |
498 return new NativeBehavior(); | 544 return new native.NativeBehavior(); |
499 } | 545 } |
500 String specString = _getStringArgument(node, 0); | 546 String specString = _getStringArgument(node, 0); |
501 if (specString == null) { | 547 if (specString == null) { |
502 reporter.internalError( | 548 reporter.internalError( |
503 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); | 549 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); |
504 return new NativeBehavior(); | 550 return new native.NativeBehavior(); |
505 } | 551 } |
506 return NativeBehavior.ofJsEmbeddedGlobalCall( | 552 return native.NativeBehavior.ofJsEmbeddedGlobalCall( |
507 specString, | 553 specString, |
508 _typeLookup(resolveAsRaw: true), | 554 _typeLookup(resolveAsRaw: true), |
509 CURRENT_ELEMENT_SPANNABLE, | 555 CURRENT_ELEMENT_SPANNABLE, |
510 reporter, | 556 reporter, |
511 _compiler.coreTypes); | 557 _compiler.coreTypes); |
512 } | 558 } |
513 | 559 |
514 /// Returns `true` is [node] has a `@Native(...)` annotation. | 560 /// Returns `true` is [node] has a `@Native(...)` annotation. |
515 // TODO(johnniwinther): Cache this for later use. | 561 // TODO(johnniwinther): Cache this for later use. |
516 bool isNative(ir.Class node) { | 562 bool isNative(ir.Class node) { |
517 for (ir.Expression annotation in node.annotations) { | 563 for (ir.Expression annotation in node.annotations) { |
518 if (annotation is ir.ConstructorInvocation) { | 564 if (annotation is ir.ConstructorInvocation) { |
519 ConstructorElement target = getElement(annotation.target).declaration; | 565 ConstructorElement target = getElement(annotation.target).declaration; |
520 if (target.enclosingClass == | 566 if (target.enclosingClass == |
521 _compiler.commonElements.nativeAnnotationClass) { | 567 _compiler.commonElements.nativeAnnotationClass) { |
522 return true; | 568 return true; |
523 } | 569 } |
524 } | 570 } |
525 } | 571 } |
526 return false; | 572 return false; |
527 } | 573 } |
528 | 574 |
529 /// Computes the native behavior for reading the native [field]. | 575 /// Computes the native behavior for reading the native [field]. |
530 // TODO(johnniwinther): Cache this for later use. | 576 // TODO(johnniwinther): Cache this for later use. |
531 NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) { | 577 native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) { |
532 DartType type = getDartType(field.type); | 578 DartType type = getDartType(field.type); |
533 List<ConstantExpression> metadata = getMetadata(field.annotations); | 579 List<ConstantExpression> metadata = getMetadata(field.annotations); |
534 return NativeBehavior.ofFieldLoad(CURRENT_ELEMENT_SPANNABLE, type, metadata, | 580 return native.NativeBehavior.ofFieldLoad(CURRENT_ELEMENT_SPANNABLE, type, |
535 _typeLookup(resolveAsRaw: false), _compiler, | 581 metadata, _typeLookup(resolveAsRaw: false), _compiler, |
536 isJsInterop: false); | 582 isJsInterop: false); |
537 } | 583 } |
538 | 584 |
539 /// Computes the native behavior for writing to the native [field]. | 585 /// Computes the native behavior for writing to the native [field]. |
540 // TODO(johnniwinther): Cache this for later use. | 586 // TODO(johnniwinther): Cache this for later use. |
541 NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) { | 587 native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) { |
542 DartType type = getDartType(field.type); | 588 DartType type = getDartType(field.type); |
543 return NativeBehavior.ofFieldStore(type, _compiler.resolution); | 589 return native.NativeBehavior.ofFieldStore(type, _compiler.resolution); |
544 } | 590 } |
545 | 591 |
546 /// Computes the native behavior for calling [procedure]. | 592 /// Computes the native behavior for calling [procedure]. |
547 // TODO(johnniwinther): Cache this for later use. | 593 // TODO(johnniwinther): Cache this for later use. |
548 NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) { | 594 native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) { |
549 DartType type = getFunctionType(procedure.function); | 595 DartType type = getFunctionType(procedure.function); |
550 List<ConstantExpression> metadata = getMetadata(procedure.annotations); | 596 List<ConstantExpression> metadata = getMetadata(procedure.annotations); |
551 return NativeBehavior.ofMethod(CURRENT_ELEMENT_SPANNABLE, type, metadata, | 597 return native.NativeBehavior.ofMethod(CURRENT_ELEMENT_SPANNABLE, type, |
552 _typeLookup(resolveAsRaw: false), _compiler, | 598 metadata, _typeLookup(resolveAsRaw: false), _compiler, |
553 isJsInterop: false); | 599 isJsInterop: false); |
554 } | 600 } |
555 } | 601 } |
556 | 602 |
557 /// Kinds of foreign functions. | 603 /// Kinds of foreign functions. |
558 enum ForeignKind { | 604 enum ForeignKind { |
559 JS, | 605 JS, |
560 JS_BUILTIN, | 606 JS_BUILTIN, |
561 JS_EMBEDDED_GLOBAL, | 607 JS_EMBEDDED_GLOBAL, |
562 JS_INTERCEPTOR_CONSTANT, | 608 JS_INTERCEPTOR_CONSTANT, |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 astAdapter.reporter.internalError( | 739 astAdapter.reporter.internalError( |
694 CURRENT_ELEMENT_SPANNABLE, "Unexpected constant target: $element."); | 740 CURRENT_ELEMENT_SPANNABLE, "Unexpected constant target: $element."); |
695 return null; | 741 return null; |
696 } | 742 } |
697 | 743 |
698 @override | 744 @override |
699 ConstantExpression visitStringLiteral(ir.StringLiteral node) { | 745 ConstantExpression visitStringLiteral(ir.StringLiteral node) { |
700 return new StringConstantExpression(node.value); | 746 return new StringConstantExpression(node.value); |
701 } | 747 } |
702 } | 748 } |
OLD | NEW |