Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

symmath.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      symmath.cc
00004  *
00005  *      Copyright (C) 2001, 2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include <string.h>
00022 
00023 #include "tools.h"
00024 #include "symmath.h"
00025 
00026 #define ATOM_SYM_INT            MAGICD("SMA\x00")
00027 #define ATOM_SYM_INT_SYMBOL     MAGICD("SMA\x01")
00028 #define ATOM_SYM_INT_CONST      MAGICD("SMA\x02")
00029 
00030 #define ATOM_SYM_BOOL           MAGICD("SMA\x10")
00031 #define ATOM_SYM_BOOL_SYMBOL    MAGICD("SMA\x11")
00032 #define ATOM_SYM_BOOL_INTCMP    MAGICD("SMA\x12")
00033 
00034 /* C operator precedence (for output) */
00035 
00036 b_op copp_mul[] = {
00037         b_mul,
00038         b_div,
00039         b_mod,
00040         b_invalid
00041 };
00042 
00043 b_op copp_add[] = {
00044         b_add,
00045         b_sub,
00046         b_invalid
00047 };
00048 
00049 b_op copp_bin[] = {
00050         b_and,
00051         b_or,
00052         b_xor,
00053         b_invalid
00054 };
00055 
00056 b_op *c_op_prec[] = {
00057         copp_bin,                       /* lowest */
00058         copp_add,
00059         copp_mul,                       /* biggest */
00060         NULL
00061 };
00062 
00063 UINT get_op_prec(b_op bop, b_op **op_prec)
00064 {
00065         UINT k = 0;
00066         while (*op_prec) {
00067                 b_op *l = *op_prec;
00068                 while (*l != b_invalid) {
00069                         if (*l == bop) return k;
00070                         l++;
00071                 }
00072                 op_prec++;
00073                 k++;
00074         }
00075         return 0;
00076 }
00077 
00078 /*
00079  *      CLASS sym_int_token
00080  */
00081 
00082 bool sym_int_token::evaluate(UINT *i)
00083 {
00084         return false;
00085 }
00086 
00087 void sym_int_token::simplify()
00088 {
00089 }
00090 
00091 /*
00092  *      CLASS sym_int_symbol
00093  */
00094 
00095 sym_int_symbol::sym_int_symbol(char *n)
00096 {
00097         name = strdup(n);
00098 }
00099 
00100 sym_int_symbol::~sym_int_symbol()
00101 {
00102         free(name);
00103 }
00104 
00105 bool sym_int_symbol::compare_eq(sym_int_token *t)
00106 {
00107         sym_int_symbol *s = (sym_int_symbol*)t;
00108         return (strcmp(name, s->name) == 0);
00109 }
00110 
00111 Object *sym_int_symbol::duplicate()
00112 {
00113         sym_int_symbol *p = new sym_int_symbol(name);
00114         return p;
00115 }
00116 
00117 bool sym_int_symbol::evaluate(UINT *i)
00118 {
00119         return false;
00120 }
00121 
00122 int sym_int_symbol::nstrfy(char *buf, int n)
00123 {
00124         int q = strlen(name)+1;
00125         if (q > n) q = n;
00126         memmove(buf, name, q);
00127         return q-1;
00128 }
00129 
00130 OBJECT_ID sym_int_symbol::object_id() const
00131 {
00132         return ATOM_SYM_INT_SYMBOL;
00133 }
00134 
00135 /*
00136  *      CLASS sym_int_const
00137  */
00138 
00139 sym_int_const::sym_int_const(UINT v)
00140 {
00141         value = v;
00142 }
00143  
00144 bool sym_int_const::compare_eq(sym_int_token *t)
00145 {
00146         sym_int_const *s = (sym_int_const*)t;
00147         return (value == s->value);
00148 }
00149 
00150 Object *sym_int_const::duplicate()
00151 {
00152         return new sym_int_const(value);
00153 }
00154 
00155 bool sym_int_const::evaluate(UINT *i)
00156 {
00157         *i = value;
00158         return true;    
00159 }
00160  
00161 int sym_int_const::nstrfy(char *buf, int n)
00162 {
00163 /* FIXME: use n */
00164         if (value < 16) return sprintf(buf, "%d", value);
00165         return sprintf(buf, "0x%x", value);
00166 }
00167  
00168 OBJECT_ID sym_int_const::object_id() const
00169 {
00170         return ATOM_SYM_INT_CONST;
00171 }
00172 
00173 /*
00174  *      CLASS sym_int_token_rec
00175  */
00176  
00177 class sym_int_token_rec: public Object {
00178 public:
00179         u_op uop;
00180         b_op bop;
00181         sym_int_token *token;
00182 
00183         sym_int_token_rec(u_op u, b_op b, sym_int_token *t)
00184         {
00185                 uop = u;
00186                 bop = b;
00187                 token = t;              
00188         }
00189 
00190         ~sym_int_token_rec()
00191         {
00192                 token->done();
00193                 delete token;
00194         }
00195 
00196         Object *duplicate()
00197         {
00198                 return new sym_int_token_rec(uop, bop, (sym_int_token*)token->duplicate());
00199         }
00200 }; 
00201 
00202 /*
00203  *      CLASS sym_int
00204  */
00205 
00206 static b_op **output_op_prec = c_op_prec;
00207 
00208 struct op_int_prop {
00209         bool has_prop;
00210         UINT value;
00211 };
00212 
00213 struct op_int_int_prop {
00214         bool has_prop;
00215         UINT value1;
00216         UINT value2;
00217 };
00218 
00219 op_int_prop op_neutrals[NUM_VALID_BOPS] = {
00220 //    b_mul=0,
00221         {true, 1},
00222 //    b_div,
00223         {true, 1},
00224 //    b_mod,
00225         {false},
00226 //    b_add,
00227         {true, 0},
00228 //    b_sub,
00229         {true, 0},
00230 //    b_and,
00231         {true, 0xffffffff},
00232 //    b_or,
00233         {true, 0},
00234 //    b_xor
00235         {true, 0}
00236 };
00237 
00238 bool op_commutative[NUM_VALID_BOPS] = {
00239 //    b_mul=0,
00240         true,
00241 //    b_div,
00242         false,
00243 //    b_mod,
00244         false,
00245 //    b_add,
00246         true,
00247 //    b_sub,
00248         false,
00249 //    b_and,
00250         true,
00251 //    b_or,
00252         true,
00253 //    b_xor
00254         true
00255 };
00256 
00257 op_int_int_prop op_destructive[NUM_VALID_BOPS] = {
00258 //    b_mul=0,
00259         {true, 0, 0},
00260 //    b_div,
00261         {false},
00262 //    b_mod,
00263         {true, 1, 0},
00264 //    b_add,
00265         {false},
00266 //    b_sub,
00267         {false},
00268 //    b_and,
00269         {true, 0, 0},
00270 //    b_or,
00271         {true, 0xffffffff, 0xffffffff},
00272 //    b_xor
00273         {false}
00274 };
00275 
00276 sym_int::sym_int()
00277 {
00278         tokens = new ht_clist();
00279         ((ht_clist*)tokens)->init();
00280 }
00281 
00282 sym_int::~sym_int()
00283 {
00284         tokens->destroy();
00285         delete tokens;
00286 }
00287 
00288 void sym_int::b_operate(b_op bop, sym_int_token *t)
00289 {
00290         if (t->object_id() == ATOM_SYM_INT) {
00291                 sym_int *i = (sym_int*)t;
00292                 if (i->tokens->count() == 1) {
00293                         sym_int_token_rec *r = (sym_int_token_rec*)i->tokens->get(0);
00294                         b_operate(bop, r->token);
00295                         return;
00296                 }
00297         }
00298         tokens->insert(new sym_int_token_rec(u_null, bop, t));
00299 }
00300 
00301 void sym_int::clear()
00302 {
00303         tokens->destroy();
00304         delete tokens;
00305 
00306         tokens = new ht_clist();
00307         ((ht_clist*)tokens)->init();
00308 }
00309 
00310 bool sym_int::compare_eq(sym_int_token *t)
00311 {
00312 // FIXME: implement me !
00313         return false;
00314 }
00315 
00316 bool sym_int::comp_eq(sym_int_token *a, sym_int_token *b)
00317 {
00318         if (a->object_id() == b->object_id()) {
00319                 return a->compare_eq(b);
00320         }
00321         return false;
00322 }
00323 
00324 Object *sym_int::duplicate()
00325 {
00326         sym_int *p = new sym_int();
00327         p->tokens = (ht_list*)tokens->duplicate();
00328         return p;
00329 }
00330 
00331 bool sym_int::evaluate(UINT *i)
00332 {
00333         int c = tokens->count();
00334         UINT l;
00335         for (int j = 0; j < c; j++) {
00336                 UINT k;
00337                 sym_int_token_rec *r = (sym_int_token_rec*)tokens->get(j);
00338                 if (!r->token->evaluate(&k)) return false;
00339                 if (j == 0) l = k;
00340                 switch (r->uop) {
00341                         case u_null: break;
00342                         case u_minus: k = -k; break;
00343                         case u_not: k = ~k; break;
00344                 }
00345                 switch (r->bop) {
00346                         case b_invalid: break;
00347                         case b_mul: l *= k; break;
00348                         case b_div: if (k) l /= k; else return false; break;
00349                         case b_mod: if (k) l %= k; else return false; break;
00350                         case b_add: l += k; break;
00351                         case b_sub: l -= k; break;
00352                         case b_and: l &= k; break;
00353                         case b_or:  l |= k; break;
00354                         case b_xor: l ^= k; break;
00355                 }
00356         }
00357         *i = l;
00358         return true;
00359 }
00360 
00361 int sym_int::nstrfy(char *buf, int n)
00362 {
00363         b_op lbop;
00364         int l = 0;
00365         int c = tokens->count();
00366         lbop = b_invalid;
00367         UINT para_count = 0;
00368         for (int i = 0; i < c; i++) {
00369                 sym_int_token_rec *r = (sym_int_token_rec*)tokens->get(i);
00370                 bool para = ((lbop != b_invalid) && (r->bop != b_invalid) &&
00371                         (get_op_prec(r->bop, output_op_prec) > get_op_prec(lbop,
00372                         output_op_prec)));
00373                 if (para) para_count++;
00374                 lbop = r->bop;
00375         }
00376         for (UINT i = 0; i < para_count; i++) buf[l++] = '(';
00377         lbop = b_invalid;
00378         for (int i = 0; i < c; i++) {
00379                 sym_int_token_rec *r = (sym_int_token_rec*)tokens->get(i);
00380                 bool para = ((lbop != b_invalid) && (r->bop != b_invalid) &&
00381                         (get_op_prec(r->bop, output_op_prec) > get_op_prec(lbop,
00382                         output_op_prec)));
00383 
00384                 if (para) buf[l++] = ')';
00385 
00386                 switch (r->uop) {
00387                         case u_null: break;
00388                         case u_minus: buf[l++] = '-'; break;
00389                         case u_not: buf[l++] = '~'; break;
00390                 }
00391 
00392                 switch (r->bop) {
00393                         case b_invalid: break;
00394                         case b_mul: buf[l++] = '*'; break;
00395                         case b_div: buf[l++] = '/'; break;
00396                         case b_mod: buf[l++] = '%'; break;
00397                         case b_add: buf[l++] = '+'; break;
00398                         case b_sub: buf[l++] = '-'; break;
00399                         case b_and: buf[l++] = '&'; break;
00400                         case b_or:  buf[l++] = '|'; break;
00401                         case b_xor: buf[l++] = '^'; break;
00402                 }
00403 //          buf[l++]='{';
00404                 l += r->token->nstrfy(buf+l, n-l);
00405 //          buf[l++]='}';
00406 
00407                 lbop = r->bop;
00408         }
00409         buf[l] = 0;
00410         return l;
00411 }
00412 
00413 OBJECT_ID sym_int::object_id() const
00414 {
00415         return ATOM_SYM_INT;
00416 }
00417 
00418 void sym_int::replace(sym_int_token *token, sym_int_token *by)
00419 {
00420         int c = tokens->count();
00421         for (int i = 0; i < c; i++) {
00422                 sym_int_token_rec *r = (sym_int_token_rec*)tokens->get(i);
00423                 if (r->token->object_id() == object_id()) {
00424                         ((sym_int*)r->token)->replace(token, by);
00425                 } else if (comp_eq(r->token, token)) {
00426                         r->token->done();
00427                         delete r->token;
00428                         r->token = (sym_int_token*)by->duplicate();
00429                 }
00430         }               
00431 }
00432 
00433 void sym_int::set(sym_int_token *t)
00434 {
00435         clear();
00436         if (t->object_id() == ATOM_SYM_INT) {
00437                 sym_int *i = (sym_int*)t;
00438                 int c = i->tokens->count();
00439                 for (int k=0; k<c; k++) {
00440                         sym_int_token_rec *r = (sym_int_token_rec*)i->tokens->get(k);
00441                         tokens->append(new sym_int_token_rec(r->uop, r->bop, (sym_int_token*)r->token->duplicate()));
00442                 }
00443                 t->done();
00444                 delete t;
00445                 return;
00446         }
00447         tokens->insert(new sym_int_token_rec(u_null, b_invalid, t));
00448 }
00449 
00450 void sym_int::simplify()
00451 {
00452         UINT c = tokens->count();
00453         UINT d;
00454 
00455         do {
00456         d = c;
00457 /* I. CONSTANTS */
00458 
00459 /* step I.1: "c$d..." (front) */
00460         while (c>=2) {
00461                 sym_int_token_rec *a = (sym_int_token_rec*)tokens->get(0);
00462                 sym_int_token_rec *b = (sym_int_token_rec*)tokens->get(1);
00463                 b_op rop;
00464                 sym_int_token *rtoken;
00465                 if (!simplify_reduce_const(b_invalid, a->token, b->bop, b->token, &rop, &rtoken)) break;
00466                 tokens->del(0);
00467                 tokens->del(0);
00468                 tokens->prepend(new sym_int_token_rec(u_null, b_invalid, rtoken));
00469                 c--;
00470         }
00471 
00472 /* step I.2: reduce all "...$c%d..." where allowed
00473    (c,d constant, $,% operators) */
00474         for (UINT i=1; i<c-1; i++) {
00475                 do {
00476                         if (i >= c-1) break;
00477                         sym_int_token_rec *a = (sym_int_token_rec*)tokens->get(i);
00478                         sym_int_token_rec *b = (sym_int_token_rec*)tokens->get(i+1);
00479                         b_op rop;
00480                         sym_int_token *rtoken;
00481                         if (!simplify_reduce_const(a->bop, a->token, b->bop, b->token, &rop, &rtoken)) break;
00482                         tokens->del(i);
00483                         tokens->del(i);
00484                         tokens->insert_before(new sym_int_token_rec(u_null, rop, rtoken), i);
00485                         c--;
00486                 } while (c>=2);
00487         }
00488 
00489 /* II. NEUTRAL OPERATIONS
00490    reduce all "N$x..." (front, commutative) and "...x$N..." (everywhere) to "x"
00491    ($ operator, N neutral element for $) */
00492 
00493 /* step II.1: "N$x..." (front, commutative) */
00494         while (c>=2) {
00495                 sym_int_token_rec *a = (sym_int_token_rec*)tokens->get(0);
00496                 sym_int_token_rec *b = (sym_int_token_rec*)tokens->get(1);
00497                 if (!op_commutative[b->bop]) break;
00498                 if (!simplify_reduce_neutral(b->bop, a->token)) break;
00499                 tokens->del(0); // delete N/a
00500                 tokens->remove(0);      // remove x/b
00501                 tokens->prepend(new sym_int_token_rec(u_null, b_invalid, b->token));
00502                 c--;
00503         }
00504 
00505 /* step II.2: "...x$N..." (everywhere) */
00506         for (UINT i=0; i<c-1; i++) {
00507                 do {
00508                         if (i >= c-1) break;
00509                         sym_int_token_rec *a = (sym_int_token_rec*)tokens->get(i);
00510                         sym_int_token_rec *b = (sym_int_token_rec*)tokens->get(i+1);
00511                         if (!simplify_reduce_neutral(b->bop, b->token)) break;
00512                         tokens->remove(i);      // remove x/a
00513                         tokens->del(i); // delete N/b
00514                         tokens->insert_before(new sym_int_token_rec(a->uop, a->bop, a->token), i);
00515                         c--;
00516                 } while (c>=2);
00517         }
00518 
00519 /* III. DESTRUCTIVE OPERATIONS
00520    reduce all destructive (e.g. "...*0" -> 0) sub-expressions */
00521 
00522 /* step III.1: "y$x..." (front, commutative) */
00523         while (c>=2) {
00524                 sym_int_token_rec *a = (sym_int_token_rec*)tokens->get(0);
00525                 sym_int_token_rec *b = (sym_int_token_rec*)tokens->get(1);
00526                 if (!op_commutative[b->bop]) break;
00527                 sym_int_token *repl = simplify_reduce_destructive(b->bop, a->token);
00528                 if (!repl) break;
00529                 tokens->del(0); // delete y
00530                 tokens->del(0); // delete x
00531                 tokens->prepend(new sym_int_token_rec(u_null, b_invalid, repl));
00532                 c--;
00533         }
00534 
00535 /* step III.2: "...x$y..." (tail) */
00536         for (UINT i=1; i<c; i++) {
00537                 do {
00538                         if (i >= c) break;
00539                         sym_int_token_rec *a = (sym_int_token_rec*)tokens->get(i);
00540                         sym_int_token *repl = simplify_reduce_destructive(a->bop, a->token);
00541                         if (!repl) break;
00542                         UINT dc = i+1;
00543                         tokens->del_multiple(0, dc);
00544                         tokens->prepend(new sym_int_token_rec(u_null, b_invalid, repl));
00545                         c -= dc-1;
00546                 } while (c>=2);
00547         }
00548 
00549 /* IV. INVERSE OPERATIONS
00550    e.g. "...-x+x", "...^x^x", etc. */
00551 
00552 /* step IV.1: "...$x$xi..." (everywhere) */
00553         for (UINT i=0; i<c-1; i++) {
00554                 do {
00555                         if (i >= c-1) break;
00556                         sym_int_token_rec *a = (sym_int_token_rec*)tokens->get(i);
00557                         sym_int_token_rec *b = (sym_int_token_rec*)tokens->get(i+1);
00558                         sym_int_token *repl;
00559                         if (!simplify_reduce_inverse(a->bop, a->token, b->bop, b->token, &repl)) break;
00560                         tokens->del(i);
00561                         tokens->del(i);
00562                         c-=2;
00563                         if (repl) {
00564                                 tokens->insert_before(new sym_int_token_rec(a->uop, a->bop, repl), i);
00565                                 c++;
00566                         }
00567                 } while (c>=2);
00568         }
00569 
00570         } while (d != c);
00571 // op_destructive
00572 }
00573 
00574 bool sym_int::simplify_reduce_inverse(b_op oa, sym_int_token *a, b_op ob, sym_int_token *b, sym_int_token **repl)
00575 {
00576         *repl = NULL;
00577         bool eq = (a->object_id() == b->object_id()) ? a->compare_eq(b) : false;
00578         if (eq) {
00579                 if (oa == b_invalid) {
00580                         if ((ob == b_sub) || (ob == b_xor)) {
00581                         // a ^ a, a - a -> 0
00582                                 *repl = new sym_int_const(0);
00583                                 return true;
00584                         } else if ((ob == b_and) || (ob == b_or)) {
00585                         // a & a, a | a -> a
00586                                 *repl = (sym_int_token*)a->duplicate();
00587                                 return true;
00588                         }
00589                 } else if ((oa == b_add) && (ob == b_sub)) {
00590                 // +x-x -> _
00591                         return true;
00592                 } else if ((oa == b_sub) && (ob == b_add)) {
00593                 // -x+x -> _
00594                         return true;
00595                 }
00596         }
00597         return false;
00598 }
00599 
00600 sym_int_token *sym_int::simplify_reduce_destructive(b_op o, sym_int_token *x)
00601 {
00602 /* e.g. "x*0", "x&0" */
00603         op_int_int_prop *k = &op_destructive[o];
00604         if (k->has_prop) {
00605                 UINT X;
00606                 if ((x->evaluate(&X)) && (X == k->value1)) {
00607                         return new sym_int_const(k->value2);
00608                 }
00609         }
00610         return NULL;
00611 }
00612 
00613 bool sym_int::simplify_reduce_neutral(b_op o, sym_int_token *x)
00614 {
00615 /* reduce "x$N" case ($ operator, N neutral element for $) */
00616         op_int_prop *k = &op_neutrals[o];
00617         if (k->has_prop) {
00618                 UINT i;
00619                 if ((x->evaluate(&i)) && (k->value == i)) {
00620                                 return true;
00621                 }
00622         }
00623         return false;
00624 }
00625 
00626 bool sym_int::simplify_reduce_const(b_op oa, sym_int_token *a, b_op ob, sym_int_token *b, b_op *res_op, sym_int_token **res_token)
00627 {
00628         UINT A, B, C;
00629         if (!a->evaluate(&A)) return false;
00630         if (!b->evaluate(&B)) return false;
00631         if (oa == b_invalid) {
00632                 switch (ob) {
00633                         case b_add: C = A+B; break;
00634                         case b_sub: C = A-B; break;
00635                         case b_mul: C = A*B; break;
00636                         case b_div: if (!B) return false; else C = A/B; break;
00637                         case b_mod: if (!B) return false; else C = A%B; break;
00638                         case b_and: C = A&B; break;
00639                         case b_or:  C = A|B; break;
00640                         case b_xor: C = A^B; break;
00641                         case b_invalid: break;
00642                 }
00643                 *res_op = b_invalid;
00644         } else if ((oa == b_add) && (ob == b_sub)) {
00645                 C = A-B;
00646                 *res_op = b_add;
00647         } else if ((oa == b_sub) && (ob == b_add)) {
00648                 C = B-A;
00649                 *res_op = b_add;
00650         } else if ((oa == b_add) && (ob == b_add)) {
00651                 C = A+B;
00652                 *res_op = b_add;
00653         } else if ((oa == b_sub) && (ob == b_sub)) {
00654                 C = -A-B;
00655                 *res_op = b_add;
00656         } else if ((oa == b_or) && (ob == b_or)) {
00657                 C = A|B;
00658                 *res_op = b_or;
00659         } else if ((oa == b_and) && (ob == b_and)) {
00660                 C = A&B;
00661                 *res_op = b_and;
00662         } else if ((oa == b_or) && (ob == b_and) && ((A&B) == 0)) {
00663                 C = B;
00664                 *res_op = b_and;
00665         } else return false;
00666 
00667         if (((int)C<0) && (*res_op == b_add)) {
00668                 *res_op = b_sub;
00669                 C = -C;
00670         }
00671         *res_token = new sym_int_const(C);
00672         return true;
00673 }
00674 
00675 void sym_int::u_operate(u_op uop)
00676 {
00677 }
00678 
00679 /*
00680  *      CLASS sym_bool_symbol
00681  */
00682 
00683 sym_bool_symbol::sym_bool_symbol(char *n)
00684 {
00685         name = strdup(n);
00686 }
00687 
00688 sym_bool_symbol::~sym_bool_symbol()
00689 {
00690         free(name);
00691 }
00692 
00693 bool sym_bool_symbol::compare_eq(sym_bool_token *t)
00694 {
00695         sym_bool_symbol *s = (sym_bool_symbol*)t;
00696         return (strcmp(name, s->name) == 0);
00697 }
00698 
00699 Object *sym_bool_symbol::duplicate()
00700 {
00701         sym_bool_symbol *p = new sym_bool_symbol(name);
00702         return p;
00703 }
00704 
00705 bool sym_bool_symbol::evaluate(bool *i)
00706 {
00707         return false;
00708 }
00709 
00710 int sym_bool_symbol::nstrfy(char *buf, int n)
00711 {
00712         int q = strlen(name)+1;
00713         if (q > n) q = n;
00714         memmove(buf, name, q);
00715         return q-1;
00716 /* FIXME: use n */
00717 //      return sprintf(buf, "%s", name);
00718 }
00719 
00720 OBJECT_ID sym_bool_symbol::object_id() const
00721 {
00722         return ATOM_SYM_BOOL_SYMBOL;
00723 }
00724 
00725 /*
00726  *      CLASS sym_bool_token
00727  */
00728 
00729 bool sym_bool_token::evaluate(bool *i)
00730 {
00731         return false;
00732 }
00733 
00734 void sym_bool_token::simplify()
00735 {
00736 }
00737 
00738 /*
00739  *      CLASS sym_bool_const
00740  */
00741 
00742 sym_bool_const::sym_bool_const(bool v)
00743 {
00744         value = v;
00745 }
00746 
00747 bool sym_bool_const::compare_eq(sym_bool_token *t)
00748 {
00749         sym_bool_const *s = (sym_bool_const*)t;
00750         return (value == s->value);
00751 }
00752 
00753 bool sym_bool_const::evaluate(bool *i)
00754 {
00755         *i = value;
00756         return true;
00757 }
00758 
00759 int sym_bool_const::nstrfy(char *buf, int n)
00760 {
00761         const char *name = value ? "true" : "false";
00762         int q = strlen(name)+1;
00763         if (q > n) q = n;
00764         memmove(buf, name, q);
00765         return q-1;
00766 //      return sprintf(buf, "%s", value ? "true" : "false");
00767 }
00768 
00769 /*
00770  *      CLASS sym_bool_intcmp
00771  */
00772 
00773 sym_bool_intcmp::sym_bool_intcmp(sym_int_token *i1, c_op c, sym_int_token *i2)
00774 {
00775         int1 = i1;
00776         cop = c;
00777         int2 = i2;
00778 }
00779 
00780 bool sym_bool_intcmp::compare_eq(sym_bool_token *t)
00781 {
00782         sym_bool_intcmp *s = (sym_bool_intcmp*)t;
00783 /* FIXME: i1 == si2 && i2 == si1 */
00784         return (int1->compare_eq(s->int1) && int2->compare_eq(s->int2) && cop == s->cop);
00785 }
00786 
00787 Object *sym_bool_intcmp::duplicate()
00788 {
00789         return new sym_bool_intcmp((sym_int_token*)int1->duplicate(), cop, (sym_int_token*)int2->duplicate());
00790 }
00791 
00792 bool sym_bool_intcmp::evaluate(bool *i)
00793 {
00794         UINT e1, e2;
00795         bool e = false;
00796         if (!int1->evaluate(&e1)) return false;
00797         if (!int2->evaluate(&e2)) return false;
00798         switch (cop) {
00799                 case c_invalid: break;
00800                 case c_eq: e = (e1 == e2); break;
00801                 case c_ne: e = (e1 != e2); break;  
00802                 case c_gt: e = (e1 > e2); break;  
00803                 case c_ge: e = (e1 >= e2); break;  
00804                 case c_lt: e = (e1 < e2); break;  
00805                 case c_le: e = (e1 <= e2); break;  
00806         }
00807         *i = e;
00808         return true;
00809 }
00810 
00811 int sym_bool_intcmp::nstrfy(char *buf, int n)
00812 {
00813         int i = 0;
00814         dword C1, C2;
00815         if (int1->evaluate(&C1) && int2->evaluate(&C2)) {
00816                 bool r;
00817                 bool handled = true;
00818                 switch (cop) {
00819                         case c_eq: r = (C1 == C2); break;
00820                         case c_ne: r = (C1 != C2); break;
00821                         case c_gt: r = (C1 > C2); break;
00822                         case c_ge: r = (C1 >= C2); break;
00823                         case c_lt: r = (C1 < C2); break;
00824                         case c_le: r = (C1 <= C2); break;
00825                         default: handled = false;
00826                 }
00827                 if (handled) {
00828                         i += sprintf(buf, "%s", r ? "true" : "false");
00829                         return i;
00830                 }
00831         }
00832         i += int1->nstrfy(buf+i, n-i);
00833         switch (cop) {
00834                 case c_invalid: break;
00835                 case c_eq:  strcpy(buf+i, "=="); i+=2; break;
00836                 case c_ne:  strcpy(buf+i, "!="); i+=2; break;
00837                 case c_gt:  buf[i++] = '>'; break;
00838                 case c_ge:  strcpy(buf+i, ">="); i+=2; break;
00839                 case c_lt:  buf[i++] = '<'; break;
00840                 case c_le:  strcpy(buf+i, "<="); i+=2; break;
00841         }
00842         i += int2->nstrfy(buf+i, n-i);
00843         return i;
00844 }
00845 
00846 OBJECT_ID sym_bool_intcmp::object_id() const
00847 {
00848         return ATOM_SYM_BOOL_INTCMP;
00849 }
00850 
00851 void sym_bool_intcmp::simplify()
00852 {
00853         int1->simplify();
00854         int2->simplify();
00855 }
00856 
00857 /*
00858  *      CLASS sym_bool_token_rec
00859  */
00860  
00861 class sym_bool_token_rec: public Object {
00862 public:
00863         n_op nop;
00864         l_op lop;
00865         sym_bool_token *token;
00866         
00867         sym_bool_token_rec(n_op n, l_op l, sym_bool_token *t)
00868         {
00869                 nop = n;
00870                 lop = l;
00871                 token = t;              
00872         }
00873         
00874         ~sym_bool_token_rec()
00875         {
00876                 token->done();
00877                 delete token;
00878         }
00879         
00880         int nstrfy(char *buf, int n)
00881         {
00882                 int i = 0;
00883                 switch (nop) {
00884                         case n_null: break;
00885                         case n_not: buf[i++] = '!'; break;
00886                 }
00887                 switch (lop) {
00888                         case l_invalid: break;
00889                         case l_and: strcpy(buf+i, "&&"); i+=2; break;
00890                         case l_or:  strcpy(buf+i, "||"); i+=2; break;
00891                         case l_eq:  strcpy(buf+i, "=="); i+=2; break;
00892                         case l_ne:  strcpy(buf+i, "!="); i+=2; break;
00893                         case l_gt:  buf[i++] = '>'; break;
00894                         case l_ge:  strcpy(buf+i, ">="); i+=2; break;
00895                         case l_lt:  buf[i++] = '<'; break;
00896                         case l_le:  strcpy(buf+i, "<="); i+=2; break;
00897                 }
00898                 return i + token->nstrfy(buf+i, n-i);
00899         }
00900         
00901         Object *duplicate()
00902         {
00903                 return new sym_bool_token_rec(nop, lop, (sym_bool_token*)token->duplicate());
00904         }
00905 };
00906 
00907 /*
00908  *      CLASS sym_bool
00909  */
00910 
00911 sym_bool::sym_bool()
00912 {
00913         tokens = new ht_clist();
00914         ((ht_clist*)tokens)->init();
00915 }
00916 
00917 sym_bool::~sym_bool()
00918 {
00919         tokens->destroy();
00920         delete tokens;
00921 }
00922 
00923 bool sym_bool::compare_eq(sym_bool_token *t)
00924 {
00925 // FIXME: implement me !
00926         return false;
00927 }
00928 
00929 Object *sym_bool::duplicate()
00930 {
00931         sym_bool *p = new sym_bool();
00932         p->tokens = (ht_list*)tokens->duplicate();
00933         return p;
00934 }
00935 
00936 void sym_bool::clear()
00937 {
00938         tokens->destroy();
00939         delete tokens;
00940 
00941         tokens = new ht_clist();
00942         ((ht_clist*)tokens)->init();
00943 }
00944 
00945 bool sym_bool::evaluate(bool *i)
00946 {
00947         int c = tokens->count();
00948         bool l;
00949         for (int j = 0; j < c; j++) {
00950                 bool k;
00951                 sym_bool_token_rec *r = (sym_bool_token_rec*)tokens->get(j);
00952                 if (!r->token->evaluate(&k)) return false;
00953                 if (j == 0) l = k;
00954                 switch (r->nop) {
00955                         case n_null: break;
00956                         case n_not: k = !k; break;
00957                 }
00958                 switch (r->lop) {
00959                         case l_invalid: break;
00960                         case l_and: l = (l && k); break;
00961                         case l_or: l = (l || k); break;
00962                         case l_eq: l = (l == k); break;
00963                         case l_ne: l = (l != k); break;
00964                         case l_gt: l = (l > k); break;
00965                         case l_ge: l = (l >= k); break;
00966                         case l_lt: l = (l < k); break;
00967                         case l_le: l = (l <= k); break;
00968                 }
00969         }
00970         *i = l;
00971         return true;
00972 }
00973 
00974 void sym_bool::l_operate(l_op l, sym_bool_token *t)
00975 {
00976         tokens->insert(new sym_bool_token_rec(n_null, l, t));
00977 }
00978 
00979 int sym_bool::nstrfy(char *buf, int n)
00980 {
00981         int l = 0;
00982         int c = tokens->count();
00983         for (int i = 0; i < c; i++) {
00984                 sym_bool_token_rec *r = (sym_bool_token_rec*)tokens->get(i);
00985                 l += r->nstrfy(buf+l, n-l);
00986         }
00987         return l;
00988 }
00989 
00990 void sym_bool::set(sym_bool_token *t)
00991 {
00992         clear();
00993         tokens->insert(new sym_bool_token_rec(n_null, l_invalid, t));
00994 }
00995 
00996 void sym_bool::simplify()
00997 {
00998         int c = tokens->count();
00999         for (int i = 0; i < c; i++) {
01000                 sym_bool_token_rec *r = (sym_bool_token_rec*)tokens->get(i);
01001                 r->token->simplify();
01002         }
01003 }
01004 
01005 void sym_bool::n_operate(n_op n)
01006 {
01007 }
01008 
01009 OBJECT_ID sym_bool::object_id() const
01010 {
01011         return ATOM_SYM_BOOL;
01012 }
01013 

Generated on Fri May 7 21:15:44 2004 by doxygen 1.3.5