nomi ed oggetti denotabili int pippo; int pluto() { pippo=1; } - PowerPoint PPT Presentation

slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
nomi ed oggetti denotabili int pippo; int pluto() { pippo=1; } PowerPoint Presentation
Download Presentation
nomi ed oggetti denotabili int pippo; int pluto() { pippo=1; }

play fullscreen
1 / 23
nomi ed oggetti denotabili int pippo; int pluto() { pippo=1; }
141 Views
Download Presentation
vui
Download Presentation

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

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

  1. 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 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

  2. 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

  3. int x; int f() { return 0; } typedef T = int; 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

  4. 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 variabile intera variabile carattere

  5. 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

  6. 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; } } blocco in-line apri blocco A; apri blocco B; chiudi blocco A; chiudi blocco B; mai permesso i cambiamenti dell’ambiente avvengono all’entrata e all’uscita dai blocchi (anche annidati)

  7. 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)

  8. ambiente associato a un blocco: • ambiente locale (nomi dichiarati localmente al blocco, eventualmente parametri locali) • ambiente non locale (nomi dichiarati fuori dal blocco, ma comunque visibili) • ambiente globale (nomi creati all’inizio del programma, usabili in tutti i blocchi)

  9. 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 ambiente locale di C + ambiente non locale + ambiente globale d=6; l’ambiente locale di C maschera quello di B nell’ambiente non locale di D non compare d e=5

  10. 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

  11. 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)

  12. operazioni su oggetti denotabili • creazione: allocazione della memoria e inizializzazione • accesso e modifica: tramite il nome • distruzione: deallocazione della memoria

  13. regole di scope A: { int x=0; void pippo(){ x=1;} B: { int x; pippo(); } write(x); } quale valore di x è stampato?

  14. 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)?

  15. 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è • le dichiarazioni locali in un blocco includono solo quelle presenti nel blocco, e non quelle dei blocchi annidati; • 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; • 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?

  16. 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

  17. 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)

  18. { 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

  19. 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

  20. { 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

  21. problemi di scope statico • dove introdurre le dichiarazioni • qual è la visibilità delle variabili • definizioni ricorsive begin const pippo = valore; const valore = 0; end valore usato prima della definizione begin const valore = 1; procedure pluto begin const pippo = valore; const valore = 0; end end valore maschera la definizione esterna nella procedura

  22. type lista = ^elemento; type elemento = record informazione: intero; successivo: lista end type elemento; type lista = access elemento; type elemento is record informazione: intero; successivo: lista end errore: elemento è usato prima di essere definito; in Pascal si può fare, ma solo con i puntatori in ADA si usano dichiarazioni incomplete

  23. procedure pippo (A: integer); forward; procedure pluto (B: integer) begin pippo(3); end procedure pippo; begin pluto(4) end in Pascal si usano definizioni incomplete per le funzioni mutuamente ricorsive; in C si può fare liberamente