.. _readme-attributes:

.. default-domain:: chpl


====================
Attributes in Chapel
====================

Overview
--------

Attributes are a mechanism to mark symbols with additional information. This
information can then be used when processing the abstract syntax tree (AST)
representation of the source code.

Generally, an attribute in Chapel is specified above a symbol declaration with
an ``@`` followed by an identifier that specifies the attribute name. A list of
arguments can be enclosed in parentheses ``()``. Arguments can be named or
specified in order, but mixing the use of named and unnamed arguments in the
same attribute is not supported. Note that whitespace is not allowed
between the ``@`` and the identifier.

Attributes in Chapel are currently used to indicate feature stability and to
exclude features from documentation when using :ref:`chpldoc <readme-chpldoc>`.
The syntax of attributes in Chapel is inspired by Rust's, and includes the
ability to specify a tool name for an attribute.

Here are examples of what an attribute might look like:

.. literalinclude:: ../../../test/technotes/doc-examples/AttributeSyntaxExample.chpl
   :language: chapel
   :start-after: START_EXAMPLE_0
   :end-before: STOP_EXAMPLE_0

Limitations
~~~~~~~~~~~

* Multiple attributes can be applied to the same symbol, however an individual
  attribute can only be applied once to a symbol.
* When both attributes and pragmas apply to a symbol, the attribute must be
  placed `after` any pragmas.

Top-level Attributes
~~~~~~~~~~~~~~~~~~~~

An attribute without any specified tool name is called `top-level`. Top-level
attributes are assumed to be language features and are reserved for use by the
Chapel development team. Any unrecognized attributes will be reported to the
user as an error. Attribute arguments can be string, bool, int, real, or
range literals.

Tool names
~~~~~~~~~~

Tool names allow the Chapel compiler to distinguish between attributes that it
should process and attributes that should be passed to other tools. By default,
all tool names other than ``chpldoc`` will be reported to the user as a warning.

Developers of other tools, such as formatters or linters, are free to design
their own attributes so long as they prefix them with a tool name. It is
recommended but not required that the tool name aligns with the tool binary
name. As an example, see the :ref:`@chpldoc.nodoc attribute <attributes-other>`,
which is used by the ``chpldoc`` tool to suppress documentation for a symbol.
The tool name ``chpldoc`` precedes the attribute name ``nodoc``, which takes no
arguments.

Tool names other than ``chpldoc`` are not recognized by the ``chpl`` compiler
and it will issue a warning to the user when it encounters a name it doesn't
recognize. This warning is on by default as a conservative approach to catching
misspellings of tool names, like `@chplldoc`, or misplaced dots '.' in attribute
names as in `@un.stable`. To suppress warnings for a particular tool name,
compile with the flag ``--using-attribute-toolname=<toolname>``. To suppress
warnings for all unknown tool names, compile with the flag
``--no-warn-unknown-attribute-toolname``.

The tool name ``chpldoc`` is recognized without additional flags because the
tool is developed and distributed with the Chapel language. The list of known
tool names may be expanded in the future. The tool name ``chpl`` is reserved
for future use by the Chapel development team.


Implemented Attributes
----------------------

Attributes are currently implemented in the following areas:

* :ref:`Stability Attributes <attributes-stability>`
* :ref:`Other Attributes <attributes-other>`


.. _attributes-stability:

Stability Attributes
~~~~~~~~~~~~~~~~~~~~

.. note::

    The API for stability attributes is still under development and may change
    in a future release.


.. literalinclude:: ../../../test/technotes/doc-examples/AttributeExamples.chpl
   :language: chapel
   :start-after: START_EXAMPLE_0
   :end-before: STOP_EXAMPLE_0
   :dedent:


.. note::

    The ``@stable`` attribute is currently not implemented. The compiler will
    parse it, but it will not have any effect.


.. _attributes-other:

Other Attributes
~~~~~~~~~~~~~~~~

* ``@chpldoc.nodoc`` is used to prevent a symbol from being included in
  documentation generated by :ref:`chpldoc <readme-chpldoc>`.
  This attribute replaces the previous method of
  using ``pragma "no doc"`` to suppress documentation for a symbol.
  When converting existing code, note that ``@chpldoc.nodoc`` must be placed `after`
  any remaining pragmas assigned to the symbol.

  .. literalinclude:: ../../../test/technotes/doc-examples/AttributeExamples.chpl
     :language: chapel
     :start-after: START_EXAMPLE_1
     :end-before: STOP_EXAMPLE_1
     :dedent:

  Pragmas must currently appear before any attributes, and interleaving
  them may lead to syntax errors:

  .. literalinclude:: ../../../test/technotes/doc-examples/AttributeInvalidPlacement.chpl
     :language: chapel
     :start-after: START_EXAMPLE_0
     :end-before: STOP_EXAMPLE_0

* ``@edition`` is a developer-oriented attribute used to specify which
  edition(s) a breaking change is associated with.  See :ref:`edition-attribute`
  for more information about the attribute, and :ref:`readme-editions` for more
  information about editions in general.

* ``@llvm.assertVectorized`` is an experimental attribute which can be applied
  to all statement-level loops. When used on a loop, it applies a post-codegen
  check for the LLVM backend to ensure the loop was vectorized.
  If the loop is not vectorized, a compile time warning will be emitted.
  This is based on LLVM's definition for a successful vectorization and
  the result may not actually contain vector instructions.
  Note that this attribute is currently only meaningful on ``for``
  and ``foreach`` loops.

  .. literalinclude:: ../../../test/technotes/doc-examples/AttributesAssertVectorized.chpl
     :language: chapel
     :start-after: START_EXAMPLE_0
     :end-before: STOP_EXAMPLE_0
     :dedent:

* ``@llvm.metadata`` is an experimental attribute which can be used to adjust
  the code generation when using the LLVM backend.
  It can take any number of arguments which are either string literals or
  2-tuples (1-tuples of string literals can be used as a
  convenience). The first element of the 2-tuple must be a string literal and
  the second element can be a string literal, an int literal, a bool literal,
  or another valid 2-tuple. The arguments are encoded directly
  into `LLVM Metadata <https://llvm.org/docs/LangRef.html#metadata>`_.
  Note that this attribute is currently only meaningful on ``for``
  and ``foreach`` loops.

  .. literalinclude:: ../../../test/technotes/doc-examples/AttributeExamples.chpl
     :language: chapel
     :start-after: START_EXAMPLE_2
     :end-before: STOP_EXAMPLE_2
     :dedent:

Future Work and Design Discussions
----------------------------------

Planned work for attributes includes:

* convert ``pragma "always RVF"`` into an attribute, possibly ``@chpl.alwaysRvf``

* allow any order of pragmas and attributes

* lock in the argument names and types for stability attributes and use them
  to improve the compiler's messages regarding symbol stability
