Appearance
| 1 | namespace Syntax.Trees.Expressions is | |
| 2 | ||
| 3 | use Source | |
| 4 | ||
| 5 | // The whole body of a synthesized `=~`. The parser never produces | |
| 6 | // one: ADD_ACCESSORS_FOR_PROPERTIES puts a single node where the | |
| 7 | // body goes, and compile-expressions emits the comparison from it | |
| 8 | // once the owner, its ancestors and its members have resolved. | |
| 9 | // | |
| 10 | // One node rather than a tree of tests and calls. Everything the | |
| 11 | // comparison needs to decide - which guard the owner takes, how | |
| 12 | // each member compares, whether a base contributes members of its | |
| 13 | // own - is settled by types and ancestors that do not exist where | |
| 14 | // the body is written, and a tree built ahead of them has to be | |
| 15 | // patched afterwards by a pass that does know. It is also read by | |
| 16 | // every diagnostic that reads user code, so it draws reports at | |
| 17 | // source locations for expressions nobody wrote. | |
| 18 | // | |
| 19 | // `members` names what to compare, in declaration order, under the | |
| 20 | // names a value of the owner is read by - an auto-property through | |
| 21 | // its backing field, a `field` member by its own name. The rules | |
| 22 | // that decide which members those are read the declarations, so | |
| 23 | // they are answered where the declarations are. | |
| 24 | class MEMBERWISE_EQUALS( | |
| 25 | location: LOCATION, | |
| 26 | members: Collections.LIST[string], | |
| 27 | // Where each member was declared, so that a report about how | |
| 28 | // it compares lands on the declaration rather than on a body | |
| 29 | // nobody wrote. | |
| 30 | member_locations: Collections.LIST[LOCATION] | |
| 31 | ): Expression is | |
| 32 | // Whether a member reaching neither an operator nor an | |
| 33 | // element-wise comparison is worth reporting. A union's | |
| 34 | // structural equality is what choosing a union asks for, so a | |
| 35 | // member that degrades it is; a struct's or a class's operator | |
| 36 | // is given rather than asked for, and reporting there would | |
| 37 | // fire on every type in a program, including the ones nothing | |
| 38 | // ever compares. | |
| 39 | reports_fallback: bool public | |
| 40 | ||
| 41 | // Every function the lowering decided to call - each member's | |
| 42 | // own comparison, and the base's operator where one is | |
| 43 | // reached. The effects walk reads them: a synthesized body | |
| 44 | // stores nothing itself, so what it can do is exactly what | |
| 45 | // these do, and the solver is told rather than left to guess. | |
| 46 | called_functions: Collections.LIST[Semantic.Symbols.Function] => memberwise_state.functions() | |
| 47 | ||
| 48 | memberwise_state: Syntax.Process.MEMBERWISE_STATE field | |
| 49 | ||
| 50 | super(location) | |
| 51 | ||
| 52 | clear() is | |
| 53 | super.clear() | |
| 54 | memberwise_state.clear() | |
| 55 | si | |
| 56 | ||
| 57 | clear_outputs() is | |
| 58 | super.clear_outputs() | |
| 59 | memberwise_state.clear() | |
| 60 | si | |
| 61 | ||
| 62 | accept(visitor: Visitor) is | |
| 63 | visitor.visit(self) | |
| 64 | si | |
| 65 | si | |
| 66 | si |