Reflection.h

// Reflection.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2022

@import "IObject.h"
@import "ReflectedType.h"
@import "ReflectedArray.h"
@import "ReflectedClass.h"
@import "ReflectedDynArray.h"
@import "ReflectedEnum.h"
@import "ReflectedField.h"
@import "ReflectedFunction.h"
@import "ReflectedInterface.h"
@import "ReflectedLeafType.h"
@import "ReflectedMap.h"
@import "ReflectedQualifier.h"
@import "ReflectedSet.h"
@import "ReflectedVector.h"
@import "ReflectedVariant.h"

//@import "PseudoPref.h"

namespace ceda
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// Reflected global variables

$struct+ ReflectedGlobalVariable <<os>>
{
    bool operator<(const ReflectedGlobalVariable& rhs) const { return this < &rhs; }
    bool operator==(const ReflectedGlobalVariable& rhs) const { return this == &rhs; }

    $ConstStringZ GetName() const { return name; }
    $void* GetAddress() const { return address; }
    void Write(xostream& os) const;

    //////////////// State //////////////////

    ConstStringZ name;
    void* address;
    const octet_t* byteCode;
    ConstStringZ const* stringTable;
    ReflectedType rtype;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedTypedef

$struct+ ReflectedTypedef <<os>>
{
    bool operator<(const ReflectedTypedef& rhs) const { return this < &rhs; }
    bool operator==(const ReflectedTypedef& rhs) const { return this == &rhs; }

    $ConstStringZ GetName() const { return name; }
    void Write(xostream& os) const;

    //////////////// State //////////////////

    ConstStringZ name;
    const octet_t* byteCode;       // Specifies type and metadata
    ConstStringZ const* stringTable;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedUnknown

struct ReflectedUnknown
{
    ConstStringZ name;
};

template <typename T> using has_GetExternTypeName_t = decltype(GetExternTypeName(std::declval<T*>()));
template <typename T> using has_GetExternTypeName = is_detected<has_GetExternTypeName_t, T>;

template<typename T>
struct GetReflectedType_class<T, std::enable_if_t<!std::is_const<T>::value && !std::is_volatile<T>::value && has_GetExternTypeName<T>::value>>
{
    static inline ReflectedType get()
    {
        static ReflectedUnknown u =
        {
            GetExternTypeName((T*) nullptr)
        };

        ReflectedType r;
        r.tag = EReflectedTypeTag::Unknown;
        r.Unknown = &u;
        return r;
    }
};

///////////////////////////////////////////////////////////////////////////////////////////////////

// todo: also PseudoPref
@for (T in [bool, char, signed char, unsigned char, char16_t, char32_t, wchar_t,
            short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long,
            float, double, long double, string8, string16, void*, AnyInterface])
{
    extern template cxObject_API_T const TypeOps& MakeTypeOps<T>();
    extern template struct cxObject_API_T GetReflectedType_class<T>;

}

} // namespace ceda