mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-04-01 01:47:13 +02:00
Implement a dynamic comparison system.
This commit is contained in:
parent
5557f666ef
commit
d31c77341c
@ -1550,6 +1550,521 @@ void ImportModuleAPI(PluginFuncs * vcapi, CCStr mod);
|
||||
|
||||
#endif // SQMOD_PLUGIN_API
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Default class for checking if the argument on the stack matches the requested type.
|
||||
*/
|
||||
template < typename U > struct SqCmpArg
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INSTANCE);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
Var< U * > var(vm, 2);
|
||||
// Is this instance valid?
|
||||
if (!var.value)
|
||||
{
|
||||
STHROWF("No such instance");
|
||||
}
|
||||
// Attempt to perform the comparison
|
||||
return val.Cmp(*var.value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < typename U > struct SqCmpArg< U * >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INSTANCE);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
Var< U * > var(vm, 2);
|
||||
// Is this instance valid?
|
||||
if (!var.value)
|
||||
{
|
||||
STHROWF("No such instance");
|
||||
}
|
||||
// Attempt to perform the comparison
|
||||
return val.Cmp(var.value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < typename U > struct SqCmpArg< const U * >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INSTANCE);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
Var< const U * > var(vm, 2);
|
||||
// Is this instance valid?
|
||||
if (!var.value)
|
||||
{
|
||||
STHROWF("No such instance");
|
||||
}
|
||||
// Attempt to perform the comparison
|
||||
return val.Cmp(*var.value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< std::nullptr_t >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_NULL);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM /*vm*/)
|
||||
{
|
||||
return val.Cmp(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< char >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< char >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< signed char >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< signed char >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< unsigned char >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< unsigned char >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< signed short >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< signed short >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< unsigned short >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< unsigned short >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< signed int >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< signed int >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< unsigned int >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< unsigned int >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< signed long >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< signed long >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< unsigned long >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< unsigned long >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< signed long long >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< signed long long >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< unsigned long long >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_INTEGER);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< unsigned long long >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< float >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_FLOAT);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< float >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< double >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_FLOAT);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< double >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< bool >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_BOOL);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< bool >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< SQChar * >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_STRING);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< SQChar * >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< const SQChar * >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_STRING);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< const SQChar * >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< String >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_STRING);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< String >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< Table >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_TABLE);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< Table >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< Array >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
return (sq_gettype(vm, 2) == OT_ARRAY);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< Array >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< Function >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM vm)
|
||||
{
|
||||
const SQObjectType type = sq_gettype(vm, 2);
|
||||
return (type == OT_CLOSURE || type == OT_NATIVECLOSURE);
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< Function >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Specialization of the argument checking structure.
|
||||
*/
|
||||
template < > struct SqCmpArg< Object >
|
||||
{
|
||||
static inline bool CanPop(HSQUIRRELVM /*vm*/)
|
||||
{
|
||||
return true; // Objects can use any type.
|
||||
}
|
||||
|
||||
template < typename T > static inline Int32 Compare(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
return val.Cmp(Var< Object >(vm, 2).value);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Common function used to compare one type of instance with a couple of other types.
|
||||
*/
|
||||
template < typename... Ts > struct SqCmpImpl;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Zeroth case of the comparison. No known comparison at this point.
|
||||
*/
|
||||
template < > struct SqCmpImpl< >
|
||||
{
|
||||
template < typename T > static Int32 Fn(const T & /*val*/, HSQUIRRELVM vm)
|
||||
{
|
||||
const String tn1(SqTypeName(vm, 1));
|
||||
const String tn2(SqTypeName(vm, 2));
|
||||
return sq_throwerror(vm, ToStrF("Unknown comparison between (%s) and (%s)",
|
||||
tn1.c_str(), tn2.c_str()));
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Argument pack type pealing. Attempt comparison with a specified type.
|
||||
*/
|
||||
template < typename U, typename... Ts > struct SqCmpImpl< U, Ts... >
|
||||
{
|
||||
template < typename T > static Int32 Fn(const T & val, HSQUIRRELVM vm)
|
||||
{
|
||||
typedef typename std::decay< U >::type ArgType;
|
||||
// Can the stack value be used with the current type?
|
||||
if (SqCmpArg< ArgType >::CanPop(vm))
|
||||
{
|
||||
// If not an instance then don't use a try catch block
|
||||
if (sq_gettype(vm, 2) != OT_INSTANCE)
|
||||
{
|
||||
return SqCmpArg< ArgType >::Compare(val, vm);
|
||||
}
|
||||
// Instances require a try/catch block since we can't differentiate types
|
||||
try
|
||||
{
|
||||
return SqCmpArg< ArgType >::Compare(val, vm);
|
||||
}
|
||||
catch (const Sqrat::Exception & e)
|
||||
{
|
||||
// Probably the wrong type
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Something bad happened. At this point, we just don't want to let
|
||||
// exceptions propagate to the virtual machine and we must end here.
|
||||
// Either way, reaching this point is bad and we just shuved it under
|
||||
// the rug. This is bad practice but circumstances forced me.
|
||||
// Don't do this at home kids!
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// On to the next type
|
||||
return SqCmpImpl< Ts... >::Fn(val, vm);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Squirrel function that forwards the call to the actual implementation.
|
||||
*/
|
||||
template < typename T, typename U, typename... Ts > SQInteger SqCmpFwd(HSQUIRRELVM vm)
|
||||
{
|
||||
// Make sure that there are enough parameters on the stack
|
||||
if (sq_gettop(vm) < 2)
|
||||
{
|
||||
return sq_throwerror(vm, "Insufficient parameters to perform comparison");
|
||||
}
|
||||
// Attempt to grab a pointer to the base instance
|
||||
Var< T * > var(vm, 1);
|
||||
// Is this instance valid?
|
||||
if (!var.value)
|
||||
{
|
||||
return sq_throwerror(vm, "No such instance to compare");
|
||||
}
|
||||
// Attempt to perform the comparison
|
||||
try
|
||||
{
|
||||
sq_pushinteger(vm, SqCmpImpl< U, Ts... >::Fn(*var.value, vm));
|
||||
}
|
||||
catch (const Sqrat::Exception & e)
|
||||
{
|
||||
return sq_throwerror(vm, e.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return sq_throwerror(vm, "Unknown error occurred during comparison");
|
||||
}
|
||||
// At this point we should have an integer on the stack
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _BASE_UTILITY_HPP_
|
||||
|
Loading…
x
Reference in New Issue
Block a user