···1414end
15151616let update (action : Action.t) (forest : State.t) =
1717- let open Action in
1817 let forest = State.update_history ~forest action in
1919- let env = forest.env in
2018 match action with
2119 | Quit e -> begin match e with Fail -> exit 1 | Finished -> exit 0 end
2220 | Query q ->
2321 let r = Forest.run_datalog_query forest.graphs q in
2424- (Query_results r, forest)
2525- | Query_results _ -> (Done, forest)
2626- | Report_errors (_, next_action) -> (next_action, forest)
2727- | Load_all_configured_dirs ->
2828- let errors, paths = Eio_util.paths_of_dirs ~env forest.config.trees in
2929- (* Config validation prevents errors from happening at this stage *)
3030- assert (List.is_empty errors);
3131- let () =
3232- let@ tree_dir = List.iter @~ paths in
3333- assert (Eio.Path.is_directory tree_dir);
3434- let@ tree = Seq.iter @~ Phases.load tree_dir in
3535- let lsp_uri = Tree.Loaded.uri tree in
3636- let uri = URI.of_lsp_uri ~base:forest.config.url lsp_uri in
3737- URI.Tbl.replace forest.resolver uri (Lsp.Uri.to_path lsp_uri);
3838- forest.={uri} <- Tree tree
3939- in
4040- (Parse_all, forest)
2222+ Query_results r
2323+ | Query_results _ -> Done
2424+ | Report_errors (_, next_action) -> next_action
2525+ | Load_configured_dirs ->
2626+ Phases.load_configured_dirs ~forest;
2727+ Parse_all
4128 | Parse_all ->
4242- let errors, codes = Phases.parse forest in
4343- let () =
4444- let@ uri, code = List.iter @~ codes in
4545- forest.={uri} <- Tree code;
4646- forest.?{uri} <- []
4747- in
4848- if List.length errors = 0 then
4949- assert (Seq.for_all Tree.is_parsed (URI.Tbl.to_seq_values forest.index));
5050- let () =
5151- let@ uri, error = List.iter @~ errors in
5252- forest.?{uri} <- [Error.parse_error error]
5353- in
5454- ( report
5555- ~errors:(List.map (snd >>> Error.parse_error) errors)
5656- ~and_then:Build_import_graph,
5757- forest )
2929+ let errors = Phases.parse_all forest in
3030+ report ~errors ~and_then:Build_import_graph
5831 | Build_import_graph ->
5932 let errors, import_graph = Phases.build_import_graph ~forest in
3333+ forest.import_graph <- import_graph;
6034 Logs.debug (fun m ->
6135 m "import graph has %d vertices" (Forest_graph.nb_vertex import_graph));
6262- (report ~errors ~and_then:Expand_all, {forest with import_graph})
3636+ report ~errors ~and_then:Expand_all
6337 | Expand_all ->
6438 Logs.debug (fun m -> m "expanding trees");
6539 let errors = Phases.expand_all forest in
6666- (report ~errors ~and_then:Eval_all, forest)
4040+ report ~errors ~and_then:Eval_all
6741 | Expand uri -> begin
6868- match Option.bind forest.={uri} Tree.to_code with
6969- | None -> assert false
7070- | Some code ->
7171- let result, errors = Phases.expand forest code in
7272- forest.={uri} <- Tree result;
7373- (report ~errors ~and_then:(Eval uri), forest)
4242+ Option.fold forest.={uri} ~none:(assert false) ~some:begin fun tree ->
4343+ match Tree.to_code tree with
4444+ | None -> assert false
4545+ | Some code ->
4646+ let result, errors = Phases.expand forest code in
4747+ forest.={uri} <- Tree result;
4848+ report ~errors ~and_then:(Eval uri)
4949+ end
7450 end
7551 | Eval_all ->
7652 Logs.debug (fun m -> m "evaluating");
7777- let errors, results = Phases.eval forest in
7878- let jobs =
7979- let@ Eval.{articles; jobs} = List.concat_map @~ results in
8080- let () =
8181- let@ article = List.iter @~ articles in
8282- State.plant_resource ~forest T.(Article article)
8383- in
8484- jobs
8585- in
8686- (report ~errors ~and_then:(Run_jobs jobs), forest)
8787- | Eval uri -> begin
8888- let jobs = Phases.eval_only uri forest in
8989- (Run_jobs jobs, forest)
9090- end
5353+ let jobs, errors = Phases.eval forest in
5454+ report ~errors ~and_then:(Run_jobs jobs)
5555+ | Eval uri ->
5656+ let errors, jobs = Phases.eval_only uri forest in
5757+ report ~errors ~and_then:(Run_jobs jobs)
9158 | Plant_assets ->
9292- (* TODO: We really only need to plant the assets that are referred to (look
9393- for calls to Asset_router.uri_of_asset).*)
9494- let errors, paths = Eio_util.paths_of_dirs ~env forest.config.assets in
9595- let paths = Dir_scanner.scan_asset_directories paths in
9696- Logs.debug (fun m -> m "planting %i assets" (Seq.length paths));
9797- let module EP = Eio.Path in
9898- begin
9999- let@ path = Eio.Fiber.List.iter ~max_fibers:20 @~ List.of_seq paths in
100100- let content = EP.load path in
101101- let source_path = EP.native_exn path in
102102- match
103103- Asset_router.install ~config:forest.config ~source_path ~content
104104- with
105105- | Error _ -> failwith "handle asset router install failure"
106106- | Ok uri ->
107107- Logs.debug (fun m -> m "Installed %s at %a" source_path URI.pp uri);
108108- State.plant_resource ~forest (T.Asset {uri; content})
109109- end;
110110- (report ~errors:(List.map Error.io_error errors) ~and_then:Done, forest)
5959+ let () = Phases.plant_assets ~forest in
6060+ Done
11161 | Plant_foreign ->
11262 Logs.debug (fun m -> m "Planting foreign forests");
11363 let errors = Phases.implant_foreign ~forest in
114114- (report ~errors ~and_then:Done, forest)
6464+ report ~errors ~and_then:Done
11565 | Run_jobs jobs ->
116116- Phases.run_jobs forest jobs;
117117- (Done, forest)
6666+ let () = Phases.run_jobs forest jobs in
6767+ Done
11868 | Load_tree path ->
11969 let doc = Imports.load_tree path in
12070 let lsp_uri = Tree.Loaded.uri doc in
12171 let uri = URI.of_lsp_uri ~base:forest.config.url lsp_uri in
12272 forest.={uri} <- Tree doc;
123123- (Parse lsp_uri, forest)
7373+ Parse lsp_uri
12474 | Parse uri ->
12575 Logs.debug (fun m -> m "Reparsing");
12676 let uri = URI.of_lsp_uri ~base:forest.config.url uri in
127127- begin match Option.bind forest.={uri} Tree.to_doc with
128128- | Some doc -> begin
129129- match Parse.parse_document doc with
130130- | Ok code ->
131131- forest.={uri} <- Tree code;
132132- forest.?{uri} <- [];
133133- Imports.fixup ~uri code forest;
134134- (Expand uri, forest)
135135- | Error parse_error ->
136136- let errors = [Error.parse_error parse_error] in
137137- forest.?{uri} <- errors;
138138- (report ~errors ~and_then:Done, forest)
139139- end
140140- | None -> (
141141- match Imports.resolve_uri_to_code ~forest uri with
142142- | Ok code ->
143143- Imports.fixup ~uri code forest;
144144- forest.={uri} <- Tree code;
145145- (Expand uri, forest)
146146- | Error errors -> (Report_errors (errors, Expand uri), forest))
147147- end
148148- | Done -> (Done, forest)
7777+ Phases.parse forest uri
7878+ | Done -> Done
1497915080let run_until_done a s : State.t =
15181 let rec go action state =
152152- let new_action, new_state = update action state in
8282+ let new_action = update action state in
15383 match action with
15484 | Quit Fail -> exit 1
15585 | Quit Finished -> exit 0
156156- | Done -> new_state
157157- | _ -> go new_action new_state
8686+ | Done -> state
8787+ | _ -> go new_action state
15888 in
15989 go a s
16090···16999 |> plant_assets |> implant_foreign
170100 in
171101 let rec go action state =
172172- let new_action, new_state = update action state in
102102+ let new_action = update action state in
173103 match action with
174104 | Quit Fail -> exit 1
175105 | Quit Finished -> exit 0
176176- | Done -> new_state
106106+ | Done -> state
177107 | Report_errors (errors, _) ->
178108 assert (List.length errors > 0);
179109 Logs.debug (fun m -> m "got %d errors" (List.length errors));
180110 List.iter Error.print errors;
181181- if any_fatal errors then go (Quit Fail) new_state
182182- else go new_action new_state
183183- | _ -> go new_action new_state
111111+ if any_fatal errors then go (Quit Fail) state else go new_action state
112112+ | _ -> go new_action state
184113 in
185185- go Load_all_configured_dirs init
114114+ go Load_configured_dirs init
186115187116let language_server ~env ~config =
188117 let init = State.make ~env ~config ~dev:true () in
189118 let rec go action state =
190190- let new_action, new_state = update action state in
119119+ let new_action = update action state in
191120 match action with
192121 | Quit Fail -> exit 1
193122 | Quit Finished -> exit 0
194194- | Done -> new_state
195195- | _ -> go new_action new_state
123123+ | Done -> state
124124+ | _ -> go new_action state
196125 in
197197- let _, state = update Plant_assets init in
126126+ let _ = update Plant_assets init in
198127 (* TODO: this ought to implant the foreign trees as well *)
199199- go Load_all_configured_dirs state
128128+ go Load_configured_dirs init
200129201130let run_with_history a s =
202131 let history = ref [] in
203132 let rec go action state =
204133 history := action :: !history;
205134 match update action state with
206206- | new_action, new_state ->
207207- if action = Done then new_state
135135+ | new_action ->
136136+ if action = Done then state
208137 else begin
209209- go new_action new_state
138138+ go new_action state
210139 end
211140 in
212141 let forest = go a s in
···216145 let errors = ref [] in
217146 let rec go action state =
218147 match update action state with
219219- | new_action, new_state -> (
148148+ | new_action -> begin
220149 match action with
221221- | Done -> new_state
150150+ | Done -> state
222151 | Report_errors (errs, _) -> begin
223152 errors := errs @ !errors;
224224- go new_action new_state
153153+ go new_action state
225154 end
226226- | _ -> go new_action new_state)
155155+ | _ -> go new_action state
156156+ end
227157 in
228158 let forest = go a s in
229159 (forest, List.rev !errors)
···233163 match msgs with
234164 | [] -> state
235165 | msg :: remaining ->
236236- let _discard, new_state = update msg state in
237237- force remaining new_state
166166+ let _discard = update msg state in
167167+ force remaining state
+86-22
lib/compiler/Phases.ml
···2323let load (tree_dir : Eio.Fs.dir_ty Eio.Path.t) =
2424 Dir_scanner.scan_directory tree_dir |> Seq.map Imports.load_tree
25252626-let parse (forest : State.t) =
2727- let trees = forest.index |> URI.Tbl.to_seq |> List.of_seq in
2828- let@ uri, result =
2929- List.partition_map
3030- @~
3131- let@ uri, tree = List.filter_map @~ trees in
3232- match Tree.to_doc tree with
3333- | Some document -> Some (uri, Parse.parse_document document)
3434- | None -> None
2626+let load_configured_dirs ~(forest : State.t) =
2727+ let errors, paths =
2828+ Eio_util.paths_of_dirs ~env:forest.env forest.config.trees
3529 in
3636- match result with Ok tree -> Right (uri, tree) | Error e -> Left (uri, e)
3030+ (* Config validation prevents errors from happening at this stage *)
3131+ assert (List.is_empty errors);
3232+ let@ tree_dir = List.iter @~ paths in
3333+ assert (Eio.Path.is_directory tree_dir);
3434+ let@ tree = Seq.iter @~ load tree_dir in
3535+ let lsp_uri = Tree.Loaded.uri tree in
3636+ let uri = URI.of_lsp_uri ~base:forest.config.url lsp_uri in
3737+ URI.Tbl.replace forest.resolver uri (Lsp.Uri.to_path lsp_uri);
3838+ forest.={uri} <- Tree tree
3939+4040+let parse (forest : State.t) uri =
4141+ let open Action in
4242+ Option.bind forest.={uri} Tree.to_doc
4343+ |> Option.fold
4444+ ~some:begin fun tree ->
4545+ match Parse.parse_document tree with
4646+ | Ok code ->
4747+ forest.={uri} <- Tree code;
4848+ forest.?{uri} <- [];
4949+ Imports.fixup ~uri code forest;
5050+ Expand uri
5151+ | Error parse_error ->
5252+ let errors = [Error.parse_error parse_error] in
5353+ forest.?{uri} <- errors;
5454+ report ~errors ~and_then:Done
5555+ end
5656+ ~none:begin match Imports.resolve_uri_to_code ~forest uri with
5757+ | Ok code ->
5858+ Imports.fixup ~uri code forest;
5959+ forest.={uri} <- Tree code;
6060+ Expand uri
6161+ | Error errors -> report ~errors ~and_then:(Expand uri)
6262+ end
6363+6464+let parse_all (forest : State.t) =
6565+ let@ uri, tree = List.filter_map @~ State.get_all_unparsed ~forest in
6666+ match Parse.parse_document tree with
6767+ | Ok tree -> begin
6868+ forest.={uri} <- Tree tree;
6969+ forest.?{uri} <- [];
7070+ None
7171+ end
7272+ | Error error ->
7373+ forest.?{uri} <- [Error.parse_error error];
7474+ Some (Error.parse_error error)
37753876let reparse (doc : Lsp.Text_document.t) (forest : State.t) =
3977 Logs.debug (fun m -> m "reparsing");
···105143 end
106144107145let eval (forest : State.t) =
108108- let expanded_trees = State.get_all_expanded ~forest |> List.of_seq in
109109- let errors, results =
110110- let@ uri, tree = List.partition_map @~ expanded_trees in
146146+ let (articles, jobs), errors =
147147+ let open List in
148148+ Pair.map_fst (split >>> Pair.map concat concat)
149149+ @@ Pair.map
150150+ (filter_map (function
151151+ | None -> None
152152+ | Some Eval.{articles; jobs} -> Some (articles, jobs)))
153153+ concat
154154+ @@ split
155155+ @@
156156+ let@ uri, tree = map @~ State.get_all_expanded ~forest in
111157 let source_path =
112158 if forest.dev then URI.Tbl.find_opt forest.resolver uri else None
113159 in
114114- right Eval.(eval_tree ~config:forest.config ~source_path ~uri tree)
160160+ Eval.(eval_tree ~config:forest.config ~source_path ~uri tree)
115161 in
116116- let results, additional_errors =
117117- let organize =
118118- List.split >>> Pair.map (List.filter_map Fun.id) List.concat
119119- in
120120- organize results
162162+ let () =
163163+ let@ article = List.iter @~ articles in
164164+ State.plant_resource ~forest T.(Article article)
121165 in
122122- (additional_errors @ List.concat errors, results)
166166+ (jobs, errors)
123167124168let eval_only (uri : URI.t) (forest : State.t) =
125169 match forest.={uri} with
···136180 in
137181 forest.?{uri} <- errors;
138182 match result with
139139- | None -> []
183183+ | None -> (errors, [])
140184 | Some {articles; jobs} ->
141185 let () =
142186 let@ article = List.iter @~ articles in
143187 State.plant_resource ~forest (Article article)
144188 in
145145- jobs
189189+ (errors, jobs)
146190 end
147191 end
192192+193193+let plant_assets ~(forest : State.t) =
194194+ (* TODO: We really only need to plant the assets that are referred to (look
195195+ for calls to Asset_router.uri_of_asset).*)
196196+ let errors, paths =
197197+ Eio_util.paths_of_dirs ~env:forest.env forest.config.assets
198198+ in
199199+ (* Config validation prevents errors from happening at this stage *)
200200+ assert (List.length errors = 0);
201201+ let paths = Dir_scanner.scan_asset_directories paths in
202202+ Logs.debug (fun m -> m "planting %i assets" (Seq.length paths));
203203+ let module EP = Eio.Path in
204204+ let@ path = Eio.Fiber.List.iter ~max_fibers:20 @~ List.of_seq paths in
205205+ let content = EP.load path in
206206+ let source_path = EP.native_exn path in
207207+ match Asset_router.install ~config:forest.config ~source_path ~content with
208208+ | Error _ -> failwith "handle asset router install failure"
209209+ | Ok uri ->
210210+ Logs.debug (fun m -> m "Installed %s at %a" source_path URI.pp uri);
211211+ State.plant_resource ~forest (T.Asset {uri; content})
148212149213let implant ~(forest : State.t) (foreign : Config.foreign) =
150214 let* path =
+10-7
lib/compiler/State.ml
···2222 index: Tree.t URI.Tbl.t;
2323 diagnostics: Error.t list URI.Tbl.t;
2424 graphs: (module Forest_graphs.S);
2525- import_graph: Forest_graph.t;
2525+ mutable import_graph: Forest_graph.t;
2626 dependency_cache: Cache.t;
2727 resolver: string URI.Tbl.t;
2828 search_index: Forester_search.Index.t;
···102102let to_seq state = URI.Tbl.to_seq state.index
103103104104let get_all_unparsed ~forest =
105105- forest.index |> URI.Tbl.to_seq_values |> Seq.filter is_unparsed
105105+ forest.index |> URI.Tbl.to_seq
106106+ |> Seq.filter_map (fun (uri, tree) ->
107107+ match Tree.to_doc tree with Some doc -> Some (uri, doc) | _ -> None)
108108+ |> List.of_seq
106109107110let get_all_code ~forest =
108111 forest.index |> URI.Tbl.to_seq
···118121 forest.index |> URI.Tbl.to_seq
119122 |> Seq.filter_map (fun (uri, tree) ->
120123 match to_syn tree with None -> None | Some tree -> Some (uri, tree))
124124+ |> List.of_seq
121125122126let get_all_unevaluated ~forest =
123127 forest.index |> URI.Tbl.to_seq
124128 |> Seq.filter_map (fun (uri, tree) ->
125129 if is_unevaluated tree then Some (uri, tree) else None)
126130127127-let get_all_articles : t -> T.content T.article Seq.t =
128128- fun state -> state.index |> URI.Tbl.to_seq_values |> Seq.filter_map to_article
131131+let get_all_articles ~forest =
132132+ forest.index |> URI.Tbl.to_seq_values |> Seq.filter_map to_article
129133130130-let get_all_evaluated : t -> evaluated Seq.t =
131131- fun state ->
132132- state.index |> URI.Tbl.to_seq_values |> Seq.filter_map to_evaluated
134134+let get_all_evaluated ~forest =
135135+ forest.index |> URI.Tbl.to_seq_values |> Seq.filter_map to_evaluated
133136134137let get_all_resources : t -> T.content T.resource Seq.t =
135138 fun state -> state.index |> URI.Tbl.to_seq_values |> Seq.filter_map to_resource
+7-7
lib/compiler/test/Test_compiler.ml
···3232 let@ path = with_test_forest ~raw_trees ~env ~config in
3333 Sys.chdir (Eio.Path.native_exn path);
3434 let forest = State.make ~env ~config ~dev:false () in
3535- Driver.run_with_history Load_all_configured_dirs forest
3535+ Driver.run_with_history Load_configured_dirs forest
3636 in
3737 Alcotest.(check @@ list action)
3838 "all actions have run"
3939 [
4040- Load_all_configured_dirs;
4040+ Load_configured_dirs;
4141 Parse_all;
4242 Build_import_graph;
4343 Expand_all;
···4848 history;
4949 Alcotest.(check @@ int)
5050 "no tree is unparsed" 0
5151- (Seq.length (State.get_all_unparsed ~forest));
5151+ (List.length (State.get_all_unparsed ~forest));
5252 Alcotest.(check @@ int)
5353 "no tree is unexpanded" 0
5454 (Seq.length (State.get_all_unexpanded ~forest));
···5757 (Seq.length (State.get_all_unevaluated ~forest));
5858 Alcotest.(check @@ int)
5959 "has correct number of articles" 8
6060- (Seq.length (State.get_all_articles forest))
6060+ (Seq.length (State.get_all_articles ~forest))
61616262let test_includes_paths ~env () =
6363 let config = Config.default () in
···6565 Sys.chdir (Eio.Path.native_exn path);
6666 let forest, history =
6767 State.make ~env ~config ~dev:true ()
6868- |> Driver.run_with_history Load_all_configured_dirs
6868+ |> Driver.run_with_history Load_configured_dirs
6969 in
7070 Alcotest.(check int)
7171 "number of parsed trees" 8
···7676 Alcotest.(check @@ list action)
7777 "evaluation succeeded"
7878 [
7979- Load_all_configured_dirs;
7979+ Load_configured_dirs;
8080 Parse_all;
8181 Build_import_graph;
8282 Expand_all;
···105105 m "In temp dir %s" (Unix.realpath @@ Eio.Path.native_exn tmp_path));
106106 let forest =
107107 State.make ~env ~config ~dev:false ()
108108- |> Driver.run_until_done Load_all_configured_dirs
108108+ |> Driver.run_until_done Load_configured_dirs
109109 in
110110 let reparse_addr = "t8.tree" in
111111 let reparse_uri = URI.path_to_uri ~base:config.url reparse_addr in
···5555let complete ~(forest : State.t) prefix : (string * string) List.t =
5656 let config = forest.config in
5757 let@ article =
5858- List.filter_map @~ List.of_seq @@ State.get_all_articles forest
5858+ List.filter_map @~ List.of_seq @@ State.get_all_articles ~forest
5959 in
6060 let@ uri = Option.bind article.frontmatter.uri in
6161 let short_uri = URI.display_path_string ~base:config.url uri in
···9797 |> (fun t -> `List t)
9898 |> Yojson.Safe.to_string
9999100100-let outputs_for_article
101101- ~(forest : State.t)
102102- ~emit_legacy_xml
100100+let outputs_for_article ~(forest : State.t) ~emit_legacy_xml
103101 (article : _ T.article) =
104102 match article.frontmatter.uri with
105103 | None -> []
···128126 let route = asset.uri in
129127 [(route, asset.content)]
130128131131-let outputs_for_json_blob_syndication
132132- ~(forest : State.t)
129129+let outputs_for_json_blob_syndication ~(forest : State.t)
133130 (syndication : _ T.json_blob_syndication) =
134131 if URI.host syndication.blob_uri = URI.host forest.config.url then
135132 let vertices = Forest.run_datalog_query forest.graphs syndication.query in
···145142 [(syndication.blob_uri, json_content)]
146143 else []
147144148148-let outputs_for_atom_feed_syndication
149149- ~(forest : State.t)
145145+let outputs_for_atom_feed_syndication ~(forest : State.t)
150146 (syndication : T.atom_feed_syndication) =
151147 let* atom_nodes =
152148 Atom_client.render_feed forest ~source_uri:syndication.source_uri
···161157 | T.Atom_feed syndication ->
162158 outputs_for_atom_feed_syndication ~forest syndication
163159164164-let outputs_for_resource
165165- ~(forest : State.t)
166166- ~emit_legacy_xml
160160+let outputs_for_resource ~(forest : State.t) ~emit_legacy_xml
167161 (evaluated : Tree.evaluated) =
168162 if not evaluated.route_locally then ok []
169163 else
···178172179173let render_forest ~dev ~emit_legacy_xml ~(forest : State.t) : unit =
180174 let cwd = Eio.Stdenv.cwd forest.env in
181181- let all_resources = forest |> State.get_all_evaluated in
175175+ let all_resources = State.get_all_evaluated ~forest in
182176 Logs.debug (fun m -> m "Rendering %i resources" (Seq.length all_resources));
183177 begin
184178 let json_string = json_manifest ~dev ~forest in
+1-1
lib/language_server/Completion.ml
···280280 L.CompletionItem.create ~insertText ~label ()
281281282282let addr_completions ~(forest : State.t) : L.CompletionItem.t list =
283283- let articles = List.of_seq @@ State.get_all_articles forest in
283283+ let articles = List.of_seq @@ State.get_all_articles ~forest in
284284 let@ article = List.filter_map @~ articles in
285285 let frontmatter = article.frontmatter in
286286 let@ _ = Option.bind frontmatter.title in
+1-1
lib/search/Search_engine.ml
···6464 in
6565 let dev = true in
6666 let forest = Driver.batch_run ~env ~dev ~config ~config_path:"forest.toml" in
6767- let articles = List.of_seq @@ State.get_all_articles forest in
6767+ let articles = List.of_seq @@ State.get_all_articles ~forest in
6868 let index = Index.create articles in
6969 let size = Obj.reachable_words @@ Obj.repr index in
7070 Format.printf "index size: %i@." size;
+1-1
lib/server/Server.ml
···106106 Result.to_option @@ query_parser @@ Uri.pct_decode @@ query)
107107 in
108108 let run_query ~forest q =
109109- let result, _ = Driver.update (Query q) forest in
109109+ let result = Driver.update (Query q) forest in
110110 match result with Query_results vertex_set -> Some vertex_set | _ -> None
111111 in
112112 match query with