| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 | 92 |
| 93 void provideFieldSyntax() => world.internalError('can not be field', span); | 93 void provideFieldSyntax() => world.internalError('can not be field', span); |
| 94 void providePropertySyntax() => | 94 void providePropertySyntax() => |
| 95 world.internalError('can not be property', span); | 95 world.internalError('can not be property', span); |
| 96 | 96 |
| 97 Definition get definition() => null; | 97 Definition get definition() => null; |
| 98 | 98 |
| 99 List<Parameter> get parameters() => []; | 99 List<Parameter> get parameters() => []; |
| 100 | 100 |
| 101 // TODO(jimhug): Fix these names once get/set are truly pseudo-keywords. | 101 // TODO(jimhug): Fix these names once get/set are truly pseudo-keywords. |
| 102 abstract Value get_(MethodGenerator context, Node node, Value target); | 102 // TODO(jmesserly): isDynamic isn't a great name for this, something better? |
| 103 abstract Value get_(MethodGenerator context, Node node, Value target, |
| 104 [bool isDynamic]); |
| 103 | 105 |
| 104 abstract Value set_(MethodGenerator context, Node node, Value target, | 106 abstract Value set_(MethodGenerator context, Node node, Value target, |
| 105 Value value, [bool checked]); | 107 Value value, [bool isDynamic]); |
| 106 | 108 |
| 107 bool canInvoke(MethodGenerator context, Arguments args) { | 109 bool canInvoke(MethodGenerator context, Arguments args) { |
| 108 return canGet && new Value(returnType, null).canInvoke(context, '\$call', ar
gs); | 110 return canGet && new Value(returnType, null).canInvoke(context, '\$call', ar
gs); |
| 109 } | 111 } |
| 110 | 112 |
| 111 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, | 113 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, |
| 112 [bool checked=true]) { | 114 [bool isDynamic=false]) { |
| 113 var newTarget = get_(context, node, target); | 115 var newTarget = get_(context, node, target, isDynamic); |
| 114 return newTarget.invoke(context, '\$call', node, args, checked); | 116 return newTarget.invoke(context, '\$call', node, args, isDynamic); |
| 115 } | 117 } |
| 116 | 118 |
| 117 bool override(Member other) { | 119 bool override(Member other) { |
| 118 if (isStatic) { | 120 if (isStatic) { |
| 119 world.error('static members can not hide parent members', | 121 world.error('static members can not hide parent members', |
| 120 span, other.span); | 122 span, other.span); |
| 121 return false; | 123 return false; |
| 122 } else if (other.isStatic) { | 124 } else if (other.isStatic) { |
| 123 world.error('can not override static member', span, other.span); | 125 world.error('can not override static member', span, other.span); |
| 124 return false; | 126 return false; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 | 158 |
| 157 // If this really becomes first class, this should return typeof(Type) | 159 // If this really becomes first class, this should return typeof(Type) |
| 158 Type get returnType() => world.isVar; | 160 Type get returnType() => world.isVar; |
| 159 | 161 |
| 160 bool canInvoke(MethodGenerator context, Arguments args) => false; | 162 bool canInvoke(MethodGenerator context, Arguments args) => false; |
| 161 bool get canGet() => true; | 163 bool get canGet() => true; |
| 162 bool get canSet() => false; | 164 bool get canSet() => false; |
| 163 | 165 |
| 164 void resolve(Type inType) {} | 166 void resolve(Type inType) {} |
| 165 | 167 |
| 166 Value get_(MethodGenerator context, Node node, Value target) { | 168 Value get_(MethodGenerator context, Node node, Value target, |
| 167 // TODO(jmesserly): is just using the raw type name good enough to ensure we | 169 [bool isDynamic=false]) { |
| 168 // don't have type name collisions on the JS side? | 170 assert(target == null || target.type.isTop); |
| 169 // TODO(jmesserly): assert(target == null); | 171 // TODO(jmesserly): named args |
| 170 // TODO(jimhug): named args. | |
| 171 return new Value(type, type.jsname, false, false, true); | 172 return new Value(type, type.jsname, false, false, true); |
| 172 } | 173 } |
| 173 | 174 |
| 174 Value set_(MethodGenerator context, Node node, Value target, Value value, | 175 Value set_(MethodGenerator context, Node node, Value target, Value value, |
| 175 [bool checked=true]) { | 176 [bool isDynamic=false]) { |
| 176 world.error('can not set type', type.definition.span); | 177 world.error('can not set type', type.definition.span); |
| 177 } | 178 } |
| 178 | 179 |
| 179 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, | 180 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, |
| 180 [bool checked=true]) { | 181 [bool isDynamic=false]) { |
| 181 world.error('can not invoke type', type.definition.span); | 182 world.error('can not invoke type', type.definition.span); |
| 182 } | 183 } |
| 183 } | 184 } |
| 184 | 185 |
| 185 /** Represents a Dart field from source code. */ | 186 /** Represents a Dart field from source code. */ |
| 186 class FieldMember extends Member { | 187 class FieldMember extends Member { |
| 187 final VariableDefinition definition; | 188 final VariableDefinition definition; |
| 188 final Expression value; | 189 final Expression value; |
| 189 | 190 |
| 190 Type type; | 191 Type type; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 | 304 |
| 304 if (isStatic) { | 305 if (isStatic) { |
| 305 _computedValue = world.gen.globalForStaticField( | 306 _computedValue = world.gen.globalForStaticField( |
| 306 this, _computedValue, [_computedValue]); | 307 this, _computedValue, [_computedValue]); |
| 307 } | 308 } |
| 308 _computing = false; | 309 _computing = false; |
| 309 } | 310 } |
| 310 return _computedValue; | 311 return _computedValue; |
| 311 } | 312 } |
| 312 | 313 |
| 313 Value get_(MethodGenerator context, Node node, Value target) { | 314 Value get_(MethodGenerator context, Node node, Value target, |
| 314 declaringType.markUsed(); | 315 [bool isDynamic=false]) { |
| 316 if (!isDynamic) { |
| 317 declaringType.markUsed(); |
| 318 } |
| 315 if (isStatic) { | 319 if (isStatic) { |
| 316 // Make sure to compute the value of all static fields, even if we don't | 320 // Make sure to compute the value of all static fields, even if we don't |
| 317 // use this value immediately. | 321 // use this value immediately. |
| 318 var cv = computeValue(); | 322 var cv = computeValue(); |
| 319 if (isFinal) { | 323 if (isFinal) { |
| 320 return cv; | 324 return cv; |
| 321 } | 325 } |
| 322 if (declaringType.isTop) { | 326 if (declaringType.isTop) { |
| 323 return new Value(type, '$jsname'); | 327 return new Value(type, '$jsname'); |
| 324 } else { | 328 } else { |
| 325 return new Value(type, '${declaringType.jsname}.$jsname'); | 329 return new Value(type, '${declaringType.jsname}.$jsname'); |
| 326 } | 330 } |
| 327 } else if (target.isConst && isFinal) { | 331 } else if (target.isConst && isFinal) { |
| 328 // take advantage of consts and retrieve the value directly if possible | 332 // take advantage of consts and retrieve the value directly if possible |
| 329 var constTarget = target is GlobalValue ? target.exp : target; | 333 var constTarget = target is GlobalValue ? target.exp : target; |
| 330 if (constTarget is ConstObjectValue) { | 334 if (constTarget is ConstObjectValue) { |
| 331 return constTarget.fields[name]; | 335 return constTarget.fields[name]; |
| 332 } else if (constTarget.type == world.stringType && name == 'length') { | 336 } else if (constTarget.type == world.stringType && name == 'length') { |
| 333 return new Value(type, '${constTarget.actualValue.length}'); | 337 return new Value(type, '${constTarget.actualValue.length}'); |
| 334 } | 338 } |
| 335 } | 339 } |
| 336 return new Value(type, '${target.code}.$jsname'); | 340 return new Value(type, '${target.code}.$jsname'); |
| 337 } | 341 } |
| 338 | 342 |
| 339 Value set_(MethodGenerator context, Node node, Value target, Value value, | 343 Value set_(MethodGenerator context, Node node, Value target, Value value, |
| 340 [bool checked=true]) { | 344 [bool isDynamic=false]) { |
| 341 var lhs = get_(context, node, target); | 345 var lhs = get_(context, node, target, isDynamic); |
| 342 value = value.convertTo(context, type, node, checked); | 346 value = value.convertTo(context, type, node, isDynamic); |
| 343 return new Value(type, '${lhs.code} = ${value.code}'); | 347 return new Value(type, '${lhs.code} = ${value.code}'); |
| 344 } | 348 } |
| 345 } | 349 } |
| 346 | 350 |
| 347 class PropertyMember extends Member { | 351 class PropertyMember extends Member { |
| 348 MethodMember getter; | 352 MethodMember getter; |
| 349 MethodMember setter; | 353 MethodMember setter; |
| 350 | 354 |
| 351 bool _provideFieldSyntax = false; | 355 bool _provideFieldSyntax = false; |
| 352 | 356 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 382 // other.returnType.ensureAssignableFrom(returnType, null, true); | 386 // other.returnType.ensureAssignableFrom(returnType, null, true); |
| 383 if (other.isProperty) addFromParent(other); | 387 if (other.isProperty) addFromParent(other); |
| 384 return true; | 388 return true; |
| 385 } else { | 389 } else { |
| 386 world.error('property can only override field or property', | 390 world.error('property can only override field or property', |
| 387 span, other.span); | 391 span, other.span); |
| 388 return false; | 392 return false; |
| 389 } | 393 } |
| 390 } | 394 } |
| 391 | 395 |
| 392 Value get_(MethodGenerator context, Node node, Value target) { | 396 Value get_(MethodGenerator context, Node node, Value target, |
| 397 [bool isDynamic=false]) { |
| 393 if (getter == null) { | 398 if (getter == null) { |
| 394 // TODO(jmesserly): fix this! should call noSuchMethod. | 399 return target.invokeNoSuchMethod(context, 'get:$name', node); |
| 395 world.warning('no getter on ${declaringType.name}.$name', node.span); | |
| 396 return new Value(null, '${target.code}.$name()/*NoGetter*/'); | |
| 397 } | 400 } |
| 398 return getter.invoke(context, node, target, Arguments.EMPTY); | 401 return getter.invoke(context, node, target, Arguments.EMPTY); |
| 399 } | 402 } |
| 400 | 403 |
| 401 Value set_(MethodGenerator context, Node node, Value target, Value value, | 404 Value set_(MethodGenerator context, Node node, Value target, Value value, |
| 402 [bool checked=true]) { | 405 [bool isDynamic=false]) { |
| 403 return setter.invoke(context, node, target, new Arguments(null, [value]), | 406 return setter.invoke(context, node, target, new Arguments(null, [value]), |
| 404 checked); | 407 isDynamic); |
| 405 } | 408 } |
| 406 | 409 |
| 407 addFromParent(Member parentMember) { | 410 addFromParent(Member parentMember) { |
| 408 // TODO(jimhug): Egregious Hack! | 411 // TODO(jimhug): Egregious Hack! |
| 409 if (parentMember is ConcreteMember) { | 412 if (parentMember is ConcreteMember) { |
| 410 parentMember = parentMember.baseMember; | 413 parentMember = parentMember.baseMember; |
| 411 } | 414 } |
| 412 | 415 |
| 413 if (getter == null) getter = parentMember.getter; | 416 if (getter == null) getter = parentMember.getter; |
| 414 if (setter == null) setter = parentMember.setter; | 417 if (setter == null) setter = parentMember.setter; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 Definition set initDelegate(ctor) { baseMember.initDelegate = ctor; } | 484 Definition set initDelegate(ctor) { baseMember.initDelegate = ctor; } |
| 482 | 485 |
| 483 Type resolveType(TypeReference node, bool isRequired) { | 486 Type resolveType(TypeReference node, bool isRequired) { |
| 484 var type = baseMember.resolveType(node, isRequired); | 487 var type = baseMember.resolveType(node, isRequired); |
| 485 return type.resolveTypeParams(declaringType); | 488 return type.resolveTypeParams(declaringType); |
| 486 } | 489 } |
| 487 | 490 |
| 488 // TODO(jimhug): Add support for type params. | 491 // TODO(jimhug): Add support for type params. |
| 489 bool override(Member other) => baseMember.override(other); | 492 bool override(Member other) => baseMember.override(other); |
| 490 | 493 |
| 491 Value get_(MethodGenerator context, Node node, Value target) { | 494 Value get_(MethodGenerator context, Node node, Value target, |
| 492 Value ret = baseMember.get_(context, node, target); | 495 [bool isDynamic=false]) { |
| 496 Value ret = baseMember.get_(context, node, target, isDynamic); |
| 493 return new Value(returnType, ret.code); | 497 return new Value(returnType, ret.code); |
| 494 } | 498 } |
| 495 | 499 |
| 496 Value set_(MethodGenerator context, Node node, Value target, Value value, | 500 Value set_(MethodGenerator context, Node node, Value target, Value value, |
| 497 [bool checked=true]) { | 501 [bool isDynamic=false]) { |
| 498 // TODO(jimhug): Check arg types in context of concrete type. | 502 // TODO(jimhug): Check arg types in context of concrete type. |
| 499 Value ret = baseMember.set_(context, node, target, value, checked); | 503 Value ret = baseMember.set_(context, node, target, value, isDynamic); |
| 500 return new Value(returnType, ret.code); | 504 return new Value(returnType, ret.code); |
| 501 } | 505 } |
| 502 | 506 |
| 503 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, | 507 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, |
| 504 [bool checked=true]) { | 508 [bool isDynamic=false]) { |
| 505 // TODO(jimhug): Check arg types in context of concrete type. | 509 // TODO(jimhug): Check arg types in context of concrete type. |
| 506 Value ret = baseMember.invoke(context, node, target, args, checked); | 510 Value ret = baseMember.invoke(context, node, target, args, isDynamic); |
| 507 var code = ret.code; | 511 var code = ret.code; |
| 508 if (isConstructor) { | 512 if (isConstructor) { |
| 509 // TODO(jimhug): Egregious hack - won't live through the weekend. | 513 // TODO(jimhug): Egregious hack - won't live through the weekend. |
| 510 code = code.replaceFirst( | 514 code = code.replaceFirst( |
| 511 declaringType.genericType.jsname, declaringType.jsname); | 515 declaringType.genericType.jsname, declaringType.jsname); |
| 512 } | 516 } |
| 513 world.gen.genMethod(this); | 517 declaringType.genMethod(this); |
| 514 return new Value(returnType, code); | 518 return new Value(returnType, code); |
| 515 } | 519 } |
| 516 } | 520 } |
| 517 | 521 |
| 518 | 522 |
| 519 /** Represents a Dart method or top-level function. */ | 523 /** Represents a Dart method or top-level function. */ |
| 520 class MethodMember extends Member { | 524 class MethodMember extends Member { |
| 521 FunctionDefinition definition; | 525 FunctionDefinition definition; |
| 522 Type returnType; | 526 Type returnType; |
| 523 List<Parameter> parameters; | 527 List<Parameter> parameters; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 return type; | 647 return type; |
| 644 } | 648 } |
| 645 | 649 |
| 646 bool get prefersPropertySyntax() => true; | 650 bool get prefersPropertySyntax() => true; |
| 647 bool get requiresFieldSyntax() => false; | 651 bool get requiresFieldSyntax() => false; |
| 648 | 652 |
| 649 void provideFieldSyntax() => _provideFieldSyntax = true; | 653 void provideFieldSyntax() => _provideFieldSyntax = true; |
| 650 void providePropertySyntax() => _providePropertySyntax = true; | 654 void providePropertySyntax() => _providePropertySyntax = true; |
| 651 | 655 |
| 652 Value set_(MethodGenerator context, Node, Value target, Value value, | 656 Value set_(MethodGenerator context, Node, Value target, Value value, |
| 653 [bool checked=true]) { | 657 [bool isDynamic=false]) { |
| 654 world.error('can not set method', definition.span); | 658 world.error('can not set method', definition.span); |
| 655 } | 659 } |
| 656 | 660 |
| 657 Value get_(MethodGenerator context, Node node, Value target) { | 661 Value get_(MethodGenerator context, Node node, Value target, |
| 658 world.gen.genMethod(this); // TODO(jimhug): Would prefer to invoke! | 662 [bool isDynamic=false]) { |
| 663 // TODO(jimhug): Would prefer to invoke! |
| 664 declaringType.genMethod(this); |
| 659 _provideOptionalParamInfo = true; | 665 _provideOptionalParamInfo = true; |
| 660 if (isStatic) { | 666 if (isStatic) { |
| 661 var type = declaringType.isTop ? '' : '${declaringType.jsname}.'; | 667 var type = declaringType.isTop ? '' : '${declaringType.jsname}.'; |
| 662 return new Value(functionType, '$type$jsname'); | 668 return new Value(functionType, '$type$jsname'); |
| 663 } | 669 } |
| 664 _providePropertySyntax = true; | 670 _providePropertySyntax = true; |
| 665 return new Value(functionType, '${target.code}.get\$$jsname()'); | 671 return new Value(functionType, '${target.code}.get\$$jsname()'); |
| 666 } | 672 } |
| 667 | 673 |
| 668 bool namesInOrder(Arguments args) { | 674 bool namesInOrder(Arguments args) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 genParameterValues() { | 708 genParameterValues() { |
| 703 // Pure lazy? | 709 // Pure lazy? |
| 704 for (var p in parameters) p.genValue(this, generator); | 710 for (var p in parameters) p.genValue(this, generator); |
| 705 } | 711 } |
| 706 | 712 |
| 707 /** | 713 /** |
| 708 * Invokes this method on the given [target] with the given [args]. | 714 * Invokes this method on the given [target] with the given [args]. |
| 709 * [node] provides a [SourceSpan] for any error messages. | 715 * [node] provides a [SourceSpan] for any error messages. |
| 710 */ | 716 */ |
| 711 Value invoke(MethodGenerator context, Node node, Value target, | 717 Value invoke(MethodGenerator context, Node node, Value target, |
| 712 Arguments args, [bool checked=true]) { | 718 Arguments args, [bool isDynamic=false]) { |
| 713 // TODO(jimhug): Fix this hack for ensuring a method is resolved. | 719 // TODO(jimhug): Fix this hack for ensuring a method is resolved. |
| 714 if (parameters == null) { | 720 if (parameters == null) { |
| 715 world.info('surprised to need to resolve: ${declaringType.name}.$name'); | 721 world.info('surprised to need to resolve: ${declaringType.name}.$name'); |
| 716 this.resolve(declaringType); | 722 this.resolve(declaringType); |
| 717 } | 723 } |
| 718 | 724 |
| 719 if (!isGenerated) { | 725 declaringType.genMethod(this); |
| 720 world.gen.genMethod(this); | |
| 721 } | |
| 722 | 726 |
| 723 if (isStatic || isFactory) { | 727 if (isStatic || isFactory) { |
| 724 declaringType.markUsed(); | 728 declaringType.markUsed(); |
| 725 } | 729 } |
| 726 | 730 |
| 727 if (!namesInOrder(args)) { | 731 if (!namesInOrder(args)) { |
| 728 // Names aren't in order. For now, use a var call because it's an | 732 // Names aren't in order. For now, use a var call because it's an |
| 729 // easy way to get the right eval order for out of order arguments. | 733 // easy way to get the right eval order for out of order arguments. |
| 730 return context.findMembers(name).invokeOnVar(context, node, target, args); | 734 return context.findMembers(name).invokeOnVar(context, node, target, args); |
| 731 } | 735 } |
| 732 | 736 |
| 733 var argsCode = []; | 737 var argsCode = []; |
| 734 if (target != null && (isConstructor || target.isSuper)) { | 738 if (target != null && (isConstructor || target.isSuper)) { |
| 735 argsCode.add('this'); | 739 argsCode.add('this'); |
| 736 } | 740 } |
| 737 | 741 |
| 738 int bareCount = args.bareCount; | 742 int bareCount = args.bareCount; |
| 739 for (int i = 0; i < bareCount; i++) { | 743 for (int i = 0; i < bareCount; i++) { |
| 740 var arg = args.values[i]; | 744 var arg = args.values[i]; |
| 741 if (i >= parameters.length) { | 745 if (i >= parameters.length) { |
| 742 // TODO(jimhug): better error location | 746 // TODO(jimhug): better error location |
| 743 var msg = _argCountMsg(args.length, parameters.length); | 747 var msg = _argCountMsg(args.length, parameters.length); |
| 744 return _argError(context, node, target, args, msg); | 748 return _argError(context, node, target, args, msg); |
| 745 } | 749 } |
| 746 arg = arg.convertTo(context, parameters[i].type, node, checked); | 750 arg = arg.convertTo(context, parameters[i].type, node, isDynamic); |
| 747 if (isConst && arg.isConst) { | 751 if (isConst && arg.isConst) { |
| 748 argsCode.add(arg.canonicalCode); | 752 argsCode.add(arg.canonicalCode); |
| 749 } else { | 753 } else { |
| 750 argsCode.add(arg.code); | 754 argsCode.add(arg.code); |
| 751 } | 755 } |
| 752 } | 756 } |
| 753 | 757 |
| 754 if (bareCount < parameters.length) { | 758 if (bareCount < parameters.length) { |
| 755 genParameterValues(); | 759 genParameterValues(); |
| 756 | 760 |
| 757 int namedArgsUsed = 0; | 761 int namedArgsUsed = 0; |
| 758 for (int i = bareCount; i < parameters.length; i++) { | 762 for (int i = bareCount; i < parameters.length; i++) { |
| 759 var arg = args.getValue(parameters[i].name); | 763 var arg = args.getValue(parameters[i].name); |
| 760 if (arg == null) { | 764 if (arg == null) { |
| 761 arg = parameters[i].value; | 765 arg = parameters[i].value; |
| 762 } else { | 766 } else { |
| 763 arg = arg.convertTo(context, parameters[i].type, node, checked); | 767 arg = arg.convertTo(context, parameters[i].type, node, isDynamic); |
| 764 namedArgsUsed++; | 768 namedArgsUsed++; |
| 765 } | 769 } |
| 766 | 770 |
| 767 if (arg == null || !parameters[i].isOptional) { | 771 if (arg == null || !parameters[i].isOptional) { |
| 768 // TODO(jimhug): better error location | 772 // TODO(jimhug): better error location |
| 769 var msg = _argCountMsg(Math.min(i, args.length), i + 1, atLeast:true); | 773 var msg = _argCountMsg(Math.min(i, args.length), i + 1, atLeast:true); |
| 770 return _argError(context, node, target, args, msg); | 774 return _argError(context, node, target, args, msg); |
| 771 } else { | 775 } else { |
| 772 argsCode.add(isConst && arg.isConst | 776 argsCode.add(isConst && arg.isConst |
| 773 ? arg.canonicalCode : arg.code); | 777 ? arg.canonicalCode : arg.code); |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1227 if (_treatAsField) { | 1231 if (_treatAsField) { |
| 1228 member.provideFieldSyntax(); | 1232 member.provideFieldSyntax(); |
| 1229 } else { | 1233 } else { |
| 1230 member.providePropertySyntax(); | 1234 member.providePropertySyntax(); |
| 1231 } | 1235 } |
| 1232 } | 1236 } |
| 1233 } | 1237 } |
| 1234 return _treatAsField; | 1238 return _treatAsField; |
| 1235 } | 1239 } |
| 1236 | 1240 |
| 1237 Value get_(MethodGenerator context, Node node, Value target) { | 1241 Value get_(MethodGenerator context, Node node, Value target, |
| 1238 if (members.length == 1) return members[0].get_(context, node, target); | 1242 [bool isDynamic=false]) { |
| 1243 if (members.length == 1) { |
| 1244 return members[0].get_(context, node, target, isDynamic); |
| 1245 } |
| 1246 final targets = members.filter((m) => m.canGet); |
| 1247 if (targets.length == 1) { |
| 1248 return targets[0].get_(context, node, target, isDynamic); |
| 1249 } |
| 1239 | 1250 |
| 1240 Value returnValue = null; | 1251 Value returnValue = null; |
| 1241 for (var member in members) { | 1252 for (var member in targets) { |
| 1242 if (!member.canGet) continue; | 1253 final value = member.get_(context, node, target, isDynamic:true); |
| 1243 final value = member.get_(context, node, target); | |
| 1244 returnValue = _tryUnion(returnValue, value, node); | 1254 returnValue = _tryUnion(returnValue, value, node); |
| 1245 } | 1255 } |
| 1246 if (returnValue == null) { | 1256 if (returnValue == null) { |
| 1247 return _makeError(node, target, 'getter'); | 1257 return _makeError(node, target, 'getter'); |
| 1248 } | 1258 } |
| 1249 if (returnValue.code == null) { | 1259 if (returnValue.code == null) { |
| 1250 if (treatAsField) { | 1260 if (treatAsField) { |
| 1251 return new Value(returnValue.type, '${target.code}.$jsname'); | 1261 return new Value(returnValue.type, '${target.code}.$jsname'); |
| 1252 } else { | 1262 } else { |
| 1253 return new Value(returnValue.type, '${target.code}.get\$$jsname()'); | 1263 return new Value(returnValue.type, '${target.code}.get\$$jsname()'); |
| 1254 } | 1264 } |
| 1255 } | 1265 } |
| 1256 return returnValue; | 1266 return returnValue; |
| 1257 } | 1267 } |
| 1258 | 1268 |
| 1259 Value set_(MethodGenerator context, Node node, Value target, Value value, | 1269 Value set_(MethodGenerator context, Node node, Value target, Value value, |
| 1260 [bool checked=true]) { | 1270 [bool isDynamic=false]) { |
| 1261 if (members.length == 1) { | 1271 if (members.length == 1) { |
| 1262 return members[0].set_(context, node, target, value, checked); | 1272 return members[0].set_(context, node, target, value, isDynamic); |
| 1263 } | 1273 } |
| 1264 final targets = members.filter((m) => m.canSet); | 1274 final targets = members.filter((m) => m.canSet); |
| 1265 if (targets.length == 1) { | 1275 if (targets.length == 1) { |
| 1266 return targets[0].set_(context, node, target, value, checked); | 1276 return targets[0].set_(context, node, target, value, isDynamic); |
| 1267 } | 1277 } |
| 1268 | 1278 |
| 1269 Value returnValue = null; | 1279 Value returnValue = null; |
| 1270 for (var member in targets) { | 1280 for (var member in targets) { |
| 1271 final setValue = member.set_(context, node, target, value, checked:false); | 1281 final res = member.set_(context, node, target, value, isDynamic:true); |
| 1272 returnValue = _tryUnion(returnValue, setValue, node); | 1282 returnValue = _tryUnion(returnValue, res, node); |
| 1273 } | 1283 } |
| 1274 if (returnValue == null) { | 1284 if (returnValue == null) { |
| 1275 return _makeError(node, target, 'setter'); | 1285 return _makeError(node, target, 'setter'); |
| 1276 } | 1286 } |
| 1277 if (returnValue.code == null) { | 1287 if (returnValue.code == null) { |
| 1278 if (treatAsField) { | 1288 if (treatAsField) { |
| 1279 return new Value(returnValue.type, | 1289 return new Value(returnValue.type, |
| 1280 '${target.code}.$jsname = ${value.code}'); | 1290 '${target.code}.$jsname = ${value.code}'); |
| 1281 } else { | 1291 } else { |
| 1282 return new Value(returnValue.type, | 1292 return new Value(returnValue.type, |
| 1283 '${target.code}.set\$$jsname(${value.code})'); | 1293 '${target.code}.set\$$jsname(${value.code})'); |
| 1284 } | 1294 } |
| 1285 } | 1295 } |
| 1286 return returnValue; | 1296 return returnValue; |
| 1287 } | 1297 } |
| 1288 | 1298 |
| 1289 Value invoke(MethodGenerator context, Node node, Value target, | 1299 Value invoke(MethodGenerator context, Node node, Value target, |
| 1290 Arguments args, [bool checked=true]) { | 1300 Arguments args, [bool isDynamic=false]) { |
| 1291 if (members.length == 1) { | 1301 if (members.length == 1) { |
| 1292 return members[0].invoke(context, node, target, args, checked); | 1302 return members[0].invoke(context, node, target, args, isDynamic); |
| 1293 } | 1303 } |
| 1294 final targets = members.filter((m) => m.canInvoke(context, args)); | 1304 final targets = members.filter((m) => m.canInvoke(context, args)); |
| 1295 if (targets.length == 1) { | 1305 if (targets.length == 1) { |
| 1296 return targets[0].invoke(context, node, target, args, checked); | 1306 return targets[0].invoke(context, node, target, args, isDynamic); |
| 1297 } | 1307 } |
| 1298 | 1308 |
| 1299 Value returnValue = null; | 1309 Value returnValue = null; |
| 1300 for (var member in targets) { | 1310 for (var member in targets) { |
| 1301 final value = member.invoke(context, node, target, args, checked:false); | 1311 final res = member.invoke(context, node, target, args, isDynamic:true); |
| 1302 returnValue = _tryUnion(returnValue, value, node); | 1312 returnValue = _tryUnion(returnValue, res, node); |
| 1303 } | 1313 } |
| 1304 | 1314 |
| 1305 if (returnValue == null) { | 1315 if (returnValue == null) { |
| 1306 return _makeError(node, target, 'method'); | 1316 return _makeError(node, target, 'method'); |
| 1307 } | 1317 } |
| 1308 | 1318 |
| 1309 // If we fail to unify the resulting code, implement as a var call. | 1319 // If we fail to unify the resulting code, implement as a var call. |
| 1310 if (returnValue.code == null) { | 1320 if (returnValue.code == null) { |
| 1311 if (name.startsWith('\$')) { | 1321 if (name.startsWith('\$')) { |
| 1312 return target.invokeSpecial(name, args, returnValue.type); | 1322 return target.invokeSpecial(name, args, returnValue.type); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1442 } | 1452 } |
| 1443 | 1453 |
| 1444 void forEach(void f(MethodMember member)) { | 1454 void forEach(void f(MethodMember member)) { |
| 1445 factories.forEach((_, Map constructors) { | 1455 factories.forEach((_, Map constructors) { |
| 1446 constructors.forEach((_, Member member) { | 1456 constructors.forEach((_, Member member) { |
| 1447 f(member); | 1457 f(member); |
| 1448 }); | 1458 }); |
| 1449 }); | 1459 }); |
| 1450 } | 1460 } |
| 1451 } | 1461 } |
| OLD | NEW |