ReflectedInstance.h
// ReflectedInstance.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2020
@import "cxObject.h"
@import "ReflectionByteCode.h"
@import "PrintReflectedType.h"
// We use the term 'instance' to mean either a variable or value.
// 'const' is not used to protect a value from being modified.
namespace ceda
{
@def CEDA_COERCE_TYPES = [bool, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, char8, char16, string8, string16]
///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedInstance
struct @api ReflectedInstance
{
ReflectedInstance() : addr(nullptr) {}
// Since there are implicit conversions from const ReflectedClass& to ReflectionByteCode,
// this ctor also allows for setting up a ReflectedInstance for a class instance.
// Similarly for various other specialised kinds of reflected instances.
ReflectedInstance(ReflectionByteCode rbc, void* addr) : rbc(rbc), addr(addr) {}
explicit ReflectedInstance(bool* v) : rbc(ReflectionByteCode::MakeLeaf(FT_BOOL)), addr(v) {}
explicit ReflectedInstance(int8* v) : rbc(ReflectionByteCode::MakeLeaf(FT_INT8)), addr(v) {}
explicit ReflectedInstance(int16* v) : rbc(ReflectionByteCode::MakeLeaf(FT_INT16)), addr(v) {}
explicit ReflectedInstance(int32* v) : rbc(ReflectionByteCode::MakeLeaf(FT_INT32)), addr(v) {}
explicit ReflectedInstance(int64* v) : rbc(ReflectionByteCode::MakeLeaf(FT_INT64)), addr(v) {}
explicit ReflectedInstance(uint8* v) : rbc(ReflectionByteCode::MakeLeaf(FT_UINT8)), addr(v) {}
explicit ReflectedInstance(uint16* v) : rbc(ReflectionByteCode::MakeLeaf(FT_UINT16)), addr(v) {}
explicit ReflectedInstance(uint32* v) : rbc(ReflectionByteCode::MakeLeaf(FT_UINT32)), addr(v) {}
explicit ReflectedInstance(uint64* v) : rbc(ReflectionByteCode::MakeLeaf(FT_UINT64)), addr(v) {}
explicit ReflectedInstance(float32* v) : rbc(ReflectionByteCode::MakeLeaf(FT_FLOAT32)), addr(v) {}
explicit ReflectedInstance(float64* v) : rbc(ReflectionByteCode::MakeLeaf(FT_FLOAT64)), addr(v) {}
explicit ReflectedInstance(char8* v) : rbc(ReflectionByteCode::MakeLeaf(FT_CHAR8)), addr(v) {}
explicit ReflectedInstance(char16* v) : rbc(ReflectionByteCode::MakeLeaf(FT_CHAR16)), addr(v) {}
explicit ReflectedInstance(string8* v) : rbc(ReflectionByteCode::MakeLeaf(FT_STRING8)), addr(v) {}
explicit ReflectedInstance(string16* v) : rbc(ReflectionByteCode::MakeLeaf(FT_STRING16)), addr(v) {}
static ReflectedInstance FromConstString8Z(ConstString8Z* v) { return ReflectedInstance( ReflectionByteCode::ForConstString8Z(), v ); }
static ReflectedInstance FromConstString16Z(ConstString16Z* v) { return ReflectedInstance( ReflectionByteCode::ForConstString16Z(), v ); }
// throw UnsupportedException if not supported
void Destruct();
void Construct();
void CopyConstruct(const void* rhs); // Copy construct from variable of the same type
void CopyAssign(const void* rhs); // Copy assign from variable of the same type
// return false if not supported
bool TryCopyAssign(ReflectedInstance rhs, bool allowExplicitConversions);
bool TryCopyConstruct(ReflectedInstance rhs, bool allowExplicitConversions);
@for(T in CEDA_COERCE_TYPES)
{
bool TryCoerce(T& v, bool allowExplicitConversions=false);
void Coerce(T& v, bool allowExplicitConversions=false); // Throws UnsupportedException if cannot coerce
}
ReflectionByteCode rbc;
void* addr;
};
@api void PrintReflectedInstance(xostream& os, ReflectedInstance v, bool allowMultiLine = true, const PrintTypeSettings& pts = PrintTypeSettings());
///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedClassInstance
struct ReflectedClassInstance
{
ReflectedClassInstance() : rc(nullptr), addr(nullptr) {}
ReflectedClassInstance(const ReflectedClass* rc, void* addr) : rc(rc), addr(addr) {}
ReflectedClassInstance(ReflectedInstance r)
{
cxAssert(*r.rbc == FT_CLASS);
rc = r.rbc.GetReflectedClass();
addr = r.addr;
}
const ReflectedClass* rc;
void* addr;
};
/*
// These throw UnsupportedException if the operation is not supported
inline bool operator==(ReflectedClassInstance a, ReflectedClassInstance b) { return CompareEqReflectedClassVariables(*a.rc, a.addr, *b.rc, b.addr); }
inline bool operator<(ReflectedClassInstance a, ReflectedClassInstance b) { return CompareLtReflectedClassVariables(*a.rc, a.addr, *b.rc, b.addr); }
inline bool operator!=(ReflectedClassInstance a, ReflectedClassInstance b) { return !(a==b); }
inline bool operator>(ReflectedClassInstance a, ReflectedClassInstance b) { return b < a; }
inline bool operator<=(ReflectedClassInstance a, ReflectedClassInstance b) { return !(b < a); }
inline bool operator>=(ReflectedClassInstance a, ReflectedClassInstance b) { return !(a < b); }
*/
///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedVariantInstance
struct ReflectedVariantInstance
{
ReflectedVariantInstance() : rv(nullptr), addr(nullptr) {}
ReflectedVariantInstance(const ReflectedVariant* rv, void* addr) : rv(rv), addr(addr) {}
ReflectedVariantInstance(ReflectedInstance r)
{
cxAssert(*r.rbc == FT_VARIANT);
rv = r.rbc.GetReflectedVariant();
addr = r.addr;
}
const ReflectedVariant* rv;
void* addr;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// Comparisons
@for(T in CEDA_COERCE_TYPES)
{
inline bool operator==(ReflectedInstance a, const T& b)
{
T v;
a.Coerce(v);
return v == b;
}
inline bool operator<(ReflectedInstance a, const T& b)
{
T v;
a.Coerce(v);
return v < b;
}
inline bool operator<(const T& b, ReflectedInstance a)
{
T v;
a.Coerce(v);
return b < v;
}
inline bool operator==(const T& a, ReflectedInstance b) { return b == a; }
inline bool operator!=(ReflectedInstance a, const T& b) { return !(a==b); }
inline bool operator!=(const T& a, ReflectedInstance b) { return !(a==b); }
inline bool operator>(ReflectedInstance a, const T& b) { return b < a; }
inline bool operator>(const T& a, ReflectedInstance b) { return b < a; }
inline bool operator<=(ReflectedInstance a, const T& b) { return !(b < a); }
inline bool operator<=(const T& a, ReflectedInstance b) { return !(b < a); }
inline bool operator>=(ReflectedInstance a, const T& b) { return b <= a; }
inline bool operator>=(const T& a, ReflectedInstance b) { return b <= a; }
}
/*
Given T1<T2 and T1==T2, generate
T1 != T2
T2 > T1
T2 <= T1
T1 >= T2
*/
// These throw UnsupportedException if the operation is not supported
@api bool operator==(ReflectedInstance a, ReflectedInstance b);
@api bool operator<(ReflectedInstance a, ReflectedInstance b);
@api bool operator==(ReflectedClassInstance a, ReflectedClassInstance b);
@api bool operator<(ReflectedClassInstance a, ReflectedClassInstance b);
@api bool operator==(ReflectedVariantInstance a, ReflectedVariantInstance b);
@api bool operator<(ReflectedVariantInstance a, ReflectedVariantInstance b);
@api bool operator==(ReflectedInstance a, ReflectedClassInstance b);
inline bool operator==(ReflectedClassInstance a, ReflectedInstance b) { return b == a; }
@api bool operator<(ReflectedInstance a, ReflectedClassInstance b);
@api bool operator<(ReflectedClassInstance a, ReflectedInstance b);
@api bool operator==(ReflectedInstance a, ReflectedVariantInstance b);
inline bool operator==(ReflectedVariantInstance a, ReflectedInstance b) { return b == a; }
@api bool operator<(ReflectedInstance a, ReflectedVariantInstance b);
@api bool operator<(ReflectedVariantInstance a, ReflectedInstance b);
@api bool operator==(ReflectedClassInstance a, ReflectedVariantInstance b);
inline bool operator==(ReflectedVariantInstance a, ReflectedClassInstance b) { return b == a; }
@api bool operator<(ReflectedClassInstance a, ReflectedVariantInstance b);
@api bool operator<(ReflectedVariantInstance a, ReflectedClassInstance b);
/*
inline bool operator!=(ReflectedInstance a, ReflectedInstance b) { return !(a==b); }
inline bool operator>(ReflectedInstance a, ReflectedInstance b) { return b < a; }
inline bool operator<=(ReflectedInstance a, ReflectedInstance b) { return !(b < a); }
inline bool operator>=(ReflectedInstance a, ReflectedInstance b) { return !(a < b); }
*/
@def CEDA_GENERATE_REMAINING_FOUR_COMPARISON_OPERATIONS(L) =
{
@for(T1 in L)
{
@for(T2 in L)
{
inline bool operator!=(const T1& a, const T2& b) { return !(a==b); }
inline bool operator>(const T1& a, const T2& b) { return b < a; }
inline bool operator<=(const T1& a, const T2& b) { return !(b < a); }
inline bool operator>=(const T1& a, const T2& b) { return !(a < b); }
}
}
}
CEDA_GENERATE_REMAINING_FOUR_COMPARISON_OPERATIONS([ReflectedInstance, ReflectedClassInstance, ReflectedVariantInstance])
} // namespace ceda