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

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