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

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

Overrideメソッド内で発生したエラーのエラーメッセージ表示処理は呼び出し元で行うようにした。

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