$class and $struct

There are 5 class types:

The Xc++ language allows for reflecting classes and structs using $class and $struct.

Public modifier

For example


$struct+ X
{
    $int32 x;
};

The public modifier (+) means that X is public - so it is:

The public modifier (+) cannot be used on a generic type such as a $mixin, or else Xcpp gives the error '+' modifier not permitted on $mixin

The public modifier (+) also cannot be used on nested classes or structs.

Example

Here's a more complicated example:


$class+ C <<dc>> isa ceda::IObject : 
    Base1, public Base2, private Base3 
    model SomeModel 
    mixin [Mixin1 Mixin2] Base4, protected Base5 : [1,2,3,foo(x)]
{ 
};

dc is a directive which determines whether a default constructor is defined.

Implementing an interface

A class or struct can declare it implements an interface using isa. For example:


$class X isa IObject
{
};

Referenced base model

A class can reference a base model by name. In the following example class X references its base model M by name:


$model M {};
$class X : model M {};

Note that M must be a pure model (a class with an embedded model is not sufficient to be referenced in this manner).

Anonymous models in the mixin chain

A class can define any number of anonymous models in its mixin chain. For example:


$class X : mixin 
    [ 
        model 
        {
            int32 x;
            float64 y;
        } 
    ]

This model is called an anonymous model mixin.

Models

Models can be free standing


$model Point
{
    int32 x;
    int32 y;
};

They can be inherited in a $class


$class X :
    model
    {
        int32 x;
    }
{
};

They can be embedded directly


$class X
{
    model
    {
        int32 x;
    }
};

More examples


$class X {};
$class X { $model{} };
$model M {};

$class X : mixin[M1 M2] {};

$mixin X {};
$mixin X<typename T> {};
$mixin X { $model{} };

$class X : model {} {};
$class X : model M {};

$mixin X : model {} {};
$mixin X<typename T,int N> : model {} {};
$mixin X : model M {};

$class X : mixin [M] {};
$mixin [model{}] {};
$mixin X : mixin [M] {};

$class X : mixin [model{}] {};

$class X isa ceda::IObject {};
$class X isa ceda::IPersistable {};

$class X : model{} mixin [model{}] {};
$class X : model{} mixin [model{}model{}] {};

$class X isa ceda::IObject : model{} mixin [model{}model{}] {};
example
pure model$model M {};
base model$class X : model {} {};
referenced base model$class X : model M {};
nested model$class X { $model{} };
embedded mixin model$class X : mixin [model{}] {};
referenced mixin model$class X : mixin [M] {};

Strict versus non-strict types

Xcpp imposes the use of platform independent types in certain cases. If a class is reflected then its members must have platform independent types. We call this a strict class.

Restrictions on pure models

A pure model is quite restricted:

The range of release numbers for which a field in a model exists in the schema

For each field in a model a half open interval [r1,r2) of integer release numbers represents the set of release numbers for which the field exists in the schema.

We use r2 = -1 to indicate that the field hasn't been dropped in the latest release.

If there is no $schema {...} section then for each model field we have r1 = 0 and r2 = -1. This represents "added but not dropped".

todo: move into description of parser

During the parsing of the $schema {...} section we assume the following

After parsing the $schema section, it should never be the case that r1 = -1. However it possible for r2 to be -1 to indicate that the field hasn't been dropped in the latest release.