| 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 /** | 5 /** |
| 6 * Represents a meta-value for code generation. | 6 * Represents a meta-value for code generation. |
| 7 */ | 7 */ |
| 8 class Value { | 8 class Value { |
| 9 /** The [Type] of the [Value]. */ | 9 /** The [Type] of the [Value]. */ |
| 10 Type type; | 10 Type type; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 new Arguments(null, [value])); | 72 new Arguments(null, [value])); |
| 73 } | 73 } |
| 74 } | 74 } |
| 75 | 75 |
| 76 | 76 |
| 77 Value invoke(MethodGenerator context, String name, Node node, Arguments args, | 77 Value invoke(MethodGenerator context, String name, Node node, Arguments args, |
| 78 [bool isDynamic=false]) { | 78 [bool isDynamic=false]) { |
| 79 // TODO(jmesserly): try to get rid of this code path. We're generating a | 79 // TODO(jmesserly): try to get rid of this code path. We're generating a |
| 80 // synthetic != on Object (see DefinedType._createNotEqualMember) already. | 80 // synthetic != on Object (see DefinedType._createNotEqualMember) already. |
| 81 // So it should be pretty easy to make this go away. | 81 // So it should be pretty easy to make this go away. |
| 82 if (_typeIsVarOrParameterType && name == '\$ne') { | 82 if (_typeIsVarOrParameterType && name == ':ne') { |
| 83 if (args.values.length != 1) { | 83 if (args.values.length != 1) { |
| 84 world.warning('wrong number of arguments for !=', node.span); | 84 world.warning('wrong number of arguments for !=', node.span); |
| 85 } | 85 } |
| 86 // Ensure the == operator is generated, and get its type | 86 // Ensure the == operator is generated, and get its type |
| 87 var eq = invoke(context, '\$eq', node, args, isDynamic); | 87 var eq = invoke(context, ':eq', node, args, isDynamic); |
| 88 world.gen.corejs.useOperator('\$ne'); | 88 world.gen.corejs.useOperator(':ne'); |
| 89 return new Value(eq.type, '\$ne($code, ${args.values[0].code})', | 89 return new Value(eq.type, '\$ne($code, ${args.values[0].code})', |
| 90 node.span); | 90 node.span); |
| 91 } | 91 } |
| 92 | 92 |
| 93 // TODO(jmesserly): it'd be nice to remove these special cases | 93 // TODO(jmesserly): it'd be nice to remove these special cases |
| 94 // We could create a $call (and $ne) in world members, and have | 94 // We could create a :call (and :ne) in world members, and have |
| 95 // those guys handle the canInvoke/Invoke logic. | 95 // those guys handle the canInvoke/Invoke logic. |
| 96 | 96 |
| 97 // Note: this check is a little different than the one in canInvoke, because | 97 // Note: this check is a little different than the one in canInvoke, because |
| 98 // sometimes we need to call dynamically even if we found the $call method | 98 // sometimes we need to call dynamically even if we found the :call method |
| 99 // statically. | 99 // statically. |
| 100 | 100 |
| 101 if (name == '\$call') { | 101 if (name == ':call') { |
| 102 if (isType) { | 102 if (isType) { |
| 103 world.error('must use "new" or "const" to construct a new instance', | 103 world.error('must use "new" or "const" to construct a new instance', |
| 104 node.span); | 104 node.span); |
| 105 } | 105 } |
| 106 if (type.needsVarCall(args)) { | 106 if (type.needsVarCall(args)) { |
| 107 return _varCall(context, args); | 107 return _varCall(context, args); |
| 108 } | 108 } |
| 109 } | 109 } |
| 110 | 110 |
| 111 var member = _resolveMember(context, name, node, isDynamic); | 111 var member = _resolveMember(context, name, node, isDynamic); |
| 112 if (member == null) { | 112 if (member == null) { |
| 113 return invokeNoSuchMethod(context, name, node, args); | 113 return invokeNoSuchMethod(context, name, node, args); |
| 114 } else { | 114 } else { |
| 115 return member.invoke(context, node, this, args, isDynamic); | 115 return member.invoke(context, node, this, args, isDynamic); |
| 116 } | 116 } |
| 117 } | 117 } |
| 118 | 118 |
| 119 bool canInvoke(MethodGenerator context, String name, Arguments args) { | 119 bool canInvoke(MethodGenerator context, String name, Arguments args) { |
| 120 // TODO(jimhug): The != method is weird - understand it better. | 120 // TODO(jimhug): The != method is weird - understand it better. |
| 121 if (_typeIsVarOrParameterType && name == '\$ne') { | 121 if (_typeIsVarOrParameterType && name == ':ne') { |
| 122 return true; | 122 return true; |
| 123 } | 123 } |
| 124 | 124 |
| 125 if (type.isVarOrFunction && name == '\$call') { | 125 if (type.isVarOrFunction && name == ':call') { |
| 126 return true; | 126 return true; |
| 127 } | 127 } |
| 128 | 128 |
| 129 var member = _resolveMember(context, name, null, isDynamic:true); | 129 var member = _resolveMember(context, name, null, isDynamic:true); |
| 130 return member != null && member.canInvoke(context, args); | 130 return member != null && member.canInvoke(context, args); |
| 131 } | 131 } |
| 132 | 132 |
| 133 /** | 133 /** |
| 134 * True if this class (or some related class that is not Object) overrides | 134 * True if this class (or some related class that is not Object) overrides |
| 135 * noSuchMethod. If it does we suppress warnings about unknown members. | 135 * noSuchMethod. If it does we suppress warnings about unknown members. |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 names.add('"${args.getName(i)}", ${args.values[i].code}'); | 507 names.add('"${args.getName(i)}", ${args.values[i].code}'); |
| 508 } | 508 } |
| 509 noSuchArgs.add(new Value(world.gen.useMapFactory(), | 509 noSuchArgs.add(new Value(world.gen.useMapFactory(), |
| 510 '\$map(${Strings.join(names, ", ")})')); | 510 '\$map(${Strings.join(names, ", ")})')); |
| 511 }*/ | 511 }*/ |
| 512 | 512 |
| 513 // Finally, invoke noSuchMethod | 513 // Finally, invoke noSuchMethod |
| 514 return _resolveMember(context, 'noSuchMethod', node).invoke( | 514 return _resolveMember(context, 'noSuchMethod', node).invoke( |
| 515 context, node, this, new Arguments(null, noSuchArgs)); | 515 context, node, this, new Arguments(null, noSuchArgs)); |
| 516 } | 516 } |
| 517 | |
| 518 Value invokeSpecial(String name, Arguments args, Type returnType) { | |
| 519 assert(name.startsWith('\$')); | |
| 520 assert(!args.hasNames); | |
| 521 // TODO(jimhug): We need to do this a little bit more like get and set on | |
| 522 // properties. We should check the set of members for something | |
| 523 // like "requiresNativeIndexer" and "requiresDartIndexer" to | |
| 524 // decide on a strategy. | |
| 525 | |
| 526 var argsString = args.getCode(); | |
| 527 // Most operator calls need to be emitted as function calls, so we don't | |
| 528 // box numbers accidentally. Indexing is the exception. | |
| 529 if (name == '\$index' || name == '\$setindex') { | |
| 530 return new Value(returnType, '$code.$name($argsString)', span); | |
| 531 } else { | |
| 532 if (argsString.length > 0) argsString = ', $argsString'; | |
| 533 world.gen.corejs.useOperator(name); | |
| 534 return new Value(returnType, '$name($code$argsString)', span); | |
| 535 } | |
| 536 } | |
| 537 } | 517 } |
| 538 | 518 |
| 539 // TODO(jmesserly): the subtypes of Value require a lot of type checks and | 519 // TODO(jmesserly): the subtypes of Value require a lot of type checks and |
| 540 // downcasts to use; can we make that cleaner? (search for ".dynamic") | 520 // downcasts to use; can we make that cleaner? (search for ".dynamic") |
| 541 | 521 |
| 542 /** A value that can has been evaluated statically. */ | 522 /** A value that can has been evaluated statically. */ |
| 543 class EvaluatedValue extends Value { | 523 class EvaluatedValue extends Value { |
| 544 | 524 |
| 545 var actualValue; | 525 var actualValue; |
| 546 | 526 |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 // Then look for members in my library. | 729 // Then look for members in my library. |
| 750 member = home.library.lookup(name, span); | 730 member = home.library.lookup(name, span); |
| 751 if (member != null) { | 731 if (member != null) { |
| 752 return member; | 732 return member; |
| 753 } | 733 } |
| 754 | 734 |
| 755 _ensureCode(); | 735 _ensureCode(); |
| 756 return null; | 736 return null; |
| 757 } | 737 } |
| 758 } | 738 } |
| OLD | NEW |