#include "stdafx.h" #include #include #include #include #include #include #include #include "../common.h" #ifdef _AMD64_ #include "../../BasicCompiler64/opcode.h" #else #include "../../BasicCompiler32/opcode.h" #endif class CLoopRefCheck{ char **names; int num; void init(){ int i; for(i=0;iAdd(namespaceScopes, importedNamespaces, temporary,nowLine); if( pClass ){ if( source[nowLine+1] == ESC_CLASS ){ if( isEnum ) { pClass->SetClassType( CClass::Enum ); } else if( isDelegate ) { pClass->SetClassType( CClass::Delegate ); } else{ pClass->SetClassType( CClass::Class ); } } else if( source[nowLine+1] == ESC_INTERFACE ){ pClass->SetClassType( CClass::Interface ); } else{ pClass->SetClassType( CClass::Structure ); } } // Blittable型の場合 if( !blittableType.IsNull() ){ pClass->SetBlittableType( blittableType ); // Blittable型として登録 compiler.GetObjectModule().meta.GetBlittableTypes().push_back( BlittableType( blittableType, pClass ) ); } } } } bool Classes::MemberVar_LoopRefCheck(const CClass &objClass){ bool result = true; BOOST_FOREACH( CMember *pMember, objClass.GetDynamicMembers() ){ if(pMember->GetType().IsStruct()){ //循環参照でないかをチェック if(pobj_LoopRefCheck->check(pMember->GetType().GetClass())){ extern int cp; SetError(124,pMember->GetType().GetClass().GetName(),cp); return false; } pobj_LoopRefCheck->add(objClass.GetName().c_str()); bool tempResult = MemberVar_LoopRefCheck(pMember->GetType().GetClass()); if( result ) { result = tempResult; } pobj_LoopRefCheck->del(objClass.GetName().c_str()); } } return result; } void Classes::GetClass_recur(const char *lpszInheritsClass){ extern char *basbuf; int i,i2,i3,sub_address,top_pos; char temporary[8192]; // 名前空間管理 NamespaceScopes backupNamespaceScopes = compiler.GetNamespaceSupporter().GetLivingNamespaceScopes(); NamespaceScopes &namespaceScopes = compiler.GetNamespaceSupporter().GetLivingNamespaceScopes(); namespaceScopes.clear(); // Importsされた名前空間の管理 NamespaceScopesCollection backupImportedNamespaces = compiler.GetNamespaceSupporter().GetImportedNamespaces(); compiler.GetNamespaceSupporter().GetImportedNamespaces().clear(); // 呼び出し元でコンパイル中のクラスポインタをバックアップ const CClass *pBackCompilingClass = compiler.pCompilingClass; for(i=0;;i++){ if(basbuf[i]=='\0') break; // 名前空間 if( basbuf[i] == 1 && basbuf[i+1] == ESC_NAMESPACE ){ for(i+=2,i2=0;;i2++,i++){ if( IsCommandDelimitation( basbuf[i] ) ){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; } namespaceScopes.push_back( temporary ); continue; } else if( basbuf[i] == 1 && basbuf[i+1] == ESC_ENDNAMESPACE ){ if( namespaceScopes.size() <= 0 ){ SetError(12, "End Namespace", i ); } else{ namespaceScopes.pop_back(); } i += 2; continue; } else if( basbuf[i] == 1 && basbuf[i+1] == ESC_IMPORTS ){ for(i+=2,i2=0;;i2++,i++){ if( IsCommandDelimitation( basbuf[i] ) ){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; } if( !compiler.GetNamespaceSupporter().ImportsNamespace( temporary ) ) { SmoothieException::Throw(64,temporary,i ); } continue; } else if( basbuf[i] == 1 && basbuf[i+1] == ESC_CLEARNAMESPACEIMPORTED ){ compiler.GetNamespaceSupporter().GetImportedNamespaces().clear(); continue; } if(basbuf[i]==1&&basbuf[i+1]==ESC_INTERFACE){ ////////////////////////// // インターフェイス ////////////////////////// top_pos=i; i+=2; //インターフェイス名を取得 GetCommandToken( temporary, basbuf, i ); char className[VN_SIZE]; Jenga::Common::Strings typeParameters; SplitGenericClassInstance( temporary, className, typeParameters ); CClass *pobj_c = const_cast( this->Find(namespaceScopes, className) ); if(!pobj_c) continue; if(lpszInheritsClass){ if(lstrcmp(lpszInheritsClass,pobj_c->GetName().c_str())!=0){ //継承先先読み用 continue; } } if(pobj_c->IsReady()){ //既に先読みされているとき continue; } ///////////////////////////////////////////////////////// // ☆★☆ ジェネリクスサポート ☆★☆ BOOST_FOREACH( const std::string &typeParameter, typeParameters ) { pobj_c->AddFormalGenericType( GenericType( typeParameter, Type(DEF_OBJECT,*GetObjectClassPtr()) ) ); } ///////////////////////////////////////////////////////// pobj_c->Readed(); pobj_c->SetConstructorMemberSubIndex( -1 ); pobj_c->SetDestructorMemberSubIndex( -1 ); if( memcmp( basbuf+i+1, "__COM", 5 ) == 0 && IsCommandDelimitation( basbuf[i+1+5] ) ) { // COMインターフェイス pobj_c->SetClassType( CClass::ComInterface ); i += 6; } if(basbuf[i+1]==1&&basbuf[i+2]==ESC_INHERITS){ //継承を行う場合 for(i+=3,i2=0;;i++,i2++){ if(IsCommandDelimitation(basbuf[i])){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; } if(lstrcmpi(temporary,pobj_c->GetName().c_str())==0){ SetError(105,temporary,i); goto Interface_InheritsError; } //継承元クラスを取得 const Classes &classes = *this; const CClass *pInheritsClass = classes.Find(temporary); if( !pInheritsClass ){ SetError(106,temporary,i); goto Interface_InheritsError; } //継承させる if( !pobj_c->InheritsClass( *pInheritsClass, Types(), i ) ){ goto Interface_InheritsError; } } else{ //継承無し if( &pobj_c->GetSuperClass() || pobj_c->GetVtblNum() ) { // TODO: ここに来ないことが実証できたらこの分岐は消す Jenga::Throw( "GetClass_recur内の例外" ); } } Interface_InheritsError: //メンバ変数、関数を取得 while(1){ i++; //エラー if(basbuf[i]==1&&(basbuf[i+1]==ESC_CLASS||basbuf[i+1]==ESC_TYPE||basbuf[i+1]==ESC_INTERFACE)){ SetError(22,"Interface",i); i--; break; } if(basbuf[i]==1&&basbuf[i+1]==ESC_INHERITS){ SetError(111,NULL,i); break; } else if( basbuf[i] == 1 && basbuf[i+1] == ESC_IMPLEMENTS ) { SetError(137, NULL, i ); break; } sub_address=i; for(i2=0;;i++,i2++){ if(IsCommandDelimitation(basbuf[i])){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; } if(temporary[0]=='\0'){ if(basbuf[i]=='\0'){ i--; SetError(22,"Interface",top_pos); break; } continue; } //End Interface記述の場合 if(temporary[0]==1&&temporary[1]==ESC_ENDINTERFACE) break; if(!(temporary[0]==1&&( temporary[1]==ESC_SUB||temporary[1]==ESC_FUNCTION ))){ SetError(1,NULL,i); break; } //メンバ関数を追加 pobj_c->AddMethod(pobj_c, Prototype::Public, //Publicアクセス権 0, // bStatic false, // isConst true, // isAbstract true, // isVirtual false, // isOverride false, // isAutoGeneration temporary, sub_address ); } } if(basbuf[i]==1&&(basbuf[i+1]==ESC_CLASS||basbuf[i+1]==ESC_TYPE)){ ////////////////////////// // クラス ////////////////////////// top_pos=i; const DWORD dwClassType=basbuf[i+1]; i+=2; int iAlign=0; if(memicmp(basbuf+i,"Align(",6)==0){ //アラインメント修飾子 i+=6; i+=GetStringInPare_RemovePare(temporary,basbuf+i)+1; iAlign=atoi(temporary); if(!(iAlign==1||iAlign==2||iAlign==4||iAlign==8||iAlign==16)) SetError(51,NULL,i); } else if( memicmp( basbuf + i, "Blittable(", 10 ) == 0 ){ // Blittable修飾子 i+=10; i=JumpStringInPare(basbuf,i)+1; } if( basbuf[i] == 1 && basbuf[i+1] == ESC_ENUM ) { // 列挙型の場合 i += 2; } else if( basbuf[i] == 1 && basbuf[i+1] == ESC_DELEGATE ) { // デリゲートの場合 i += 2; } //クラス名を取得 GetCommandToken( temporary, basbuf, i ); char className[VN_SIZE]; Jenga::Common::Strings typeParameters; SplitGenericClassInstance( temporary, className, typeParameters ); CClass *pobj_c = const_cast( this->Find(namespaceScopes, className) ); if(!pobj_c) continue; compiler.pCompilingClass = pobj_c; if(lpszInheritsClass){ if( pobj_c->GetName() != lpszInheritsClass ){ //継承先先読み用 continue; } } if(pobj_c->IsReady()){ //既に先読みされているとき continue; } ///////////////////////////////////////////////////////// // ☆★☆ ジェネリクスサポート ☆★☆ BOOST_FOREACH( const std::string &typeParameter, typeParameters ) { pobj_c->AddFormalGenericType( GenericType( typeParameter, Type(DEF_OBJECT,*GetObjectClassPtr()) ) ); } ///////////////////////////////////////////////////////// pobj_c->SetFixedAlignment( iAlign ); pobj_c->Readed(); pobj_c->SetConstructorMemberSubIndex( -1 ); pobj_c->SetDestructorMemberSubIndex( -1 ); //アクセス制限の初期値をセット Prototype::Accessibility accessibility; if(dwClassType==ESC_CLASS){ accessibility = Prototype::Private; } else{ accessibility = Prototype::Public; } if( pobj_c->GetName() == "Object" || dwClassType == ESC_TYPE ) { // 何も継承しない if( &pobj_c->GetSuperClass() || pobj_c->GetVtblNum() ) { // TODO: ここに来ないことが実証できたらこの分岐は消す Jenga::Throw( "GetClass_recur内の例外" ); } } else{ if(basbuf[i+1]==1&&basbuf[i+2]==ESC_INHERITS) { // クラス継承先が指定されているとき i += 3; GetCommandToken( temporary, basbuf, i ); if(lstrcmpi(temporary,pobj_c->GetName().c_str())==0){ SetError(105,temporary,i); goto InheritsError; } } else { // 何の指定もないときはObjectクラスを継承する lstrcpy( temporary, "Object" ); } pobj_c->Inherits( temporary, i ); if( basbuf[i+1] == 1 && basbuf[i+2] == ESC_IMPLEMENTS ) { // インターフェイス実装を行う場合 i += 3; GetCommandToken( temporary, basbuf, i ); pobj_c->Implements( temporary, i ); } } InheritsError: //メンバとメソッドを取得 while(1){ i++; //エラー if(basbuf[i]==1&&(basbuf[i+1]==ESC_CLASS||basbuf[i+1]==ESC_TYPE)){ SetError(22,"Class",i); i--; break; } if(basbuf[i]==1&&basbuf[i+1]==ESC_INHERITS){ SetError(111,NULL,i); break; } else if( basbuf[i] == 1 && basbuf[i+1] == ESC_IMPLEMENTS ) { SetError(137, NULL, i ); break; } //Static修飾子 BOOL bStatic; if(basbuf[i]==1&&basbuf[i+1]==ESC_STATIC){ bStatic=1; i+=2; } else bStatic=0; //Const修飾子 bool isConst = false; if( basbuf[i] == 1 && basbuf[i + 1] == ESC_CONST ){ isConst = true; i += 2; } if(basbuf[i]==1&&( basbuf[i+1]==ESC_ABSTRACT||basbuf[i+1]==ESC_VIRTUAL||basbuf[i+1]==ESC_OVERRIDE|| basbuf[i+1]==ESC_SUB||basbuf[i+1]==ESC_FUNCTION )){ i3=basbuf[i+1]; sub_address=i; } else i3=0; bool isVirtual = false, isAbstract = false, isOverride = false; if(i3==ESC_ABSTRACT){ isAbstract=1; isVirtual=1; i+=2; i3=basbuf[i+1]; } else if(i3==ESC_VIRTUAL){ isAbstract=0; isVirtual=1; i+=2; i3=basbuf[i+1]; } else if(i3==ESC_OVERRIDE){ isOverride=1; isVirtual=1; i+=2; i3=basbuf[i+1]; } for(i2=0;;i++,i2++){ if(IsCommandDelimitation(basbuf[i])){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; } if(temporary[0]=='\0'){ if(basbuf[i]=='\0'){ if(dwClassType==ESC_CLASS) SetError(22,"Class",top_pos); else SetError(22,"Type",top_pos); i--; break; } continue; } //End Class記述の場合 if(temporary[0]==1&&temporary[1]==ESC_ENDCLASS&&dwClassType==ESC_CLASS) break; if(temporary[0]==1&&temporary[1]==ESC_ENDTYPE&&dwClassType==ESC_TYPE) break; //アクセスを変更 if(lstrcmpi(temporary,"Private")==0){ accessibility = Prototype::Private; continue; } if(lstrcmpi(temporary,"Public")==0){ accessibility = Prototype::Public; continue; } if(lstrcmpi(temporary,"Protected")==0){ accessibility = Prototype::Protected; continue; } extern int cp; if(i3==0){ if(bStatic){ //静的メンバを追加 cp=i; //エラー用 pobj_c->AddStaticMember( accessibility, isConst, false, temporary, i); } else{ //メンバを追加 cp=i; //エラー用 pobj_c->AddMember( accessibility, isConst, false, temporary, i ); if(pobj_c->GetDynamicMembers()[pobj_c->GetDynamicMembers().size()-1]->GetType().IsStruct()){ if( !pobj_c->GetDynamicMembers()[pobj_c->GetDynamicMembers().size()-1]->GetType().GetClass().IsReady() ){ //参照先が読み取られていないとき GetClass_recur(pobj_c->GetDynamicMembers()[pobj_c->GetDynamicMembers().size()-1]->GetType().GetClass().GetName().c_str()); } } if(pobj_c->GetDynamicMembers()[pobj_c->GetDynamicMembers().size()-1]->GetType().IsStruct()){ //循環参照のチェック pobj_LoopRefCheck->add(pobj_c->GetName().c_str()); if(!MemberVar_LoopRefCheck(pobj_c->GetDynamicMembers()[pobj_c->GetDynamicMembers().size()-1]->GetType().GetClass())){ //エラー回避 Type &type = const_cast(pobj_c->GetDynamicMembers().back()->GetType()); type.SetBasicType( DEF_PTR_VOID ); } pobj_LoopRefCheck->del(pobj_c->GetName().c_str()); } } } else{ //メソッドを追加 cp=i; //エラー用 pobj_c->AddMethod(pobj_c, accessibility, bStatic, isConst, isAbstract, isVirtual, isOverride, false, temporary, sub_address); if( isAbstract ) continue; for(;;i++){ if(basbuf[i]=='\0'){ i--; break; } if(basbuf[i-1]!='*'&& basbuf[i]==1&&( basbuf[i+1]==ESC_SUB|| basbuf[i+1]==ESC_FUNCTION|| basbuf[i+1]==ESC_MACRO|| basbuf[i+1]==ESC_TYPE|| basbuf[i+1]==ESC_CLASS|| basbuf[i+1]==ESC_INTERFACE|| basbuf[i+1]==ESC_ENUM)){ GetDefaultNameFromES(i3,temporary); SetError(22,temporary,i); } if(basbuf[i]==1&&basbuf[i+1]==GetEndXXXCommand((char)i3)){ i+=2; break; } } } } } } // 呼び出し元でコンパイル中のクラスポインタを元に戻す compiler.pCompilingClass = pBackCompilingClass; // 名前空間を元に戻す compiler.GetNamespaceSupporter().GetLivingNamespaceScopes() = backupNamespaceScopes; // インポートされた名前空間を元に戻す compiler.GetNamespaceSupporter().GetImportedNamespaces() = backupImportedNamespaces; } void Classes::LookaheadClass( const char *className ) { pobj_LoopRefCheck->add( className ); compiler.GetObjectModule().meta.GetClasses().GetClass_recur( className ); pobj_LoopRefCheck->del( className ); } bool Classes::LoopRefCheck( const CClass &objClass ) { if( pobj_LoopRefCheck->check( objClass ) ) { return false; } return true; } void Classes::GetAllClassInfo(void){ //ループ継承チェック用のクラス pobj_LoopRefCheck=new CLoopRefCheck(); //クラスを取得 GetClass_recur(0); delete pobj_LoopRefCheck; pobj_LoopRefCheck=0; // イテレータの準備 this->Iterator_Init(); }