GME  13
OCLTree.cpp
Go to the documentation of this file.
00001 //###############################################################################################################################################
00002 //
00003 //      Object Constraint Language Generic Manager
00004 //      OCLTree.cpp
00005 //
00006 //###############################################################################################################################################
00007 #include "Solve4786.h"
00008 #include "OCLTree.h"
00009 
00010 #include "OCLObjectExBasic.h"
00011 #include "OCLSignature.h"
00012 #include "OCLFeature.h"
00013 #include "OCLFeatureImplementation.h"
00014 #include "OCLParserStatic.h"
00015 #include "OCLException.h"
00016 
00017 #define NILNAMESPACE ""
00018 namespace OclTree
00019 {
00020         #define EXCEPTION0( iCode, pos )        \
00021                 OclCommon::Exception( OclCommon::Exception::ET_SEMANTIC, iCode, pos.iLine, pos.iColumn )
00022 
00023         #define EXCEPTION1( iCode, param1, pos ) \
00024                 OclCommon::Exception( OclCommon::Exception::ET_SEMANTIC, iCode, param1, pos.iLine, pos.iColumn )
00025 
00026         #define EXCEPTION2( iCode, param1, param2, pos ) \
00027                 OclCommon::Exception( OclCommon::Exception::ET_SEMANTIC, iCode, param1, param2, pos.iLine, pos.iColumn )
00028 
00029         #define ADDEX( ex ) \
00030         { \
00031                 OclCommon::Exception exp( ex ); \
00032                 context.m_poolExceptions.Add( exp ); \
00033         }
00034 
00035         #define ADDEXP( ex ) \
00036                 context.m_poolExceptions.Add( ex )
00037 
00038         #define POOLADDEX( ex_pool, ex ) \
00039         { \
00040                 OclCommon::Exception exp( ex ); \
00041                 ex_pool.Add( exp ); \
00042         }
00043 
00044         #define SETEXPOS( ex, pos ) \
00045                 ex.SetLine( pos.iLine ); ex.SetColumn( pos.iColumn );
00046 
00047         #define EVALTRY         \
00048                 try
00049 
00050         #define EVALCATCH( iLinee, strSigg )                                                                            \
00051                 catch ( OclCommon::Exception ex ) {                                                                     \
00052                         AddViolation( context, iLinee, strSigg, ex.GGetMessage() );             \
00053                 }                                                                                                                                               \
00054                 catch ( char* ex ) {                                                                                                    \
00055                         AddViolation( context, iLinee, strSigg, std::string( ex ) + " " );              \
00056                 }                                                                                                                                               \
00057                 catch ( ... ) {                                                                                                                 \
00058                         AddViolation( context, iLinee, strSigg, "UNEX" );                                       \
00059                 }
00060 
00061 //##############################################################################################################################################
00062 //
00063 //      A B S T R A C T   C L A S S : OclTree::TreeNode
00064 //
00065 //==============================================================================================================================================
00066 //
00067 //      D E S C R I P T I O N :
00068 //
00069 //##############################################################################################################################################
00070 
00071         TreeNode::TreeNode( TreeManager* pManager, NodeKind eKind )
00072                 : m_pManager( pManager ), m_eKind( eKind ), m_bTester( false ), m_bSelfTester( false )
00073         {
00074         }
00075 
00076         TreeNode::~TreeNode()
00077         {
00078         }
00079 
00080         TreeManager* TreeNode::GetTreeManager() const
00081         {
00082                 return m_pManager;
00083         }
00084 
00085         TreeNode::NodeKind TreeNode::GetKind() const
00086         {
00087                 return m_eKind;
00088         }
00089 
00090         bool TreeNode::ParseTypeSeq( TypeContext& context, const Position& position, std::string& strType, TypeSeq& vecType ) const
00091         {
00092                 TypeSeq vecSavedType = vecType;
00093                 int iRes = OclCommon::Convert( strType, vecType );
00094                 if ( iRes > 0 ) {
00095                         ADDEX( EXCEPTION1( EX_INVALID_TYPE, strType, position ) );
00096                         return false;
00097                 }
00098                 bool bValid = true;
00099                 for ( unsigned int i = 0 ; i < vecType.size() ; i++ ) {
00100                         try {
00101                                 std::shared_ptr<OclMeta::Type> pType = m_pManager->GetTypeManager()->GetType( vecType[ i ], context.m_namespace);
00102                                 if ( i != vecType.size() - 1 ) {
00103                                         if ( ! pType->IsCompound() ) {
00104                                                 ADDEX( EXCEPTION1( EX_TYPE_ISNT_COMPOUND, vecType[ i ], position ) );
00105                                                 bValid = false;
00106                                         }
00107                                 }
00108                                 else {
00109                                         if ( pType->IsCompound() )
00110                                                 vecType.push_back( "ocl::Any" );
00111                                 }
00112                                 if ( bValid )
00113                                         vecType[ i ] = pType->GetName();
00114                         } catch ( OclCommon::Exception ex ) {
00115                                 SETEXPOS( ex, position );
00116                                 ADDEX( ex );
00117                                 bValid = false;
00118                         }
00119                 }
00120                 if ( ! bValid )
00121                         vecType = vecSavedType;
00122                 else
00123                         OclCommon::Convert( vecType, strType );
00124                 return bValid;
00125         }
00126 
00127         bool TreeNode::CastType( TypeContext& context, const Position& position, const TypeSeq& vecTypeFrom, const TypeSeq& vecTypeTo ) const
00128         {
00129                 OclMeta::TypeManager* pManager = m_pManager->GetTypeManager();
00130                 if ( ! pManager->IsTypeA( vecTypeFrom, vecTypeTo ) && ! pManager ->IsTypeA( vecTypeTo, vecTypeFrom ) ) {
00131                         std::string strCType, strSType;
00132                         OclCommon::Convert( vecTypeFrom, strSType );
00133                         OclCommon::Convert( vecTypeTo, strCType );
00134                         ADDEX( EXCEPTION2( EX_CAST_TYPE_MISMATCH, strSType, strCType, position ) );
00135                         return false;
00136                 }
00137                 return true;
00138         }
00139 
00140         TypeSeq TreeNode::GetParametralTypeSeq( const TypeSeq& vecType1, const TypeSeq& vecType2, const TypeSeq& vecTypeReturn )
00141         {
00142                 m_vecType.clear();
00143                 int i;
00144 
00145                 for ( i = 0 ; i < (int) vecTypeReturn.size() - 1 ; i++ )
00146                         m_vecType.push_back( vecTypeReturn[ i ] );
00147 
00148                 std::string strLastType = vecTypeReturn[ vecTypeReturn.size() - 1 ];
00149 
00150                 if ( strLastType == TYPE_AGGREGATED_OBJECT ) {
00151                         for ( i = 1 ; i < (int) vecType1.size() ; i++ )
00152                                 m_vecType.push_back( vecType1[ i ] );
00153                         return m_vecType;
00154                 }
00155 
00156                 if ( ! vecType2.empty() ) {
00157 
00158                         if ( strLastType == TYPE_EXPRESSION_RETURN ) {
00159                                 for ( i = 0 ; i < (int) vecType2.size() ; i++ )
00160                                         m_vecType.push_back( vecType2[ i ] );
00161                                 return m_vecType;
00162                         }
00163 
00164                         if ( GetTreeManager()->GetTypeManager()->GetType( vecType1[ 0 ], NILNAMESPACE )->IsCompound() ) {
00165 
00166                                 if ( strLastType == TYPE_ARGUMENT_SELF_BASE || strLastType == TYPE_COMPOUNDARGUMENT_SELF_BASE ) {
00167 
00168                                         TypeSeq vecTypeS = vecType1;
00169                                         vecTypeS.erase( vecTypeS.begin() );
00170                                         TypeSeq vecTypeA = vecType2;
00171 
00172                                         if ( strLastType == TYPE_COMPOUNDARGUMENT_SELF_BASE && GetTreeManager()->GetTypeManager()->GetType( vecType2[ 0 ], NILNAMESPACE )->IsCompound() )
00173                                                 vecTypeA.erase( vecTypeA.begin() );
00174 
00175                                         vecTypeS = GetTreeManager()->GetTypeManager()->GetTypeBase( vecTypeS, vecTypeA );
00176                                         for ( i = 0 ; i < (int) vecTypeS.size() ; i++ )
00177                                                 m_vecType.push_back( vecTypeS[ i ] );
00178 
00179                                         return m_vecType;
00180                                 }
00181                         }
00182                 }
00183 
00184                 m_vecType.push_back( strLastType );
00185                 return m_vecType;
00186         }
00187 
00188         VariableNode* TreeNode::CreateThis( TypeContext& context, int iImplicitPos ) const
00189         {
00190                 if ( iImplicitPos == -1 )
00191                         iImplicitPos = context.m_vecImplicits.size() - 1;
00192 
00193                 VariableNode* pVariableNode = GetTreeManager()->CreateVariable();
00194                 pVariableNode->m_strName = context.m_vecImplicits[ iImplicitPos ];
00195                 context.m_ctxTypes.GetVariable(  context.m_vecImplicits[ iImplicitPos ], pVariableNode->m_vecType );
00196                 return pVariableNode;
00197         }
00198 
00199         int TreeNode::GetLastExceptionCode( TypeContext& context ) const
00200         {
00201                 int iLastCode = context.m_poolExceptions.Size();
00202                 return ( iLastCode == 0 ) ? -1 : context.m_poolExceptions.GetAt( context.m_poolExceptions.Size() - 1 ).GetCode();
00203         }
00204 
00205         OclMeta::Feature* TreeNode::CheckAmbiguity( const std::vector<OclMeta::Type*>& vecTypes, const std::vector<OclSignature::Feature*>& vecSignatures, std::vector<int>& vecAmbiguities, int& iPrecedence, OclCommon::ExceptionPool& exAmbiguity )
00206         {
00207                 OclCommon::Exception exception;
00208                 OclCommon::Exception exception2;
00209                 OclMeta::Feature* feature1 = NULL;
00210                 OclMeta::Feature* feature2 = NULL;
00211                 try {
00212                         switch ( vecSignatures[ 0 ]->GetKind() ) {
00213                                 case OclSignature::Feature::FK_OPERATOR                 : feature1 = m_pManager->GetTypeManager()->GetOperator( *( (OclSignature::Operator*)vecSignatures[ 0 ] ) ); break;
00214                                 case OclSignature::Feature::FK_FUNCTION                 : feature1 = m_pManager->GetTypeManager()->GetFunction( *( (OclSignature::Function*)vecSignatures[ 0 ] ) ); break;
00215                                 case OclSignature::Feature::FK_METHOD                   : feature1 = vecTypes[ 0 ]->GetMethod( *( (OclSignature::Method*)vecSignatures[ 0 ] ) ); break;
00216                                 case OclSignature::Feature::FK_ITERATOR                 : feature1 = ( ( OclMeta::CompoundType*) vecTypes[ 0 ] )->GetIterator(0, *( (OclSignature::Iterator*)vecSignatures[ 0 ] ) ); break;
00217                                 case OclSignature::Feature::FK_ATTRIBUTE                : feature1 = vecTypes[ 0 ]->GetAttribute( *( (OclSignature::Attribute*)vecSignatures[ 0 ] ) ); break;
00218                                 case OclSignature::Feature::FK_ASSOCIATION      : feature1 = vecTypes[ 0 ]->GetAssociation( *( (OclSignature::Association*)vecSignatures[ 0 ] ) ); break;
00219                         }
00220                         if ( iPrecedence == -1 )
00221                                 return feature1;
00222                 }
00223                 catch ( OclCommon::Exception ex ) {
00224                         if ( iPrecedence == -1 )  {
00225                                 exAmbiguity.Add( ex );
00226                                 return NULL;
00227                         }
00228                         exception = ex;
00229                 }
00230                 try {
00231                         switch ( vecSignatures[ 1 ]->GetKind() ) {
00232                                 case OclSignature::Feature::FK_OPERATOR                 : feature2 = m_pManager->GetTypeManager()->GetOperator( *( (OclSignature::Operator*)vecSignatures[ 1 ] ) ); break;
00233                                 case OclSignature::Feature::FK_FUNCTION                 : feature2 = m_pManager->GetTypeManager()->GetFunction( *( (OclSignature::Function*)vecSignatures[ 1 ] ) ); break;
00234                                 case OclSignature::Feature::FK_METHOD                   : feature2 = vecTypes[ 1 ]->GetMethod( *( (OclSignature::Method*)vecSignatures[ 1 ] ) ); break;
00235                                 case OclSignature::Feature::FK_ITERATOR                 : feature2 = ( ( OclMeta::CompoundType*) vecTypes[ 1 ] )->GetIterator(0, *( (OclSignature::Iterator*)vecSignatures[ 1 ] ) ); break;
00236                                 case OclSignature::Feature::FK_ATTRIBUTE                : feature2 = vecTypes[ 1 ]->GetAttribute( *( (OclSignature::Attribute*)vecSignatures[ 1 ] ) ); break;
00237                                 case OclSignature::Feature::FK_ASSOCIATION      : feature2 = vecTypes[ 1 ]->GetAssociation( *( (OclSignature::Association*)vecSignatures[ 1 ] ) ); break;
00238                         }
00239                         if ( iPrecedence == 1 )
00240                                 return feature2;
00241 
00242                         vecAmbiguities[ 1 ] = 0;
00243                         if ( feature1 || ! feature1 && exception.GetCode() == vecAmbiguities[ 0 ] ) {
00244                                 if ( feature1 )
00245                                         vecAmbiguities[ 0 ] = 0;
00246                                 POOLADDEX(exAmbiguity, OclCommon::Exception( OclCommon::Exception::ET_SEMANTIC, vecAmbiguities[ 2 ], vecSignatures[ 0 ]->Print(), vecSignatures[ 1 ]->Print() ) );
00247                                 return NULL;
00248                         }
00249                         iPrecedence = 1;
00250                         return feature2;
00251                 }
00252                 catch ( OclCommon::Exception ex ) {
00253                         if ( iPrecedence == 1 )  {
00254                                 exAmbiguity.Add( ex );
00255                                 return NULL;
00256                         }
00257 
00258                         if ( ex.GetCode() == vecAmbiguities[ 1 ] ) {
00259                                 if ( feature1 || ! feature1 && exception.GetCode() == vecAmbiguities[ 0 ] ) {
00260                                         if ( feature1 )
00261                                                 vecAmbiguities[ 0 ] = 0;
00262                                         POOLADDEX(exAmbiguity, OclCommon::Exception( OclCommon::Exception::ET_SEMANTIC, vecAmbiguities[ 2 ], vecSignatures[ 0 ]->Print(), vecSignatures[ 1 ]->Print() ) );
00263                                         return NULL;
00264                                 }
00265                                 else {
00266                                         vecAmbiguities[ 0 ] = exception.GetCode();
00267                                         exAmbiguity.Add( ex );
00268                                         return NULL;
00269                                 }
00270                         }
00271                         else {
00272                                 vecAmbiguities[ 1 ] = ex.GetCode();
00273                                 if ( feature1 ) {
00274                                         vecAmbiguities[ 0 ] = 0;
00275                                         iPrecedence = -1;
00276                                         return feature1;
00277                                 }
00278                                 else {
00279                                         exAmbiguity.Add( exception );
00280                                         if ( exception.GetCode() != vecAmbiguities[ 0 ] )
00281                                                 exAmbiguity.Add( ex );
00282                                         vecAmbiguities[ 0 ] = exception.GetCode();
00283                                         return NULL;
00284                                 }
00285                         }
00286                 }
00287         }
00288 
00289         void TreeNode::AddViolation( ObjectContext& context, int iLine, const std::string& strSignature, const std::string& strMessage )
00290         {
00291                 if ( ! context.m_bEnableTracking )
00292                         return;
00293 
00294                 Violation violation;
00295 
00296                 violation.bIsException = ! strMessage.empty();
00297                 violation.position.iLine = iLine;
00298                 if ( strMessage.empty() )
00299                         violation.strMessage = "Expression evaluated to false.";
00300                 else
00301                         if ( strMessage == "UNEX" )
00302                                 violation.strMessage = "Unexpected exception occurred.";
00303                         else
00304                                 violation.strMessage = strMessage;
00305                 violation.strSignature = strSignature;
00306 
00307                 ObjectContextStack::StateItemVector vecItems = context.oCtx.GetState();
00308                 for ( unsigned int i = 0 ; i < vecItems.size() ; i++ ) {
00309 //                      ObjectContextStack::StateItem itemx = vecItems[i];
00310                         string nam = vecItems[ i ].name;
00311                         violation.vecVariables.push_back( nam );
00312                         string str = vecItems[ i ].item.Print();
00313                         violation.vecObjects.push_back( str );
00314                         IUnknown* iu;
00315                         iu = vecItems[ i ].item.GetObject();
00316                         violation.vecObjectsPtr.push_back(iu);
00317                 }
00318                 context.vecViolations.push_back( violation );
00319                 context.iViolationCount++;
00320 
00321                 if ( violation.bIsException )
00322                         context.m_bHasException;
00323         }
00324 
00325         // terge
00326         void TreeNode::AddViolation(ObjectContext& context, Violation &violation)
00327         {
00328                 context.vecViolations.push_back( violation );
00329                 context.iViolationCount++;
00330 
00331                 if ( violation.bIsException )
00332                         context.m_bHasException;
00333         }
00334 
00335         bool TreeNode::IsBooleanReturned()
00336         {
00337                 return GetTreeManager()->GetTypeManager()->IsTypeA( m_vecType[ 0 ], "ocl::Boolean" ) >= 0;
00338         }
00339 
00340         OclMeta::Object TreeNode::CheckFalseResult( ObjectContext& context, OclMeta::Object spObject, int iLine, const std::string& strSignature )
00341         {
00342                 if ( spObject.IsUndefined() )
00343                         return spObject;
00344                 if ( IsBooleanReturned() && context.bDoSnapshot ) {
00345                         DECL_BOOLEAN( bResult, spObject );
00346                         if ( ! bResult )
00347                                 AddViolation( context, iLine, strSignature );
00348                 }
00349                 return spObject;
00350         }
00351 
00352         OclMeta::Object TreeNode::EvaluateCast( ObjectContext& context, OclMeta::Object spObject, int iLine, const std::string& strSignature, const std::string& strTypeName, bool bOnlyTest )
00353         {
00354                 std::string strTypeName2 = ( strTypeName.empty() ) ? m_vecType[ 0 ] : strTypeName;
00355                 if ( spObject.IsUndefined() )
00356                         return spObject;
00357                 EVALTRY {
00358                         if ( GetTreeManager()->GetTypeManager()->IsTypeA( spObject.GetTypeName(), strTypeName2 ) >= 0 ) {
00359                                 if ( ! bOnlyTest ) {
00360                                         OclMeta::Object spNewObject( spObject );
00361                                         spNewObject.SetStaticTypeName( strTypeName2 );
00362                                         return spNewObject;
00363                                 }
00364                                 return spObject;
00365                         }
00366                         AddViolation( context, iLine, strSignature, "Object is not instance of type [ " + strTypeName2 + " ]." );
00367                         return OclMeta::Object::UNDEFINED;
00368                 } EVALCATCH( iLine, "At casting object: " + strSignature );
00369                 return OclMeta::Object::UNDEFINED;
00370         }
00371 
00372         void TreeNode::CheckInitialize()
00373         {
00374                 m_vecType.clear();
00375                 m_bSelfTester = false;
00376         }
00377 
00378         bool TreeNode::Check( TypeContext& context )
00379         {
00380                 CheckInitialize();
00381                 return CheckImplementation( context );
00382         }
00383 
00384 //##############################################################################################################################################
00385 //
00386 //      C L A S S : OclNodes::ObjectNode <<< + OclTree::TreeNode
00387 //
00388 //##############################################################################################################################################
00389 
00390         ObjectNode::ObjectNode( TreeManager* pManager )
00391                 : TreeNode( pManager, TreeNode::NK_OBJECT ), m_strType( "" ), m_strValue( "" )
00392         {
00393         }
00394 
00395         std::string ObjectNode::Print( const std::string& strTabs ) const
00396         {
00397                 return GetTreeManager()->m_pOAdaptor->Print( strTabs, (ObjectNode*)this );
00398         }
00399 
00400         bool ObjectNode::CheckImplementation( TypeContext& context )
00401         {
00402                 return GetTreeManager()->m_pOAdaptor->Check( context, (ObjectNode*)this );
00403         }
00404 
00405         OclMeta::Object ObjectNode::Evaluate( ObjectContext& context )
00406         {
00407                 OclMeta::Object spResult = GetTreeManager()->m_pOAdaptor->Evaluate( context, (ObjectNode*)this );
00408                 spResult = EvaluateCast( context, spResult, m_mapPositions[ LID_NODE_START ].iLine, "At creating object: " + m_vecType[ 0 ] );
00409                 return CheckFalseResult( context, spResult, m_mapPositions[ LID_NODE_START ].iLine, "At creating object: " + m_vecType[ 0 ] );
00410         }
00411 
00412 //##############################################################################################################################################
00413 //
00414 //      C L A S S : OclTree::CollectionNode <<< + OclTree::TreeNode
00415 //
00416 //==============================================================================================================================================
00417 //
00418 //      D E S C R I P T I O N :
00419 //
00420 //##############################################################################################################################################
00421 
00422         CollectionNode::CollectionNode( TreeManager* pManager )
00423                 : TreeNode( pManager, TreeNode::NK_COLLECTION ), m_strType( "" )
00424         {
00425         }
00426 
00427         CollectionNode::~CollectionNode()
00428         {
00429                 if ( ! m_bTester && ! m_bSelfTester )
00430                         for ( unsigned int i = 0; i < m_vecNodes.size() ; i++ )
00431                                 delete m_vecNodes[ i ];
00432         }
00433 
00434         std::string CollectionNode::Print( const std::string& strTabs ) const
00435         {
00436                 return GetTreeManager()->m_pCAdaptor->Print( strTabs, (CollectionNode*)this );
00437         }
00438 
00439         bool CollectionNode::CheckImplementation( TypeContext& context )
00440         {
00441                 return GetTreeManager()->m_pCAdaptor->Check( context, (CollectionNode*)this );
00442         }
00443 
00444         OclMeta::Object CollectionNode::Evaluate( ObjectContext& context )
00445         {
00446                 OclMeta::Object spResult = GetTreeManager()->m_pCAdaptor->Evaluate( context, (CollectionNode*)this );
00447                 spResult = EvaluateCast( context, spResult, m_mapPositions[ LID_NODE_START ].iLine, "At creating collection: " + m_vecType[ 0 ] );
00448                 return CheckFalseResult( context, spResult, m_mapPositions[ LID_NODE_START ].iLine, "At creating collection: " + m_vecType[ 0 ] );
00449         }
00450 
00451 //##############################################################################################################################################
00452 //
00453 //      C L A S S : OclNodes::DeclarationNode <<< + OclNodes::SyntaxTreeNode
00454 //
00455 //##############################################################################################################################################
00456 
00457         DeclarationNode::DeclarationNode( TreeManager* pManager )
00458                 : TreeNode( pManager, TreeNode::NK_DECLARATION ), m_strName( "" ), m_strType( "" ), m_pValueNode( NULL ), m_pInnerNode( NULL )
00459         {
00460         }
00461 
00462         DeclarationNode::~DeclarationNode()
00463         {
00464                 if ( ! m_bTester && ! m_bSelfTester ) {
00465                         if ( m_pInnerNode )
00466                                 delete m_pInnerNode;
00467                         if ( m_pValueNode )
00468                                 delete m_pValueNode;
00469                 }
00470         }
00471 
00472         std::string DeclarationNode::Print( const std::string& strTabs ) const
00473         {
00474                 std::string strOut = strTabs + "<Declaration name=\"" + m_strName + "\" type=\"" + m_strType + "\">\r\n";
00475 
00476                 strOut += strTabs + TABSTR + "<Variable>\r\n";
00477                 strOut += m_pValueNode->Print( strTabs + TABSTR + TABSTR );
00478                 strOut += strTabs + TABSTR + "</Variable>\r\n";
00479 
00480                 strOut += strTabs + TABSTR + "<Expression>\r\n";
00481                 strOut += m_pInnerNode->Print( strTabs + TABSTR + TABSTR );
00482                 strOut += strTabs + TABSTR + "</Expression>\r\n";
00483 
00484                 strOut += strTabs + "</Declaration>\r\n";
00485                 return strOut;
00486         }
00487 
00488         void DeclarationNode::CheckInitialize()
00489         {
00490                 TreeNode::CheckInitialize();
00491                 m_vecTypeDecl.clear();
00492         }
00493 
00494         bool DeclarationNode::CheckImplementation( TypeContext& context )
00495         {
00496                 // Check Expression of Declaration
00497 
00498                 if ( m_pValueNode->Check( context ) )
00499                         m_vecTypeDecl = m_pValueNode->m_vecType;
00500 
00501                 // Check explicit type of variable if it exists
00502 
00503                 if ( ! m_strType.empty() )
00504                         if ( ParseTypeSeq( context, m_mapPositions[ LID_VARIABLE_TYPE ], m_strType, m_vecTypeDecl ) )
00505                                 if ( ! m_pValueNode->m_vecType.empty() )
00506                                         if ( ! CastType( context, m_mapPositions[ LID_VARIABLE_TYPE ], m_pValueNode->m_vecType, m_vecTypeDecl ) )
00507                                                 m_vecTypeDecl.clear();
00508 
00509 
00510                 // Check if variable already exists , Add variable
00511 
00512                 if ( context.m_ctxTypes.ExistsVariable( m_strName ) )
00513                         ADDEX( EXCEPTION1( EX_VARIABLE_ALREADY_EXISTS, m_strName, m_mapPositions[ LID_VARIABLE_NAME ] ) )
00514                 else
00515                         if ( ! m_vecTypeDecl.empty() )
00516                                 context.m_ctxTypes.AddVariable( m_strName, m_vecTypeDecl, true );
00517 
00518                 // Check Expression
00519 
00520                 if ( m_pInnerNode->Check( context ) )
00521                         m_vecType = m_pInnerNode->m_vecType;
00522 
00523                 // Remove Variable
00524 
00525                 if ( ! m_vecTypeDecl.empty() )
00526                         context.m_ctxTypes.RemoveVariable( m_strName );
00527 
00528                 return ! m_vecType.empty() && ! m_pValueNode->m_vecType.empty();
00529         }
00530 
00531         OclMeta::Object DeclarationNode::Evaluate( ObjectContext& context )
00532         {
00533                 OclMeta::Object spObject = EvaluateCast( context, m_pValueNode->Evaluate( context ), m_mapPositions[ LID_NODE_START ].iLine, "let " + m_strName + " : " + m_vecTypeDecl[ 0 ] + " = ...", m_vecTypeDecl[ 0 ], m_strType.empty() );
00534 
00535                 context.oCtx.AddVariable( m_strName, spObject, true );
00536                 OclMeta::Object spResult = m_pInnerNode->Evaluate( context );
00537                 context.oCtx.RemoveVariable( m_strName );
00538 
00539                 return spResult;
00540         }
00541 
00542 //##############################################################################################################################################
00543 //
00544 //      C L A S S : OclTree::TypeCastNode <<< + OclTree::TreeNode
00545 //
00546 //==============================================================================================================================================
00547 //
00548 //      D E S C R I P T I O N :
00549 //
00550 //##############################################################################################################################################
00551 
00552         TypeCastNode::TypeCastNode( TreeManager* pManager )
00553                 : TreeNode( pManager, TreeNode::NK_TYPECAST ), m_pThisNode( NULL ), m_strType( "" ), m_bIsDynamic( false )
00554         {
00555         }
00556 
00557         TypeCastNode::~TypeCastNode()
00558         {
00559                 if ( ! m_bTester )
00560                         if ( m_pThisNode )
00561                                 delete m_pThisNode;
00562         }
00563 
00564         std::string TypeCastNode::Print( const std::string& strTabs ) const
00565         {
00566                 std::string strOut = strTabs + "<TypeCast type=\"" + m_strType + "\" dynamic=\"" + ( ( m_bIsDynamic ) ? "true" : "false" ) + "\">\r\n";
00567 
00568                 strOut += strTabs + TABSTR + "<This>\r\n";
00569                 if ( m_pThisNode )
00570                         strOut += m_pThisNode->Print( strTabs + TABSTR + TABSTR );
00571                 strOut += strTabs + TABSTR + "</This>\r\n";
00572 
00573                 strOut += strTabs + "</TypeCast>\r\n";
00574                 return strOut;
00575         }
00576 
00577         void TypeCastNode::CheckInitialize()
00578         {
00579                 if ( m_bSelfTester && m_pThisNode ) {
00580                         delete m_pThisNode;
00581                         m_pThisNode = NULL;
00582                 }
00583                 TreeNode::CheckInitialize();
00584         }
00585 
00586         bool TypeCastNode::CheckImplementation( TypeContext& context )
00587         {
00588                 bool bThisValid = true;
00589                 if ( ! m_pThisNode ) {
00590                         if ( context.m_vecImplicits.empty() )
00591                                 return false;
00592                         m_bSelfTester = true;
00593                         m_pThisNode = CreateThis( context, -1 );
00594                 }
00595                 else
00596                         bThisValid = m_pThisNode->Check( context );
00597 
00598                 if ( bThisValid ) {
00599 
00600                         // Check if Object Node is callable
00601 
00602                         if ( m_pThisNode->GetKind() == TreeNode::NK_OBJECT ) {
00603                                 ObjectNode* pONode = (ObjectNode*) m_pThisNode;
00604                                 if ( ! pONode->m_bCallable )
00605                                         ADDEX( EXCEPTION1( EX_OBJECT_CALL_PROHIBITED, m_pThisNode->m_vecType[ 0 ], m_mapPositions[ LID_CALL_OPERATOR ] ) );
00606                         }
00607 
00608                         if ( ParseTypeSeq( context, m_mapPositions[ LID_FEATURE_NAME ], m_strType, m_vecType ) ) {
00609                                 if ( ! CastType( context, m_mapPositions[ LID_FEATURE_NAME ], m_pThisNode->m_vecType, m_vecType ) ) {
00610                                         m_vecType.clear();
00611                                         return false;
00612                                 }
00613                                 return true;
00614                         }
00615                 }
00616                 return false;
00617         }
00618 
00619         OclMeta::Object TypeCastNode::Evaluate( ObjectContext& context )
00620         {
00621                 return EvaluateCast( context, m_pThisNode->Evaluate( context ), m_mapPositions[ LID_FEATURE_NAME ].iLine, "ocl::Any::oclAsType( ocl::Type )" , m_vecType[ 0 ], false );
00622         }
00623 
00624 //##############################################################################################################################################
00625 //
00626 //      C L A S S : OclTree::IfThenElseNode <<< + OclTree::TreeNode
00627 //
00628 //##############################################################################################################################################
00629 
00630         IfThenElseNode::IfThenElseNode( TreeManager* pManager )
00631                 : TreeNode( pManager, TreeNode::NK_IFTHENELSE ), m_pIfNode( NULL ), m_pThenNode( NULL ), m_pElseNode( NULL )
00632         {
00633         }
00634 
00635         IfThenElseNode::~IfThenElseNode()
00636         {
00637                 if ( ! m_bTester && ! m_bSelfTester ) {
00638                         if ( m_pIfNode )
00639                                 delete m_pIfNode;
00640                         if ( m_pThenNode )
00641                                 delete m_pThenNode;
00642                         if ( m_pElseNode )
00643                                 delete m_pElseNode;
00644                 }
00645         }
00646 
00647         std::string IfThenElseNode::Print( const std::string& strTabs ) const
00648         {
00649                 std::string strOut = strTabs + "<IfThenElse>\r\n";
00650 
00651                 strOut += strTabs + TABSTR + "<IfExpression>\r\n";
00652                 strOut += m_pIfNode->Print( strTabs + TABSTR + TABSTR );
00653                 strOut += strTabs + TABSTR + "</IfExpression>\r\n";
00654 
00655                 strOut += strTabs + TABSTR + "<ThenExpression>\r\n";
00656                 strOut += m_pThenNode->Print( strTabs + TABSTR + TABSTR );
00657                 strOut += strTabs + TABSTR + "</ThenExpression>\r\n";
00658 
00659                 strOut += strTabs + TABSTR + "<ElseExpression>\r\n";
00660                 strOut += m_pElseNode->Print( strTabs + TABSTR + TABSTR );
00661                 strOut += strTabs + TABSTR + "</ElseExpression>\r\n";
00662 
00663                 strOut += strTabs + "</IfThenElse>\r\n";
00664                 return strOut;
00665         }
00666 
00667         bool IfThenElseNode::CheckImplementation( TypeContext& context )
00668         {
00669                 // Check if IF Expression returns kind of ocl::Boolean
00670 
00671                 bool bIfValid = m_pIfNode->Check( context );
00672                 if ( bIfValid ) {
00673                         TypeSeq vecTypeB( 1, "ocl::Boolean" );
00674                         bIfValid = GetTreeManager()->GetTypeManager()->IsTypeA( m_pIfNode->m_vecType, vecTypeB );
00675                         if ( ! bIfValid )
00676                                 ADDEX( EXCEPTION0( EX_BOOLEAN_REQUIRED, m_pIfNode->m_mapPositions[ LID_NODE_START ] ) );
00677                 }
00678 
00679                 // Check THEN and ELSE Expressions
00680 
00681                 bool bThenElseValid = m_pThenNode->Check( context );
00682                 bThenElseValid = m_pElseNode->Check( context ) && bThenElseValid;
00683 
00684                 // Check whether these Expression returns the same type
00685 
00686                 if ( bThenElseValid ) {
00687                         if ( ! ( m_pThenNode->m_vecType[ 0 ] == m_pElseNode->m_vecType[ 0 ] ) ) {
00688                                 std::string strType1, strType2;
00689                                 OclCommon::Convert( m_pThenNode->m_vecType, strType1 );
00690                                 OclCommon::Convert( m_pElseNode->m_vecType, strType2 );
00691                                 ADDEX( EXCEPTION2( EX_IF_TYPE_MISMATCH, strType1, strType2, m_mapPositions[ LID_NODE_START ] ) );
00692                                 return false;
00693                         }
00694                         if ( bIfValid ) {
00695                                 m_vecType = GetTreeManager()->GetTypeManager()->GetTypeBase( m_pThenNode->m_vecType, m_pElseNode->m_vecType );
00696                                 return true;
00697                         }
00698                 }
00699                 return false;
00700         }
00701 
00702         OclMeta::Object IfThenElseNode::Evaluate( ObjectContext& context )
00703         {
00704                 OclMeta::Object spCondition = m_pIfNode->Evaluate( context );
00705                 if ( spCondition.IsUndefined() )
00706                         return spCondition;
00707 
00708                 DECL_BOOLEAN( bCondition, spCondition );
00709                 if ( bCondition )
00710                         return m_pThenNode->Evaluate( context );
00711                 else
00712                         return m_pElseNode->Evaluate( context );
00713         }
00714 
00715 //##############################################################################################################################################
00716 //
00717 //      C L A S S : OclTree::OperatorNode <<< + OclTree::TreeNode
00718 //
00719 //##############################################################################################################################################
00720 
00721         OperatorNode::OperatorNode( TreeManager* pManager )
00722                 : TreeNode( pManager, TreeNode::NK_OPERATOR ), m_pOperandNode1( NULL ), m_pOperandNode2( NULL ), m_strName( "" )
00723         {
00724         }
00725 
00726         OperatorNode::~OperatorNode()
00727         {
00728                 if ( ! m_bTester && ! m_bSelfTester ) {
00729                         if ( m_pOperandNode1 )
00730                                 delete m_pOperandNode1;
00731                         if ( m_pOperandNode2 )
00732                                 delete m_pOperandNode2;
00733                 }
00734         }
00735 
00736         std::string OperatorNode::Print( const std::string& strTabs ) const
00737         {
00738                 std::string strOut = strTabs + "<Operator name=\"" + m_strName + "\">\r\n";
00739 
00740                 strOut += strTabs + TABSTR + "<Operand1>\r\n";
00741                 strOut += m_pOperandNode1->Print( strTabs + TABSTR + TABSTR );
00742                 strOut += strTabs + TABSTR + "</Operand1>\r\n";
00743 
00744                 if ( m_pOperandNode2 ) {
00745                         strOut += strTabs + TABSTR + "<Operand2>\r\n";
00746                         strOut += m_pOperandNode2->Print( strTabs + TABSTR + TABSTR );
00747                         strOut += strTabs + TABSTR + "</Operand2>\r\n";
00748                 }
00749 
00750                 strOut += strTabs + "</Operator>\r\n";
00751                 return strOut;
00752         }
00753 
00754         void OperatorNode::CheckInitialize()
00755         {
00756                 TreeNode::CheckInitialize();
00757                 m_strAssignVarName = "";
00758         }
00759 
00760         bool OperatorNode::CheckImplementation( TypeContext& context )
00761         {
00762                 bool bIsValid = m_pOperandNode1->Check( context );
00763                 if ( m_pOperandNode2 )
00764                         bIsValid = m_pOperandNode2->Check( context ) && bIsValid;
00765 
00766                 if ( bIsValid ) {
00767 
00768                         /*
00769                                 This Feature is commented for the time being
00770 
00771                         // Assignment operator check
00772 
00773                         if ( m_strName == "=" && m_pOperandNode2 && m_pOperandNode1->GetKind() == TreeNode::NK_VARIABLE ) {
00774                                 VariableNode* pVariable = ( VariableNode* ) m_pOperandNode1;
00775                                 bool bAssignable = false;
00776                                 context.m_ctxTypes.IsAssignable( pVariable->m_strName, bAssignable );
00777                                 if ( bAssignable ) {
00778                                         m_strAssignVarName = pVariable->m_strName;
00779                                         if ( ! GetTreeManager()->GetTypeManager()->IsTypeA( m_pOperandNode2->m_vecType, m_pOperandNode1->m_vecType ) ) {
00780                                                 std::string strVarType, strValType;
00781                                                 OclCommon::Convert( m_pOperandNode1->m_vecType , strVarType );
00782                                                 OclCommon::Convert( m_pOperandNode2->m_vecType , strValType );
00783                                                 ADDEX( EXCEPTION2( EX_ASSIGNMENT_TYPE_MISMATCH, strVarType, strValType, GetPos( LID_NODE_START ) ) );
00784                                                 return false;
00785                                         }
00786                                         m_vecType = m_pOperandNode1->m_vecType;
00787                                         return true;
00788                                 }
00789                         }
00790                         */
00791 
00792                         // Any other operator check
00793 
00794                         OclMeta::Operator* pOperator = NULL;
00795                         if ( ! m_pOperandNode2 ) {
00796                                 try {
00797                                         pOperator = GetTreeManager()->GetTypeManager()->GetOperator( OclSignature::Operator( m_strName, m_pOperandNode1->m_vecType[ 0 ] ) );
00798                                         GetParametralTypeSeq( m_pOperandNode1->m_vecType, TypeSeq(), pOperator->GetReturnTypeSeq() );
00799                                         return true;
00800                                 }
00801                                 catch ( OclCommon::Exception ex ) {
00802                                         SETEXPOS( ex, m_mapPositions[ LID_FEATURE_NAME ] );
00803                                         ADDEX( ex );
00804                                         return false;
00805                                 }
00806                         }
00807                         try {
00808                                 pOperator = GetTreeManager()->GetTypeManager()->GetOperator( OclSignature::Operator( m_strName, m_pOperandNode1->m_vecType[ 0 ], m_pOperandNode2->m_vecType[ 0 ] ) );
00809                                 GetParametralTypeSeq( m_pOperandNode1->m_vecType, m_pOperandNode1->m_vecType, pOperator->GetReturnTypeSeq() );
00810                                 return true;
00811                         }
00812                         catch ( OclCommon::Exception ex ) {
00813                                 SETEXPOS( ex, m_mapPositions[ LID_FEATURE_NAME ] );
00814                                 ADDEX( ex );
00815                                 return false;
00816                         }
00817                 }
00818                 return false;
00819         }
00820 
00821         OclMeta::Object OperatorNode::Evaluate( ObjectContext& context )
00822         {
00823                 OclSignature::Operator signature = ( ! m_pOperandNode2 ) ? OclSignature::Operator( m_strName, m_pOperandNode1->m_vecType[ 0 ] ) : OclSignature::Operator( m_strName, m_pOperandNode1->m_vecType[ 0 ], m_pOperandNode2->m_vecType[ 0 ] );
00824                 int iLineFeatureName = m_mapPositions[ LID_FEATURE_NAME ].iLine;
00825 
00826                 // Evaluation of Logical Operators
00827 
00828 /*              if ( m_pOperandNode1->IsBooleanReturned() && m_pOperandNode2 && m_pOperandNode2->IsBooleanReturned() && m_vecType[ 0 ] == "ocl::Boolean" ) {
00829 
00830                         if ( m_strName == "and" || m_strName == "&&" ) {
00831                                 OclMeta::Object spOperand1 = m_pOperandNode1->Evaluate( context );
00832                                 if ( spOperand1.IsUndefined() ) {
00833                                         if ( m_strName == "and" || ! context.m_bShortCircuitLogical )
00834                                                 m_pOperandNode2->Evaluate( context );
00835                                         return spOperand1;
00836                                 }
00837                                 DECL_BOOLEAN( bOperand1, spOperand1 );
00838                                 if ( ! bOperand1 ) {
00839                                         if ( m_strName == "and" || ! context.m_bShortCircuitLogical ) {
00840                                                 OclMeta::Object spOperand2 = m_pOperandNode2->Evaluate( context );
00841                                                 if ( spOperand2.IsUndefined() )
00842                                                         return spOperand2;
00843                                         }
00844                                         return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), false ), iLineFeatureName, signature.Print() );
00845                                 }
00846                                 OclMeta::Object spOperand2 = m_pOperandNode2->Evaluate( context );
00847                                 if ( spOperand2.IsUndefined() )
00848                                         return spOperand2;
00849                                 DECL_BOOLEAN( bOperand2, spOperand2 );
00850                                 return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), bOperand2 ), iLineFeatureName, signature.Print() );
00851                         }*/
00852 
00853                 // undef and/&& false = false and/&& undef = false
00854                 // undef and/&& anything = undef
00855                 if ( m_pOperandNode1->IsBooleanReturned() && m_pOperandNode2 && m_pOperandNode2->IsBooleanReturned() && m_vecType[ 0 ] == "ocl::Boolean" ) {
00856 
00857                         if ( m_strName == "and" || m_strName == "&&" ) {
00858                                 OclMeta::Object spOperand1 = m_pOperandNode1->Evaluate( context );
00859                                 if ( ! spOperand1.IsUndefined() ) {
00860                                         DECL_BOOLEAN( bOperand1, spOperand1 );
00861                                         if ( ! bOperand1 ) {
00862                                                 if ( m_strName == "&&" || context.m_bShortCircuitLogical )
00863                                                         return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), false ), iLineFeatureName, signature.Print() );
00864                                         }
00865                                 }
00866                                 OclMeta::Object spOperand2 = m_pOperandNode2->Evaluate( context );
00867                                 if ( ! spOperand1.IsUndefined()  &&  ! spOperand2.IsUndefined()) {
00868                                         DECL_BOOLEAN( bOperand1, spOperand1 );
00869                                         DECL_BOOLEAN( bOperand2, spOperand2 );
00870                                         return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), bOperand1 && bOperand2 ), iLineFeatureName, signature.Print() );
00871                                 }
00872                                 // cannot create UNDEFINED result
00873                                 else if (spOperand1.IsUndefined()  &&  spOperand2.IsUndefined()) {
00874                                         return spOperand1;
00875                                 }
00876                                 else if (spOperand1.IsUndefined()) {
00877                                         DECL_BOOLEAN( bOperand2, spOperand2 );
00878                                         if (bOperand2)
00879                                                 return spOperand1;
00880                                         else
00881                                                 return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), false ), iLineFeatureName, signature.Print() );
00882                                 }
00883                                 else if (spOperand2.IsUndefined()) {
00884                                         DECL_BOOLEAN( bOperand1, spOperand1 );
00885                                         if (bOperand1)
00886                                                 return spOperand2;
00887                                         else
00888                                                 return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), false ), iLineFeatureName, signature.Print() );
00889                                 }
00890                         }
00891 
00892 
00893 /*                      if ( m_strName == "or" || m_strName == "||" ) {
00894                                 OclMeta::Object spOperand1 = m_pOperandNode1->Evaluate( context );
00895                                 if ( ! spOperand1.IsUndefined() ) {
00896                                         DECL_BOOLEAN( bOperand1, spOperand1 );
00897                                         if ( bOperand1 ) {
00898                                                 if ( m_strName == "or" || ! context.m_bShortCircuitLogical )
00899                                                         m_pOperandNode2->Evaluate( context );
00900                                                 return CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true );
00901                                         }
00902                                 }
00903                                 OclMeta::Object spOperand2 = m_pOperandNode2->Evaluate( context );
00904                                 if ( spOperand2.IsUndefined() ) {
00905                                         if ( spOperand1.IsUndefined() )
00906                                                 return spOperand1;
00907                                         return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), false ), iLineFeatureName, signature.Print() );
00908                                 }
00909                                 DECL_BOOLEAN( bOperand2, spOperand2 );
00910                                 return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), bOperand2 ), iLineFeatureName, signature.Print() );
00911                         }*/
00912 
00913                         // true OR/|| UNDEF = UNDEF OR/|| true = true
00914                         // UNDEF OR/|| anything = UNDEF
00915                         if ( m_strName == "or" || m_strName == "||" ) {
00916                                 OclMeta::Object spOperand1 = m_pOperandNode1->Evaluate( context );
00917                                 if ( ! spOperand1.IsUndefined() ) {
00918                                         DECL_BOOLEAN( bOperand1, spOperand1 );
00919                                         if ( bOperand1 ) {
00920                                                 if ( m_strName == "||"  ||  context.m_bShortCircuitLogical )
00921                                                         return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true ), iLineFeatureName, signature.Print() );
00922                                         }
00923                                 }
00924                                 OclMeta::Object spOperand2 = m_pOperandNode2->Evaluate( context );
00925                                 if ( ! spOperand1.IsUndefined()  &&  ! spOperand2.IsUndefined()) {
00926                                         DECL_BOOLEAN( bOperand1, spOperand1 );
00927                                         DECL_BOOLEAN( bOperand2, spOperand2 );
00928                                         return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), bOperand1 || bOperand2 ), iLineFeatureName, signature.Print() );
00929                                 }
00930                                 else if (spOperand1.IsUndefined()  &&  spOperand2.IsUndefined() )
00931                                         return spOperand1;
00932                                 else if (spOperand1.IsUndefined()) {
00933                                         DECL_BOOLEAN( bOperand2, spOperand2 );
00934                                         if (!bOperand2)
00935                                                 return spOperand1;
00936                                         else
00937                                                 return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true ), iLineFeatureName, signature.Print() );
00938                                 }
00939                                 else if (spOperand2.IsUndefined()) {
00940                                         DECL_BOOLEAN( bOperand1, spOperand1 );
00941                                         if (!bOperand1)
00942                                                 return spOperand2;
00943                                         else
00944                                                 return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true ), iLineFeatureName, signature.Print() );
00945                                 }
00946                         }
00947 
00948 
00949 
00950 /*                      if ( m_strName == "implies" || m_strName == "=>" ) {
00951                                 OclMeta::Object spOperand1 = m_pOperandNode1->Evaluate( context );
00952                                 if ( spOperand1.IsUndefined() )
00953                                         return spOperand1;
00954                                 DECL_BOOLEAN( bOperand1, spOperand1 );
00955                                 if ( ! bOperand1 ) {
00956                                         if ( m_strName == "implies" || ! context.m_bShortCircuitLogical )
00957                                                 m_pOperandNode2->Evaluate( context );
00958                                         return CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true );
00959                                 }
00960                                 OclMeta::Object spOperand2 = m_pOperandNode2->Evaluate( context );
00961                                 if ( spOperand2.IsUndefined() )
00962                                         return spOperand2;
00963                                 DECL_BOOLEAN( bOperand2, spOperand2 );
00964                                 return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), bOperand2 ), iLineFeatureName, signature.Print() );
00965                         }
00966                 }*/
00967 
00968                         // FALSE =>/implies anything - true
00969                         // anything =>/implies TRUE - true
00970                         if ( m_strName == "implies" || m_strName == "=>" ) {
00971                                 OclMeta::Object spOperand1 = m_pOperandNode1->Evaluate( context );
00972                                 if ( !spOperand1.IsUndefined() ) {
00973                                         DECL_BOOLEAN( bOperand1, spOperand1 );
00974                                         if (! bOperand1) {
00975                                                 if ( m_strName == "=>" || context.m_bShortCircuitLogical )
00976                                                         return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true ), iLineFeatureName, signature.Print() );
00977                                         }
00978                                 }
00979                                 OclMeta::Object spOperand2 = m_pOperandNode2->Evaluate( context );
00980                                 if ( ! spOperand1.IsUndefined()  &&  ! spOperand2.IsUndefined()) {
00981                                         DECL_BOOLEAN( bOperand1, spOperand1 );
00982                                         DECL_BOOLEAN( bOperand2, spOperand2 );
00983                                         return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), !bOperand1  ||  bOperand2), iLineFeatureName, signature.Print() );
00984                                 }
00985                                 else if (spOperand1.IsUndefined()  &&  spOperand2.IsUndefined() )
00986                                         return spOperand1;
00987                                 else if (spOperand1.IsUndefined()) {
00988                                         DECL_BOOLEAN( bOperand2, spOperand2 );
00989                                         if (!bOperand2)
00990                                                 return spOperand1;
00991                                         else
00992                                                 return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true), iLineFeatureName, signature.Print() );
00993                                 }
00994                                 else if (spOperand2.IsUndefined()) {
00995                                         DECL_BOOLEAN( bOperand1, spOperand1 );
00996                                         if (bOperand1)
00997                                                 return spOperand2;
00998                                         else
00999                                                 return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true ), iLineFeatureName, signature.Print() );
01000                                 }
01001                         }
01002                 }
01003 
01004                 OclMeta::Object spOperand1 = m_pOperandNode1->Evaluate( context );
01005                 OclMeta::Object spOperand2;
01006 
01007                 /*
01008                 // Evaluation of Assignment
01009 
01010                 if ( ! m_strAssignVarName.empty() ) {
01011                         operand2 = EvaluateAndCast( context, m_pOperandNode2, LID_NODE_START, signature.Print(), m_pOperandNode1->m_vecType[ 0 ] );
01012                         context.oCtx.SetVariable( m_strAssignVarName, operand2 );
01013                         if ( bIsBoolean && ! operand2.IsUndefined() && context.bDoSnapshot ) {
01014                                 DECL_BOOLEAN( bResult, operand2 );
01015                                 if ( ! bResult )
01016                                         AddViolation( context, false, LID_FEATURE_NAME, signature.Print() );
01017                         }
01018                         return operand2;
01019                 }
01020                 */
01021 
01022                 // Evaluation of Equality and non equality
01023 
01024                 if ( m_pOperandNode2 )
01025                         spOperand2 = m_pOperandNode2->Evaluate( context );
01026 
01027                 if ( ( m_strName == "==" || m_strName == "=" ) && m_pOperandNode2 && m_vecType[ 0 ] == "ocl::Boolean" ) {
01028                         if ( spOperand1.IsUndefined() )
01029                                 if ( spOperand2.IsUndefined() )
01030                                         return CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true );
01031                                 else
01032                                         CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), false ), iLineFeatureName, signature.Print() );
01033                         else
01034                                 if ( spOperand2.IsUndefined() )
01035                                         CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), false ), iLineFeatureName, signature.Print() );
01036                 }
01037 
01038                 if ( ( m_strName == "!=" || m_strName == "<>" ) && m_pOperandNode2 && m_vecType[ 0 ] == "ocl::Boolean" ) {
01039                         if ( spOperand1.IsUndefined() )
01040                                 if ( spOperand2.IsUndefined() )
01041                                         CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), false ), iLineFeatureName, signature.Print() );
01042                                 else
01043                                         return CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true );
01044                         else
01045                                 if ( spOperand2.IsUndefined() )
01046                                         return CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), true );
01047                 }
01048 
01049                 // Evaluation of any kind of operators
01050 
01051                 if ( spOperand1.IsUndefined() || m_pOperandNode2 && spOperand2.IsUndefined() )
01052                         return OclMeta::Object::UNDEFINED;
01053 
01054                 EVALTRY {
01055                         OclMeta::Operator* pOperator = GetTreeManager()->GetTypeManager()->GetOperator( signature );
01056                         OclImplementation::Operator* pIOperator = pOperator->GetImplementation();
01057                         if ( ! pIOperator )
01058                                 THROWOCL0( ET_RUNTIME, EX_OPERATOR_NOT_IMPLEMENTED );
01059 
01060                         OclMeta::ObjectVector vecOperands( 1, spOperand1 );
01061                         if ( m_pOperandNode2 )
01062                                 vecOperands.push_back( spOperand2 );
01063                         pIOperator->SetArguments( vecOperands );
01064                         pIOperator->Initialize();
01065 
01066                         (*pIOperator)();
01067 
01068                         OclMeta::Object spResult = EvaluateCast( context, pIOperator->GetResult(), iLineFeatureName, signature.Print() );
01069                         pIOperator->Finalize();
01070 
01071                         return CheckFalseResult( context, spResult, iLineFeatureName, signature.Print() );
01072                 } EVALCATCH( iLineFeatureName, signature.Print() );
01073                 return OclMeta::Object::UNDEFINED;
01074         }
01075 
01076 //##############################################################################################################################################
01077 //
01078 //      C L A S S : OclTree::IteratorNode <<< + OclTree::TreeNode
01079 //
01080 //##############################################################################################################################################
01081         int IteratorNode::m_iteratorLevel = 0;
01082 
01083         IteratorNode::IteratorNode( TreeManager* pManager )
01084                 : TreeNode( pManager, TreeNode::NK_ITERATOR ), m_strName( "" ), m_pThisNode( NULL ), m_pArgumentNode( NULL ), m_strDeclType( "" ), m_strCallOperator( "" ), m_strAccuName( "" ), m_strAccuType( "" ), m_pAccuNode( NULL )
01085         {
01086         }
01087 
01088         IteratorNode::~IteratorNode()
01089         {
01090                 if ( ! m_bTester ) {
01091                         if ( m_pThisNode )
01092                                 delete m_pThisNode;
01093                         if ( m_pArgumentNode )
01094                                 delete m_pArgumentNode;
01095                         if ( m_pAccuNode )
01096                                 delete m_pAccuNode;
01097                 }
01098         }
01099 
01100         std::string IteratorNode::Print( const std::string& strTabs ) const
01101         {
01102                 std::string strOut = strTabs + "<Iterator name=\"" + m_strName + "\">\r\n";
01103 
01104                 if ( m_vecDeclarators.size() > 0 ) {
01105                         strOut += strTabs + TABSTR + "<Declarators type=\"" + m_strDeclType + "\">\r\n" + strTabs + TABSTR + TABSTR;
01106                         for ( unsigned int i = 0 ; i < m_vecDeclarators.size() ; i++ )
01107                                 strOut += m_vecDeclarators[ i ] + " ";
01108                         strOut += "\r\n" + strTabs + TABSTR + "</Declarators>\r\n";
01109                 }
01110 
01111                 if ( m_pAccuNode ) {
01112                         strOut += strTabs + TABSTR + "<Accumulator type=\"" + m_strAccuType + "\">\r\n";
01113                         strOut += m_pAccuNode->Print( strTabs + TABSTR + TABSTR );
01114                         strOut += strTabs + TABSTR + "</Accumulator>\r\n";
01115                 }
01116 
01117                 strOut += strTabs + TABSTR + "<This>\r\n";
01118                 if ( m_pThisNode )
01119                         strOut += m_pThisNode->Print( strTabs + TABSTR + TABSTR );
01120                 strOut += strTabs + TABSTR + "</This>\r\n";
01121 
01122                 strOut += strTabs + TABSTR + "<Argument>\r\n";
01123                 strOut += m_pArgumentNode->Print( strTabs + TABSTR + TABSTR );
01124                 strOut += strTabs + TABSTR + "</Argument>\r\n";
01125 
01126                 strOut += strTabs + "</Method>\r\n";
01127 
01128                 return strOut;
01129         }
01130 
01131         void IteratorNode::CheckInitialize()
01132         {
01133                 if ( m_bSelfTester && ! m_bTester && m_pThisNode ) {
01134                         delete m_pThisNode;
01135                         m_pThisNode = NULL;
01136                 }
01137                 TreeNode::CheckInitialize();
01138                 if ( ! m_vecDeclarators.empty() && m_vecDeclarators[ 0 ].substr( 0, 1 ) == "!" )
01139                         m_vecDeclarators.clear();
01140         }
01141 
01142         bool IteratorNode::CheckImplementation( TypeContext& context )
01143         {
01144                 // Iterator cannot be called by .
01145 
01146                 if ( m_strCallOperator == "." )
01147                         ADDEX( EXCEPTION1( EX_INVALID_CALL, m_strCallOperator, m_mapPositions[ LID_CALL_OPERATOR ] ) );
01148 
01149                 // Check This if exists
01150 
01151                 if ( m_pThisNode ) {
01152                         bool bThisValid = m_bTester || m_pThisNode->Check( context );
01153                         if ( bThisValid )
01154                                 return CheckIterator( context );
01155                         return false;
01156                 }
01157 
01158                 m_bSelfTester = true;
01159 
01160                 // Check Implicits variables
01161 
01162                 for ( int i = context.m_vecImplicits.size() - 1 ; i >= 0 ; i-- ) {
01163 
01164                         TypeContext contextIterator( context.m_namespace);
01165                         CheckInitialize();
01166                         m_pThisNode = CreateThis( context, i );
01167                         if ( CheckIterator( contextIterator ) )
01168                                 return true;
01169                         else {
01170                                 delete m_pThisNode;
01171                                 m_pThisNode = NULL;
01172                                 int iLastCode = GetLastExceptionCode( contextIterator );
01173                                 if ( iLastCode != EX_ITERATOR_DOESNT_EXIST && iLastCode != EX_TYPE_NOT_COMPOUND_ITERATOR && iLastCode != -1 ) {
01174                                         ADDEXP( contextIterator.m_poolExceptions );
01175                                         return false;
01176                                 }
01177                         }
01178                 }
01179                 ADDEX( EXCEPTION1( EX_IMPL_ITER_DOESNT_EXIST, m_strName + "( ... | ... )", m_mapPositions[ LID_FEATURE_NAME ] ) );
01180                 return false;
01181         }
01182 
01183         bool IteratorNode::CheckIterator( TypeContext& context )
01184         {
01185 
01186                 std::shared_ptr<OclMeta::Type> pType = GetTreeManager()->GetTypeManager()->GetType( m_pThisNode->m_vecType[ 0 ], context.m_namespace );
01187 
01188                 // Not compound Type cannot have iterators
01189 
01190                 if ( ! pType->IsCompound() ) {
01191                         ADDEX( EXCEPTION1( EX_TYPE_NOT_COMPOUND_ITERATOR, pType->GetName(), m_mapPositions[ LID_NODE_START ] ) );
01192                         return false;
01193                 }
01194                 m_vecTypeDecl = m_pThisNode->m_vecType;
01195                 m_vecTypeDecl.erase( m_vecTypeDecl.begin() );
01196 
01197                 // Check Type of Declaration if it exists
01198 
01199                 if ( ! m_strDeclType.empty() ) {
01200                         TypeSeq vecType;
01201                         if ( ParseTypeSeq( context, m_mapPositions[ LID_DECLARATOR_TYPE ], m_strDeclType, vecType ) )
01202                                 if ( CastType( context, m_mapPositions[ LID_DECLARATOR_TYPE ], m_vecTypeDecl, vecType ) )
01203                                         m_vecTypeDecl = vecType;
01204                 }
01205 
01206                 // Check Accu expression and set accumulator type
01207 
01208                 if ( m_pAccuNode && m_pAccuNode->Check( context ) ) {
01209                         m_vecTypeAccu = m_pAccuNode->m_vecType;
01210 
01211                         if ( ! m_strAccuType.empty() ) {
01212                                 TypeSeq vecType;
01213                                 if ( ParseTypeSeq( context, m_mapPositions[ LID_ACCUMULATOR_TYPE ], m_strAccuType, vecType ) )
01214                                         if ( CastType( context, m_mapPositions[ LID_ACCUMULATOR_TYPE ], m_vecTypeAccu, vecType ) )
01215                                                 m_vecTypeAccu = vecType;
01216                         }
01217                 }
01218 
01219                 // Create implicit iterator variable if it is necessary
01220 
01221                 if ( m_vecDeclarators.empty() ) {
01222                         char chBuffer[ 20 ];
01223                         sprintf_s( chBuffer, sizeof(chBuffer), "!iter%ld", context.m_vecImplicits.size() );
01224                         m_vecDeclarators.push_back( std::string( chBuffer ) );
01225                         context.m_vecImplicits.push_back( std::string( chBuffer ) );
01226                 }
01227 
01228                 // Check and Add Declarators
01229 
01230                 std::vector< bool > vecDeclDone( m_vecDeclarators.size(), true );
01231 
01232                 if ( ! m_vecTypeDecl.empty() ) {
01233                         for ( unsigned int i = 0 ; i < m_vecDeclarators.size() ; i++ ) {
01234                                 vecDeclDone[ i ] = context.m_ctxTypes.AddVariable( m_vecDeclarators[ i ], m_vecTypeDecl, true );
01235                                 if ( ! vecDeclDone[ i ] )
01236                                         ADDEX( EXCEPTION1( EX_VARIABLE_ALREADY_EXISTS, m_vecDeclarators[ i ], m_mapPositions[ LID_DECLARATOR_NAME + i ] ) );
01237                         }
01238                 }
01239 
01240                 // Check and Add Accumulator
01241 
01242                 bool bAccuAdded = false;
01243                 if ( ! m_vecTypeAccu.empty() ) {
01244                         if ( context.m_ctxTypes.AddVariable( m_strAccuName, m_vecTypeAccu, true ) )
01245                                 bAccuAdded = true;
01246                         else
01247                                 ADDEX( EXCEPTION1( EX_VARIABLE_ALREADY_EXISTS, m_strAccuName, m_mapPositions[ LID_ACCUMULATOR_NAME ] ) );
01248                 }
01249 
01250                 // Check Argument
01251 
01252                 bool bArgumentValid = m_bTester && ! m_pArgumentNode->m_vecType.empty() || ! m_vecTypeDecl.empty() && m_pArgumentNode->Check( context );
01253 
01254                 // Check if Iterator exists
01255 
01256                 if ( bArgumentValid ) {
01257 
01258                         if ( ! m_pAccuNode ) {
01259 
01260                                 // It is predefined iterator
01261 
01262                                 try {
01263                                         OclMeta::CompoundType* pCType = (OclMeta::CompoundType*) pType.get();
01264                                         OclMeta::Iterator* pIterator = pCType->GetIterator(0, OclSignature::Iterator( m_strName, m_pThisNode->m_vecType[ 0 ], m_pArgumentNode->m_vecType[ 0 ] ) );
01265                                         GetParametralTypeSeq( m_pThisNode->m_vecType, m_pArgumentNode->m_vecType, pIterator->GetReturnTypeSeq() );
01266                                 }
01267                                 catch ( OclCommon::Exception ex ) {
01268                                         SETEXPOS( ex, m_mapPositions[ LID_FEATURE_NAME ] );
01269                                         ADDEX( ex );
01270                                 }
01271                         }
01272                         else {
01273 
01274                                 // It is generic iterator
01275 
01276                                 CastType( context, m_mapPositions[ LID_ACCUMULATOR_TYPE ], m_vecTypeAccu, m_pArgumentNode->m_vecType );
01277                                 m_vecType = m_vecTypeAccu;
01278                         }
01279                 }
01280 
01281                 // Remove Declarators
01282 
01283                 if ( ! m_vecTypeDecl.empty() ) {
01284                         for ( unsigned int i = 0 ; i < m_vecDeclarators.size() ; i++ )
01285                                 if ( vecDeclDone[ i ] )
01286                                         context.m_ctxTypes.RemoveVariable( m_vecDeclarators[ i ] );
01287                 }
01288 
01289                 // Remove Accumulator
01290 
01291                 if ( bAccuAdded )
01292                         context.m_ctxTypes.RemoveVariable( m_strAccuName );
01293 
01294                 // Remove Implicit variable if it was
01295 
01296                 if ( m_vecDeclarators[ 0 ].substr( 0, 1 ) == "!" ) {
01297                         context.m_vecImplicits.pop_back();
01298                 }
01299 
01300                 return ! m_vecType.empty();
01301         }
01302 
01303         OclMeta::Object IteratorNode::Evaluate( ObjectContext& context )
01304         {
01305                 // recursion corrected: terge
01306                 LevelCounter level(&m_iteratorLevel);
01307 
01308                 int iLineFeatureName = m_mapPositions[ LID_FEATURE_NAME ].iLine;
01309                 OclSignature::Iterator signature( m_strName, m_pThisNode->m_vecType[ 0 ], m_pArgumentNode->m_vecType[ 0 ] );
01310 
01311                 OclMeta::Object objectThis = m_pThisNode->Evaluate( context );
01312 
01313                 if ( objectThis.IsUndefined() )
01314                         return OclMeta::Object::UNDEFINED;
01315 
01316                 EVALTRY {
01317                         OclImplementation::Iterator* pIIterator = NULL;
01318                         if ( ! m_pAccuNode ) {
01319                                 OclMeta::CompoundType* pCType = (OclMeta::CompoundType*) GetTreeManager()->GetTypeManager()->GetType( objectThis.GetStaticTypeName(), NILNAMESPACE ).get();
01320                                 OclMeta::Iterator* pIterator = pCType->GetIterator(m_iteratorLevel, signature );
01321                                 pIIterator = pIterator->GetImplementation();
01322                                 if ( ! pIIterator )
01323                                         THROWOCL0( ET_RUNTIME, EX_ITERATOR_NOT_IMPLEMENTED );
01324 
01325                                 pIIterator->Initialize();
01326                                 pIIterator->SetThis( objectThis );
01327                         }
01328                         else {
01329                                 OclMeta::Object accumulator = EvaluateCast( context, m_pAccuNode->Evaluate( context ), m_mapPositions[ LID_ACCUMULATOR_TYPE ].iLine, m_strAccuName + " = ...", m_vecType[ 0 ], m_strAccuType.empty() );
01330                                 context.oCtx.AddVariable( m_strAccuName, accumulator, true );
01331                         }
01332 
01333                         OclMeta::ObjectVector vecArguments( m_vecDeclarators.size(), OclMeta::Object::UNDEFINED );
01334 
01335                         Iterate( context, pIIterator, objectThis, vecArguments, 0 );
01336 
01337                         OclMeta::Object spResult;
01338                         if ( ! m_pAccuNode ) {
01339                                 spResult = pIIterator->GetResult();
01340                                 pIIterator->Finalize();
01341                         }
01342                         else {
01343                                 context.oCtx.GetVariable( m_strAccuName, spResult );
01344                                 context.oCtx.RemoveVariable( m_strAccuName );
01345                         }
01346                         spResult = EvaluateCast( context, spResult, iLineFeatureName, signature.Print() );
01347                         return CheckFalseResult( context, spResult, iLineFeatureName, signature.Print() );
01348                 } EVALCATCH( iLineFeatureName, signature.Print() );
01349                 return OclMeta::Object::UNDEFINED;
01350         }
01351 
01352         bool IteratorNode::Iterate( ObjectContext& context, OclImplementation::Iterator* pIIterator, OclMeta::Object& objectThis, OclMeta::ObjectVector& vecArguments, int iDeclNum )
01353         {
01354                 int iLineFeatureName = m_mapPositions[ LID_FEATURE_NAME ].iLine;
01355                 OclSignature::Iterator signature( m_strName, m_pThisNode->m_vecType[ 0 ], m_pArgumentNode->m_vecType[ 0 ] );
01356 
01357                 std::string strDecl = m_vecDeclarators[ iDeclNum ];
01358                 context.oCtx.AddVariable( strDecl, OclMeta::Object::UNDEFINED, true );
01359 
01360                 DECL_ITERATOR( iterator, objectThis );
01361                 OclMeta::Object objectIter;
01362 
01363                 bool bDoStop = false;
01364 
01365                 while ( iterator->HasNext() && ( ! bDoStop || ! context.m_bShortCircuitIterator ) ) {
01366 
01367                         objectIter = iterator->GetNext();
01368                         if ( ! m_strDeclType.empty() )
01369                                 objectIter = EvaluateCast( context, objectIter, m_mapPositions[ LID_DECLARATOR_TYPE ].iLine, signature.Print(), m_vecTypeDecl[ 0 ], false );
01370                         context.oCtx.SetVariable( strDecl, objectIter );
01371                         vecArguments[ iDeclNum ] = objectIter;
01372 
01373                         if ( iDeclNum == (int)m_vecDeclarators.size() - 1 ) {
01374                                 EVALTRY {
01375                                         OclMeta::Object spAccu = m_pArgumentNode->Evaluate( context ); // evaluate the argument
01376                                         if ( ! m_pAccuNode ) {
01377                                                 pIIterator->SetArguments( vecArguments );
01378                                                 pIIterator->SetSubResult( spAccu );
01379                                                 pIIterator->SetSubOriResult( objectIter );
01380                                                 (*pIIterator)();
01381                                                 if ( pIIterator->DoStop() )
01382                                                         bDoStop = true;
01383                                         }
01384                                         else
01385                                                 context.oCtx.SetVariable( m_strAccuName, spAccu );
01386                                 } EVALCATCH( iLineFeatureName, signature.Print() );
01387                         }
01388                         else
01389                                 bDoStop = Iterate( context, pIIterator, objectThis, vecArguments, iDeclNum + 1 );
01390                 }
01391                 context.oCtx.RemoveVariable( strDecl );
01392                 return bDoStop;
01393         }
01394 
01395 //##############################################################################################################################################
01396 //
01397 //      C L A S S : OclTree::MethodNode <<< + OclTree::TreeNode
01398 //
01399 //##############################################################################################################################################
01400         int MethodNode::m_stackLevel = 0;
01401 
01402         MethodNode::MethodNode( TreeManager* pManager )
01403                 : TreeNode( pManager, TreeNode::NK_METHOD ), m_strName( "" ), m_pThisNode( NULL ), m_strCallOperator( "" ), m_pIterator( NULL )
01404         {
01405         }
01406 
01407         MethodNode::~MethodNode()
01408         {
01409                 if ( ! m_bTester && ! m_bSelfTester ) {
01410                         delete m_pThisNode;
01411                         for ( unsigned int i = 0 ; i < m_vecArguments.size() ; i++ )
01412                                 delete m_vecArguments[ i ];
01413                 }
01414                 if ( m_pIterator ) {
01415                         delete m_pIterator;
01416                         m_pIterator = NULL;
01417                 }
01418         }
01419 
01420         std::string MethodNode::Print( const std::string& strTabs ) const
01421         {
01422                 if ( m_pIterator )
01423                         return m_pIterator->Print( strTabs );
01424 
01425                 std::string strOut = strTabs + "<Method name=\"" + m_strName + "\">\r\n";
01426 
01427                 strOut += strTabs + TABSTR + "<This>\r\n";
01428                 strOut += m_pThisNode->Print( strTabs + TABSTR + TABSTR );
01429                 strOut += strTabs + TABSTR + "</This>\r\n";
01430 
01431                 if ( ! m_vecArguments.empty() ) {
01432                         for ( unsigned int i = 0 ; i < m_vecArguments.size() ; i++ ) {
01433                                 char chNum[ 100 ];
01434                                 sprintf_s( chNum, sizeof(chNum), "%lu", i );
01435                                 strOut += strTabs + TABSTR + "<Argument_" + std::string( chNum ) + ">\r\n";
01436                                 strOut += m_vecArguments[ i ]->Print( strTabs + TABSTR + TABSTR );
01437                                 strOut += strTabs + TABSTR + "</Argument_" + std::string( chNum ) + ">\r\n";
01438                         }
01439                 }
01440 
01441                 strOut += strTabs + "</Method>\r\n";
01442                 return strOut;
01443         }
01444 
01445         void MethodNode::CheckInitialize()
01446         {
01447                 TreeNode::CheckInitialize();
01448                 if ( m_pIterator ) {
01449                         m_pIterator->m_bTester = true;
01450                         delete m_pIterator;
01451                         m_pIterator = NULL;
01452                 }
01453         }
01454 
01455         bool MethodNode::CheckImplementation( TypeContext& context )
01456         {
01457                 // Check Self
01458 
01459                 bool bThisValid = m_bTester || m_pThisNode->Check( context );
01460 
01461                 // Check whether it is IsUndefined method
01462 
01463                 if ( m_strName == "isUndefined" && m_vecArguments.empty() ) {
01464                         m_vecType = TypeSeq( 1, "ocl::Boolean" );
01465                         return true;
01466                 }
01467 
01468                 if ( bThisValid ) {
01469 
01470                         OclMeta::Type* pType = GetTreeManager()->GetTypeManager()->GetType( m_pThisNode->m_vecType[ 0 ], context.m_namespace ).get();
01471 
01472                         // Check if Object Node is callable
01473 
01474                         if ( m_pThisNode->GetKind() == TreeNode::NK_OBJECT ) {
01475                                 ObjectNode* pONode = (ObjectNode*) m_pThisNode;
01476                                 if ( ! pONode->m_bCallable )
01477                                         ADDEX( EXCEPTION1( EX_OBJECT_CALL_PROHIBITED, m_pThisNode->m_vecType[ 0 ], m_mapPositions[ LID_CALL_OPERATOR ] ) );
01478                         }
01479 
01480                         // Check member selection operator
01481 
01482                         if ( m_strCallOperator == "->" && ! pType->IsCompound() )
01483                                 ADDEX( EXCEPTION1( EX_TYPE_NOT_COMPOUND_ITERATOR, pType->GetName(), m_mapPositions[ LID_CALL_OPERATOR ] ) );
01484 
01485                         // Check method exists
01486 
01487                         if ( ! pType->IsCompound() || m_vecArguments.size() != 1 ) {
01488 
01489                                 bool bArgumentsValid = true;
01490                                 unsigned int i;
01491                                 for ( i = 0 ; i < m_vecArguments.size() ; i++ )
01492                                         bArgumentsValid = m_vecArguments[ i ]->Check( context ) && bArgumentsValid;
01493 
01494                                 if ( bArgumentsValid ) {
01495                                         StringVector vecTypes;
01496                                         for ( i = 0 ; i < m_vecArguments.size() ; i++ )
01497                                                 vecTypes.push_back( m_vecArguments[ i ]->m_vecType[ 0 ] );
01498                                         OclSignature::Method sigMethod( m_strName, pType->GetName(), vecTypes );
01499 
01500                                         try {
01501                                                 OclMeta::Method* pMethod = pType->GetMethod( sigMethod );
01502                                                 GetParametralTypeSeq( m_pThisNode->m_vecType, ( m_vecArguments.empty() ) ? TypeSeq() : m_vecArguments[ 0 ]->m_vecType, pMethod->GetReturnTypeSeq() );
01503                                                 if ( pMethod->IsDependence() )
01504                                                         context.m_setDependencies.insert( OclMeta::Dependency( sigMethod.Print(), m_mapPositions[ LID_FEATURE_NAME ] ) );
01505                                                 return true;
01506                                         }
01507                                         catch ( OclCommon::Exception ex ) {
01508                                                 SETEXPOS( ex, m_mapPositions[ LID_FEATURE_NAME ] );
01509                                                 ADDEX( ex );
01510                                                 return false;
01511                                         }
01512                                 }
01513                                 return false;
01514 
01515                         }
01516 
01517                         // Try argument as method argument
01518 
01519                         TypeContext contextMethod = context;
01520                         contextMethod.m_poolExceptions.Clear();
01521                         bool bMethodValid = m_vecArguments[ 0 ]->Check( contextMethod );
01522                         TypeSeq vecTypeMethod = m_vecArguments[ 0 ]->m_vecType;
01523 
01524                         // Try argument as iterator body expression
01525 
01526                         TypeContext contextIterator = context;
01527                         contextIterator.m_poolExceptions.Clear();
01528 
01529                                 // Add new implicit iterator variable
01530 
01531                                 TypeSeq vecType = m_pThisNode->m_vecType;
01532                                 vecType.erase( vecType.begin() );
01533                                 char chBuffer[ 20 ];
01534                                 sprintf_s( chBuffer, sizeof(chBuffer), "!iter%lu", contextIterator.m_vecImplicits.size() );
01535                                 contextIterator.m_ctxTypes.AddVariable( std::string( chBuffer ), vecType, true );
01536                                 contextIterator.m_vecImplicits.push_back( std::string( chBuffer ) );
01537 
01538                                 // Check the iterator
01539 
01540                                 bool bIteratorValid = m_vecArguments[ 0 ]->Check( contextIterator );
01541 
01542                                 // Remove the newly created implicit iterator
01543 
01544                                 contextIterator.m_ctxTypes.RemoveVariable( std::string( chBuffer ) );
01545                                 contextIterator.m_vecImplicits.pop_back();
01546 
01547                         TypeSeq vecTypeIterator = m_vecArguments[ 0 ]->m_vecType;
01548 
01549                         if ( bMethodValid ) {
01550                                 std::vector<OclMeta::Type*> vecTypes( 2, pType );
01551 
01552                                 OclSignature::Method sigMethod( m_strName, pType->GetName(), StringVector( 1, vecTypeMethod[ 0 ] ) );
01553                                 OclSignature::Iterator sigIterator( m_strName, pType->GetName(), vecTypeMethod[ 0 ] );
01554                                 std::vector<OclSignature::Feature*> vecSignatures( 2, &sigMethod ); vecSignatures[ 1 ] = &sigIterator;
01555 
01556                                 std::vector<int> vecCodes( 3, EX_METHOD_AMBIGUOUS ); vecCodes[ 1 ] = EX_ITERATOR_AMBIGUOUS; vecCodes[ 2 ] = EX_METHOD_ITERATOR_AMBIGUOUS;
01557 
01558                                 OclCommon::ExceptionPool poolResult;
01559 
01560                                 int iPrecedence = ( m_strCallOperator.empty() ) ? 0 : ( m_strCallOperator == "." ) ? -1 : 1;
01561 
01562                                 OclMeta::Feature* pFeature = CheckAmbiguity( vecTypes, vecSignatures, vecCodes, iPrecedence, poolResult );
01563                                 if ( ! pFeature ) {
01564                                         ADDEXP( poolResult );
01565                                         return false;
01566                                 }
01567                                 else {
01568                                         if ( iPrecedence == -1 ) {
01569                                                 ADDEXP( contextMethod.m_poolExceptions );
01570                                                 TypeContext contextTemp = context;
01571                                                 m_vecArguments[ 0 ]->Check( contextTemp );
01572                                                 GetParametralTypeSeq( m_pThisNode->m_vecType, vecTypeMethod, pFeature->GetReturnTypeSeq() );
01573                                                 if ( pFeature->IsDependence() )
01574                                                         context.m_setDependencies.insert( OclMeta::Dependency( sigMethod.Print(), m_mapPositions[ LID_FEATURE_NAME ] ) );
01575                                                 return true;
01576                                         }
01577                                         else {
01578                                                 ADDEXP( contextIterator.m_poolExceptions );
01579                                                 if ( ! bIteratorValid )
01580                                                         return false;
01581                                                 if ( vecTypeMethod != vecTypeIterator )
01582                                                         return false;
01583                                                 m_pIterator= GetTreeManager()->CreateIterator();
01584                                                 m_pIterator->m_bTester = true;
01585                                                 m_pIterator->m_pThisNode = m_pThisNode;
01586                                                 m_pIterator->m_strCallOperator = "->";
01587                                                 m_pIterator->m_strName = m_strName;
01588                                                 m_pIterator->m_vecDeclarators;
01589                                                 m_pIterator->m_mapPositions = m_mapPositions;
01590                                                 m_pIterator->m_pArgumentNode = m_vecArguments[ 0 ];
01591 
01592                                                 m_pIterator->Check( context );
01593                                                 m_pIterator->m_bTester = false;
01594                                                 m_bSelfTester = true;
01595                                                 m_vecType = m_pIterator->m_vecType;
01596                                                 return true;
01597                                         }
01598                                 }
01599                         }
01600                         if ( bIteratorValid ) {
01601                                 std::vector<OclMeta::Type*> vecTypes( 2, pType );
01602 
01603                                 OclSignature::Iterator sigIterator( m_strName, pType->GetName(), vecTypeIterator[ 0 ] );
01604                                 OclSignature::Method sigMethod( m_strName, pType->GetName(), StringVector( 1, vecTypeIterator[ 0 ] ) );
01605                                 std::vector<OclSignature::Feature*> vecSignatures( 2, &sigIterator ); vecSignatures[ 1 ] = &sigMethod;
01606 
01607                                 std::vector<int> vecCodes( 3, EX_ITERATOR_AMBIGUOUS ); vecCodes[ 1 ] = EX_METHOD_AMBIGUOUS; vecCodes[ 2 ] = EX_METHOD_ITERATOR_AMBIGUOUS;
01608 
01609                                 OclCommon::ExceptionPool poolResult;
01610 
01611                                 int iPrecedence = 0;
01612 
01613                                 OclMeta::Feature* pFeature = CheckAmbiguity( vecTypes, vecSignatures, vecCodes, iPrecedence, poolResult );
01614                                 if ( ! pFeature ) {
01615                                         ADDEXP( poolResult );
01616                                         return false;
01617                                 }
01618                                 else {
01619                                         if ( iPrecedence == 1 ) {
01620                                                 ADDEXP( contextMethod.m_poolExceptions );
01621                                                 if ( pFeature->IsDependence() )
01622                                                         context.m_setDependencies.insert( OclMeta::Dependency( sigMethod.Print(), m_mapPositions[ LID_FEATURE_NAME ] ) );
01623                                                 return true;
01624                                         }
01625                                         else {
01626                                                 ADDEXP( contextIterator.m_poolExceptions );
01627                                                 m_pIterator= GetTreeManager()->CreateIterator();
01628                                                 m_pIterator->m_bTester = true;
01629                                                 m_pIterator->m_pThisNode = m_pThisNode;
01630                                                 m_pIterator->m_strCallOperator = "->";
01631                                                 m_pIterator->m_strName = m_strName;
01632                                                 m_pIterator->m_vecDeclarators;
01633                                                 m_pIterator->m_mapPositions = m_mapPositions;
01634                                                 m_pIterator->m_pArgumentNode = m_vecArguments[ 0 ];
01635 
01636                                                 m_pIterator->Check( context );
01637                                                 m_pIterator->m_bTester = false;
01638                                                 m_bSelfTester = true;
01639                                                 m_vecType = m_pIterator->m_vecType;
01640                                                 return true;
01641                                         }
01642                                 }
01643                         }
01644                         if ( m_strCallOperator == "->" )
01645                                 ADDEXP( contextIterator.m_poolExceptions );
01646                         else
01647                                 ADDEXP( contextMethod.m_poolExceptions );
01648                         return false;
01649                 }
01650                 return false;
01651         }
01652 
01653 #define MAX_CONSTR_FUNC_LEVEL 100 // max level of constraint function encapsulation
01654 
01655         OclMeta::Object MethodNode::Evaluate( ObjectContext& context )
01656         {
01657                 LevelCounter level(&m_stackLevel);
01658                 std::string lastFuncName = "";
01659                 static std::string currFuncName = "";
01660                 std::string *szivas = &currFuncName;
01661 
01662                 if (m_stackLevel <= 1)
01663                         currFuncName = "";
01664 
01665                 if ( m_pIterator )
01666                         return m_pIterator->Evaluate( context );
01667 
01668                 int iLineFeatureName = m_mapPositions[ LID_FEATURE_NAME ].iLine;
01669 
01670                 StringVector vecTypes;
01671                 unsigned int i;
01672                 for ( i = 0 ; i < m_vecArguments.size() ; i++ )
01673                         vecTypes.push_back( m_vecArguments[ i ]->m_vecType[ 0 ] );
01674                 OclSignature::Method signature( m_strName, m_pThisNode->m_vecType[ 0 ], vecTypes );
01675 
01676                 if (m_stackLevel >= MAX_CONSTR_FUNC_LEVEL)
01677                 {
01678                         std::string message = "possibly infinite loop broken";
01679                         AddViolation(context, iLineFeatureName, signature.Print(), message);
01680                         return OclMeta::Object::UNDEFINED;
01681                 }
01682 
01683                 OclMeta::Object objectThis = m_pThisNode->Evaluate( context );
01684                 OclMeta::ObjectVector vecArguments;
01685                 for ( i = 0 ; i < m_vecArguments.size() ; i++ )
01686                         vecArguments.push_back( m_vecArguments[ i ]->Evaluate( context ) );
01687 
01688                 if ( m_strName == "isUndefined" && m_vecArguments.empty() && m_vecType[ 0 ] == "ocl::Boolean" )
01689                         return CheckFalseResult( context, CREATE_BOOLEAN( GetTreeManager()->GetTypeManager(), objectThis.IsUndefined() ), iLineFeatureName, signature.Print() );
01690 
01691                 if ( objectThis.IsUndefined() )
01692                         return OclMeta::Object::UNDEFINED;
01693                 for ( i = 0 ; i < vecArguments.size() ; i++ )
01694                         if ( vecArguments[ i ].IsUndefined() )
01695                                 return OclMeta::Object::UNDEFINED;
01696 
01697                 EVALTRY {
01698                         OclMeta::Type* pType = GetTreeManager()->GetTypeManager()->GetType( objectThis.GetStaticTypeName(), NILNAMESPACE ).get();
01699                         OclMeta::Method* pMethod = pType->GetMethod( signature );
01700                         OclImplementation::Method* pIMethod = pMethod->GetImplementation();
01701                         if ( ! pIMethod )
01702                                 THROWOCL0( ET_RUNTIME, EX_METHOD_NOT_IMPLEMENTED );
01703 
01704                         if (((OclMeta::Feature*)pMethod)->IsDynamic()) // userdef method
01705                         {
01706                                 lastFuncName = currFuncName;
01707                                 currFuncName =  m_strName; // GetFullName();
01708                         }
01709 
01710                         pIMethod->Initialize();
01711                         pIMethod->SetThis( objectThis );
01712                         pIMethod->SetArguments( vecArguments );
01713 
01714                         (*pIMethod)();
01715 
01716                         OclMeta::Object spResult = EvaluateCast( context, pIMethod->GetResult(), iLineFeatureName, signature.Print() );
01717 
01718                         pIMethod->Finalize();
01719 
01720                         // all of the violations collected in pIMethod (((OclGmeCM::ConstraintMethod*)pIMethod)->m_spFunction)
01721                         // will lose, one violation will be added to context depending on spResult
01722                         // ?? !! terge
01723                         OclTree::ViolationVector vec = pIMethod->GetViolations();
01724                         pIMethod->ClearViolations();
01725                         int num = vec.size();
01726                         for (int kk=0; kk<num; kk++)
01727                         {
01728                                 if (vec[kk].methodName.empty())
01729                                         vec[kk].methodName = currFuncName;
01730                                 AddViolation(context, vec[kk]);
01731                         }
01732                         if (!lastFuncName.empty())
01733                                 currFuncName = lastFuncName;
01734 
01735                         return CheckFalseResult( context, spResult, iLineFeatureName, signature.Print() );
01736                 } EVALCATCH( iLineFeatureName, signature.Print() );
01737                 return OclMeta::Object::UNDEFINED;
01738         }
01739 
01740 //##############################################################################################################################################
01741 //
01742 //      C L A S S : OclTree::FunctionNode <<< + OclTree::TreeNode
01743 //
01744 //##############################################################################################################################################
01745 
01746         FunctionNode::FunctionNode( TreeManager* pManager )
01747                 : TreeNode( pManager, TreeNode::NK_FUNCTION ), m_strName( "" ), m_pMethod( NULL )
01748         {
01749         }
01750 
01751         FunctionNode::~FunctionNode()
01752         {
01753                 if ( ! m_bTester && ! m_bSelfTester ) {
01754                         for ( unsigned int i = 0 ; i < m_vecArguments.size() ; i++ )
01755                                 delete m_vecArguments[ i ];
01756                 }
01757                 CheckInitialize();
01758         }
01759 
01760         std::string FunctionNode::Print( const std::string& strTabs ) const
01761         {
01762                 if ( m_pMethod )
01763                         return m_pMethod->Print( strTabs );
01764 
01765                 std::string strOut = strTabs + "<Function name=\"" + m_strName + "\">\r\n";
01766 
01767                 if ( ! m_vecArguments.empty() ) {
01768                         for ( unsigned int i = 0 ; i < m_vecArguments.size() ; i++ ) {
01769                                 char chNum[ 100 ];
01770                                 sprintf_s( chNum, sizeof(chNum), "%lu", i );
01771                                 strOut += strTabs + TABSTR + "<Argument_" + std::string( chNum ) + ">\r\n";
01772                                 strOut += m_vecArguments[ i ]->Print( strTabs + TABSTR + TABSTR );
01773                                 strOut += strTabs + TABSTR + "</Argument_" + std::string( chNum ) + ">\r\n";
01774                         }
01775                 }
01776 
01777                 strOut += strTabs + "</Function>\r\n";
01778                 return strOut;
01779         }
01780 
01781         void FunctionNode::CheckInitialize()
01782         {
01783                 TreeNode::CheckInitialize();
01784                 if ( m_pMethod ) {
01785                         m_pMethod->CheckInitialize();
01786                         m_pMethod->m_bTester = true;
01787                         delete m_pMethod->m_pThisNode;
01788                         m_pMethod->m_pThisNode = NULL;
01789                         delete m_pMethod;
01790                         m_pMethod = NULL;
01791                 }
01792         }
01793 
01794         bool FunctionNode::CheckImplementation( TypeContext& context )
01795         {
01796                 TypeContext contextFunction = context;
01797                 contextFunction.m_poolExceptions.Clear();
01798 
01799                 bool bArgumentsValid = true;
01800                 int i;
01801                 for ( i = 0 ; i < (int) m_vecArguments.size() ; i++ )
01802                         bArgumentsValid = m_vecArguments[ i ]->Check( contextFunction ) && bArgumentsValid;
01803 
01804                 OclCommon::Exception exFunction;
01805 
01806                 if ( bArgumentsValid ) {
01807                         StringVector vecTypes;
01808                         for ( i = 0 ; i < (int) m_vecArguments.size() ; i++ )
01809                                 vecTypes.push_back( m_vecArguments[ i ]->m_vecType[ 0 ] );
01810                         OclSignature::Function sigFunction( m_strName, vecTypes );
01811 
01812                         try {
01813                                 OclMeta::Function* pFunction = GetTreeManager()->GetTypeManager()->GetFunction( sigFunction );
01814                                 ADDEXP( contextFunction.m_poolExceptions );
01815                                 GetParametralTypeSeq( TypeSeq(), ( m_vecArguments.empty() ) ? TypeSeq() : m_vecArguments[ 0 ]->m_vecType, pFunction->GetReturnTypeSeq() );
01816                                 if ( pFunction->IsDependence() )
01817                                         context.m_setDependencies.insert( OclMeta::Dependency( sigFunction.Print(), m_mapPositions[ LID_FEATURE_NAME ] ) );
01818                                 return true;
01819                         }
01820                         catch ( OclCommon::Exception ex ) {
01821                                 SETEXPOS( ex, m_mapPositions[ LID_FEATURE_NAME ] );
01822                                 if ( ex.GetCode() != EX_FUNCTION_DOESNT_EXIST ) {
01823                                         ADDEXP( contextFunction.m_poolExceptions );
01824                                         ADDEX( ex );
01825                                         return false;
01826                                 }
01827                                 exFunction = ex;
01828                         }
01829                 }
01830 
01831                 // Check implicit variables
01832 
01833                 OclCommon::ExceptionPool poolExceptions;
01834                 for ( i = context.m_vecImplicits.size() - 1 ; i >= 0 ; i-- ) {
01835 
01836                         TypeContext contextMethod = context;
01837                         contextMethod.m_poolExceptions.Clear();
01838 
01839                         m_pMethod = GetTreeManager()->CreateMethod();
01840                         m_pMethod->m_bTester = true;
01841                         m_pMethod->m_pThisNode = CreateThis( context, i );
01842                         m_pMethod->m_strCallOperator = "";
01843                         m_pMethod->m_strName = m_strName;
01844                         m_pMethod->m_mapPositions = m_mapPositions;
01845                         m_pMethod->m_vecArguments = m_vecArguments;
01846 
01847                         if ( m_pMethod->Check( contextMethod ) ) {
01848                                 ADDEXP( contextMethod.m_poolExceptions );
01849                                 m_pMethod->m_bTester = false;
01850                                 m_bSelfTester = true;
01851                                 m_vecType = m_pMethod->m_vecType;
01852                                 return true;
01853                         }
01854                         else {
01855                                 delete m_pMethod->m_pThisNode;
01856                                 m_pMethod->m_pThisNode = NULL;
01857                                 delete m_pMethod;
01858                                 m_pMethod = NULL;
01859                                 int iLastCode = GetLastExceptionCode( contextMethod);
01860                                 if ( iLastCode != EX_METHOD_DOESNT_EXIST && iLastCode != EX_ITERATOR_DOESNT_EXIST &&  iLastCode != EX_TYPE_NOT_COMPOUND_ITERATOR && iLastCode != -1 ) {
01861                                         ADDEXP( contextMethod.m_poolExceptions );
01862                                         return false;
01863                                 }
01864                         }
01865                 }
01866                 ADDEX( EXCEPTION1( EX_FUNC_IMPL_METH_ITER_DOESNT_EXIST, m_strName + "( ... )", m_mapPositions[ LID_FEATURE_NAME ] ) );
01867                 return false;
01868         }
01869 
01870         OclMeta::Object FunctionNode::Evaluate( ObjectContext& context )
01871         {
01872                 if ( m_pMethod )
01873                         return m_pMethod->Evaluate( context );
01874 
01875                 int iLineFeatureName = m_mapPositions[ LID_FEATURE_NAME ].iLine;
01876                 StringVector vecTypes;
01877                 unsigned int i;
01878                 for ( i = 0 ; i < m_vecArguments.size() ; i++ )
01879                         vecTypes.push_back( m_vecArguments[ i ]->m_vecType[ 0 ] );
01880                 OclSignature::Function signature( m_strName, vecTypes );
01881 
01882                 OclMeta::ObjectVector vecArguments;
01883                 for ( i = 0 ; i < m_vecArguments.size() ; i++ )
01884                         vecArguments.push_back( m_vecArguments[ i ]->Evaluate( context ) );
01885 
01886                 for ( i = 0 ; i < vecArguments.size() ; i++ )
01887                         if ( vecArguments[ i ].IsUndefined() )
01888                                 return OclMeta::Object::UNDEFINED;
01889 
01890                 EVALTRY {
01891                         OclMeta::Function* pFunction = GetTreeManager()->GetTypeManager()->GetFunction( signature );
01892                         OclImplementation::Function* pIFunction = pFunction->GetImplementation();
01893                         if ( ! pIFunction )
01894                                 THROWOCL0( ET_RUNTIME, EX_FUNCTION_NOT_IMPLEMENTED );
01895 
01896                         pIFunction->Initialize();
01897                         pIFunction->SetArguments( vecArguments );
01898 
01899                         (*pIFunction)();
01900 
01901                         OclMeta::Object spResult = EvaluateCast( context, pIFunction->GetResult(), iLineFeatureName, signature.Print() );
01902                         pIFunction->Finalize();
01903 
01904                         return CheckFalseResult( context, spResult, iLineFeatureName, signature.Print() );
01905                 } EVALCATCH( iLineFeatureName, signature.Print() );
01906                 return OclMeta::Object::UNDEFINED;
01907         }
01908 
01909 //##############################################################################################################################################
01910 //
01911 //      C L A S S : OclTree::AssociationNode <<< + OclTree::TreeNode
01912 //
01913 //##############################################################################################################################################
01914 
01915         AssociationNode::AssociationNode( TreeManager* pManager )
01916                 : TreeNode( pManager, TreeNode::NK_ASSOCIATION), m_strName( "" ), m_strAcceptable( "" ), m_pThisNode( NULL )
01917         {
01918         }
01919 
01920         AssociationNode::~AssociationNode()
01921         {
01922                 if ( ! m_bTester )
01923                         if ( m_pThisNode )
01924                                 delete m_pThisNode;
01925         }
01926 
01927         std::string AssociationNode::Print( const std::string& strTabs ) const
01928         {
01929                 std::string strOut = strTabs + "<Association name=\"" + m_strName + "\" class=\"" + m_strAcceptable + "\">\r\n";
01930 
01931                 strOut += strTabs + TABSTR + "<This>\r\n";
01932                 if ( m_pThisNode )
01933                         strOut += m_pThisNode->Print( strTabs + TABSTR + TABSTR );
01934                 strOut += strTabs + TABSTR + "</This>\r\n";
01935 
01936                 strOut += strTabs + "</Association>\r\n";
01937                 return strOut;
01938         }
01939 
01940         void AssociationNode::CheckInitialize()
01941         {
01942                 if ( m_bSelfTester && ! m_bTester && m_pThisNode ) {
01943                         delete m_pThisNode;
01944                         m_pThisNode = NULL;
01945                 }
01946                 TreeNode::CheckInitialize();
01947         }
01948 
01949         bool AssociationNode::CheckImplementation( TypeContext& context )
01950         {
01951                 // Association cannot be called by ->
01952 
01953                 if ( m_strCallOperator == "->" )
01954                         ADDEX( EXCEPTION1( EX_INVALID_CALL, m_strCallOperator, m_mapPositions[ LID_CALL_OPERATOR ] ) );
01955 
01956                 // If This exists
01957 
01958                 if ( m_pThisNode ) {
01959                         bool bThisValid = m_bTester || m_pThisNode->Check( context );
01960                         if ( bThisValid )
01961                                 return CheckAssociation( context );
01962                         return false;
01963                 }
01964 
01965                 // If This does not exist
01966 
01967                 m_bSelfTester = true;
01968 
01969                 // Check Implicits variables
01970 
01971                 for ( int i = context.m_vecImplicits.size() - 1 ; i >= 0 ; i-- ) {
01972 
01973                         TypeContext contextAssociation( context.m_namespace);
01974                         CheckInitialize();
01975                         m_pThisNode = CreateThis( context, i );
01976                         if ( CheckAssociation( contextAssociation ) )
01977                                 return true;
01978                         else {
01979                                 delete m_pThisNode;
01980                                 m_pThisNode = NULL;
01981                                 int iLastCode = GetLastExceptionCode( contextAssociation );
01982                                 if ( iLastCode != EX_ASSOCIATION_DOESNT_EXIST ) {
01983                                         ADDEXP( contextAssociation.m_poolExceptions );
01984                                         return false;
01985                                 }
01986                         }
01987                 }
01988                 ADDEX( EXCEPTION1( EX_IMPL_ASSOC_DOESNT_EXIST, OclSignature::Association( m_strName, "", m_strAcceptable ).Print(), m_mapPositions[ LID_FEATURE_NAME ] ) );
01989                 return false;
01990         }
01991 
01992         bool AssociationNode::CheckAssociation( TypeContext& context )
01993         {
01994                 OclMeta::Type* pType = GetTreeManager()->GetTypeManager()->GetType( m_pThisNode->m_vecType[ 0 ], context.m_namespace ).get();
01995 
01996                 // Check static object can be called
01997 
01998                 if ( m_pThisNode->GetKind() == TreeNode::NK_OBJECT && ! m_bTester ) {
01999                         ObjectNode* pONode = (ObjectNode*) m_pThisNode;
02000                         if ( ! pONode->m_bCallable )
02001                                 ADDEX( EXCEPTION1( EX_OBJECT_CALL_PROHIBITED, m_pThisNode->m_vecType[ 0 ], m_mapPositions[ LID_CALL_OPERATOR ] ) );
02002                 }
02003 
02004                 // Compound Type cannot have associations
02005 
02006                 if ( pType->IsCompound() ) {
02007                         ADDEX( EXCEPTION1( EX_TYPE_COMPOUND_ASSOCIATION, pType->GetName(), m_mapPositions[ LID_FEATURE_NAME ] ) );
02008                         return false;
02009                 }
02010 
02011                 // Check Association Exists
02012 
02013                 try {
02014                         OclMeta::Association* pAssociation = pType->GetAssociation( OclSignature::Association( m_strName, m_pThisNode->m_vecType[ 0 ], m_strAcceptable ) );
02015                         m_vecType = pAssociation->GetReturnTypeSeq();
02016                         return true;
02017                 }
02018                 catch ( OclCommon::Exception ex ) {
02019                         SETEXPOS( ex, m_mapPositions[ LID_FEATURE_NAME ] );
02020                         ADDEX( ex );
02021                         return false;
02022                 }
02023         }
02024 
02025         OclMeta::Object AssociationNode::Evaluate( ObjectContext& context )
02026         {
02027                 int iLineFeatureName = m_mapPositions[ LID_FEATURE_NAME ].iLine;
02028                 OclSignature::Association signature( m_strName, m_pThisNode->m_vecType[ 0 ], m_strAcceptable );
02029 
02030                 OclMeta::Object objectThis = m_pThisNode->Evaluate( context );
02031                 if ( objectThis.IsUndefined() )
02032                         return objectThis;
02033 
02034                 EVALTRY {
02035                         OclMeta::Type* pType = GetTreeManager()->GetTypeManager()->GetType( objectThis.GetStaticTypeName(), NILNAMESPACE ).get();
02036                         OclMeta::Association* pAssociation = pType->GetAssociation( signature );
02037                         OclImplementation::Association* pIAssociation = pAssociation->GetImplementation();
02038                         if ( ! pIAssociation )
02039                                 THROWOCL0( ET_RUNTIME, EX_ASSOCIATION_NOT_IMPLEMENTED );
02040 
02041                         pIAssociation->Initialize();
02042                         pIAssociation->SetThis( objectThis );
02043 
02044                         (*pIAssociation)();
02045 
02046                         OclMeta::Object spResult = EvaluateCast( context, pIAssociation->GetResult(), iLineFeatureName, signature.Print() );
02047                         pIAssociation->Finalize();
02048 
02049                         return CheckFalseResult( context, spResult, iLineFeatureName, signature.Print() );
02050                 } EVALCATCH( iLineFeatureName, signature.Print() );
02051                 return OclMeta::Object::UNDEFINED;
02052         }
02053 
02054 //##############################################################################################################################################
02055 //
02056 //      C L A S S : OclTree::AttributeNode <<< + OclTree::TreeNode
02057 //
02058 //##############################################################################################################################################
02059 
02060         AttributeNode::AttributeNode( TreeManager* pManager )
02061                 : TreeNode( pManager, TreeNode::NK_ATTRIBUTE ), m_strName( "" ), m_pThisNode( NULL ), m_pAssociation( NULL ), m_pCollector( NULL )
02062         {
02063         }
02064 
02065         AttributeNode::~AttributeNode()
02066         {
02067                 if ( ! m_bTester && ! m_bSelfTester )
02068                         if ( m_pThisNode )
02069                                 delete m_pThisNode;
02070                 if ( m_pAssociation ) {
02071                         delete m_pAssociation;
02072                         m_pAssociation = NULL;
02073                 }
02074                 if ( m_pCollector ) {
02075                         delete m_pCollector;
02076                         m_pCollector = NULL;
02077                 }
02078         }
02079 
02080         std::string AttributeNode::Print( const std::string& strTabs ) const
02081         {
02082                 if ( m_pAssociation )
02083                         return m_pAssociation->Print( strTabs );
02084                 if ( m_pCollector )
02085                         return m_pCollector->Print( strTabs );
02086 
02087                 std::string strOut = strTabs + "<Attribute name=\"" + m_strName + "\">\r\n";
02088 
02089                 strOut += strTabs + TABSTR + "<This>\r\n";
02090                 strOut += m_pThisNode->Print( strTabs + TABSTR + TABSTR );
02091                 strOut += strTabs + TABSTR + "</This>\r\n";
02092 
02093                 strOut += strTabs + "</Attribute>\r\n";
02094                 return strOut;
02095         }
02096 
02097         void AttributeNode::CheckInitialize()
02098         {
02099                 TreeNode::CheckInitialize();
02100                 if ( m_pAssociation ) {
02101                         m_pAssociation->m_bTester = true;
02102                         delete m_pAssociation;
02103                         m_pAssociation = NULL;
02104                 }
02105                 if ( m_pCollector ) {
02106                         m_pCollector->m_bTester = true;
02107                         delete m_pCollector->m_pArgumentNode;
02108                         m_pCollector->m_pArgumentNode = NULL;
02109                         delete m_pCollector;
02110                         m_pCollector = NULL;
02111                 }
02112         }
02113 
02114         bool AttributeNode::CheckImplementation( TypeContext& context )
02115         {
02116                 // Check Self
02117 
02118                 bool bThisValid = m_bTester || m_pThisNode->Check( context );
02119 
02120                 if ( bThisValid ) {
02121 
02122                         OclMeta::Type* pType = GetTreeManager()->GetTypeManager()->GetType( m_pThisNode->m_vecType[ 0 ], context.m_namespace ).get();
02123 
02124                         // Type is not compound
02125 
02126                         if ( ! pType->IsCompound() ) {
02127 
02128                                 // Check static object can be called
02129 
02130                                 if ( m_pThisNode->GetKind() == TreeNode::NK_OBJECT ) {
02131                                         ObjectNode* pONode = (ObjectNode*) m_pThisNode;
02132                                         if ( ! pONode->m_bCallable )
02133                                                 ADDEX( EXCEPTION1( EX_OBJECT_CALL_PROHIBITED, m_pThisNode->m_vecType[ 0 ], m_mapPositions[ LID_CALL_OPERATOR ] ) );
02134                                 }
02135 
02136                                 // Check member selection operator
02137 
02138                                 if ( m_strCallOperator == "->" )
02139                                         ADDEX( EXCEPTION1( EX_INVALID_CALL, m_strCallOperator, m_mapPositions[ LID_CALL_OPERATOR ] ) );
02140 
02141                                 // Create Feature Call Check
02142 
02143                                 std::vector<OclMeta::Type*> vecTypes( 2, pType );
02144 
02145                                 OclSignature::Attribute sigAttribute( m_strName, pType->GetName() );
02146                                 OclSignature::Association sigAssociation( m_strName, pType->GetName(), "" );
02147                                 std::vector<OclSignature::Feature*> vecSignatures( 2, &sigAttribute ); vecSignatures[ 1 ] = &sigAssociation;
02148 
02149                                 std::vector<int> vecCodes( 3, EX_ATTRIBUTE_AMBIGUOUS ); vecCodes[ 1 ] = EX_ASSOCIATION_AMBIGUOUS; vecCodes[ 2 ] = EX_ATTRIBUTE_ASSOCIATION_AMBIGUOUS;
02150 
02151                                 OclCommon::ExceptionPool poolResult;
02152 
02153                                 int iPrecedence = 0;
02154 
02155                                 // Get Feature
02156 
02157                                 OclMeta::Feature* pFeature = CheckAmbiguity( vecTypes, vecSignatures, vecCodes, iPrecedence, poolResult );
02158                                 if ( ! pFeature ) {
02159                                         ADDEXP( poolResult );
02160                                         return false;
02161                                 }
02162                                 else {
02163                                         if ( iPrecedence == -1 ) {
02164                                                 m_vecType = pFeature->GetReturnTypeSeq();
02165                                                 if ( pFeature->IsDependence() )
02166                                                         context.m_setDependencies.insert( OclMeta::Dependency( sigAttribute.Print(), m_mapPositions[ LID_FEATURE_NAME ] ) );
02167                                         }
02168                                         else {
02169                                                 m_pAssociation = GetTreeManager()->CreateAssociation();
02170                                                 m_pAssociation->m_bTester = true;
02171                                                 m_pAssociation->m_pThisNode = m_pThisNode;
02172                                                 m_pAssociation->m_strCallOperator = ".";
02173                                                 m_pAssociation->m_strName = m_strName;
02174                                                 m_pAssociation->m_strAcceptable = "";
02175 
02176                                                 m_pAssociation->Check( context );
02177                                                 m_pAssociation->m_bTester = false;
02178                                                 m_bSelfTester = true;
02179                                                 m_vecType = m_pAssociation->m_vecType;
02180                                         }
02181                                         return true;
02182                                 }
02183                         }
02184                         else {
02185 
02186                         // Type is compound
02187 
02188                                 // Create Feature Call Check
02189 
02190                                 OclMeta::Type* pTypeInner = GetTreeManager()->GetTypeManager()->GetType( m_pThisNode->m_vecType[ 1 ], context.m_namespace ).get();
02191 
02192                                 std::vector<OclMeta::Type*> vecTypes( 2, pType ); vecTypes[ 1 ] = pTypeInner;
02193 
02194                                 OclSignature::Attribute sigAttribute( m_strName, pType->GetName() );
02195                                 OclSignature::Attribute sigAttributeInner( m_strName, pTypeInner->GetName() );
02196                                 std::vector<OclSignature::Feature*> vecSignatures( 2, &sigAttribute ); vecSignatures[ 1 ] = &sigAttributeInner;
02197 
02198                                 std::vector<int> vecCodes( 3, EX_ATTRIBUTE_AMBIGUOUS ); vecCodes[ 2 ] = EX_ATTRIBUTE_INNERATTRIBUTE_AMBIGUOUS;
02199 
02200                                 OclCommon::ExceptionPool poolResult;
02201 
02202                                 int iPrecedence = ( m_strCallOperator.empty() ) ? 0 : ( m_strCallOperator == "->" ) ? -1 : 1;
02203 
02204                                 // Get Feature
02205 
02206                                 OclMeta::Feature* pFeature = CheckAmbiguity( vecTypes, vecSignatures, vecCodes, iPrecedence, poolResult );
02207                                 if ( ! pFeature ) {
02208                                         ADDEXP( poolResult );
02209                                         return false;
02210                                 }
02211                                 else {
02212                                         if ( iPrecedence == -1 ) {
02213                                                 m_vecType = pFeature->GetReturnTypeSeq();
02214                                                 if ( pFeature->IsDependence() )
02215                                                         context.m_setDependencies.insert( OclMeta::Dependency( sigAttribute.Print(), m_mapPositions[ LID_FEATURE_NAME ] ) );
02216                                         }
02217                                         else {
02218                                                 if ( pFeature->IsDependence() )
02219                                                         context.m_setDependencies.insert( OclMeta::Dependency( sigAttributeInner.Print(), m_mapPositions[ LID_FEATURE_NAME ] ) );
02220                                                 int iPiece = 0; char chBuffer[ 500 ];
02221                                                 std::string strDeclarator = "-" + m_strName;
02222                                                 sprintf_s( chBuffer, sizeof(chBuffer), "%ld", iPiece );
02223                                                 while ( context.m_ctxTypes.ExistsVariable( strDeclarator + std::string( chBuffer ) ) )
02224                                                         sprintf_s( chBuffer, sizeof(chBuffer), "%ld", ++iPiece );
02225 
02226                                                 VariableNode* pVariableNode = GetTreeManager()->CreateVariable();
02227                                                 pVariableNode->m_strName = strDeclarator + std::string( chBuffer );
02228                                                 pVariableNode->m_vecType = TypeSeq( 1, pTypeInner->GetName() );
02229 
02230                                                 AttributeNode* pAttributeNode = GetTreeManager()->CreateAttribute();
02231                                                 pAttributeNode->m_pThisNode = pVariableNode;
02232                                                 pAttributeNode->m_strCallOperator = ( pTypeInner->IsCompound() ) ? "->" : ".";
02233                                                 pAttributeNode->m_strName = m_strName;
02234                                                 pAttributeNode->m_vecType = pFeature->GetReturnTypeSeq();
02235 
02236                                                 m_pCollector = GetTreeManager()->CreateIterator();
02237                                                 m_pCollector->m_bTester = true;
02238                                                 m_pCollector->m_pThisNode = m_pThisNode;
02239                                                 m_pCollector->m_strCallOperator = "->";
02240                                                 m_pCollector->m_strName = "collect";
02241                                                 m_pCollector->m_vecDeclarators = StringVector( 1, std::string( chBuffer ) );
02242                                                 m_pCollector->m_mapPositions = m_mapPositions;
02243                                                 m_pCollector->m_pArgumentNode = pAttributeNode;
02244 
02245                                                 m_pCollector->Check( context );
02246                                                 m_pCollector->m_bTester = false;
02247                                                 m_bSelfTester = true;
02248                                                 m_vecType = m_pCollector->m_vecType;
02249                                         }
02250                                         return true;
02251                                 }
02252                         }
02253                 }
02254                 return false;
02255         }
02256 
02257         OclMeta::Object AttributeNode::Evaluate( ObjectContext& context )
02258         {
02259                 if ( m_pAssociation )
02260                         return m_pAssociation->Evaluate( context );
02261                 if ( m_pCollector )
02262                         return m_pCollector->Evaluate( context );
02263 
02264                 int iLineFeatureName = m_mapPositions[ LID_FEATURE_NAME ].iLine;
02265                 OclSignature::Attribute signature( m_strName, m_pThisNode->m_vecType[ 0 ] );
02266 
02267                 OclMeta::Object objectThis = m_pThisNode->Evaluate( context );
02268                 if ( objectThis.IsUndefined() )
02269                         return objectThis;
02270 
02271                 EVALTRY {
02272                         OclMeta::Type* pType = GetTreeManager()->GetTypeManager()->GetType( objectThis.GetStaticTypeName(), NILNAMESPACE ).get();
02273                         OclMeta::Attribute* pAttribute = pType->GetAttribute( signature );
02274                         OclImplementation::Attribute* pIAttribute = pAttribute->GetImplementation();
02275                         if ( ! pIAttribute )
02276                                 THROWOCL0( ET_RUNTIME, EX_ATTRIBUTE_NOT_IMPLEMENTED );
02277 
02278                         pIAttribute->Initialize();
02279                         pIAttribute->SetThis( objectThis );
02280 
02281                         (*pIAttribute)();
02282 
02283                         OclMeta::Object spResult = EvaluateCast( context, pIAttribute->GetResult(), iLineFeatureName, signature.Print() );
02284                         pIAttribute->Finalize();
02285 
02286                         return CheckFalseResult( context, spResult, iLineFeatureName, signature.Print() );
02287                 } EVALCATCH( iLineFeatureName, signature.Print() );
02288                 return OclMeta::Object::UNDEFINED;
02289         }
02290 
02291 //##############################################################################################################################################
02292 //
02293 //      C L A S S : OclTree::VariableNode <<< + OclTree::TreeNode
02294 //
02295 //##############################################################################################################################################
02296 
02297         VariableNode::VariableNode( TreeManager* pManager )
02298                 : TreeNode( pManager, TreeNode::NK_VARIABLE ), m_strName( "" ), m_pAttribute( NULL ), m_pType( NULL )
02299         {
02300         }
02301 
02302         VariableNode::~VariableNode()
02303         {
02304                 CheckInitialize();
02305         }
02306 
02307         std::string VariableNode::Print( const std::string& strTabs ) const
02308         {
02309                 if ( m_pAttribute )
02310                         return m_pAttribute->Print( strTabs );
02311 
02312                 std::string strOut = strTabs + "<Variable name=\"" + m_strName + "\">\r\n";
02313                 strOut += strTabs + "</Variable>\r\n";
02314                 return strOut;
02315         }
02316 
02317         void VariableNode::CheckInitialize()
02318         {
02319                 TreeNode::CheckInitialize();
02320                 if ( m_pAttribute ) {
02321                         m_pAttribute->m_bTester = true;
02322                         m_pAttribute->CheckInitialize();
02323                         delete m_pAttribute->m_pThisNode;
02324                         m_pAttribute->m_pThisNode = NULL;
02325                         delete m_pAttribute;
02326                         m_pAttribute = NULL;
02327                 }
02328                 if ( m_pType ) {
02329                         delete m_pType;
02330                         m_pType = NULL;
02331                 }
02332         }
02333 
02334         bool VariableNode::CheckImplementation( TypeContext& context )
02335         {
02336                 // Check if Type exists
02337 
02338                 TypeContext contextType( context.m_namespace);
02339                 m_pType = GetTreeManager()->CreateObject();
02340                 m_pType->m_bTester = true;
02341                 m_pType->m_strType = "ocl::Type";
02342                 m_pType->m_strValue = m_strName;
02343                 m_pType->m_bCallable = false;
02344                 m_pType->m_mapPositions = m_mapPositions;
02345                 if ( m_pType->Check( contextType ) ) {
02346                         m_pType->m_bTester = false;
02347                         m_bSelfTester = true;
02348                         m_vecType = m_pType->m_vecType;
02349                         return true;
02350                 }
02351                 else {
02352                         delete m_pType;
02353                         m_pType = NULL;
02354                         if ( m_strName.find( ":" ) != std::string::npos ) {
02355                                 ADDEXP( contextType.m_poolExceptions );
02356                                 return false;
02357                         }
02358                 }
02359 
02360                 // Check if Variable exists
02361 
02362                 OclCommon::Exception exVariable = EXCEPTION1( EX_VARIABLE_DOESNT_EXIST, m_strName, m_mapPositions[ LID_NODE_START ] );
02363                 if ( context.m_ctxTypes.GetVariable( m_strName, m_vecType ) )
02364                         return true;
02365                 else
02366                         if ( m_strName == "self" || m_strName.substr( 0, 1 ) == "!" || m_strName.substr( 0, 1 ) == "-" ) {
02367                                 ADDEX( exVariable );
02368                                 return false;
02369                         }
02370 
02371                 // Check Self
02372 
02373                 for ( int i = context.m_vecImplicits.size() - 1 ; i >= 0 ; i-- ) {
02374 
02375                         TypeContext contextAttribute = context;
02376                         contextAttribute.m_poolExceptions.Clear();
02377 
02378                         m_pAttribute = GetTreeManager()->CreateAttribute();
02379                         m_pAttribute->m_bTester = true;
02380                         m_pAttribute->m_pThisNode = CreateThis( context, i );
02381                         m_pAttribute->m_strCallOperator = "";
02382                         m_pAttribute->m_strName = m_strName;
02383 
02384                         if ( m_pAttribute->Check( contextAttribute ) ) {
02385                                 m_pAttribute->m_bTester = false;
02386                                 m_bSelfTester = true;
02387                                 m_vecType = m_pAttribute->m_vecType;
02388                                 return true;
02389                         }
02390                         else {
02391                                 delete m_pAttribute->m_pThisNode;
02392                                 m_pAttribute->m_pThisNode = NULL;
02393                                 delete m_pAttribute;
02394                                 m_pAttribute = NULL;
02395                                 int iLastCode = GetLastExceptionCode( contextAttribute );
02396                                 if ( iLastCode != EX_ATTRIBUTE_DOESNT_EXIST && iLastCode != EX_ASSOCIATION_DOESNT_EXIST ) {
02397                                         ADDEXP( contextAttribute.m_poolExceptions );
02398                                         return false;
02399                                 }
02400                         }
02401                 }
02402                 ADDEX( EXCEPTION1( EX_VAR_IMPL_ATTRIB_ASSOC_DOESNT_EXIST, m_strName, m_mapPositions[ LID_NODE_START ] ) );
02403                 return false;
02404         }
02405 
02406         OclMeta::Object VariableNode::Evaluate( ObjectContext& context )
02407         {
02408                 if ( m_pType )
02409                         return m_pType->Evaluate( context );
02410                 if ( m_pAttribute )
02411                         return m_pAttribute->Evaluate( context );
02412 
02413                 OclMeta::Object spObject;
02414                 context.oCtx.GetVariable( m_strName, spObject );
02415                 return spObject;
02416         }
02417 
02418 //##############################################################################################################################################
02419 //
02420 //      C L A S S : OclTree::ContextNode <<< + OclTree::TreeNode
02421 //
02422 //##############################################################################################################################################
02423 
02424         ContextNode::ContextNode( TreeManager* pManager )
02425                 : TreeNode( pManager, TreeNode::NK_CONTEXT ), m_strName( "" ), m_strType( "" ), m_bClassifier( false ), m_strStereotype( "" ), m_strReturnType( "" )
02426         {
02427         }
02428 
02429         std::string ContextNode::Print( const std::string& strTabs ) const
02430         {
02431                 std::string strOut = strTabs + "<Context type=\"" +( ( m_bClassifier ) ? "Classifier" : "Operation" ) + "\" stereotype=\"" + m_strStereotype + "\">\r\n";
02432                 if ( m_bClassifier )
02433                         strOut += strTabs + TABSTR + ( ( ! m_strName.empty() ) ? m_strName : "self" ) + " : " + m_strType + "\r\n";
02434                 else {
02435                         strOut += strTabs + TABSTR + m_strType + "::" + m_strName + "( ";
02436                         for ( unsigned int i = 0 ; i < m_vecParameters.size() ; i++ ) {
02437                                 strOut += m_vecParameters[ i ].GetName() + " : " + m_vecParameters[ i ].GetTypeName();
02438                                 if ( i != m_vecParameters.size() - 1 )
02439                                         strOut += ", ";
02440                         }
02441                         strOut += " )" + ( ( ! m_strReturnType.empty() ) ? " : " + m_strReturnType : "" ) + "\r\n";
02442                 }
02443                 strOut += strTabs + "</Context>\r\n";
02444                 return strOut;
02445         }
02446 
02447         void ContextNode::CheckInitialize()
02448         {
02449                 TreeNode::CheckInitialize();
02450                 m_setDependencies.clear();
02451                 m_vecTypeReturn.clear();
02452         }
02453 
02454         bool ContextNode::CheckImplementation( TypeContext& context )
02455         {
02456                 context.m_strStereotype = m_strStereotype;
02457 
02458                 // C L A S S I F I E R   C O N T E X T
02459 
02460                 // Check type of "self" and Add "self"
02461 
02462                 if ( m_strStereotype == "inv" ) {
02463                         if ( ! ParseTypeSeq( context, m_mapPositions[ LID_CONTEXT_TYPE ], m_strType, m_vecType ) )
02464                                 return false;
02465                         context.m_ctxTypes.AddVariable( ( m_strName == "" ) ? "self" : m_strName, m_vecType );
02466                         context.m_vecImplicits.push_back( ( m_strName == "" ) ? "self" : m_strName );
02467                         m_vecTypeReturn.push_back( "ocl::Boolean" );
02468                         return true;
02469                 }
02470 
02471                 // O P E R A T I O N   C O N T E X T
02472 
02473                 // Check type of "self" and Add "self"
02474 
02475                 if ( ParseTypeSeq( context, m_mapPositions[ LID_CONTEXT_TYPE ], m_strType, m_vecType ) ) {
02476                         context.m_ctxTypes.AddVariable( "self", m_vecType );
02477                         context.m_vecImplicits.push_back( "self" );
02478                 }
02479 
02480                 // Check Parameters
02481 
02482                 TypeSeq vecType;
02483                 for ( unsigned int i = 0 ; i < m_vecParameters.size() ; i++ ) {
02484                         vecType.clear();
02485                         std::string strType = m_vecParameters[ i ].GetTypeName();
02486                         std::string strName = m_vecParameters[ i ].GetName();
02487                         if ( ParseTypeSeq( context, m_mapPositions[ LID_PARAMETER_TYPE + i ], strType, vecType ) )
02488                                 m_vecParameters[ i ] = OclCommon::FormalParameter( strName, strType, m_vecParameters[ i ].IsRequired() );
02489                         if ( context.m_ctxTypes.ExistsVariable( strName ) )
02490                                 ADDEX( EXCEPTION1( EX_VARIABLE_ALREADY_EXISTS, strName, m_mapPositions[ LID_PARAMETER_NAME + i ] ) )
02491                         else
02492                                 if ( ! vecType.empty() )
02493                                         context.m_ctxTypes.AddVariable( strName, vecType );
02494                 }
02495 
02496                 // Check Return Type if exists
02497 
02498                 if ( ! m_strReturnType.empty() )
02499                         ParseTypeSeq( context, m_mapPositions[ LID_CONTEXT_RETURNTYPE ], m_strReturnType, m_vecTypeReturn );
02500                 if ( m_strStereotype == "defattribute" || m_strStereotype == "defmethod" ) {
02501                         if ( m_strReturnType.empty() )
02502                                 ADDEX( EXCEPTION0( EX_CONSTRAINT_DEF_RETURN_MISSING, m_mapPositions[ LID_NODE_START ] ) );
02503                 }
02504                 else
02505                         m_vecTypeReturn.push_back( "ocl::Boolean" );
02506                 if ( ! m_vecTypeReturn.empty() )
02507                         context.m_ctxTypes.AddVariable( "result", m_vecTypeReturn, m_strStereotype == "defattribute" || m_strStereotype == "defmethod" );
02508 
02509                 return ! m_vecType.empty();
02510         }
02511 
02512         OclMeta::Object ContextNode::Evaluate( ObjectContext& context )
02513         {
02514                 OclMeta::Object spResult;
02515                 context.oCtx.GetVariable( ( m_strName == "" ) ? "self" : m_strName, spResult );
02516                 return spResult;
02517         }
02518 
02519 //##############################################################################################################################################
02520 //
02521 //      C L A S S : OclTree::Constraint <<< + OclTree::TreeNode
02522 //
02523 //##############################################################################################################################################
02524 
02525         Constraint::Constraint( TreeManager* pManager )
02526                 : TreeNode( pManager, TreeNode::NK_CONSTRAINT ), m_strName( "" ), m_pContext( NULL ), m_pExpression( NULL )
02527         {
02528         }
02529 
02530         Constraint::~Constraint()
02531         {
02532                 if ( m_pContext )
02533                         delete m_pContext;
02534                 if ( m_pExpression )
02535                         delete m_pExpression;
02536         }
02537 
02538         std::string Constraint::Print( const std::string& strTabs ) const
02539         {
02540                 std::string strOut = strTabs + strTabs + "<Constraint name=\"" + m_strName + "\">\r\n";
02541 
02542                 strOut += strTabs + TABSTR + "<Context>\r\n";
02543                 strOut += m_pContext->Print( strTabs + TABSTR + TABSTR );
02544                 strOut += strTabs + TABSTR + "</Context>\r\n";
02545 
02546                 strOut += strTabs + TABSTR + "<Expression>\r\n";
02547                 strOut += m_pExpression->Print( strTabs + TABSTR + TABSTR );
02548                 strOut += strTabs + TABSTR + "</Expression>\r\n";
02549 
02550                 strOut += "</Constraint>\r\n";
02551                 return strOut;
02552         }
02553 
02554         bool Constraint::CheckImplementation( TypeContext& context )
02555         {
02556                 m_pContext->Check( context );
02557                 bool bValidC = context.m_poolExceptions.IsEmpty();
02558                 bool bValidE = true;
02559                 if ( m_pExpression ) {
02560                         bValidE = m_pExpression->Check( context );
02561                         if ( bValidE && bValidC ) {
02562                                 m_pContext->m_setDependencies = context.m_setDependencies;
02563                                 if ( ! GetTreeManager()->GetTypeManager()->IsTypeA( m_pExpression->m_vecType, m_pContext->m_vecTypeReturn ) ) {
02564                                         if ( m_pContext->m_strStereotype == "defattribute" || m_pContext->m_strStereotype == "defmethod" ) {
02565                                                 std::string strEType, strDType;
02566                                                 OclCommon::Convert( m_pExpression->m_vecType, strEType );
02567                                                 OclCommon::Convert( m_pContext->m_vecTypeReturn, strDType );
02568                                                 ADDEX( EXCEPTION2( EX_CONSTRAINT_DEF_RETURN_MISMATCH, strDType, strEType, m_pExpression->m_mapPositions[ LID_NODE_START ] ) );
02569                                         }
02570                                         else
02571                                                 ADDEX( EXCEPTION0( EX_BOOLEAN_REQUIRED, m_pExpression->m_mapPositions[ LID_NODE_START ]  ) );
02572                                         bValidE = false;
02573                                 }
02574                                 else
02575                                         m_vecType = m_pExpression->m_vecType;
02576                         }
02577                 }
02578                 return bValidC && bValidE;
02579         }
02580 
02581         OclMeta::Object Constraint::Evaluate( ObjectContext& context )
02582         {
02583                 int iLineNodeStart = m_mapPositions[ LID_NODE_START ].iLine;
02584                 EVALTRY {
02585                         OclMeta::Object spResult = EvaluateCast( context, m_pExpression->Evaluate( context ), iLineNodeStart, "At root expression" );
02586                         context.m_bEnableTracking = true;
02587                         if ( spResult.IsUndefined() ) {
02588                                 std::string strMyself = ( m_pContext->m_strStereotype == "defattribute" || m_pContext->m_strStereotype == "defmethod" ) ? "Definition " : "Constraint ";
02589                                 AddViolation( context, iLineNodeStart, "At root expression", strMyself + "evaluated to undefined object." );
02590                         }
02591 
02592                         return CheckFalseResult( context, spResult, iLineNodeStart, "At root expression" );
02593                 } EVALCATCH( iLineNodeStart, "At root expression" );
02594                 return OclMeta::Object::UNDEFINED;
02595         }
02596 
02597 //##############################################################################################################################################
02598 //
02599 //      C L A S S : OclTree::ObjectNodeAdaptor
02600 //
02601 //##############################################################################################################################################
02602 
02603         std::string ObjectNodeAdaptor::Print( const std::string& strTabs, ObjectNode* pNode ) const
02604         {
02605                 std::string strOut = strTabs + "<Object type=\"" + pNode->m_strType + "\">\r\n";
02606 
02607                 strOut += strTabs + TABSTR + "<Value>\r\n";
02608                 strOut += strTabs + TABSTR + TABSTR;
02609                 if ( pNode->m_strType == "ocl::String" )
02610                         strOut += "\"" + pNode->m_strValue + "\"\r\n";
02611                 else
02612                         if ( pNode->m_strType == "ocl::Enumeration" )
02613                                 strOut += "#" + pNode->m_strValue + "\r\n";
02614                         else
02615                                 strOut += pNode->m_strValue + "\r\n";
02616                 strOut += strTabs + TABSTR + "</Value>\r\n";
02617 
02618                 strOut += strTabs +  "</Object>\r\n";
02619                 return strOut;
02620         }
02621 
02622         bool ObjectNodeAdaptor::Check( TypeContext& context, ObjectNode* pNode ) const
02623         {
02624                 if ( pNode->ParseTypeSeq( context, pNode->m_mapPositions[ LID_NODE_START ], pNode->m_strType, pNode->m_vecType ) ) {
02625 
02626                         // Check whether this adaptor is able to create object
02627 
02628                         if ( pNode->m_strType == "ocl::String" || pNode->m_strType == "ocl::Enumeration" || pNode->m_strType == "ocl::Real" || pNode->m_strType == "ocl::Integer" || pNode->m_strType == "ocl::Boolean" )
02629                                 return true;
02630                         else {
02631                                 if ( pNode->m_strType == "ocl::Type" ) {
02632                                         std::string strValue = pNode->m_strValue;
02633                                         TypeSeq vecType;
02634                                         bool bIsType = pNode->ParseTypeSeq( context, pNode->m_mapPositions[ LID_NODE_START ], strValue, vecType );
02635                                         if ( ! bIsType )
02636                                                 pNode->m_vecType.clear();
02637                                         else
02638                                                 pNode->m_strValue = strValue;
02639                                         return bIsType;
02640                                 }
02641                                 ADDEX( EXCEPTION2( EX_CANNOT_CREATE_OBJECT, pNode->m_strType, pNode->m_strValue, pNode->m_mapPositions[ LID_NODE_START ] ) );
02642                                 pNode->m_vecType.clear();
02643                         }
02644                 }
02645                 return false;
02646         }
02647 
02648         OclMeta::Object ObjectNodeAdaptor::Evaluate( ObjectContext& context, ObjectNode* pNode ) const
02649         {
02650                 if ( pNode->m_strType == "ocl::String" )
02651                         return CREATE_STRING( pNode->GetTreeManager()->GetTypeManager(), pNode->m_strValue );
02652                 if ( pNode->m_strType == "ocl::Enumeration" )
02653                         return CREATE_ENUMERATION( pNode->GetTreeManager()->GetTypeManager(), pNode->m_strValue );
02654                 if ( pNode->m_strType == "ocl::Boolean" ) {
02655                         return CREATE_BOOLEAN( pNode->GetTreeManager()->GetTypeManager(), pNode->m_strValue == "true" );
02656                 }
02657                 if ( pNode->m_strType == "ocl::Real" ) {
02658                         char* pchStop;
02659                         double dValue = strtod( pNode->m_strValue.c_str(), &pchStop );
02660                         return CREATE_REAL( pNode->GetTreeManager()->GetTypeManager(), dValue );
02661                 }
02662                 if ( pNode->m_strType == "ocl::Integer" ) {
02663                         long lValue = atol( pNode->m_strValue.c_str() );
02664                         return CREATE_INTEGER( pNode->GetTreeManager()->GetTypeManager(), lValue );
02665                 }
02666                 if ( pNode->m_strType == "ocl::Type" )
02667                         return CREATE_TYPE( pNode->GetTreeManager()->GetTypeManager(), pNode->m_strValue );
02668                 return OclMeta::Object::UNDEFINED;
02669         }
02670 
02671 //##############################################################################################################################################
02672 //
02673 //      C L A S S : OclTree::CollectionNodeAdaptor
02674 //
02675 //##############################################################################################################################################
02676 
02677         std::string CollectionNodeAdaptor::Print( const std::string& strTabs, CollectionNode* pNode ) const
02678         {
02679                 std::string strOut = strTabs + "<Collection type=\"" + pNode->m_strType + "\">\r\n";
02680 
02681                 for ( unsigned int i = 0 ; i < pNode->m_vecNodes.size() ; i++ ) {
02682                         char chNum[ 100 ];
02683                         sprintf_s( chNum, sizeof(chNum), "%lu", i );
02684                         strOut += strTabs + TABSTR + "<Element_" + std::string( chNum ) + ">\r\n";
02685                         strOut += pNode->m_vecNodes[ i ]->Print( strTabs + TABSTR + TABSTR );
02686                         strOut += strTabs + TABSTR + "</Element_" + std::string( chNum ) + ">\r\n";
02687                 }
02688 
02689                 strOut += strTabs + "</Collection>\r\n";
02690                 return strOut;
02691         }
02692 
02693         bool CollectionNodeAdaptor::Check( TypeContext& context, CollectionNode* pNode ) const
02694         {
02695                 if ( pNode->m_strType == "Set" || pNode->m_strType == "Sequence" || pNode->m_strType == "Bag" || pNode->m_strType == "OrderedSet" )
02696                         pNode->m_strType = "ocl::" + pNode->m_strType;
02697 
02698                 bool bValid = pNode->ParseTypeSeq( context, pNode->m_mapPositions[ LID_NODE_START ], pNode->m_strType, pNode->m_vecType );
02699 
02700                 // Check if this object is Compound
02701 
02702                 if ( bValid ) {
02703                         OclMeta::Type* pType = pNode->GetTreeManager()->GetTypeManager()->GetType( pNode->m_vecType[ 0 ], context.m_namespace ).get();
02704                         if ( ! pType->IsCompound() ) {
02705                                 ADDEX( EXCEPTION1( EX_TYPE_ISNT_COMPOUND, pNode->m_vecType[ 0 ], pNode->m_mapPositions[ LID_NODE_START ] ) );
02706                                 bValid = false;
02707                         }
02708 
02709                         // Check if this adaptor can create Compound Object
02710 
02711                         if ( ! ( pNode->m_vecType[ 0 ] == "ocl::Set" || pNode->m_vecType[ 0 ] == "ocl::Sequence" || pNode->m_vecType[ 0 ] == "ocl::Bag"  || pNode->m_vecType[ 0 ] == "ocl::OrderedSet" ) ) {
02712                                 ADDEX( EXCEPTION1( EX_CANNOT_CREATE_COLLECTION, pNode->m_strType, pNode->m_mapPositions[ LID_NODE_START ] ) );
02713                                 bValid = false;
02714                         }
02715                 }
02716 
02717                 // Determine the base of consisted Objects
02718 
02719                 bool bArgumentsValid = true;
02720                 TypeSeq vecAggregatedType;
02721                 for ( unsigned int i = 0 ; i < pNode->m_vecNodes.size() ; i++ ) {
02722                         bArgumentsValid = pNode->m_vecNodes[ i ]->Check( context )  && bArgumentsValid;
02723                         if ( bArgumentsValid ) {
02724                                 TypeSeq vecType = pNode->m_vecNodes[ i ]->m_vecType;
02725                                 if ( vecAggregatedType.empty() )
02726                                         vecAggregatedType = vecType;
02727                                 else
02728                                         vecAggregatedType = pNode->GetTreeManager()->GetTypeManager()->GetTypeBase( vecAggregatedType, vecType );
02729                         }
02730                 }
02731 
02732                 // Set return type
02733 
02734                 if ( bValid && bArgumentsValid ) {
02735                         if ( vecAggregatedType.empty() )
02736                                 vecAggregatedType.push_back( "ocl::Any" );
02737                         vecAggregatedType.insert( vecAggregatedType.begin(), pNode->m_vecType[ 0 ] );
02738                         pNode->m_vecType = vecAggregatedType;
02739                 }
02740                 return bValid && bArgumentsValid;
02741         }
02742 
02743         OclMeta::Object CollectionNodeAdaptor::Evaluate( ObjectContext& context, CollectionNode* pNode ) const
02744         {
02745                 OclMeta::ObjectVector vecObjects;
02746                 for ( unsigned int i = 0 ; i < pNode->m_vecNodes.size() ; i++ )
02747                         vecObjects.push_back( pNode->m_vecNodes[ i ]->Evaluate( context ) );
02748 
02749                 if ( pNode->m_vecType[ 0 ] == "ocl::Set" )
02750                         return CREATE_SET( pNode->GetTreeManager()->GetTypeManager(), vecObjects );
02751                 if ( pNode->m_vecType[ 0 ] == "ocl::Bag" )
02752                         return CREATE_BAG( pNode->GetTreeManager()->GetTypeManager(), vecObjects );
02753                 if ( pNode->m_vecType[ 0 ] == "ocl::Sequence" )
02754                         return CREATE_SEQUENCE( pNode->GetTreeManager()->GetTypeManager(), vecObjects );
02755                 if ( pNode->m_vecType[ 0 ] == "ocl::OrderedSet" )
02756                         return CREATE_ORDEREDSET( pNode->GetTreeManager()->GetTypeManager(), vecObjects );
02757 
02758                 return OclMeta::Object::UNDEFINED;
02759         }
02760 
02761 //##############################################################################################################################################
02762 //
02763 //      C L A S S : OclTree::TreeManager
02764 //
02765 //##############################################################################################################################################
02766 
02767         TreeManager::TreeManager( OclMeta::TypeManager* pTypeManager, ObjectNodeAdaptor* pOAdaptor, CollectionNodeAdaptor* pCAdaptor )
02768                 : m_pTypeManager( pTypeManager ), m_pOAdaptor( pOAdaptor ), m_pCAdaptor( pCAdaptor )
02769         {
02770         }
02771 
02772         TreeManager::~TreeManager()
02773         {
02774                 delete m_pTypeManager;
02775                 delete m_pOAdaptor;
02776                 delete m_pCAdaptor;
02777         }
02778 
02779         OclMeta::TypeManager* TreeManager::GetTypeManager() const
02780         {
02781                 return m_pTypeManager;
02782         }
02783 
02784         ObjectNode* TreeManager::CreateObject() const
02785         {
02786                 return new ObjectNode( (TreeManager*) this );
02787         }
02788 
02789         CollectionNode* TreeManager::CreateCollection() const
02790         {
02791                 return new CollectionNode( (TreeManager*) this );
02792         }
02793 
02794         DeclarationNode* TreeManager::CreateDeclaration() const
02795         {
02796                 return new DeclarationNode( (TreeManager*) this );
02797         }
02798 
02799         IteratorNode* TreeManager::CreateIterator() const
02800         {
02801                 return new IteratorNode( (TreeManager*) this );
02802         }
02803 
02804         MethodNode* TreeManager::CreateMethod() const
02805         {
02806                 return new MethodNode( (TreeManager*) this );
02807         }
02808 
02809         FunctionNode* TreeManager::CreateFunction() const
02810         {
02811                 return new FunctionNode( (TreeManager*) this );
02812         }
02813 
02814         AssociationNode* TreeManager::CreateAssociation() const
02815         {
02816                 return new AssociationNode( (TreeManager*) this );
02817         }
02818 
02819         AttributeNode* TreeManager::CreateAttribute() const
02820         {
02821                 return new AttributeNode( (TreeManager*) this );
02822         }
02823 
02824         VariableNode* TreeManager::CreateVariable() const
02825         {
02826                 return new VariableNode( (TreeManager*) this );
02827         }
02828 
02829         ContextNode* TreeManager::CreateContext() const
02830         {
02831                 return new ContextNode( (TreeManager*) this );
02832         }
02833 
02834         TypeCastNode* TreeManager::CreateTypeCast() const
02835         {
02836                 return new TypeCastNode( (TreeManager*) this );
02837         }
02838 
02839         IfThenElseNode* TreeManager::CreateIfThenElse() const
02840         {
02841                 return new IfThenElseNode( (TreeManager*) this );
02842         }
02843 
02844         OperatorNode* TreeManager::CreateOperator() const
02845         {
02846                 return new OperatorNode( (TreeManager*) this );
02847         }
02848 
02849         Constraint* TreeManager::CreateConstraint() const
02850         {
02851                 return new Constraint( (TreeManager*) this );
02852         }
02853 
02854 //udmoclpat_ocltree_cpp_1 __please do not remove or change this line__
02855 
02856 }; // namespace OclTree