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

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

ヘッダファイルを整理中

File size: 31.9 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
16
17bool CClass::IsClass() const
18{
19 return classType == CClass::Class;
20}
21bool CClass::IsInterface() const
22{
23 return classType == CClass::Interface;
24}
25bool CClass::IsComInterface() const
26{
27 return classType == CClass::ComInterface;
28}
29bool CClass::IsEnum() const
30{
31 return classType == CClass::Enum;
32}
33bool CClass::IsDelegate() const
34{
35 return classType == CClass::Delegate;
36}
37bool CClass::IsStructure() const
38{
39 return classType == CClass::Structure;
40}
41
42
43// コンストラクタのコンパイルを開始
44void CClass::NotifyStartConstructorCompile() const
45{
46 isCompilingConstructor = true;
47}
48
49//コンストラクタのコンパイルを終了
50void CClass::NotifyFinishConstructorCompile() const
51{
52 isCompilingConstructor = false;
53}
54
55//コンストラクタをコンパイル中かどうかを判別
56bool CClass::IsCompilingConstructor() const
57{
58 return isCompilingConstructor;
59}
60
61//デストラクタのコンパイルを開始
62void CClass::NotifyStartDestructorCompile() const{
63 isCompilingDestructor = true;
64}
65
66//デストラクタのコンパイルを終了
67void CClass::NotifyFinishDestructorCompile() const{
68 isCompilingDestructor = false;
69}
70
71//デストラクタをコンパイル中かどうかを判別
72bool CClass::IsCompilingDestructor() const
73{
74 return isCompilingDestructor;
75}
76
77//自身の派生クラスかどうかを確認
78bool CClass::IsSubClass( const CClass *pSubClass ) const
79{
80 if( !pSubClass->HasSuperClass() )
81 {
82 return false;
83 }
84
85 const CClass *pTempClass = &pSubClass->GetSuperClass();
86 while( pTempClass ){
87 if( this == pTempClass ) return true;
88 pTempClass = &pTempClass->GetSuperClass();
89 }
90 return false;
91}
92
93//自身と等しいまたは派生クラスかどうかを確認
94bool CClass::IsEqualsOrSubClass( const CClass *pSubClass ) const
95{
96 if( IsEquals( pSubClass ) ) return true;
97 return IsSubClass( pSubClass );
98}
99
100// 自身と等しいまたは派生クラス、基底クラスかどうかを確認
101bool CClass::IsEqualsOrSubClassOrSuperClass( const CClass &objClass ) const
102{
103 if( IsEquals( &objClass ) ) return true;
104 if( IsSubClass( &objClass ) ) return true;
105 if( objClass.IsSubClass( this ) ) return true;
106 return false;
107}
108
109bool CClass::IsInheritsInterface( const CClass *pInterfaceClass ) const
110{
111 BOOST_FOREACH( const ::Interface *pInterface, interfaces ){
112 if( pInterfaceClass == &pInterface->GetClass() ){
113 return true;
114 }
115 }
116 return false;
117}
118
119bool CClass::InheritsClass( const CClass &inheritsClass, const Types &actualTypeParameters, int nowLine )
120{
121 //メソッドをコピー
122 BOOST_FOREACH( const CMethod *pBaseMethod, inheritsClass.GetDynamicMethods() ){
123 CMethod *pMethod = new DynamicMethod( *pBaseMethod );
124
125 // アクセシビリティ
126 if(pBaseMethod->GetAccessibility() == Prototype::Private){
127 pMethod->SetAccessibility( Prototype::None );
128 }
129 else{
130 pMethod->SetAccessibility( pBaseMethod->GetAccessibility() );
131 }
132
133 //pobj_Inherits
134 // ※継承元のClassIndexをセット(入れ子継承を考慮する)
135 if(pBaseMethod->GetInheritsClassPtr()==0){
136 pMethod->SetInheritsClassPtr( &inheritsClass );
137 }
138 else{
139 pMethod->SetInheritsClassPtr( pBaseMethod->GetInheritsClassPtr() );
140 }
141
142 GetDynamicMethods().push_back( pMethod );
143 }
144
145 //仮想関数の数
146 AddVtblNum( inheritsClass.GetVtblNum() );
147
148 //継承先のクラスをメンバとして保持する
149 SetSuperClass( &inheritsClass );
150 SetSuperClassActualTypeParameters( actualTypeParameters );
151
152 // インターフェイスを引き継ぐ
153 BOOST_FOREACH( ::Interface *pInterface, inheritsClass.GetInterfaces() )
154 {
155 interfaces.push_back( new ::Interface( *pInterface ) );
156 }
157
158 if( this->IsInterface() && inheritsClass.IsComInterface() )
159 {
160 // COMインターフェイスを継承した場合はCOMインターフェイスにする
161 this->SetClassType( CClass::ComInterface );
162 }
163
164 return true;
165}
166
167bool CClass::Implements( const CClass &interfaceClass, const Types &actualTypeParameters, int nowLine )
168{
169 if( !interfaceClass.IsInterface() && !interfaceClass.IsComInterface() )
170 {
171 // インターフェイスではないとき
172 compiler.errorMessenger.Output(138,interfaceClass.GetName().c_str(),nowLine );
173 return false;
174 }
175
176 ::Interface *pDestInterface = new ::Interface( &interfaceClass, actualTypeParameters );
177
178 interfaces.push_back( pDestInterface );
179
180
181 /////////////////////////////////////////////////////////////////
182 // 基底クラスのメソッドからインターフェイスメソッドを再実装する
183 /////////////////////////////////////////////////////////////////
184 BOOST_FOREACH( CMethod *pMethod, GetDynamicMethods() )
185 {
186 CMethod *pMethodForOverride = pDestInterface->GetDynamicMethods().FindForOverride( pDestInterface->GetActualTypeParameters(), &pMethod->GetUserProc() );
187 if( pMethodForOverride )
188 {
189 pMethodForOverride->Override( &pMethod->GetUserProc(), pMethod->GetAccessibility(), false );
190
191 // 実装元になるメソッドは呼び出し不可にしておく(オーバーロードの解決から除外する)
192 pMethod->SetNotUseMark( true );
193 }
194 }
195
196
197 /////////////////////////////////////////////////////////////////
198 // キャストメソッドを追加(内部コードは自動生成すること)
199 /////////////////////////////////////////////////////////////////
200 if( interfaceClass.IsInterface() )
201 {
202 // Function Operator() As ITest
203
204 char methodName[255] = { 1, ESC_OPERATOR, CALC_AS, '\0' };
205
206 //関数ハッシュへ登録
207 UserProc *pUserProc = new UserProc(
208 NamespaceScopes(),
209 NamespaceScopesCollection(),
210 methodName,
211 Procedure::Function,
212 false,
213 false,
214 false );
215 pUserProc->SetParentClass( this );
216
217 Parameters params;
218 params.push_back( new Parameter( "_System_LocalThis", Type( DEF_PTR_VOID ) ) );
219 pUserProc->SetRealParams( params );
220
221 pUserProc->SetReturnType( Type( DEF_OBJECT, interfaceClass ) );
222 pUserProc->_paramStr = "";
223 pUserProc->Using();
224 compiler.GetObjectModule().meta.GetUserProcs().Insert( pUserProc, -1 );
225
226 LexicalAnalyzer::AddMethod(this,
227 pUserProc,
228 Prototype::Public,
229 0,
230 false, // isConst
231 false, // isAbstract
232 false, // isVirtual
233 false, // isOverride
234 "",
235 true, // isAutoGeneration
236 -1
237 );
238 }
239
240
241 return true;
242}
243
244CMember *CClass::CreateMember( Prototype::Accessibility accessibility, bool isConst, bool isRef, char *buffer, int nowLine )
245{
246 extern int cp;
247
248 //構文を解析
249 char VarName[VN_SIZE];
250 char initBuffer[VN_SIZE];
251 char lpszConstructParameter[VN_SIZE];
252 Subscripts subscripts;
253 Type type;
254 GetDimentionFormat(buffer,VarName,subscripts,type,initBuffer,lpszConstructParameter);
255
256 //重複チェック
257 if(this->DupliCheckAll(VarName)){
258 compiler.errorMessenger.Output(15,VarName,cp);
259 }
260
261 CMember *pMember = new CMember( accessibility, VarName, type, isConst, subscripts, initBuffer, lpszConstructParameter );
262 pMember->source_code_address = nowLine;
263 return pMember;
264}
265void CClass::AddMember( Prototype::Accessibility accessibility, bool isConst, bool isRef, char *buffer, int nowLine ){
266 dynamicMembers.push_back(
267 CreateMember( accessibility, isConst, isRef, buffer, nowLine )
268 );
269}
270void CClass::AddStaticMember( Prototype::Accessibility accessibility, bool isConst, bool isRef, char *buffer, int nowLine ){
271 staticMembers.push_back(
272 CreateMember( accessibility, isConst, isRef, buffer, nowLine )
273 );
274}
275
276bool CClass::DupliCheckAll(const char *name) const
277{
278 //重複チェック
279
280 //メンバ
281 if(DupliCheckMember(name)) return 1;
282
283 //メソッド
284 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
285 if( lstrcmp( name, pMethod->GetUserProc().GetName().c_str() ) == 0 ){
286 return 1;
287 }
288 }
289
290 return 0;
291}
292bool CClass::DupliCheckMember(const char *name) const
293{
294 //重複チェック
295
296 if( this->HasSuperClass() )
297 {
298 if( this->GetSuperClass().DupliCheckMember( name ) )
299 {
300 // 基底クラスで重複が発見された
301 return true;
302 }
303 }
304
305 // 動的メンバ
306 BOOST_FOREACH( CMember *pMember, dynamicMembers )
307 {
308 if( GetName() == pMember->GetName() )
309 {
310 return true;
311 }
312 }
313
314 // 静的メンバ
315 BOOST_FOREACH( CMember *pMember, staticMembers ){
316 if( GetName() == pMember->GetName() ){
317 return true;
318 }
319 }
320
321 return false;
322}
323
324const CMember *CClass::FindDynamicMember( const char *memberName ) const
325{
326 if( this->HasSuperClass() )
327 {
328 // 基底クラスで検索
329 const CMember *result = this->GetSuperClass().FindDynamicMember( memberName );
330 if( result )
331 {
332 return result;
333 }
334 }
335
336 BOOST_FOREACH( CMember *pMember, GetDynamicMembers() )
337 {
338 if( pMember->GetName() == memberName )
339 {
340 return pMember;
341 }
342 }
343 return NULL;
344}
345
346void CClass::EnumDynamicMethodsOrInterfaceMethods( const char *methodName, std::vector<const UserProc *> &subs ) const
347{
348 // 動的メソッド
349 GetDynamicMethods().Enum( methodName, subs );
350
351 // インターフェイス メソッド
352 BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() )
353 {
354 pInterface->GetDynamicMethods().Enum( methodName, subs );
355 }
356}
357const CMethod *CClass::GetDynamicMethodOrInterfaceMethod( const UserProc *pUserProc ) const
358{
359 // 動的メソッド
360 const CMethod *result = GetDynamicMethods().GetMethodPtr( pUserProc );
361
362 if( !result )
363 {
364 // インターフェイス メソッド
365 BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() )
366 {
367 result = pInterface->GetDynamicMethods().GetMethodPtr( pUserProc );
368 if( result )
369 {
370 return result;
371 }
372 }
373 }
374
375 return result;
376}
377
378const ::Delegate &CClass::GetDelegate() const
379{
380 const ::Delegate *dg = compiler.GetObjectModule().meta.GetDelegates().GetHashArrayElement( GetName().c_str() );
381 while( dg )
382 {
383 if( dg->IsEqualSymbol( GetNamespaceScopes(), GetName() ) ){
384 //名前空間とクラス名が一致した
385 return *dg;
386 }
387 dg = dg->GetChainNext();
388 }
389
390 Jenga::Throw( "CClass::GetDelegateメソッドに失敗" );
391 static ::Delegate dummy;
392 return dummy;
393}
394
395//サイズを取得
396int CClass::GetSize() const
397{
398 int resultSize = 0;
399
400 int alignment = 1;
401 if( this->IsStructure() )
402 {
403 // 構造体のとき
404
405 if( this->GetFixedAlignment() )
406 {
407 // アラインメントの固定値が指定されていた場合はそれを取得
408 alignment = this->GetFixedAlignment();
409 }
410 }
411 else
412 {
413 // それ以外
414
415 if( this->HasSuperClass() )
416 {
417 // 基底クラスのサイズを追加
418 resultSize += this->GetSuperClass().GetSize();
419
420 // 基底クラスのアラインメントを取得
421 alignment = this->GetSuperClass().GetAlignment();
422 }
423 else
424 {
425 // 基底クラスが存在しないとき
426
427 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
428 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0;
429 }
430 }
431
432 BOOST_FOREACH( CMember *pMember, dynamicMembers )
433 {
434 // メンバサイズ
435 int tempMemberSize = pMember->GetType().GetSize();
436
437 // 一時アラインメントを算出
438 int tempAlignment = tempMemberSize;
439 if( pMember->GetType().IsStruct() )
440 {
441 // メンバが構造体の場合は、メンバのアラインメントを取得
442 tempAlignment = pMember->GetType().GetClass().GetAlignment();
443 }
444
445 // アラインメントを考慮してパディングを追加
446 if( GetFixedAlignment() && alignment < tempAlignment )
447 {
448 if( resultSize % alignment )
449 {
450 resultSize += alignment - ( resultSize % alignment );
451 }
452 }
453 else
454 {
455 if( alignment < tempAlignment )
456 {
457 // 最大アラインメントを更新
458 alignment = tempAlignment;
459 }
460
461 if( tempMemberSize == 0 )
462 {
463 if( !pMember->GetType().IsStruct() )
464 {
465 compiler.errorMessenger.OutputFatalError();
466 }
467
468 //メンバを持たない構造体
469 //※何もしない(オフセットの計算をしない)
470 }
471 else{
472 if( resultSize % tempAlignment )
473 {
474 resultSize += tempAlignment - ( resultSize % tempAlignment );
475 }
476 }
477 }
478
479 // メンバサイズを加算(配列を考慮)
480 resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() );
481 }
482
483 if( alignment )
484 {
485 // 末尾アラインメントを考慮してパディングを追加
486 if( resultSize % alignment )
487 {
488 resultSize += alignment - ( resultSize % alignment );
489 }
490 }
491
492 return resultSize;
493}
494
495//メンバのオフセットを取得
496int CClass::GetMemberOffset( const char *memberName ) const
497{
498 int resultSize = 0;
499
500 int alignment = 1;
501 if( this->IsStructure() )
502 {
503 // 構造体のとき
504
505 if( this->GetFixedAlignment() )
506 {
507 // アラインメントの固定値が指定されていた場合はそれを取得
508 alignment = this->GetFixedAlignment();
509 }
510 }
511 else
512 {
513 // それ以外
514
515 if( this->HasSuperClass() )
516 {
517 if( this->GetSuperClass().HasDynamicMember( memberName ) )
518 {
519 // 基底クラスのメンバを取得
520 return this->GetSuperClass().GetMemberOffset( memberName );
521 }
522
523 // 基底クラスのサイズを追加
524 resultSize += this->GetSuperClass().GetSize();
525
526 // 基底クラスのアラインメントを取得
527 alignment = this->GetSuperClass().GetAlignment();
528 }
529 else
530 {
531 // 基底クラスが存在しないとき
532
533 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
534 resultSize += IsExistVirtualFunctions() ? PTR_SIZE*2 : 0;
535 }
536 }
537
538 BOOST_FOREACH( CMember *pMember, dynamicMembers )
539 {
540 // メンバサイズ
541 int tempMemberSize = pMember->GetType().GetSize();
542
543 // 一時アラインメントを算出
544 int tempAlignment = tempMemberSize;
545 if( pMember->GetType().IsStruct() )
546 {
547 // メンバが構造体の場合は、メンバのアラインメントを取得
548 tempAlignment = pMember->GetType().GetClass().GetAlignment();
549 }
550
551 // アラインメントを考慮してパディングを追加
552 if( GetFixedAlignment() && alignment < tempAlignment )
553 {
554 if( resultSize % alignment )
555 {
556 resultSize += alignment - ( resultSize % alignment );
557 }
558 }
559 else
560 {
561 if( alignment < tempAlignment )
562 {
563 // 最大アラインメントを更新
564 alignment = tempAlignment;
565 }
566
567 if( tempMemberSize == 0 )
568 {
569 if( !pMember->GetType().IsStruct() )
570 {
571 compiler.errorMessenger.OutputFatalError();
572 }
573
574 //メンバを持たない構造体
575 //※何もしない(オフセットの計算をしない)
576 }
577 else{
578 if( resultSize % tempAlignment )
579 {
580 resultSize += tempAlignment - ( resultSize % tempAlignment );
581 }
582 }
583 }
584
585 if(memberName){
586 //メンバ指定がある場合は、オフセットを返す
587 if( pMember->GetName() == memberName )
588 {
589 return resultSize;
590 }
591 }
592
593 // メンバサイズを加算(配列を考慮)
594 resultSize += tempMemberSize * Variable::GetSubScriptCounts( pMember->GetSubscripts() );
595 }
596
597 if( alignment )
598 {
599 // 末尾アラインメントを考慮してパディングを追加
600 if( resultSize % alignment )
601 {
602 resultSize += alignment - ( resultSize % alignment );
603 }
604 }
605
606 return resultSize;
607}
608int CClass::GetAlignment() const
609{
610 int alignment = 1;
611 if( this->IsStructure() )
612 {
613 // 構造体のとき
614
615 if( this->GetFixedAlignment() )
616 {
617 // アラインメントの固定値が指定されていた場合はそれを取得
618 return this->GetFixedAlignment();
619 }
620 }
621 else
622 {
623 // それ以外
624
625 if( this->HasSuperClass() )
626 {
627 // 基底クラスのアラインメントを取得
628 alignment = this->GetSuperClass().GetAlignment();
629 }
630 else
631 {
632 // 基底クラスが存在しないとき
633
634 // 仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
635 alignment = PTR_SIZE;
636 }
637 }
638
639 BOOST_FOREACH( CMember *pMember, dynamicMembers )
640 {
641 int tempAlignment = pMember->GetType().GetSize();
642 if( pMember->GetType().IsStruct() )
643 {
644 // メンバが構造体の場合は、メンバのアラインメントを取得
645 tempAlignment = pMember->GetType().GetClass().GetAlignment();
646 }
647
648 if( alignment < tempAlignment )
649 {
650 // 最大アラインメントを更新
651 alignment = tempAlignment;
652 }
653 }
654
655 return alignment;
656}
657
658void CClass::GetVtblMasterListIndexAndVtblIndex( const UserProc *pUserProc, int &vtblMasterListIndex, int &vtblIndex ) const
659{
660 vtblMasterListIndex = 0;
661
662 vtblIndex = 0;
663 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
664 if( &pMethod->GetUserProc() == pUserProc )
665 {
666 return;
667 }
668
669 if( pMethod->IsVirtual() )
670 {
671 vtblIndex++;
672 }
673 }
674
675 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
676 {
677 vtblMasterListIndex++;
678
679 vtblIndex = 0;
680 BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){
681 if( &pMethod->GetUserProc() == pUserProc )
682 {
683 return;
684 }
685
686 if( pMethod->IsVirtual() )
687 {
688 vtblIndex++;
689 }
690 }
691 }
692
693 compiler.errorMessenger.OutputFatalError();
694 return;
695}
696int CClass::GetVtblMasterListIndex( const CClass *pClass ) const
697{
698 int result = 0;
699
700 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
701 {
702 result++;
703
704 if( &pInterface->GetClass() == pClass )
705 {
706 return result;
707 }
708 }
709
710 compiler.errorMessenger.OutputFatalError();
711 return 0;
712}
713long CClass::GetComVtblOffset() const
714{
715 return comVtblOffset;
716}
717long CClass::GetVtblMasterListOffset() const
718{
719 //既に存在する場合はそれを返す
720 if( vtblMasterListOffset == -1 )
721 {
722 compiler.errorMessenger.OutputFatalError();
723 }
724
725 return vtblMasterListOffset;
726}
727void CClass::GenerateVTableMasterList( const std::vector<long> &vtableMasterList, long &offset )
728{
729 offset = compiler.GetObjectModule().dataTable.AddBinary(
730 (void *)&vtableMasterList[0],
731 static_cast<int>(vtableMasterList.size()*sizeof(LONG_PTR))
732 );
733}
734void CClass::GenerateFullVTables()
735{
736 if( IsAbstract() )
737 {
738 // 抽象クラスは無視
739 return;
740 }
741 if( !IsUsing() )
742 {
743 // 使われていないクラスは無視
744 return;
745 }
746
747 // vtblマスターリストの元データに不要なデータが含まれていたらエラー
748 if( vtblMasterList.size() )
749 {
750 compiler.errorMessenger.OutputFatalError();
751 }
752
753 // 自身のクラスのvtblを生成
754 GetDynamicMethods().GenerateVTablePart( this->vtbl_offset );
755 vtblMasterList.push_back( this->vtbl_offset );
756
757 // インターフェイスのvtblを生成
758 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
759 {
760 long tempVtblOffset;
761 pInterface->GetDynamicMethods().GenerateVTablePart( tempVtblOffset );
762 vtblMasterList.push_back( tempVtblOffset );
763
764 pInterface->SetVtblOffset( tempVtblOffset );
765
766 if( pInterface->GetClass().IsComInterface() )
767 {
768 if( this->comVtblOffset )
769 {
770 compiler.errorMessenger.OutputFatalError();
771 }
772 this->comVtblOffset = tempVtblOffset;
773 }
774 }
775
776 // vtblマスターリストを生成
777 GenerateVTableMasterList( vtblMasterList, this->vtblMasterListOffset );
778}
779void CClass::ActionVtblSchedule( LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection, LONG_PTR MemPos_DataSection )
780{
781 if( IsAbstract() )
782 {
783 // 抽象クラスは無視
784 return;
785 }
786 if( !IsUsing() )
787 {
788 // 使われていないクラスは無視
789 return;
790 }
791 if(vtbl_offset==-1) return;
792
793 // 自身のクラスのvtbl
794 {
795 LONG_PTR *pVtbl = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + vtbl_offset);
796
797 for( int i=0; i<GetVtblNum(); i++ ){
798 const UserProc *pUserProc = (UserProc *)pVtbl[i];
799 if(!pUserProc) continue;
800
801 if( pUserProc->GetBeginOpAddress() == 0
802 && pUserProc->GetEndOpAddress() == 0 )
803 {
804 Jenga::Throw( "未解決の仮想関数が存在する" );
805 }
806
807 pVtbl[i] = pUserProc->GetBeginOpAddress() + ImageBase + MemPos_CodeSection;
808 }
809 }
810
811 // インターフェイスのvtbl
812 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
813 {
814 LONG_PTR *pVtbl = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + pInterface->GetVtblOffset());
815
816 for( int i=0; i<pInterface->GetClass().GetVtblNum(); i++ ){
817 const UserProc *pUserProc = (UserProc *)pVtbl[i];
818 if(!pUserProc) continue;
819
820 if( pUserProc->GetBeginOpAddress() == 0
821 && pUserProc->GetEndOpAddress() == 0 )
822 {
823 Jenga::Throw( "未解決の仮想関数が存在する" );
824 }
825
826 pVtbl[i] = pUserProc->GetBeginOpAddress() + ImageBase + MemPos_CodeSection;
827 }
828 }
829
830 // vtblマスターリスト
831 LONG_PTR *pVtblMasterList = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + vtblMasterListOffset );
832 for( int i=0; i<static_cast<int>(vtblMasterList.size()); i++ )
833 {
834 pVtblMasterList[i] = vtblMasterList[i] + ImageBase + MemPos_DataSection;
835 }
836}
837bool CClass::IsAbstract() const
838{
839 // 未実装(abstract)の仮想関数を持つ場合はtrueを返す
840
841 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
842 if(pMethod->IsVirtual()){
843 if(pMethod->IsAbstract()){
844 return true;
845 }
846 }
847 }
848
849 // インターフェイスのvtbl
850 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
851 {
852 BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){
853 if(pMethod->IsVirtual()){
854 if(pMethod->IsAbstract()){
855 return true;
856 }
857 }
858 }
859 }
860
861 return false;
862}
863
864CClass *Classes::Create( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name){
865 return new CClass(namespaceScopes, importedNamespaces, name);
866}
867bool Classes::Insert( CClass *pClass, int nowLine )
868{
869 /////////////////////////////////
870 // ハッシュデータに追加
871 /////////////////////////////////
872
873 if( !Put( pClass ) )
874 {
875 compiler.errorMessenger.Output(15,pClass->GetName(), nowLine);
876 return false;
877 }
878 return true;
879}
880CClass *Classes::Add( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name,int nowLine){
881 //////////////////////////////////////////////////////////////////////////
882 // クラスを追加
883 // ※名前のみを登録。その他の情報はSetClassメソッドで!
884 //////////////////////////////////////////////////////////////////////////
885
886 CClass *pClass = Create(namespaceScopes, importedNamespaces, name);
887
888 if( !Insert( pClass, nowLine ) )
889 {
890 return NULL;
891 }
892
893 return pClass;
894}
895
896void Classes::GenerateVTables()
897{
898 Iterator_Reset();
899 while( Iterator_HasNext() )
900 {
901 CClass *pClass = Iterator_GetNext();
902 pClass->GenerateFullVTables();
903 }
904}
905
906void Classes::ActionVtblSchedule( LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection, LONG_PTR MemPos_DataSection ){
907 Iterator_Reset();
908 while( Iterator_HasNext() )
909 {
910 CClass *pClass = Iterator_GetNext();
911 pClass->ActionVtblSchedule( ImageBase, MemPos_CodeSection, MemPos_DataSection);
912 }
913}
914
915
916void Classes::InitStaticMember(){
917 //静的メンバをグローバル領域に作成
918
919 //イテレータをリセット
920
921 extern int cp;
922 int back_cp=cp;
923
924 this->Iterator_Reset();
925 while(this->Iterator_HasNext()){
926 CClass &objClass = *this->Iterator_GetNext();
927 if( objClass.isTargetObjectModule == false )
928 {
929 // 静的リンクライブラリの場合は飛ばす(既にインスタンスが定義済みであるため)
930 continue;
931 }
932
933 // 名前空間をセット
934 compiler.GetNamespaceSupporter().GetLivingNamespaceScopes() = objClass.GetNamespaceScopes();
935
936 DWORD dwFlags = 0;
937 if( objClass.GetName() == "_System_TypeBase" )
938 {
939 // _System_TypeBaseクラスはグローバル、スタティック領域を初期化するためのクラスなのでここでの初期化は除外する
940 dwFlags |= DIMFLAG_NONCALL_CONSTRACTOR;
941 }
942
943 // コンパイル中クラスとしてセット
944 compiler.pCompilingClass = &objClass;
945
946 const EnumInfo *pEnumInfo = NULL;
947 if( objClass.IsEnum() )
948 {
949 pEnumInfo = compiler.enumInfoCollection.Find( objClass );
950 }
951
952 int i=0;
953 BOOST_FOREACH( CMember *member, objClass.GetStaticMembers() )
954 {
955 if( pEnumInfo )
956 {
957 cp = pEnumInfo->GetEnumMember( member->GetName() ).GetSourceIndex();
958 }
959
960 char temporary[VN_SIZE];
961 sprintf(temporary,"%s.%s",objClass.GetName().c_str(),member->GetName().c_str());
962 dim(
963 temporary,
964 member->GetSubscripts(),
965 member->GetType(),
966 member->GetInitializeExpression().c_str(),
967 member->GetConstructParameter().c_str(),
968 dwFlags);
969
970 i++;
971 }
972
973 compiler.pCompilingClass = NULL;
974 }
975
976 compiler.GetNamespaceSupporter().GetLivingNamespaceScopes().clear();
977
978 cp=back_cp;
979}
980
981void Classes::Compile_System_InitializeUserTypes(){
982 char temporary[VN_SIZE];
983
984 ////////////////////////////////////////////////////////////////////
985 // クラス登録
986 ////////////////////////////////////////////////////////////////////
987
988 // イテレータをリセット
989 Iterator_Reset();
990
991 while( Iterator_HasNext() ){
992 const CClass &objClass = *Iterator_GetNext();
993
994 if( !objClass.IsUsing() ){
995 // 未使用のクラスは無視する
996 continue;
997 }
998
999 std::string referenceOffsetsBuffer;
1000 int numOfReference = 0;
1001 objClass.GetReferenceOffsetsInitializeBuffer( referenceOffsetsBuffer, numOfReference );
1002
1003 sprintf( temporary
1004 , "Add(%c%c_System_TypeForClass[strNamespace=\"%s\",name=\"%s\",fullName=\"%s\",referenceOffsets=[%s],numOfReference=%d])"
1005 , 1
1006 , ESC_SYSTEM_STATIC_NEW
1007 , objClass.GetNamespaceScopes().ToString().c_str() // 名前空間
1008 , objClass.GetName().c_str() // クラス名
1009 , objClass.GetFullName().c_str() // フルネーム
1010 , referenceOffsetsBuffer.c_str() // 参照メンバオフセット配列
1011 , numOfReference // 参照メンバの個数
1012 );
1013
1014 // コンパイル
1015 ChangeOpcode( temporary );
1016
1017 objClass.SetTypeInfoDataTableOffset(
1018 compiler.GetObjectModule().dataTable.GetLastMadeConstObjectDataTableOffset()
1019 );
1020 }
1021}
1022void Classes::Compile_System_InitializeUserTypesForBaseType()
1023{
1024 extern int cp;
1025 cp = -1;
1026 ////////////////////////////////////////////////////////////////////
1027 // 基底クラスを登録
1028 ////////////////////////////////////////////////////////////////////
1029
1030 char temporary[8192];
1031 sprintf(temporary, "%c%ctempType=Nothing%c%c_System_TypeForClass"
1032 , HIBYTE( COM_DIM )
1033 , LOBYTE( COM_DIM )
1034 , 1
1035 , ESC_AS
1036 );
1037 ChangeOpcode( temporary );
1038
1039 // イテレータをリセット
1040 Iterator_Reset();
1041
1042 while( Iterator_HasNext() ){
1043 const CClass &objClass = *Iterator_GetNext();
1044
1045 if( !objClass.IsUsing() ){
1046 // 未使用のクラスは無視する
1047 continue;
1048 }
1049
1050 if( objClass.HasSuperClass() || objClass.GetDynamicMembers().size() ){
1051 sprintf( temporary
1052 , "tempType=Search(\"%s\") As ActiveBasic.Core._System_TypeForClass"
1053 , objClass.GetFullName().c_str()
1054 );
1055
1056 // コンパイル
1057 MakeMiddleCode( temporary );
1058 ChangeOpcode( temporary );
1059
1060 sprintf( temporary
1061 , "tempType.SetClassInfo(%d,_System_GetComVtbl(%s),_System_GetVtblList(%s),_System_GetDefaultConstructor(%s),_System_GetDestructor(%s))"
1062 , objClass.GetSize()
1063 , objClass.GetFullName().c_str()
1064 , objClass.GetFullName().c_str()
1065 , objClass.GetFullName().c_str()
1066 , objClass.GetFullName().c_str()
1067 , objClass.GetName().c_str()
1068 );
1069
1070 // コンパイル
1071 ChangeOpcode( temporary );
1072
1073 if( objClass.HasSuperClass() )
1074 {
1075 sprintf( temporary
1076 , "tempType.SetBaseType(Search(\"%s\"))"
1077 , objClass.GetSuperClass().GetFullName().c_str()
1078 );
1079
1080 // コンパイル
1081 ChangeOpcode( temporary );
1082 }
1083
1084 if( objClass.GetDynamicMembers().size() )
1085 {
1086 // メンバの型を示すTypeInfoオブジェクトへのDataOffset配列の静的データ定義文字列を取得
1087 sprintf(
1088 temporary,
1089 "tempType.SetMembers([%s],[%s],[%s],%d)",
1090 objClass.GetStaticDefiningStringAsMemberNames().c_str(),
1091 objClass.GetStaticDefiningStringAsMemberTypeInfoNames().c_str(),
1092 objClass.GetStaticDefiningStringAsMemberOffsets().c_str(),
1093 objClass.GetDynamicMembers().size()
1094 );
1095 ChangeOpcode( temporary );
1096 }
1097 }
1098 }
1099}
1100
1101const CClass *Classes::Find( const NamespaceScopes &namespaceScopes, const std::string &name ) const
1102{
1103 if( namespaceScopes.size() == 0 && name == "Object" ){
1104 return GetObjectClassPtr();
1105 }
1106 else if( namespaceScopes.size() == 0 && name == "String" ){
1107 return GetStringClassPtr();
1108 }
1109
1110 std::vector<const CClass *> classes;
1111 const CClass *pClass = GetHashArrayElement( name.c_str() );
1112 while( pClass )
1113 {
1114 if( pClass->IsEqualSymbol( namespaceScopes, name ) ){
1115 //名前空間とクラス名が一致した
1116 classes.push_back( pClass );
1117 }
1118 pClass = pClass->GetChainNext();
1119 }
1120 if( classes.size() > 0 )
1121 {
1122 // 複数の名前空間の中に同一のクラス名が存在する場合があるので、アクセス可能で尚且つ階層が一番深いものをチョイスする
1123 pClass = classes.front();
1124
1125 BOOST_FOREACH( const CClass *pTempClass, classes )
1126 {
1127 if( pClass->GetNamespaceScopes().size() < pTempClass->GetNamespaceScopes().size() )
1128 {
1129 pClass = pTempClass;
1130 }
1131 }
1132
1133 return pClass;
1134 }
1135
1136 // TypeDefも見る
1137 int index = compiler.GetObjectModule().meta.GetTypeDefs().GetIndex( namespaceScopes, name );
1138 if( index != -1 ){
1139 Type type = compiler.GetObjectModule().meta.GetTypeDefs()[index].GetBaseType();
1140 if( type.IsObject() ){
1141 return &type.GetClass();
1142 }
1143 }
1144
1145 return NULL;
1146}
1147const CClass *Classes::Find( const std::string &fullName ) const
1148{
1149 char AreaName[VN_SIZE] = ""; //オブジェクト変数
1150 char NestName[VN_SIZE] = ""; //入れ子メンバ
1151 bool isNest = SplitMemberName( fullName.c_str(), AreaName, NestName );
1152
1153 return Find( NamespaceScopes( AreaName ), NestName );
1154}
1155void Classes::StartCompile( const UserProc *pUserProc ){
1156 const CClass *pParentClass = pUserProc->GetParentClassPtr();
1157 if( pParentClass ){
1158 pParentClass->Using();
1159
1160 // 仮想関数になるメソッドに使用チェックをつける
1161 BOOST_FOREACH( const CMethod *pMethod, pParentClass->GetDynamicMethods() )
1162 {
1163 if( pMethod->IsVirtual() )
1164 {
1165 pMethod->GetUserProc().Using();
1166 }
1167 }
1168
1169 pCompilingMethod = pParentClass->GetDynamicMethodOrInterfaceMethod( pUserProc );
1170 if( !pCompilingMethod ){
1171 pCompilingMethod = pParentClass->GetStaticMethods().GetMethodPtr( pUserProc );
1172 if( !pCompilingMethod ){
1173 compiler.errorMessenger.OutputFatalError();
1174 }
1175 }
1176 }
1177 else{
1178 pCompilingMethod = NULL;
1179 }
1180}
1181
1182const CClass *Classes::GetStringClassPtr() const
1183{
1184 if( !pStringClass ){
1185 // キャッシュしておく
1186 pStringClass = this->Find( NamespaceScopes( "System" ), "String" );
1187
1188 if( !pStringClass )
1189 {
1190 compiler.errorMessenger.Output(400, "System.String", cp);
1191 static CClass dummy;
1192 return &dummy;
1193 }
1194 return pStringClass;
1195 }
1196 return pStringClass;
1197}
1198const CClass *Classes::GetObjectClassPtr() const
1199{
1200 if( !pObjectClass ){
1201 // キャッシュしておく
1202 pObjectClass = this->Find( NamespaceScopes( "System" ), "Object" );
1203
1204 if( !pObjectClass )
1205 {
1206 compiler.errorMessenger.Output(400, "System.Object", cp);
1207 static CClass dummy;
1208 return &dummy;
1209 }
1210 return pObjectClass;
1211 }
1212 return pObjectClass;
1213}
1214const CClass *Classes::GetInterfaceInfoClassPtr() const
1215{
1216 if( !pInterfaceInfo ){
1217 // キャッシュしておく
1218 pInterfaceInfo = this->Find( "ActiveBasic.Core.InterfaceInfo" );
1219
1220 if( !pInterfaceInfo )
1221 {
1222 compiler.errorMessenger.Output(400, "ActiveBasic.Core.InterfaceInfo", cp);
1223 static CClass dummy;
1224 return &dummy;
1225 }
1226 return pInterfaceInfo;
1227 }
1228 return pInterfaceInfo;
1229}
1230
1231std::string CClass::GetStaticDefiningStringAsMemberNames() const
1232{
1233 std::string result;
1234
1235 BOOST_FOREACH( const CMember *pMember, dynamicMembers )
1236 {
1237 if( result.size() )
1238 {
1239 result += ",";
1240 }
1241
1242 result += "\"" + pMember->GetName() + "\"";
1243 }
1244
1245 return result;
1246}
1247std::string CClass::GetStaticDefiningStringAsMemberTypeInfoNames() const
1248{
1249 std::string result;
1250
1251 BOOST_FOREACH( const CMember *pMember, dynamicMembers )
1252 {
1253 if( result.size() )
1254 {
1255 result += ",";
1256 }
1257
1258 result += "\"" + compiler.TypeToString( pMember->GetType() ) + "\"";
1259 }
1260
1261 return result;
1262}
1263std::string CClass::GetStaticDefiningStringAsMemberOffsets() const
1264{
1265 std::string result;
1266
1267 BOOST_FOREACH( const CMember *pMember, dynamicMembers )
1268 {
1269 if( result.size() )
1270 {
1271 result += ",";
1272 }
1273
1274 int offset = this->GetMemberOffset( pMember->GetName().c_str() );
1275
1276 char temporary[255];
1277 itoa( offset, temporary, 16 );
1278
1279 result += (std::string)"&H" + temporary;
1280 }
1281
1282 return result;
1283}
1284
1285void CClass::GetReferenceOffsetsInitializeBuffer( std::string &referenceOffsetsBuffer, int &numOfReference, int baseOffset ) const
1286{
1287 const CClass &thisClass = *this;
1288 BOOST_FOREACH( const CMember *pMember, thisClass.GetDynamicMembers() )
1289 {
1290 if( pMember->GetType().IsObject() || pMember->GetType().IsPointer() )
1291 {
1292 if( referenceOffsetsBuffer.size() )
1293 {
1294 referenceOffsetsBuffer += ",";
1295 }
1296
1297 char temp[255];
1298 sprintf( temp, "%d", baseOffset + thisClass.GetMemberOffset( pMember->GetName().c_str() ) );
1299 referenceOffsetsBuffer += temp;
1300
1301 numOfReference++;
1302 }
1303 if( pMember->GetType().IsStruct() && !pMember->GetType().IsPointer() )
1304 {
1305 // 構造体の実体をメンバに持つとき
1306 int baseOffset = thisClass.GetMemberOffset( pMember->GetName().c_str() );
1307
1308 // 構造体メンバでGCによるチェックが必要な参照位置を追加
1309 pMember->GetType().GetClass().GetReferenceOffsetsInitializeBuffer( referenceOffsetsBuffer, numOfReference, baseOffset );
1310 }
1311 }
1312}
Note: See TracBrowser for help on using the repository browser.