diff --git a/src/chap4.ml b/src/chap4.ml new file mode 100644 index 0000000..76be122 --- /dev/null +++ b/src/chap4.ml @@ -0,0 +1,133 @@ +type info = { line : int; column : int } + +let dummyinfo = { line = 0; column = 0 } + +type term = + TmTrue of info + | TmFalse of info + | TmIf of info * term * term * term + | TmZero of info + | TmSucc of info * term + | TmPred of info * term + | TmIsZero of info * term + +let rec is_numeric_val t = + match t with + | TmZero(_) -> true + | TmSucc(_, t1) -> is_numeric_val t1 + | _ -> false + +let rec is_val t = + match t with + | TmTrue(_) -> true + | TmFalse(_) -> true + | t when is_numeric_val t -> true + | _ -> false + +exception NoRuleApplies + +let rec eval1 t = + match t with + | TmIf(_, TmTrue(_), t2, _) -> t2 + | TmIf(_, TmFalse(_), _, t3) -> t3 + | TmIf(fi, t1, t2, t3) -> + let t1' = eval1 t1 in + TmIf(fi, t1', t2, t3) + | TmSucc(fi, t1) -> + let t1' = eval1 t1 in + TmSucc(fi, t1') + | TmPred(_, TmZero(_)) -> TmZero(dummyinfo) + | TmPred(_, TmSucc(_, nv1)) when is_numeric_val nv1 -> nv1 + | TmPred(fi, t1) -> + let t1' = eval1 t1 in + TmPred(fi, t1') + | TmIsZero(_, TmZero(_)) -> TmTrue(dummyinfo) + | TmIsZero(_, TmSucc(_, nv1)) when is_numeric_val nv1 -> TmFalse(dummyinfo) + | TmIsZero(fi, t1) -> + let t1' = eval1 t1 in + TmIsZero(fi, t1') + | _ -> raise NoRuleApplies + +let rec eval t = + try + let t' = eval1 t in + eval t' + with NoRuleApplies -> t + +(* 4.2.2 *) +let rec eval_big_step t = + match t with + (* B-IfTrue *) + | TmIf(_, TmTrue(_), t2, _) -> eval_big_step t2 + + (* B-IfFalse *) + | TmIf(_, TmFalse(_), _, t3) -> eval_big_step t3 + + (* B-If *) + | TmIf(fi, t1, t2, t3) -> + let t1' = eval_big_step t1 in + eval_big_step (TmIf(fi, t1', t2, t3)) + + (* B-Succ *) + | TmSucc(fi, t1) -> + let t1' = eval_big_step t1 in + TmSucc(fi, t1') + + (* B-PredZero *) + | TmPred(_, TmZero(_)) -> TmZero(dummyinfo) + + (* B-PredSucc *) + | TmPred(_, TmSucc(_, nv1)) when is_numeric_val nv1 -> nv1 + + | TmPred(fi, t1) -> + let t1' = eval_big_step t1 in + eval_big_step (TmPred(fi, t1')) + + (* B-IsZeroZero *) + | TmIsZero(_, TmZero(_)) -> TmTrue(dummyinfo) + + (* B-IsZeroSucc *) + | TmIsZero(_, TmSucc(_, nv1)) when is_numeric_val nv1 -> TmFalse(dummyinfo) + + | TmIsZero(fi, t1) -> + let t1' = eval_big_step t1 in + eval_big_step (TmIsZero(fi, t1')) + + (* B-Value *) + | _ -> t + +let rec stringify_term t = + match t with + | TmTrue(_) -> "true" + | TmFalse(_) -> "false" + | TmIf(_, t1, t2, t3) -> + "if " ^ (stringify_term t1) ^ " then " ^ (stringify_term t2) ^ " else " ^ (stringify_term t3) + | TmZero(_) -> "0" + | TmSucc(_, t1) -> "succ(" ^ (stringify_term t1) ^ ")" + | TmPred(_, t1) -> "pred(" ^ (stringify_term t1) ^ ")" + | TmIsZero(_, t1) -> "iszero(" ^ (stringify_term t1) ^ ")" + +let () = + let t1 = TmIf(dummyinfo, TmTrue(dummyinfo), TmZero(dummyinfo), TmSucc(dummyinfo, TmZero(dummyinfo))) in + let t2 = TmIf(dummyinfo, TmFalse(dummyinfo), TmZero(dummyinfo), TmSucc(dummyinfo, TmZero(dummyinfo))) in + let t3 = TmIsZero(dummyinfo, TmZero(dummyinfo)) in + let t4 = TmIsZero(dummyinfo, TmSucc(dummyinfo, TmZero(dummyinfo))) in + let r1 = eval t1 in + let r1_big = eval_big_step t1 in + let r2 = eval t2 in + let r2_big = eval_big_step t2 in + let r3 = eval t3 in + let r3_big = eval_big_step t3 in + let r4 = eval t4 in + let r4_big = eval_big_step t4 in + print_endline "Small-step evaluation results:"; + print_endline ("t1 evaluates to: " ^ (stringify_term r1)); + print_endline ("t2 evaluates to: " ^ (stringify_term r2)); + print_endline ("t3 evaluates to: " ^ (stringify_term r3)); + print_endline ("t4 evaluates to: " ^ (stringify_term r4)); + print_endline ""; + print_endline "Big-step evaluation results:"; + print_endline ("t1 evaluates to: " ^ (stringify_term r1_big)); + print_endline ("t2 evaluates to: " ^ (stringify_term r2_big)); + print_endline ("t4 evaluates to: " ^ (stringify_term r3_big)); + print_endline ("t4 evaluates to: " ^ (stringify_term r4_big));