Since AdaYaml is written in Ada 2012, you can currently only use it in conjunction with the GNAT compiler; there are no other compilers available supporting Ada 2012. Since GNAT is the only viable compiler anyway, the AdaYaml source makes use of some GNAT-specific features.
Moreover, AdaYaml integrates with other tools of the GNAT environment, particularly the build system GPRbuild. You can easily define AdaYaml as dependency of your project using GPRbuild, and you can easily install AdaYaml on your system using GPRinstall. This is all described in detail in the GPRbuild documentation.
AdaYaml uses reference counting for managing resources allocated on the heap. Since reference counting makes it necessary to use smart pointers instead of raw access types, AdaYaml uses naming conventions derived from Rosen ‘95 to communicate the nature of these smart pointer types:
- A type named
Referenceor suffixed with
_Referencealways is a reference to a reference-counted heap object. It is always a tagged type and always has a function
Valuewhich retrieves an
Accessortype to access the underlying object. The
Accessortype is used to prevent deallocation and always has the
Implicit_Dereferenceaspect. Copying a
Referencetype always performs a shallow copy.
- A type named
Instancetypically allocates its content on the stack (if used as a stack variable), but may contain references to heap values. If a
Referencetype exists wrapping an
Instancetype, using the
Referencetype is generally optional. If a subroutine, particularly in another package, may take co-ownership of an instance, it will require a
Referenceas parameter type.
- A type named
Pointeris a raw access type to heap memory. A subroutine taking a value of such a type is guaranteed to take ownership of the value and deallocate it once it is not needed anymore.
The API has been designed so that a user does never need to actively deallocate anything, minimizing the danger of memory leaks.
Most parts of the API are concerned with either producing or consuming a stream of YAML events. A possible approach to make all consumers compatible with all producers would be to define a tagged base type that provides an abstract subroutine to query the next event from the stream. However, this would result in dispatching calls for every event query. Therefore, a different approach has been taken:
The API defines a package
Yaml.Stream_Concept which does not contain any
content other than generic parameters for a stream producer type, its reference,
and a subroutine querying the next event. Any type that can be used to
instantiate that package is considered an event stream producer. Basic packages
Yaml.Parser provide an instantiation of
Stream_Concept as child package
Yaml.Parser.Stream in this case).
Any package that either takes an instance of
Stream_Concept as generic
parameter itself or provides a generic subroutine taking such an instance is
considered an event stream consumer. So if you e.g. want to consume the event
stream generated by a parser, you instantiate your generic consumer with the
Yaml.Parser.Stream. A consumer provided by AdaYaml would be
Yaml.Presenter with its generic subroutine
This example code reads a file (or stdin, if no file is given on the command line) and writes the resulting YAML events to stdout.