···90909191module Tape = Tape_effect.Make ()
92929393-module Lex_env = Algaeff.Reader.Make (struct
9494- type t = Value.t String_map.t
9595-end)
9696-9797-module Dyn_env = Algaeff.Reader.Make (struct
9898- type t = Value.t Symbol_map.t
9999-end)
100100-101101-module Config_env = Algaeff.Reader.Make (struct
102102- type t = Config.t
103103-end)
104104-10593module Heap = Algaeff.State.Make (struct
10694 type t = Value.obj Symbol_map.t
10795end)
···118106 type t = T.content T.frontmatter
119107end)
120108121121-module Mode_env = Algaeff.Reader.Make (struct
122122- type t = eval_mode
123123-end)
109109+type eval_env = {
110110+ mode: eval_mode;
111111+ config: Config.t;
112112+ lex_env: Value.t String_map.t;
113113+ dyn_env: Value.t Symbol_map.t;
114114+}
115115+116116+let initial_eval_env config : eval_env =
117117+ {
118118+ mode = Text_mode;
119119+ config;
120120+ lex_env = String_map.empty;
121121+ dyn_env = Symbol_map.empty;
122122+ }
123123+124124+module Eval_env = struct
125125+ include Algaeff.Reader.Make (struct
126126+ type t = eval_env
127127+ end)
128128+end
124129125130let get_current_uri ~loc =
126131 match (Frontmatter.get ()).uri with
···130135 ~extra_remarks:[Asai.Diagnostic.loctext "No uri for tree"]
131136132137let get_transclusion_flags ~loc =
133133- let dynenv = Dyn_env.read () in
138138+ let {dyn_env; _} = Eval_env.read () in
134139 let get_bool key =
135135- let@ value = Option.map @~ Symbol_map.find_opt key dynenv in
140140+ let@ value = Option.map @~ Symbol_map.find_opt key dyn_env in
136141 extract_bool @@ Range.locate_opt loc value
137142 in
138143 let module S = Expand.Builtins.Transclude in
···155160 treat it as a link to a local tree. *)
156161 match (URI.scheme uri, URI.host uri, URI.path_components uri) with
157162 | None, None, ([] | [_]) ->
158158- let config = Config_env.read () in
163163+ let {config; _} = Eval_env.read () in
159164 let uri = URI_scheme.named_uri ~base:config.url str in
160165 Result.ok uri
161166 | _ -> Ok uri
···206211 | Some node -> eval_node node
207212208213and eval_tape tape = Tape.run ~tape process_tape
214214+209215and eval_pop_arg ~loc = Tape.pop_arg ~loc |> Range.map eval_tape
216216+210217and pop_content_arg ~loc = eval_pop_arg ~loc |> extract_content
218218+211219and pop_text_arg ~loc = eval_pop_arg ~loc |> extract_text
220220+212221and pop_text_arg_loc ~loc = eval_pop_arg ~loc |> extract_text_loc
213222214223and eval_node node : Value.t =
···222231 in
223232 emit_content_node ~loc @@ T.prim p @@ T.Content content
224233 | Fun (xs, body) ->
225225- let env = Lex_env.read () in
226226- focus_clo ?loc env (List.map (fun (info, x) -> (info, Some x)) xs) body
234234+ let {lex_env; _}= Eval_env.read () in
235235+ focus_clo ?loc lex_env (List.map (fun (info, x) -> (info, Some x)) xs) body
227236 | Ref -> begin
228237 match eval_pop_arg ~loc |> extract_uri with
229238 | Ok href ->
···262271 emit_content_node ~loc @@ Link {href; content}
263272 | Math (mode, body) ->
264273 let content =
265265- let@ () = Mode_env.run ~env:TeX_mode in
274274+ let@ () = Eval_env.scope @@ fun env -> {env with mode = TeX_mode} in
266275 {node with value = eval_tape body} |> extract_content
267276 in
268277 emit_content_node ~loc @@ KaTeX (mode, content)
···284293 let tex_cs_opt =
285294 match path with [name] -> TeX_cs.parse name | _ -> None
286295 in
287287- begin match (Mode_env.read (), tex_cs_opt) with
296296+ let {mode; _} = Eval_env.read () in
297297+ begin match (mode, tex_cs_opt) with
288298 | TeX_mode, Some (cs, rest) ->
289299 emit_content_node ~loc
290300 @@ T.Text (Format.asprintf "%a%s" pp_tex_cs cs rest)
···309319 emit_content_node ~loc @@ T.Transclude {href; target = Full flags}
310320 | Subtree (addr_opt, nodes) ->
311321 let flags = get_transclusion_flags ~loc in
312312- let config = Config_env.read () in
322322+ let {config; _} = Eval_env.read () in
313323 let uri =
314324 match addr_opt with
315325 | Some addr -> Some (URI_scheme.named_uri ~base:config.url addr)
···343353 end
344354 | Syndicate_query_as_json_blob ->
345355 let name = pop_text_arg ~loc in
346346- let config = Config_env.read () in
356356+ let {config; _} = Eval_env.read () in
347357 let blob_uri = URI_scheme.named_uri ~base:config.url @@ name ^ ".json" in
348358 let query_arg = eval_pop_arg ~loc in
349359 begin match query_arg.value with
···367377 Jobs.modify @@ List.cons @@ Range.locate_opt loc job;
368378 process_tape ()
369379 | Embed_tex ->
370370- let config = Config_env.read () in
380380+ let {config; _} = Eval_env.read () in
371381 let preamble, body =
372372- let@ () = Mode_env.run ~env:TeX_mode in
382382+ let@ () = Eval_env.scope @@ fun env -> {env with mode = TeX_mode} in
373383 let preamble = pop_content_arg ~loc |> TeX_like.string_of_content in
374384 let body = pop_content_arg ~loc |> TeX_like.string_of_content in
375385 (preamble, body)
···415425 emit_content_nodes ~loc @@ [T.Route_of_uri uri]
416426 | Object {self; methods} ->
417427 let table =
418418- let env = Lex_env.read () in
428428+ let {lex_env;_} = Eval_env.read () in
419429 let add (name, body) =
420420- Value.Method_table.add name Value.{body; self; super = None; env}
430430+ Value.Method_table.add name Value.{body; self; super = None; env = lex_env}
421431 in
422432 List.fold_right add methods Value.Method_table.empty
423433 in
···429439 {node with value = obj} |> Range.map eval_tape |> extract_obj_ptr
430440 in
431441 let table =
432432- let env = Lex_env.read () in
442442+ let {lex_env;_} = Eval_env.read () in
433443 let add (name, body) =
434434- Value.Method_table.add name Value.{body; self; super; env}
444444+ Value.Method_table.add name Value.{body; self; super; env = lex_env}
435445 in
436446 List.fold_right add methods Value.Method_table.empty
437447 in
···454464 let proto_val = obj.prototype |> Option.map @@ fun ptr -> Value.Obj ptr in
455465 match Value.Method_table.find_opt method_name obj.methods with
456466 | Some mthd ->
457457- let env =
467467+ let lex_env =
458468 let env =
459469 match mthd.self with
460470 | None -> mthd.env
···467477 | None -> env
468478 | Some super -> String_map.add super proto_val env)
469479 in
470470- let@ () = Lex_env.run ~env in
480480+ let@ () = Eval_env.scope @@ fun env -> {env with lex_env} in
471481 eval_tape mthd.body
472482 | None -> (
473483 match obj.prototype with
···480490 | Put (k, v, body) ->
481491 let k = {node with value = k} |> Range.map eval_tape |> extract_sym in
482492 let body =
483483- let@ () = Dyn_env.scope (Symbol_map.add k (eval_tape v)) in
493493+ let@ () =
494494+ Eval_env.scope @@ fun env ->
495495+ {env with dyn_env = Symbol_map.add k (eval_tape v) env.dyn_env}
496496+ in
484497 eval_tape body
485498 in
486499 focus ?loc:node.loc body
···491504 if Symbol_map.mem k flenv then flenv
492505 else Symbol_map.add k (eval_tape v) flenv
493506 in
494494- let@ () = Dyn_env.scope upd in
507507+ let@ () =
508508+ Eval_env.scope @@ fun env -> {env with dyn_env = upd env.dyn_env}
509509+ in
495510 eval_tape body
496511 in
497512 focus ?loc:node.loc body
498513 | Get k ->
499514 let k = {node with value = k} |> Range.map eval_tape |> extract_sym in
500500- let env = Dyn_env.read () in
501501- begin match Symbol_map.find_opt k env with
515515+ let {dyn_env; _} = Eval_env.read () in
516516+ begin match Symbol_map.find_opt k dyn_env with
502517 | None -> Reporter.fatal ?loc:node.loc (Unbound_fluid_symbol k)
503518 | Some v -> focus ?loc:node.loc v
504519 end
···640655 emit_content_node ~loc:node.loc @@ T.Uri (get_current_uri ~loc:node.loc)
641656642657and eval_var ~loc (x : string) =
643643- let env = Lex_env.read () in
644644- match String_map.find_opt x env with
658658+ let {lex_env; _} = Eval_env.read () in
659659+ match String_map.find_opt x lex_env with
645660 | Some v -> focus ?loc v
646661 | None -> Reporter.fatal ?loc (Unbound_variable x)
647662···672687 | [] ->
673688 focus ?loc
674689 @@
675675- let@ () = Lex_env.run ~env:rho in
690690+ let@ () = Eval_env.scope @@ fun env -> {env with lex_env = rho} in
676691 eval_tape body
677692 | (info, y) :: ys -> (
678693 match Tape.pop_arg_opt () with
···680695 let yval =
681696 match info with
682697 | Strict -> eval_tape arg.value
683683- | Lazy -> Clo (Lex_env.read (), [(Strict, None)], arg.value)
698698+ | Lazy -> Clo ((Eval_env.read ()).lex_env, [(Strict, None)], arg.value)
684699 in
685700 let rhoy =
686701 match y with Some y -> String_map.add y yval rho | None -> rho
···739754 ~emit:push
740755 @@ fun () ->
741756 let fm = T.default_frontmatter ~uri ?source_path () in
742742- let@ () = Mode_env.run ~env:Text_mode in
757757+ let@ () = Eval_env.run ~env:(initial_eval_env config) in
743758 let@ () = Frontmatter.run ~init:fm in
744759 let@ () = Emitted_trees.run ~init:[] in
745760 let@ () = Jobs.run ~init:[] in
746761 let@ () = Heap.run ~init:Symbol_map.empty in
747747- let@ () = Lex_env.run ~env:String_map.empty in
748748- let@ () = Dyn_env.run ~env:Symbol_map.empty in
749749- let@ () = Config_env.run ~env:config in
750762 let main = eval_tree_inner ~uri tree in
751763 let side = Emitted_trees.get () in
752764 let jobs = Jobs.get () in