12 Xc++ code generation examples
$visit
The xc++ language provides a special mechanism for helping to implement the VisitObjects method of interface IObject
$interface+ IObject
{
void VisitObjects(IObjectVisitor& v) const;
...
};
Before translation
$struct X isa ceda::IObject
{
$visit
{
v << x;
}
ceda::ptr<ceda::IObject> x;
};
After translation
struct X : public ceda::IObjectBaseMixin<X,ceda::EmptyBase>
{
void VisitObjects(ceda::IObjectVisitor& v) const;
...
ceda::ptr<ceda::IObject> x;
};
void X::VisitObjects(ceda::IObjectVisitor& v) const
{
BaseClass::VisitObjects(v);
v << x;
}
Note that supporting $visit on a $mixin makes a lot of sense but it currently leads to compiler errors. This needs to be fixed.
$indep
Before translation
$struct X isa ceda::IObject
{
$indep int x
// called when the DGIndepNode is constructed
create {}
// called when the DGIndepNode is destructed
destroy {}
// allows for replacing the generated code to visit
// the containing object and the indep variable
visit {};
};
After translation
struct X : public ceda::IObjectBaseMixin<X,ceda::EmptyBase>
{
...
void x_create(int& x) const {}
void x_destroy(int& x) const {}
void x_visit(ceda::IObjectVisitor& _v) const {}
int _x_;
struct Indepnode_x : ceda::DGIndepNode
{
typedef int value_type;
Indepnode_x()
{
X* _self = ATTRIB_CAST(X,x);
_self->x_create(_self->_x_);
}
~Indepnode_x()
{
X* _self = ATTRIB_CAST(X,x);
_self->x_destroy(_self->_x_);
}
virtual ceda::xstring Name() const { return "X::x"; }
virtual void VisitContainingObject(ceda::IObjectVisitor& _v) const
{
X const* _self = CONST_ATTRIB_CAST(X,x);
_self->x_visit(_v);
}
value_type const& read() const { ReadBarrier(); return CONST_ATTRIB_CAST(X,x)->_x_; }
value_type& write() { OnChange(); return ATTRIB_CAST(X,x)->_x_; }
operator value_type const&() const { return CONST_ATTRIB_CAST(X,x)->Getx(); }
void operator=(value_type const& _v) { write() = _v; }
} x;
int const& Getx() const { x.ReadBarrier(); return _x_; }
void Setx(int const& _v) { x.OnChange(); _x_ = _v; }
void EvictDgsNodes() const
{
BaseClass::EvictDgsNodes();
x.TryEvict(false);
}
};
If no 'visit {...}' block was given then the generated VisitContainingObject method would be as follows:
virtual void VisitContainingObject(ceda::IObjectVisitor& _v) const
{
X const* _self = CONST_ATTRIB_CAST(X,x);
_v << _self->_x_;
_v << _self;
}
$dep
Before translation
$struct X isa ceda::IObject
{
$visit
{
v << x;
}
$dep ceda::ptr<ceda::IObject> y
evictable { return false; }
evict {}
create {}
destroy {}
invalidate {}
visit {}
calc { y = null; };
ceda::ptr<ceda::IObject> x;
};
After translation
struct X : public ceda::IObjectBaseMixin<X,ceda::EmptyBase>
{
typedef ceda::IObjectBaseMixin<X,ceda::EmptyBase> BaseClass;
void VisitObjects(ceda::IObjectVisitor& v) const;
bool y_evictable() const { return false; }
void y_evict() const {}
void y_create(ceda::ptr<ceda::IObject>& y) const {}
void y_destroy(ceda::ptr<ceda::IObject>& y) const {}
void y_invalidate() const {}
void y_visit(ceda::IObjectVisitor& _v) const {}
void y_calc(ceda::ptr<ceda::IObject>& y) const { y = null; }
mutable ceda::ptr<ceda::IObject> _y_;
struct Depnode_y : ceda::DGDepNode
{
typedef ceda::ptr<ceda::IObject> value_type;
Depnode_y() : ceda::DGDepNode(true)
{
X const* _self = CONST_ATTRIB_CAST(X,y);
_self->y_create(_self->_y_);
}
~Depnode_y()
{
X const* _self = CONST_ATTRIB_CAST(X,y);
_self->y_destroy(_self->_y_);
}
virtual ceda::xstring Name() const { return "X::y"; }
virtual void VisitContainingObject(ceda::IObjectVisitor& _v) const
{
X const* _self = CONST_ATTRIB_CAST(X,y);
_self->y_visit(_v);
}
virtual bool RecalcCache() const
{
X const* _self = CONST_ATTRIB_CAST(X,y);
value_type _prev = _self->_y_;
_self->y_calc(_self->_y_);
return _prev != _self->_y_;
}
virtual bool IsEvictable() const
{
X const* _self = CONST_ATTRIB_CAST(X,y);
return _self->y_evictable();
}
virtual void OnEvict() const
{
X const* _self = CONST_ATTRIB_CAST(X,y);
_self->y_evict();
}
virtual void OnInvalidate() const
{
X const* _self = CONST_ATTRIB_CAST(X,y);
_self->y_invalidate();
}
value_type const& read() const { return CONST_ATTRIB_CAST(X,y)->Gety(); }
operator value_type const&() const { return CONST_ATTRIB_CAST(X,y)->Gety(); }
} y;
ceda::ptr<ceda::IObject> const& Gety() const { y.ReadBarrier(); return _y_; }
ceda::ptr<ceda::IObject> x;
public:
void EvictDgsNodes() const
{
BaseClass::EvictDgsNodes();
y.TryEvict(false);
}
ceda::AnyInterface QueryInterface(const ceda::ReflectedInterface&);
ceda::ReflectedClass const* GetReflectedClass() const;
};
ceda::AnyInterface X::QueryInterface(const ceda::ReflectedInterface& _ri)
{
if (&_ri == &ceda::GetReflectedInterface<ceda::IObject >()) { ceda::ptr<ceda::IObject> p(this); return reinterpret_cast<ceda::AnyInterface&>(p); }
return ceda::AnyInterface();
}
ceda::ReflectedClass const* X::GetReflectedClass() const
{
return NULL;
}
void X::VisitObjects(ceda::IObjectVisitor& v) const
{
BaseClass::VisitObjects(v);
v << x;
}