type 'a t = {
data : 'a list ;
f_data : 'a list ;
}
;;
exception No_more;;
let create v = { data = [v] ; f_data = [] };;
let push x t = { data = x :: t.data ; f_data = [] };;
let undo t =
match t.data with
[] | [_] -> raise No_more
| x :: q ->
let t = { data = q; f_data = x :: t.f_data } in
(x, t)
;;
let redo t =
match t.f_data with
[] -> raise No_more
| x :: q ->
let t = { data = x :: t.data ; f_data = q } in
(x, t)
;;
let can_redo t = t.f_data <> [];;
let get t =
match t.data with
[] -> assert false
| x :: _ -> x
;;
let length t = List.length t.data;;
let forward_length t = List.length t.f_data;;
let as_list t = (List.rev t.data) @ t.f_data;;
type 'a imp_t = { mutable h : 'a t } ;;
let imp_create v = { h = create v } ;;
let imp_push x t = t.h <- push x t.h ;;
let imp_get t = get t.h ;;
let imp_undo t = let (v, h2) = undo t.h in t.h <- h2; v ;;
let imp_redo t = let (v, h2) = redo t.h in t.h <- h2; v ;;
let imp_can_redo t = can_redo t.h ;;
let imp_as_list t = as_list t.h ;;
let t_to_imp t = { h = t } ;;
let imp_to_t t = t.h ;;