vrq
/usr/src/RPM/BUILD/vrq-1.0.96/src/cnode.h
Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Copyright (C) 1997-2007, Mark Hummel
00003  * This file is part of Vrq.
00004  *
00005  * Vrq is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * Vrq is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00018  * Boston, MA  02110-1301  USA
00019  *****************************************************************************
00020  */
00021 /******************************************************************************
00022  *
00023  *
00024  *         cnode.hpp
00025  *              - abstract class for declaration 
00026  *
00027  *
00028  ******************************************************************************
00029  */
00030 
00031 #ifndef CNODE_HPP
00032 #define CNODE_HPP
00033 
00034 #include <stdio.h>
00035 #include <iostream>
00036 #include <sstream>
00037 #include <math.h>
00038 #include <list>
00039 #include <set>
00040 #include "glue.h"
00041 #include "csymbol.h"
00042 #include "cdecl.h"
00043 #include "cvector.h"
00044 #include "cobstack.h"
00045 #include "cattr.h"
00046 
00047 class CGenvar;
00048 class CParam;
00049 class CFref;
00050 class CVar;
00051 class CNet;
00052 class CPort;
00053 class CPortDir;
00054 class CInstance;
00055 class CFunction;
00056 class CModule;
00057 class CGate;
00058 class CEvent;
00059 class CAttr;
00060 class CBlock;
00061 class CSpecify;
00062 class CNode;
00063 class CTypedef;
00064 class CEnum;
00065 typedef CBlock CScope;
00066 inline char* d2s( double d, CObstack* stack );
00067 
00071 enum Edge_t {
00072         eEDGE01 = 0x1,
00073         eEDGE10 = 0x2,
00074         eEDGE0x = 0x4,
00075         eEDGEx1 = 0x8,
00076         eEDGE1x = 0x10,
00077         eEDGEx0 = 0x20,
00078 };
00079         
00083 enum DelayMode_t {
00084         eMIN_DELAY,
00085         eTYP_DELAY,
00086         eMAX_DELAY
00087 };
00088 
00092 enum Strength_t {
00093         eUNDEFINED = 0,
00094         eSUPPLY,
00095         eSTRONG,
00096         ePULL,
00097         eLARGE,
00098         eWEAK,
00099         eMEDIUM,
00100         eSMALL,
00101         eHIGHZ,
00102 };
00103 
00107 struct StrengthPair_t {
00108         Strength_t      s0;
00109         Strength_t      s1;
00110 };
00111 
00112 #define DEFINE_ENUM
00113 #include "cnode_def.h"
00114 #undef DEFINE_ENUM
00115 
00116 
00123 template<class T>
00124 class CNode_sp {
00125         T* ptr; 
00126 public:
00127         CNode_sp( void** np ) { ptr = (T*)np; }
00128         T operator=( T n ) { *ptr = n; return n; }
00129         T operator->() { return *ptr; }
00130         T* Ptr() { return ptr; }
00131         operator T() { return *ptr; }
00132         int operator==( T v ) { return *ptr == v; }
00133         int operator!=( T v ) { return *ptr != v; }
00134         int operator==( CNode_sp<T> p ) { return *ptr == *p.ptr; }
00135         int operator!=( CNode_sp<T> p ) { return *ptr != *p.ptr; }
00136 };
00137 
00142 struct CNode_pr {
00143         CNode* head;
00144         CNode* tail;
00145 public:
00146         CNode* operator=( CNode* n ) { head = n; tail = n; return n; }
00147         CNode* operator->() { return head; }
00148         operator CNode*() { return head; }
00149         int operator==( CNode* v ) { return head == v; }
00150         int operator!=( CNode* v ) { return head != v; }
00151         int operator==( CNode_pr p ) { return head == p.head; }
00152         int operator!=( CNode_pr p ) { return head != p.head; }
00153         friend CNode_pr cLINK( CNode_pr pr1, CNode* n2 );
00154 };
00155 
00160 struct CNode_triplet {
00161         CNode* first;
00162         CNode* second;
00163         CNode* third;
00164 };
00165 
00166 
00187 class CNode : public CObject
00188 {
00189 private:
00190         static list<CObstack*> stackList; 
00191         static CObstack         evalHeap; 
00192         static INT32            evalCount; 
00193         static CObstack* stack;     
00194         static map<CNode*,int> labelCache;  
00195         static int labelCacheEnabled;   
00196         NodeOp_t        op;         
00197         void*           left;       
00198         void*           right;      
00199         Coord_t         loc;        
00200         Coord_t         *locp;      
00201         CNode*          attributes; 
00202         /*
00203          * These decorations are temporary and used
00204          * by the expression evaluation routines
00205          */
00206         NodeType_t      type;       
00207         INT32           width;      
00208         int             fixedWidth; 
00209 private:
00210         int     LabelBits( int supressErrorMessages = FALSE );
00211         CNode*  FixBits( INT32 newWidth, NodeType_t newType );
00212         void    _EvalVector( CVector& v );
00213         double  _EvalReal( void );
00214         void FixedWidth( int v ) { fixedWidth = v; }
00215         int  FixedWidth() { return fixedWidth; }
00216         int  ConditionalWiden();
00217         int  WidthFixed();
00218         unsigned  NodeMask();
00219         CNode*  GetNLeft( void ) { return (CNode*)left; }
00220         CNode*  GetNRight( void ) { return (CNode*)right; }
00221         static void _LabelBits( CNode* n, void* arg );
00222 public:
00227         static CObstack* CurrentHeap() { return stack; }
00237         static void UseEvalStack( void ) {
00238                 stackList.push_front( stack );
00239                 evalCount++;
00240                 stack = &evalHeap;
00241         }
00246         static void SetBuildStack( CObstack* aStack ) {
00247                 MASSERT( evalCount == 0 );
00248                 stackList.push_front( stack );
00249                 stack = aStack;
00250         }
00254         static void ResetBuildStack( void ) {
00255                 if( stack == &evalHeap ) {
00256                         evalCount--;
00257                         if( evalCount == 0 ) {
00258                                 evalHeap.Free( NULL );
00259                         }
00260                 }
00261                 if( stackList.empty() ) {
00262                         stack = NULL;
00263                 } else {
00264                         stack = *stackList.begin();
00265                         stackList.pop_front();
00266                 }
00267         }
00277         static void EnableLabelCache()
00278         {
00279             labelCacheEnabled = 1;
00280         }
00285         static void DisableAndClearLabelCache()
00286         {
00287             labelCacheEnabled = 0;
00288             labelCache.erase( labelCache.begin(), labelCache.end() );
00289         }
00297         CNode( Coord_t* aLoc, NodeOp_t aOp ); 
00302         Coord_t* GetCoord() { return locp; }
00307         NodeOp_t GetOp() { return op; }
00314         void SetOp( NodeOp_t aOp ) { 
00315                 int oldCount = ArgCount();
00316                 op = aOp; 
00317                 MASSERT( oldCount == ArgCount() );
00318         }
00324         unsigned Hash();
00330         template<class T> CNode_sp<T> Arg( int index );
00335         int     ArgCount( void );
00343         CNode*  Clone( CObstack* heap = stack );
00348         int     Precedence();
00355         void    PostVisit1( void (*callback)(CNode*,void*), void* data );
00364         CNode*  PostSubVisit1( CNode* (*callback)(CNode*,void*), 
00365                                                         void* data );
00373         void    PreVisit1( int (*callback)(CNode*,void*), void* data );
00382         CNode*  Simplify( INT32 newWidth, NodeType_t newType );
00392         int     IsNonX( int integerIsNonX = 0, char* exclude = NULL );
00398         int     IsConstant();
00408         int     IsEvaluateable();
00414         int     IsVolatile( void );
00419         INT32   EvalINT32();
00426         void    EvalVector( CVector& v );
00435         void    EvalVector( CVector& v, INT32 newWidth, NodeType_t newType );
00441         double  EvalReal( void );
00446         void    Dump( FILE* f );
00452         int     IsWidthConstant( void );
00458         int     IsWidthVolatile( void );
00468         int     IsWidthEvaluateable( void );
00473         CNode*  GetWidthExp( void );
00479         INT32   GetWidth( void ) { LabelBits(TRUE); return width; }
00484         int     IsScalar( void ) { LabelBits(TRUE); return width==1; }
00489         int     IsVector( void ) { LabelBits(TRUE); return width>1; }
00494         int     IsReal( void ) { LabelBits(TRUE); return type==eR; }
00499         CNode*  GetAttributes() { return attributes; }
00504         void    SetAttributes( CNode* attr ) { attributes = attr; }
00512         int   HasAttribute( const char* name, CNode* n=NULL, int init = 1 );
00520         CAttr* GetAttribute( const char* name, CNode* n=NULL, int init = 1 );
00525         NodeType_t GetNodeType( void ) { LabelBits(TRUE); return type; }
00526 };
00527 
00528 
00529 /************************************************
00530         Arg<CNode*>     
00531         - returns CNode smart pointer to arg by index
00532  ***********************************************/
00533 
00534 template<class T> CNode_sp<T> CNode::Arg(int index) 
00535 {
00536         switch( ArgCount() ) {
00537         case 1:
00538                 switch( index ) {
00539                 case 0:
00540                         return CNode_sp<T>(&left);              
00541                 default:
00542                         MASSERT( FALSE );
00543                         return NULL;
00544                 } 
00545         case 2:
00546                 switch( index ) {
00547                 case 0:
00548                         return CNode_sp<T>(&left);              
00549                 case 1:
00550                         return CNode_sp<T>(&right);             
00551                 default:
00552                         MASSERT( FALSE );
00553                         return NULL;
00554                 } 
00555         case 3:
00556                 switch( index ) {
00557                 case 0:
00558                         return CNode_sp<T>(&GetNLeft()->left);          
00559                 case 1:
00560                         return CNode_sp<T>(&GetNLeft()->right);         
00561                 case 2:
00562                         return CNode_sp<T>(&right);             
00563                 default:
00564                         MASSERT( FALSE );
00565                         return NULL;
00566                 } 
00567         case 4:
00568                 switch( index ) {
00569                 case 0:
00570                         return CNode_sp<T>(&GetNLeft()->left);          
00571                 case 1:
00572                         return CNode_sp<T>(&GetNLeft()->right);         
00573                 case 2:
00574                         return CNode_sp<T>(&GetNRight()->left);         
00575                 case 3:
00576                         return CNode_sp<T>(&GetNRight()->right);                
00577                 default:
00578                         MASSERT( FALSE );
00579                         return NULL;
00580                 } 
00581         case 5:
00582                 switch( index ) {
00583                 case 0:
00584                         return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);              
00585                 case 1:
00586                         return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);             
00587                 case 2:
00588                         return CNode_sp<T>(&GetNLeft()->right);         
00589                 case 3:
00590                         return CNode_sp<T>(&GetNRight()->left);         
00591                 case 4:
00592                         return CNode_sp<T>(&GetNRight()->right);                
00593                 default:
00594                         MASSERT( FALSE );
00595                         return NULL;
00596                 } 
00597         case 6:
00598                 switch( index ) {
00599                 case 0:
00600                         return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);              
00601                 case 1:
00602                         return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);             
00603                 case 2:
00604                         return CNode_sp<T>(&GetNLeft()->GetNRight()->left);             
00605                 case 3:
00606                         return CNode_sp<T>(&GetNLeft()->GetNRight()->right);            
00607                 case 4:
00608                         return CNode_sp<T>(&GetNRight()->left);         
00609                 case 5:
00610                         return CNode_sp<T>(&GetNRight()->right);                
00611                 default:
00612                         MASSERT( FALSE );
00613                         return NULL;
00614                 } 
00615         case 7:
00616                 switch( index ) {
00617                 case 0:
00618                         return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);              
00619                 case 1:
00620                         return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);             
00621                 case 2:
00622                         return CNode_sp<T>(&GetNLeft()->GetNRight()->left);             
00623                 case 3:
00624                         return CNode_sp<T>(&GetNLeft()->GetNRight()->right);            
00625                 case 4:
00626                         return CNode_sp<T>(&GetNRight()->GetNLeft()->left);             
00627                 case 5:
00628                         return CNode_sp<T>(&GetNRight()->GetNLeft()->right);            
00629                 case 6:
00630                         return CNode_sp<T>(&GetNRight()->right);                
00631                 default:
00632                         MASSERT( FALSE );
00633                         return NULL;
00634                 } 
00635         case 8:
00636                 switch( index ) {
00637                 case 0:
00638                         return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);              
00639                 case 1:
00640                         return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);             
00641                 case 2:
00642                         return CNode_sp<T>(&GetNLeft()->GetNRight()->left);             
00643                 case 3:
00644                         return CNode_sp<T>(&GetNLeft()->GetNRight()->right);            
00645                 case 4:
00646                         return CNode_sp<T>(&GetNRight()->GetNLeft()->left);             
00647                 case 5:
00648                         return CNode_sp<T>(&GetNRight()->GetNLeft()->right);            
00649                 case 6:
00650                         return CNode_sp<T>(&GetNRight()->GetNRight()->left);            
00651                 case 7:
00652                         return CNode_sp<T>(&GetNRight()->GetNRight()->right);           
00653                 default:
00654                         MASSERT( FALSE );
00655                         return NULL;
00656                 } 
00657                 
00658         default:
00659                 MASSERT( FALSE );               
00660         }
00661 }
00662 int Equivalent( CNode* a, CNode* b );
00663 /******************************************************
00664   real operation routines
00665  ******************************************************/
00666 
00667 inline void Add( double* r, double* a, double* b )
00668 {
00669         *r = *a + *b;
00670 }
00671 
00672 inline void Sub( double* r, double* a, double* b )
00673 {
00674         *r = *a - *b;
00675 }
00676 
00677 inline void Mul( double* r, double* a, double* b )
00678 {
00679         *r = *a * *b;
00680 }
00681 
00682 inline void Div( double* r, double* a, double* b )
00683 {
00684         *r = *a / *b;
00685 }
00686 
00687 inline void Neg( double* r, double* a )
00688 {
00689         *r = - *a; 
00690 }
00691 
00692 inline void Plus( double* r, double* a )
00693 {
00694         *r = *a; 
00695 }
00696 
00697 inline void Pow( double* r, double* a, double* b )
00698 {
00699         *r = pow(*a,*b);
00700 }
00701 
00702 
00703 /*****************************************************
00704  * Create stubs for illegal operations
00705  ****************************************************/
00706 #define ILLEGAL_OP2(op) \
00707 inline void op( double*, double*, double* )\
00708 { fatal( NULL, #op " is illegal for reals" ); }
00709 
00710 #define ILLEGAL_OP1(op) \
00711 inline void op( double*, double* )\
00712 { fatal( NULL, #op " is illegal for reals" ); }
00713 
00714 ILLEGAL_OP2(Rsh);
00715 ILLEGAL_OP2(Lsh);
00716 
00717 ILLEGAL_OP2(Rep);
00718 ILLEGAL_OP2(Mod);
00719 ILLEGAL_OP2(And);
00720 ILLEGAL_OP2(Xor);
00721 ILLEGAL_OP2(Xnor);
00722 ILLEGAL_OP2(Or);
00723 ILLEGAL_OP2(Lor);
00724 ILLEGAL_OP2(Land);
00725 ILLEGAL_OP1(Com);
00726 ILLEGAL_OP1(Rand);
00727 ILLEGAL_OP1(Rnand);
00728 ILLEGAL_OP1(Ror);
00729 ILLEGAL_OP1(Rnor);
00730 ILLEGAL_OP1(Rxor);
00731 ILLEGAL_OP1(Rxnor);
00732 
00733 #define DEFINE_CONSTRUCTOR
00734 #include "cnode_def.h"
00735 #undef DEFINE_CONSTRUCTOR
00736 
00737 /****************************************************
00738         Node building helper routines
00739 *****************************************************/
00740 
00747 inline CNode*   cVECTOR( CVector& vec ) 
00748 {
00749         CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), vec.GetWidth() );
00750         CNode* n;
00751         *v = vec;
00752         v->SetPreferredBase( vec.GetPreferredBase() );
00753         n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00754         n->Arg<CVector*>(0) = v;
00755         return n;
00756 }
00757 
00764 inline CNode*   cSTRING( const char* s ) 
00765 {
00766         int len = strlen( s );
00767         if( !len ) {
00768              len = 1;
00769         }
00770         CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), len*8 );
00771         v->LoadString( s );
00772         CNode* n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00773         n->Arg<CVector*>(0) = v;
00774         return n;
00775 }
00776 
00783 inline CNode*   cINT32( INT32 i ) 
00784 {
00785         CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), 32 );
00786         CNode* n;
00787         *v = i;
00788         v->Sized(FALSE);
00789         v->Signed(TRUE);
00790         v->Based(FALSE);
00791         n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00792         n->Arg<CVector*>(0) = v;
00793         return n;
00794 }
00795 
00802 inline CNode* cREAL( double number ) 
00803 {
00804     CNode* node = new(CNode::CurrentHeap()) CNode( NULL, eRCONSTANT );
00805     node->Arg<char*>(0) = d2s(number,CNode::CurrentHeap());
00806     return node;
00807 }
00808 
00816 inline CNode*   cELINK( CNode* n1, CNode* n2 )
00817 {
00818         if( n1 == NULL ) {
00819                 return n2;
00820         } else if( n2 == NULL ) {
00821                 return n1;
00822         }
00823         return cELIST( n1, n2 );
00824 }
00825 
00833 inline CNode*   cABS( CNode* a ) 
00834 {
00835         CNode* a1 = a->Clone();
00836         CNode* a2 = a->Clone();
00837         CNode* c = cGE(a,cINT32(0));
00838         return cHOOK( c, a1, cNEG( a2) );
00839 }
00840 
00849 inline CNode*   cABSDIFF( CNode* a, CNode* b ) 
00850 {
00851         return cABS( cSUB( a, b ) );
00852 }
00853 
00862 inline CNode*   cLINK( CNode* n1, CNode* n2 )
00863 {
00864         if( n1 == NULL ) {
00865                 return n2;
00866         } else if( n2 == NULL ) {
00867                 return n1;
00868         }
00869         return cLIST( n1, n2 );
00870 }
00871 
00880 inline CNode*   cMAX( CNode* n1, CNode* n2 ) 
00881 {
00882         CNode* cond = cLT(n2->Clone(),n1->Clone());
00883         return cHOOK(cond,n1,n2);
00884 }
00885 
00886 
00887 /****************************************************
00888         utility routines
00889 *****************************************************/
00890 
00903 template<class T> void ArgList2Vector(CNode* n, NodeOp_t op, 
00904                                 int argNumber, vector<T>& v) 
00905 {
00906     if( !n ) {
00907         return;
00908     }
00909     switch( n->GetOp() ) {
00910     case eLIST:
00911         ArgList2Vector<T>(n->Arg<CNode*>(0),op,argNumber,v);
00912         ArgList2Vector<T>(n->Arg<CNode*>(1),op,argNumber,v);
00913         break;
00914     default:
00915         if( n->GetOp() == op ) {
00916             v.push_back(n->Arg<T>(argNumber));
00917         }
00918         break;
00919     }
00920 }
00921 
00930 inline void EList2VectorExclude(CNode* n, const set<NodeOp_t>& excludeOps, vector<CNode*>& v) 
00931 {
00932     if( !n ) {
00933         return;
00934     }
00935     switch( n->GetOp() ) {
00936     case eELIST:
00937         EList2VectorExclude(n->Arg<CNode*>(0),excludeOps,v);
00938         EList2VectorExclude(n->Arg<CNode*>(1),excludeOps,v);
00939         break;
00940     default:
00941         if( excludeOps.find(n->GetOp()) == excludeOps.end() ) {
00942             v.push_back(n);
00943         }
00944         break;
00945     }
00946 }
00947 
00956 inline void List2VectorExclude(CNode* n, const set<NodeOp_t>& excludeOps, vector<CNode*>& v) 
00957 {
00958     if( !n ) {
00959         return;
00960     }
00961     switch( n->GetOp() ) {
00962     case eLIST:
00963         List2VectorExclude(n->Arg<CNode*>(0),excludeOps,v);
00964         List2VectorExclude(n->Arg<CNode*>(1),excludeOps,v);
00965         break;
00966     default:
00967         if( excludeOps.find(n->GetOp()) == excludeOps.end() ) {
00968             v.push_back(n);
00969         }
00970         break;
00971     }
00972 }
00973 
00980 inline CNode* Vector2EList(const vector<CNode*>& v) 
00981 {
00982     CNode* result = NULL;
00983     vector<CNode*>::const_reverse_iterator ptr;
00984     for( ptr = v.rbegin(); ptr != v.rend(); ++ptr ) {
00985         if( result ) {
00986             result = cELIST(*ptr, result);
00987         } else {
00988             result = *ptr;
00989         }
00990     }
00991     return result;
00992 }
00993 
01000 inline CNode* List2EList(list<CNode*>& v) 
01001 {
01002     CNode* result = NULL;
01003     list<CNode*>::reverse_iterator ptr;
01004     for( ptr = v.rbegin(); ptr != v.rend(); ++ptr ) {
01005         if( result ) {
01006             result = cELIST(*ptr, result);
01007         } else {
01008             result = *ptr;
01009         }
01010     }
01011     return result;
01012 }
01013 
01022 inline int ListCount(CNode* n, NodeOp_t op) 
01023 {
01024     int result = 0;
01025     if( !n ) {
01026         return result;
01027     }
01028     switch( n->GetOp() ) {
01029     case eLIST:
01030     case eELIST:
01031         result += ListCount(n->Arg<CNode*>(0),op);
01032         result += ListCount(n->Arg<CNode*>(1),op);
01033         break;
01034     default:
01035         if( n->GetOp() == op ) {
01036             result = 1;
01037         }
01038         break;
01039     }
01040     return result;
01041 }
01042 
01049 inline int ListCount(CNode* n) 
01050 {
01051     int result = 0;
01052     if( !n ) {
01053         return result;
01054     }
01055     switch( n->GetOp() ) {
01056     case eLIST:
01057     case eELIST:
01058         result += ListCount(n->Arg<CNode*>(0));
01059         result += ListCount(n->Arg<CNode*>(1));
01060         break;
01061     default:
01062         result = 1;
01063         break;
01064     }
01065     return result;
01066 }
01067 
01078 inline double s2d( char* s ) {
01079         return atof(s);
01080 }
01081 
01090 inline char* d2s( double d, CObstack* heap ) {
01091      char buffer[256];
01092      // note this isn't quite correct as it will turn
01093      // reals into ints, ie 2.0 => 2
01094      snprintf( buffer, sizeof(buffer), "%g", d );
01095      char* s = (char*)heap->Alloc(strlen(buffer)+1);
01096      strcpy( s, buffer );
01097      return s;
01098 }
01099 
01100 /*********************************************
01101  * Adjust nodes structure to be efficient for
01102  * tail recursion
01103  *********************************************/
01104 inline CNode* RebalanceRight( CNode* n ) {
01105         if( n == NULL ) {
01106                 return n;
01107         }
01108         if( n->GetOp() != eLIST ) {
01109                 return n;
01110         }
01111         CNode* result = n;
01112         CNode* parent = NULL;   
01113         while( 1 ) {
01114             while( n->Arg<CNode*>(0) && n->Arg<CNode*>(0)->GetOp() == eLIST ) {
01115                 CNode* l = n->Arg<CNode*>(0);
01116                 CNode* ll = l->Arg<CNode*>(0);
01117                 CNode* lr = l->Arg<CNode*>(1);
01118                 l->Arg<CNode*>(1) = n;
01119                 n->Arg<CNode*>(0) = lr;
01120                 n = l;
01121                 if( parent ) { 
01122                     parent->Arg<CNode*>(1) = n;
01123                 } else {
01124                     result = n;
01125                 }
01126             }
01127             if( n->Arg<CNode*>(1) && n->Arg<CNode*>(1)->GetOp() == eLIST ) {
01128                 parent = n;
01129                 n = n->Arg<CNode*>(1);
01130             } else {
01131                 break;
01132             }
01133         }
01134         return result;
01135 }
01136 /*********************************************
01137  * Analyse tree struct.
01138  * - depth is worst case stack depth right side
01139  *   optimization.
01140  *   count is number nodes.
01141  *********************************************/
01142 inline void MeasureDepth( CNode* n, int* count, int* depth )
01143 {
01144     *count = 0;
01145     *depth = 0;
01146     if( !n ) {
01147         return;
01148     }
01149     if( n->GetOp() == eLIST ) {
01150         int count0 = 0;
01151         int depth0 = 0;
01152         int count1 = 0;
01153         int depth1 = 0;
01154         if( n->Arg<CNode*>(0) ) {
01155             MeasureDepth( n->Arg<CNode*>(0), &count0, &depth0 );
01156             depth0++;
01157         }
01158         if( n->Arg<CNode*>(1)  ) {
01159             MeasureDepth( n->Arg<CNode*>(1), &count1, &depth1 );
01160         }
01161         *count = count0+count1;
01162         *depth = depth0 > depth1 ? depth0 : depth1;
01163     }
01164     (*count)++;
01165 }
01166 
01167 
01168 /**************************************************
01169  * Helper routine for parser to build trees that 
01170  * are effient for tail recursion.
01171  *************************************************/
01172 inline CNode_pr cLINK( CNode_pr pr1, CNode* n2 )
01173 {
01174     if( !n2 ) {
01175         return pr1;
01176     } else if( !pr1.tail ) {
01177         CNode_pr pr;
01178         pr.head = n2;
01179         pr.tail = n2;
01180         return pr;
01181     } else if( pr1.tail->GetOp() != eLIST ) {
01182         CNode* t = cLINK( pr1.head, n2 );
01183         CNode_pr pr;
01184         pr.head = t;
01185         pr.tail = t;
01186         return pr;
01187     } else {
01188         pr1.tail->Arg<CNode*>(1) = cLINK(pr1.tail->Arg<CNode*>(1),n2);
01189         CNode_pr pr;
01190         pr.head = pr1.head;
01191         pr.tail = pr1.tail->Arg<CNode*>(1);
01192         return pr;
01193     }
01194 }
01195 
01196 /**************************************************
01197  * convert hierarchical reference tree to string
01198  *************************************************/
01199 inline string HierarchicalReference2String( CNode* ref )
01200 {
01201     string buffer;
01202     switch( ref->GetOp() ) {
01203     case eARRAY: {
01204         buffer = HierarchicalReference2String(ref->Arg<CNode*>(0)).c_str();
01205         vector<CNode*> indexes;
01206         EList2VectorExclude( ref->Arg<CNode*>(1), 
01207                          set<NodeOp_t>(), indexes );
01208         vector<CNode*>::iterator ptr;
01209         for( ptr = indexes.begin(); ptr != indexes.end(); ++ptr ) {
01210             switch( ref->Arg<CNode*>(0)->GetOp() ) {
01211             case eSLICE:
01212             case ePSLICE:
01213             case eMSLICE:
01214             break;
01215             default: {
01216                 INT32 value = (*ptr)->EvalINT32();
01217             ostringstream subscript;
01218             subscript << '[' << value << ']'; 
01219             buffer += subscript.str();
01220             } break;
01221             }
01222         }
01223         } break;
01224     case eMEMBER:
01225         buffer = HierarchicalReference2String(ref->Arg<CNode*>(0)).c_str();
01226         buffer += ".";
01227         buffer += ref->Arg<CSymbol*>(1)->GetName();
01228         break;
01229     case eEXTERNAL_REF:
01230         buffer = ref->Arg<CSymbol*>(0)->GetName();
01231         ref = NULL;
01232         break;
01233     case eNET_REF:              
01234     case eVAR_REF:              
01235     case ePARAM_REF:            
01236     case ePORT_REF:             
01237     case eFWD_REF:              
01238     case eGENVAR_REF:           
01239         buffer = ref->Arg<CDecl*>(0)->GetName();
01240         ref = NULL;
01241         break;
01242     default:;
01243         MASSERT( FALSE );
01244     }
01245     return buffer;
01246 }
01247 
01248 /*****************************************************
01249  * Support routines for cnode_def.h constructs
01250  *****************************************************/
01251 inline CNode* cMAX_N( CNode* first, ... )
01252 {
01253     CNode* result = first;
01254     va_list ap;
01255     va_start( ap, first );
01256     while( 1 ) {
01257         CNode* arg = va_arg(ap,CNode*);
01258         if( !arg ) {
01259             break;
01260         }
01261         if( !Equivalent( result, arg ) ) {
01262             result = cMAX( result, arg );
01263         }
01264     }
01265     va_end( ap );
01266     return result;
01267 }
01268 
01269 inline CNode* cADD_N( CNode* first, ... )
01270 {
01271     CNode* result = first;
01272     va_list ap;
01273     va_start( ap, first );
01274     while( 1 ) {
01275         CNode* arg = va_arg(ap,CNode*);
01276         if( !arg ) {
01277             break;
01278         }
01279         result = cADD( result, arg );
01280     }
01281     va_end( ap );
01282     return result;
01283 }
01284 
01285 inline CNode* cMUL_N( CNode* first, ... )
01286 {
01287     CNode* result = first;
01288     va_list ap;
01289     va_start( ap, first );
01290     while( 1 ) {
01291         CNode* arg = va_arg(ap,CNode*);
01292         if( !arg ) {
01293             break;
01294         }
01295         result = cMUL( result, arg );
01296     }
01297     va_end( ap );
01298     return result;
01299 }
01300 
01301 inline CNode* cABSDIFFPLUS1_N( CNode* first, ... )
01302 {
01303     va_list ap;
01304     va_start( ap, first );
01305     CNode* second = va_arg(ap,CNode*);
01306     /*
01307      * only make sense for 2 args
01308      */
01309     MASSERT( va_arg(ap,CNode*) == NULL );
01310     va_end( ap );
01311 //    return cADD(cABSDIFF(first,second),cINT32(1));
01312     return cHOOK(
01313                 cGE(first,second),
01314                 cADD(cSUB(first->Clone(),second->Clone()),cINT32(1)),
01315                 cADD(cSUB(second->Clone(),first->Clone()),cINT32(1)) );
01316                 
01317 }
01318 
01319 inline int cMAX( int a1, int a2 )
01320 {
01321     return a1 < a2 ? a2 : a1;
01322 }
01323 
01324 inline int cMAX( int a1, int a2, int a3 )
01325 {
01326     return cMAX(a1,cMAX(a2,a3));
01327 }
01328 
01329 inline int cADD( int a1, int a2 )
01330 {
01331     return a1 + a2;
01332 }
01333 
01334 inline int cMUL( int a1, int a2 )
01335 {
01336     return a1 * a2;
01337 }
01338 
01339 inline int cABSDIFFPLUS1( int a1, int a2 )
01340 {
01341     int diff = a1-a2;
01342     return (diff < 0 ? -diff : diff)+1;
01343 }
01344 
01345 
01346 #endif // CNODE_HPP
01347