aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/SubstantialRelation.ml
diff options
context:
space:
mode:
authorMarcos Magueta <maguetamarcos@gmail.com>2026-09-09 22:35:09 -0300
committerMarcos Magueta <maguetamarcos@gmail.com>2026-09-11 01:10:28 -0300
commit152f817f8dc622aec7936ace7c16ce645aaed159 (patch)
tree045d24750c7960983b366ea13afc464d518b7a3f /lib/kernel/SubstantialRelation.ml
parent8baa58d7683b092d9e27e35d46a6b9ecb61fa4ab (diff)
downloadRNT-152f817f8dc622aec7936ace7c16ce645aaed159.tar.gz
RNT-152f817f8dc622aec7936ace7c16ce645aaed159.zip
substantial relation and schematics
Diffstat (limited to 'lib/kernel/SubstantialRelation.ml')
-rw-r--r--lib/kernel/SubstantialRelation.ml64
1 files changed, 59 insertions, 5 deletions
diff --git a/lib/kernel/SubstantialRelation.ml b/lib/kernel/SubstantialRelation.ml
index eebae3e..b0c8a51 100644
--- a/lib/kernel/SubstantialRelation.ml
+++ b/lib/kernel/SubstantialRelation.ml
@@ -1,4 +1,7 @@
-module Make (S : Abstract.Storage.STORAGE) = struct
+module Make (S : Abstract.Storage.STORAGE) (Schematics : sig
+ include Protocols.Schematics.S
+ val of_blob : Concepts.Blob.t -> (Schema.t, Concepts.Condition.condition) result
+end) = struct
module SI = Storage.Make (S)
module Error = struct
@@ -107,6 +110,45 @@ module Make (S : Abstract.Storage.STORAGE) = struct
let* present = TupleSet.lookup tx tuple node in
Ok (Option.is_some present)
+ let heading_value tx relation =
+ let open Utilities.Result in
+ let* data = SI.get_req tx (S.Hash relation.heading) in
+ Schematics.of_blob data
+
+ let enumerate storage relation =
+ let open Utilities.Result in
+ let* tx = S.start storage in
+ let* node = tuple_node tx relation in
+ (* TODO: `TupleSet.keys` walks the whole Merkle structure eagerly,
+ before the first tuple is yielded. Fine for this sketch; a real
+ implementation should walk it lazily instead (its own small
+ generator, or an explicit stack over Merkle.node) so that
+ stacking e.g. `restrict` on a huge relation does not pay for the
+ entire scan before the first `next`. *)
+ let* keys = TupleSet.keys tx node in
+ let remaining = ref keys in
+ let closed = ref false in
+ let close () = if not !closed then begin closed := true; ignore (S.abort tx) end in
+ let produce ~yield =
+ let rec loop () =
+ match BatFingerTree.front !remaining with
+ | None ->
+ close ();
+ Ok ()
+ | Some (rest, addr) ->
+ remaining := rest;
+ match SI.get_req tx (S.Hash addr) |> fmap Concepts.Tuple.Representation.of_blob with
+ | Error _ as e ->
+ close ();
+ e
+ | Ok tuple ->
+ yield tuple;
+ loop ()
+ in
+ loop ()
+ in
+ Ok (Generator.cursor_of ~on_release:close produce)
+
class relation storage value =
object (self)
inherit Lifecycle.null
@@ -115,12 +157,24 @@ module Make (S : Abstract.Storage.STORAGE) = struct
method heading = Ok relation.heading
method predicate = Ok relation.predicate
method local_constraints = Ok relation.local_constraints
- method tuples = Ok relation.tuples
- method contains tuple =
- SI.with_transaction storage (fun tx -> contains_tuple tx relation tuple)
+ (* The protocol takes a tuple, not bytes: encoding is this object's business, and a caller
+ that had to produce the exact stored bytes would have to know this encoding to do it. *)
+ method contains (tuple : Concepts.Tuple.t) =
+ SI.with_transaction storage (fun tx ->
+ contains_tuple tx relation (Concepts.Tuple.Representation.to_blob tuple) )
+
+ method schema = SI.with_transaction storage (fun tx -> heading_value tx relation)
+
+ (* A substantial relation is finitely enumerable, so it carries [Enumerable] as well as
+ [Relation]. A procedural relation would carry only the latter, which is how an evaluator
+ discovers it cannot iterate one -- see [Protocols.Enumerable]. The context is accepted and
+ unused here: this enumeration reads through its own cursor-lifetime transaction and needs
+ no name resolution, but cancellation should eventually be checked between tuples. *)
+ method enumerate (_ : Protocols.Context.t) = enumerate storage relation
- method protocols : Protocols.Handle.protocol list = Protocols.[Relation.make self]
+ method protocols : Protocols.Handle.protocol list =
+ [Protocols.Relation.make self; Protocols.Enumerable.make self; Schematics.make self]
method hash = hash relation
end