1 
2 /******************************************************************************
3 * MODULE     : observer.cpp
4 * DESCRIPTION: Observers of trees
5 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11 
12 #include "modification.hpp"
13 #include "analyze.hpp"
14 #include "hashmap.hpp"
15 #include "blackbox.hpp"
16 
17 #define DETACHED (-5)
18 
19 observer nil_observer;
20 extern tree the_et;
21 extern bool packrat_invalid_colors;
22 
23 /******************************************************************************
24 * Debugging facilities
25 ******************************************************************************/
26 
27 static void
consistency_check(tree t,path ip)28 consistency_check (tree t, path ip) {
29   if (obtain_ip (t) != ip)
30     cout << "Wrong ip] " << t << " " << obtain_ip (t)
31 	 << " instead of " << ip << "\n";
32   if (is_compound (t)) {
33     int i, n= N(t);
34     for (i=0; i<n; i++) {
35       //if (!strong_equal (ip, obtain_ip (t[i])->next))
36       if (obtain_ip (t) != obtain_ip (t[i])->next)
37 	cout << "Bad node] " << t << " " << obtain_ip (t) << " #" << i << "\n";
38       consistency_check (t[i], path (i, ip));
39     }
40   }
41 }
42 
43 void
consistency_check()44 consistency_check () {
45   consistency_check (the_et, path ());
46   cout << HRULE;
47 }
48 
49 void
stretched_print(tree t,bool ips,int indent)50 stretched_print (tree t, bool ips, int indent) {
51   int i;
52   for (i=0; i<indent; i++) cout << "  ";
53   if (is_atomic (t)) {
54     cout << raw_quote (t->label);
55     if (ips) cout << " -- " << obtain_ip (t);
56     cout << "\n";
57   }
58   else {
59     cout << as_string (L(t));
60     if (ips) cout << " -- " << obtain_ip (t);
61     cout << "\n";
62     for (i=0; i<N(t); i++)
63       stretched_print (t[i], ips, indent+1);
64   }
65 }
66 
67 tm_ostream&
operator <<(tm_ostream & out,observer o)68 operator << (tm_ostream& out, observer o) {
69   out << "<observer";
70   if (is_nil (o)) out << " null";
71   else o->print (out);
72   out << ">";
73   return out;
74 }
75 
76 /******************************************************************************
77 * Routines for modifying trees
78 *******************************************************************************
79 * 1) The "inserting modifications" (insert, split and insert_node) invoke
80 *    the observers call-back routines after the actual modification and
81 *    "assigning and deleting modifications" (assign, remove, join,
82 *    assign_node and remove_node) before the actual modification.
83 *    set_cursor does not make any modifications in the tree
84 * 2) The split and join modifications pass the joined tree
85 *    at position pos as an additional argument to the call-back routines.
86 * 3) They also admit variant call back routines for the split/join nodes.
87 ******************************************************************************/
88 
89 static void
simplify(observer & obs)90 simplify (observer& obs) {
91   if (is_nil (obs)) return;
92   observer& o1= obs->get_child (0);
93   observer& o2= obs->get_child (1);
94   if (!is_nil (o1) || !is_nil (o2)) {
95     simplify (o1);
96     simplify (o2);
97     obs= list_observer (o1, o2);
98   }
99 }
100 
101 static void
detach(tree & ref,tree closest,bool right)102 detach (tree& ref, tree closest, bool right) {
103   if (!is_nil (ref->obs)) {
104     ref->obs->notify_detach (ref, closest, right);
105     simplify (ref->obs);
106   }
107   if (is_compound (ref)) {
108     int i, n= N(ref);
109     for (i=0; i<n; i++)
110       detach (ref[i], closest, right);
111   }
112 }
113 
114 void
raw_assign(tree & ref,tree t)115 raw_assign (tree& ref, tree t) {
116   // cout << "Assign " << ref << " := " << t << "\n";
117   modification mod= mod_assign (path (), t);
118   if (!is_nil (ref->obs)) {
119     ref->obs->announce (ref, mod);
120     ref->obs->notify_assign (ref, t);
121     simplify (ref->obs);
122   }
123   if (is_compound (ref)) {
124     int i, n= N(ref), mid= (n+1)>>1;
125     for (i=0; i<n; i++)
126       detach (ref[i], t, i >= mid);
127   }
128   ref= t;
129   if (!is_nil (ref->obs)) ref->obs->done (ref, mod);
130   // stretched_print (ref, true, 1);
131   // consistency_check ();
132 }
133 
134 void
raw_insert(tree & ref,int pos,tree t)135 raw_insert (tree& ref, int pos, tree t) {
136   // cout << "Insert " << ref << " += " << t << " at " << pos << "\n";
137   modification mod= mod_insert (path (), pos, t);
138   if (!is_nil (ref->obs))
139     ref->obs->announce (ref, mod);
140   if (is_atomic (ref) && is_atomic (t))
141     ref->label= ref->label (0, pos) *t->label* ref->label (pos, N(ref->label));
142   else {
143     int i, n= N(ref), nr= N(t);
144     AR(ref)->resize (n+nr);
145     for (i=n-1; i>=pos; i--)
146       ref[i+nr]= ref[i];
147     for (i=0; i<nr; i++)
148       ref[pos+i]= t[i];
149   }
150   if (!is_nil (ref->obs)) {
151     ref->obs->notify_insert (ref, pos, is_atomic (t)? N(t->label): N(t));
152     simplify (ref->obs);
153   }
154   if (!is_nil (ref->obs)) ref->obs->done (ref, mod);
155   // stretched_print (ref, true, 1);
156   // consistency_check ();
157 }
158 
159 void
raw_remove(tree & ref,int pos,int nr)160 raw_remove (tree& ref, int pos, int nr) {
161   // cout << "Remove " << ref << " -= " << nr << " at " << pos << "\n";
162   modification mod= mod_remove (path (), pos, nr);
163   if (nr == 0) return;
164   if (!is_nil (ref->obs)) {
165     ref->obs->announce (ref, mod);
166     ref->obs->notify_remove (ref, pos, nr);
167     simplify (ref->obs);
168   }
169   if (is_compound (ref)) {
170     int i, n= N(ref), end= pos+nr, mid= (pos+end+1) >> 1;
171     for (i=pos; i<mid; i++)
172       if (pos == 0) detach (ref[i], ref, false);
173       else detach (ref[i], ref[pos-1], true);
174     for (; i<end; i++)
175       if (end == n) detach (ref[i], ref, true);
176       else detach (ref[i], ref[pos+nr], false);
177   }
178 
179   if (is_atomic (ref))
180     ref->label= ref->label (0, pos) * ref->label (pos+nr, N(ref->label));
181   else {
182     int i, n= N(ref)-nr;
183     for (i=pos; i<n; i++)
184       ref[i]= ref[i+nr];
185     AR(ref)->resize (n);
186   }
187   if (!is_nil (ref->obs)) ref->obs->done (ref, mod);
188   // stretched_print (ref, true, 1);
189   // consistency_check ();
190 }
191 
192 void
raw_split(tree & ref,int pos,int at)193 raw_split (tree& ref, int pos, int at) {
194   // cout << "Split " << ref << " at " << pos << ", " << at << "\n";
195   modification mod= mod_split (path (), pos, at);
196   if (!is_nil (ref->obs))
197     ref->obs->announce (ref, mod);
198   tree t= ref[pos], t1, t2;
199   if (is_atomic (ref[pos])) {
200     t1= ref[pos]->label (0, at);
201     t2= ref[pos]->label (at, N(ref[pos]->label));
202   }
203   else {
204     t1= ref[pos] (0, at);
205     t2= ref[pos] (at, N(ref[pos]));
206   }
207   int i, n= N(ref);
208   AR(ref)->resize (n+1);
209   for (i=n; i>(pos+1); i--)
210     ref[i]= ref[i-1];
211   ref[pos  ]= t1;
212   ref[pos+1]= t2;
213 
214   if (!is_nil (ref->obs)) {
215     ref->obs->notify_split (ref, pos, t);
216     simplify (ref->obs);
217   }
218   if (!is_nil (t->obs)) {
219     t->obs->notify_var_split (t, t1, t2);
220     simplify (t->obs);
221   }
222   if (!is_nil (ref->obs)) ref->obs->done (ref, mod);
223   // stretched_print (ref, true, 1);
224   // consistency_check ();
225 }
226 
227 void
raw_join(tree & ref,int pos)228 raw_join (tree& ref, int pos) {
229   // cout << "Join " << ref << " at " << pos << "\n";
230   // the following code is added for security
231   if (is_atomic (ref[pos]) && (!is_atomic (ref[pos+1])))
232     insert_node (ref[pos], 0, tree (L(ref[pos+1])));
233   if (is_atomic (ref[pos+1]) && (!is_atomic (ref[pos])))
234     insert_node (ref[pos+1], 0, tree (L(ref[pos])));
235   // end security code
236 
237   modification mod= mod_join (path (), pos);
238   if (!is_nil (ref->obs)) ref->obs->announce (ref, mod);
239   tree t1= ref[pos], t2= ref[pos+1], t;
240   int offset= is_atomic (ref)? N(t1->label): N(t1);
241   if (is_atomic (t1) && is_atomic (t2)) t= t1->label * t2->label;
242   else t= t1 * t2;
243   if (!is_nil (ref->obs)) ref->obs->notify_join (ref, pos, t);
244   if (!is_nil (t1->obs)) {
245     t1->obs->notify_var_join (t1, t, 0);
246     simplify (t1->obs);
247   }
248   if (!is_nil (t2->obs)) {
249     t2->obs->notify_var_join (t2, t, offset);
250     simplify (t2->obs);
251   }
252   ref[pos]= t;
253 
254   int i, n= N(ref)-1;
255   for (i=pos+1; i<n; i++)
256     ref[i]= ref[i+1];
257   AR(ref)->resize (n);
258   if (!is_nil (ref->obs)) ref->obs->done (ref, mod);
259   // stretched_print (ref, true, 1);
260   // consistency_check ();
261 }
262 
263 void
raw_assign_node(tree & ref,tree_label op)264 raw_assign_node (tree& ref, tree_label op) {
265   // cout << "Assign node " << ref << " : " << tree (op) << "\n";
266   modification mod= mod_assign_node (path (), op);
267   if (!is_nil (ref->obs)) {
268     ref->obs->announce (ref, mod);
269     ref->obs->notify_assign_node (ref, op);
270     simplify (ref->obs);
271   }
272   LR (ref)= op;
273   if (!is_nil (ref->obs)) ref->obs->done (ref, mod);
274   // stretched_print (ref, true, 1);
275   // consistency_check ();
276 }
277 
278 void
raw_insert_node(tree & ref,int pos,tree t)279 raw_insert_node (tree& ref, int pos, tree t) {
280   // cout << "Insert node " << ref << " : " << t << " at " << pos << "\n";
281   modification mod= mod_insert_node (path (), pos, t);
282   if (!is_nil (ref->obs)) ref->obs->announce (ref, mod);
283   int i, n= N(t);
284   tree r (t, n+1);
285   for (i=0; i<pos; i++) r[i]= t[i];
286   r[pos]= ref;
287   for (i=pos; i<n; i++) r[i+1]= t[i];
288   ref= r;
289   if (!is_nil (ref[pos]->obs)) {
290     ref[pos]->obs->notify_insert_node (ref, pos);
291     simplify (ref[pos]->obs);
292   }
293   if (!is_nil (ref->obs)) ref->obs->done (ref, mod);
294   // stretched_print (ref, true, 1);
295   // consistency_check ();
296 }
297 
298 void
raw_remove_node(tree & ref,int pos)299 raw_remove_node (tree& ref, int pos) {
300   // cout << "Remove node " << ref << " : " << pos << "\n";
301   modification mod= mod_remove_node (path (), pos);
302   if (!is_nil (ref->obs)) {
303     ref->obs->announce (ref, mod);
304     ref->obs->notify_remove_node (ref, pos);
305     simplify (ref->obs);
306   }
307   for (int i=0; i<N(ref); i++)
308     if (i < pos) detach (ref[i], ref[pos], false);
309     else if (i > pos) detach (ref[i], ref[pos], true);
310   ref= ref[pos];
311   if (!is_nil (ref->obs)) ref->obs->done (ref, mod);
312   // stretched_print (ref, true, 1);
313   // consistency_check ();
314 }
315 
316 void
raw_set_cursor(tree & ref,int pos,tree data)317 raw_set_cursor (tree& ref, int pos, tree data) {
318   // cout << "Set cursor " << ref << " : " << pos << ", " << data << "\n";
319   modification mod= mod_set_cursor (path (), pos, data);
320   if (!is_nil (ref->obs)) {
321     ref->obs->announce (ref, mod);
322     ref->obs->notify_set_cursor (ref, pos, data);
323     simplify (ref->obs);
324   }
325   if (!is_nil (ref->obs)) ref->obs->done (ref, mod);
326   // stretched_print (ref, true, 1);
327   // consistency_check ();
328 }
329 
330 void
raw_apply(tree & t,modification mod)331 raw_apply (tree& t, modification mod) {
332   ASSERT (is_applicable (t, mod), "invalid modification");
333   switch (mod->k) {
334   case MOD_ASSIGN:
335     raw_assign (subtree (t, root (mod)), mod->t);
336     break;
337   case MOD_INSERT:
338     raw_insert (subtree (t, root (mod)), index (mod), mod->t);
339     break;
340   case MOD_REMOVE:
341     raw_remove (subtree (t, root (mod)), index (mod), argument (mod));
342     break;
343   case MOD_SPLIT:
344     raw_split (subtree (t, root (mod)), index (mod), argument (mod));
345     break;
346   case MOD_JOIN:
347     raw_join (subtree (t, root (mod)), index (mod));
348     break;
349   case MOD_ASSIGN_NODE:
350     raw_assign_node (subtree (t, root (mod)), L (mod));
351     break;
352   case MOD_INSERT_NODE:
353     raw_insert_node (subtree (t, root (mod)), argument (mod), mod->t);
354     break;
355   case MOD_REMOVE_NODE:
356     raw_remove_node (subtree (t, root (mod)), index (mod));
357     break;
358   case MOD_SET_CURSOR:
359     raw_set_cursor (subtree (t, root (mod)), index (mod), mod->t);
360     break;
361   }
362   packrat_invalid_colors= true;
363 }
364 
365 /******************************************************************************
366 * Wrappers which take into account mirroring
367 ******************************************************************************/
368 
369 bool busy_modifying= false;
370 bool busy_versioning= false;
371 static bool is_busy= false;
372 static list<path> busy_paths;
373 static list<modification> upcoming;
374 
375 bool
busy_path(path p)376 busy_path (path p) {
377   for (list<path> l= busy_paths; !is_nil (l); l= l->next)
378     if (l->item <= p) return true;
379   return false;
380 }
381 
382 bool
busy_tree(tree & ref)383 busy_tree (tree& ref) {
384   path ip= obtain_ip (ref);
385   if (ip_attached (ip)) return busy_path (reverse (ip));
386   else return true;
387 }
388 
389 void
apply(tree & ref,modification mod)390 apply (tree& ref, modification mod) {
391   if (!is_applicable (ref, mod)) {
392     failed_error << "mod= " << mod << "\n";
393     failed_error << "ref= " << ref << "\n";
394     FAILED ("invalid modification");
395   }
396   path ip= obtain_ip (ref);
397   path rp= reverse (ip);
398   path p = rp * root (mod);
399   if (busy_modifying) raw_apply (ref, mod);
400   else if (is_busy) {
401     if (ip_attached (ip) && !busy_path (p)) {
402       //cout << "Postpone " << (reverse (ip) * mod) << "\n";
403       busy_paths= busy_paths * p;
404       upcoming  = upcoming * (reverse (ip) * mod);
405     }
406   }
407   else {
408     if (!ip_attached (ip)) raw_apply (ref, mod);
409     else {
410       is_busy= true;
411       busy_paths= list<path> (p);
412       upcoming  = list<modification> (reverse (ip) * mod);
413       while (!is_nil (upcoming)) {
414 	//cout << "Handle " << upcoming->item << "\n";
415 	raw_apply (the_et, upcoming->item);
416 	//cout << "Done " << upcoming->item << "\n";
417 	upcoming= upcoming->next;
418       }
419       busy_paths= list<path> ();
420       is_busy= false;
421       if (has_subtree (the_et, rp))
422 	ref= subtree (the_et, rp);
423     }
424   }
425 }
426 
427 void
assign(tree & ref,tree t)428 assign (tree& ref, tree t) {
429   apply (ref, mod_assign (path (), t));
430 }
431 
432 void
insert(tree & ref,int pos,tree t)433 insert (tree& ref, int pos, tree t) {
434   apply (ref, mod_insert (path (), pos, t));
435 }
436 
437 void
remove(tree & ref,int pos,int nr)438 remove (tree& ref, int pos, int nr) {
439   apply (ref, mod_remove (path (), pos, nr));
440 }
441 
442 void
split(tree & ref,int pos,int at)443 split (tree& ref, int pos, int at) {
444   apply (ref, mod_split (path (), pos, at));
445 }
446 
447 void
join(tree & ref,int pos)448 join (tree& ref, int pos) {
449   apply (ref, mod_join (path (), pos));
450 }
451 
452 void
assign_node(tree & ref,tree_label op)453 assign_node (tree& ref, tree_label op) {
454   apply (ref, mod_assign_node (path (), op));
455 }
456 
457 void
insert_node(tree & ref,int pos,tree t)458 insert_node (tree& ref, int pos, tree t) {
459   apply (ref, mod_insert_node (path (), pos, t));
460 }
461 
462 void
remove_node(tree & ref,int pos)463 remove_node (tree& ref, int pos) {
464   apply (ref, mod_remove_node (path (), pos));
465 }
466 
467 void
set_cursor(tree & ref,int pos,tree data)468 set_cursor (tree& ref, int pos, tree data) {
469   apply (ref, mod_set_cursor (path (), pos, data));
470 }
471 
472 void
touch(tree & ref)473 touch (tree& ref) {
474   //cout << "Touch " << ref << "\n";
475   if (!is_nil (ref->obs))
476     ref->obs->touched (ref, path ());
477 }
478 
479 /******************************************************************************
480 * Wrappers for trees given by a path
481 ******************************************************************************/
482 
483 void
assign(path p,tree t)484 assign (path p, tree t) {
485   assign (subtree (the_et, p), t);
486 }
487 
488 void
insert(path p,tree ins)489 insert (path p, tree ins) {
490   insert (subtree (the_et, path_up (p)), last_item (p), ins);
491 }
492 
493 void
remove(path p,int nr)494 remove (path p, int nr) {
495   remove (subtree (the_et, path_up (p)), last_item (p), nr);
496 }
497 
498 void
split(path p)499 split (path p) {
500   tree& st= subtree (the_et, path_up (path_up (p)));
501   int   l1= last_item (path_up (p));
502   int   l2= last_item (p);
503   split (st, l1, l2);
504 }
505 
506 void
join(path p)507 join (path p) {
508   join (subtree (the_et, path_up (p)), last_item (p));
509 }
510 
511 void
assign_node(path p,tree_label op)512 assign_node (path p, tree_label op) {
513   assign_node (subtree (the_et, p), op);
514 }
515 
516 void
insert_node(path p,tree ins)517 insert_node (path p, tree ins) {
518   insert_node (subtree (the_et, path_up (p)), last_item (p), ins);
519 }
520 
521 void
remove_node(path p)522 remove_node (path p) {
523   remove_node (subtree (the_et, path_up (p)), last_item (p));
524 }
525 
526 void
set_cursor(path p,tree data)527 set_cursor (path p, tree data) {
528   if (is_inside (the_et, p))
529     set_cursor (subtree (the_et, path_up (p)), last_item (p), data);
530   else
531     cout << "TeXmacs] warning: invalid cursor position " << p << "\n";
532 }
533 
534 void
touch(path p)535 touch (path p) {
536   touch (subtree (the_et, p));
537 }
538 
539 /******************************************************************************
540 * Default virtual routines
541 ******************************************************************************/
542 
543 void
announce(tree & ref,modification mod)544 observer_rep::announce (tree& ref, modification mod) {
545   // cout << "Modify: " << mod << "\n";
546   switch (mod->k) {
547   case MOD_ASSIGN:
548     announce_assign (ref, mod->p, mod->t);
549     break;
550   case MOD_INSERT:
551     announce_insert (ref, mod->p, mod->t);
552     break;
553   case MOD_REMOVE:
554     announce_remove (ref, path_up (mod->p), last_item (mod->p));
555     break;
556   case MOD_SPLIT:
557     announce_split (ref, mod->p);
558     break;
559   case MOD_JOIN:
560     announce_join (ref, mod->p);
561     break;
562   case MOD_ASSIGN_NODE:
563     announce_assign_node (ref, mod->p, L(mod->t));
564     break;
565   case MOD_INSERT_NODE:
566     announce_insert_node (ref, mod->p, mod->t);
567     break;
568   case MOD_REMOVE_NODE:
569     announce_remove_node (ref, mod->p);
570     break;
571   case MOD_SET_CURSOR:
572     announce_set_cursor (ref, mod->p, mod->t);
573     break;
574   }
575 }
576 
577 void
done(tree & ref,modification mod)578 observer_rep::done (tree& ref, modification mod) {
579   (void) ref; (void) mod;
580 }
581 
582 void
touched(tree & ref,path p)583 observer_rep::touched (tree& ref, path p) {
584   (void) ref; (void) p;
585 }
586 
587 void
announce_assign(tree & ref,path p,tree t)588 observer_rep::announce_assign (tree& ref, path p, tree t) {
589   (void) ref; (void) p; (void) t;
590 }
591 
592 void
announce_insert(tree & ref,path p,tree ins)593 observer_rep::announce_insert (tree& ref, path p, tree ins) {
594   (void) ref; (void) p; (void) ins;
595 }
596 
597 void
announce_remove(tree & ref,path p,int nr)598 observer_rep::announce_remove (tree& ref, path p, int nr) {
599   (void) ref; (void) p; (void) nr;
600 }
601 
602 void
announce_split(tree & ref,path p)603 observer_rep::announce_split (tree& ref, path p) {
604   (void) ref; (void) p;
605 }
606 
607 void
announce_join(tree & ref,path p)608 observer_rep::announce_join (tree& ref, path p) {
609   (void) ref; (void) p;
610 }
611 
612 void
announce_assign_node(tree & ref,path p,tree_label op)613 observer_rep::announce_assign_node (tree& ref, path p, tree_label op) {
614   (void) ref; (void) p; (void) op;
615 }
616 
617 void
announce_insert_node(tree & ref,path p,tree ins)618 observer_rep::announce_insert_node (tree& ref, path p, tree ins) {
619   (void) ref; (void) p; (void) ins;
620 }
621 
622 void
announce_remove_node(tree & ref,path p)623 observer_rep::announce_remove_node (tree& ref, path p) {
624   (void) ref; (void) p;
625 }
626 
627 void
announce_set_cursor(tree & ref,path p,tree data)628 observer_rep::announce_set_cursor (tree& ref, path p, tree data) {
629   (void) ref; (void) p; (void) data;
630 }
631 
632 void
notify_assign(tree & ref,tree t)633 observer_rep::notify_assign (tree& ref, tree t) {
634   (void) ref; (void) t;
635 }
636 
637 void
notify_insert(tree & ref,int pos,int nr)638 observer_rep::notify_insert (tree& ref, int pos, int nr) {
639   (void) ref; (void) pos; (void) nr;
640 }
641 
642 void
notify_remove(tree & ref,int pos,int nr)643 observer_rep::notify_remove (tree& ref, int pos, int nr) {
644   (void) ref; (void) pos; (void) nr;
645 }
646 
647 void
notify_split(tree & ref,int pos,tree prev)648 observer_rep::notify_split (tree& ref, int pos, tree prev) {
649   (void) ref; (void) pos; (void) prev;
650 }
651 
652 void
notify_var_split(tree & ref,tree t1,tree t2)653 observer_rep::notify_var_split (tree& ref, tree t1, tree t2) {
654   (void) ref; (void) t1; (void) t2;
655 }
656 
657 void
notify_join(tree & ref,int pos,tree next)658 observer_rep::notify_join (tree& ref, int pos, tree next) {
659   (void) ref; (void) pos; (void) next;
660 }
661 
662 void
notify_var_join(tree & ref,tree t,int offset)663 observer_rep::notify_var_join (tree& ref, tree t, int offset) {
664   (void) ref; (void) t; (void) offset;
665 }
666 
667 void
notify_assign_node(tree & ref,tree_label op)668 observer_rep::notify_assign_node (tree& ref, tree_label op) {
669   (void) ref; (void) op;
670 }
671 
672 void
notify_insert_node(tree & ref,int pos)673 observer_rep::notify_insert_node (tree& ref, int pos) {
674   (void) ref; (void) pos;
675 }
676 
677 void
notify_remove_node(tree & ref,int pos)678 observer_rep::notify_remove_node (tree& ref, int pos) {
679   (void) ref; (void) pos;
680 }
681 
682 void
notify_set_cursor(tree & ref,int pos,tree data)683 observer_rep::notify_set_cursor (tree& ref, int pos, tree data) {
684   (void) ref; (void) pos; (void) data;
685 }
686 
687 void
notify_detach(tree & ref,tree closest,bool right)688 observer_rep::notify_detach (tree& ref, tree closest, bool right) {
689   (void) ref; (void) closest; (void) right;
690 }
691 
692 bool
get_ip(path & ip)693 observer_rep::get_ip (path& ip) {
694   (void) ip;
695   return false;
696 }
697 
698 bool
set_ip(path ip)699 observer_rep::set_ip (path ip) {
700   (void) ip;
701   return false;
702 }
703 
704 bool
get_position(tree & t,int & index)705 observer_rep::get_position (tree& t, int& index) {
706   (void) t; (void) index;
707   return false;
708 }
709 
710 bool
set_position(tree t,int index)711 observer_rep::set_position (tree t, int index) {
712   (void) t; (void) index;
713   return false;
714 }
715 
716 observer&
get_child(int which)717 observer_rep::get_child (int which) {
718   (void) which;
719   return nil_observer;
720 }
721 
722 list<observer>
get_tree_pointers()723 observer_rep::get_tree_pointers () {
724   return list<observer> ();
725 }
726 
727 bool
get_tree(tree & t)728 observer_rep::get_tree (tree& t) {
729   (void) t;
730   return false;
731 }
732 
733 bool
get_contents(int kind,blackbox & bb)734 observer_rep::get_contents (int kind, blackbox& bb) {
735   (void) kind; (void) bb;
736   return false;
737 }
738 
739 bool
set_highlight(int lan,int col,int start,int end)740 observer_rep::set_highlight (int lan, int col, int start, int end) {
741   (void) col; (void) start; (void) end; (void) lan;
742   return false;
743 }
744 
745 bool
get_highlight(int lan,array<int> & cols)746 observer_rep::get_highlight (int lan, array<int>& cols) {
747   (void) lan; (void) cols; return false;
748 }
749