Small CBotTwoOpExpr cleanup

dev-time-step
krzys-h 2016-01-05 13:04:15 +01:00
parent d63773d89d
commit 70555d984c
4 changed files with 94 additions and 57 deletions

View File

@ -148,7 +148,7 @@ public:
/*! /*!
* \brief SetUpdateFunc Defines routine to be called to update the elements * \brief SetUpdateFunc Defines routine to be called to update the elements
* of the class. * of the class.
* \param rMaj * \param rUpdate
* \return * \return
*/ */
bool SetUpdateFunc(void rUpdate(CBotVar* thisVar, void* user)); bool SetUpdateFunc(void rUpdate(CBotVar* thisVar, void* user));

View File

@ -49,75 +49,93 @@ CBotTwoOpExpr::~CBotTwoOpExpr()
delete m_rightop; delete m_rightop;
} }
// type of operands accepted by operations // This list contains all possible operations
#define ENTIER ((1<<CBotTypByte)|(1<<CBotTypShort)|(1<<CBotTypChar)|(1<<CBotTypInt)|(1<<CBotTypLong)) // They are sorted in reversed order of precedence (the ones that get executed first are at the end),
#define FLOTANT ((1<<CBotTypFloat)|(1<<CBotTypDouble)) // the operations have equal precedence until 0 marker
#define BOOLEEN (1<<CBotTypBoolean) // The entries are made of pairs: bitmask of acceptable parameters type and operand token
#define CHAINE (1<<CBotTypString)
#define INTEGER ((1<<CBotTypByte)|(1<<CBotTypShort)|(1<<CBotTypChar)|(1<<CBotTypInt)|(1<<CBotTypLong))
#define FLOAT ((1<<CBotTypFloat)|(1<<CBotTypDouble))
#define BOOLEAN (1<<CBotTypBoolean)
#define STRING (1<<CBotTypString)
#define POINTER (1<<CBotTypPointer) #define POINTER (1<<CBotTypPointer)
#define INSTANCE (1<<CBotTypClass) #define INSTANCE (1<<CBotTypClass)
// list of operations (précéance)
// acceptable type, operand
// zero ends level \TODO précéance
static int ListOp[] = static int ListOp[] =
{ {
BOOLEEN, ID_LOGIC, 0, BOOLEAN, ID_LOGIC,
BOOLEEN, ID_TXT_OR,
BOOLEEN, ID_LOG_OR, 0,
BOOLEEN, ID_TXT_AND,
BOOLEEN, ID_LOG_AND, 0,
BOOLEEN|ENTIER, ID_OR, 0,
BOOLEEN|ENTIER, ID_XOR, 0,
BOOLEEN|ENTIER, ID_AND, 0,
BOOLEEN|ENTIER|FLOTANT
|CHAINE
|POINTER
|INSTANCE,ID_EQ,
BOOLEEN|ENTIER|FLOTANT
|CHAINE
|POINTER
|INSTANCE,ID_NE, 0,
ENTIER|FLOTANT|CHAINE, ID_HI,
ENTIER|FLOTANT|CHAINE, ID_LO,
ENTIER|FLOTANT|CHAINE, ID_HS,
ENTIER|FLOTANT|CHAINE, ID_LS, 0,
ENTIER, ID_SR,
ENTIER, ID_SL,
ENTIER, ID_ASR, 0,
ENTIER|FLOTANT|CHAINE, ID_ADD,
ENTIER|FLOTANT, ID_SUB, 0,
ENTIER|FLOTANT, ID_MUL,
ENTIER|FLOTANT, ID_DIV,
ENTIER|FLOTANT, ID_MODULO, 0,
ENTIER|FLOTANT, ID_POWER, 0,
0, 0,
BOOLEAN, ID_TXT_OR,
BOOLEAN, ID_LOG_OR,
0,
BOOLEAN, ID_TXT_AND,
BOOLEAN, ID_LOG_AND,
0,
BOOLEAN | INTEGER, ID_OR,
0,
BOOLEAN | INTEGER, ID_XOR,
0,
BOOLEAN | INTEGER, ID_AND,
0,
BOOLEAN | INTEGER | FLOAT | STRING | POINTER | INSTANCE, ID_EQ,
BOOLEAN | INTEGER | FLOAT | STRING | POINTER | INSTANCE, ID_NE,
0,
INTEGER | FLOAT | STRING, ID_HI,
INTEGER | FLOAT | STRING, ID_LO,
INTEGER | FLOAT | STRING, ID_HS,
INTEGER | FLOAT | STRING, ID_LS,
0,
INTEGER, ID_SR,
INTEGER, ID_SL,
INTEGER, ID_ASR,
0,
INTEGER | FLOAT | STRING, ID_ADD,
INTEGER | FLOAT, ID_SUB,
0,
INTEGER | FLOAT, ID_MUL,
INTEGER | FLOAT, ID_DIV,
INTEGER | FLOAT, ID_MODULO,
0,
INTEGER | FLOAT, ID_POWER,
0,
0, // end of list
}; };
bool IsInList( int val, int* list, int& typemasque ) bool IsInList(int val, int* list, int& typeMask)
{ {
while (true) while (true)
{ {
if ( *list == 0 ) return false; if ( *list == 0 ) return false;
typemasque = *list++; typeMask = *list++;
if ( *list++ == val ) return true; if ( *list++ == val ) return true;
} }
} }
bool TypeOk( int type, int test ) bool TypeOk(int type, int test)
{ {
while (true) while (true)
{ {
if ( type == 0 ) return (test & 1); if ( type == 0 ) return (test & 1) != 0;
type--; test /= 2; type--; test >>= 1;
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations) CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations)
{ {
int typemasque; int typeMask;
if ( pOperations == nullptr ) pOperations = ListOp; if ( pOperations == nullptr ) pOperations = ListOp;
int* pOp = pOperations; int* pOp = pOperations;
@ -133,13 +151,13 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
if (left == nullptr) return pStack->Return(nullptr, pStk); // if error, transmit if (left == nullptr) return pStack->Return(nullptr, pStk); // if error, transmit
// did we expected the operand? // did we expected the operand?
int TypeOp = p->GetType(); int typeOp = p->GetType();
if ( IsInList( TypeOp, pOperations, typemasque ) ) if ( IsInList(typeOp, pOperations, typeMask) )
{ {
CBotTypResult type1, type2; CBotTypResult type1, type2;
type1 = pStk->GetTypResult(); // what kind of the first operand? type1 = pStk->GetTypResult(); // what kind of the first operand?
if ( TypeOp == ID_LOGIC ) // special case provided for: ? op1: op2; if (typeOp == ID_LOGIC) // special case provided for: ? op1: op2;
{ {
if ( !type1.Eq(CBotTypBoolean) ) if ( !type1.Eq(CBotTypBoolean) )
{ {
@ -197,19 +215,19 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
// what kind of result? // what kind of result?
int TypeRes = std::max( type1.GetType(CBotTypResult::GetTypeMode::NULL_AS_POINTER), type2.GetType(CBotTypResult::GetTypeMode::NULL_AS_POINTER) ); int TypeRes = std::max( type1.GetType(CBotTypResult::GetTypeMode::NULL_AS_POINTER), type2.GetType(CBotTypResult::GetTypeMode::NULL_AS_POINTER) );
if ( TypeOp == ID_ADD && type1.Eq(CBotTypString) ) if (typeOp == ID_ADD && type1.Eq(CBotTypString))
{ {
TypeRes = CBotTypString; TypeRes = CBotTypString;
type2 = type1; // any type convertible chain type2 = type1; // any type convertible chain
} }
else if ( TypeOp == ID_ADD && type2.Eq(CBotTypString) ) else if (typeOp == ID_ADD && type2.Eq(CBotTypString))
{ {
TypeRes = CBotTypString; TypeRes = CBotTypString;
type1 = type2; // any type convertible chain type1 = type2; // any type convertible chain
} }
else if (!TypeOk( TypeRes, typemasque )) type1.SetType(99);// error of type else if (!TypeOk(TypeRes, typeMask)) type1.SetType(99);// error of type
switch ( TypeOp ) switch (typeOp)
{ {
case ID_LOG_OR: case ID_LOG_OR:
case ID_LOG_AND: case ID_LOG_AND:
@ -223,15 +241,15 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
case ID_LS: case ID_LS:
TypeRes = CBotTypBoolean; TypeRes = CBotTypBoolean;
} }
if ( TypeCompatible (type1, type2, TypeOp ) ) // the results are compatible if ( TypeCompatible (type1, type2, typeOp) ) // the results are compatible
{ {
// ok so, saves the operand in the object // ok so, saves the operand in the object
inst->m_leftop = left; inst->m_leftop = left;
// special for evaluation of the operations of the same level from left to right // special for evaluation of the operations of the same level from left to right
while ( IsInList( p->GetType(), pOperations, typemasque ) ) // same operation(s) follows? while ( IsInList(p->GetType(), pOperations, typeMask) ) // same operation(s) follows?
{ {
TypeOp = p->GetType(); typeOp = p->GetType();
CBotTwoOpExpr* i = new CBotTwoOpExpr(); // element for operation CBotTwoOpExpr* i = new CBotTwoOpExpr(); // element for operation
i->SetToken(p); // stores the operation i->SetToken(p); // stores the operation
i->m_leftop = inst; // left operand i->m_leftop = inst; // left operand
@ -241,7 +259,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
i->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp ); i->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp );
type2 = pStk->GetTypResult(); type2 = pStk->GetTypResult();
if ( !TypeCompatible (type1, type2, TypeOp) ) // the results are compatible if ( !TypeCompatible (type1, type2, typeOp) ) // the results are compatible
{ {
pStk->SetError(CBotErrBadType2, &i->m_token); pStk->SetError(CBotErrBadType2, &i->m_token);
delete i; delete i;

View File

@ -32,6 +32,25 @@ namespace CBot
* op1 + op2 * op1 + op2
* op1 > op2 * op1 > op2
* \endcode * \endcode
*
* \section Operations Supported operations
*
* This table is sorted by operator precedence
*
* | Operator |
* | -------------------------------------- |
* | ** |
* | *, /, % |
* | +, - |
* | <<, >>, >>> |
* | >, <, >=, <= |
* | ==, != |
* | & |
* | ^ |
* | \| |
* | &&, and |
* | \|\|, or |
* | a ? b : c (special, see CBotLogicExpr) |
*/ */
class CBotTwoOpExpr : public CBotInstr class CBotTwoOpExpr : public CBotInstr
{ {

View File

@ -96,7 +96,7 @@ public:
~CBotTypResult(); ~CBotTypResult();
/** /**
* \brief Mode for GetType() and GetTypResult() * \brief Mode for GetType()
*/ */
enum class GetTypeMode enum class GetTypeMode
{ {