Back to index

texmacs  1.0.7.15
std_environment.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : std_environment.cpp
00004 * DESCRIPTION: environments for standard TeXmacs style rewriting mechanism
00005 * COPYRIGHT  : (C) 2006  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 "list_environment.hpp"
00013 #include "memorizer.hpp"
00014 #include "iterator.hpp"
00015 
00016 /******************************************************************************
00017 * Standard environments
00018 ******************************************************************************/
00019 
00020 class std_environment_rep;
00021 class std_environment {
00022   ABSTRACT_NULL(std_environment);
00023   inline std_environment
00024     (bool pure, list_environment env, std_environment next,
00025      list_environment accel, list_environment args);
00026   inline friend environment as_environment (const std_environment& env) {
00027     return environment ((environment_rep*) env.rep); }
00028   inline friend std_environment as_std_environment (const environment& env);
00029   inline friend int weak_hash (std_environment env) {
00030     return hash ((void*) env.rep); }
00031   inline friend bool weak_equal (std_environment env1, std_environment env2) {
00032     return env1.rep == env2.rep; }
00033 };
00034 
00035 class std_environment_rep: public environment_rep {
00036 public:
00037   bool             pure;   // pure environment or allow side effects?
00038   list_environment env;    // the local variables
00039   std_environment  next;   // the next environment
00040   list_environment accel;  // accelerated access to environment
00041   list_environment args;   // recursive macro arguments environment
00042 
00043 public:
00044   inline std_environment_rep (bool pure2,
00045                            list_environment env2,
00046                            std_environment next2,
00047                            list_environment accel2,
00048                            list_environment args2):
00049     pure (pure2), env (env2), next (next2), accel (accel2), args (args2) {}
00050 
00051   inline bool contains (int key) {
00052     return accel->contains (key); }
00053   inline tree read (int key) {
00054     return accel->read (key); }
00055   inline void write (int key, const tree& val) {
00056     env->write (key, val);
00057     accel->write (key, val); }
00058   inline void remove (int key) {
00059     // NOTE: it is not allowed to change next, in the case
00060     // when 'key' does not exist in the std environment 'env'
00061     env->remove (key);
00062     accel->remove (key); }
00063   void print (const string& prefix);
00064 };
00065 
00066 inline std_environment::std_environment
00067   (bool pure, list_environment env, std_environment next,
00068    list_environment accel, list_environment args):
00069      rep (tm_new<std_environment_rep> (pure, env, next, accel, args)) {}
00070 ABSTRACT_NULL_CODE(std_environment);
00071 
00072 void
00073 std_environment_rep::print (const string& prefix) {
00074   cout << prefix << "Std environment" << LF;
00075   env->print (prefix * (pure? string ("|* "): string ("|  ")));
00076   std_environment it= next;
00077   while (!is_nil (it)) {
00078     it->env->print (prefix * (it->pure? string ("|* "): string ("|  ")));
00079     it= it->next;
00080   }
00081   if (total_size (args) != 0)
00082     args->print (prefix * "|o ");
00083 }
00084 
00085 inline std_environment as_std_environment (const environment& env) {
00086     return std_environment ((std_environment_rep*) as_pointer (env)); }
00087 
00088 /******************************************************************************
00089 * Primitive environments
00090 ******************************************************************************/
00091 
00092 std_environment
00093 primitive_environment (basic_environment global) {
00094   list_environment env (global);
00095   return std_environment (false, env, std_environment (),
00096                        env, list_environment ());
00097 }
00098 
00099 std_environment
00100 primitive_environment (hashmap<string,tree> h) {
00101   basic_environment global (1);
00102   iterator<string> it= iterate (h);
00103   while (it->busy ()) {
00104     string key= it->next();
00105     global->write ((int) make_tree_label (key), copy (h[key]));
00106   }
00107   return primitive_environment (global);
00108 }
00109 
00110 void
00111 primitive (environment& env, hashmap<string,tree> h) {
00112   env= as_environment (primitive_environment (h));
00113   //cout << HRULE;
00114   //env->print ("");
00115 }
00116 
00117 /******************************************************************************
00118 * Assignments
00119 ******************************************************************************/
00120 
00121 std_environment
00122 assign_environment (std_environment env, basic_environment local) {
00123   list_environment accel (local, env->accel);
00124   if (env->pure) return std_environment (false, local, env, accel, env->args);
00125   list_environment merged (local, env->env);
00126   return std_environment (false, merged, env->next, accel, env->args);
00127 }
00128 
00129 class assign_memorizer_rep: public memorizer_rep {
00130   std_environment   in;
00131   assoc_environment local;
00132   std_environment   out;
00133   int               h;
00134 
00135 public:
00136   inline assign_memorizer_rep (environment env, assoc_environment ch):
00137     in (as_std_environment (env)), local (ch), out (in),
00138     h (weak_hash (env) ^ weak_hash (ch)) {}
00139 
00140   void print (tm_ostream& out) { out << "assign_memorizer"; }
00141   int type () { return MEMORIZE_ASSIGN; }
00142   int hash () { return h; }
00143   bool equal (memorizer_rep* mem) {
00144     assign_memorizer_rep* rep= (assign_memorizer_rep*) mem;
00145     return weak_equal (in, rep->in) && weak_equal (local, rep->local); }
00146   void compute () {
00147     out= assign_environment (in, basic_environment (local)); }
00148   void set_environment (environment out2) {
00149     out= as_std_environment (out2); }
00150   environment get_environment () {
00151     return as_environment (out); }
00152 };
00153 
00154 void
00155 assign (environment& env, assoc_environment local) {
00156   memorizer mem= tm_new<assign_memorizer_rep> (env, local);
00157   if (!is_memorized (mem)) mem->compute ();
00158   env= mem->get_environment ();
00159 }
00160 
00161 /******************************************************************************
00162 * Starting local environments
00163 ******************************************************************************/
00164 
00165 std_environment
00166 begin_with_environment (std_environment env, basic_environment local) {
00167   list_environment accel (local, env->accel);
00168   return std_environment (true, local, env, accel, env->args);
00169 }
00170 
00171 class begin_with_memorizer_rep: public memorizer_rep {
00172   std_environment   in;
00173   assoc_environment local;
00174   std_environment   out;
00175   int               h;
00176 
00177 public:
00178   inline begin_with_memorizer_rep (environment env, assoc_environment ch):
00179     in (as_std_environment (env)), local (ch), out (in),
00180     h (weak_hash (env) ^ weak_hash (ch)) {}
00181 
00182   void print (tm_ostream& out) { out << "begin_with_memorizer"; }
00183   int type () { return MEMORIZE_BEGIN_WITH; }
00184   int hash () { return h; }
00185   bool equal (memorizer_rep* mem) {
00186     begin_with_memorizer_rep* rep= (begin_with_memorizer_rep*) mem;
00187     return weak_equal (in, rep->in) && weak_equal (local, rep->local); }
00188   void compute () {
00189     out= begin_with_environment (in, basic_environment (local)); }
00190   void set_environment (environment out2) {
00191     out= as_std_environment (out2); }
00192   environment get_environment () {
00193     return as_environment (out); }
00194 };
00195 
00196 void
00197 begin_with (environment& env, assoc_environment local) {
00198   memorizer mem= tm_new<begin_with_memorizer_rep> (env, local);
00199   if (!is_memorized (mem)) mem->compute ();
00200   env= mem->get_environment ();
00201 }
00202 
00203 /******************************************************************************
00204 * Closing local environments
00205 ******************************************************************************/
00206 
00207 std_environment
00208 end_with_environment (std_environment env) {
00209   if (env->pure) return env->next;
00210   ASSERT (env->next->pure, "pure environment expected");
00211   basic_environment patch= flatten (env->env);
00212   basic_environment with_env= flatten (env->next->env);
00213   patch->multiple_remove (with_env->a, with_env->n);
00214   if (patch->size == 0) return env->next->next;
00215   while (patch->size < (patch->n>>1))
00216     patch->resize (patch->n >> 1);
00217   std_environment up= env->next->next;
00218   std_environment aux (up->pure, up->env, up->next, up->accel, env->args);
00219   return assign_environment (aux, patch);
00220 }
00221 
00222 class end_with_memorizer_rep: public memorizer_rep {
00223   std_environment   in;
00224   std_environment   out;
00225 
00226 public:
00227   inline end_with_memorizer_rep (environment env):
00228     in (as_std_environment (env)), out (in) {}
00229 
00230   void print (tm_ostream& out) { out << "end_with_memorizer"; }
00231   int type () { return MEMORIZE_END_WITH; }
00232   int hash () { return weak_hash (in); }
00233   bool equal (memorizer_rep* mem) {
00234     end_with_memorizer_rep* rep= (end_with_memorizer_rep*) mem;
00235     return weak_equal (in, rep->in); }
00236   void compute () {
00237     out= end_with_environment (in); }
00238   void set_environment (environment out2) {
00239     out= as_std_environment (out2); }
00240   environment get_environment () {
00241     return as_environment (out); }
00242 };
00243 
00244 void
00245 end_with (environment& env) {
00246   memorizer mem= tm_new<end_with_memorizer_rep> (env);
00247   if (!is_memorized (mem)) mem->compute ();
00248   env= mem->get_environment ();
00249 }
00250 
00251 /******************************************************************************
00252 * Adding an additional macro level
00253 ******************************************************************************/
00254 
00255 #ifdef CLASSICAL_MACRO_EXPANSION
00256 
00257 std_environment
00258 macro_down_environment (std_environment env, basic_environment local) {
00259   list_environment args (local, env->args);
00260   return std_environment (env->pure, env->env, env->next, env->accel, args);
00261 }
00262 
00263 class macro_down_memorizer_rep: public memorizer_rep {
00264   std_environment   in;
00265   assoc_environment local;
00266   std_environment   out;
00267   int               h;
00268 
00269 public:
00270   inline macro_down_memorizer_rep (environment env, assoc_environment ch):
00271     in (as_std_environment (env)), local (ch), out (in),
00272     h (weak_hash (env) ^ weak_hash (ch)) {}
00273 
00274   void print (tm_ostream& out) { out << "macro_down_memorizer"; }
00275   int type () { return MEMORIZE_MACRO_DOWN; }
00276   int hash () { return h; }
00277   bool equal (memorizer_rep* mem) {
00278     macro_down_memorizer_rep* rep= (macro_down_memorizer_rep*) mem;
00279     return weak_equal (in, rep->in) && weak_equal (local, rep->local); }
00280   void compute () {
00281     out= macro_down_environment (in, basic_environment (local)); }
00282   void set_environment (environment out2) {
00283     out= as_std_environment (out2); }
00284   environment get_environment () {
00285     return as_environment (out); }
00286 };
00287 
00288 class macro_redown_memorizer_rep: public memorizer_rep {
00289   std_environment   in;
00290   basic_environment local;
00291   std_environment   out;
00292   int               h;
00293 
00294 public:
00295   inline macro_redown_memorizer_rep (environment env, basic_environment ch):
00296     in (as_std_environment (env)), local (ch), out (in),
00297     h (weak_hash (env) ^ weak_hash (as_environment (ch))) {}
00298 
00299   void print (tm_ostream& out) { out << "macro_redown_memorizer"; }
00300   int type () { return MEMORIZE_MACRO_DOWN; }
00301   int hash () { return h; }
00302   bool equal (memorizer_rep* mem) {
00303     macro_redown_memorizer_rep* rep= (macro_redown_memorizer_rep*) mem;
00304     return weak_equal (in, rep->in) &&
00305            weak_equal (as_environment (local), as_environment (rep->local)); }
00306   void compute () {
00307     out= macro_down_environment (in, local); }
00308   void set_environment (environment out2) {
00309     out= as_std_environment (out2); }
00310   environment get_environment () {
00311     return as_environment (out); }
00312 };
00313 
00314 void
00315 macro_down (environment& env, assoc_environment local) {
00316   memorizer mem= tm_new<macro_down_memorizer_rep> (env, local);
00317   if (!is_memorized (mem)) mem->compute ();
00318   env= mem->get_environment ();
00319 }
00320 
00321 void
00322 macro_redown (environment& env, basic_environment local) {
00323   memorizer mem= tm_new<macro_redown_memorizer_rep> (env, local);
00324   if (!is_memorized (mem)) mem->compute ();
00325   env= mem->get_environment ();
00326 }
00327 
00328 bool
00329 macro_top_level (environment& env) {
00330   std_environment std= as_std_environment (env);
00331   return is_nil (std->args);
00332 }
00333 
00334 basic_environment
00335 macro_arguments (environment& env) {
00336   std_environment std= as_std_environment (env);
00337   return std->args->env;
00338 }
00339 
00340 #endif // CLASSICAL_MACRO_EXPANSION
00341 
00342 /******************************************************************************
00343 * Remove the uppermost macro level
00344 ******************************************************************************/
00345 
00346 #ifdef CLASSICAL_MACRO_EXPANSION
00347 
00348 std_environment
00349 macro_up_environment (std_environment env) {
00350   return std_environment (env->pure, env->env, env->next, env->accel,
00351                        env->args->next);
00352 }
00353 
00354 class macro_up_memorizer_rep: public memorizer_rep {
00355   std_environment   in;
00356   std_environment   out;
00357 
00358 public:
00359   inline macro_up_memorizer_rep (environment env):
00360     in (as_std_environment (env)), out (in) {}
00361 
00362   void print (tm_ostream& out) { out << "macro_up_memorizer"; }
00363   int type () { return MEMORIZE_MACRO_UP; }
00364   int hash () { return weak_hash (in); }
00365   bool equal (memorizer_rep* mem) {
00366     macro_up_memorizer_rep* rep= (macro_up_memorizer_rep*) mem;
00367     return weak_equal (in, rep->in); }
00368   void compute () {
00369     out= macro_up_environment (in); }
00370   void set_environment (environment out2) {
00371     out= as_std_environment (out2); }
00372   environment get_environment () {
00373     return as_environment (out); }
00374 };
00375 
00376 void
00377 macro_up (environment& env) {
00378   memorizer mem= tm_new<macro_up_memorizer_rep> (env);
00379   if (!is_memorized (mem)) mem->compute ();
00380   env= mem->get_environment ();
00381 }
00382 
00383 #endif // CLASSICAL_MACRO_EXPANSION
00384 
00385 /******************************************************************************
00386 * Testing the code for environments
00387 ******************************************************************************/
00388 
00389 assoc_environment
00390 assoc (int key1, const tree& val1) {
00391   assoc_environment env (1);
00392   env->raw_write (0, key1, val1);
00393   return env;
00394 }
00395 
00396 assoc_environment
00397 assoc (int key1, const tree& val1, int key2, const tree& val2) {
00398   assoc_environment env (2);
00399   env->raw_write (0, key1, val1);
00400   env->raw_write (1, key2, val2);
00401   return env;
00402 }
00403 
00404 basic_environment
00405 test_environment (int n, int code) {
00406   array<string> s (8);
00407   s[0]= "Hallo"; s[1]= "Hop"; s[2]= "Blah"; s[3]= "Holala";
00408   s[4]= "Ploef"; s[5]= "Blurk"; s[6]= "Blauwbilgorgel"; s[7]= "Vrolijk";
00409   int modulo= 32;
00410   while (modulo<n) modulo <<= 1;
00411   basic_environment env (1);
00412   for (int i=0; i<n; i++) {
00413     int i1= code%8, i2= (3*code)%8;
00414     if (i1 == i2) i2= (i2+1)%8;
00415     string s1= copy (s[i1]), s2= copy (s[i2]);
00416     env->write (code % modulo, s1);
00417     int j1= code % N(s1), j2= code % N(s2);
00418     s[i1]= s2 (0, j2) * s1 (j1, N(s1));
00419     s[i2]= s1 (0, j1) * s2 (j2, N(s2));
00420     code= code*code % 176246173;
00421     if (code < 0) code= -code;
00422     while (env->contains (code % modulo)) code= (code+1) % 176246173;
00423   }
00424   return env;
00425 }
00426 
00427 void
00428 test_environments () {
00429   assoc_environment a1= assoc (6, "Sylvie", 9, "Nicole");
00430   assoc_environment a2= assoc (9, "Joris");
00431   assoc_environment a3= assoc (21, "Judith");
00432   assoc_environment a4= assoc (9, "Judith", 6, "Tessa");
00433   assoc_environment a5= assoc (9, "Piet", 21, "Joris");
00434 
00435   basic_environment b1= test_environment (23, 1234567);
00436   std_environment std1= primitive_environment (b1);
00437   std1->print (""); cout << HRULE;
00438   std1->accel->print (""); cout << HRULE;
00439   std_environment std2= begin_with_environment (std1, a1);
00440   std2->print (""); cout << HRULE;
00441   std2->accel->print (""); cout << HRULE;
00442   std_environment std3= assign_environment (std2, a5);
00443   std3->print (""); cout << HRULE;
00444   std3->accel->print (""); cout << HRULE;
00445   std_environment std4= assign_environment (std3, a3);
00446   std4->print (""); cout << HRULE;
00447   std4->accel->print (""); cout << HRULE;
00448   std_environment std5= begin_with_environment (std4, a4);
00449   std5->print (""); cout << HRULE;
00450   std5->accel->print (""); cout << HRULE;
00451   std_environment std6= assign_environment (std5, a2);
00452   std6->print (""); cout << HRULE;
00453   std6->accel->print (""); cout << HRULE;
00454   for (int i=0; i<10; i++)
00455     cout << i << "\t" << std6->read (i) << "\n";
00456   cout << HRULE;
00457   std6->accel->print (""); cout << HRULE;
00458   for (int i=0; i<10; i++)
00459     cout << i << "\t" << std6->read (i) << "\n";
00460   cout << HRULE;
00461   std6->accel->print (""); cout << HRULE;
00462   for (int i=0; i<40; i++)
00463     cout << i << "\t" << std6->read (i) << "\n";
00464   cout << HRULE;
00465   std6->accel->print (""); cout << HRULE;
00466   std_environment std7= end_with_environment (std6);
00467   std7->print (""); cout << HRULE;
00468   std7->accel->print (""); cout << HRULE;
00469   std_environment std8= end_with_environment (std7);
00470   std8->print (""); cout << HRULE;
00471   std8->accel->print (""); cout << HRULE;
00472 }