blob: 6846e43c9406559d37e7215783aef279afe6088a (
plain) (
tree)
|
|
module Error = struct
open Concepts.Condition
let not_generative () =
condition "not-generative"
"A relation was used where the expression must produce members under a binding, but it \
declares no modes. A relation that cannot be asked this way can still be reached through \
another access path."
empty
let attributes bound = Concepts.Value.String (String.concat ", " (BatSet.String.elements bound))
let ungenerable bound =
condition "ungenerable-binding"
"The relation declares no mode that generates under the attributes bound."
("bound" |=| attributes bound)
let undecidable bound =
condition "undecidable-membership"
"The relation declares no mode that decides membership under the attributes of the tuple."
("bound" |=| attributes bound)
end
type binding = Concepts.Value.value BatMap.String.t
class type implementation = object
method modes : (Concepts.Mode.t, Concepts.Condition.condition) result
method generate : binding -> (Handle.t, Concepts.Condition.condition) result
end
type Handle.protocol += Generative of implementation
type t = implementation
let make impl = Generative (impl :> implementation)
let from handle = Handle.into handle (function Generative impl -> Some impl | _ -> None)
let require handle = from handle |> Option.to_result ~none:(Error.not_generative ())
let nothing = BatMap.String.empty
let bound = Concepts.Mode.attributes_of_map
let modes i = Handle.invoke i (fun o -> o#modes)
let generate i binding =
Handle.invoke i (fun o ->
let open Utilities.Result in
let bound = bound binding in
let* declaration = o#modes in
if Option.is_some (Concepts.Mode.generation declaration bound) then o#generate binding
else Error (Error.ungenerable bound) )
let satisfies binding tuple =
BatMap.String.for_all
(fun attribute value ->
match BatMap.String.find_opt attribute tuple.Concepts.Tuple.attributes with
| Some found -> Concepts.Value.equal found value
| None -> false )
binding
class virtual membership =
object (self)
val virtual heading : Concepts.Mode.attributes
method virtual modes : (Concepts.Mode.t, Concepts.Condition.condition) result
method virtual generate : binding -> (Handle.t, Concepts.Condition.condition) result
method contains (tuple : Concepts.Tuple.t) =
let open Utilities.Result in
let binding = tuple.Concepts.Tuple.attributes in
let bound = bound binding in
if not (BatSet.String.equal heading bound) then Ok false
else
let* declaration = self#modes in
let* () =
if Concepts.Mode.decision declaration bound then Ok ()
else Error (Error.undecidable bound)
in
let* cursor = self#generate binding in
let expected = Concepts.Tuple.hash tuple in
Fun.protect
~finally:(fun () -> Handle.release cursor)
(fun () ->
let* scan = Cursor.require cursor in
Cursor.exists scan (fun member ->
Concepts.Hash.hash_equals (Concepts.Tuple.hash member) expected ) )
end
|