From 68295a4ac3aefa39349eee44bc5b620f2582addd Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Thu, 3 Sep 2026 13:18:44 +0200 Subject: [PATCH] Give the nearest-neighbour cursors classes of their own MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `rtree_nn_cursor_open` answers an `RTreeNNCursor *` that `_next` walks and `_close` frees, and `sptree_nn_cursor_*` do the same for an `SPNNCursor *`. Both types are `typedef struct X X;` in `meos.h` — published without their layout, registered in no enum — so they are `Value` leaves stating a null temptype, as `RTree` and `SPTree` themselves are. The three cursor entries move off the tree's class onto the cursor's, longest prefix winning: a cursor is opened FROM a tree and then walked on its own, so `open` belongs to the cursor it answers rather than among the tree's twenty methods. RTree and SPTree read 20 methods each against 23, and the cursors 3. Without a class for the cursor a binding reaches none of the three, which is the whole kNN surface: the tree can be built and searched by containment while the question "which entries are nearest" has no answer. --- docs/object-model.md | 3 ++- meta/object-model.json | 18 ++++++++++++++++++ tests/test_object_model.py | 3 ++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/object-model.md b/docs/object-model.md index 3a20c4a..35f8be1 100644 --- a/docs/object-model.md +++ b/docs/object-model.md @@ -125,7 +125,8 @@ that set from the two predicates and fails until each has a class, so a base type MEOS adds reaches the model with no edit to the file. `Nsegment`, `Raquet` and `JsonPath` are the MeosTypes no membership predicate admits; the model states them, and the same gate states that it -does. `Pcschema`, `RTree`, `SPTree` and `MeosArray` go further: MEOS +does. `Pcschema`, `RTree`, `RTreeNNCursor`, `SPTree`, `SPNNCursor` and +`MeosArray` go further: MEOS registers them in no enum at all, and they say so with a null `temptype` rather than by leaving the field out. To a binding a pointer to a struct is one thing — an instance it holds and calls through — whether MEOS diff --git a/meta/object-model.json b/meta/object-model.json index cd1c751..4b47a51 100644 --- a/meta/object-model.json +++ b/meta/object-model.json @@ -726,6 +726,15 @@ "temptype": null, "doc": "MEOS's in-memory R-tree over spans, boxes and their kin. MEOS registers it in no enum, so it names no temptype." }, + "RTreeNNCursor": { + "kind": "leaf", + "parent": "Value", + "prefixes": [ + "rtree_nn_cursor" + ], + "temptype": null, + "doc": "A walk over an R-tree's entries in order of distance from a query. MEOS registers it in no enum, so it names no temptype." + }, "SPTree": { "kind": "leaf", "parent": "Value", @@ -735,6 +744,15 @@ "temptype": null, "doc": "MEOS's in-memory SP-tree, the R-tree's sibling over the same key types. MEOS registers it in no enum, so it names no temptype." }, + "SPNNCursor": { + "kind": "leaf", + "parent": "Value", + "prefixes": [ + "sptree_nn_cursor" + ], + "temptype": null, + "doc": "The SP-tree's nearest-neighbour walk, the R-tree cursor's sibling. MEOS registers it in no enum, so it names no temptype." + }, "MeosArray": { "kind": "leaf", "parent": "Value", diff --git a/tests/test_object_model.py b/tests/test_object_model.py index a8dbbc4..987b1ff 100644 --- a/tests/test_object_model.py +++ b/tests/test_object_model.py @@ -241,7 +241,8 @@ def test_a_type_meos_registers_in_no_enum_still_gets_a_class(self): unregistered = {n for n, s in nodes.items() if s["kind"] == "leaf" and s["temptype"] is None} self.assertEqual(unregistered, - {"Pcschema", "RTree", "SPTree", "MeosArray"}) + {"Pcschema", "RTree", "RTreeNNCursor", "SPTree", + "SPNNCursor", "MeosArray"}) def test_a_function_named_as_its_own_prefix_still_has_a_member_name(self): # `meos_pc_schema` IS its class's prefix, so dropping the prefix leaves