Created
August 23, 2020 12:50
-
-
Save FedericoPonzi/8896e71e6eec81f8103f538313ad1db2 to your computer and use it in GitHub Desktop.
Project for my Programming languages exam, an interpreter for a programming language called ffun.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
datatype ffun = const of int (* Possiamo trovare delle costanti intere *) | |
| plus of (ffun*ffun) (* Addizione *) | |
| var of string (* Variabili di tipo stringhe *) | |
| llet of (string*ffun*ffun) (* La funzione let, che prende una variabile stringa, e due oggetti di tipo ffun *) | |
| fffun of (string*ffun) (* Una funzione *) | |
| ycombinator of (ffun) | |
| appl of (ffun*ffun) | |
| ifelse of (ffun*ffun*ffun) | |
| minus of ffun | |
| prod of (ffun*ffun); | |
datatype env = emptyenv | cons of env*string*ffun; | |
(* | |
* Questo nuovo datatype viene usato come valore di ritorno della funzione di valutazione eval | |
* Possiamo avere degli interi (di tipo Int), o delle semi-valutazioni di funzioni formate da: il nome della variabile in input, il corpo della funzione e l'ambiente in cui valutarla. | |
*) | |
datatype valore = Int of int | funval of (string*ffun*env); | |
(* | |
* Definizione delle eccezioni: | |
*) | |
exception envexception; (* Stiamo cercando di valutare qualcosa in un ambiente vuoto *) | |
exception notintexception; (* Stiamo cercando di usare una funzione semivalutata (vedi datatype valore) al posto di un intero *) | |
exception notcorrectparameter; (* Stiamo cercando di usare l' applicazione di funzioni su un parametro di tipo costante *) | |
fun tofun(funval(s,f,e)) = f; | |
fun tostring(funval(s,f,e)) = s; | |
fun lookup (emptyenv, s) = raise envexception | |
| lookup(cons(e,x,v),s) = if (s=x) then (e,v) else lookup(e,s); | |
(* | |
* Estrattore di Interi: Se riceve in input un oggetto di tipo Int (wrapper del tipo int) allora restituisce l' intero contenuto in esso | |
* Se però cerchiamo di estrarre un intero da funval, allora viene lanciata una eccezione. | |
* Questa funzione ci serve perchè nell' eval l' operazione di somma ha senso solo se stiamo usando degli interi. | |
*) | |
fun toint (Int(x)) = x | | |
toint (funval(s,f,e)) = (print s; raise notintexception); | |
exception notfunexception; | |
(* | |
Si può fare: | |
appl(const(2), const(2))? | |
se no: | |
eval(e, appl(x,l)) = | |
*) | |
fun eval (e,const(x)) = Int(x) | |
(* Se è di tipo costante, ne restituisce il valore *) | |
| eval (e,var(x)) = eval(lookup(e,x)) | |
(* Se è una variabile, restituisce tramite la funzione Lookup il valore ad essa associata *) | |
| eval (e,plus(x,y)) = Int((toint(eval(e,x)))+(toint((eval(e,y))))) | |
| eval (e,llet(s,m,n)) = eval(cons(e,s,m),n) | |
(* | |
* Il let consiste in un' assegnamento di variabile e di una funzione. Aumentiamo l' ambiente con l' associazione | |
* fra variabile e valore e valutiamo usando eval la funzione N.eval (e, ycombinator(h) )= eval(e,appl(appl(fffun("f", fffun("x",appl(var("f"),fffun("v",appl(appl(var("x"),var("x")),var("v")))))), fffun("x",appl(var("f"),fffun("v",appl(appl(var("x"),var("x")),var("v")))))), h)) | |
*) | |
| eval (e, fffun(s, f)) = funval(s, f,cons(e,s,f)) | |
(* | |
| eval (e, ycombinator(h ))= eval(e, appl(fffun("f",appl(fffun("x",appl(var("f"),fffun("v",appl(appl(var("x"),var("x")),var("v"))))),fffun("x",appl(var("f"),fffun("v",appl(appl(var("x"),var("x")),var("v"))))))),h)) | |
appl(fffun("h",fffun("F",appl(var("F" *) | |
| eval (e, ycombinator(h)) = eval(e,appl( | |
fffun("x",appl(h,appl(var("x"),var("x")))), | |
fffun("x",appl(h,appl(var("x"),var("x")))) | |
)) | |
| eval (e, appl(fffun(s,m), n)) = eval(cons(e, s, n), m) | |
| eval (e, appl(var(m), n)) = eval(e, appl(tofun(eval(e,var(m))),n)) | |
| eval (e, appl(const(x), n)) = eval(e,const(x)) | |
|eval (e, appl(appl(f,n), appl(m,p))) = | |
eval(cons(e, tostring(eval(e,appl(f,n))), tofun(eval(e,appl(m,p)))), tofun(eval(e,appl(f,n)))) | |
(* se il primo paraemtro è una appl *) | |
|eval (e, ifelse(b,iffun,elsefun)) = if (toint(eval(e,b))=0) then eval (e, iffun) else eval(e,elsefun) | |
|eval (e, appl(appl(f,l), const(n))) = eval(cons(e, tostring(eval(e, appl(f,l))), const(n)), tofun(eval(e,appl(f,l)))) | |
|eval (e, appl(appl(f,l), fffun(s,n)))= eval(cons(e, tostring(eval(e,appl(f,l))), tofun(eval(e,n))), tofun(eval(e,appl(f,l)))) | |
|eval (e, appl(appl(f,l), var(n))) = eval(cons(e, tostring(eval(e, appl(f,l))), var(n)), tofun(eval(e,appl(f,l)))) | |
|eval (e, appl(ifelse(var(x),iffun,elsefun),n)) = eval(cons(e,x,n),ifelse(var(x),iffun,elsefun)) | |
|eval (e, appl(ycombinator(fffun(s,h)), n)) = eval(cons(e,s,h), appl(tofun(eval(e,ycombinator(fffun(s,h)))),n)) | |
|eval (e, appl(x,y)) = raise notcorrectparameter | |
|eval(e, minus(n)) = Int(toint(eval(e,n))-1) | |
|eval(e,prod(n,m)) = Int((toint(eval(e,n)))*(toint(eval(e,m)))); | |
eval(emptyenv, ycombinator(fffun("ci", fffun("di", plus(var("di"), const(1)))))); | |
eval(emptyenv, ycombinator(fffun("n", fffun("x", fffun("y", var("n")))))); | |
(*tofun(eval(emptyenv,ycombinator(fffun("b",fffun("c",appl(var("c"),const(1)))))));*) | |
val fact = fffun("fact", fffun("n", ifelse(var("n"), const(1),(prod(var("n"), appl(var("fact"), (minus(var("n"))))))))); | |
val fact2 = fffun("fact", fffun("n", ifelse(var("n"), const(1),var("n")))); | |
eval(emptyenv,appl(ycombinator(fact2),const(3))); | |
ycombinator fact; | |
eval(emptyenv, appl(ycombinator fact, const(11))); | |
(cons(emptyenv, "fact", fffun("n", ifelse(var("n"), const(1),(prod(var("n"), appl(var("n"), (minus(var("n"))))))))), appl(fffun("n", ifelse(var("n"), const(1),appl(( var("fact")),var("n")))) ,const(3))); | |
eval(cons(emptyenv, "fact", fffun("n", ifelse(var("n"), const(1), var("fact")))), appl(fffun("n", ifelse(var("n"), const(1),appl(( var("fact")),minus(const(2))))) ,const(3))); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment