ReflectedInterface.h

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

@import "IObject.h"
@import "ReflectedType.h"
@import "ReflectedFunction.h"

namespace ceda
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedAttribute

$struct+ ReflectedAttribute <<os>>
{
    $ConstStringZ GetName() const { return name; }
    void Write(xostream& os) const;

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

    ConstStringZ name;
    const octet_t* byteCode;
    ReflectedType rtype;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedInterfaceMethod

$struct+ ReflectedInterfaceMethod <<os>>
{
    $bool IsConst() const { return isConst; }
    $ConstStringZ GetName() const { return name; }
    $ssize_t GetNumArgs() const { return numArgs; }
    $const ReflectedArg& GetArg(ssize_t i) const { return args[i]; }
    void Write(xostream& os) const;

    ConstStringZ name;
    ReflectedReturnType returnType;
    const ReflectedArg* args;
    ssize_t numArgs;
    const octet_t* metaData;
    bool isConst;                 // Was the method declared with the 'const' qualfifier?
};

inline const ReflectedFunction& AsReflectedFunction(const ReflectedInterfaceMethod& rim)
{
    // Assumes that the ReflectedInterfaceMethod begins with all the members defined in ReflectedFunction
    return reinterpret_cast<const ReflectedFunction&>(rim);
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedInterface

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

    $ConstStringZ GetName() const { return name; }

    $ssize_t GetNumBaseInterfaces() const { return m_numBaseInterfaces; }
    $ConstStringZ GetBaseInterfaceName(ssize_t i) const { return m_baseInterfaces[i]; }
    
    $ssize_t GetNumBaseMethods() const { return m_numBaseMethods; }
    $ssize_t GetNumMethods() const { return numMethods; }
    $const ReflectedInterfaceMethod& GetMethod(ssize_t i) const { return methods[i]; }
    
    $ssize_t GetNumAttributes() const { return m_numAttributes; }
    $const ReflectedAttribute& GetAttribute(ssize_t i) const { return m_attributes[i]; }
    
    void Write(xostream& os) const;
    //////////////// State //////////////////

    @if (!CEDA_ENABLE_STRING_TABLES)
    {
        const octet_t* byteCode;
    }
    ConstStringZ name;
    const octet_t* metaData;
    
    ConstStringZ const* m_baseInterfaces;      // fully qualified names of all the base interfaces
    ssize_t m_numBaseInterfaces;
    
    ssize_t m_numBaseMethods;               // Offset into FnTable due to base interfaces
    const ReflectedInterfaceMethod* methods;
    ssize_t numMethods;
    
    const ReflectedAttribute* m_attributes;
    ssize_t m_numAttributes;
    
    ConstStringZ const* stringTable;
};

@api bool InterfaceSubTypesIObject(const ReflectedInterface& ri);
@api void GetInterfaces(const ReflectedClass& rc, xvector<const ReflectedInterface*> v);
@api void GetStrictSubInterfaces(const ReflectedInterface& ri, xvector<const ReflectedInterface*> v);

template<typename T>
struct GetReflectedType_class<T, std::enable_if_t<!std::is_const<T>::value && !std::is_volatile<T>::value && IsReflectedInterface<T>::value>>
{
    static inline ReflectedType get()
    {
        ReflectedType r;
        r.tag = EReflectedTypeTag::Interface;
        r.Interface = &GetReflectedInterface<T>();
        return r;
    }
};
} // namespace ceda