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

Last change on this file since 190 was 190, checked in by dai_9181, 17 years ago
File size: 12.5 KB
Line 
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( -1 )
13 , DestructorMemberSubIndex( -1 )
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::GetHashCode(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{
339 memset( pobj_ClassHash, 0, MAX_CLASS_HASH * sizeof(CClass *) );
340 Clear();
341}
342Classes::~Classes(){
343 Clear();
344}
345void Classes::Clear()
346{
347 int i;
348 for(i=0;i<MAX_CLASS_HASH;i++){
349 if(pobj_ClassHash[i]) DestroyClass(pobj_ClassHash[i]);
350 }
351
352 if(ppobj_IteClass)
353 {
354 free(ppobj_IteClass);
355 ppobj_IteClass = NULL;
356 }
357 memset( pobj_ClassHash, 0, MAX_CLASS_HASH * sizeof(CClass *) );
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=GetHashCode(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も見る
403 int index = Smoothie::GetMeta().typeDefs.GetIndex( namespaceScopes, name );
404 if( index != -1 ){
405 Type type = Smoothie::GetMeta().typeDefs[index].GetBaseType();
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
422bool Classes::Insert( CClass *pClass )
423{
424 /////////////////////////////////
425 // ハッシュデータに追加
426 /////////////////////////////////
427
428 int key;
429 key=GetHashCode( pClass->GetName().c_str() );
430
431 if(pobj_ClassHash[key]){
432 CClass *pobj_c2;
433 pobj_c2=pobj_ClassHash[key];
434 while(1){
435 if( pobj_c2->IsEqualSymbol( *pClass ) ){
436 //名前空間及びクラス名が重複した場合
437 SmoothieException::Throw(15,pClass->GetName());
438 return false;
439 }
440
441 if(pobj_c2->pobj_NextClass==0) break;
442 pobj_c2=pobj_c2->pobj_NextClass;
443 }
444 pobj_c2->pobj_NextClass=pClass;
445 }
446 else{
447 pobj_ClassHash[key]=pClass;
448 }
449 return true;
450}
451CClass *Classes::Add( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name,int nowLine){
452 //////////////////////////////////////////////////////////////////////////
453 // クラスを追加
454 // ※名前のみを登録。その他の情報はSetClassメソッドで!
455 //////////////////////////////////////////////////////////////////////////
456
457 CClass *pClass = Create(namespaceScopes, importedNamespaces, name);
458
459 if(lstrcmp(name,"String")==0){
460 //Stringクラス
461 pStringClass=pClass;
462 }
463 if( lstrcmp( name, "Object" ) == 0 ){
464 pObjectClass = pClass;
465 }
466
467 if( !Insert( pClass ) )
468 {
469 return NULL;
470 }
471
472 return pClass;
473}
474
475
476
477CClass *Classes::GetStringClassPtr() const
478{
479 if( !pStringClass ){
480 SmoothieException::Throw();
481 return NULL;
482 }
483 return pStringClass;
484}
485CClass *Classes::GetObjectClassPtr() const
486{
487 if( !pObjectClass ){
488 SmoothieException::Throw();
489 return NULL;
490 }
491 return pObjectClass;
492}
493
494void Classes::StartCompile( UserProc *pUserProc ){
495 pCompilingClass = pUserProc->GetParentClassPtr();
496 if( pCompilingClass ){
497 pCompilingClass->Using();
498
499 pCompilingMethod = pCompilingClass->GetMethods().GetMethodPtr( pUserProc );
500 if( !pCompilingMethod ){
501 pCompilingMethod = pCompilingClass->GetStaticMethods().GetMethodPtr( pUserProc );
502 if( !pCompilingMethod ){
503 SmoothieException::Throw(300);
504 }
505 }
506 }
507 else{
508 pCompilingMethod = NULL;
509 }
510}
511const CClass *Classes::GetNowCompilingClass() const
512{
513 return pCompilingClass;
514}
515const CMethod *Classes::GetNowCompilingMethodInfo(){
516 return pCompilingMethod;
517}
518
519
520
521
522//////////////////////
523// イテレータ
524//////////////////////
525
526void Classes::Iterator_Init() const
527{
528 if(ppobj_IteClass) free(ppobj_IteClass);
529
530 iIteMaxNum=0;
531 iIteNextNum=0;
532 ppobj_IteClass=(CClass **)malloc(1);
533
534 int i;
535 for(i=0;i<MAX_CLASS_HASH;i++){
536 if(pobj_ClassHash[i]){
537 CClass *pobj_c;
538 pobj_c=pobj_ClassHash[i];
539 while(1){
540 ppobj_IteClass=(CClass **)realloc(ppobj_IteClass,(iIteMaxNum+1)*sizeof(CClass *));
541 ppobj_IteClass[iIteMaxNum]=pobj_c;
542 iIteMaxNum++;
543
544 if(pobj_c->pobj_NextClass==0) break;
545 pobj_c=pobj_c->pobj_NextClass;
546 }
547 }
548 }
549}
550void Classes::Iterator_Reset() const
551{
552 iIteNextNum = 0;
553}
554BOOL Classes::Iterator_HasNext() const
555{
556 if(iIteNextNum<iIteMaxNum) return 1;
557 return 0;
558}
559CClass *Classes::Iterator_GetNext() const
560{
561 CClass *pobj_c;
562 pobj_c=ppobj_IteClass[iIteNextNum];
563 iIteNextNum++;
564 return pobj_c;
565}
566int Classes::Iterator_GetMaxCount() const
567{
568 return iIteMaxNum;
569}
Note: See TracBrowser for help on using the repository browser.