
.. _dev_architecture:

Architecture
============

Components & Data Flow
----------------------

.. image:: /autogen/architecture.svg

Runtime Libraries
-----------------

HILTI and Spicy each come with their own runtime libraries providing
functionality that the execution of compiled code requires. The bulk
of the functionality here resides with the HILTI side, with the Spicy
runtime adding pieces that are specific to its functionality.

Conceptually, there are a few different categories of functionality
going into these runtime libraries, per the following summary.

.. rubric:: Categories of Functionality

.. image:: /_static/runtime-libraries.svg

Category 1
    Public library functionality that Spicy programs can ``import``
    (e.g., functions like ``spicy::current_time()`` inside the
    ``spicy`` module; filters like ``filter::Zlib`` inside the
    ``filter`` module). This functionality is declared in
    ``spicy/lib/*.spicy`` and implemented in C++ in ``libspicy-rt.a``.

Category 2
    Public library functionality that HILTI programs can ``import``
    (e.g., the ``hilti::print()`` function inside the ``hilti``
    module). This functionality is declared in ``hilti/lib/hilti.hlt``
    and implemented in C++ in ``libhilti-rt.a``.

    .. note::

        "Public functionality" here means being available to any
        *HILTI* program. This functionality is *not* exposed inside
        Spicy, and hence usually not visible to users unless they
        happen to start writing HILTI programs (e.g., when adding test
        cases to the code base).

Category 3
    Public library functionality for C++ host applications to
    ``#include`` for interacting with the generated C++ code (e.g., to
    retrieve the list of available Spicy parsers, start parsing, and
    gain access to parsed values). This is declared inside the
    ``hilti:rt`` C++ namespace by ``hilti/include/rt/libhilti.h``
    for HILTI-side functionality; and inside the ``spicy::rt``
    namespace by ``spicy/include/rt/libspicy.h`` for purely Spicy-side
    functionality. This functionality is implemented in
    ``libhilti-rt.a`` and ``libspicy-rt.a``, respectively.

    .. note::

        Everything in the sub-namespaces ``{hilti,spicy}::rt::detail``
        remains private and is covered by categories 4 and 5.

Category 4
    Private Spicy-side library functionality that the HILTI code
    coming out of Spicy compilation can ``import`` (e.g., functions to
    access parsing input, such as ``spicy_rt::waitForInput()``;
    HILTI-side type definitions for Spicy-specific types, such as for
    a ``sink``). This functionality is declared in
    ``spicy/lib/spicy_rt.spicy`` and implemented in C++ in
    ``libspicy-rt.a``.

Category 5
    Private HILTI-side library functionality for use by C++ code
    generated from HILTI code. This is declared by
    ``hilti/include/rt/libhilti.h`` inside the ``hilti::rt::detail``
    namespace. The functionality is implemented in ``libhilti-rt.a``.
    (The generated C++ code uses public ``hilti::rt`` functionality
    from Category 3 as well.)

    .. note::

        This category does not have any Spicy-side logic (by
        definition, because Spicy does not generate C++ code
        directly). Everything in ``libspicy-rt.a``, and
        ``spicy::rt::detail`` is covered by one of the other
        categories.

.. rubric:: What goes where?

Think of Category 1 as the "Spicy standard library": functionality for
user-side Spicy code to leverage.

Category 2 is the same for HILTI, except that the universe of HILTI
users remains extremely small right now (it’s just Spicy and people
writing tests).

Category 3 is our client-side C++ API for host applications to drive
Spicy parsers and retrieve results.

When adding new functionality, one needs to decide between the HILTI
and Spicy sides. Rules of thumb:

    1. If it’s "standard library"-type stuff that's meant for Spicy
       users to ``import``, make it part of Category 1.

    2. If it’s something that’s specific to parsing, add it to the
       Spicy side, either Category 3 for public functionality meant to
       be used by host applications; or Category 4 if it’s something
       needed just by the generated HILTI code doing the parsing.

    3. If it's something that’s generic enough to be used by other
       HILTI applications (once we get them), add it to the HILTI
       side, either Category 2 or 5. Think, e.g., a Zeek script
       compiler.
