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

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

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

File size: 16.8 KB
Line 
1#include "stdafx.h"
2
3void CClass::Using() const
4{
5 if( this->IsUsing() )
6 {
7 // 既に使用することになっている
8 return;
9 }
10
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
24bool CClass::IsClass() const
25{
26 return classType == CClass::Class;
27}
28bool CClass::IsInterface() const
29{
30 return classType == CClass::Interface;
31}
32bool CClass::IsComInterface() const
33{
34 return classType == CClass::ComInterface;
35}
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//自身の派生クラスかどうかを確認
85bool CClass::IsSubClass( const CClass *pSubClass ) const
86{
87 if( !pSubClass->HasSuperClass() )
88 {
89 return false;
90 }
91
92 const CClass *pTempClass = &pSubClass->GetSuperClass();
93 while( pTempClass ){
94 if( this == pTempClass ) return true;
95 pTempClass = &pTempClass->GetSuperClass();
96 }
97 return false;
98}
99
100//自身と等しいまたは派生クラスかどうかを確認
101bool CClass::IsEqualsOrSubClass( const CClass *pSubClass ) const
102{
103 if( IsEquals( pSubClass ) ) return true;
104 return IsSubClass( pSubClass );
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{
118 BOOST_FOREACH( const ::Interface *pInterface, interfaces ){
119 if( pInterfaceClass == &pInterface->GetClass() ){
120 return true;
121 }
122 }
123 return false;
124}
125
126bool CClass::InheritsClass( const CClass &inheritsClass, const Types &actualTypeParameters, int nowLine )
127{
128 //メソッドをコピー
129 BOOST_FOREACH( const CMethod *pBaseMethod, inheritsClass.GetDynamicMethods() ){
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
149 GetDynamicMethods().push_back( pMethod );
150 }
151
152 //仮想関数の数
153 AddVtblNum( inheritsClass.GetVtblNum() );
154
155 //継承先のクラスをメンバとして保持する
156 SetSuperClass( &inheritsClass );
157 SetSuperClassActualTypeParameters( actualTypeParameters );
158
159 // インターフェイスを引き継ぐ
160 BOOST_FOREACH( ::Interface *pInterface, inheritsClass.GetInterfaces() )
161 {
162 interfaces.push_back( new ::Interface( *pInterface ) );
163 }
164
165 if( this->IsInterface() && inheritsClass.IsComInterface() )
166 {
167 // COMインターフェイスを継承した場合はCOMインターフェイスにする
168 this->SetClassType( CClass::ComInterface );
169 }
170
171 return true;
172}
173
174void CClass::AddDynamicMember( Member *pMember )
175{
176 dynamicMembers.push_back( pMember );
177}
178void CClass::AddStaticMember( Member *pMember )
179{
180 staticMembers.push_back( pMember );
181}
182
183bool CClass::DupliCheckAll(const char *name) const
184{
185 //重複チェック
186
187 //メンバ
188 if(DupliCheckMember(name)) return 1;
189
190 //メソッド
191 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
192 if( lstrcmp( name, pMethod->GetUserProc().GetName().c_str() ) == 0 ){
193 return 1;
194 }
195 }
196
197 return 0;
198}
199bool CClass::DupliCheckMember(const char *name) const
200{
201 //重複チェック
202
203 if( this->HasSuperClass() )
204 {
205 if( this->GetSuperClass().DupliCheckMember( name ) )
206 {
207 // 基底クラスで重複が発見された
208 return true;
209 }
210 }
211
212 // 動的メンバ
213 BOOST_FOREACH( Member *pMember, dynamicMembers )
214 {
215 if( GetName() == pMember->GetName() )
216 {
217 return true;
218 }
219 }
220
221 // 静的メンバ
222 BOOST_FOREACH( Member *pMember, staticMembers ){
223 if( GetName() == pMember->GetName() ){
224 return true;
225 }
226 }
227
228 return false;
229}
230
231const Member *CClass::FindDynamicMember( const char *memberName ) const
232{
233 if( this->HasSuperClass() )
234 {
235 // 基底クラスで検索
236 const Member *result = this->GetSuperClass().FindDynamicMember( memberName );
237 if( result )
238 {
239 return result;
240 }
241 }
242
243 BOOST_FOREACH( Member *pMember, GetDynamicMembers() )
244 {
245 if( pMember->GetName() == memberName )
246 {
247 return pMember;
248 }
249 }
250 return NULL;
251}
252
253void CClass::EnumDynamicMethodsOrInterfaceMethods( const char *methodName, std::vector<const UserProc *> &subs ) const
254{
255 // 動的メソッド
256 GetDynamicMethods().Enum( methodName, subs );
257
258 // インターフェイス メソッド
259 BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() )
260 {
261 pInterface->GetDynamicMethods().Enum( methodName, subs );
262 }
263}
264const CMethod *CClass::GetDynamicMethodOrInterfaceMethod( const UserProc *pUserProc ) const
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 );
275 if( result )
276 {
277 return result;
278 }
279 }
280 }
281
282 return result;
283}
284
285//サイズを取得
286int CClass::GetSize() const
287{
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
322 BOOST_FOREACH( Member *pMember, dynamicMembers )
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 {
355 throw;
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;
383}
384
385//メンバのオフセットを取得
386int CClass::GetMemberOffset( const char *memberName ) const
387{
388 int resultSize = 0;
389
390 int alignment = 1;
391 if( this->IsStructure() )
392 {
393 // 構造体のとき
394
395 if( this->GetFixedAlignment() )
396 {
397 // アラインメントの固定値が指定されていた場合はそれを取得
398 alignment = this->GetFixedAlignment();
399 }
400 }
401 else
402 {
403 // それ以外
404
405 if( this->HasSuperClass() )
406 {
407 if( this->GetSuperClass().HasDynamicMember( memberName ) )
408 {
409 // 基底クラスのメンバを取得
410 return this->GetSuperClass().GetMemberOffset( memberName );
411 }
412
413 // 基底クラスのサイズを追加
414 resultSize += this->GetSuperClass().GetSize();
415
416 // 基底クラスのアラインメントを取得
417 alignment = this->GetSuperClass().GetAlignment();
418 }
419 else
420 {
421 // 基底クラスが存在しないとき
422
423 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
424 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0;
425 }
426 }
427
428 BOOST_FOREACH( Member *pMember, dynamicMembers )
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();
439 }
440
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 {
461 throw;
462 }
463
464 //メンバを持たない構造体
465 //※何もしない(オフセットの計算をしない)
466 }
467 else{
468 if( resultSize % tempAlignment )
469 {
470 resultSize += tempAlignment - ( resultSize % tempAlignment );
471 }
472 }
473 }
474
475 if(memberName){
476 //メンバ指定がある場合は、オフセットを返す
477 if( pMember->GetName() == memberName )
478 {
479 return resultSize;
480 }
481 }
482
483 // メンバサイズを加算(配列を考慮)
484 resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() );
485 }
486
487 if( alignment )
488 {
489 // 末尾アラインメントを考慮してパディングを追加
490 if( resultSize % alignment )
491 {
492 resultSize += alignment - ( resultSize % alignment );
493 }
494 }
495
496 return resultSize;
497}
498int CClass::GetAlignment() const
499{
500 int alignment = 1;
501 if( this->IsStructure() )
502 {
503 // 構造体のとき
504
505 if( this->GetFixedAlignment() )
506 {
507 // アラインメントの固定値が指定されていた場合はそれを取得
508 return this->GetFixedAlignment();
509 }
510 }
511 else
512 {
513 // それ以外
514
515 if( this->HasSuperClass() )
516 {
517 // 基底クラスのアラインメントを取得
518 alignment = this->GetSuperClass().GetAlignment();
519 }
520 else
521 {
522 // 基底クラスが存在しないとき
523
524 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
525 alignment = PTR_SIZE;
526 }
527 }
528
529 BOOST_FOREACH( Member *pMember, dynamicMembers )
530 {
531 int tempAlignment = pMember->GetType().GetSize();
532 if( pMember->GetType().IsStruct() )
533 {
534 // メンバが構造体の場合は、メンバのアラインメントを取得
535 tempAlignment = pMember->GetType().GetClass().GetAlignment();
536 }
537
538 if( alignment < tempAlignment )
539 {
540 // 最大アラインメントを更新
541 alignment = tempAlignment;
542 }
543 }
544
545 return alignment;
546}
547
548void CClass::GetVtblMasterListIndexAndVtblIndex( const UserProc *pUserProc, int &vtblMasterListIndex, int &vtblIndex ) const
549{
550 vtblMasterListIndex = 0;
551
552 vtblIndex = 0;
553 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
554 if( &pMethod->GetUserProc() == pUserProc )
555 {
556 return;
557 }
558
559 if( pMethod->IsVirtual() )
560 {
561 vtblIndex++;
562 }
563 }
564
565 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
566 {
567 vtblMasterListIndex++;
568
569 vtblIndex = 0;
570 BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){
571 if( &pMethod->GetUserProc() == pUserProc )
572 {
573 return;
574 }
575
576 if( pMethod->IsVirtual() )
577 {
578 vtblIndex++;
579 }
580 }
581 }
582
583 throw;
584}
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
599 throw;
600}
601long CClass::GetVtblMasterListOffset() const
602{
603 if( vtblMasterListOffset == -1 )
604 {
605 throw;
606 }
607
608 return vtblMasterListOffset;
609}
610bool CClass::IsAbstract() const
611{
612 // 未実装(abstract)の仮想関数を持つ場合はtrueを返す
613
614 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
615 if(pMethod->IsVirtual()){
616 if(pMethod->IsAbstract()){
617 return true;
618 }
619 }
620 }
621
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
634 return false;
635}
636
637const CClass *Classes::FindEx( const Symbol &symbol ) const
638{
639 if( symbol.GetNamespaceScopes().size() == 0 && symbol.GetName() == "Object" )
640 {
641 return GetObjectClassPtr();
642 }
643 else if( symbol.GetNamespaceScopes().size() == 0 && symbol.GetName() == "String" )
644 {
645 return GetStringClassPtr();
646 }
647
648 std::vector<const CClass *> classes;
649 const CClass *pClass = GetHashArrayElement( symbol.GetName().c_str() );
650 while( pClass )
651 {
652 if( pClass->IsEqualSymbol( symbol.GetNamespaceScopes(), symbol.GetName() ) ){
653 //名前空間とクラス名が一致した
654 classes.push_back( pClass );
655 }
656 pClass = pClass->GetChainNext();
657 }
658 if( classes.size() > 0 )
659 {
660 // 複数の名前空間の中に同一のクラス名が存在する場合があるので、アクセス可能で尚且つ階層が一番深いものをチョイスする
661 pClass = classes.front();
662
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
674 return NULL;
675}
676
677const CClass *Classes::GetStringClassPtr() const
678{
679 if( !pStringClass )
680 {
681 // キャッシュしておく
682 pStringClass = this->FindEx( Symbol( NamespaceScopes( "System" ), "String" ) );
683 }
684 return pStringClass;
685}
686const CClass *Classes::GetObjectClassPtr() const
687{
688 if( !pObjectClass )
689 {
690 // キャッシュしておく
691 pObjectClass = this->FindEx( Symbol( NamespaceScopes( "System" ), "Object" ) );
692 }
693 return pObjectClass;
694}
695const CClass *Classes::GetInterfaceInfoClassPtr() const
696{
697 if( !pInterfaceInfo )
698 {
699 // キャッシュしておく
700 pInterfaceInfo = this->FindEx( Symbol( NamespaceScopes( "ActiveBasic.Core" ), "InterfaceInfo" ) );
701 }
702 return pInterfaceInfo;
703}
704
705std::string CClass::GetStaticDefiningStringAsMemberNames() const
706{
707 std::string result;
708
709 BOOST_FOREACH( const Member *pMember, dynamicMembers )
710 {
711 if( result.size() )
712 {
713 result += ",";
714 }
715
716 result += "\"" + pMember->GetName() + "\"";
717 }
718
719 return result;
720}
721std::string CClass::GetStaticDefiningStringAsMemberOffsets() const
722{
723 std::string result;
724
725 BOOST_FOREACH( const Member *pMember, dynamicMembers )
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}
742
743void CClass::GetReferenceOffsetsInitializeBuffer( std::string &referenceOffsetsBuffer, int &numOfReference, int baseOffset ) const
744{
745 const CClass &thisClass = *this;
746 BOOST_FOREACH( const Member *pMember, thisClass.GetDynamicMembers() )
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.