source: dev/trunk/jenga/src/smoothie/Class.cpp@ 183

Last change on this file since 183 was 181, checked in by dai_9181, 17 years ago
File size: 12.3 KB
RevLine 
[172]1#include <stdlib.h>
2
3#include <jenga/include/smoothie/Smoothie.h>
4#include <jenga/include/smoothie/Class.h>
5#include <jenga/include/smoothie/SmoothieException.h>
6
7
8CClass::CClass( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const string &name )
9 : isReady( false )
10 , Prototype( namespaceScopes, name )
11 , importedNamespaces( importedNamespaces )
12 , ConstructorMemberSubIndex( 0 )
13 , DestructorMemberSubIndex( 0 )
14 , classType( Class )
15 , pobj_InheritsClass( NULL )
16 , vtblNum( 0 )
17 , iAlign( 0 )
18 , vtbl_offset( -1 )
19 , isCompilingConstructor( false )
20 , isCompilingDestructor( false )
21 , pobj_NextClass( NULL )
22{
23}
24CClass::~CClass(){
25 // 動的メンバ
26 BOOST_FOREACH( CMember *member, dynamicMembers ){
27 delete member;
28 }
29
30 // 静的メンバ
31 BOOST_FOREACH( CMember *member, staticMembers ){
32 delete member;
33 }
34}
35
36bool CClass::IsInheritsInterface( const CClass *pInterfaceClass ) const
37{
38 BOOST_FOREACH( const InheritedInterface &objInterface, interfaces ){
39 if( pInterfaceClass == &objInterface.GetInterfaceClass() ){
40 return true;
41 }
42 }
43 return false;
44}
45
46bool CClass::IsClass() const
47{
48 return classType == CClass::Class;
49}
50bool CClass::IsInterface() const
51{
52 return classType == CClass::Interface;
53}
54bool CClass::IsEnum() const
55{
56 return classType == CClass::Enum;
57}
58bool CClass::IsDelegate() const
59{
60 return classType == CClass::Delegate;
61}
62bool CClass::IsStructure() const
63{
64 return classType == CClass::Structure;
65}
66
67BOOL CClass::DupliCheckAll(const char *name){
68 //重複チェック
69
70 //メンバ
71 if(DupliCheckMember(name)) return 1;
72
73 //メソッド
74 BOOST_FOREACH( const CMethod *pMethod, methods ){
75 if( lstrcmp( name, pMethod->pUserProc->GetName().c_str() ) == 0 ){
76 return 1;
77 }
78 }
79
80 return 0;
81}
82BOOL CClass::DupliCheckMember(const char *name){
83 //重複チェック
84
85 // 動的メンバ
86 BOOST_FOREACH( CMember *pMember, dynamicMembers ){
87 if( GetName() == pMember->GetName() ){
88 return 1;
89 }
90 }
91
92 // 静的メンバ
93 BOOST_FOREACH( CMember *pMember, staticMembers ){
94 if( GetName() == pMember->GetName() ){
95 return 1;
96 }
97 }
98
99 return 0;
100}
101
102//デフォルト コンストラクタ メソッドを取得
103const CMethod *CClass::GetConstructorMethod() const
104{
105 if( ConstructorMemberSubIndex == -1 ) return NULL;
106 return methods[ConstructorMemberSubIndex];
107}
108
109//デストラクタ メソッドを取得
110const CMethod *CClass::GetDestructorMethod() const
111{
112 if( DestructorMemberSubIndex == -1 ) return NULL;
113 return methods[DestructorMemberSubIndex];
114}
115
116//サイズを取得
117int CClass::GetSize() const
118{
119 return GetMemberOffset( NULL, NULL );
120}
121
122//メンバのオフセットを取得
123int CClass::GetMemberOffset( const char *memberName, int *pMemberNum ) const
124{
125 int i2;
126
127 //仮想関数が存在する場合は関数リストへのポインタのサイズを追加
128 int offset = IsExistVirtualFunctions() ? PTR_SIZE : 0;
129
130 int alignment;
131 if(iAlign) alignment=iAlign;
132 else alignment=1;
133
134 int iMaxAlign=0;
135 int i = -1;
136 BOOST_FOREACH( CMember *pMember, dynamicMembers ){
137 i++;
138
139 i2 = pMember->GetType().GetSize();
140
141 //アラインメントを算出
142 int member_size;
143 if( pMember->GetType().IsStruct() ){
144 //メンバクラスのアラインメントを取得
145 member_size=pMember->GetType().GetClass().GetAlignment();
146 }
147 else{
148 //メンバサイズを取得
149 member_size=i2;
150 }
151 if(iMaxAlign<member_size) iMaxAlign=member_size;
152
153 //アラインメントを考慮
154 if(iAlign&&iAlign<member_size){
155 if(offset%alignment) offset+=alignment-(offset%alignment);
156 }
157 else{
158 if(alignment<member_size) alignment=member_size;
159
160 if(member_size==0){
161 //メンバを持たないクラス
162 //※何もしない(オフセットの計算をしない)
163 }
164 else{
165 if(offset%member_size) offset+=member_size-(offset%member_size);
166 }
167 }
168
169 if(memberName){
170 //メンバ指定がある場合は、オフセットを返す
171 if( pMember->GetName() == memberName ){
172 if(pMemberNum) *pMemberNum=i;
173 return offset;
174 }
175 }
176
177 //配列を考慮したメンバサイズを取得
178 member_size=i2 * Variable::GetSubScriptCounts(pMember->SubScripts);
179
180 //メンバサイズを加算
181 offset+= member_size;
182 }
183
184 if(iMaxAlign<alignment) alignment=iMaxAlign;
185
186 //アラインメントを考慮
187 if(alignment){
188 if(offset%alignment) offset+=alignment-(offset%alignment);
189 }
190
191 if(pMemberNum) *pMemberNum=i;
192 return offset;
193}
194
195int CClass::GetAlignment() const
196{
197 //仮想関数が存在する場合は関数リストへのポインタのサイズを追加
198 int alignment = IsExistVirtualFunctions() ? PTR_SIZE : 0;
199
200 BOOST_FOREACH( CMember *pMember, dynamicMembers ){
201 int member_size;
202 if(pMember->GetType().IsStruct()){
203 //メンバクラスのアラインメントを取得
204 member_size=pMember->GetType().GetClass().GetAlignment();
205 }
206 else{
207 //メンバサイズを取得
208 member_size = pMember->GetType().GetSize();
209 }
210
211 //アラインメントをセット
212 if(alignment<member_size) alignment=member_size;
213 }
214
215 if(alignment==0) return 0;
216
217 if(iAlign) alignment=iAlign;
218
219 return alignment;
220}
221
222
223
224int CClass::GetFuncNumInVtbl( const UserProc *pUserProc ) const
225{
226 int n = 0;
227 BOOST_FOREACH( const CMethod *pMethod, methods ){
228 if( pMethod->pUserProc == pUserProc ) break;
229 if( pMethod->IsVirtual() ) n++;
230 }
231 return n;
232}
233
234bool CClass::IsAbstract() const
235{
236 // 未実装(abstract)の仮想関数を持つ場合はtrueを返す
237
238 BOOST_FOREACH( const CMethod *pMethod, methods ){
239 if(pMethod->IsVirtual()){
240 if(pMethod->IsAbstract()){
241 return true;
242 }
243 }
244 }
245
246 return false;
247}
248
249// コンストラクタのコンパイルを開始
250void CClass::NotifyStartConstructorCompile() const
251{
252 isCompilingConstructor = true;
253}
254
255//コンストラクタのコンパイルを終了
256void CClass::NotifyFinishConstructorCompile() const
257{
258 isCompilingConstructor = false;
259}
260
261//コンストラクタをコンパイル中かどうかを判別
262bool CClass::IsCompilingConstructor() const
263{
264 return isCompilingConstructor;
265}
266
267//デストラクタのコンパイルを開始
268void CClass::NotifyStartDestructorCompile() const{
269 isCompilingDestructor = true;
270}
271
272//デストラクタのコンパイルを終了
273void CClass::NotifyFinishDestructorCompile() const{
274 isCompilingDestructor = false;
275}
276
277//デストラクタをコンパイル中かどうかを判別
278bool CClass::IsCompilingDestructor() const
279{
280 return isCompilingDestructor;
281}
282
283//自身の派生クラスかどうかを確認
284bool CClass::IsSubClass( const CClass *pClass ) const
285{
286 pClass = pClass->pobj_InheritsClass;
287 while( pClass ){
288 if( this == pClass ) return true;
289 pClass = pClass->pobj_InheritsClass;
290 }
291 return false;
292}
293
294//自身と等しいまたは派生クラスかどうかを確認
295bool CClass::IsEqualsOrSubClass( const CClass *pClass ) const
296{
297 if( IsEquals( pClass ) ) return true;
298 return IsSubClass( pClass );
299}
300
301// 自身と等しいまたは派生クラス、基底クラスかどうかを確認
302bool CClass::IsEqualsOrSubClassOrSuperClass( const CClass &objClass ) const
303{
304 if( IsEquals( &objClass ) ) return true;
305 if( IsSubClass( &objClass ) ) return true;
306 if( objClass.IsSubClass( this ) ) return true;
307 return false;
308}
309
310
311
312int Classes::hash(const char *name) const{
313 int key;
314
315 for(key=0;*name!='\0';name++){
316 key=((key<<8)+ *name )%MAX_CLASS_HASH;
317 }
318
319 return key;
320}
321
322void Classes::DestroyClass(CClass *pobj_c){
323 if(pobj_c->pobj_NextClass){
324 DestroyClass(pobj_c->pobj_NextClass);
325 }
326
327 delete pobj_c;
328}
329
330Classes::Classes():
331 pStringClass( NULL ),
332 pObjectClass( NULL ),
333 pCompilingClass( NULL ),
334 pCompilingMethod( NULL ),
335 ppobj_IteClass( NULL ),
336 iIteMaxNum( 0 ),
337 iIteNextNum( 0 )
338{
[181]339 memset( pobj_ClassHash, 0, MAX_CLASS_HASH * sizeof(CClass *) );
[173]340 Clear();
[172]341}
342Classes::~Classes(){
[173]343 Clear();
344}
345void Classes::Clear()
346{
[172]347 int i;
348 for(i=0;i<MAX_CLASS_HASH;i++){
349 if(pobj_ClassHash[i]) DestroyClass(pobj_ClassHash[i]);
350 }
351
[181]352 if(ppobj_IteClass)
353 {
354 free(ppobj_IteClass);
355 ppobj_IteClass = NULL;
356 }
[173]357 memset( pobj_ClassHash, 0, MAX_CLASS_HASH * sizeof(CClass *) );
[172]358}
359
360void Classes::ActionVtblSchedule(LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection){
361 int i;
362 for(i=0;i<MAX_CLASS_HASH;i++){
363 if(pobj_ClassHash[i]){
364 CClass *pobj_c;
365 pobj_c=pobj_ClassHash[i];
366 while(1){
367 pobj_c->ActionVtblSchedule(ImageBase,MemPos_CodeSection);
368
369 if(pobj_c->pobj_NextClass==0) break;
370 pobj_c=pobj_c->pobj_NextClass;
371 }
372 }
373 }
374}
375
376const CClass *Classes::Find( const NamespaceScopes &namespaceScopes, const string &name ) const
377{
378 int key;
379 key=hash(name.c_str());
380
381 if( namespaceScopes.size() == 0 && name == "Object" ){
382 return GetObjectClassPtr();
383 }
384 else if( namespaceScopes.size() == 0 && name == "String" ){
385 return GetStringClassPtr();
386 }
387
388 if(pobj_ClassHash[key]){
389 CClass *pobj_c;
390 pobj_c=pobj_ClassHash[key];
391 while(1){
392 if( pobj_c->IsEqualSymbol( namespaceScopes, name ) ){
393 //名前空間とクラス名が一致した
394 return pobj_c;
395 }
396
397 if(pobj_c->pobj_NextClass==0) break;
398 pobj_c=pobj_c->pobj_NextClass;
399 }
400 }
401
402 // TypeDefも見る
[181]403 int index = Smoothie::GetMeta().typeDefs.GetIndex( namespaceScopes, name );
[172]404 if( index != -1 ){
[181]405 Type type = Smoothie::GetMeta().typeDefs[index].GetBaseType();
[172]406 if( type.IsObject() ){
407 return &type.GetClass();
408 }
409 }
410
411 return NULL;
412}
413const CClass *Classes::Find( const string &fullName ) const
414{
415 char AreaName[VN_SIZE] = ""; //オブジェクト変数
416 char NestName[VN_SIZE] = ""; //入れ子メンバ
417 bool isNest = CClass::SplitName( fullName.c_str(), AreaName, NestName );
418
419 return Find( NamespaceScopes( AreaName ), NestName );
420}
421
[181]422CClass *Classes::Add( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name,int nowLine){
[172]423 //////////////////////////////////////////////////////////////////////////
424 // クラスを追加
425 // ※名前のみを登録。その他の情報はSetClassメソッドで!
426 //////////////////////////////////////////////////////////////////////////
427
[181]428 CClass *pobj_c = Create(namespaceScopes, importedNamespaces, name);
[172]429
430 if(lstrcmp(name,"String")==0){
431 //Stringクラス
432 pStringClass=pobj_c;
433 }
434 if( lstrcmp( name, "Object" ) == 0 ){
435 pObjectClass = pobj_c;
436 }
437
438
439 /////////////////////////////////
440 // ハッシュデータに追加
441 /////////////////////////////////
442
443 int key;
444 key=hash(name);
445
446 if(pobj_ClassHash[key]){
447 CClass *pobj_c2;
448 pobj_c2=pobj_ClassHash[key];
449 while(1){
450 if( pobj_c2->IsEqualSymbol( namespaceScopes, name ) ){
451 //名前空間及びクラス名が重複した場合
452 throw SmoothieException(15,name,nowLine);
453 return 0;
454 }
455
456 if(pobj_c2->pobj_NextClass==0) break;
457 pobj_c2=pobj_c2->pobj_NextClass;
458 }
459 pobj_c2->pobj_NextClass=pobj_c;
460 }
461 else{
462 pobj_ClassHash[key]=pobj_c;
463 }
464
465 return pobj_c;
466}
467
468
469
470CClass *Classes::GetStringClassPtr() const
471{
472 if( !pStringClass ){
473 throw SmoothieException();
474 return NULL;
475 }
476 return pStringClass;
477}
478CClass *Classes::GetObjectClassPtr() const
479{
480 if( !pObjectClass ){
481 throw SmoothieException();
482 return NULL;
483 }
484 return pObjectClass;
485}
486
487void Classes::StartCompile( UserProc *pUserProc ){
488 pCompilingClass = pUserProc->GetParentClassPtr();
489 if( pCompilingClass ){
490 pCompilingClass->Using();
491
492 pCompilingMethod = pCompilingClass->GetMethods().GetMethodPtr( pUserProc );
493 if( !pCompilingMethod ){
494 pCompilingMethod = pCompilingClass->GetStaticMethods().GetMethodPtr( pUserProc );
495 if( !pCompilingMethod ){
496 throw SmoothieException(300);
497 }
498 }
499 }
500 else{
501 pCompilingMethod = NULL;
502 }
503}
504const CClass *Classes::GetNowCompilingClass() const
505{
506 return pCompilingClass;
507}
508const CMethod *Classes::GetNowCompilingMethodInfo(){
509 return pCompilingMethod;
510}
511
512
513
514
515//////////////////////
516// イテレータ
517//////////////////////
518
519void Classes::Iterator_Init(void){
520 if(ppobj_IteClass) free(ppobj_IteClass);
521
522 iIteMaxNum=0;
523 iIteNextNum=0;
524 ppobj_IteClass=(CClass **)malloc(1);
525
526 int i;
527 for(i=0;i<MAX_CLASS_HASH;i++){
528 if(pobj_ClassHash[i]){
529 CClass *pobj_c;
530 pobj_c=pobj_ClassHash[i];
531 while(1){
532 ppobj_IteClass=(CClass **)realloc(ppobj_IteClass,(iIteMaxNum+1)*sizeof(CClass *));
533 ppobj_IteClass[iIteMaxNum]=pobj_c;
534 iIteMaxNum++;
535
536 if(pobj_c->pobj_NextClass==0) break;
537 pobj_c=pobj_c->pobj_NextClass;
538 }
539 }
540 }
541}
542void Classes::Iterator_Reset(void){
543 iIteNextNum = 0;
544}
545BOOL Classes::Iterator_HasNext(void){
546 if(iIteNextNum<iIteMaxNum) return 1;
547 return 0;
548}
549CClass *Classes::Iterator_GetNext(void){
550 CClass *pobj_c;
551 pobj_c=ppobj_IteClass[iIteNextNum];
552 iIteNextNum++;
553 return pobj_c;
554}
555int Classes::Iterator_GetMaxCount(void){
556 return iIteMaxNum;
557}
Note: See TracBrowser for help on using the repository browser.