Fix C4Value

-Various conversion tables
-Store -0.0 as 0.0
-Operator ==

Fix float parsing

Change operator type check
floating-point
Julius Michaelis 2012-03-24 13:00:25 +01:00
parent 962b4f0070
commit 7e857994d0
5 changed files with 67 additions and 51 deletions

View File

@ -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)); }

View File

@ -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();

View File

@ -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;}// "->~"

View File

@ -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:

View File

@ -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;