====== Identifier definitions ======
Einen Identifier kann man auf verschiedene Weise erzeugen. Zu unterscheiden sind vier Typen
* Gleichsetzung (alias, typedef, static const, enum, flag)
* Definition einer Variablen/Member
* Definition eines Typs mit Variablendefinition
===== Konstanten =====
Konstanten werden einfach mit '=' gesetzt:
a = 4;
b = int(4);
p = Point(1, 2, 3);
Point contains
{
x, y, z is double; // Variablen
construct( as x, as y, as z );
Origin = Point( 0, 0, 0 ); // Konstante
}
===== statische Funktionen =====
...sind im Prinzip wie Konstanten, nur dass die Identifier von Parametern abhängig sind:
add( a, b is int ) = a+b;
===== Funktionszeiger =====
add( a, b is int ) = a+b; // Konstante
addref is code( a, b is int ) (add); // Variable
===== Typedefs =====
Typedefs entsprechen im Prinzip Konstanten, da sie statisch sind und nicht verändert werden können.
MyInt = int;
funcType = code( int a, int b) as int;
===== enums und flags =====
sind konstante Werte und werden direkt zugewiesen:
enum Color
{
Rot = 0xFF0000,
Gruen = 0x00FF00,
Blau = 0x0000FF
};
===== Definitionen einer Variablen =====
Definitionen werden mit 'is' beschrieben
Variabeln können im Gegensatz zu Konstanten überschrieben werden.
a is int;
t is type;
i is 0; // int
j is int(0); // int
p is Point( 1, 2, 3 );
===== alias =====
Aliase sind funktionsinterne Namen, bzw. Abkürzungen.
Auto contains
{
Farbe, Hersteller;
construct( f = .Farbe, h = .Hersteller ) :=
print "Das neue Auto ist %s und wird von %s gebaut\n" % ( f%, h$ );
}
add( summand1 = s1, summand2 = s2 as int ) = s1+s2;
===== Typedef mit automatischer Variablendeklaration =====
Count is discrete int(4711);
int integer = 7328;
User contains
{
Id is discrete int; // erzeugt den Typ User::Id, der von int erbt.
Name is string; // einfache String-Variable
staticValue = 0;
construct( construct .Id, .Name ); // String wird 1:1 durchgeschleift,
// Id darf konstruiert werden, es dürfen also auch explizite
// Konstruktoren von Id gerufen werden, z.B. Id( int )
// Der erste Parameter muss auf einen Konstruktor von Id passen (also Id oder int)
// Hat der Konstruktor mehrere Parameter, darf geklappert werden. Der Aufruf muss nicht Id( 1, 2) sein,
// sondern (1, 2) reicht, wenn er erste Parameter - eben (1,2) - auf einen Id-Construktor passt.
{
// nothing to do
// Aufruf User( User::Id( 1 ), "Peter" )
// Aber auch User( 2 /* da construct id */, "Gustav" );
// auch User( integer /* da construct id */, , "Heinrich" )
// NICHT User( Count, "Markus" ) // da Count discrete ist und Id keinen Konstruktor für Count hat
}
construct( .Id )
{
.Name : Id$;
// Aufruf User( User::Id(2) ) ok
// Aufruf User( cast 2 ), User( cast integer )
// Aufruf User( cast Count ) // nicht ok, cast Count wäre z.B. int, aber es steht ist kein Cast für User::Id definiert. (müsste man erklären)
// Aufruf User( 2 ) geht nicht, da Id kein int mehr ist und explizit konstruiert werden muss
// Aufruf User( integer ), User( Count ) geht beides nicht
// Aufruf User( User::Id( cast Count ) ) ok // User::Id verlangt int, cast Count kann int liefern
}
construct( a is Id ) // Variable vom Typ Id
{
.Id : a; // Eventuell erst Standard-Konstruktor, dann operator =
.Name : a$;
// Aufruf User( User::Id(2) ) ok
// Aufruf User( 2 ) nopes
// Aufruf User( staticValue ) // nopes
// Aufruf User( cast integer ), // ok
// Aufruf User( cast Count ) nopes
}
construct( a is Id ) // Variable vom Typ Id
{
.Id = a; // Eventuell erst Standard-Konstruktor, dann operator =
.Name = a$;
// Aufruf User( User::Id(2) ) ok
// Aufruf User( 2 ) nopes
// Aufruf User( staticValue ) // nopes
// Aufruf User( cast integer ), // ok
// Aufruf User( cast Count ) nopes
}
};
===== Initialisierung =====
Der = Operator ersetzt die Initialisierungsliste. Das ermöglicht einen Programmablauf, bevor Membervariblen initialisiert sind.
User contains
{
Id is discrete int; // erzeugt den Typ User::Id, der von int erbt.
Name is string; // einfache String-Variable
construct( id is Id, name is Name )
{
.Id = id; // Standardkonstruktor für .Id wird nicht aufgerufen, sondern Copy-Construktor
.Id = User::Id( 1 ); // Fehler: Initialisiert wird nur einmal
.Name : name; // Standardkonstruktor, dann Zuweisung. Hint: Könnte auch über Initialisierung laufen
.Name = "Name"; // Fehler: .Name wurde schon per Standardkonstruktor initialisiert.
}
// besser
construct( .Id, .Name );
};