From 8330f5cfd6a332df10fc806b0c0bdab6e0abe8e7 Mon Sep 17 00:00:00 2001 From: Pierre-Marie Pédrot Date: Fri, 25 Apr 2014 19:46:30 +0200 Subject: Adding a stm/ folder, as asked during last workgroup. It was essentially moving files around. A bunch of files from lib/ that were only used in the STM were moved, as well as part of toplevel/ related to the STM. --- stm/vcs.ml | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 stm/vcs.ml (limited to 'stm/vcs.ml') diff --git a/stm/vcs.ml b/stm/vcs.ml new file mode 100644 index 000000000..e2513b1c1 --- /dev/null +++ b/stm/vcs.ml @@ -0,0 +1,193 @@ +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* t + val equal : t -> t -> bool + val compare : t -> t -> int + val to_string : t -> string + val master : t + end + + type id + + (* Branches have [branch_info] attached to them. *) + type ('kind) branch_info = { + kind : [> `Master] as 'kind; + root : id; + pos : id; + } + + type ('kind,'diff,'info) t constraint 'kind = [> `Master ] + + val empty : id -> ('kind,'diff,'info) t + + val current_branch : ('k,'e,'i) t -> Branch.t + val branches : ('k,'e,'i) t -> Branch.t list + + val get_branch : ('k,'e,'i) t -> Branch.t -> 'k branch_info + val reset_branch : ('k,'e,'i) t -> Branch.t -> id -> ('k,'e,'i) t + val branch : + ('kind,'e,'i) t -> ?root:id -> ?pos:id -> + Branch.t -> 'kind -> ('kind,'e,'i) t + val delete_branch : ('k,'e,'i) t -> Branch.t -> ('k,'e,'i) t + val merge : + ('k,'diff,'i) t -> id -> ours:'diff -> theirs:'diff -> ?into:Branch.t -> + Branch.t -> ('k,'diff,'i) t + val commit : ('k,'diff,'i) t -> id -> 'diff -> ('k,'diff,'i) t + val rewrite_merge : + ('k,'diff,'i) t -> id -> ours:'diff -> theirs:'diff -> at:id -> + Branch.t -> ('k,'diff,'i) t + val checkout : ('k,'e,'i) t -> Branch.t -> ('k,'e,'i) t + + val set_info : ('k,'e,'info) t -> id -> 'info -> ('k,'e,'info) t + val get_info : ('k,'e,'info) t -> id -> 'info option + + module NodeSet : Set.S with type elt = id + + val gc : ('k,'e,'info) t -> ('k,'e,'info) t * NodeSet.t + + val reachable : ('k,'e,'info) t -> id -> NodeSet.t + + module Dag : Dag.S with type node = id + val dag : ('kind,'diff,'info) t -> ('diff,'info,id) Dag.t + + val create_cluster : ('k,'e,'i) t -> id list -> id -> ('k,'e,'i) t + val cluster_of : ('k,'e,'i) t -> id -> id Dag.Cluster.t option + val delete_cluster : ('k,'e,'i) t -> id Dag.Cluster.t -> ('k,'e,'i) t + +end + +module Make(OT : Map.OrderedType) = struct + +module Dag = Dag.Make(OT) + +type id = OT.t + +module NodeSet = Dag.NodeSet + + +module Branch = +struct + type t = string + let make = + let bid = ref 0 in + fun s -> incr bid; string_of_int !bid ^ "_" ^ s + let equal = CString.equal + let compare = CString.compare + let to_string s = s + let master = "master" +end + +module BranchMap = Map.Make(Branch) + +type 'kind branch_info = { + kind : [> `Master] as 'kind; + root : id; + pos : id; +} + +type ('kind,'edge,'info) t = { + cur_branch : Branch.t; + heads : 'kind branch_info BranchMap.t; + dag : ('edge,'info,id) Dag.t; +} + +let empty root = { + cur_branch = Branch.master; + heads = BranchMap.singleton Branch.master { root = root; pos = root; kind = `Master }; + dag = Dag.empty; +} + +let add_node vcs id edges = + assert (not (CList.is_empty edges)); + { vcs with dag = + List.fold_left (fun g (t,tgt) -> Dag.add_edge g id t tgt) vcs.dag edges } + +let get_branch vcs head = + try BranchMap.find head vcs.heads + with Not_found -> anomaly (str"head " ++ str head ++ str" not found") + +let reset_branch vcs head id = + let map name h = + if Branch.equal name head then { h with pos = id } else h + in + { vcs with heads = BranchMap.mapi map vcs.heads; } + +let current_branch vcs = vcs.cur_branch + +let branch + vcs ?(root=(get_branch vcs vcs.cur_branch).pos) ?(pos=root) name kind += + { vcs with + heads = BranchMap.add name { kind; root; pos } vcs.heads; + cur_branch = name } + +let delete_branch vcs name = + if Branch.equal Branch.master name then vcs else + let filter n _ = not (Branch.equal n name) in + { vcs with heads = BranchMap.filter filter vcs.heads } + +let merge vcs id ~ours:tr1 ~theirs:tr2 ?(into = vcs.cur_branch) name = + assert (not (Branch.equal name into)); + let br_id = (get_branch vcs name).pos in + let cur_id = (get_branch vcs into).pos in + let vcs = add_node vcs id [tr1,cur_id; tr2,br_id] in + let vcs = reset_branch vcs into id in + vcs + +let del_edge id vcs tgt = { vcs with dag = Dag.del_edge vcs.dag id tgt } + +let rewrite_merge vcs id ~ours:tr1 ~theirs:tr2 ~at:cur_id name = + let br_id = (get_branch vcs name).pos in + let old_edges = List.map fst (Dag.from_node vcs.dag id) in + let vcs = List.fold_left (del_edge id) vcs old_edges in + let vcs = add_node vcs id [tr1,cur_id; tr2,br_id] in + vcs + +let commit vcs id tr = + let vcs = add_node vcs id [tr, (get_branch vcs vcs.cur_branch).pos] in + let vcs = reset_branch vcs vcs.cur_branch id in + vcs + +let checkout vcs name = { vcs with cur_branch = name } + +let set_info vcs id info = { vcs with dag = Dag.set_info vcs.dag id info } +let get_info vcs id = Dag.get_info vcs.dag id + +let create_cluster vcs l i = { vcs with dag = Dag.create_cluster vcs.dag l i } +let cluster_of vcs i = Dag.cluster_of vcs.dag i +let delete_cluster vcs c = { vcs with dag = Dag.del_cluster vcs.dag c } + +let branches vcs = BranchMap.fold (fun x _ accu -> x :: accu) vcs.heads [] +let dag vcs = vcs.dag + +let rec closure s d n = + let l = try Dag.from_node d n with Not_found -> [] in + List.fold_left (fun s (n',_) -> + if Dag.NodeSet.mem n' s then s + else closure s d n') + (Dag.NodeSet.add n s) l + +let reachable vcs i = closure Dag.NodeSet.empty vcs.dag i + +let gc vcs = + let alive = + BranchMap.fold (fun b { pos } s -> closure s vcs.dag pos) + vcs.heads Dag.NodeSet.empty in + let dead = Dag.NodeSet.diff (Dag.all_nodes vcs.dag) alive in + { vcs with dag = Dag.del_nodes vcs.dag dead }, dead + +end -- cgit v1.2.3