The project is open to external contributions, in the spirit of open source. If you want to open a pull request, please follow the instructions below.
To ask a question to the Catala team, please open an issue on this repository. You can also join the Zulip chat to ask any questions about the project.
If you want to contribute to the project on a longer-term basis, or if you have specific competences as a socio-fiscal lawyer or a programming language specialist, please contact the authors. The Catala team meets over visioconference once every week.
Please note that the copyright of this code is owned by Inria; by contributing, you disclaim all copyright interests in favor of Inria. Both the code for the compiler and the examples in this repository are distributed under the Apache2 license.
Before writing Catala code, please read the Catala book. You can run the
programs of the tutorial yourself by following the instruction in the README of
the examples repository.
Then, it is suggested that you create a new example directory again according to
the instructions of this README.
The Catala compiler is a standard dune-managed OCaml project. You can look at the online OCaml documentation for the different modules' interfaces as well as high-level architecture documentation.
We provide a nix environement to develop the Catala compiler. It is available
after installing nix. You can then just
use nix develop to enter the environment.
Requirements of catala that are not inside nixpkgs are available inside the .nix directory of the repo. The main part is inside the .nix/packages.nix, where all the packages are either added (because absent from nixpkgs) using ocamlPackage.callPackage; or modified from nixpkgs, for instance cmdliner is currently pinned at version 1.1.0.
Please ensure to submit commits formatted using the included ocamlformat
configuration. The make build target should ensure that.
In case the formatting rules or ocamlformat version changed remotely, you can use this script to reformat your branch patch by patch before rebasing.
Pull requests must be approved by, at least, one knowledgable contributor before merging.
Unless there exists legitimate reasons, every commit of the pull request must compile, and, the final commit must successfully pass the CI check.
All requested changes should ideally be included in the PR. However, if the PR is merged while there are still open discussions or if there are late remarks, it should be addressed as soon as possible in a follow-up PR.
As much as possible, offline interactions between the author and reviewer(s) leading to a discussion resolution should result in a quick summary that documents the decision.
Whenever major changes are requested, both PR's author and reviewer(s) may reach an agreement to delay the resolution (e.g., in a future PR) in which case it must be documented as an issue in order to properly track it.
The language provides a limited number of builtin functions, which are sometimes needed for things that can't easily be expressed in Catala itself; in case you need more, here is how one can be added:
- Choose a name wisely. Be ready to patch any code that already used the name for scope parameters, variables or structure fields, since it won't compile anymore.
- Add an element to the
builtin_expressiontype insurface/ast.ml - Add your builtin in the
builtinslist insurface/lexer.cppo.ml, and with proper translations in all of the language-specific modulessurface/lexer_en.cppo.ml,surface/lexer_fr.cppo.ml, etc. Don't forget the macro at the beginning oflexer.cppo.ml. - The rest can all be done by following the type errors downstream:
- Add a corresponding element to the lower-level AST in
shared_ast/definitions.ml, typeOp.t - Extend the generic operations on operators in
shared_ast/operators.mlas well as the type information for the operator - Extend the translation accordingly in
desugared/from_surface.ml - Extend the printer (
shared_ast/print.ml) - Finally, provide the implementations:
- in
dcalc/interpreter.ml, functionevaluate_operator - in
../runtimes/ocaml/runtime.ml - in
../runtimes/python/catala/src/catala/runtime.py
- in
- Add a corresponding element to the lower-level AST in
- Update the syntax guide in
doc/syntax/syntax.texwith your new builtin
The Catala language should be adapted to any legislative text that follows a general-to-specifics statutes order. Therefore, there exists multiple versions of the Catala surface syntax, adapted to the language of the legislative text.
Currently, Catala supports English, French and Polish legislative text via the
--language=en, --language=fr or --language=pl options.
To add support for a new language:
-
the basic syntax localisation is defined in
compiler/surface/lexer_xx.cppo.mlwherexxis the language code (en,fr...) -
copy the files from another language, e.g. english, then replace the strings with your translations. Be careful with the following:
- The file must be encoded in latin-1
- For a given token
FOO, defineMS_FOOto be the string version of the keyword. Due to the encoding, use\xNNescape sequences for utf8 characters. - If the string contains spaces or non-latin1 characters, you need to define
MR_FOOas well with a regular expression in sedlex format. Replace spaces with", space_plus, ", and unicode characters with", 0xNNNN, "whereNNNNis the hexadecimal unicode codepoint.
Hint: You may get syntax errors with unhelpful locations because of
sedlex. In that case the commandocamlc _build/default/compiler/surface/lexer_xx.mlmay point you to the source of the error. -
add your translation to the compilation rules:
- in
compiler/surface/dune, copying anotherparser_xx.cppo.mlrule - in the
extensionslist incompiler/driver.ml - add a corresponding variant to
compiler/utils/cli.mlbackend_lang, try to runmake buildand follow all type errors andmatch non exhaustivewarnings to be sure it is well handled everywhere.
- in
-
you may want to add syntax highlighting support, see
syntax_highlighting/and the rules inMakefile -
add examples and documentation!
Feel free to open a pull request for discussion even if you couldn't go through
all these steps, the lexer_xx.cppo.ml file is the important part.
Catala has support for dynamically-loaded plugins to use as alternative
backends. See compiler/plugins for examples, and the
documentation for more
detail.