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

Last change on this file since 342 was 342, checked in by dai_9181, 17 years ago

vtblの構造を変更。vtblMasterListをはさんでvtblを表現した。
その他メンバ名変更。
ClassPrototypeクラスを追加。

File size: 48.0 KB
Line 
1#include "stdafx.h"
2
3#include <jenga/include/smoothie/Smoothie.h>
4#include <jenga/include/smoothie/SmoothieException.h>
5#include <jenga/include/smoothie/LexicalAnalysis.h>
6
7#include <Source.h>
8#include <Class.h>
9#include <Compiler.h>
10#include <NamespaceSupporter.h>
11
12#include "../common.h"
13#ifdef _AMD64_
14#include "../../BasicCompiler64/opcode.h"
15#else
16#include "../../BasicCompiler32/opcode.h"
17#endif
18
19
20class CLoopRefCheck{
21 char **names;
22 int num;
23 void init(){
24 int i;
25 for(i=0;i<num;i++){
26 free(names[i]);
27 }
28 free(names);
29 }
30public:
31 CLoopRefCheck()
32 {
33 names=(char **)malloc(1);
34 num=0;
35 }
36 ~CLoopRefCheck()
37 {
38 init();
39 }
40 void add(const char *lpszInheritsClass)
41 {
42 names=(char **)realloc(names,(num+1)*sizeof(char *));
43 names[num]=(char *)malloc(lstrlen(lpszInheritsClass)+1);
44 lstrcpy(names[num],lpszInheritsClass);
45 num++;
46 }
47 void del(const char *lpszInheritsClass)
48 {
49 int i;
50 for(i=0;i<num;i++){
51 if(lstrcmp(names[i],lpszInheritsClass)==0){
52 free(names[i]);
53 break;
54 }
55 }
56 if(i!=num){
57 num--;
58 for(;i<num;i++){
59 names[i]=names[i+1];
60 }
61 }
62 }
63 BOOL check(const CClass &inheritsClass) const
64 {
65 //ループ継承チェック
66 int i;
67 for(i=0;i<num;i++){
68 if( inheritsClass.GetName() == names[i] ){
69 return 1;
70 }
71 }
72 return 0;
73 }
74};
75CLoopRefCheck *pobj_LoopRefCheck;
76
77
78bool CClass::IsClass() const
79{
80 return classType == CClass::Class;
81}
82bool CClass::IsInterface() const
83{
84 return classType == CClass::Interface;
85}
86bool CClass::IsEnum() const
87{
88 return classType == CClass::Enum;
89}
90bool CClass::IsDelegate() const
91{
92 return classType == CClass::Delegate;
93}
94bool CClass::IsStructure() const
95{
96 return classType == CClass::Structure;
97}
98
99
100// コンストラクタのコンパイルを開始
101void CClass::NotifyStartConstructorCompile() const
102{
103 isCompilingConstructor = true;
104}
105
106//コンストラクタのコンパイルを終了
107void CClass::NotifyFinishConstructorCompile() const
108{
109 isCompilingConstructor = false;
110}
111
112//コンストラクタをコンパイル中かどうかを判別
113bool CClass::IsCompilingConstructor() const
114{
115 return isCompilingConstructor;
116}
117
118//デストラクタのコンパイルを開始
119void CClass::NotifyStartDestructorCompile() const{
120 isCompilingDestructor = true;
121}
122
123//デストラクタのコンパイルを終了
124void CClass::NotifyFinishDestructorCompile() const{
125 isCompilingDestructor = false;
126}
127
128//デストラクタをコンパイル中かどうかを判別
129bool CClass::IsCompilingDestructor() const
130{
131 return isCompilingDestructor;
132}
133
134//自身の派生クラスかどうかを確認
135bool CClass::IsSubClass( const CClass *pClass ) const
136{
137 if( !pClass->HasSuperClass() )
138 {
139 return false;
140 }
141
142 const CClass *pTempClass = &pClass->GetSuperClass();
143 while( pTempClass ){
144 if( this == pTempClass ) return true;
145 pTempClass = &pTempClass->GetSuperClass();
146 }
147 return false;
148}
149
150//自身と等しいまたは派生クラスかどうかを確認
151bool CClass::IsEqualsOrSubClass( const CClass *pClass ) const
152{
153 if( IsEquals( pClass ) ) return true;
154 return IsSubClass( pClass );
155}
156
157// 自身と等しいまたは派生クラス、基底クラスかどうかを確認
158bool CClass::IsEqualsOrSubClassOrSuperClass( const CClass &objClass ) const
159{
160 if( IsEquals( &objClass ) ) return true;
161 if( IsSubClass( &objClass ) ) return true;
162 if( objClass.IsSubClass( this ) ) return true;
163 return false;
164}
165
166bool CClass::IsInheritsInterface( const CClass *pInterfaceClass ) const
167{
168 BOOST_FOREACH( const ::Interface &objInterface, interfaces ){
169 if( pInterfaceClass == &objInterface.GetClass() ){
170 return true;
171 }
172 }
173 return false;
174}
175
176bool CClass::Inherits( const char *inheritNames, int nowLine ){
177 int i = 0;
178 bool isInheritsClass = false;
179 while( true ){
180
181 char temporary[VN_SIZE];
182 for( int i2=0;; i++, i2++ ){
183 if( inheritNames[i] == '\0' || inheritNames[i] == ',' ){
184 temporary[i2] = 0;
185 break;
186 }
187 temporary[i2] = inheritNames[i];
188 }
189
190 // ジェネリクス構文を分解
191 char className[VN_SIZE];
192 Jenga::Common::Strings typeParameterStrings;
193 SplitGenericClassInstance( temporary, className, typeParameterStrings );
194
195 // 型パラメータ文字列から型データを取得
196 std::vector<Type> actualTypeParameters;
197 BOOST_FOREACH( const std::string &typeParameterStr, typeParameterStrings )
198 {
199 Type type;
200 compiler.StringToType( typeParameterStr, type );
201 actualTypeParameters.push_back( type );
202 }
203
204 //継承元クラスを取得
205 const CClass *pInheritsClass = compiler.GetObjectModule().meta.GetClasses().Find(className);
206 if( !pInheritsClass ){
207 SmoothieException::Throw(106,className,nowLine);
208 return false;
209 }
210
211 if( pInheritsClass->IsInterface() ){
212 // インターフェイスはあとで継承する
213 }
214 else if( pInheritsClass->IsClass() ){
215 // クラスを継承する
216 isInheritsClass = true;
217
218 if( !InheritsClass( *pInheritsClass, actualTypeParameters, nowLine ) ){
219 return false;
220 }
221 }
222 else{
223 SmoothieException::Throw(135,NULL,nowLine);
224 return false;
225 }
226
227 if( inheritNames[i] == '\0' ){
228 break;
229 }
230 i++;
231 }
232
233 if( !isInheritsClass ){
234 // クラスを一つも継承していないとき
235 if( !InheritsClass( *compiler.GetObjectModule().meta.GetClasses().GetObjectClassPtr(), Types(), nowLine ) ){
236 return false;
237 }
238 }
239
240 i=0;
241 while( true ){
242
243 char temporary[VN_SIZE];
244 for( int i2=0;; i++, i2++ ){
245 if( inheritNames[i] == '\0' || inheritNames[i] == ',' ){
246 temporary[i2] = 0;
247 break;
248 }
249 temporary[i2] = inheritNames[i];
250 }
251
252 char className[VN_SIZE];
253 Jenga::Common::Strings typeParameters;
254 SplitGenericClassInstance( temporary, className, typeParameters );
255
256 //継承元クラスを取得
257 const CClass *pInheritsClass = compiler.GetObjectModule().meta.GetClasses().Find(className);
258 if( !pInheritsClass ){
259 SmoothieException::Throw(106,className,nowLine);
260 return false;
261 }
262
263 if( pInheritsClass->IsInterface() ){
264 // インターフェイスを継承する
265 if( !InheritsInterface( *pInheritsClass, nowLine ) ){
266 return false;
267 }
268 }
269 else if( pInheritsClass->IsClass() ){
270 // クラスはさっき継承した
271 }
272 else{
273 SmoothieException::Throw(135,NULL,nowLine);
274 return false;
275 }
276
277 if( inheritNames[i] == '\0' ){
278 break;
279 }
280 i++;
281 }
282
283 return true;
284}
285bool CClass::InheritsClass( const CClass &inheritsClass, const Types &actualTypeParameters, int nowLine ){
286
287 //ループ継承でないかをチェック
288 if(pobj_LoopRefCheck->check(inheritsClass)){
289 SmoothieException::Throw(123,inheritsClass.GetName(),nowLine);
290 return false;
291 }
292
293 if( !inheritsClass.IsReady() ){
294 //継承先が読み取られていないとき
295 pobj_LoopRefCheck->add(this->GetName().c_str());
296 compiler.GetObjectModule().meta.GetClasses().GetClass_recur(inheritsClass.GetName().c_str());
297 pobj_LoopRefCheck->del(this->GetName().c_str());
298 }
299
300 //メンバをコピー
301 BOOST_FOREACH( CMember *inheritsClassDynamicMember, inheritsClass.GetDynamicMembers() ){
302 CMember *pMember = new CMember( *inheritsClassDynamicMember );
303
304 // アクセシビリティ
305 if( inheritsClassDynamicMember->IsPrivate() ){
306 pMember->SetAccessibility( Prototype::None );
307 }
308 else{
309 pMember->SetAccessibility( inheritsClassDynamicMember->GetAccessibility() );
310 }
311
312 // メンバのみ、型パラメータを解決する(メソッドのほうは呼び出し時に解決する)
313 if( pMember->GetType().IsTypeParameter() )
314 {
315 pMember->ResetType( actualTypeParameters[pMember->GetType().GetFormalTypeIndex()] );
316 }
317
318 dynamicMembers.push_back( pMember );
319 }
320
321 //メソッドをコピー
322 BOOST_FOREACH( const CMethod *pBaseMethod, inheritsClass.GetDynamicMethods() ){
323 CMethod *pMethod = new DynamicMethod( *pBaseMethod );
324
325 // アクセシビリティ
326 if(pBaseMethod->GetAccessibility() == Prototype::Private){
327 pMethod->SetAccessibility( Prototype::None );
328 }
329 else{
330 pMethod->SetAccessibility( pBaseMethod->GetAccessibility() );
331 }
332
333 //pobj_Inherits
334 // ※継承元のClassIndexをセット(入れ子継承を考慮する)
335 if(pBaseMethod->GetInheritsClassPtr()==0){
336 pMethod->SetInheritsClassPtr( &inheritsClass );
337 }
338 else{
339 pMethod->SetInheritsClassPtr( pBaseMethod->GetInheritsClassPtr() );
340 }
341
342 GetDynamicMethods().push_back( pMethod );
343 }
344
345 //仮想関数の数
346 AddVtblNum( inheritsClass.GetVtblNum() );
347
348 //継承先のクラスをメンバとして保持する
349 SetSuperClass( &inheritsClass );
350 SetSuperClassActualTypeParameters( actualTypeParameters );
351
352 return true;
353}
354bool CClass::InheritsInterface( const CClass &inheritsInterface, int nowLine ){
355
356 //ループ継承でないかをチェック
357 if(pobj_LoopRefCheck->check(inheritsInterface)){
358 SmoothieException::Throw(123,inheritsInterface.GetName(),nowLine);
359 return false;
360 }
361
362 if( !inheritsInterface.IsReady() ){
363 //継承先が読み取られていないとき
364 pobj_LoopRefCheck->add(this->GetName().c_str());
365 compiler.GetObjectModule().meta.GetClasses().GetClass_recur(inheritsInterface.GetName().c_str());
366 pobj_LoopRefCheck->del(this->GetName().c_str());
367 }
368
369 //メソッドをコピー
370 BOOST_FOREACH( const CMethod *pBaseMethod, inheritsInterface.GetDynamicMethods() ){
371 CMethod *pMethod = new DynamicMethod( *pBaseMethod );
372
373 // アクセシビリティ
374 if(pBaseMethod->GetAccessibility() == Prototype::Private){
375 pMethod->SetAccessibility( Prototype::None );
376 }
377 else{
378 pMethod->SetAccessibility( pBaseMethod->GetAccessibility() );
379 }
380
381 //pobj_Inherits
382 // ※継承元のClassIndexをセット(入れ子継承を考慮する)
383 if(pBaseMethod->GetInheritsClassPtr()==0){
384 pMethod->SetInheritsClassPtr( &inheritsInterface );
385 }
386 else{
387 pMethod->SetInheritsClassPtr( pBaseMethod->GetInheritsClassPtr() );
388 }
389
390 GetDynamicMethods().push_back( pMethod );
391 }
392
393 //interfaces.push_back( Interface( &inheritsInterface, vtblNum ) );
394
395 //仮想関数の数
396 AddVtblNum( inheritsInterface.GetVtblNum() );
397
398 return true;
399}
400
401bool CClass::Implements( const CClass &interfaceClass, int nowLine )
402{
403 if( !interfaceClass.IsInterface() )
404 {
405 // インターフェイスではないとき
406 SetError(138,interfaceClass.GetName().c_str(),nowLine );
407 return false;
408 }
409
410 if( !interfaceClass.IsReady() ){
411 // インターフェイスが未解析のとき
412 pobj_LoopRefCheck->add(this->GetName().c_str());
413 compiler.GetObjectModule().meta.GetClasses().GetClass_recur(interfaceClass.GetName().c_str());
414 pobj_LoopRefCheck->del(this->GetName().c_str());
415 }
416
417 interfaces.push_back( ::Interface( &interfaceClass ) );
418
419 return true;
420}
421bool CClass::Implements( const char *interfaceNames, int nowLine )
422{
423 Jenga::Common::Strings paramStrs;
424 SplitParameter( interfaceNames, paramStrs );
425
426 BOOST_FOREACH( const std::string &paramStr, paramStrs )
427 {
428 //継承元クラスを取得
429 const CClass *pInterfaceClass = compiler.GetObjectModule().meta.GetClasses().Find( paramStr.c_str() );
430 if( !pInterfaceClass ){
431 SetError(106,paramStr.c_str(),nowLine);
432 continue;
433 }
434
435 // インターフェイスを継承する
436 Implements( *pInterfaceClass, nowLine );
437 }
438
439 return true;
440}
441
442CMember *CClass::CreateMember( Prototype::Accessibility accessibility, bool isConst, bool isRef, char *buffer, int nowLine )
443{
444 extern int cp;
445
446 //構文を解析
447 char VarName[VN_SIZE];
448 char initBuffer[VN_SIZE];
449 char lpszConstructParameter[VN_SIZE];
450 Subscripts subscripts;
451 Type type;
452 GetDimentionFormat(buffer,VarName,subscripts,type,initBuffer,lpszConstructParameter);
453
454 //重複チェック
455 if(this->DupliCheckAll(VarName)){
456 SetError(15,VarName,cp);
457 }
458
459 CMember *pMember = new CMember( accessibility, VarName, type, isConst, subscripts, initBuffer, lpszConstructParameter );
460 pMember->source_code_address = nowLine;
461 return pMember;
462}
463void CClass::AddMember( Prototype::Accessibility accessibility, bool isConst, bool isRef, char *buffer, int nowLine ){
464 dynamicMembers.push_back(
465 CreateMember( accessibility, isConst, isRef, buffer, nowLine )
466 );
467}
468void CClass::AddStaticMember( Prototype::Accessibility accessibility, bool isConst, bool isRef, char *buffer, int nowLine ){
469 staticMembers.push_back(
470 CreateMember( accessibility, isConst, isRef, buffer, nowLine )
471 );
472}
473
474void CClass::AddMethod(CClass *pobj_c, Prototype::Accessibility accessibility, BOOL bStatic, bool isConst, bool isAbstract,
475 bool isVirtual, bool isOverride, char *buffer, int nowLine){
476 int i,i2;
477 char temporary[VN_SIZE];
478
479 i=2;
480 for(i2=0;;i++,i2++){
481 if(buffer[i]=='('||buffer[i]=='\0'){
482 temporary[i2]=0;
483 break;
484 }
485 temporary[i2]=buffer[i];
486 }
487
488
489 //関数ハッシュへ登録
490 UserProc *pUserProc = compiler.GetObjectModule().meta.GetUserProcs().Add( NamespaceScopes(), NamespaceScopesCollection(), buffer,nowLine,isVirtual,pobj_c, (bStatic!=0) );
491 if(!pUserProc) return;
492
493
494 ////////////////////////////////////////////////////////////
495 // コンストラクタ、デストラクタの場合の処理
496 ////////////////////////////////////////////////////////////
497 BOOL fConstructor=0,bDestructor=0;
498
499 if(lstrcmp(temporary,pobj_c->GetName().c_str())==0){
500 //コンストラクタの場合
501
502 //標準コンストラクタ(引数なし)
503 if(pUserProc->Params().size()==0) fConstructor=1;
504
505 //強制的にConst修飾子をつける
506 isConst = true;
507 }
508 else if(temporary[0]=='~'){
509 //デストラクタの場合はその名前が正しいかチェックを行う
510 if(lstrcmp(temporary+1,pobj_c->GetName().c_str())!=0)
511 SetError(117,NULL,nowLine);
512 else
513 bDestructor=1;
514 }
515 if(fConstructor||bDestructor){
516 // コンストラクタ、デストラクタのアクセシビリティをチェック
517
518 //強制的にConst修飾子をつける
519 isConst = true;
520 }
521
522 if( fConstructor == 1 )
523 pobj_c->SetConstructorMemberSubIndex( (int)pobj_c->GetDynamicMethods().size() );
524 else if( bDestructor )
525 pobj_c->SetDestructorMemberSubIndex( (int)pobj_c->GetDynamicMethods().size() );
526
527
528
529 //////////////////
530 // 重複チェック
531 //////////////////
532
533 if(pobj_c->DupliCheckMember(temporary)){
534 SetError(15,temporary,nowLine);
535 return;
536 }
537
538 //メソッド
539 BOOST_FOREACH( const CMethod *pMethod, pobj_c->GetDynamicMethods() ){
540 //基底クラスと重複する場合はオーバーライドを行う
541 if( pMethod->GetInheritsClassPtr() ) continue;
542
543 if( pMethod->GetUserProc().GetName() == temporary ){
544 if( pMethod->GetUserProc().Params().Equals( pUserProc->Params() )
545 && pMethod->GetUserProc().ReturnType().Equals( pUserProc->ReturnType() ) )
546 {
547 //関数名、パラメータ、戻り値が合致したとき
548 SetError(15,pUserProc->GetName().c_str(),nowLine);
549 return;
550 }
551 }
552 }
553
554 //仮想関数の場合
555 if( isAbstract ) pUserProc->CompleteCompile();
556
557 //メソッドのオーバーライド
558 BOOST_FOREACH( CMethod *pMethod, pobj_c->GetDynamicMethods() ){
559 if( pMethod->GetUserProc().GetName() == temporary ){
560 if( pMethod->GetUserProc().Params().Equals( pUserProc->Params() )
561 && pMethod->GetUserProc().ReturnType().Equals( pUserProc->ReturnType() ) )
562 {
563 //メンバ関数を上書き
564 pMethod->SetUserProcPtr( pUserProc );
565 pMethod->Override();
566
567 if( !pMethod->IsVirtual() )
568 {
569 // オーバーライドミス
570 SetError(136,NULL,cp);
571 }
572 if( !isOverride )
573 {
574 SetError(127,NULL,nowLine);
575 }
576 if(pMethod->GetAccessibility() != accessibility )
577 {
578 SetError(128,NULL,nowLine);
579 }
580
581 pUserProc->SetMethod( pMethod );
582 return;
583 }
584 }
585 }
586
587 if( isVirtual ){
588 pobj_c->AddVtblNum( 1 );
589 }
590
591 if( isOverride ){
592 SetError(12,"Override",nowLine);
593 }
594
595 if(bStatic){
596 pobj_c->GetStaticMethods().AddStatic( pUserProc, accessibility );
597 }
598 else{
599 pobj_c->GetDynamicMethods().Add(pUserProc, accessibility, isConst, isAbstract, isVirtual);
600 }
601}
602
603bool CClass::DupliCheckAll(const char *name){
604 //重複チェック
605
606 //メンバ
607 if(DupliCheckMember(name)) return 1;
608
609 //メソッド
610 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
611 if( lstrcmp( name, pMethod->GetUserProc().GetName().c_str() ) == 0 ){
612 return 1;
613 }
614 }
615
616 return 0;
617}
618bool CClass::DupliCheckMember(const char *name){
619 //重複チェック
620
621 // 動的メンバ
622 BOOST_FOREACH( CMember *pMember, dynamicMembers ){
623 if( GetName() == pMember->GetName() ){
624 return 1;
625 }
626 }
627
628 // 静的メンバ
629 BOOST_FOREACH( CMember *pMember, staticMembers ){
630 if( GetName() == pMember->GetName() ){
631 return 1;
632 }
633 }
634
635 return 0;
636}
637
638const ::Delegate &CClass::GetDelegate() const
639{
640 const ::Delegate *dg = compiler.GetObjectModule().meta.GetDelegates().GetHashArrayElement( GetName().c_str() );
641 while( dg )
642 {
643 if( dg->IsEqualSymbol( GetNamespaceScopes(), GetName() ) ){
644 //名前空間とクラス名が一致した
645 return *dg;
646 }
647 dg = dg->GetChainNext();
648 }
649
650 Jenga::Throw( "CClass::GetDelegateメソッドに失敗" );
651 static ::Delegate dummy;
652 return dummy;
653}
654
655//サイズを取得
656int CClass::GetSize() const
657{
658 return GetMemberOffset( NULL, NULL );
659}
660
661//メンバのオフセットを取得
662int CClass::GetMemberOffset( const char *memberName, int *pMemberNum ) const
663{
664 int i2;
665
666 //仮想関数が存在する場合は関数リストへのポインタのサイズを追加
667 int offset = IsExistVirtualFunctions() ? PTR_SIZE : 0;
668
669 int alignment = 1;
670 if( GetFixedAlignment() )
671 {
672 alignment = GetFixedAlignment();
673 }
674
675 int iMaxAlign=0;
676 int i = -1;
677 BOOST_FOREACH( CMember *pMember, dynamicMembers ){
678 i++;
679
680 i2 = pMember->GetType().GetSize();
681
682 //アラインメントを算出
683 int member_size;
684 if( pMember->GetType().IsStruct() ){
685 //メンバクラスのアラインメントを取得
686 member_size=pMember->GetType().GetClass().GetAlignment();
687 }
688 else{
689 //メンバサイズを取得
690 member_size=i2;
691 }
692 if(iMaxAlign<member_size) iMaxAlign=member_size;
693
694 //アラインメントを考慮
695 if(GetFixedAlignment()&&GetFixedAlignment()<member_size){
696 if(offset%alignment) offset+=alignment-(offset%alignment);
697 }
698 else{
699 if(alignment<member_size) alignment=member_size;
700
701 if(member_size==0){
702 //メンバを持たないクラス
703 //※何もしない(オフセットの計算をしない)
704 }
705 else{
706 if(offset%member_size) offset+=member_size-(offset%member_size);
707 }
708 }
709
710 if(memberName){
711 //メンバ指定がある場合は、オフセットを返す
712 if( pMember->GetName() == memberName ){
713 if(pMemberNum) *pMemberNum=i;
714 return offset;
715 }
716 }
717
718 //配列を考慮したメンバサイズを取得
719 member_size = i2 * Variable::GetSubScriptCounts( pMember->GetSubscripts() );
720
721 //メンバサイズを加算
722 offset+= member_size;
723 }
724
725 if(iMaxAlign<alignment) alignment=iMaxAlign;
726
727 //アラインメントを考慮
728 if(alignment){
729 if(offset%alignment) offset+=alignment-(offset%alignment);
730 }
731
732 if(pMemberNum) *pMemberNum=i;
733 return offset;
734}
735int CClass::GetAlignment() const
736{
737 //仮想関数が存在する場合は関数リストへのポインタのサイズを追加
738 int alignment = IsExistVirtualFunctions() ? PTR_SIZE : 0;
739
740 BOOST_FOREACH( CMember *pMember, dynamicMembers ){
741 int member_size;
742 if(pMember->GetType().IsStruct()){
743 //メンバクラスのアラインメントを取得
744 member_size=pMember->GetType().GetClass().GetAlignment();
745 }
746 else{
747 //メンバサイズを取得
748 member_size = pMember->GetType().GetSize();
749 }
750
751 //アラインメントをセット
752 if(alignment<member_size) alignment=member_size;
753 }
754
755 if(alignment==0) return 0;
756
757 if(GetFixedAlignment()) alignment=GetFixedAlignment();
758
759 return alignment;
760}
761
762int CClass::GetVtblMasterListIndex( const UserProc *pUserProc ) const
763{
764 int index = 0;
765 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
766 if( &pMethod->GetUserProc() == pUserProc )
767 {
768 return index;
769 }
770 }
771
772 BOOST_FOREACH( const ::Interface &objInterface, interfaces )
773 {
774 index++;
775
776 BOOST_FOREACH( const CMethod *pMethod, objInterface.GetClass().GetDynamicMethods() ){
777 if( &pMethod->GetUserProc() == pUserProc )
778 {
779 return index;
780 }
781 }
782 }
783
784 SetError();
785 return 0;
786}
787int CClass::GetFuncNumInVtbl( const UserProc *pUserProc ) const
788{
789 int n = 0;
790 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
791 if( &pMethod->GetUserProc() == pUserProc ) break;
792 if( pMethod->IsVirtual() ) n++;
793 }
794 return n;
795}
796LONG_PTR CClass::GetVtblMasterListOffset() const
797{
798 //既に存在する場合はそれを返す
799 if( vtblMasterListOffset == -1 )
800 {
801 SetError();
802 }
803
804 return vtblMasterListOffset;
805}
806void CClass::GenerateVTablePart( LONG_PTR &vtableDataTableOffset ) const
807{
808 const UserProc **ppsi = (const UserProc **)malloc(GetVtblNum()*sizeof(UserProc *));
809
810 //関数テーブルに値をセット
811 int i2 = 0;
812 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
813 if(pMethod->IsVirtual()){
814 if( !pMethod->GetUserProc().IsUsing() )
815 {
816 ts((char *)pMethod->GetUserProc().GetFullName().c_str());
817 }
818 pMethod->GetUserProc().Using();
819
820 if(pMethod->IsAbstract()){
821 extern int cp;
822 SmoothieException::Throw(300,NULL,cp);
823
824 ppsi[i2]=0;
825 }
826 else{
827 ppsi[i2]=&pMethod->GetUserProc();
828 }
829 i2++;
830 }
831 }
832
833 vtableDataTableOffset = compiler.GetObjectModule().dataTable.AddBinary( (void *)ppsi, GetVtblNum()*sizeof(LONG_PTR) );
834
835 for( int i=0; i < GetVtblNum(); i++ ){
836 pobj_Reloc->AddSchedule_DataSection(vtableDataTableOffset+i*sizeof(LONG_PTR));
837 }
838
839 free(ppsi);
840}
841void CClass::GenerateVTableMasterList( const std::vector<LONG_PTR> &vtableMasterList, LONG_PTR &offset )
842{
843 offset = compiler.GetObjectModule().dataTable.AddBinary(
844 (void *)&vtableMasterList[0],
845 vtableMasterList.size()*sizeof(LONG_PTR)
846 );
847}
848void CClass::GenerateFullVTables()
849{
850 if( IsAbstract() )
851 {
852 // 抽象クラスは無視
853 return;
854 }
855 if( !IsUsing() )
856 {
857 // 使われていないクラスは無視
858 return;
859 }
860
861 // vtblマスターリストの元データに不要なデータが含まれていたらエラー
862 if( vtblMasterList.size() )
863 {
864 SetError();
865 }
866
867 // 自身のクラスのvtblを生成
868 GenerateVTablePart( this->vtbl_offset );
869 vtblMasterList.push_back( this->vtbl_offset );
870
871 // インターフェイスのvtblを生成
872 BOOST_FOREACH( const ::Interface &objInterface, interfaces )
873 {
874 LONG_PTR tempVtblOffset;
875 objInterface.GetClass().GenerateVTablePart( tempVtblOffset );
876 vtblMasterList.push_back( tempVtblOffset );
877
878 objInterface.SetVtblOffset( tempVtblOffset );
879 }
880
881 // vtblマスターリストを生成
882 GenerateVTableMasterList( vtblMasterList, this->vtblMasterListOffset );
883}
884void CClass::ActionVtblSchedule( LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection, LONG_PTR MemPos_DataSection )
885{
886 if( IsAbstract() )
887 {
888 // 抽象クラスは無視
889 return;
890 }
891 if( !IsUsing() )
892 {
893 // 使われていないクラスは無視
894 return;
895 }
896 if(vtbl_offset==-1) return;
897
898 // 自身のクラスのvtbl
899 {
900 LONG_PTR *pVtbl = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + vtbl_offset);
901
902 for( int i=0; i<GetVtblNum(); i++ ){
903 const UserProc *pUserProc = (UserProc *)pVtbl[i];
904 if(!pUserProc) continue;
905
906 if( pUserProc->GetBeginOpAddress() == 0
907 && pUserProc->GetEndOpAddress() == 0 )
908 {
909 Jenga::Throw( "未解決の仮想関数が存在する" );
910 }
911
912 pVtbl[i] = pUserProc->GetBeginOpAddress() + ImageBase + MemPos_CodeSection;
913 }
914 }
915
916 // インターフェイスのvtbl
917 BOOST_FOREACH( const ::Interface &objInterface, interfaces )
918 {
919 LONG_PTR *pVtbl = (LONG_PTR *)((char *)compiler.GetObjectModule().dataTable.GetPtr() + objInterface.GetClass().vtbl_offset);
920
921 for( int i=0; i<objInterface.GetClass().GetVtblNum(); i++ ){
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 }
933 }
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 }
941}
942bool CClass::IsAbstract() const
943{
944 // 未実装(abstract)の仮想関数を持つ場合はtrueを返す
945
946 BOOST_FOREACH( const CMethod *pMethod, GetDynamicMethods() ){
947 if(pMethod->IsVirtual()){
948 if(pMethod->IsAbstract()){
949 return true;
950 }
951 }
952 }
953
954 return false;
955}
956
957CClass *Classes::Create( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name){
958 return new CClass(namespaceScopes, importedNamespaces, name);
959}
960bool Classes::Insert( CClass *pClass )
961{
962 /////////////////////////////////
963 // ハッシュデータに追加
964 /////////////////////////////////
965
966 if( !Put( pClass ) )
967 {
968 SetError(15,pClass->GetName(), cp);
969 return false;
970 }
971 return true;
972}
973CClass *Classes::Add( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, const char *name,int nowLine){
974 //////////////////////////////////////////////////////////////////////////
975 // クラスを追加
976 // ※名前のみを登録。その他の情報はSetClassメソッドで!
977 //////////////////////////////////////////////////////////////////////////
978
979 CClass *pClass = Create(namespaceScopes, importedNamespaces, name);
980
981 if( !Insert( pClass ) )
982 {
983 return NULL;
984 }
985
986 return pClass;
987}
988
989void Classes::CollectClassesForNameOnly( const BasicSource &source )
990{
991 int i, i2;
992 char temporary[VN_SIZE];
993
994 // 名前空間管理
995 NamespaceScopes &namespaceScopes = compiler.GetNamespaceSupporter().GetLivingNamespaceScopes();
996 namespaceScopes.clear();
997
998 // Importsされた名前空間の管理
999 NamespaceScopesCollection &importedNamespaces = compiler.GetNamespaceSupporter().GetImportedNamespaces();
1000 importedNamespaces.clear();
1001
1002 for(i=0;;i++){
1003 if(source[i]=='\0') break;
1004
1005 if( source[i] == 1 && source[i+1] == ESC_NAMESPACE ){
1006 for(i+=2,i2=0;;i2++,i++){
1007 if( IsCommandDelimitation( source[i] ) ){
1008 temporary[i2]=0;
1009 break;
1010 }
1011 temporary[i2]=source[i];
1012 }
1013 namespaceScopes.push_back( temporary );
1014
1015 continue;
1016 }
1017 else if( source[i] == 1 && source[i+1] == ESC_ENDNAMESPACE ){
1018 if( namespaceScopes.size() <= 0 ){
1019 SmoothieException::Throw(12, "End Namespace", i );
1020 }
1021 else{
1022 namespaceScopes.pop_back();
1023 }
1024
1025 i += 2;
1026 continue;
1027 }
1028 else if( source[i] == 1 && source[i+1] == ESC_IMPORTS ){
1029 for(i+=2,i2=0;;i2++,i++){
1030 if( IsCommandDelimitation( source[i] ) ){
1031 temporary[i2]=0;
1032 break;
1033 }
1034 temporary[i2]=source[i];
1035 }
1036 if( !compiler.GetNamespaceSupporter().ImportsNamespace( temporary ) )
1037 {
1038 SmoothieException::Throw(64,temporary,i );
1039 }
1040
1041 continue;
1042 }
1043 else if( source[i] == 1 && source[i+1] == ESC_CLEARNAMESPACEIMPORTED ){
1044 importedNamespaces.clear();
1045 continue;
1046 }
1047
1048 if(source[i]==1&&(
1049 source[i+1]==ESC_CLASS||
1050 source[i+1]==ESC_TYPE||
1051 source[i+1]==ESC_INTERFACE
1052 ))
1053 {
1054 int nowLine = i;
1055 i += 2;
1056
1057 Type blittableType;
1058 if(memicmp(source.GetBuffer()+i,"Align(",6)==0){
1059 //アラインメント修飾子
1060 i+=6;
1061 i=JumpStringInPare(source.GetBuffer(),i)+1;
1062 }
1063 else if( memicmp( source.GetBuffer() + i, "Blittable(", 10 ) == 0 ){
1064 // Blittable修飾子
1065 i+=10;
1066 i+=GetStringInPare_RemovePare(temporary,source.GetBuffer()+i)+1;
1067 compiler.StringToType( temporary, blittableType );
1068 }
1069
1070 bool isEnum = false;
1071 bool isDelegate = false;
1072 if( source[i] == 1 && source[i+1] == ESC_ENUM ){
1073 // 列挙型の場合
1074 isEnum = true;
1075
1076 i += 2;
1077 }
1078 else if( source[i] == 1 && source[i+1] == ESC_DELEGATE )
1079 {
1080 // デリゲートの場合
1081 isDelegate = true;
1082
1083 i += 2;
1084 }
1085
1086 for(i2=0;;i++,i2++){
1087 if(!IsVariableChar(source[i])){
1088 temporary[i2]=0;
1089 break;
1090 }
1091 temporary[i2]=source[i];
1092 }
1093
1094 //クラスを追加
1095 CClass *pClass = this->Add(namespaceScopes, importedNamespaces, temporary,nowLine);
1096 if( pClass ){
1097 if( source[nowLine+1] == ESC_CLASS ){
1098 if( isEnum )
1099 {
1100 pClass->SetClassType( CClass::Enum );
1101 }
1102 else if( isDelegate )
1103 {
1104 pClass->SetClassType( CClass::Delegate );
1105 }
1106 else{
1107 pClass->SetClassType( CClass::Class );
1108 }
1109 }
1110 else if( source[nowLine+1] == ESC_INTERFACE ){
1111 pClass->SetClassType( CClass::Interface );
1112 }
1113 else{
1114 pClass->SetClassType( CClass::Structure );
1115 }
1116 }
1117
1118 // Blittable型の場合
1119 if( !blittableType.IsNull() ){
1120 pClass->SetBlittableType( blittableType );
1121
1122 // Blittable型として登録
1123 compiler.GetObjectModule().meta.GetBlittableTypes().push_back( BlittableType( blittableType, pClass ) );
1124 }
1125 }
1126 }
1127}
1128
1129void Classes::GenerateVTables()
1130{
1131 Iterator_Reset();
1132 while( Iterator_HasNext() )
1133 {
1134 CClass *pClass = Iterator_GetNext();
1135 pClass->GenerateFullVTables();
1136 }
1137}
1138
1139void Classes::ActionVtblSchedule( LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection, LONG_PTR MemPos_DataSection ){
1140 Iterator_Reset();
1141 while( Iterator_HasNext() )
1142 {
1143 CClass *pClass = Iterator_GetNext();
1144 pClass->ActionVtblSchedule( ImageBase, MemPos_CodeSection, MemPos_DataSection);
1145 }
1146}
1147
1148
1149void Classes::InitStaticMember(){
1150 //静的メンバをグローバル領域に作成
1151
1152 //イテレータをリセット
1153
1154 extern int cp;
1155 int back_cp=cp;
1156
1157 this->Iterator_Reset();
1158 while(this->Iterator_HasNext()){
1159 CClass &objClass = *this->Iterator_GetNext();
1160 if( objClass.isTargetObjectModule == false )
1161 {
1162 // 静的リンクライブラリの場合は飛ばす(既にインスタンスが定義済みであるため)
1163 continue;
1164 }
1165
1166 // 名前空間をセット
1167 compiler.GetNamespaceSupporter().GetLivingNamespaceScopes() = objClass.GetNamespaceScopes();
1168
1169 int i=0;
1170 BOOST_FOREACH( CMember *member, objClass.GetStaticMembers() ){
1171 char temporary[VN_SIZE];
1172 sprintf(temporary,"%s.%s",objClass.GetName().c_str(),member->GetName().c_str());
1173 dim(
1174 temporary,
1175 member->GetSubscripts(),
1176 member->GetType(),
1177 member->GetInitializeExpression().c_str(),
1178 member->GetConstructParameter().c_str(),
1179 0);
1180
1181 i++;
1182 }
1183 }
1184
1185 compiler.GetNamespaceSupporter().GetLivingNamespaceScopes().clear();
1186
1187 cp=back_cp;
1188}
1189bool Classes::MemberVar_LoopRefCheck(const CClass &objClass){
1190 bool result = true;
1191 BOOST_FOREACH( CMember *pMember, objClass.GetDynamicMembers() ){
1192 if(pMember->GetType().IsStruct()){
1193 //循環参照でないかをチェック
1194 if(pobj_LoopRefCheck->check(pMember->GetType().GetClass())){
1195 extern int cp;
1196 SetError(124,pMember->GetType().GetClass().GetName(),cp);
1197 return false;
1198 }
1199
1200 pobj_LoopRefCheck->add(objClass.GetName().c_str());
1201
1202 bool tempResult = MemberVar_LoopRefCheck(pMember->GetType().GetClass());
1203 if( result )
1204 {
1205 result = tempResult;
1206 }
1207
1208 pobj_LoopRefCheck->del(objClass.GetName().c_str());
1209 }
1210 }
1211
1212 return result;
1213}
1214void Classes::GetClass_recur(const char *lpszInheritsClass){
1215 extern char *basbuf;
1216 int i,i2,i3,sub_address,top_pos;
1217 char temporary[8192];
1218
1219 // 名前空間管理
1220 NamespaceScopes backupNamespaceScopes = compiler.GetNamespaceSupporter().GetLivingNamespaceScopes();
1221 NamespaceScopes &namespaceScopes = compiler.GetNamespaceSupporter().GetLivingNamespaceScopes();
1222 namespaceScopes.clear();
1223
1224 // Importsされた名前空間の管理
1225 NamespaceScopesCollection backupImportedNamespaces = compiler.GetNamespaceSupporter().GetImportedNamespaces();
1226 compiler.GetNamespaceSupporter().GetImportedNamespaces().clear();
1227
1228 // 呼び出し元でコンパイル中のクラスポインタをバックアップ
1229 const CClass *pBackCompilingClass = compiler.pCompilingClass;
1230
1231 for(i=0;;i++){
1232 if(basbuf[i]=='\0') break;
1233
1234
1235 // 名前空間
1236 if( basbuf[i] == 1 && basbuf[i+1] == ESC_NAMESPACE ){
1237 for(i+=2,i2=0;;i2++,i++){
1238 if( IsCommandDelimitation( basbuf[i] ) ){
1239 temporary[i2]=0;
1240 break;
1241 }
1242 temporary[i2]=basbuf[i];
1243 }
1244 namespaceScopes.push_back( temporary );
1245
1246 continue;
1247 }
1248 else if( basbuf[i] == 1 && basbuf[i+1] == ESC_ENDNAMESPACE ){
1249 if( namespaceScopes.size() <= 0 ){
1250 SetError(12, "End Namespace", i );
1251 }
1252 else{
1253 namespaceScopes.pop_back();
1254 }
1255
1256 i += 2;
1257 continue;
1258 }
1259
1260 else if( basbuf[i] == 1 && basbuf[i+1] == ESC_IMPORTS ){
1261 for(i+=2,i2=0;;i2++,i++){
1262 if( IsCommandDelimitation( basbuf[i] ) ){
1263 temporary[i2]=0;
1264 break;
1265 }
1266 temporary[i2]=basbuf[i];
1267 }
1268 if( !compiler.GetNamespaceSupporter().ImportsNamespace( temporary ) )
1269 {
1270 SmoothieException::Throw(64,temporary,i );
1271 }
1272
1273 continue;
1274 }
1275 else if( basbuf[i] == 1 && basbuf[i+1] == ESC_CLEARNAMESPACEIMPORTED ){
1276 compiler.GetNamespaceSupporter().GetImportedNamespaces().clear();
1277 continue;
1278 }
1279
1280
1281
1282 if(basbuf[i]==1&&basbuf[i+1]==ESC_INTERFACE){
1283 //////////////////////////
1284 // インターフェイス
1285 //////////////////////////
1286
1287 top_pos=i;
1288
1289 i+=2;
1290
1291 //インターフェイス名を取得
1292 GetIdentifierToken( temporary, basbuf, i );
1293
1294 CClass *pobj_c = const_cast<CClass *>( this->Find(namespaceScopes, temporary) );
1295 if(!pobj_c) continue;
1296
1297 if(lpszInheritsClass){
1298 if(lstrcmp(lpszInheritsClass,pobj_c->GetName().c_str())!=0){
1299 //継承先先読み用
1300 continue;
1301 }
1302 }
1303
1304 if(pobj_c->IsReady()){
1305 //既に先読みされているとき
1306 continue;
1307 }
1308
1309 pobj_c->Readed();
1310
1311 pobj_c->SetConstructorMemberSubIndex( -1 );
1312 pobj_c->SetDestructorMemberSubIndex( -1 );
1313
1314 if(basbuf[i+1]==1&&basbuf[i+2]==ESC_INHERITS){
1315 //継承を行う場合
1316 for(i+=3,i2=0;;i++,i2++){
1317 if(IsCommandDelimitation(basbuf[i])){
1318 temporary[i2]=0;
1319 break;
1320 }
1321 temporary[i2]=basbuf[i];
1322 }
1323
1324 if(lstrcmpi(temporary,pobj_c->GetName().c_str())==0){
1325 SetError(105,temporary,i);
1326 goto Interface_InheritsError;
1327 }
1328
1329 //継承元クラスを取得
1330 const Classes &classes = *this;
1331 const CClass *pInheritsClass = classes.Find(temporary);
1332 if( !pInheritsClass ){
1333 SetError(106,temporary,i);
1334 goto Interface_InheritsError;
1335 }
1336
1337 //継承させる
1338 if( !pobj_c->InheritsClass( *pInheritsClass, Types(), i ) ){
1339 goto Interface_InheritsError;
1340 }
1341 }
1342 else{
1343 //継承無し
1344 if( &pobj_c->GetSuperClass() || pobj_c->GetVtblNum() )
1345 {
1346 // TODO: ここに来ないことが実証できたらこの分岐は消す
1347 Jenga::Throw( "GetClass_recur内の例外" );
1348 }
1349 }
1350Interface_InheritsError:
1351
1352 //メンバ変数、関数を取得
1353 while(1){
1354 i++;
1355
1356 //エラー
1357 if(basbuf[i]==1&&(basbuf[i+1]==ESC_CLASS||basbuf[i+1]==ESC_TYPE||basbuf[i+1]==ESC_INTERFACE)){
1358 SetError(22,"Interface",i);
1359 i--;
1360 break;
1361 }
1362
1363 if(basbuf[i]==1&&basbuf[i+1]==ESC_INHERITS){
1364 SetError(111,NULL,i);
1365 break;
1366 }
1367 else if( basbuf[i] == 1 && basbuf[i+1] == ESC_IMPLEMENTS )
1368 {
1369 SetError(137, NULL, i );
1370 break;
1371 }
1372
1373 sub_address=i;
1374
1375 for(i2=0;;i++,i2++){
1376 if(IsCommandDelimitation(basbuf[i])){
1377 temporary[i2]=0;
1378 break;
1379 }
1380 temporary[i2]=basbuf[i];
1381 }
1382 if(temporary[0]=='\0'){
1383 if(basbuf[i]=='\0'){
1384 i--;
1385 SetError(22,"Interface",top_pos);
1386 break;
1387 }
1388 continue;
1389 }
1390
1391 //End Interface記述の場合
1392 if(temporary[0]==1&&temporary[1]==ESC_ENDINTERFACE) break;
1393
1394 if(!(temporary[0]==1&&(
1395 temporary[1]==ESC_SUB||temporary[1]==ESC_FUNCTION
1396 ))){
1397 SetError(1,NULL,i);
1398 break;
1399 }
1400
1401 //メンバ関数を追加
1402 pobj_c->AddMethod(pobj_c,
1403 Prototype::Public, //Publicアクセス権
1404 0, //Static指定なし
1405 false, //Constではない
1406 1, //Abstract
1407 1, //Virtual
1408 0,
1409 temporary,
1410 sub_address
1411 );
1412 }
1413 }
1414
1415 if(basbuf[i]==1&&(basbuf[i+1]==ESC_CLASS||basbuf[i+1]==ESC_TYPE)){
1416 //////////////////////////
1417 // クラス
1418 //////////////////////////
1419
1420 top_pos=i;
1421
1422 const DWORD dwClassType=basbuf[i+1];
1423
1424 i+=2;
1425
1426 int iAlign=0;
1427 if(memicmp(basbuf+i,"Align(",6)==0){
1428 //アラインメント修飾子
1429 i+=6;
1430 i+=GetStringInPare_RemovePare(temporary,basbuf+i)+1;
1431 iAlign=atoi(temporary);
1432
1433 if(!(iAlign==1||iAlign==2||iAlign==4||iAlign==8||iAlign==16))
1434 SetError(51,NULL,i);
1435 }
1436 else if( memicmp( basbuf + i, "Blittable(", 10 ) == 0 ){
1437 // Blittable修飾子
1438 i+=10;
1439 i=JumpStringInPare(basbuf,i)+1;
1440 }
1441
1442 if( basbuf[i] == 1 && basbuf[i+1] == ESC_ENUM )
1443 {
1444 // 列挙型の場合
1445 i += 2;
1446 }
1447 else if( basbuf[i] == 1 && basbuf[i+1] == ESC_DELEGATE )
1448 {
1449 // デリゲートの場合
1450 i += 2;
1451 }
1452
1453 //クラス名を取得
1454 GetCommandToken( temporary, basbuf, i );
1455
1456 char className[VN_SIZE];
1457 Jenga::Common::Strings typeParameters;
1458 SplitGenericClassInstance( temporary, className, typeParameters );
1459
1460 CClass *pobj_c = const_cast<CClass *>( this->Find(namespaceScopes, className) );
1461 if(!pobj_c) continue;
1462
1463 compiler.pCompilingClass = pobj_c;
1464
1465 if(lpszInheritsClass){
1466 if( pobj_c->GetName() != lpszInheritsClass ){
1467 //継承先先読み用
1468 continue;
1469 }
1470 }
1471
1472 if(pobj_c->IsReady()){
1473 //既に先読みされているとき
1474 continue;
1475 }
1476
1477
1478 /////////////////////////////////////////////////////////
1479 // ☆★☆ ジェネリクスサポート ☆★☆
1480 BOOST_FOREACH( const std::string &typeParameter, typeParameters )
1481 {
1482 pobj_c->AddFormalGenericType( GenericType( typeParameter, Type(DEF_OBJECT,*GetObjectClassPtr()) ) );
1483 }
1484 /////////////////////////////////////////////////////////
1485
1486
1487 pobj_c->SetFixedAlignment( iAlign );
1488
1489 pobj_c->Readed();
1490
1491 pobj_c->SetConstructorMemberSubIndex( -1 );
1492 pobj_c->SetDestructorMemberSubIndex( -1 );
1493
1494 //アクセス制限の初期値をセット
1495 Prototype::Accessibility accessibility;
1496 if(dwClassType==ESC_CLASS){
1497 accessibility = Prototype::Private;
1498 }
1499 else{
1500 accessibility = Prototype::Public;
1501 }
1502
1503 if( pobj_c->GetName() == "Object" || dwClassType == ESC_TYPE ){
1504 if( &pobj_c->GetSuperClass() || pobj_c->GetVtblNum() )
1505 {
1506 // TODO: ここに来ないことが実証できたらこの分岐は消す
1507 Jenga::Throw( "GetClass_recur内の例外" );
1508 }
1509 }
1510 else{
1511 if(basbuf[i+1]==1&&basbuf[i+2]==ESC_INHERITS)
1512 {
1513 // クラス継承先が指定されているとき
1514 i += 3;
1515 GetCommandToken( temporary, basbuf, i );
1516
1517 if(lstrcmpi(temporary,pobj_c->GetName().c_str())==0){
1518 SetError(105,temporary,i);
1519 goto InheritsError;
1520 }
1521 }
1522 else
1523 {
1524 // 何の指定もないときはObjectクラスを継承する
1525 lstrcpy( temporary, "Object" );
1526 }
1527 pobj_c->Inherits( temporary, i );
1528
1529 if( basbuf[i+1] == 1 && basbuf[i+2] == ESC_IMPLEMENTS )
1530 {
1531 // インターフェイス実装を行う場合
1532 i += 3;
1533 GetCommandToken( temporary, basbuf, i );
1534
1535 pobj_c->Implements( temporary, i );
1536 }
1537 }
1538InheritsError:
1539
1540 //メンバとメソッドを取得
1541 while(1){
1542 i++;
1543
1544 //エラー
1545 if(basbuf[i]==1&&(basbuf[i+1]==ESC_CLASS||basbuf[i+1]==ESC_TYPE)){
1546 SetError(22,"Class",i);
1547 i--;
1548 break;
1549 }
1550
1551 if(basbuf[i]==1&&basbuf[i+1]==ESC_INHERITS){
1552 SetError(111,NULL,i);
1553 break;
1554 }
1555 else if( basbuf[i] == 1 && basbuf[i+1] == ESC_IMPLEMENTS )
1556 {
1557 SetError(137, NULL, i );
1558 break;
1559 }
1560
1561 //Static修飾子
1562 BOOL bStatic;
1563 if(basbuf[i]==1&&basbuf[i+1]==ESC_STATIC){
1564 bStatic=1;
1565 i+=2;
1566 }
1567 else bStatic=0;
1568
1569 //Const修飾子
1570 bool isConst = false;
1571 if( basbuf[i] == 1 && basbuf[i + 1] == ESC_CONST ){
1572 isConst = true;
1573 i += 2;
1574 }
1575
1576 if(basbuf[i]==1&&(
1577 basbuf[i+1]==ESC_ABSTRACT||basbuf[i+1]==ESC_VIRTUAL||basbuf[i+1]==ESC_OVERRIDE||
1578 basbuf[i+1]==ESC_SUB||basbuf[i+1]==ESC_FUNCTION
1579 )){
1580 i3=basbuf[i+1];
1581 sub_address=i;
1582 }
1583 else i3=0;
1584
1585 bool isVirtual = false, isAbstract = false, isOverride = false;
1586 if(i3==ESC_ABSTRACT){
1587 isAbstract=1;
1588 isVirtual=1;
1589 i+=2;
1590
1591 i3=basbuf[i+1];
1592 }
1593 else if(i3==ESC_VIRTUAL){
1594 isAbstract=0;
1595 isVirtual=1;
1596 i+=2;
1597
1598 i3=basbuf[i+1];
1599 }
1600 else if(i3==ESC_OVERRIDE){
1601 isOverride=1;
1602 isVirtual=1;
1603
1604 i+=2;
1605
1606 i3=basbuf[i+1];
1607 }
1608
1609 for(i2=0;;i++,i2++){
1610 if(IsCommandDelimitation(basbuf[i])){
1611 temporary[i2]=0;
1612 break;
1613 }
1614 temporary[i2]=basbuf[i];
1615 }
1616 if(temporary[0]=='\0'){
1617 if(basbuf[i]=='\0'){
1618
1619 if(dwClassType==ESC_CLASS)
1620 SetError(22,"Class",top_pos);
1621 else
1622 SetError(22,"Type",top_pos);
1623
1624 i--;
1625 break;
1626 }
1627 continue;
1628 }
1629
1630 //End Class記述の場合
1631 if(temporary[0]==1&&temporary[1]==ESC_ENDCLASS&&dwClassType==ESC_CLASS) break;
1632 if(temporary[0]==1&&temporary[1]==ESC_ENDTYPE&&dwClassType==ESC_TYPE) break;
1633
1634 //アクセスを変更
1635 if(lstrcmpi(temporary,"Private")==0){
1636 accessibility = Prototype::Private;
1637 continue;
1638 }
1639 if(lstrcmpi(temporary,"Public")==0){
1640 accessibility = Prototype::Public;
1641 continue;
1642 }
1643 if(lstrcmpi(temporary,"Protected")==0){
1644 accessibility = Prototype::Protected;
1645 continue;
1646 }
1647
1648 extern int cp;
1649 if(i3==0){
1650 if(bStatic){
1651 //静的メンバを追加
1652 cp=i; //エラー用
1653 pobj_c->AddStaticMember( accessibility, isConst, false, temporary, i);
1654 }
1655 else{
1656 //メンバを追加
1657 cp=i; //エラー用
1658 pobj_c->AddMember( accessibility, isConst, false, temporary, i );
1659
1660
1661 if(pobj_c->GetDynamicMembers()[pobj_c->GetDynamicMembers().size()-1]->GetType().IsStruct()){
1662 if( !pobj_c->GetDynamicMembers()[pobj_c->GetDynamicMembers().size()-1]->GetType().GetClass().IsReady() ){
1663 //参照先が読み取られていないとき
1664 GetClass_recur(pobj_c->GetDynamicMembers()[pobj_c->GetDynamicMembers().size()-1]->GetType().GetClass().GetName().c_str());
1665 }
1666 }
1667
1668
1669 if(pobj_c->GetDynamicMembers()[pobj_c->GetDynamicMembers().size()-1]->GetType().IsStruct()){
1670 //循環参照のチェック
1671 pobj_LoopRefCheck->add(pobj_c->GetName().c_str());
1672 if(!MemberVar_LoopRefCheck(pobj_c->GetDynamicMembers()[pobj_c->GetDynamicMembers().size()-1]->GetType().GetClass())){
1673 //エラー回避
1674 Type &type = const_cast<Type &>(pobj_c->GetDynamicMembers().back()->GetType());
1675 type.SetBasicType( DEF_PTR_VOID );
1676 }
1677 pobj_LoopRefCheck->del(pobj_c->GetName().c_str());
1678 }
1679 }
1680 }
1681 else{
1682 //メソッドを追加
1683 cp=i; //エラー用
1684 pobj_c->AddMethod(pobj_c,
1685 accessibility,
1686 bStatic,
1687 isConst,
1688 isAbstract,
1689 isVirtual,
1690 isOverride,
1691 temporary,
1692 sub_address);
1693
1694 if( isAbstract ) continue;
1695
1696 for(;;i++){
1697 if(basbuf[i]=='\0'){
1698 i--;
1699 break;
1700 }
1701 if(basbuf[i-1]!='*'&&
1702 basbuf[i]==1&&(
1703 basbuf[i+1]==ESC_SUB||
1704 basbuf[i+1]==ESC_FUNCTION||
1705 basbuf[i+1]==ESC_MACRO||
1706 basbuf[i+1]==ESC_TYPE||
1707 basbuf[i+1]==ESC_CLASS||
1708 basbuf[i+1]==ESC_INTERFACE||
1709 basbuf[i+1]==ESC_ENUM)){
1710 GetDefaultNameFromES(i3,temporary);
1711 SetError(22,temporary,i);
1712 }
1713 if(basbuf[i]==1&&basbuf[i+1]==GetEndXXXCommand((char)i3)){
1714 i+=2;
1715 break;
1716 }
1717 }
1718 }
1719 }
1720 }
1721 }
1722
1723 // 呼び出し元でコンパイル中のクラスポインタを元に戻す
1724 compiler.pCompilingClass = pBackCompilingClass;
1725
1726 // 名前空間を元に戻す
1727 compiler.GetNamespaceSupporter().GetLivingNamespaceScopes() = backupNamespaceScopes;
1728
1729 // インポートされた名前空間を元に戻す
1730 compiler.GetNamespaceSupporter().GetImportedNamespaces() = backupImportedNamespaces;
1731}
1732void Classes::GetAllClassInfo(void){
1733 //ループ継承チェック用のクラス
1734 pobj_LoopRefCheck=new CLoopRefCheck();
1735
1736 //クラスを取得
1737 GetClass_recur(0);
1738
1739 delete pobj_LoopRefCheck;
1740 pobj_LoopRefCheck=0;
1741
1742 // イテレータの準備
1743 this->Iterator_Init();
1744}
1745void Classes::Compile_System_InitializeUserTypes(){
1746 char temporary[VN_SIZE];
1747
1748 ////////////////////////////////////////////////////////////////////
1749 // クラス登録
1750 ////////////////////////////////////////////////////////////////////
1751
1752 // イテレータをリセット
1753 Iterator_Reset();
1754
1755 while( Iterator_HasNext() ){
1756 const CClass &objClass = *Iterator_GetNext();
1757
1758 if( !objClass.IsUsing() ){
1759 // 未使用のクラスは無視する
1760 continue;
1761 }
1762
1763 char referenceOffsetsBuffer[1024] = "";
1764 int numOfReference = 0;
1765 BOOST_FOREACH( CMember *pMember, objClass.GetDynamicMembers() ){
1766 if( pMember->GetType().IsObject() || pMember->GetType().IsPointer() ){
1767 if( referenceOffsetsBuffer[0] ){
1768 lstrcat( referenceOffsetsBuffer, "," );
1769 }
1770
1771 sprintf( referenceOffsetsBuffer + lstrlen( referenceOffsetsBuffer ),
1772 "%d",
1773 objClass.GetMemberOffset( pMember->GetName().c_str() ) );
1774
1775 numOfReference++;
1776 }
1777 }
1778
1779 sprintf( temporary
1780 , "Add(%c%c_System_TypeForClass(\"%s\",\"%s\",[%s],%d))"
1781 , 1
1782 , ESC_NEW
1783 , "" // 名前空間 (TODO: 実装)
1784 , objClass.GetName().c_str() // クラス名
1785 , referenceOffsetsBuffer // 参照メンバオフセット配列
1786 , numOfReference // 参照メンバの個数
1787 );
1788
1789 // コンパイル
1790 ChangeOpcode( temporary );
1791 }
1792
1793
1794 ////////////////////////////////////////////////////////////////////
1795 // 基底クラスを登録
1796 ////////////////////////////////////////////////////////////////////
1797
1798 sprintf(temporary, "%c%ctempType=Nothing%c%cTypeBaseImpl"
1799 , HIBYTE( COM_DIM )
1800 , LOBYTE( COM_DIM )
1801 , 1
1802 , ESC_AS
1803 );
1804 ChangeOpcode( temporary );
1805
1806 // イテレータをリセット
1807 Iterator_Reset();
1808
1809 while( Iterator_HasNext() ){
1810 const CClass &objClass = *Iterator_GetNext();
1811
1812 if( !objClass.IsUsing() ){
1813 // 未使用のクラスは無視する
1814 continue;
1815 }
1816
1817 if( objClass.HasSuperClass() ){
1818 sprintf( temporary
1819 , "tempType=Search(\"%s\",\"%s\")"
1820 , "" // 名前空間 (TODO: 実装)
1821 , objClass.GetName().c_str() // クラス名
1822 );
1823
1824 // コンパイル
1825 ChangeOpcode( temporary );
1826
1827 sprintf( temporary
1828 , "tempType.SetBaseType(Search(\"%s\",\"%s\"))"
1829 , "" // 名前空間 (TODO: 実装)
1830 , objClass.GetSuperClass().GetName().c_str() // 基底クラス名
1831 );
1832
1833 // コンパイル
1834 ChangeOpcode( temporary );
1835 }
1836 }
1837
1838
1839
1840 ////////////////////////////////////////////////////////////////////
1841 // 継承関係登録
1842 ////////////////////////////////////////////////////////////////////
1843 // TODO: 未完成
1844 /*
1845
1846 // イテレータをリセット
1847 Iterator_Reset();
1848
1849 while( Iterator_HasNext() ){
1850 CClass *pClass = Iterator_GetNext();
1851
1852 sprintf( genBuffer + length
1853 , "obj.Search( \"%s\" ).SetBaseType( Search( \"%s\" ) ):"
1854 , "" // クラス名
1855 , pClass->name // クラス名
1856 );
1857 length += lstrlen( genBuffer + length );
1858
1859 while( length + 8192 > max ){
1860 max += 8192;
1861 genBuffer = (char *)realloc( genBuffer, max );
1862 }
1863 }*/
1864}
1865
1866const CClass *Classes::Find( const NamespaceScopes &namespaceScopes, const string &name ) const
1867{
1868 if( namespaceScopes.size() == 0 && name == "Object" ){
1869 return GetObjectClassPtr();
1870 }
1871 else if( namespaceScopes.size() == 0 && name == "String" ){
1872 return GetStringClassPtr();
1873 }
1874
1875 const CClass *pClass = GetHashArrayElement( name.c_str() );
1876 while( pClass )
1877 {
1878 if( pClass->IsEqualSymbol( namespaceScopes, name ) ){
1879 //名前空間とクラス名が一致した
1880 return pClass;
1881 }
1882 pClass = pClass->GetChainNext();
1883 }
1884
1885 // TypeDefも見る
1886 int index = compiler.GetObjectModule().meta.GetTypeDefs().GetIndex( namespaceScopes, name );
1887 if( index != -1 ){
1888 Type type = compiler.GetObjectModule().meta.GetTypeDefs()[index].GetBaseType();
1889 if( type.IsObject() ){
1890 return &type.GetClass();
1891 }
1892 }
1893
1894 return NULL;
1895}
1896const CClass *Classes::Find( const string &fullName ) const
1897{
1898 char AreaName[VN_SIZE] = ""; //オブジェクト変数
1899 char NestName[VN_SIZE] = ""; //入れ子メンバ
1900 bool isNest = SplitMemberName( fullName.c_str(), AreaName, NestName );
1901
1902 return Find( NamespaceScopes( AreaName ), NestName );
1903}
1904void Classes::StartCompile( const UserProc *pUserProc ){
1905 const CClass *pParentClass = pUserProc->GetParentClassPtr();
1906 if( pParentClass ){
1907 pParentClass->Using();
1908
1909 // 仮想関数になるメソッドに使用チェックをつける
1910 BOOST_FOREACH( const CMethod *pMethod, pParentClass->GetDynamicMethods() )
1911 {
1912 if( pMethod->IsVirtual() )
1913 {
1914 pMethod->GetUserProc().Using();
1915 }
1916 }
1917
1918 pCompilingMethod = pParentClass->GetDynamicMethods().GetMethodPtr( pUserProc );
1919 if( !pCompilingMethod ){
1920 pCompilingMethod = pParentClass->GetStaticMethods().GetMethodPtr( pUserProc );
1921 if( !pCompilingMethod ){
1922 SmoothieException::Throw(300);
1923 }
1924 }
1925 }
1926 else{
1927 pCompilingMethod = NULL;
1928 }
1929}
1930
1931const CClass *Classes::GetStringClassPtr() const
1932{
1933 if( !pStringClass ){
1934 // キャッシュしておく
1935 pStringClass = this->Find( NamespaceScopes( "System" ), "String" );
1936
1937 if( !pStringClass )
1938 {
1939 SmoothieException::Throw();
1940 }
1941 return pStringClass;
1942 }
1943 return pStringClass;
1944}
1945const CClass *Classes::GetObjectClassPtr() const
1946{
1947 if( !pObjectClass ){
1948 // キャッシュしておく
1949 pObjectClass = this->Find( NamespaceScopes( "System" ), "Object" );
1950
1951 if( !pObjectClass )
1952 {
1953 SmoothieException::Throw();
1954 }
1955 return pObjectClass;
1956 }
1957 return pObjectClass;
1958}
Note: See TracBrowser for help on using the repository browser.