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

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

メンバ情報を保持するようにした

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