PageRenderTime 55ms CodeModel.GetById 31ms app.highlight 20ms RepoModel.GetById 0ms app.codeStats 1ms

/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}