C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

dismantle-expr.cc

Go to the documentation of this file.
00001 // $Id: dismantle-expr.cc,v 1.25 2003/08/07 23:13:43 pnav Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 // 
00009 //  Samuel Z. Guyer
00010 //  Daniel A. Jimenez
00011 //  Calvin Lin
00012 //  Adam Brown
00013 // 
00014 //  Permission is hereby granted, free of charge, to any person
00015 //  obtaining a copy of this software and associated documentation
00016 //  files (the "Software"), to deal in the Software without
00017 //  restriction, including without limitation the rights to use, copy,
00018 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00019 //  of the Software, and to permit persons to whom the Software is
00020 //  furnished to do so, subject to the following conditions:
00021 //  
00022 //  The above copyright notice and this permission notice shall be
00023 //  included in all copies or substantial portions of the Software.
00024 //  
00025 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00026 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00027 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00028 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00029 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00030 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00031 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00032 //  THE SOFTWARE.
00033 //
00034 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00035 //  Computer Science for inspiring parts of the C-Breeze design.
00036 //
00037 // ----------------------------------------------------------------------
00038 //
00039 // dismantle-expr.cc
00040 //
00041 
00042 #include <assert.h>
00043 #include "c_breeze.h"
00044 #include "dismantle.h"
00045 #include "ref_clone_changer.h"
00046 
00047 ArrowDismantle::ArrowDismantle(void):
00048   Changer(Postorder, Subtree, false)
00049 {}
00050 
00051 Node * ArrowDismantle::at_binary(binaryNode * the_binary, Order ord) {
00052   Operator * op = the_binary->op();
00053   if ( op->id() == Operator::ARROW ) {
00054     // change foo->bar to *(foo).bar
00055     unaryNode * deref = new unaryNode(Operator::INDIR, 
00056                                       the_binary->left(), 
00057                                       the_binary->left()->coord());
00058     binaryNode * dot = new binaryNode('.', deref, the_binary->right(), 
00059                                       the_binary->right()->coord());
00060     dot->type((typeNode*) ref_clone_changer::clone(the_binary->type(),
00061                                                    false));
00062     return dot;
00063   }
00064   return the_binary;
00065 }
00066 
00067 map<unsigned int, unsigned int> ExpressionDismantle::_op_assign_map;
00068 set<unsigned int> ExpressionDismantle::_op_post;
00069 
00070 void ExpressionDismantle::init() {
00071   if ( _op_assign_map.empty() ) {
00072     _op_assign_map[Operator::PLUSassign] = '+';
00073     _op_assign_map[Operator::MINUSassign] = '-';
00074     _op_assign_map[Operator::MULTassign] = '*';
00075     _op_assign_map[Operator::DIVassign] = '/';
00076     _op_assign_map[Operator::MODassign] = '%';
00077     _op_assign_map[Operator::ANDassign] = '&';
00078     _op_assign_map[Operator::ORassign] = '|';
00079     _op_assign_map[Operator::LSassign] = Operator::LS;
00080     _op_assign_map[Operator::RSassign] = Operator::RS;
00081     _op_assign_map[Operator::ERassign] = '^';
00082     _op_assign_map[Operator::PREINC] = Operator::PLUSassign;
00083     _op_assign_map[Operator::POSTINC] = Operator::PLUSassign;
00084     _op_assign_map[Operator::PREDEC] = Operator::MINUSassign;
00085     _op_assign_map[Operator::POSTDEC] = Operator::MINUSassign;
00086   }
00087 
00088   if( _op_post.empty() ) {
00089     _op_post.insert(Operator::POSTINC);
00090     _op_post.insert(Operator::POSTDEC);
00091   }
00092 }
00093 
00094 ExpressionDismantle::ExpressionDismantle(void):
00095   Changer(Both, Subtree, false),
00096   _new_block(NULL),
00097   _in_type(0)
00098 {}
00099 
00100 Node * ExpressionDismantle::at_exprstmt(exprstmtNode * the_exprstmt,
00101                                                  Order ord) {
00102   if ( ord == Preorder ) {
00103     // don't worry if the expr() is NULL, like in the stmt() of a labelNode
00104     if ( the_exprstmt->expr() ) {
00105       ArrowDismantle ad;
00106       the_exprstmt = (exprstmtNode *) the_exprstmt->change(ad);
00107       _new_block = new blockNode(NULL, NULL, the_exprstmt->coord());
00108     }
00109   } else { // ord == Postorder
00110     // _new_block is NULL only when the expr() was NULL, like in the stmt()
00111     // of a labelNode
00112     if ( _new_block ) {
00113       blockNode * ret = _new_block;
00114       _new_block = NULL;
00115       // This 'recursion' is safe, because we bottom out once we
00116       // have only threeAddrNodes in the AST, and no more exprstmtNodes.
00117       ExpressionDismantle ed;
00118       return ret->change(ed);
00119     }
00120   }
00121   return the_exprstmt;
00122 }
00123 
00124 Node * ExpressionDismantle::at_type(typeNode * the_type, Order ord) {
00125   // We don't want to inadvertently process exprNodes under a typeNode, thus
00126   // generating incorrect intermediate result nodes.
00127   if ( ord == Preorder ) 
00128     _in_type++;
00129   else
00130     _in_type--;
00131   return the_type;
00132 }
00133 
00134 // TODO: factor?
00135 Node * ExpressionDismantle::at_binary(binaryNode * the_binary,
00136                                                Order ord) {
00137   if ( !_new_block || _in_type ) // we're not in an expression statement
00138     return the_binary;
00139 
00140   if ( ord == Postorder ) {
00141     Operator * op = the_binary->op();
00142     exprNode * left = the_binary->left();
00143     exprNode * right = the_binary->right();
00144     exprNode * ret = the_binary;  // the return value
00145     
00146     switch ( op->id() ) {
00147     case '=': 
00148       {
00149         if ( left->typ() == Id ) {
00150           // make an operandNode from left
00151           left = new operandNode((idNode *) ref_clone_changer::clone(left, 
00152                                                                      false),
00153                                  left->coord());
00154         }
00155         // make an operandNode from right
00156         if ( right->typ() != Operand ) {
00157           assert(right->typ() == Id || right->typ() == Const);
00158           right = new operandNode((indexNode *) right, right->coord());
00159         }
00160         assert(left->typ() == Operand && right->typ() == Operand);
00161         threeAddrNode * new_stmt = new threeAddrNode((operandNode *) left, 
00162                                                      (operandNode *) right,
00163                                                      the_binary->coord());
00164         _new_block->stmts().push_back(new_stmt);
00165         // must return a clone, b/c left appears in the AST in the
00166         // threeAddrNode new_stmt
00167         ret = (operandNode *) ref_clone_changer::clone(left, false);
00168       }
00169       break;
00170     case Operator::PLUSassign: case Operator::MINUSassign: 
00171     case Operator::MULTassign: case Operator::DIVassign: 
00172     case Operator::MODassign: case Operator::ANDassign:
00173     case Operator::ORassign: case Operator::LSassign:
00174     case Operator::RSassign: case Operator::ERassign:
00175       {
00176         // TODO: finish/fix to handle a[b] += 1; properly
00177         // actually, b/c we dismantle from bottom to top, we are guaranteed
00178         // that an array subscript will be either a constant or a variable;
00179         // we won't have a more complex expression.  so, it is safe not
00180         // to generate a temporary pointer.
00181         exprNode * new_rhs = 
00182           new binaryNode(_op_assign_map[op->id()],
00183                          (exprNode*) ref_clone_changer::clone(left,
00184                                                               false),
00185                          right);
00186         new_rhs->type((typeNode *) ref_clone_changer::clone(the_binary->type(),
00187                                                             false));
00188         the_binary->right(new_rhs);
00189         the_binary->op(Operators::table['=']);
00190         _new_block->stmts().push_back(new exprstmtNode(the_binary));
00191         ret = (exprNode *) ref_clone_changer::clone(left, false);
00192       }
00193       break;
00194     case '.':
00195       {
00196         if ( left->typ() == Id ) {
00197           // make an operandNode from left
00198           left = new operandNode((idNode *) left, left->coord());
00199         } else {
00200           assert(left->typ() == Operand);
00201           operandNode * left_oper = (operandNode *) left;
00202           if(left_oper->addr()) {
00203             cout << "Error: does not make sense to access field in \"(";
00204             output_context oc(cout);
00205             left_oper->output(oc,NULL);
00206             cout << ").";
00207             right->output(oc,NULL);
00208             cout << "\" at " << the_binary->coord() << "\n";
00209             exit(1);
00210           }
00211           if ( left_oper->index() ) {
00212             // foo[idx].fld
00213             // =>
00214             // elem * T1;
00215             // T1 = &foo[idx];
00216             // (*T1).fld (is output)
00217 
00218             // the temporary is really a pointer to the array element type
00219             typeNode * left_type = 
00220               new ptrNode(typeNode::NONE, left_oper->type());
00221             declNode * tmp_arry_decl =
00222               DismantleUtil::new_temp_decl(left_type,
00223                                                     the_binary->coord());
00224             _new_block->decls().push_back(tmp_arry_decl);
00225             left_oper->addr(true);
00226             threeAddrNode * assign_tmp_array =
00227               new threeAddrNode(new operandNode(new idNode(tmp_arry_decl),
00228                                                 left_oper->coord()), 
00229                                 left_oper,
00230                                 left_oper->coord());
00231             _new_block->stmts().push_back(assign_tmp_array);
00232             left = new operandNode(new idNode(tmp_arry_decl), true, false,
00233                                    left_oper->coord());
00234           }
00235         }
00236         assert(left->typ() == Operand && right->typ() == Id);
00237         ((operandNode *) left)->fields().push_back((idNode *) right);
00238         // don't clone, b/c left doesn't appear anywhere in the AST, yet
00239         // it won't until it appears in a threeAddrNode
00240         ret = left;
00241       }
00242       break;
00243     case Operator::Index:
00244       {
00245         if ( left->typ() == Id ) {
00246           // make an operandNode from left
00247           left = new operandNode((idNode *) left, left->coord());
00248         } else if ( left->typ() == Const ) {
00249           // make an operandNode from left
00250           left = new operandNode((constNode *) left, left->coord());
00251         } else if ( left->typ() == Operand ) {
00252           // must ensure that the left is not already being subscripted
00253           operandNode * left_oper = (operandNode *) left;
00254           if(left_oper->addr()) {
00255             // "(&S)[x]" -> "tmp = &S; tmp[x]"
00256             typeNode * left_type = left_oper->type();
00257             declNode * tmp_addr_decl =
00258               DismantleUtil::new_temp_decl(left_type, the_binary->coord());
00259             _new_block->decls().push_back(tmp_addr_decl);
00260             threeAddrNode * assign_tmp_addr =
00261               new threeAddrNode(new operandNode(new idNode(tmp_addr_decl),
00262                                                 left->coord()), 
00263                                 (operandNode *) left,
00264                                 left->coord());
00265             _new_block->stmts().push_back(assign_tmp_addr);
00266             left_oper=new operandNode(new idNode(tmp_addr_decl), left->coord());
00267             left = left_oper;
00268           }
00269           if ( left_oper->index() ) {
00270             typeNode * left_type = left_oper->type();
00271             declNode * tmp_arry_decl =
00272               DismantleUtil::new_temp_decl(left_type,
00273                                                     the_binary->coord());
00274             _new_block->decls().push_back(tmp_arry_decl);
00275             threeAddrNode * assign_tmp_array =
00276               new threeAddrNode(new operandNode(new idNode(tmp_arry_decl),
00277                                                 left->coord()), 
00278                                 (operandNode *) left,
00279                                 left->coord());
00280             _new_block->stmts().push_back(assign_tmp_array);
00281             left = new operandNode(new idNode(tmp_arry_decl), 
00282                                    left->coord());
00283           }
00284         }
00285         if ( right->typ() == Operand ) {
00286           // create temporary for the index value
00287           declNode * index_decl =
00288             DismantleUtil::new_temp_decl(right->type(),
00289                                                   the_binary->coord());
00290           _new_block->decls().push_back(index_decl);
00291           threeAddrNode * assign_index = 
00292             new threeAddrNode(new operandNode(new idNode(index_decl),
00293                                               right->coord()), 
00294                               (operandNode *) right);
00295           _new_block->stmts().push_back(assign_index);
00296           right = new idNode(index_decl);
00297         }
00298 
00299         assert(left->typ() == Operand && ( right->typ() == Id 
00300                                            || right->typ() == Const ) );
00301         ((operandNode *) left)->index((indexNode *)right);
00302         // don't clone, b/c left doesn't appear anywhere in the AST, yet
00303         // it won't until it appears in a threeAddrNode
00304         ret = left;
00305       }
00306     break;
00307     case '*': case '/': case '%': case '+': case '-': case Operator::LS:
00308     case Operator::RS: case '&': case '|': case '^': case Operator::LE:
00309     case Operator::GE: case Operator::EQ: case Operator::NE: case '<': 
00310     case '>':
00311       {
00312         if ( left->typ() != Operand ) {
00313           assert(left->typ() == Id || left->typ() == Const);
00314           left = new operandNode((indexNode *) left, left->coord());
00315         }
00316         if ( right->typ() != Operand ) {
00317           assert(right->typ() == Id || right->typ() == Const);
00318           right = new operandNode((indexNode *) right, right->coord()) ;
00319         }
00320         assert(left->typ() == Operand && right->typ() == Operand);
00321         declNode * temp_decl =
00322           DismantleUtil::new_temp_decl(the_binary->type(),
00323                                                 the_binary->coord());
00324         _new_block->decls().push_back(temp_decl);
00325         threeAddrNode * assign_temp =
00326           new threeAddrNode(new operandNode(new idNode(temp_decl),
00327                                             the_binary->coord()), 
00328                             (operandNode *) left, 
00329                             op->id(), 
00330                             (operandNode *) right);
00331         _new_block->stmts().push_back(assign_temp);
00332         ret = new idNode(temp_decl);
00333       }
00334       break;
00335     default:
00336       cout << "Unknown binary op to dismantle: " << op->id() << endl;
00337       break;
00338     }
00339     return ret;
00340   } // end if ( ord == Postorder )
00341   return the_binary;
00342 }
00343 
00344 // TODO: factor?
00345 Node * ExpressionDismantle::at_unary(unaryNode * the_unary, 
00346                                               Order ord) {
00347   if ( !_new_block || _in_type ) // we're not in an expression statement
00348     return the_unary;
00349 
00350   Operator * op = the_unary->op();
00351   exprNode * expr = the_unary->expr();
00352   exprNode * ret = the_unary;
00353 
00354   if ( ord == Preorder ) {
00355     switch ( op->id() ) {
00356     case Operator::SIZEOF:
00357       {
00358         if ( expr ) {
00359           the_unary->sizeof_type(the_unary->expr()->type());
00360           the_unary->expr(NULL);
00361           return the_unary;
00362         }
00363       }
00364     break;
00365     }
00366   }
00367 
00368   if ( ord == Postorder ) {
00369     switch ( op->id() ) {
00370     case Operator::SIZEOF:
00371       {
00372         assert(the_unary->expr() == NULL && the_unary->sizeof_type() != NULL);
00373         declNode * unary_temp_decl =
00374           DismantleUtil::new_temp_decl(the_unary->type(),
00375                                                 the_unary->coord());
00376         _new_block->decls().push_back(unary_temp_decl);
00377         threeAddrNode * assign_unary_temp =
00378           new threeAddrNode(new operandNode(new idNode(unary_temp_decl),
00379                                             the_unary->coord()),
00380                             the_unary->sizeof_type(),
00381                             the_unary->coord());
00382         _new_block->stmts().push_back(assign_unary_temp);
00383         return new idNode(unary_temp_decl);
00384       }
00385     break;
00386     case Operator::UMINUS: case Operator::UPLUS: case '!': case '~':
00387       {
00388         if ( expr->typ() == Operand ) {
00389           operandNode * expr_oper = (operandNode *) expr;
00390           declNode * temp_decl = 
00391             DismantleUtil::new_temp_decl(expr->type(),
00392                                                   expr->coord());
00393           _new_block->decls().push_back(temp_decl);
00394           threeAddrNode * assign_temp =
00395             new threeAddrNode(new operandNode(new idNode(temp_decl),
00396                                               expr_oper->coord()),
00397                               expr_oper);
00398           _new_block->stmts().push_back(assign_temp);
00399           expr = new idNode(temp_decl, expr->coord());
00400         }
00401         assert(expr->typ() == Id || expr->typ() == Const);
00402         typeNode * unary_type = the_unary->type();
00403         declNode * unary_temp_decl =
00404           DismantleUtil::new_temp_decl(unary_type,
00405                                                 expr->coord());
00406         _new_block->decls().push_back(unary_temp_decl);
00407         threeAddrNode * assign_unary_temp =
00408           new threeAddrNode(new operandNode(new idNode(unary_temp_decl),
00409                                             expr->coord()),
00410                             op->id(),
00411                             new operandNode((indexNode *) expr, 
00412                                             expr->coord()));
00413         _new_block->stmts().push_back(assign_unary_temp);
00414         ret = new idNode(unary_temp_decl);
00415       }
00416     break;
00417     case Operator::ADDRESS:
00418       {
00419         if ( expr->typ() == Operand ) {
00420           operandNode * expr_oper = (operandNode *) expr;
00421           expr_oper->addr(true);
00422           ret = expr_oper;
00423         } else {
00424           assert(expr->typ() == Id);
00425           expr = new operandNode((indexNode*) expr, false, true);
00426         }
00427         ret = expr;
00428       }
00429     break;
00430     case Operator::INDIR:
00431       {
00432         if ( expr->typ() == Operand ) {
00433           operandNode * expr_oper = (operandNode *) expr;
00434           if ( expr_oper->star() ||
00435                ! expr_oper->fields().empty() ||
00436                expr_oper->index()) {
00437             // case 1:
00438             // **foo
00439             // =>
00440             // {
00441             //   tmp = *foo;
00442             // } (returns tmp w/ star)
00443             // must create a temporary if we are already deref'ing
00444             //
00445             // case 2:
00446             // *(foo.f)
00447             // =>
00448             // {
00449             //   tmp = foo.f;
00450             // } (returns tmp w/ star)
00451             //
00452             // case 3:
00453             // *(foo[a])
00454             // =>
00455             // {
00456             //   tmp = foo[a];
00457             // } (returns tmp w/ star)
00458             declNode * temp_decl =
00459               DismantleUtil::new_temp_decl(expr->type(),
00460                                                     expr->coord());
00461             _new_block->decls().push_back(temp_decl);
00462             threeAddrNode * assign_temp = 
00463               new threeAddrNode(new operandNode(new idNode(temp_decl), 
00464                                                 expr_oper->coord()),
00465                                 expr_oper);
00466             _new_block->stmts().push_back(assign_temp);
00467             expr = new operandNode(new idNode(temp_decl), true, false);
00468           } else if(expr_oper->addr())
00469             expr_oper->addr(false);
00470           else
00471             expr_oper->star(true);
00472         } else {
00473           assert(expr->typ() == Id || expr->typ() == Const);
00474           expr = new operandNode((indexNode *) expr, true, false);
00475         }
00476         ret = expr;
00477       }
00478     break;
00479     case Operator::PREINC: case Operator::POSTINC:
00480     case Operator::PREDEC: case Operator::POSTDEC:
00481       {
00482         // ++a => a += 1; (return a)
00483         // a++ => tmp = a; a += 1; (return tmp)
00484         // --a => a -= 1; (return a);
00485         // a-- => tmp = a; a -= 1; (return tmp)
00486         bool post_op = false;
00487         if ( _op_post.find(the_unary->op()->id()) !=
00488              _op_post.end() ) {
00489           declNode * temp_decl = 
00490             DismantleUtil::new_temp_decl(the_unary->type(),
00491                                                   the_unary->coord());
00492           // temp = expr;
00493           exprNode * clone_expr = (exprNode *) ref_clone_changer::clone(expr,
00494                                                                         false);
00495           exprstmtNode * assign_temp = 
00496             new exprstmtNode(new binaryNode('=',
00497                                             new idNode(temp_decl,
00498                                                        the_unary->coord()),
00499                                             clone_expr,
00500                                             the_unary->coord()));
00501           assign_temp->expr()->type((typeNode *) 
00502                                     ref_clone_changer::clone(the_unary->type(),
00503                                                              false));
00504           _new_block->decls().push_back(temp_decl);
00505           _new_block->stmts().push_back(assign_temp);
00506           ret = new idNode(temp_decl, the_unary->coord());
00507           post_op = true;
00508         }
00509         // TODO: is this the right type?
00510         constNode * one = new constNode(constant::constant(1));
00511         exprstmtNode * update = 
00512           new exprstmtNode(new binaryNode(_op_assign_map[op->id()], // += or -=
00513                                           expr,
00514                                           one,
00515                                           the_unary->coord()));
00516         update->expr()->type(the_unary->type());
00517         _new_block->stmts().push_back(update);
00518         if ( !post_op )
00519           ret = (exprNode *) ref_clone_changer::clone(expr, false);
00520       }
00521     break;
00522     default:
00523       cout << "Unknown unary op to dismantle: " << op->id() << endl;
00524       break;
00525     }
00526     return ret;
00527   } // end if ( ord == Postorder )
00528   return the_unary;
00529 }
00530 
00531 Node * ExpressionDismantle::at_call(callNode * the_call, Order ord) {
00532   if ( !_new_block || _in_type ) // we're not in an expression statement
00533     return the_call;
00534 
00535   if ( ord == Postorder ) {
00536     operand_list * args = new operand_list;
00537     for ( expr_list_p p = the_call->args().begin();
00538           p != the_call->args().end();
00539           p++ ) {
00540       operandNode * arg;
00541       if ( (*p)->typ() != Operand ) {
00542         assert((*p)->typ() == Id || (*p)->typ() == Const);
00543         arg = new operandNode((indexNode *) *p, (*p)->coord());
00544       } else
00545         arg = (operandNode *) *p;
00546       args->push_back(arg);
00547     }
00548 
00549     exprNode * call_expr = the_call->name();
00550     if ( call_expr->typ() == Id ) {
00551       call_expr = new operandNode((idNode *) call_expr, call_expr->coord());
00552     }
00553     assert(call_expr->typ() == Operand);
00554     operandNode * call_oper = (operandNode *) call_expr;
00555 
00556     // TODO: is this right for void return types?
00557     if ( the_call->type() && 
00558          the_call->type()->is_void() ) { // the proc returns void
00559       threeAddrNode * call =
00560         new threeAddrNode(call_oper, args, the_call->coord());
00561       _new_block->stmts().push_back(call);
00562       return call; // value doesn't matter, since it won't be in final code
00563     } else { // the proc returns non-void
00564       declNode * return_decl =
00565         DismantleUtil::new_temp_decl(the_call->type(),
00566                                               the_call->coord());
00567       _new_block->decls().push_back(return_decl);
00568       threeAddrNode * assign_return =
00569         new threeAddrNode(new operandNode(new idNode(return_decl)), call_oper,
00570                           args, the_call->coord());
00571       _new_block->stmts().push_back(assign_return);
00572       return new idNode(return_decl, the_call->coord());
00573     }
00574   } // end if ( ord == Postorder )
00575   return the_call;
00576 }
00577 
00578 Node * ExpressionDismantle::at_comma(commaNode * the_comma, 
00579                                               Order ord) {
00580   if ( ord == Postorder ) {
00581     exprNode * last_expr = *(the_comma->exprs().rbegin());
00582     if ( last_expr->typ() == Id || last_expr->typ() == Const ) {
00583       last_expr = new operandNode((indexNode *) last_expr);
00584     }
00585     assert(last_expr->typ() == Operand);
00586     return last_expr;
00587   } // end if ( ord == Postorder )
00588   return the_comma;
00589 }
00590 
00591 Node * ExpressionDismantle::at_cast(castNode * the_cast, Order ord) {
00592   if ( !_new_block || _in_type ) // we're not in an expression statement
00593     return the_cast;
00594 
00595   // TODO: should we distinguish between implicit and explicit casts?
00596   if ( ord == Postorder ) {
00597     exprNode * expr = the_cast->expr();
00598     if ( expr->typ() == ThreeAddr ) {
00599       assert( the_cast->type()->is_void() );
00600       return expr;
00601     } else if ( expr->typ() != Operand ) {
00602       assert(expr->typ() == Id || expr->typ() == Const);
00603       expr = new operandNode((indexNode *) expr);
00604     }
00605     assert(expr->typ() == Operand);
00606     ((operandNode *) expr)->cast(the_cast->type());
00607     return expr;
00608   }
00609   return the_cast;
00610 }
00611 
00612 // We don't want to generate operandNodes everywhere by using at_id() and
00613 // at_const().  For field names and array indices, we would generate a
00614 // useless operandNode on the way up from the bottom of the AST.  This
00615 // operandNode would be discarded once we extract the indexNode from it
00616 // to obtain the actual Node we wanted.

Generated on August 27, 2003
Back to the C-Breeze home page