ReflectionByteCodeTypes.h
// ReflectionByteCodeTypes.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2006
@import "IObject.h"
/*
A bytecode is used to represent a type together with its meta-data. It is implicitly assumed there
is an associated string table holding the strings, indexed with a 16 bit integer.
The following (binary) grammar describes the byte code, where
int8 is a single byte
int16 is a 16 bit integer formed by 2 consecutive bytes in the byte code assuming
little endian
int32 is a 32 bit integer formed by 4 consecutive bytes in the byte code assuming
little endian
float64 is a 64 bit double precision floating point formed by 8 consecutive bytes in
the byte code assuming little endian.
meta-data:
MDT_BOOL int8
MDT_INT32 int32
MDT_FLOAT64 float64
MDT_STRING int32
MDT_FUNCTOR_i int32 [meta-data]*i
MDT_LIST_i [meta-data]*i
MDT_BEGIN_FUNCTOR int32 [meta-data]* MDT_END_FUNCTOR
MDT_BEGIN_LIST [meta-data]* MDT_END_LIST
basic-type:
FT_VOID
FT_BOOL
FT_INT8
FT_INT16
FT_INT32
FT_INT64
FT_INT128
FT_UINT8
FT_UINT16
FT_UINT32
FT_UINT64
FT_UINT128
FT_FLOAT32
FT_FLOAT64
FT_CHAR8
FT_CHAR16
FT_STRING8
FT_STRING16
ext-type-key:
FT_CLASS
FT_INTERFACE
FT_TYPEDEF
FT_ENUM
FT_FUNCTOR
FT_VARIANT
FT_FUNCTION_PTR
FT_NOT_REFLECTED
unary-type-qualifier:
FT_VOLATILE volatile T
FT_CONST const T
FT_ASSIGNABLE
FT_MOVABLE
FT_OFFSETTABLE
FT_POINTER T*
FT_REFERENCE T&
FT_INTERFACE_POINTER ptr<T> T = interface
FT_OPEN_VARIANT openvariant<T> T = interface
FT_PREF pref<T> T = interface
FT_CREF cref<T> T = concrete class
FT_VECTOR xvector<T>
FT_DEQUE xdeque<T>
FT_LIST xlist<T>
FT_SET xset<T>
FT_BAG xbag<T>
FT_DYNARRAY T[]
type:
basic-type
unary-type-qualifier type
ext-type-key int16
FT_ARRAY size type
FT_MAP type type
[MDT_FLAGS int32] [meta-data]* type
Note that ignoring metadata and qualifiers like FT_CONST, just after FT_CREF you always get
FT_CLASS then a 16 bit index into the string table for the name of the class. Just after FT_PREF
or FT_INTERFACE_POINTER you always get FT_INTERFACE then a 16 bit index into the string table
for the name of the interface.
FT_CREF FT_CLASS int16
FT_PREF FT_INTERFACE int16
FT_INTERFACE_POINTER FT_INTERFACE int16
Support for parameterised types
-------------------------------
We allow for parametersied types. Parameters are identified by a zero based index
and here we designate them by T0,T1,T2,...
An example of a type parameterised in T0,T1 is
map<T0,const T1*>
It is easy to represent parameterised types in byte code, by using special byte codes for
T0,T1,...
The instantiation of the parameterised type requires a context, which is basically a mapping
from the Ti to actual types.
We allow for registration of parameterised interfaces. ReflectedInterface has a field
for the number of template parameters. Zero indicates it is not parameterised.
*/
namespace ceda
{
$enum+ ETypeByteCode
{
// Simple leaf types
FT_VOID, // 0x00
FT_BOOL, // 0x01
FT_INT8, // 0x02
FT_INT16, // 0x03
FT_INT32, // 0x04
FT_INT64, // 0x05
FT_INT128, // 0x06
FT_UINT8, // 0x07
FT_UINT16, // 0x08
FT_UINT32, // 0x09
FT_UINT64, // 0x0a
FT_UINT128, // 0x0b
FT_FLOAT32, // 0x0c
FT_FLOAT64, // 0x0d
FT_CHAR8, // 0x0e
FT_CHAR16, // 0x0f
FT_STRING8, // 0x10
FT_STRING16, // 0x11
// Named leaf types
FT_CLASS = 0x20, // 0x20
FT_INTERFACE, // 0x21
FT_TYPEDEF, // 0x22
FT_ENUM, // 0x23
FT_FUNCTOR, // 0x24
FT_VARIANT, // 0x25
FT_FUNCTION_PTR, // 0x26
FT_NOT_REFLECTED, // 0x27
// Unary qualified types
FT_VOLATILE=0x30, // 0x30 volatile T
FT_CONST, // 0x31 const T
FT_ASSIGNABLE, // 0x32 causes its argument to have assignment semantics
FT_MOVABLE, // 0x33 causes it pref argument to support move semantics
FT_OFFSETTABLE, // 0x34 causes its argument to have offset semantics
FT_POINTER, // 0x35 T*
FT_REFERENCE, // 0x36 T&
FT_INTERFACE_POINTER=0x40, // 0x40 ptr<T>
FT_OPEN_VARIANT, // 0x41 openvariant<T>
FT_PREF, // 0x42 pref<T>
FT_CREF, // 0x43 cref<T>
FT_VECTOR, // 0x44 xvector<T>
FT_DEQUE, // 0x45 xdeque<T>
FT_LIST, // 0x46 xlist<T>
FT_SET, // 0x47 xset<T>
FT_BAG, // 0x48 xbag<T>
FT_DYNARRAY, // 0x49 T[]
FT_ARRAY=0x50, // 0x50 T[size]
FT_MAP, // 0x51 xmap<K,V>
// We support 0..63 template parameters
FT_PARAM_0 = 0x60,
FT_PARAM_1,
FT_PARAM_2,
FT_PARAM_3,
FT_PARAM_4,
FT_PARAM_5,
//////////////////////// Meta data ////////////////////////
MDT_FLAGS = 0xA0, // 0xA0
MDT_BOOL, // 0xA1
MDT_INT32, // 0xA2
MDT_FLOAT64, // 0xA3
MDT_STRING, // 0xA4
MDT_BEGIN_FUNCTOR, // 0xA5
MDT_END_FUNCTOR, // 0xA6
MDT_BEGIN_LIST, // 0xA7
MDT_END_LIST, // 0xA8
// We support functors with arity 0 to 31
MDT_FUNCTOR_0 = 0xC0,
MDT_FUNCTOR_1,
MDT_FUNCTOR_2,
MDT_FUNCTOR_3,
MDT_FUNCTOR_4,
MDT_FUNCTOR_5,
// We supports lists with 0-31 elements
MDT_LIST_0 = 0xE0,
MDT_LIST_1,
MDT_LIST_2,
MDT_LIST_3,
MDT_LIST_4,
MDT_LIST_5,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// Simple fixed size assignable types
/*
inline bool bcIsSimpleFixedSizeAssignableType(octet_t type)
{
return FT_BOOL <= type && type <= FT_CHAR16 || type == FT_ENUM;
}
*/
///////////////////////////////////////////////////////////////////////////////////////////////////
// Simple leaf types
inline bool bcIsSignedIntegralType(octet_t type)
{
return FT_INT8 <= type && type <= FT_INT128;
}
inline bool bcIsUnsignedIntegralType(octet_t type)
{
return FT_UINT8 <= type && type <= FT_UINT128;
}
inline bool bcIsIntegralType(octet_t type)
{
return FT_INT8 <= type && type <= FT_UINT128;
}
inline bool bcIsFloatType(octet_t type)
{
return FT_FLOAT32 <= type && type <= FT_FLOAT64;
}
inline bool bcIsCharType(octet_t type)
{
return FT_CHAR8 <= type && type <= FT_CHAR16;
}
inline bool bcIsStringType(octet_t type)
{
return FT_STRING8 <= type && type <= FT_STRING16;
}
const ETypeByteCode bcSimpleLeafType_first = FT_VOID;
const ETypeByteCode bcSimpleLeafType_last = FT_STRING16;
inline bool bcIsSimpleLeafType(octet_t type)
{
return bcSimpleLeafType_first <= type && type <= bcSimpleLeafType_last;
}
inline ConstStringZ bcUnqualifiedSimpleLeafTypeName(octet_t type)
{
cxAssert(bcIsSimpleLeafType(type));
static ConstStringZ names[] =
{
"void",
"bool",
"int8",
"int16",
"int32",
"int64",
"int128",
"uint8",
"uint16",
"uint32",
"uint64",
"uint128",
"float32",
"float64",
"char8",
"char16",
"string8",
"string16",
};
return names[type-bcSimpleLeafType_first];
}
inline ConstStringZ bcQualifiedSimpleLeafTypeName(octet_t type)
{
cxAssert(bcIsSimpleLeafType(type));
static ConstStringZ names[] =
{
"void",
"bool",
"ceda::int8",
"ceda::int16",
"ceda::int32",
"ceda::int64",
"ceda::int128",
"ceda::uint8",
"ceda::uint16",
"ceda::uint32",
"ceda::uint64",
"ceda::uint128",
"ceda::float32",
"ceda::float64",
"ceda::char8",
"ceda::char16",
"ceda::string8",
"ceda::string16",
};
return names[type-bcSimpleLeafType_first];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Named leaf types
const ETypeByteCode bcNamedLeafType_first = FT_CLASS;
const ETypeByteCode bcNamedLeafType_last = FT_NOT_REFLECTED;
inline bool bcIsNamedLeafType(octet_t type)
{
return bcNamedLeafType_first <= type && type <= bcNamedLeafType_last;
}
inline ConstStringZ bcNamedLeafTypeName(octet_t type)
{
cxAssert(bcIsNamedLeafType(type));
static ConstStringZ names[] =
{
"class",
"interface",
"typedef",
"enum",
"functor",
"variant",
"function",
"?"
};
return names[type-bcNamedLeafType_first];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// leaf types
const ETypeByteCode bcLeafType_first = FT_VOID;
const ETypeByteCode bcLeafType_last = FT_NOT_REFLECTED;
inline bool bcIsLeafType(octet_t type)
{
return bcLeafType_first <= type && type <= bcLeafType_last;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Unary types that don't really change the underlying data type
inline bool bcIsAnnotationalUnaryType(octet_t type)
{
return type == FT_VOLATILE ||
type == FT_CONST ||
type == FT_ASSIGNABLE ||
type == FT_MOVABLE ||
type == FT_OFFSETTABLE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Unary template types
const ETypeByteCode bcUnaryTemplateType_first = FT_INTERFACE_POINTER;
const ETypeByteCode bcUnaryTemplateType_last = FT_DYNARRAY;
inline bool bcIsUnaryTemplateType(octet_t type)
{
return bcUnaryTemplateType_first <= type && type <= bcUnaryTemplateType_last;
}
inline ConstStringZ bcUnqualifiedUnaryTemplateName(octet_t type)
{
cxAssert(bcIsUnaryTemplateType(type));
static ConstStringZ names[] =
{
"ptr",
"openvariant",
"pref",
"cref",
"xvector",
"xdeque",
"xlist",
"xset",
"xbag",
"DynArray",
};
return names[type-bcUnaryTemplateType_first];
}
inline ConstStringZ bcQualifiedUnaryTemplateName(octet_t type)
{
cxAssert(bcIsUnaryTemplateType(type));
static ConstStringZ names[] =
{
"ceda::ptr",
"ceda::openvariant",
"ceda::pref",
"ceda::cref",
"ceda::xvector",
"ceda::xdeque",
"ceda::xlist",
"ceda::xset",
"ceda::xbag",
"ceda::DynArray",
};
return names[type-bcUnaryTemplateType_first];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Unary Qualifier Types
const ETypeByteCode bcUnaryQualifierType_first = FT_VOLATILE;
const ETypeByteCode bcUnaryQualifierType_last = FT_DYNARRAY;
inline bool bcIsUnaryQualifierType(octet_t type)
{
return bcUnaryQualifierType_first <= type && type <= bcUnaryQualifierType_last;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// POD Types
// Test whether the given underlying type is a POD, where it is assumed that an FT_CLASS is not
// a POD
inline bool bcIsPOD(octet_t type)
{
// What about arrays? What about functors?
return (FT_BOOL <= type && type <= FT_CHAR16)
|| type == FT_ENUM
|| type == FT_POINTER
|| type == FT_FUNCTION_PTR
|| type == FT_REFERENCE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Type sizes
const ssize_t SIZE_OF_FUNCTOR = 2*sizeof(void*);
const ssize_t SIZE_OF_INTERFACE_PTR = 2*sizeof(void*);
const ssize_t SIZE_OF_XVECTOR = sizeof(void*)+2*sizeof(ssize_t);
const ssize_t SIZE_OF_VECTOR_MODEL = SIZE_OF_XVECTOR*2;
const ssize_t SIZE_OF_OID = 8;
const ssize_t SIZE_OF_PREF = SIZE_OF_OID + SIZE_OF_INTERFACE_PTR;
const ssize_t SIZE_OF_XMAP = SIZE_OF_PREF;
const ssize_t SIZE_OF_XSET = SIZE_OF_PREF;
inline ssize_t bcTypeSize(octet_t type)
{
cxAssert(0 <= type && type <= FT_MAP);
static const ssize_t sizes[] =
{
-1, // 0x00 void
1, // 0x01 bool
1, // 0x02 int8
2, // 0x03 int16
4, // 0x04 int32
8, // 0x05 int64
16, // 0x06 int128
1, // 0x07 uint8
2, // 0x08 uint16
4, // 0x09 uint32
8, // 0x0a uint64
16, // 0x0b uint128
4, // 0x0c float32
8, // 0x0d float64
1, // 0x0e char8
2, // 0x0f char16
SIZE_OF_XVECTOR, // 0x10 string8
SIZE_OF_XVECTOR, // 0x11 string16
-1,-1,-1,-1,-1, // padding 0x12-0x1f
-1,-1,-1,-1,-1,
-1,-1,-1,-1,
-1, // 0x20 class
-1, // 0x21 interface
-1, // 0x22 typedef
4, // 0x23 enum
SIZE_OF_FUNCTOR, // 0x24 functor
-1, // 0x25 variant
sizeof(void*), // 0x26 function ptr
-1, // 0x27 not reflected
-1,-1,-1,-1,-1, // padding 0x28-0x2f
-1,-1,-1,
-1, // 0x30 volatile
-1, // 0x31 const
-1, // 0x32 assignable
SIZE_OF_PREF, // 0x33 movable
-1, // 0x34 offsettable
sizeof(void*), // 0x35 T*
-1, // 0x36 T&
-1,-1,-1,-1,-1, // padding 0x37-0x3f
-1,-1,-1,-1,
SIZE_OF_INTERFACE_PTR, // 0x40 ptr<T>
SIZE_OF_INTERFACE_PTR, // 0x41 openvariant<T>
SIZE_OF_PREF, // 0x42 pref<T>
SIZE_OF_PREF, // 0x43 cref<T>
SIZE_OF_XVECTOR, // 0x44 xvector<T>
-1, // 0x45 xdeque<T>
-1, // 0x46 xlist<T>
SIZE_OF_XSET, // 0x47 xset<T>
-1, // 0x48 xbag<T>
SIZE_OF_XVECTOR, // 0x49 dynarray<T>
-1,-1,-1,-1,-1, // padding 0x4a-0x4f
-1,
-1, // 0x50 T[size]
SIZE_OF_XMAP, // 0x51 xmap<K,V>
};
cxAssert(cxArraySize(sizes) == FT_MAP+1);
return sizes[type];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Metadata
inline bool bcIsMetaData(octet_t type)
{
return type >= MDT_FLAGS;
}
enum MetaDataBitMasks
{
MDF_READ_ONLY = 0x00000001, // A read only field can't be edited by the user
MDF_INVISIBLE = 0x00000002, // An invisible field is completely hidden from the user
MDF_DISABLED = 0x00000004, // A disabled field is typically grayed
MDF_INVALID = 0x00000008, // An invalid field is typically shown in red
MDF_SECURE = 0x00000010, // Used for a string that represents a password that must not be readable on the screen
MDF_HEX = 0x00000020, // Allows int8,int16,int32,int64 fields to be displayed in hexadecimal
};
} // namespace ceda