Categories are an extension of the 'class' and 'struct' concepts in C++.
Think of the difference between the keyword 'class' in C# and C++, this is the sort of
difference in features you can specify with opC++ categories.
Adding different categories allows you to control the code generated
for an object type based on the category keyword.
In the Standard opC++ dialect for example, code is organized into the 'opstruct' and 'opclass' categories.
Notes
Notes are the basic building block for generating code in opC++ Dialects.
Notes are like automatically generated code snippets, but also have:
a category - notes are specific to a category
a location - in the source, at the top of the header, in the class definition, etc.
arguments - for substituting class name, namespace, parent name, etc.
conditions - generate a note only when a specific condition is met.
hiding - have the debugger display the dialect file or the code file when in note code.
Notes are always generated from category declarations in opC++ code files.
1. Definition
You can easily generate code for categories via simple notes. The code that you specify in a note body is C++ code. For example, here we automatically generate a typedef called Super for uclasses that have single inheritance. We can use Super to reference the parent class. Notice that we can pass arguments to notes from the category.
2. Usage
Here, we use the automatically generated typedef Super to call a virtual method on the base class. The typedef was automatically generated from our dialect code.
Maps
Maps in opC++ generate Notes for each member in a category definition.
Maps are like Notes, but also have:
sub notes: each map generates 'start', 'end' and per member 'mapping' notes.
statement type: may apply to data members or function members.
conditions - generate the Mapping only when a specific condition is met on the member being mapped.
[need a diagram for maps here]
Modifiers
You can define additional modifiers - like 'const' or 'volatile' in opC++ dialects.
You can also define valued modifiers - like 'xml()' for example. These modifiers
may have additional text within the parentheses which constitute the modifier's value.
1. Declaration
Here, we create a user-defined valued data modifier called xml. Putting this valued modifier in front a data member in a uclass will automatically bind the data member to an xml serialization routine called PrintXml(). This routine will be automatically generated from the printxml datamap.
2. Definition
In this screenshot we implement the notes for the printxml datamap. The start and end notes are generated once, while the mapping note is generated once for each data member meeting the criteria. In this simple example, we output the tagged data members to xml. You can create much more robust serialization routines using C++ templates in the generated code.
3. opC++ Usage
Here we declare a uclass called Person, and create several data members tagged with the user-defined valued modifier xml from above. We put the name of the desired xml tag in the parentheses.
4. C++ Usage
To print the Person uclass's tagged members to xml, we simply call the PrintXml() generated method.
5. Resulting Xml
Here is the resulting xml for the Person uclass.
Custom Errors
User-Defined Errors
Tell the opC++ compiler to enforce custom rules when compiling opC++ code, and control the error messages the compiler outputs.
For example, here we force the user to capitalize all opclass members.
Compiler Errors
Here are the error messages after enforcing the custom rules for capitalizing member names.
Notice the custom errors!
Dialect Visualization
Visualize your dialects using the compiler's generated xml descriptions.
Here you can see all available arguments for notes, and all available modifiers
for criteria expressions: