Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: frog/member.dart

Issue 8523012: first stage of Value cleanups (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: rebased Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 133
134 Definition get initDelegate() => 134 Definition get initDelegate() =>
135 world.internalError('cannot have initializers', span); 135 world.internalError('cannot have initializers', span);
136 Definition set initDelegate(ctor) => 136 Definition set initDelegate(ctor) =>
137 world.internalError('cannot have initializers', span); 137 world.internalError('cannot have initializers', span);
138 138
139 Definition get definition() => null; 139 Definition get definition() => null;
140 140
141 List<Parameter> get parameters() => []; 141 List<Parameter> get parameters() => [];
142 142
143 // 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? 143 // TODO(jmesserly): isDynamic isn't a great name for this, something better?
145 abstract Value get_(MethodGenerator context, Node node, Value target, 144 abstract Value _get(MethodGenerator context, Node node, Value target,
146 [bool isDynamic]); 145 [bool isDynamic]);
147 146
148 abstract Value set_(MethodGenerator context, Node node, Value target, 147 abstract Value _set(MethodGenerator context, Node node, Value target,
149 Value value, [bool isDynamic]); 148 Value value, [bool isDynamic]);
150 149
151 bool canInvoke(MethodGenerator context, Arguments args) { 150 bool canInvoke(MethodGenerator context, Arguments args) {
152 return canGet && new Value(returnType, null).canInvoke(context, '\$call', ar gs); 151 // TODO(jimhug): Needs better source location?
Jennifer Messerly 2011/11/10 22:50:39 I would hope that "canInvoke" can't emit errors.
152 return canGet &&
153 new Value(returnType, null, null).canInvoke(context, '\$call', args);
153 } 154 }
154 155
155 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, 156 Value invoke(MethodGenerator context, Node node, Value target, Arguments args,
156 [bool isDynamic=false]) { 157 [bool isDynamic=false]) {
157 var newTarget = get_(context, node, target, isDynamic); 158 var newTarget = _get(context, node, target, isDynamic);
158 return newTarget.invoke(context, '\$call', node, args, isDynamic); 159 return newTarget.invoke(context, '\$call', node, args, isDynamic);
159 } 160 }
160 161
161 bool override(Member other) { 162 bool override(Member other) {
162 if (isStatic) { 163 if (isStatic) {
163 world.error('static members can not hide parent members', 164 world.error('static members can not hide parent members',
164 span, other.span); 165 span, other.span);
165 return false; 166 return false;
166 } else if (other.isStatic) { 167 } else if (other.isStatic) {
167 world.error('can not override static member', span, other.span); 168 world.error('can not override static member', span, other.span);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 211
211 // If this really becomes first class, this should return typeof(Type) 212 // If this really becomes first class, this should return typeof(Type)
212 Type get returnType() => world.varType; 213 Type get returnType() => world.varType;
213 214
214 bool canInvoke(MethodGenerator context, Arguments args) => false; 215 bool canInvoke(MethodGenerator context, Arguments args) => false;
215 bool get canGet() => true; 216 bool get canGet() => true;
216 bool get canSet() => false; 217 bool get canSet() => false;
217 218
218 void resolve(Type inType) {} 219 void resolve(Type inType) {}
219 220
220 Value get_(MethodGenerator context, Node node, Value target, 221 Value _get(MethodGenerator context, Node node, Value target,
221 [bool isDynamic=false]) { 222 [bool isDynamic=false]) {
222 assert(target == null || target.type.isTop);
223 // TODO(jmesserly): named args 223 // TODO(jmesserly): named args
Jennifer Messerly 2011/11/10 22:50:39 btw, I think the VM is the main blocker here. Mayb
224 return new Value(type, type.jsname, false, false, true); 224 return new Value(type, type.jsname, node.span, false, false, true);
225 } 225 }
226 226
227 Value set_(MethodGenerator context, Node node, Value target, Value value, 227 Value _set(MethodGenerator context, Node node, Value target, Value value,
228 [bool isDynamic=false]) { 228 [bool isDynamic=false]) {
229 world.error('can not set type', type.definition.span); 229 world.error('can not set type', type.definition.span);
230 } 230 }
231 231
232 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, 232 Value invoke(MethodGenerator context, Node node, Value target, Arguments args,
233 [bool isDynamic=false]) { 233 [bool isDynamic=false]) {
234 world.error('can not invoke type', type.definition.span); 234 world.error('can not invoke type', type.definition.span);
235 } 235 }
236 } 236 }
237 237
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 360
361 if (isStatic) { 361 if (isStatic) {
362 _computedValue = world.gen.globalForStaticField( 362 _computedValue = world.gen.globalForStaticField(
363 this, _computedValue, [_computedValue]); 363 this, _computedValue, [_computedValue]);
364 } 364 }
365 _computing = false; 365 _computing = false;
366 } 366 }
367 return _computedValue; 367 return _computedValue;
368 } 368 }
369 369
370 Value get_(MethodGenerator context, Node node, Value target, 370 Value _get(MethodGenerator context, Node node, Value target,
371 [bool isDynamic=false]) { 371 [bool isDynamic=false]) {
372 if (!isDynamic) { 372 if (!isDynamic) {
373 declaringType.markUsed(); 373 declaringType.markUsed();
374 } 374 }
375 if (isStatic) { 375 if (isStatic) {
376 // Make sure to compute the value of all static fields, even if we don't 376 // Make sure to compute the value of all static fields, even if we don't
377 // use this value immediately. 377 // use this value immediately.
378 var cv = computeValue(); 378 var cv = computeValue();
379 if (isFinal) { 379 if (isFinal) {
380 return cv; 380 return cv;
381 } 381 }
382 if (declaringType.isTop) { 382 if (declaringType.isTop) {
383 return new Value(type, '$jsname'); 383 return new Value(type, '$jsname', node.span);
384 } else { 384 } else {
385 return new Value(type, '${declaringType.jsname}.$jsname'); 385 return new Value(type, '${declaringType.jsname}.$jsname', node.span);
386 } 386 }
387 } else if (target.isConst && isFinal) { 387 } else if (target.isConst && isFinal) {
388 // take advantage of consts and retrieve the value directly if possible 388 // take advantage of consts and retrieve the value directly if possible
389 var constTarget = target is GlobalValue ? target.dynamic.exp : target; 389 var constTarget = target is GlobalValue ? target.dynamic.exp : target;
390 if (constTarget is ConstObjectValue) { 390 if (constTarget is ConstObjectValue) {
391 return constTarget.fields[name]; 391 return constTarget.fields[name];
392 } else if (constTarget.type == world.stringType && name == 'length') { 392 } else if (constTarget.type == world.stringType && name == 'length') {
393 return new Value(type, '${constTarget.actualValue.length}'); 393 return new Value(type, '${constTarget.actualValue.length}', node.span);
394 } 394 }
395 } 395 }
396 return new Value(type, '${target.code}.$jsname'); 396 return new Value(type, '${target.code}.$jsname', node.span);
397 } 397 }
398 398
399 Value set_(MethodGenerator context, Node node, Value target, Value value, 399 Value _set(MethodGenerator context, Node node, Value target, Value value,
400 [bool isDynamic=false]) { 400 [bool isDynamic=false]) {
401 var lhs = get_(context, node, target, isDynamic); 401 var lhs = _get(context, node, target, isDynamic);
402 value = value.convertTo(context, type, node, isDynamic); 402 value = value.convertTo(context, type, node, isDynamic);
403 return new Value(type, '${lhs.code} = ${value.code}'); 403 return new Value(type, '${lhs.code} = ${value.code}', node.span);
404 } 404 }
405 } 405 }
406 406
407 class PropertyMember extends Member { 407 class PropertyMember extends Member {
408 MethodMember getter; 408 MethodMember getter;
409 MethodMember setter; 409 MethodMember setter;
410 410
411 Member _overriddenField; 411 Member _overriddenField;
412 412
413 bool _provideFieldSyntax = false; 413 bool _provideFieldSyntax = false;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 if (other.isProperty) addFromParent(other); 445 if (other.isProperty) addFromParent(other);
446 else _overriddenField = other; 446 else _overriddenField = other;
447 return true; 447 return true;
448 } else { 448 } else {
449 world.error('property can only override field or property', 449 world.error('property can only override field or property',
450 span, other.span); 450 span, other.span);
451 return false; 451 return false;
452 } 452 }
453 } 453 }
454 454
455 Value get_(MethodGenerator context, Node node, Value target, 455 Value _get(MethodGenerator context, Node node, Value target,
456 [bool isDynamic=false]) { 456 [bool isDynamic=false]) {
457 if (getter == null) { 457 if (getter == null) {
458 if (_overriddenField != null) { 458 if (_overriddenField != null) {
459 return _overriddenField.get_(context, node, target, isDynamic); 459 return _overriddenField._get(context, node, target, isDynamic);
460 } 460 }
461 return target.invokeNoSuchMethod(context, 'get:$name', node); 461 return target.invokeNoSuchMethod(context, 'get:$name', node);
462 } 462 }
463 return getter.invoke(context, node, target, Arguments.EMPTY); 463 return getter.invoke(context, node, target, Arguments.EMPTY);
464 } 464 }
465 465
466 Value set_(MethodGenerator context, Node node, Value target, Value value, 466 Value _set(MethodGenerator context, Node node, Value target, Value value,
467 [bool isDynamic=false]) { 467 [bool isDynamic=false]) {
468 if (setter == null) { 468 if (setter == null) {
469 if (_overriddenField != null) { 469 if (_overriddenField != null) {
470 return _overriddenField.set_(context, node, target, value, isDynamic); 470 return _overriddenField._set(context, node, target, value, isDynamic);
471 } 471 }
472 return target.invokeNoSuchMethod(context, 'set:$name', node, 472 return target.invokeNoSuchMethod(context, 'set:$name', node,
473 new Arguments(null, [value])); 473 new Arguments(null, [value]));
474 } 474 }
475 return setter.invoke(context, node, target, new Arguments(null, [value]), 475 return setter.invoke(context, node, target, new Arguments(null, [value]),
476 isDynamic); 476 isDynamic);
477 } 477 }
478 478
479 addFromParent(Member parentMember) { 479 addFromParent(Member parentMember) {
480 // TODO(jimhug): Egregious Hack! 480 // TODO(jimhug): Egregious Hack!
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 Definition set initDelegate(ctor) { baseMember.initDelegate = ctor; } 557 Definition set initDelegate(ctor) { baseMember.initDelegate = ctor; }
558 558
559 Type resolveType(TypeReference node, bool isRequired) { 559 Type resolveType(TypeReference node, bool isRequired) {
560 var type = baseMember.resolveType(node, isRequired); 560 var type = baseMember.resolveType(node, isRequired);
561 return type.resolveTypeParams(declaringType); 561 return type.resolveTypeParams(declaringType);
562 } 562 }
563 563
564 // TODO(jimhug): Add support for type params. 564 // TODO(jimhug): Add support for type params.
565 bool override(Member other) => baseMember.override(other); 565 bool override(Member other) => baseMember.override(other);
566 566
567 Value get_(MethodGenerator context, Node node, Value target, 567 Value _get(MethodGenerator context, Node node, Value target,
568 [bool isDynamic=false]) { 568 [bool isDynamic=false]) {
569 Value ret = baseMember.get_(context, node, target, isDynamic); 569 Value ret = baseMember._get(context, node, target, isDynamic);
570 return new Value(returnType, ret.code); 570 return new Value(returnType, ret.code, node.span);
571 } 571 }
572 572
573 Value set_(MethodGenerator context, Node node, Value target, Value value, 573 Value _set(MethodGenerator context, Node node, Value target, Value value,
574 [bool isDynamic=false]) { 574 [bool isDynamic=false]) {
575 // TODO(jimhug): Check arg types in context of concrete type. 575 // TODO(jimhug): Check arg types in context of concrete type.
576 Value ret = baseMember.set_(context, node, target, value, isDynamic); 576 Value ret = baseMember._set(context, node, target, value, isDynamic);
577 return new Value(returnType, ret.code); 577 return new Value(returnType, ret.code, node.span);
578 } 578 }
579 579
580 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, 580 Value invoke(MethodGenerator context, Node node, Value target, Arguments args,
581 [bool isDynamic=false]) { 581 [bool isDynamic=false]) {
582 // TODO(jimhug): Check arg types in context of concrete type. 582 // TODO(jimhug): Check arg types in context of concrete type.
583 Value ret = baseMember.invoke(context, node, target, args, isDynamic); 583 Value ret = baseMember.invoke(context, node, target, args, isDynamic);
584 var code = ret.code; 584 var code = ret.code;
585 if (isConstructor) { 585 if (isConstructor) {
586 // TODO(jimhug): Egregious hack - won't live through the weekend. 586 // TODO(jimhug): Egregious hack - won't live through the weekend.
587 code = code.replaceFirst( 587 code = code.replaceFirst(
588 declaringType.genericType.jsname, declaringType.jsname); 588 declaringType.genericType.jsname, declaringType.jsname);
589 } 589 }
590 declaringType.genMethod(this); 590 declaringType.genMethod(this);
591 return new Value(returnType, code); 591 return new Value(returnType, code, node.span);
592 } 592 }
593 } 593 }
594 594
595 595
596 /** Represents a Dart method or top-level function. */ 596 /** Represents a Dart method or top-level function. */
597 class MethodMember extends Member { 597 class MethodMember extends Member {
598 FunctionDefinition definition; 598 FunctionDefinition definition;
599 Type returnType; 599 Type returnType;
600 List<Parameter> parameters; 600 List<Parameter> parameters;
601 601
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 } 710 }
711 return -1; 711 return -1;
712 } 712 }
713 713
714 bool get prefersPropertySyntax() => true; 714 bool get prefersPropertySyntax() => true;
715 bool get requiresFieldSyntax() => false; 715 bool get requiresFieldSyntax() => false;
716 716
717 void provideFieldSyntax() => _provideFieldSyntax = true; 717 void provideFieldSyntax() => _provideFieldSyntax = true;
718 void providePropertySyntax() => _providePropertySyntax = true; 718 void providePropertySyntax() => _providePropertySyntax = true;
719 719
720 Value set_(MethodGenerator context, Node, Value target, Value value, 720 Value _set(MethodGenerator context, Node, Value target, Value value,
721 [bool isDynamic=false]) { 721 [bool isDynamic=false]) {
722 world.error('can not set method', definition.span); 722 world.error('can not set method', definition.span);
723 } 723 }
724 724
725 Value get_(MethodGenerator context, Node node, Value target, 725 Value _get(MethodGenerator context, Node node, Value target,
726 [bool isDynamic=false]) { 726 [bool isDynamic=false]) {
727 // TODO(jimhug): Would prefer to invoke! 727 // TODO(jimhug): Would prefer to invoke!
728 declaringType.genMethod(this); 728 declaringType.genMethod(this);
729 _provideOptionalParamInfo = true; 729 _provideOptionalParamInfo = true;
730 if (isStatic) { 730 if (isStatic) {
731 var type = declaringType.isTop ? '' : '${declaringType.jsname}.'; 731 var type = declaringType.isTop ? '' : '${declaringType.jsname}.';
732 return new Value(functionType, '$type$jsname'); 732 return new Value(functionType, '$type$jsname', node.span);
733 } 733 }
734 _providePropertySyntax = true; 734 _providePropertySyntax = true;
735 return new Value(functionType, '${target.code}.get\$$jsname()'); 735 return new Value(functionType, '${target.code}.get\$$jsname()', node.span);
736 } 736 }
737 737
738 bool namesInOrder(Arguments args) { 738 bool namesInOrder(Arguments args) {
739 if (!args.hasNames) return true; 739 if (!args.hasNames) return true;
740 740
741 int lastParameter = null; 741 int lastParameter = null;
742 for (int i = args.bareCount; i < parameters.length; i++) { 742 for (int i = args.bareCount; i < parameters.length; i++) {
743 var p = args.getIndexOfName(parameters[i].name); 743 var p = args.getIndexOfName(parameters[i].name);
744 // Only worry about parameters that needTemps. Otherwise it's fine to 744 // Only worry about parameters that needTemps. Otherwise it's fine to
745 // reorder. 745 // reorder.
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 894
895 var argsString = Strings.join(argsCode, ', '); 895 var argsString = Strings.join(argsCode, ', ');
896 896
897 if (isConstructor) { 897 if (isConstructor) {
898 return _invokeConstructor(context, node, target, args, argsString); 898 return _invokeConstructor(context, node, target, args, argsString);
899 } 899 }
900 900
901 // TODO(jimhug): target really shouldn't ever be null... 901 // TODO(jimhug): target really shouldn't ever be null...
902 if (target != null && target.isSuper) { 902 if (target != null && target.isSuper) {
903 return new Value(returnType, 903 return new Value(returnType,
904 '${declaringType.jsname}.prototype.$jsname.call($argsString)'); 904 '${declaringType.jsname}.prototype.$jsname.call($argsString)',
905 node.span);
905 } 906 }
906 907
907 if (name.startsWith('\$')) { 908 if (name.startsWith('\$')) {
908 return _invokeBuiltin(context, node, target, args, argsCode); 909 return _invokeBuiltin(context, node, target, args, argsCode);
909 } 910 }
910 911
911 if (isFactory) { 912 if (isFactory) {
912 return new Value(returnType, '$generatedFactoryName($argsString)'); 913 return new Value(returnType, '$generatedFactoryName($argsString)',
914 node.span);
913 } 915 }
914 916
915 if (isStatic) { 917 if (isStatic) {
916 if (declaringType.isTop) { 918 if (declaringType.isTop) {
917 // TODO(jimhug): Explore moving libraries into their own namespaces 919 // TODO(jimhug): Explore moving libraries into their own namespaces
918 return new Value(returnType, '$jsname($argsString)'); 920 return new Value(returnType, '$jsname($argsString)', node != null ? node .span : node);
919 } 921 }
920 return new Value(returnType, 922 return new Value(returnType,
921 '${declaringType.jsname}.$jsname($argsString)'); 923 '${declaringType.jsname}.$jsname($argsString)', node.span);
922 } 924 }
923 925
924 var code = '${target.code}.$jsname($argsString)'; 926 var code = '${target.code}.$jsname($argsString)';
925 // optimize expressions which we know statically their value. 927 // optimize expressions which we know statically their value.
926 if (target.isConst) { 928 if (target.isConst) {
927 if (target is GlobalValue) { 929 if (target is GlobalValue) {
928 target = target.dynamic.exp; // TODO: an inline "cast" would be nice. 930 target = target.dynamic.exp; // TODO: an inline "cast" would be nice.
929 } 931 }
930 if (name == 'get\$length') { 932 if (name == 'get\$length') {
931 if (target is ConstListValue || target is ConstMapValue) { 933 if (target is ConstListValue || target is ConstMapValue) {
932 code = '${target.dynamic.values.length}'; 934 code = '${target.dynamic.values.length}';
933 } 935 }
934 } else if (name == 'isEmpty') { 936 } else if (name == 'isEmpty') {
935 if (target is ConstListValue || target is ConstMapValue) { 937 if (target is ConstListValue || target is ConstMapValue) {
936 code = '${target.dynamic.values.isEmpty()}'; 938 code = '${target.dynamic.values.isEmpty()}';
937 } 939 }
938 } 940 }
939 } 941 }
940 942
941 // TODO(jmesserly): factor this better 943 // TODO(jmesserly): factor this better
942 if (name == 'get\$typeName' && declaringType.library == world.dom) { 944 if (name == 'get\$typeName' && declaringType.library == world.dom) {
943 world.gen.corejs.useTypeNameOf = true; 945 world.gen.corejs.useTypeNameOf = true;
944 } 946 }
945 947
946 return new Value(returnType, code); 948 return new Value(returnType, code, node.span);
947 } 949 }
948 950
949 Value _invokeConstructor(MethodGenerator context, Node node, 951 Value _invokeConstructor(MethodGenerator context, Node node,
950 Value target, Arguments args, argsString) { 952 Value target, Arguments args, argsString) {
951 declaringType.markUsed(); 953 declaringType.markUsed();
952 954
953 if (target != null) { 955 if (target != null) {
954 // initializer call to another constructor 956 // initializer call to another constructor
955 var code = (constructorName != '') 957 var code = (constructorName != '')
956 ? '${declaringType.jsname}.${constructorName}\$ctor.call($argsString)' 958 ? '${declaringType.jsname}.${constructorName}\$ctor.call($argsString)'
957 : '${declaringType.jsname}.call($argsString)'; 959 : '${declaringType.jsname}.call($argsString)';
958 return new Value(declaringType, code); 960 return new Value(declaringType, code, node.span);
959 } else { 961 } else {
960 var code = (constructorName != '') 962 var code = (constructorName != '')
961 ? 'new ${declaringType.jsname}.${constructorName}\$ctor($argsString)' 963 ? 'new ${declaringType.jsname}.${constructorName}\$ctor($argsString)'
962 : 'new ${declaringType.jsname}($argsString)'; 964 : 'new ${declaringType.jsname}($argsString)';
963 // TODO(jmesserly): using the "node" here feels really hacky 965 // TODO(jmesserly): using the "node" here feels really hacky
964 if (isConst && node is NewExpression && node.dynamic.isConst) { 966 if (isConst && node is NewExpression && node.dynamic.isConst) {
965 return _invokeConstConstructor(node, code, target, args); 967 return _invokeConstConstructor(node, code, target, args);
966 } else { 968 } else {
967 return new Value(declaringType, code); 969 return new Value(declaringType, code, node.span);
968 } 970 }
969 } 971 }
970 } 972 }
971 973
972 /** 974 /**
973 * Special handling for const constructors so that so that: 975 * Special handling for const constructors so that so that:
974 * [: const B() === const B.a(0, 1) === const B.b(0) :] 976 * [: const B() === const B.a(0, 1) === const B.b(0) :]
975 * where: [: 977 * where: [:
976 * class A { 978 * class A {
977 * final int x; 979 * final int x;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 } else if (name == '\$bit_not') { 1089 } else if (name == '\$bit_not') {
1088 code = '~${target.code}'; 1090 code = '~${target.code}';
1089 } else if (name == '\$truncdiv' || name == '\$mod') { 1091 } else if (name == '\$truncdiv' || name == '\$mod') {
1090 world.gen.corejs.useOperator(name); 1092 world.gen.corejs.useOperator(name);
1091 code = '$name(${target.code}, ${argsCode[0]})'; 1093 code = '$name(${target.code}, ${argsCode[0]})';
1092 } else { 1094 } else {
1093 var op = TokenKind.rawOperatorFromMethod(name); 1095 var op = TokenKind.rawOperatorFromMethod(name);
1094 code = '${target.code} $op ${argsCode[0]}'; 1096 code = '${target.code} $op ${argsCode[0]}';
1095 } 1097 }
1096 1098
1097 return new Value(returnType, code); 1099 return new Value(returnType, code, node.span);
1098 } else { 1100 } else {
1099 var value; 1101 var value;
1100 num val0, val1, ival0, ival1; 1102 num val0, val1, ival0, ival1;
1101 val0 = target.dynamic.actualValue; 1103 val0 = target.dynamic.actualValue;
1102 ival0 = val0.toInt(); 1104 ival0 = val0.toInt();
1103 if (args.values.length > 0) { 1105 if (args.values.length > 0) {
1104 val1 = args.values[0].dynamic.actualValue; 1106 val1 = args.values[0].dynamic.actualValue;
1105 ival1 = val1.toInt(); 1107 ival1 = val1.toInt();
1106 } 1108 }
1107 switch (name) { 1109 switch (name) {
(...skipping 19 matching lines...) Expand all
1127 case '\$shl': value = (ival0 << ival1).toDouble(); break; 1129 case '\$shl': value = (ival0 << ival1).toDouble(); break;
1128 case '\$sar': value = (ival0 >> ival1).toDouble(); break; 1130 case '\$sar': value = (ival0 >> ival1).toDouble(); break;
1129 case '\$shr': value = (ival0 >>> ival1).toDouble(); break; 1131 case '\$shr': value = (ival0 >>> ival1).toDouble(); break;
1130 } 1132 }
1131 return new EvaluatedValue(returnType, value, "$value", node.span); 1133 return new EvaluatedValue(returnType, value, "$value", node.span);
1132 } 1134 }
1133 } else if (declaringType.isString) { 1135 } else if (declaringType.isString) {
1134 if (name == '\$index') { 1136 if (name == '\$index') {
1135 // Note: this could technically propagate constness, but that's not 1137 // Note: this could technically propagate constness, but that's not
1136 // specified explicitly and the VM doesn't do that. 1138 // specified explicitly and the VM doesn't do that.
1137 return new Value(declaringType, '${target.code}[${argsCode[0]}]'); 1139 return new Value(declaringType, '${target.code}[${argsCode[0]}]',
1140 node.span);
1138 } else if (name == '\$add') { 1141 } else if (name == '\$add') {
1139 if (allConst) { 1142 if (allConst) {
1140 var val0 = target.dynamic.actualValue; 1143 var val0 = target.dynamic.actualValue;
1141 val0 = val0.substring(1, val0.length - 1); 1144 val0 = val0.substring(1, val0.length - 1);
1142 var val1 = args.values[0].dynamic.actualValue; 1145 var val1 = args.values[0].dynamic.actualValue;
1143 if (args.values[0].type.isString) { 1146 if (args.values[0].type.isString) {
1144 val1 = val1.substring(1, val1.length - 1); 1147 val1 = val1.substring(1, val1.length - 1);
1145 } 1148 }
1146 var value = '${val0}${val1}'; 1149 var value = '${val0}${val1}';
1147 value = '"' + value.replaceAll('"', '\\"') + '"'; 1150 value = '"' + value.replaceAll('"', '\\"') + '"';
1148 return new EvaluatedValue(world.stringType, value, value, node.span); 1151 return new EvaluatedValue(world.stringType, value, value, node.span);
1149 } 1152 }
1150 1153
1151 // Ensure we generate toString on the right side 1154 // Ensure we generate toString on the right side
1152 args.values[0].invoke(context, 'toString', node, Arguments.EMPTY); 1155 args.values[0].invoke(context, 'toString', node, Arguments.EMPTY);
1153 return new Value(declaringType, '${target.code} + ${argsCode[0]}'); 1156 return new Value(declaringType, '${target.code} + ${argsCode[0]}',
1157 node.span);
1154 } 1158 }
1155 } else if (declaringType.isNativeType) { 1159 } else if (declaringType.isNativeType) {
1156 if (name == '\$index') { 1160 if (name == '\$index') {
1157 // Note: this could technically propagate constness, but that's not 1161 // Note: this could technically propagate constness, but that's not
1158 // specified explicitly and the VM doesn't do that. 1162 // specified explicitly and the VM doesn't do that.
1159 // TODO(jmesserly): why are we using a return type of "var"? 1163 // TODO(jmesserly): why are we using a return type of "var"?
1160 return new Value(null, '${target.code}[${argsCode[0]}]'); 1164 return new Value(null, '${target.code}[${argsCode[0]}]', node.span);
1161 } else if (name == '\$setindex') { 1165 } else if (name == '\$setindex') {
1162 return new Value(null, 1166 return new Value(null,
1163 '${target.code}[${argsCode[0]}] = ${argsCode[1]}'); 1167 '${target.code}[${argsCode[0]}] = ${argsCode[1]}', node.span);
1164 } 1168 }
1165 } 1169 }
1166 1170
1167 // TODO(jimhug): Optimize null on lhs as well. 1171 // TODO(jimhug): Optimize null on lhs as well.
1168 if (name == '\$eq' || name == '\$ne') { 1172 if (name == '\$eq' || name == '\$ne') {
1169 final op = name == '\$eq' ? '==' : '!='; 1173 final op = name == '\$eq' ? '==' : '!=';
1170 if (allConst) { 1174 if (allConst) {
1171 var val0 = target.dynamic.actualValue; 1175 var val0 = target.dynamic.actualValue;
1172 var val1 = args.values[0].dynamic.actualValue; 1176 var val1 = args.values[0].dynamic.actualValue;
1173 var newVal = name == '\$eq' ? val0 == val1 : val0 != val1; 1177 var newVal = name == '\$eq' ? val0 == val1 : val0 != val1;
1174 return new EvaluatedValue(world.boolType, 1178 return new EvaluatedValue(world.boolType,
1175 newVal, "$newVal", node.span); 1179 newVal, "$newVal", node.span);
1176 } 1180 }
1177 // Optimize test when null is on the rhs. 1181 // Optimize test when null is on the rhs.
1178 if (argsCode[0] == 'null') { 1182 if (argsCode[0] == 'null') {
1179 return new Value(returnType, '${target.code} $op null'); 1183 return new Value(returnType, '${target.code} $op null', node.span);
1180 } else if (target.type.isNum || target.type.isString) { 1184 } else if (target.type.isNum || target.type.isString) {
1181 // TODO(jimhug): Maybe check rhs. 1185 // TODO(jimhug): Maybe check rhs.
1182 return new Value(returnType, '${target.code} $op ${argsCode[0]}'); 1186 return new Value(returnType, '${target.code} $op ${argsCode[0]}',
1187 node.span);
1183 } 1188 }
1184 world.gen.corejs.useOperator(name); 1189 world.gen.corejs.useOperator(name);
1185 return new Value(returnType, '$name(${target.code}, ${argsCode[0]})'); 1190 return new Value(returnType, '$name(${target.code}, ${argsCode[0]})',
1191 node.span);
1186 } 1192 }
1187 1193
1188 if (name == '\$call') { 1194 if (name == '\$call') {
1189 declaringType.markUsed(); 1195 declaringType.markUsed();
1190 return new Value(returnType, 1196 return new Value(returnType,
1191 '${target.code}(${Strings.join(argsCode, ", ")})'); 1197 '${target.code}(${Strings.join(argsCode, ", ")})', node.span);
1192 } 1198 }
1193 1199
1194 if (name == '\$index') { 1200 if (name == '\$index') {
1195 world.gen.corejs.useIndex = true; 1201 world.gen.corejs.useIndex = true;
1196 } else if (name == '\$setindex') { 1202 } else if (name == '\$setindex') {
1197 world.gen.corejs.useSetIndex = true; 1203 world.gen.corejs.useSetIndex = true;
1198 } 1204 }
1199 1205
1200 // Fall back to normal method invocation. 1206 // Fall back to normal method invocation.
1201 var argsString = Strings.join(argsCode, ', '); 1207 var argsString = Strings.join(argsCode, ', ');
1202 return new Value(returnType, '${target.code}.$jsname($argsString)'); 1208 return new Value(returnType, '${target.code}.$jsname($argsString)',
1209 node.span);
1203 } 1210 }
1204 1211
1205 1212
1206 resolve(Type inType) { 1213 resolve(Type inType) {
1207 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve 1214 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve
1208 isStatic = inType.isTop; 1215 isStatic = inType.isTop;
1209 isConst = false; 1216 isConst = false;
1210 isFactory = false; 1217 isFactory = false;
1211 isAbstract = !declaringType.isClass; 1218 isAbstract = !declaringType.isClass;
1212 if (definition.modifiers != null) { 1219 if (definition.modifiers != null) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1313 // TODO(jimhug): Always false, or is this needed? 1320 // TODO(jimhug): Always false, or is this needed?
1314 bool get isStatic() => members.length == 1 && members[0].isStatic; 1321 bool get isStatic() => members.length == 1 && members[0].isStatic;
1315 1322
1316 bool canInvoke(MethodGenerator context, Arguments args) => 1323 bool canInvoke(MethodGenerator context, Arguments args) =>
1317 members.some((m) => m.canInvoke(context, args)); 1324 members.some((m) => m.canInvoke(context, args));
1318 1325
1319 Value _makeError(Node node, Value target, String action) { 1326 Value _makeError(Node node, Value target, String action) {
1320 if (!target.type.isVar) { 1327 if (!target.type.isVar) {
1321 world.warning('could not find applicable $action for "$name"', node.span); 1328 world.warning('could not find applicable $action for "$name"', node.span);
1322 } 1329 }
1323 return new Value(null, '${target.code}.$jsname() /*no applicable $action*/') ; 1330 return new Value(null, '${target.code}.$jsname() /*no applicable $action*/',
1331 node.span);
1324 } 1332 }
1325 1333
1326 bool _treatAsField; 1334 bool _treatAsField;
1327 bool get treatAsField() { 1335 bool get treatAsField() {
1328 if (_treatAsField == null) { 1336 if (_treatAsField == null) {
1329 _treatAsField = true; 1337 _treatAsField = true;
1330 for (var member in members) { 1338 for (var member in members) {
1331 if (member.requiresFieldSyntax) { 1339 if (member.requiresFieldSyntax) {
1332 _treatAsField = true; 1340 _treatAsField = true;
1333 break; 1341 break;
1334 } 1342 }
1335 if (member.prefersPropertySyntax) { 1343 if (member.prefersPropertySyntax) {
1336 _treatAsField = false; 1344 _treatAsField = false;
1337 } 1345 }
1338 } 1346 }
1339 for (var member in members) { 1347 for (var member in members) {
1340 if (_treatAsField) { 1348 if (_treatAsField) {
1341 member.provideFieldSyntax(); 1349 member.provideFieldSyntax();
1342 } else { 1350 } else {
1343 member.providePropertySyntax(); 1351 member.providePropertySyntax();
1344 } 1352 }
1345 } 1353 }
1346 } 1354 }
1347 return _treatAsField; 1355 return _treatAsField;
1348 } 1356 }
1349 1357
1350 Value get_(MethodGenerator context, Node node, Value target, 1358 Value _get(MethodGenerator context, Node node, Value target,
1351 [bool isDynamic=false]) { 1359 [bool isDynamic=false]) {
1352 if (members.length == 1) { 1360 if (members.length == 1) {
1353 return members[0].get_(context, node, target, isDynamic); 1361 return members[0]._get(context, node, target, isDynamic);
1354 } 1362 }
1355 final targets = members.filter((m) => m.canGet); 1363 final targets = members.filter((m) => m.canGet);
1356 if (targets.length == 1) { 1364 if (targets.length == 1) {
1357 return targets[0].get_(context, node, target, isDynamic); 1365 return targets[0]._get(context, node, target, isDynamic);
1358 } 1366 }
1359 1367
1360 Value returnValue = null; 1368 Value returnValue = null;
1361 for (var member in targets) { 1369 for (var member in targets) {
1362 final value = member.get_(context, node, target, isDynamic:true); 1370 final value = member._get(context, node, target, isDynamic:true);
1363 returnValue = _tryUnion(returnValue, value, node); 1371 returnValue = _tryUnion(returnValue, value, node);
1364 } 1372 }
1365 if (returnValue == null) { 1373 if (returnValue == null) {
1366 return _makeError(node, target, 'getter'); 1374 return _makeError(node, target, 'getter');
1367 } 1375 }
1368 if (returnValue.code == null) { 1376 if (returnValue.code == null) {
1369 if (treatAsField) { 1377 if (treatAsField) {
1370 return new Value(returnValue.type, '${target.code}.$jsname'); 1378 return new Value(returnValue.type, '${target.code}.$jsname',
1379 node.span);
1371 } else { 1380 } else {
1372 return new Value(returnValue.type, '${target.code}.get\$$jsname()'); 1381 return new Value(returnValue.type, '${target.code}.get\$$jsname()',
1382 node.span);
1373 } 1383 }
1374 } 1384 }
1375 return returnValue; 1385 return returnValue;
1376 } 1386 }
1377 1387
1378 Value set_(MethodGenerator context, Node node, Value target, Value value, 1388 Value _set(MethodGenerator context, Node node, Value target, Value value,
1379 [bool isDynamic=false]) { 1389 [bool isDynamic=false]) {
1380 if (members.length == 1) { 1390 if (members.length == 1) {
1381 return members[0].set_(context, node, target, value, isDynamic); 1391 return members[0]._set(context, node, target, value, isDynamic);
1382 } 1392 }
1383 final targets = members.filter((m) => m.canSet); 1393 final targets = members.filter((m) => m.canSet);
1384 if (targets.length == 1) { 1394 if (targets.length == 1) {
1385 return targets[0].set_(context, node, target, value, isDynamic); 1395 return targets[0]._set(context, node, target, value, isDynamic);
1386 } 1396 }
1387 1397
1388 Value returnValue = null; 1398 Value returnValue = null;
1389 for (var member in targets) { 1399 for (var member in targets) {
1390 final res = member.set_(context, node, target, value, isDynamic:true); 1400 final res = member._set(context, node, target, value, isDynamic:true);
1391 returnValue = _tryUnion(returnValue, res, node); 1401 returnValue = _tryUnion(returnValue, res, node);
1392 } 1402 }
1393 if (returnValue == null) { 1403 if (returnValue == null) {
1394 return _makeError(node, target, 'setter'); 1404 return _makeError(node, target, 'setter');
1395 } 1405 }
1396 if (returnValue.code == null) { 1406 if (returnValue.code == null) {
1397 if (treatAsField) { 1407 if (treatAsField) {
1398 return new Value(returnValue.type, 1408 return new Value(returnValue.type,
1399 '${target.code}.$jsname = ${value.code}'); 1409 '${target.code}.$jsname = ${value.code}', node.span);
1400 } else { 1410 } else {
1401 return new Value(returnValue.type, 1411 return new Value(returnValue.type,
1402 '${target.code}.set\$$jsname(${value.code})'); 1412 '${target.code}.set\$$jsname(${value.code})', node.span);
1403 } 1413 }
1404 } 1414 }
1405 return returnValue; 1415 return returnValue;
1406 } 1416 }
1407 1417
1408 Value invoke(MethodGenerator context, Node node, Value target, 1418 Value invoke(MethodGenerator context, Node node, Value target,
1409 Arguments args, [bool isDynamic=false]) { 1419 Arguments args, [bool isDynamic=false]) {
1410 if (members.length == 1) { 1420 if (members.length == 1) {
1411 return members[0].invoke(context, node, target, args, isDynamic); 1421 return members[0].invoke(context, node, target, args, isDynamic);
1412 } 1422 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 1463
1454 Value _tryUnion(Value x, Value y, Node node) { 1464 Value _tryUnion(Value x, Value y, Node node) {
1455 if (x == null) return y; 1465 if (x == null) return y;
1456 var type = Type.union(x.type, y.type); 1466 var type = Type.union(x.type, y.type);
1457 if (x.code == y.code) { 1467 if (x.code == y.code) {
1458 if (type == x.type) { 1468 if (type == x.type) {
1459 return x; 1469 return x;
1460 } else if (x.isConst || y.isConst) { 1470 } else if (x.isConst || y.isConst) {
1461 world.internalError("unexpected: union of const values "); 1471 world.internalError("unexpected: union of const values ");
1462 } else { 1472 } else {
1463 return new Value(type, x.code, 1473 return new Value(type, x.code, node.span,
1464 x.isSuper && y.isSuper, 1474 x.isSuper && y.isSuper,
1465 x.needsTemp || y.needsTemp, 1475 x.needsTemp || y.needsTemp,
1466 x.isType && y.isType); 1476 x.isType && y.isType);
1467 } 1477 }
1468 } else { 1478 } else {
1469 return new Value(type, null); 1479 return new Value(type, null, node.span);
1470 } 1480 }
1471 } 1481 }
1472 1482
1473 dumpAllMembers() { 1483 dumpAllMembers() {
1474 for (var member in members) { 1484 for (var member in members) {
1475 world.warning('hard-multi $name on ${member.declaringType.name}', 1485 world.warning('hard-multi $name on ${member.declaringType.name}',
1476 member.span); 1486 member.span);
1477 } 1487 }
1478 } 1488 }
1479 1489
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1561 } 1571 }
1562 1572
1563 void forEach(void f(Member member)) { 1573 void forEach(void f(Member member)) {
1564 factories.forEach((_, Map constructors) { 1574 factories.forEach((_, Map constructors) {
1565 constructors.forEach((_, Member member) { 1575 constructors.forEach((_, Member member) {
1566 f(member); 1576 f(member);
1567 }); 1577 });
1568 }); 1578 });
1569 } 1579 }
1570 } 1580 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698