Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
(*This allows the current file to access the env file*)
use "env.sml";
Control.Print.printDepth := 32;
exception NotAnInt;
exception InvalidCondition;
exception NotAFunction;
datatype Expr = Bool of bool
| Int of int
| Add of Expr * Expr
| If of Expr * Expr * Expr
| Ident of string
| Let of (string * Expr) list * Expr
| Def of string * Expr
| Fun of Expr * Expr (*First Expr will be Ident*)
| App of Expr * Expr
| Seq of Expr list
| Disp of Expr
| Clos of Expr * Expr * Expr Env
| String of string
| Nothing;
(*This function converts an Expr to a string for ease of printing*)
fun e2s (Bool b) = "Bool(" ^ Bool.toString b ^ ")"
| e2s (Int i) = "Int(" ^ Int.toString i ^ ")"
| e2s (Add (x, y)) = "Add(" ^ (e2s x) ^ "," ^ (e2s y) ^ ")"
| e2s (If (cond, conseq, alt)) = "If(" ^ (e2s cond) ^ "," ^ (e2s conseq) ^ "," ^ (e2s alt) ^ ")"
| e2s (Ident s) = "Ident(" ^ s ^ ")"
| e2s (Let (l, e)) = "Let([" ^ (e2s_let_helper l) ^ "]," ^ (e2s e) ^ ")"
| e2s (Def (s, e)) = "Def(" ^ s ^ "," ^ (e2s e) ^ ")"
| e2s (Fun (x, y)) = "Fun(" ^ (e2s x) ^ "," ^ (e2s y) ^ ")"
| e2s (App (x, y)) = "App(" ^ (e2s x) ^ "," ^ (e2s y) ^ ")"
| e2s (Seq s) = "Seq[" ^ (e2s_seq_helper s) ^ "]"
| e2s (Disp d) = "Disp(" ^ (e2s d) ^ ")"
| e2s (Clos (x, y, _)) = "Clos(" ^ (e2s x) ^ "," ^ (e2s y) ^ ")"
| e2s (String s) = "String(" ^ s ^ ")"
| e2s (Nothing) = "Nothing"
and e2s_let_helper ((s, e)::[]) = "(" ^ s ^ "," ^ (e2s e) ^ ")"
| e2s_let_helper ((s, e)::t) = "(" ^ s ^ "," ^ (e2s e) ^ ")," ^ (e2s_let_helper t)
| e2s_let_helper [] = ""
and e2s_seq_helper (h::[]) = (e2s h)
| e2s_seq_helper (h::t) = (e2s h) ^ "," ^ (e2s_seq_helper t)
| e2s_seq_helper [] = "";
(*This function evaluates the given Expr in the given environment and returns both the expr and the env*)
fun eval env (Ident i) = (env, env_lookup env i)
| eval env (Add (x, y)) = let val (env1, val1) = eval env x;
val (env2, val2) = eval env1 y;
in
eval_add_helper env2 (val1, val2)
end
| eval env (If (cond, conseq, alt)) = let val (env1, newVar) = eval env cond
in
if (eval_if_helper newVar)
then (eval env1 conseq)
else
(eval env1 alt)
end
| eval env (Let (l, e)) = (env, #2 ((eval (eval_let_helper env l) e)))
| eval env (Seq s) = eval_seq_helper env s
| eval env (Def (s, e)) = let val (env1, newVar) = eval env e;
in (env_bind env1 s newVar, Nothing)
end
| eval env (Disp d) = let val (env1, newVar) = eval env d;
val _ = print (e2s newVar ^ "\n");
in (env1, newVar)
end
| eval env (Fun (x, y)) = (env, Clos(x, y, env))
| eval env (App (x, y)) = let val (env1, param) = eval env y
val (env2, f) = eval env x
in
eval_app_helper env1 (f, param)
end
| eval env expr = (env, expr) (*constants evaluate to themselves*)
(*This helper function adds the two operands if both are Ints. Otherwise it raises an exception*)
and eval_add_helper env (Int a, Int b) = (env, Int(a + b))
| eval_add_helper env (_, _) = raise NotAnInt
(*This helper function raises an exception if the given condition is not a Bool*)
and eval_if_helper (Bool b) = b
| eval_if_helper (_) = raise InvalidCondition
(*This helper function binds the variables in the list to the current env*)
and eval_let_helper env (h::[]) = #1(eval env (Def h))
| eval_let_helper env (h::t) = let val (env1, newVal) = eval env (Def h);
in
#1(eval (eval_let_helper env1 t) newVal)
end
| eval_let_helper env [] = env
(*This helper function evaluates each Expr in the list and returns the value of the last one*)
and eval_seq_helper env (h::[]) = eval env h
| eval_seq_helper env (h::t) = let val (env1, _) = eval env h;
in eval_seq_helper env1 t
end
| eval_seq_helper env [] = (env, Nothing)
(*This helper function ensures that App is being applied to a Fun*)
and eval_app_helper env ((Clos (Ident a, b, _)), y) = eval env (Let ([(a, y)], b))
| eval_app_helper env (_, _) = raise NotAFunction;