Remaining alignment follows cpp_generator_parity_plan.md. The Context-bound Q/E milestone is complete; full Rust generator parity remains active.
The C++ generator lives in the independent teaql_code_gen_cpp checkout on
branch cpp_support. It extends the existing Java DomainGenerationService
with scope cpp-lib-core, sharing the KSML parser, centralized pluralization
and Java/Rust naming model. No new runtime or generator dependency is added.
The generator baseline is locked in its cpp_generator.lock.json; the runtime
now targets the exact Rust v5.0.6 baseline. Earlier qualification remains
historical; see the upgrade audit.
Generated AGENTS.md starts with ASSIST.md, then links to the next entity
action in assist/<entity>/<action>.md or exact field guidance in
assist/<entity>/fields/<field>.md. Runtime support lives in assist/runtime/.
The action examples and
field/runtime guidance use existing
SDK/runtime contracts; application helper functions in their code blocks are
examples rather than additional SDK methods. Missing external utility facades
remain explicitly unavailable. Full G12 acceptance still requires the separate
assembly, sample and integration matrix.
The three source-shaped startup entries now return
Result<Ref<DataServiceExecutor>, ServiceRuntimeError>, including
serviceRuntimeFromConnection(user_context, connection). Check the Result before
schema or business execution. Business-ID domains install a managed environment
key before executor registration; ordinary domains do not read key variables.
The explicit filename configureRuntime/setup path retains manual typed-key
installation. See the startup contract and qualification boundary.
source scripts/toolchains/activate.sh
python3 scripts/generate_examples.py
python3 scripts/generate_examples.py --check
python3 scripts/format_cpp.py
python3 scripts/format_cpp.py --check
cmake --preset native
cmake --build --preset native --target teaql_generated_query_expression teaql_generated_api_tests
ctest --preset native -R '^(example_generated_query_expression|generated_api_contracts|generated_api_type_errors)$'Use --generator-dir PATH for another copy of the generator branch. Generation
builds the existing Maven reactor, then calls the local Java entry point without
a service, API key, network request or generated application dependency on Java.
Maven may need to obtain its existing build dependencies on a clean machine.
Ordinary CMake builds consume the checked-in headers and do not run Maven.
The script generates both examples/generator/model.xml and
tests/generator/types.xml, formats all emitted C++ with clang-format18.1.8,
and records source/model/formatter fingerprints. --check renders into a new
temporary directory and compares every output byte and the complete file set.
It never edits checked-in generated files. Regenerate instead of patching headers.
The implementation follows query_expression_change_plan.md. Runtime Q/E and handwritten syntax gates passed against 5.0.5 before generator migration. The generator emits thin Context-bound adapters; Phase E integration is qualified and its historical 5.0.5 evidence is recorded in that plan. The new producer/runtime reference is locked; complete 5.0.6 alignment remains open.
cpp_examples::setup(user_context);
auto Q = user_context.queries<cpp_examples::query_factory>();
auto products = Q.products().selectName();
auto lines = Q.orderLines().selectProductWith(products);
auto request = Q.orders()
.withNameIs("generated-order")
.selectLinesWith(lines)
.comment("Load the order and its products")
.purpose("Display the saved graph");
const auto& rows = cpp_examples::require_value(request.executeForList(user_context).wait());
auto product_name = cpp_examples::E::order(rows[0])
.getLines().first().getProduct().getName().unwrap();Canonical missing-load suggestions for scalar C++ keywords have callable Q/E
aliases: for example, selectClass(), unselectClass() and getClass() delegate
to the existing escaped selectModelClass(), unselectModelClass() and
getModelClass() methods. The model-specific Assist lists affected fields;
see the repair contract.
Generated E factories also supply their own static entry name to runtime
provenance, so keyword entities display E::modelClass(...) while retaining
canonical identity Class. Business calls keep the same one-argument signature;
see expression entry identity.
Application Q/E/model methods use lowerCamelCase. Runtime protocols such as
memory_resource, audit_as and wait_next, canonical metadata and SQL identifiers
retain their spelling. Entries take no Context argument. Execution takes exactly
one UserContext and must match construction. Default entries project self fields
and positive versions; ordersMinimal() selects ID/version.
purpose() produces an executable specialization. Comment and purpose need not
be adjacent; both must be nonblank at execution. executeForList returns an enhanced
typed SmartList, executeForOne an optional first match and executeForStream a
pollable typed stream. execute/executeForEntity and executeForEntityList retain
their existing one/list roles. executeForRows provides compact aggregate rows.
Generated methods delegate execution, cancellation and decoding to runtime.
Stream enhancement restrictions remain enforced.
returnType<T>() also accepts a non-Entity marker during ordinary request
construction, inspection and composition. No marker object is allocated.
All public execution entries, including compact rows/count/exists, and
newEntity require an Entity result; restore that result before execution.
The generated marker contract records
the original enclosing guards, compiler checks and Context ownership evidence.
Models provide Model::withId(user_context, id), isLoaded(field) and
setLoadState(state) over existing Value/indexed-state mechanics. The Context
argument selects the ID Value's allocation domain. State replacement copies
into the model's domain and rejects incompatible layouts before replacement;
it changes availability without changing values or staging mutations. See
entity helper entries.
The runnable example saves an audited
order/child graph, loads nested relations and exercises all three execution forms.
newEntity(user_context) delegates ID allocation; graph save uses the existing
AuditedSaveExt and audit_as(reason) protocol.
Q wrappers are values with Context-owned registered roots. Copies create independent
state, moves transfer bindings, fluent methods preserve value categories, and child
queries are checked and captured as snapshots. copyTo explicitly copies into a
UserContext; copyToGlobal delegates Global retention and rebindGlobal explicitly
changes its User access binding. Unexecuted queries are reclaimed at Context close.
E adapters use RuntimeExpression, checked EntityBorrow/EntityListBorrow and
Context-owned immutable scalar state. Scalar getters preserve eager snapshots.
Entity destruction, moves, list relocation and actual User deletion are checked
before dereference. Temporary entity bindings are deleted overloads. Wrappers can
outlive a closed/deleted User safely while Global diagnostics remain alive, but
access then fails. No hidden/shared owner extends the source lifetime.
Value, Null and NotLoaded remain distinct. Missing fields never trigger SQL and
fallbacks never hide NotLoaded. Loaded NULL/out-of-range elements are legitimate
Null; loaded empty lists have size zero. Explicit scalar copyTo or complete model
copies into a destination scope permit deliberate retention. Runtime allocation
protocols propagate into nested strings, JSON, query state and model relations.
See Q execution and
E binding for the qualified contracts and limits.
| Rust generator responsibility | C++ status |
|---|---|
| Entity/scalar metadata, ID/version, mapped columns, nullable fields, text/JSON/Decimal/date/time | Implemented; typed scalar runtime tests qualify the exercised shapes; not every schema option has a distinct semantic comparison. |
| Forward relations and reverse one/many descriptors; recursive row mapping; graph value injection | Implemented through generated mappings and existing runtime graph/query services. Nested forward/many behavior and explicit destination copies are exercised. |
| Mutation tracking and load state | Implemented through EntityRuntimeState and LoadState. Original snapshots and dirty fields remain separate from mutation values. |
| Q default/minimal projection and live-version predicate | Implemented and tested; this default is required for relation attachment keys. |
| Human/non-human predicates and centralized plurals | Implemented; paired cross-language naming tests and regular/irregular/uncountable fixtures pass. |
| Typed equality/order/range/IN predicates, boolean predicates, text predicates, projections/sort/group and scalar aggregates | Generated over the existing Expr/SelectQuery operations. Runtime range/text/boolean and relation composition are exercised; not every emitted aggregate has a separate semantic comparison. |
| Staged query intent; typed list/one/stream/compact execution; context-only runtime lookup | Implemented. Real compiler negative tests verify unavailable/incorrect operations, and runtime tests cover intent failures and context mismatch. |
| E scalar, forward/reverse and list traversal; legitimate Null versus NotLoaded; null fallbacks | Implemented with RuntimeExpression over EvalResult and checked entity/list borrows; a generated nested graph example and scalar/load-state/lifetime tests pass. |
| Inheritance | Supported in normal generation. Parent/child identity, projections/enhancement, typed decoding, graph save and lifecycle checks have source comparisons. Inherited Business IDs use the documented source binding adaptation; the untouched broken Rust artifact is preserved. See inheritance qualification. |
| Constant initialization/seeding | Supported in normal generation. Root/constant recipes, candidates, typed fields, topology, governance, overrides and cleanup are qualified with explicit source binding/Context adaptations. Invalid models still reject before output. See constant acceptance. |
| Typed checker/behavior scaffolds and candidate shortcuts | Emitted over runtime protocols. Candidate and bootstrap evidence compose in P3 acceptance; full general Checker/behavior configuration retains its own G02/G03 obligations. |
| Dynamic JSON request decoding, relation aggregates/facets and pagination optimization helpers | Generated adapters use the shared runtime. The capability ledger records scoped source/execution evidence and remaining complete model/configuration qualification. |
| Rust Cargo/web/workspace integrations and external backends | Outside the agreed C++ edge scope. Only SQLite is generated. |
| Native named-module ownership for generated domain declarations | Deferred. Generated headers can consume the existing qualified runtime module frontend. |
This adds a usable C++ generation frontend; it does not claim complete Rust generator parity. Existing handwritten examples remain unchanged reference flows. Current Q/E validation is recorded in the change plan. The initial generation evidence is historical and does not describe the new naming/binding surface.
Generated dynamic-carrier checkpoint adds the shared GeneratedDynamicFields helper, thin indexed Model install/mutation adapters, camelCase application methods and ref-qualified Q selectDynamicFields. All five fixtures regenerate and reproduce (55 files), selected Java tests pass 11/11, and 80 direct frozen entity-macro observations match. Native 5/5, targeted sanitizer 5/5 (leak scanning disabled), modules 3/3, formatting 804 files, 1,406 exports and seven facade archives pass. See generated_dynamic_fields_5_0_6.md. The original generator checkout remains untouched. Full readonly, generated configuration and remaining G01-G17/P0-P7 acceptance stay open.