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

Last change on this file since 536 was 536, checked in by dai_9181, 15 years ago

Compiler::pCompilingClassメンバをprivateにし、setter/getterにあたるメソッドを用意した。

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