Internals

This page documents internals that are not meant to be used by the users.

Parsing

The conversion from XML to the internal representation of ATDF format heavily relies on the generated function AtmelToolsDeviceFiles.node_to_atdf.

AtmelToolsDeviceFiles.node_to_atdfFunction
node_to_atdf([dest::Type{T},] node::XML.Node) where {T <: AbstractATDF}

Convert an XML node to the destination type. If dest is not given, then node XML.nodetype must me an XML.Document, and the function will attempt to extract the root <avr-tools-device-file> node and convert it to an AVRToolsDeviceFile instance.

source

The main bit of AtmelToolsDeviceFiles.node_to_atdf is @generated and is intended to use AtmelToolsDeviceFiles.AbstractATDF subtypes as a template for interpreting the XML.Node object it has been fed.

This approach simplifies the description of the format as it relies mostly on the defined structures in types.jl.

Schema

The structures are built from the inferred schema from examples of files I have found so far. Unfortunately I was unable to find a proper schema on the internet yet. If you are in possiession of such a schema from Microship please reach out, for example by opening an issue!

Of course, the structures themselve are not exactly enough to define the XML schema, so we define a set of helper functions. We can define four kind of data we want to fetch from the XML code: attributes, single-valued structures, direct children arrays, wrapped children arrays.

Attribute fetching

AtmelToolsDeviceFiles._generate_attribute_fetchingFunction
_generate_attribute_fetching(name, type)

Generate the code to fetch an attribute given a field name and a template type. Returns a named tuple with a fetchcode expression to retrieve the attribute, and a checkcode expression to perform verification on the input XML node.

source

Single-valued child structures

Direct children arrays

AtmelToolsDeviceFiles._generate_children_fetchingFunction
_generate_children_fetching(name, Vector{type})

Generate the codes to fetch struct children of an XML node. Return a named tuple with the condition to trigger the code fetching, the type of the children, the variable used in the main function to store the children, and the fetchcode to parse a specific child.

source

Wrapped children arrays

AtmelToolsDeviceFiles._has_wrapper_childrenFunction
_has_wrapper_children(T)

Default to false. Types that have wrapped children must return true.

Example of a wrapped children case:

<tag>
<signals>
<signal></signal>
...
<signal></signal>
</signals>
</tag>

The equivalent un-wrapped case would be:

<tag>
<signal></signal>
...
<signal></signal>
</tag>
source
AtmelToolsDeviceFiles._generate_wrapped_children_fetchingFunction
_generate_wrapped_children_fetching(name, Vector{type})

Generate the codes to fetch wrapped struct children of an XML node. Return a named tuple with the condition to trigger the code fetching, the type of the children, the variable used in the main function to store the children, and the fetchcode to parse a specific child using _fetch_wrapped_children.

source

node_to_atdf generated methods structure

Reading the source code of AtmelToolsDeviceFiles.node_to_atdf is probably the best option. However, we give here a summary of what the structure of generated methods look like.

  1. Attributes fetching. If the node is expected to have attributes, we fetch them and run the checkcode expressions generated by AtmelToolsDeviceFiles._generate_attribute_fetching.
  2. Declaration of the variables used by single-valued children and array children. Single-valued children variables are initialized as nothing and arrays as empty arrays.
  3. A for loop that iterates over the children and checks if it needs to trigger the fetchcode of the single-valued childrent, array children, or wrapped array children.
  4. Check over all single-valued children that they are not nothing after the loop (we do not allow optional structure single-valued children at the time).
  5. Build the internal representation of the node from the extracted variables.