Sezione TYPE
Permette di dichiarare nuovi tipi di dato costruiti sulla base dei tipi
semplici e dei costruttori di strutture dati ARRAY e RECORD.
I tipi predefiniti sono:
Il tipo BOOLEAN rappresenta i valori logici TRUE e FALSE.
Il valore iniziale di una variabile di tipo BOOLEAN è FALSE.
Il tipo INTEGER rappresenta numeri interi con segno.
Il valore iniziale di una variabile di tipo INTEGER è 0 (zero).
Il tipo enumerativo permette di definire in una unica dichiarazione
un nome di tipo sinonimo per INTEGER e una o più costanti INTEGER.
Le costanti enumerative vanno elencate tra parentesi rotonde ed assumono
per default i valori interi 0, 1, 2, ... Ad esempio:
TYPE Orientamento = (nord, sud, est, ovest)
definisce 4 costanti di tipo INTEGER che hanno i valori 0, 1, 2 e 3
rispettivamente.
E' possibile indicare un valore esplicito per la costante enumerativa,
ma questo valore deve essere maggiore o uguale al valore che verrebbe
assegnato per default; il valore default per le costanti enumerative
che seguono è il valore assegnato incrementato di uno. Ad esempio:
TYPE Permessi = (esecuzione=1, scrittura, lettura=4)
assegna alla costante scrittura il valore 2.
Il valore iniziale di una variabile di tipo enumerativo è
sempre zero. Il linguaggio non prevede controlli sulla validità
dei valori assegnati alle variabili di tipo enumerativo. Le variabili
di tipo enumerativo sono in realtà di tipo INTEGER. Se alla prima
costante del tipo enumerativo viene assegnato un valore diverso da zero,
allora il valore default di una variabile enumerativa (che è
zero per gli INTEGER) risulta non valido.
Il tipo REAL rappresenta numeri a virgola mobile e precisione limitata.
Il valore iniziale di una variabile di tipo REAL è 0.0.
Il tipo STRING permette di rappresentare stringhe di qualsiasi
lunghezza e contenenti qualsiasi codice. Il valore iniziale di una
variabile di tipo STRING è il valore speciale NIL.
Il tipo ARRAY permette di rappresentare un elenco di variabili
dette elementi. Tutti gli elementi di un ARRAY devono essere
dello stesso tipo, e ciascuno viene individuato da un indice di tipo
INTEGER positivo o nullo. Il valore iniziale di un ARRAY è NIL
e non contiene elementi.
La funzione count(a), esportata dal modulo m2runtime,
ritorna il numero di elementi contenuti nell'ARRAY. Gli elementi di
un array si possono allocare anche a partire da un indice arbitrario:
gli elementi non definiti vengono inizializzati per default come
per le variabili. Pertanto, per un array di elementi di tipo T, gli
elementi non esplicitamente assegnati assumono il valore iniziale delle
variabili di tipo T. Mentre l'assegnamento può essere eseguito
su qualsiasi elemento con indice >=0, il tentativo del programma di
leggere un elemento di un ARRAY NIL, oppure un elemento che non esiste
(cioè con indice < 0 o >= count(a) ) produce
un errore fatale di esecuzione.
Il tipo RECORD permette di rappresentare zero, una o più
variabili dette campi. Il valore iniziale di un RECORD è
NIL. I campi possono avere tipi fra loro differenti, e ciascun campo
viene individuato da un nome. Il RECORD viene automaticamente allocato
quando si assegna almeno un campo. I campi non assegnati vengono
inizializzati come per le altre variabili di tipo corrispondente. Il
tentativo di accedere al valore di un campo di un RECORD NIL produce un
errore fatale di esecuzione.
Il tipo FUNCTION è un puntatore a funzione. La dichiarazione
di questo tipo deve includere gli argomenti formali, il tipo del valore
ritornato e l'eventuale attributo RAISE ERROR.
I tipi ARRAY e RECORD si possono combinare per costruire strutture dati
più complesse. Ad esempio, un ARRAY di ARRAY costituisce una
matrice. La disallocazione dei tipi dinamici è automatica quando
all'interno del programma non ci sono più riferimenti alla memoria
occupata da essi.
Esempi di dichiarazioni di tipo:
TYPE
(* Punto del piano in coordinate cartesiane: *)
Punto = RECORD x,y: REAL END
(* Poligono descritto come elenco di punti del piano: *)
Poligono = ARRAY OF Punto
(* Matrice rettangolare di dimensione arbitraria: *)
Matrice = ARRAY OF ARRAY OF REAL
(* Un sinonimo di INTEGER introdotto per migliorare la
leggibilita' del programma: *)
Livello = INTEGER
(* Un tipo enumerativo che introduce alcune costanti: *)
Qualifica = (impiegato, operaio, quadro, dirigente, altro)
(* Generica struttura dati che rappresenta un impiegato: *)
Persona = RECORD
nome, cogn: STRING
qualifica: Qualifica
livello: Livello
END
Personale = ARRAY OF Persona
(* Una funzione che accetta due stringhe e ritorna un intero: *)
CompareString = FUNCTION(a: STRING, b: STRING): INTEGER
I tipi così dichiarati vanno ad integrare i tipi predefiniti dal
linguaggio, e si possono usare per dichiarare nuovi tipi, per dichiarare
nuove variabili, come tipi per gli argomenti formali delle funzioni,
e come tipi per il valore di ritorno delle funzioni.
In M2 due variabili sono compatibili per assegnamento e per passaggio
di argomento a funzione se hanno la stessa struttura. Nel dettaglio,
due tipi sono compatibili se ricorre almeno una delle seguenti condizioni:
- sono entrambi lo stesso tipo semplice
BOOLEAN o
INTEGER o REAL o STRING;
- un tipo enumerativo è compatibile con un tipo INTEGER;
- sono entrambi ARRAY e gli elementi sono compatibili;
- sono entrambi RECORD e i campi sono per numero e per ordine
compatibili (i nomi dei campi dei due tipi possono differire);
- sono entrambi funzioni, gli argomenti corrispondono per tipo,
il valore di ritorno corrisponde per tipo e corrisponde la presenza
dell'attributo RAISE ERROR.
Quindi, facendo riferimento all'esempio precedente, una variabile di
tipo Persona è compatibile con qualsiasi variabile o
argomento di funzione che sia un RECORD costituito da due campi di tipo
STRING seguiti da un campo di tipo INTEGER. Le seguenti dichiarazioni,
che fanno uso dei tipi con nome:
VAR a, b, c: Persona
FUNCTION Coniugato(p: Punto): REAL
VAR q: Punto
BEGIN
q[x] = p[x]
q[y] = -p[y]
RETURN q
END
sono perfettamente equivalenti alle seguenti, che fanno uso di tipi
anonimi (o espliciti):
VAR a, b, c:
RECORD
nome, cogn: STRING
q, l: INTEGER
END
FUNCTION Coniugato(p: RECORD h, v: REAL END): RECORD x, y: REAL END
VAR q: RECORD a, b: REAL END
BEGIN
q[a] = p[h]
q[b] = -p[v]
RETURN q
END
L'uso dei tipi con nome rende il sorgente più sintetico e più
chiaro, e permette di eseguire modifiche più facilmente.
|