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

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

ImplementsメソッドをLexicalAnalyzerクラスに移動した。

File size: 25.8 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
187CMember *CClass::CreateMember( Prototype::Accessibility accessibility, bool isConst, bool isRef, char *buffer, int nowLine )
188{
189 extern int cp;
190
191 //構文を解析
192 char VarName[VN_SIZE];
193 char initBuffer[VN_SIZE];
194 char lpszConstructParameter[VN_SIZE];
195 Subscripts subscripts;
196 Type type;
197 GetDimentionFormat(buffer,VarName,subscripts,type,initBuffer,lpszConstructParameter);
198
199 //重複チェック
200 if(this->DupliCheckAll(VarName)){
201 compiler.errorMessenger.Output(15,VarName,cp);
202 }
203
204 CMember *pMember = new CMember( accessibility, VarName, type, isConst, subscripts, initBuffer, lpszConstructParameter );
205 pMember->source_code_address = nowLine;
206 return pMember;
207}
208void CClass::AddMember( Prototype::Accessibility accessibility, bool isConst, bool isRef, char *buffer, int nowLine ){
209 dynamicMembers.push_back(
210 CreateMember( accessibility, isConst, isRef, buffer, nowLine )
211 );
212}
213void CClass::AddStaticMember( Prototype::Accessibility accessibility, bool isConst, bool isRef, char *buffer, int nowLine ){
214 staticMembers.push_back(
215 CreateMember( accessibility, isConst, isRef, buffer, nowLine )
216 );
217}
218
219bool CClass::DupliCheckAll(const char *name) const
220{
221 //重複チェック
222
223 //メンバ
224 if(DupliCheckMember(name)) return 1;
225
226 //メソッド
227 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
228 if( lstrcmp( name, pMethod->GetUserProc().GetName().c_str() ) == 0 ){
229 return 1;
230 }
231 }
232
233 return 0;
234}
235bool CClass::DupliCheckMember(const char *name) const
236{
237 //重複チェック
238
239 if( this->HasSuperClass() )
240 {
241 if( this->GetSuperClass().DupliCheckMember( name ) )
242 {
243 // 基底クラスで重複が発見された
244 return true;
245 }
246 }
247
248 // 動的メンバ
249 BOOST_FOREACH( CMember *pMember, dynamicMembers )
250 {
251 if( GetName() == pMember->GetName() )
252 {
253 return true;
254 }
255 }
256
257 // 静的メンバ
258 BOOST_FOREACH( CMember *pMember, staticMembers ){
259 if( GetName() == pMember->GetName() ){
260 return true;
261 }
262 }
263
264 return false;
265}
266
267const CMember *CClass::FindDynamicMember( const char *memberName ) const
268{
269 if( this->HasSuperClass() )
270 {
271 // 基底クラスで検索
272 const CMember *result = this->GetSuperClass().FindDynamicMember( memberName );
273 if( result )
274 {
275 return result;
276 }
277 }
278
279 BOOST_FOREACH( CMember *pMember, GetDynamicMembers() )
280 {
281 if( pMember->GetName() == memberName )
282 {
283 return pMember;
284 }
285 }
286 return NULL;
287}
288
289void CClass::EnumDynamicMethodsOrInterfaceMethods( const char *methodName, std::vector<const UserProc *> &subs ) const
290{
291 // 動的メソッド
292 GetDynamicMethods().Enum( methodName, subs );
293
294 // インターフェイス メソッド
295 BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() )
296 {
297 pInterface->GetDynamicMethods().Enum( methodName, subs );
298 }
299}
300const CMethod *CClass::GetDynamicMethodOrInterfaceMethod( const UserProc *pUserProc ) const
301{
302 // 動的メソッド
303 const CMethod *result = GetDynamicMethods().GetMethodPtr( pUserProc );
304
305 if( !result )
306 {
307 // インターフェイス メソッド
308 BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() )
309 {
310 result = pInterface->GetDynamicMethods().GetMethodPtr( pUserProc );
311 if( result )
312 {
313 return result;
314 }
315 }
316 }
317
318 return result;
319}
320
321const ::Delegate &CClass::GetDelegate() const
322{
323 const ::Delegate *dg = compiler.GetObjectModule().meta.GetDelegates().GetHashArrayElement( GetName().c_str() );
324 while( dg )
325 {
326 if( dg->IsEqualSymbol( GetNamespaceScopes(), GetName() ) ){
327 //名前空間とクラス名が一致した
328 return *dg;
329 }
330 dg = dg->GetChainNext();
331 }
332
333 Jenga::Throw( "CClass::GetDelegateメソッドに失敗" );
334 static ::Delegate dummy;
335 return dummy;
336}
337
338//サイズを取得
339int CClass::GetSize() const
340{
341 int resultSize = 0;
342
343 int alignment = 1;
344 if( this->IsStructure() )
345 {
346 // 構造体のとき
347
348 if( this->GetFixedAlignment() )
349 {
350 // アラインメントの固定値が指定されていた場合はそれを取得
351 alignment = this->GetFixedAlignment();
352 }
353 }
354 else
355 {
356 // それ以外
357
358 if( this->HasSuperClass() )
359 {
360 // 基底クラスのサイズを追加
361 resultSize += this->GetSuperClass().GetSize();
362
363 // 基底クラスのアラインメントを取得
364 alignment = this->GetSuperClass().GetAlignment();
365 }
366 else
367 {
368 // 基底クラスが存在しないとき
369
370 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
371 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0;
372 }
373 }
374
375 BOOST_FOREACH( CMember *pMember, dynamicMembers )
376 {
377 // メンバサイズ
378 int tempMemberSize = pMember->GetType().GetSize();
379
380 // 一時アラインメントを算出
381 int tempAlignment = tempMemberSize;
382 if( pMember->GetType().IsStruct() )
383 {
384 // メンバが構造体の場合は、メンバのアラインメントを取得
385 tempAlignment = pMember->GetType().GetClass().GetAlignment();
386 }
387
388 // アラインメントを考慮してパディングを追加
389 if( GetFixedAlignment() && alignment < tempAlignment )
390 {
391 if( resultSize % alignment )
392 {
393 resultSize += alignment - ( resultSize % alignment );
394 }
395 }
396 else
397 {
398 if( alignment < tempAlignment )
399 {
400 // 最大アラインメントを更新
401 alignment = tempAlignment;
402 }
403
404 if( tempMemberSize == 0 )
405 {
406 if( !pMember->GetType().IsStruct() )
407 {
408 compiler.errorMessenger.OutputFatalError();
409 }
410
411 //メンバを持たない構造体
412 //※何もしない(オフセットの計算をしない)
413 }
414 else{
415 if( resultSize % tempAlignment )
416 {
417 resultSize += tempAlignment - ( resultSize % tempAlignment );
418 }
419 }
420 }
421
422 // メンバサイズを加算(配列を考慮)
423 resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() );
424 }
425
426 if( alignment )
427 {
428 // 末尾アラインメントを考慮してパディングを追加
429 if( resultSize % alignment )
430 {
431 resultSize += alignment - ( resultSize % alignment );
432 }
433 }
434
435 return resultSize;
436}
437
438//メンバのオフセットを取得
439int CClass::GetMemberOffset( const char *memberName ) const
440{
441 int resultSize = 0;
442
443 int alignment = 1;
444 if( this->IsStructure() )
445 {
446 // 構造体のとき
447
448 if( this->GetFixedAlignment() )
449 {
450 // アラインメントの固定値が指定されていた場合はそれを取得
451 alignment = this->GetFixedAlignment();
452 }
453 }
454 else
455 {
456 // それ以外
457
458 if( this->HasSuperClass() )
459 {
460 if( this->GetSuperClass().HasDynamicMember( memberName ) )
461 {
462 // 基底クラスのメンバを取得
463 return this->GetSuperClass().GetMemberOffset( memberName );
464 }
465
466 // 基底クラスのサイズを追加
467 resultSize += this->GetSuperClass().GetSize();
468
469 // 基底クラスのアラインメントを取得
470 alignment = this->GetSuperClass().GetAlignment();
471 }
472 else
473 {
474 // 基底クラスが存在しないとき
475
476 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
477 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0;
478 }
479 }
480
481 BOOST_FOREACH( CMember *pMember, dynamicMembers )
482 {
483 // メンバサイズ
484 int tempMemberSize = pMember->GetType().GetSize();
485
486 // 一時アラインメントを算出
487 int tempAlignment = tempMemberSize;
488 if( pMember->GetType().IsStruct() )
489 {
490 // メンバが構造体の場合は、メンバのアラインメントを取得
491 tempAlignment = pMember->GetType().GetClass().GetAlignment();
492 }
493
494 // アラインメントを考慮してパディングを追加
495 if( GetFixedAlignment() && alignment < tempAlignment )
496 {
497 if( resultSize % alignment )
498 {
499 resultSize += alignment - ( resultSize % alignment );
500 }
501 }
502 else
503 {
504 if( alignment < tempAlignment )
505 {
506 // 最大アラインメントを更新
507 alignment = tempAlignment;
508 }
509
510 if( tempMemberSize == 0 )
511 {
512 if( !pMember->GetType().IsStruct() )
513 {
514 compiler.errorMessenger.OutputFatalError();
515 }
516
517 //メンバを持たない構造体
518 //※何もしない(オフセットの計算をしない)
519 }
520 else{
521 if( resultSize % tempAlignment )
522 {
523 resultSize += tempAlignment - ( resultSize % tempAlignment );
524 }
525 }
526 }
527
528 if(memberName){
529 //メンバ指定がある場合は、オフセットを返す
530 if( pMember->GetName() == memberName )
531 {
532 return resultSize;
533 }
534 }
535
536 // メンバサイズを加算(配列を考慮)
537 resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() );
538 }
539
540 if( alignment )
541 {
542 // 末尾アラインメントを考慮してパディングを追加
543 if( resultSize % alignment )
544 {
545 resultSize += alignment - ( resultSize % alignment );
546 }
547 }
548
549 return resultSize;
550}
551int CClass::GetAlignment() const
552{
553 int alignment = 1;
554 if( this->IsStructure() )
555 {
556 // 構造体のとき
557
558 if( this->GetFixedAlignment() )
559 {
560 // アラインメントの固定値が指定されていた場合はそれを取得
561 return this->GetFixedAlignment();
562 }
563 }
564 else
565 {
566 // それ以外
567
568 if( this->HasSuperClass() )
569 {
570 // 基底クラスのアラインメントを取得
571 alignment = this->GetSuperClass().GetAlignment();
572 }
573 else
574 {
575 // 基底クラスが存在しないとき
576
577 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
578 alignment = PTR_SIZE;
579 }
580 }
581
582 BOOST_FOREACH( CMember *pMember, dynamicMembers )
583 {
584 int tempAlignment = pMember->GetType().GetSize();
585 if( pMember->GetType().IsStruct() )
586 {
587 // メンバが構造体の場合は、メンバのアラインメントを取得
588 tempAlignment = pMember->GetType().GetClass().GetAlignment();
589 }
590
591 if( alignment < tempAlignment )
592 {
593 // 最大アラインメントを更新
594 alignment = tempAlignment;
595 }
596 }
597
598 return alignment;
599}
600
601void CClass::GetVtblMasterListIndexAndVtblIndex( const UserProc *pUserProc, int &vtblMasterListIndex, int &vtblIndex ) const
602{
603 vtblMasterListIndex = 0;
604
605 vtblIndex = 0;
606 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
607 if( &pMethod->GetUserProc() == pUserProc )
608 {
609 return;
610 }
611
612 if( pMethod->IsVirtual() )
613 {
614 vtblIndex++;
615 }
616 }
617
618 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
619 {
620 vtblMasterListIndex++;
621
622 vtblIndex = 0;
623 BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){
624 if( &pMethod->GetUserProc() == pUserProc )
625 {
626 return;
627 }
628
629 if( pMethod->IsVirtual() )
630 {
631 vtblIndex++;
632 }
633 }
634 }
635
636 compiler.errorMessenger.OutputFatalError();
637 return;
638}
639int CClass::GetVtblMasterListIndex( const CClass *pClass ) const
640{
641 int result = 0;
642
643 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
644 {
645 result++;
646
647 if( &pInterface->GetClass() == pClass )
648 {
649 return result;
650 }
651 }
652
653 compiler.errorMessenger.OutputFatalError();
654 return 0;
655}
656long CClass::GetVtblMasterListOffset() const
657{
658 //既に存在する場合はそれを返す
659 if( vtblMasterListOffset == -1 )
660 {
661 compiler.errorMessenger.OutputFatalError();
662 }
663
664 return vtblMasterListOffset;
665}
666bool CClass::IsAbstract() const
667{
668 // 未実装(abstract)の仮想関数を持つ場合はtrueを返す
669
670 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
671 if(pMethod->IsVirtual()){
672 if(pMethod->IsAbstract()){
673 return true;
674 }
675 }
676 }
677
678 // インターフェイスのvtbl
679 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
680 {
681 BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){
682 if(pMethod->IsVirtual()){
683 if(pMethod->IsAbstract()){
684 return true;
685 }
686 }
687 }
688 }
689
690 return false;
691}
692
693CClass *Classes::Create( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name){
694 return new CClass(namespaceScopes, importedNamespaces, name);
695}
696bool Classes::Insert( CClass *pClass, int nowLine )
697{
698 /////////////////////////////////
699 // ハッシュデータに追加
700 /////////////////////////////////
701
702 if( !Put( pClass ) )
703 {
704 compiler.errorMessenger.Output(15,pClass->GetName(), nowLine);
705 return false;
706 }
707 return true;
708}
709CClass *Classes::Add( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name,int nowLine){
710 //////////////////////////////////////////////////////////////////////////
711 // クラスを追加
712 // ※名前のみを登録。その他の情報はSetClassメソッドで!
713 //////////////////////////////////////////////////////////////////////////
714
715 CClass *pClass = Create(namespaceScopes, importedNamespaces, name);
716
717 if( !Insert( pClass, nowLine ) )
718 {
719 return NULL;
720 }
721
722 return pClass;
723}
724
725
726void Classes::InitStaticMember(){
727 //静的メンバをグローバル領域に作成
728
729 //イテレータをリセット
730
731 extern int cp;
732 int back_cp=cp;
733
734 this->Iterator_Reset();
735 while(this->Iterator_HasNext()){
736 CClass &objClass = *this->Iterator_GetNext();
737 if( objClass.isTargetObjectModule == false )
738 {
739 // 静的リンクライブラリの場合は飛ばす(既にインスタンスが定義済みであるため)
740 continue;
741 }
742
743 // 名前空間をセット
744 compiler.GetNamespaceSupporter().GetLivingNamespaceScopes() = objClass.GetNamespaceScopes();
745
746 DWORD dwFlags = 0;
747 if( objClass.GetName() == "_System_TypeBase" )
748 {
749 // _System_TypeBaseクラスはグローバル、スタティック領域を初期化するためのクラスなのでここでの初期化は除外する
750 dwFlags |= DIMFLAG_NONCALL_CONSTRACTOR;
751 }
752
753 // コンパイル中クラスとしてセット
754 compiler.SetCompilingClass( &objClass );
755
756 const EnumInfo *pEnumInfo = NULL;
757 if( objClass.IsEnum() )
758 {
759 pEnumInfo = compiler.enumInfoCollection.Find( objClass );
760 }
761
762 int i=0;
763 BOOST_FOREACH( CMember *member, objClass.GetStaticMembers() )
764 {
765 if( pEnumInfo )
766 {
767 cp = pEnumInfo->GetEnumMember( member->GetName() ).GetSourceIndex();
768 }
769
770 char temporary[VN_SIZE];
771 sprintf(temporary,"%s.%s",objClass.GetName().c_str(),member->GetName().c_str());
772 dim(
773 temporary,
774 member->GetSubscripts(),
775 member->GetType(),
776 member->GetInitializeExpression().c_str(),
777 member->GetConstructParameter().c_str(),
778 dwFlags);
779
780 i++;
781 }
782
783 compiler.SetCompilingClass( NULL );
784 }
785
786 compiler.GetNamespaceSupporter().GetLivingNamespaceScopes().clear();
787
788 cp=back_cp;
789}
790
791void Classes::Compile_System_InitializeUserTypes(){
792 char temporary[VN_SIZE];
793
794 ////////////////////////////////////////////////////////////////////
795 // クラス登録
796 ////////////////////////////////////////////////////////////////////
797
798 // イテレータをリセット
799 Iterator_Reset();
800
801 while( Iterator_HasNext() ){
802 const CClass &objClass = *Iterator_GetNext();
803
804 if( !objClass.IsUsing() ){
805 // 未使用のクラスは無視する
806 continue;
807 }
808
809 std::string referenceOffsetsBuffer;
810 int numOfReference = 0;
811 objClass.GetReferenceOffsetsInitializeBuffer( referenceOffsetsBuffer, numOfReference );
812
813 sprintf( temporary
814 , "Add(%c%c_System_TypeForClass[strNamespace=\"%s\",name=\"%s\",fullName=\"%s\",referenceOffsets=[%s],numOfReference=%d])"
815 , 1
816 , ESC_SYSTEM_STATIC_NEW
817 , objClass.GetNamespaceScopes().ToString().c_str() // 名前空間
818 , objClass.GetName().c_str() // クラス名
819 , objClass.GetFullName().c_str() // フルネーム
820 , referenceOffsetsBuffer.c_str() // 参照メンバオフセット配列
821 , numOfReference // 参照メンバの個数
822 );
823
824 // コンパイル
825 ChangeOpcode( temporary );
826
827 objClass.SetTypeInfoDataTableOffset(
828 compiler.GetObjectModule().dataTable.GetLastMadeConstObjectDataTableOffset()
829 );
830 }
831}
832void Classes::Compile_System_InitializeUserTypesForBaseType()
833{
834 extern int cp;
835 cp = -1;
836 ////////////////////////////////////////////////////////////////////
837 // 基底クラスを登録
838 ////////////////////////////////////////////////////////////////////
839
840 char temporary[8192];
841 sprintf(temporary, "%c%ctempType=Nothing%c%c_System_TypeForClass"
842 , HIBYTE( COM_DIM )
843 , LOBYTE( COM_DIM )
844 , 1
845 , ESC_AS
846 );
847 ChangeOpcode( temporary );
848
849 // イテレータをリセット
850 Iterator_Reset();
851
852 while( Iterator_HasNext() ){
853 const CClass &objClass = *Iterator_GetNext();
854
855 if( !objClass.IsUsing() ){
856 // 未使用のクラスは無視する
857 continue;
858 }
859
860 if( objClass.HasSuperClass() || objClass.GetDynamicMembers().size() ){
861 sprintf( temporary
862 , "tempType=Search(\"%s\") As ActiveBasic.Core._System_TypeForClass"
863 , objClass.GetFullName().c_str()
864 );
865
866 // コンパイル
867 MakeMiddleCode( temporary );
868 ChangeOpcode( temporary );
869
870 sprintf( temporary
871 , "tempType.SetClassInfo(%d,_System_GetComVtbl(%s),_System_GetVtblList(%s),_System_GetDefaultConstructor(%s),_System_GetDestructor(%s))"
872 , objClass.GetSize()
873 , objClass.GetFullName().c_str()
874 , objClass.GetFullName().c_str()
875 , objClass.GetFullName().c_str()
876 , objClass.GetFullName().c_str()
877 , objClass.GetName().c_str()
878 );
879
880 // コンパイル
881 ChangeOpcode( temporary );
882
883 if( objClass.HasSuperClass() )
884 {
885 sprintf( temporary
886 , "tempType.SetBaseType(Search(\"%s\"))"
887 , objClass.GetSuperClass().GetFullName().c_str()
888 );
889
890 // コンパイル
891 ChangeOpcode( temporary );
892 }
893
894 if( objClass.GetDynamicMembers().size() )
895 {
896 // メンバの型を示すTypeInfoオブジェクトへのDataOffset配列の静的データ定義文字列を取得
897 sprintf(
898 temporary,
899 "tempType.SetMembers([%s],[%s],[%s],%d)",
900 objClass.GetStaticDefiningStringAsMemberNames().c_str(),
901 objClass.GetStaticDefiningStringAsMemberTypeInfoNames().c_str(),
902 objClass.GetStaticDefiningStringAsMemberOffsets().c_str(),
903 objClass.GetDynamicMembers().size()
904 );
905 ChangeOpcode( temporary );
906 }
907 }
908 }
909}
910
911const CClass *Classes::Find( const NamespaceScopes &namespaceScopes, const std::string &name ) const
912{
913 if( namespaceScopes.size() == 0 && name == "Object" ){
914 return GetObjectClassPtr();
915 }
916 else if( namespaceScopes.size() == 0 && name == "String" ){
917 return GetStringClassPtr();
918 }
919
920 std::vector<const CClass *> classes;
921 const CClass *pClass = GetHashArrayElement( name.c_str() );
922 while( pClass )
923 {
924 if( pClass->IsEqualSymbol( namespaceScopes, name ) ){
925 //名前空間とクラス名が一致した
926 classes.push_back( pClass );
927 }
928 pClass = pClass->GetChainNext();
929 }
930 if( classes.size() > 0 )
931 {
932 // 複数の名前空間の中に同一のクラス名が存在する場合があるので、アクセス可能で尚且つ階層が一番深いものをチョイスする
933 pClass = classes.front();
934
935 BOOST_FOREACH( const CClass *pTempClass, classes )
936 {
937 if( pClass->GetNamespaceScopes().size() < pTempClass->GetNamespaceScopes().size() )
938 {
939 pClass = pTempClass;
940 }
941 }
942
943 return pClass;
944 }
945
946 // TypeDefも見る
947 int index = compiler.GetObjectModule().meta.GetTypeDefs().GetIndex( namespaceScopes, name );
948 if( index != -1 ){
949 Type type = compiler.GetObjectModule().meta.GetTypeDefs()[index].GetBaseType();
950 if( type.IsObject() ){
951 return &type.GetClass();
952 }
953 }
954
955 return NULL;
956}
957const CClass *Classes::Find( const std::string &fullName ) const
958{
959 char AreaName[VN_SIZE] = ""; //オブジェクト変数
960 char NestName[VN_SIZE] = ""; //入れ子メンバ
961 bool isNest = SplitMemberName( fullName.c_str(), AreaName, NestName );
962
963 return Find( NamespaceScopes( AreaName ), NestName );
964}
965
966const CClass *Classes::GetStringClassPtr() const
967{
968 if( !pStringClass ){
969 // キャッシュしておく
970 pStringClass = this->Find( NamespaceScopes( "System" ), "String" );
971
972 if( !pStringClass )
973 {
974 compiler.errorMessenger.Output(400, "System.String", cp);
975 static CClass dummy;
976 return &dummy;
977 }
978 return pStringClass;
979 }
980 return pStringClass;
981}
982const CClass *Classes::GetObjectClassPtr() const
983{
984 if( !pObjectClass ){
985 // キャッシュしておく
986 pObjectClass = this->Find( NamespaceScopes( "System" ), "Object" );
987
988 if( !pObjectClass )
989 {
990 compiler.errorMessenger.Output(400, "System.Object", cp);
991 static CClass dummy;
992 return &dummy;
993 }
994 return pObjectClass;
995 }
996 return pObjectClass;
997}
998const CClass *Classes::GetInterfaceInfoClassPtr() const
999{
1000 if( !pInterfaceInfo ){
1001 // キャッシュしておく
1002 pInterfaceInfo = this->Find( "ActiveBasic.Core.InterfaceInfo" );
1003
1004 if( !pInterfaceInfo )
1005 {
1006 compiler.errorMessenger.Output(400, "ActiveBasic.Core.InterfaceInfo", cp);
1007 static CClass dummy;
1008 return &dummy;
1009 }
1010 return pInterfaceInfo;
1011 }
1012 return pInterfaceInfo;
1013}
1014
1015std::string CClass::GetStaticDefiningStringAsMemberNames() const
1016{
1017 std::string result;
1018
1019 BOOST_FOREACH( const CMember *pMember, dynamicMembers )
1020 {
1021 if( result.size() )
1022 {
1023 result += ",";
1024 }
1025
1026 result += "\"" + pMember->GetName() + "\"";
1027 }
1028
1029 return result;
1030}
1031std::string CClass::GetStaticDefiningStringAsMemberTypeInfoNames() const
1032{
1033 std::string result;
1034
1035 BOOST_FOREACH( const CMember *pMember, dynamicMembers )
1036 {
1037 if( result.size() )
1038 {
1039 result += ",";
1040 }
1041
1042 result += "\"" + compiler.TypeToString( pMember->GetType() ) + "\"";
1043 }
1044
1045 return result;
1046}
1047std::string CClass::GetStaticDefiningStringAsMemberOffsets() const
1048{
1049 std::string result;
1050
1051 BOOST_FOREACH( const CMember *pMember, dynamicMembers )
1052 {
1053 if( result.size() )
1054 {
1055 result += ",";
1056 }
1057
1058 int offset = this->GetMemberOffset( pMember->GetName().c_str() );
1059
1060 char temporary[255];
1061 itoa( offset, temporary, 16 );
1062
1063 result += (std::string)"&H" + temporary;
1064 }
1065
1066 return result;
1067}
1068
1069void CClass::GetReferenceOffsetsInitializeBuffer( std::string &referenceOffsetsBuffer, int &numOfReference, int baseOffset ) const
1070{
1071 const CClass &thisClass = *this;
1072 BOOST_FOREACH( const CMember *pMember, thisClass.GetDynamicMembers() )
1073 {
1074 if( pMember->GetType().IsObject() || pMember->GetType().IsPointer() )
1075 {
1076 if( referenceOffsetsBuffer.size() )
1077 {
1078 referenceOffsetsBuffer += ",";
1079 }
1080
1081 char temp[255];
1082 sprintf( temp, "%d", baseOffset + thisClass.GetMemberOffset( pMember->GetName().c_str() ) );
1083 referenceOffsetsBuffer += temp;
1084
1085 numOfReference++;
1086 }
1087 if( pMember->GetType().IsStruct() && !pMember->GetType().IsPointer() )
1088 {
1089 // 構造体の実体をメンバに持つとき
1090 int baseOffset = thisClass.GetMemberOffset( pMember->GetName().c_str() );
1091
1092 // 構造体メンバでGCによるチェックが必要な参照位置を追加
1093 pMember->GetType().GetClass().GetReferenceOffsetsInitializeBuffer( referenceOffsetsBuffer, numOfReference, baseOffset );
1094 }
1095 }
1096}
Note: See TracBrowser for help on using the repository browser.