Appearance
| 1 | namespace Semantic.Symbols is | |
| 2 | use Source.LOCATION; | |
| 3 | ||
| 4 | // One reversible mutation made on behalf of a class's | |
| 5 | // pull_down_super_symbols: members pulled into its store, override / | |
| 6 | // implementor links registered on other symbols, and IL-name / | |
| 7 | // assign-accessor state inherited onto its own members. Each op is | |
| 8 | // self-contained; undo happens in strict reverse order, so an op's | |
| 9 | // undo precondition is exactly the state its do-site left behind. | |
| 10 | union InheritanceOp is | |
| 11 | MEMBER_ADDED(scope: Scoped, name: string); | |
| 12 | MEMBER_REPLACED(scope: Scoped, name: string, previous: Symbol); | |
| 13 | GROUP_MEMBER_ADDED(group: FUNCTION_GROUP, function: Function); | |
| 14 | TYPE_GROUP_MEMBER_ADDED(group: TYPE_GROUP, classy: Classy); | |
| 15 | FUNCTION_OVERRIDER_ADDED(holder: Function, overrider: Symbol); | |
| 16 | FUNCTION_OVERRIDEE_ADDED(holder: Function, overridee: Symbol); | |
| 17 | PROPERTY_OVERRIDER_ADDED(holder: Property, overrider: Symbol); | |
| 18 | PROPERTY_OVERRIDEE_ADDED(holder: Property, overridee: Symbol); | |
| 19 | IMPLEMENTOR_ADDED(holder: Classy, implementor: Symbol); | |
| 20 | IL_NAME_SET(symbol: Symbol); | |
| 21 | PROPERTY_ASSIGN_INHERITED(property: Property); | |
| 22 | si | |
| 23 | ||
| 24 | // Journal of the mutations one class's pull_down_super_symbols made, | |
| 25 | // so they can be undone exactly - the operation an incremental | |
| 26 | // re-resolve needs before re-running resolve-overrides for a class | |
| 27 | // against a retained symbol table. While a journal is on the stack, | |
| 28 | // the pull-down mutation sites record into it; with the stack empty | |
| 29 | // (batch import paths, reflected symbol construction) recording is a | |
| 30 | // no-op and behaviour is unchanged. | |
| 31 | // | |
| 32 | // The stack nests because pull_down_super_symbols recurses into | |
| 33 | // unresolved ancestors: each class's pull-down pushes its own journal, | |
| 34 | // so every op lands on the class it belongs to. | |
| 35 | class INHERITANCE_JOURNAL is | |
| 36 | _stack: Collections.LIST[INHERITANCE_JOURNAL] static; | |
| 37 | ||
| 38 | init() static is | |
| 39 | _stack = Collections.LIST[INHERITANCE_JOURNAL](); | |
| 40 | si | |
| 41 | ||
| 42 | current: INHERITANCE_JOURNAL? static => | |
| 43 | if _stack.count > 0 then | |
| 44 | _stack[_stack.count - 1] | |
| 45 | else | |
| 46 | null | |
| 47 | fi; | |
| 48 | ||
| 49 | push(journal: INHERITANCE_JOURNAL) static is | |
| 50 | _stack.add(journal); | |
| 51 | si | |
| 52 | ||
| 53 | pop() static is | |
| 54 | assert _stack.count > 0 else "inheritance journal stack is empty"; | |
| 55 | ||
| 56 | _stack.remove_at(_stack.count - 1); | |
| 57 | si | |
| 58 | ||
| 59 | for_class: Classy; | |
| 60 | ||
| 61 | _ops: Collections.LIST[InheritanceOp]; | |
| 62 | ||
| 63 | init(for_class: Classy) is | |
| 64 | self.for_class = for_class; | |
| 65 | ||
| 66 | _ops = Collections.LIST[InheritanceOp](); | |
| 67 | si | |
| 68 | ||
| 69 | record(op: InheritanceOp) is | |
| 70 | _ops.add(op); | |
| 71 | si | |
| 72 | ||
| 73 | // Reverse every recorded mutation, newest first. | |
| 74 | undo() is | |
| 75 | let i mut = _ops.count - 1; | |
| 76 | ||
| 77 | while i >= 0 do | |
| 78 | let op = _ops[i]; | |
| 79 | ||
| 80 | if let member_added: InheritanceOp.MEMBER_ADDED = op then | |
| 81 | member_added.scope.remove_direct(member_added.name); | |
| 82 | elif let member_replaced: InheritanceOp.MEMBER_REPLACED = op then | |
| 83 | member_replaced.scope.put_direct(member_replaced.name, member_replaced.previous); | |
| 84 | elif let group_member: InheritanceOp.GROUP_MEMBER_ADDED = op then | |
| 85 | group_member.group.remove(group_member.function); | |
| 86 | elif let type_group_member: InheritanceOp.TYPE_GROUP_MEMBER_ADDED = op then | |
| 87 | type_group_member.group.remove(type_group_member.classy); | |
| 88 | elif let function_overrider: InheritanceOp.FUNCTION_OVERRIDER_ADDED = op then | |
| 89 | function_overrider.holder.remove_overrider(function_overrider.overrider); | |
| 90 | elif let function_overridee: InheritanceOp.FUNCTION_OVERRIDEE_ADDED = op then | |
| 91 | function_overridee.holder.remove_overridee(function_overridee.overridee); | |
| 92 | elif let property_overrider: InheritanceOp.PROPERTY_OVERRIDER_ADDED = op then | |
| 93 | property_overrider.holder.remove_overrider(property_overrider.overrider); | |
| 94 | elif let property_overridee: InheritanceOp.PROPERTY_OVERRIDEE_ADDED = op then | |
| 95 | property_overridee.holder.remove_overridee(property_overridee.overridee); | |
| 96 | elif let implementor_added: InheritanceOp.IMPLEMENTOR_ADDED = op then | |
| 97 | implementor_added.holder.remove_implementor(implementor_added.implementor); | |
| 98 | elif let il_name_set: InheritanceOp.IL_NAME_SET = op then | |
| 99 | il_name_set.symbol.il_name_override = null; | |
| 100 | elif let assign_inherited: InheritanceOp.PROPERTY_ASSIGN_INHERITED = op then | |
| 101 | assign_inherited.property.assign_function = null; | |
| 102 | assign_inherited.property.is_assignable = false; | |
| 103 | fi | |
| 104 | ||
| 105 | i = i - 1; | |
| 106 | od | |
| 107 | ||
| 108 | _ops.clear(); | |
| 109 | si | |
| 110 | si | |
| 111 | si |