Polaris: expr_simplify_test.cc Source File

expr_simplify_test.cc

Go to the documentation of this file.
00001 /// Test routine for the simplification of expressions
00002 ///
00003 #include <stdio.h>
00004 #include <iostream.h>
00005 #include <ctype.h>
00006 #include <string.h>
00007 
00008 #include "../HeapStats.h"
00009 #include "../Type.h"
00010 #include "../String.h"
00011 #include "../Collection/RefList.h"
00012 #include "../Collection/Iterator.h"
00013 #include "../macros.h"
00014 #include "../utilities/switches_util.h"
00015 #include "../Symbol/Symbol.h"
00016 #include "../Symbol/VariableSymbol.h"
00017 #include "../Symbol/FunctionSymbol.h"
00018 #include "../Symtab.h"
00019 #include "../p-setjmp.h"
00020 #include "../debug.h"
00021 #include "../Info.h"
00022 #include "../OmegaInfo.h"
00023 
00024 #include "Expression.h"
00025 #include "Expression.all.h"
00026 #include "../Wildcard/Wildcard.all.h"
00027 #include "expr.h"
00028 #include "ExprSignature.h"
00029 
00030 void test_expr_str(char *);
00031 Expression *parse_expr (char *&, Symtab &);
00032 void skip_whitespace(char *&);
00033 Symbol *parse_symbol(char *&, Symtab &);
00034 long parse_int(char *&);
00035 Expression *parse_real(char *&);
00036 Expression *parse_op(char *&, Symtab &);
00037 Expression *parse_wildcard_op(char *&, Symtab &);
00038 Expression *parse_unary_expr(char *&, OP_TYPE, EXPR_TYPE, Symtab &);
00039 Expression *parse_binary_expr(char *&, OP_TYPE, EXPR_TYPE, Symtab &);
00040 Expression *parse_nonbinary_expr(char *&, OP_TYPE, EXPR_TYPE, Symtab &);
00041 Expression *parse_no_arg_wildcard_expr(char *&, OP_TYPE, Symtab &);
00042 Expression *parse_unary_wildcard_expr(char *&, OP_TYPE, Symtab &);
00043 Expression *parse_binary_wildcard_expr(char *&, OP_TYPE, Symtab &);
00044 Expression *parse_array_ref(char *&, Symtab &);
00045 Expression *parse_intrinsic_call(char *&, const String &, Symtab &);
00046 Expression *parse_function_call(char *&, const String &, Symtab &);
00047 Expression *parse_phi_expr(char *&, OP_TYPE, Symtab &);
00048 void parse_non_binary_args(char *&, Symtab &, Expression *);
00049 void parse_close_paren(char *&);
00050 void parse_close_angle_bracket(char *&);
00051 Expression * do_fold(Expression *, ExtraInfo &);
00052 struct fold_info { Wildcard *hook1, *hook2; };
00053 Boolean do_funny_check(const Expression &, ExtraInfo &);
00054 Expression * do_funny(Expression *, ExtraInfo &);
00055 struct funny2_info { Wildcard *hook1; };
00056 Expression * do_funny2(Expression *, ExtraInfo &);
00057 Boolean do_funny2_check(const Expression &, ExtraInfo &);
00058 Expression * do_funny3(Expression *, ExtraInfo &);
00059 void print_wildcard_matches(Expression &e);
00060 void traverse_action1(const Expression &subexpr, ExtraInfo &other_args);
00061 
00062 template class Info<funny2_info>;
00063 template class Info<fold_info>;
00064 
00065 ////////////////////////////////////////////////////////////
00066 
00067 int main(int argc, char *argv[])
00068 {
00069     FILE *infile;
00070     char expr_str[255];
00071     char *version = "1.0-35.5 May 24, 1995";
00072 
00073     char *intrin_file_name;
00074 
00075     int index = parse_switches( argc, argv, version, &intrin_file_name );
00076 
00077     if (index < 0) {
00078         cerr << "Error: can not open switches database, aborting.\n";
00079         exit(1);
00080     }
00081 
00082     dbx_full_parenthesization = 1;
00083     dbx_wildcards_debug_level = 1;
00084 
00085     if (index == argc)
00086         infile = stdin;
00087     else if (index == argc - 1) {
00088         infile = fopen(argv[index], "r");
00089         
00090         if (infile == 0)
00091             {
00092                 cerr << "Error: Couldn't open file " << argv[1] << endl;
00093                 exit(1);
00094             }
00095     }
00096     else {
00097         cerr << "Usage: " << argv[0] << " [file]\n";
00098         exit(1);
00099     }
00100 
00101     /// ...  The following code is just to hide a false memory leak in arg_list()
00102     /// ...  from the HeapStats module
00103 
00104     Expression *dummy = omega();
00105     (void) dummy->arg_list();
00106     delete dummy;
00107 
00108     HeapStats::restart();
00109 
00110     SETJUMP() {
00111         while (fgets(expr_str, 255, infile) != 0)
00112             if (expr_str[0] == ';')
00113                 cout << expr_str;
00114             else
00115                 test_expr_str(expr_str);
00116     }
00117 
00118     HeapStats::report(cout);
00119     HeapStats::print_memory_leaks(cout);
00120 }
00121 
00122 void
00123 test_expr_str(char *expr_str)
00124 {
00125     char *e_str = expr_str;
00126     HeapStats::reset();
00127     Symtab *symtab = new Symtab;
00128     
00129     if (e_str[0] == '=' && e_str[1] == '=') {
00130         e_str += 2;
00131         Expression *e1 = parse_expr(e_str, *symtab);
00132         Expression *e2 = parse_expr(e_str, *symtab);
00133         
00134         if (e1 && e2) {
00135             cout << "Comparing (" << *e1 << ") with (" << *e2 << ")\n";
00136             HeapStats::report(cout);
00137             
00138             if (*e1 == *e2)
00139                 cout << "**Expressions are EQUAL.\n";
00140             else
00141                 cout << "**Expressions are NOT equal.\n";
00142         }
00143 
00144         if (e1) delete e1;
00145         if (e2) delete e2;
00146         delete symtab;
00147         HeapStats::report(cout);
00148         HeapStats::print_memory_leaks(cout);
00149     }
00150     else if (strncmp(e_str, "backup ", 7) == 0) {
00151         e_str += 7;
00152 
00153         /// ...  This test is designed to test the resetting of wildcards
00154         /// ...  if a subexpression which they match at one point must be
00155         /// ...  abandoned because of a failed match later on.
00156 
00157         Expression *e1 = parse_expr(e_str, *symtab);
00158         Expression *e2 = parse_expr(e_str, *symtab);
00159 
00160         if (e1 && e2) {
00161             cout << "Comparing (" << *e1 << ") with (" << *e2 << ")\n";
00162 
00163         e1->standardize();
00164         e2->standardize();
00165         
00166             cout << "Before:\n";
00167             print_wildcard_matches(*e1);
00168             print_wildcard_matches(*e2);
00169             
00170             HeapStats::report(cout);
00171             
00172             if (*e1 == *e2)
00173                 cout << "**Expressions are EQUAL.\n";
00174             else
00175                 cout << "**Expressions are NOT equal.\n";
00176 
00177             cout << "After:\n";
00178             print_wildcard_matches(*e1);
00179             print_wildcard_matches(*e2);
00180         }
00181 
00182         if (e1) delete e1;
00183         if (e2) delete e2;
00184         delete symtab;
00185         HeapStats::report(cout);
00186         HeapStats::print_memory_leaks(cout);
00187     }
00188     else if (strncmp(e_str, "constant ", 9) == 0) {
00189         e_str += 9;
00190 
00191     /// ...  Test the ::constant(const char *) function from
00192     // Expression/expr_funcs.h
00193 
00194     while (e_str[strlen(e_str) - 1] == '\n') {
00195       e_str[strlen(e_str) - 1] = '\000';
00196     }
00197     
00198     if (*e_str) {
00199       cout << "Calling constant(const char *) with input: "
00200            << e_str << endl;
00201     }
00202 
00203     HeapStats::report(cout);
00204 
00205     Expression *e1 = ::constant(e_str);
00206 
00207     if (e1) {
00208       cout << "** Returned expression: " << *e1 << endl;
00209       delete e1;
00210     }
00211     else {
00212       cout << "** Returned ERROR **" << endl;
00213     }
00214 
00215     delete symtab;
00216         HeapStats::report(cout);
00217         HeapStats::print_memory_leaks(cout);
00218     }
00219     else if (strncmp(e_str, "sort ", 5) == 0) {
00220         e_str += 5;
00221         Expression *e1 = parse_expr(e_str, *symtab);
00222         
00223         if (e1) {
00224             cout << "Sorting (" << *e1 << ")\n";
00225             HeapStats::report(cout);
00226 
00227             e1->create_signature();
00228             cout << "**After creating signature: " << *e1 << endl;
00229             
00230             _sort_expr_list(e1->arg_list());
00231             cout << "**Result: " << *e1 << endl;
00232         }
00233 
00234         if (e1) delete e1;
00235         delete symtab;
00236         HeapStats::report(cout);
00237         HeapStats::print_memory_leaks(cout);
00238     }
00239     else if (strncmp(e_str, "match ", 6) == 0) {
00240         e_str += 6;
00241         Expression *e1 = parse_expr(e_str, *symtab);
00242         Expression *e2 = parse_expr(e_str, *symtab);
00243         
00244         if (e1 && e2) {
00245             cout << "Matching (" << *e1 << ") with (" << *e2 << ")\n";
00246             HeapStats::report(cout);
00247             
00248             if (e1->match(*e2))
00249                 cout << "**Expressions MATCH.\n";
00250             else
00251                 cout << "**Expressions do NOT match.\n";
00252         }
00253 
00254         if (e1) delete e1;
00255         if (e2) delete e2;
00256         delete symtab;
00257         HeapStats::report(cout);
00258         HeapStats::print_memory_leaks(cout);
00259     }
00260     else if (strncmp(e_str, "sum ", 4) == 0) {
00261         e_str += 4;
00262         Expression *e1 = parse_expr(e_str, *symtab);
00263         Expression *e2 = parse_expr(e_str, *symtab);
00264         Expression *e3 = parse_expr(e_str, *symtab);
00265         Expression *e4 = parse_expr(e_str, *symtab);
00266         
00267         if (e1 && e2 && e3 && e4) {
00268             cout << "SUM(" << *e1 << ", " << *e2 << ", " << 
00269                               *e3 << ", " << *e4 << ") " << endl;
00270 
00271             HeapStats::report(cout);
00272 
00273             e1 = sum( e1, *e2, *e3, *e4 );
00274 
00275             if (e1 != 0) {
00276                 cout << "**Result:  " << *e1 << endl;
00277             }
00278             else {
00279                 cout << "**Result:  UNKNOWN" << endl;
00280             }
00281         }
00282 
00283         if (e1) delete e1;
00284         if (e2) delete e2;
00285         if (e3) delete e3;
00286         if (e4) delete e4;
00287 
00288         delete symtab;
00289         HeapStats::report(cout);
00290         HeapStats::print_memory_leaks(cout);
00291     }
00292     else if (strncmp(e_str, "traverse ", 9) == 0) {
00293         e_str += 9;
00294         Expression *e = parse_expr(e_str, *symtab);
00295         Expression *pattern = parse_expr(e_str, *symtab);
00296         
00297         /// ...  Next we expect an option: 'non-recursive' or 'recursive'
00298         REPLACE_OPTION option = NON_RECURSIVE_REPLACE;
00299         skip_whitespace(e_str);
00300         if (strncmp(e_str, "non-recursive", 13) == 0) {
00301           option = NON_RECURSIVE_REPLACE;
00302           e_str += 13;
00303         }
00304         else if (strncmp(e_str, "recursive", 9) == 0) {
00305           option = RECURSIVE_REPLACE;
00306           e_str += 9;
00307         }
00308         else cout << "Missing REPLACE_OPTION: Assuming non-recursive\n";
00309 
00310         /// ...  Next we expect an order: 'pre' or 'post'
00311         REPLACE_ORDER order = POSTORDER_REPLACE;
00312         skip_whitespace(e_str);
00313         if (strncmp(e_str, "post", 4) == 0) {
00314           order = POSTORDER_REPLACE; e_str += 4; }
00315         else if (strncmp(e_str, "pre", 3) == 0) {
00316           order = PREORDER_REPLACE; e_str += 3; }
00317         else cout << "Missing REPLACE_ORDER: Assuming post\n";
00318 
00319         if (e && pattern) {
00320             cout << "Traversing (" << *e
00321          << ") using pattern ("
00322          << *pattern << ")\n";
00323             HeapStats::report(cout);
00324 
00325         cout << "**Results:\n";
00326 
00327         traverse(*e, *pattern, traverse_action1, (ExtraInfo &)* new Info<int>(0),
00328              option, order);
00329         }
00330 
00331         delete e;
00332         delete  pattern;
00333         delete symtab;
00334     
00335         HeapStats::report(cout);
00336         HeapStats::print_memory_leaks(cout);
00337     }
00338     else if (strncmp(e_str, "subst ", 6) == 0) {
00339         e_str += 6;
00340         Expression *e = parse_expr(e_str, *symtab);
00341         skip_whitespace(e_str);
00342         Symbol *var = parse_symbol(e_str, *symtab);
00343         Expression *value = parse_expr(e_str, *symtab);
00344 
00345         if (e && var && value) {
00346             cout << "Substituting " << var->name_ref() << "=" << *value
00347                  << " into " << *e << endl;
00348             HeapStats::report(cout);
00349             e = substitute_var(e, *var, *value);
00350             cout << "**Result:  " << *e << endl;
00351         }
00352 
00353         if (e) delete e;
00354         if (value) delete value;
00355         delete symtab;
00356         HeapStats::report(cout);
00357         HeapStats::print_memory_leaks(cout);
00358     }
00359     else if (strncmp(e_str, "replace ", 8) == 0) {
00360         e_str += 8;
00361         Expression *e = parse_expr(e_str, *symtab);
00362         skip_whitespace(e_str);
00363         Expression *pattern = parse_expr(e_str, *symtab);
00364         skip_whitespace(e_str);
00365         Expression *replacement = parse_expr(e_str, *symtab);
00366 
00367         /// ...  Next we expect an option: 'non-recursive' or 'recursive'
00368         REPLACE_OPTION option = NON_RECURSIVE_REPLACE;
00369         skip_whitespace(e_str);
00370         if (strncmp(e_str, "non-recursive", 13) == 0) {
00371           option = NON_RECURSIVE_REPLACE;
00372           e_str += 13;
00373         }
00374         else if (strncmp(e_str, "recursive", 9) == 0) {
00375           option = RECURSIVE_REPLACE;
00376           e_str += 9;
00377         }
00378         else cout << "Missing REPLACE_OPTION: Assuming non-recursive\n";
00379 
00380         /// ...  Next we expect an order: 'pre' or 'post'
00381         REPLACE_ORDER order = POSTORDER_REPLACE;
00382         skip_whitespace(e_str);
00383         if (strncmp(e_str, "post", 4) == 0) {
00384           order = POSTORDER_REPLACE; e_str += 4; }
00385         else if (strncmp(e_str, "pre", 3) == 0) {
00386           order = PREORDER_REPLACE; e_str += 3; }
00387         else cout << "Missing REPLACE_ORDER: Assuming post\n";
00388 
00389         if (e && pattern && replacement) {
00390             cout << "Replacing:\n  expr = "
00391                  << *e << "\n  pattern = "
00392                  << *pattern << "\n  replacement = "
00393                  << *replacement << "\n  options: "
00394                  << (option == NON_RECURSIVE_REPLACE ? "non-recursive "
00395                      : "recursive")
00396                  << ", "
00397                  << (order == PREORDER_REPLACE ? "pre-order" : "post-order")
00398                  << endl;
00399             HeapStats::report(cout);
00400             e = replace(e, *pattern, *replacement, option, order);
00401             cout << "**Result:  " << *e << endl;
00402         }
00403 
00404         if (e) delete e;
00405         if (pattern) delete pattern;
00406         if (replacement) delete replacement;
00407         delete symtab;
00408         HeapStats::report(cout);
00409         HeapStats::print_memory_leaks(cout);
00410     }
00411     else if (strncmp(e_str, "fold ", 5) == 0) {
00412         e_str += 5;
00413         Expression *e = parse_expr(e_str, *symtab);
00414         skip_whitespace(e_str);
00415 
00416         fold_info my_fold_info;
00417 
00418         Expression *pattern =
00419           add(my_fold_info.hook1 = any_int_const(),
00420               my_fold_info.hook2 = any_int_const());
00421               
00422         /// ...  Next we expect an option: 'non-recursive' or 'recursive'
00423         REPLACE_OPTION option = NON_RECURSIVE_REPLACE;
00424         skip_whitespace(e_str);
00425         if (strncmp(e_str, "non-recursive", 13) == 0) {
00426           option = NON_RECURSIVE_REPLACE;
00427           e_str += 13;
00428         }
00429         else if (strncmp(e_str, "recursive", 9) == 0) {
00430           option = RECURSIVE_REPLACE;
00431           e_str += 9;
00432         }
00433         else cout << "Missing REPLACE_OPTION: Assuming non-recursive\n";
00434 
00435         /// ...  Next we expect an order: 'pre' or 'post'
00436         REPLACE_ORDER order = POSTORDER_REPLACE;
00437         skip_whitespace(e_str);
00438         if (strncmp(e_str, "post", 4) == 0) {
00439           order = POSTORDER_REPLACE; e_str += 4; }
00440         else if (strncmp(e_str, "pre", 3) == 0) {
00441           order = PREORDER_REPLACE; e_str += 3; }
00442         else cout << "Missing REPLACE_ORDER: Assuming post\n";
00443 
00444         if (e && pattern) {
00445             cout << "Folding:\n  expr = "
00446                  << *e << "\n  pattern = "
00447                  << *pattern << "\n  options: "
00448                  << (option == NON_RECURSIVE_REPLACE ? "non-recursive "
00449                      : "recursive")
00450                  << ", "
00451                  << (order == PREORDER_REPLACE ? "pre-order" : "post-order")
00452                  << endl;
00453             HeapStats::report(cout);
00454             e = replace(e, *pattern,
00455                         do_fold, (ExtraInfo &)*new Info<fold_info>(my_fold_info),
00456                         option, order);
00457             cout << "**Result:  " << *e << endl;
00458         }
00459 
00460         if (e) delete e;
00461         if (pattern) delete pattern;
00462         delete symtab;
00463         HeapStats::report(cout);
00464         HeapStats::print_memory_leaks(cout);
00465     }
00466     else if (strncmp(e_str, "funny ", 6) == 0) {
00467         e_str += 6;
00468         Expression *e = parse_expr(e_str, *symtab);
00469         skip_whitespace(e_str);
00470 
00471         Expression *pattern = any_int_const();
00472               
00473         /// ...  Next we expect an option: 'non-recursive' or 'recursive'
00474         REPLACE_OPTION option = NON_RECURSIVE_REPLACE;
00475         skip_whitespace(e_str);
00476         if (strncmp(e_str, "non-recursive", 13) == 0) {
00477           option = NON_RECURSIVE_REPLACE;
00478           e_str += 13;
00479         }
00480         else if (strncmp(e_str, "recursive", 9) == 0) {
00481           option = RECURSIVE_REPLACE;
00482           e_str += 9;
00483         }
00484         else cout << "Missing REPLACE_OPTION: Assuming non-recursive\n";
00485 
00486         /// ...  Next we expect an order: 'pre' or 'post'
00487         REPLACE_ORDER order = POSTORDER_REPLACE;
00488         skip_whitespace(e_str);
00489         if (strncmp(e_str, "post", 4) == 0) {
00490           order = POSTORDER_REPLACE; e_str += 4; }
00491         else if (strncmp(e_str, "pre", 3) == 0) {
00492           order = PREORDER_REPLACE; e_str += 3; }
00493         else cout << "Missing REPLACE_ORDER: Assuming post\n";
00494 
00495         if (e && pattern) {
00496             cout << "Funny:\n  expr = "
00497                  << *e << "\n  pattern = "
00498                  << *pattern << "\n  options: "
00499                  << (option == NON_RECURSIVE_REPLACE ? "non-recursive "
00500                      : "recursive")
00501                  << ", "
00502                  << (order == PREORDER_REPLACE ? "pre-order" : "post-order")
00503                  << endl;
00504             HeapStats::report(cout);
00505             e = replace(e, *pattern,
00506                         do_funny_check, do_funny, (ExtraInfo &)*new OmegaInfo(),
00507                         option, order);
00508             cout << "**Result:  " << *e << endl;
00509         }
00510 
00511         if (e) delete e;
00512         if (pattern) delete pattern;
00513         delete symtab;
00514         HeapStats::report(cout);
00515         HeapStats::print_memory_leaks(cout);
00516     }
00517     else if (strncmp(e_str, "funny2 ", 7) == 0) {
00518         e_str += 7;
00519         Expression *e = parse_expr(e_str, *symtab);
00520         skip_whitespace(e_str);
00521 
00522         struct funny2_info info;
00523         
00524         Expression *pattern =
00525           add(
00526               info.hook1 = any_int_const(),
00527               constant(-1));
00528               
00529         /// ...  Next we expect an option: 'non-recursive' or 'recursive'
00530         REPLACE_OPTION option = NON_RECURSIVE_REPLACE;
00531         skip_whitespace(e_str);
00532         if (strncmp(e_str, "non-recursive", 13) == 0) {
00533           option = NON_RECURSIVE_REPLACE;
00534           e_str += 13;
00535         }
00536         else if (strncmp(e_str, "recursive", 9) == 0) {
00537           option = RECURSIVE_REPLACE;
00538           e_str += 9;
00539         }
00540         else cout << "Missing REPLACE_OPTION: Assuming non-recursive\n";
00541 
00542         /// ...  Next we expect an order: 'pre' or 'post'
00543         REPLACE_ORDER order = POSTORDER_REPLACE;
00544         skip_whitespace(e_str);
00545         if (strncmp(e_str, "post", 4) == 0) {
00546           order = POSTORDER_REPLACE; e_str += 4; }
00547         else if (strncmp(e_str, "pre", 3) == 0) {
00548           order = PREORDER_REPLACE; e_str += 3; }
00549         else cout << "Missing REPLACE_ORDER: Assuming post\n";
00550 
00551         if (e && pattern) {
00552             cout << "Funny2:\n  expr = "
00553                  << *e << "\n  pattern = "
00554                  << *pattern << "\n  options: "
00555                  << (option == NON_RECURSIVE_REPLACE ? "non-recursive "
00556                      : "recursive")
00557                  << ", "
00558                  << (order == PREORDER_REPLACE ? "pre-order" : "post-order")
00559                  << endl;
00560             HeapStats::report(cout);
00561             e = replace(e, *pattern,
00562                         do_funny2_check, do_funny2, (ExtraInfo &)*new Info<funny2_info>(info),
00563                         option, order);
00564             cout << "**Result:  " << *e << endl;
00565         }
00566 
00567         if (e) delete e;
00568         if (pattern) delete pattern;
00569         delete symtab;
00570         HeapStats::report(cout);
00571         HeapStats::print_memory_leaks(cout);
00572     }
00573     else if (strncmp(e_str, "funny3 ", 7) == 0) {
00574         e_str += 7;
00575         Expression *e = parse_expr(e_str, *symtab);
00576         skip_whitespace(e_str);
00577 
00578         /// ...  What we are going to do is the following:
00579         /// ...  Replace all integer constants with 100, unless it is
00580         /// ...  in an array reference, in which case replace it with 200
00581         /// ...  (this will use a recursive call to replace() inside of
00582         /// ...  the replacement function.
00583         
00584         Expression *pattern =
00585           wildcard_or(any_int_const(),
00586                       any_array_ref());
00587               
00588         REPLACE_OPTION option = NON_RECURSIVE_REPLACE;
00589         REPLACE_ORDER order = PREORDER_REPLACE;
00590 
00591         if (e && pattern) {
00592             cout << "Funny3:\n  expr = "
00593                  << *e << "\n  pattern = "
00594                  << *pattern << "\n";
00595             
00596             HeapStats::report(cout);
00597             e = replace(e, *pattern,
00598                         do_funny3, (ExtraInfo &)*new OmegaInfo(),
00599                         option, order);
00600             cout << "**Result:  " << *e << endl;
00601         }
00602 
00603         if (e) delete e;
00604         if (pattern) delete pattern;
00605         delete symtab;
00606         HeapStats::report(cout);
00607         HeapStats::print_memory_leaks(cout);
00608     }
00609     else if (strncmp(e_str, "clone ", 6) == 0) {
00610         e_str += 6;
00611         Expression *e = parse_expr(e_str, *symtab);
00612         Expression *clone = 0;
00613 
00614         if (e) {
00615             cout << "Cloning Expression " << *e << endl;
00616             HeapStats::report(cout);
00617             clone = e->clone();
00618             cout << "**Result:  " << *clone << endl;
00619         }
00620 
00621         if (e) delete e;
00622         if (clone) delete clone;
00623         delete symtab;
00624         HeapStats::report(cout);
00625         HeapStats::print_memory_leaks(cout);
00626     }
00627     else if (strncmp(e_str, "arg_refs ", 9) == 0) {
00628         e_str += 9;
00629         Expression *e = parse_expr(e_str, *symtab);
00630 
00631         if (e) {
00632             cout << "**Arg refs for: " << *e << endl;
00633             HeapStats::report(cout);
00634             const RefList<Expression> *args = e->arg_refs();
00635             Iterator<Expression> iter(*args);
00636 
00637             for ( ; iter.valid(); iter.next())
00638                 cout << "    " << iter.current() << endl;
00639 
00640             /// ...  delete args;
00641             delete e;
00642         }
00643 
00644         delete symtab;
00645         
00646         if (e) {
00647             HeapStats::report(cout);
00648             HeapStats::print_memory_leaks(cout);
00649         }
00650     }       
00651     else {
00652         Expression *e = parse_expr(e_str, *symtab);
00653         
00654         if (e) {
00655             cout << "**Before: " << *e << endl;
00656             HeapStats::report(cout);
00657             e = simplify(e);
00658             cout << "**After:  " << *e << endl;
00659             ExprSignature old_signature = e->signature();
00660             e->standardize();
00661 
00662             if (old_signature.hash_value() != e->signature().hash_value()) {
00663                 cout << "WARNING: Expr signature is not correct: ";
00664                 cout << "(" << e->signature();
00665                 cout << " should be " << old_signature << ")\n";
00666             }
00667 
00668             delete e;
00669         }
00670         else
00671             cout << endl;
00672         
00673         delete symtab;
00674         
00675         if (e) {
00676             HeapStats::report(cout);
00677             HeapStats::print_memory_leaks(cout);
00678         }
00679     }
00680 }
00681 
00682 Expression *
00683 parse_expr (char *& expr_str, Symtab &symtab)
00684 {
00685     char ch;
00686     
00687     skip_whitespace(expr_str);
00688     
00689     if (! *expr_str)
00690         return 0;
00691     
00692     if (isalpha(*expr_str)) {
00693         Symbol *sym = parse_symbol(expr_str, symtab);
00694 
00695         if (strcmp(sym->name_ref(), "TRUE") == 0)
00696             return constant(".TRUE.");
00697         else if (strcmp(sym->name_ref(), "FALSE") == 0)
00698             return constant(".FALSE.");
00699         else if (strcmp(sym->name_ref(), "NULL") == 0)
00700             return 0;
00701         else if (strcmp(sym->name_ref(), "OM") == 0)
00702             return omega();
00703         else if (strcmp(sym->name_ref(), "INF") == 0)
00704             return infinity();
00705         else
00706             return id(*sym);
00707     }
00708     else if (isdigit(*expr_str) || *expr_str == '-')
00709         return constant(parse_int(expr_str));
00710     else if (*expr_str == '#')
00711         return parse_real(expr_str);
00712     else if (*expr_str == '(')
00713         return parse_op(expr_str, symtab);
00714     else if (*expr_str == '<')
00715         return parse_wildcard_op(expr_str, symtab);
00716     else {
00717         cerr << "Expression Parser Error: Unrecognized char " << *expr_str
00718              << endl;
00719         ++expr_str;
00720         return 0;
00721     }
00722 }
00723 
00724 void
00725 skip_whitespace(char *& expr_str)
00726 {
00727     while (*expr_str && isspace(*expr_str))
00728         ++expr_str;
00729 }
00730 
00731 Symbol *
00732 parse_name(char *& expr_str, char buf[])
00733 {
00734     int i = 0;
00735     
00736     while (*expr_str && isalnum(*expr_str))
00737         buf[i++] = *(expr_str++);
00738     
00739     buf[i] = '\0';
00740     
00741     for (i = 0; buf[i] != '\0'; i++)
00742         if (islower(buf[i]))
00743             buf[i] = toupper(buf[i]);
00744 }
00745 
00746 Symbol *
00747 parse_symbol(char *& expr_str, Symtab &symtab)
00748 {
00749     Symbol *sym;
00750     char buf[100];
00751 
00752     parse_name(expr_str, buf);
00753     sym = symtab.find_ref(buf);
00754     
00755     if (! sym) {
00756         sym = new VariableSymbol(buf, make_type(INTEGER_TYPE),
00757                                  NOT_FORMAL, NOT_SAVED);
00758         symtab.ins(sym);
00759     }
00760     
00761     p_assert(sym->sym_class() == VARIABLE_CLASS,
00762          "Symbol is not a variable symbol.");
00763 
00764     return sym;
00765 }
00766 
00767 Symbol *
00768 parse_function_symbol(char *expr_str, Symtab &symtab)
00769 {
00770     Symbol *sym;
00771     char buf[100];
00772 
00773     parse_name(expr_str, buf);
00774     sym = symtab.find_ref(buf);
00775     
00776     if (! sym) {
00777         sym = new FunctionSymbol(buf, make_type(INTEGER_TYPE),
00778                  NOT_EXTERNAL, IS_INTRINSIC, NOT_FORMAL);
00779         symtab.ins(sym);
00780     }
00781     
00782     p_assert(sym->sym_class() == FUNCTION_CLASS,
00783          "Symbol is not a function symbol.");
00784 
00785     return sym;
00786 }
00787 
00788 long
00789 parse_int(char *& expr_str)
00790 {
00791     char buf[100];
00792     int i = 0;
00793     
00794     if (*expr_str == '-')
00795         buf[i++] = *(expr_str++);
00796     
00797     while (*expr_str && isdigit(*expr_str))
00798         buf[i++] = *(expr_str++);
00799     
00800     buf[i] = '\0';
00801     
00802     return (long) atoi(buf);
00803 }
00804 
00805 Expression *
00806 parse_real(char *& expr_str)
00807 {
00808     char buf[100];
00809     int i = 0;
00810     
00811     if (*expr_str == '#')
00812         ++expr_str;
00813     
00814     if (*expr_str == '-')
00815         buf[i++] = *(expr_str++);
00816     
00817     while (*expr_str && (isdigit(*expr_str) || *expr_str == '.'))
00818         buf[i++] = *(expr_str++);
00819     
00820     buf[i] = '\0';
00821     
00822     return constant(buf);
00823 }
00824 
00825 Expression *
00826 parse_op(char *& expr_str, Symtab &symtab)
00827 {
00828     char buf[100];
00829     int i = 0;
00830     
00831     if (*expr_str == '(')
00832         ++expr_str;
00833     
00834     skip_whitespace(expr_str);
00835     
00836     while (*expr_str && ! isspace(*expr_str)
00837            && *expr_str != '(' && *expr_str != ')')
00838         buf[i++] = *(expr_str++);
00839     
00840     buf[i] = '\0';
00841     
00842     String op(buf);
00843     
00844     if (op == "+")
00845         return parse_nonbinary_expr(expr_str, ADD_OP, INTEGER_TYPE, symtab);
00846     else if (op == "*")
00847         return parse_nonbinary_expr(expr_str, MULT_OP, INTEGER_TYPE, symtab);
00848     else if (op == "-")
00849         return parse_binary_expr(expr_str, SUB_OP, INTEGER_TYPE, symtab);
00850     else if (op == "/")
00851         return parse_binary_expr(expr_str, DIV_OP, INTEGER_TYPE, symtab);
00852     else if (op == "**")
00853         return parse_binary_expr(expr_str, EXP_OP, INTEGER_TYPE, symtab);
00854     else if (op == "[]")
00855         return parse_array_ref(expr_str, symtab);
00856     else if (op == "U-")
00857         return parse_unary_expr(expr_str, U_MINUS_OP, INTEGER_TYPE, symtab);
00858     else if (op == "U+")
00859         return parse_unary_expr(expr_str, U_PLUS_OP, INTEGER_TYPE, symtab);
00860     else if (op == "not")
00861         return parse_unary_expr(expr_str, NOT_OP, LOGICAL_TYPE, symtab);
00862     else if (op == "<")
00863         return parse_binary_expr(expr_str, LT_OP, LOGICAL_TYPE, symtab);
00864     else if (op == "<=")
00865         return parse_binary_expr(expr_str, LE_OP, LOGICAL_TYPE, symtab);
00866     else if (op == ">")
00867         return parse_binary_expr(expr_str, GT_OP, LOGICAL_TYPE, symtab);
00868     else if (op == ">=")
00869         return parse_binary_expr(expr_str, GE_OP, LOGICAL_TYPE, symtab);
00870     else if (op == "==")
00871         return parse_binary_expr(expr_str, EQ_OP, LOGICAL_TYPE, symtab);
00872     else if (op == "!=")
00873         return parse_binary_expr(expr_str, NE_OP, LOGICAL_TYPE, symtab);
00874     else if (op == "and")
00875         return parse_nonbinary_expr(expr_str, AND_OP, LOGICAL_TYPE, symtab);
00876     else if (op == "or")
00877         return parse_nonbinary_expr(expr_str, OR_OP, LOGICAL_TYPE, symtab);
00878     else if (op == "eqv")
00879         return parse_nonbinary_expr(expr_str, EQV_OP, LOGICAL_TYPE, symtab);
00880     else if (op == "neqv")
00881         return parse_nonbinary_expr(expr_str, NEQV_OP, LOGICAL_TYPE, symtab);
00882     else if (op == "gamma")
00883         return parse_phi_expr(expr_str, GAMMA_OP, symtab);
00884     else if (op == "mu")
00885         return parse_phi_expr(expr_str, MU_OP, symtab);
00886     else if (op == "min" || op == "max" || op == "mod" || op == "abs"
00887              || op == "ifix")
00888         return parse_intrinsic_call(expr_str, op, symtab);
00889     else
00890         return parse_function_call(expr_str, op, symtab);
00891 }
00892 
00893 Expression *
00894 parse_wildcard_op(char *& expr_str, Symtab &symtab)
00895 {
00896     char buf[100];
00897     int i = 0;
00898 
00899     if (*expr_str == '<')
00900       ++expr_str;
00901 
00902     skip_whitespace(expr_str);
00903     
00904     while (*expr_str && ! isspace(*expr_str)
00905            && *expr_str != '(' && *expr_str != ')' && *expr_str != '>')
00906         buf[i++] = *(expr_str++);
00907     
00908     buf[i] = '\0';
00909     
00910     String op(buf);
00911     
00912     if (op == ".")
00913         return parse_no_arg_wildcard_expr(expr_str, ANY_WC, symtab);
00914     if (op == ".*")
00915         return parse_no_arg_wildcard_expr(expr_str,
00916                                           ANY_EXPR_SUBSET_WC,
00917                                           symtab);
00918     if (op == "AnyID")
00919         return parse_no_arg_wildcard_expr(expr_str, ANY_ID_WC, symtab);
00920     if (op == "AnyArrayRef")
00921         return parse_no_arg_wildcard_expr(expr_str, ANY_ARRAY_REF_WC, symtab);
00922     if (op == "AnyIntConst")
00923         return parse_no_arg_wildcard_expr(expr_str, ANY_INT_CONST_WC,
00924                                           symtab);
00925     if (op == "AnyLogicalConst")
00926         return parse_no_arg_wildcard_expr(expr_str, ANY_LOGICAL_CONST_WC,
00927                                           symtab);
00928     else if (op == "NOT")
00929         return parse_unary_wildcard_expr(expr_str, NOT_WC, symtab);
00930     else if (op == "Contains")
00931         return parse_unary_wildcard_expr(expr_str, CONTAINS_WC, symtab);
00932     else if (op == "AND")
00933         return parse_binary_wildcard_expr(expr_str, AND_WC, symtab);
00934     else if (op == "OR")
00935         return parse_binary_wildcard_expr(expr_str, OR_WC, symtab);
00936     else {
00937       cerr << "Unrecognized WildCard '" << op << "'\n";
00938       return 0;
00939     }
00940 }
00941 
00942 Expression *
00943 parse_unary_expr(char *& expr_str, OP_TYPE op, EXPR_TYPE type, Symtab &symtab)
00944 {
00945     Expression *e = new UnaryExpr(op, make_type(type),
00946                                   parse_expr(expr_str, symtab));
00947     parse_close_paren(expr_str);
00948     
00949     return e;
00950 }
00951 
00952 Expression *
00953 parse_binary_expr(char *& expr_str, OP_TYPE op, EXPR_TYPE type, Symtab &symtab)
00954 {
00955     Expression *e = new BinaryExpr(op, make_type(type),
00956                                    parse_expr(expr_str, symtab),
00957                                    parse_expr(expr_str, symtab));
00958     parse_close_paren(expr_str);
00959     
00960     return e;
00961 }
00962 
00963 Expression *
00964 parse_nonbinary_expr(char *& expr_str, OP_TYPE op, EXPR_TYPE type,
00965                      Symtab &symtab)
00966 {
00967     Expression *e = new NonBinaryExpr(op, make_type(type));
00968     parse_non_binary_args(expr_str, symtab, e);
00969     return e;
00970 }
00971 
00972 Expression *
00973 parse_no_arg_wildcard_expr(char *& expr_str, OP_TYPE op, Symtab &symtab)
00974 {
00975   Expression *e = 0;
00976   
00977   switch(op) {
00978   case ANY_WC:
00979     e = new AnyExpr;
00980     break;
00981   case ANY_EXPR_SUBSET_WC:
00982     e = new AnyExprSubset;
00983     break;
00984   case ANY_ID_WC:
00985     e = new AnyID;
00986     break;
00987   case ANY_INT_CONST_WC:
00988     e = new AnyIntConst;
00989     break;
00990   case ANY_LOGICAL_CONST_WC:
00991     e = new AnyLogicalConst;
00992     break;
00993   default:
00994     p_assert(0, "Unrecognized No-Arg WildCard Type");
00995     break;
00996   }
00997 
00998   p_assert(e, "e is NULL");
00999   
01000   parse_close_angle_bracket(expr_str);
01001   return e;
01002 }
01003 
01004 Expression *
01005 parse_unary_wildcard_expr(char *& expr_str, OP_TYPE op, Symtab &symtab)
01006 {
01007   Expression *arg = parse_expr(expr_str, symtab);
01008 
01009   Expression *e = 0;
01010   
01011   switch(op) {
01012   case NOT_WC:
01013     e = new WildcardNot(arg);
01014     break;
01015   case CONTAINS_WC:
01016     e = new WildcardContains(arg);
01017     break;
01018   default:
01019     p_assert(0, "Unrecognized Unary WildCard Type");
01020     break;
01021   }
01022 
01023   p_assert(e, "e is NULL");
01024   
01025   parse_close_angle_bracket(expr_str);
01026   return e;
01027 }
01028 
01029 Expression *
01030 parse_binary_wildcard_expr(char *& expr_str, OP_TYPE op, Symtab &symtab)
01031 {
01032   Expression *left = parse_expr(expr_str, symtab);
01033   Expression *right = parse_expr(expr_str, symtab);
01034 
01035   Expression *e = 0;
01036   
01037   switch(op) {
01038   case AND_WC:
01039     e = new WildcardAnd(left, right);
01040     break;
01041   case OR_WC:
01042     e = new WildcardOr(left, right);
01043     break;
01044   default:
01045     p_assert(0, "Unrecognized Binary WildCard Type");
01046     break;
01047   }
01048 
01049   p_assert(e, "e is NULL");
01050   parse_close_angle_bracket(expr_str);
01051   return e;
01052 }
01053 
01054 Expression *
01055 parse_array_ref(char *& expr_str, Symtab &symtab)
01056 {
01057     Expression *array = parse_expr(expr_str, symtab);
01058     Expression *subscript = new CommaExpr();
01059     parse_non_binary_args(expr_str, symtab, subscript);
01060 
01061     return array_reference(array, subscript);
01062 }
01063 
01064 
01065 Expression *
01066 parse_intrinsic_call(char *& expr_str, const String &name, Symtab &symtab)
01067 {
01068     Symbol *nsym = parse_function_symbol(CASTAWAY(char *)(const char *)name, symtab);
01069     nsym->intrinsic(IS_INTRINSIC);
01070     Expression *args = new CommaExpr();
01071     parse_non_binary_args(expr_str, symtab, args);
01072 
01073     return intrinsic_call(id(*nsym), args);
01074 }
01075 
01076 
01077 Expression *
01078 parse_function_call(char *& expr_str, const String &name, Symtab &symtab)
01079 {
01080     Symbol *nsym = parse_function_symbol(CASTAWAY(char *)(const char *)name, symtab);
01081     nsym->intrinsic(NOT_INTRINSIC);
01082     Expression *args = new CommaExpr();
01083     parse_non_binary_args(expr_str, symtab, args);
01084 
01085     return function_call(id(*nsym), args);
01086 }
01087 
01088 Expression *
01089 parse_phi_expr(char *& expr_str, OP_TYPE op, Symtab &symtab)
01090 {
01091     Expression *gate = 0;
01092 
01093     if (op == GAMMA_OP)
01094         gate = parse_expr(expr_str, symtab);
01095 
01096     Expression *args = new CommaExpr();
01097     parse_non_binary_args(expr_str, symtab, args);
01098 
01099     switch (op) {
01100     case GAMMA_OP:
01101         return gamma(gate, args);
01102     case MU_OP:
01103         return mu(gate, args);
01104     default:
01105       return NULL;
01106     }
01107     return NULL;
01108 }
01109 
01110 
01111 void
01112 parse_non_binary_args(char *& expr_str, Symtab &symtab, Expression *nbe)
01113 {
01114     while (*expr_str && *expr_str != ')') {
01115         Expression *arg = parse_expr(expr_str, symtab);
01116         
01117         if (arg)
01118             nbe->arg_list().ins_last(arg);
01119     }
01120     
01121     parse_close_paren(expr_str);
01122 }
01123 
01124 void
01125 parse_close_paren(char *& expr_str)
01126 {
01127     skip_whitespace(expr_str);
01128     
01129     if (*expr_str != ')')
01130         cerr << "Missing closing ')' in expression string\n";
01131     else
01132         ++expr_str;
01133 }
01134 void
01135 parse_close_angle_bracket(char *& expr_str)
01136 {
01137     skip_whitespace(expr_str);
01138     
01139     if (*expr_str != '>')
01140         cerr << "Missing closing '>' in wildcard expression string\n";
01141     else
01142         ++expr_str;
01143 }
01144 
01145 Expression * do_fold(Expression * e,
01146                      ExtraInfo &extra_data) {
01147   fold_info & info = ((Info<fold_info> &) extra_data).data();
01148   p_assert(info.hook1->matched_exists() && info.hook2->matched_exists(),
01149            "One of the hooks didn't match");
01150 
01151   int folded_value = info.hook1->matched().value()
01152     + info.hook2->matched().value();
01153   delete e;
01154   return constant(folded_value);
01155 }
01156 
01157 /// replace_func (given an integer constant expr), increments the
01158 /// constant and adds to it a real constant 1.0 if the integer
01159 /// constant is less than 5.  (This is intended for testing the
01160 /// recursive option of replace.)
01161 Boolean do_funny_check(const Expression &e, ExtraInfo &other) {
01162   return (e.op() == INTEGER_CONSTANT_OP && e.value() < 4);
01163 }
01164 Expression * do_funny(Expression * e,
01165                       ExtraInfo &extra_data) {
01166   e->value(e->value() + 1);
01167   return add(constant("1.0"), e);
01168 }
01169 
01170 /// replace_func (given a sum of an integer constant expr
01171 /// and the constant -1), increments the
01172 /// constant and adds to it a constant -1 if the integer
01173 /// constant is less than 5.  (This is intended for testing the
01174 /// recursive option of replace.)
01175 
01176 Boolean do_funny2_check(const Expression &, ExtraInfo &other) {
01177   funny2_info & info = ((Info<funny2_info> &) other).data();
01178   p_assert(info.hook1->matched_exists(),
01179            "The hook didn't match");
01180 
01181   return (info.hook1->matched().value() < 5);
01182 }
01183 Expression * do_funny2(Expression *e,
01184                        ExtraInfo &extra_data) {
01185   funny2_info & info = ((Info<funny2_info> &) extra_data).data();
01186   p_assert(info.hook1->matched_exists(),
01187            "The hook didn't match");
01188 
01189   info.hook1->matched().value(info.hook1->matched().value() + 1);
01190   return add(constant(-1), e);
01191 }
01192 
01193 /// If was an intconst, replace with 100.  If was an arrayref,
01194 /// replace all intconsts within all args with 200.
01195 Expression * do_funny3(Expression * e,
01196                        ExtraInfo &) {
01197   switch(e->op()) {
01198   case INTEGER_CONSTANT_OP:
01199     delete e;
01200     return constant(100);
01201     break;
01202   case ARRAY_REF_OP:
01203     {
01204       Expression *repl = constant(200);
01205       Expression *pattern = any_int_const();
01206       Expression *new_e = replace(e, *pattern, *repl);
01207       delete repl;
01208       delete pattern;
01209       return new_e;
01210     }
01211     break;
01212   default:
01213     p_assert(False, "Error");
01214     return 0;
01215   }
01216 }
01217 
01218 ////////////////////////////////////////////////////////////
01219 /// manipulator class 'print_match' for use by the 'backup' test
01220 /// (not exactly necessary, but fun and good experience! :-)
01221 
01222 class print_match {
01223   private:
01224     Wildcard &_w;
01225   public:
01226     print_match(Wildcard &w) : _w(w) { }
01227 friend ostream & operator << (ostream &o, const print_match &pm) {
01228     if (pm._w.matched_exists()) {
01229         o << "(matched [ " << pm._w.matched() << " ])";
01230     }
01231     else {
01232         o << "(No Match)";
01233     }
01234     return o;
01235 }
01236 };
01237 
01238 void print_wildcard_matches(Expression &e) {
01239     if (e.is_wildcard()) {
01240         cout << "  Wildcard '" << e << "': "
01241              << print_match((Wildcard&)e)
01242              << endl;
01243     }
01244     for (Iterator<Expression> iter = e.arg_list(); iter.valid(); ++iter) {
01245         print_wildcard_matches(iter.current());
01246     }
01247 }
01248 
01249 ////////////////////////////////////////////////////////////
01250 /// traverse actions
01251 
01252 void
01253 traverse_action1(const Expression &subexpr, ExtraInfo &other_args) {
01254     cout << "**  Traversal match: " << subexpr << endl;
01255 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:47 2005