From dfedcd91fa4e948600fb4b2edb3516f70376c3a9 Mon Sep 17 00:00:00 2001 From: Marcos Magueta Date: Fri, 11 Sep 2026 01:06:06 -0300 Subject: runtime context --- lib/runtime/Context.ml | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/runtime/Context.mli | 8 +++++++ 2 files changed, 68 insertions(+) create mode 100644 lib/runtime/Context.ml create mode 100644 lib/runtime/Context.mli (limited to 'lib') diff --git a/lib/runtime/Context.ml b/lib/runtime/Context.ml new file mode 100644 index 0000000..10422e4 --- /dev/null +++ b/lib/runtime/Context.ml @@ -0,0 +1,60 @@ +module Error = struct + open Concepts.Condition + + let budget_exhausted ~requested ~remaining = + condition "budget-exhausted" "An evaluation asked for more budget than it had left" + ("requested" |=| Concepts.Value.Integer requested + & "remaining" |=| Concepts.Value.Integer remaining) + + let not_a_directory segment = + condition "not-a-directory" "A path segment named an object with no Directory protocol" + ("segment" |=| Concepts.Value.String segment) +end + +type budget = int Atomic.t + +let charge_budget budget n = + let open Utilities.Result in + let* _ = + Utilities.Atomic.mswap budget (fun remaining -> + if remaining >= n then Ok (remaining - n) + else Error (Error.budget_exhausted ~requested:n ~remaining) ) + in + Ok () + +class context ~root ~budget ~cancelled = + object (self) + val root : Protocols.Handle.t = root + val budget : budget = budget + val cancelled : unit -> bool = cancelled + + method resolve (name : string) : + (Protocols.Handle.t option, Concepts.Condition.condition) result = + let open Utilities.Result in + let rec walk handle = function + | [] -> Ok (Protocols.Handle.copy handle) + | segment :: rest -> + let* directory = Protocols.Directory.from handle + |> Option.to_result ~none:(Error.not_a_directory segment) + in + let* found = Protocols.Directory.find directory segment in + match found with + | None -> Ok None + | Some child -> + Fun.protect ~finally:(fun () -> Protocols.Handle.release child) + (fun () -> walk child rest) + in + String.split_on_char '/' name |> List.filter (fun segment -> segment <> "") |> walk root + + method cancelled = cancelled () + method charge n = charge_budget budget n + method nest ?authority:(_ : string BatSet.t option) () = + (new context ~root ~budget ~cancelled :> Protocols.Context.implementation) + + initializer ignore self + end + +let over ~root ?(budget = max_int) ?(cancelled = fun () -> false) () = + Protocols.Context.make (new context ~root ~budget:(Atomic.make budget) ~cancelled) + +let remaining (_ : Protocols.Context.t) : int option = failwith "not implemented" diff --git a/lib/runtime/Context.mli b/lib/runtime/Context.mli new file mode 100644 index 0000000..31ef194 --- /dev/null +++ b/lib/runtime/Context.mli @@ -0,0 +1,8 @@ +val over : + root:Protocols.Handle.t -> + ?budget:int -> + ?cancelled:(unit -> bool) -> + unit -> + Protocols.Context.t + +val remaining : Protocols.Context.t -> int option -- cgit v1.2.3