-calcolo Vogliamo studiare le problematiche relative al meccanismo di chiamata di funzione (eg differenze fra binding statico e dinamico) in isolamento.

Slides:



Advertisements
Presentazioni simili
Introduzione al linguaggio C++
Advertisements

Definitezza Vogliamo poter richiedere la “definitezza” delle funzioni
Sistemi dinamici discreti e computabilità intrinseca
23/11/06Dino Puller1 Analisi statica in tempo reale con domini numerici Facoltà di scienze MM.FF.NN. Università degli studi di Verona.
IL MODELLO CLIENTE / SERVITORE. Servitore: un qualunque ente computazionale capace di nascondere la propria organizzazione interna presentando ai clienti.
Linguaggi algoritmici
Sommario Nelle lezioni precedenti abbiamo introdotto tutti gli elementi che formano un particolare tipo di linguaggio logico, denominato linguaggio predicativo.
Sintassi (prima parte)
Linguaggi di programmazione
Algebra parziale con predicati
Esercitazione guidata 1
Semantica di linguaggi di programmazione Ne esistono differenti stili a seconda di paradigma di programmazione uso (validazione, prototyping, verifica.
SOS a piccoli passi Invece di semplificare sempre in configurazioni finali, fattorizziamo in passi più piccoli (da cui il nome). In questo modo la non.
Paradigma Funzionale Paradigma Imperativo: Programma = transizione di stato Paradigma Funzionale: Programma = valutazione di un’espressione La maggior.
Linguaggi a memoria condivisa Lidea è di aggiungere ad un linguaggio imperativo dei costrutti per rappresentare lesecuzione parallela di statements. Supponiamo.
Paradigma Funzionale Paradigma Imperativo: Programma = transizione di stato Paradigma Funzionale: Programma = valutazione di unespressione La maggior parte.
Liste di Interi Esercitazione. Liste Concatenate Tipo di dato utile per memorizzare sequenze di elementi di dimensioni variabile Definizione tipicamente.
Metodologie di Programmazione = decomposizione basata su astrazioni
Lez. 41 Universita' di Ferrara Facolta' di Scienze Matematiche, Fisiche e Naturali Laurea Specialistica in Informatica Algoritmi Avanzati Programmazione.
Fondamenti di Informatica I a.a Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.
Il ragionamento classico
Reaching Definitions. Tino CortesiTecniche di Analisi di Programmi 2 Reaching definitions Dato un punto del programma, quali sono i comandi di assegnamento.
Interpretazione Astratta
Semantica Denotazionale
Semantiche dei linguaggi di programmazione
Iterazione enumerativa (for)
CORSO DI PROGRAMMAZIONE II Introduzione alla ricorsione
Algoritmi e Strutture Dati
Fondamenti di Informatica I a.a Il linguaggio C Il controllo di flusso La selezione condizionale Listruzione switch I cicli Le istruzioni break,
Semantica denotazionale algebrica di LW Idea intuitiva: i valori che vogliamo denotare sono: gli statements sono funzioni di trasformazioni di stato (interno)
Semantica Operazionale Strutturata
Semantica di Tarski.
Semantica per formule di un linguaggio proposizionale p.9 della dispensa.
mosaic manipola oggetti primitivi (ruota e unisci) regole:
Intelligenza Artificiale
Lezione 2 Programmare in ASP
AN FI Un denominatoe comune Comandi u notazioni che esprimono azioni che, una volta eseguite, comportano una modifica permanente dello stato interno.
FUNZIONI: IL MODELLO APPLICATIVO 1) Valutazione, nellenvironment corrente, del simbolo che denota il nome della funzione; 2) Valutazione, nellenvironment.
INSIEMI NUMERABILI L’analisi matematica introduce il concetto di insieme numerabile come insieme i cui elementi possono essere “contati” ossia che possiede.
LINGUAGGI DI PROGRAMMAZIONE
AN FI Un denominatoe comune Lo stile funzionale Concetti fondamentali.
FUNZIONI... Una funzione permette di dare un nome a una espressione rendendola parametrica float f(){ return * sin(0.75); } float f1(int x) { return.
Studio funzioni Premesse Campo esistenza Derivate Limiti Definizione di funzione Considerazioni preliminari Funzioni crescenti, decrescenti Massimi,
1 Programmazione = decomposizione basata su astrazioni (con riferimento a Java)
Pierdaniele Giaretta Linguaggio della logica predicativa
Pierdaniele Giaretta Linguaggio della logica predicativa
Complessità di un algoritmo
Sessione live Testing. Esercizio Quesito 1 Soluzione 1.
alberi completamente sbilanciati
Introduzione a Javascript
La ricorsione.
Variabili Numeriche –Interi (byte, short, int, long): complemento a 2 –A virgola mobile (float, double): IEEE 745 Alfanumeriche –Carattere (char): Unicode.
Didattica e Fondamenti degli Algoritmi e della Calcolabilità Terza giornata: principali classi di complessità computazionale dei problemi Guido Proietti.
Allievi Elettrici - AA Le funzioni ricorsive in C
1 Interpretazione astratta: un approccio sistematico all’analisi statica.
Nucleo di Java: Struttura e Semantica Espressioni Assegnamento Controllo di sequenza Dichiarazioni.
Semantica dinamica Vogliamo definire una funzione che associ ad ogni termine corretto del mio linguaggio di programmazione un valore. Questa associazione.
Lo stato  I domini della semantica restano invariati: Ide, Val (Int  { ,  }) Loc (locazioni di memoria), FunctDecl. ma definiamo 2 funzioni: Loc :
Grammatiche Grammatiche libere da contesto Grammatiche regolari
Grammatiche non contestuali (1)
Elementi di semantica denotazionale ed operazionale
Flusso di Costo Minimo Applicazione di algoritmi: Cammini Minimi Successivi (SSP) Esercizio 1 Sia data la seguente rete di flusso, in cui i valori riportati.
Corso integrato di Matematica, Informatica e Statistica Informatica di base Linea 1 Daniela Besozzi Dipartimento di Informatica e Comunicazione Università.
Integrali definiti I parte
6. LIMITI Definizione - Funzioni continue - Calcolo dei limiti
Analisi matematica Introduzione ai limiti
Parsing ricorsivo discendente Il parsing ricorsivo discendente (recursive descent parsing) è un metodo di tipo top-down che può essere facilmente codificato.
La scrittura decimale Quando un numero è scritto in forma decimale, vi è un numero finito di cifre dopo la virgola. Ma sappiamo che ci sono divisioni “che.
Logica Lezione 8, DISTRIBUIRE COMPITO 1.
Logica Lez. 5, Varzi su affermazione del conseguente Malgrado alcuni esempi di questa forma siano argomentazioni valide, altri non lo sono.
Transcript della presentazione:

-calcolo Vogliamo studiare le problematiche relative al meccanismo di chiamata di funzione (eg differenze fra binding statico e dinamico) in isolamento rispetto alle problematiche dovute ad altri aspetti (eg lo stato, introdotto per gestire aspetti imperativi). Vogliamo quindi individuare un linguaggio quanto più semplice possibile in cui siano presenti solo meccanismi per Astrazione, cioè definizione di funzione Applicazione, cioè uso di funzioni Il linguaggio più semplice possibile è il -calcolo, introdotto negli anni 30 e ancora oggetto di studio. Deve il nome al fatto che lastrazione si denota in esso con la lettera

Sintassi Fissato un insieme X di simboli per le variabili del linguaggio, i suoi termini sono definiti induttivamente da: x L x X x.e L e L x X e 1 e 2 ) L e 2 Le 1 L Base le variabili sono espressioni Astrazione rappresenta la funzione con parametro x e corpo e Applicazione rappresenta lapplicazione della funzione e 1 allargomento e 2 Rispetto ai linguaggi visti finora è estremamente semplificato, non solo perché è più conciso, ma soprattutto perché mancano (gli elementi sintattici corrispondenti a) dei concetti, ad esempio non ci sono definizioni, quindi non avremo bisogno di ambienti né di semantica statica Esercizio proposto: dare una grammatica context free che descriva lo stesso linguaggio

Semantica (SOS): -regola Lidea chiave è la corrispondenza fra applicazione ed espansione: ( x.e a) e[a/x] dove e[a/x] deve essere definito (a parte) in modo da corrispondere alla sostituzione di a (parametro attuale) al posto di x (parametro formale) in e (corpo della funzione). Nel definire la sostituzione bisogna fare attenzione a due problemi Vogliamo sostituire solo le occorrenze di x che corrispondono (sono legate da) al parametro formale ( x). Ad esempio se e= ( y. x.(x y) x) solo quella rossa, cioè vanno sostituite solo le occorrenze libere. Nelleseguire la sostituzione non vogliamo che variabili libere del parametro attuale siano catturate da qualche occorrenza legante ( x). Ad esempio effettuando una sostituzione brutale in y.(x y) [y/x] si ottiene y. y y) in cui la y globale è stata catturata dal y (questo corrisponderebbe a binding dinamico).

x.… x.... Uso di una variabile avulsa dal contesto. Si riconduce alla regola di introduzione delle variabili come espressioni Occorrenze libere, legate e leganti (riassunto di cose ben note!) x Libera x Legantex Legata Analisi Logica LP -calcolo ln(x)+3 p(x) if (x){f(2)} else {f(7)} (x x) f(x)=… …dx void g(bool x){…} x.... f(x)= ln(x)+3 x. p(x) void g(bool x){ if (x){f(2)} else {f(7)} } x. (x x) Individua una variabile come buco di un contesto Uso di una variabile in un contesto in cui la stessa variabile rappresenta il buco

Variabili libere (altre cose ben note) Vogliamo definire le variabili libere in unespressione del -calcolo, analogamente a quanto si fa in logica, come linsieme delle variabili per cui ce almeno unoccorrenza libera nellespressione (in (x x.x) la x compare, da sinistra verso destra, come libera, legante e legata) Lo facciamo per induzione, seguendo le 3 regole che descrivono le espressioni (termini) del -calcolo FV(x)={x} x X FV( x.e )=A-{x} FV(e)=A FV( e 1 e 2 ))=A 1 A 2 FV( e 1 )=A 1 FV( e 2 )=A 2

Definizione di sostituzione x[a/x]=a ogni occorrenza libera va sostituita le altre variabili restano immutate y[a/x]=y xy le occorrenze legate restano immutate x.e[a/x]= x.e le altre variabili legate restano immutate y.e[a/x]= y.e e[a/x]= e xy y FV(a) facendo attenzione a non legare eventuali variabili libere lapplicazione è trasparente (e 1 e 2 )[a/x]=(e 1 e 2 ) e 1 [a/x] = e 1 e 2 [a/x] = e 2 y.(x x.(x y))[(t w)/x]= y.((x x.(x y)) [(t w)/x]) = y. ((x[(t w)/x]) ( x.(x y)[(t w)/x]) )= y. (((t w))( x.(x y)))

…e se y FV(a), come si fa a sostituire a al posto di x? y. (y x)[y/x]=? Certamente non a y. (y y) anzi con le regole attuali non si riduce a nessun -termine. Questo non è sensato, perché la scelta del nome di una variabile locale, la y, influenza la possibilità di applicazione della funzione x. y. (y x), di cui questo termine è il corpo, a y. Ma i nomi delle variabili locali non dovrebbero essere rilevanti (neppure visibili allesterno in altri linguaggi). Bisogna codificare nel nostro formalismo questo fatto, cioè che y.(y x) e z.(z x) sono per noi la stessa cosa (si noti che z.(z x)[y/x]= z.(z y)). Questo può essere fatto o localmente alla definizione di sostituzione -regola y.e[a/x]= y.e e[a/x]= e xy y FV(a) y.e[a/x]= w.e[a/x] e[w/y]= e y FV(a) xy w FV(a) xw Questa regola rende non deterministico il calcolo di e[a/x] (perché posso scegliere vari nomi nuovi in caso di collisione) o, meglio, lasciare la sostituzione così comè e aggiungere una regola di riscrittura generale (che prende il nome di -regola) x.e y.e[y/x] y FV(e) Questa regola introduce catene infinite di riscrittura di - termini in cui si continuano a ridenominare variabili locali, per cui non si tratta di vere semplificazioni

SOS completa ( x.e a) e[a/x] Due regole di calcolo, che catturano il significato di applicazione funzionale: Più regole di chiusura contestuale, che stabiliscono le strategie di valutazione. x.e x. e e e 1 e 2 ) e 1 e 2 ) e 2 e 1 e 2 ) e 1 e 2 ) e 1 -regola che stabilisce che lapplicazione corrisponde alla sostituzione intelligente x.e y.e[y/x] y FV(e) -regola che stabilisce che i nomi delle variabili locali sono irrilevanti Ad esempio la più liberale possibile:

Utilità del -calcolo La sua estrema semplicità permette di mettere bene a fuoco alcune problematiche: Si capisce bene come sia possibile avere per uno stesso termine due catene di riscrittura, una delle quali finita e laltra no : ( x.t ( y.(y y) y.(y y))) si può riscrivere in t usando la -regola sullapplicazione più esterna, ma può anche essere origine di una riscrittura infinita se si espande largomento ( y.(y y) y.(y y)) usando su di esso la -regola La definizione di sostituzione decide se il binding è statico (come lo abbiamo fatto) o dinamico (se si toglie la condizione a lato in rosso dellultima regola). Aggiungendo condizioni alla -regola se ne può forzare lapplicazione solo ai casi in cui largomento sia già stato valutato, per ottenere la semantica di call-by-value (quella standard è la call- by-need) Provare la confluenza del sistema dato è (stato fatto, quindi è) fattibile. Non ha però senso imparare a programmare in -calcolo

Potenza del -calcolo Per essere semplice è semplice, ma ci si può fare qualcosa? Incredibile ma vero: è un linguaggio universale Si può codificare (in vari modi) un operatore di iterazione (punto fisso): f.( y.((f (y y)) (f (y y))) Si possono codificare in esso valori base: n diventa x. y.((...((x x) x)...x) y) Ad esempio la scelta condizionale diventa c. r 1. r 2 ((c r 1 ) r 2 ) Si possono descrivere funzioni parziali: x. (x x) Usando il currying si possono definire (elementi isomorfi a) funzioni di più variabili n volte true diventa x. y.x e false diventa x. y.y Quindi si presta ad analizzare varie problematiche.

Semantica denotazionale (?) Per poter dare una semantica denotazionale del -calcolo dovremmo anzitutto definire un insieme (dominio) di interpretazione D. Intuitivamente gli elementi rappresentati dai -termini sono funzioni, quindi D deve essere della forma [ P ]. Siccome si possono applicare a se stesse, = D e siccome il risultato dellapplicazione è a sua volta accettabile come argomento = D. Perciò D = [D P D], ma questo è possibile? La risposta è affermativa, ma la dimostrazione non è banale. Il punto cruciale è che si può dimostrare che la funzione Fun che associa un insieme X allinsieme [X P X] ammette un (minimo) punto fisso, cioè esiste un insieme D tale che D = Fun(D) (ed è incluso in ogni punto fisso Y, cioè se Y=Fun(Y), allora D Y).

Punto fisso ed induzione Fino ad ora non abbiamo avuto bisogno della teoria del punto fisso, perché tutti i problemi tecnici solitamente risolti con essa (eg semantica di iterazione e ricorsione) li abbiamo risolti usando linduzione. Cerchiamo di capire perché qui fallisce. Nel caso di un linguaggio applicativo tipato, come LF, i tipi e la loro semantica sono definiti induttivamente a partire dai tipi base grazie ad una regola per i tipi funzionali. int Quindi ad esempio, usando una notazione ad albero per rappresentare i tipi funzionali, (int (int int)) int è Analogamente linterpretazione semantica avrà lo stesso albero, con sulle foglie gli insiemi corrispondenti In generale, i tipi funzionali sono rappresentati da alberi binari con tutti i nodi intermedi etichettati da frecce e le foglie da tipi base. Proviamo la stessa tecnica, espandendo man mano i sotto- alberi da foglie etichettate con D ad alberelli per D D. D D DD DD DD DD... Si ottiene un albero binario infinito perfettamente bilanciato con tutti i nodi etichettati dalla freccia (e nessuna foglia). Rispetto alla definizione induttiva di albero binario, per ottenere anche quelli infiniti serve lanalogo di un passaggio al limite, ovvero il calcolo di un punto fisso (che è il limite in unopportuna teoria)