aboutsummaryrefslogblamecommitdiffstats
path: root/lib/protocols/Context.ml
blob: ea314a69b6a80633ba9265735d67319564722dc2 (plain) (tree)





























                                                                                                    
module Error = struct
  open Concepts.Condition

  let unresolved name =
    condition "unresolved-name" "A name did not resolve to any object reachable from this context"
      ("name" |=| Concepts.Value.String name)
end

class type implementation = object
  method resolve : string -> (Handle.t option, Concepts.Condition.condition) result
  method cancelled : bool
  method charge : int -> (unit, Concepts.Condition.condition) result
  method nest : ?authority:string BatSet.t -> unit -> implementation
end

(* Unlike every other protocol here, a context is handed to [Program.invoke] directly rather than
   looked up through [Handle.into], exactly as evaluators.org's pseudocode shows. It therefore needs
   no extensible-variant constructor and [make] is a plain upcast. *)
type t = implementation

let make impl = (impl :> implementation)
let resolve context name = context#resolve name
let cancelled context = context#cancelled
let charge context n = context#charge n
let nest ?authority context = context#nest ?authority () |> make

let require context name =
  let open Utilities.Result in
  let* found = resolve context name in
  Option.to_result ~none:(Error.unresolved name) found