Back to index

texmacs  1.0.7.15
tag_info.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : tag_info.cpp
00004 * DESCRIPTION: DRD information about tags
00005 * COPYRIGHT  : (C) 2003  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 "tag_info.hpp"
00013 #include "hashmap.hpp"
00014 
00015 #define get_bits(which,nr) which=i&((1<<nr)-1);i=i>>nr
00016 #define set_bits(which,nr) i+=((int)which)<<offset;offset+=nr
00017 
00018 /******************************************************************************
00019 * Compact representation for environment changes
00020 ******************************************************************************/
00021 
00022 static hashmap<tree,int> encode_table (-1);
00023 static array<tree>       decode_table;
00024 
00025 int
00026 drd_encode (tree t) {
00027   if (encode_table->contains (t))
00028     return encode_table[t];
00029   int n= N(decode_table);
00030   ASSERT (n < (1 << 16), "drd_encode overflow");
00031   encode_table (t) = n;
00032   decode_table << t;
00033   return n;
00034 }
00035 
00036 tree
00037 drd_decode (int i) {
00038   ASSERT (i >= 0 && i < N (decode_table), "out of range");
00039   return decode_table[i];
00040 }
00041 
00042 /******************************************************************************
00043 * Names for drd types
00044 ******************************************************************************/
00045 
00046 string
00047 drd_decode_type (int i) {
00048   switch (i) {
00049   case TYPE_REGULAR: return "regular";
00050   case TYPE_ADHOC: return "adhoc";
00051   case TYPE_VARIABLE: return "variable";
00052   case TYPE_ARGUMENT: return "argument";
00053   case TYPE_BOOLEAN: return "boolean";
00054   case TYPE_INTEGER: return "integer";
00055   case TYPE_STRING: return "string";
00056   case TYPE_LENGTH: return "length";
00057   case TYPE_NUMERIC: return "numeric";
00058   case TYPE_CODE: return "code";
00059   case TYPE_IDENTIFIER: return "identifier";
00060   case TYPE_URL: return "url";
00061   case TYPE_GRAPHICAL: return "graphical";
00062   case TYPE_POINT: return "point";
00063   case TYPE_ANIMATION: return "animation";
00064   case TYPE_DURATION: return "duration";
00065   case TYPE_UNKNOWN: return "unknown";
00066   case TYPE_ERROR: return "error";
00067   default: return "unknown";
00068   }
00069 }
00070 
00071 int
00072 drd_encode_type (string s) {
00073   if (s == "regular") return TYPE_REGULAR;
00074   else if (s == "adhoc") return TYPE_ADHOC;
00075   else if (s == "variable") return TYPE_VARIABLE;
00076   else if (s == "argument") return TYPE_ARGUMENT;
00077   else if (s == "boolean") return TYPE_BOOLEAN;
00078   else if (s == "integer") return TYPE_INTEGER;
00079   else if (s == "string") return TYPE_STRING;
00080   else if (s == "length") return TYPE_LENGTH;
00081   else if (s == "numeric") return TYPE_NUMERIC;
00082   else if (s == "code") return TYPE_CODE;
00083   else if (s == "identifier") return TYPE_IDENTIFIER;
00084   else if (s == "url") return TYPE_URL;
00085   else if (s == "graphical") return TYPE_GRAPHICAL;
00086   else if (s == "point") return TYPE_POINT;
00087   else if (s == "animation") return TYPE_ANIMATION;
00088   else if (s == "duration") return TYPE_DURATION;
00089   else if (s == "unknown") return TYPE_UNKNOWN;
00090   else if (s == "error") return TYPE_ERROR;
00091   else return -1;
00092 }
00093 
00094 /******************************************************************************
00095 * Properties of the tag
00096 ******************************************************************************/
00097 
00098 parent_info::parent_info (int a, int x, int am, int cm, bool frozen) {
00099   type             = TYPE_REGULAR;
00100   arity_mode       = am;
00101   arity_base       = a;
00102   arity_extra      = x;
00103   child_mode       = cm;
00104   border_mode      = BORDER_YES;
00105   block            = BLOCK_NO;
00106   with_like        = false;
00107   freeze_arity     = frozen;
00108   freeze_border    = frozen;
00109   freeze_block     = frozen;
00110   freeze_with      = frozen;
00111 }
00112 
00113 parent_info::parent_info (tree t) {
00114   int i= as_int (t);
00115   get_bits (type            , 5);
00116   get_bits (arity_mode      , 2);
00117   get_bits (arity_base      , 6);
00118   get_bits (arity_extra     , 4);
00119   get_bits (child_mode      , 2);
00120   get_bits (border_mode     , 2);
00121   get_bits (block           , 2);
00122   get_bits (with_like       , 1);
00123   get_bits (freeze_type     , 1);
00124   get_bits (freeze_arity    , 1);
00125   get_bits (freeze_border   , 1);
00126   get_bits (freeze_block    , 1);
00127   get_bits (freeze_with     , 1);
00128 }
00129 
00130 parent_info::operator tree () {
00131   int i=0, offset=0;
00132   set_bits (type            , 5);
00133   set_bits (arity_mode      , 2);
00134   set_bits (arity_base      , 6);
00135   set_bits (arity_extra     , 4);
00136   set_bits (child_mode      , 2);
00137   set_bits (border_mode     , 2);
00138   set_bits (block           , 2);
00139   set_bits (with_like       , 1);
00140   set_bits (freeze_type     , 1);
00141   set_bits (freeze_arity    , 1);
00142   set_bits (freeze_border   , 1);
00143   set_bits (freeze_block    , 1);
00144   set_bits (freeze_with     , 1);
00145   return as_string (i);
00146 }
00147 
00148 bool
00149 parent_info::operator == (const parent_info& pi) {
00150   return
00151     (type             == pi.type            ) &&
00152     (arity_mode       == pi.arity_mode      ) &&
00153     (arity_base       == pi.arity_base      ) &&
00154     (arity_extra      == pi.arity_extra     ) &&
00155     (child_mode       == pi.child_mode      ) &&
00156     (border_mode      == pi.border_mode     ) &&
00157     (block            == pi.block           ) &&
00158     (with_like        == pi.with_like       ) &&
00159     (freeze_arity     == pi.freeze_arity    ) &&
00160     (freeze_border    == pi.freeze_border   ) &&
00161     (freeze_block     == pi.freeze_block    ) &&
00162     (freeze_with      == pi.freeze_with     );
00163 }
00164 
00165 bool
00166 parent_info::operator != (const parent_info& pi) {
00167   return !(operator == (pi));
00168 }
00169 
00170 tm_ostream&
00171 operator << (tm_ostream& out, parent_info pi) {
00172   return out << ((tree) pi);
00173 }
00174 
00175 /******************************************************************************
00176 * Properties of the children of the tag
00177 ******************************************************************************/
00178 
00179 child_info::child_info (bool frozen) {
00180   type               = TYPE_ADHOC;
00181   accessible         = ACCESSIBLE_NEVER;
00182   writability        = WRITABILITY_NORMAL;
00183   block              = 0;
00184   env                = drd_encode (tree (WITH));
00185   freeze_type        = frozen;
00186   freeze_accessible  = frozen;
00187   freeze_writability = frozen;
00188   freeze_block       = frozen;
00189   freeze_env         = frozen;
00190 }
00191 
00192 child_info::child_info (tree t) {
00193   int i= as_int (is_atomic (t)? t: t[N(t)-1]);
00194   get_bits (type              ,  5);
00195   get_bits (accessible        ,  2);
00196   get_bits (writability       ,  2);
00197   get_bits (block             ,  2);
00198   get_bits (freeze_type       ,  1);
00199   get_bits (freeze_accessible ,  1);
00200   get_bits (freeze_writability,  1);
00201   get_bits (freeze_block      ,  1);
00202   get_bits (freeze_env        ,  1);
00203   if (is_atomic (t)) env= drd_encode (tree (WITH));
00204   else env= drd_encode (t (0, N(t)-1));
00205 }
00206 
00207 child_info::operator tree () {
00208   int i=0, offset=0;
00209   set_bits (type              ,  5);
00210   set_bits (accessible        ,  2);
00211   set_bits (writability       ,  2);
00212   set_bits (block             ,  2);
00213   set_bits (freeze_type       ,  1);
00214   set_bits (freeze_accessible ,  1);
00215   set_bits (freeze_writability,  1);
00216   set_bits (freeze_block      ,  1);
00217   set_bits (freeze_env        ,  1);
00218   if (drd_decode (env) == tree (WITH)) return as_string (i);
00219   else return drd_decode (env) * tree (WITH, as_string (i));
00220 }
00221 
00222 bool
00223 child_info::operator == (const child_info& ci) {
00224   return
00225     (type               == ci.type              ) &&
00226     (accessible         == ci.accessible        ) &&
00227     (writability        == ci.writability       ) &&
00228     (block              == ci.block             ) &&
00229     (env                == ci.env               ) &&
00230     (freeze_type        == ci.freeze_type       ) &&
00231     (freeze_accessible  == ci.freeze_accessible ) &&
00232     (freeze_writability == ci.freeze_writability) &&
00233     (freeze_block       == ci.freeze_block      ) &&
00234     (freeze_env         == ci.freeze_env        );
00235 }
00236 
00237 bool
00238 child_info::operator != (const child_info& ci) {
00239   return !(operator == (ci));
00240 }
00241 
00242 tm_ostream&
00243 operator << (tm_ostream& out, child_info ci) {
00244   return out << ((tree) ci);
00245 }
00246 
00247 /******************************************************************************
00248 * Constructors, destructors and converters
00249 ******************************************************************************/
00250 
00251 tag_info_rep::tag_info_rep (parent_info pi2, array<child_info> ci2, tree x):
00252   pi (pi2), ci (ci2), extra (x) {}
00253 
00254 tag_info_rep::tag_info_rep (int a, int x, int am, int cm, bool frozen):
00255   pi (a, x, am, cm, frozen),
00256   ci ((a+x)==0? 0: (cm==CHILD_UNIFORM? 1: (cm==CHILD_BIFORM? 2: (a+x))))
00257 {
00258   if (frozen) {
00259     int i, n= N(ci);
00260     for (i=0; i<n; i++)
00261       ci[i]= child_info (true);
00262   }
00263 }
00264 
00265 tag_info::tag_info (parent_info pi, array<child_info> ci, tree extra) {
00266   rep= tm_new<tag_info_rep> (pi, ci, extra);
00267 }
00268 
00269 tag_info::tag_info (int a, int x, int am, int cm, bool frozen) {
00270   rep= tm_new<tag_info_rep> (a, x, am, cm, frozen);
00271 }
00272 
00273 tag_info::tag_info (tree t) {
00274   if ((!is_func (t, TUPLE)) || (N(t)<2) || (L(t[1]) != TUPLE)) {
00275     cerr << "\nt= " << t << "\n";
00276     FAILED ("bad tag_info");
00277   }
00278   parent_info pi (t[0]);
00279   int i, n= N(t[1]);
00280   array<child_info> ci (n);
00281   for (i=0; i<n; i++)
00282     ci[i]= child_info (t[1][i]);
00283   rep= tm_new<tag_info_rep> (pi, ci, N(t)==3? t[2]: tree (""));
00284 }
00285 
00286 tag_info::operator tree () {
00287   if (rep->extra == "") return tree (TUPLE, (tree) rep->pi, (tree) rep->ci);
00288   else return tree (TUPLE, (tree) rep->pi, (tree) rep->ci, rep->extra);
00289 }
00290 
00291 /******************************************************************************
00292 * Access routines and getting the index of a child
00293 ******************************************************************************/
00294 
00295 tag_info
00296 tag_info_rep::inner_border () {
00297   pi.border_mode= BORDER_INNER;
00298   return tag_info (pi, ci, extra);
00299 }
00300 
00301 tag_info
00302 tag_info_rep::outer_border () {
00303   pi.border_mode= BORDER_OUTER;
00304   return tag_info (pi, ci, extra);
00305 }
00306 
00307 tag_info
00308 tag_info_rep::with_like () {
00309   pi.with_like= true;
00310   return tag_info (pi, ci, extra);
00311 }
00312 
00313 tag_info
00314 tag_info_rep::type (int tp) {
00315   pi.type= tp;
00316   return tag_info (pi, ci, extra);
00317 }
00318 
00319 tag_info
00320 tag_info_rep::type (int i, int tp) {
00321   if (i < 0 || i >= N(ci)) cout << i << " out of " << N(ci) << "\n";
00322   ASSERT (i >= 0 && i<N(ci), "index out of range");
00323   ci[i].type= tp;
00324   return tag_info (pi, ci, extra);
00325 }
00326 
00327 tag_info
00328 tag_info_rep::accessible (int i) {
00329   if (i < 0 || i >= N(ci)) cout << i << " out of " << N(ci) << "\n";
00330   ASSERT (i >= 0 && i<N(ci), "index out of range");
00331   ci[i].type= TYPE_REGULAR;
00332   ci[i].accessible= ACCESSIBLE_ALWAYS;
00333   return tag_info (pi, ci, extra);
00334 }
00335 
00336 tag_info
00337 tag_info_rep::hidden (int i) {
00338   if (i < 0 || i >= N(ci)) cout << i << " out of " << N(ci) << "\n";
00339   ASSERT (i >= 0 && i<N(ci), "index out of range");
00340   ci[i].type= TYPE_REGULAR;
00341   ci[i].accessible= ACCESSIBLE_HIDDEN;
00342   return tag_info (pi, ci, extra);
00343 }
00344 
00345 tag_info
00346 tag_info_rep::disable_writable (int i) {
00347   if (i < 0 || i >= N(ci)) cout << i << " out of " << N(ci) << "\n";
00348   ASSERT (i >= 0 && i<N(ci), "index out of range");
00349   ci[i].writability= WRITABILITY_DISABLE;
00350   return tag_info (pi, ci, extra);
00351 }
00352 
00353 tag_info
00354 tag_info_rep::enable_writable (int i) {
00355   if (i < 0 || i >= N(ci)) cout << i << " out of " << N(ci) << "\n";
00356   ASSERT (i >= 0 && i<N(ci), "index out of range");
00357   ci[i].writability= WRITABILITY_ENABLE;
00358   return tag_info (pi, ci, extra);
00359 }
00360 
00361 tag_info
00362 tag_info_rep::locals (int i, string var, string val) {
00363   if (i < 0 || i >= N(ci)) cout << i << " out of " << N(ci) << "\n";
00364   ASSERT (i >= 0 && i<N(ci), "index out of range");
00365   ci[i].env= drd_encode (tree (ATTR, var, val));
00366   return tag_info (pi, ci, extra);
00367 }
00368 
00369 void
00370 tag_info_rep::set_attribute (string which, tree val) {
00371   if (extra == "") extra= tree (ATTR);
00372   for (int i=0; i+1<N(extra); i+=2)
00373     if (extra[i] == tree (which)) {
00374       extra[i+1]= val;
00375       return;
00376     }
00377   extra << tree (which) << val;
00378 }
00379 
00380 tree
00381 tag_info_rep::get_attribute (string which) {
00382   if (!is_func (extra, ATTR)) return "";
00383   int i, n= N(extra);
00384   for (i=0; i+1<n; i+=2)
00385     if (extra[i] == which)
00386       return extra[i+1];
00387   return "";
00388 }
00389 
00390 tag_info
00391 tag_info_rep::name (string s) {
00392   set_attribute ("name", s);
00393   return tag_info (pi, ci, extra);
00394 }
00395 
00396 tag_info
00397 tag_info_rep::long_name (string s) {
00398   set_attribute ("long-name", s);
00399   return tag_info (pi, ci, extra);
00400 }
00401 
00402 tag_info
00403 tag_info_rep::name (int i, string s) {
00404   if (i < 0 || i >= N(ci)) cout << i << " out of " << N(ci) << "\n";
00405   ASSERT (i >= 0 && i<N(ci), "index out of range");
00406   set_attribute ("name-" * as_string (i), s);
00407   return tag_info (pi, ci, extra);
00408 }
00409 
00410 tag_info
00411 tag_info_rep::long_name (int i, string s) {
00412   if (i < 0 || i >= N(ci)) cout << i << " out of " << N(ci) << "\n";
00413   ASSERT (i >= 0 && i<N(ci), "index out of range");
00414   set_attribute ("long-name-" * as_string (i), s);
00415   return tag_info (pi, ci, extra);
00416 }
00417 
00418 int
00419 tag_info_rep::get_index (int child, int n) {
00420   int r= 0;
00421   switch (pi.child_mode) {
00422   case CHILD_UNIFORM:
00423     r= 0;
00424     break;
00425   case CHILD_BIFORM:
00426     if (pi.arity_mode != ARITY_VAR_REPEAT) {
00427       if (child < ((int) pi.arity_base)) r= 0;
00428       else r= 1;
00429     }
00430     else {
00431       if (child < (n-((int) pi.arity_base))) r= 0;
00432       else r= 1;
00433     }
00434     break;
00435   case CHILD_DETAILED:
00436     if (((int) pi.arity_mode) <= ARITY_OPTIONS)
00437       r= child;
00438     else if (pi.arity_mode == ARITY_REPEAT) {
00439       if (child < ((int) pi.arity_base)) r= child;
00440       else r= (child - pi.arity_base) % pi.arity_extra + pi.arity_base;
00441     }
00442     else {
00443       if (child < (n-((int) pi.arity_base))) r= child % pi.arity_extra;
00444       else r= pi.arity_base + pi.arity_extra + child - n;
00445     }
00446     break;
00447   }
00448   return r;
00449 }
00450 
00451 child_info&
00452 tag_info::operator () (int child, int n) {
00453   int index= rep->get_index (child, n);
00454   if (index < 0 || index >= N(rep->ci)) {
00455     cout << "child       = " << child << "\n";
00456     cout << "out of      = " << n << "\n";
00457     cout << "child_mode  = " << rep->pi.child_mode << "\n";
00458     cout << "arity_mode  = " << rep->pi.arity_mode << "\n";
00459     cout << "arity_base  = " << rep->pi.arity_base << "\n";
00460     cout << "arity_extra = " << rep->pi.arity_extra << "\n";
00461     cout << "N(ci)       = " << N(rep->ci) << "\n";
00462     ASSERT (false, "index out of range");
00463   }
00464   return rep->ci [index];
00465 }
00466 
00467 /******************************************************************************
00468 * Usual extra routines
00469 ******************************************************************************/
00470 
00471 tm_ostream&
00472 operator << (tm_ostream& out, tag_info ti) {
00473   out << "[ " << ti->pi << ", " << ti->ci;
00474   if (ti->extra != "") out << ", " << ti->extra << "\n";
00475   return out << " ]";
00476 }
00477 
00478 tag_info
00479 copy (tag_info ti) {
00480   return tag_info (ti->pi, copy (ti->ci), copy (ti->extra));
00481 }
00482 
00483 bool
00484 operator == (tag_info ti1, tag_info ti2) {
00485   return
00486     (ti1->pi == ti2->pi) && (ti1->ci == ti2->ci) && (ti1->extra == ti2->extra);
00487 }
00488 
00489 bool
00490 operator != (tag_info ti1, tag_info ti2) {
00491   return !(ti1 == ti2);
00492 }