Follow properties into generated parameters¶
Run the tutorial with --extended. It generates Point(x, y) and Size(x) from
two class rows and five field rows. The same field spelling x belongs to two
owners. A hidden field and an orphan row make incorrect selection visible.
Input rows¶
| ClassId | ClassName | ClassOrder | SlotNames |
|---|---|---|---|
| point | Point | 10 | x, y |
| size | Size | 20 | x |
| FieldId | Owner | FieldName | FieldOrder | Selected |
|---|---|---|---|---|
| point.y | point | y | 20 | True |
| point.x | point | x | 10 | True |
| point.hidden | point | hidden | 30 | False |
| size.x | size | x | 10 | True |
| orphan.z | absent | z | 99 | True |
Fields uses FieldId as collection identity. The semantic property FieldName
is populated with the generated constructor keyword field_name. Neither is the
runtime field value, which is supplied later to Point(3, 4).
Selection, projection and destination¶
InitProduction(cls: Classes) retains the current class as context. Each from
field: Fields enumerates candidates and where Owner == ClassId and Selected ==
True relates them to that class. This is explicit filtering, not an implicit
keyed join. For Point, point.y and point.x survive; for Size, only size.x
survives. No class can match orphan.z.
Params(cls: Classes, field: Fields) chooses Param. Its ident field_name =
FieldName turns the chosen name into a Python parameter identifier.
Assignment binds the same property as ident value and external slot for the
outer parameter read and direct attribute target. Target params or stores
resolves against /InitMethod within the nested production's mapped root.
Build index (ClassOrder, FieldOrder) identifies an insertion independently of
its collection identity. order FieldOrder determines parameter/store sequence.
The facts are deliberately inserted y before x, but output is x before y:
Source authority: tests/data/goldens/materialized/documentation_classes/extended_model.py.
class Point:
__slots__ = ('x', 'y')
pass
def __init__(self, x, y):
pass
pass
self.x = x
self.y = y
class Size:
__slots__ = ('x',)
pass
def __init__(self, x):
pass
pass
self.x = x
M01–M10 contract map¶
| Case | Contract and executable evidence |
|---|---|
| M01 subset/properties | Tutorial selects FieldName while identity/owner/order have separate roles |
| M02 inputs/combinations | Tutorial contextual class + field filtering; standalone yidl_update_a_multi_source_from.py enumerates two sources; empty collection contributes nothing |
| M03 view/lookup | dds_composite_identity_lookup.py: tuple key (TxKey, Phase), explicit projection; a computed view filters existing records |
| M04 ownership/ambiguity | DDS Python API input.prop(property) is explicit; contribution syntax exposes visible semantic names and rejects duplicates; do not invent field.FieldName there |
| M05 selection | test_matcher.py: broad/narrow, weight, default, no-match, overlap; contribution rules are separately checked |
| M06 evaluated fields | matcher.evaluated_field(..., inputs=(left,right), value=callable, value_type=...) derives tuple entries; emitted evaluators require an importable/generated name |
| M07 projection | dds_matcher_productions.py: match.record("field").prop(name) versus match.value(0); invalid tuple index/name diagnostics are tested |
| M08 context | Tutorial retains cls; unavailable/duplicate visible properties reject rather than guessed qualification |
| M09 bindings/parameters | Tutorial maps one property to parameter identifier, outer read and attribute path; captures/defaults remain consumer policy |
| M10 identity/order | Tutorial numeric composite index avoids two-owner collisions; ClassId/FieldId, owner, name, index, order and target remain distinct |
Original records versus extracted values¶
Generic matcher-result productions offer three different expressions:
match.resource() # selected generated value
match.record("field").prop(name) # original input record's property
match.value(0) # positional extracted/evaluated tuple entry
The tuple schema includes fields demanded by conditions/evaluators, not every
property of every input record. Inspect matcher.tuple_schema; never assume
index zero means the first record's first declared property. This complete
canonical example demonstrates the projection and generated operation snapshot:
Source authority: tests/data/gold_src/dds_matcher_productions.py.
from __future__ import annotations
from support.golden_case import run_case
from yidl.generation.data_def_sys import AddIfAbsent
from yidl.generation.data_def_sys import DataDefinitionSystem
from yidl.generation.data_def_sys import REQUIRED
from yidl.generation.data_def_sys import emit_container_runtime_source
from yidl.generation.data_def_sys import from_astichi_code
from yidl.generation.data_def_sys import match
from yidl.generation.data_def_sys import read
REQUIRED_TEMPLATE = from_astichi_code("{'param': 'required'}")
DEFAULTED_TEMPLATE = from_astichi_code("{'param': 'defaulted'}")
def _build_dds() -> DataDefinitionSystem:
dds = DataDefinitionSystem()
name = dds.property("Name", str, default=REQUIRED, storage_name="name")
init = dds.property("Init", bool, default=True, storage_name="init")
defaulted = dds.property(
"Defaulted",
bool,
default=False,
storage_name="defaulted",
)
order = dds.property("Order", int, default=0, storage_name="order")
target_port = dds.property(
"TargetPort",
object,
default=REQUIRED,
storage_name="target_port",
)
template = dds.property(
"Template",
object,
default=REQUIRED,
storage_name="template",
)
field = dds.record("Field", name, init, defaulted, order)
param = dds.record("ParamComponent", name, target_port, order, template, defaulted)
fields = dds.collection("Fields", field, cardinality=dds.many, identity=name)
init_fields = dds.computed_collection(
"InitFields",
source=fields,
when=(init.eq(True),),
)
params = dds.collection("Params", param, cardinality=dds.many, identity=name)
init_params = dds.port("Init.params", cardinality=dds.many)
dds.port_index(target=target_port, order=order)
matcher = dds.matcher("InitParamTemplate")
field_input = matcher.input("field", init_fields)
matcher.default(REQUIRED_TEMPLATE)
matcher.rule(
when=(field_input.prop(defaulted).eq(True),),
resource=DEFAULTED_TEMPLATE,
name="defaulted-param",
)
production = dds.production(
"InitParamTemplateProvidesParam",
source=matcher.results(),
target=params,
values={
name: match.record("field").prop(name),
target_port: init_params.of(("Example", "__init__")),
order: match.record("field").prop(order),
template: match.resource(),
defaulted: match.value(0),
},
policy=AddIfAbsent,
)
dds.production_group("FieldChildren", production)
return dds
def render_case() -> str:
return emit_container_runtime_source(_build_dds())
def validate_case(source: str) -> None:
namespace: dict[str, object] = {}
exec(source, namespace)
builder = namespace["new_builder"]()
field = namespace["Field"]
fields = namespace["FieldsCollection"]
init_params = namespace["InitParamsPort"]
builder.add(fields, field(name="count", init=True, defaulted=False, order=1))
builder.add(fields, field(name="label", init=True, defaulted=True, order=2))
builder.add(fields, field(name="skip", init=False, defaulted=True, order=0))
container = namespace["build_container"](builder)
runtime_params = init_params.of(("Example", "__init__"))
children = container.children_at(runtime_params)
assert [record.name for record in children] == ["count", "label"]
assert [record.template for record in children] == [
REQUIRED_TEMPLATE,
DEFAULTED_TEMPLATE,
]
assert [record.defaulted for record in children] == [False, True]
assert "snapshot = builder._snapshot()" in source
assert "snapshot.matchers.InitParamTemplate.sequence()" in source
assert "source.resource" in source
assert "source.records[0].name" in source
assert "source.values[0]" in source
assert source.index("from itertools import product") < source.index("_NameProperty")
assert source.index("from yidl.generation.data_def_sys import") < source.index(
"_NameProperty"
)
assert source.index("from_astichi_code") < source.index("_NameProperty")
assert source.count("from itertools import product") == 1
assert source.count("from yidl.generation.data_def_sys import") == 1
assert "dds.matcher_production" not in source
assert "dds.production(" not in source
if __name__ == "__main__":
raise SystemExit(
run_case("dds_matcher_productions.py", render_case, validate_case)
)
For multi-input derived values, the evaluator receives inputs in its declared
inputs order. Source emission cannot serialize an arbitrary closure. Conditions
on the derived field can select a generated value; original records remain
available separately. Matchers gives selection rules;
consumer excerpts show real constructor/accessor uses.
A derived value from two original inputs¶
This exact existing test is the minimal in-memory Python-API recipe. Four combinations yield one selected result; original records remain ordered field, facade, while the extracted tuple contains only the derived boolean.
Source authority: tests/generation/test_matcher.py.
def test_evaluated_field_can_depend_on_multiple_inputs() -> None:
dds = DataDefinitionSystem()
field_name = dds.property("FieldName", str, default=REQUIRED, storage_name="field_name")
facade_name = dds.property(
"FacadeName",
str,
default=REQUIRED,
storage_name="facade_name",
)
field_spec = dds.record("FieldSpec", field_name)
facade_spec = dds.record("FacadeSpec", facade_name)
fields = dds.collection(
"Fields",
field_spec,
cardinality=dds.many,
identity=field_name,
)
facades = dds.collection(
"Facades",
facade_spec,
cardinality=dds.many,
identity=facade_name,
)
matcher = dds.matcher("Visibility")
field = matcher.input("field", fields)
facade = matcher.input("facade", facades)
visible = matcher.evaluated_field(
"Visible",
inputs=(field, facade),
value=lambda field_record, facade_record: (
field_record.field_name == "count"
and facade_record.facade_name == "runtime"
),
value_type=bool,
)
visible_resource = from_literal("visible")
matcher.rule(
name="visible",
when=(visible.eq(True),),
resource=visible_resource,
)
runtime = matcher.runtime()
results = tuple(
runtime.sequence(
(
field_spec.record(field_name="count"),
field_spec.record(field_name="label"),
),
(
facade_spec.record(facade_name="runtime"),
facade_spec.record(facade_name="debug"),
),
)
)
assert len(results) == 1
assert results[0].resource is visible_resource
assert results[0].records[0].field_name == "count"
assert results[0].records[1].facade_name == "runtime"
assert results[0].values == (True,)
For emitted runtime source, use emit_matcher_runtime_source with explicit
evaluator_names=((callable, "generated_name"),) and provide that callable under
the declared name in the runtime namespace (or an import at the owning boundary).
The canonical matcher_runtime.py fixture exercises this emission contract. A
lambda in the in-memory example is not by itself an emitted evaluator.