Skip to content

Generate the object layer from the catalog's object model - #15

Merged
estebanzimanyi merged 2 commits into
MobilityDB:mainfrom
estebanzimanyi:gen/object-layer
Sep 2, 2026
Merged

estebanzimanyi merged 2 commits into
MobilityDB:mainfrom
estebanzimanyi:gen/object-layer

Conversation

@estebanzimanyi

Copy link
Copy Markdown
Member

The catalog's objectModel is the ecosystem-wide source of truth for the
class hierarchy implicit in MEOS: lattice carries the temporal tree,
companions the Box and Collection hierarchies, and
classes.<Class>.methods assigns every public MEOS function to the class it
is a method of, with its canonical camelCase name. objectgen.py projects
that model onto C# — 93 classes and 578 methods over the current catalog,
one file per class under MEOS.NET/Types/Generated/ — so the object layer
is derived rather than curated, and a family MEOS adds arrives with the next
catalog refresh.

Inheritance follows the model's own parent edges. A concrete class is the
product leaf x subtype — TFloatSeq, TGeomPointInst — and inherits its
leaf, which carries by far the larger surface. Every method delegates to the
MEOSExposedFunctions wrapper of the function the model assigns it and
reads that wrapper's signature from codegen.py, so the two generators
cannot disagree about a folded out-parameter.

A returned MEOS pointer goes through MEOSFactory, which reads the
discriminator the catalog's own struct layout puts in the value's header —
Temporal.temptype and Temporal.subtype, Set.settype, Span.spantype,
SpanSet.spansettype — and hands back the exact class, so TFloat.In over
an instant answers a TFloatInst and over a sequence a TFloatSeq. Every
temporal struct begins with the Temporal header, so a TInstant * or
TSequence * return is a Temporal at the surface whose runtime class is
the concrete one; modelling those as classes of their own would spend a
concrete class's one base on the template axis instead of its family.

The 314 methods the layer does not emit are named with their reason by
--report, which CI runs: a GSERIALIZED * geometry, an Interval *, a
Pose *, a counted array argument, a scalar out-parameter. T *values, int count is MEOS's counted-array convention, so wrapping that pointer as
one object would hand the callee a single element and a length that lies;
those are left to the raw binding, which carries every function either way.

Twelve tests read the surface against the library the provisioning builds:
the class a text form answers, the instants a sequence holds, the moment a
timestamp names, the value extent of a temporal float, the spans a float
span set holds and their text, the time domain of a sequence, and the error
a malformed text raises.

The Utf8 string marshaller frees the pointer a `char *` return hands back.
That is right for a string MEOS mallocs for the caller and fatal for the
`const char *` it returns out of a static table: `temporal_interp` answers
with an element of `MEOS_INTERPTYPE_NAMES`, and freeing that ends the
process — `Test host process crashed : free(): invalid pointer`. The
eleven functions whose return is `const char *` — `temporal_interp`,
`temporal_subtype`, `temporal_basetype_name`, `meostype_name` and their
kin — come back as the pointer itself and are read with
`Marshal.PtrToStringUTF8`, which copies and frees nothing.

Three tests read an interpolation name: off a linear sequence, off a
discrete one, and off two temporal values in turn. They exercise the native
library, so the test step takes the LD_LIBRARY_PATH of the prefix the
provisioning built, as the smoke step does, and every test class opens a
MEOS session of its own: MEOS keeps the timezone its text I/O goes through
and the error handler per thread, and the test host runs a test on
whichever thread it has free, so a session opened once for the assembly
reaches the thread that opened it and no other.
The catalog's `objectModel` is the ecosystem-wide source of truth for the
class hierarchy implicit in MEOS: `lattice` carries the temporal tree,
`companions` the Box and Collection hierarchies, and
`classes.<Class>.methods` assigns every public MEOS function to the class it
is a method of, with its canonical camelCase name. `objectgen.py` projects
that model onto C# — 93 classes and 578 methods over the current catalog,
one file per class under `MEOS.NET/Types/Generated/` — so the object layer
is derived rather than curated, and a family MEOS adds arrives with the next
catalog refresh.

Inheritance follows the model's own parent edges. A concrete class is the
product leaf x subtype — `TFloatSeq`, `TGeomPointInst` — and inherits its
leaf, which carries by far the larger surface. Every method delegates to the
`MEOSExposedFunctions` wrapper of the function the model assigns it and
reads that wrapper's signature from `codegen.py`, so the two generators
cannot disagree about a folded out-parameter.

A returned MEOS pointer goes through `MEOSFactory`, which reads the
discriminator the catalog's own struct layout puts in the value's header —
`Temporal.temptype` and `Temporal.subtype`, `Set.settype`, `Span.spantype`,
`SpanSet.spansettype` — and hands back the exact class, so `TFloat.In` over
an instant answers a `TFloatInst` and over a sequence a `TFloatSeq`. Every
temporal struct begins with the Temporal header, so a `TInstant *` or
`TSequence *` return is a `Temporal` at the surface whose runtime class is
the concrete one; modelling those as classes of their own would spend a
concrete class's one base on the template axis instead of its family.

The 314 methods the layer does not emit are named with their reason by
`--report`, which CI runs: a `GSERIALIZED *` geometry, an `Interval *`, a
`Pose *`, a counted array argument, a scalar out-parameter. `T *values,
int count` is MEOS's counted-array convention, so wrapping that pointer as
one object would hand the callee a single element and a length that lies;
those are left to the raw binding, which carries every function either way.

Twelve tests read the surface against the library the provisioning builds:
the class a text form answers, the instants a sequence holds, the moment a
timestamp names, the value extent of a temporal float, the spans a float
span set holds and their text, the time domain of a sequence, and the error
a malformed text raises.
@estebanzimanyi
estebanzimanyi merged commit a854c88 into MobilityDB:main Sep 2, 2026
1 check passed
@estebanzimanyi
estebanzimanyi deleted the gen/object-layer branch September 2, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant