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 |