aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMarcos Magueta <maguetamarcos@gmail.com>2026-10-12 11:58:25 -0300
committerMarcos Magueta <maguetamarcos@gmail.com>2026-10-12 11:58:25 -0300
commitad33454a204aa5791445e7d15f02ba0447fff85e (patch)
treeb1730a9ac5b40ff58ddc23976cd5df5dac924231 /lib
parentd4f603fa04283efe54c79b5f7664c4c9bc193857 (diff)
downloadRNT-ad33454a204aa5791445e7d15f02ba0447fff85e.tar.gz
RNT-ad33454a204aa5791445e7d15f02ba0447fff85e.zip
relation scan with enumerable and release
Diffstat (limited to 'lib')
-rw-r--r--lib/evaluators/FOL.ml9
-rw-r--r--lib/kernel/EphemeralRelation.ml9
-rw-r--r--lib/kernel/Multigroup.ml8
-rw-r--r--lib/protocols/Cursor.ml2
-rw-r--r--lib/protocols/Cursor.mli6
-rw-r--r--lib/protocols/Enumerable.ml2
-rw-r--r--lib/protocols/Enumerable.mli7
-rw-r--r--lib/protocols/Relation.ml8
8 files changed, 25 insertions, 26 deletions
diff --git a/lib/evaluators/FOL.ml b/lib/evaluators/FOL.ml
index 92b1c38..050e528 100644
--- a/lib/evaluators/FOL.ml
+++ b/lib/evaluators/FOL.ml
@@ -118,14 +118,9 @@ let rec modes =
|> Result.map
(Concepts.Mode.project (BatSet.String.of_list (BatFingerTree.to_list attributes)))
-let enumerate relation =
- let open Utilities.Result in
- let* enumerable = Protocols.Enumerable.require relation in
- Protocols.Enumerable.enumerate enumerable
-
let project description relation =
let open Utilities.Result in
- let* cursor = enumerate relation in
+ let* cursor = Protocols.Enumerable.cursor relation in
let produce ~yield =
let* scan = Protocols.Cursor.require cursor in
let rec distinct seen =
@@ -168,7 +163,7 @@ let rec execute plan =
match plan with
| Base relation ->
let relation = Protocols.Handle.move relation in
- Ok (derive ~decide:(contains relation) relation description modes enumerate)
+ Ok (derive ~decide:(contains relation) relation description modes Protocols.Enumerable.cursor)
| Project (plan, _) ->
let* relation = execute plan in
Ok (derive relation description modes (project description))
diff --git a/lib/kernel/EphemeralRelation.ml b/lib/kernel/EphemeralRelation.ml
index fd40aff..250aacc 100644
--- a/lib/kernel/EphemeralRelation.ml
+++ b/lib/kernel/EphemeralRelation.ml
@@ -84,8 +84,7 @@ class ephemeral_relation ?program ?decide description value modes enumerate inpu
Error (Error.undecidable_membership ())
else
let* cursor = self#enumerate in
- Protocols.Handle.releasing cursor (fun () ->
- let* scan = Protocols.Cursor.require cursor in
+ Protocols.Cursor.consuming cursor (fun scan ->
Protocols.Cursor.exists scan (fun member ->
Concepts.Hash.hash_equals (Concepts.Tuple.hash member)
(Concepts.Tuple.hash tuple) ) )
@@ -119,7 +118,6 @@ type binding = {root: Protocols.Handle.t; within: Protocols.Handle.t}
(* The relation a program produced has to outlive the cursor over it. *)
let enumerate_owned relation =
- let open Utilities.Result in
let owner =
object
method reference = true
@@ -127,10 +125,7 @@ let enumerate_owned relation =
method is_managed = true
end
in
- match
- let* enumerable = Protocols.Enumerable.require relation in
- Protocols.Enumerable.enumerate enumerable
- with
+ match Protocols.Enumerable.cursor relation with
| Error c -> Protocols.Handle.release relation; Error c
| Ok cursor ->
Ok
diff --git a/lib/kernel/Multigroup.ml b/lib/kernel/Multigroup.ml
index 9fbd386..669babb 100644
--- a/lib/kernel/Multigroup.ml
+++ b/lib/kernel/Multigroup.ml
@@ -192,12 +192,8 @@ module Make (S : Abstract.Storage.STORAGE) = struct
if not (Concepts.Mode.exhaustible modes BatSet.String.empty) then
Error (Error.unjudgeable name)
else
- let* enumerable = Protocols.Enumerable.require relation in
- let* cursor = Protocols.Enumerable.enumerate enumerable in
- Protocols.Handle.releasing cursor (fun () ->
- let* scan = Protocols.Cursor.require cursor in
- let* first = Protocols.Cursor.next scan in
- Ok (Option.to_list (Option.map (fun witness -> name, witness) first)) ) ) )
+ let* first = Protocols.Enumerable.scan relation Protocols.Cursor.next in
+ Ok (Option.to_list (Option.map (fun witness -> name, witness) first)) ) )
class multigroup ?bind conn value schema_tree denial_tree =
object (self)
diff --git a/lib/protocols/Cursor.ml b/lib/protocols/Cursor.ml
index f9bd697..f53bfa1 100644
--- a/lib/protocols/Cursor.ml
+++ b/lib/protocols/Cursor.ml
@@ -39,3 +39,5 @@ let drain i ?(limit = 256) () =
if batch.exhausted then Ok tuples else loop tuples
in
loop BatFingerTree.empty
+
+let consuming cursor f = Handle.releasing cursor (fun () -> Result.bind (require cursor) f)
diff --git a/lib/protocols/Cursor.mli b/lib/protocols/Cursor.mli
index ff6c027..deccf2a 100644
--- a/lib/protocols/Cursor.mli
+++ b/lib/protocols/Cursor.mli
@@ -19,3 +19,9 @@ val drain :
?limit:int ->
unit ->
(Concepts.Tuple.t BatFingerTree.t, Concepts.Condition.condition) result
+
+(** [f] over [cursor], which is released once [f] returns. *)
+val consuming :
+ Handle.t ->
+ (t Handle.interface -> ('a, Concepts.Condition.condition) result) ->
+ ('a, Concepts.Condition.condition) result
diff --git a/lib/protocols/Enumerable.ml b/lib/protocols/Enumerable.ml
index 53db834..76b4e86 100644
--- a/lib/protocols/Enumerable.ml
+++ b/lib/protocols/Enumerable.ml
@@ -19,3 +19,5 @@ let make impl = Enumerable (impl :> implementation)
let from handle = Handle.into handle (function Enumerable impl -> Some impl | _ -> None)
let require handle = from handle |> Option.to_result ~none:(Error.not_enumerable ())
let enumerate i = Handle.invoke i (fun o -> o#enumerate)
+let cursor handle = Result.bind (require handle) enumerate
+let scan handle f = Result.bind (cursor handle) (fun cursor -> Cursor.consuming cursor f)
diff --git a/lib/protocols/Enumerable.mli b/lib/protocols/Enumerable.mli
index 2c0ee69..a0c1f1c 100644
--- a/lib/protocols/Enumerable.mli
+++ b/lib/protocols/Enumerable.mli
@@ -8,3 +8,10 @@ val make : #implementation -> Handle.protocol
val from : Handle.t -> t Handle.interface option
val require : Handle.t -> (t Handle.interface, Concepts.Condition.condition) result
val enumerate : t Handle.interface -> (Handle.t, Concepts.Condition.condition) result
+val cursor : Handle.t -> (Handle.t, Concepts.Condition.condition) result
+
+(** [f] over a cursor on [handle], released once [f] returns. *)
+val scan :
+ Handle.t ->
+ (Cursor.t Handle.interface -> ('a, Concepts.Condition.condition) result) ->
+ ('a, Concepts.Condition.condition) result
diff --git a/lib/protocols/Relation.ml b/lib/protocols/Relation.ml
index c1cdfee..e475919 100644
--- a/lib/protocols/Relation.ml
+++ b/lib/protocols/Relation.ml
@@ -31,9 +31,5 @@ let heading relation =
let read relation =
let open Utilities.Result in
let* heading = heading relation in
- let* enumerable = Enumerable.require relation in
- let* cursor = Enumerable.enumerate enumerable in
- Handle.releasing cursor (fun () ->
- let* scan = Cursor.require cursor in
- let* tuples = Cursor.drain scan () in
- Ok (heading, BatFingerTree.to_list tuples) )
+ let* tuples = Enumerable.scan relation (fun scan -> Cursor.drain scan ()) in
+ Ok (heading, BatFingerTree.to_list tuples)