Appearance
| 1 | namespace Semantic is | |
| 2 | use Types.Type | |
| 3 | ||
| 4 | // Which argument decides the tuple a spread formal's pack binds to. | |
| 5 | // | |
| 6 | // A literal written at `f: T.. -> U` is adapted into a one-parameter | |
| 7 | // wrapper that destructures the pack's tuple, and the wrapper is not | |
| 8 | // rebuilt once it is in place. While the tuple is still a placeholder | |
| 9 | // the adaptation is premature exactly when some other formal holds the | |
| 10 | // same placeholder - `each[T](source: Iterable[T], f: T.. -> void)` - | |
| 11 | // because that formal's argument settles the tuple on a later walk. | |
| 12 | // Where no other formal holds it, the literal is the only thing that | |
| 13 | // can decide it, and adapting it is how that happens. | |
| 14 | class PACK_TUPLE_SOURCE is | |
| 15 | init() is | |
| 16 | super.init() | |
| 17 | si | |
| 18 | ||
| 19 | is_decided_by_another_formal(formals: Collections.List[Type], index: int, pack: Type) -> bool is | |
| 20 | for i in 0..formals.count do | |
| 21 | if i != index /\ _shares_placeholder(formals[i], pack) then | |
| 22 | return true | |
| 23 | fi | |
| 24 | od | |
| 25 | ||
| 26 | return false | |
| 27 | si | |
| 28 | ||
| 29 | _shares_placeholder(type: Type, pack: Type) -> bool is | |
| 30 | if type.is_inferred then | |
| 31 | return _holds(pack, type) | |
| 32 | fi | |
| 33 | ||
| 34 | for argument in type.arguments do | |
| 35 | if _shares_placeholder(argument, pack) then | |
| 36 | return true | |
| 37 | fi | |
| 38 | od | |
| 39 | ||
| 40 | return false | |
| 41 | si | |
| 42 | ||
| 43 | _holds(type: Type, placeholder: Type) -> bool is | |
| 44 | if type == placeholder then | |
| 45 | return true | |
| 46 | fi | |
| 47 | ||
| 48 | for argument in type.arguments do | |
| 49 | if _holds(argument, placeholder) then | |
| 50 | return true | |
| 51 | fi | |
| 52 | od | |
| 53 | ||
| 54 | return false | |
| 55 | si | |
| 56 | si | |
| 57 | si |