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

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

エラーコード138をLexicalAnalyzer_Class.cppで表示するようにした。

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