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