Data dictionary
The data dictionary is the resolved form of a project: every data object with its owner, its users, its shape, its limits and its scaling already worked out. It is the contract between the checking front end of DDD and its output backends, and it is the only thing they share. Everything before it - loading the description files, resolving the declarations, running the consistency checks - produces a dictionary; everything after it - the c backend, the a2l backend, whatever is added next - consumes one and nothing else. A backend therefore never reaches into the loader or into the analysis, and if it needs to know something, that something is a field of the dictionary rather than a second calculation performed in a template.
That arrangement is worth having for two reasons. The first is that two backends cannot
disagree about what a project contains: the shape a c array is declared with and the
MATRIX_DIM written into the a2l are read from one field, so they cannot drift apart -
each backend only has to order the indices the way its own format wants them, c with the
last index running fastest and ASAP2 with the first. The second is that the work of
resolving a project is done once, in a place that reports findings, instead of once per
output format in a place that can only crash.
DDD publishes the dictionary rather than keeping it to itself. ddd dump writes it out as
json, and ddd schema dictionary prints its json schema, so a generator DDD does not ship
- a report, a database importer, a header for a language DDD knows nothing about - can
consume a checked project without importing python and without depending on any of the
implementation:
ddd dump examples/demo/demo.ddd.json > dictionary.json
ddd schema dictionary > dictionary.schema.json
$ ddd dump examples/demo/demo.ddd.json
{
"format": 4,
"name": "DemoDevice",
"description": "Demonstration project showing every DDD feature",
"source": "demo.ddd.json",
"components": [
{
"name": "Controller",
"description": "Consumes the raw values and produces the derived ones",
"source": "controller.ddd.json",
"declarations": [
{
"name": "ValueA",
"scope": "input",
"condition": null
},
...
ddd dump is the one command whose standard output is the payload, so its findings go
to standard error and the redirection above works whether or not the project has any. The
same file is what comparing two deliveries needs: archive the
dictionary of a delivery next to its binary, and a later ddd compare can answer whether
the next delivery may replace it, long after the sources of the first one have moved on.
What is already resolved
The value of the dictionary is what a backend no longer has to work out. By the time a backend sees it:
The limits are filled in. limits is never absent. A declaration that states its
physical limits keeps them; one that does not gets the full range its datatype and
conversion imply, computed once. A backend writing LOWER_LIMIT and UPPER_LIMIT into
an a2l therefore never has to decide what a missing limit means, and cannot decide it
differently from anybody else.
The shape is a tuple of dimensions, empty for a scalar, and it is complete even when the
description file never stated it. A measurement or a value block declares its dimensions
and an axis its size, but a curve and a map deliberately do not repeat the size of their
tables: they name the axes they are interpolated over, and the shape follows from those. The
demo project declares CurveA like this - no limits, no dimensions:
{
"scope": "local",
"definition": {
"kind": "curve",
"name": "CurveA",
"description": "Calibratable curve over AxisA",
"datatype": "uint16",
"unit": "ms",
"conversion": { "factor": 0.01 },
"axis": "AxisA",
"init": [1200, 900, 800, 750, 700, 650],
"volatile": false
}
}
and the dictionary hands the backends this:
{
"name": "CurveA",
"kind": "curve",
"datatype": "uint16",
"description": "Calibratable curve over AxisA",
"unit": "ms",
"conversion": { "kind": "linear", "factor": 0.01, "offset": 0.0 },
"limits": { "min": 0.0, "max": 655.35 },
"shape": [6],
"dimensions": [6],
"init": [1200, 900, 800, 750, 700, 650],
"section": null,
"volatile": false,
"condition": null,
"references": { "axis": "AxisA" },
"owner": "Controller",
"consumers": [],
"local": true,
"a2l": { "export": true, "format": null, "display_identifier": null }
}
The six points come from AxisA, and the limits from the full uint16 range through
the linear conversion: 65535 raw counts of 0.01 ms are 655.35 ms. dimensions is the same
shape again, spelled the way the project spells it: here the number, and for an array
dimensioned by a declared constant the constant’s name, so a
generator can declare the array by the name while sizing it by the number. The kind of the
conversion, left out of the description because a block carrying a factor can only be
linear, is spelled out. Both blocks above are folded onto fewer lines than the files
themselves use; the values are exactly the ones in examples/demo and in the dump of it.
The owner and the consumers are worked out. owner names the component whose
declaration was taken as the authoritative one, consumers lists the components that
declared the object as an input, and local says whether the owner keeps it to itself.
This is what lets the c backend group the definitions by owning component and emit a header
per component that contains that component’s interface and nothing else, and what lets the
a2l backend build one GROUP per component - without either of them knowing anything
about scopes, ownership rules or how a disagreement between two components is settled.
Where components disagreed, the producing component’s declaration is the one that
survives: the analysis reports the disagreement against the deviating consumer and puts
the producer’s definition into the dictionary, so a backend never sees two versions of one
object.
The condition is the producing declaration’s. A variable that only exists when a
preprocessor symbol is defined carries that expression here, which is what the c backend
wraps in #if and what the a2l backend notes in a comment, a2l having no notion of
conditional compilation.
The objects are sorted by name and the enumerations are collected, de-duplicated and sorted by name as well, so that a generated file depends on the content of a project and not on the order in which its files happened to be read. Together with the include patterns being expanded in sorted order and the generated files carrying no time stamp, that is what makes a regeneration without an input change produce a byte identical result - and therefore what lets a build system skip the recompilation. The components, by contrast, keep the order in which the project included them, and the declarations of a component keep the order the author wrote them in, because that order is information: it is how the interface of a component reads in its own file, and it is how it reads in its generated header.
Note
owner may be null, but only for a project that is already known to be
inconsistent and is being generated anyway with ddd generate --force. Every other
field is always present.
The format field
A dumped dictionary is meant to be archived next to a delivery and read back by a later
version of DDD, possibly years later. The format field stamps the shape of the document
- currently 4 - and changes only when that shape changes, not with every release of the
tool.
It exists so that a later reader can say this file is newer than I understand rather than misread it. DDD accepts a dictionary whose format is the one it knows or older, and refuses one that is newer:
$ ddd compare baseline.json demo.ddd.json
baseline.json#format: error[schema]: in the baseline: this dictionary is in format 5, and this DDD understands up to 4; use a newer DDD to read it
1 error
Refusing is the only safe answer: reading the file anyway would compare a delivery against fields this version does not know about, and quietly report every one of them as unchanged - which is precisely the verdict that would let a broken delivery out of the door. The rule is one-directional on purpose, so that a new DDD keeps reading the dictionaries archived by older ones.
That is also why a field of the dictionary may keep a default the description files no longer
allow. volatile has to be stated by every definition an author writes, but the dictionary
still defaults it to false, so a dictionary dumped by an older DDD still reads back and can
still be compared against, instead of a required field turning every archived document into a
file this version refuses.
Warning
A dictionary is a snapshot of a project, not a description of it. ddd generate and
ddd check read description files; the dictionary is what ddd compare reads back
and what a foreign generator consumes. Treat it as an artefact of a build - archive it,
do not edit it, and do not maintain a project in it.
Consuming it from another tool
The document is plain json, described by a published schema, and it round-trips: a
dictionary written by ddd dump and read back is the same dictionary, and a backend fed
the reloaded document produces byte identical output. Both properties are asserted by the
test suite (tests/test_backends.py), because they are the whole point of publishing the
contract - a third party generating from a dumped dictionary has to get what DDD would have
got.
ddd schema dictionary prints the whole thing, definitions included; its top level, which
is where a consumer starts, is this (the per field documentation the schema also carries is
elided here for space):
{
"additionalProperties": false,
"description": "The resolved data of one project.",
"properties": {
"format": {
"default": 4,
"title": "Format",
"type": "integer"
},
"name": {
"maxLength": 128,
"minLength": 1,
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
"title": "Name",
"type": "string"
},
"description": {
"default": "",
"title": "Description",
"type": "string"
},
"source": {
"default": "",
"title": "Source",
"type": "string"
},
"components": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedComponent"
},
"title": "Components",
"type": "array"
},
"objects": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedObject"
},
"title": "Objects",
"type": "array"
},
"enums": {
"default": [],
"items": {
"$ref": "#/$defs/EnumConversion"
},
"title": "Enums",
"type": "array"
},
"constants": {
"default": [],
"items": {
"$ref": "#/$defs/ConstantDeclaration"
},
"title": "Constants",
"type": "array"
},
"types": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedStruct"
},
"title": "Types",
"type": "array"
},
"instances": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedInstance"
},
"title": "Instances",
"type": "array"
},
"leaves": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedLeaf"
},
"title": "Leaves",
"type": "array"
}
},
"required": [
"name"
],
"title": "DDD data dictionary",
"type": "object"
}
additionalProperties is false here as it is everywhere else in DDD, so a consumer
validating against the schema finds a key it was not expecting instead of skipping it.
enums carries the distinct enumerations the objects use, so a consumer that wants to
emit a type per enumeration - which is what the c backend offers its templates as
model.enums - does not have to walk every object and de-duplicate them itself.
constants records the declared constants whole - name,
value and description - so a dimension an object spells by name stays resolvable from the
document alone. The
conversions themselves are the same models the description files use, and they are documented
with the other data contracts. types, instances and
leaves describe the structured variables: the declared structures, the variables
instantiating one, and the member objects each instance flattens into.
Reference
The dictionary is a pydantic model like every other contract, which means it is validated when the analysis hands it over: a bug in the front end surfaces at that boundary rather than half way through a jinja template.
- pydantic model DataDictionary[source]
The resolved data of one project.
What
ddd dumpwrites and every backend reads. Unlike the description files, this one is produced rather than authored: every derived property is already worked out, so a consumer never has to repeat the resolution and two consumers can never disagree about it.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ComponentDeclaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ComponentDeclaration</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>scope</td><td port="scope">Scope</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr></table>>,
tooltip="ddd.ir.ComponentDeclaration

One entry of a component interface, in the order the component declared it.

A reference \
to an object rather than the object itself: the definition lives once, under
``objects``, and is the one the producing component \
gave. Two components declaring the
same name appear here twice and in ``objects`` once.
"];
"ddd.ir.DataDictionary" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>DataDictionary</b></td></tr><tr><td>format</td><td port="format">int</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>source</td><td port="source">str</td></tr><tr><td>components</td><td port="components">tuple[ResolvedComponent, ...]</td></tr><tr><td>objects</td><td port="objects">tuple[ResolvedObject, ...]</td></tr><tr><td>enums</td><td port="enums">tuple[EnumConversion, ...]</td></tr><tr><td>constants</td><td port="constants">tuple[ConstantDeclaration, ...]</td></tr><tr><td>types</td><td port="types">tuple[ResolvedStruct, ...]</td></tr><tr><td>instances</td><td port="instances">tuple[ResolvedInstance, ...]</td></tr><tr><td>leaves</td><td port="leaves">tuple[ResolvedLeaf, ...]</td></tr></table>>,
tooltip="ddd.ir.DataDictionary

The resolved data of one project.

What ``ddd dump`` writes and every backend reads. Unlike \
the description files, this one
is produced rather than authored: every derived property is already worked out, so a
consumer \
never has to repeat the resolution and two consumers can never disagree about it.
"];
"ddd.ir.ResolvedComponent" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedComponent</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>source</td><td port="source">str</td></tr><tr><td>declarations</td><td port="declarations">tuple[ComponentDeclaration, ...]</td></tr></table>>,
tooltip="ddd.ir.ResolvedComponent

A component and the objects it declares.
"];
"ddd.ir.DataDictionary":components:e -> "ddd.ir.ResolvedComponent":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedInstance" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedInstance</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>type</td><td port="type">str</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>shape</td><td port="shape">tuple[int, ...]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>owner</td><td port="owner">str | None</td></tr><tr><td>consumers</td><td port="consumers">tuple[str, ...]</td></tr><tr><td>local</td><td port="local">bool</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.ir.ResolvedInstance

One variable whose datatype is a structure.

Kept apart from :class:`ResolvedObject` rather \
than widening it: an object with no datatype
and no limits would turn every reader of those two fields into a branch, and they \
are read
unconditionally in a dozen places on the strength of always being there.
"];
"ddd.ir.DataDictionary":instances:e -> "ddd.ir.ResolvedInstance":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedLeaf" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedLeaf</b></td></tr><tr><td>path</td><td port="path">str</td></tr><tr><td>instance</td><td port="instance">str</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr><tr><td>datatype</td><td port="datatype">Datatype</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">IdentityConversion | LinearConversion | EnumConversion</td></tr><tr><td>limits</td><td port="limits">Limits</td></tr><tr><td>shape</td><td port="shape">tuple[int, ...]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">int | None</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>owner</td><td port="owner">str | None</td></tr><tr><td>consumers</td><td port="consumers">tuple[str, ...]</td></tr><tr><td>local</td><td port="local">bool</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.ir.ResolvedLeaf

One member of one structured variable, at the end of one access path.

The flattening. A structure \
reaches the a2l as an object per member rather than as an a2l
structure, so this is the form that backend consumes - an ordinary \
object in every respect
but its name, which is a path rather than an identifier.
"];
"ddd.ir.DataDictionary":leaves:e -> "ddd.ir.ResolvedLeaf":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedObject" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedObject</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr><tr><td>datatype</td><td port="datatype">Datatype</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">IdentityConversion | LinearConversion | EnumConversion</td></tr><tr><td>limits</td><td port="limits">Limits</td></tr><tr><td>shape</td><td port="shape">tuple[int, ...]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>references</td><td port="references">dict[str, str]</td></tr><tr><td>owner</td><td port="owner">str | None</td></tr><tr><td>consumers</td><td port="consumers">tuple[str, ...]</td></tr><tr><td>local</td><td port="local">bool</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.ir.ResolvedObject

One data object, with every derived property already worked out.
"];
"ddd.ir.DataDictionary":objects:e -> "ddd.ir.ResolvedObject":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedStruct" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedStruct</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>members</td><td port="members">tuple[ResolvedMember, ...]</td></tr></table>>,
tooltip="ddd.ir.ResolvedStruct

One structure, in an order a c file can be written out in.

The order of :attr:`DataDictionary.types` \
matters and is not alphabetical: a structure
appears after every structure it nests, because a c compiler needs the nested one \
to be
complete first. The members keep the order the author wrote them in, which is the order the
compiler lays them out.&#\
xA;"];
"ddd.ir.DataDictionary":types:e -> "ddd.ir.ResolvedStruct":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.constants.ConstantDeclaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ConstantDeclaration</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.constants.ConstantDeclaration

One named integer constant, declared once and named wherever a shape needs it.&#\
xA;"];
"ddd.ir.DataDictionary":constants:e -> "ddd.models.constants.ConstantDeclaration":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.ir.DataDictionary":enums:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedComponent":declarations:e -> "ddd.ir.ComponentDeclaration":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.ir.ResolvedInstance":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedLeaf":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.ir.ResolvedLeaf":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedMember" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedMember</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>type</td><td port="type">str | None</td></tr><tr><td>external</td><td port="external">str | None</td></tr><tr><td>header</td><td port="header">str | None</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">int | None</td></tr></table>>,
tooltip="ddd.ir.ResolvedMember

One member of a structure, as the c templates need it to declare the member.

Only what a \
declaration takes. The meaning of the member - its unit, its conversion, its
limits - travels with the *leaf* instead, because \
that is the form the a2l consumes and
there is no second place a reader should have to look.
"];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedObject":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedObject":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedStruct":members:e -> "ddd.ir.ResolvedMember":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-4164c74586da681515a943775b135db07eb60092.png)
Show JSON schema
{ "title": "DDD data dictionary", "description": "The resolved data of one project.\n\nWhat ``ddd dump`` writes and every backend reads. Unlike the description files, this one\nis produced rather than authored: every derived property is already worked out, so a\nconsumer never has to repeat the resolution and two consumers can never disagree about it.", "type": "object", "properties": { "format": { "default": 4, "description": "Version of this document format, raised only when the shape of the document changes.\n\nStamped so that a dictionary archived next to a delivery can be read back years later by\na version of DDD that can say \"this file is newer than I understand\" rather than misread\nit. It does not follow the version of the tool.", "title": "Format", "type": "integer" }, "name": { "description": "Name of the project, from the root project description.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text from the root project description.", "title": "Description", "type": "string" }, "source": { "default": "", "description": "Name of the root description file, for reference in generated comments.", "title": "Source", "type": "string" }, "components": { "default": [], "description": "Every component of the project, including those of its sub-projects.", "items": { "$ref": "#/$defs/ResolvedComponent" }, "title": "Components", "type": "array" }, "objects": { "default": [], "description": "Sorted by name, so that every backend produces a stable output.", "items": { "$ref": "#/$defs/ResolvedObject" }, "title": "Objects", "type": "array" }, "enums": { "default": [], "description": "Distinct enumerations used by the objects, sorted by name.", "items": { "$ref": "#/$defs/EnumConversion" }, "title": "Enums", "type": "array" }, "constants": { "default": [], "description": "The named constants the project declares, sorted by name.\n\nRecorded whole - name, value and description - so that a generator consuming the\ndictionary can emit them the way the shipped templates do, and so that a dimension\nspelled by name stays resolvable after the description files have moved on.", "items": { "$ref": "#/$defs/ConstantDeclaration" }, "title": "Constants", "type": "array" }, "types": { "default": [], "description": "The structures the project declares, each after every structure it nests.\n\nDependency order rather than alphabetical, because a template that simply loops over them\nhas to be able to write them out as they come: c needs a nested structure to be complete\nbefore the one that contains it.", "items": { "$ref": "#/$defs/ResolvedStruct" }, "title": "Types", "type": "array" }, "instances": { "default": [], "description": "Variables whose datatype is a structure, sorted by name.", "items": { "$ref": "#/$defs/ResolvedInstance" }, "title": "Instances", "type": "array" }, "leaves": { "default": [], "description": "Every member of every structured variable, flattened, sorted by path.\n\nWritten out rather than worked out on demand, because the dictionary is a produced\ndocument: a generator DDD does not ship reads it without importing python, and no backend\nshould repeat resolution the analysis has already done.", "items": { "$ref": "#/$defs/ResolvedLeaf" }, "title": "Leaves", "type": "array" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "ComponentDeclaration": { "additionalProperties": false, "description": "One entry of a component interface, in the order the component declared it.\n\nA reference to an object rather than the object itself: the definition lives once, under\n``objects``, and is the one the producing component gave. Two components declaring the\nsame name appear here twice and in ``objects`` once.", "properties": { "name": { "description": "Name of the declared object; a key into the ``objects`` list of the dictionary.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "scope": { "$ref": "#/$defs/Scope", "description": "How this component uses the object: ``input``, ``output`` or ``local``." }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor expression this component guarded the declaration with, if any.", "title": "Condition" } }, "required": [ "name", "scope" ], "title": "ComponentDeclaration", "type": "object" }, "ConstantDeclaration": { "additionalProperties": false, "description": "One named integer constant, declared once and named wherever a shape needs it.", "properties": { "name": { "description": "The name a shape writes where it would state a number: ``PRESSURE_CELLS``.\n\nAn identifier, because the name reaches the generated code as an identifier of its own;\nthe templates receive every declared constant to emit.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The value, an integer of at least 1, written as a number.\n\nA literal only: an expression would put a parser and an evaluation order into a\ndescription format, and a constant cannot name another constant, so what cannot be\nwritten cannot cycle. At least 1 because the value is an array dimension, and an array\nof no elements is no array.", "minimum": 1, "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the constant counts, e.g. ``cells of the pressure manifold``.\n\nThis is where the meaning of a size is written down once, instead of being implied by\nevery object that happens to be dimensioned by it.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "ConstantDeclaration", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "ObjectKind": { "description": "What sort of data object a definition describes.", "enum": [ "measurement", "parameter", "value_block", "curve", "map", "axis" ], "title": "ObjectKind", "type": "string" }, "ResolvedComponent": { "additionalProperties": false, "description": "A component and the objects it declares.", "properties": { "name": { "description": "Name of the component, unique within the project.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text from the component description, offered to the templates.", "title": "Description", "type": "string" }, "source": { "default": "", "description": "Path of the description file, for reference in generated comments.", "title": "Source", "type": "string" }, "declarations": { "default": [], "description": "The interface of the component, in the order it declared it.", "items": { "$ref": "#/$defs/ComponentDeclaration" }, "title": "Declarations", "type": "array" } }, "required": [ "name" ], "title": "ResolvedComponent", "type": "object" }, "ResolvedInstance": { "additionalProperties": false, "description": "One variable whose datatype is a structure.\n\nKept apart from :class:`ResolvedObject` rather than widening it: an object with no datatype\nand no limits would turn every reader of those two fields into a branch, and they are read\nunconditionally in a dozen places on the strength of always being there.", "properties": { "name": { "description": "Name of the variable; its c identifier and the root of every leaf path.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "type": { "description": "Name of the structure it is, which is the c type of the declaration.", "title": "Type", "type": "string" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "``measurement`` or ``parameter``: what the whole object is, and so how it is qualified." }, "description": { "default": "", "description": "What the object is; the comment in the generated c.", "title": "Description", "type": "string" }, "shape": { "default": [], "description": "Array dimensions of the variable itself, empty for a single structure.\n\nAn array of structures reaches the a2l as its elements: there is no one address that\ndescribes ``cell[0].raw`` and ``cell[1].raw`` at once, so each element contributes its own\nleaves at its own path. Every dimension is a resolved number; the spelling is in\n``dimensions``.", "items": { "exclusiveMinimum": 0, "type": "integer" }, "title": "Shape", "type": "array" }, "dimensions": { "default": [], "description": "The shape again, each dimension spelled the way the declaration spells it.\n\nParallel to ``shape`` exactly as on a plain object: the number, or the name of the\ndeclared constant the generated code declares the array by. Empty in a dictionary from\nformat 3 or older.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "volatile": { "default": false, "description": "Whether the declaration carries ``volatile``, which qualifies the whole object.", "title": "Volatile", "type": "boolean" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the whole structure is placed in; its members have no placement\nof their own.", "title": "Section" }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor condition of the producing declaration, if any.", "title": "Condition" }, "owner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Component owning the object; ``None`` only when the project is inconsistent.", "title": "Owner" }, "consumers": { "default": [], "description": "Components declaring the object as an input, sorted.", "items": { "type": "string" }, "title": "Consumers", "type": "array" }, "local": { "default": false, "description": "Owned exclusively by ``owner``; no other component may declare it.", "title": "Local", "type": "boolean" }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What the whole object asks of the a2l; a member may ask for more of its own." } }, "required": [ "name", "type", "kind" ], "title": "ResolvedInstance", "type": "object" }, "ResolvedLeaf": { "additionalProperties": false, "description": "One member of one structured variable, at the end of one access path.\n\nThe flattening. A structure reaches the a2l as an object per member rather than as an a2l\nstructure, so this is the form that backend consumes - an ordinary object in every respect\nbut its name, which is a path rather than an identifier.", "properties": { "path": { "description": "The c expression that reads this member: ``Inlet.latest.value``, ``Inlet.cell[2].raw``.\n\nBoth the name the a2l gives the object and the symbol it links it to. Written the way it\nwould be written in c, so that a reader of the a2l, of the generated c and of a map file is\nlooking at one string rather than at three spellings of one thing.", "title": "Path", "type": "string" }, "instance": { "description": "Name of the variable this leaf belongs to, which is the root of :attr:`path`.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Instance", "type": "string" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "Taken from the variable: every leaf of one object has the storage class of the whole." }, "datatype": { "$ref": "#/$defs/Datatype", "description": "Storage of one element." }, "description": { "default": "", "description": "What this member is; the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, from the member or from the type it names.", "title": "Unit", "type": "string" }, "conversion": { "description": "Always present: the member's conversion, or the identity when none was given.", "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ], "title": "Conversion" }, "limits": { "$ref": "#/$defs/Limits", "description": "Always present: stated, or derived from the storage - a bitfield's from its width." }, "shape": { "default": [], "description": "Array dimensions of this member; empty for a scalar.\n\nEvery dimension is a resolved number, because this is the form the a2l consumes; a\ndimension the member spells as a constant name carries that name in ``dimensions``.", "items": { "exclusiveMinimum": 0, "type": "integer" }, "title": "Shape", "type": "array" }, "dimensions": { "default": [], "description": "The shape again, each dimension spelled the way the member spells it.\n\nParallel to ``shape`` exactly as on a plain object. Empty in a dictionary from format 3\nor older.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width in bits when the member is a c bitfield.\n\nSuch a leaf has no address of its own - ``&s.ready`` does not compile - so it reaches no\na2l until a build tells DDD both where the word is and which bits inside it to read.", "title": "Bits" }, "volatile": { "default": false, "description": "From the variable, which carries the qualifier for all of its members at once.", "title": "Volatile", "type": "boolean" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section of the structure this member belongs to; a member has no placement\nof its own.", "title": "Section" }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor condition of the producing declaration, if any.", "title": "Condition" }, "owner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Component owning the variable this leaf belongs to.", "title": "Owner" }, "consumers": { "default": [], "description": "Components declaring the variable as an input, sorted.", "items": { "type": "string" }, "title": "Consumers", "type": "array" }, "local": { "default": false, "description": "Owned exclusively by ``owner``.", "title": "Local", "type": "boolean" }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "The member's own a2l options; a member may be kept out of the file on its own." } }, "required": [ "path", "instance", "kind", "datatype", "conversion", "limits" ], "title": "ResolvedLeaf", "type": "object" }, "ResolvedMember": { "additionalProperties": false, "description": "One member of a structure, as the c templates need it to declare the member.\n\nOnly what a declaration takes. The meaning of the member - its unit, its conversion, its\nlimits - travels with the *leaf* instead, because that is the form the a2l consumes and\nthere is no second place a reader should have to look.", "properties": { "name": { "description": "Name of the member, as it is written in the c struct.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "What the member is, for a comment beside its declaration.", "title": "Description", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of the member when it is a base one; ``None`` when it names a declared type." }, "type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of the structure this member is, when it is one; ``None`` when it is a datatype.", "title": "Type" }, "external": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of the external type this member is, when it is one; ``None`` otherwise.\n\nAn external type is one DDD does not declare - a hand written header defines it - so the\nmember is opaque storage: it appears in the generated structure verbatim, spelled with\nthis name, and contributes no leaf, because DDD knows neither its layout nor its meaning.", "title": "External" }, "header": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "The header defining the external type, spelled the way the generated inclusion writes\nit: ``my_driver.h`` for the quoted form, ``<os_types.h>`` for the angle form. Stated\nexactly when ``external`` is, and carried on the member so a consumer of the dictionary\nnever has to resolve the type name a second time.", "title": "Header" }, "dimensions": { "default": [], "description": "Array dimensions, empty for a scalar, each spelled the way the member spells it.\n\nA number, or the name of a declared constant, exactly as ``dimensions`` is spelled on\nan object or an instance. A member carries no numeric ``shape`` beside it: it is the\ndeclaration side of the answer, and the resolved numbers live on the leaves of every\ninstantiated structure, with the value of a named dimension in the dictionary's\n``constants``.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width in bits when the member is a c bitfield; ``None`` when it is not.", "title": "Bits" } }, "required": [ "name" ], "title": "ResolvedMember", "type": "object" }, "ResolvedObject": { "additionalProperties": false, "description": "One data object, with every derived property already worked out.", "properties": { "name": { "description": "Name of the object, unique across the whole project; its c and a2l identifier.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "Which sort of object this is, taken from the definition that produced it." }, "datatype": { "$ref": "#/$defs/Datatype", "description": "Storage type of one element." }, "description": { "default": "", "description": "What the object is; the a2l long identifier and the comment in the generated c.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, as the declaring components agreed on it.", "title": "Unit", "type": "string" }, "conversion": { "description": "Always present: the declared conversion, or the identity when none was given.", "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ], "title": "Conversion" }, "limits": { "$ref": "#/$defs/Limits", "description": "Always present: the explicit limits, or the range the datatype and conversion imply." }, "shape": { "default": [], "description": "Storage shape, empty for a scalar; for a curve or a map it comes from its axes.\n\nEvery dimension is at least one, like the ``dimensions`` and ``size`` it derives from,\nand every dimension is a resolved number: a dimension stated as the name of a declared\nconstant carries its value here and its name in ``dimensions``.", "items": { "exclusiveMinimum": 0, "type": "integer" }, "title": "Shape", "type": "array" }, "dimensions": { "default": [], "description": "The shape again, each dimension spelled the way the project spells it.\n\nParallel to ``shape``: the same dimensions in the same order, each the number itself or\nthe name of the declared constant that states it - the name under which the generated\ncode declares the array. Empty in a dictionary from format 3 or older, which recorded\nno spellings.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, nested to match ``shape``; ``null`` means zero initialised." }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the producing declaration placed the object in; ``null`` for the\ntoolchain's defaults.", "title": "Section" }, "volatile": { "default": false, "description": "Generate the object ``volatile``: stated by every declaration, on every kind.\n\nCalibration data carries it as ``const volatile``, which is what a value the calibration\ntool changes in a running ecu needs - see the field of the same name on the authored\ndefinition. The default is kept although a definition may no longer omit it, so that a\ndictionary dumped by an older DDD still reads back; that is what ``DICTIONARY_FORMAT``\nexists to make safe.", "title": "Volatile", "type": "boolean" }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor condition of the producing declaration, if any.", "title": "Condition" }, "references": { "additionalProperties": { "type": "string" }, "description": "Other objects this one refers to, keyed by field name (``axis``, ``x_axis``, ...).", "title": "References", "type": "object" }, "owner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Component owning the object; ``None`` only when the project is inconsistent.", "title": "Owner" }, "consumers": { "default": [], "description": "Components declaring the object as an input, sorted; empty when nothing reads it.", "items": { "type": "string" }, "title": "Consumers", "type": "array" }, "local": { "default": false, "description": "Owned exclusively by ``owner``; no other component may declare it.", "title": "Local", "type": "boolean" }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What the author asked for in the ``a2l`` block. Only the a2l backend interprets it." } }, "required": [ "name", "kind", "datatype", "conversion", "limits" ], "title": "ResolvedObject", "type": "object" }, "ResolvedStruct": { "additionalProperties": false, "description": "One structure, in an order a c file can be written out in.\n\nThe order of :attr:`DataDictionary.types` matters and is not alphabetical: a structure\nappears after every structure it nests, because a c compiler needs the nested one to be\ncomplete first. The members keep the order the author wrote them in, which is the order the\ncompiler lays them out.", "properties": { "name": { "description": "Name of the structure, which is the name of the generated typedef.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "What the structure is, for a comment above it.", "title": "Description", "type": "string" }, "members": { "default": [], "description": "The members, in declaration order.", "items": { "$ref": "#/$defs/ResolvedMember" }, "title": "Members", "type": "array" } }, "required": [ "name" ], "title": "ResolvedStruct", "type": "object" }, "Scope": { "description": "Direction of a variable with respect to the declaring component.", "enum": [ "input", "output", "local" ], "title": "Scope", "type": "string" } }, "additionalProperties": false, "required": [ "name" ] }
- field format: int = 4
Version of this document format, raised only when the shape of the document changes.
Stamped so that a dictionary archived next to a delivery can be read back years later by a version of DDD that can say “this file is newer than I understand” rather than misread it. It does not follow the version of the tool.
Version of this document format, raised only when the shape of the document changes.
Stamped so that a dictionary archived next to a delivery can be read back years later by a version of DDD that can say “this file is newer than I understand” rather than misread it. It does not follow the version of the tool.
- field name: Identifier [Required]
Name of the project, from the root project description.
- field description: str = ''
Free text from the root project description.
- field source: str = ''
Name of the root description file, for reference in generated comments.
- field components: tuple[ResolvedComponent, ...] = ()
Every component of the project, including those of its sub-projects.
- field objects: tuple[ResolvedObject, ...] = ()
Sorted by name, so that every backend produces a stable output.
- field enums: tuple[EnumConversion, ...] = ()
Distinct enumerations used by the objects, sorted by name.
- field constants: tuple[ConstantDeclaration, ...] = ()
The named constants the project declares, sorted by name.
Recorded whole - name, value and description - so that a generator consuming the dictionary can emit them the way the shipped templates do, and so that a dimension spelled by name stays resolvable after the description files have moved on.
The named constants the project declares, sorted by name.
Recorded whole - name, value and description - so that a generator consuming the dictionary can emit them the way the shipped templates do, and so that a dimension spelled by name stays resolvable after the description files have moved on.
- field types: tuple[ResolvedStruct, ...] = ()
The structures the project declares, each after every structure it nests.
Dependency order rather than alphabetical, because a template that simply loops over them has to be able to write them out as they come: c needs a nested structure to be complete before the one that contains it.
The structures the project declares, each after every structure it nests.
Dependency order rather than alphabetical, because a template that simply loops over them has to be able to write them out as they come: c needs a nested structure to be complete before the one that contains it.
- field instances: tuple[ResolvedInstance, ...] = ()
Variables whose datatype is a structure, sorted by name.
- field leaves: tuple[ResolvedLeaf, ...] = ()
Every member of every structured variable, flattened, sorted by path.
Written out rather than worked out on demand, because the dictionary is a produced document: a generator DDD does not ship reads it without importing python, and no backend should repeat resolution the analysis has already done.
Every member of every structured variable, flattened, sorted by path.
Written out rather than worked out on demand, because the dictionary is a produced document: a generator DDD does not ship reads it without importing python, and no backend should repeat resolution the analysis has already done.
- pydantic model ResolvedObject[source]
One data object, with every derived property already worked out.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ResolvedObject" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedObject</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr><tr><td>datatype</td><td port="datatype">Datatype</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">IdentityConversion | LinearConversion | EnumConversion</td></tr><tr><td>limits</td><td port="limits">Limits</td></tr><tr><td>shape</td><td port="shape">tuple[int, ...]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>references</td><td port="references">dict[str, str]</td></tr><tr><td>owner</td><td port="owner">str | None</td></tr><tr><td>consumers</td><td port="consumers">tuple[str, ...]</td></tr><tr><td>local</td><td port="local">bool</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.ir.ResolvedObject

One data object, with every derived property already worked out.
"];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.ir.ResolvedObject":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.ir.ResolvedObject":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-6f4bec723fca126d8e62521cde41be5396e75798.png)
Show JSON schema
{ "title": "ResolvedObject", "description": "One data object, with every derived property already worked out.", "type": "object", "properties": { "name": { "description": "Name of the object, unique across the whole project; its c and a2l identifier.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "Which sort of object this is, taken from the definition that produced it." }, "datatype": { "$ref": "#/$defs/Datatype", "description": "Storage type of one element." }, "description": { "default": "", "description": "What the object is; the a2l long identifier and the comment in the generated c.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, as the declaring components agreed on it.", "title": "Unit", "type": "string" }, "conversion": { "description": "Always present: the declared conversion, or the identity when none was given.", "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ], "title": "Conversion" }, "limits": { "$ref": "#/$defs/Limits", "description": "Always present: the explicit limits, or the range the datatype and conversion imply." }, "shape": { "default": [], "description": "Storage shape, empty for a scalar; for a curve or a map it comes from its axes.\n\nEvery dimension is at least one, like the ``dimensions`` and ``size`` it derives from,\nand every dimension is a resolved number: a dimension stated as the name of a declared\nconstant carries its value here and its name in ``dimensions``.", "items": { "exclusiveMinimum": 0, "type": "integer" }, "title": "Shape", "type": "array" }, "dimensions": { "default": [], "description": "The shape again, each dimension spelled the way the project spells it.\n\nParallel to ``shape``: the same dimensions in the same order, each the number itself or\nthe name of the declared constant that states it - the name under which the generated\ncode declares the array. Empty in a dictionary from format 3 or older, which recorded\nno spellings.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, nested to match ``shape``; ``null`` means zero initialised." }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the producing declaration placed the object in; ``null`` for the\ntoolchain's defaults.", "title": "Section" }, "volatile": { "default": false, "description": "Generate the object ``volatile``: stated by every declaration, on every kind.\n\nCalibration data carries it as ``const volatile``, which is what a value the calibration\ntool changes in a running ecu needs - see the field of the same name on the authored\ndefinition. The default is kept although a definition may no longer omit it, so that a\ndictionary dumped by an older DDD still reads back; that is what ``DICTIONARY_FORMAT``\nexists to make safe.", "title": "Volatile", "type": "boolean" }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor condition of the producing declaration, if any.", "title": "Condition" }, "references": { "additionalProperties": { "type": "string" }, "description": "Other objects this one refers to, keyed by field name (``axis``, ``x_axis``, ...).", "title": "References", "type": "object" }, "owner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Component owning the object; ``None`` only when the project is inconsistent.", "title": "Owner" }, "consumers": { "default": [], "description": "Components declaring the object as an input, sorted; empty when nothing reads it.", "items": { "type": "string" }, "title": "Consumers", "type": "array" }, "local": { "default": false, "description": "Owned exclusively by ``owner``; no other component may declare it.", "title": "Local", "type": "boolean" }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What the author asked for in the ``a2l`` block. Only the a2l backend interprets it." } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "ObjectKind": { "description": "What sort of data object a definition describes.", "enum": [ "measurement", "parameter", "value_block", "curve", "map", "axis" ], "title": "ObjectKind", "type": "string" } }, "additionalProperties": false, "required": [ "name", "kind", "datatype", "conversion", "limits" ] }
- Fields:
- field name: Identifier [Required]
Name of the object, unique across the whole project; its c and a2l identifier.
- field kind: ObjectKind [Required]
Which sort of object this is, taken from the definition that produced it.
- field datatype: Datatype [Required]
Storage type of one element.
- field description: str = ''
What the object is; the a2l long identifier and the comment in the generated c.
- field unit: str = ''
Physical unit, as the declaring components agreed on it.
- field conversion: Conversion [Required]
Always present: the declared conversion, or the identity when none was given.
- field limits: Limits [Required]
Always present: the explicit limits, or the range the datatype and conversion imply.
- field shape: tuple[PositiveInt, ...] = ()
Storage shape, empty for a scalar; for a curve or a map it comes from its axes.
Every dimension is at least one, like the
dimensionsandsizeit derives from, and every dimension is a resolved number: a dimension stated as the name of a declared constant carries its value here and its name indimensions.Storage shape, empty for a scalar; for a curve or a map it comes from its axes.
Every dimension is at least one, like the
dimensionsandsizeit derives from, and every dimension is a resolved number: a dimension stated as the name of a declared constant carries its value here and its name indimensions.
- field dimensions: tuple[Dimension, ...] = ()
The shape again, each dimension spelled the way the project spells it.
Parallel to
shape: the same dimensions in the same order, each the number itself or the name of the declared constant that states it - the name under which the generated code declares the array. Empty in a dictionary from format 3 or older, which recorded no spellings.The shape again, each dimension spelled the way the project spells it.
Parallel to
shape: the same dimensions in the same order, each the number itself or the name of the declared constant that states it - the name under which the generated code declares the array. Empty in a dictionary from format 3 or older, which recorded no spellings.
- field init: InitValue | None = None
Raw initial value, nested to match
shape;nullmeans zero initialised.
- field section: str | None = None
Linker section the producing declaration placed the object in;
nullfor the toolchain’s defaults.Linker section the producing declaration placed the object in;
nullfor the toolchain’s defaults.
- field volatile: bool = False
Generate the object
volatile: stated by every declaration, on every kind.Calibration data carries it as
const volatile, which is what a value the calibration tool changes in a running ecu needs - see the field of the same name on the authored definition. The default is kept although a definition may no longer omit it, so that a dictionary dumped by an older DDD still reads back; that is whatDICTIONARY_FORMATexists to make safe.Generate the object
volatile: stated by every declaration, on every kind.Calibration data carries it as
const volatile, which is what a value the calibration tool changes in a running ecu needs - see the field of the same name on the authored definition. The default is kept although a definition may no longer omit it, so that a dictionary dumped by an older DDD still reads back; that is whatDICTIONARY_FORMATexists to make safe.
- field condition: str | None = None
Preprocessor condition of the producing declaration, if any.
- field references: dict[str, str] [Optional]
Other objects this one refers to, keyed by field name (
axis,x_axis, …).
- field owner: str | None = None
Component owning the object;
Noneonly when the project is inconsistent.
- field consumers: tuple[str, ...] = ()
Components declaring the object as an input, sorted; empty when nothing reads it.
- field local: bool = False
Owned exclusively by
owner; no other component may declare it.
- field a2l: A2lObjectOptions = A2lObjectOptions(export=None, format=None, display_identifier=None)
What the author asked for in the
a2lblock. Only the a2l backend interprets it.
- pydantic model ResolvedComponent[source]
A component and the objects it declares.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ComponentDeclaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ComponentDeclaration</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>scope</td><td port="scope">Scope</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr></table>>,
tooltip="ddd.ir.ComponentDeclaration

One entry of a component interface, in the order the component declared it.

A reference \
to an object rather than the object itself: the definition lives once, under
``objects``, and is the one the producing component \
gave. Two components declaring the
same name appear here twice and in ``objects`` once.
"];
"ddd.ir.ResolvedComponent" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedComponent</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>source</td><td port="source">str</td></tr><tr><td>declarations</td><td port="declarations">tuple[ComponentDeclaration, ...]</td></tr></table>>,
tooltip="ddd.ir.ResolvedComponent

A component and the objects it declares.
"];
"ddd.ir.ResolvedComponent":declarations:e -> "ddd.ir.ComponentDeclaration":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-af15c370f270848132627844b1d23f49c90d5c48.png)
Show JSON schema
{ "title": "ResolvedComponent", "description": "A component and the objects it declares.", "type": "object", "properties": { "name": { "description": "Name of the component, unique within the project.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text from the component description, offered to the templates.", "title": "Description", "type": "string" }, "source": { "default": "", "description": "Path of the description file, for reference in generated comments.", "title": "Source", "type": "string" }, "declarations": { "default": [], "description": "The interface of the component, in the order it declared it.", "items": { "$ref": "#/$defs/ComponentDeclaration" }, "title": "Declarations", "type": "array" } }, "$defs": { "ComponentDeclaration": { "additionalProperties": false, "description": "One entry of a component interface, in the order the component declared it.\n\nA reference to an object rather than the object itself: the definition lives once, under\n``objects``, and is the one the producing component gave. Two components declaring the\nsame name appear here twice and in ``objects`` once.", "properties": { "name": { "description": "Name of the declared object; a key into the ``objects`` list of the dictionary.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "scope": { "$ref": "#/$defs/Scope", "description": "How this component uses the object: ``input``, ``output`` or ``local``." }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor expression this component guarded the declaration with, if any.", "title": "Condition" } }, "required": [ "name", "scope" ], "title": "ComponentDeclaration", "type": "object" }, "Scope": { "description": "Direction of a variable with respect to the declaring component.", "enum": [ "input", "output", "local" ], "title": "Scope", "type": "string" } }, "additionalProperties": false, "required": [ "name" ] }
- Fields:
- field name: Identifier [Required]
Name of the component, unique within the project.
- field description: str = ''
Free text from the component description, offered to the templates.
- field source: str = ''
Path of the description file, for reference in generated comments.
- field declarations: tuple[ComponentDeclaration, ...] = ()
The interface of the component, in the order it declared it.
- pydantic model ComponentDeclaration[source]
One entry of a component interface, in the order the component declared it.
A reference to an object rather than the object itself: the definition lives once, under
objects, and is the one the producing component gave. Two components declaring the same name appear here twice and inobjectsonce.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ComponentDeclaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ComponentDeclaration</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>scope</td><td port="scope">Scope</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr></table>>,
tooltip="ddd.ir.ComponentDeclaration

One entry of a component interface, in the order the component declared it.

A reference \
to an object rather than the object itself: the definition lives once, under
``objects``, and is the one the producing component \
gave. Two components declaring the
same name appear here twice and in ``objects`` once.
"];
}](_images/graphviz-8edead6011e89bd06e5b266bc785496f43b1dba6.png)
Show JSON schema
{ "title": "ComponentDeclaration", "description": "One entry of a component interface, in the order the component declared it.\n\nA reference to an object rather than the object itself: the definition lives once, under\n``objects``, and is the one the producing component gave. Two components declaring the\nsame name appear here twice and in ``objects`` once.", "type": "object", "properties": { "name": { "description": "Name of the declared object; a key into the ``objects`` list of the dictionary.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "scope": { "$ref": "#/$defs/Scope", "description": "How this component uses the object: ``input``, ``output`` or ``local``." }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor expression this component guarded the declaration with, if any.", "title": "Condition" } }, "$defs": { "Scope": { "description": "Direction of a variable with respect to the declaring component.", "enum": [ "input", "output", "local" ], "title": "Scope", "type": "string" } }, "additionalProperties": false, "required": [ "name", "scope" ] }
- field name: Identifier [Required]
Name of the declared object; a key into the
objectslist of the dictionary.
- field scope: Scope [Required]
How this component uses the object:
input,outputorlocal.
- field condition: str | None = None
Preprocessor expression this component guarded the declaration with, if any.