Replace C4Value typecheck table with switch statements

This has the advantage that the compiler can simplify the check when the
target type is known at compile time.
Günther Brammer 2011-04-10 03:46:59 +02:00
parent 2a770e37da
commit 7eedece257
2 changed files with 24 additions and 94 deletions

View File

@ -68,83 +68,22 @@ bool C4Value::FnCnvObject() const
if (Data.PropList->GetObject()) return true;
return false;
}
// Type conversion table
#define CnvOK C4VCnvFn::CnvOK, false // allow conversion by same value
#define CnvOK0 C4VCnvFn::CnvOK0, true
#define CnvError C4VCnvFn::CnvError, true
#define CnvObject C4VCnvFn::CnvObject, false
C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
bool C4Value::WarnAboutConversion(C4V_Type Type, C4V_Type vtToType)
{
{ // C4V_Any - is always 0, convertible to everything
{ CnvOK }, // any same
{ CnvOK }, // int
{ CnvOK }, // Bool
{ CnvOK }, // PropList
{ CnvOK }, // C4Object
{ CnvOK }, // String
{ CnvOK }, // Array
},
{ // C4V_Int
{ CnvOK }, // any
{ CnvOK }, // int same
{ CnvOK }, // Bool
{ CnvOK0 }, // PropList only if 0
{ CnvOK0 }, // C4Object only if 0
{ CnvOK0 }, // String only if 0
{ CnvOK0 }, // Array only if 0
},
{ // C4V_Bool
{ CnvOK }, // any
{ CnvOK }, // int might be used
{ CnvOK }, // Bool same
{ CnvError }, // PropList NEVER!
{ CnvError }, // C4Object NEVER!
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
},
{ // C4V_PropList
{ CnvOK }, // any
{ CnvError }, // int NEVER!
{ CnvOK }, // Bool
{ CnvOK }, // PropList same
{ CnvObject }, // C4Object
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
},
{ // C4V_Object
{ CnvOK }, // any
{ CnvError }, // int NEVER!
{ CnvOK }, // Bool
{ CnvOK }, // PropList
{ CnvOK }, // C4Object same
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
},
{ // C4V_String
{ CnvOK }, // any
{ CnvError }, // int NEVER!
{ CnvOK }, // Bool
{ CnvError }, // PropList NEVER!
{ CnvError }, // C4Object NEVER!
{ CnvOK }, // String same
{ CnvError }, // Array NEVER!
},
{ // C4V_Array
{ CnvOK }, // any
{ CnvError }, // int NEVER!
{ CnvOK }, // Bool
{ CnvError }, // PropList NEVER!
{ CnvError }, // C4Object NEVER!
{ CnvError }, // String NEVER!
{ CnvOK }, // Array same
switch (vtToType)
{
case C4V_Any: return false;
case C4V_Int: return Type != C4V_Int && Type != C4V_Any && Type != C4V_Bool;
case C4V_Bool: return false;
case C4V_PropList: return Type != C4V_PropList && Type != C4V_C4Object && Type != C4V_Any;
case C4V_C4Object: return Type != C4V_C4Object && Type != C4V_PropList && Type != C4V_Any;
case C4V_String: return Type != C4V_String && Type != C4V_Any;
case C4V_Array: return Type != C4V_Array && Type != C4V_Any;
default: assert(!"C4Value::ConvertTo: impossible conversion target"); return false;
}
};
#undef CnvOK
#undef CnvOK0
#undef CnvError
#undef CnvObject
}
// Humanreadable debug output
StdStrBuf C4Value::GetDataString() const

View File

@ -60,13 +60,6 @@ union C4V_Data
C4V_Data &operator = (void *p) { Obj = reinterpret_cast<C4Object *>(p); return *this; }
};
// converter function, used in converter table
struct C4VCnvFn
{
enum { CnvOK, CnvOK0, CnvError, CnvObject } Function;
bool Warn;
};
class C4Value
{
public:
@ -153,22 +146,21 @@ public:
StdStrBuf GetDataString() const;
inline bool ConvertTo(C4V_Type vtToType) const // convert to dest type
ALWAYS_INLINE bool ConvertTo(C4V_Type vtToType) const // convert to dest type
{
switch (C4ScriptCnvMap[Type][vtToType].Function)
switch (vtToType)
{
case C4VCnvFn::CnvOK: return true;
case C4VCnvFn::CnvOK0: return !*this;
case C4VCnvFn::CnvError: return false;
case C4VCnvFn::CnvObject: return FnCnvObject();
case C4V_Any: return true;
case C4V_Int: return Type == C4V_Int || Type == C4V_Any || Type == C4V_Bool;
case C4V_Bool: return true;
case C4V_PropList: return Type == C4V_PropList || Type == C4V_C4Object || Type == C4V_Any || (Type == C4V_Int && !*this);
case C4V_C4Object: return Type == C4V_C4Object || (Type == C4V_PropList && FnCnvObject()) || Type == C4V_Any || (Type == C4V_Int && !*this);
case C4V_String: return Type == C4V_String || Type == C4V_Any || (Type == C4V_Int && !*this);
case C4V_Array: return Type == C4V_Array || Type == C4V_Any || (Type == C4V_Int && !*this);
default: assert(!"C4Value::ConvertTo: impossible conversion target"); return false;
}
assert(!"C4Value::ConvertTo: Invalid conversion function specified");
return false;
}
inline static bool WarnAboutConversion(C4V_Type vtFromType, C4V_Type vtToType)
{
return C4ScriptCnvMap[vtFromType][vtToType].Warn;
}
static bool WarnAboutConversion(C4V_Type Type, C4V_Type vtToType);
// Compilation
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
@ -194,7 +186,6 @@ protected:
void AddDataRef();
void DelDataRef(C4V_Data Data, C4V_Type Type, C4Value *pNextRef);
static C4VCnvFn C4ScriptCnvMap[C4V_Last+1][C4V_Last+1];
bool FnCnvObject() const;
void LogDeletedObjectWarning(C4PropList *);