/TeXmacs-1.0.7.11-src/src/Data/Observers/ip_observer.cpp
C++ | 248 lines | 173 code | 34 blank | 41 comment | 32 complexity | ecf9e7f08b545f588198f9ae46e84d68 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
1
2/******************************************************************************
3* MODULE : ip_observer.cpp
4* DESCRIPTION: Persistently attach inverse paths to trees
5* COPYRIGHT : (C) 1999 Joris van der Hoeven
6*******************************************************************************
7* An inverse path observer maintains the inverse path of the position
8* of the corresponding tree with respect to the global meta-tree.
9*******************************************************************************
10* This software falls under the GNU general public license version 3 or later.
11* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
12* in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
13******************************************************************************/
14
15#include "modification.hpp"
16
17#define DETACHED (-5)
18extern tree the_et;
19
20/******************************************************************************
21* Definition of the ip_observer_rep class
22******************************************************************************/
23
24class ip_observer_rep: public observer_rep {
25 path ip;
26public:
27 ip_observer_rep (path ip2): ip (ip2) {}
28 int get_type () { return OBSERVER_IP; }
29 tm_ostream& print (tm_ostream& out) { return out << " " << ip; }
30
31 void announce (tree& ref, modification mod);
32 void done (tree& ref, modification mod);
33 void touched (tree& ref, path p);
34
35 void notify_assign (tree& ref, tree t);
36 void notify_insert (tree& ref, int pos, int nr);
37 void notify_remove (tree& ref, int pos, int nr);
38 void notify_split (tree& ref, int pos, tree prev);
39 void notify_var_split (tree& ref, tree t1, tree t2);
40 void notify_join (tree& ref, int pos, tree next);
41 void notify_var_join (tree& ref, tree t, int offset);
42 void notify_assign_node (tree& ref, tree_label op);
43 void notify_insert_node (tree& ref, int pos);
44 void notify_remove_node (tree& ref, int pos);
45 void notify_detach (tree& ref, tree closest, bool right);
46
47 bool get_ip (path& ip);
48 bool set_ip (path ip);
49};
50
51/******************************************************************************
52* Call back routines for announcements
53******************************************************************************/
54
55bool
56has_parent (path ip) {
57 return !is_nil (ip) && last_item (ip) != DETACHED;
58}
59
60void
61ip_observer_rep::announce (tree& ref, modification mod) {
62 (void) ref;
63 //cout << "Announce " << ip << ", " << p << "\n";
64 if (!has_parent (ip)) return;
65 tree& parent (subtree (the_et, reverse (ip->next)));
66 parent->obs->announce (parent, ip->item * mod);
67}
68
69void
70ip_observer_rep::done (tree& ref, modification mod) {
71 (void) ref;
72 //cout << "Done " << ip << ", " << p << "\n";
73 if (!has_parent (ip)) return;
74 tree& parent (subtree (the_et, reverse (ip->next)));
75 parent->obs->done (parent, ip->item * mod);
76}
77
78void
79ip_observer_rep::touched (tree& ref, path p) {
80 (void) ref;
81 //cout << "Touched " << ip << ", " << p << "\n";
82 if (!has_parent (ip)) return;
83 tree& parent (subtree (the_et, reverse (ip->next)));
84 parent->obs->touched (parent, path (ip->item, p));
85}
86
87/******************************************************************************
88* Call back routines for modifications
89******************************************************************************/
90
91void
92ip_observer_rep::notify_assign (tree& ref, tree t) {
93 // cout << "Notify assign " << ref << ", " << t << "\n";
94 path temp_ip= obtain_ip (ref);
95 temp_ip= path (temp_ip->item, temp_ip->next); // prevents overriding temp_ip
96 detach_ip (ref);
97 attach_ip (t, temp_ip);
98}
99
100void
101ip_observer_rep::notify_insert (tree& ref, int pos, int nr) {
102 // cout << "Notify insert " << ref << ", " << pos << ", " << nr << "\n";
103 (void) nr;
104 if (is_compound (ref)) {
105 int i, n= N(ref);
106 for (i=pos; i<n; i++)
107 attach_ip (ref[i], path (i, ip));
108 }
109}
110
111void
112ip_observer_rep::notify_remove (tree& ref, int pos, int nr) {
113 // cout << "Notify remove " << ref << ", " << pos << ", " << nr << "\n";
114 (void) nr;
115 if (is_compound (ref)) {
116 int i, n= N(ref);
117 for (i=pos; i<(pos+nr); i++)
118 detach_ip (ref[i]);
119 for (; i<n; i++)
120 attach_ip (ref[i], path (i-nr, ip));
121 }
122}
123
124void
125ip_observer_rep::notify_split (tree& ref, int pos, tree prev) {
126 // cout << "Notify split " << ref << ", " << pos << ", " << prev << "\n";
127 int i, n= N(ref);
128 detach_ip (prev);
129 for (i=pos; i<n; i++)
130 attach_ip (ref[i], path (i, ip));
131}
132
133void
134ip_observer_rep::notify_var_split (tree& ref, tree t1, tree t2) {
135 (void) ref; (void) t1; (void) t2;
136}
137
138void
139ip_observer_rep::notify_join (tree& ref, int pos, tree next) {
140 // cout << "Notify join " << ref << ", " << pos << ", " << next << "\n";
141 int i, n= N(ref);
142 detach_ip (ref[pos]);
143 detach_ip (ref[pos+1]);
144 for (i=pos+2; i<n; i++)
145 attach_ip (ref[i], path (i-1, ip));
146 attach_ip (next, path (pos, ip));
147}
148
149void
150ip_observer_rep::notify_var_join (tree& ref, tree t, int offset) {
151 (void) ref; (void) t; (void) offset;
152}
153
154void
155ip_observer_rep::notify_assign_node (tree& ref, tree_label op) {
156 // cout << "Notify assign node " << ref << ", " << as_string (op) << "\n";
157 (void) ref; (void) op;
158}
159
160void
161ip_observer_rep::notify_insert_node (tree& ref, int pos) {
162 // cout << "Notify insert node " << ref << ", " << pos << "\n";
163 ip= path (pos, ip);
164 attach_ip (ref[pos], ip); // updates children's ips
165 attach_ip (ref, ip->next);
166}
167
168void
169ip_observer_rep::notify_remove_node (tree& ref, int pos) {
170 // cout << "Notify remove node " << ref << ", " << pos << "\n";
171 for (int i=0; i<N(ref); i++)
172 if (i != pos)
173 detach_ip (ref[i]);
174 if ((!is_nil (ip)) && (ip->item>=0)) attach_ip (ref[pos], ip);
175 else detach_ip (ref[pos]);
176 ip= DETACHED; // detach_ip (ref);
177}
178
179void
180ip_observer_rep::notify_detach (tree& ref, tree closest, bool right) {
181 (void) ref; (void) closest; (void) right;
182}
183
184/******************************************************************************
185* Setting and getting inverse paths
186******************************************************************************/
187
188bool
189ip_observer_rep::get_ip (path& ip2) {
190 ip2= ip;
191 return true;
192}
193
194bool
195ip_observer_rep::set_ip (path ip2) {
196 if (is_nil (ip) || is_nil (ip2))
197 FAILED ("cannot alter global root");
198 ip->item= ip2->item;
199 ip->next= ip2->next;
200 return true;
201}
202
203void
204attach_ip (tree& ref, path ip) {
205 // cout << "Set ip of " << ref << " to " << ip << "\n";
206 if (is_nil (ref->obs) || !ref->obs->set_ip (ip)) {
207 // cout << "Create ip observer " << ip << " for " << ref << "\n";
208 ref->obs= list_observer (ip_observer (ip), ref->obs);
209 }
210 if (is_compound (ref)) {
211 int i, n= N(ref);
212 for (i=0; i<n; i++) {
213 path old_ip= obtain_ip (ref[i]);
214 if ((old_ip->item != i) || (!strong_equal (old_ip->next, ip))) {
215 attach_ip (ref[i], path (i, ip));
216 }
217 }
218 }
219}
220
221void
222detach_ip (tree& ref) {
223 // cout << "Detach ip of " << ref << "\n";
224 if (!is_nil (ref->obs))
225 (void) ref->obs->set_ip (DETACHED);
226}
227
228path
229obtain_ip (tree& ref) {
230 path ip;
231 if (is_nil (ref->obs)) return DETACHED;
232 if (!ref->obs->get_ip (ip)) return DETACHED;
233 return ip;
234}
235
236bool
237ip_attached (path ip) {
238 return is_nil (ip) || last_item (ip) != DETACHED;
239}
240
241/******************************************************************************
242* Setting and getting inverse paths
243******************************************************************************/
244
245observer
246ip_observer (path ip) {
247 return tm_new<ip_observer_rep> (ip);
248}