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: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart

Issue 2515353003: Support lazy JS types. (Closed)
Patch Set: Support lazy JS types. Created 4 years 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
« no previous file with comments | « pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart ('k') | no next file » | 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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 /// This library defines the representation of runtime types. 5 /// This library defines the representation of runtime types.
6 part of dart._runtime; 6 part of dart._runtime;
7 7
8 final metadata = JS('', 'Symbol("metadata")'); 8 final metadata = JS('', 'Symbol("metadata")');
9 9
10 /// The symbol used to store the cached `Type` object associated with a class. 10 /// The symbol used to store the cached `Type` object associated with a class.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 /// T.as(o): Implements 'o as T'. 49 /// T.as(o): Implements 'o as T'.
50 /// T._check(o): Implements the type assertion of 'T x = o;' 50 /// T._check(o): Implements the type assertion of 'T x = o;'
51 /// 51 ///
52 /// By convention, we used named JavaScript functions for these methods with the 52 /// By convention, we used named JavaScript functions for these methods with the
53 /// name 'is_X', 'as_X' and 'check_X' for various X to indicate the type or the 53 /// name 'is_X', 'as_X' and 'check_X' for various X to indicate the type or the
54 /// implementation strategy for the test (e.g 'is_String', 'is_G' for generic 54 /// implementation strategy for the test (e.g 'is_String', 'is_G' for generic
55 /// types, etc.) 55 /// types, etc.)
56 // TODO(jmesserly): we shouldn't implement Type here. It should be moved down 56 // TODO(jmesserly): we shouldn't implement Type here. It should be moved down
57 // to AbstractFunctionType. 57 // to AbstractFunctionType.
58 class TypeRep implements Type { 58 class TypeRep implements Type {
59 TypeRep() { _initialize; } 59 TypeRep() {
60 _initialize;
61 }
60 String get name => this.toString(); 62 String get name => this.toString();
61 } 63 }
62 64
63 class Dynamic extends TypeRep { 65 class Dynamic extends TypeRep {
64 toString() => 'dynamic'; 66 toString() => 'dynamic';
65 } 67 }
66 68
69 class LazyJSType implements Type {
70 final _jsTypeCallback;
71 final _dartName;
72
73 LazyJSType(this._jsTypeCallback, this._dartName);
74
75 get _rawJSType => JS('', '#()', _jsTypeCallback);
76
77 toString() => _jsTypeCallback != null ? typeName(_rawJSType) : _dartName;
78 }
79
80 _isInstanceOfLazyJSType(o, LazyJSType t) {
81 if (t._jsTypeCallback != null) {
82 return JS('bool', 'dart.is(#, #)', o, t._rawJSType);
83 }
84 if (o == null) return false;
85 // Anonymous case: match any JS type.
86 return _isJSObject(o);
87 }
88
89 _asInstanceOfLazyJSType(o, LazyJSType t) {
90 if (t._jsTypeCallback != null) {
91 return JS('bool', 'dart.as(#, #)', o, t._rawJSType);
92 }
93 // Anonymous case: allow any JS type.
94 if (o == null) return null;
95 if (!_isJSObject(o)) _throwCastError(o, t, true);
96 return o;
97 }
98
99 bool _isJSObject(o) => JS('bool', '!dart.getReifiedType(o)[dart._runtimeType]');
100
67 @JSExportName('dynamic') 101 @JSExportName('dynamic')
68 final _dynamic = new Dynamic(); 102 final _dynamic = new Dynamic();
69 103
70 final _initialize = _initialize2(); 104 final _initialize = _initialize2();
71 105
72 _initialize2() => JS('', '''(() => { 106 _initialize2() => JS(
107 '',
108 '''(() => {
73 // JavaScript API forwards to runtime library. 109 // JavaScript API forwards to runtime library.
74 $TypeRep.prototype.is = function is_T(object) { 110 $TypeRep.prototype.is = function is_T(object) {
75 return dart.is(object, this); 111 return dart.is(object, this);
76 }; 112 };
77 $TypeRep.prototype.as = function as_T(object) { 113 $TypeRep.prototype.as = function as_T(object) {
78 return dart.as(object, this); 114 return dart.as(object, this);
79 }; 115 };
80 $TypeRep.prototype._check = function check_T(object) { 116 $TypeRep.prototype._check = function check_T(object) {
81 return dart.check(object, this); 117 return dart.check(object, this);
82 }; 118 };
83 119
84 // Fast path for type `dynamic`. 120 // Fast path for type `dynamic`.
85 $Dynamic.prototype.is = function is_Dynamic(object) { 121 $Dynamic.prototype.is = function is_Dynamic(object) {
86 return true; 122 return true;
87 }; 123 };
88 $Dynamic.prototype.as = function as_Dynamic(object) { 124 $Dynamic.prototype.as = function as_Dynamic(object) {
89 return object; 125 return object;
90 }; 126 };
91 $Dynamic.prototype._check = function check_Dynamic(object) { 127 $Dynamic.prototype._check = function check_Dynamic(object) {
92 return object; 128 return object;
93 }; 129 };
130
131 $LazyJSType.prototype.is = function is_T(object) {
132 return $_isInstanceOfLazyJSType(object, this);
133 };
134 $LazyJSType.prototype.as = function as_T(object) {
135 return $_asInstanceOfLazyJSType(object, this);
136 };
94 })()'''); 137 })()''');
95 138
96 class Void extends TypeRep { 139 class Void extends TypeRep {
97 toString() => 'void'; 140 toString() => 'void';
98 } 141 }
99 142
100 @JSExportName('void') 143 @JSExportName('void')
101 final _void = new Void(); 144 final _void = new Void();
102 145
103 class Bottom extends TypeRep { 146 class Bottom extends TypeRep {
104 toString() => 'bottom'; 147 toString() => 'bottom';
105 } 148 }
149
106 final bottom = new Bottom(); 150 final bottom = new Bottom();
107 151
108 class JSObject extends TypeRep { 152 class JSObject extends TypeRep {
109 toString() => 'NativeJavaScriptObject'; 153 toString() => 'NativeJavaScriptObject';
110 } 154 }
111 155
112 final jsobject = new JSObject(); 156 final jsobject = new JSObject();
113 157
114 class WrappedType extends Type { 158 class WrappedType extends Type {
115 final _wrappedType; 159 final _wrappedType;
116 WrappedType(this._wrappedType); 160 WrappedType(this._wrappedType);
117 toString() => typeName(_wrappedType); 161 toString() => typeName(_wrappedType);
118 } 162 }
119 163
120 final AbstractFunctionType = JS('', ''' 164 final AbstractFunctionType = JS(
165 '',
166 '''
121 class AbstractFunctionType extends $TypeRep { 167 class AbstractFunctionType extends $TypeRep {
122 constructor() { 168 constructor() {
123 super(); 169 super();
124 this._stringValue = null; 170 this._stringValue = null;
125 } 171 }
126 172
127 toString() { return this.name; } 173 toString() { return this.name; }
128 174
129 get name() { 175 get name() {
130 if (this._stringValue) return this._stringValue; 176 if (this._stringValue) return this._stringValue;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 } 211 }
166 } 212 }
167 '''); 213 ''');
168 214
169 /// Memo table for named argument groups. A named argument packet 215 /// Memo table for named argument groups. A named argument packet
170 /// {name1 : type1, ..., namen : typen} corresponds to the path 216 /// {name1 : type1, ..., namen : typen} corresponds to the path
171 /// n, name1, type1, ...., namen, typen. The element of the map 217 /// n, name1, type1, ...., namen, typen. The element of the map
172 /// reached via this path (if any) is the canonical representative 218 /// reached via this path (if any) is the canonical representative
173 /// for this packet. 219 /// for this packet.
174 final _fnTypeNamedArgMap = JS('', 'new Map()'); 220 final _fnTypeNamedArgMap = JS('', 'new Map()');
221
175 /// Memo table for positional argument groups. A positional argument 222 /// Memo table for positional argument groups. A positional argument
176 /// packet [type1, ..., typen] (required or optional) corresponds to 223 /// packet [type1, ..., typen] (required or optional) corresponds to
177 /// the path n, type1, ...., typen. The element reached via 224 /// the path n, type1, ...., typen. The element reached via
178 /// this path (if any) is the canonical representative for this 225 /// this path (if any) is the canonical representative for this
179 /// packet. Note that required and optional parameters packages 226 /// packet. Note that required and optional parameters packages
180 /// may have the same canonical representation. 227 /// may have the same canonical representation.
181 final _fnTypeArrayArgMap = JS('', 'new Map()'); 228 final _fnTypeArrayArgMap = JS('', 'new Map()');
229
182 /// Memo table for function types. The index path consists of the 230 /// Memo table for function types. The index path consists of the
183 /// path length - 1, the returnType, the canonical positional argument 231 /// path length - 1, the returnType, the canonical positional argument
184 /// packet, and if present, the canonical optional or named argument 232 /// packet, and if present, the canonical optional or named argument
185 /// packet. A level of indirection could be avoided here if desired. 233 /// packet. A level of indirection could be avoided here if desired.
186 final _fnTypeTypeMap = JS('', 'new Map()'); 234 final _fnTypeTypeMap = JS('', 'new Map()');
235
187 /// Memo table for small function types with no optional or named 236 /// Memo table for small function types with no optional or named
188 /// arguments and less than a fixed n (currently 3) number of 237 /// arguments and less than a fixed n (currently 3) number of
189 /// required arguments. Indexing into this table by the number 238 /// required arguments. Indexing into this table by the number
190 /// of required arguments yields a map which is indexed by the 239 /// of required arguments yields a map which is indexed by the
191 /// argument types themselves. The element reached via this 240 /// argument types themselves. The element reached via this
192 /// index path (if present) is the canonical function type. 241 /// index path (if present) is the canonical function type.
193 final _fnTypeSmallMap = JS('', '[new Map(), new Map(), new Map()]'); 242 final _fnTypeSmallMap = JS('', '[new Map(), new Map(), new Map()]');
194 243
195 final FunctionType = JS('', ''' 244 final FunctionType = JS(
245 '',
246 '''
196 class FunctionType extends $AbstractFunctionType { 247 class FunctionType extends $AbstractFunctionType {
197 static _memoizeArray(map, arr, create) { 248 static _memoizeArray(map, arr, create) {
198 let len = arr.length; 249 let len = arr.length;
199 map = FunctionType._lookupNonTerminal(map, len); 250 map = FunctionType._lookupNonTerminal(map, len);
200 for (var i = 0; i < len-1; ++i) { 251 for (var i = 0; i < len-1; ++i) {
201 map = FunctionType._lookupNonTerminal(map, arr[i]); 252 map = FunctionType._lookupNonTerminal(map, arr[i]);
202 } 253 }
203 let result = map.get(arr[len-1]); 254 let result = map.get(arr[len-1]);
204 if (result !== void 0) return result; 255 if (result !== void 0) return result;
205 map.set(arr[len-1], result = create()); 256 map.set(arr[len-1], result = create());
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 } 390 }
340 return result; 391 return result;
341 } 392 }
342 this.args = process(this.args, this.metadata); 393 this.args = process(this.args, this.metadata);
343 this.optionals = process(this.optionals, this.metadata); 394 this.optionals = process(this.optionals, this.metadata);
344 // TODO(vsm): Add named arguments. 395 // TODO(vsm): Add named arguments.
345 } 396 }
346 } 397 }
347 '''); 398 ''');
348 399
349 400 final Typedef = JS(
350 final Typedef = JS('', ''' 401 '',
402 '''
351 class Typedef extends $AbstractFunctionType { 403 class Typedef extends $AbstractFunctionType {
352 constructor(name, closure) { 404 constructor(name, closure) {
353 super(); 405 super();
354 this._name = name; 406 this._name = name;
355 this._closure = closure; 407 this._closure = closure;
356 this._functionType = null; 408 this._functionType = null;
357 } 409 }
358 410
359 get name() { 411 get name() {
360 return this._name; 412 return this._name;
(...skipping 23 matching lines...) Expand all
384 } 436 }
385 437
386 get metadata() { 438 get metadata() {
387 return this.functionType.metadata; 439 return this.functionType.metadata;
388 } 440 }
389 } 441 }
390 '''); 442 ''');
391 443
392 final _typeFormalCount = JS('', 'Symbol("_typeFormalCount")'); 444 final _typeFormalCount = JS('', 'Symbol("_typeFormalCount")');
393 445
394 _functionType(definite, returnType, args, extra) => JS('', '''(() => { 446 _functionType(definite, returnType, args, extra) => JS(
447 '',
448 '''(() => {
395 // TODO(jmesserly): this is a bit of a retrofit, to easily fit 449 // TODO(jmesserly): this is a bit of a retrofit, to easily fit
396 // generic functions into all of the existing ways we generate function 450 // generic functions into all of the existing ways we generate function
397 // signatures. Given `(T) => [T, [T]]` we'll return a function that does 451 // signatures. Given `(T) => [T, [T]]` we'll return a function that does
398 // `(T) => _functionType(definite, T, [T])` ... we could do this in the 452 // `(T) => _functionType(definite, T, [T])` ... we could do this in the
399 // compiler instead, at a slight cost to code size. 453 // compiler instead, at a slight cost to code size.
400 if ($args === void 0 && $extra === void 0) { 454 if ($args === void 0 && $extra === void 0) {
401 const fnTypeParts = $returnType; 455 const fnTypeParts = $returnType;
402 // A closure that computes the remaining arguments. 456 // A closure that computes the remaining arguments.
403 // Return a function that makes the type. 457 // Return a function that makes the type.
404 function makeGenericFnType(...types) { 458 function makeGenericFnType(...types) {
(...skipping 15 matching lines...) Expand all
420 474
421 /// 475 ///
422 /// Create a definite function type. No substitution of dynamic for 476 /// Create a definite function type. No substitution of dynamic for
423 /// bottom occurs. 477 /// bottom occurs.
424 /// 478 ///
425 definiteFunctionType(returnType, args, extra) => 479 definiteFunctionType(returnType, args, extra) =>
426 _functionType(true, returnType, args, extra); 480 _functionType(true, returnType, args, extra);
427 481
428 typedef(name, closure) => JS('', 'new #(#, #)', Typedef, name, closure); 482 typedef(name, closure) => JS('', 'new #(#, #)', Typedef, name, closure);
429 483
430 typeName(type) => JS('', '''(() => { 484 typeName(type) => JS(
485 '',
486 '''(() => {
431 if ($type === void 0) return "undefined type"; 487 if ($type === void 0) return "undefined type";
432 if ($type === null) return "null type"; 488 if ($type === null) return "null type";
433 // Non-instance types 489 // Non-instance types
434 if ($type instanceof $TypeRep) { 490 if ($type instanceof $TypeRep) {
435 if ($type instanceof $Typedef) { 491 if ($type instanceof $Typedef) {
436 return $type.name + "(" + $type.functionType.toString() + ")"; 492 return $type.name + "(" + $type.functionType.toString() + ")";
437 } 493 }
438 return $type.toString(); 494 return $type.toString();
439 } 495 }
440 496
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 return "JSObject<" + $type.name + ">"; 529 return "JSObject<" + $type.name + ">";
474 })()'''); 530 })()''');
475 531
476 /// Get the underlying function type, potentially from the call method 532 /// Get the underlying function type, potentially from the call method
477 /// for a class type. 533 /// for a class type.
478 getImplicitFunctionType(type) { 534 getImplicitFunctionType(type) {
479 if (isFunctionType(type)) return type; 535 if (isFunctionType(type)) return type;
480 return getMethodTypeFromType(type, 'call'); 536 return getMethodTypeFromType(type, 'call');
481 } 537 }
482 538
483 bool isFunctionType(type) => 539 bool isFunctionType(type) => JS('bool', '# instanceof # || # === #', type,
484 JS('bool', '# instanceof # || # === #', 540 AbstractFunctionType, type, Function);
485 type, AbstractFunctionType, type, Function); 541
542 isLazyJSSubtype(LazyJSType t1, LazyJSType t2, covariant) {
543 if (t1 == t2) return true;
544
545 // All anonymous JS types are subtypes of each other.
546 if (t1._jsTypeCallback == null || t2._jsTypeCallback == null) return true;
547 return isClassSubType(t1._rawJSType, t2._rawJSType, covariant);
548 }
486 549
487 /// Returns true if [ft1] <: [ft2]. 550 /// Returns true if [ft1] <: [ft2].
488 /// Returns false if [ft1] </: [ft2] in both spec and strong mode 551 /// Returns false if [ft1] </: [ft2] in both spec and strong mode
489 /// Returns null if [ft1] </: [ft2] in strong mode, but spec mode 552 /// Returns null if [ft1] </: [ft2] in strong mode, but spec mode
490 /// may differ 553 /// may differ
491 /// If [covariant] is true, then we are checking subtyping in a covariant 554 /// If [covariant] is true, then we are checking subtyping in a covariant
492 /// position, and hence the direction of the check for function types 555 /// position, and hence the direction of the check for function types
493 /// corresponds to the direction of the check according to the Dart spec. 556 /// corresponds to the direction of the check according to the Dart spec.
494 isFunctionSubtype(ft1, ft2, covariant) => JS('', '''(() => { 557 isFunctionSubtype(ft1, ft2, covariant) => JS(
558 '',
559 '''(() => {
495 if ($ft2 === $Function) { 560 if ($ft2 === $Function) {
496 return true; 561 return true;
497 } 562 }
498 563
499 if ($ft1 === $Function) { 564 if ($ft1 === $Function) {
500 return false; 565 return false;
501 } 566 }
502 567
503 let ret1 = $ft1.returnType; 568 let ret1 = $ft1.returnType;
504 let ret2 = $ft2.returnType; 569 let ret2 = $ft2.returnType;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 // Dart allows void functions to subtype dynamic functions, but not 629 // Dart allows void functions to subtype dynamic functions, but not
565 // other functions. 630 // other functions.
566 if (ret1 === $_void) return (ret2 === $dynamic); 631 if (ret1 === $_void) return (ret2 === $dynamic);
567 if (!$_isSubtype(ret1, ret2, $covariant)) return null; 632 if (!$_isSubtype(ret1, ret2, $covariant)) return null;
568 return true; 633 return true;
569 })()'''); 634 })()''');
570 635
571 /// TODO(leafp): This duplicates code in operations.dart. 636 /// TODO(leafp): This duplicates code in operations.dart.
572 /// I haven't found a way to factor it out that makes the 637 /// I haven't found a way to factor it out that makes the
573 /// code generator happy though. 638 /// code generator happy though.
574 _subtypeMemo(f) => JS('', '''(() => { 639 _subtypeMemo(f) => JS(
640 '',
641 '''(() => {
575 let memo = new Map(); 642 let memo = new Map();
576 return (t1, t2) => { 643 return (t1, t2) => {
577 let map = memo.get(t1); 644 let map = memo.get(t1);
578 let result; 645 let result;
579 if (map) { 646 if (map) {
580 result = map.get(t2); 647 result = map.get(t2);
581 if (result !== void 0) return result; 648 if (result !== void 0) return result;
582 } else { 649 } else {
583 memo.set(t1, map = new Map()); 650 memo.set(t1, map = new Map());
584 } 651 }
585 result = $f(t1, t2); 652 result = $f(t1, t2);
586 map.set(t2, result); 653 map.set(t2, result);
587 return result; 654 return result;
588 }; 655 };
589 })()'''); 656 })()''');
590 657
591 /// Returns true if [t1] <: [t2]. 658 /// Returns true if [t1] <: [t2].
592 /// Returns false if [t1] </: [t2] in both spec and strong mode 659 /// Returns false if [t1] </: [t2] in both spec and strong mode
593 /// Returns undefined if [t1] </: [t2] in strong mode, but spec 660 /// Returns undefined if [t1] </: [t2] in strong mode, but spec
594 /// mode may differ 661 /// mode may differ
595 final isSubtype = 662 final isSubtype = JS(
596 JS('', '$_subtypeMemo((t1, t2) => (t1 === t2) || $_isSubtype(t1, t2, true))' ); 663 '', '$_subtypeMemo((t1, t2) => (t1 === t2) || $_isSubtype(t1, t2, true))');
597 664
598 _isBottom(type) => JS('bool', '# == #', type, bottom); 665 _isBottom(type) => JS('bool', '# == #', type, bottom);
599 666
600 _isTop(type) => JS('bool', '# == # || # == #', type, Object, type, dynamic); 667 _isTop(type) => JS('bool', '# == # || # == #', type, Object, type, dynamic);
601 668
602 _isSubtype(t1, t2, covariant) => JS('', '''(() => { 669 _isSubtype(t1, t2, covariant) => JS(
670 '',
671 '''(() => {
603 if ($t1 === $t2) return true; 672 if ($t1 === $t2) return true;
604 673
605 // Trivially true. 674 // Trivially true.
606 if ($_isTop($t2) || $_isBottom($t1)) { 675 if ($_isTop($t2) || $_isBottom($t1)) {
607 return true; 676 return true;
608 } 677 }
609 678
610 // Trivially false. 679 // Trivially false.
611 if ($_isBottom($t2)) return null; 680 if ($_isBottom($t2)) return null;
612 if ($_isTop($t1)) { 681 if ($_isTop($t1)) {
(...skipping 13 matching lines...) Expand all
626 // Function subtyping. 695 // Function subtyping.
627 696
628 // Handle Objects with call methods. Those are functions 697 // Handle Objects with call methods. Those are functions
629 // even if they do not *nominally* subtype core.Function. 698 // even if they do not *nominally* subtype core.Function.
630 t1 = $getImplicitFunctionType(t1); 699 t1 = $getImplicitFunctionType(t1);
631 if (!t1) return false; 700 if (!t1) return false;
632 701
633 if ($isFunctionType($t1) && $isFunctionType($t2)) { 702 if ($isFunctionType($t1) && $isFunctionType($t2)) {
634 return $isFunctionSubtype($t1, $t2, $covariant); 703 return $isFunctionSubtype($t1, $t2, $covariant);
635 } 704 }
705
706 if ($t1 instanceof $LazyJSType && $t2 instanceof $LazyJSType) {
707 return $isLazyJSSubtype($t1, $t2, $covariant);
708 }
709
636 return false; 710 return false;
637 })()'''); 711 })()''');
638 712
639 isClassSubType(t1, t2, covariant) => JS('', '''(() => { 713 isClassSubType(t1, t2, covariant) => JS(
714 '',
715 '''(() => {
640 // We support Dart's covariant generics with the caveat that we do not 716 // We support Dart's covariant generics with the caveat that we do not
641 // substitute bottom for dynamic in subtyping rules. 717 // substitute bottom for dynamic in subtyping rules.
642 // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow: 718 // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow:
643 // - S !<: S<T1, ..., Tn> 719 // - S !<: S<T1, ..., Tn>
644 // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn> 720 // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn>
645 if ($t1 == $t2) return true; 721 if ($t1 == $t2) return true;
646 722
647 if ($t1 == $Object) return false; 723 if ($t1 == $Object) return false;
648 724
649 // If t1 is a JS Object, we may not hit core.Object. 725 // If t1 is a JS Object, we may not hit core.Object.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 // so the answer is indefinite. 786 // so the answer is indefinite.
711 if (indefinite) return null; 787 if (indefinite) return null;
712 // We found no definite supertypes and no indefinite supertypes, so we 788 // We found no definite supertypes and no indefinite supertypes, so we
713 // can return false. 789 // can return false.
714 return false; 790 return false;
715 })()'''); 791 })()''');
716 792
717 // TODO(jmesserly): this isn't currently used, but it could be if we want 793 // TODO(jmesserly): this isn't currently used, but it could be if we want
718 // `obj is NonGroundType<T,S>` to be rejected at runtime instead of compile 794 // `obj is NonGroundType<T,S>` to be rejected at runtime instead of compile
719 // time. 795 // time.
720 isGroundType(type) => JS('', '''(() => { 796 isGroundType(type) => JS(
797 '',
798 '''(() => {
721 // TODO(vsm): Cache this if we start using it at runtime. 799 // TODO(vsm): Cache this if we start using it at runtime.
722 800
723 if ($type instanceof $AbstractFunctionType) { 801 if ($type instanceof $AbstractFunctionType) {
724 if (!$_isTop($type.returnType)) return false; 802 if (!$_isTop($type.returnType)) return false;
725 for (let i = 0; i < $type.args.length; ++i) { 803 for (let i = 0; i < $type.args.length; ++i) {
726 if (!$_isBottom($type.args[i])) return false; 804 if (!$_isBottom($type.args[i])) return false;
727 } 805 }
728 for (let i = 0; i < $type.optionals.length; ++i) { 806 for (let i = 0; i < $type.optionals.length; ++i) {
729 if (!$_isBottom($type.optionals[i])) return false; 807 if (!$_isBottom($type.optionals[i])) return false;
730 } 808 }
731 let names = $getOwnPropertyNames($type.named); 809 let names = $getOwnPropertyNames($type.named);
732 for (let i = 0; i < names.length; ++i) { 810 for (let i = 0; i < names.length; ++i) {
733 if (!$_isBottom($type.named[names[i]])) return false; 811 if (!$_isBottom($type.named[names[i]])) return false;
734 } 812 }
735 return true; 813 return true;
736 } 814 }
737 815
738 let typeArgs = $getGenericArgs($type); 816 let typeArgs = $getGenericArgs($type);
739 if (!typeArgs) return true; 817 if (!typeArgs) return true;
740 for (let t of typeArgs) { 818 for (let t of typeArgs) {
741 if (t != $Object && t != $dynamic) return false; 819 if (t != $Object && t != $dynamic) return false;
742 } 820 }
743 return true; 821 return true;
744 })()'''); 822 })()''');
OLDNEW
« no previous file with comments | « pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698