This section addresses the language specification of OpenC++. OpenC++ is identical to C++ except two extensions. To connect a base-level program and a meta-level program, OpenC++ introduces a new kind of declaration into C++. Also, new extended syntax is available in OpenC++ if the syntax is defined by the meta-level program.
Base-level Connection to the MOP
OpenC++ provides a new syntax for metaclass declaration. This
declaration form is the only connection between the base level
and the meta level. Although the default metaclass is Class,
programmers can change it by using this declaration form:
metaclass metaclass-name [ class-name [ ( meta-arguments ) ] ] ;
This declares the metaclass for a class. It must appear
before the class is defined. If the class name is not specified, this
declaration means nothing except that the metaclass is loaded
into the compiler. meta-arguments is a sequence of
identifiers, type names,
literals, and C++ expressions surrounded by (). The
elements must be separated by commas. The identifiers appearing in meta-arguments do not have to be declared in advance. What
should be placed at meta-arguments is specified by the metaclass.
The code shown below is an example of metaclass declaration:
metaclass PersistentClass Point;
class Point {
public:
int x, y;
};
The metaclass for Point is PersistentClass.
This syntax was chosen so that it looks like a variable declaration such
as:
class Point p0;
The former declaration defines a class metaobject Point as
an instance of metaclass PersistentClass, and the latter defines
an object p0 as an instance of class Point.
Syntax ExtensionsThe extended syntax described here is effective if programmers define it by the MOP. By default, it causes a syntax error. To make it available, the programmers must register a new keyword, which is used in one of the following forms:
( function-arguments ) ]
A keyword can be registered to lead a modifier. It may
appear in front of class declarations, the new operator, or
function arguments. For example, these statements are valid:
distribute class Dictionary { ... };
Point* p = remote(athos) new Point;
void append(ref int i, int j);
Here, distribute, remote, and ref are registered keywords.
Also, a modifier can be placed in front of a member declaration. For example,
class Point {
public:
sync int x, y;
};
The keyword sync is a modifier.
( function-arguments ) ] :
Programmers may define a keyword as a member-access specifier. It
appears at the same place that the built-in access specifier such as public can appears. For example, if after is a
user-defined keyword, then programmers may write:
class Window {
public:
void Move();
after:
void Move() { ... } // after method
}
-> keyword ( expression ){ statements } . keyword ( expression ){ statements } :: keyword ( expression ){ statements }
A user-defined keyword may lead something like the while
statement. In the grammar, that is not a statement but an expression.
It can appear at any place where C++ expressions appear. expression is any C++ expression. It may be empty or separated by
commas like function-call arguments.
Here is an example of the while-style statement:
Matrix m2;
m2.forall(e){
e = 0;
}
A user-defined keyword can also lead other styles of statements.
-> keyword ( expr ; expr ; expr ){ statements } . keyword ( expr ; expr ; expr ){ statements } :: keyword ( expr ; expr ; expr ){ statements }
The for-style statement takes three expressions like the for
statement. Except that, it is the same as the while-style statement.
-> keyword ( arg-declaration-list ){ statements } . keyword ( arg-declaration-list ){ statements } :: keyword ( arg-declaration-list ){ statements }
The closure statement takes an argument declaration list instead of an expression. That is the only difference from the while-style statement. For example, programmers may write something like this:
ButtonWidget b;
b.press(int x, int y){
printf("pressed at (%d, %d)\n", x, y);
}
This might be translated into this:
void callback(int x, int y){
printf("pressed at (%d, %d)\n", x, y);
}
:
ButtonWidget b;
b.press(callback); // register a callback function
Loosened GrammarBesides extended syntax, OpenC++'s grammar is somewhat loosened as compared with C++'s grammar. For example, the next code is semantically wrong in C++:
Point p = { 1, 3, 5 };
The C++ compiler will report that p cannot be initialized by
{ 1, 3, 5 }. Such an aggregate can be used only to
initialize an array.
The OpenC++ compiler simply accepts such a semantically-wrong code.
It ignores semantical correctness expecting that the code will be
translated into valid C++ code.