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

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

StartCompileメソッドを廃止し、Usingメソッドのオーバーロードに差し替えた。

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