Attributes
The language can be extended with attributes, enabling a variety of extensions.
An attribute is of the form #[key.of.extension] or #[key.of.extension = VALUE],
where VALUE can be of the form "STRING", or an expression in Catala syntax.
An attribute is always bound to the element directly following it, for instance,
the following binds the doc attribute to the input variable children_of_age
in scope SomeComputation:
declaration scope SomeComputation:
#[doc = "Enter the number of children satisfying the condition XXX"]
input children_of_age content integer
Built-in attributes
Some attributes affect the Catala tooling and have built-in support; they are all listed below. The table lists which attribute has an effect on which part of the Catala tooling.
| Attribute | Attached to | Interpreter | Generated code | Test editor UI | JSON Schema |
|---|---|---|---|---|---|
#[test] | Scope declarations | ✅ | ✅ | ✅ | |
#[doc = "..."] or ## | Anything | ✅ | ✅ | ||
#[description = "..."] | Anything | ✅ | |||
#[error.message = "..."] | impossible, assertion | ✅ | ✅ | ||
#[debug.print = "..."] | Any expression | ✅ | |||
#[implicit_position_argument] | Function declarations | ✅ | ✅ | ||
#[json = "..."] | External expression | ✅ | ✅ | ||
#[testcase.testui] | Test scope declaration | ✅ | |||
#[testcase.test_title = "..."] | Test scope declaration | ✅ | |||
#[testcase.uid = "..."] | Any expression | ✅ | |||
#[testcase.array_item_label = "..."] | Array items | ✅ |
#[test]
Used on scope declarations to mark them for testing. See the “Test” section.
#[doc] or ##
Attached to declarations, structure fields, enumeration cases, or function
arguments, the #[doc = "documentation text"] attribute can be used to document
them. This information will be available to the users of the module and should
explain the purpose and usage of its linked element.
The alternative syntax ## documentation text (a code comment starting with a
double # character) is available and preferred for readability. Like the
attribute, it must be present just above its target.
The documentation items attached to type or scope items declarations are
passed down in the generated JSON Schema in
the description property of the objects.
#[description]
Attaches a short readable string to an element, which tools display beside
its identifier. Unlike #[doc], which explains an element’s purpose and
usage, a description is a caption. The compiler accepts it on declarations,
structure fields, enumeration cases, function arguments and assertions; the
value must be a string. For now, tooling only displays the descriptions of
enumeration cases – see the test case
editor.
#[error.message]
The #[error.message = "informative message"] attribute can be attached to
assertions or to the impossible keyword. The given message will be printed
alongside the normal error message and the code location when the error is
triggered, both in the interpreter and other backends.
#[debug.print]
By adding #[debug.print] in front of an expression in a Catala program, the
value of that expression will be printed upon computation by the interpreter,
when run with the --debug option. It is otherwise ignored by the other
backends.
It is also possible to print the value along with a specific tag using
#[debug.print = "some debug tag"].
Note that, in some cases, due to how the compiler works, debug prints could
appear duplicated or not at all, especially if optimisations are enabled (with
the -O flag). If that happens, try to move the attribute to the root of the
definition.
#[implicit_position_argument]
The #[implicit_position_argument] is used when declaring a function (often
useful in conjunction with external modules), to
mark one of its arguments of type code_location as implicit. The argument
will not appear when calling the function, and will automatically be filled with
the code position where the function was called from.
This enables functions from libraries that can fail in some definite conditions
to report the error where it happens in the user code, rather than point to the
library. For example, it wouldn’t be very helpful when calling
Utils.custom_division of 2, 0 to report the position of the Utils module
where the custom_division function is defined.
#[json]
Used to supply constants of external types.
#[testcase.*]
These attributes are used by the test case editor UI. They should be attached
to scope declarations used for tests, and usually also marked with #[test].
A test scope declaration produced by the test case editor UI will thus look like this:
#[test]
#[testcase.testui]
#[testcase.test_title = "Some computation"]
declaration scope SomeComputation:
input children_of_age content integer
...
#[testcase.testui]
Signals to the test case editor UI that this scope declaration is a test
that should be displayed in the UI. Must always be accompanied by a
#[test] since UI test cases shoudl always also be regular tests.
#[testcase.test_title]
Displays a title for the test, distinct from the scope name, in the test case editor UI.
#[testcase.uid]
This attribute stores the unique identifier used in React applications to identify React components in a list. It’s a technical stub used by the test case editor UI.
#[testcase.array_item_label]
Displays a name for the the array item in the test case editor UI.
Plugin-supplied attributes
The attribute system of Catala is extensible, and each compiler plugin can define an array of attributes which can be parsed and passed to the plugin, on top of giving new meaning and actions to built-in attributes.