Die Datenelemente, die in einem User-Language-Programm verwendet werden sollen, müssen definiert werden, bevor sie verwendet werden können. Es gibt drei Arten von Definitionen:
Der Umfang einer Konstanten- oder Variablendefinition reicht von der Zeile, in der sie erstellt wurde, bis zum Ende des aktuellen Blocks oder bis zum Ende des User-Language-Programms, wenn die Definition außerhalb eines Blocks existiert.
Der Umfang einer Funktionsdefinition reicht von der schließenden Klammer (}) des Funktionskörpers bis zum Ende des User-Language-Programms.
Konstanten werden mithilfe des Schlüsselworts enum definiert. Beispiel:
enum { a, b, c };
Hierbei werden die drei Konstanten a, b und c definiert, wodurch sie die Werte 0, 1 bzw. 2 erhalten.
Konstanten können auch auf bestimmte Werte initialisiert werden. Beispiel:
enum { a, b = 5, c };
Dabei wäre a 0, b 5 und c 6.
Die allgemeine Syntax einer Variablendefinition lautet
[numeric] type identifier [= initializer][, ...];
Dabei ist type einer der Daten- oder Objekttypen, identifier der Variablenname und initializer ein optionaler Anfangswert.
Mehrere Variablendefinitionen desselben Typs werden durch Kommata (,) getrennt.
Wenn auf identifier ein Klammernpaar ([ ]) folgt, wird damit eine Anordnung von Variablen des angegebenen Typs definiert. Die Größe einer Anordnung wird zur Laufzeit automatisch angepasst.
Das optionale numerische Schlüsselwort kann mit Zeichenfolgenanordnungen verwendet werden, damit sie von der sort()-Funktion alphanumerisch sortiert werden.
Vorgabemäßig (wenn initializer nicht vorhanden ist) sind die Datenvariablen auf 0 (oder im Falle einer Zeichenfolge auf "") und die Objektvariablen auf Ungültig gesetzt.
| int i; | Definiert eine int-Variable namens i. |
| string s = "Hello"; | Definiert eine string-Variable namens s, und initialisiert sie auf "Hello". |
| real a, b = 1.0, c; | Definiert drei real-Variablen namens a, b und c, wobei b auf den Wert 1.0 initialisiert wird. |
| int n[] = { 1, 2, 3 }; | Definiert eine int-Anordnung, und initialisiert die ersten drei Elemente auf 1, 2 und 3. |
| Numerische Zeichenfolgennamen[]; | Definiert eine Zeichenfolgenanordnung, die alphanumerisch sortiert werden kann. |
| UL_WIRE w; | Definiert ein UL_WIRE-Objekt namens w. |
| Auf die Anordnungselemente von Objekttypen kann nicht direkt zugegriffen werden: | |
| UL_SIGNAL signals[]; | |
| ... | |
| UL_SIGNAL s = signals[0]; | |
| printf("%s", s.name); |
Sie können eigene User-Language-Funktionen schreiben und diese genauso wie die Builtin-Funktionen aufrufen. Die allgemeine Syntax einer Funktionsdefinition lautet:
type identifier(parameters)
{
statements
}Dabei ist type einer der Daten- oder Objekttypen, identifier der Funktionsname, parameters eine Liste durch Kommas getrennter Parameterdefinitionen und statements eine Folge von Anweisungen. Funktionen, die keinen Wert zurückgeben, weisen den Typ void auf.
Eine Funktion muss definiert werden, bevor sie aufgerufen werden kann, und Funktionsaufrufe können nicht rekursiv sein (eine Funktion kann sich nicht selbst aufrufen).
Die Anweisungen im Funktionskörper können die Werte der Parameter ändern, dies hat jedoch keine Auswirkung auf die Argumente des Funktionsaufrufs.
Die Ausführung einer Funktion kann mit der return-Anweisung beendet werden. Ohne eine return-Anweisung wird der Funktionskörper bis zur schließenden Klammer (}) ausgeführt.
Ein Aufruf der exit()-Funktion beendet das gesamte User-Language-Programm.
Wenn Ihr User-Language-Programm eine Funktion namens main() enthält, wird diese Funktion explizit als Hauptfunktion aufgerufen, und der Rückgabewert entspricht dem Rückgabewert des Programms.
Befehlszeilenargumente sind für das Programm über die globalen Builtin-Variablen argc und argv verfügbar.
int CountDots(string s)
{
int dots = 0;
for (int i = 0; s[i]; ++i)
if (s[i] == '.')
++dots;
return dots;
}
string dotted = "This.has.dots...";
output("test") {
printf("Number of dots: %d\n",
CountDots(dotted));
}