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

Last change on this file since 192 was 192, checked in by dai_9181, 17 years ago
File size: 11.6 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 string &fullName ) const
377{
378 char AreaName[VN_SIZE] = ""; //オブジェクト変数
379 char NestName[VN_SIZE] = ""; //入れ子メンバ
380 bool isNest = CClass::SplitName( fullName.c_str(), AreaName, NestName );
381
382 return Find( NamespaceScopes( AreaName ), NestName );
383}
384
385bool Classes::Insert( CClass *pClass )
386{
387 /////////////////////////////////
388 // ハッシュデータに追加
389 /////////////////////////////////
390
391 int key;
392 key=GetHashCode( pClass->GetName().c_str() );
393
394 if(pobj_ClassHash[key]){
395 CClass *pobj_c2;
396 pobj_c2=pobj_ClassHash[key];
397 while(1){
398 if( pobj_c2->IsEqualSymbol( *pClass ) ){
399 //名前空間及びクラス名が重複した場合
400 SmoothieException::Throw(15,pClass->GetName());
401 return false;
402 }
403
404 if(pobj_c2->pobj_NextClass==0) break;
405 pobj_c2=pobj_c2->pobj_NextClass;
406 }
407 pobj_c2->pobj_NextClass=pClass;
408 }
409 else{
410 pobj_ClassHash[key]=pClass;
411 }
412 return true;
413}
414CClass *Classes::Add( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name,int nowLine){
415 //////////////////////////////////////////////////////////////////////////
416 // クラスを追加
417 // ※名前のみを登録。その他の情報はSetClassメソッドで!
418 //////////////////////////////////////////////////////////////////////////
419
420 CClass *pClass = Create(namespaceScopes, importedNamespaces, name);
421
422 if(lstrcmp(name,"String")==0){
423 //Stringクラス
424 pStringClass=pClass;
425 }
426 if( lstrcmp( name, "Object" ) == 0 ){
427 pObjectClass = pClass;
428 }
429
430 if( !Insert( pClass ) )
431 {
432 return NULL;
433 }
434
435 return pClass;
436}
437
438
439
440CClass *Classes::GetStringClassPtr() const
441{
442 if( !pStringClass ){
443 SmoothieException::Throw();
444 return NULL;
445 }
446 return pStringClass;
447}
448CClass *Classes::GetObjectClassPtr() const
449{
450 if( !pObjectClass ){
451 SmoothieException::Throw();
452 return NULL;
453 }
454 return pObjectClass;
455}
456
457void Classes::StartCompile( UserProc *pUserProc ){
458 pCompilingClass = pUserProc->GetParentClassPtr();
459 if( pCompilingClass ){
460 pCompilingClass->Using();
461
462 pCompilingMethod = pCompilingClass->GetMethods().GetMethodPtr( pUserProc );
463 if( !pCompilingMethod ){
464 pCompilingMethod = pCompilingClass->GetStaticMethods().GetMethodPtr( pUserProc );
465 if( !pCompilingMethod ){
466 SmoothieException::Throw(300);
467 }
468 }
469 }
470 else{
471 pCompilingMethod = NULL;
472 }
473}
474const CClass *Classes::GetNowCompilingClass() const
475{
476 return pCompilingClass;
477}
478const CMethod *Classes::GetNowCompilingMethodInfo(){
479 return pCompilingMethod;
480}
481
482
483
484
485//////////////////////
486// イテレータ
487//////////////////////
488
489void Classes::Iterator_Init() const
490{
491 if(ppobj_IteClass) free(ppobj_IteClass);
492
493 iIteMaxNum=0;
494 iIteNextNum=0;
495 ppobj_IteClass=(CClass **)malloc(1);
496
497 int i;
498 for(i=0;i<MAX_CLASS_HASH;i++){
499 if(pobj_ClassHash[i]){
500 CClass *pobj_c;
501 pobj_c=pobj_ClassHash[i];
502 while(1){
503 ppobj_IteClass=(CClass **)realloc(ppobj_IteClass,(iIteMaxNum+1)*sizeof(CClass *));
504 ppobj_IteClass[iIteMaxNum]=pobj_c;
505 iIteMaxNum++;
506
507 if(pobj_c->pobj_NextClass==0) break;
508 pobj_c=pobj_c->pobj_NextClass;
509 }
510 }
511 }
512}
513void Classes::Iterator_Reset() const
514{
515 iIteNextNum = 0;
516}
517BOOL Classes::Iterator_HasNext() const
518{
519 if(iIteNextNum<iIteMaxNum) return 1;
520 return 0;
521}
522CClass *Classes::Iterator_GetNext() const
523{
524 CClass *pobj_c;
525 pobj_c=ppobj_IteClass[iIteNextNum];
526 iIteNextNum++;
527 return pobj_c;
528}
529int Classes::Iterator_GetMaxCount() const
530{
531 return iIteMaxNum;
532}
Note: See TracBrowser for help on using the repository browser.