Programmazione II Esercitazione dell'11 marzo 2014 ================================ 1) Verificare di aver istallato correttamente il compilatore Java, compilando ed eseguendo (con "javac" e "java") un semplice programma, per esempio Benvenuto.java. 2) Esaminare il file "expr1.ml" contente la definizione di tipo "expr" e una funzione di valutazione "eval", nonche' alcuni esempi di espressioni e di valutazione. Compilare il file con "ocamlc" e eseguirlo con "ocamlrun a.out" osservando il risultato. Si possono anche valutare parti del file nell'interprete OCaml. 3) Il file "Test1.java" contiene parte della "traduzione" di "expr1.ml" in Java, secondo la metodologia descritta nelle pagine 6 e 7 dei lucidi http://www.di.unipi.it/~andrea/Didattica/PR2-B-14/PR2B-2014-06-004-OCAMLvsJAVA.pdf In particolare: - il tipo "expr" e' realizzato con l'interfaccia Expr - i costruttori CstI e Prim sono realizzati con corrispondenti classi che implementano Expr - la valutazione delle espressioni avviene con il metodo "int eval()", con firma in Expr e implementazione nelle classi che la implementano. - la creazione di espressioni e la loro stampa sono nel metodo main, nella classe Test1 L'intero file puo' essere compilato con "javac Test1.java" e eseguito con "java Test1". Nota: e' possibile mettere piu' classi e interfacce in un file Java, purche' non siano dichiarate pubbliche. 4) TODO: 4.1) completare l'implementazione della classe Prim in modo che togliendo tutti commenti dal corpo del metodo Test1.main il file compili e l'esecuzione di "java Test1" stampi esattamente lo stesso output ottenuto con "ocamlrun a.out". Completato l'esercizio, copiare Test1.java in Test.java, cambiando il nome della classe principale (da Test1 a Test), e usare il file Test.java in quanto segue. 4.2) Si consideri la seguente estensione del tipo OCaml expr, che definisce espressioni con variabili: type expr = | CstI of int (* costante intera *) | Var of string (* variabile *) | Prim of string * expr * expr;; (* operatore applicato a due argomenti *) Per valutare un'espressione di questo tipo, e' necessario usare un "ambiente" che leghi i nomi di variabile a corrispondenti valori. Sia definito il tipo ricorsivo type env = | Empty | Bind of string * int * env;; e la seguente funzione, che restituisce il valore associato a una variabile: let rec lookup env name = match env with | Empty -> failwith (name ^ " not found") | Bind (w, n, env1) -> if name = w then n else lookup env1 name;; 4.3) Tradurre in java il tipo "env" e la funzione "lookup", sulla falsariga della traduzione da expr1.ml a Test1.ml. Aggiungere interfaccia e classi richieste in Test.java. 4.4) Definire (sempre in Test.java) la classe Var che implementa Expr e rappresenta una espressione del tipo "Var x", con x stringa 4.5) Poiche' le espressioni con variabili possono essere valutate solo in presenza di un ambiente, arricchire l'interfaccia Expr con il metodo public int eval(Env env); Di conseguenza tutte le classi che implementano Expr dovranno essere modificate per implementare questo metodo, ottenendo la traduzione in Java della seguente funzione OCaml: let rec eval e env : int = match e with | CstI i -> i | Var x -> lookup env x | Prim("+", e1, e2) -> eval e1 env + eval e2 env | Prim("*", e1, e2) -> eval e1 env * eval e2 env | Prim("-", e1, e2) -> eval e1 env - eval e2 env | Prim _ -> failwith "unknown primitive";; 4.6) Testare progressivamente le funzionalita' che vengono aggiunte al programma java creando opportune espressioni e valutandole nel metodo main 4.7) Rendere robusto il codice: - aggiungere controlli nei costruttori in modo da evitare di costruire espressioni non significative (come 'new Prim(null, 3, 4)') - gestire nel main eventuali eccezioni lanciate dai metodi - analizzare l'applicazione, e decidere se e' il caso di sostituire eccezioni standard con nuove eccezioni da definire. ==============================