source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/src/Class.cpp@ 567

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

GetStringClassPtrGetObjectClassPtr、GetInterfaceInfoClassPtrクラスからエラー出力を排除した。
・GetStaticDefiningStringAsMemberTypeInfoNamesメソッドの実装位置をCClassクラスからProcedureGeneratorクラスに移動した。

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