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