| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 /** A formal parameter to a [Method]. */ | 5 /** A formal parameter to a [Method]. */ |
| 6 class Parameter { | 6 class Parameter { |
| 7 FormalNode definition; | 7 FormalNode definition; |
| 8 | 8 |
| 9 String name; | 9 String name; |
| 10 Type type; | 10 Type type; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 Library get library() => declaringType.library; | 108 Library get library() => declaringType.library; |
| 109 | 109 |
| 110 bool get isPrivate() => name.startsWith('_'); | 110 bool get isPrivate() => name.startsWith('_'); |
| 111 | 111 |
| 112 bool get isConstructor() => false; | 112 bool get isConstructor() => false; |
| 113 bool get isField() => false; | 113 bool get isField() => false; |
| 114 bool get isMethod() => false; | 114 bool get isMethod() => false; |
| 115 bool get isProperty() => false; | 115 bool get isProperty() => false; |
| 116 bool get isAbstract() => false; | 116 bool get isAbstract() => false; |
| 117 | 117 |
| 118 // TODO(jmesserly): these only makes sense on methods, but because of |
| 119 // ConcreteMember we need to support them on Member. |
| 120 bool get isConst() => false; |
| 121 bool get isFactory() => false; |
| 122 |
| 118 bool get prefersPropertySyntax() => true; | 123 bool get prefersPropertySyntax() => true; |
| 119 bool get requiresFieldSyntax() => false; | 124 bool get requiresFieldSyntax() => false; |
| 120 | 125 |
| 121 bool get isNative() => false; | 126 bool get isNative() => false; |
| 122 String get constructorName() => | 127 String get constructorName() => |
| 123 world.internalError('can not be a constructor', span); | 128 world.internalError('can not be a constructor', span); |
| 124 | 129 |
| 125 void provideFieldSyntax() => world.internalError('can not be field', span); | 130 void provideFieldSyntax() => world.internalError('can not be field', span); |
| 126 void providePropertySyntax() => | 131 void providePropertySyntax() => |
| 127 world.internalError('can not be property', span); | 132 world.internalError('can not be property', span); |
| 133 |
| 134 Definition get initDelegate() => |
| 135 world.internalError('cannot have initializers', span); |
| 136 Definition set initDelegate(ctor) => |
| 137 world.internalError('cannot have initializers', span); |
| 128 | 138 |
| 129 Definition get definition() => null; | 139 Definition get definition() => null; |
| 130 | 140 |
| 131 List<Parameter> get parameters() => []; | 141 List<Parameter> get parameters() => []; |
| 132 | 142 |
| 133 // TODO(jimhug): Fix these names once get/set are truly pseudo-keywords. | 143 // TODO(jimhug): Fix these names once get/set are truly pseudo-keywords. |
| 134 // TODO(jmesserly): isDynamic isn't a great name for this, something better? | 144 // TODO(jmesserly): isDynamic isn't a great name for this, something better? |
| 135 abstract Value get_(MethodGenerator context, Node node, Value target, | 145 abstract Value get_(MethodGenerator context, Node node, Value target, |
| 136 [bool isDynamic]); | 146 [bool isDynamic]); |
| 137 | 147 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 162 | 172 |
| 163 String get generatedFactoryName() { | 173 String get generatedFactoryName() { |
| 164 assert(this.isFactory); | 174 assert(this.isFactory); |
| 165 String prefix = '${declaringType.jsname}.${constructorName}\$'; | 175 String prefix = '${declaringType.jsname}.${constructorName}\$'; |
| 166 if (name == '') { | 176 if (name == '') { |
| 167 return '${prefix}factory'; | 177 return '${prefix}factory'; |
| 168 } else { | 178 } else { |
| 169 return '${prefix}$name\$factory'; | 179 return '${prefix}$name\$factory'; |
| 170 } | 180 } |
| 171 } | 181 } |
| 182 |
| 183 Type resolveType(TypeReference node, bool isRequired) { |
| 184 var type = declaringType.resolveType(node, isRequired); |
| 185 if (isStatic && type.hasTypeParams) { |
| 186 // TODO(jimhug): Is this really so hard? |
| 187 world.error('using type parameter in static context', |
| 188 node.span); |
| 189 } |
| 190 return type; |
| 191 } |
| 172 } | 192 } |
| 173 | 193 |
| 174 | 194 |
| 175 /** | 195 /** |
| 176 * Types are treated as first class members of their library's top type. | 196 * Types are treated as first class members of their library's top type. |
| 177 */ | 197 */ |
| 178 // TODO(jmesserly): perhaps Type should extend Member, but that can get | 198 // TODO(jmesserly): perhaps Type should extend Member, but that can get |
| 179 // complicated. | 199 // complicated. |
| 180 class TypeMember extends Member { | 200 class TypeMember extends Member { |
| 181 final DefinedType type; | 201 final DefinedType type; |
| 182 | 202 |
| 183 TypeMember(DefinedType type) | 203 TypeMember(DefinedType type) |
| 184 : super(type.name, type.library.topType), | 204 : super(type.name, type.library.topType), |
| 185 this.type = type; | 205 this.type = type; |
| 186 | 206 |
| 187 SourceSpan get span() => type.definition.span; | 207 SourceSpan get span() => type.definition.span; |
| 188 | 208 |
| 189 bool get isStatic() => true; | 209 bool get isStatic() => true; |
| 190 | 210 |
| 191 // If this really becomes first class, this should return typeof(Type) | 211 // If this really becomes first class, this should return typeof(Type) |
| 192 Type get returnType() => world.isVar; | 212 Type get returnType() => world.varType; |
| 193 | 213 |
| 194 bool canInvoke(MethodGenerator context, Arguments args) => false; | 214 bool canInvoke(MethodGenerator context, Arguments args) => false; |
| 195 bool get canGet() => true; | 215 bool get canGet() => true; |
| 196 bool get canSet() => false; | 216 bool get canSet() => false; |
| 197 | 217 |
| 198 void resolve(Type inType) {} | 218 void resolve(Type inType) {} |
| 199 | 219 |
| 200 Value get_(MethodGenerator context, Node node, Value target, | 220 Value get_(MethodGenerator context, Node node, Value target, |
| 201 [bool isDynamic=false]) { | 221 [bool isDynamic=false]) { |
| 202 assert(target == null || target.type.isTop); | 222 assert(target == null || target.type.isTop); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 if (isFinal) { | 379 if (isFinal) { |
| 360 return cv; | 380 return cv; |
| 361 } | 381 } |
| 362 if (declaringType.isTop) { | 382 if (declaringType.isTop) { |
| 363 return new Value(type, '$jsname'); | 383 return new Value(type, '$jsname'); |
| 364 } else { | 384 } else { |
| 365 return new Value(type, '${declaringType.jsname}.$jsname'); | 385 return new Value(type, '${declaringType.jsname}.$jsname'); |
| 366 } | 386 } |
| 367 } else if (target.isConst && isFinal) { | 387 } else if (target.isConst && isFinal) { |
| 368 // take advantage of consts and retrieve the value directly if possible | 388 // take advantage of consts and retrieve the value directly if possible |
| 369 var constTarget = target is GlobalValue ? target.exp : target; | 389 var constTarget = target is GlobalValue ? target.dynamic.exp : target; |
| 370 if (constTarget is ConstObjectValue) { | 390 if (constTarget is ConstObjectValue) { |
| 371 return constTarget.fields[name]; | 391 return constTarget.fields[name]; |
| 372 } else if (constTarget.type == world.stringType && name == 'length') { | 392 } else if (constTarget.type == world.stringType && name == 'length') { |
| 373 return new Value(type, '${constTarget.actualValue.length}'); | 393 return new Value(type, '${constTarget.actualValue.length}'); |
| 374 } | 394 } |
| 375 } | 395 } |
| 376 return new Value(type, '${target.code}.$jsname'); | 396 return new Value(type, '${target.code}.$jsname'); |
| 377 } | 397 } |
| 378 | 398 |
| 379 Value set_(MethodGenerator context, Node node, Value target, Value value, | 399 Value set_(MethodGenerator context, Node node, Value target, Value value, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 } | 471 } |
| 452 return target.invokeNoSuchMethod(context, 'set:$name', node, | 472 return target.invokeNoSuchMethod(context, 'set:$name', node, |
| 453 new Arguments(null, [value])); | 473 new Arguments(null, [value])); |
| 454 } | 474 } |
| 455 return setter.invoke(context, node, target, new Arguments(null, [value]), | 475 return setter.invoke(context, node, target, new Arguments(null, [value]), |
| 456 isDynamic); | 476 isDynamic); |
| 457 } | 477 } |
| 458 | 478 |
| 459 addFromParent(Member parentMember) { | 479 addFromParent(Member parentMember) { |
| 460 // TODO(jimhug): Egregious Hack! | 480 // TODO(jimhug): Egregious Hack! |
| 481 PropertyMember parent; |
| 461 if (parentMember is ConcreteMember) { | 482 if (parentMember is ConcreteMember) { |
| 462 parentMember = parentMember.baseMember; | 483 ConcreteMember c = parentMember; |
| 484 parent = c.baseMember; |
| 485 } else { |
| 486 parent = parentMember; |
| 463 } | 487 } |
| 464 | 488 |
| 465 if (getter == null) getter = parentMember.getter; | 489 if (getter == null) getter = parent.getter; |
| 466 if (setter == null) setter = parentMember.setter; | 490 if (setter == null) setter = parent.setter; |
| 467 } | 491 } |
| 468 | 492 |
| 469 resolve(Type inType) { | 493 resolve(Type inType) { |
| 470 if (getter != null) getter.resolve(inType); | 494 if (getter != null) getter.resolve(inType); |
| 471 if (setter != null) setter.resolve(inType); | 495 if (setter != null) setter.resolve(inType); |
| 472 | 496 |
| 473 library._addMember(this); | 497 library._addMember(this); |
| 474 } | 498 } |
| 475 } | 499 } |
| 476 | 500 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 493 parameters.add(p); | 517 parameters.add(p); |
| 494 } | 518 } |
| 495 } | 519 } |
| 496 } | 520 } |
| 497 | 521 |
| 498 SourceSpan get span() => baseMember.span; | 522 SourceSpan get span() => baseMember.span; |
| 499 | 523 |
| 500 bool get isStatic() => baseMember.isStatic; | 524 bool get isStatic() => baseMember.isStatic; |
| 501 bool get isAbstract() => baseMember.isAbstract; | 525 bool get isAbstract() => baseMember.isAbstract; |
| 502 bool get isConst() => baseMember.isConst; | 526 bool get isConst() => baseMember.isConst; |
| 527 bool get isFactory() => baseMember.isFactory; |
| 503 | 528 |
| 504 String get jsname() => baseMember.jsname; | 529 String get jsname() => baseMember.jsname; |
| 505 set jsname(String name) => | 530 set jsname(String name) => |
| 506 world.internalError('bad set of jsname on ConcreteMember'); | 531 world.internalError('bad set of jsname on ConcreteMember'); |
| 507 | 532 |
| 508 bool get isFactory() => baseMember.isFactory; | |
| 509 | 533 |
| 510 bool get canGet() => baseMember.canGet; | 534 bool get canGet() => baseMember.canGet; |
| 511 bool get canSet() => baseMember.canSet; | 535 bool get canSet() => baseMember.canSet; |
| 512 bool canInvoke(MethodGenerator context, Arguments args) => | 536 bool canInvoke(MethodGenerator context, Arguments args) => |
| 513 baseMember.canInvoke(context, args); | 537 baseMember.canInvoke(context, args); |
| 514 | 538 |
| 515 bool get isField() => baseMember.isField; | 539 bool get isField() => baseMember.isField; |
| 516 bool get isMethod() => baseMember.isMethod; | 540 bool get isMethod() => baseMember.isMethod; |
| 517 bool get isProperty() => baseMember.isProperty; | 541 bool get isProperty() => baseMember.isProperty; |
| 518 | 542 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 bool get isMethod() => !isConstructor; | 633 bool get isMethod() => !isConstructor; |
| 610 | 634 |
| 611 bool get isNative() => definition.body is NativeStatement; | 635 bool get isNative() => definition.body is NativeStatement; |
| 612 | 636 |
| 613 bool get canGet() => false; // TODO(jimhug): get bound method support. | 637 bool get canGet() => false; // TODO(jimhug): get bound method support. |
| 614 bool get canSet() => false; | 638 bool get canSet() => false; |
| 615 | 639 |
| 616 SourceSpan get span() => definition == null ? null : definition.span; | 640 SourceSpan get span() => definition == null ? null : definition.span; |
| 617 | 641 |
| 618 String get constructorName() { | 642 String get constructorName() { |
| 619 if (definition.returnType == null) return ''; | 643 NameTypeReference returnType = definition.returnType; |
| 644 if (returnType == null) return ''; |
| 620 | 645 |
| 621 // TODO(jmesserly): make this easier? | 646 // TODO(jmesserly): make this easier? |
| 622 if (definition.returnType.names != null) { | 647 if (returnType.names != null) { |
| 623 return definition.returnType.names[0].name; | 648 return returnType.names[0].name; |
| 624 } else if (definition.returnType.name != null) { | 649 } else if (returnType.name != null) { |
| 625 return definition.returnType.name.name; | 650 return returnType.name.name; |
| 626 } | 651 } |
| 627 world.internalError('no valid constructor name', definition.span); | 652 world.internalError('no valid constructor name', definition.span); |
| 628 } | 653 } |
| 629 | 654 |
| 630 Type get functionType() { | 655 Type get functionType() { |
| 631 if (_functionType == null) { | 656 if (_functionType == null) { |
| 632 _functionType = library.getOrAddFunctionType(name, | 657 _functionType = library.getOrAddFunctionType(name, |
| 633 definition, declaringType); | 658 definition, declaringType); |
| 634 // TODO(jimhug): Better resolution checks. | 659 // TODO(jimhug): Better resolution checks. |
| 635 if (parameters == null) { | 660 if (parameters == null) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 int indexOfParameter(String name) { | 704 int indexOfParameter(String name) { |
| 680 for (int i = 0; i < parameters.length; i++) { | 705 for (int i = 0; i < parameters.length; i++) { |
| 681 final p = parameters[i]; | 706 final p = parameters[i]; |
| 682 if (p.isOptional && p.name == name) { | 707 if (p.isOptional && p.name == name) { |
| 683 return i; | 708 return i; |
| 684 } | 709 } |
| 685 } | 710 } |
| 686 return -1; | 711 return -1; |
| 687 } | 712 } |
| 688 | 713 |
| 689 Type resolveType(TypeReference node, bool isRequired) { | |
| 690 var type = declaringType.resolveType(node, isRequired); | |
| 691 if (isStatic && type.hasTypeParams) { | |
| 692 // TODO(jimhug): Is this really so hard? | |
| 693 world.error('using type parameter in static context', | |
| 694 node.span); | |
| 695 } | |
| 696 return type; | |
| 697 } | |
| 698 | |
| 699 bool get prefersPropertySyntax() => true; | 714 bool get prefersPropertySyntax() => true; |
| 700 bool get requiresFieldSyntax() => false; | 715 bool get requiresFieldSyntax() => false; |
| 701 | 716 |
| 702 void provideFieldSyntax() => _provideFieldSyntax = true; | 717 void provideFieldSyntax() => _provideFieldSyntax = true; |
| 703 void providePropertySyntax() => _providePropertySyntax = true; | 718 void providePropertySyntax() => _providePropertySyntax = true; |
| 704 | 719 |
| 705 Value set_(MethodGenerator context, Node, Value target, Value value, | 720 Value set_(MethodGenerator context, Node, Value target, Value value, |
| 706 [bool isDynamic=false]) { | 721 [bool isDynamic=false]) { |
| 707 world.error('can not set method', definition.span); | 722 world.error('can not set method', definition.span); |
| 708 } | 723 } |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 return new Value(returnType, '$jsname($argsString)'); | 918 return new Value(returnType, '$jsname($argsString)'); |
| 904 } | 919 } |
| 905 return new Value(returnType, | 920 return new Value(returnType, |
| 906 '${declaringType.jsname}.$jsname($argsString)'); | 921 '${declaringType.jsname}.$jsname($argsString)'); |
| 907 } | 922 } |
| 908 | 923 |
| 909 var code = '${target.code}.$jsname($argsString)'; | 924 var code = '${target.code}.$jsname($argsString)'; |
| 910 // optimize expressions which we know statically their value. | 925 // optimize expressions which we know statically their value. |
| 911 if (target.isConst) { | 926 if (target.isConst) { |
| 912 if (target is GlobalValue) { | 927 if (target is GlobalValue) { |
| 913 target = target.exp; | 928 target = target.dynamic.exp; // TODO: an inline "cast" would be nice. |
| 914 } | 929 } |
| 915 if (name == 'get\$length') { | 930 if (name == 'get\$length') { |
| 916 if (target is ConstListValue || target is ConstMapValue) { | 931 if (target is ConstListValue || target is ConstMapValue) { |
| 917 code = '${target.values.length}'; | 932 code = '${target.dynamic.values.length}'; |
| 918 } | 933 } |
| 919 } else if (name == 'isEmpty') { | 934 } else if (name == 'isEmpty') { |
| 920 if (target is ConstListValue || target is ConstMapValue) { | 935 if (target is ConstListValue || target is ConstMapValue) { |
| 921 code = '${target.values.isEmpty()}'; | 936 code = '${target.dynamic.values.isEmpty()}'; |
| 922 } | 937 } |
| 923 } | 938 } |
| 924 } | 939 } |
| 925 | 940 |
| 926 // TODO(jmesserly): factor this better | 941 // TODO(jmesserly): factor this better |
| 927 if (name == 'get\$typeName' && declaringType.library == world.dom) { | 942 if (name == 'get\$typeName' && declaringType.library == world.dom) { |
| 928 world.gen.corejs.useTypeNameOf = true; | 943 world.gen.corejs.useTypeNameOf = true; |
| 929 } | 944 } |
| 930 | 945 |
| 931 return new Value(returnType, code); | 946 return new Value(returnType, code); |
| 932 } | 947 } |
| 933 | 948 |
| 934 Value _invokeConstructor(MethodGenerator context, Node node, Value target, | 949 Value _invokeConstructor(MethodGenerator context, Node node, |
| 935 Arguments args, argsString) { | 950 Value target, Arguments args, argsString) { |
| 936 declaringType.markUsed(); | 951 declaringType.markUsed(); |
| 937 | 952 |
| 938 if (target != null) { | 953 if (target != null) { |
| 939 // initializer call to another constructor | 954 // initializer call to another constructor |
| 940 var code = (constructorName != '') | 955 var code = (constructorName != '') |
| 941 ? '${declaringType.jsname}.${constructorName}\$ctor.call($argsString)' | 956 ? '${declaringType.jsname}.${constructorName}\$ctor.call($argsString)' |
| 942 : '${declaringType.jsname}.call($argsString)'; | 957 : '${declaringType.jsname}.call($argsString)'; |
| 943 return new Value(declaringType, code); | 958 return new Value(declaringType, code); |
| 944 } else { | 959 } else { |
| 945 var code = (constructorName != '') | 960 var code = (constructorName != '') |
| 946 ? 'new ${declaringType.jsname}.${constructorName}\$ctor($argsString)' | 961 ? 'new ${declaringType.jsname}.${constructorName}\$ctor($argsString)' |
| 947 : 'new ${declaringType.jsname}($argsString)'; | 962 : 'new ${declaringType.jsname}($argsString)'; |
| 948 if (isConst && node.isConst) { | 963 // TODO(jmesserly): using the "node" here feels really hacky |
| 964 if (isConst && node is NewExpression && node.dynamic.isConst) { |
| 949 return _invokeConstConstructor(node, code, target, args); | 965 return _invokeConstConstructor(node, code, target, args); |
| 950 } else { | 966 } else { |
| 951 return new Value(declaringType, code); | 967 return new Value(declaringType, code); |
| 952 } | 968 } |
| 953 } | 969 } |
| 954 } | 970 } |
| 955 | 971 |
| 956 /** | 972 /** |
| 957 * Special handling for const constructors so that so that: | 973 * Special handling for const constructors so that so that: |
| 958 * [: const B() === const B.a(0, 1) === const B.b(0) :] | 974 * [: const B() === const B.a(0, 1) === const B.b(0) :] |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 // Super-call: embed the value the super class fields. | 1041 // Super-call: embed the value the super class fields. |
| 1026 if (value is GlobalValue) { | 1042 if (value is GlobalValue) { |
| 1027 value = value.exp; | 1043 value = value.exp; |
| 1028 } | 1044 } |
| 1029 for (var fname in value.fields.getKeys()) { | 1045 for (var fname in value.fields.getKeys()) { |
| 1030 fields[fname] = value.fields[fname]; | 1046 fields[fname] = value.fields[fname]; |
| 1031 } | 1047 } |
| 1032 } | 1048 } |
| 1033 } else { | 1049 } else { |
| 1034 // Normal field initializer assignment. | 1050 // Normal field initializer assignment. |
| 1035 var fname = init.x.name.name; | 1051 BinaryExpression assign = init; |
| 1036 var val = generator.visitValue(init.y); | 1052 VarExpression x = assign.x; |
| 1053 var fname = x.name.name; |
| 1054 var val = generator.visitValue(assign.y); |
| 1037 fields[fname] = val; | 1055 fields[fname] = val; |
| 1038 } | 1056 } |
| 1039 } | 1057 } |
| 1040 | 1058 |
| 1041 generator._popBlock(); | 1059 generator._popBlock(); |
| 1042 } | 1060 } |
| 1043 | 1061 |
| 1044 // Add default values only if they weren't overriden in the constructor. | 1062 // Add default values only if they weren't overriden in the constructor. |
| 1045 for (var f in declaringType.members.getValues()) { | 1063 for (var f in declaringType.members.getValues()) { |
| 1046 if (f is FieldMember && !f.isStatic && f.value != null | 1064 if (f is FieldMember && !f.isStatic && f.value != null |
| (...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1543 } | 1561 } |
| 1544 | 1562 |
| 1545 void forEach(void f(Member member)) { | 1563 void forEach(void f(Member member)) { |
| 1546 factories.forEach((_, Map constructors) { | 1564 factories.forEach((_, Map constructors) { |
| 1547 constructors.forEach((_, Member member) { | 1565 constructors.forEach((_, Member member) { |
| 1548 f(member); | 1566 f(member); |
| 1549 }); | 1567 }); |
| 1550 }); | 1568 }); |
| 1551 } | 1569 } |
| 1552 } | 1570 } |
| OLD | NEW |