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, 15 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.