The vertex-vertex language extension to C++ provides keywords and constructs for expressing algorithms using the vertex-vertex data structure and algebra. There are three things that are added to C++ with this language extension: property definitions, execution blocks and vertex-vertex algebra expression.
Each vertex-vertex program requires definitions for the edge, vertex and mesh properties used in the program. Any C++ type with implemented streaming operators or function can be included as property. Properties are read or written to file using the streaming operators implemented for it. If a type that does not have implemented streaming operators is used, compile errors will occur. Note that all the plain data types in C++ have this already. The names of the data properties are matched to property fields in the data file automaticaly. Properties that are functions can be considered as member functions for an instance of a vertex or mesh.
The syntax for property definitions are as follows:
edge { property1_type property1_name; property2_type property2_name; property3_type property3_name; }; vertex { property1_type property1_name; property2_type property2_name; property3_type property3_name; }; mesh { property1_type property1_name; property2_type property2_name; property3_type property3_name; };
Any permissible C++ identifier can be used as a property name except for "nb", which is reserved as the property name for the neighbourhood data in the data file.
To use the rendering algorithms, a function void glRender() must be defined in the vertex definition. If the rendering algorithms are not used, this function does not need to be present.
Edge, vertex and mesh definitions are required in a vertex-vertex program prior to any other use of the edge, vertex or mesh keywords. However, if no properties are required for the program, they may be empty statements.
To get a property from an edge e
, the syntax is:
e.property_name
To get a property from a vertex v
, the syntax is:
v$property_name
To get a property from a mesh m
, the syntax is:
m.property_name
The interpreter program executes the vertex-vertex program according to the defined execution blocks. A vertex-vertex program may include at most one instance of each block, though none of them are manditory.
The syntax for each block is the block name followed by a pair of curly braces. The curly braces may contain any amount of code to be executed in that block. The block names cannot be preceeded with qualifiers.
The valid execution block names are:
The interpreter uses the blocks as follows:
The following terms are used:
If more than one of the above terms us used in one of the following statements, they are suffixed with numbers to distinguish them.
Edges are structures that can contain the data of how one vertex relates to a neighbouring vertex. Every pair of neighbouring vertices has two edge structure. For a pair of vertices a and b, there is an edge structure that contains the information of how a relates to b and a second edge structure for how b relates to a.
Edge structures may be accessed symmetrically or asymmetrically. If an edge is accessed asymmetrically, only one edge structure in the vertex pair is updated. When accessed symmetrically, the second vertex structure is overwritten by the information contained in the first.
Symmetric access to the edge between vertices vexpr1 and vexpr2.
Assymmetric access to an edge. This accesses the edge structure that contains the information of how vexpr1 relates to vexpr2.
Declare an edge structure.
Vertices are dynamicaly allocated and referenced counted automaticaly. The program does not need to take care of vertex allocation. A vertex object in the program is actualy a pointer to this allocated vertex. It is illegal to create a vertex in the global scope. A vertex may have a null value.
Allocates a new vertex pointed to by the object referred to by ident.
Creates a new reference to the vertex pointed to by the expression vexpr.
Creates a null vertex.
The mesh objects in vertex-vertex programs are regular objects, following the existing C++ rules; mesh can be used just as any other C++ class name.
Any of the following expressions can be used in place of vexpr.
Any C++ identifier refering to a vertex variable may be vertex expression.
Returns a vertex representing the old state of the vertex referred to by vexpr. If vexpr is a null vertex then an error occurs.
Returns a vertex from the neighbourhood of the vertex pointed to by vexpr. If the neighbourhood is empty a null vertex is returned.
Returns the vertex following vexpr1 in vexpr2. If vexpr1 is not in the neighbourhood of vexpr2, then the expression returns a null vertex. If vexpr2 refers to a null vertex then an error occurs.
Returns the vertex preceding vexpr1 in vexpr2. If vexpr1 is not in the neighbourhood of vexpr2, then the expression returns a null vertex. If vexpr2 refers to a null vertex then an error occurs.
Returns the ith vertex following vexpr1 in vexpr2. If vexpr1 is not in the neighbourhood of vexpr2, then the expression returns a null vertex. If vexpr2 refers to a null vertex then an error occurs.
Returns the ith vertex preceding vexpr1 in vexpr2. If vexpr1 is not in the neighbourhood of vexpr2, then the expression returns a null vertex. If vexpr2 refers to a null vertex then an error occurs.
Excutes the path specified by pOp1, pOp2..., pOpN. Each pOpi may be one of next, prev or swap, each has the following cummulative effect:
The expression returns the second vertex in the resulting pair.
The path statement as above uses the current neighbourhoods of the vertices. To use the old neighbourhoods, use a prefixed backquote: `@(vexpr, vexpr) pOp1, pOp2..., pOpN@.
A variation on the path expression where vexpr1 and vexpr2 are passed by reference. This is useful when access to both members of the resulting pair are desired. Again, a prefixed backquote can be used to act on the old neighbourhoods.
The following are used to query values regarding the state of a vertex.
Returns the unique integer representation of the vertex as an unsigned int. If vexpr refers to a null vertex, then an error occurs.
Returns the number of neighbours of vexpr. If vexpr refers to a null vertex, then an error occurs.
If vexpr1 exists in the neighbourhood of vexpr2, then the statement returns true, otherwise false. If vexpr2 is a null vertex, then an error occurs.
The following are used to edit the neighbourhood of a vertex. These expressions always modify the current state of the vertex referred to by the last vexpr in the expression, even if the vexpr evaluates to the old vertex representation.
Modifies the neighbourhood of vexpr2 such that vexpr1 is not in it. If vexpr2 is a null vertex, then an error occurs.
Modifies the neighbourhood of vexpr3 such that vexpr1 is replaced with vexpr2. If vexpr3 is null, then an error occurs.
Modifies the neighbourhood of vexpr3 such that vexpr1 follows vexpr2. If vexpr3 is null, then an error occurs.
Modifies the neighbourhood of vexpr3 such that vexpr1 percedes vexpr2. If vexpr3 is null, then an error occurs.
Assigns the neighbourhood of vexpr to be the list of N vertices listed. Any neighbourhood that was previously there is overwritten. If vexpr is a null vertex, then an error occurs.
Vertices can be compared using ordered relations with boolean tests. The tests use the integer representation of a vertex, available using the labelof vexpr statement, as described above. The implemented tests are ==, !=, <, >, <=, >=.
There is also an automatic cast to bool to test if the vertex is a null vertex. This is useful for use in if statements. The unary ! operator is also available with this cast.
Any of the following expressions can be used in place of mexpr.
Any C++ identifier refering to a vertex variable may be mesh expression.
Check if the vertex referred to by vexpr exists in mexpr.
Removes all the vertices from mexpr.
Adds the vertex referred to by vexpr to mexpr.
Removes the vertex referred to by vexpr from mexpr.
Adds all of the vertices contained in mexpr2 into mexpr1.
Removes all the vertices from mexpr1 and adds to it all the vertices from mexpr2.
Assigns the current vertex state to the old state of each vertex contained in mexpr.
Iteration can be done over both vertex neighbourhoods and meshes. There is no guarantee with regard to the order of the vertices in the iteration. In both cases below, the ellipsis is replaced by any amount of arbitrary code. Also, in both cases, the expression, either vexpr or mexpr is evaluated once, just prior to entering the code in the curly braces for the first time.
iterate over each vertex, accessible with the name ident, in the mesh referred to by mexpr.
iterate over each vertex, accessible with the name ident, in the neighbourhood of the vertex referred to by vexpr.
The proxy object provides an intermediary repsoitory for data that needs to be communicated between the program and the interpreter. See generation/proxy.hpp for all the values that can be set.