source: dev/trunk/abdev/BasicCompiler_Common/src/Class.cpp@ 382

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

ジェネリクスインターフェイス実装時のオーバーロード解決ロジックを改良。(型パラメータを戻り値に持つメソッドのオーバーロードをミスしてしまうバグを修正)

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