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

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

Enum.cpp/Enum.hを移動した

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