#include "common.h" int MakeWholeType(int size,int bSigned){ switch(size){ case 1: if(bSigned) return DEF_SBYTE; else return DEF_BYTE; break; case 2: if(bSigned) return DEF_INTEGER; else return DEF_WORD; break; case 4: if(bSigned) return DEF_LONG; else return DEF_DWORD; break; case 8: if(bSigned) return DEF_INT64; else return DEF_QWORD; break; } return 0; } int AutoBigCast(int BaseType,int CalcType){ int type; type=CalcType; if(BaseType==0||BaseType==-1){ //ベースタイプが未定のとき return type; } if(!IsWholeNumberType(type)){ //整数型ではないときは暗黙の変換は必要なし return type; } if(BaseType==DEF_OBJECT||BaseType==DEF_STRUCT){ //ベースタイプがオブジェクトのときは暗黙の変換は必要なし return type; } int BaseTypeSize; BaseTypeSize=GetTypeSize(BaseType,-1); if(IsRealNumberType(BaseType)){ if(GetTypeSize(CalcType,-1)<4) type=MakeWholeType(4,IsSignedType(CalcType)); } else if(BaseTypeSize>GetTypeSize(CalcType,-1)){ //要求される型のほうがサイズが大きいとき type=MakeWholeType(BaseTypeSize,IsSignedType(CalcType)); } if(!type){ extern int cp; SetError(300,NULL,cp); } return type; } BOOL CheckCalcType(int idCalc,int *type,int sp){ //演算子の右辺、左辺の型をチェック extern int cp; //演算子名を取得 char temporary[255]; GetCalcName(idCalc,temporary); switch(idCalc){ ///////////////////////////////////// // 実数に対する論理演算はエラー ///////////////////////////////////// case CALC_XOR: case CALC_OR: case CALC_AND: if(IsRealNumberType(type[sp-2])||IsRealNumberType(type[sp-1])){ //いずれかの項が実数のとき SetError(45,temporary,cp); return 0; } //As以外の演算子に型名が指定されていないかをチェック if((type[sp-2]&FLAG_CAST)||(type[sp-1]&FLAG_CAST)){ SetError(48,temporary,cp); return 0; } break; case CALC_NOT: if(IsRealNumberType(type[sp-1])){ //実数のとき SetError(45,temporary,cp); return 0; } //As以外の演算子に型名が指定されていないかをチェック if(type[sp-1]&FLAG_CAST){ SetError(48,temporary,cp); return 0; } break; ///////////////////////////////////// // 比較演算はチェック項目なし ///////////////////////////////////// case CALC_PE: case CALC_QE: case CALC_NOTEQUAL: case CALC_EQUAL: case CALC_P: case CALC_Q: //As以外の演算子に型名が指定されていないかをチェック if((type[sp-2]&FLAG_CAST)||(type[sp-1]&FLAG_CAST)){ SetError(48,temporary,cp); return 0; } break; ///////////////////////////////////// // 算術演算をチェック ///////////////////////////////////// case CALC_ADDITION: case CALC_SUBTRACTION: case CALC_PRODUCT: case CALC_QUOTIENT: case CALC_POWER: //As以外の演算子に型名が指定されていないかをチェック if((type[sp-2]&FLAG_CAST)||(type[sp-1]&FLAG_CAST)){ SetError(48,temporary,cp); return 0; } break; case CALC_SHL: case CALC_SHR: case CALC_MOD: case CALC_INTQUOTIENT: if(IsRealNumberType(type[sp-2])||IsRealNumberType(type[sp-1])){ //いずれかの項が実数のとき SetError(45,temporary,cp); return 0; } //As以外の演算子に型名が指定されていないかをチェック if((type[sp-2]&FLAG_CAST)||(type[sp-1]&FLAG_CAST)){ SetError(48,temporary,cp); return 0; } break; case CALC_AS: if((type[sp-1]&FLAG_CAST)==0){ //型名が指定されていないときはエラー SetError(47,NULL,cp); return 0; } break; case CALC_BYVAL: if(type[sp-1]&FLAG_CAST){ //型名が指定されていないときはエラー SetError(47,NULL,cp); return 0; } break; case CALC_MINUSMARK: //As以外の演算子に型名が指定されていないかをチェック if(type[sp-1]&FLAG_CAST){ SetError(48,temporary,cp); return 0; } break; } return 1; } int GetReturnType_OperatorProc(int idCalc,const Type &baseType,int *type,LONG_PTR *index_stack,int &sp){ //オーバーロードされたオペレータ関数の戻り値を取得 CClass *pobj_c; pobj_c=(CClass *)index_stack[sp-2]; std::vector subs; pobj_c->EnumMethod( idCalc, subs ); if( subs.size() == 0 ){ return 0; } //項の数 BOOL bTwoTerm=1; if(idCalc==CALC_AS) bTwoTerm=0; ///////////////////////////////////////////// // オーバーロード解決用のパラメータを設定 ///////////////////////////////////////////// //_System_LocalThis Parameters params; if(bTwoTerm){ params.push_back( new Parameter( "", Type( type[sp-1], index_stack[sp-1] ) ) ); } //オーバーロードを解決 char temporary[255]; if(idCalc==CALC_EQUAL) lstrcpy(temporary,"=="); else GetCalcName(idCalc,temporary); UserProc *pUserProc = OverloadSolution( temporary, subs, params, baseType ); if(bTwoTerm){ delete params[0]; } if(!pUserProc){ return 0; } else{ //オーバーロードされていないが、パラメータ個数が一致しないとき if(params.size()!=pUserProc->Params().size()){ return 0; } } sp--; type[sp-1]=pUserProc->ReturnType().GetBasicType(); index_stack[sp-1]=pUserProc->ReturnType().GetIndex(); return 1; } bool Operator_New_GetType(const char *Parameter,const Type &baseType, Type &resultType ){ char TypeName[VN_SIZE],CreateParameter[VN_SIZE],objectSizeStr[VN_SIZE]; int i,i2; i=0; if(Parameter[0]=='['){ i=GetStringInBracket(objectSizeStr,Parameter); SlideString(objectSizeStr+1,-1); objectSizeStr[i-2]=0; } else objectSizeStr[0]=0; for(i2=0;;i++,i2++){ if(Parameter[i]=='('){ TypeName[i2]=0; //コンストラクタに渡すパラメータを取得 i2=GetStringInPare(CreateParameter,Parameter+i); RemoveStringPare(CreateParameter); i+=i2; if(Parameter[i]!='\0'){ SetError(42,NULL,cp); return false; } break; } TypeName[i2]=Parameter[i]; if(Parameter[i]=='\0'){ CreateParameter[0]=0; break; } } if( !Type::StringToType( TypeName, resultType ) ){ return false; } if( baseType.IsObject() ){ resultType.SetBasicType( DEF_OBJECT ); } else{ resultType.SetBasicType( DEF_PTR_OBJECT ); } return true; } bool GetTermType( const char *term, Type &resultType, bool &isLiteral, bool *pIsClassName ){ char parameter[VN_SIZE]; // Withを解決 char termFull[VN_SIZE]; if(term[0]=='.'){ GetWithName(termFull); lstrcat(termFull,term); } else lstrcpy(termFull,term); char termLeft[VN_SIZE]; lstrcpy(termLeft,termFull); // パース char member[VN_SIZE]; CClass::RefType refType; if( SplitMemberName( termFull, termLeft, member, refType ) ){ /////////////////////////////////////////////////////////////////// // オブジェクトとメンバに分解できるとき // termLeft.member /////////////////////////////////////////////////////////////////// isLiteral = false; // オブジェクト側の型を取得 bool isClassName = false; Type leftType; if( GetTermType( termLeft, leftType, isLiteral, &isClassName ) ){ if( isClassName == false && Smoothie::Meta::blittableTypes.IsExist( leftType ) ){ // 左側のオブジェクト部分がBlittable型のとき char temporary[VN_SIZE]; lstrcpy( temporary, termLeft ); sprintf( termLeft, "%s(%s)", Smoothie::Meta::blittableTypes.Find( leftType ).GetCreateStaticMethodFullName().c_str(), temporary ); if( !GetTermType( termLeft, leftType, isLiteral, &isClassName ) ){ goto globalArea; } } } else{ goto globalArea; } if( isClassName ){ // 静的メンバ/メソッドの場合 goto globalArea; } if( !leftType.HasMember() ){ // メンバを持たない型の場合 return false; } const CClass &objClass = leftType.GetClass(); /////////////////////////////////////////////////////////////////// // メンバを検索 /////////////////////////////////////////////////////////////////// if( GetMemberType( objClass, member, resultType, 0, false ) ){ // メンバが見つかったとき return true; } /////////////////////////////////////////////////////////////////// // 動的メソッドを検索 /////////////////////////////////////////////////////////////////// vector userProcs; char methodName[VN_SIZE] ,lpPtrOffset[VN_SIZE]; lstrcpy( methodName, member ); GetVarFormatString(methodName,parameter,lpPtrOffset,member,refType); objClass.EnumMethod( methodName, userProcs ); UserProc *pUserProc; if(userProcs.size()){ //オーバーロードを解決 pUserProc=OverloadSolutionWithStrParam(termFull,userProcs,parameter,termLeft); if( pUserProc ){ resultType = pUserProc->ReturnType(); return true; } } return false; } ////////////////////////////////////////////// // クラス名かどうかをチェック(静的メンバ用) ////////////////////////////////////////////// if( pIsClassName ){ if( pobj_DBClass->Find( termFull ) ){ *pIsClassName = true; return true; } } ///////////////////////////////////////////////////////////////// // グローバル属性 ///////////////////////////////////////////////////////////////// globalArea: if(lstrcmpi(termFull,"This")==0){ //Thisオブジェクト resultType.SetType( DEF_OBJECT, pobj_CompilingClass ); isLiteral = false; return true; } ////////////////////////////////////// // 関数(DLL、ユーザー定義、組み込み) ////////////////////////////////////// char procName[VN_SIZE]; char temporary[8192]; int i2=GetCallProcName(termFull,procName); if(termFull[i2]=='('){ int i4=GetStringInPare_RemovePare(parameter,termFull+i2+1); void *pProc; int idProc=GetProc(procName,(void **)&pProc); if(idProc){ //閉じカッコ")"に続く文字がNULLでないとき if(termFull[i2+1+i4+1]!='\0'){ SetError(42,NULL,cp); } //////////////// // 呼び出し //////////////// if( !CallProc(idProc,pProc,procName,parameter, resultType, false ) ){ return false; } if( resultType.IsNull() ){ //戻り値が存在しないとき return false; } isLiteral = false; return true; } else if(GetConstCalcBuffer(procName,parameter,temporary)){ ///////////////////////// // マクロ関数 ///////////////////////// //閉じカッコ")"に続く文字がNULLでないときはエラーにする if(termFull[i2+1+i4+1]!='\0') SetError(42,NULL,cp); //マクロ関数の場合 if( !NumOpe_GetType(temporary,Type(),resultType) ){ return false; } if( !IS_LITERAL( resultType.GetIndex() ) ){ //リテラル値ではなかったとき isLiteral = false; } return true; } } //////////////////////////////// // インデクサ(getアクセサ) //////////////////////////////// char VarName[VN_SIZE],ArrayElements[VN_SIZE]; GetArrayElement(termFull,VarName,ArrayElements); if(ArrayElements[0]){ GetVarType(VarName,resultType,false); if( resultType.IsObject() ){ if( !GetReturnTypeOfIndexerGetterProc( resultType.GetClass(),resultType) ){ SetError(1,NULL,cp); return false; } isLiteral = false; return true; } } //////////////////////////////// // 変数 //////////////////////////////// if( GetVarType( termFull, resultType, false ) ){ if( resultType.GetBasicType() & FLAG_PTR ){ //配列ポインタ resultType.SetBasicType( GetPtrType( resultType.GetBasicType()^FLAG_PTR ) ); } isLiteral = false; return true; } ///////////////////////////////// // プロパティ用のメソッド ///////////////////////////////// //配列要素を排除 GetArrayElement(termFull,VarName,ArrayElements); if(GetSubHash(VarName,0)){ GetReturnTypeOfPropertyMethod(termFull,NULL,resultType); isLiteral = false; return true; } return false; } bool NumOpe_GetType( const char *expression, const Type &baseType, Type &resultType ){ extern int cp; int i,i3; if(expression[0]=='\0'){ SetError(1,NULL,cp); return false; } if(expression[0]==1&& expression[1]==ESC_NEW ){ //New演算子(オブジェクト生成) return Operator_New_GetType(expression+2,baseType, resultType ); } if( expression[0] == '[' ){ if( !baseType.IsPointer() ){ SetError(1,NULL,cp); return false; } resultType = baseType; return true; } ///////////////////////////////// // 式要素を逆ポーランド式で取得 ///////////////////////////////// char *values[255]; long calc[255]; long stack[255]; int pnum; if(!GetNumOpeElements(expression,&pnum,values,calc,stack)){ for(i=0;iIsEqualsOrSubClass( (CClass *)index_stack[sp-2] ) || ((CClass *)index_stack[sp-2])->IsEqualsOrSubClass( (CClass *)index_stack[sp-1] ) )){ // ダウンキャストを許可する } else{ //オーバーロードされたオペレータを呼び出す if(!GetReturnType_OperatorProc(idCalc,baseType,type_stack,index_stack,sp)){ goto error; } continue; } } if(!CheckCalcType(idCalc,type_stack,sp)) goto error; } switch(idCalc){ //数値 case 0: index_stack[sp]=-1; isNothing_stack[sp] = false; char *term; term = values[i]; if( calc[i+1]%100 == CALC_AS ){ // As演算子の右辺値 //型名 if( Type::StringToType( term, resultType ) ){ if( resultType.IsObject() ){ if( resultType.GetClass().IsBlittableType() ){ // Blittable型のときは基本型として扱う // ※ただし、コンパイル中のメソッドがBlittable型クラスに属していないこと if( UserProc::IsLocalAreaCompiling() && UserProc::CompilingUserProc().HasParentClass() && UserProc::CompilingUserProc().GetParentClass().IsBlittableType() ) { // コンパイル中のメソッドがBlittable型クラスに属している } else{ resultType = resultType.GetClass().GetBlittableType(); } } } resultType.SetBasicType( resultType.GetBasicType() | FLAG_CAST ); } else{ SetError(3, term, cp ); goto error; } type_stack[sp] = resultType.GetBasicType(); index_stack[sp] = resultType.GetIndex(); sp++; break; } if(term[0]=='\"'){ StrLiteral: if( baseType.IsObject() || baseType.IsNull() ){ //要求タイプがオブジェクト、または未定のとき type_stack[sp]=DEF_OBJECT; index_stack[sp]=(LONG_PTR)pobj_DBClass->GetStringClassPtr(); bLiteralCalculation=0; sp++; break; } type_stack[sp]=typeOfPtrChar; bLiteralCalculation=0; } else if((term[0]=='e'||term[0]=='E')&& (term[1]=='x'||term[1]=='X')&& term[2]=='\"'){ //拡張版リテラル文字列(エスケープシーケンス可能) goto StrLiteral; } else if(IsVariableTopChar(term[0])|| term[0]=='*'|| (term[0]=='.'&&IsVariableTopChar(term[1]))){ ////////////////// // 何らかの識別子 bool isLiteral = true; if( GetTermType( term, resultType, isLiteral ) ){ type_stack[sp] = resultType.GetBasicType(); index_stack[sp] = resultType.GetIndex(); if( !isLiteral ){ bLiteralCalculation=0; } sp++; break; } // Nothing if( lstrcmp( term, "Nothing" ) == 0 ){ isNothing_stack[sp] = true; type_stack[sp] = DEF_OBJECT; if( baseType.IsObject() ){ index_stack[sp] = baseType.GetIndex(); } else{ index_stack[sp] = (LONG_PTR)pobj_DBClass->GetObjectClassPtr(); } bLiteralCalculation = 0; sp++; break; } ////////////// // 定数の場合 ////////////// i3 = CDBConst::obj.GetBasicType(term); if(i3){ if( CDBConst::obj.IsStringPtr( term ) ){ //リテラル文字列 goto StrLiteral; } type_stack[sp]=i3; if(IsRealNumberType(i3)){ //実数 goto Literal; } else if(IsWholeNumberType(i3)){ //整数 goto Literal; } else if(Is64Type(i3)){ //64ビット整数値 goto Literal; } else{ SetError(1,NULL,0); goto error; } } ///////////////////////////////// // プロパティ用のメソッド ///////////////////////////////// //配列要素を排除 char VarName[VN_SIZE],ArrayElements[VN_SIZE]; GetArrayElement(term,VarName,ArrayElements); if(GetSubHash(VarName,0)){ SetError(); Type tempType; GetReturnTypeOfPropertyMethod(term,NULL,tempType); //大きな型への暗黙の変換 type_stack[sp]=tempType.GetBasicType(); index_stack[sp]=tempType.GetIndex(); bLiteralCalculation=0; sp++; break; } //該当する識別子が見当たらないときはエラー扱いにする bError=1; SetError(3,term,cp); type_stack[sp]=DEF_DOUBLE; } else{ //リテラル値 int base_type = 0; if( !baseType.IsNull() ) base_type = baseType.GetBasicType(); type_stack[sp]=GetLiteralValue(term,&i64data,base_type); Literal: if((long)i64data==0&&index_stack[sp]==-1) index_stack[sp]=LITERAL_NULL; } sp++; break; //論理演算子 case CALC_XOR: case CALC_OR: case CALC_AND: sp--; type_stack[sp-1]=NeutralizationType(type_stack[sp-1],index_stack[sp-1],type_stack[sp],index_stack[sp]); break; case CALC_NOT: //values[sp-1]=Not values[sp-1] //NOT演算子 break; //比較演算子 case CALC_PE: //values[sp-2] <= values[sp-1] case CALC_QE: //values[sp-2] >= values[sp-1] case CALC_P: //values[sp-2] < values[sp-1] case CALC_Q: //values[sp-2] > values[sp-1] case CALC_NOTEQUAL: //values[sp-2] <> values[sp-1] case CALC_EQUAL: //values[sp-2] = values[sp-1] sp--; type_stack[sp-1]=DEF_LONG; break; //ビットシフト case CALC_SHL: //values[sp-2] << values[sp-1] case CALC_SHR: //values[sp-2] >> values[sp-1] sp--; break; //算術演算 case CALC_ADDITION: case CALC_SUBTRACTION: case CALC_PRODUCT: sp--; type_stack[sp-1]=NeutralizationType(type_stack[sp-1],index_stack[sp-1],type_stack[sp],index_stack[sp]); break; case CALC_MOD: //values[sp-2]%=values[sp-1] //剰余演算 sp--; type_stack[sp-1]=NeutralizationType(type_stack[sp-1],index_stack[sp-1],type_stack[sp],index_stack[sp]); break; case CALC_QUOTIENT: //values[sp-2]/=values[sp-1]; //除算 sp--; type_stack[sp-1]=NeutralizationType(type_stack[sp-1],index_stack[sp-1],type_stack[sp],index_stack[sp]); break; case CALC_INTQUOTIENT: //values[sp-2]/=values[sp-1] //整数除算 sp--; type_stack[sp-1]=NeutralizationType(type_stack[sp-1],index_stack[sp-1],type_stack[sp],index_stack[sp]); break; case CALC_MINUSMARK: //values[sp-1]=-values[sp-1] //符号反転 break; case CALC_POWER: //べき乗演算(浮動小数点演算のみ) sp--; //未完成 break; case CALC_AS: //キャスト type_stack[sp-2]=type_stack[sp-1]&(~FLAG_CAST); index_stack[sp-2]=index_stack[sp-1]; sp--; break; case CALC_BYVAL: //ポインタ型→参照型 if( PTR_LEVEL( type_stack[sp-1] ) <= 0 ){ //ポインタ型ではないとき SetError( 3, NULL, cp ); goto error; } type_stack[sp-1] = PTR_LEVEL_DOWN( type_stack[sp-1] ); break; } } if(bError) goto error; if(sp!=1){ SetError(1,NULL,cp); goto error; } if(bLiteralCalculation){ //右辺値が数値の定数式の場合 int base_type = 0; if( !baseType.IsNull() ) base_type = baseType.GetBasicType(); Type tempType; StaticCalculation(true, expression,base_type,&i64data,tempType); type_stack[0]=tempType.GetBasicType(); index_stack[0]=tempType.GetIndex(); } else{ //右辺値が数値の定数式ではないとき if(IS_LITERAL(index_stack[0])) index_stack[0]=-1; } resultType.SetType( type_stack[0], index_stack[0] ); bool isSuccessful = true; goto finish; ////////////////// // エラー処理 ////////////////// error: isSuccessful = false; goto finish; finish: for(i=0;i