00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #include "tree_checker.h"
00039 #include "print_walker.h"
00040 
00041 void TreeChecker::setPreDismantled(const char * nodeType, Node * node) {
00042   _preDismantled = true;
00043   if ( _verbose )
00044     cout << nodeType << " node (" << node << ") set the pre-dismantled flag."
00045          << endl;
00046 }
00047 
00048 void TreeChecker::setPostDismantled(const char * nodeType, Node * node) {
00049   _postDismantled = true;
00050   if ( _verbose )
00051     cout << nodeType << " node (" << node << ") set the post-dismantled flag."
00052          << endl;
00053 }
00054 
00055 void TreeChecker::checkTree (Node * n, const char * type) {
00056   if (_visitedNodes[n]++ > 0) {
00057     cout << "Error: " << type << " node (" << n << ") has been visited "
00058          << _visitedNodes[n] << " times.\n";
00059     print_walker::print(n, cout);
00060     _errorCount++;
00061   }
00062   else if (_verbose) 
00063     cout << "Visiting " << type << " node (" << n << ").\n";
00064 }
00065 
00066 void TreeChecker::checkField (Node * node, Node * field, 
00067                               const char * type, const char * fieldName, 
00068                               bool isError ) {
00069   if (! field) {
00070     if (isError) {
00071       cout << "Error: " << type << " node (" << node 
00072            << ") has empty " << fieldName << " field.\n";
00073       _errorCount++;
00074     }
00075     else if (_warning)
00076       cout << type << " node (" << node << ") has empty "
00077            << fieldName << " field.\n";
00078   }
00079   else if (_verbose) 
00080     cout << type << " node (" << node << ") has " << fieldName
00081          << " field = " << field << ".\n";
00082 }
00083 
00084 void TreeChecker::checkString (Node * node, string & field, 
00085                                const char * type, const char * fieldName, 
00086                                bool isError ) {
00087   if (field == "") {
00088     if (isError) {
00089       cout << "Error: " << type << " node (" << node 
00090            << ") has empty " << fieldName << " field.\n";
00091       _errorCount++;
00092     }
00093     else if (_warning)
00094       cout << type << " node (" << node << ") has empty "
00095            << fieldName << " field.\n";
00096   }
00097   else if (_verbose) 
00098     cout << type << " node (" << node << ") has " << fieldName
00099          << " field = " << field << ".\n";
00100 }
00101 
00102 void TreeChecker::checkConstant (Node * node, constant & field, 
00103                                  const char * type, const char * fieldName, 
00104                                  bool isError ) {
00105   if (field.no_val()) {
00106     if (isError) {
00107       cout << "Error: " << type << " node (" << node
00108            << ") has non-constant " << fieldName << " field.\n";
00109       _errorCount++;
00110     }
00111     else
00112       cout << type << " node (" << node << ") has non-constant "
00113            << fieldName << " field.\n";
00114   }
00115   else if (_verbose) 
00116     cout << type << " node (" << node << ") has " << fieldName
00117          << " field = " << field.to_string() << ".\n";
00118 }
00119 
00120 template <class T>
00121 void TreeChecker::checkOperator(Node * node, Operator * field, 
00122                                 const char * type, const char * fieldName, 
00123                                 T check, string desc,
00124                                 bool isError ) {
00125   if (! field) {
00126     if (isError) {
00127       cout << "Error: " << type << " node (" << node
00128            << ") has empty " << fieldName << " field.\n";
00129       _errorCount++;
00130     }
00131     else if (_warning)
00132       cout << type << " node (" << node << ") has empty "
00133            << fieldName << " field.\n";
00134   }
00135   else {
00136     if ( ! check(field) ) {
00137       cout << "Error: " << type << " node (" << node
00138            << ") has non-" << desc << " " << fieldName << endl;
00139       _errorCount++;
00140     }
00141   }
00142 }
00143 
00144 template <class T>
00145 void TreeChecker::checkFieldInList (Node * node, list<T> & field, 
00146                                     const char * type, 
00147                                     const char * fieldName,
00148                                     int count, list<T> & collection, 
00149                                     const char * itemName, 
00150                                     bool isError ) {
00151   if (field.empty()) {
00152     if (isError) {
00153       cout << "Error: " << type << " node (" << node
00154            << ") has empty " << fieldName << " field.\n";
00155       _errorCount++;
00156     }
00157     else if (_warning)
00158       cout << type << " node (" << node << ") has empty "
00159            << fieldName << " field.\n";
00160   }
00161   else {
00162     if (field.size() != count) {
00163       cout << "Error: " << type << " node (" << node
00164            << ") has incorrect count for the " 
00165            << fieldName << " field ";
00166       cout << "<" << field.size() << " != " << count << ">.\n";
00167       _errorCount++;
00168 
00169       typename list<T>::iterator lp;
00170       for (lp = field.begin() ; lp != field.end() ; lp++) {
00171         typename list<T>::iterator p;
00172         p = find(collection.begin(), collection.end(), (*lp));
00173         if (p == collection.end())
00174           cout << "  Invalid " << itemName << " node (" 
00175                << (*lp) << ")\n";
00176         else if (_verbose)
00177           cout << "  " << itemName << " node (" << (*lp) << ")\n";
00178       }
00179     }
00180     else {
00181       if (_verbose) {
00182         cout << type << " node (" << node << ") has " 
00183              << field.size() << " " << fieldName;
00184         cout << (field.size() > 1 ? "s:\n" : ":\n");
00185       }
00186       typename list<T>::iterator lp;
00187       for (lp = field.begin() ; lp != field.end() ; lp++) {
00188         typename list<T>::iterator p;
00189         p = find(collection.begin(), collection.end(), (*lp));
00190         if (p == collection.end()) {
00191           cout << "Error: " << type << " node (" << node 
00192                << ") has invalid " << itemName << " reference at "
00193                << (*lp) << ".\n";
00194           _errorCount++;
00195         }
00196         else if (_verbose) 
00197           cout << "  " << itemName << " node (" << (*lp) << ")\n";
00198       }
00199     }
00200   }
00201 }
00202 
00203 template <class T>
00204 void TreeChecker::checkList (Node * node, list<T> & field, 
00205                              const char * type, 
00206                              const char * fieldName, 
00207                              bool isError ) {
00208   if (field.empty()) {
00209     if (isError) {
00210       cout << "Error: " << type << " node (" << node
00211            << ") has empty " << fieldName << " field.\n";
00212       _errorCount++;
00213     }
00214     else if (_warning)
00215       cout << type << " node (" << node << ") has empty "
00216            << fieldName << " field.\n";
00217   }
00218   else if (_verbose) {
00219     cout << type << " node (" << node << ") has " << field.size()
00220          << " " << fieldName;
00221     cout << (field.size() > 1 ? "s:\n" : ":\n");
00222   }
00223 }
00224 
00225 template <class T>
00226 void TreeChecker::checkFieldInList (Node * node, T field, const char * type, 
00227                                     const char * fieldName, 
00228                                     list<T> & collection, 
00229                                     bool isError ) {
00230   if (! field) {
00231     if (isError) {
00232       cout << "Error: " << type << " node (" << node 
00233            << ") has empty " << fieldName << " field.\n";
00234       _errorCount++;
00235     }
00236     else if (_warning)
00237       cout << type << " node (" << node << ") has empty "
00238            << fieldName << " field.\n";
00239   }
00240   else {
00241     typename list<T>::iterator lp;
00242     lp = find(collection.begin(), collection.end(), field);
00243     if (lp == _labels.end()) {
00244       cout << "Error: " << type << " node (" << node << ") has invalid ";
00245       cout << fieldName << " reference at " << field << ".\n";
00246       _errorCount++;
00247     }
00248     else if (_verbose) 
00249       cout << type << " node (" << node << ") has " << fieldName
00250            << " field = " << field << ".\n";
00251   }
00252 }
00253 
00254 TreeChecker::TreeChecker () : 
00255   Walker(Both, Subtree), _preDismantled(false), _postDismantled(false),
00256   _verbose(false), _errorCount(0), _typeDepth(0)
00257 {}
00258 
00259 TreeChecker::TreeChecker (bool verbose, bool warning) : 
00260   Walker(Both, Subtree), _preDismantled(false), _postDismantled(false), 
00261   _verbose(verbose), _warning(warning), _errorCount(0), _typeDepth(0)
00262 {}
00263 
00264 TreeChecker::~TreeChecker () {
00265   _visitedNodes.clear();
00266   _gotos.clear();
00267   _labels.clear();
00268   _procs.clear();
00269   _dupProcs.clear();
00270   _switches.clear();
00271   _decls.clear();
00272   _gotoCount.clear();
00273   _formals.clear();
00274 }
00275 
00276 void TreeChecker::check() {
00277   for ( unit_list_p u = CBZ::Program.begin(); u != CBZ::Program.end(); u++ )
00278     check(*u);
00279 }
00280 
00281 void TreeChecker::check(unitNode * the_unit) {
00282   TreeChecker tc;
00283   the_unit->walk(tc);
00284 }
00285 
00286 void TreeChecker::at_node(Node * the_node, Order ord) {
00287   if ( ord == Preorder ) {
00288     checkTree(the_node, "Node");
00289   }
00290 }
00291 
00292 void TreeChecker::at_unit (unitNode * unit, Order ord) {
00293   if (ord == Preorder) {
00294     UnitWalker uw;
00295     unit->walk(uw);  
00296     _procs = uw.procs();  
00297     _dupProcs = uw.dupProcs();  
00298     _formals = uw.formals();  
00299   }
00300 }
00301 
00302 void TreeChecker::at_proc (procNode * proc, Order ord) {
00303   if (ord == Preorder) {
00304     ProcWalker pw;
00305     proc->walk(pw);  
00306     _labels = pw.labels();
00307     _gotos = pw.gotos();
00308     _gotoCount = pw.gotoCount();
00309     _switches = pw.switches();
00310     _decls = pw.decls();
00311     _errorCount = 0;
00312     _preDismantled = false;
00313     _postDismantled = false;
00314 
00315     cout << "\n---- Begin: Procedure \"" << proc->decl()->name()
00316          << "\"----\n";
00317 
00318     
00319     proc_list_p dup = find(_dupProcs.begin(), _dupProcs.end(), proc);
00320     if (dup != _dupProcs.end()) {  
00321       _errorCount++;
00322       cout << "Error: Procedure \"" << proc->decl()->name() 
00323            << "\" at (" << proc << ") is re-declared.\n";
00324     }
00325   }
00326   else { 
00327     if (_preDismantled && _postDismantled) 
00328       cout << "Note: Procedure \"" << proc->decl()->name()
00329            << "\" contains both dismantled and non-dismantled Nodes.\n";
00330     cout << "---- End: Procedure \"" << proc->decl()->name()
00331          << "\"----\n====> ";
00332     if (_errorCount == 0) 
00333       cout << "Procedure \"" << proc->decl()->name()
00334            << "\" has no detected errors.\n";
00335     else { 
00336       cout << "Procedure \"" << proc->decl()->name() << "\" has "
00337            << _errorCount << " error" 
00338            << (_errorCount > 1 ? "s.\n" : ".\n");
00339     }
00340   }
00341 }
00342 
00343 void TreeChecker::at_decl(declNode * the_decl, Order ord) {
00344   if ( ord == Preorder ) {
00345     checkTree(the_decl, "Decl");
00346     
00347     checkField(the_decl, the_decl->type(), "Decl", "type");
00348     if (arrayNode * the_array = dynamic_cast<arrayNode *>(the_decl->type())) {
00349       
00350       if ( ! the_array->dim() ) {
00351         setPreDismantled("Decl", the_decl);
00352       } else {
00353         the_array->dim()->eval();
00354         checkConstant(the_decl, the_array->dim()->value(), "Decl", "dim");
00355       }
00356     }
00357   }
00358 }
00359 
00360 
00361 void TreeChecker::at_case (caseNode * the_case, Order ord) {
00362   if (ord == Preorder) {
00363     setPreDismantled("Case", the_case);
00364     checkTree(the_case, "Case");
00365     
00366     checkField(the_case, the_case->expr(), "Case", "expr", false);
00367     if (the_case->expr()) {  
00368       the_case->expr()->eval();  
00369       checkConstant(the_case, the_case->expr()->value(), "Case", "expr");
00370     }
00371     checkField(the_case, the_case->stmt(), "Case", "statement");
00372     checkFieldInList(the_case, the_case->container(), "Case", "switch", 
00373                      _switches);
00374   }
00375 }
00376 
00377 void TreeChecker::at_label (labelNode * the_label, Order ord) {
00378   if (ord == Preorder) {
00379     checkTree(the_label, "Label");
00380     checkString(the_label, the_label->name(), "Label", "name");
00381     checkField(the_label, the_label->stmt(), "Label", "statement");
00382     
00383     checkFieldInList(the_label, the_label->references(), "Label", "reference", 
00384                      _gotoCount[the_label], _gotos, "goto", false);
00385 
00386     if (the_label->stmt()) {  
00387       stmt_list stmts = the_label->stmt()->stmts();
00388       if (stmts.size() == 0) {
00389         if (_verbose || _warning)
00390           cout << "Label node (" << the_label << ") has an empty block.\n";
00391         setPreDismantled("Label", the_label);
00392       }
00393       else if (stmts.size() > 1) {
00394         if (_verbose || _warning)
00395           cout << "Label node (" << the_label
00396                << ") has a block with multiple statements.\n";
00397         setPreDismantled("Label", the_label);
00398       }
00399       else {
00400         stmtNode * stmt = stmts.front();  
00401         if (stmt->typ() == Expr) {
00402           exprstmtNode * exprstmt = (exprstmtNode *) stmt;
00403           exprNode * expr = exprstmt->expr();
00404           if (expr) {
00405             if (_verbose || _warning)
00406               cout << "Label node (" << the_label 
00407                 << ") has a block with non-empty expression statement.\n";
00408             setPreDismantled("Label", the_label);
00409           }
00410           else {
00411             if (_verbose || _warning)
00412               cout << "Label node (" << the_label
00413                    << ") has a block with an empty expression statement.\n";
00414           }
00415         }
00416         else {
00417           if (_verbose || _warning)
00418             cout << "Label node (" << the_label 
00419                  << ") has a block with non-expression statement.\n";
00420           setPreDismantled("Label", the_label);
00421         }
00422       }
00423     }
00424   }
00425 }
00426 
00427 
00428 void TreeChecker::at_goto (gotoNode * the_goto, Order ord) {
00429   if (ord == Preorder) {
00430     checkTree(the_goto, "Goto");
00431     checkString(the_goto, the_goto->name(), "Goto", "name");
00432     checkFieldInList(the_goto, the_goto->label(), "Goto", "label", _labels);
00433   }
00434 }
00435 
00436 class ComparisonOperator : public OperatorCheck {
00437 public:
00438   bool operator()(Operator * op) {
00439     return op->is_comparison();
00440   }
00441   string desc() { return string("comparison"); }
00442 };
00443 
00444 void TreeChecker::at_conditiongoto (conditiongotoNode * the_condgoto, 
00445                                     Order ord) {
00446   if (ord == Preorder) {
00447     setPostDismantled("Condition goto", the_condgoto);
00448     checkTree(the_condgoto, "Condition goto");
00449     checkField(the_condgoto, the_condgoto->left(), "Condition goto", 
00450                "left operand");
00451     checkField(the_condgoto, the_condgoto->right(), "Condition goto", 
00452                "right operand");
00453     ComparisonOperator co;
00454     checkOperator(the_condgoto, the_condgoto->op(), "Condition goto",
00455                   "operator", co, co.desc());
00456   }
00457 }
00458 
00459 void TreeChecker::at_break (breakNode * the_break, Order ord) {
00460   if (ord == Preorder) {
00461     setPreDismantled("Break", the_break);
00462     checkTree(the_break, "Break");
00463     checkField(the_break, the_break->container(), "Break", "container");
00464   }
00465 }
00466 
00467 void TreeChecker::at_continue (continueNode * the_continue, Order ord) {
00468   if (ord == Preorder) {
00469     setPreDismantled("Continue", the_continue);
00470     checkTree(the_continue, "Continue");
00471     checkField(the_continue, the_continue->container(), "Continue", 
00472                "container");
00473   }
00474 }
00475 
00476 void TreeChecker::at_return (returnNode * the_return, Order ord) {
00477   if (ord == Preorder) {
00478     checkTree(the_return, "Return");
00479     
00480     checkField(the_return, the_return->expr(), "Return", "expr", false);
00481     
00482     if (the_return->expr()) {
00483       if (the_return->expr()->typ() != Id) { 
00484         setPreDismantled("Return", the_return);
00485         if (_verbose || _warning) 
00486           cout << "Return node (" << the_return 
00487                << ") has non id return type.\n";
00488       }
00489       else if (_verbose || _warning) 
00490         cout << "Return node (" << the_return << ") has id return type.\n";
00491     }
00492     checkFieldInList(the_return, the_return->proc(), "Return", "proc", _procs);
00493   }
00494 }
00495 
00496 
00497 void TreeChecker::at_if (ifNode * the_if, Order ord) {
00498   if (ord == Preorder) {
00499     setPreDismantled("If", the_if);
00500     checkTree(the_if, "If");
00501     checkField(the_if, the_if->expr(), "If", "expr");
00502     
00503     checkField(the_if, the_if->true_br(), "If", "true-branch");
00504     
00505     checkField(the_if, the_if->false_br(), "If", "false-branch", false);
00506   }
00507 }
00508 
00509 void TreeChecker::at_switch (switchNode * the_switch, Order ord) {
00510   if (ord == Preorder) {
00511     setPreDismantled("Switch", the_switch);
00512     checkTree(the_switch, "Switch");
00513     checkField(the_switch, the_switch->expr(), "Switch", 
00514                "conditional expression");
00515     checkField(the_switch, the_switch->stmt(), "Switch", "statements");
00516     checkList(the_switch, the_switch->cases(), "Switch", "cases");
00517     
00518     
00519   }
00520 }
00521 
00522 
00523 void TreeChecker::at_for(forNode * the_for, Order ord) {
00524   if ( ord == Preorder ) {
00525     setPreDismantled("For-loop", the_for);
00526     checkTree(the_for, "For-loop");
00527     
00528     checkField(the_for, the_for->cond(), "For-loop", "expr", false);
00529     checkField(the_for, the_for->body(), "For-loop", "body");
00530   }
00531 }
00532 
00533 void TreeChecker::at_loop (loopNode * loop, Order ord) {
00534   if (ord == Preorder) {
00535     setPreDismantled("Loop", loop);
00536     checkTree(loop, "Loop");
00537     checkField(loop, loop->cond(), "Loop", "expr");
00538     checkField(loop, loop->body(), "Loop", "body");
00539   }
00540 }
00541 
00542 
00543 void TreeChecker::at_call (callNode * the_call, Order ord) {
00544   if (ord == Preorder) {
00545     if ( _typeDepth == 0 )
00546       setPreDismantled("Call", the_call);
00547     checkTree(the_call, "Call");
00548     checkField(the_call, the_call->name(), "Call", "name");
00549     
00550     checkList(the_call, the_call->args(), "Call", "argument list", false);
00551     
00552     
00553     checkField(the_call, the_call->proc(), "Call", "procedure", false);
00554 
00555     
00556     
00557     if (the_call->name()) {
00558       if (the_call->name()->typ() == Id) {
00559         
00560         idNode * id = (idNode *) the_call->name();
00561         if ( _formals.find(id->name()) != _formals.end() ) {
00562           if ( _formals[id->name()] != the_call->args().size() ) {
00563             cout << "Error: Call node (" << the_call
00564                  << ") has incorrect number of arguments = " 
00565                  << the_call->args().size() << ".\n";
00566             _errorCount++;
00567           } else if (_verbose || _warning) {
00568             cout << "Call node (" << the_call << ") has " 
00569                  << the_call->args().size() << " argument";
00570             cout << ((the_call->args().size() > 1) ? "s.\n" : ".\n");
00571           }
00572         }
00573       } else {
00574         
00575         
00576         cout << "Unable to check that the actual arguments for call node ("
00577              << the_call << ") match the number of formal parameters." << endl;
00578       }
00579     }
00580     
00581     
00582   }
00583 }
00584 
00585 void TreeChecker::at_id (idNode * id, Order ord) {
00586   if (ord == Preorder) {
00587     checkTree(id, "Id");
00588     checkString(id, id->name(), "Id", "name");
00589     checkFieldInList(id, id->decl(), "Id", "decl", _decls);
00590     
00591   }
00592 }
00593 
00594 void TreeChecker::at_const (constNode * the_const, Order ord) {
00595   if (ord == Preorder) {
00596     checkTree(the_const, "Const");
00597     the_const->eval();  
00598     checkConstant(the_const, the_const->value(), "Const", "value");
00599   }
00600 }
00601 
00602 class UnaryOperator : OperatorCheck {
00603 public:
00604   virtual bool operator()(Operator * op) { return op->is_unary(); }
00605   virtual string desc() { return string("unary"); }
00606 };
00607 
00608 void TreeChecker::at_unary (unaryNode * unary, Order ord) {
00609   if (ord == Preorder) {
00610     if ( _typeDepth == 0 )
00611       setPreDismantled("Unary", unary);
00612     checkTree(unary, "Unary");
00613     UnaryOperator uo;
00614     checkOperator(unary, unary->op(), "Unary", "operator", uo, uo.desc());
00615     if ( unary->op()->id() != Operator::SIZEOF ) {
00616       checkField(unary, unary->expr(), "Unary", "expr");
00617     } else {
00618       checkField(unary, unary->sizeof_type(), "Unary", "sizeof_type");
00619     }
00620   }
00621 }
00622 
00623 class BinaryOperator : public OperatorCheck {
00624 public:
00625   bool operator()(Operator * op) {
00626     return op->is_binary();
00627   }
00628   string desc() { return string("binary"); }
00629 };
00630 
00631 void TreeChecker::at_binary (binaryNode * binary, Order ord) {
00632   if (ord == Preorder) {
00633     if ( _typeDepth == 0 )
00634       setPreDismantled("Binary", binary);
00635     checkTree(binary, "binary");
00636     BinaryOperator bo;
00637     checkOperator(binary, binary->op(), "Binary", "operator", bo, bo.desc());
00638     checkField(binary, binary->left(), "Binary", "left side");
00639     checkField(binary, binary->right(), "Binary", "right side");
00640   }
00641 }
00642 
00643 void TreeChecker::at_ternary (ternaryNode * ternary, Order ord) {
00644   if (ord == Preorder) {
00645     if ( _typeDepth == 0 )
00646       setPreDismantled("Ternary", ternary);
00647     checkTree(ternary, "Ternary");
00648     ComparisonOperator co;
00649 
00650     checkField(ternary, ternary->cond(), "Ternary", "cond");
00651     checkField(ternary, ternary->true_br(), "Ternary", "true branch");
00652     checkField(ternary, ternary->false_br(), "Ternary", "false branch");
00653   }
00654 }
00655 
00656 void TreeChecker::at_threeAddr (threeAddrNode * the_3addr, Order ord) {
00657   if (ord == Preorder) {
00658     setPostDismantled("Three address", the_3addr);
00659     checkTree(the_3addr, "Three address");
00660     
00661     
00662 
00663     
00664     checkField(the_3addr, the_3addr->lhs(), "Three address", "lhs", false);
00665     Operator * op = the_3addr->op();
00666     if ( op ) {
00667       if ( op->id() == Operator::SIZEOF ) {
00668         checkField(the_3addr, the_3addr->sizeof_type(), "Three address", 
00669                    "sizeof_type");
00670       } else {
00671         checkField(the_3addr, the_3addr->rhs1(), "Three address", "rhs1");
00672         if ( op->id() == Operator::FUNC_CALL ) {
00673           checkList(the_3addr, the_3addr->arg_list(), "Three address",
00674                     "arg_list", false);
00675         } else if ( op->is_dismantled_binary() ) {
00676           checkField(the_3addr, the_3addr->rhs2(), "Three address", "rhs2");
00677         }
00678       }
00679     }
00680   }
00681 }
00682 
00683 void TreeChecker::at_operand (operandNode * operand, Order ord) {
00684   if (ord == Preorder) {
00685     setPostDismantled("Operand", operand);
00686     checkTree(operand, "Operand");
00687     checkField(operand, operand->var(), "Operand", "variable");
00688     
00689     
00690     checkField(operand, operand->cast(), "Operand", "typecast", false);
00691     checkField(operand, operand->index(), "Operand", "index", false);
00692     checkList(operand, operand->fields(), "Operand", "fields", false);
00693   }
00694 }
00695 
00696 void TreeChecker::at_cast (castNode * cast, Order ord) {
00697   if (ord == Preorder) {
00698     if ( _typeDepth == 0 )
00699       setPreDismantled("Cast", cast);
00700     checkTree(cast, "Cast");
00701     checkField(cast, cast->expr(), "Cast", "expression");
00702   }
00703 }
00704 
00705 void TreeChecker::at_comma (commaNode * comma, Order ord) {
00706   if (ord == Preorder) {
00707     if ( _typeDepth == 0 )
00708       setPreDismantled("Comma", comma);
00709     checkTree(comma, "Comma");
00710     checkList(comma, comma->exprs(), "Comma", "expression list");
00711   }
00712 }
00713 
00714 void TreeChecker::at_initializer (initializerNode * init, Order ord) {
00715   if (ord == Preorder) {
00716     if ( _arrayDepth == 0 )
00717       setPreDismantled("Initializer", init);
00718     checkTree(init, "Initializer");
00719     checkList(init, init->exprs(), "Initializer", "expression list");
00720   }
00721 }
00722 
00723 
00724 void TreeChecker::at_type (typeNode * the_type, Order ord) {
00725   if ( ord == Preorder ) {
00726     _typeDepth++;
00727   } else {
00728     _typeDepth--;
00729   }
00730 }
00731 
00732 void TreeChecker::at_func (funcNode * func, Order ord) {
00733   at_type(func, ord);
00734   if (ord == Preorder) {
00735     checkTree(func, "Function");
00736     checkField(func, func->returns(), "Function", "return");
00737     
00738     
00739     checkFieldInList(func, func->args(), "Function", "argument list", 
00740                      func->args().size(), _decls, "argument", false);
00741   }
00742 }
00743 
00744 void TreeChecker::at_tdef (tdefNode * tdef, Order ord) {
00745   at_type(tdef, ord);
00746   if (ord == Preorder) {
00747     
00748     checkTree(tdef, "Typedef");
00749     checkString(tdef, tdef->name(), "Typedef", "name");
00750     checkField(tdef, tdef->def(), "Typedef", "def");
00751   }
00752 }
00753 
00754 void TreeChecker::at_array (arrayNode * array, Order ord) {
00755   at_type(array, ord);
00756   if (ord == Preorder) {
00757     _arrayDepth++;
00758     checkTree(array, "Array");
00759     checkField(array, array->dim(), "Array", "dimension expression", 
00760                false);  
00761     
00762   } else {
00763     _arrayDepth--;
00764   }
00765 }
00766 
00767 UnitWalker::UnitWalker () : 
00768   Walker(Preorder, Subtree) 
00769 {}
00770 
00771 UnitWalker::~UnitWalker () { 
00772   _procs.clear();
00773   _procNames.clear();
00774   _dupProcs.clear();
00775   _formals.clear();
00776 }
00777 
00778 void UnitWalker::at_proc (procNode * the_proc, Order ord) {
00779   _procs.push_back(the_proc);
00780   declNode * proc_decl = the_proc->decl();
00781   if ( !proc_decl ) {
00782     cout << "procNode " << the_proc << " contains no declNode." << endl;
00783     return;
00784   }
00785   string procName = proc_decl->name();
00786 
00787   
00788   funcNode * proc_func = (funcNode *) proc_decl->type();
00789   if ( !proc_func ) {
00790     cout << "procNode " << the_proc << " w/ declNode " << proc_decl
00791          << " does not have Func typ()." << endl;
00792     return;
00793   }
00794   int argc = proc_func->args().size();
00795   if (proc_func->is_void_args()) 
00796     argc = 0;
00797 
00798   
00799   if (find(_procNames.begin(), _procNames.end(), procName)
00800       != _procNames.end()) {  
00801     _dupProcs.push_back(the_proc);  
00802     return;  
00803   }
00804   else _procNames.push_back(procName);  
00805 
00806   
00807   if ( _formals.find(procName) == _formals.end() )
00808     _formals[procName] = argc;
00809 }