OLD | NEW |
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 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 result = new $FunctionType.new($returnType, args, [], {}); | 301 result = new $FunctionType.new($returnType, args, [], {}); |
302 map.set($returnType, result); | 302 map.set($returnType, result); |
303 return result; | 303 return result; |
304 })()'''); | 304 })()'''); |
305 | 305 |
306 class FunctionType extends AbstractFunctionType { | 306 class FunctionType extends AbstractFunctionType { |
307 final returnType; | 307 final returnType; |
308 List args; | 308 List args; |
309 List optionals; | 309 List optionals; |
310 final named; | 310 final named; |
311 dynamic metadata; | 311 // TODO(vsm): This is just parameter metadata for now. |
| 312 List metadata = []; |
312 String _stringValue; | 313 String _stringValue; |
313 | 314 |
314 /** | 315 /** |
315 * Construct a function type. There are two arrow constructors, | 316 * Construct a function type. There are two arrow constructors, |
316 * distinguished by the "definite" flag. | 317 * distinguished by the "definite" flag. |
317 * | 318 * |
318 * The fuzzy arrow (definite is false) treats any arguments | 319 * The fuzzy arrow (definite is false) treats any arguments |
319 * of type dynamic as having type bottom, and will always be | 320 * of type dynamic as having type bottom, and will always be |
320 * called with a dynamic invoke. | 321 * called with a dynamic invoke. |
321 * | 322 * |
(...skipping 27 matching lines...) Expand all Loading... |
349 create = | 350 create = |
350 () => new FunctionType(returnType, args, optionals, JS('', '{}')); | 351 () => new FunctionType(returnType, args, optionals, JS('', '{}')); |
351 } else { | 352 } else { |
352 var named = _canonicalizeNamed(definite, extra, _fnTypeNamedArgMap); | 353 var named = _canonicalizeNamed(definite, extra, _fnTypeNamedArgMap); |
353 keys = [returnType, args, named]; | 354 keys = [returnType, args, named]; |
354 create = () => new FunctionType(returnType, args, [], named); | 355 create = () => new FunctionType(returnType, args, [], named); |
355 } | 356 } |
356 return _memoizeArray(_fnTypeTypeMap, keys, create); | 357 return _memoizeArray(_fnTypeTypeMap, keys, create); |
357 } | 358 } |
358 | 359 |
359 List _process(List array, metadata) { | 360 List _process(List array) { |
360 var result = []; | 361 var result = []; |
361 for (var i = 0; JS('bool', '# < #.length', i, array); ++i) { | 362 for (var i = 0; JS('bool', '# < #.length', i, array); ++i) { |
362 var arg = JS('', '#[#]', array, i); | 363 var arg = JS('', '#[#]', array, i); |
363 if (JS('bool', '# instanceof Array', arg)) { | 364 if (JS('bool', '# instanceof Array', arg)) { |
364 metadata.add(JS('', '#.slice(1)', arg)); | 365 JS('', '#.push(#.slice(1))', metadata, arg); |
365 result.add(JS('', '#[0]', arg)); | 366 JS('', '#.push(#[0])', result, arg); |
366 } else { | 367 } else { |
367 JS('', '#.push([])', metadata); | 368 JS('', '#.push([])', metadata); |
368 JS('', '#.push(#)', result, arg); | 369 JS('', '#.push(#)', result, arg); |
369 } | 370 } |
370 } | 371 } |
371 return result; | 372 return result; |
372 } | 373 } |
373 | 374 |
374 FunctionType(this.returnType, this.args, this.optionals, this.named) { | 375 FunctionType(this.returnType, this.args, this.optionals, this.named) { |
375 // TODO(vsm): This is just parameter metadata for now. | 376 this.args = _process(this.args); |
376 metadata = []; | 377 this.optionals = _process(this.optionals); |
377 this.args = _process(this.args, metadata); | |
378 this.optionals = _process(this.optionals, metadata); | |
379 // TODO(vsm): Add named arguments. | 378 // TODO(vsm): Add named arguments. |
380 } | 379 } |
381 | 380 |
382 toString() => name; | 381 toString() => name; |
383 | 382 |
384 get name { | 383 get name { |
385 if (_stringValue != null) return _stringValue; | 384 if (_stringValue != null) return _stringValue; |
386 | 385 |
387 var buffer = '('; | 386 var buffer = '('; |
388 for (var i = 0; JS('bool', '# < #.length', i, args); ++i) { | 387 for (var i = 0; JS('bool', '# < #.length', i, args); ++i) { |
(...skipping 29 matching lines...) Expand all Loading... |
418 | 417 |
419 var returnTypeName = typeName(returnType); | 418 var returnTypeName = typeName(returnType); |
420 buffer += ') -> $returnTypeName'; | 419 buffer += ') -> $returnTypeName'; |
421 _stringValue = buffer; | 420 _stringValue = buffer; |
422 return buffer; | 421 return buffer; |
423 } | 422 } |
424 } | 423 } |
425 | 424 |
426 class Typedef extends AbstractFunctionType { | 425 class Typedef extends AbstractFunctionType { |
427 dynamic _name; | 426 dynamic _name; |
428 dynamic _closure; | 427 AbstractFunctionType Function() _closure; |
429 AbstractFunctionType _functionType; | 428 AbstractFunctionType _functionType; |
430 | 429 |
431 Typedef(this._name, this._closure) {} | 430 Typedef(this._name, this._closure) {} |
432 | 431 |
433 toString() => JS('', '# + "(" + #.toString() + ")"', _name, functionType); | 432 toString() => |
| 433 JS('String', '# + "(" + #.toString() + ")"', _name, functionType); |
434 get name => _name; | 434 get name => _name; |
435 | 435 |
436 AbstractFunctionType get functionType { | 436 AbstractFunctionType get functionType { |
437 return _functionType ??= JS('', '#()', _closure); | 437 var ft = _functionType; |
| 438 return ft == null ? _functionType = _closure() : ft; |
438 } | 439 } |
439 } | 440 } |
440 | 441 |
441 /// A type variable, used by [GenericFunctionType] to represent a type formal. | 442 /// A type variable, used by [GenericFunctionType] to represent a type formal. |
442 class TypeVariable extends TypeRep { | 443 class TypeVariable extends TypeRep { |
443 final String name; | 444 final String name; |
444 | 445 |
445 TypeVariable(this.name); | 446 TypeVariable(this.name); |
446 | 447 |
447 toString() => name; | 448 toString() => name; |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 if (partials.isNotEmpty) { | 595 if (partials.isNotEmpty) { |
595 throwStrongModeError('Instantiate to bounds failed for type with ' | 596 throwStrongModeError('Instantiate to bounds failed for type with ' |
596 'recursive generic bounds: ${typeName(this)}. ' | 597 'recursive generic bounds: ${typeName(this)}. ' |
597 'Try passing explicit type arguments.'); | 598 'Try passing explicit type arguments.'); |
598 } | 599 } |
599 | 600 |
600 return defaults; | 601 return defaults; |
601 } | 602 } |
602 } | 603 } |
603 | 604 |
604 typedef(name, closure) => new Typedef(name, closure); | 605 typedef(name, AbstractFunctionType Function() closure) => |
| 606 new Typedef(name, closure); |
605 | 607 |
606 /// Create a definite function type. | 608 /// Create a definite function type. |
607 /// | 609 /// |
608 /// No substitution of dynamic for bottom occurs. | 610 /// No substitution of dynamic for bottom occurs. |
609 fnType(returnType, List args, extra) => | 611 fnType(returnType, List args, extra) => |
610 FunctionType.create(true, returnType, args, extra); | 612 FunctionType.create(true, returnType, args, extra); |
611 | 613 |
612 /// Create a "fuzzy" function type. | 614 /// Create a "fuzzy" function type. |
613 /// | 615 /// |
614 /// If any arguments are dynamic they will be replaced with bottom. | 616 /// If any arguments are dynamic they will be replaced with bottom. |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 return true; | 1057 return true; |
1056 } | 1058 } |
1057 | 1059 |
1058 let typeArgs = $getGenericArgs($type); | 1060 let typeArgs = $getGenericArgs($type); |
1059 if (!typeArgs) return true; | 1061 if (!typeArgs) return true; |
1060 for (let t of typeArgs) { | 1062 for (let t of typeArgs) { |
1061 if (t != $Object && t != $dynamic) return false; | 1063 if (t != $Object && t != $dynamic) return false; |
1062 } | 1064 } |
1063 return true; | 1065 return true; |
1064 })()'''); | 1066 })()'''); |
OLD | NEW |