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

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

幾つかの構文解析系の処理をLexicalAnalyzerに実装し直した

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