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