Skip to content

Instantly share code, notes, and snippets.

@FedericoPonzi
Created August 23, 2020 12:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FedericoPonzi/8896e71e6eec81f8103f538313ad1db2 to your computer and use it in GitHub Desktop.
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.
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