Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (*INTERPRETE DIOCAMEL BY LUIGGI FINALMENTE CHE WORKA YAHUUU*)
- (*Definisco cosa stracazzo è un identificatore*)
- type ide = string;;
- (*Definisco i tipi di tutte le espressioni usabili nel mio linguaggio MUAHAHAHAHA*)
- type exp =
- EInt of int |
- EBool of bool |
- EString of string |
- Den of ide |
- Addizione of exp * exp |
- Sottrazione of exp * exp |
- Moltiplicazione of exp * exp |
- Divisione of exp * exp |
- Quadrato of exp |
- Cubo of exp |
- Esp of exp * exp |
- Zero of exp |
- Equivalente of exp * exp |
- Maggiore of exp * exp |
- Minore of exp * exp |
- MaggioreUg of exp * exp |
- MinoreUg of exp * exp |
- Meno of exp |
- Not of exp |
- And of exp * exp |
- Or of exp * exp|
- Impl of exp * exp|
- Xor of exp * exp |
- Nand of exp * exp |
- IfThenElse of exp * exp * exp |
- Let of ide * exp * exp | (*ASSEGNAMENTO VARIABILE CON IL LET COME IN OCAMELL*)
- Fun of ide * exp | (*FUNZIONE ANONIMA CON UN PARAMETRO COME IN OCAMELL*)
- Apply of exp * exp | (*CHIAMATA DI FUNZIONE (LA FAMOSA FUNCALL DIOCAML)*)
- Letrec of ide * exp * exp;; (*CHIAMATA DI FUNZIONE RICORSIVA*)
- (*CREAZIONE DELL'AMBIENTE POLIMORFO (OVVERO L'AMBIENTE E' UNA FUNZIONE)*)
- type 't env = ide -> 't;;
- (*DEFINIZIONE DEI TIPI ESPRIMIBILI NEL MIO LINGUAGGIO*)
- type evT = Bool of bool | Int of int | Den of string | String of string | Unbound | Funval of efun | RecFunval of ide * efun and efun = ide * exp * evT env;;
- (*DEFINIZIONE DI AMBIENTE VUOTO*)
- let emptyenv = fun x -> Unbound;;
- (*FUNZIONE CHE CREA UNA NUOVA ASSOCIAZIONE NELL'AMBIENTE*)
- let applyenv (r : 't env) (i : ide) = r i;;
- (*FUNZIONE CHE ASSOCIA UN NUOVO VALORE A UN IDENTIFICATORE NELL'AMBIENTE SE ESISTE GIA', CHIAMA APPLYENV ALTRIMENTI (E QUINDI LO CREA)*)
- let bind (r : 't env) (i : ide) (v : 't) = fun x -> if (x = i) then v else applyenv r x;;
- (*RUN TIME SUPPORT*)
- (*FUNZIONE CHE MI CONTROLLA I TIPI SENNO' SONO CAZZOTTI IN FACCIA*)
- let typecheck (s : string) (e : evT) : bool =
- match s with
- "int" -> (match e with
- Int(_) -> true |
- (_) -> false) |
- "string" -> (match e with
- String(_) -> true |
- (_) -> false) |
- "bool" -> (match e with
- Bool(_) -> true |
- (_) -> false) |
- _ -> failwith("Errore, tipo non valido");;
- (*let stringa x = match x with
- Int a -> "Intero"
- | String a -> "Stringa"
- | Bool a -> "Booleano"
- | Unbound -> "Unbound ci scommetto 10 euro";;*)
- (*FUNZIONI AUSILIARIE DELLE OPERAZIONI DI BASE*)
- let add x y = if (typecheck "int" x && typecheck "int" y) then
- (match (x, y) with
- (Int(a),Int(b)) -> Int(a+b) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let sott x y = if (typecheck "int" x && typecheck "int" y) then
- (match (x, y) with
- (Int(a),Int(b)) -> Int(a-b) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let molt x y = if (typecheck "int" x && typecheck "int" y) then
- (match (x, y) with
- (Int(a),Int(b)) -> Int(a*b) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let div x y = if (typecheck "int" x && typecheck "int" y) then
- (match (x, y) with
- (Int(a),Int(b)) -> if (b != 0) then Int(a/b) else failwith("Errore divisione per zero") |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let quad x = if (typecheck "int" x) then
- (match x with
- Int(a) -> Int(a*a) |
- (_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let cub x = if (typecheck "int" x) then
- (match x with
- (Int(a)) -> Int(a*a*a) |
- (_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let rec pow x y = match (x,y) with
- (0,0) -> failwith("Che stracazzo volevi fare") |
- (0,_) -> 0 |
- (1,_) -> 1 |
- (_,0) -> 1 |
- (x,1) -> x |
- (x,y) -> x * pow x (y-1);;
- let espon x y = if (typecheck "int" x && typecheck "int" y) then
- (match (x, y) with
- (Int(a),Int(b)) -> Int(pow a b) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let iszero x = if (typecheck "int" x) then
- (match x with
- (Int(a)) -> if x = Int(0) then Bool(true) else Bool(false) |
- (_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let meno x = if (typecheck "int" x) then
- (match x with
- (Int(a)) -> Int(-a) |
- (_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let equiv x y = if (typecheck "int" x && typecheck "int" y) then
- (match (x, y) with
- (Int(a),Int(b)) -> Bool(a = b) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let magg x y = if (typecheck "int" x && typecheck "int" y) then
- (match (x, y) with
- (Int(a),Int(b)) -> Bool(a > b) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let minn x y = if (typecheck "int" x && typecheck "int" y) then
- (match (x, y) with
- (Int(a),Int(b)) -> Bool(a < b)|
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let maggu x y = if (typecheck "int" x && typecheck "int" y) then
- (match (x, y) with
- (Int(a),Int(b)) -> Bool(a >= b) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let minu x y = if (typecheck "int" x && typecheck "int" y) then
- (match (x, y) with
- (Int(a),Int(b)) -> Bool(a <= b) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let et x y = if (typecheck "bool" x && typecheck "bool" y) then
- (match (x, y) with
- (Bool(a),Bool(b)) -> Bool(a && b) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let oooh x y = if (typecheck "bool" x && typecheck "bool" y) then
- (match (x, y) with
- (Bool(a),Bool(b)) -> (Bool(a || b)) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let impl x y = if (typecheck "bool" x && typecheck "bool" y) then
- (match (x, y) with
- (Bool(a),Bool(b)) -> if (a && not(b)) then Bool(false) else Bool(true) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let nooh x = if (typecheck "bool" x) then
- (match x with
- Bool(a) -> Bool(not(a))
- | (_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let nand x y = if (typecheck "bool" x && typecheck "bool" y) then
- (match (x, y) with
- (Bool(a),Bool(b)) -> Bool((not(a)&¬(b)) || (not(a)&&b) || (a&¬(b))) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- let escorr x y = if (typecheck "bool" x && typecheck "bool" y) then
- (match (x, y) with
- (Bool(a),Bool(b)) -> Bool(not((a&&b) || (not(a)&¬(b)))) |
- (_,_) -> failwith("Match sbagliato"))
- else failwith("Errore di tipo");;
- (*CREAZIONE DEL FINALMENTE INTERPRETE*)
- let rec eval (x:exp) (r: evT env) : evT = match x with
- EInt n -> Int n |
- EBool n -> Bool n |
- EString n -> String n |
- Den n -> applyenv r n |
- Addizione (n,m) -> add(eval n r)(eval m r) |
- Sottrazione (n,m) -> sott(eval n r)(eval m r)|
- Moltiplicazione (n,m) -> molt(eval n r)(eval m r)|
- Divisione (n,m) -> div(eval n r)(eval m r)|
- Maggiore (n,m) -> magg(eval n r)(eval m r)|
- Minore (n,m) -> minn(eval n r)(eval m r)|
- MinoreUg (n,m) -> minu(eval n r)(eval m r)|
- MaggioreUg (n,m) -> maggu(eval n r)(eval m r)|
- Equivalente (n,m) -> equiv(eval n r)(eval m r)|
- Cubo n -> cub (eval n r)|
- Quadrato n -> quad (eval n r)|
- Esp (n,m) -> espon(eval n r)(eval m r)|
- Zero n -> meno (eval n r)|
- Meno n -> meno (eval n r)|
- Not n -> nooh (eval n r)|
- And (n,m) -> et(eval n r)(eval m r)|
- Or (n,m) -> oooh(eval n r)(eval m r)|
- Xor (n,m) -> escorr(eval n r)(eval m r)|
- Nand (n,m) -> nand(eval n r)(eval m r)|
- Impl (n,m) -> impl(eval n r)(eval m r)| (*QUA TI VOGLIO*)
- IfThenElse (cond,thn,els) -> let c = eval cond r in
- if c=Bool(true) then eval thn r else eval els r |
- Let (ide,e1,e2) -> eval e2 (bind r ide (eval e1 r))|
- Fun (nomePar,corpoFun) -> Funval (nomePar,corpoFun,r) (*Dichiarazione di funzione (un solo parametro)*)|
- Apply (ambFunDich,valParam) -> (*Devo dichiarare la chiusura della funzione*)
- let chiusura = (eval ambFunDich r) in
- (match chiusura with (*Guardo che tipo di funzione è, ricorsiva oppure normale*)
- Funval (paramName,corpFun,ambDich) ->
- eval corpFun (bind ambDich paramName (eval valParam r)) (*caso di funzione normale, valuto il corpo della funzione con il parametro attuale nell'ambiente di dichiarazione della fnzione stessa*)
- |RecFunval(nomeFun, (paramName, corpoFun, ambDich)) ->
- let actVal = (eval valParam r) in (*Valuto il parametro attuale in un ambiente intermedio, nel quale associo il risultato della chiamata precedente e che verrà valutato nella chiamata successiva (fino al caso base se esiste, ma è un problema di chi lo usa non mio)*)
- let ambFinale = (bind ambDich nomeFun chiusura) in
- let ambAct = (bind ambFinale paramName actVal) in
- eval corpoFun ambAct (* Valuto il corpo della funzione nell'ambiente finale, quello più aggiornato*)
- | _ -> failwith("Definizione che non è una funzione"))
- |Letrec(nome, defFun, corpoFun) -> (*Questo è il riferimento alla chiusura di una funzione che sarà ricorsiva, ha infatti il nome della funzione a cui punta, la definizione della funzione (Fun) e il corpo del "let", ovvero la chiamata della funzione con un parametro attuale*)
- (match defFun with
- Fun(nomePar, corp) -> let r1 = (bind r nome (RecFunval(nome, (nomePar, corp, r)))) in
- eval corpoFun r1
- | _ -> failwith("Definfunzione"));;
- (*TEST CASES*)
- (*Tutte le operazioni booleane YEY*)
- let funzTest = Fun("y",IfThenElse(MaggioreUg(EInt 5, EInt 6),Let("x",Addizione(EInt 0, EInt 3),Cubo(Den "x")),Quadrato(EInt 5)));;
- eval (Apply(funzTest, EInt 7)) emptyenv;;
- let gabri = Fun("x", Addizione(Den "x", EInt 1));;
- let chiamata = Apply(gabri,(Moltiplicazione(EInt 7, EInt 12)));;
- eval chiamata emptyenv;;
- let trasformaInAssoluto = Fun("x",IfThenElse(MaggioreUg(Den "x", EInt 0),Den "x", Meno(Den "x")));;
- let chiamata = Apply(trasformaInAssoluto, EInt (-3));;
- eval chiamata emptyenv;;
- (*Test dell'IF THEN ELSE (con addizione,sottrazione, maggioreuguale, quadrato, cubo, let funzionanti)*)
- let espr1 =
- IfThenElse(
- MaggioreUg(
- EInt 5, EInt 6
- ),
- Let(
- "x",
- Addizione(
- EInt 0,
- EInt 3
- ),
- Cubo(
- Den "x"
- )
- ),
- Quadrato(
- EInt 5
- )
- );;
- eval espr1 emptyenv;;
- let espr2 =
- IfThenElse(
- MaggioreUg(
- EInt 5, EInt 4
- ),
- Let(
- "x",
- Sottrazione(
- EInt 0,
- EInt 3
- ),
- Cubo(
- Den "x"
- )
- ),
- Quadrato(
- EInt 5
- )
- );;
- eval espr2 emptyenv;;
- (* Test dei booleani *)
- let espr3 =
- IfThenElse(
- Impl(
- Xor(
- Nand(
- Not(
- EBool true
- ),
- EBool false
- ),
- Or(
- And(
- EBool false,
- EBool false
- ),
- EBool true
- )
- ),
- EBool false
- ),
- EBool true,
- EBool false
- );;
- eval espr3 emptyenv;;
- let espr4 =
- IfThenElse(
- Impl(
- Xor(
- Nand(
- Not(
- EBool true
- ),
- EBool false
- ),
- Or(
- And(
- EBool false,
- EBool false
- ),
- EBool false
- )
- ),
- EBool false
- ),
- EBool true,
- EBool false
- );;
- eval espr4 emptyenv;;
- (*Test FUNZIONI (normali e ricorsive)*)
- (*Funzione che dato un parametro mi restituisce il suo doppio diviso per 4 (in intero)*)
- let corpoFunzioneAnon =
- Fun(
- "x",
- Divisione(
- Moltiplicazione(
- Den "x",
- EInt 2
- ),
- EInt 4
- )
- );;
- let chiamataFunzAnon =
- Apply(
- corpoFunzioneAnon,
- EInt 8
- );;
- eval chiamataFunzAnon emptyenv;;
- (*Funzione del fattoriale, dato un numero restituisce il suo fattoriale*)
- let corpF =
- Fun(
- "x",
- IfThenElse(
- Equivalente(
- Den "x",
- EInt 0
- ),
- EInt 1,
- Moltiplicazione(
- Den "x",
- Apply(
- Den "fact",
- Sottrazione(
- Den "x",
- EInt 1
- )
- )
- )
- )
- );;
- (*Applico il fattoriale di 5 *)
- let fattoriale =
- Letrec(
- "fact",
- corpF,
- Apply(
- Den "fact",
- EInt 5
- )
- );;
- eval fattoriale emptyenv;; (*EUREKA*)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement