open MiniML (* let failwith s = raise (Failure s) *) let rec get id = function [] -> failwith ("Unbound value " ^ id) | (i, v) :: ls -> if i = id then (match !v with Undefined -> failwith "undefined value used inside letrec bindings" | x -> x) else get id ls let get_int = function Int(v1) -> v1 | _ -> failwith "not an int value" let get_bool = function Bool(v1) -> v1 | _ -> failwith "not a bool value" exception MatchFailed let match_pattern (pat : pattern) (v : mlvalue) = (failwith "unimplemented yet (practice No. 2)" : (string * mlvalue ref) list) (* val eval : env * expr -> mlvalue *) let rec eval env = function Const(v) -> v | Var(id) -> get id env | Plus(e1, e2) -> Int(get_int (eval env e1) + get_int (eval env e2)) | Minus(e1, e2) -> Int(get_int (eval env e1) - get_int (eval env e2)) | Times(e1, e2) -> Int(get_int (eval env e1) * get_int (eval env e2)) | Div(e1, e2) -> Int(get_int (eval env e1) / get_int (eval env e2)) | Equal(e1, e2) -> Bool((eval env e1) = (eval env e2)) | ConsExp(e1, e2) -> Cons(eval env e1, eval env e2) | PairExp(e1, e2) -> Pair(eval env e1, eval env e2) | IfExp(ec, e1, e2) -> if get_bool (eval env ec) then eval env e1 else eval env e2 | LambdaExp [p1, e] -> Closure([p1, e], env) | LambdaExp ps -> (* practice No. 3B *) Closure(ps, env) | App(e1, e2) -> begin match eval env e1 with Closure([IdentPtn arg, body], i_env) -> failwith "unimplemented yet (practice No. 1)" | Closure(pats, i_env) -> failwith "unimplemented yet (practice No. 3B)" | _ -> failwith "applying value to non-closure" end | MatchExp(exp,pats) -> failwith "unimplemented yet (practice No. 2)" | LetExp([IdentPtn id, e1], e2) -> let v1 = eval env e1 in eval ((id, ref v1) :: env) e2 | LetExp(ptns, e2) -> failwith "unimplemented yet (practice No. 3A)" | LetRecExp([IdentPtn id, e1], e2) -> failwith "unimplemented yet (practice No. 1)" | LetRecExp(ptns, e2) -> failwith "unimplemented yet (practice No. 3A)" | TopLetExp(_) | TopLetRecExp(_) -> failwith "top level definition is not supported"