summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@baturin.org>2015-01-31 23:11:59 +0600
committerDaniil Baturin <daniil@baturin.org>2015-01-31 23:11:59 +0600
commit62dc6df905b53435340dcbacefc26ae72c518d57 (patch)
treeec185ec02a9f413f222833a6775ab63c80037cb3
parent68ef875b1e530fd8451b99deadd3d2f252d43e38 (diff)
downloadvyconf-62dc6df905b53435340dcbacefc26ae72c518d57.tar.gz
vyconf-62dc6df905b53435340dcbacefc26ae72c518d57.zip
Node module prototype.
-rw-r--r--src/vyconf_tree.ml62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/vyconf_tree.ml b/src/vyconf_tree.ml
new file mode 100644
index 0000000..546498e
--- /dev/null
+++ b/src/vyconf_tree.ml
@@ -0,0 +1,62 @@
+type 'a vyconf_tree = Node of string * 'a * ('a vyconf_tree list)
+
+let name_of_node (Node (name, _, _)) = name
+
+let children_of_node (Node (_, _, children)) = children
+
+let data_of_node (Node (_, data, _)) = data
+
+let destructure_node node =
+ name_of_node node,
+ data_of_node node,
+ children_of_node node
+
+let rec find_child_in_list children name =
+ match children with
+ | [] -> None
+ | c :: cs -> if (name_of_node c) = name then (Some c)
+ else find_child_in_list cs name
+
+let find_child node name =
+ find_child_in_list (children_of_node node) name
+
+let rec remove_child_from_list children name =
+ match children with
+ | [] -> []
+ | c :: cs -> if (name_of_node c) = name then cs
+ else c :: (remove_child_from_list cs name)
+
+let extract_child children name =
+ find_child_in_list children name,
+ remove_child_from_list children name
+
+let insert_immediate_child node name data =
+ let new_node = Node (name, data, []) in
+ let (old_name, old_data, old_children) = destructure_node node in
+ Node (old_name, old_data, new_node :: old_children)
+
+let adopt_child node child =
+ let (old_name, old_data, old_children) = destructure_node node in
+ Node (old_name, old_data, child :: old_children)
+
+let replace_child node child =
+ let (old_name, old_data, old_children) = destructure_node node in
+ let child_name = name_of_node child in
+ let old_children' = remove_child_from_list old_children child_name in
+ Node (old_name, old_data, child :: old_children')
+
+let rec insert_child default_data node path data =
+ match path with
+ | [] -> raise (Failure "Can't insert at empty path")
+ | [name] -> insert_immediate_child node name data
+ | name :: names ->
+ let next_child = find_child node name in
+ match next_child with
+ | Some next_child' ->
+ let new_node = insert_child default_data next_child' names data in
+ replace_child node new_node
+ | None ->
+ let next_child' = Node (name, default_data, []) in
+ let new_node = insert_child default_data next_child' names data in
+ let (old_name, old_data, old_children) = destructure_node node in
+ Node (old_name, old_data, new_node :: old_children)