commit
bf2e3cdfae
|
@ -71,6 +71,13 @@ CBotInstr* CBotExpression::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( p->GetType() == ID_SEP )
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrNoExpression, p);
|
||||||
|
delete inst;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
inst->m_rightop = CBotExpression::Compile(p, pStack);
|
inst->m_rightop = CBotExpression::Compile(p, pStack);
|
||||||
if (inst->m_rightop == nullptr)
|
if (inst->m_rightop == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -118,13 +125,13 @@ CBotInstr* CBotExpression::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
break;
|
break;
|
||||||
case ID_ASSADD:
|
case ID_ASSADD:
|
||||||
if (type2.Eq(CBotTypBoolean) ||
|
if (type2.Eq(CBotTypBoolean) ||
|
||||||
type2.Eq(CBotTypPointer) ) type2 = -1; // numbers and strings
|
type2.GetType() > CBotTypString ) type2.SetType(-1); // numbers and strings
|
||||||
break;
|
break;
|
||||||
case ID_ASSSUB:
|
case ID_ASSSUB:
|
||||||
case ID_ASSMUL:
|
case ID_ASSMUL:
|
||||||
case ID_ASSDIV:
|
case ID_ASSDIV:
|
||||||
case ID_ASSMODULO:
|
case ID_ASSMODULO:
|
||||||
if (type2.GetType() >= CBotTypBoolean) type2 = -1; // numbers only
|
if (type2.GetType() >= CBotTypBoolean) type2.SetType(-1); // numbers only
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +186,18 @@ bool CBotExpression::Execute(CBotStack* &pj)
|
||||||
if ( pile2->GetState()==0)
|
if ( pile2->GetState()==0)
|
||||||
{
|
{
|
||||||
if (m_rightop && !m_rightop->Execute(pile2)) return false; // initial value // interrupted?
|
if (m_rightop && !m_rightop->Execute(pile2)) return false; // initial value // interrupted?
|
||||||
|
if (m_rightop)
|
||||||
|
{
|
||||||
|
CBotVar* var = pile1->GetVar();
|
||||||
|
CBotVar* value = pile2->GetVar();
|
||||||
|
if (var->GetType() == CBotTypString && value->GetType() != CBotTypString)
|
||||||
|
{
|
||||||
|
CBotVar* newVal = CBotVar::Create("", var->GetTypResult());
|
||||||
|
value->Update(pj->GetUserPtr());
|
||||||
|
newVal->SetValString(value->GetValString());
|
||||||
|
pile2->SetVar(newVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
pile2->IncState();
|
pile2->IncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,9 +97,9 @@ bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op)
|
||||||
if (max == 99) return false; // result is void?
|
if (max == 99) return false; // result is void?
|
||||||
|
|
||||||
// special case for strin concatenation
|
// special case for strin concatenation
|
||||||
if (op == ID_ADD && max >= CBotTypString) return true;
|
if (op == ID_ADD && t1 == CBotTypString) return true;
|
||||||
if (op == ID_ASSADD && max >= CBotTypString) return true;
|
if (op == ID_ASSADD && t2 == CBotTypString) return true;
|
||||||
if (op == ID_ASS && t1 == CBotTypString) return true;
|
if (op == ID_ASS && t2 == CBotTypString) return true;
|
||||||
|
|
||||||
if (max >= CBotTypBoolean)
|
if (max >= CBotTypBoolean)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,7 +39,13 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief TypeCompatible Check if two results are consistent to make an
|
* \brief TypeCompatible Check if two results are consistent to make an
|
||||||
* operation.
|
* operation. TypeCompatible is used in two ways:
|
||||||
|
* For non-assignment operations: see CBotTwoOpExpr::Compile
|
||||||
|
* TypeCompatible( leftType, rightType, opType )
|
||||||
|
|
||||||
|
* For assignment or compound assignment operations (it's reversed):
|
||||||
|
* see CBotReturn::Compile & CBotExpression::Compile
|
||||||
|
* TypeCompatible( valueType, varType, opType )
|
||||||
* \param type1
|
* \param type1
|
||||||
* \param type2
|
* \param type2
|
||||||
* \param op
|
* \param op
|
||||||
|
|
|
@ -64,6 +64,12 @@ bool CBotLeftExprVar::Execute(CBotStack* &pj)
|
||||||
CBotVar* var2 = pj->GetVar(); // Initial value on the stack
|
CBotVar* var2 = pj->GetVar(); // Initial value on the stack
|
||||||
if (var2 != nullptr)
|
if (var2 != nullptr)
|
||||||
{
|
{
|
||||||
|
if (m_typevar.Eq(CBotTypString) && var2->GetType() != CBotTypString)
|
||||||
|
{
|
||||||
|
var2->Update(pj->GetUserPtr());
|
||||||
|
var1->SetValString(var2->GetValString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
var1->SetVal(var2); // Set the value
|
var1->SetVal(var2); // Set the value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -214,6 +214,13 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
|
||||||
|
|
||||||
type2 = pStk->GetTypResult(); // what kind of results?
|
type2 = pStk->GetTypResult(); // what kind of results?
|
||||||
|
|
||||||
|
if ( type1.Eq(99) || type2.Eq(99) ) // operand is void
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrBadType2, &inst->m_token);
|
||||||
|
delete inst;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// 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))
|
||||||
|
@ -267,7 +274,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
|
||||||
return pStack->Return(nullptr, pStk);
|
return pStack->Return(nullptr, pStk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( TypeRes != CBotTypString )
|
if ( TypeRes != CBotTypString ) // keep string conversion
|
||||||
TypeRes = std::max(type1.GetType(), type2.GetType());
|
TypeRes = std::max(type1.GetType(), type2.GetType());
|
||||||
inst = i;
|
inst = i;
|
||||||
}
|
}
|
||||||
|
@ -370,7 +377,9 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack)
|
||||||
// what kind of result?
|
// what kind of result?
|
||||||
int TypeRes = std::max(type1.GetType(), type2.GetType());
|
int TypeRes = std::max(type1.GetType(), type2.GetType());
|
||||||
|
|
||||||
if ( GetTokenType() == ID_ADD && type1.Eq(CBotTypString) )
|
// see "any type convertible chain" in compile method
|
||||||
|
if ( GetTokenType() == ID_ADD &&
|
||||||
|
(type1.Eq(CBotTypString) || type2.Eq(CBotTypString)) )
|
||||||
{
|
{
|
||||||
TypeRes = CBotTypString;
|
TypeRes = CBotTypString;
|
||||||
}
|
}
|
||||||
|
@ -397,7 +406,8 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack)
|
||||||
CBotVar* result = CBotVar::Create("", TypeRes);
|
CBotVar* result = CBotVar::Create("", TypeRes);
|
||||||
|
|
||||||
// creates a variable to perform the calculation in the appropriate type
|
// creates a variable to perform the calculation in the appropriate type
|
||||||
TypeRes = std::max(type1.GetType(), type2.GetType());
|
if ( TypeRes != CBotTypString ) // keep string conversion
|
||||||
|
TypeRes = std::max(type1.GetType(), type2.GetType());
|
||||||
|
|
||||||
if ( GetTokenType() == ID_ADD && type1.Eq(CBotTypString) )
|
if ( GetTokenType() == ID_ADD && type1.Eq(CBotTypString) )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue