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

Side by Side Diff: frog/value.dart

Issue 8509035: TBR (red build bot). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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
« no previous file with comments | « frog/utils.dart ('k') | frog/world.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 /** 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 10 matching lines...) Expand all
21 /** If we reference this value multiple times, do we need a temp? */ 21 /** If we reference this value multiple times, do we need a temp? */
22 bool needsTemp; 22 bool needsTemp;
23 23
24 Value(this.type, this.code, 24 Value(this.type, this.code,
25 // TODO(sigmund): reorder, so that needsTemp comes first. 25 // TODO(sigmund): reorder, so that needsTemp comes first.
26 [this.isSuper = false, this.needsTemp = true, this.isType = false]) { 26 [this.isSuper = false, this.needsTemp = true, this.isType = false]) {
27 if (type == null) type = world.varType; 27 if (type == null) type = world.varType;
28 } 28 }
29 29
30 /** Is this value a constant expression? */ 30 /** Is this value a constant expression? */
31 bool get isConst() => false; 31 bool get isConst () => false;
32 32
33 // TODO(jimhug): These three methods are still a little too similar for me. 33 // TODO(jimhug): These three methods are still a little too similar for me.
34 get_(MethodGenerator context, String name, Node node) { 34 get_(MethodGenerator context, String name, Node node) {
35 var member = _resolveMember(context, name, node); 35 var member = _resolveMember(context, name, node);
36 if (member != null) { 36 if (member != null) {
37 member = member.get_(context, node, this); 37 member = member.get_(context, node, this);
38 } 38 }
39 // member.get_ returns null if no signatures match the given node. 39 // member.get_ returns null if no signatures match the given node.
40 if (member != null) { 40 if (member != null) {
41 return member; 41 return member;
42 } else { 42 } else {
43 return invokeNoSuchMethod(context, 'get:$name', node); 43 return invokeNoSuchMethod(context, 'get:$name', node);
44 } 44 }
45 } 45 }
46 46
47 set_(MethodGenerator context, String name, Node node, Value value, 47 set_(MethodGenerator context, String name, Node node, Value value,
48 [bool isDynamic=false]) { 48 [bool isDynamic=false]) {
49 var member = _resolveMember(context, name, node, isDynamic); 49 var member = _resolveMember(context, name, node);
50 if (member != null) { 50 if (member != null) {
51 member = member.set_(context, node, this, value, isDynamic); 51 member = member.set_(context, node, this, value, isDynamic);
52 } 52 }
53 // member.set_ returns null if no signatures match the given node. 53 // member.set_ returns null if no signatures match the given node.
54 if (member != null) { 54 if (member != null) {
55 return member; 55 return member;
56 } else { 56 } else {
57 return invokeNoSuchMethod(context, 'set:$name', node, 57 return invokeNoSuchMethod(context, 'set:$name', node,
58 new Arguments(null, [value])); 58 new Arguments(null, [value]));
59 } 59 }
(...skipping 21 matching lines...) Expand all
81 if (name == '\$call') { 81 if (name == '\$call') {
82 if (isType) { 82 if (isType) {
83 world.error('must use "new" or "const" to construct a new instance', 83 world.error('must use "new" or "const" to construct a new instance',
84 node.span); 84 node.span);
85 } 85 }
86 if (type.needsVarCall(args)) { 86 if (type.needsVarCall(args)) {
87 return _varCall(context, args); 87 return _varCall(context, args);
88 } 88 }
89 } 89 }
90 90
91 var member = _resolveMember(context, name, node, isDynamic); 91 var member = _resolveMember(context, name, node);
92 if (member == null) { 92 if (member == null) {
93 return invokeNoSuchMethod(context, name, node, args); 93 return invokeNoSuchMethod(context, name, node, args);
94 } else { 94 } else {
95 return member.invoke(context, node, this, args, isDynamic); 95 return member.invoke(context, node, this, args, isDynamic);
96 } 96 }
97 } 97 }
98 98
99 bool canInvoke(MethodGenerator context, String name, Arguments args) { 99 bool canInvoke(MethodGenerator context, String name, Arguments args) {
100 // TODO(jimhug): The != method is weird - understand it better. 100 // TODO(jimhug): The != method is weird - understand it better.
101 if (type.isVar && name == '\$ne') { 101 if (type.isVar && name == '\$ne') {
102 return true; 102 return true;
103 } 103 }
104 104
105 if (type.isVarOrFunction && name == '\$call') { 105 if (type.isVarOrFunction && name == '\$call') {
106 return true; 106 return true;
107 } 107 }
108 108
109 var member = _resolveMember(context, name, null, isDynamic:true); 109 var member = _tryResolveMember(context, name);
110 return member != null && member.canInvoke(context, args); 110 return member != null && member.canInvoke(context, args);
111 } 111 }
112 112
113 /** 113 // TODO(jimhug): Better type here - currently is union(Member, MemberSet)
114 * True if this class (or some related class that is not Object) overrides 114 _tryResolveMember(MethodGenerator context, String name) {
115 * noSuchMethod. If it does we suppress warnings about unknown members. 115 var member = null;
116 */ 116 if (!type.isVar) {
117 // TODO(jmesserly): should we be doing this? 117 if (isSuper) {
118 bool _hasOverriddenNoSuchMethod() { 118 return type.getMember(name);
119 if (isSuper) { 119 } else {
120 var m = type.getMember('noSuchMethod'); 120 member = type.resolveMember(name);
121 return m != null && !m.declaringType.isObject; 121 }
122 }
123
124 if (member == null) {
125 // TODO(jmesserly): shouldn't look in world except for "var"
126 member = context.findMembers(name);
127 }
128 return member;
129 }
130
131 _resolveMember(MethodGenerator context, String name, Node node) {
132 var member = _tryResolveMember(context, name);
133 if (member != null) {
134 if (isType && !member.isStatic) {
135 world.error('can not refer to instance member as static', node.span);
136 }
137 return member;
122 } else { 138 } else {
123 return type.resolveMember('noSuchMethod').members.length > 1; 139 // TODO(jmesserly): we suppress warnings if someone has overridden
140 // noSuchMethod, and we know it will call their version. Is that right?
141 if (_tryResolveMember(context, 'noSuchMethod').members.length > 1) {
142 return null;
143 }
144
145 var typeName = type.name == null ? type.library.name : type.name;
146 var message = 'can not resolve "$name" on "${typeName}"';
147 if (isType) {
148 world.error(message, node.span);
149 } else {
150 world.warning(message, node.span);
151 }
152 // TODO(jmesserly): isn't this condition always true if we got here?
153 if (context.findMembers(name) == null) {
154 world.warning('$name is not defined anywhere in the world.', node.span);
155 }
156 return null;
124 } 157 }
125 } 158 }
126 159
127 // TODO(jimhug): Better type here - currently is union(Member, MemberSet)
128 _resolveMember(MethodGenerator context, String name, Node node,
129 [bool isDynamic=false]) {
130
131 // TODO(jmesserly): until reified generic lists are fixed, treat
132 // ParameterType as "var".
133 var member;
134 if (!type.isVar && type is! ParameterType) {
135 if (isSuper) {
136 member = type.getMember(name);
137 } else {
138 member = type.resolveMember(name);
139 }
140
141 if (member != null && isType && !member.isStatic) {
142 if (!isDynamic) {
143 world.error('can not refer to instance member as static', node.span);
144 }
145 return null;
146 }
147
148 if (member == null && !isDynamic && !_hasOverriddenNoSuchMethod()) {
149 var typeName = type.name == null ? type.library.name : type.name;
150 var message = 'can not resolve "$name" on "${typeName}"';
151 if (isType) {
152 world.error(message, node.span);
153 } else {
154 world.warning(message, node.span);
155 }
156 }
157 }
158
159 // Fall back to a dynamic operation for instance members
160 if (member == null && !isSuper && !isType) {
161 member = context.findMembers(name);
162 if (member == null && !isDynamic) {
163 world.warning('$name is not defined anywhere in the world.',
164 node.span);
165 }
166 }
167
168 return member;
169 }
170
171 checkFirstClass(SourceSpan span) { 160 checkFirstClass(SourceSpan span) {
172 if (isType) { 161 if (isType) {
173 world.error('Types are not first class', span); 162 world.error('Types are not first class', span);
174 } 163 }
175 } 164 }
176 165
177 /** Generate a call to an unknown function type. */ 166 /** Generate a call to an unknown function type. */
178 Value _varCall(MethodGenerator context, Arguments args) { 167 Value _varCall(MethodGenerator context, Arguments args) {
179 // TODO(jmesserly): calls to unknown functions will bypass type checks, 168 // TODO(jmesserly): calls to unknown functions will bypass type checks,
180 // which normally happen on the caller side, or in the generated stub for 169 // which normally happen on the caller side, or in the generated stub for
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 /*if (args != null && args.hasNames) { 417 /*if (args != null && args.hasNames) {
429 var names = []; 418 var names = [];
430 for (int i = args.bareCount; i < args.length; i++) { 419 for (int i = args.bareCount; i < args.length; i++) {
431 names.add('"${args.getName(i)}", ${args.values[i].code}'); 420 names.add('"${args.getName(i)}", ${args.values[i].code}');
432 } 421 }
433 noSuchArgs.add(new Value(world.gen.useMapFactory(), 422 noSuchArgs.add(new Value(world.gen.useMapFactory(),
434 '\$map(${Strings.join(names, ", ")})')); 423 '\$map(${Strings.join(names, ", ")})'));
435 }*/ 424 }*/
436 425
437 // Finally, invoke noSuchMethod 426 // Finally, invoke noSuchMethod
438 return _resolveMember(context, 'noSuchMethod', node).invoke( 427 return _tryResolveMember(context, 'noSuchMethod').invoke(
439 context, node, this, new Arguments(null, noSuchArgs)); 428 context, node, this, new Arguments(null, noSuchArgs));
440 } 429 }
441 430
442 Value invokeSpecial(String name, Arguments args, Type returnType) { 431 Value invokeSpecial(String name, Arguments args, Type returnType) {
443 assert(name.startsWith('\$')); 432 assert(name.startsWith('\$'));
444 assert(!args.hasNames); 433 assert(!args.hasNames);
445 // TODO(jimhug): We need to do this a little bit more like get and set on 434 // TODO(jimhug): We need to do this a little bit more like get and set on
446 // properties. We should check the set of members for something 435 // properties. We should check the set of members for something
447 // like "requiresNativeIndexer" and "requiresDartIndexer" to 436 // like "requiresNativeIndexer" and "requiresDartIndexer" to
448 // decide on a strategy. 437 // decide on a strategy.
449 438
450 var argsString = args.getCode(); 439 var argsString = args.getCode();
451 // Most operator calls need to be emitted as function calls, so we don't 440 // Most operator calls need to be emitted as function calls, so we don't
452 // box numbers accidentally. Indexing is the exception. 441 // box numbers accidentally. Indexing is the exception.
453 if (name == '\$index' || name == '\$setindex') { 442 if (name == '\$index' || name == '\$setindex') {
454 return new Value(returnType, '$code.$name($argsString)'); 443 return new Value(returnType, '$code.$name($argsString)');
455 } else { 444 } else {
456 if (argsString.length > 0) argsString = ', $argsString'; 445 if (argsString.length > 0) argsString = ', $argsString';
457 world.gen.corejs.useOperator(name); 446 world.gen.corejs.useOperator(name);
458 return new Value(returnType, '$name($code$argsString)'); 447 return new Value(returnType, '$name($code$argsString)');
459 } 448 }
460 } 449 }
461 } 450 }
462 451
463 // TODO(jmesserly): the subtypes of Value require a lot of type checks and
464 // downcasts to use; can we make that cleaner? (search for ".dynamic")
465
466 /** A value that can has been evaluated statically. */ 452 /** A value that can has been evaluated statically. */
467 class EvaluatedValue extends Value { 453 class EvaluatedValue extends Value {
468 454
469 var actualValue; 455 var actualValue;
470 456
471 bool get isConst() => true; 457 bool get isConst() => true;
472 458
473 /** 459 /**
474 * A canonicalized form of the code. Two const expressions that result in the 460 * A canonicalized form of the code. Two const expressions that result in the
475 * same instance should have the same [canonicalCode]. 461 * same instance should have the same [canonicalCode].
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 return 1; 614 return 1;
629 } else if (name != null && other.name == null) { 615 } else if (name != null && other.name == null) {
630 return -1; 616 return -1;
631 } else if (name != null) { 617 } else if (name != null) {
632 return name.compareTo(other.name); 618 return name.compareTo(other.name);
633 } else { 619 } else {
634 return field.name.compareTo(other.field.name); 620 return field.name.compareTo(other.field.name);
635 } 621 }
636 } 622 }
637 } 623 }
OLDNEW
« no previous file with comments | « frog/utils.dart ('k') | frog/world.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698