diff options
author | Daniil Baturin <daniil@baturin.org> | 2015-01-31 23:11:59 +0600 |
---|---|---|
committer | Daniil Baturin <daniil@baturin.org> | 2015-01-31 23:11:59 +0600 |
commit | 62dc6df905b53435340dcbacefc26ae72c518d57 (patch) | |
tree | ec185ec02a9f413f222833a6775ab63c80037cb3 | |
parent | 68ef875b1e530fd8451b99deadd3d2f252d43e38 (diff) | |
download | vyconf-62dc6df905b53435340dcbacefc26ae72c518d57.tar.gz vyconf-62dc6df905b53435340dcbacefc26ae72c518d57.zip |
Node module prototype.
-rw-r--r-- | src/vyconf_tree.ml | 62 |
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) |