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

Last change on this file since 378 was 378, checked in by dai_9181, 16 years ago
File size: 33.6 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( &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( 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( pUserProc );
539 if( pMethodForOverride )
540 {
541 pMethodForOverride->Override( pUserProc, accessibility, isOverride );
542 pUserProc->SetMethod( pMethodForOverride );
543 return;
544 }
545 else
546 {
547 ts(buffer);
548 // インターフェイス メソッドのオーバーライド
549 BOOST_FOREACH( ::Interface *pInterface, pobj_c->GetInterfaces() )
550 {
551 if( interfaceName[0] )
552 {
553 if( pInterface->GetClass().GetName() != interfaceName )
554 {
555 // 指定されたインターフェイス名と整合しないとき
556 continue;
557 }
558 }
559
560 if( !pInterface->GetClass().IsReady() ){
561 // インターフェイスが未解析のとき
562 compiler.GetObjectModule().meta.GetClasses().LookaheadClass( pInterface->GetClass().GetName().c_str() );
563 }
564
565 CMethod *pMethodForOverride = pInterface->GetDynamicMethods().FindForOverride( pUserProc );
566 if( pMethodForOverride )
567 {
568 pMethodForOverride->Override( pUserProc, accessibility, isOverride );
569 pUserProc->SetMethod( pMethodForOverride );
570 return;
571 }
572 }
573 }
574
575 if( interfaceName[0] )
576 {
577 SetError(139,interfaceName,nowLine);
578 }
579
580 if( isVirtual ){
581 pobj_c->AddVtblNum( 1 );
582 }
583
584 if( isOverride ){
585 SetError(12,"Override",nowLine);
586 }
587
588 if(bStatic){
589 pobj_c->GetStaticMethods().AddStatic( pUserProc, accessibility );
590 }
591 else{
592 pobj_c->GetDynamicMethods().Add(pUserProc, accessibility, isConst, isAbstract, isVirtual);
593 }
594}
595
596bool CClass::DupliCheckAll(const char *name){
597 //重複チェック
598
599 //メンバ
600 if(DupliCheckMember(name)) return 1;
601
602 //メソッド
603 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
604 if( lstrcmp( name, pMethod->GetUserProc().GetName().c_str() ) == 0 ){
605 return 1;
606 }
607 }
608
609 return 0;
610}
611bool CClass::DupliCheckMember(const char *name){
612 //重複チェック
613
614 // 動的メンバ
615 BOOST_FOREACH( CMember *pMember, dynamicMembers ){
616 if( GetName() == pMember->GetName() ){
617 return 1;
618 }
619 }
620
621 // 静的メンバ
622 BOOST_FOREACH( CMember *pMember, staticMembers ){
623 if( GetName() == pMember->GetName() ){
624 return 1;
625 }
626 }
627
628 return 0;
629}
630
631void CClass::EnumDynamicMethodsOrInterfaceMethods( const char *methodName, std::vector<const UserProc *> &subs ) const
632{
633 // 動的メソッド
634 GetDynamicMethods().Enum( methodName, subs );
635
636 // インターフェイス メソッド
637 BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() )
638 {
639 pInterface->GetDynamicMethods().Enum( methodName, subs );
640 }
641}
642const CMethod *CClass::GetDynamicMethodOrInterfaceMethod( const UserProc *pUserProc ) const
643{
644 // 動的メソッド
645 const CMethod *result = GetDynamicMethods().GetMethodPtr( pUserProc );
646
647 if( !result )
648 {
649 // インターフェイス メソッド
650 BOOST_FOREACH( ::Interface *pInterface, GetInterfaces() )
651 {
652 result = pInterface->GetDynamicMethods().GetMethodPtr( pUserProc );
653 if( result )
654 {
655 return result;
656 }
657 }
658 }
659
660 return result;
661}
662
663const ::Delegate &CClass::GetDelegate() const
664{
665 const ::Delegate *dg = compiler.GetObjectModule().meta.GetDelegates().GetHashArrayElement( GetName().c_str() );
666 while( dg )
667 {
668 if( dg->IsEqualSymbol( GetNamespaceScopes(), GetName() ) ){
669 //名前空間とクラス名が一致した
670 return *dg;
671 }
672 dg = dg->GetChainNext();
673 }
674
675 Jenga::Throw( "CClass::GetDelegateメソッドに失敗" );
676 static ::Delegate dummy;
677 return dummy;
678}
679
680//サイズを取得
681int CClass::GetSize() const
682{
683 return GetMemberOffset( NULL, NULL );
684}
685
686//メンバのオフセットを取得
687int CClass::GetMemberOffset( const char *memberName, int *pMemberNum ) const
688{
689 int i2;
690
691 //仮想関数が存在する場合はvtbl及びvtblMasterListへのポインタのサイズを追加
692 int offset = IsExistVirtualFunctions() ? PTR_SIZE*2 : 0;
693
694 int alignment = 1;
695 if( GetFixedAlignment() )
696 {
697 alignment = GetFixedAlignment();
698 }
699
700 int iMaxAlign=0;
701 int i = -1;
702 BOOST_FOREACH( CMember *pMember, dynamicMembers ){
703 i++;
704
705 i2 = pMember->GetType().GetSize();
706
707 //アラインメントを算出
708 int member_size;
709 if( pMember->GetType().IsStruct() ){
710 //メンバクラスのアラインメントを取得
711 member_size=pMember->GetType().GetClass().GetAlignment();
712 }
713 else{
714 //メンバサイズを取得
715 member_size=i2;
716 }
717 if(iMaxAlign<member_size) iMaxAlign=member_size;
718
719 //アラインメントを考慮
720 if(GetFixedAlignment()&&GetFixedAlignment()<member_size){
721 if(offset%alignment) offset+=alignment-(offset%alignment);
722 }
723 else{
724 if(alignment<member_size) alignment=member_size;
725
726 if(member_size==0){
727 //メンバを持たないクラス
728 //※何もしない(オフセットの計算をしない)
729 }
730 else{
731 if(offset%member_size) offset+=member_size-(offset%member_size);
732 }
733 }
734
735 if(memberName){
736 //メンバ指定がある場合は、オフセットを返す
737 if( pMember->GetName() == memberName ){
738 if(pMemberNum) *pMemberNum=i;
739 return offset;
740 }
741 }
742
743 //配列を考慮したメンバサイズを取得
744 member_size = i2 * Variable::GetSubScriptCounts( pMember->GetSubscripts() );
745
746 //メンバサイズを加算
747 offset+= member_size;
748 }
749
750 if(iMaxAlign<alignment) alignment=iMaxAlign;
751
752 //アラインメントを考慮
753 if(alignment){
754 if(offset%alignment) offset+=alignment-(offset%alignment);
755 }
756
757 if(pMemberNum) *pMemberNum=i;
758 return offset;
759}
760int CClass::GetAlignment() const
761{
762 //仮想関数が存在する場合は関数リストへのポインタのサイズを追加
763 int alignment = IsExistVirtualFunctions() ? PTR_SIZE : 0;
764
765 BOOST_FOREACH( CMember *pMember, dynamicMembers ){
766 int member_size;
767 if(pMember->GetType().IsStruct()){
768 //メンバクラスのアラインメントを取得
769 member_size=pMember->GetType().GetClass().GetAlignment();
770 }
771 else{
772 //メンバサイズを取得
773 member_size = pMember->GetType().GetSize();
774 }
775
776 //アラインメントをセット
777 if(alignment<member_size) alignment=member_size;
778 }
779
780 if(alignment==0) return 0;
781
782 if(GetFixedAlignment()) alignment=GetFixedAlignment();
783
784 return alignment;
785}
786
787void CClass::GetVtblMasterListIndexAndVtblIndex( const UserProc *pUserProc, int &vtblMasterListIndex, int &vtblIndex ) const
788{
789 vtblMasterListIndex = 0;
790
791 vtblIndex = 0;
792 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
793 if( &pMethod->GetUserProc() == pUserProc )
794 {
795 return;
796 }
797
798 if( pMethod->IsVirtual() )
799 {
800 vtblIndex++;
801 }
802 }
803
804 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
805 {
806 vtblMasterListIndex++;
807
808 vtblIndex = 0;
809 BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){
810 if( &pMethod->GetUserProc() == pUserProc )
811 {
812 return;
813 }
814
815 if( pMethod->IsVirtual() )
816 {
817 vtblIndex++;
818 }
819 }
820 }
821
822 SetError();
823 return;
824}
825int CClass::GetVtblMasterListIndex( const CClass *pClass ) const
826{
827 int result = 0;
828
829 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
830 {
831 result++;
832
833 if( &pInterface->GetClass() == pClass )
834 {
835 return result;
836 }
837 }
838
839 SetError();
840 return 0;
841}
842long CClass::GetComVtblOffset() const
843{
844 return comVtblOffset;
845}
846long CClass::GetVtblMasterListOffset() const
847{
848 //既に存在する場合はそれを返す
849 if( vtblMasterListOffset == -1 )
850 {
851 SetError();
852 }
853
854 return vtblMasterListOffset;
855}
856void CClass::GenerateVTableMasterList( const std::vector<long> &vtableMasterList, long &offset )
857{
858 offset = compiler.GetObjectModule().dataTable.AddBinary(
859 (void *)&vtableMasterList[0],
860 static_cast<int>(vtableMasterList.size()*sizeof(LONG_PTR))
861 );
862}
863void CClass::GenerateFullVTables()
864{
865 if( IsAbstract() )
866 {
867 // 抽象クラスは無視
868 return;
869 }
870 if( !IsUsing() )
871 {
872 // 使われていないクラスは無視
873 return;
874 }
875
876 // vtblマスターリストの元データに不要なデータが含まれていたらエラー
877 if( vtblMasterList.size() )
878 {
879 SetError();
880 }
881
882 // 自身のクラスのvtblを生成
883 GetDynamicMethods().GenerateVTablePart( this->vtbl_offset );
884 vtblMasterList.push_back( this->vtbl_offset );
885
886 // インターフェイスのvtblを生成
887 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
888 {
889 long tempVtblOffset;
890 pInterface->GetDynamicMethods().GenerateVTablePart( tempVtblOffset );
891 vtblMasterList.push_back( tempVtblOffset );
892
893 pInterface->SetVtblOffset( tempVtblOffset );
894
895 if( pInterface->GetClass().IsComInterface() )
896 {
897 if( this->comVtblOffset )
898 {
899 SetError();
900 }
901 this->comVtblOffset = tempVtblOffset;
902 }
903 }
904
905 // vtblマスターリストを生成
906 GenerateVTableMasterList( vtblMasterList, this->vtblMasterListOffset );
907}
908void CClass::ActionVtblSchedule( LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection, LONG_PTR MemPos_DataSection )
909{
910 if( IsAbstract() )
911 {
912 // 抽象クラスは無視
913 return;
914 }
915 if( !IsUsing() )
916 {
917 // 使われていないクラスは無視
918 return;
919 }
920 if(vtbl_offset==-1) return;
921
922 // 自身のクラスのvtbl
923 {
924 LONG_PTR *pVtbl = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + vtbl_offset);
925
926 for( int i=0; i<GetVtblNum(); i++ ){
927 const UserProc *pUserProc = (UserProc *)pVtbl[i];
928 if(!pUserProc) continue;
929
930 if( pUserProc->GetBeginOpAddress() == 0
931 && pUserProc->GetEndOpAddress() == 0 )
932 {
933 Jenga::Throw( "未解決の仮想関数が存在する" );
934 }
935
936 pVtbl[i] = pUserProc->GetBeginOpAddress() + ImageBase + MemPos_CodeSection;
937 }
938 }
939
940 // インターフェイスのvtbl
941 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
942 {
943 LONG_PTR *pVtbl = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + pInterface->GetVtblOffset());
944
945 for( int i=0; i<pInterface->GetClass().GetVtblNum(); i++ ){
946 const UserProc *pUserProc = (UserProc *)pVtbl[i];
947 if(!pUserProc) continue;
948
949 if( pUserProc->GetBeginOpAddress() == 0
950 && pUserProc->GetEndOpAddress() == 0 )
951 {
952 Jenga::Throw( "未解決の仮想関数が存在する" );
953 }
954
955 pVtbl[i] = pUserProc->GetBeginOpAddress() + ImageBase + MemPos_CodeSection;
956 }
957 }
958
959 // vtblマスターリスト
960 LONG_PTR *pVtblMasterList = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + vtblMasterListOffset );
961 for( int i=0; i<static_cast<int>(vtblMasterList.size()); i++ )
962 {
963 pVtblMasterList[i] = vtblMasterList[i] + ImageBase + MemPos_DataSection;
964 }
965}
966bool CClass::IsAbstract() const
967{
968 // 未実装(abstract)の仮想関数を持つ場合はtrueを返す
969
970 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
971 if(pMethod->IsVirtual()){
972 if(pMethod->IsAbstract()){
973 return true;
974 }
975 }
976 }
977
978 // インターフェイスのvtbl
979 BOOST_FOREACH( const ::Interface *pInterface, interfaces )
980 {
981 BOOST_FOREACH( const CMethod *pMethod, pInterface->GetDynamicMethods() ){
982 if(pMethod->IsVirtual()){
983 if(pMethod->IsAbstract()){
984 return true;
985 }
986 }
987 }
988 }
989
990 return false;
991}
992
993CClass *Classes::Create( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name){
994 return new CClass(namespaceScopes, importedNamespaces, name);
995}
996bool Classes::Insert( CClass *pClass, int nowLine )
997{
998 /////////////////////////////////
999 // ハッシュデータに追加
1000 /////////////////////////////////
1001
1002 if( !Put( pClass ) )
1003 {
1004 SetError(15,pClass->GetName(), nowLine);
1005 return false;
1006 }
1007 return true;
1008}
1009CClass *Classes::Add( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name,int nowLine){
1010 //////////////////////////////////////////////////////////////////////////
1011 // クラスを追加
1012 // ※名前のみを登録。その他の情報はSetClassメソッドで!
1013 //////////////////////////////////////////////////////////////////////////
1014
1015 CClass *pClass = Create(namespaceScopes, importedNamespaces, name);
1016
1017 if( !Insert( pClass, nowLine ) )
1018 {
1019 return NULL;
1020 }
1021
1022 return pClass;
1023}
1024
1025void Classes::GenerateVTables()
1026{
1027 Iterator_Reset();
1028 while( Iterator_HasNext() )
1029 {
1030 CClass *pClass = Iterator_GetNext();
1031 pClass->GenerateFullVTables();
1032 }
1033}
1034
1035void Classes::ActionVtblSchedule( LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection, LONG_PTR MemPos_DataSection ){
1036 Iterator_Reset();
1037 while( Iterator_HasNext() )
1038 {
1039 CClass *pClass = Iterator_GetNext();
1040 pClass->ActionVtblSchedule( ImageBase, MemPos_CodeSection, MemPos_DataSection);
1041 }
1042}
1043
1044
1045void Classes::InitStaticMember(){
1046 //静的メンバをグローバル領域に作成
1047
1048 //イテレータをリセット
1049
1050 extern int cp;
1051 int back_cp=cp;
1052
1053 this->Iterator_Reset();
1054 while(this->Iterator_HasNext()){
1055 CClass &objClass = *this->Iterator_GetNext();
1056 if( objClass.isTargetObjectModule == false )
1057 {
1058 // 静的リンクライブラリの場合は飛ばす(既にインスタンスが定義済みであるため)
1059 continue;
1060 }
1061
1062 // 名前空間をセット
1063 compiler.GetNamespaceSupporter().GetLivingNamespaceScopes() = objClass.GetNamespaceScopes();
1064
1065 DWORD dwFlags = 0;
1066 if( objClass.GetName() == "_System_TypeBase" )
1067 {
1068 // _System_TypeBaseクラスはグローバル、スタティック領域を初期化するためのクラスなのでここでの初期化は除外する
1069 dwFlags |= DIMFLAG_NONCALL_CONSTRACTOR;
1070 }
1071
1072 int i=0;
1073 BOOST_FOREACH( CMember *member, objClass.GetStaticMembers() ){
1074 char temporary[VN_SIZE];
1075 sprintf(temporary,"%s.%s",objClass.GetName().c_str(),member->GetName().c_str());
1076 dim(
1077 temporary,
1078 member->GetSubscripts(),
1079 member->GetType(),
1080 member->GetInitializeExpression().c_str(),
1081 member->GetConstructParameter().c_str(),
1082 dwFlags);
1083
1084 i++;
1085 }
1086 }
1087
1088 compiler.GetNamespaceSupporter().GetLivingNamespaceScopes().clear();
1089
1090 cp=back_cp;
1091}
1092
1093void Classes::Compile_System_InitializeUserTypes(){
1094 char temporary[VN_SIZE];
1095
1096 ////////////////////////////////////////////////////////////////////
1097 // クラス登録
1098 ////////////////////////////////////////////////////////////////////
1099
1100 // イテレータをリセット
1101 Iterator_Reset();
1102
1103 while( Iterator_HasNext() ){
1104 const CClass &objClass = *Iterator_GetNext();
1105
1106 if( !objClass.IsUsing() ){
1107 // 未使用のクラスは無視する
1108 continue;
1109 }
1110
1111 char referenceOffsetsBuffer[1024] = "";
1112 int numOfReference = 0;
1113 BOOST_FOREACH( CMember *pMember, objClass.GetDynamicMembers() ){
1114 if( pMember->GetType().IsObject() || pMember->GetType().IsPointer() ){
1115 if( referenceOffsetsBuffer[0] ){
1116 lstrcat( referenceOffsetsBuffer, "," );
1117 }
1118
1119 sprintf( referenceOffsetsBuffer + lstrlen( referenceOffsetsBuffer ),
1120 "%d",
1121 objClass.GetMemberOffset( pMember->GetName().c_str() ) );
1122
1123 numOfReference++;
1124 }
1125 }
1126
1127 sprintf( temporary
1128 , "Add(%c%c_System_TypeForClass[strNamespace=\"%s\",name=\"%s\",fullName=\"%s\",referenceOffsets=[%s],numOfReference=%d])"
1129 , 1
1130 , ESC_SYSTEM_STATIC_NEW
1131 , objClass.GetNamespaceScopes().ToString().c_str() // 名前空間
1132 , objClass.GetName().c_str() // クラス名
1133 , objClass.GetFullName().c_str() // フルネーム
1134 , referenceOffsetsBuffer // 参照メンバオフセット配列
1135 , numOfReference // 参照メンバの個数
1136 );
1137
1138 // コンパイル
1139 ChangeOpcode( temporary );
1140
1141 objClass.SetTypeInfoDataTableOffset(
1142 compiler.GetObjectModule().dataTable.GetLastMadeConstObjectDataTableOffset()
1143 );
1144 }
1145}
1146void Classes::Compile_System_InitializeUserTypesForBaseType()
1147{
1148 extern int cp;
1149 cp = -1;
1150 ////////////////////////////////////////////////////////////////////
1151 // 基底クラスを登録
1152 ////////////////////////////////////////////////////////////////////
1153
1154 char temporary[VN_SIZE];
1155 sprintf(temporary, "%c%ctempType=Nothing%c%cTypeBaseImpl"
1156 , HIBYTE( COM_DIM )
1157 , LOBYTE( COM_DIM )
1158 , 1
1159 , ESC_AS
1160 );
1161 ChangeOpcode( temporary );
1162
1163 // イテレータをリセット
1164 Iterator_Reset();
1165
1166 while( Iterator_HasNext() ){
1167 const CClass &objClass = *Iterator_GetNext();
1168
1169 if( !objClass.IsUsing() ){
1170 // 未使用のクラスは無視する
1171 continue;
1172 }
1173
1174 if( objClass.HasSuperClass() ){
1175 sprintf( temporary
1176 , "tempType=Search(\"%s\")"
1177 , objClass.GetFullName().c_str()
1178 );
1179
1180 // コンパイル
1181 ChangeOpcode( temporary );
1182
1183 sprintf( temporary
1184 , "tempType.SetBaseType(Search(\"%s\"))"
1185 , objClass.GetSuperClass().GetFullName().c_str()
1186 );
1187
1188 // コンパイル
1189 ChangeOpcode( temporary );
1190 }
1191 }
1192
1193
1194
1195 ////////////////////////////////////////////////////////////////////
1196 // 継承関係登録
1197 ////////////////////////////////////////////////////////////////////
1198 // TODO: 未完成
1199 /*
1200
1201 // イテレータをリセット
1202 Iterator_Reset();
1203
1204 while( Iterator_HasNext() ){
1205 CClass *pClass = Iterator_GetNext();
1206
1207 sprintf( genBuffer + length
1208 , "obj.Search( \"%s\" ).SetBaseType( Search( \"%s\" ) ):"
1209 , "" // クラス名
1210 , pClass->name // クラス名
1211 );
1212 length += lstrlen( genBuffer + length );
1213
1214 while( length + 8192 > max ){
1215 max += 8192;
1216 genBuffer = (char *)realloc( genBuffer, max );
1217 }
1218 }*/
1219}
1220
1221const CClass *Classes::Find( const NamespaceScopes &namespaceScopes, const string &name ) const
1222{
1223 if( namespaceScopes.size() == 0 && name == "Object" ){
1224 return GetObjectClassPtr();
1225 }
1226 else if( namespaceScopes.size() == 0 && name == "String" ){
1227 return GetStringClassPtr();
1228 }
1229
1230 const CClass *pClass = GetHashArrayElement( name.c_str() );
1231 while( pClass )
1232 {
1233 if( pClass->IsEqualSymbol( namespaceScopes, name ) ){
1234 //名前空間とクラス名が一致した
1235 return pClass;
1236 }
1237 pClass = pClass->GetChainNext();
1238 }
1239
1240 // TypeDefも見る
1241 int index = compiler.GetObjectModule().meta.GetTypeDefs().GetIndex( namespaceScopes, name );
1242 if( index != -1 ){
1243 Type type = compiler.GetObjectModule().meta.GetTypeDefs()[index].GetBaseType();
1244 if( type.IsObject() ){
1245 return &type.GetClass();
1246 }
1247 }
1248
1249 return NULL;
1250}
1251const CClass *Classes::Find( const string &fullName ) const
1252{
1253 char AreaName[VN_SIZE] = ""; //オブジェクト変数
1254 char NestName[VN_SIZE] = ""; //入れ子メンバ
1255 bool isNest = SplitMemberName( fullName.c_str(), AreaName, NestName );
1256
1257 return Find( NamespaceScopes( AreaName ), NestName );
1258}
1259void Classes::StartCompile( const UserProc *pUserProc ){
1260 const CClass *pParentClass = pUserProc->GetParentClassPtr();
1261 if( pParentClass ){
1262 pParentClass->Using();
1263
1264 // 仮想関数になるメソッドに使用チェックをつける
1265 BOOST_FOREACH( const CMethod *pMethod, pParentClass->GetDynamicMethods() )
1266 {
1267 if( pMethod->IsVirtual() )
1268 {
1269 pMethod->GetUserProc().Using();
1270 }
1271 }
1272
1273 pCompilingMethod = pParentClass->GetDynamicMethodOrInterfaceMethod( pUserProc );
1274 if( !pCompilingMethod ){
1275 pCompilingMethod = pParentClass->GetStaticMethods().GetMethodPtr( pUserProc );
1276 if( !pCompilingMethod ){
1277 SmoothieException::Throw(300);
1278 }
1279 }
1280 }
1281 else{
1282 pCompilingMethod = NULL;
1283 }
1284}
1285
1286const CClass *Classes::GetStringClassPtr() const
1287{
1288 if( !pStringClass ){
1289 // キャッシュしておく
1290 pStringClass = this->Find( NamespaceScopes( "System" ), "String" );
1291
1292 if( !pStringClass )
1293 {
1294 SetError(400, "System.String", cp);
1295 static CClass dummy;
1296 return &dummy;
1297 }
1298 return pStringClass;
1299 }
1300 return pStringClass;
1301}
1302const CClass *Classes::GetObjectClassPtr() const
1303{
1304 if( !pObjectClass ){
1305 // キャッシュしておく
1306 pObjectClass = this->Find( NamespaceScopes( "System" ), "Object" );
1307
1308 if( !pObjectClass )
1309 {
1310 SetError(400, "System.Object", cp);
1311 static CClass dummy;
1312 return &dummy;
1313 }
1314 return pObjectClass;
1315 }
1316 return pObjectClass;
1317}
1318const CClass *Classes::GetInterfaceInfoClassPtr() const
1319{
1320 if( !pInterfaceInfo ){
1321 // キャッシュしておく
1322 pInterfaceInfo = this->Find( "ActiveBasic.Core.InterfaceInfo" );
1323
1324 if( !pInterfaceInfo )
1325 {
1326 SetError(400, "ActiveBasic.Core.InterfaceInfo", cp);
1327 static CClass dummy;
1328 return &dummy;
1329 }
1330 return pInterfaceInfo;
1331 }
1332 return pInterfaceInfo;
1333}
Note: See TracBrowser for help on using the repository browser.