Back to index

texmacs  1.0.7.15
bridge_argument.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : bridge_argument.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 
00014 class bridge_argument_rep: public bridge_rep {
00015 protected:
00016   bool   valid;
00017   string name;
00018   path   prefix;
00019   bridge body;
00020 
00021 public:
00022   bridge_argument_rep (typesetter ttt, tree st, path ip);
00023   void initialize ();
00024   void initialize (string name, path head, tree body_t, path body_ip);
00025 
00026   void notify_assign (path p, tree u);
00027   bool notify_macro  (int type, string var, int level, path p, tree u);
00028   void notify_change ();
00029 
00030   bool my_typeset_will_be_complete ();
00031   void my_typeset (int desired_status);
00032 };
00033 
00034 bridge_argument_rep::bridge_argument_rep (typesetter ttt, tree st, path ip):
00035   bridge_rep (ttt, st, ip)
00036 {
00037   valid= false;
00038 }
00039 
00040 void
00041 bridge_argument_rep::initialize (string name2, path pf, tree b_t, path b_ip) {
00042   // cout << "Initialize arg: " << name2 << ", " << pf << ": " << b_t << "\n";
00043   if ((!valid) || (name != name2) || (prefix != pf) ||
00044       (body->st != b_t) || (body->ip != b_ip))
00045     {
00046       valid = true;
00047       name  = name2;
00048       prefix= pf;
00049       if (is_nil (body)) body = make_bridge (ttt, b_t, b_ip);
00050       else replace_bridge (body, b_t, b_ip);
00051     }
00052 }
00053 
00054 bridge
00055 bridge_argument (typesetter ttt, tree st, path ip) {
00056   return tm_new<bridge_argument_rep> (ttt, st, ip);
00057 }
00058 
00059 /******************************************************************************
00060 * Event notification
00061 ******************************************************************************/
00062 
00063 void
00064 bridge_argument_rep::notify_assign (path p, tree u) {
00065   // cout << "Assign " << p << ", " << u << " in " << st << "\n";
00066   status= CORRUPTED;
00067   st    = substitute (st, p, u);
00068   valid = false;
00069 }
00070 
00071 bool
00072 bridge_argument_rep::notify_macro (int tp, string var, int l, path p, tree u) {
00073   /*
00074   cout << "Macro argument " << var << " [action=" << tp
00075        << ", level=" << l << "] " << p << ", " << u << " in " << st << "\n";
00076   */
00077 
00078   bool flag;
00079   if (valid) {
00080     // cout << "  " << body->st << ", " << body->ip << "\n";
00081     flag= true;
00082     if (l==0) {
00083       int n= N(prefix);
00084       if ((var == name) && (N(p) >= n) && (head (p, n) == prefix)) {
00085        p= tail (p, n);
00086        switch (tp) {
00087        case MACRO_ASSIGN:
00088          if (is_nil (p)) replace_bridge (body, u, body->ip);
00089          else body->notify_assign (p, u);
00090          break;
00091        case MACRO_INSERT:
00092          body->notify_insert (p, u);
00093          break;
00094        case MACRO_REMOVE:
00095          body->notify_remove (p, as_int (u->label));
00096          break;
00097        }
00098       }
00099       else flag= false;
00100     }
00101     else {
00102       list<hashmap<string,tree> > old_var= env->macro_arg;
00103       list<hashmap<string,path> > old_src= env->macro_src;
00104       if (!is_nil (env->macro_arg)) env->macro_arg= env->macro_arg->next;
00105       if (!is_nil (env->macro_src)) env->macro_src= env->macro_src->next;
00106       flag= body->notify_macro (tp, var, l-1, p, u);
00107       env->macro_arg= old_var;
00108       env->macro_src= old_src;
00109     }
00110   }
00111   else flag= env->depends (st, var, l);
00112   if (flag) status= CORRUPTED;
00113   return flag;
00114 }
00115 
00116 void
00117 bridge_argument_rep::notify_change () {
00118   status= CORRUPTED;
00119   body->notify_change ();
00120 }
00121 
00122 /******************************************************************************
00123 * Typesetting
00124 ******************************************************************************/
00125 
00126 bool
00127 bridge_argument_rep::my_typeset_will_be_complete () {
00128   return !valid;
00129 }
00130 
00131 void
00132 bridge_argument_rep::my_typeset (int desired_status) {
00133   string name;
00134   tree   value;
00135   path   valip= decorate_right (ip);
00136 
00137   tree r= st[0];
00138   if (is_compound (r)) value= tree (ERROR, "arg");
00139   else {
00140     name = r->label;
00141     if ((!is_nil (env->macro_arg)) && env->macro_arg->item->contains (r->label)) {
00142       value= env->macro_arg->item [name];
00143       if (!is_func (value, BACKUP)) {
00144        path new_valip= env->macro_src->item [name];
00145        if (is_accessible (new_valip)) valip= new_valip;
00146       }
00147     }
00148     else value= tree (ERROR, "arg " * name);
00149   }
00150 
00151   path prefix;
00152   if (N(st) > 1) {
00153     int i, n= N(st);
00154     for (i=1; i<n; i++) {
00155       tree r= env->exec (st[i]);
00156       if (!is_int (r)) {
00157         prefix= path ();
00158         value= tree (ERROR, "arg " * name);
00159         valip= decorate_right (ip);
00160         break;
00161       }
00162       int nr= as_int (r);
00163       if ((!is_compound (value)) || (nr<0) || (nr>=N(value))) {
00164         prefix= path ();
00165         value= tree (ERROR, "arg " * name);
00166         valip= decorate_right (ip);
00167         break;
00168       }
00169       value = value[nr];
00170       valip = descend (valip, nr);
00171       prefix= prefix * nr;
00172     }
00173   }
00174   initialize (name, prefix, attach_here (value, valip));
00175 
00176   ttt->insert_marker (body->st, ip);
00177   list<hashmap<string,tree> > old_var= env->macro_arg;
00178   list<hashmap<string,path> > old_src= env->macro_src;
00179   if (!is_nil (env->macro_arg)) env->macro_arg= env->macro_arg->next;
00180   if (!is_nil (env->macro_src)) env->macro_src= env->macro_src->next;
00181   body->typeset (desired_status);
00182   env->macro_arg= old_var;
00183   env->macro_src= old_src;
00184 }