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

Side by Side Diff: frog/value.dart

Issue 8538019: incremental progress on Value (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 /** 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;
11 11
12 /** The code to generate this value. */ 12 /** The javascript code to generate this value. */
13 String code; 13 String code;
14 14
15 /** The source location that created this value for error messages. */ 15 /** The source location that created this value for error messages. */
16 SourceSpan span; 16 SourceSpan span;
17 17
18 /** Is this a reference to super? */ 18 /** Is this a reference to super? */
19 bool isSuper; 19 bool isSuper = false;
20 20
21 /** Is this a pretend first-class type? */ 21 /** Is this a pretend first-class type? */
22 bool isType; 22 bool isType = false;
23 23
24 /** If we reference this value multiple times, do we need a temp? */ 24 /** If we reference this value multiple times, do we need a temp? */
25 bool needsTemp; 25 bool needsTemp;
26 26
27 // TODO(jmesserly): until reified generics are fixed, treat ParameterType as 27 // TODO(jmesserly): until reified generics are fixed, treat ParameterType as
28 // "var". 28 // "var".
29 bool get _typeIsVarOrParameterType() => type.isVar || type is ParameterType; 29 bool get _typeIsVarOrParameterType() => type.isVar || type is ParameterType;
30 30
31 Value(this.type, this.code, this.span, 31 Value(this.type, this.code, this.span, [this.needsTemp = true]) {
32 // TODO(sigmund): reorder, so that needsTemp comes first. 32 if (type == null) world.internalError('type passed as null', span);
33 [this.isSuper = false, this.needsTemp = true, this.isType = false]) {
34 if (type == null) type = world.varType;
35 } 33 }
36 34
37 /** Is this value a constant expression? */ 35 /** Is this value a constant expression? */
38 bool get isConst() => false; 36 bool get isConst() => false;
39 37
40 /** 38 /**
41 * A canonicalized form of the code. Two const expressions that result in the 39 * A canonicalized form of the code. Two const expressions that result in the
42 * same instance should have the same [canonicalCode]. 40 * same instance should have the same [canonicalCode].
43 */ 41 */
44 String get canonicalCode() => null; 42 String get canonicalCode() => null;
(...skipping 23 matching lines...) Expand all
68 66
69 67
70 Value invoke(MethodGenerator context, String name, Node node, Arguments args, 68 Value invoke(MethodGenerator context, String name, Node node, Arguments args,
71 [bool isDynamic=false]) { 69 [bool isDynamic=false]) {
72 // TODO(jimhug): The != method is weird - understand it better. 70 // TODO(jimhug): The != method is weird - understand it better.
73 if (_typeIsVarOrParameterType && name == '\$ne') { 71 if (_typeIsVarOrParameterType && name == '\$ne') {
74 if (args.values.length != 1) { 72 if (args.values.length != 1) {
75 world.warning('wrong number of arguments for !=', node.span); 73 world.warning('wrong number of arguments for !=', node.span);
76 } 74 }
77 world.gen.corejs.useOperator('\$ne'); 75 world.gen.corejs.useOperator('\$ne');
78 return new Value(null, '\$ne($code, ${args.values[0].code})', node.span); 76 return new Value(world.varType, '\$ne($code, ${args.values[0].code})',
77 node.span);
79 } 78 }
80 79
81 // TODO(jmesserly): it'd be nice to remove these special cases 80 // TODO(jmesserly): it'd be nice to remove these special cases
82 // We could create a $call (and $ne) in world members, and have 81 // We could create a $call (and $ne) in world members, and have
83 // those guys handle the canInvoke/Invoke logic. 82 // those guys handle the canInvoke/Invoke logic.
84 83
85 // Note: this check is a little different than the one in canInvoke, because 84 // Note: this check is a little different than the one in canInvoke, because
86 // sometimes we need to call dynamically even if we found the $call method 85 // sometimes we need to call dynamically even if we found the $call method
87 // statically. 86 // statically.
88 87
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 world.error('Types are not first class', span); 182 world.error('Types are not first class', span);
184 } 183 }
185 } 184 }
186 185
187 /** Generate a call to an unknown function type. */ 186 /** Generate a call to an unknown function type. */
188 Value _varCall(MethodGenerator context, Arguments args) { 187 Value _varCall(MethodGenerator context, Arguments args) {
189 // TODO(jmesserly): calls to unknown functions will bypass type checks, 188 // TODO(jmesserly): calls to unknown functions will bypass type checks,
190 // which normally happen on the caller side, or in the generated stub for 189 // which normally happen on the caller side, or in the generated stub for
191 // dynamic method calls. What should we do? 190 // dynamic method calls. What should we do?
192 var stub = world.functionType.getCallStub(args); 191 var stub = world.functionType.getCallStub(args);
193 return new Value(null, '$code.${stub.name}(${args.getCode()})', span); 192 return new Value(world.varType, '$code.${stub.name}(${args.getCode()})',
193 span);
194 } 194 }
195 195
196 /** True if convertTo would generate a conversion. */ 196 /** True if convertTo would generate a conversion. */
197 // TODO(jmesserly): I don't like how this is coupled to convertTo. 197 // TODO(jmesserly): I don't like how this is coupled to convertTo.
198 bool needsConversion(Type toType) { 198 bool needsConversion(Type toType) {
199 var callMethod = toType.getCallMethod(); 199 var callMethod = toType.getCallMethod();
200 if (callMethod != null) { 200 if (callMethod != null) {
201 int arity = callMethod.parameters.length; 201 int arity = callMethod.parameters.length;
202 var myCall = type.getCallMethod(); 202 var myCall = type.getCallMethod();
203 if (myCall == null || myCall.parameters.length != arity) { 203 if (myCall == null || myCall.parameters.length != arity) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 return _typeAssert(context, toType, node); 276 return _typeAssert(context, toType, node);
277 } else { 277 } else {
278 return this; 278 return this;
279 } 279 }
280 } 280 }
281 281
282 // TODO(jmesserly): this generates an unnecessary check for the 90% 282 // TODO(jmesserly): this generates an unnecessary check for the 90%
283 // case where the thing passed in was a non-overloaded == or != expression 283 // case where the thing passed in was a non-overloaded == or != expression
284 // We'll want to eliminate these, probably by tracking non-null bools in the 284 // We'll want to eliminate these, probably by tracking non-null bools in the
285 // type system. 285 // type system.
286 // This matches the interesting Boolean Conversion section of the spec.
286 Value convertToNonNullBool(MethodGenerator context, Node node) { 287 Value convertToNonNullBool(MethodGenerator context, Node node) {
287 if (!type.isAssignable(world.boolType)) { 288 if (!type.isAssignable(world.boolType)) {
288 convertWarning(world.boolType, node); 289 convertWarning(world.boolType, node);
289 } 290 }
290 if (!options.enableTypeChecks) { 291 if (!options.enableTypeChecks) {
292 // TODO(jimhug): If type != world.boolType, this should return
293 // this.code === true according to the spec.
291 return this; 294 return this;
292 } else { 295 } else {
293 // TODO(jmesserly): this is hacky. 296 // TODO(jmesserly): this is hacky.
294 if (code.startsWith('\$notnull_bool')) { 297 if (code.startsWith('\$notnull_bool')) {
295 return this; 298 return this;
296 } else { 299 } else {
297 world.gen.corejs.useNotNullBool = true; 300 world.gen.corejs.useNotNullBool = true;
298 return new Value(world.boolType, '\$notnull_bool($code)', span); 301 return new Value(world.boolType, '\$notnull_bool($code)', span);
299 } 302 }
300 } 303 }
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 String canonicalCode; 498 String canonicalCode;
496 499
497 factory EvaluatedValue(Type type, actualValue, String canonicalCode, 500 factory EvaluatedValue(Type type, actualValue, String canonicalCode,
498 SourceSpan span) { 501 SourceSpan span) {
499 return new EvaluatedValue._internal(type, actualValue, 502 return new EvaluatedValue._internal(type, actualValue,
500 canonicalCode, span, codeWithComments(canonicalCode, span)); 503 canonicalCode, span, codeWithComments(canonicalCode, span));
501 } 504 }
502 505
503 EvaluatedValue._internal(Type type, this.actualValue, this.canonicalCode, 506 EvaluatedValue._internal(Type type, this.actualValue, this.canonicalCode,
504 SourceSpan span, String code) 507 SourceSpan span, String code)
505 : super(type, code, span, false, false, false); 508 : super(type, code, span, false);
506 509
507 static String codeWithComments(String canonicalCode, SourceSpan span) { 510 static String codeWithComments(String canonicalCode, SourceSpan span) {
508 return (span != null && span.text != canonicalCode) 511 return (span != null && span.text != canonicalCode)
509 ? '$canonicalCode/*${span.text}*/' : canonicalCode; 512 ? '$canonicalCode/*${span.text}*/' : canonicalCode;
510 } 513 }
511 } 514 }
512 515
513 /** An evaluated constant list expression. */ 516 /** An evaluated constant list expression. */
514 class ConstListValue extends EvaluatedValue { 517 class ConstListValue extends EvaluatedValue {
515 List<EvaluatedValue> values; 518 List<EvaluatedValue> values;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 var codeWithComment = "$name/*${exp.span.text}*/"; 619 var codeWithComment = "$name/*${exp.span.text}*/";
617 return new GlobalValue( 620 return new GlobalValue(
618 exp.type, codeWithComment, true, null, name, exp, name, 621 exp.type, codeWithComment, true, null, name, exp, name,
619 exp.span, 622 exp.span,
620 dependencies.filter((d) => d is GlobalValue)); 623 dependencies.filter((d) => d is GlobalValue));
621 } 624 }
622 625
623 GlobalValue(Type type, String code, bool isConst, 626 GlobalValue(Type type, String code, bool isConst,
624 this.field, this.name, this.exp, this.canonicalCode, 627 this.field, this.name, this.exp, this.canonicalCode,
625 SourceSpan span, this.dependencies) 628 SourceSpan span, this.dependencies)
626 : super(type, code, span, false, !isConst, false); 629 : super(type, code, span, !isConst);
627 630
628 int compareTo(GlobalValue other) { 631 int compareTo(GlobalValue other) {
629 // order by dependencies, o.w. by name 632 // order by dependencies, o.w. by name
630 if (other == this) { 633 if (other == this) {
631 return 0; 634 return 0;
632 } else if (dependencies.indexOf(other, 0) >= 0) { 635 } else if (dependencies.indexOf(other, 0) >= 0) {
633 return 1; 636 return 1;
634 } else if (other.dependencies.indexOf(this, 0) >= 0) { 637 } else if (other.dependencies.indexOf(this, 0) >= 0) {
635 return -1; 638 return -1;
636 } else if (dependencies.length > other.dependencies.length) { 639 } else if (dependencies.length > other.dependencies.length) {
(...skipping 13 matching lines...) Expand all
650 } 653 }
651 654
652 /** 655 /**
653 * Represents the hidden or implicit value in a bare reference like 'a'. 656 * Represents the hidden or implicit value in a bare reference like 'a'.
654 * This could be this, the current type, or the current library for purposes 657 * This could be this, the current type, or the current library for purposes
655 * of resolving members. 658 * of resolving members.
656 */ 659 */
657 class BareValue extends Value { 660 class BareValue extends Value {
658 MethodGenerator home; 661 MethodGenerator home;
659 662
660 BareValue(this.home, MethodGenerator outermost, SourceSpan span): 663 BareValue(this.home, MethodGenerator outermost, SourceSpan span)
661 super(outermost.method.declaringType, null, span, false, false, 664 : super(outermost.method.declaringType, null, span, false) {
662 outermost.isStatic); 665 isType = outermost.isStatic;
666 }
663 667
664 _tryResolveMember(MethodGenerator context, String name) { 668 _tryResolveMember(MethodGenerator context, String name) {
665 assert(context == home); 669 assert(context == home);
666 670
667 // First look for members directly defined on my type. 671 // First look for members directly defined on my type.
668 var member = type.resolveMember(name); 672 var member = type.resolveMember(name);
669 if (member != null) { 673 if (member != null) {
670 assert(code == null); 674 assert(code == null);
671 // TODO(jimhug): Lazy initialization here is weird! 675 // TODO(jimhug): Lazy initialization here is weird!
672 if (isType) { 676 if (isType) {
673 code = type.jsname; 677 code = type.jsname;
674 } else { 678 } else {
675 code = home._makeThisCode(); 679 code = home._makeThisCode();
676 } 680 }
677 return member; 681 return member;
678 } 682 }
679 683
680 // Then look for members in my library. 684 // Then look for members in my library.
681 member = home.library.lookup(name, span); 685 member = home.library.lookup(name, span);
682 if (member != null) { 686 if (member != null) {
683 return member; 687 return member;
684 } 688 }
685 689
686 return null; 690 return null;
687 } 691 }
688 } 692 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698