source: dev/trunk/ab5.0/abdev/ab_common/src/Lexical/Class.cpp@ 603

Last change on this file since 603 was 603, checked in by dai_9181, 16 years ago

ObjectModuleに関連するクラス一式をab_commonプロジェクトに移動した。

File size: 16.8 KB
RevLine 
[206]1#include "stdafx.h"
2
[540]3void CClass::Using() const
4{
5 if( this->IsUsing() )
6 {
7 // 既に使用することになっている
8 return;
9 }
[511]10
[540]11 Prototype::Using();
12
13 // 仮想関数になるメソッドに使用チェックをつける
14 const CClass &objThis = *this;
15 BOOST_FOREACH( const CMethod *pMethod, objThis.GetDynamicMethods() )
16 {
17 if( pMethod->IsVirtual() )
18 {
19 pMethod->GetUserProc().Using();
20 }
21 }
22}
23
[206]24bool CClass::IsClass() const
[193]25{
[206]26 return classType == CClass::Class;
27}
28bool CClass::IsInterface() const
29{
30 return classType == CClass::Interface;
31}
[370]32bool CClass::IsComInterface() const
33{
34 return classType == CClass::ComInterface;
35}
[206]36bool CClass::IsEnum() const
37{
38 return classType == CClass::Enum;
39}
40bool CClass::IsDelegate() const
41{
42 return classType == CClass::Delegate;
43}
44bool CClass::IsStructure() const
45{
46 return classType == CClass::Structure;
47}
48
49
50// コンストラクタのコンパイルを開始
51void CClass::NotifyStartConstructorCompile() const
52{
53 isCompilingConstructor = true;
54}
55
56//コンストラクタのコンパイルを終了
57void CClass::NotifyFinishConstructorCompile() const
58{
59 isCompilingConstructor = false;
60}
61
62//コンストラクタをコンパイル中かどうかを判別
63bool CClass::IsCompilingConstructor() const
64{
65 return isCompilingConstructor;
66}
67
68//デストラクタのコンパイルを開始
69void CClass::NotifyStartDestructorCompile() const{
70 isCompilingDestructor = true;
71}
72
73//デストラクタのコンパイルを終了
74void CClass::NotifyFinishDestructorCompile() const{
75 isCompilingDestructor = false;
76}
77
78//デストラクタをコンパイル中かどうかを判別
79bool CClass::IsCompilingDestructor() const
80{
81 return isCompilingDestructor;
82}
83
84//自身の派生クラスかどうかを確認
[447]85bool CClass::IsSubClass( const CClass *pSubClass ) const
[206]86{
[447]87 if( !pSubClass->HasSuperClass() )
[206]88 {
[193]89 return false;
90 }
91
[447]92 const CClass *pTempClass = &pSubClass->GetSuperClass();
[206]93 while( pTempClass ){
94 if( this == pTempClass ) return true;
95 pTempClass = &pTempClass->GetSuperClass();
96 }
97 return false;
[193]98}
99
[206]100//自身と等しいまたは派生クラスかどうかを確認
[447]101bool CClass::IsEqualsOrSubClass( const CClass *pSubClass ) const
[206]102{
[447]103 if( IsEquals( pSubClass ) ) return true;
104 return IsSubClass( pSubClass );
[206]105}
106
107// 自身と等しいまたは派生クラス、基底クラスかどうかを確認
108bool CClass::IsEqualsOrSubClassOrSuperClass( const CClass &objClass ) const
109{
110 if( IsEquals( &objClass ) ) return true;
111 if( IsSubClass( &objClass ) ) return true;
112 if( objClass.IsSubClass( this ) ) return true;
113 return false;
114}
115
116bool CClass::IsInheritsInterface( const CClass *pInterfaceClass ) const
117{
[346]118 BOOST_FOREACH( const ::Interface *pInterface, interfaces ){
119 if( pInterfaceClass == &pInterface->GetClass() ){
[206]120 return true;
121 }
122 }
123 return false;
124}
125
[376]126bool CClass::InheritsClass( const CClass &inheritsClass, const Types &actualTypeParameters, int nowLine )
127{
[184]128 //メソッドをコピー
[342]129 BOOST_FOREACH( const CMethod *pBaseMethod, inheritsClass.GetDynamicMethods() ){
[184]130 CMethod *pMethod = new DynamicMethod( *pBaseMethod );
131
132 // アクセシビリティ
133 if(pBaseMethod->GetAccessibility() == Prototype::Private){
134 pMethod->SetAccessibility( Prototype::None );
135 }
136 else{
137 pMethod->SetAccessibility( pBaseMethod->GetAccessibility() );
138 }
139
140 //pobj_Inherits
141 // ※継承元のClassIndexをセット(入れ子継承を考慮する)
142 if(pBaseMethod->GetInheritsClassPtr()==0){
143 pMethod->SetInheritsClassPtr( &inheritsClass );
144 }
145 else{
146 pMethod->SetInheritsClassPtr( pBaseMethod->GetInheritsClassPtr() );
147 }
148
[342]149 GetDynamicMethods().push_back( pMethod );
[184]150 }
151
152 //仮想関数の数
153 AddVtblNum( inheritsClass.GetVtblNum() );
154
155 //継承先のクラスをメンバとして保持する
[204]156 SetSuperClass( &inheritsClass );
[299]157 SetSuperClassActualTypeParameters( actualTypeParameters );
[184]158
[351]159 // インターフェイスを引き継ぐ
160 BOOST_FOREACH( ::Interface *pInterface, inheritsClass.GetInterfaces() )
161 {
162 interfaces.push_back( new ::Interface( *pInterface ) );
163 }
164
[370]165 if( this->IsInterface() && inheritsClass.IsComInterface() )
166 {
167 // COMインターフェイスを継承した場合はCOMインターフェイスにする
168 this->SetClassType( CClass::ComInterface );
[184]169 }
170
171 return true;
172}
[340]173
[561]174void CClass::AddDynamicMember( Member *pMember )
[184]175{
[561]176 dynamicMembers.push_back( pMember );
[184]177}
[561]178void CClass::AddStaticMember( Member *pMember )
179{
180 staticMembers.push_back( pMember );
[184]181}
182
[409]183bool CClass::DupliCheckAll(const char *name) const
184{
[206]185 //重複チェック
186
187 //メンバ
188 if(DupliCheckMember(name)) return 1;
189
190 //メソッド
[342]191 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
[206]192 if( lstrcmp( name, pMethod->GetUserProc().GetName().c_str() ) == 0 ){
193 return 1;
194 }
195 }
196
197 return 0;
198}
[409]199bool CClass::DupliCheckMember(const char *name) const
200{
[206]201 //重複チェック
202
[409]203 if( this->HasSuperClass() )
204 {
205 if( this->GetSuperClass().DupliCheckMember( name ) )
206 {
207 // 基底クラスで重複が発見された
208 return true;
209 }
210 }
211
[206]212 // 動的メンバ
[561]213 BOOST_FOREACH( Member *pMember, dynamicMembers )
[409]214 {
215 if( GetName() == pMember->GetName() )
216 {
217 return true;
[206]218 }
219 }
220
221 // 静的メンバ
[561]222 BOOST_FOREACH( Member *pMember, staticMembers ){
[206]223 if( GetName() == pMember->GetName() ){
[409]224 return true;
[206]225 }
226 }
227
[409]228 return false;
[206]229}
230
[561]231const Member *CClass::FindDynamicMember( const char *memberName ) const
[409]232{
233 if( this->HasSuperClass() )
234 {
235 // 基底クラスで検索
[561]236 const Member *result = this->GetSuperClass().FindDynamicMember( memberName );
[409]237 if( result )
238 {
239 return result;
240 }
241 }
242
[561]243 BOOST_FOREACH( Member *pMember, GetDynamicMembers() )
[409]244 {
245 if( pMember->GetName() == memberName )
246 {
247 return pMember;
248 }
249 }
250 return NULL;
251}
252
[350]253void CClass::EnumDynamicMethodsOrInterfaceMethods( const char *methodName, std::vector<const UserProc *> &subs ) const
[347]254{
255 // 動的メソッド
256 GetDynamicMethods().Enum( methodName, subs );
257
258 // インターフェイス メソッド
259 BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() )
260 {
261 pInterface->GetDynamicMethods().Enum( methodName, subs );
262 }
263}
[350]264const CMethod *CClass::GetDynamicMethodOrInterfaceMethod( const UserProc *pUserProc ) const
[347]265{
266 // 動的メソッド
267 const CMethod *result = GetDynamicMethods().GetMethodPtr( pUserProc );
268
269 if( !result )
270 {
271 // インターフェイス メソッド
272 BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() )
273 {
274 result = pInterface->GetDynamicMethods().GetMethodPtr( pUserProc );
[350]275 if( result )
276 {
277 return result;
278 }
[347]279 }
280 }
281
282 return result;
283}
284
[206]285//サイズを取得
286int CClass::GetSize() const
[184]287{
[409]288 int resultSize = 0;
289
290 int alignment = 1;
291 if( this->IsStructure() )
292 {
293 // 構造体のとき
294
295 if( this->GetFixedAlignment() )
296 {
297 // アラインメントの固定値が指定されていた場合はそれを取得
298 alignment = this->GetFixedAlignment();
299 }
300 }
301 else
302 {
303 // それ以外
304
305 if( this->HasSuperClass() )
306 {
307 // 基底クラスのサイズを追加
308 resultSize += this->GetSuperClass().GetSize();
309
310 // 基底クラスのアラインメントを取得
311 alignment = this->GetSuperClass().GetAlignment();
312 }
313 else
314 {
315 // 基底クラスが存在しないとき
316
317 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
318 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0;
319 }
320 }
321
[561]322 BOOST_FOREACH( Member *pMember, dynamicMembers )
[409]323 {
324 // メンバサイズ
325 int tempMemberSize = pMember->GetType().GetSize();
326
327 // 一時アラインメントを算出
328 int tempAlignment = tempMemberSize;
329 if( pMember->GetType().IsStruct() )
330 {
331 // メンバが構造体の場合は、メンバのアラインメントを取得
332 tempAlignment = pMember->GetType().GetClass().GetAlignment();
333 }
334
335 // アラインメントを考慮してパディングを追加
336 if( GetFixedAlignment() && alignment < tempAlignment )
337 {
338 if( resultSize % alignment )
339 {
340 resultSize += alignment - ( resultSize % alignment );
341 }
342 }
343 else
344 {
345 if( alignment < tempAlignment )
346 {
347 // 最大アラインメントを更新
348 alignment = tempAlignment;
349 }
350
351 if( tempMemberSize == 0 )
352 {
353 if( !pMember->GetType().IsStruct() )
354 {
[563]355 throw;
[409]356 }
357
358 //メンバを持たない構造体
359 //※何もしない(オフセットの計算をしない)
360 }
361 else{
362 if( resultSize % tempAlignment )
363 {
364 resultSize += tempAlignment - ( resultSize % tempAlignment );
365 }
366 }
367 }
368
369 // メンバサイズを加算(配列を考慮)
370 resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() );
371 }
372
373 if( alignment )
374 {
375 // 末尾アラインメントを考慮してパディングを追加
376 if( resultSize % alignment )
377 {
378 resultSize += alignment - ( resultSize % alignment );
379 }
380 }
381
382 return resultSize;
[206]383}
[184]384
[206]385//メンバのオフセットを取得
[409]386int CClass::GetMemberOffset( const char *memberName ) const
[206]387{
[409]388 int resultSize = 0;
[206]389
[232]390 int alignment = 1;
[409]391 if( this->IsStructure() )
[232]392 {
[409]393 // 構造体のとき
394
395 if( this->GetFixedAlignment() )
396 {
397 // アラインメントの固定値が指定されていた場合はそれを取得
398 alignment = this->GetFixedAlignment();
399 }
[232]400 }
[409]401 else
402 {
403 // それ以外
[206]404
[409]405 if( this->HasSuperClass() )
406 {
407 if( this->GetSuperClass().HasDynamicMember( memberName ) )
408 {
409 // 基底クラスのメンバを取得
410 return this->GetSuperClass().GetMemberOffset( memberName );
411 }
[206]412
[409]413 // 基底クラスのサイズを追加
414 resultSize += this->GetSuperClass().GetSize();
[206]415
[409]416 // 基底クラスのアラインメントを取得
417 alignment = this->GetSuperClass().GetAlignment();
[206]418 }
[409]419 else
420 {
421 // 基底クラスが存在しないとき
422
423 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
424 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0;
[206]425 }
[409]426 }
[206]427
[561]428 BOOST_FOREACH( Member *pMember, dynamicMembers )
[409]429 {
430 // メンバサイズ
431 int tempMemberSize = pMember->GetType().GetSize();
432
433 // 一時アラインメントを算出
434 int tempAlignment = tempMemberSize;
435 if( pMember->GetType().IsStruct() )
436 {
437 // メンバが構造体の場合は、メンバのアラインメントを取得
438 tempAlignment = pMember->GetType().GetClass().GetAlignment();
[206]439 }
440
[409]441 // アラインメントを考慮してパディングを追加
442 if( GetFixedAlignment() && alignment < tempAlignment )
443 {
444 if( resultSize % alignment )
445 {
446 resultSize += alignment - ( resultSize % alignment );
447 }
448 }
449 else
450 {
451 if( alignment < tempAlignment )
452 {
453 // 最大アラインメントを更新
454 alignment = tempAlignment;
455 }
456
457 if( tempMemberSize == 0 )
458 {
459 if( !pMember->GetType().IsStruct() )
460 {
[563]461 throw;
[409]462 }
463
464 //メンバを持たない構造体
[206]465 //※何もしない(オフセットの計算をしない)
466 }
467 else{
[409]468 if( resultSize % tempAlignment )
469 {
470 resultSize += tempAlignment - ( resultSize % tempAlignment );
471 }
[206]472 }
473 }
474
475 if(memberName){
476 //メンバ指定がある場合は、オフセットを返す
[409]477 if( pMember->GetName() == memberName )
478 {
479 return resultSize;
[206]480 }
481 }
482
[409]483 // メンバサイズを加算(配列を考慮)
484 resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() );
[206]485 }
486
[409]487 if( alignment )
488 {
489 // 末尾アラインメントを考慮してパディングを追加
490 if( resultSize % alignment )
491 {
492 resultSize += alignment - ( resultSize % alignment );
493 }
[206]494 }
495
[409]496 return resultSize;
[206]497}
498int CClass::GetAlignment() const
499{
[409]500 int alignment = 1;
501 if( this->IsStructure() )
502 {
503 // 構造体のとき
[206]504
[409]505 if( this->GetFixedAlignment() )
506 {
507 // アラインメントの固定値が指定されていた場合はそれを取得
508 return this->GetFixedAlignment();
[206]509 }
[409]510 }
511 else
512 {
513 // それ以外
514
515 if( this->HasSuperClass() )
516 {
517 // 基底クラスのアラインメントを取得
518 alignment = this->GetSuperClass().GetAlignment();
[206]519 }
[409]520 else
521 {
522 // 基底クラスが存在しないとき
[206]523
[409]524 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
525 alignment = PTR_SIZE;
526 }
[206]527 }
528
[561]529 BOOST_FOREACH( Member *pMember, dynamicMembers )
[409]530 {
531 int tempAlignment = pMember->GetType().GetSize();
532 if( pMember->GetType().IsStruct() )
533 {
534 // メンバが構造体の場合は、メンバのアラインメントを取得
535 tempAlignment = pMember->GetType().GetClass().GetAlignment();
536 }
[206]537
[409]538 if( alignment < tempAlignment )
539 {
540 // 最大アラインメントを更新
541 alignment = tempAlignment;
542 }
543 }
[206]544
545 return alignment;
546}
[342]547
[348]548void CClass::GetVtblMasterListIndexAndVtblIndex( const UserProc *pUserProc, int &vtblMasterListIndex, int &vtblIndex ) const
[342]549{
[348]550 vtblMasterListIndex = 0;
551
552 vtblIndex = 0;
[342]553 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
554 if( &pMethod->GetUserProc() == pUserProc )
555 {
[348]556 return;
[342]557 }
[348]558
559 if( pMethod->IsVirtual() )
560 {
561 vtblIndex++;
562 }
[342]563 }
564
[346]565 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
[342]566 {
[348]567 vtblMasterListIndex++;
[342]568
[348]569 vtblIndex = 0;
[347]570 BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){
[342]571 if( &pMethod->GetUserProc() == pUserProc )
572 {
[348]573 return;
[342]574 }
[348]575
576 if( pMethod->IsVirtual() )
577 {
578 vtblIndex++;
579 }
[342]580 }
581 }
582
[563]583 throw;
[342]584}
[350]585int CClass::GetVtblMasterListIndex( const CClass *pClass ) const
586{
587 int result = 0;
588
589 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
590 {
591 result++;
592
593 if( &pInterface->GetClass() == pClass )
594 {
595 return result;
596 }
597 }
598
[563]599 throw;
[350]600}
[345]601long CClass::GetVtblMasterListOffset() const
[206]602{
[342]603 if( vtblMasterListOffset == -1 )
604 {
[563]605 throw;
[342]606 }
[184]607
[342]608 return vtblMasterListOffset;
609}
[206]610bool CClass::IsAbstract() const
611{
612 // 未実装(abstract)の仮想関数を持つ場合はtrueを返す
[184]613
[342]614 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
[206]615 if(pMethod->IsVirtual()){
616 if(pMethod->IsAbstract()){
617 return true;
618 }
619 }
620 }
621
[351]622 // インターフェイスのvtbl
623 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
624 {
625 BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){
626 if(pMethod->IsVirtual()){
627 if(pMethod->IsAbstract()){
628 return true;
629 }
630 }
631 }
632 }
633
[206]634 return false;
[184]635}
636
[598]637const CClass *Classes::FindEx( const Symbol &symbol ) const
[193]638{
[598]639 if( symbol.GetNamespaceScopes().size() == 0 && symbol.GetName() == "Object" )
[566]640 {
[193]641 return GetObjectClassPtr();
642 }
[598]643 else if( symbol.GetNamespaceScopes().size() == 0 && symbol.GetName() == "String" )
[566]644 {
[193]645 return GetStringClassPtr();
646 }
647
[380]648 std::vector<const CClass *> classes;
[598]649 const CClass *pClass = GetHashArrayElement( symbol.GetName().c_str() );
[270]650 while( pClass )
651 {
[598]652 if( pClass->IsEqualSymbol( symbol.GetNamespaceScopes(), symbol.GetName() ) ){
[270]653 //名前空間とクラス名が一致した
[380]654 classes.push_back( pClass );
[193]655 }
[270]656 pClass = pClass->GetChainNext();
[193]657 }
[380]658 if( classes.size() > 0 )
659 {
660 // 複数の名前空間の中に同一のクラス名が存在する場合があるので、アクセス可能で尚且つ階層が一番深いものをチョイスする
661 pClass = classes.front();
[193]662
[380]663 BOOST_FOREACH( const CClass *pTempClass, classes )
664 {
665 if( pClass->GetNamespaceScopes().size() < pTempClass->GetNamespaceScopes().size() )
666 {
667 pClass = pTempClass;
668 }
669 }
670
671 return pClass;
672 }
673
[193]674 return NULL;
675}
[206]676
[272]677const CClass *Classes::GetStringClassPtr() const
[206]678{
[567]679 if( !pStringClass )
680 {
[272]681 // キャッシュしておく
[598]682 pStringClass = this->FindEx( Symbol( NamespaceScopes( "System" ), "String" ) );
[206]683 }
684 return pStringClass;
685}
[272]686const CClass *Classes::GetObjectClassPtr() const
[206]687{
[567]688 if( !pObjectClass )
689 {
[272]690 // キャッシュしておく
[598]691 pObjectClass = this->FindEx( Symbol( NamespaceScopes( "System" ), "Object" ) );
[206]692 }
693 return pObjectClass;
694}
[349]695const CClass *Classes::GetInterfaceInfoClassPtr() const
696{
[567]697 if( !pInterfaceInfo )
698 {
[349]699 // キャッシュしておく
[598]700 pInterfaceInfo = this->FindEx( Symbol( NamespaceScopes( "ActiveBasic.Core" ), "InterfaceInfo" ) );
[349]701 }
702 return pInterfaceInfo;
703}
[387]704
705std::string CClass::GetStaticDefiningStringAsMemberNames() const
706{
707 std::string result;
708
[561]709 BOOST_FOREACH( const Member *pMember, dynamicMembers )
[387]710 {
711 if( result.size() )
712 {
713 result += ",";
714 }
715
716 result += "\"" + pMember->GetName() + "\"";
717 }
718
719 return result;
720}
[412]721std::string CClass::GetStaticDefiningStringAsMemberOffsets() const
722{
723 std::string result;
[387]724
[561]725 BOOST_FOREACH( const Member *pMember, dynamicMembers )
[412]726 {
727 if( result.size() )
728 {
729 result += ",";
730 }
731
732 int offset = this->GetMemberOffset( pMember->GetName().c_str() );
733
734 char temporary[255];
735 itoa( offset, temporary, 16 );
736
737 result += (std::string)"&H" + temporary;
738 }
739
740 return result;
741}
[417]742
743void CClass::GetReferenceOffsetsInitializeBuffer( std::string &referenceOffsetsBuffer, int &numOfReference, int baseOffset ) const
744{
745 const CClass &thisClass = *this;
[561]746 BOOST_FOREACH( const Member *pMember, thisClass.GetDynamicMembers() )
[417]747 {
748 if( pMember->GetType().IsObject() || pMember->GetType().IsPointer() )
749 {
750 if( referenceOffsetsBuffer.size() )
751 {
752 referenceOffsetsBuffer += ",";
753 }
754
755 char temp[255];
756 sprintf( temp, "%d", baseOffset + thisClass.GetMemberOffset( pMember->GetName().c_str() ) );
757 referenceOffsetsBuffer += temp;
758
759 numOfReference++;
760 }
761 if( pMember->GetType().IsStruct() && !pMember->GetType().IsPointer() )
762 {
763 // 構造体の実体をメンバに持つとき
764 int baseOffset = thisClass.GetMemberOffset( pMember->GetName().c_str() );
765
766 // 構造体メンバでGCによるチェックが必要な参照位置を追加
767 pMember->GetType().GetClass().GetReferenceOffsetsInitializeBuffer( referenceOffsetsBuffer, numOfReference, baseOffset );
768 }
769 }
770}
Note: See TracBrowser for help on using the repository browser.