Back to index

texmacs  1.0.7.15
bridge_compound.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : bridge_compound.cpp
00004 * DESCRIPTION: Bridge between logical and physical long macro expansions
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "bridge.hpp"
00013 #include "drd_std.hpp"
00014 
00015 tree insert_at (tree, path, tree);
00016 tree remove_at (tree, path, int);
00017 
00018 class bridge_compound_rep: public bridge_rep {
00019 protected:
00020   bool   valid;
00021   bridge body;
00022   int    delta;
00023   tree   fun;
00024 
00025 public:
00026   bridge_compound_rep (typesetter ttt, tree st, path ip);
00027   void initialize (tree body_t, int delta, tree fun);
00028 
00029   void notify_assign (path p, tree u);
00030   void notify_insert (path p, tree u);
00031   void notify_remove (path p, int nr);
00032   bool notify_macro  (int type, string var, int level, path p, tree u);
00033   void notify_change ();
00034 
00035   bool my_typeset_will_be_complete ();
00036   void my_typeset (int desired_status);
00037 };
00038 
00039 bridge_compound_rep::bridge_compound_rep (typesetter ttt, tree st, path ip):
00040   bridge_rep (ttt, st, ip)
00041 {
00042   valid= false;
00043 }
00044 
00045 void
00046 bridge_compound_rep::initialize (tree body_t, int delta2, tree fun2) {
00047   if ((!valid) || (body->st != body_t) || (delta != delta2) || (fun != fun2)) {
00048     valid= true;
00049     if (is_nil (body)) body= make_bridge (ttt, attach_right (body_t, ip));
00050     else replace_bridge (body, attach_right (body_t, ip));
00051     delta= delta2;
00052     fun  = fun2;
00053   }
00054 }
00055 
00056 bridge
00057 bridge_compound (typesetter ttt, tree st, path ip) {
00058   return tm_new<bridge_compound_rep> (ttt, st, ip);
00059 }
00060 
00061 /******************************************************************************
00062 * Event notification
00063 ******************************************************************************/
00064 
00065 void
00066 bridge_compound_rep::notify_assign (path p, tree u) {
00067   // cout << "Assign " << p << ", " << u << " in " << st << "\n";
00068   ASSERT (!is_nil (p) || L(u) >= START_EXTENSIONS, "nil path");
00069   if (is_nil (p) || (p->item == 0) || is_nil (body)) {
00070     st= substitute (st, p, u);
00071     valid= false;
00072   }
00073   else {
00074     // bool mp_flag= is_multi_paragraph (st);
00075     if (is_func (fun, XMACRO, 2))
00076       notify_macro (MACRO_ASSIGN, fun[0]->label, -1, p, u);
00077     else if (is_applicable (fun) && (p->item < N(fun)))
00078       notify_macro (MACRO_ASSIGN, fun[p->item-delta]->label, -1, p->next, u);
00079     st= substitute (st, p, u);
00080     // if (mp_flag != is_multi_paragraph (st)) valid= false;
00081   }
00082   status= CORRUPTED;
00083 }
00084 
00085 void
00086 bridge_compound_rep::notify_insert (path p, tree u) {
00087   // cout << "Insert " << p << ", " << u << " in " << st << "\n";
00088   ASSERT (!is_nil (p), "nil path");
00089   if (is_atom (p) || is_nil (body)) bridge_rep::notify_insert (p, u);
00090   else {
00091     // bool mp_flag= is_multi_paragraph (st);
00092     if (is_func (fun, XMACRO, 2))
00093       notify_macro (MACRO_INSERT, fun[0]->label, -1, p, u);
00094     else if (is_applicable (fun) && (p->item < N(fun)))
00095       notify_macro (MACRO_INSERT, fun[p->item-delta]->label, -1, p->next, u);
00096     st= insert_at (st, p, u);
00097     // if (mp_flag != is_multi_paragraph (st)) valid= false;
00098   }
00099   status= CORRUPTED;
00100 }
00101 
00102 void
00103 bridge_compound_rep::notify_remove (path p, int nr) {
00104   // cout << "Remove " << p << ", " << nr << " in " << st << "\n";
00105   ASSERT (!is_nil (p), "nil path");
00106   if (is_atom (p) || is_nil (body)) bridge_rep::notify_remove (p, nr);
00107   else {
00108     // bool mp_flag= is_multi_paragraph (st);
00109     if (is_func (fun, XMACRO, 2))
00110       notify_macro (MACRO_REMOVE, fun[0]->label, -1, p, tree (as_string (nr)));
00111     else if (is_applicable (fun) && (p->item < N(fun)))
00112       notify_macro (MACRO_REMOVE, fun[p->item-delta]->label, -1, p->next,
00113                   tree (as_string (nr)));
00114     st= remove_at (st, p, nr);
00115     // if (mp_flag != is_multi_paragraph (st)) valid= false;
00116   }
00117   status= CORRUPTED;
00118 }
00119 
00120 bool
00121 bridge_compound_rep::notify_macro (
00122   int type, string var, int l, path p, tree u)
00123 {
00124   /*
00125   cout << "Macro argument " << var << " [action=" << type
00126        << ", level=" << l << "] " << p << ", " << u << " in " << st << "\n";
00127   */
00128 
00129   bool flag;
00130   if (valid) {
00131     int i, n=N(fun)-1, m=N(st);
00132     env->macro_arg= list<hashmap<string,tree> > (
00133       hashmap<string,tree> (UNINIT), env->macro_arg);
00134     env->macro_src= list<hashmap<string,path> > (
00135       hashmap<string,path> (path (DECORATION)), env->macro_src);
00136     if (L(fun) == XMACRO) {
00137       if (is_atomic (fun[0])) {
00138        string var= fun[0]->label;
00139        env->macro_arg->item (var)= st;
00140        env->macro_src->item (var)= ip;
00141       }
00142     }
00143     else for (i=0; i<n; i++)
00144       if (is_atomic (fun[i])) {
00145        string var= fun[i]->label;
00146        env->macro_arg->item (var)=
00147          i<m? st[i+delta]: attach_dip (tree (UNINIT), decorate_right (ip));
00148        env->macro_src->item (var)=
00149          i<m? descend (ip,i+delta): decorate_right(ip);
00150       }
00151     flag= body->notify_macro (type, var, l+1, p, u);
00152     env->macro_arg= env->macro_arg->next;
00153     env->macro_src= env->macro_src->next;
00154   }
00155   else flag= env->depends (st, var, l);
00156   if (flag) status= CORRUPTED;
00157   return flag;
00158 }
00159 
00160 void
00161 bridge_compound_rep::notify_change () {
00162   status= CORRUPTED;
00163   if (!is_nil (body)) body->notify_change ();
00164 }
00165 
00166 /******************************************************************************
00167 * Typesetting
00168 ******************************************************************************/
00169 
00170 bool
00171 bridge_compound_rep::my_typeset_will_be_complete () {
00172   return !valid;
00173 }
00174 
00175 void
00176 bridge_compound_rep::my_typeset (int desired_status) {
00177   int d; tree f;
00178   if (L(st) == COMPOUND) {
00179     d= 1;
00180     f= st[0];
00181     if (is_compound (f)) f= env->exec (f);
00182     if (is_atomic (f)) {
00183       string var= f->label;
00184       if (env->provides (var)) f= env->read (var);
00185       else f= tree (ERROR, st);
00186     }
00187   }
00188   else {
00189     string var= as_string (L(st));
00190     if (env->provides (var)) f= env->read (var);
00191     else f= tree (ERROR, st);
00192     d= 0;
00193   }
00194 
00195   if (is_applicable (f)) {
00196     int i, n=N(f)-1, m=N(st)-d;
00197     env->macro_arg= list<hashmap<string,tree> > (
00198       hashmap<string,tree> (UNINIT), env->macro_arg);
00199     env->macro_src= list<hashmap<string,path> > (
00200       hashmap<string,path> (path (DECORATION)), env->macro_src);
00201     if (L(f) == XMACRO) {
00202       if (is_atomic (f[0])) {
00203        string var= f[0]->label;
00204        env->macro_arg->item (var)= st;
00205        env->macro_src->item (var)= ip;
00206       }
00207     }
00208     else for (i=0; i<n; i++)
00209       if (is_atomic (f[i])) {
00210        string var= f[i]->label;
00211        env->macro_arg->item (var)=
00212          i<m? st[i+d]: attach_dip (tree (UNINIT), decorate_right (ip));
00213        env->macro_src->item (var)=
00214          i<m? descend (ip,i+d): decorate_right(ip);
00215       }
00216     initialize (f[n], d, f);
00217     // /*IF_NON_CHILD_ENFORCING(st)*/ ttt->insert_marker (st, ip);
00218     if (!the_drd->is_child_enforcing (st))
00219       ttt->insert_marker (st, ip);
00220     body->typeset (desired_status);
00221     env->macro_arg= env->macro_arg->next;
00222     env->macro_src= env->macro_src->next;
00223   }
00224   else {
00225     initialize (f, d, f);
00227     if (!the_drd->is_child_enforcing (st))
00228       ttt->insert_marker (st, ip);
00229     body->typeset (desired_status);
00230   }
00231 }