Semantic Values
===============

If successful, a parser produces a semantic value, which describes the
input in some way useful to the application invoking the parser.
In addition, semantic values may be used to control how other parts of the
input are to be parsed.  DaeDaLus has a number of built-in semantic values
types, and allows for user-defined record and union types.

Booleans
--------

The type ``bool`` classifies the usual boolean values ``true`` and ``false``.

The operator ``!`` may be used to negate a boolean value.
The operators ``||`` and ``&&`` are for (short-circuiting) "or" and "and"
respectively.

Boolean values may be compared for equality using ``==`` and are ordered
with ``false < true``.

Decisions on a boolean may be made either using :ref:`If-then-else`, by
using :ref:`Guards`, or by using :ref:`Case`.




Numeric Types
-------------

DaeDaLus supports a variety of numeric types: ``int``, ``uint N``, and
``sint N``, the latter two being families of types indexed by a number.
The type ``int`` classifies integers of arbitrary size.
The ``uint N`` classify unsigned numbers that can be represented using ``N``
bits and ``sint N`` is for signed numbers that can be represented
in ``N`` bits.


Numeric Literals
^^^^^^^^^^^^^^^^

Literals of the numeric types may written either using decimal or hexadecimal
notation (e.g., ``10`` or ``0xA``).  The type of a literal can be inferred
from the context (e.g., ``10`` can be used as both ``int`` a ``uint 8``).


Comparisons
^^^^^^^^^^^

Numeric types can also be compared for equality, using ``==`` and ordering
using ``<``, ``<=``, ``>``, and ``>=``.

Basic Arithmetic
^^^^^^^^^^^^^^^^

Numeric types support basic arithmetic: addition, subtraction, 
multiplication, division, and modulus using the usual operators
``+``, ``-``, ``*``, ``/``, and ``%``.

Bitwise Operations
^^^^^^^^^^^^^^^^^^

DaeDaLus also supports shift operations ``<<`` and ``>>``.
These operations are overloaded and can be used on all numeric types,
with the restriction that the inputs and the outputs must be of the
same type.  The shift amount is a value of type ``uint 64``.

Unsigned integers may also be treated as bit-vectors, and support various
bitwise operations:

* complement: ``~``
* bitwise exclusive-or ``.^.``
* bitwise-or ``.|.``
* bitwise-and ``.&.``.

Unsigned numbers can also be appended to other numbers via the
``#`` and ``<#`` operator.  To see the difference between the two,
consider two bitvectors ``(x : uint A)`` and ``(y : uint B)``.
The result of ``x # y`` is a bitvector of type ``A + B`` with
``x`` in the more significant bits, and ``y`` in the less significant bits.
The result of ``x <# y`` is a bitvector of type ``A`` that contains
``x # y`` but truncated to the ``A`` less significant bits.


``maybe`` type
--------------

DaeDaLus supports the special polymorphic type ``maybe A``, which has possible 
values ``nothing`` and ``just x``, for some value, ``x`` of type ``A``.

The parser ``Optional P`` will try to parse the input using and produce
a ``maybe`` value.  If ``P`` succeeds with result ``x`` then
``Optional P`` will succeed with ``just x``, and if ``P`` fails, then
``Optional P`` will *succeed* with ``nothing``.

.. code-block:: DaeDaLus 

  def MaybeLetter = Optional $[ 'A'..'Z' ]

To examine values of the ``maybe`` type you may use
:ref:`Guards` or :ref:`Case`.


Arrays
------

The type of arrays containg elements of type ``T`` is ``[T]``.

.. code-block:: DaeDaLus

  -- Array literals
  []        -- empty array
  [1,2,3]   -- array with 3 elements
  "Hello"   -- array with 5 elements

  -- Get the element at the given array index
  -- This is a parser, which fails if the index is out of bounds
  Index (a : [?a]) (i : uint 64) : ?a

  -- Length of an array
  length (a : [?a]) : uint 64

To visit all elements in array you may use a ``for`` loop :ref:`for_loops`.


Array Builders
--------------

A ``builder`` is a datastructure that helps build arrays.
To build an array, start with the empty builder ``builder`` and use
``emit`` to add elements to the builder.  Once all elements have been
added, you may use ``build`` to convert the ``builder`` to an array.

.. code-block:: DaeDaLus

  -- empty builder
  builder : builder ?a

  emit (front : builder ?a) (back : ?a) : builder ?a

  -- Add an array of element to the end of the builder
  emitArray (front : builder ?a) (back : [?a]) : builder ?a

  -- Add a builder at the end of another builder
  emitBuilder (front : builder ?a) (back : builder ?a) : builder ?a

  -- Turn a builder into an array
  build (b : builder ?a) : [?a]



Association Maps
----------------

The type of association maps with keys of type ``K`` and elements of type
``T`` is ``[ K -> T ]``.

.. code-block:: DaeDaLus

  -- An empty map
  empty : [ ?k -> ?v ]

  -- Insert an element in a map.
  -- The element is replaced, if it was already present.
  insert (key : ?k) (value : ?v) (m : [ ?k -> ?v ]) : [ ?k -> ?v ]

  -- Insert an element in a map.
  -- This is a parser which fails if the element was already in the map.
  Insert (key : ?k) (value : ?v) (m : [ ?k -> ?v ]) : [ ?k -> ?v ]

  -- Lookup an element in the map.
  lookup (key : ?k) (m : [ ?k -> ?v ]) : maybe ?v

  -- Lookup an element in the map.
  -- This is a parse which fails if the element is not in the map.
  Lookup (key : ?k) (m : [ ?k -> ?v ]) : ?v

To visit all elements of an association map you may use a
``for`` loop :ref:`for_loops`.


Streams
-------

The type ``stream`` is for values representing streams of data that
can be parserd by a parser.   See :ref:`stream_manipulation` for more examples
of how to manipualte the parser's stream.

.. code-block:: DaeDaLus

  -- Get the current stream for the parser
  GetStream : stream

  -- Restrict a stream to the fist `n` bytes.
  -- Will fail if the stream does not have enough bytes
  Take (n : uint 64) (s : stream) : stream

  -- Restrict a stream to at most `n` bytes.
  -- The resulting stream might be shorter if there are not
  -- enough bytes
  take (n : uint 64) (s : stream) : stream

  -- Advance a stream by `n` bytes.
  -- Will fail if the stream does not have enough bytes
  Drop (n : uint 64) (s : stream) : stream

  -- Make a stream with the given name and bytes to parser
  arrayStream (name : [uint 8]) (data : [uint 8]) : stream

  -- Get the bytes associates with a stream as an array
  bytesOfStream (s : stream) : [uint 8]