forked from Mirrors/openclonk
Fix C4Value
-Various conversion tables -Store -0.0 as 0.0 -Operator == Fix float parsing Change operator type checkfloating-point
parent
962b4f0070
commit
7e857994d0
|
@ -1273,6 +1273,7 @@ protected:
|
|||
virtual void ProcessChar(char &rChar) = 0;
|
||||
virtual void ProcessString(char *szString, size_t iMaxLength, bool fIsID) = 0;
|
||||
virtual void ProcessString(char **pszString, bool fIsID) = 0;
|
||||
virtual void ProcessFloat(float &) = 0;
|
||||
|
||||
public:
|
||||
// value functions
|
||||
|
@ -1284,7 +1285,7 @@ public:
|
|||
virtual void Byte(uint8_t &rByte) { if (haveCompleteMatch()) if (!iEntryNr--) { int32_t i=rByte; ProcessInt(i); rByte =i; } }
|
||||
virtual void Boolean(bool &rBool) { if (haveCompleteMatch()) if (!iEntryNr--) ProcessBool(rBool); }
|
||||
virtual void Character(char &rChar) { if (haveCompleteMatch()) if (!iEntryNr--) ProcessChar(rChar); }
|
||||
virtual void Float(float &) { assert(!"Can't compile floats to/from structs"); }
|
||||
virtual void Float(float &rFloat) { if (haveCompleteMatch()) if (!iEntryNr--) ProcessFloat(rFloat); }
|
||||
|
||||
// The C4ID-Adaptor will set RCT_ID for it's strings (see C4Id.h), so we don't have to guess the type.
|
||||
virtual void String(char *szString, size_t iMaxLength, RawCompileType eType)
|
||||
|
@ -1330,9 +1331,10 @@ public:
|
|||
|
||||
protected:
|
||||
// get values as C4Value
|
||||
virtual void ProcessInt(int32_t &rInt) { Res = C4VInt(rInt); }
|
||||
virtual void ProcessBool(bool &rBool) { Res = C4VBool(rBool); }
|
||||
virtual void ProcessChar(char &rChar) { Res = C4VString(FormatString("%c", rChar)); }
|
||||
virtual void ProcessInt(int32_t &rInt) { Res = C4VInt(rInt); }
|
||||
virtual void ProcessBool(bool &rBool) { Res = C4VBool(rBool); }
|
||||
virtual void ProcessChar(char &rChar) { Res = C4VString(FormatString("%c", rChar)); }
|
||||
virtual void ProcessFloat(float &rFloat) { Res = C4VFloat(rFloat); }
|
||||
|
||||
virtual void ProcessString(char *szString, size_t iMaxLength, bool fIsID)
|
||||
{ Res = (fIsID ? C4VPropList(C4Id2Def(C4ID(szString))) : C4VString(szString)); }
|
||||
|
|
|
@ -268,21 +268,21 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
pCurVal->SetBool(!pCurVal->getBool());
|
||||
break;
|
||||
case AB_Neg: // -
|
||||
CheckOpPar(C4V_Int, "-");
|
||||
CheckOpPar(C4V_Numeric, "-");
|
||||
pCurVal->Set(-*pCurVal);
|
||||
break;
|
||||
case AB_Inc: // ++
|
||||
CheckOpPar(C4V_Int, "++");
|
||||
CheckOpPar(C4V_Numeric, "++");
|
||||
++(*pCurVal);
|
||||
break;
|
||||
case AB_Dec: // --
|
||||
CheckOpPar(C4V_Int, "--");
|
||||
CheckOpPar(C4V_Numeric, "--");
|
||||
--(*pCurVal);
|
||||
break;
|
||||
// postfix
|
||||
case AB_Pow: // **
|
||||
{
|
||||
CheckOpPars(C4V_Int, C4V_Int, "**");
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, "**");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
pPar1->Set(pPar1->Pow(*pPar2));
|
||||
PopValue();
|
||||
|
@ -290,7 +290,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
}
|
||||
case AB_Div: // /
|
||||
{
|
||||
CheckOpPars(C4V_Int, C4V_Int, "/");
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, "/");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
if (!pPar2->_getInt())
|
||||
throw new C4AulExecError(pCurCtx->Obj, "division by zero");
|
||||
|
@ -300,7 +300,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
}
|
||||
case AB_Mul: // *
|
||||
{
|
||||
CheckOpPars(C4V_Int, C4V_Int, "*");
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, "*");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
*pPar1 *= *pPar2;
|
||||
PopValue();
|
||||
|
@ -308,7 +308,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
}
|
||||
case AB_Mod: // %
|
||||
{
|
||||
CheckOpPars(C4V_Int, C4V_Int, "%");
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, "%");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
if (pPar2->_getInt())
|
||||
pPar1->SetInt(pPar1->_getInt() % pPar2->_getInt());
|
||||
|
@ -319,7 +319,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
}
|
||||
case AB_Sub: // -
|
||||
{
|
||||
CheckOpPars(C4V_Int, C4V_Int, "-");
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, "-");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
*pPar1 -= *pPar2;
|
||||
PopValue();
|
||||
|
@ -327,7 +327,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
}
|
||||
case AB_Sum: // +
|
||||
{
|
||||
CheckOpPars(C4V_Int, C4V_Int, "+");
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, "+");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
*pPar1 += *pPar2;
|
||||
PopValue();
|
||||
|
@ -351,7 +351,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
}
|
||||
case AB_LessThan: // <
|
||||
{
|
||||
CheckOpPars(C4V_Int, C4V_Int, "<");
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, "<");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
pPar1->SetBool(pPar1->_getInt() < pPar2->_getInt());
|
||||
PopValue();
|
||||
|
@ -359,7 +359,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
}
|
||||
case AB_LessThanEqual: // <=
|
||||
{
|
||||
CheckOpPars(C4V_Int, C4V_Int, "<=");
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, "<=");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
pPar1->SetBool(pPar1->_getInt() <= pPar2->_getInt());
|
||||
PopValue();
|
||||
|
@ -367,7 +367,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
}
|
||||
case AB_GreaterThan: // >
|
||||
{
|
||||
CheckOpPars(C4V_Int, C4V_Int, ">");
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, ">");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
pPar1->SetBool(pPar1->_getInt() > pPar2->_getInt());
|
||||
PopValue();
|
||||
|
@ -375,7 +375,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
}
|
||||
case AB_GreaterThanEqual: // >=
|
||||
{
|
||||
CheckOpPars(C4V_Int, C4V_Int, ">=");
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, ">=");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
pPar1->SetBool(pPar1->_getInt() >= pPar2->_getInt());
|
||||
PopValue();
|
||||
|
|
|
@ -490,25 +490,22 @@ C4AulTokenType C4AulParseState::GetNextToken(OperatorPolicy Operator)
|
|||
else if (C == ';') return ATT_SCOLON; // ";"
|
||||
else if (Inside(C, '0', '9'))
|
||||
{
|
||||
// integer
|
||||
if (C == '0' && *SPos == 'x')
|
||||
{
|
||||
// hexadecimal
|
||||
cInt = StrToI32(SPos + 1, 16, &SPos);
|
||||
return ATT_INT;
|
||||
}
|
||||
cInt = StrToI32(SPos+1, 16, &SPos); // hexadecimal
|
||||
else
|
||||
{
|
||||
// decimal
|
||||
cInt = StrToI32(SPos0, 10, &SPos);
|
||||
if(*SPos == '.') // float
|
||||
{
|
||||
float value = StrToF32(SPos0, 0);
|
||||
cInt = *reinterpret_cast<int*>(&value);
|
||||
return ATT_FLOAT;
|
||||
}
|
||||
if (*SPos != '.' && *SPos != 'e' && *SPos != 'E') // float check: point or exponent
|
||||
return ATT_INT;
|
||||
}
|
||||
*reinterpret_cast<float*>(&cInt) = StrToF32(SPos0, const_cast<char**>(&SPos));
|
||||
/* bool dot = *SPos == '.';
|
||||
while (Inside(*++SPos, '0', '9'));
|
||||
if (dot && (*SPos == 'e' || *SPos == 'E'))
|
||||
{
|
||||
++SPos;
|
||||
if(*SPos == '+' || *SPos == '-') ++SPos;
|
||||
Inside(C, '0', '9');
|
||||
} */ // Use this block if you don't trust the const_cast
|
||||
return ATT_FLOAT;
|
||||
}
|
||||
else if (C == '-' && *SPos == '>' && *(SPos + 1) == '~')
|
||||
{ SPos+=2; return ATT_CALLFS;}// "->~"
|
||||
|
|
|
@ -111,7 +111,7 @@ bool C4Value::WarnAboutConversion(C4V_Type Type, C4V_Type vtToType)
|
|||
{
|
||||
case C4V_Nil: return Type != C4V_Nil && Type != C4V_Any;
|
||||
case C4V_Float: case C4V_Numeric:
|
||||
case C4V_Int: return Type != C4V_Int && Type != C4V_Nil && Type != C4V_Bool && Type != C4V_Any;
|
||||
case C4V_Int: return Type != C4V_Int && Type != C4V_Float && Type != C4V_Nil && Type != C4V_Bool && Type != C4V_Any;
|
||||
case C4V_Bool: return false;
|
||||
case C4V_PropList: return Type != C4V_PropList && Type != C4V_Effect && Type != C4V_Def && Type != C4V_Object && Type != C4V_Nil && Type != C4V_Any;
|
||||
case C4V_String: return Type != C4V_String && Type != C4V_Nil && Type != C4V_Any;
|
||||
|
@ -537,7 +537,7 @@ bool C4Value::operator == (const C4Value& Value2) const
|
|||
{
|
||||
case C4V_Int:
|
||||
case C4V_Bool:
|
||||
return C4Real(Data.Float) == static_cast<int>(Data.Int);
|
||||
return C4Real(Data.Float) == static_cast<int>(Value2.Data.Int);
|
||||
case C4V_Float:
|
||||
return Data.Float == Value2.Data.Float;
|
||||
default:
|
||||
|
|
|
@ -98,8 +98,22 @@ public:
|
|||
~C4Value() { DelDataRef(Data, Type, NextRef); }
|
||||
|
||||
// Checked getters
|
||||
int32_t getInt() const { return CheckConversion(C4V_Int) ? Data.Int : 0; }
|
||||
C4Real getFloat() const { if(CheckConversion(C4V_Float)) return Data.Float; return C4Real(0); }
|
||||
int32_t getInt() const
|
||||
{
|
||||
if (!CheckConversion(C4V_Int))
|
||||
return 0;
|
||||
if (Type == C4V_Float)
|
||||
return C4Real(Data.Float);
|
||||
return Data.Int;
|
||||
}
|
||||
C4Real getFloat() const
|
||||
{
|
||||
if (!CheckConversion(C4V_Float))
|
||||
return C4Real(0);
|
||||
if (Type != C4V_Float)
|
||||
return C4Real(_getInt());
|
||||
return C4Real(Data.Float);
|
||||
}
|
||||
bool getBool() const { return CheckConversion(C4V_Bool) ? !! Data : 0; }
|
||||
C4ID getC4ID() const;
|
||||
C4Object * getObj() const;
|
||||
|
@ -126,8 +140,7 @@ public:
|
|||
void Set(const C4Value &nValue) { Set(nValue.Data, nValue.Type); }
|
||||
|
||||
void SetInt(int i) { C4V_Data d; d.Int = i; Set(d, C4V_Int); }
|
||||
void SetFloat(C4Real f) { C4V_Data d; d.Float = f; Set(d, C4V_Float); }
|
||||
|
||||
void SetFloat(C4Real f) { C4V_Data d; d.Float = f; if(d.Int == 0x80000000) d.Int = 0; Set(d, C4V_Float); }
|
||||
void SetBool(bool b) { C4V_Data d; d.Int = b; Set(d, C4V_Bool); }
|
||||
void SetString(C4String * Str) { C4V_Data d; d.Str = Str; Set(d, C4V_String); }
|
||||
void SetArray(C4ValueArray * Array) { C4V_Data d; d.Array = Array; Set(d, C4V_Array); }
|
||||
|
@ -166,7 +179,7 @@ public:
|
|||
{
|
||||
switch (Type)
|
||||
{
|
||||
case C4V_Any:
|
||||
case C4V_Nil:
|
||||
case C4V_Int:
|
||||
case C4V_Bool:
|
||||
++Data.Int; Type = C4V_Int; break;
|
||||
|
@ -187,7 +200,7 @@ public:
|
|||
{
|
||||
switch (Type)
|
||||
{
|
||||
case C4V_Any:
|
||||
case C4V_Nil:
|
||||
case C4V_Int:
|
||||
case C4V_Bool:
|
||||
--Data.Int; Type = C4V_Int; break;
|
||||
|
@ -209,7 +222,7 @@ public:
|
|||
C4Value nrv;
|
||||
switch (Type)
|
||||
{
|
||||
case C4V_Any:
|
||||
case C4V_Nil:
|
||||
case C4V_Int:
|
||||
case C4V_Bool:
|
||||
nrv.Data.Int = -Data.Int;
|
||||
|
@ -217,6 +230,7 @@ public:
|
|||
break;
|
||||
case C4V_Float:
|
||||
nrv.Data.Int = Data.Int ^ 0x80000000;
|
||||
if(nrv.Data.Int == 0x80000000) nrv.Data.Int = 0;
|
||||
nrv.Type = C4V_Float;
|
||||
break;
|
||||
default:
|
||||
|
@ -236,6 +250,9 @@ public:
|
|||
nrv.SetInt(::Pow(getInt(), rhs.getInt()));
|
||||
return nrv;
|
||||
}
|
||||
inline bool isWeakNil() const {
|
||||
return Type == C4V_Nil || ((Type == C4V_Int || Type == C4V_Float || Type == C4V_Bool) && !*this);
|
||||
}
|
||||
|
||||
// getters
|
||||
C4V_Data GetData() const { return Data; }
|
||||
|
@ -251,18 +268,18 @@ public:
|
|||
{
|
||||
switch (vtToType)
|
||||
{
|
||||
case C4V_Nil: return Type == C4V_Nil || (Type == C4V_Int && !*this);
|
||||
case C4V_Nil: return isWeakNil();
|
||||
case C4V_Float: case C4V_Numeric:
|
||||
case C4V_Int: return Type == C4V_Int || Type == C4V_Float || Type == C4V_Nil || Type == C4V_Bool;
|
||||
case C4V_Bool: return true;
|
||||
case C4V_PropList: return Type == C4V_PropList || Type == C4V_Nil || (Type == C4V_Int && !*this);
|
||||
case C4V_String: return Type == C4V_String || Type == C4V_Nil || (Type == C4V_Int && !*this);
|
||||
case C4V_Array: return Type == C4V_Array || Type == C4V_Nil || (Type == C4V_Int && !*this);
|
||||
case C4V_Function: return Type == C4V_Function || Type == C4V_Nil || (Type == C4V_Int && !*this);
|
||||
case C4V_PropList: return Type == C4V_PropList || isWeakNil();
|
||||
case C4V_String: return Type == C4V_String || isWeakNil();
|
||||
case C4V_Array: return Type == C4V_Array || isWeakNil();
|
||||
case C4V_Function: return Type == C4V_Function || isWeakNil();
|
||||
case C4V_Any: return true;
|
||||
case C4V_Object: return (Type == C4V_PropList && FnCnvObject()) || Type == C4V_Nil || (Type == C4V_Int && !*this);
|
||||
case C4V_Def: return (Type == C4V_PropList && FnCnvDef()) || Type == C4V_Nil || (Type == C4V_Int && !*this);
|
||||
case C4V_Effect: return (Type == C4V_PropList && FnCnvEffect()) || Type == C4V_Nil || (Type == C4V_Int && !*this);
|
||||
case C4V_Object: return (Type == C4V_PropList && FnCnvObject()) || isWeakNil();
|
||||
case C4V_Def: return (Type == C4V_PropList && FnCnvDef()) || isWeakNil();
|
||||
case C4V_Effect: return (Type == C4V_PropList && FnCnvEffect()) || isWeakNil();
|
||||
default: assert(!"C4Value::CheckParConversion: impossible conversion target"); return false;
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +289,7 @@ public:
|
|||
{
|
||||
case C4V_Nil: return Type == C4V_Nil;
|
||||
case C4V_Float: case C4V_Numeric:
|
||||
case C4V_Int: return Type == C4V_Nil || Type == C4V_Int || Type == C4V_Bool;
|
||||
case C4V_Int: return Type == C4V_Nil || Type == C4V_Int || Type == C4V_Float || Type == C4V_Bool;
|
||||
case C4V_Bool: return true;
|
||||
case C4V_PropList: return Type == C4V_PropList;
|
||||
case C4V_String: return Type == C4V_String;
|
||||
|
@ -404,7 +421,7 @@ ALWAYS_INLINE void C4Value::DelDataRef(C4V_Data Data, C4V_Type Type, C4Value *pN
|
|||
ALWAYS_INLINE void C4Value::Set(C4V_Data nData, C4V_Type nType)
|
||||
{
|
||||
// Do not add this to the same linked list twice.
|
||||
if (Data == nData && Type >= C4V_PropList) return;
|
||||
if (Data == nData && Type >= C4V_PropList) return;
|
||||
|
||||
C4V_Data oData = Data;
|
||||
C4V_Type oType = Type;
|
||||
|
|
Loading…
Reference in New Issue