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": 9,
  "name": "DemoDevice",
  "description": "Demonstration project showing every kind of data object",
  "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. A script writes the file with -o dictionary.json instead: the same text, as the same bytes on every platform, and a file whose content would not change is left untouched, so that what reads it does not run again for nothing - a redirection leaves the bytes to the shell, and empties the file before the tool has even started. A run that generates anyway writes it beside the artefacts with ddd generate --dictionary, in the same write as them, which is what the cmake integration does. 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",
    "id": "6ywadt4ekhj3",
    "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",
  "id": "6ywadt4ekhj3",
  "extensions": {},
  "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,
  "raster": null,
  "point_counts": "none",
  "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 with something to export - 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.

The plugin blocks are resolved too. Every object, every structured instance and the dictionary itself carry extensions, validated and dumped back with each plugin’s own defaults filled in, and the dictionary names the plugins in play under plugins. That is what keeps a plugin’s questions answerable from the dictionary alone, long after the project that named the plugin has moved on: the archived dump is what ddd compare --plugin reads back a plugin’s comparison rules against, and what ddd generate <name> hands to a plugin’s own backend. See Plugins for what a plugin does with them.

Note

owner is null for an input that no component produces, which reaches the dictionary whenever missing-producer is relaxed - a component checked or dumped on its own, or an inconsistent project generated with ddd generate --force; the c backend files such an object under <unresolved>. Every other field is always present.

Point counts ahead of a table

Some firmware stores the number of axis points inside every curve, map and axis, ahead of its data, in the object’s own type - a 16 by 16 uint32 map begins with its two counts:

8093841c  10000000 10000000 00000000 ...     a 16 x 16 map of uint32
          nx = 16  ny = 16   then the 256 values

point_counts says whether an object is stored that way. It takes "none", the ordinary layout, or "leading". It may be stated once, on the project, as the default for every curve, map and axis; a component may state it again to override that default for the curves, maps and axes it defines - the producing declaration, exactly as a component’s raster does. A reader of the object never influences it. A component read on its own - a standalone ddd dump, list or generate of a component file - has no project to take a default from, so its tables resolve to "none" unless the component states the key itself.

A table resolved to "leading" is declared flat, counts first, in its own datatype:

const uint32_t M[2 + (16) * (16)] = { 16U, 16U, ... };

and the a2l describes it with a record layout of its own, the counts ahead of the values it governs:

/begin RECORD_LAYOUT RL_MAP_COUNTED_ULONG
  NO_AXIS_PTS_X 1 ULONG
  NO_AXIS_PTS_Y 2 ULONG
  FNC_VALUES 3 ULONG ROW_DIR DIRECT
/end RECORD_LAYOUT

Two consistency checks come with the setting: point-counts-unrepresentable refuses a table whose datatype cannot hold one of its counts, and point-counts-mismatch warns when a curve or a map resolves to one convention and one of its axes to the other. From format 9 on, every resolved object carries the point_counts it was given, "none" for every kind but a curve, a map or an axis.

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 9 - 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 10, and this DDD understands up to 9; 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.

One field asks something of its reader: init is carried as the declaration wrote it, so a list is nested one level per dimension and a scalar written for an array is still a scalar - "init": 0 beside "shape": [4] means four zeros. It is not expanded here because expanding it would write one literal per element for a value the description states once, and an array of ten thousand elements would carry ten thousand of them. A generator broadcasts the scalar over shape, which is what the c backend does before rendering the initialiser.

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": 9,
      "minimum": 1,
      "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"
    },
    "rasters": {
      "default": [],
      "items": {
        "$ref": "#/$defs/ResolvedRaster"
      },
      "title": "Rasters",
      "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"
    },
    "plugins": {
      "default": [],
      "items": {
        "type": "string"
      },
      "title": "Plugins",
      "type": "array"
    },
    "extensions": {
      "additionalProperties": {
        "additionalProperties": true,
        "type": "object"
      },
      "title": "Extensions",
      "type": "object"
    }
  },
  "required": [
    "name"
  ],
  "title": "DDD data dictionary",
  "type": "object"
}

additionalProperties is false here, as it is on every object DDD describes - the one open door is extensions, whose blocks belong to the plugins that own them - 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. rasters records the declared measurement rasters the same way - name, event channel, period and description - so that a generator can write the XCP event list itself instead of reconstructing it from the events the objects happen to name. 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 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.

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&#xA;&#xA;One entry of a component interface, in the order the component declared it.&#xA;&#xA;A reference \
to an object rather than the object itself: the definition lives once, under&#xA;``objects``, and is the one the producing component \
gave. Two components declaring the&#xA;same name appear here twice and in ``objects`` once.&#xA;"];
   "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>rasters</td><td port="rasters">tuple[ResolvedRaster, ...]</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><tr><td>plugins</td><td port="plugins">tuple[str, ...]</td></tr><tr><td>extensions</td><td port="extensions">dict[str, dict[str, Any]]</td></tr></table>>,
      tooltip="ddd.ir.DataDictionary&#xA;&#xA;The resolved data of one project.&#xA;&#xA;What ``ddd dump`` writes and every backend reads. Unlike \
the description files, this one&#xA;is produced rather than authored: every derived property is already worked out, so a&#xA;consumer \
never has to repeat the resolution and two consumers can never disagree about it.&#xA;"];
   "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&#xA;&#xA;A component and the objects it declares.&#xA;"];
   "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>id</td><td port="id">str | None</td></tr><tr><td>extensions</td><td port="extensions">dict[str, dict[str, Any]]</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>raster</td><td port="raster">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&#xA;&#xA;One variable whose datatype is a structure.&#xA;&#xA;Kept apart from :class:`ResolvedObject` rather \
than widening it: an object with no datatype&#xA;and no limits would turn every reader of those two fields into a branch, and they \
are read&#xA;unconditionally in a dozen places on the strength of always being there.&#xA;"];
   "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>instance_id</td><td port="instance_id">str | None</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 | StringConversion</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>raster</td><td port="raster">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&#xA;&#xA;One member of one structured variable, at the end of one access path.&#xA;&#xA;The flattening. A structure \
reaches the a2l as an object per member rather than as an a2l&#xA;structure, so this is the form that backend consumes - an ordinary \
object in every respect&#xA;but its name, which is a path rather than an identifier.&#xA;"];
   "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>id</td><td port="id">str | None</td></tr><tr><td>extensions</td><td port="extensions">dict[str, dict[str, Any]]</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 | StringConversion</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>raster</td><td port="raster">str | None</td></tr><tr><td>point_counts</td><td port="point_counts">PointCounts</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&#xA;&#xA;One data object, with every derived property already worked out.&#xA;"];
   "ddd.ir.DataDictionary":objects:e -> "ddd.ir.ResolvedObject":_root:w   [arrowhead=crownone,
      arrowtail=nonenone];
   "ddd.ir.ResolvedRaster"   [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedRaster</b></td></tr><tr><td>raster</td><td port="raster">str</td></tr><tr><td>event</td><td port="event">int</td></tr><tr><td>cycle</td><td port="cycle">str | None</td></tr><tr><td>cycle_ns</td><td port="cycle_ns">int | None</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
      tooltip="ddd.ir.ResolvedRaster&#xA;&#xA;One declared daq event, as the dictionary publishes it.&#xA;"];
   "ddd.ir.DataDictionary":rasters:e -> "ddd.ir.ResolvedRaster":_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&#xA;&#xA;One structure, in an order a c file can be written out in.&#xA;&#xA;The order of :attr:`DataDictionary.types` \
matters and is not alphabetical: a structure&#xA;appears after every structure it nests, because a c compiler needs the nested one \
to be&#xA;complete first. The members keep the order the author wrote them in, which is the order the&#xA;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">Union[int, float]</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
      tooltip="ddd.models.constants.ConstantDeclaration&#xA;&#xA;One named number, declared once and named wherever the project 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&#xA;&#xA;A verbal conversion table; the raw value *is* the physical value.&#xA;&#xA;Accepts \
both the explicit form::&#xA;&#xA;    {\"kind\": \"enum\", \"name\": \"StateA\",&#xA;     \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}&#xA;&#xA;and the mapping shorthand::&#xA;&#xA;    {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}&#xA;"];
   "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&#xA;&#xA;What a declaration asks of the a2l backend. Only that backend interprets it.&#xA;&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that&#xA;generates no a2l can leave the whole block \
out.&#xA;"];
   "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&#xA;&#xA;``physical == raw``; stated like any other conversion, ``{}`` its shortest spelling.&#\
xA;&#xA;Not a default: a definition naming storage by ``datatype`` states this one where raw and&#xA;physical are the same number, \
so that the claim is written down rather than left to&#xA;silence.&#xA;"];
   "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&#xA;&#xA;``physical = raw * factor + offset``, the scaling of a fixed point value.&#xA;"];
   "ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w   [arrowhead=noneteetee,
      arrowtail=nonenone];
   "ddd.models.conversion.StringConversion"   [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>StringConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['string']</td></tr></table>>,
      tooltip="ddd.models.conversion.StringConversion&#xA;&#xA;Bytes read as text: each element of the array holds one character code.&#xA;&#xA;\
Stated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the&#xA;datatype because the same pair is written \
in three places. ``kind`` is required here,&#xA;unlike on the other three kinds: a string has no key of its own to be inferred from,&#\
xA;and ``{}`` is the identity.&#xA;&#xA;The two mappings are the identity on one byte, so that the derived limits of a string&#xA;\
are the raw range of its datatype - which is what the a2l record states - and nothing&#xA;that ranges a conversion has to know that \
a string exists. A byte has no reading of its&#xA;own, so no reading is produced for it, as for the identity.&#xA;"];
   "ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.StringConversion":_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&#xA;&#xA;Physical lower/upper limit of a data object.&#xA;"];
   "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&#xA;&#xA;One member of a structure, as the c templates need it to declare the member.&#xA;&#xA;Only what a \
declaration takes. The meaning of the member - its unit, its conversion, its&#xA;limits - travels with the *leaf* instead, because \
that is the form the a2l consumes and&#xA;there is no second place a reader should have to look.&#xA;&#xA;Exactly one of ``datatype``, ``\
type`` and ``external`` is stated: a member holds a value&#xA;of a base datatype, is a structure, or is storage of a type DDD does \
not describe. A&#xA;member stating none of them would be storage with no size, no meaning and no name, which&#xA;a consumer of this \
document has nothing to do with.&#xA;"];
   "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":conversion:e -> "ddd.models.conversion.StringConversion":_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&#xA;&#xA;One named value of an enum conversion, and what that value means.&#xA;"];
   "ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w   [arrowhead=crownone,
      arrowtail=nonenone];
}

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": 9,
         "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.\n\nA whole number of at least 1, and strictly that: ``\"9\"``, ``9.0`` and ``0`` are not\nversions any DDD ever wrote, and the check that refuses a dictionary from a newer DDD has\nno version to compare them with.",
         "minimum": 1,
         "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"
      },
      "rasters": {
         "default": [],
         "description": "The measurement rasters the project declares, sorted by name.\n\nRecorded whole - name, event, period and description - so that a generator consuming the\ndictionary can write the event list itself rather than repeat the resolution. Empty in a\ndictionary from format 4 or older.",
         "items": {
            "$ref": "#/$defs/ResolvedRaster"
         },
         "title": "Rasters",
         "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\nBy path with every ``[n]`` in it read as the number it is, so the elements of an array of\nstructures are in the order they are stored in rather than in the order their spellings\nhappen to sort in: ``[2]`` before ``[10]``.\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"
      },
      "plugins": {
         "default": [],
         "description": "The names of the plugins that interpreted this dictionary, sorted.\n\nNames rather than module spellings: a path is relative to a project file the dump no\nlonger has, and the name is what the blocks are keyed by. Empty in a dictionary from\nformat 6 or older, and what ``missing-plugin`` reads when a comparison runs without one\nof them.",
         "items": {
            "type": "string"
         },
         "title": "Plugins",
         "type": "array"
      },
      "extensions": {
         "additionalProperties": {
            "additionalProperties": true,
            "type": "object"
         },
         "description": "The settings of each plugin, in resolved form, keyed by plugin name.\n\nRecorded so that a comparison over an archived dump can rebuild what the plugin's hooks\nwere given, without the project file that stated them.",
         "title": "Extensions",
         "type": "object"
      }
   },
   "$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, and an object nobody\nmentions is exported: see \"Who asks for an export\" on the definition page.",
               "title": "Export"
            },
            "format": {
               "anyOf": [
                  {
                     "pattern": "^%[0-9]*\\.[0-9]+$",
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.\n\nRefused beside a ``string`` conversion, which has no decimals to display.",
               "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 number, declared once and named wherever the project 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": {
               "anyOf": [
                  {
                     "maximum": 18446744073709551615,
                     "minimum": -9223372036854775808,
                     "type": "integer"
                  },
                  {
                     "type": "number"
                  }
               ],
               "description": "The value, a number: a whole number of either sign, or one written with a point.\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.  How it is written settles what it is - ``2`` is a whole number,\nand anything carrying a point or an exponent is fractional, so ``2.0`` and ``1e3`` both\nare - because that is what the author is picking: the type, not the format.  The\noutputs carry the number in its shortest spelling that reads back as the same number, a\nwhole number without a point and any other with a point or an exponent, so ``2.50``\nreaches the generated code as ``2.5`` and ``1e3`` as ``1000.0``.\nA whole number is bounded by what a 64 bit target can express, signed or unsigned, and\na fractional one must be finite: ``inf`` and ``nan`` name nothing a description can\nstate, and would reach a template as those words.\n\nNothing here requires the value to be a size.  A constant that a shape names has to be\na whole number of at least 1, the same rule a dimension written as a literal obeys, but\nthat is checked where the shape names it - the declaration is not the place, because a\nconstant may be declared to be emitted and never dimension anything.",
               "title": "Value"
            },
            "description": {
               "default": "",
               "description": "What the constant stands for, e.g. ``cells of the pressure manifold``.\n\nThis is where the meaning of a number is written down once, instead of being implied by\nevery object that happens to use 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",
               "description": "The tag of this kind, which may be left out: a block stating ``enumerators`` or a\n``name`` is an 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": {
               "anyOf": [
                  {
                     "items": {
                        "$ref": "#/$defs/Enumerator"
                     },
                     "minItems": 1,
                     "type": "array"
                  },
                  {
                     "additionalProperties": {
                        "maximum": 18446744073709551615,
                        "minimum": -9223372036854775808,
                        "type": "integer"
                     },
                     "description": "The enumerators as a ``{\"NAME\": value}`` mapping.",
                     "minProperties": 1,
                     "propertyNames": {
                        "maxLength": 128,
                        "minLength": 1,
                        "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
                     },
                     "type": "object"
                  }
               ],
               "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.\n\nTwo of them may not carry the same name, which the mapping form cannot express twice and\nthe list form can: the generated enumeration would not compile, and a calibration tool\nreading the generated table of labels would have two answers for one. Two names sharing a\n*value* is a different matter - it is the C idiom for an alias, reported as\n``enum-duplicate-value`` rather than refused.",
               "title": "Enumerators"
            }
         },
         "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; two enumerators of one enum sharing one is reported as a warning.\n\n``enum-duplicate-value``, a warning rather than a refusal, because it is legal c and\noccasionally meant as an alias - but the a2l table then offers a calibration tool two\nnames for one reading.\n\nBounded to what 64 bits can hold - no datatype DDD offers stores more - so a value no\nstorage could ever represent is refused here rather than overflowing a comparison once\nit is checked against the c ``int`` every enumerator has to fit, or against the\ndatatype carrying it.\n\nA whole number written without a decimal point: ``4``, not ``4.0``, which the published\nschema accepts and the loader refuses.",
               "maximum": 18446744073709551615,
               "minimum": -9223372036854775808,
               "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``; stated like any other conversion, ``{}`` its shortest spelling.\n\nNot a default: a definition naming storage by ``datatype`` states this one where raw and\nphysical are the same number, so that the claim is written down rather than left to\nsilence.",
         "properties": {
            "kind": {
               "const": "identity",
               "default": "identity",
               "description": "The tag of this kind, which may be left out: an empty block is the identity.",
               "title": "Kind",
               "type": "string"
            }
         },
         "title": "IdentityConversion",
         "type": "object"
      },
      "InitElement": {
         "anyOf": [
            {
               "$ref": "#/$defs/InitScalar"
            },
            {
               "items": {
                  "$ref": "#/$defs/InitElement"
               },
               "type": "array"
            }
         ]
      },
      "InitScalar": {
         "anyOf": [
            {
               "maximum": 18446744073709551615,
               "minimum": -9223372036854775808,
               "type": "integer"
            },
            {
               "type": "boolean"
            },
            {
               "type": "number"
            }
         ]
      },
      "InitValue": {
         "anyOf": [
            {
               "$ref": "#/$defs/InitScalar"
            },
            {
               "type": "string"
            },
            {
               "items": {
                  "$ref": "#/$defs/InitElement"
               },
               "type": "array"
            }
         ]
      },
      "Limits": {
         "additionalProperties": false,
         "description": "Physical lower/upper limit of a data object.",
         "properties": {
            "min": {
               "anyOf": [
                  {
                     "maximum": 18446744073709551615,
                     "minimum": -9223372036854775808,
                     "type": "integer"
                  },
                  {
                     "type": "number"
                  }
               ],
               "description": "Smallest physical value the object may take.",
               "title": "Min"
            },
            "max": {
               "anyOf": [
                  {
                     "maximum": 18446744073709551615,
                     "minimum": -9223372036854775808,
                     "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",
               "description": "The tag of this kind, which may be left out: a block stating ``factor`` or ``offset``\nis 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"
      },
      "PointCounts": {
         "description": "Where an interpolation object stores its number of axis points, if anywhere.",
         "enum": [
            "none",
            "leading"
         ],
         "title": "PointCounts",
         "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": "File name of the description file, for reference in generated comments.\n\nThe name alone, without the directories above it: a dictionary dumped from two checkouts\nof one project is otherwise two different documents, and the banner of a generated file\nwould carry the path of whoever's machine generated it.",
               "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"
            },
            "id": {
               "anyOf": [
                  {
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Identity the producer gave this object, which survives a rename of it.\n\nEmpty in a dictionary from format 5 or older, which recorded none: an object that pairs\non nothing pairs on its name, exactly as it did then.",
               "title": "Id"
            },
            "extensions": {
               "additionalProperties": {
                  "additionalProperties": true,
                  "type": "object"
               },
               "description": "The blocks of the project's plugins, keyed by plugin name, in resolved form.\n\nEach validated against its plugin's model and dumped back, defaults filled in, so two\ndumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded\nnone, and empty for an object nothing stamped.",
               "title": "Extensions",
               "type": "object"
            },
            "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": [
                     {
                        "maximum": 18446744073709551615,
                        "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"
            },
            "raster": {
               "anyOf": [
                  {
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Measurement raster the producing component updates the object in; ``null`` when the\nproject named none. Empty in a dictionary from format 4 or older.",
               "title": "Raster"
            },
            "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; ``null`` 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"
            },
            "instance_id": {
               "anyOf": [
                  {
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Identity of the variable this leaf belongs to; a member has none of its own.\n\nA leaf is identified by this together with the part of :attr:`path` below the instance,\nso renaming the instance is tracked and renaming a *member of the type* is not - the\npath is half of the identity. Empty in a dictionary from format 5 or older.",
               "title": "Instance Id"
            },
            "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",
                     "string": "#/$defs/StringConversion"
                  },
                  "propertyName": "kind"
               },
               "oneOf": [
                  {
                     "$ref": "#/$defs/IdentityConversion"
                  },
                  {
                     "$ref": "#/$defs/LinearConversion"
                  },
                  {
                     "$ref": "#/$defs/EnumConversion"
                  },
                  {
                     "$ref": "#/$defs/StringConversion"
                  }
               ],
               "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": [
                     {
                        "maximum": 18446744073709551615,
                        "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"
            },
            "raster": {
               "anyOf": [
                  {
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Raster of the variable this member belongs to; a member has none of its own.",
               "title": "Raster"
            },
            "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.\n\nExactly one of ``datatype``, ``type`` and ``external`` is stated: a member holds a value\nof a base datatype, is a structure, or is storage of a type DDD does not describe. A\nmember stating none of them would be storage with no size, no meaning and no name, which\na consumer of this document has nothing to do with.",
         "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; ``null`` 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; ``null`` when it is a datatype.\n\nThe name as the types file spells it, which in a dictionary carrying an ``unknown-type``\nerror may be a name no ``types`` entry answers: the member says what it was declared as,\nand the finding says that nothing declares it.",
               "title": "Type"
            },
            "external": {
               "anyOf": [
                  {
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Name of the external type this member is, when it is one; ``null`` 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": [
                     {
                        "maximum": 18446744073709551615,
                        "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; ``null`` 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"
            },
            "id": {
               "anyOf": [
                  {
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Identity the producer gave this object, which survives a rename of it.\n\nEmpty in a dictionary from format 5 or older, which recorded none: an object that pairs\non nothing pairs on its name, exactly as it did then.",
               "title": "Id"
            },
            "extensions": {
               "additionalProperties": {
                  "additionalProperties": true,
                  "type": "object"
               },
               "description": "The blocks of the project's plugins, keyed by plugin name, in resolved form.\n\nEach validated against its plugin's model and dumped back, defaults filled in, so two\ndumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded\nnone, and empty for an object nothing stamped.",
               "title": "Extensions",
               "type": "object"
            },
            "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",
                     "string": "#/$defs/StringConversion"
                  },
                  "propertyName": "kind"
               },
               "oneOf": [
                  {
                     "$ref": "#/$defs/IdentityConversion"
                  },
                  {
                     "$ref": "#/$defs/LinearConversion"
                  },
                  {
                     "$ref": "#/$defs/EnumConversion"
                  },
                  {
                     "$ref": "#/$defs/StringConversion"
                  }
               ],
               "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": [
                     {
                        "maximum": 18446744073709551615,
                        "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 as the description wrote it, or the text of a string object;\n``null`` means zero initialised.\n\nA list is nested to match ``shape``, one level per dimension. A scalar written for an\narray is carried as the scalar: it initialises every element, and expanding it here\nwould write one literal per element into the dumped dictionary for a value the\ndescription states once. A consumer that needs the elements broadcasts the scalar over\n``shape``, which is what the c backend does to render the initialiser."
            },
            "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"
            },
            "raster": {
               "anyOf": [
                  {
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Measurement raster the producing component updates the object in; ``null`` when the\nproject named none. Empty in a dictionary from format 4 or older.",
               "title": "Raster"
            },
            "point_counts": {
               "$ref": "#/$defs/PointCounts",
               "default": "none",
               "description": "Whether this curve, map or axis stores its point counts ahead of its data: its\nproducing component's ``point_counts``, else the project's. ``none`` for every other kind,\nand in a dictionary from format 8 or older, which never stored any."
            },
            "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: an older document is read with the\ndefaults of the format it states, which is what the ``format`` key of this document is\nfor.",
               "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; ``null`` 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"
      },
      "ResolvedRaster": {
         "additionalProperties": false,
         "description": "One declared daq event, as the dictionary publishes it.",
         "properties": {
            "raster": {
               "description": "Name the objects refer to, and the short name of the xcp event.",
               "title": "Raster",
               "type": "string"
            },
            "event": {
               "description": "The xcp event channel number.",
               "title": "Event",
               "type": "integer"
            },
            "cycle": {
               "anyOf": [
                  {
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "The period as the project wrote it: ``10ms``. Absent when the event is not cyclic.",
               "title": "Cycle"
            },
            "cycle_ns": {
               "anyOf": [
                  {
                     "type": "integer"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "The same period in nanoseconds, resolved so that a consumer never parses the spelling.\n\nBoth are kept for the reason ``shape`` and ``dimensions`` both are: the authored form is\nwhat a reader recognises, and the number is what a consumer computes with.",
               "title": "Cycle Ns"
            },
            "description": {
               "default": "",
               "description": "Free text from the declaration; the long name of the eventual ``EVENT``.",
               "title": "Description",
               "type": "string"
            }
         },
         "required": [
            "raster",
            "event"
         ],
         "title": "ResolvedRaster",
         "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"
      },
      "StringConversion": {
         "additionalProperties": false,
         "description": "Bytes read as text: each element of the array holds one character code.\n\nStated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the\ndatatype because the same pair is written in three places. ``kind`` is required here,\nunlike on the other three kinds: a string has no key of its own to be inferred from,\nand ``{}`` is the identity.\n\nThe two mappings are the identity on one byte, so that the derived limits of a string\nare the raw range of its datatype - which is what the a2l record states - and nothing\nthat ranges a conversion has to know that a string exists. A byte has no reading of its\nown, so no reading is produced for it, as for the identity.",
         "properties": {
            "kind": {
               "const": "string",
               "description": "The tag of this kind, which is required: a string has no key of its own to be\nrecognised by, so nothing else would tell it from the identity.",
               "title": "Kind",
               "type": "string"
            }
         },
         "required": [
            "kind"
         ],
         "title": "StringConversion",
         "type": "object"
      }
   },
   "additionalProperties": false,
   "required": [
      "name"
   ]
}

Fields:
field format: Annotated[int, Field(ge=1, strict=True)] = 9

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.

A whole number of at least 1, and strictly that: "9", 9.0 and 0 are not versions any DDD ever wrote, and the check that refuses a dictionary from a newer DDD has no version to compare them with.

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.

A whole number of at least 1, and strictly that: "9", 9.0 and 0 are not versions any DDD ever wrote, and the check that refuses a dictionary from a newer DDD has no version to compare them with.

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 rasters: tuple[ResolvedRaster, ...] = ()

The measurement rasters the project declares, sorted by name.

Recorded whole - name, event, period and description - so that a generator consuming the dictionary can write the event list itself rather than repeat the resolution. Empty in a dictionary from format 4 or older.

The measurement rasters the project declares, sorted by name.

Recorded whole - name, event, period and description - so that a generator consuming the dictionary can write the event list itself rather than repeat the resolution. Empty in a dictionary from format 4 or older.

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.

By path with every [n] in it read as the number it is, so the elements of an array of structures are in the order they are stored in rather than in the order their spellings happen to sort in: [2] before [10].

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.

By path with every [n] in it read as the number it is, so the elements of an array of structures are in the order they are stored in rather than in the order their spellings happen to sort in: [2] before [10].

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.

field plugins: tuple[str, ...] = ()

The names of the plugins that interpreted this dictionary, sorted.

Names rather than module spellings: a path is relative to a project file the dump no longer has, and the name is what the blocks are keyed by. Empty in a dictionary from format 6 or older, and what missing-plugin reads when a comparison runs without one of them.

The names of the plugins that interpreted this dictionary, sorted.

Names rather than module spellings: a path is relative to a project file the dump no longer has, and the name is what the blocks are keyed by. Empty in a dictionary from format 6 or older, and what missing-plugin reads when a comparison runs without one of them.

field extensions: dict[str, dict[str, Any]] [Optional]

The settings of each plugin, in resolved form, keyed by plugin name.

Recorded so that a comparison over an archived dump can rebuild what the plugin’s hooks were given, without the project file that stated them.

The settings of each plugin, in resolved form, keyed by plugin name.

Recorded so that a comparison over an archived dump can rebuild what the plugin’s hooks were given, without the project file that stated them.

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>id</td><td port="id">str | None</td></tr><tr><td>extensions</td><td port="extensions">dict[str, dict[str, Any]]</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 | StringConversion</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>raster</td><td port="raster">str | None</td></tr><tr><td>point_counts</td><td port="point_counts">PointCounts</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&#xA;&#xA;One data object, with every derived property already worked out.&#xA;"];
   "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&#xA;&#xA;A verbal conversion table; the raw value *is* the physical value.&#xA;&#xA;Accepts \
both the explicit form::&#xA;&#xA;    {\"kind\": \"enum\", \"name\": \"StateA\",&#xA;     \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}&#xA;&#xA;and the mapping shorthand::&#xA;&#xA;    {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}&#xA;"];
   "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&#xA;&#xA;``physical == raw``; stated like any other conversion, ``{}`` its shortest spelling.&#\
xA;&#xA;Not a default: a definition naming storage by ``datatype`` states this one where raw and&#xA;physical are the same number, \
so that the claim is written down rather than left to&#xA;silence.&#xA;"];
   "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&#xA;&#xA;``physical = raw * factor + offset``, the scaling of a fixed point value.&#xA;"];
   "ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w   [arrowhead=noneteetee,
      arrowtail=nonenone];
   "ddd.models.conversion.StringConversion"   [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>StringConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['string']</td></tr></table>>,
      tooltip="ddd.models.conversion.StringConversion&#xA;&#xA;Bytes read as text: each element of the array holds one character code.&#xA;&#xA;\
Stated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the&#xA;datatype because the same pair is written \
in three places. ``kind`` is required here,&#xA;unlike on the other three kinds: a string has no key of its own to be inferred from,&#\
xA;and ``{}`` is the identity.&#xA;&#xA;The two mappings are the identity on one byte, so that the derived limits of a string&#xA;\
are the raw range of its datatype - which is what the a2l record states - and nothing&#xA;that ranges a conversion has to know that \
a string exists. A byte has no reading of its&#xA;own, so no reading is produced for it, as for the identity.&#xA;"];
   "ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.StringConversion":_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&#xA;&#xA;What a declaration asks of the a2l backend. Only that backend interprets it.&#xA;&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that&#xA;generates no a2l can leave the whole block \
out.&#xA;"];
   "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&#xA;&#xA;Physical lower/upper limit of a data object.&#xA;"];
   "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&#xA;&#xA;One named value of an enum conversion, and what that value means.&#xA;"];
   "ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w   [arrowhead=crownone,
      arrowtail=nonenone];
}

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"
      },
      "id": {
         "anyOf": [
            {
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "Identity the producer gave this object, which survives a rename of it.\n\nEmpty in a dictionary from format 5 or older, which recorded none: an object that pairs\non nothing pairs on its name, exactly as it did then.",
         "title": "Id"
      },
      "extensions": {
         "additionalProperties": {
            "additionalProperties": true,
            "type": "object"
         },
         "description": "The blocks of the project's plugins, keyed by plugin name, in resolved form.\n\nEach validated against its plugin's model and dumped back, defaults filled in, so two\ndumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded\nnone, and empty for an object nothing stamped.",
         "title": "Extensions",
         "type": "object"
      },
      "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",
               "string": "#/$defs/StringConversion"
            },
            "propertyName": "kind"
         },
         "oneOf": [
            {
               "$ref": "#/$defs/IdentityConversion"
            },
            {
               "$ref": "#/$defs/LinearConversion"
            },
            {
               "$ref": "#/$defs/EnumConversion"
            },
            {
               "$ref": "#/$defs/StringConversion"
            }
         ],
         "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": [
               {
                  "maximum": 18446744073709551615,
                  "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 as the description wrote it, or the text of a string object;\n``null`` means zero initialised.\n\nA list is nested to match ``shape``, one level per dimension. A scalar written for an\narray is carried as the scalar: it initialises every element, and expanding it here\nwould write one literal per element into the dumped dictionary for a value the\ndescription states once. A consumer that needs the elements broadcasts the scalar over\n``shape``, which is what the c backend does to render the initialiser."
      },
      "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"
      },
      "raster": {
         "anyOf": [
            {
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "Measurement raster the producing component updates the object in; ``null`` when the\nproject named none. Empty in a dictionary from format 4 or older.",
         "title": "Raster"
      },
      "point_counts": {
         "$ref": "#/$defs/PointCounts",
         "default": "none",
         "description": "Whether this curve, map or axis stores its point counts ahead of its data: its\nproducing component's ``point_counts``, else the project's. ``none`` for every other kind,\nand in a dictionary from format 8 or older, which never stored any."
      },
      "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: an older document is read with the\ndefaults of the format it states, which is what the ``format`` key of this document is\nfor.",
         "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; ``null`` 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, and an object nobody\nmentions is exported: see \"Who asks for an export\" on the definition page.",
               "title": "Export"
            },
            "format": {
               "anyOf": [
                  {
                     "pattern": "^%[0-9]*\\.[0-9]+$",
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.\n\nRefused beside a ``string`` conversion, which has no decimals to display.",
               "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",
               "description": "The tag of this kind, which may be left out: a block stating ``enumerators`` or a\n``name`` is an 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": {
               "anyOf": [
                  {
                     "items": {
                        "$ref": "#/$defs/Enumerator"
                     },
                     "minItems": 1,
                     "type": "array"
                  },
                  {
                     "additionalProperties": {
                        "maximum": 18446744073709551615,
                        "minimum": -9223372036854775808,
                        "type": "integer"
                     },
                     "description": "The enumerators as a ``{\"NAME\": value}`` mapping.",
                     "minProperties": 1,
                     "propertyNames": {
                        "maxLength": 128,
                        "minLength": 1,
                        "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
                     },
                     "type": "object"
                  }
               ],
               "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.\n\nTwo of them may not carry the same name, which the mapping form cannot express twice and\nthe list form can: the generated enumeration would not compile, and a calibration tool\nreading the generated table of labels would have two answers for one. Two names sharing a\n*value* is a different matter - it is the C idiom for an alias, reported as\n``enum-duplicate-value`` rather than refused.",
               "title": "Enumerators"
            }
         },
         "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; two enumerators of one enum sharing one is reported as a warning.\n\n``enum-duplicate-value``, a warning rather than a refusal, because it is legal c and\noccasionally meant as an alias - but the a2l table then offers a calibration tool two\nnames for one reading.\n\nBounded to what 64 bits can hold - no datatype DDD offers stores more - so a value no\nstorage could ever represent is refused here rather than overflowing a comparison once\nit is checked against the c ``int`` every enumerator has to fit, or against the\ndatatype carrying it.\n\nA whole number written without a decimal point: ``4``, not ``4.0``, which the published\nschema accepts and the loader refuses.",
               "maximum": 18446744073709551615,
               "minimum": -9223372036854775808,
               "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``; stated like any other conversion, ``{}`` its shortest spelling.\n\nNot a default: a definition naming storage by ``datatype`` states this one where raw and\nphysical are the same number, so that the claim is written down rather than left to\nsilence.",
         "properties": {
            "kind": {
               "const": "identity",
               "default": "identity",
               "description": "The tag of this kind, which may be left out: an empty block is the identity.",
               "title": "Kind",
               "type": "string"
            }
         },
         "title": "IdentityConversion",
         "type": "object"
      },
      "InitElement": {
         "anyOf": [
            {
               "$ref": "#/$defs/InitScalar"
            },
            {
               "items": {
                  "$ref": "#/$defs/InitElement"
               },
               "type": "array"
            }
         ]
      },
      "InitScalar": {
         "anyOf": [
            {
               "maximum": 18446744073709551615,
               "minimum": -9223372036854775808,
               "type": "integer"
            },
            {
               "type": "boolean"
            },
            {
               "type": "number"
            }
         ]
      },
      "InitValue": {
         "anyOf": [
            {
               "$ref": "#/$defs/InitScalar"
            },
            {
               "type": "string"
            },
            {
               "items": {
                  "$ref": "#/$defs/InitElement"
               },
               "type": "array"
            }
         ]
      },
      "Limits": {
         "additionalProperties": false,
         "description": "Physical lower/upper limit of a data object.",
         "properties": {
            "min": {
               "anyOf": [
                  {
                     "maximum": 18446744073709551615,
                     "minimum": -9223372036854775808,
                     "type": "integer"
                  },
                  {
                     "type": "number"
                  }
               ],
               "description": "Smallest physical value the object may take.",
               "title": "Min"
            },
            "max": {
               "anyOf": [
                  {
                     "maximum": 18446744073709551615,
                     "minimum": -9223372036854775808,
                     "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",
               "description": "The tag of this kind, which may be left out: a block stating ``factor`` or ``offset``\nis 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"
      },
      "PointCounts": {
         "description": "Where an interpolation object stores its number of axis points, if anywhere.",
         "enum": [
            "none",
            "leading"
         ],
         "title": "PointCounts",
         "type": "string"
      },
      "StringConversion": {
         "additionalProperties": false,
         "description": "Bytes read as text: each element of the array holds one character code.\n\nStated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the\ndatatype because the same pair is written in three places. ``kind`` is required here,\nunlike on the other three kinds: a string has no key of its own to be inferred from,\nand ``{}`` is the identity.\n\nThe two mappings are the identity on one byte, so that the derived limits of a string\nare the raw range of its datatype - which is what the a2l record states - and nothing\nthat ranges a conversion has to know that a string exists. A byte has no reading of its\nown, so no reading is produced for it, as for the identity.",
         "properties": {
            "kind": {
               "const": "string",
               "description": "The tag of this kind, which is required: a string has no key of its own to be\nrecognised by, so nothing else would tell it from the identity.",
               "title": "Kind",
               "type": "string"
            }
         },
         "required": [
            "kind"
         ],
         "title": "StringConversion",
         "type": "object"
      }
   },
   "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 id: str | None = None

Identity the producer gave this object, which survives a rename of it.

Empty in a dictionary from format 5 or older, which recorded none: an object that pairs on nothing pairs on its name, exactly as it did then.

Identity the producer gave this object, which survives a rename of it.

Empty in a dictionary from format 5 or older, which recorded none: an object that pairs on nothing pairs on its name, exactly as it did then.

field extensions: dict[str, dict[str, Any]] [Optional]

The blocks of the project’s plugins, keyed by plugin name, in resolved form.

Each validated against its plugin’s model and dumped back, defaults filled in, so two dumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded none, and empty for an object nothing stamped.

The blocks of the project’s plugins, keyed by plugin name, in resolved form.

Each validated against its plugin’s model and dumped back, defaults filled in, so two dumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded none, and empty for an object nothing stamped.

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 dimensions and size it 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 in dimensions.

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 dimensions and size it 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 in dimensions.

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 as the description wrote it, or the text of a string object; null means zero initialised.

A list is nested to match shape, one level per dimension. A scalar written for an array is carried as the scalar: it initialises every element, and expanding it here would write one literal per element into the dumped dictionary for a value the description states once. A consumer that needs the elements broadcasts the scalar over shape, which is what the c backend does to render the initialiser.

Raw initial value as the description wrote it, or the text of a string object; null means zero initialised.

A list is nested to match shape, one level per dimension. A scalar written for an array is carried as the scalar: it initialises every element, and expanding it here would write one literal per element into the dumped dictionary for a value the description states once. A consumer that needs the elements broadcasts the scalar over shape, which is what the c backend does to render the initialiser.

field section: str | None = None

Linker section the producing declaration placed the object in; null for the toolchain’s defaults.

Linker section the producing declaration placed the object in; null for the toolchain’s defaults.

field raster: str | None = None

Measurement raster the producing component updates the object in; null when the project named none. Empty in a dictionary from format 4 or older.

Measurement raster the producing component updates the object in; null when the project named none. Empty in a dictionary from format 4 or older.

field point_counts: PointCounts = PointCounts.NONE

Whether this curve, map or axis stores its point counts ahead of its data: its producing component’s point_counts, else the project’s. none for every other kind, and in a dictionary from format 8 or older, which never stored any.

Whether this curve, map or axis stores its point counts ahead of its data: its producing component’s point_counts, else the project’s. none for every other kind, and in a dictionary from format 8 or older, which never stored any.

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: an older document is read with the defaults of the format it states, which is what the format key of this document is for.

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: an older document is read with the defaults of the format it states, which is what the format key of this document is for.

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; null only 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 a2l block. 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&#xA;&#xA;One entry of a component interface, in the order the component declared it.&#xA;&#xA;A reference \
to an object rather than the object itself: the definition lives once, under&#xA;``objects``, and is the one the producing component \
gave. Two components declaring the&#xA;same name appear here twice and in ``objects`` once.&#xA;"];
   "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&#xA;&#xA;A component and the objects it declares.&#xA;"];
   "ddd.ir.ResolvedComponent":declarations:e -> "ddd.ir.ComponentDeclaration":_root:w   [arrowhead=crownone,
      arrowtail=nonenone];
}

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": "File name of the description file, for reference in generated comments.\n\nThe name alone, without the directories above it: a dictionary dumped from two checkouts\nof one project is otherwise two different documents, and the banner of a generated file\nwould carry the path of whoever's machine generated it.",
         "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 = ''

File name of the description file, for reference in generated comments.

The name alone, without the directories above it: a dictionary dumped from two checkouts of one project is otherwise two different documents, and the banner of a generated file would carry the path of whoever’s machine generated it.

File name of the description file, for reference in generated comments.

The name alone, without the directories above it: a dictionary dumped from two checkouts of one project is otherwise two different documents, and the banner of a generated file would carry the path of whoever’s machine generated it.

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 in objects once.

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&#xA;&#xA;One entry of a component interface, in the order the component declared it.&#xA;&#xA;A reference \
to an object rather than the object itself: the definition lives once, under&#xA;``objects``, and is the one the producing component \
gave. Two components declaring the&#xA;same name appear here twice and in ``objects`` once.&#xA;"];
}

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"
   ]
}

Fields:
field name: Identifier [Required]

Name of the declared object; a key into the objects list of the dictionary.

field scope: Scope [Required]

How this component uses the object: input, output or local.

field condition: str | None = None

Preprocessor expression this component guarded the declaration with, if any.

pydantic model ResolvedRaster[source]

One declared daq event, as the dictionary publishes 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.ResolvedRaster"   [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedRaster</b></td></tr><tr><td>raster</td><td port="raster">str</td></tr><tr><td>event</td><td port="event">int</td></tr><tr><td>cycle</td><td port="cycle">str | None</td></tr><tr><td>cycle_ns</td><td port="cycle_ns">int | None</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
      tooltip="ddd.ir.ResolvedRaster&#xA;&#xA;One declared daq event, as the dictionary publishes it.&#xA;"];
}

Show JSON schema
{
   "title": "ResolvedRaster",
   "description": "One declared daq event, as the dictionary publishes it.",
   "type": "object",
   "properties": {
      "raster": {
         "description": "Name the objects refer to, and the short name of the xcp event.",
         "title": "Raster",
         "type": "string"
      },
      "event": {
         "description": "The xcp event channel number.",
         "title": "Event",
         "type": "integer"
      },
      "cycle": {
         "anyOf": [
            {
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "The period as the project wrote it: ``10ms``. Absent when the event is not cyclic.",
         "title": "Cycle"
      },
      "cycle_ns": {
         "anyOf": [
            {
               "type": "integer"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "The same period in nanoseconds, resolved so that a consumer never parses the spelling.\n\nBoth are kept for the reason ``shape`` and ``dimensions`` both are: the authored form is\nwhat a reader recognises, and the number is what a consumer computes with.",
         "title": "Cycle Ns"
      },
      "description": {
         "default": "",
         "description": "Free text from the declaration; the long name of the eventual ``EVENT``.",
         "title": "Description",
         "type": "string"
      }
   },
   "additionalProperties": false,
   "required": [
      "raster",
      "event"
   ]
}

Fields:
field raster: str [Required]

Name the objects refer to, and the short name of the xcp event.

field event: int [Required]

The xcp event channel number.

field cycle: str | None = None

The period as the project wrote it: 10ms. Absent when the event is not cyclic.

field cycle_ns: int | None = None

The same period in nanoseconds, resolved so that a consumer never parses the spelling.

Both are kept for the reason shape and dimensions both are: the authored form is what a reader recognises, and the number is what a consumer computes with.

The same period in nanoseconds, resolved so that a consumer never parses the spelling.

Both are kept for the reason shape and dimensions both are: the authored form is what a reader recognises, and the number is what a consumer computes with.

field description: str = ''

Free text from the declaration; the long name of the eventual EVENT.

pydantic model ResolvedStruct[source]

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

The order of 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.

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.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&#xA;&#xA;One member of a structure, as the c templates need it to declare the member.&#xA;&#xA;Only what a \
declaration takes. The meaning of the member - its unit, its conversion, its&#xA;limits - travels with the *leaf* instead, because \
that is the form the a2l consumes and&#xA;there is no second place a reader should have to look.&#xA;&#xA;Exactly one of ``datatype``, ``\
type`` and ``external`` is stated: a member holds a value&#xA;of a base datatype, is a structure, or is storage of a type DDD does \
not describe. A&#xA;member stating none of them would be storage with no size, no meaning and no name, which&#xA;a consumer of this \
document has nothing to do with.&#xA;"];
   "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&#xA;&#xA;One structure, in an order a c file can be written out in.&#xA;&#xA;The order of :attr:`DataDictionary.types` \
matters and is not alphabetical: a structure&#xA;appears after every structure it nests, because a c compiler needs the nested one \
to be&#xA;complete first. The members keep the order the author wrote them in, which is the order the&#xA;compiler lays them out.&#\
xA;"];
   "ddd.ir.ResolvedStruct":members:e -> "ddd.ir.ResolvedMember":_root:w   [arrowhead=crownone,
      arrowtail=nonenone];
}

Show JSON schema
{
   "title": "ResolvedStruct",
   "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.",
   "type": "object",
   "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"
      }
   },
   "$defs": {
      "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"
      },
      "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.\n\nExactly one of ``datatype``, ``type`` and ``external`` is stated: a member holds a value\nof a base datatype, is a structure, or is storage of a type DDD does not describe. A\nmember stating none of them would be storage with no size, no meaning and no name, which\na consumer of this document has nothing to do with.",
         "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; ``null`` 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; ``null`` when it is a datatype.\n\nThe name as the types file spells it, which in a dictionary carrying an ``unknown-type``\nerror may be a name no ``types`` entry answers: the member says what it was declared as,\nand the finding says that nothing declares it.",
               "title": "Type"
            },
            "external": {
               "anyOf": [
                  {
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Name of the external type this member is, when it is one; ``null`` 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": [
                     {
                        "maximum": 18446744073709551615,
                        "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; ``null`` when it is not.",
               "title": "Bits"
            }
         },
         "required": [
            "name"
         ],
         "title": "ResolvedMember",
         "type": "object"
      }
   },
   "additionalProperties": false,
   "required": [
      "name"
   ]
}

Fields:
field name: Identifier [Required]

Name of the structure, which is the name of the generated typedef.

field description: str = ''

What the structure is, for a comment above it.

field members: tuple[ResolvedMember, ...] = ()

The members, in declaration order.

pydantic model ResolvedMember[source]

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.

Exactly one of datatype, type and external is stated: a member holds a value of a base datatype, is a structure, or is storage of a type DDD does not describe. A member stating none of them would be storage with no size, no meaning and no name, which a consumer of this document has nothing to do with.

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.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&#xA;&#xA;One member of a structure, as the c templates need it to declare the member.&#xA;&#xA;Only what a \
declaration takes. The meaning of the member - its unit, its conversion, its&#xA;limits - travels with the *leaf* instead, because \
that is the form the a2l consumes and&#xA;there is no second place a reader should have to look.&#xA;&#xA;Exactly one of ``datatype``, ``\
type`` and ``external`` is stated: a member holds a value&#xA;of a base datatype, is a structure, or is storage of a type DDD does \
not describe. A&#xA;member stating none of them would be storage with no size, no meaning and no name, which&#xA;a consumer of this \
document has nothing to do with.&#xA;"];
}

Show JSON schema
{
   "title": "ResolvedMember",
   "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.\n\nExactly one of ``datatype``, ``type`` and ``external`` is stated: a member holds a value\nof a base datatype, is a structure, or is storage of a type DDD does not describe. A\nmember stating none of them would be storage with no size, no meaning and no name, which\na consumer of this document has nothing to do with.",
   "type": "object",
   "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; ``null`` 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; ``null`` when it is a datatype.\n\nThe name as the types file spells it, which in a dictionary carrying an ``unknown-type``\nerror may be a name no ``types`` entry answers: the member says what it was declared as,\nand the finding says that nothing declares it.",
         "title": "Type"
      },
      "external": {
         "anyOf": [
            {
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "Name of the external type this member is, when it is one; ``null`` 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": [
               {
                  "maximum": 18446744073709551615,
                  "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; ``null`` when it is not.",
         "title": "Bits"
      }
   },
   "$defs": {
      "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"
      }
   },
   "additionalProperties": false,
   "required": [
      "name"
   ]
}

Fields:
field name: Identifier [Required]

Name of the member, as it is written in the c struct.

field description: str = ''

What the member is, for a comment beside its declaration.

field datatype: Datatype | None = None

Storage of the member when it is a base one; null when it names a declared type.

field type: str | None = None

Name of the structure this member is, when it is one; null when it is a datatype.

The name as the types file spells it, which in a dictionary carrying an unknown-type error may be a name no types entry answers: the member says what it was declared as, and the finding says that nothing declares it.

Name of the structure this member is, when it is one; null when it is a datatype.

The name as the types file spells it, which in a dictionary carrying an unknown-type error may be a name no types entry answers: the member says what it was declared as, and the finding says that nothing declares it.

field external: str | None = None

Name of the external type this member is, when it is one; null otherwise.

An external type is one DDD does not declare - a hand written header defines it - so the member is opaque storage: it appears in the generated structure verbatim, spelled with this name, and contributes no leaf, because DDD knows neither its layout nor its meaning.

Name of the external type this member is, when it is one; null otherwise.

An external type is one DDD does not declare - a hand written header defines it - so the member is opaque storage: it appears in the generated structure verbatim, spelled with this name, and contributes no leaf, because DDD knows neither its layout nor its meaning.

field header: str | None = None

The header defining the external type, spelled the way the generated inclusion writes it: my_driver.h for the quoted form, <os_types.h> for the angle form. Stated exactly when external is, and carried on the member so a consumer of the dictionary never has to resolve the type name a second time.

The header defining the external type, spelled the way the generated inclusion writes it: my_driver.h for the quoted form, <os_types.h> for the angle form. Stated exactly when external is, and carried on the member so a consumer of the dictionary never has to resolve the type name a second time.

field dimensions: tuple[Dimension, ...] = ()

Array dimensions, empty for a scalar, each spelled the way the member spells it.

A number, or the name of a declared constant, exactly as dimensions is spelled on an object or an instance. A member carries no numeric shape beside it: it is the declaration side of the answer, and the resolved numbers live on the leaves of every instantiated structure, with the value of a named dimension in the dictionary’s constants.

Array dimensions, empty for a scalar, each spelled the way the member spells it.

A number, or the name of a declared constant, exactly as dimensions is spelled on an object or an instance. A member carries no numeric shape beside it: it is the declaration side of the answer, and the resolved numbers live on the leaves of every instantiated structure, with the value of a named dimension in the dictionary’s constants.

field bits: int | None = None

Width in bits when the member is a c bitfield; null when it is not.

pydantic model ResolvedInstance[source]

One variable whose datatype is a structure.

Kept apart from 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.

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.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>id</td><td port="id">str | None</td></tr><tr><td>extensions</td><td port="extensions">dict[str, dict[str, Any]]</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>raster</td><td port="raster">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&#xA;&#xA;One variable whose datatype is a structure.&#xA;&#xA;Kept apart from :class:`ResolvedObject` rather \
than widening it: an object with no datatype&#xA;and no limits would turn every reader of those two fields into a branch, and they \
are read&#xA;unconditionally in a dozen places on the strength of always being there.&#xA;"];
   "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&#xA;&#xA;What a declaration asks of the a2l backend. Only that backend interprets it.&#xA;&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that&#xA;generates no a2l can leave the whole block \
out.&#xA;"];
   "ddd.ir.ResolvedInstance":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w   [arrowhead=noneteetee,
      arrowtail=nonenone];
}

Show JSON schema
{
   "title": "ResolvedInstance",
   "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.",
   "type": "object",
   "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"
      },
      "id": {
         "anyOf": [
            {
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "Identity the producer gave this object, which survives a rename of it.\n\nEmpty in a dictionary from format 5 or older, which recorded none: an object that pairs\non nothing pairs on its name, exactly as it did then.",
         "title": "Id"
      },
      "extensions": {
         "additionalProperties": {
            "additionalProperties": true,
            "type": "object"
         },
         "description": "The blocks of the project's plugins, keyed by plugin name, in resolved form.\n\nEach validated against its plugin's model and dumped back, defaults filled in, so two\ndumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded\nnone, and empty for an object nothing stamped.",
         "title": "Extensions",
         "type": "object"
      },
      "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": [
               {
                  "maximum": 18446744073709551615,
                  "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"
      },
      "raster": {
         "anyOf": [
            {
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "Measurement raster the producing component updates the object in; ``null`` when the\nproject named none. Empty in a dictionary from format 4 or older.",
         "title": "Raster"
      },
      "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; ``null`` 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."
      }
   },
   "$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, and an object nobody\nmentions is exported: see \"Who asks for an export\" on the definition page.",
               "title": "Export"
            },
            "format": {
               "anyOf": [
                  {
                     "pattern": "^%[0-9]*\\.[0-9]+$",
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.\n\nRefused beside a ``string`` conversion, which has no decimals to display.",
               "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"
      },
      "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",
      "type",
      "kind"
   ]
}

Fields:
field name: Identifier [Required]

Name of the variable; its c identifier and the root of every leaf path.

field id: str | None = None

Identity the producer gave this object, which survives a rename of it.

Empty in a dictionary from format 5 or older, which recorded none: an object that pairs on nothing pairs on its name, exactly as it did then.

Identity the producer gave this object, which survives a rename of it.

Empty in a dictionary from format 5 or older, which recorded none: an object that pairs on nothing pairs on its name, exactly as it did then.

field extensions: dict[str, dict[str, Any]] [Optional]

The blocks of the project’s plugins, keyed by plugin name, in resolved form.

Each validated against its plugin’s model and dumped back, defaults filled in, so two dumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded none, and empty for an object nothing stamped.

The blocks of the project’s plugins, keyed by plugin name, in resolved form.

Each validated against its plugin’s model and dumped back, defaults filled in, so two dumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded none, and empty for an object nothing stamped.

field type: str [Required]

Name of the structure it is, which is the c type of the declaration.

field kind: ObjectKind [Required]

measurement or parameter: what the whole object is, and so how it is qualified.

field description: str = ''

What the object is; the comment in the generated c.

field shape: tuple[PositiveInt, ...] = ()

Array dimensions of the variable itself, empty for a single structure.

An array of structures reaches the a2l as its elements: there is no one address that describes cell[0].raw and cell[1].raw at once, so each element contributes its own leaves at its own path. Every dimension is a resolved number; the spelling is in dimensions.

Array dimensions of the variable itself, empty for a single structure.

An array of structures reaches the a2l as its elements: there is no one address that describes cell[0].raw and cell[1].raw at once, so each element contributes its own leaves at its own path. Every dimension is a resolved number; the spelling is in dimensions.

field dimensions: tuple[Dimension, ...] = ()

The shape again, each dimension spelled the way the declaration spells it.

Parallel to shape exactly as on a plain object: the number, or the name of the declared constant the generated code declares the array by. Empty in a dictionary from format 3 or older.

The shape again, each dimension spelled the way the declaration spells it.

Parallel to shape exactly as on a plain object: the number, or the name of the declared constant the generated code declares the array by. Empty in a dictionary from format 3 or older.

field volatile: bool = False

Whether the declaration carries volatile, which qualifies the whole object.

field section: str | None = None

Linker section the whole structure is placed in; its members have no placement of their own.

Linker section the whole structure is placed in; its members have no placement of their own.

field raster: str | None = None

Measurement raster the producing component updates the object in; null when the project named none. Empty in a dictionary from format 4 or older.

Measurement raster the producing component updates the object in; null when the project named none. Empty in a dictionary from format 4 or older.

field condition: str | None = None

Preprocessor condition of the producing declaration, if any.

field owner: str | None = None

Component owning the object; null only when the project is inconsistent.

field consumers: tuple[str, ...] = ()

Components declaring the object as an input, sorted.

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 whole object asks of the a2l; a member may ask for more of its own.

pydantic model ResolvedLeaf[source]

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.

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.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>instance_id</td><td port="instance_id">str | None</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 | StringConversion</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>raster</td><td port="raster">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&#xA;&#xA;One member of one structured variable, at the end of one access path.&#xA;&#xA;The flattening. A structure \
reaches the a2l as an object per member rather than as an a2l&#xA;structure, so this is the form that backend consumes - an ordinary \
object in every respect&#xA;but its name, which is a path rather than an identifier.&#xA;"];
   "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&#xA;&#xA;A verbal conversion table; the raw value *is* the physical value.&#xA;&#xA;Accepts \
both the explicit form::&#xA;&#xA;    {\"kind\": \"enum\", \"name\": \"StateA\",&#xA;     \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}&#xA;&#xA;and the mapping shorthand::&#xA;&#xA;    {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}&#xA;"];
   "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&#xA;&#xA;``physical == raw``; stated like any other conversion, ``{}`` its shortest spelling.&#\
xA;&#xA;Not a default: a definition naming storage by ``datatype`` states this one where raw and&#xA;physical are the same number, \
so that the claim is written down rather than left to&#xA;silence.&#xA;"];
   "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&#xA;&#xA;``physical = raw * factor + offset``, the scaling of a fixed point value.&#xA;"];
   "ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w   [arrowhead=noneteetee,
      arrowtail=nonenone];
   "ddd.models.conversion.StringConversion"   [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>StringConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['string']</td></tr></table>>,
      tooltip="ddd.models.conversion.StringConversion&#xA;&#xA;Bytes read as text: each element of the array holds one character code.&#xA;&#xA;\
Stated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the&#xA;datatype because the same pair is written \
in three places. ``kind`` is required here,&#xA;unlike on the other three kinds: a string has no key of its own to be inferred from,&#\
xA;and ``{}`` is the identity.&#xA;&#xA;The two mappings are the identity on one byte, so that the derived limits of a string&#xA;\
are the raw range of its datatype - which is what the a2l record states - and nothing&#xA;that ranges a conversion has to know that \
a string exists. A byte has no reading of its&#xA;own, so no reading is produced for it, as for the identity.&#xA;"];
   "ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.StringConversion":_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&#xA;&#xA;What a declaration asks of the a2l backend. Only that backend interprets it.&#xA;&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that&#xA;generates no a2l can leave the whole block \
out.&#xA;"];
   "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&#xA;&#xA;Physical lower/upper limit of a data object.&#xA;"];
   "ddd.ir.ResolvedLeaf":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&#xA;&#xA;One named value of an enum conversion, and what that value means.&#xA;"];
   "ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w   [arrowhead=crownone,
      arrowtail=nonenone];
}

Show JSON schema
{
   "title": "ResolvedLeaf",
   "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.",
   "type": "object",
   "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"
      },
      "instance_id": {
         "anyOf": [
            {
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "Identity of the variable this leaf belongs to; a member has none of its own.\n\nA leaf is identified by this together with the part of :attr:`path` below the instance,\nso renaming the instance is tracked and renaming a *member of the type* is not - the\npath is half of the identity. Empty in a dictionary from format 5 or older.",
         "title": "Instance Id"
      },
      "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",
               "string": "#/$defs/StringConversion"
            },
            "propertyName": "kind"
         },
         "oneOf": [
            {
               "$ref": "#/$defs/IdentityConversion"
            },
            {
               "$ref": "#/$defs/LinearConversion"
            },
            {
               "$ref": "#/$defs/EnumConversion"
            },
            {
               "$ref": "#/$defs/StringConversion"
            }
         ],
         "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": [
               {
                  "maximum": 18446744073709551615,
                  "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"
      },
      "raster": {
         "anyOf": [
            {
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "Raster of the variable this member belongs to; a member has none of its own.",
         "title": "Raster"
      },
      "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."
      }
   },
   "$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, and an object nobody\nmentions is exported: see \"Who asks for an export\" on the definition page.",
               "title": "Export"
            },
            "format": {
               "anyOf": [
                  {
                     "pattern": "^%[0-9]*\\.[0-9]+$",
                     "type": "string"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.\n\nRefused beside a ``string`` conversion, which has no decimals to display.",
               "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",
               "description": "The tag of this kind, which may be left out: a block stating ``enumerators`` or a\n``name`` is an 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": {
               "anyOf": [
                  {
                     "items": {
                        "$ref": "#/$defs/Enumerator"
                     },
                     "minItems": 1,
                     "type": "array"
                  },
                  {
                     "additionalProperties": {
                        "maximum": 18446744073709551615,
                        "minimum": -9223372036854775808,
                        "type": "integer"
                     },
                     "description": "The enumerators as a ``{\"NAME\": value}`` mapping.",
                     "minProperties": 1,
                     "propertyNames": {
                        "maxLength": 128,
                        "minLength": 1,
                        "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
                     },
                     "type": "object"
                  }
               ],
               "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.\n\nTwo of them may not carry the same name, which the mapping form cannot express twice and\nthe list form can: the generated enumeration would not compile, and a calibration tool\nreading the generated table of labels would have two answers for one. Two names sharing a\n*value* is a different matter - it is the C idiom for an alias, reported as\n``enum-duplicate-value`` rather than refused.",
               "title": "Enumerators"
            }
         },
         "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; two enumerators of one enum sharing one is reported as a warning.\n\n``enum-duplicate-value``, a warning rather than a refusal, because it is legal c and\noccasionally meant as an alias - but the a2l table then offers a calibration tool two\nnames for one reading.\n\nBounded to what 64 bits can hold - no datatype DDD offers stores more - so a value no\nstorage could ever represent is refused here rather than overflowing a comparison once\nit is checked against the c ``int`` every enumerator has to fit, or against the\ndatatype carrying it.\n\nA whole number written without a decimal point: ``4``, not ``4.0``, which the published\nschema accepts and the loader refuses.",
               "maximum": 18446744073709551615,
               "minimum": -9223372036854775808,
               "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``; stated like any other conversion, ``{}`` its shortest spelling.\n\nNot a default: a definition naming storage by ``datatype`` states this one where raw and\nphysical are the same number, so that the claim is written down rather than left to\nsilence.",
         "properties": {
            "kind": {
               "const": "identity",
               "default": "identity",
               "description": "The tag of this kind, which may be left out: an empty block is the identity.",
               "title": "Kind",
               "type": "string"
            }
         },
         "title": "IdentityConversion",
         "type": "object"
      },
      "Limits": {
         "additionalProperties": false,
         "description": "Physical lower/upper limit of a data object.",
         "properties": {
            "min": {
               "anyOf": [
                  {
                     "maximum": 18446744073709551615,
                     "minimum": -9223372036854775808,
                     "type": "integer"
                  },
                  {
                     "type": "number"
                  }
               ],
               "description": "Smallest physical value the object may take.",
               "title": "Min"
            },
            "max": {
               "anyOf": [
                  {
                     "maximum": 18446744073709551615,
                     "minimum": -9223372036854775808,
                     "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",
               "description": "The tag of this kind, which may be left out: a block stating ``factor`` or ``offset``\nis 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"
      },
      "StringConversion": {
         "additionalProperties": false,
         "description": "Bytes read as text: each element of the array holds one character code.\n\nStated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the\ndatatype because the same pair is written in three places. ``kind`` is required here,\nunlike on the other three kinds: a string has no key of its own to be inferred from,\nand ``{}`` is the identity.\n\nThe two mappings are the identity on one byte, so that the derived limits of a string\nare the raw range of its datatype - which is what the a2l record states - and nothing\nthat ranges a conversion has to know that a string exists. A byte has no reading of its\nown, so no reading is produced for it, as for the identity.",
         "properties": {
            "kind": {
               "const": "string",
               "description": "The tag of this kind, which is required: a string has no key of its own to be\nrecognised by, so nothing else would tell it from the identity.",
               "title": "Kind",
               "type": "string"
            }
         },
         "required": [
            "kind"
         ],
         "title": "StringConversion",
         "type": "object"
      }
   },
   "additionalProperties": false,
   "required": [
      "path",
      "instance",
      "kind",
      "datatype",
      "conversion",
      "limits"
   ]
}

Fields:
field path: str [Required]

The c expression that reads this member: Inlet.latest.value, Inlet.cell[2].raw.

Both the name the a2l gives the object and the symbol it links it to. Written the way it would be written in c, so that a reader of the a2l, of the generated c and of a map file is looking at one string rather than at three spellings of one thing.

The c expression that reads this member: Inlet.latest.value, Inlet.cell[2].raw.

Both the name the a2l gives the object and the symbol it links it to. Written the way it would be written in c, so that a reader of the a2l, of the generated c and of a map file is looking at one string rather than at three spellings of one thing.

field instance: Identifier [Required]

Name of the variable this leaf belongs to, which is the root of path.

field instance_id: str | None = None

Identity of the variable this leaf belongs to; a member has none of its own.

A leaf is identified by this together with the part of path below the instance, so renaming the instance is tracked and renaming a member of the type is not - the path is half of the identity. Empty in a dictionary from format 5 or older.

Identity of the variable this leaf belongs to; a member has none of its own.

A leaf is identified by this together with the part of path below the instance, so renaming the instance is tracked and renaming a member of the type is not - the path is half of the identity. Empty in a dictionary from format 5 or older.

field kind: ObjectKind [Required]

Taken from the variable: every leaf of one object has the storage class of the whole.

field datatype: Datatype [Required]

Storage of one element.

field description: str = ''

What this member is; the a2l long identifier.

field unit: str = ''

Physical unit, from the member or from the type it names.

field conversion: Conversion [Required]

Always present: the member’s conversion, or the identity when none was given.

field limits: Limits [Required]

Always present: stated, or derived from the storage - a bitfield’s from its width.

field shape: tuple[PositiveInt, ...] = ()

Array dimensions of this member; empty for a scalar.

Every dimension is a resolved number, because this is the form the a2l consumes; a dimension the member spells as a constant name carries that name in dimensions.

Array dimensions of this member; empty for a scalar.

Every dimension is a resolved number, because this is the form the a2l consumes; a dimension the member spells as a constant name carries that name in dimensions.

field dimensions: tuple[Dimension, ...] = ()

The shape again, each dimension spelled the way the member spells it.

Parallel to shape exactly as on a plain object. Empty in a dictionary from format 3 or older.

The shape again, each dimension spelled the way the member spells it.

Parallel to shape exactly as on a plain object. Empty in a dictionary from format 3 or older.

field bits: int | None = None

Width in bits when the member is a c bitfield.

Such a leaf has no address of its own - &s.ready does not compile - so it reaches no a2l until a build tells DDD both where the word is and which bits inside it to read.

Width in bits when the member is a c bitfield.

Such a leaf has no address of its own - &s.ready does not compile - so it reaches no a2l until a build tells DDD both where the word is and which bits inside it to read.

field volatile: bool = False

From the variable, which carries the qualifier for all of its members at once.

field section: str | None = None

Linker section of the structure this member belongs to; a member has no placement of its own.

Linker section of the structure this member belongs to; a member has no placement of its own.

field raster: str | None = None

Raster of the variable this member belongs to; a member has none of its own.

field condition: str | None = None

Preprocessor condition of the producing declaration, if any.

field owner: str | None = None

Component owning the variable this leaf belongs to.

field consumers: tuple[str, ...] = ()

Components declaring the variable as an input, sorted.

field local: bool = False

Owned exclusively by owner.

field a2l: A2lObjectOptions = A2lObjectOptions(export=None, format=None, display_identifier=None)

The member’s own a2l options; a member may be kept out of the file on its own.