nomi ed oggetti denotabili int pippo; int pluto() { pippo=1; }

23
nomi ed oggetti denotabili int pippo; int pluto() { pippo=1; } distinguere il nome e l’oggetto denotato uno stesso oggetto può avere più nomi (aliasing) uno stesso nome può denotare oggetti diversi in momenti diversi l’uso dei nomi realizza la più semplice astrazione sui dati (l’ambiente è la parte dell’implementazione responsabile dell’associazione nome-oggetto denotato) l’uso dei nomi realizza la più semplice astrazione sul controllo nome: sequenza di caratteri usata per denotare un oggetto

description

nome: sequenza di caratteri usata per denotare un oggetto. nomi ed oggetti denotabili int pippo; int pluto() { pippo=1; } distinguere il nome e l’oggetto denotato uno stesso oggetto può avere più nomi (aliasing) uno stesso nome può denotare oggetti diversi in momenti diversi - PowerPoint PPT Presentation

Transcript of nomi ed oggetti denotabili int pippo; int pluto() { pippo=1; }

Page 1: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

nomi ed oggetti denotabili

int pippo;

int pluto() { pippo=1; }

– distinguere il nome e l’oggetto denotato – uno stesso oggetto può avere più nomi (aliasing)– uno stesso nome può denotare oggetti diversi in momenti

diversi– l’uso dei nomi realizza la più semplice astrazione sui dati

(l’ambiente è la parte dell’implementazione responsabile dell’associazione nome-oggetto denotato)

– l’uso dei nomi realizza la più semplice astrazione sul controllo

nome: sequenza di caratteri usata per

denotare un oggetto

Page 2: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

oggetti denotabili: oggetti a cui posso assegnare un nome – oggetti i cui nomi sono definiti dall’utente (variabili, parametri, procedure tipi definiti, costanti simboliche, …)– oggetti i cui nomi sono definiti dal linguaggio di programmazione (tipi primitivi, operazioni primitive, …)

il binding (legame) nome-oggetto avviene in differenti fasi:

– progettazione del linguaggio– scrittura del programma– compile-time– run-time

Page 3: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

ambiente: insieme delle associazioni nome-oggetto esistenti a run-time in uno specifico punto del programma ed in uno specifico momento

dichiarazione:costrutto del linguaggio che permette di introdurre un’associazione nell’ambiente (alcuni linguaggi hanno associazioni implicite)

int x;

int f() { return 0; }

typedef T = int;

Page 4: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

stesso nome denota oggetti diversi

{ int pippo;

pippo = 2;

{ char pippo;

pippo = a; } }

stesso oggetto denotato da più nomi in ambienti diversi

una variabile passata per riferimento è accessibile:– con il suo nome nel programma chiamante– con il nome del parametro formale nella procedura

più puntatori a una stessa variabile

variabile intera

variabile carattere

Page 5: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

stesso oggetto denotato da più nomi, stesso ambiente

int *X, *Y;

X = (int *) malloc (sizeof (int));

*X = 5;

Y = X;

*Y = 10;

write(*X);

stesso nome, nello stesso ambiente, denota oggetti diversi a seconda del flusso di esecuzione del programma

– procedura ricorsiva che dichiara un nome locale– scope dinamico

aliasing

il risultato è 10, perché X e Y puntano alla stessa locazione

Page 6: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

blocco:

regione testuale di un programma, individuata da un segnale di inizio e uno di fine, che può contenere dichiarazioni locali a quella regione

– blocco associato a una procedura– blocco in-line (o anonimo)

{ int pippo; pippo = 2;

{ char pippo; pippo = a; } }

i cambiamenti dell’ambiente avvengono all’entrata e all’uscita dai blocchi (anche annidati)

blocco in-line apri blocco A;apri blocco B;

chiudi blocco A;chiudi blocco B;

mai permesso

Page 7: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

regola di visibilità canonica:

una dichiarazione locale in un blocco è visibile:– in quel blocco– in tutti i blocchi annidati– salvo ri-dichiarazioni dello stesso nome (mascheramento)

Page 8: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

ambiente associato a un blocco:

– ambiente locale (nomi dichiarati localmente al blocco, eventualmente parametri formali)

– ambiente non locale (nomi dichiarati fuori dal blocco, ma comunque visibili)

– ambiente globale (nomi creati all’inizio del programma, usabili in tutti i blocchi)

Page 9: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

A: { int a =1;

B: { int b=2; int c=2;

C: { int c=3; int d;

d=a+b+c;

write(d);

}

D: { int e;

e=a+b+c;

write(e);

}}}

associazione nell’ambiente globale

ambiente locale di B + ambiente globale

d=6;l’ambiente locale di C maschera quello di B

e=5

ambiente locale di C + ambiente non locale +

ambiente globale

nell’ambiente non locale di D non compare d

Page 10: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

operazioni sull’ambiente

entrando in un blocco:– creazione delle associazioni fra i nomi locali al blocco e gli oggetti denotati– disattivazione delle associazioni per i nomi ridefiniti

uscendo dal blocco:– distruzione delle associazioni fra i nomi locali al blocco e gli oggetti denotati– riattivazione delle associazioni per i nomi che erano stati ridefiniti

Page 11: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

operazioni sui nomi e sull’ambiente

– naming: creazione di associazione fra nome e oggetto denotato (dichiarazione locale al blocco o parametro)

– referencing: riferimento di un oggetto denotato mediante il suo nome (uso del nome per accedere all’oggetto denotato)

– disattivazione di associazione fra nome e oggetto denotato (la nuova associazione per un nome maschera la vecchia associazione, che rimane disattivata fino all’uscita dal blocco)

– riattivazione di associazione fra nome e oggetto denotato (una vecchia associazione che era mascherata è riattivata all’uscita da un blocco)

– unnaming: distruzione di associazione fra nome e oggetto denotato (all’uscita di un blocco)

Page 12: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

operazioni su oggetti denotabili

– creazione: allocazione della memoria e inizializzazione

– accesso e modifica: tramite il nome

– distruzione: deallocazione della memoria

tempo di vita degli oggetti

tempo di vita delle associazioni

Page 13: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

regole di scope

A: { int x=0;

void pippo(){ x=1;}

B: { int x;

pippo();

}

write(x);

}

quale valore di x è stampato?

Page 14: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

regola di visibilità canonica:

una dichiarazione locale in un blocco è visibile:– in quel blocco– in tutti i blocchi annidati– salvo ri-dichiarazioni dello stesso nome (mascheramento)

MA

la regola di visibilità (cioè l’annidamento) è basata:– sul testo del programma (scope statico) ?– sul flusso di esecuzione (scope dinamico)?

Page 15: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

scope statico o scope annidato più vicino

l’ambiente in qualsiasi punto e in qualsiasi momento dipende SOLO dalla struttura sintattica del programma

(basic, algol, ada, pascal, java)

cioè1. le dichiarazioni locali in un blocco includono solo quelle

presenti nel blocco, e non quelle dei blocchi annidati;

2. se si usa un nome in un blocco, l’associazione valida è quella locale al blocco; se non esiste, si prende la prima associazione valida a partire dal blocco immediatamente esterno, dal più vicino al più lontano; se non esiste, si considera l’ambiente predefinito del linguaggio; se non esiste, errore;

3. se il blocco ha un nome, allora il nome fa parte dell’ambiente locale del blocco immediatamente esterno (caso procedure).

che succede al compilatore con questa regola?

Page 16: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

esempio con scope statico

{

int x=0;

void pippo(int n) {x=n+1;}

pippo(3);

write(x);

{int x=0;

pippo(3);

write(x);

}

write(x);

}

stampa 4

stampa 0

stampa 4

Page 17: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

lo scope statico permette di determinare tutti gli ambienti di un programma leggendone il testo

– migliore comprensione del programma– controlli di correttezza a compile-time– ottimizzazione del codice a compile-time– problema del tipaggio statico e della sicurezza dei tipi

– gestione a run-time complicata (gli ambienti non locali evolvono diversamente dal flusso di attivazione e disattivazione dei blocchi)

Page 18: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

{

const x=0;

void pippo() {write(x);}

void pluto() {const x=1;

pippo();}

pluto();

}

con lo scope statico la sequenza di blocchi da considerare per risolvere i riferimenti a nomi non locali è diversa da quella dei blocchi aperti e chiusi durante l’esecuzione (gestibile LIFO)

seguendo il flusso del programma, con scope statico, è stampato 0, mentre ci aspettavamo 1, essendo pluto l’ultimo blocco attivo

Page 19: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

scope dinamico

l’associazione valida per un nome X, in un punto P di un programma, è la più recente associazione creata (in senso temporale) per X che sia ancora attiva quando il flusso di esecuzione arriva a P

scope statico e scope dinamico sono uguali per la determinazione dell’ambiente locale e di quello globale

– gestione a run-time semplice ma poco efficiente(LIFO sulle attivazioni dei blocchi)– flessibilità nei programmi– difficile comprensione delle chiamate delle procedure

Page 20: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

{

const x=0;

void pippo() {write(x);}

void pluto() {const x=1;

{const x=2;

}

pippo();}

pluto();

}

stampa 1 con scope dinamico, perché considera la più recente

associazione ancora attiva

Page 21: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

problemi di scope statico– dove introdurre le dichiarazioni– qual è la visibilità delle variabili– definizioni ricorsive

beginconst pippo = valore;const valore = 0;

end

valore usato prima della definizione

beginconst valore = 1;procedure plutobegin const pippo = valore; const valore = 0;end

end

valore maschera la definizione esterna

nella procedura

Page 22: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

errore: elemento è usato prima di essere definito; in

Pascal si può fare, ma solo con i puntatori

in ADA si usano dichiarazioni incomplete

type lista = ^elemento;type elemento = record

informazione: intero;successivo: listaend

type elemento;type lista = access elemento;type elemento is record

informazione: intero;successivo: listaend

Page 23: nomi ed oggetti denotabili int  pippo; int  pluto() { pippo=1; }

in Pascal si usano definizioni incomplete per le funzioni

mutuamente ricorsive; in C si può fare liberamente

procedure pippo (A: integer); forward;

procedure pluto (B: integer)begin pippo(3);end

procedure pippo;begin pluto(4)end