#include "stdafx.h" CClass::CClass( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const std::string &name ) : ClassPrototype( namespaceScopes, name ) , importedNamespaces( importedNamespaces ) , classType( Class ) , pSuperClass( NULL ) , blittableType( Type() ) , isReady( false ) , fixedAlignment( 0 ) , ConstructorMemberSubIndex( -1 ) , DestructorMemberSubIndex( -1 ) , vtblNum( 0 ) , vtbl_offset( -1 ) , comVtblOffset( 0 ) , isCompilingConstructor( false ) , isCompilingDestructor( false ) , cacheSize( 0 ) { } CClass::CClass( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const std::string &name, ClassType classType, const GenericTypes &formalGenericTypes, const Types &superClassActualTypeParameters, int ConstructorMemberSubIndex, int DestructorMemberSubIndex, int vtblNum, int fixedAlignment ) : ClassPrototype( namespaceScopes, name ) , importedNamespaces( importedNamespaces ) , classType( classType ) , formalGenericTypes( formalGenericTypes ) , pSuperClass( NULL ) , superClassActualTypeParameters( superClassActualTypeParameters ) , blittableType( Type() ) , isReady( false ) , ConstructorMemberSubIndex( ConstructorMemberSubIndex ) , DestructorMemberSubIndex( DestructorMemberSubIndex ) , vtblNum( vtblNum ) , fixedAlignment( fixedAlignment ) , vtbl_offset( -1 ) , comVtblOffset( 0 ) , isCompilingConstructor( false ) , isCompilingDestructor( false ) , cacheSize( 0 ) { } CClass::CClass() : ClassPrototype() , importedNamespaces() , classType() , pSuperClass( NULL ) , blittableType( Type() ) , isReady( false ) , fixedAlignment( 0 ) , ConstructorMemberSubIndex( -1 ) , DestructorMemberSubIndex( -1 ) , vtblNum( 0 ) , vtbl_offset( -1 ) , comVtblOffset( 0 ) , isCompilingConstructor( false ) , isCompilingDestructor( false ) , cacheSize( 0 ) { } CClass::~CClass() { // 動的メンバ BOOST_FOREACH( Member *member, dynamicMembers ) { delete member; } // 静的メンバ BOOST_FOREACH( Member *member, staticMembers ) { delete member; } // インターフェイス BOOST_FOREACH( ::Interface *pInterface, interfaces ) { delete pInterface; } // テンプレート展開済みのクラス BOOST_FOREACH( ExpandedTemplateClass *pExpandedTemplateClass, expandedTemplateClasses ) { delete pExpandedTemplateClass; } } void CClass::Using() const { if( this->IsUsing() ) { // 既に使用することになっている return; } Prototype::Using(); // 仮想関数になるメソッドに使用チェックをつける const CClass &objThis = *this; BOOST_FOREACH( const CMethod *pMethod, objThis.GetDynamicMethods() ) { if( pMethod->IsVirtual() ) { pMethod->GetUserProc().Using(); } } } bool CClass::IsClass() const { return classType == CClass::Class; } bool CClass::IsInterface() const { return classType == CClass::Interface; } bool CClass::IsComInterface() const { return classType == CClass::ComInterface; } bool CClass::IsEnum() const { return classType == CClass::Enum; } bool CClass::IsDelegate() const { return classType == CClass::Delegate; } bool CClass::IsStructure() const { return classType == CClass::Structure; } // コンストラクタのコンパイルを開始 void CClass::NotifyStartConstructorCompile() const { isCompilingConstructor = true; } //コンストラクタのコンパイルを終了 void CClass::NotifyFinishConstructorCompile() const { isCompilingConstructor = false; } //コンストラクタをコンパイル中かどうかを判別 bool CClass::IsCompilingConstructor() const { return isCompilingConstructor; } //デストラクタのコンパイルを開始 void CClass::NotifyStartDestructorCompile() const{ isCompilingDestructor = true; } //デストラクタのコンパイルを終了 void CClass::NotifyFinishDestructorCompile() const{ isCompilingDestructor = false; } //デストラクタをコンパイル中かどうかを判別 bool CClass::IsCompilingDestructor() const { return isCompilingDestructor; } //自身の派生クラスかどうかを確認 bool CClass::IsSubClass( const CClass *pSubClass ) const { if( !pSubClass->HasSuperClass() ) { return false; } const CClass *pTempClass = &pSubClass->GetSuperClass(); while( pTempClass ){ if( this == pTempClass ) return true; pTempClass = &pTempClass->GetSuperClass(); } return false; } //自身と等しいまたは派生クラスかどうかを確認 bool CClass::IsEqualsOrSubClass( const CClass *pSubClass ) const { if( IsEquals( pSubClass ) ) return true; return IsSubClass( pSubClass ); } // 自身と等しいまたは派生クラス、基底クラスかどうかを確認 bool CClass::IsEqualsOrSubClassOrSuperClass( const CClass &objClass ) const { if( IsEquals( &objClass ) ) return true; if( IsSubClass( &objClass ) ) return true; if( objClass.IsSubClass( this ) ) return true; return false; } bool CClass::IsInheritsInterface( const CClass *pInterfaceClass ) const { BOOST_FOREACH( const ::Interface *pInterface, interfaces ){ if( pInterfaceClass == &pInterface->GetClass() ){ return true; } } return false; } bool CClass::InheritsClass( const CClass &inheritsClass, const Types &actualTypeParameters, int nowLine ) { //メソッドをコピー BOOST_FOREACH( const CMethod *pBaseMethod, inheritsClass.GetDynamicMethods() ){ CMethod *pMethod = new DynamicMethod( *pBaseMethod ); // アクセシビリティ if(pBaseMethod->GetAccessibility() == Prototype::Private){ pMethod->SetAccessibility( Prototype::None ); } else{ pMethod->SetAccessibility( pBaseMethod->GetAccessibility() ); } //pobj_Inherits // ※継承元のClassIndexをセット(入れ子継承を考慮する) if(pBaseMethod->GetInheritsClassPtr()==0){ pMethod->SetInheritsClassPtr( &inheritsClass ); } else{ pMethod->SetInheritsClassPtr( pBaseMethod->GetInheritsClassPtr() ); } GetDynamicMethods().push_back( pMethod ); } //仮想関数の数 AddVtblNum( inheritsClass.GetVtblNum() ); //継承先のクラスをメンバとして保持する SetSuperClass( &inheritsClass ); SetSuperClassActualTypeParameters( actualTypeParameters ); // インターフェイスを引き継ぐ BOOST_FOREACH( ::Interface *pInterface, inheritsClass.GetInterfaces() ) { interfaces.push_back( new ::Interface( *pInterface ) ); } if( this->IsInterface() && inheritsClass.IsComInterface() ) { // COMインターフェイスを継承した場合はCOMインターフェイスにする this->SetClassType( CClass::ComInterface ); } return true; } void CClass::AddDynamicMember( Member *pMember ) { dynamicMembers.push_back( pMember ); } void CClass::AddStaticMember( Member *pMember ) { staticMembers.push_back( pMember ); } bool CClass::DupliCheckAll(const char *name) const { //重複チェック //メンバ if(DupliCheckMember(name)) return 1; //メソッド BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){ if( lstrcmp( name, pMethod->GetUserProc().GetName().c_str() ) == 0 ){ return 1; } } return 0; } bool CClass::DupliCheckMember(const char *name) const { //重複チェック if( this->HasSuperClass() ) { if( this->GetSuperClass().DupliCheckMember( name ) ) { // 基底クラスで重複が発見された return true; } } // 動的メンバ BOOST_FOREACH( Member *pMember, dynamicMembers ) { if( GetName() == pMember->GetName() ) { return true; } } // 静的メンバ BOOST_FOREACH( Member *pMember, staticMembers ){ if( GetName() == pMember->GetName() ){ return true; } } return false; } const Member *CClass::FindDynamicMember( const char *memberName ) const { if( this->HasSuperClass() ) { // 基底クラスで検索 const Member *result = this->GetSuperClass().FindDynamicMember( memberName ); if( result ) { return result; } } BOOST_FOREACH( Member *pMember, GetDynamicMembers() ) { if( pMember->GetName() == memberName ) { return pMember; } } return NULL; } void CClass::EnumDynamicMethodsOrInterfaceMethods( const char *methodName, std::vector &subs ) const { // 動的メソッド GetDynamicMethods().Enum( methodName, subs ); // インターフェイス メソッド BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() ) { pInterface->GetDynamicMethods().Enum( methodName, subs ); } } const CMethod *CClass::GetDynamicMethodOrInterfaceMethod( const UserProc *pUserProc ) const { // 動的メソッド const CMethod *result = GetDynamicMethods().GetMethodPtr( pUserProc ); if( !result ) { // インターフェイス メソッド BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() ) { result = pInterface->GetDynamicMethods().GetMethodPtr( pUserProc ); if( result ) { return result; } } } return result; } //サイズを取得 int CClass::GetSize() const { int resultSize = 0; int alignment = 1; if( this->IsStructure() ) { // 構造体のとき if( this->GetFixedAlignment() ) { // アラインメントの固定値が指定されていた場合はそれを取得 alignment = this->GetFixedAlignment(); } } else { // それ以外 if( this->HasSuperClass() ) { // 基底クラスのサイズを追加 resultSize += this->GetSuperClass().GetSize(); // 基底クラスのアラインメントを取得 alignment = this->GetSuperClass().GetAlignment(); } else { // 基底クラスが存在しないとき // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0; } } BOOST_FOREACH( Member *pMember, dynamicMembers ) { // メンバサイズ int tempMemberSize = pMember->GetType().GetSize(); // 一時アラインメントを算出 int tempAlignment = tempMemberSize; if( pMember->GetType().IsStruct() ) { // メンバが構造体の場合は、メンバのアラインメントを取得 tempAlignment = pMember->GetType().GetClass().GetAlignment(); } // アラインメントを考慮してパディングを追加 if( GetFixedAlignment() && alignment < tempAlignment ) { if( resultSize % alignment ) { resultSize += alignment - ( resultSize % alignment ); } } else { if( alignment < tempAlignment ) { // 最大アラインメントを更新 alignment = tempAlignment; } if( tempMemberSize == 0 ) { if( !pMember->GetType().IsStruct() ) { throw; } //メンバを持たない構造体 //※何もしない(オフセットの計算をしない) } else{ if( resultSize % tempAlignment ) { resultSize += tempAlignment - ( resultSize % tempAlignment ); } } } // メンバサイズを加算(配列を考慮) resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() ); } if( alignment ) { // 末尾アラインメントを考慮してパディングを追加 if( resultSize % alignment ) { resultSize += alignment - ( resultSize % alignment ); } } return resultSize; } //メンバのオフセットを取得 int CClass::GetMemberOffset( const char *memberName ) const { int resultSize = 0; int alignment = 1; if( this->IsStructure() ) { // 構造体のとき if( this->GetFixedAlignment() ) { // アラインメントの固定値が指定されていた場合はそれを取得 alignment = this->GetFixedAlignment(); } } else { // それ以外 if( this->HasSuperClass() ) { if( this->GetSuperClass().HasDynamicMember( memberName ) ) { // 基底クラスのメンバを取得 return this->GetSuperClass().GetMemberOffset( memberName ); } // 基底クラスのサイズを追加 resultSize += this->GetSuperClass().GetSize(); // 基底クラスのアラインメントを取得 alignment = this->GetSuperClass().GetAlignment(); } else { // 基底クラスが存在しないとき // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0; } } BOOST_FOREACH( Member *pMember, dynamicMembers ) { // メンバサイズ int tempMemberSize = pMember->GetType().GetSize(); // 一時アラインメントを算出 int tempAlignment = tempMemberSize; if( pMember->GetType().IsStruct() ) { // メンバが構造体の場合は、メンバのアラインメントを取得 tempAlignment = pMember->GetType().GetClass().GetAlignment(); } // アラインメントを考慮してパディングを追加 if( GetFixedAlignment() && alignment < tempAlignment ) { if( resultSize % alignment ) { resultSize += alignment - ( resultSize % alignment ); } } else { if( alignment < tempAlignment ) { // 最大アラインメントを更新 alignment = tempAlignment; } if( tempMemberSize == 0 ) { if( !pMember->GetType().IsStruct() ) { throw; } //メンバを持たない構造体 //※何もしない(オフセットの計算をしない) } else{ if( resultSize % tempAlignment ) { resultSize += tempAlignment - ( resultSize % tempAlignment ); } } } if(memberName){ //メンバ指定がある場合は、オフセットを返す if( pMember->GetName() == memberName ) { return resultSize; } } // メンバサイズを加算(配列を考慮) resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() ); } if( alignment ) { // 末尾アラインメントを考慮してパディングを追加 if( resultSize % alignment ) { resultSize += alignment - ( resultSize % alignment ); } } return resultSize; } int CClass::GetAlignment() const { int alignment = 1; if( this->IsStructure() ) { // 構造体のとき if( this->GetFixedAlignment() ) { // アラインメントの固定値が指定されていた場合はそれを取得 return this->GetFixedAlignment(); } } else { // それ以外 if( this->HasSuperClass() ) { // 基底クラスのアラインメントを取得 alignment = this->GetSuperClass().GetAlignment(); } else { // 基底クラスが存在しないとき // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加 alignment = PTR_SIZE; } } BOOST_FOREACH( Member *pMember, dynamicMembers ) { int tempAlignment = pMember->GetType().GetSize(); if( pMember->GetType().IsStruct() ) { // メンバが構造体の場合は、メンバのアラインメントを取得 tempAlignment = pMember->GetType().GetClass().GetAlignment(); } if( alignment < tempAlignment ) { // 最大アラインメントを更新 alignment = tempAlignment; } } return alignment; } void CClass::GetVtblMasterListIndexAndVtblIndex( const UserProc *pUserProc, int &vtblMasterListIndex, int &vtblIndex ) const { vtblMasterListIndex = 0; vtblIndex = 0; BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){ if( &pMethod->GetUserProc() == pUserProc ) { return; } if( pMethod->IsVirtual() ) { vtblIndex++; } } BOOST_FOREACH( const ::Interface *pInterface, interfaces ) { vtblMasterListIndex++; vtblIndex = 0; BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){ if( &pMethod->GetUserProc() == pUserProc ) { return; } if( pMethod->IsVirtual() ) { vtblIndex++; } } } _ASSERT( false ); throw; } int CClass::GetVtblMasterListIndex( const CClass *pClass ) const { int result = 0; BOOST_FOREACH( const ::Interface *pInterface, interfaces ) { result++; if( &pInterface->GetClass() == pClass ) { return result; } } _ASSERT( false ); throw; } long CClass::GetVtblMasterListOffset() const { if( vtblMasterListOffset == -1 ) { _ASSERT( false ); throw; } return vtblMasterListOffset; } bool CClass::IsAbstract() const { // 未実装(abstract)の仮想関数を持つ場合はtrueを返す BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){ if(pMethod->IsVirtual()){ if(pMethod->IsAbstract()){ return true; } } } // インターフェイスのvtbl BOOST_FOREACH( const ::Interface *pInterface, interfaces ) { BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){ if(pMethod->IsVirtual()){ if(pMethod->IsAbstract()){ return true; } } } } return false; } const CClass *Classes::FindEx( const Symbol &symbol ) const { if( symbol.GetNamespaceScopes().size() == 0 && symbol.GetName() == "Object" ) { return GetObjectClassPtr(); } else if( symbol.GetNamespaceScopes().size() == 0 && symbol.GetName() == "String" ) { return GetStringClassPtr(); } std::vector classes; const CClass *pClass = GetHashArrayElement( symbol.GetName().c_str() ); while( pClass ) { if( pClass->IsEqualSymbol( symbol.GetNamespaceScopes(), symbol.GetName() ) ){ //名前空間とクラス名が一致した classes.push_back( pClass ); } pClass = pClass->GetChainNext(); } if( classes.size() > 0 ) { // 複数の名前空間の中に同一のクラス名が存在する場合があるので、アクセス可能で尚且つ階層が一番深いものをチョイスする pClass = classes.front(); BOOST_FOREACH( const CClass *pTempClass, classes ) { if( pClass->GetNamespaceScopes().size() < pTempClass->GetNamespaceScopes().size() ) { pClass = pTempClass; } } return pClass; } return NULL; } const CClass *Classes::GetStringClassPtr() const { if( !pStringClass ) { // キャッシュしておく pStringClass = this->FindEx( Symbol( NamespaceScopes( "System" ), "String" ) ); } return pStringClass; } const CClass *Classes::GetObjectClassPtr() const { if( !pObjectClass ) { // キャッシュしておく pObjectClass = this->FindEx( Symbol( NamespaceScopes( "System" ), "Object" ) ); } return pObjectClass; } const CClass *Classes::GetInterfaceInfoClassPtr() const { if( !pInterfaceInfo ) { // キャッシュしておく pInterfaceInfo = this->FindEx( Symbol( NamespaceScopes( "ActiveBasic.Core" ), "InterfaceInfo" ) ); } return pInterfaceInfo; } std::string CClass::GetStaticDefiningStringAsMemberNames() const { std::string result; BOOST_FOREACH( const Member *pMember, dynamicMembers ) { if( result.size() ) { result += ","; } result += "\"" + pMember->GetName() + "\""; } return result; } std::string CClass::GetStaticDefiningStringAsMemberOffsets() const { std::string result; BOOST_FOREACH( const Member *pMember, dynamicMembers ) { if( result.size() ) { result += ","; } int offset = this->GetMemberOffset( pMember->GetName().c_str() ); char temporary[255]; itoa( offset, temporary, 16 ); result += (std::string)"&H" + temporary; } return result; } void CClass::GetReferenceOffsetsInitializeBuffer( std::string &referenceOffsetsBuffer, int &numOfReference, int baseOffset ) const { const CClass &thisClass = *this; BOOST_FOREACH( const Member *pMember, thisClass.GetDynamicMembers() ) { if( pMember->GetType().IsObject() || pMember->GetType().IsPointer() ) { if( referenceOffsetsBuffer.size() ) { referenceOffsetsBuffer += ","; } char temp[255]; sprintf( temp, "%d", baseOffset + thisClass.GetMemberOffset( pMember->GetName().c_str() ) ); referenceOffsetsBuffer += temp; numOfReference++; } if( pMember->GetType().IsStruct() && !pMember->GetType().IsPointer() ) { // 構造体の実体をメンバに持つとき int baseOffset = thisClass.GetMemberOffset( pMember->GetName().c_str() ); // 構造体メンバでGCによるチェックが必要な参照位置を追加 pMember->GetType().GetClass().GetReferenceOffsetsInitializeBuffer( referenceOffsetsBuffer, numOfReference, baseOffset ); } } }