Merge pull request #84 from EmileRolley/markdown_literate

Switch to markdown syntax
This commit is contained in:
Denis Merigoux 2021-03-11 11:50:32 +01:00 committed by GitHub
commit 1eeb4405d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
113 changed files with 2441 additions and 2178 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
*.catala* linguist-language=Markdown

View File

@ -1,48 +1,48 @@
# Contributing to Catala
The project is open to external contributions, in the spirit of open source.
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](https://zulip.catala-lang.org/) to ask
To ask a question to the Catala team, please open an issue on this repository.
You can also join the [Zulip chat](https://zulip.catala-lang.org/) 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,
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](mailto:contact@catala-lang.org).
The Catala team meets over visioconference once every two weeks.
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
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.
### Writing Catala code
Before writing Catala code, please read the
[tutorial](https://catala-lang.org/en/examples/tutorial). You can run the
programs of the tutorial yourself by following the instruction in the
[README of the `examples` directory](examples/README.md). Then, it is suggested
that you create a new example directory again according to the instructions of
Before writing Catala code, please read the
[tutorial](https://catala-lang.org/en/examples/tutorial). You can run the
programs of the tutorial yourself by following the instruction in the
[README of the `examples` directory](examples/README.md). Then, it is suggested
that you create a new example directory again according to the instructions of
this README.
Let us now present the typical Catala workflow. First, you need to locate
the legislative text that you want to use as a reference. Then, simply
the legislative text that you want to use as a reference. Then, simply
copy-paste the text into your source file.
First you will have to format the copy-pasted text using Catala headings
First you will have to format the copy-pasted text using Catala headings
and articles markers:
```
@@Heading@@
```markdown
## Heading
@@Sub-heading (the more +, the less important)@@++
### Sub-heading (the more '#', the less important)
@Legislative atom@
#### [Legislative atom]
```
Please look at the code of other examples to see how to format things properly.
While formatting the text, don't forget regularly to try and parse your example
Please look at the code of other examples to see how to format things properly.
While formatting the text, don't forget regularly to try and parse your example
using for instance
@ -50,57 +50,59 @@ using for instance
make -C examples/foo foo.tex
```
to see if you've made any syntax errors. Once the text formatting is done, you
can start to annotate each legislative atom (article, provision, etc.) with
to see if you've made any syntax errors. Once the text formatting is done, you
can start to annotate each legislative atom (article, provision, etc.) with
some Catala code. To open up a code section in Catala, simply use
```
/*
~~~markdown
```catala
# In code sections, comments start with #
scope Foo:
<your code goes here>
*/
```
~~~
While all the code sections are equivalent in terms of execution, you can
mark some as "metadata" so that they are printed differently on lawyer-facing
While all the code sections are equivalent in terms of execution, you can
mark some as "metadata" so that they are printed differently on lawyer-facing
documents. Here's how it works:
```
@@Begin metadata@@ # @@Début métadonnées@@ en français
/*
~~~markdown
> Begin metadata # > Début métadonnées en français
```catala
declaration structure FooBar:
data foo content boolean
data bar content money
<your structure/enumeration/scope declarations goes here>
*/
@@End metadata@@ # @@Fin métadonnées@@ en français
```
Again, make sure to regularly check that your example is parsing correctly. The error message from the compiler should help you debug the syntax if need be. You can also
> End metadata # > Fin métadonnées en français
~~~
Again, make sure to regularly check that your example is parsing correctly. The error message from the compiler should help you debug the syntax if need be. You can also
live-test the programs you wrote by feeding them to the interpreter
(see the [README of the `examples` directory](examples/README.md)); this will
(see the [README of the `examples` directory](examples/README.md)); this will
also type-check the programs, which is useful for debugging them.
## Working on the compiler
The Catala compiler is a standard dune-managed OCaml project.
You can look at the
[online OCaml documentation](https://catala-lang.org/ocaml_docs/) for the
The Catala compiler is a standard dune-managed OCaml project.
You can look at the
[online OCaml documentation](https://catala-lang.org/ocaml_docs/) for the
different modules' interfaces as well as high-level architecture documentation.
## Internationalization
The Catala language should be adapted to any legislative text that follows a
general-to-specifics statutes order. Therefore, there exists multiple versions
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 and French legislative text via the
`--language=en` or `--language=fr` option.
Currently, Catala supports English and French legislative text via the
`--language=en` or `--language=fr` option.
Technically, support for new languages can be added via a new lexer. If you want
to add a new language, you can start from
[existing lexer examples](src/catala/catala_surface/lexer_fr.ml), tweak and open
a pull request. If you don't feel familiar enough with OCaml to do so, please
Technically, support for new languages can be added via a new lexer. If you want
to add a new language, you can start from
[existing lexer examples](src/catala/catala_surface/lexer_fr.ml), tweak and open
a pull request. If you don't feel familiar enough with OCaml to do so, please
leave an issue on this repository.

View File

@ -25,7 +25,7 @@ you want to implement. Then, you can proceed to annotate the text article by
article, in your favorite text editor :
<center>
<img src="https://github.com/CatalaLang/catala/raw/master/doc/images/ScreenShotVSCode.png" alt="Screenshot" height="500"/>
<img src="https://github.com/CatalaLang/catala/raw/master/doc/images/ScreenShotVSCode.png" alt="Screenshot" height="450"/>
</center>
Once your code is complete and tested, you can use the Catala
@ -36,7 +36,7 @@ can be reviewed and certified correct by the domain experts, which
are in this case lawyers and not programmers.
<center>
<img src="https://github.com/CatalaLang/catala/raw/master/doc/images/CatalaScreenShot.png" alt="Screenshot" height="500"/>
<img src="https://github.com/CatalaLang/catala/raw/master/doc/images/CatalaScreenShot.png" alt="Screenshot" height="400"/>
</center>
The Catala language is special because its logical structure mimics

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 199 KiB

View File

@ -1,63 +1,63 @@
# Catala examples
This directory contains examples of Catala programs. It is highly recommended
to locate your own Catala programs in this directory, since programs in this
directory will receive first-class support during the alpha and beta stage
This directory contains examples of Catala programs. It is highly recommended
to locate your own Catala programs in this directory, since programs in this
directory will receive first-class support during the alpha and beta stage
of the Catala programming language development.
## List of examples
## List of examples
* `allocations_familiales/`: computation of the French family benefits, based
on the _Code de la sécurité sociale_. This case study is the biggest and
* `allocations_familiales/`: computation of the French family benefits, based
on the _Code de la sécurité sociale_. This case study is the biggest and
most ambitious for Catala so far.
* `code_general_impots/`: computation of the French income tax, based on the
* `code_general_impots/`: computation of the French income tax, based on the
_Code général des impôts_. Currently, there are only stubs of program.
* `tutorial/`: Catala language tutorial for developers of tech-savvy lawyers.
The tutorial is written like a piece of legislation that gets annotated by
The tutorial is written like a piece of legislation that gets annotated by
Catala snippets.
* `us_tax_code/`: contains the Catala formalization of several sections of the
* `us_tax_code/`: contains the Catala formalization of several sections of the
US Tax Code.
## Building and running examples
Building and running examples is done via Makefiles. Each example directory
contains its own Makefile, which includes `Makefile.common.mk`. This common
Makefiles defines a list of targets that call the Catala compiler with the
right options. Each of these targers can be called from the root of the
Building and running examples is done via Makefiles. Each example directory
contains its own Makefile, which includes `Makefile.common.mk`. This common
Makefiles defines a list of targets that call the Catala compiler with the
right options. Each of these targers can be called from the root of the
repository with:
make -C examples/<directory of example> <name of target>
make -C examples/<directory of example> <name of target>
The `<name of target>` can be replaced with the following (we assume an example
file `examples/foo/foo.catala_en`) list.
* `foo.tex`: builds the LaTeX literate programming output from the Catala program
* `foo.tex`: builds the LaTeX literate programming output from the Catala program
* `foo.pdf`: compiles `foo.tex` using `latexmk`
* `foo.html`: builds the HTML literate programming output from the Catala program
* `foo.run`: interprets the Catala program contained in `foo.catala_en`. Note
* `foo.run`: interprets the Catala program contained in `foo.catala_en`. Note
that you have to pass in the scope that you want to interpret via the `SCOPE`
Makefile variable (`SCOPE=FooScope make -C examples/foo foo.run`).
When invoking any of these targets, additional options to the Catala compiler
When invoking any of these targets, additional options to the Catala compiler
can be passed using the `CATALA_OPTS` Makefile variable.
## Testing examples
Unit testing is important, and we encourage Catala developers to write lots
of tests for their programs. Again, the Makefile system provides a way to
Unit testing is important, and we encourage Catala developers to write lots
of tests for their programs. Again, the Makefile system provides a way to
collect tests into a regression test suite.
In order to enjoy the benefits of this system, you have to create a `tests/`
In order to enjoy the benefits of this system, you have to create a `tests/`
directory in your examples directory, for instance `examples/foo/tests`. Then,
create a test file `foo_tests.catala_en` inside that directory.
Inside `foo_tests.catala_en`, declare one ore more test scopes. It is assumed
that all these scopes should execute correctly. Include the program scope you
Inside `foo_tests.catala_en`, declare one ore more test scopes. It is assumed
that all these scopes should execute correctly. Include the program scope you
want to test and use assertions to provide the expected values of your test.
See existing tests in examples directory for more information.
Once your tests are written, then will automatically be added to the regression
suite executed using
Once your tests are written, then will automatically be added to the regression
suite executed using
make -C examples tests
@ -67,28 +67,28 @@ You can isolate a part of the regression suite by invoking:
## Adding an example
This section describes what to do to setup a working directory for a new Catala
example, as well as the development cycle. Let us suppose that you want to
This section describes what to do to setup a working directory for a new Catala
example, as well as the development cycle. Let us suppose that you want to
create a new example named `foo`.
First, follow the instructions of [the installation readme](../INSTALL.md) to
get the compiler up and working up to `make build`. You can also set up the
get the compiler up and working up to `make build`. You can also set up the
syntax highlighting for your editor.
Then, create the directory `examples/foo`. In there, create a master source
file `foo.catala` that will be the root of your Catala program.
You can then start programming in `foo.catala`, or split up your example
into multiple files. In the later case, `foo.catala` must only contain
Then, create the directory `examples/foo`. In there, create a master source
file `foo.catala` that will be the root of your Catala program.
You can then start programming in `foo.catala`, or split up your example
into multiple files. In the later case, `foo.catala` must only contain
something like this:
```
@@Master file@@
```markdown
# Master file
@@Include: bar.catala@@
> Include: bar.catala
```
where `examples/bar.catala` is another source file containing code for your
example. Make sure you start by including some content in the source files,
where `examples/bar.catala` is another source file containing code for your
example. Make sure you start by including some content in the source files,
like
```
@ -114,9 +114,9 @@ make -C examples/foo foo.tex
from the repository root to create the LaTeX weaving output of your source
program. `Hello, world!` should appear in `examples/foo/foo.tex`.
Finally, please add a rule for your example in the repository root
Finally, please add a rule for your example in the repository root
`Makefile` in the section "Examples-related rules", following the pattern
for other examples. This will ensure that your example is built every
time the compiler is modified; if a change in the compiler breaks your example,
for other examples. This will ensure that your example is built every
time the compiler is modified; if a change in the compiler breaks your example,
the authors will be notified and find a solution.

View File

@ -1,13 +1,13 @@
@@Fichier maître@@
# Fichier maître
@@Inclusion: prologue.catala_fr@@
> Inclusion: prologue.catala_fr
@@Inclusion: securite_sociale_L.catala_fr@@
> Inclusion: securite_sociale_L.catala_fr
@@Inclusion: securite_sociale_R.catala_fr@@
> Inclusion: securite_sociale_R.catala_fr
@@Inclusion: securite_sociale_D.catala_fr@@
> Inclusion: securite_sociale_D.catala_fr
@@Inclusion: decrets_divers.catala_fr@@
> Inclusion: decrets_divers.catala_fr
@@Inclusion: epilogue.catala_fr@@
> Inclusion: epilogue.catala_fr

View File

@ -1,110 +1,110 @@
@@Instructions ministérielles@@
## Instructions ministérielles
@INSTRUCTION INTERMINISTERIELLE N° DSS/SD2B/2019/65 du 25 mars 2019 relative
à la revalorisation au 1er avril 2019 des prestations familiales servies en
métropole@
#### [INSTRUCTION INTERMINISTERIELLE N° DSS/SD2B/2019/65 du 25 mars 2019 relative
à la revalorisation au 1er avril 2019 des prestations familiales servies en
métropole]
Conformément à larticle L. 551-1 du code de la sécurité sociale, le montant
des prestations familiales est déterminé d'après des bases mensuelles
de calcul revalorisées au 1er avril de chaque année, par application
du coefficient mentionnée à larticle L. 161-25 du code de la
sécurité sociale. Au titre de lannée 2019, larticle 68 de la loi du 22
décembre 2018 de financement de la sécurité sociale a prévu, par dérogation
aux dispositions de larticle L. 161-25, une revalorisation de 0,3 % du montant
des prestations relevant de cet article.
Conformément à larticle L. 551-1 du code de la sécurité sociale, le montant
des prestations familiales est déterminé d'après des bases mensuelles
de calcul revalorisées au 1er avril de chaque année, par application
du coefficient mentionnée à larticle L. 161-25 du code de la
sécurité sociale. Au titre de lannée 2019, larticle 68 de la loi du 22
décembre 2018 de financement de la sécurité sociale a prévu, par dérogation
aux dispositions de larticle L. 161-25, une revalorisation de 0,3 % du montant
des prestations relevant de cet article.
Le montant précité de la base mensuelle de calcul des allocations
familiales (BMAF), en pourcentage duquel sont fixés les montants des prestations
Le montant précité de la base mensuelle de calcul des allocations
familiales (BMAF), en pourcentage duquel sont fixés les montants des prestations
familiales, est ainsi porté de 411,92 € à 413,16 € au 1er avril 2019.
/*
```catala
champ d'application PrestationsFamiliales :
définition base_mensuelle
sous condition
date_courante >=@ |01/04/2019| et
date_courante <@ |01/04/2020|
conséquence égal à 413,16 €
*/
```
@Instruction interministérielle no DSS/SD2B/2020/33 du 18 février 2020
#### [Instruction interministérielle no DSS/SD2B/2020/33 du 18 février 2020
relative à la revalorisation au 1er avril 2020 des prestations
familiales servies en métropole, en Guadeloupe, en Guyane, en
Martinique, à La Réunion, à Saint-Barthélemy, à Saint-Martin et dans
le département de Mayotte@
le département de Mayotte]
Au titre de lannée 2020, larticle 81 de la loi du 24 décembre 2019 de
financement de la sécurité sociale a prévu, par dérogation aux dispositions
de larticle L. 161-25, une revalorisation de 0,3 % du montant des prestations
relevant de cet article.
Le montant précité de la base mensuelle de calcul des allocations familiales
(BMAF), en pourcentage duquel sont fxés les montants des prestations familiales,
Le montant précité de la base mensuelle de calcul des allocations familiales
(BMAF), en pourcentage duquel sont fxés les montants des prestations familiales,
est ainsi porté de 413,16 € à 414,4 € au 1er avril 2020.
/*
```catala
champ d'application PrestationsFamiliales :
définition base_mensuelle
sous condition
date_courante >=@ |01/04/2020| et
date_courante <@ |01/04/2021|
conséquence égal à 414,4 €
*/
```
@Instruction interministerielle no DSS/SD2B/2019/261 du 18 décembre 2019
relative à la revalorisation au 1er janvier 2020 des plafonds de ressources
dattribution de certaines prestations familiales servies en métropole,
en Guadeloupe, en Guyane, en Martinique, à La Réunion, à Saint-Barthélemy,
à Saint-Martin et à Mayotte@
#### [Instruction interministerielle no DSS/SD2B/2019/261 du 18 décembre 2019
relative à la revalorisation au 1er janvier 2020 des plafonds de ressources
dattribution de certaines prestations familiales servies en métropole,
en Guadeloupe, en Guyane, en Martinique, à La Réunion, à Saint-Barthélemy,
à Saint-Martin et à Mayotte]
Plafonds de ressources applicables pour lattribution du montant modulé des
allocations familiales, de la majoration pour âge et de lallocation forfaitaire,
du 1er janvier 2020 au 31 décembre 2020 (à comparer au revenu net catégoriel de
Plafonds de ressources applicables pour lattribution du montant modulé des
allocations familiales, de la majoration pour âge et de lallocation forfaitaire,
du 1er janvier 2020 au 31 décembre 2020 (à comparer au revenu net catégoriel de
lannée 2018)
La première tranche est celle dont les revenus sont inférieurs ou
égaux à un plafond de base de 57 759 € majoré de 5 775 € par
enfant à charge. La deuxième tranche est celle dont les revenus
sont supérieurs à un plafond de base de 57 759 € majoré de 5 775
€ par enfant à charge mais inférieurs ou égaux au plafond de base
de 80 831 € majoré de 5 775 € par enfant à charge. La troisième
tranche est celle dont les revenus sont supérieurs au plafond de base de
La première tranche est celle dont les revenus sont inférieurs ou
égaux à un plafond de base de 57 759 € majoré de 5 775 € par
enfant à charge. La deuxième tranche est celle dont les revenus
sont supérieurs à un plafond de base de 57 759 € majoré de 5 775
€ par enfant à charge mais inférieurs ou égaux au plafond de base
de 80 831 € majoré de 5 775 € par enfant à charge. La troisième
tranche est celle dont les revenus sont supérieurs au plafond de base de
80 831 € majoré de 5 775 € par enfant à charge.
/*
```catala
champ d'application AllocationsFamiliales :
exception
définition plafond_I_d521_3 sous condition
définition plafond_I_d521_3 sous condition
date_courante >=@ |01/01/2020| et date_courante <=@ |31/12/2020|
conséquence égal à 57 759 € +€
5 775 € *€ (entier_vers_décimal de
5 775 € *€ (entier_vers_décimal de
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale))
exception
définition plafond_II_d521_3 sous condition
exception
définition plafond_II_d521_3 sous condition
date_courante >=@ |01/01/2020| et date_courante <=@ |31/12/2020|
conséquence égal à 80 831 € +€
5 775 € *€ (entier_vers_décimal de
5 775 € *€ (entier_vers_décimal de
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale))
*/
```
@@Décrets divers@@
## Décrets divers
@@Décret n° 2018-1173 du 19 décembre 2018 portant relèvement du salaire minimum de croissance@@+
### Décret n° 2018-1173 du 19 décembre 2018 portant relèvement du salaire minimum de croissance
@Article 1|JORFARTI000037833214@
#### [Article 1|JORFARTI000037833214]
A compter du 1er janvier 2019, pour les catégories de travailleurs mentionnés à
l'article L. 2211-1 du code du travail, le montant du salaire minimum de
A compter du 1er janvier 2019, pour les catégories de travailleurs mentionnés à
l'article L. 2211-1 du code du travail, le montant du salaire minimum de
croissance est relevé dans les conditions ci-après :
1° En métropole, en Guadeloupe, en Guyane, en Martinique, à La Réunion,
à Saint-Barthélemy, à Saint-Martin et à Saint-Pierre-et-Miquelon,
1° En métropole, en Guadeloupe, en Guyane, en Martinique, à La Réunion,
à Saint-Barthélemy, à Saint-Martin et à Saint-Pierre-et-Miquelon,
son montant est porté à 10,03 € l'heure.
/*
```catala
champ d'application Smic :
définition brut_horaire sous condition
définition brut_horaire sous condition
date_courante >=@ |01/01/2019| et date_courante <=@ |31/12/2019| et (
(résidence = Métropole) ou
(résidence = Guadeloupe) ou
@ -116,30 +116,34 @@ champ d'application Smic :
(résidence = SaintPierreEtMiquelon)
)
conséquence égal à 10,03 €
*/
```
2° A Mayotte, son montant est fixé à 7,57 € l'heure.
/*
```catala
champ d'application Smic :
définition brut_horaire sous condition
date_courante >=@ |01/01/2019| et date_courante <=@ |31/12/2019| et (
(résidence = Mayotte)
)
conséquence égal à 7,57 €
*/
```
@@Décret n° 2019-1387 du 18 décembre 2019 portant relèvement du salaire minimum de croissance@@+
### Décret n° 2019-1387 du 18 décembre 2019 portant relèvement du salaire minimum de croissance
@Article 1|LEGIARTI000039640195@
A compter du 1er janvier 2020, pour les catégories de travailleurs mentionnés à
l' article L. 2211-1 du code du travail , le montant du salaire minimum de
#### [Article 1|LEGIARTI000039640195]
A compter du 1er janvier 2020, pour les catégories de travailleurs mentionnés à
l' article L. 2211-1 du code du travail , le montant du salaire minimum de
croissance est relevé dans les conditions ci-après :
1° En métropole, en Guadeloupe, en Guyane, en Martinique, à La Réunion,
à Saint-Barthélemy, à Saint-Martin et à Saint-Pierre-et-Miquelon,
1° En métropole, en Guadeloupe, en Guyane, en Martinique, à La Réunion,
à Saint-Barthélemy, à Saint-Martin et à Saint-Pierre-et-Miquelon,
son montant est porté à 10,15 € l'heure ;
/*
```catala
champ d'application Smic :
définition brut_horaire sous condition
définition brut_horaire sous condition
date_courante >=@ |01/01/2020| et date_courante <=@ |31/12/2020| et (
(résidence = Métropole) ou
(résidence = Guadeloupe) ou
@ -151,31 +155,34 @@ champ d'application Smic :
(résidence = SaintPierreEtMiquelon)
)
conséquence égal à 10,15 €
*/
```
2° A Mayotte, son montant est fixé à 7,66 € l'heure.
/*
```catala
champ d'application Smic :
définition brut_horaire sous condition
date_courante >=@ |01/01/2020| et date_courante <=@ |31/12/2020| et (
(résidence = Mayotte)
)
conséquence égal à 7,66 €
*/
```
@@Décret n° 2020-1598 du 16 décembre 2020 portant relèvement du salaire minimum de croissance@@+
### Décret n° 2020-1598 du 16 décembre 2020 portant relèvement du salaire minimum de croissance
@Article 1|JORFARTI000042677367@
#### [Article 1|JORFARTI000042677367]
A compter du 1er janvier 2021, pour les catégories de travailleurs mentionnés à
l'article L. 2211-1 du code du travail, le montant du salaire minimum de
A compter du 1er janvier 2021, pour les catégories de travailleurs mentionnés à
l'article L. 2211-1 du code du travail, le montant du salaire minimum de
croissance est relevé dans les conditions ci-après :
1° En métropole, en Guadeloupe, en Guyane, en Martinique, à La Réunion,
à Saint-Barthélemy, à Saint-Martin et à Saint-Pierre-et-Miquelon,
1° En métropole, en Guadeloupe, en Guyane, en Martinique, à La Réunion,
à Saint-Barthélemy, à Saint-Martin et à Saint-Pierre-et-Miquelon,
son montant est porté à 10,25 € l'heure ;
/*
```catala
champ d'application Smic :
définition brut_horaire sous condition
définition brut_horaire sous condition
date_courante >=@ |01/01/2021| et date_courante <=@ |31/12/2021| et (
(résidence = Métropole) ou
(résidence = Guadeloupe) ou
@ -187,50 +194,51 @@ champ d'application Smic :
(résidence = SaintPierreEtMiquelon)
)
conséquence égal à 10,25 €
*/
```
2° A Mayotte, son montant est fixé à 7,74 € l'heure.
/*
```catala
champ d'application Smic :
définition brut_horaire sous condition
date_courante >=@ |01/01/2021| et date_courante <=@ |31/12/2021| et (
(résidence = Mayotte)
)
conséquence égal à 7,74 €
*/
```
@@Arrêté du 14 décembre 2020 relatif au montant des plafonds de ressources de certaines prestations familiales et aux tranches du barème applicable au recouvrement des indus et à la saisie des prestations@@+
### Arrêté du 14 décembre 2020 relatif au montant des plafonds de ressources de certaines prestations familiales et aux tranches du barème applicable au recouvrement des indus et à la saisie des prestations
@Article 1|JORFARTI000042694985@
#### [Article 1|JORFARTI000042694985]
I. - Le plafond de ressources prévu au 1° du I des articles D. 521-1 et D. 521-2
du code de la sécurité sociale relatif aux allocations familiales, à la majoration
pour âge et à l'allocation forfaitaire prévue au deuxième alinéa de l'article
L. 521-1 est fixé à 58 279 euros pour la période du 1er janvier 2021 au 31
I. - Le plafond de ressources prévu au 1° du I des articles D. 521-1 et D. 521-2
du code de la sécurité sociale relatif aux allocations familiales, à la majoration
pour âge et à l'allocation forfaitaire prévue au deuxième alinéa de l'article
L. 521-1 est fixé à 58 279 euros pour la période du 1er janvier 2021 au 31
décembre 2021. Il est majoré de 5 827 euros par enfant à charge.
/*
```catala
champ d'application AllocationsFamiliales :
exception
définition plafond_I_d521_3 sous condition
définition plafond_I_d521_3 sous condition
date_courante >=@ |01/01/2021| et date_courante <=@ |31/12/2021|
conséquence égal à 58 279 € +€
5 827 € *€ (entier_vers_décimal de
5 827 € *€ (entier_vers_décimal de
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale))
*/
```
II. - Le plafond de ressources prévu au 2° du I des articles D. 521-1 et
D. 521-2 du même code relatif aux allocations familiales, à la majoration
pour âge et à l'allocation forfaitaire prévue au deuxième alinéa de l'article
L. 521-1 est fixé à 81 558 euros pour la période du 1er janvier 2021 au 31
II. - Le plafond de ressources prévu au 2° du I des articles D. 521-1 et
D. 521-2 du même code relatif aux allocations familiales, à la majoration
pour âge et à l'allocation forfaitaire prévue au deuxième alinéa de l'article
L. 521-1 est fixé à 81 558 euros pour la période du 1er janvier 2021 au 31
décembre 2021. Il est majoré de 5 827 euros par enfant à charge.
/*
```catala
champ d'application AllocationsFamiliales :
exception
définition plafond_II_d521_3 sous condition
exception
définition plafond_II_d521_3 sous condition
date_courante >=@ |01/01/2021| et date_courante <=@ |31/12/2021|
conséquence égal à 81 558 € +€
5 827 € *€ (entier_vers_décimal de
5 827 € *€ (entier_vers_décimal de
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale))
*/
```

View File

@ -1,84 +1,87 @@
@@Épilogue@@
## Épilogue
@@Règles diverses@@+
### Règles diverses
Les textes législatifs et règlementaires contiennent toutes les informations
nécessaires au calcul. Cependant, certaines règles de calcul sont implicites
dans ces textes et doivent être explicitées pour le calcul informatique. C'est
kécessaires au calcul. Cependant, certaines règles de calcul sont implicites
dans ces textes et doivent être explicitées pour le calcul informatique. C'est
la fonction du bloc de code ci-dessous.
@@Début métadonnées@@
/*
> Début métadonnées
```catala
champ d'application EnfantLePlusÂgé:
définition le_plus_âgé égal à
définition le_plus_âgé égal à
contenu maximum entier initial Enfant {
-- identifiant: -1
-- fin_obligation_scolaire: |01/01/1900|
-- rémuneration_mensuelle: 0€
-- date_de_naissance: |01/01/1900|
-- âge: 0
-- âge: 0
-- garde_alternée: NonGardeUnique
-- prise_en_charge_par_services_sociaux: NonPriseEnChargeFamille
}
pour potentiel_plus_âgé dans enfants de
}
pour potentiel_plus_âgé dans enfants de
potentiel_plus_âgé.âge
champ d'application PrestationsFamiliales:
champ d'application PrestationsFamiliales:
définition âge_l512_3_2_alternatif égal à Absent
champ d'application AllocationsFamiliales:
définition montant_initial_majoration de enfant sous condition
définition montant_initial_majoration de enfant sous condition
non (droit_ouvert_majoration de enfant)
conséquence égal à 0 €
règle droit_ouvert_complément rempli
définition enfant_le_plus_âgé.enfants égal à enfants_à_charge
définition est_enfant_le_plus_âgé de enfant égal à
définition enfant_le_plus_âgé.enfants égal à enfants_à_charge
définition est_enfant_le_plus_âgé de enfant égal à
enfant_le_plus_âgé.le_plus_âgé = enfant
définition montant_versé_base égal à
définition montant_versé_base égal à
si droit_ouvert_base alors montant_avec_garde_alternée_base sinon 0€
définition montant_versé_majoration égal à
définition montant_versé_majoration égal à
si droit_ouvert_base alors
somme argent pour enfant dans enfants_à_charge de
montant_avec_garde_alternée_majoration de enfant
somme argent pour enfant dans enfants_à_charge de
montant_avec_garde_alternée_majoration de enfant
sinon 0€
définition montant_versé égal à
définition montant_versé égal à
si droit_ouvert_base alors
montant_versé_base +€
montant_versé_majoration +€
montant_versé_forfaitaire +€
montant_versé_complément_pour_base_et_majoration +€
montant_versé_complément_pour_forfaitaire
montant_versé_complément_pour_forfaitaire
sinon 0€
*/
@@Fin métadonnées@@
```
@@Interface du programme@@+
> Fin métadonnées
Le calcul des allocations familiales nécessite un certain nombre d'informations
sur les enfants à charge. Certaines de ces informations sont dépendantes les
unes des autres : par exemple, l'âge de l'enfant se déduit de sa date de
naissance. Le but du block ci-dessous est d'encoder ces dépendances, de telle
sorte que l'utilisateur puisse ne doive saisir que le nombre minimal
d'informations sur les enfants à charge.
### Interface du programme
@@Début métadonnées@@
/*
déclaration structure EnfantEntrée:
Le calcul des allocations familiales nécessite un certain nombre d'informations
sur les enfants à charge. Certaines de ces informations sont dépendantes les
unes des autres : par exemple, l'âge de l'enfant se déduit de sa date de
naissance. Le but du block ci-dessous est d'encoder ces dépendances, de telle
sorte que l'utilisateur puisse ne doive saisir que le nombre minimal
d'informations sur les enfants à charge.
> Début métadonnées
```catala
déclaration structure EnfantEntrée:
donnée d_identifiant contenu entier
donnée d_rémuneration_mensuelle contenu argent
donnée d_date_de_naissance contenu date
donnée d_garde_alternée contenu GardeAlternée
donnée d_prise_en_charge_par_services_sociaux contenu
donnée d_prise_en_charge_par_services_sociaux contenu
PriseEnChargeServiceSociaux
déclaration champ d'application InterfaceAllocationsFamiliales:
contexte date_courante contenu date
contexte enfants contenu collection EnfantEntrée
contexte enfants contenu collection EnfantEntrée
contexte enfants_à_charge contenu collection Enfant
contexte allocations_familiales champ d'application AllocationsFamiliales
contexte ressources_ménage contenu argent
@ -86,39 +89,41 @@ déclaration champ d'application InterfaceAllocationsFamiliales:
contexte montant_versé contenu argent
champ d'application InterfaceAllocationsFamiliales:
définition allocations_familiales.date_courante égal à date_courante
définition allocations_familiales.date_courante égal à date_courante
définition allocations_familiales.enfants_à_charge égal à enfants_à_charge
définition allocations_familiales.ressources_ménage égal à ressources_ménage
définition allocations_familiales.résidence égal à résidence
définition montant_versé égal à allocations_familiales.montant_versé
assertion non (existe enfant dans enfants tel que
enfant.d_garde_alternée != NonGardeUnique et
assertion non (existe enfant dans enfants tel que
enfant.d_garde_alternée != NonGardeUnique et
enfant.d_prise_en_charge_par_services_sociaux != NonPriseEnChargeFamille
)
*/
@@Fin métadonnées@@
```
@@Code de l'éducation@@++
> Fin métadonnées
@Article L131-1|LEGIARTI000038901859@
#### Code de l'éducation
L'instruction est obligatoire pour chaque enfant dès l'âge de trois ans et
#### [Article L131-1|LEGIARTI000038901859]
L'instruction est obligatoire pour chaque enfant dès l'âge de trois ans et
jusqu'à l'âge de seize ans.
La présente disposition ne fait pas obstacle à l'application des prescriptions
La présente disposition ne fait pas obstacle à l'application des prescriptions
particulières imposant une scolarité plus longue.
/*
```catala
champ d'application InterfaceAllocationsFamiliales:
définition enfants_à_charge égal à application pour enfant dans enfants de
définition enfants_à_charge égal à application pour enfant dans enfants de
Enfant {
-- identifiant : enfant.d_identifiant
-- rémuneration_mensuelle : enfant.d_rémuneration_mensuelle
-- date_de_naissance : enfant.d_date_de_naissance
-- prise_en_charge_par_services_sociaux :
-- prise_en_charge_par_services_sociaux :
enfant.d_prise_en_charge_par_services_sociaux
-- garde_alternée : enfant.d_garde_alternée
-- âge: accès_année de
-- âge: accès_année de
(|01/01/0000| +@ (date_courante -@ enfant.d_date_de_naissance))
-- fin_obligation_scolaire : enfant.d_date_de_naissance +@ 16 an
}
*/
```

View File

@ -1,11 +1,12 @@
@@Prologue@@
## Prologue
Avant de présenter les textes réglementaires qui régissent le calcul des
Avant de présenter les textes réglementaires qui régissent le calcul des
allocations familiales, il est nécessaire de définir les structures de données
informatiques qui modélisent la situation dont parlent ces textes législatifs.
@@Début métadonnées@@
/*
> Début métadonnées
```catala
déclaration structure Personne:
donnée numéro_sécurité_sociale contenu entier
@ -26,7 +27,7 @@ déclaration structure Enfant :
donnée date_de_naissance contenu date
donnée âge contenu entier
donnée garde_alternée contenu GardeAlternée
donnée prise_en_charge_par_services_sociaux contenu
donnée prise_en_charge_par_services_sociaux contenu
PriseEnChargeServiceSociaux
déclaration énumération Collectivité :
@ -49,28 +50,28 @@ déclaration énumération PriseEnCompteÉvaluationMontant:
-- Complète
-- Partagée
déclaration énumération VersementAllocations:
déclaration énumération VersementAllocations:
-- Normal
-- AllocationVerséeAuxServicesSociaux
déclaration énumération ÂgeAlternatif:
-- Absent
-- Absent
-- Présent contenu entier
déclaration énumération ÉlémentPrestationsFamiliales:
-- PrestationAccueilJeuneEnfant
-- AllocationsFamiliales
-- ComplémentFamilial
-- ComplémentFamilial
-- AllocationLogement
-- AllocationÉducationEnfantHandicapé
-- AllocationSoutienFamilial
-- AllocationRentréeScolaire
-- AllocationRentréeScolaire
-- AllocationJournalièrePresenceParentale
déclaration champ d'application PrestationsFamiliales:
contexte droit_ouvert condition dépend de Enfant
contexte conditions_hors_âge condition dépend de Enfant
contexte plafond_l512_3_2 contenu argent
contexte plafond_l512_3_2 contenu argent
contexte âge_l512_3_2 contenu entier
contexte âge_l512_3_2_alternatif contenu ÂgeAlternatif
contexte régime_outre_mer_l751_1 condition
@ -88,23 +89,23 @@ déclaration champ d'application AllocationFamilialesAvril2008:
contexte âge_limite_alinéa_1_l521_3 contenu entier
déclaration énumération StockageEnfant:
-- PasEnfant
-- PasEnfant
-- UnEnfant contenu Enfant
déclaration champ d'application EnfantLePlusÂgé:
contexte enfants contenu collection Enfant
contexte le_plus_âgé contenu Enfant
contexte enfants contenu collection Enfant
contexte le_plus_âgé contenu Enfant
déclaration champ d'application AllocationsFamiliales:
contexte enfants_à_charge contenu collection Enfant
contexte enfants_à_charge_droit_ouvert_prestation_familiale
contexte enfants_à_charge contenu collection Enfant
contexte enfants_à_charge_droit_ouvert_prestation_familiale
contenu collection Enfant
contexte date_courante contenu date
contexte résidence contenu Collectivité
contexte ressources_ménage contenu argent
contexte prise_en_compte contenu
contexte prise_en_compte contenu
PriseEnCompteÉvaluationMontant dépend de Enfant
contexte versement contenu
contexte versement contenu
VersementAllocations dépend de Enfant
contexte montant_versé contenu argent
@ -114,14 +115,14 @@ déclaration champ d'application AllocationsFamiliales:
contexte montant_versé_base contenu argent
contexte montant_avec_garde_alternée_base contenu argent
contexte montant_initial_base contenu argent
contexte montant_initial_base_premier_enfant contenu argent
contexte montant_initial_base_deuxième_enfant contenu argent
contexte montant_initial_base_premier_enfant contenu argent
contexte montant_initial_base_deuxième_enfant contenu argent
contexte montant_initial_base_troisième_enfant_et_plus contenu argent
contexte rapport_enfants_total_moyen contenu décimal
contexte nombre_moyen_enfants contenu décimal
contexte nombre_total_enfants contenu décimal
contexte droit_ouvert_forfaitaire condition dépend de Enfant
contexte droit_ouvert_forfaitaire condition dépend de Enfant
contexte montant_versé_forfaitaire contenu argent
contexte montant_versé_majoration contenu argent
@ -147,12 +148,13 @@ déclaration champ d'application AllocationsFamiliales:
contexte plafond_II_d521_3 contenu argent
champ d'application AllocationsFamiliales:
définition prestations_familiales.prestation_courante égal à
définition prestations_familiales.prestation_courante égal à
AllocationsFamiliales
définition prestations_familiales.date_courante égal à
définition prestations_familiales.date_courante égal à
date_courante
définition prestations_familiales.résidence égal à
définition prestations_familiales.résidence égal à
résidence
*/
@@Fin métadonnées@@
```
> Fin métadonnées

View File

@ -1,29 +1,32 @@
## Partie réglementaire - Décrets simples
@@Partie réglementaire - Décrets simples@@+
#### Livre 5 : Prestations familiales et prestations assimilées
@@Livre 5 : Prestations familiales et prestations assimilées@@++
##### Titre 2 : Prestations générales d'entretien
@@Titre 2 : Prestations générales d'entretien@@+++
###### Chapitre 1er : Allocations familiales
@@Chapitre 1er : Allocations familiales@@++++
#### [Article D521-1|LEGIARTI000030680318]
@Article D521-1|LEGIARTI000030680318@
I.-Pour l'application de l'article L. 521-1 , le montant des allocations
familiales et de la majoration pour âge prévue à l'article L. 521-3
I.-Pour l'application de l'article L. 521-1 , le montant des allocations
familiales et de la majoration pour âge prévue à l'article L. 521-3
est défini selon le barème suivant :
/*
```catala
# Composantes des allocations familiales
champ d'application AllocationsFamiliales :
définition montant_initial_base égal à
montant_initial_base_deuxième_enfant +€
montant_initial_base_troisième_enfant_et_plus
*/
1° Lorsque le ménage ou la personne a disposé d'un montant de ressources
inférieur ou égal au plafond défini au I de l'article D. 521-3, les taux
servant au calcul des allocations familiales sont fixés, en pourcentage
```
1° Lorsque le ménage ou la personne a disposé d'un montant de ressources
inférieur ou égal au plafond défini au I de l'article D. 521-3, les taux
servant au calcul des allocations familiales sont fixés, en pourcentage
de la base mensuelle prévue à l'article L. 551-1, à :
a) 32 % pour le deuxième enfant à charge ;
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_initial_base_deuxième_enfant sous condition
ressources_ménage <=€ plafond_I_d521_3
@ -31,10 +34,11 @@ champ d'application AllocationsFamiliales :
si nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 2
alors prestations_familiales.base_mensuelle *€ 32 %
sinon 0 €
*/
```
b) 41 % pour le troisième enfant à charge et chacun des suivants.
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_initial_base_troisième_enfant_et_plus
sous condition
@ -42,29 +46,33 @@ champ d'application AllocationsFamiliales :
conséquence égal à
si nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 3
alors (prestations_familiales.base_mensuelle *€ 41 %) *€ (
entier_vers_décimal de
entier_vers_décimal de
((nombre de enfants_à_charge_droit_ouvert_prestation_familiale) - 2)
) sinon 0 €
*/
La majoration pour âge est fixée à 16 % de la base mensuelle de calcul des
```
La majoration pour âge est fixée à 16 % de la base mensuelle de calcul des
prestations familiales ;
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_initial_majoration de enfant
sous condition
sous condition
(droit_ouvert_majoration de enfant) et
(ressources_ménage <=€ plafond_I_d521_3) et
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 2)
conséquence égal à
prestations_familiales.base_mensuelle *€ 16 %
*/
2° Lorsque le ménage ou la personne a disposé d'un montant de ressources
supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal
à celui défini au II du même article, les taux servant au calcul des
allocations familiales sont fixés, en pourcentage de la base mensuelle
```
2° Lorsque le ménage ou la personne a disposé d'un montant de ressources
supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal
à celui défini au II du même article, les taux servant au calcul des
allocations familiales sont fixés, en pourcentage de la base mensuelle
prévue à l'article L. 551-1, à :
a) 16 % pour le deuxième enfant à charge ;
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_initial_base_deuxième_enfant sous condition
(ressources_ménage >€ plafond_I_d521_3) et
@ -73,9 +81,11 @@ champ d'application AllocationsFamiliales :
si nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 2
alors prestations_familiales.base_mensuelle *€ 32 %
sinon 0 €
*/
```
b) 20,5 % pour le troisième enfant à charge et chacun des suivants.
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_initial_base_troisième_enfant_et_plus
sous condition
@ -84,13 +94,15 @@ champ d'application AllocationsFamiliales :
conséquence égal à
si nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 3
alors (prestations_familiales.base_mensuelle *€ 20,5 %) *€ (
entier_vers_décimal de
entier_vers_décimal de
((nombre de enfants_à_charge_droit_ouvert_prestation_familiale) - 2)
) sinon 0 €
*/
La majoration pour âge est fixée à 8 % de la base mensuelle de calcul des
```
La majoration pour âge est fixée à 8 % de la base mensuelle de calcul des
prestations familiales ;
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_initial_majoration de enfant sous condition
(droit_ouvert_majoration de enfant) et
@ -99,14 +111,15 @@ champ d'application AllocationsFamiliales :
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 2)
conséquence égal à
prestations_familiales.base_mensuelle *€ 8 %
*/
```
3° Lorsque le ménage ou la personne a disposé d'un montant de ressources
supérieur au plafond défini au II de l'article D. 521-3, les taux servant
au calcul des allocations familiales sont fixés, en pourcentage de la base
3° Lorsque le ménage ou la personne a disposé d'un montant de ressources
supérieur au plafond défini au II de l'article D. 521-3, les taux servant
au calcul des allocations familiales sont fixés, en pourcentage de la base
mensuelle prévue à l'article L. 551-1, à :
a) 8 % pour le deuxième enfant à charge ;
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_initial_base_deuxième_enfant sous condition
(ressources_ménage >€ plafond_II_d521_3)
@ -114,9 +127,11 @@ champ d'application AllocationsFamiliales :
si nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 2
alors prestations_familiales.base_mensuelle *€ 8 %
sinon 0 €
*/
```
b) 10,25 % pour le troisième enfant à charge et chacun des suivants.
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_initial_base_troisième_enfant_et_plus
sous condition
@ -124,13 +139,15 @@ champ d'application AllocationsFamiliales :
conséquence égal à
si nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 3
alors (prestations_familiales.base_mensuelle *€ 10,25 %) *€ (
entier_vers_décimal de
entier_vers_décimal de
((nombre de enfants_à_charge_droit_ouvert_prestation_familiale) - 2)
) sinon 0 €
*/
La majoration pour âge est fixée à 4 % de la base mensuelle de calcul des
```
La majoration pour âge est fixée à 4 % de la base mensuelle de calcul des
prestations familiales.
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_initial_majoration de enfant sous condition
(droit_ouvert_majoration de enfant) et
@ -138,20 +155,21 @@ champ d'application AllocationsFamiliales :
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 2)
conséquence égal à
prestations_familiales.base_mensuelle *€ 4 %
*/
```
II.-En application du sixième alinéa de l'article L. 521-1, le montant
mensuel des allocations familiales et, le cas échéant, de la majoration
pour âge est majoré d'un complément dégressif, lorsque les ressources
annuelles du ménage ou de la personne dépassent l'un des plafonds défini
au I ou au II de l'article D. 521-3 d'une somme inférieure à douze fois
le montant mensuel des allocations familiales augmenté, le cas échéant,
II.-En application du sixième alinéa de l'article L. 521-1, le montant
mensuel des allocations familiales et, le cas échéant, de la majoration
pour âge est majoré d'un complément dégressif, lorsque les ressources
annuelles du ménage ou de la personne dépassent l'un des plafonds défini
au I ou au II de l'article D. 521-3 d'une somme inférieure à douze fois
le montant mensuel des allocations familiales augmenté, le cas échéant,
de la ou des majorations pour âge.
Ce complément dégressif est égal, pour chaque mois, au douzième de la
différence entre, d'une part, ce plafond de ressources majoré de la somme
Ce complément dégressif est égal, pour chaque mois, au douzième de la
différence entre, d'une part, ce plafond de ressources majoré de la somme
définie à l'alinéa précédent et, d'autre part, le montant des ressources.
/*
```catala
champ d'application AllocationsFamiliales :
exception
définition dépassement_plafond_ressources de allocation
@ -173,54 +191,58 @@ champ d'application AllocationsFamiliales :
définition dépassement_plafond_ressources de allocations égal à 0 €
définition montant_versé_complément_pour_base_et_majoration égal à
si droit_ouvert_complément alors
(dépassement_plafond_ressources de
si droit_ouvert_complément alors
(dépassement_plafond_ressources de
montant_base_complément_pour_base_et_majoration) *€ (1,0 /. 12,0)
sinon 0 €
définition montant_base_complément_pour_base_et_majoration égal à
définition montant_base_complément_pour_base_et_majoration égal à
montant_versé_base +€ montant_versé_majoration
*/
```
@Article D521-2|LEGIARTI000030680324@
I.-Le montant mensuel de l'allocation forfaitaire prévue au deuxième alinéa de
#### [Article D521-2|LEGIARTI000030680324]
I.-Le montant mensuel de l'allocation forfaitaire prévue au deuxième alinéa de
l'article L. 521-1 est défini selon le barème suivant :
1° Lorsque le ménage ou la personne a disposé d'un montant de ressources
inférieur ou égal au plafond défini au I de l'article D. 521-3, le montant
mensuel de l'allocation forfaitaire est fixé à 20,234 % de la base mensuelle
1° Lorsque le ménage ou la personne a disposé d'un montant de ressources
inférieur ou égal au plafond défini au I de l'article D. 521-3, le montant
mensuel de l'allocation forfaitaire est fixé à 20,234 % de la base mensuelle
de calcul des allocations familiales par enfant ;
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_versé_forfaitaire sous condition
ressources_ménage <=€ plafond_I_d521_3
conséquence égal à
(prestations_familiales.base_mensuelle *€ 20,234 %) *
(prestations_familiales.base_mensuelle *€ 20,234 %) *
entier_vers_décimal de (nombre pour enfant dans enfants_à_charge de
droit_ouvert_forfaitaire de enfant)
*/
```
2° Lorsque le ménage ou la personne a disposé d'un montant de ressources
supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal
à celui défini au II du même article, le montant mensuel de l'allocation
forfaitaire est fixé à 10,117 % de la base mensuelle de calcul des allocations
2° Lorsque le ménage ou la personne a disposé d'un montant de ressources
supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal
à celui défini au II du même article, le montant mensuel de l'allocation
forfaitaire est fixé à 10,117 % de la base mensuelle de calcul des allocations
familiales par enfant ;
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_versé_forfaitaire sous condition
(ressources_ménage >€ plafond_I_d521_3) et
(ressources_ménage <=€ plafond_II_d521_3)
conséquence égal à
(prestations_familiales.base_mensuelle *€ 10,117 %) *
(prestations_familiales.base_mensuelle *€ 10,117 %) *
entier_vers_décimal de (nombre pour enfant dans enfants_à_charge de
droit_ouvert_forfaitaire de enfant)
*/
```
3° Lorsque le ménage ou la personne a disposé d'un montant de ressources
supérieur au plafond défini au II de l'article D. 521-3, le montant mensuel
de l'allocation forfaitaire est fixé à 5,059 % de la base mensuelle de calcul
3° Lorsque le ménage ou la personne a disposé d'un montant de ressources
supérieur au plafond défini au II de l'article D. 521-3, le montant mensuel
de l'allocation forfaitaire est fixé à 5,059 % de la base mensuelle de calcul
des allocations familiales par enfant.
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_versé_forfaitaire sous condition
ressources_ménage >€ plafond_II_d521_3
@ -228,84 +250,89 @@ champ d'application AllocationsFamiliales :
(prestations_familiales.base_mensuelle *€ 5,059 %) *
entier_vers_décimal de (nombre pour enfant dans enfants_à_charge de
droit_ouvert_forfaitaire de enfant)
*/
```
II.-En application du sixième alinéa de l'article L. 521-1, le montant mensuel
de l'allocation forfaitaire est majoré d'un complément dégressif lorsque les
ressources annuelles du ménage ou de la personne dépassent l'un des plafonds
défini au I ou au II de l'article D. 521-3 d'une somme inférieure à douze fois
II.-En application du sixième alinéa de l'article L. 521-1, le montant mensuel
de l'allocation forfaitaire est majoré d'un complément dégressif lorsque les
ressources annuelles du ménage ou de la personne dépassent l'un des plafonds
défini au I ou au II de l'article D. 521-3 d'une somme inférieure à douze fois
le montant mensuel de l'allocation forfaitaire auquel l'enfant ouvre droit.
Ce complément dégressif est égal, pour chaque mois, au douzième de la différence
entre, d'une part, ce plafond de ressources majoré de la somme définie à
entre, d'une part, ce plafond de ressources majoré de la somme définie à
l'alinéa précédent et, d'autre part, le montant des ressources.
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_versé_complément_pour_forfaitaire égal à
si droit_ouvert_complément alors
(dépassement_plafond_ressources de montant_versé_forfaitaire) *€
(dépassement_plafond_ressources de montant_versé_forfaitaire) *€
(1,0 /. 12,0)
sinon 0 €
*/
```
III.-Le nombre minimum d'enfants à charge mentionné au deuxième alinéa de
III.-Le nombre minimum d'enfants à charge mentionné au deuxième alinéa de
l'article L. 521-1 est fixé à trois.
/*
```catala
champ d'application AllocationsFamiliales :
définition nombre_enfants_l521_1 égal à 3
*/
```
@Article D521-3|LEGIARTI000030678079@
#### [Article D521-3|LEGIARTI000030678079]
I.-Le plafond prévu au 1° du I des articles D. 521-1 et D. 521-2 est fixé à
I.-Le plafond prévu au 1° du I des articles D. 521-1 et D. 521-2 est fixé à
55 950 euros. Il est majoré de 5 595 euros par enfant à charge.
/*
```catala
champ d'application AllocationsFamiliales :
définition plafond_I_d521_3 égal à 55 950 € +€
5 595 € *€ (entier_vers_décimal de
5 595 € *€ (entier_vers_décimal de
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale))
*/
```
II.-Le plafond prévu au 2° du I des articles D. 521-1 et D. 521-2 est fixé à
II.-Le plafond prévu au 2° du I des articles D. 521-1 et D. 521-2 est fixé à
78 300 euros. Il est majoré de 5 595 euros par enfant à charge.
/*
```catala
champ d'application AllocationsFamiliales :
définition plafond_II_d521_3 égal à 78 300 € +€
5 595 € *€ (entier_vers_décimal de
5 595 € *€ (entier_vers_décimal de
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale))
*/
```
III.-Les montants des plafonds et de leur majoration respective fixés au présent
article sont revalorisés au 1er janvier de chaque année, conformément à
l'évolution en moyenne annuelle des prix à la consommation hors tabac de
l'année civile de référence, par arrêté des ministres chargés de la sécurité
III.-Les montants des plafonds et de leur majoration respective fixés au présent
article sont revalorisés au 1er janvier de chaque année, conformément à
l'évolution en moyenne annuelle des prix à la consommation hors tabac de
l'année civile de référence, par arrêté des ministres chargés de la sécurité
sociale, du budget et de l'agriculture.
@@Livre 7 : Régimes divers - Dispositions diverses@@++
#### Livre 7 : Régimes divers - Dispositions diverses
@@Titre 5 : Départements d'outre-mer@@+++
##### Titre 5 : Départements d'outre-mer
@@Chapitre 5 : Prestations familiales et prestations assimilées@@++++
###### Chapitre 5 : Prestations familiales et prestations assimilées
@Article D755-5|LEGIARTI000006738575@
I. - Les taux servant au calcul des allocations familiales et de la majoration
prévue à l'article L. 755-11 sont identiques à ceux mentionnés à l'article
#### [Article D755-5|LEGIARTI000006738575]
I. - Les taux servant au calcul des allocations familiales et de la majoration
prévue à l'article L. 755-11 sont identiques à ceux mentionnés à l'article
D. 521-1.
/*
```catala
# Pas de changement à déclarer
*/
```
II. - En application de l'article L. 755-11, 2e alinéa, le taux servant au
calcul des allocations familiales servies pour un seul enfant à charge est
II. - En application de l'article L. 755-11, 2e alinéa, le taux servant au
calcul des allocations familiales servies pour un seul enfant à charge est
fixé à 5,88 p. 100 de la base mensuelle prévue à l'article L. 755-3.
/*
```catala
# Composantes des allocations familiales
champ d'application AllocationsFamiliales :
exception
définition montant_initial_base sous condition
prestations_familiales.régime_outre_mer_l751_1 et
prestations_familiales.régime_outre_mer_l751_1 et
nombre de enfants_à_charge_droit_ouvert_prestation_familiale = 1
conséquence égal à
montant_initial_base_premier_enfant
@ -315,13 +342,13 @@ champ d'application AllocationsFamiliales :
conséquence égal à 0€
définition montant_initial_base_premier_enfant sous condition
(ressources_ménage <=€ plafond_I_d521_3) et
(ressources_ménage <=€ plafond_I_d521_3) et
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale = 1)
conséquence égal à
prestations_familiales.base_mensuelle *€ 5,88 %
définition montant_initial_base_premier_enfant sous condition
(ressources_ménage >€ plafond_I_d521_3) et
(ressources_ménage <=€ plafond_II_d521_3) et
(ressources_ménage <=€ plafond_II_d521_3) et
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale = 1)
conséquence égal à
(prestations_familiales.base_mensuelle *€ 5,88 %) *€ 50%
@ -335,17 +362,19 @@ champ d'application AllocationsFamiliales :
# Question : le complément dégressif s'applique-t-il ici ? Car le complément
# est basé sur les plafonds du taux de base qui ne s'appliquent pas ici,
# donc il serait logique que le plafond ne s'applique pas.
*/
La majoration des allocations familiales pour un seul enfant à charge est
fixée à 3,69 p. 100 de la base mensuelle prévue à l'article L. 755-3 à
```
La majoration des allocations familiales pour un seul enfant à charge est
fixée à 3,69 p. 100 de la base mensuelle prévue à l'article L. 755-3 à
partir de onze ans et à 5,67 p. 100 à partir de seize ans.
/*
```catala
champ d'application AllocationsFamiliales :
exception base_âge_limite_alinéa_1_l521_3
définition âge_limite_alinéa_1_l521_3 de enfant
sous condition prestations_familiales.régime_outre_mer_l751_1
conséquence égal à 11
conséquence égal à 11
définition
montant_initial_majoration de enfant
sous condition
@ -355,4 +384,4 @@ champ d'application AllocationsFamiliales :
conséquence égal à
prestations_familiales.base_mensuelle *€
(si enfant.âge >= 16 alors 5,67 % sinon 3,69 %)
*/
```

View File

@ -1,14 +1,14 @@
@@Code de la sécurité sociale@@
## Code de la sécurité sociale
@@Partie législative@@+
### Partie législative
@@Livre 5 : Prestations familiales et prestations assimilées@@++
#### Livre 5 : Prestations familiales et prestations assimilées
@@Titre 1 : Champ d'application - Généralités@@+++
##### Titre 1 : Champ d'application - Généralités
@@Chapitre 1er : Liste des prestations@@++++
###### Chapitre 1er : Liste des prestations
@Article L511-1|LEGIARTI000038834530@
#### [Article L511-1|LEGIARTI000038834530]
Les prestations familiales comprennent :
@ -29,27 +29,31 @@ Les prestations familiales comprennent :
8°) (Abrogé) ;
9°) l'allocation journalière de présence parentale.
/*
```catala
# Voir l'énumération ÉlémentPrestationsFamiliale
*/
```
@@Chapitre 2 : Champ d'application@@++++
###### Chapitre 2 : Champ d'application
@Article L512-3|LEGIARTI000038834523@
Sous réserve des règles particulières à chaque prestation,
#### [Article L512-3|LEGIARTI000038834523]
Sous réserve des règles particulières à chaque prestation,
ouvre droit aux prestations familiales :
1°) tout enfant jusqu'à la fin de l'obligation scolaire ;
/*
```catala
champ d'application PrestationsFamiliales :
règle droit_ouvert de enfant sous condition
(date_courante <=@ enfant.fin_obligation_scolaire)
conséquence rempli
*/
```
2°) après la fin de l'obligation scolaire, et jusqu'à un âge limite,
2°) après la fin de l'obligation scolaire, et jusqu'à un âge limite,
tout enfant dont la rémunération éventuelle n'excède pas un plafond.
/*
```catala
champ d'application PrestationsFamiliales :
# On définit les conditions hors âge d'abord car elles
# sont référencées plus tard dans l'article L521-1
@ -65,47 +69,51 @@ champ d'application PrestationsFamiliales :
conséquence rempli
champ d'application AllocationsFamiliales:
définition enfants_à_charge_droit_ouvert_prestation_familiale égal à
filtre pour enfant dans enfants_à_charge de
définition enfants_à_charge_droit_ouvert_prestation_familiale égal à
filtre pour enfant dans enfants_à_charge de
prestations_familiales.droit_ouvert de enfant
*/
```
Toutefois, pour l'attribution du complément familial et de l'allocation
de logement mentionnés aux 3° et 4° de l'article L. 511-1 , l'âge limite
Toutefois, pour l'attribution du complément familial et de l'allocation
de logement mentionnés aux 3° et 4° de l'article L. 511-1 , l'âge limite
peut être différent de celui mentionné au 2° du présent article.
/*
```catala
champ d'application PrestationsFamiliales :
définition âge_l512_3_2 sous condition
(âge_l512_3_2_alternatif sous forme Présent) et
(prestation_courante = ComplémentFamilial ou
prestation_courante = AllocationLogement)
conséquence égal à
selon âge_l512_3_2_alternatif sous forme
-- Présent de âge : âge
selon âge_l512_3_2_alternatif sous forme
-- Présent de âge : âge
-- Absent: 0
*/
```
@@Titre 2 : Prestations générales d'entretien@@+++
##### Titre 2 : Prestations générales d'entretien
@@Chapitre 1er : Allocations familiales@@++++
###### Chapitre 1er : Allocations familiales
#### [Article L521-1|LEGIARTI000029963006]
@Article L521-1|LEGIARTI000029963006@
Les allocations familiales sont dues à partir du deuxième enfant à charge.
/*
```catala
champ d'application AllocationsFamiliales :
règle droit_ouvert_base sous condition
nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 2
conséquence rempli
*/
```
Une allocation forfaitaire par enfant d'un montant fixé par décret est versée
pendant un an à la personne ou au ménage qui assume la charge d'un nombre
minimum d'enfants également fixé par décret lorsque l'un ou plusieurs des
enfants qui ouvraient droit aux allocations familiales atteignent l'âge
limite mentionné au 2° de l'article L. 512-3 . Cette allocation est versée
à la condition que le ou les enfants répondent aux conditions autres que
pendant un an à la personne ou au ménage qui assume la charge d'un nombre
minimum d'enfants également fixé par décret lorsque l'un ou plusieurs des
enfants qui ouvraient droit aux allocations familiales atteignent l'âge
limite mentionné au 2° de l'article L. 512-3 . Cette allocation est versée
à la condition que le ou les enfants répondent aux conditions autres que
celles de l'âge pour l'ouverture du droit aux allocations familiales.
/*
```catala
champ d'application AllocationsFamiliales :
assertion fixé montant_versé par décret
@ -122,126 +130,133 @@ champ d'application AllocationsFamiliales :
(enfant.âge = prestations_familiales.âge_l512_3_2) et
(conditions_hors_âge de enfant)
conséquence rempli
*/
```
Le montant des allocations mentionnées aux deux premiers alinéas du présent
article, ainsi que celui des majorations mentionnées à l'article L. 521-3
varient en fonction des ressources du ménage ou de la personne qui a la charge
Le montant des allocations mentionnées aux deux premiers alinéas du présent
article, ainsi que celui des majorations mentionnées à l'article L. 521-3
varient en fonction des ressources du ménage ou de la personne qui a la charge
des enfants, selon un barème défini par décret.
/*
```catala
champ d'application AllocationsFamiliales :
assertion fixé montant_versé_base par décret
assertion varie montant_versé_base avec ressources_ménage
assertion fixé montant_versé_majorations par décret
assertion varie montant_versé_majorations avec ressources_ménage
*/
```
Le montant des allocations familiales varie en fonction du nombre d'enfants
Le montant des allocations familiales varie en fonction du nombre d'enfants
à charge.
/*
```catala
champ d'application AllocationsFamiliales :
assertion varie montant_versé_base.montant_versé avec
nombre de enfants_à_charge_droit_ouvert_prestation_familiale
*/
```
Les niveaux des plafonds de ressources, qui varient en fonction du nombre
d'enfants à charge, sont révisés conformément à l'évolution annuelle de
Les niveaux des plafonds de ressources, qui varient en fonction du nombre
d'enfants à charge, sont révisés conformément à l'évolution annuelle de
l'indice des prix à la consommation, hors tabac.
/*
```catala
# Pour formaliser l'évolution des prix, il faudrait recopier ici
# tous les décrets d'application qui fixent la valeur des plafonds
# de ressources. Si cela reste possible à faire pour notre langage,
# nous avons choisi de ne pas inclure tout ce code dans ce document.
*/
```
Un complément dégressif est versé lorsque les ressources du bénéficiaire
dépassent l'un des plafonds, dans la limite de montants définis par décret.
Les modalités de calcul de ces montants et celles du complément dégressif
Un complément dégressif est versé lorsque les ressources du bénéficiaire
dépassent l'un des plafonds, dans la limite de montants définis par décret.
Les modalités de calcul de ces montants et celles du complément dégressif
sont définies par décret.
/*
```catala
# Ditto, le volume du code à inclure pour formaliser cette assertion
# est assez important et nous avons choisi de ne pas l'inclure dans ce
# document.
champ d'application AllocationsFamiliales :
assertion fixé montant_versé_complément par décret
*/
```
@Article L521-2|LEGIARTI000006743210@
Les allocations sont versées à la personne qui assume, dans quelques conditions
#### [Article L521-2|LEGIARTI000006743210]
Les allocations sont versées à la personne qui assume, dans quelques conditions
que ce soit, la charge effective et permanente de l'enfant.
/*
```catala
champ d'application AllocationsFamiliales :
définition prise_en_compte de enfant égal à Complète
définition versement de enfant égal à Normal
*/
```
En cas de résidence alternée de l'enfant au domicile de chacun des parents telle
que prévue à l'article 373-2-9 du code civil, mise en oeuvre de manière
effective, les parents désignent l'allocataire. Cependant, la charge de l'enfant
pour le calcul des allocations familiales est partagée par moitié entre les deux
parents soit sur demande conjointe des parents, soit si les parents sont en
désaccord sur la désignation de l'allocataire. Un décret en Conseil d'Etat fixe
En cas de résidence alternée de l'enfant au domicile de chacun des parents telle
que prévue à l'article 373-2-9 du code civil, mise en oeuvre de manière
effective, les parents désignent l'allocataire. Cependant, la charge de l'enfant
pour le calcul des allocations familiales est partagée par moitié entre les deux
parents soit sur demande conjointe des parents, soit si les parents sont en
désaccord sur la désignation de l'allocataire. Un décret en Conseil d'Etat fixe
les conditions d'application du présent alinéa.
/*
```catala
champ d'application AllocationsFamiliales :
# Premier cas : garde alternée, parents désignent un unique allocataire
exception
définition prise_en_compte de enfant sous condition
définition prise_en_compte de enfant sous condition
enfant.garde_alternée sous forme OuiAllocataireUnique
conséquence égal à Complète
exception
définition versement de enfant sous condition
définition versement de enfant sous condition
enfant.garde_alternée sous forme OuiAllocataireUnique
conséquence égal à Normal
# Deuxième cas : garde alternée, parents partagent la charge pour
# l'allocation
exception
définition prise_en_compte de enfant sous condition
définition prise_en_compte de enfant sous condition
enfant.garde_alternée sous forme OuiPartageAllocations
conséquence égal à Partagée
exception
définition versement de enfant sous condition
définition versement de enfant sous condition
enfant.garde_alternée sous forme OuiPartageAllocations
conséquence égal à Normal
*/
```
Lorsque la personne qui assume la charge effective et permanente de l'enfant ne
remplit pas les conditions prévues au titre I du présent livre pour l'ouverture
du droit aux allocations familiales, ce droit s'ouvre du chef du père ou,
Lorsque la personne qui assume la charge effective et permanente de l'enfant ne
remplit pas les conditions prévues au titre I du présent livre pour l'ouverture
du droit aux allocations familiales, ce droit s'ouvre du chef du père ou,
à défaut, du chef de la mère.
/*
# Non formalisé pour le calcul du montant des allocations
*/
Lorsqu'un enfant est confié au service d'aide sociale à l'enfance, les
allocations familiales continuent d'être évaluées en tenant compte à la fois
des enfants présents au foyer et du ou des enfants confiés au service de
l'aide sociale à l'enfance. La part des allocations familiales dues à la
famille pour cet enfant est versée à ce service. Toutefois, le juge peut
décider, d'office ou sur saisine du président du conseil général, à la
suite d'une mesure prise en application des articles 375-3 et 375-5 du code
civil ou des articles 15,16,16 bis et 28 de l' ordonnance n° 45-174 du 2
février 1945 relative à l'enfance délinquante, de maintenir le versement
des allocations à la famille, lorsque celle-ci participe à la prise en
charge morale ou matérielle de l'enfant ou en vue de faciliter le retour
```catala
# Non formalisé pour le calcul du montant des allocations
```
Lorsqu'un enfant est confié au service d'aide sociale à l'enfance, les
allocations familiales continuent d'être évaluées en tenant compte à la fois
des enfants présents au foyer et du ou des enfants confiés au service de
l'aide sociale à l'enfance. La part des allocations familiales dues à la
famille pour cet enfant est versée à ce service. Toutefois, le juge peut
décider, d'office ou sur saisine du président du conseil général, à la
suite d'une mesure prise en application des articles 375-3 et 375-5 du code
civil ou des articles 15,16,16 bis et 28 de l' ordonnance n° 45-174 du 2
février 1945 relative à l'enfance délinquante, de maintenir le versement
des allocations à la famille, lorsque celle-ci participe à la prise en
charge morale ou matérielle de l'enfant ou en vue de faciliter le retour
de l'enfant dans son foyer.
/*
```catala
champ d'application AllocationsFamiliales :
exception
définition versement de enfant sous condition
définition versement de enfant sous condition
enfant.prise_en_charge_par_services_sociaux sous forme
OuiAllocationVerséeAuxServicesSociaux
conséquence égal à AllocationVerséeAuxServicesSociaux
*/
```
Un décret en Conseil d'Etat fixe les conditions d'application du présent
Un décret en Conseil d'Etat fixe les conditions d'application du présent
article, notamment dans les cas énumérés ci-dessous :
a) retrait total de l'autorité parentale des parents ou de l'un d'eux ;
@ -252,63 +267,70 @@ c) divorce, séparation de corps ou de fait des parents ;
d) enfants confiés à un service public, à une institution privée, à un particulier.
/*
```catala
# Ce programme ne cherche pas à formaliser les détails pour lesquels un enfant
# est confié à un service social.
*/
```
@Article L521-3|LEGIARTI000006743289@ Chacun des enfants à charge, à
l'exception du plus âgé, ouvre droit à partir d'un âge minimum à une
majoration des allocations familiales.
/*
#### [Article L521-3|LEGIARTI000006743289]
Chacun des enfants à charge, à l'exception du plus âgé, ouvre droit à partir
d'un âge minimum à une majoration des allocations familiales.
```catala
champ d'application AllocationsFamiliales :
règle droit_ouvert_majoration de enfant
sous condition
(non (est_enfant_le_plus_âgé de enfant)) et
(enfant.âge >= âge_limite_alinéa_1_l521_3 de enfant)
conséquence rempli
*/
```
Toutefois, les personnes ayant un nombre déterminé d'enfants à charge
bénéficient de ladite majoration pour chaque enfant à charge à partir
Toutefois, les personnes ayant un nombre déterminé d'enfants à charge
bénéficient de ladite majoration pour chaque enfant à charge à partir
de l'âge mentionné au premier alinéa.
/*
```catala
champ d'application AllocationsFamiliales :
exception
règle droit_ouvert_majoration de enfant
sous condition
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale >=
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale >=
nombre_enfants_alinéa_2_l521_3) et
(enfant.âge >= âge_limite_alinéa_1_l521_3 de enfant)
conséquence rempli
*/
```
@@Titre 5 : Dispositions communes@@+++
##### Titre 5 : Dispositions communes
@@Chapitre 1er : Etablissement du salaire de base@@++++
###### Chapitre 1er : Etablissement du salaire de base
@Article L551-1|LEGIARTI000031688371@
Le montant des prestations familiales est déterminé d'après des bases
mensuelles de calcul revalorisées au 1er avril de chaque année par application
#### [Article L551-1|LEGIARTI000031688371]
Le montant des prestations familiales est déterminé d'après des bases
mensuelles de calcul revalorisées au 1er avril de chaque année par application
du coefficient mentionné à l'article L. 161-25 .
/*
```catala
# Idem que L521-1, on ne formalise pas ici l'évolution de la BMPA
champ d'application PrestationsFamiliales :
assertion fixé prestations_familiales.base_mensuelle par décret
*/
```
@@Livre 7 : Régimes divers - Dispositions diverses@@++
#### Livre 7 : Régimes divers - Dispositions diverses
@@Titre 5 : Dispositions particulières à la Guadeloupe, à la Guyane, à la Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin@@+++
##### Titre 5 : Dispositions particulières à la Guadeloupe, à la Guyane, à la Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin
@@Chapitre 1er : Généralités@@++++
###### Chapitre 1er : Généralités
@Article L751-1|LEGIARTI000031323778@
Les dispositions du présent titre s'appliquent en Guadeloupe, en Guyane,
en Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin à
l'ensemble des bénéficiaires de la législation générale de sécurité
#### [Article L751-1|LEGIARTI000031323778]
Les dispositions du présent titre s'appliquent en Guadeloupe, en Guyane,
en Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin à
l'ensemble des bénéficiaires de la législation générale de sécurité
sociale, y compris les membres des professions agricoles.
/*
```catala
champ d'application PrestationsFamiliales :
règle régime_outre_mer_l751_1 sous condition
(résidence = Guadeloupe) ou
@ -318,47 +340,53 @@ champ d'application PrestationsFamiliales :
(résidence = SaintBarthélemy) ou
(résidence = SaintMartin)
conséquence rempli
*/
```
@@Chapitre 5 : Prestations familiales et prestations assimilées@@++++
###### Chapitre 5 : Prestations familiales et prestations assimilées
@Article L755-3|LEGIARTI000033728786@
Les dispositions des articles L. 512-1 à L. 512-4 , L. 513-1 , L. 521-2 ,
L. 552-1 , L. 553-1 , L. 553-2 , L. 553-4 , L. 582-1 , L. 582-2 , L. 583-3
#### [Article L755-3|LEGIARTI000033728786]
Les dispositions des articles L. 512-1 à L. 512-4 , L. 513-1 , L. 521-2 ,
L. 552-1 , L. 553-1 , L. 553-2 , L. 553-4 , L. 582-1 , L. 582-2 , L. 583-3
et L. 583-5 sont applicables aux collectivités mentionnées à l'article L. 751-1 .
La base de calcul des prestations familiales est la même que celle qui est
La base de calcul des prestations familiales est la même que celle qui est
fixée en application de l'article L. 551-1 .
/*
```catala
# Aucun changement dans le code, puisque les articles restent applicables
*/
```
@Article L755-11|LEGIARTI000031323803@
Les conditions d'attribution des allocations familiales et de leurs majorations
fixées par les articles L. 521-1 et L. 521-3 sont applicables dans les
collectivités mentionnées à l'article L. 751-1 .
/*
#### [Article L755-11|LEGIARTI000031323803]
Les conditions d'attribution des allocations familiales et de leurs majorations
fixées par les articles L. 521-1 et L. 521-3 sont applicables dans les
collectivités mentionnées à l'article L. 751-1.
```catala
# Aucun changement dans le code, puisque les articles restent applicables
*/
```
Toutefois, les dispositions de l'article L. 755-12 restent en vigueur aussi
Toutefois, les dispositions de l'article L. 755-12 restent en vigueur aussi
longtemps que le présent chapitre V est applicable.
@Article L755-12|LEGIARTI000029962999@
Les allocations familiales sont dues, pour tout enfant, à la personne qui a
#### [Article L755-12|LEGIARTI000029962999]
Les allocations familiales sont dues, pour tout enfant, à la personne qui a
effectivement la charge de celui-ci.
/*
```catala
champ d'application AllocationsFamiliales:
exception
règle droit_ouvert_base sous condition
prestations_familiales.régime_outre_mer_l751_1 et
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale >= 1)
conséquence rempli
*/
Toutefois, les quatre derniers alinéas de l'article L. 521-1 ne sont pas
```
Toutefois, les quatre derniers alinéas de l'article L. 521-1 ne sont pas
applicables lorsque le ménage ou la personne a un seul enfant à charge.
/*
```catala
# Ceci concerne l'ouverture du droit à l'allocation forfaitaire
# et au complément dégressif.
@ -374,4 +402,4 @@ champ d'application AllocationsFamiliales :
prestations_familiales.régime_outre_mer_l751_1 et
(nombre de enfants_à_charge_droit_ouvert_prestation_familiale = 1)
conséquence non rempli
*/
```

View File

@ -1,63 +1,70 @@
@@Partie réglementaire - Décrets en Conseil d'Etat@@+
### Partie réglementaire - Décrets en Conseil d'Etat
@@Livre 5 : Prestations familiales et prestations assimilées@@++
#### Livre 5 : Prestations familiales et prestations assimilées
@@Titre 1 : Champ d'application - Généralités@@+++
##### Titre 1 : Champ d'application - Généralités
@@Chapitre 2 : Champ d'application.@@++++
###### Chapitre 2 : Champ d'application.
@Article R512-2|LEGIARTI000006750602@
Les enfants ouvrent droit aux prestations familiales jusqu'à l'âge de vingt
ans sous réserve que leur rémunération n'excède pas le plafond fixé au deuxième
#### [Article R512-2|LEGIARTI000006750602]
Les enfants ouvrent droit aux prestations familiales jusqu'à l'âge de vingt
ans sous réserve que leur rémunération n'excède pas le plafond fixé au deuxième
alinéa du présent article.
/*
```catala
champ d'application PrestationsFamiliales :
définition âge_l512_3_2 égal à 20
*/
```
Le plafond de rémunération mentionné au 2° de l'article L. 512-3 est égal, pour
un mois, à 55 % du salaire minimum interprofessionnel de croissance défini aux
Le plafond de rémunération mentionné au 2° de l'article L. 512-3 est égal, pour
un mois, à 55 % du salaire minimum interprofessionnel de croissance défini aux
articles L. 141-1 à L. 141-9 du code du travail, multiplié par 169.
/*
```catala
champ d'application PrestationsFamiliales :
définition plafond_l512_3_2 égal à
(smic.brut_horaire *€ 55 %) *€ 169,0
*/
```
Pour ceux des enfants qui bénéficient d'avantages en nature, l'évaluation de ces
avantages devra être faite suivant les barèmes fixés pour l'application de la
Pour ceux des enfants qui bénéficient d'avantages en nature, l'évaluation de ces
avantages devra être faite suivant les barèmes fixés pour l'application de la
législation sur les assurances sociales.
/*
```catala
# Le programme ne tient pas en compte des avantages en nature
*/
```
@@Titre 2 : Prestations générales d'entretien@@+++
##### Titre 2 : Prestations générales d'entretien
@@Chapitre 1er : Allocations familiales@@++++
###### Chapitre 1er : Allocations familiales
@Article R521-1|LEGIARTI000018735853@
L'âge mentionné au premier alinéa de l'article L. 521-3 à partir duquel les
enfants ouvrent droit à la majoration des allocations familiales est fixé à
#### [Article R521-1|LEGIARTI000018735853]
L'âge mentionné au premier alinéa de l'article L. 521-3 à partir duquel les
enfants ouvrent droit à la majoration des allocations familiales est fixé à
14 ans.
/*
```catala
champ d'application AllocationsFamiliales :
étiquette base_âge_limite_alinéa_1_l521_3
définition âge_limite_alinéa_1_l521_3 de enfant égal à 14
*/
```
Le nombre minimum d'enfants à charge, mentionné au deuxième alinéa de l'article
Le nombre minimum d'enfants à charge, mentionné au deuxième alinéa de l'article
L. 521-3 ouvrant droit à ladite majoration pour chaque enfant est fixé à trois.
/*
```catala
champ d'application AllocationsFamiliales :
définition nombre_enfants_alinéa_2_l521_3 égal à 3
*/
```
NOTA : Décret n° 2008-409 du 28 avril 2008 JORF du 29 avril 2008 art. 2 : Les
modifications induites par le décret n° 2008-409 s'appliquent aux enfants dont
NOTA : Décret n° 2008-409 du 28 avril 2008 JORF du 29 avril 2008 art. 2 : Les
modifications induites par le décret n° 2008-409 s'appliquent aux enfants dont
le onzième anniversaire est postérieur au 30 avril 2008.
/*
```catala
# Notons ici un champ d'application différent, correspondant à une ancienne
# version du corpus législatif dont un morceau s'applique encore. Nous avons
# choisi de montrer ce vieux champ d'application ici plutôt qu'à côté du texte
@ -71,39 +78,44 @@ champ d'application AllocationsFamiliales :
sous condition (enfant.date_de_naissance +@ 11 an <=@ |30/04/2008|)
conséquence égal à
version_avril_2008.âge_limite_alinéa_1_l521_3
*/
@Article R521-2|LEGIARTI000006750608@
Dans les situations visées au deuxième alinéa de l'article L. 521-2 ,
l'allocataire est celui des deux parents qu'ils désignent d'un commun accord.
A défaut d'accord sur la désignation d'un allocataire unique, chacun des deux
```
#### [Article R521-2|LEGIARTI000006750608]
Dans les situations visées au deuxième alinéa de l'article L. 521-2 ,
l'allocataire est celui des deux parents qu'ils désignent d'un commun accord.
A défaut d'accord sur la désignation d'un allocataire unique, chacun des deux
parents peut se voir reconnaître la qualité d'allocataire :
1° Lorsque les deux parents en ont fait la demande conjointe ;
2° Lorsque les deux parents n'ont ni désigné un allocataire unique, ni fait
2° Lorsque les deux parents n'ont ni désigné un allocataire unique, ni fait
une demande conjointe de partage.
/*
```catala
# Le fait que l'allocataire dans le cas d'un commun accord soit celui des
# deux parents désigné par l'accord est déjà modélisé dans L512-2.
*/
```
Lorsque les parents ont désigné un allocataire unique ou fait une demande
conjointe de partage, ils ne peuvent remettre en cause les modalités ainsi
Lorsque les parents ont désigné un allocataire unique ou fait une demande
conjointe de partage, ils ne peuvent remettre en cause les modalités ainsi
choisies qu'au bout d'un an, sauf modification des modalités de résidence du
ou des enfants.
/*
```catala
# On ne modélise pas le délai minimal entre changement de situation dans
# ce programme.
*/
```
@Article R521-3|LEGIARTI000006750610@
Sous réserve de l'article R. 521-4, dans les situations visées aux 1° et 2° de
l'article R. 521-2 , la prestation due à chacun des parents est égale au
montant des allocations familiales dues pour le total des enfants à charge,
multiplié par un coefficient résultant du rapport entre le nombre moyen
#### [Article R521-3|LEGIARTI000006750610]
Sous réserve de l'article R. 521-4, dans les situations visées aux 1° et 2° de
l'article R. 521-2 , la prestation due à chacun des parents est égale au
montant des allocations familiales dues pour le total des enfants à charge,
multiplié par un coefficient résultant du rapport entre le nombre moyen
d'enfants et le nombre total d'enfants.
/*
```catala
champ d'application AllocationsFamiliales :
définition montant_avec_garde_alternée_base égal à
montant_initial_base *€ rapport_enfants_total_moyen
@ -111,49 +123,53 @@ champ d'application AllocationsFamiliales :
définition rapport_enfants_total_moyen égal à
si nombre_total_enfants = 0,0 alors 0,0 sinon
(nombre_moyen_enfants /. nombre_total_enfants)
*/
```
Le nombre moyen d'enfants, pour chaque foyer, est obtenu en faisant la somme
Le nombre moyen d'enfants, pour chaque foyer, est obtenu en faisant la somme
du nombre d'enfants à charge dans les conditions suivantes :
1° Chaque enfant en résidence alternée compte pour 0,5 ;
2° Les autres enfants à charge comptent pour 1.
/*
```catala
champ d'application AllocationsFamiliales :
définition nombre_moyen_enfants égal à
somme décimal pour enfant dans
enfants_à_charge_droit_ouvert_prestation_familiale
somme décimal pour enfant dans
enfants_à_charge_droit_ouvert_prestation_familiale
de (
selon (prise_en_compte de enfant) sous forme
-- Complète : 1,0
-- Partagée : 0,5
)
*/
Le nombre total d'enfants, pour chaque foyer, est obtenu en faisant la somme du
ou des enfants en résidence alternée et, le cas échéant, du ou des autres
enfants à charge.
/*
champ d'application AllocationsFamiliales :
définition nombre_total_enfants égal à
entier_vers_décimal de (nombre de
enfants_à_charge_droit_ouvert_prestation_familiale)
*/
```
@Article R521-4|LEGIARTI000006750613@
Pour l'ouverture du droit à la majoration prévue à l'article L. 521-3 , le
nombre d'enfants à charge est évalué dans les conditions prévues au premier
Le nombre total d'enfants, pour chaque foyer, est obtenu en faisant la somme du
ou des enfants en résidence alternée et, le cas échéant, du ou des autres
enfants à charge.
```catala
champ d'application AllocationsFamiliales :
définition nombre_total_enfants égal à
entier_vers_décimal de (nombre de
enfants_à_charge_droit_ouvert_prestation_familiale)
```
#### [Article R521-4|LEGIARTI000006750613]
Pour l'ouverture du droit à la majoration prévue à l'article L. 521-3 , le
nombre d'enfants à charge est évalué dans les conditions prévues au premier
alinéa de l'article R. 521-3.
/*
```catala
# enfants_à_charge ne contient que des enfants à charge donc rien à formaliser
# ici
*/
```
Lorsque le ou les enfants ouvrant droit à ladite majoration sont en résidence
alternée, le montant servi au titre de cette majoration est réduit de moitié.
/*
```catala
champ d'application AllocationsFamiliales :
définition
montant_avec_garde_alternée_majoration de enfant
@ -162,24 +178,26 @@ champ d'application AllocationsFamiliales :
-- Complète : 100%
-- Partagée : 50%
)
*/
```
@@Livre 7 : Régimes divers - Dispositions diverses@@++
#### Livre 7 : Régimes divers - Dispositions diverses
@@Titre 5 : Départements d'outre-mer@@+++
##### Titre 5 : Départements d'outre-mer
@@Chapitre 5 : Prestations familiales et prestations assimilées@@++++
###### Chapitre 5 : Prestations familiales et prestations assimilées
@Article R755-0-2|LEGIARTI000006752633@
Le plafond de rémunération des enfants à charge mentionnés à l'article
L. 512-3 est égal, pour un mois, à 55 % du salaire minimum de croissance en
vigueur dans chacun des départements mentionnés à l'article L. 751-1 ,
#### [Article R755-0-2|LEGIARTI000006752633]
Le plafond de rémunération des enfants à charge mentionnés à l'article
L. 512-3 est égal, pour un mois, à 55 % du salaire minimum de croissance en
vigueur dans chacun des départements mentionnés à l'article L. 751-1 ,
multiplié par 169.
/*
```catala
champ d'application PrestationsFamiliales :
exception
définition plafond_l512_3_2
sous condition régime_outre_mer_l751_1
conséquence égal à
(smic.brut_horaire *€ 55%) *€ 169,0
*/
```

View File

@ -1,14 +1,14 @@
@@Inclusion: ../allocations_familiales.catala_fr@@
> Inclusion: ../allocations_familiales.catala_fr
@@Tests@@
## Tests
@Tests@
### [Tests]
/*
```catala
déclaration champ d'application Données:
contexte enfant1 contenu EnfantEntrée
contexte enfant1 contenu EnfantEntrée
contexte enfant2 contenu EnfantEntrée
contexte enfant3 contenu EnfantEntrée
contexte enfant3 contenu EnfantEntrée
contexte enfant4 contenu EnfantEntrée
contexte enfant5 contenu EnfantEntrée
@ -51,10 +51,10 @@ champ d'application Données:
déclaration champ d'application Test1:
contexte f champ d'application InterfaceAllocationsFamiliales
contexte données champ d'application Données
contexte données champ d'application Données
champ d'application Test1:
définition f.enfants égal à
définition f.enfants égal à
[données.enfant1;données.enfant2;données.enfant3;données.enfant4]
définition f.ressources_ménage égal à 30 000 €
définition f.date_courante égal à |01/05/2020|
@ -63,10 +63,10 @@ champ d'application Test1:
déclaration champ d'application Test2:
contexte f champ d'application InterfaceAllocationsFamiliales
contexte données champ d'application Données
contexte données champ d'application Données
champ d'application Test2:
définition f.enfants égal à
définition f.enfants égal à
[données.enfant1;données.enfant2;données.enfant5]
définition f.ressources_ménage égal à 30 000 €
définition f.date_courante égal à |01/05/2020|
@ -76,7 +76,7 @@ champ d'application Test2:
déclaration champ d'application Test3:
contexte f champ d'application InterfaceAllocationsFamiliales
contexte données champ d'application Données
contexte données champ d'application Données
champ d'application Test3:
définition f.enfants égal à [données.enfant1]
@ -87,7 +87,7 @@ champ d'application Test3:
déclaration champ d'application Test4:
contexte f champ d'application InterfaceAllocationsFamiliales
contexte données champ d'application Données
contexte données champ d'application Données
champ d'application Test4:
définition f.enfants égal à [données.enfant1; données.enfant3]
@ -98,7 +98,7 @@ champ d'application Test4:
déclaration champ d'application Test5:
contexte f champ d'application InterfaceAllocationsFamiliales
contexte données champ d'application Données
contexte données champ d'application Données
champ d'application Test5:
définition f.enfants égal à [données.enfant1]
@ -131,10 +131,10 @@ champ d'application Test6:
déclaration champ d'application Test7:
contexte f champ d'application InterfaceAllocationsFamiliales
contexte données champ d'application Données
contexte données champ d'application Données
champ d'application Test7:
définition f.enfants égal à
définition f.enfants égal à
[données.enfant1;données.enfant2;données.enfant3;données.enfant4]
définition f.ressources_ménage égal à 30 000 €
définition f.date_courante égal à |01/02/2021|
@ -142,4 +142,4 @@ champ d'application Test7:
assertion f.montant_versé = 417,51€
*/
```

View File

@ -1,15 +1,15 @@
@@Inclusion: ../allocations_familiales.catala_fr@@
> Inclusion: ../allocations_familiales.catala_fr
@@Tests@@
## Tests
@Tests@
### [Tests]
/*
```catala
déclaration champ d'application Données:
contexte enfant1 contenu Enfant
contexte enfant2 contenu Enfant
contexte enfant3 contenu Enfant
contexte enfant4 contenu Enfant
contexte enfant1 contenu Enfant
contexte enfant2 contenu Enfant
contexte enfant3 contenu Enfant
contexte enfant4 contenu Enfant
champ d'application Données:
définition enfant1 égal à Enfant {
@ -55,11 +55,11 @@ déclaration champ d'application Test1:
champ d'application Test1:
définition f.âge_l512_3_2_alternatif égal à Absent
définition f.date_courante égal à |01/05/2020|
définition f.date_courante égal à |01/05/2020|
définition f.prestation_courante égal à AllocationsFamiliales
définition f.résidence égal à Métropole
assertion (f.droit_ouvert de données.enfant1)
assertion (non (f.droit_ouvert de données.enfant2))
assertion (f.droit_ouvert de données.enfant3)
assertion (non (f.droit_ouvert de données.enfant4))
*/
```

View File

@ -1,25 +1,32 @@
@@Code général des impôts@@
@@Livre premier : Assiette et liquidation de l'impôt@@+
@@Première Partie : Impôts d'État@@++
@@Titre premier : Impôts directs et taxes assimilées@@+++
@@Chapitre premier : Impôt sur le revenu@@++++
@@Section I : Dispositions générales@@+++++
@@0I : Définition du revenu net global@@++++++
@Article 1 A@
## Code général des impôts
Il est établi un impôt annuel unique sur le revenu des personnes physiques
désigné sous le nom d'impôt sur le revenu. Cet impôt frappe le revenu net
global du contribuable déterminé conformément aux dispositions des
### Livre premier : Assiette et liquidation de l'impôt
#### Première Partie : Impôts d'État
##### Titre premier : Impôts directs et taxes assimilées
###### Chapitre premier : Impôt sur le revenu
####### Section I : Dispositions générales
######## 0I : Définition du revenu net global
######### [Article 1 A]
Il est établi un impôt annuel unique sur le revenu des personnes physiques
désigné sous le nom d'impôt sur le revenu. Cet impôt frappe le revenu net
global du contribuable déterminé conformément aux dispositions des
articles 156 à 168.
Ce revenu net global est constitué par le total des revenus nets des
Ce revenu net global est constitué par le total des revenus nets des
catégories suivantes :
Revenus fonciers ;
Bénéfices industriels et commerciaux ;
Rémunérations, d'une part, des gérants majoritaires des sociétés à
Rémunérations, d'une part, des gérants majoritaires des sociétés à
responsabilité limitée n'ayant pas opté pour le régime fiscal des sociétés de personnes dans les conditions prévues au IV de l'article 3 du décret n° 55-594 du 20 mai 1955 modifié et des gérants des sociétés en commandite par actions et, d'autre part, des associés en nom des sociétés de personnes et des membres des sociétés en participation lorsque ces sociétés ont opté pour le régime fiscal des sociétés de capitaux ;
Bénéfices de l'exploitation agricole ;
@ -30,11 +37,11 @@ responsabilité limitée n'ayant pas opté pour le régime fiscal des sociétés
Revenus de capitaux mobiliers ;
Plus-values de cession à titre onéreux de biens ou de droits de toute
nature, déterminés conformément aux dispositions des articles 14 à 155,
Plus-values de cession à titre onéreux de biens ou de droits de toute
nature, déterminés conformément aux dispositions des articles 14 à 155,
total dont sont retranchées les charges énumérées à l'article 156.
/*
```catala
déclaration structure RevenuNetGlobal:
donnée revenus_fonciers contenu argent
donnée bénéfices_industriels_commerciaux contenu argent
@ -55,17 +62,17 @@ champ d'application CalculImpotSurLeRevenu:
+ revenu_net_global.rémunérations_dirigeants + revenu_net_global.bénéfices_agricoles
+ revenu_net_global.traitements_salaires + revenu_net_global.bénéfices_non_commerciaux
+ revenu_net_global.revenus_capitaux_mobiliers + revenu_net_global.plus_values
*/
```
@@0I : Définition du revenu net global@@++++++
######## 0I : Définition du revenu net global
@Article 4 A@
######### [Article 4 A]
Les personnes qui ont en France leur domicile fiscal sont passibles de l'impôt sur le revenu en raison de l'ensemble de leurs revenus.
Celles dont le domicile fiscal est situé hors de France sont passibles de cet impôt en raison de leurs seuls revenus de source française.
/*
```catala
déclaration énumération DomicileFiscal:
-- France
-- HorsDeFrance
@ -77,16 +84,16 @@ déclaration structure MontantsSourcesRevenus:
déclaration structure Personne:
donnée domicile_fiscal contenu DomicileFiscal
donnée revenus contenu argent
donnée montants_sources_revenus contenu MontantsSourcesRevenus
donnée montants_sources_revenus contenu MontantsSourcesRevenus
déclaration champ d'application CalculImpotSurLeRevenu :
contexte personne contenu Personne
champ d'application CalculImpotSurLeRevenu:
définition personne.revenus égal à
définition personne.revenus égal à
si personne.domicileFiscal = France alors
montants_sources_revenus.source_française +€ montants_sources_revenus.source_étrangère
sinon
sinon
montants_sources_revenus.source_française
*/
```

View File

@ -1,3 +1,3 @@
@@Fichier maître@@
# Fichier maître
@@Inclusion: Section_I_Dispositions_generales.catala_fr@@
> Inclusion: Section_I_Dispositions_generales.catala_fr

View File

@ -1,14 +1,14 @@
@@Include: ../tutorial_en.catala_en@@
> Include: ../tutorial_en.catala_en
@Test@
## [Test]
/*
```catala
declaration scope UnitTest1:
context tax_computation scope NewIncomeTaxComputation
scope UnitTest1:
definition
tax_computation.individual
tax_computation.individual
equals
Individual {
-- income: $230,000
@ -26,4 +26,4 @@ scope UnitTest2:
}
assertion tax_computation.income_tax = $0.00
*/
```

View File

@ -1,206 +1,222 @@
@@The Catala language tutorial@@
## The Catala language tutorial
Welcome to this tutorial, whose objective is to guide you through the features
of the Catala language and teach you how to annotate a legislative text using
the language. This document is addressed primarily to developers or people that
have a programming background, though tech-savvy lawyers will probably figure
Welcome to this tutorial, whose objective is to guide you through the features
of the Catala language and teach you how to annotate a legislative text using
the language. This document is addressed primarily to developers or people that
have a programming background, though tech-savvy lawyers will probably figure
things out.
@@Literate programming@@+
### Literate programming
To begin writing a Catala program, you must start from the text of the
legislative source that will justify the code that you will write. Concretely,
that means copy-pasting the text of the law into a Catala source file and
formatting it according so that Catala can understand it. Catala source files
have the ".catala_en" extension. If you were to write a Catala program for a
To begin writing a Catala program, you must start from the text of the
legislative source that will justify the code that you will write. Concretely,
that means copy-pasting the text of the law into a Catala source file and
formatting it according so that Catala can understand it. Catala source files
have the ".catala_en" extension. If you were to write a Catala program for a
French law, you would use the ".catala_fr" extension.
You can write any kind of plain text in Catala, and it will be printed as is
in PDF or HTML output. You can split your text into short lines, those
will appear as a single paragraph in the output. If you want to create a
new paragrah, you have to leave a blank line in the source.
You can write any kind of plain text in Catala, and it will be printed as is
in PDF or HTML output. You can split your text into short lines, those
will appear as a single paragraph in the output. If you want to create a
new paragrah, you have to leave a blank line in the source.
Catala allows you to declare section or subsection headers as it is done
here, with the "at" symbol repeated twice. You can define heading of lower
importance by adding increasing numbers of "+" after the title of the heading.
here, with the "at" symbol repeated twice. You can define heading of lower
importance by adding increasing numbers of "+" after the title of the heading.
The fundamental division unit is the article, introduced by a single "at".
Let's analyse a fictional example that defines an income tax.
@Article 1@
The income tax for an individual is defined as a fixed percentage of the
#### [Article 1]
The income tax for an individual is defined as a fixed percentage of the
individual's income over a year.
/*
# Welcome to the code mode of Catala. This is a comment, because the line is
```catala
# Welcome to the code mode of Catala. This is a comment, because the line is
# prefixed by #.
# We will soon learn what to write here in order to translate the meaning
# We will soon learn what to write here in order to translate the meaning
# of the article into Catala code.
*/
```
To do that, we will intertwine short snippets of code between the sentences of
the legislative text. Each snippet of code should be as short as possible and
as close as possible to the actual sentence that justifies the code. This style
is called literate programming, a programming paradigm invented by the famous
To do that, we will intertwine short snippets of code between the sentences of
the legislative text. Each snippet of code should be as short as possible and
as close as possible to the actual sentence that justifies the code. This style
is called literate programming, a programming paradigm invented by the famous
computer scientist Donald Knuth in the 70s.
@@Defining a fictional income tax@@+
### Defining a fictional income tax
The content of article 1 uses a lot of implicit context: there exists an
individual with an income, as well as an income tax that the individual has
to pay each year. Even if this implicit context is not verbatim in the law,
we have to explicit it for programming purposes. Concretely, we need a
"metadata" section that defines the shape and types of the data used
The content of article 1 uses a lot of implicit context: there exists an
individual with an income, as well as an income tax that the individual has
to pay each year. Even if this implicit context is not verbatim in the law,
we have to explicit it for programming purposes. Concretely, we need a
"metadata" section that defines the shape and types of the data used
inside the law.
Let's start our metadata section by declaring the type information for the
Let's start our metadata section by declaring the type information for the
individual:
@@Begin metadata@@
/*
> Begin metadata
```catala
declaration structure Individual:
# The name of the structure "Individual", must start with an
# uppercase letter: this is the CamelCase convention.
data income content money
# In this line, "income" is the name of the structure field and
# In this line, "income" is the name of the structure field and
# "money" is the type of what is stored in that field.
# Available types include: integer, decimal, money, date, duration,
# Available types include: integer, decimal, money, date, duration,
# and any other structure or enumeration that you declare
data number_of_children content integer
# "income" and "number_of_children" start by a lowercase letter,
# "income" and "number_of_children" start by a lowercase letter,
# they follow the snake_case convention
*/
@@End metadata@@
```
This structure contains two data fields, "income" and "number_of_children". Structures are
useful to group together data that goes together. Usually, you
get one structure per concrete object on which the law applies (like the
individual). It is up to you to decide how to group the data together,
> End metadata
This structure contains two data fields, "income" and "number_of_children". Structures are
useful to group together data that goes together. Usually, you
get one structure per concrete object on which the law applies (like the
individual). It is up to you to decide how to group the data together,
but you should aim to optimize code readability.
Sometimes, the law gives an enumeration of different situations. These
Sometimes, the law gives an enumeration of different situations. These
enumerations are modeled in Catala using an enumeration type, like:
@@Begin metadata@@
/*
> Begin metadata
```catala
declaration enumeration TaxCredit:
# The name "TaxCredit" is also written in CamelCase
# The name "TaxCredit" is also written in CamelCase
-- NoTaxCredit
# This line says that "TaxCredit" can be a "NoTaxCredit" situation
-- ChildrenTaxCredit content integer
# This line says that alternatively, "TaxCredit" can be a
-- ChildrenTaxCredit content integer
# This line says that alternatively, "TaxCredit" can be a
# "ChildrenTaxCredit" situation. This situation carries a content
# of type integer corresponding to the number of children concerned
# of type integer corresponding to the number of children concerned
# by the tax credit. This means that if you're in the "ChildrenTaxCredit"
# situation, you will also have access to this number of children
*/
@@End metadata@@
# situation, you will also have access to this number of children
```
In computer science terms, such an enumeration is called a "sum type" or simply
an enum. The combination of structures and enumerations allow the Catala
programmer to declare all possible shapes of data, as they are equivalent to
the powerful notion of "algebraic datatypes".
> End metadata
We've defined and typed the data that the program will manipulate. Now we have
to define the logical context in which these data will evolve. This is done in
Catala using "scopes". Scopes are close to functions in terms of traditional
In computer science terms, such an enumeration is called a "sum type" or simply
an enum. The combination of structures and enumerations allow the Catala
programmer to declare all possible shapes of data, as they are equivalent to
the powerful notion of "algebraic datatypes".
We've defined and typed the data that the program will manipulate. Now we have
to define the logical context in which these data will evolve. This is done in
Catala using "scopes". Scopes are close to functions in terms of traditional
programming. Scopes also have to be declared in metadata, so here we go:
@@Begin metadata@@
/*
> Begin metadata
```catala
declaration scope IncomeTaxComputation:
# Scope names use CamelCase
context individual content Individual
# This line declares a context element of the scope, which is akin to
# a function parameter in computer science term. This is the piece of
# This line declares a context element of the scope, which is akin to
# a function parameter in computer science term. This is the piece of
# data on which the scope will operate
context fixed_percentage content decimal
context income_tax content money
*/
@@End metadata@@
```
We now have everything to annotate the contents of article 1, which is copied
> End metadata
We now have everything to annotate the contents of article 1, which is copied
over below.
@Article 1@
The income tax for an individual is defined as a fixed percentage of the
#### [Article 1]
The income tax for an individual is defined as a fixed percentage of the
individual's income over a year.
/*
```catala
scope IncomeTaxComputation:
definition income_tax equals
individual.income *$ fixed_percentage
*/
```
In the code, we are defining inside our scope the amount of the income tax
according to the formula described in the article. When defining formulae,
you have access to all the usual arithmetic operators: addition "+",
substraction "-", multiplication "*" and division (slash).
In the code, we are defining inside our scope the amount of the income tax
according to the formula described in the article. When defining formulae,
you have access to all the usual arithmetic operators: addition "+",
substraction "-", multiplication "*" and division (slash).
However, in the Catala code, you can see that we use "*$" to multiply the
individual income by the fixed percentage. The $ suffix indicates that we
are performing a multiplication on an amount of money. Indeed, in Catala,
you have to keep track of what you are dealing with: is it money ? Is it
an integer? Using just "+" or "*" can be ambiguous in terms of rounding,
since money is usually rounded at the cent. So to disambiguate, we suffix these
operations with something that indicates the type of what we manipulate.
The suffixes are "$" for money "." for decimals, "at" (like in email adresses)
for dates and the hat symbol for durations. If you forget the suffix, the Catala type
checker will display an error message that will help you put it where it
belongs.
However, in the Catala code, you can see that we use "*$" to multiply the
individual income by the fixed percentage. The $ suffix indicates that we
are performing a multiplication on an amount of money. Indeed, in Catala,
you have to keep track of what you are dealing with: is it money ? Is it
an integer? Using just "+" or "*" can be ambiguous in terms of rounding,
since money is usually rounded at the cent. So to disambiguate, we suffix these
operations with something that indicates the type of what we manipulate.
The suffixes are "$" for money "." for decimals, "at" (like in email adresses)
for dates and the hat symbol for durations. If you forget the suffix, the Catala type
checker will display an error message that will help you put it where it
belongs.
But inside article 1, one question remains unknown: what is the value of
But inside article 1, one question remains unknown: what is the value of
of the fixed percentage? Often, precise values are defined elsewhere in the
legislative source. Here, let's suppose we have:
@Article 2@
#### [Article 2]
The fixed percentage mentionned at article 1 is equal to 20 %.
/*
```catala
scope IncomeTaxComputation:
definition fixed_percentage equals 20 %
# Writing 20% is just an abbreviation for 0.20
*/
```
You can see here that Catala allows definitions to be scattered throughout
You can see here that Catala allows definitions to be scattered throughout
the annotation of the legislative text, so that each
definition is as close as possible to its location in the text.
@@Conditional definitions@@+
### Conditional definitions
So far so good, but now the legislative text introduces some trickiness. Let us
So far so good, but now the legislative text introduces some trickiness. Let us
suppose the third article says:
@Article 3@ If the individual is in charge of 2 or more children, then the fixed
#### [Article 3]
If the individual is in charge of 2 or more children, then the fixed
percentage mentionned at article 1 is equal to 15 %.
/*
```catala
# How to redefine fixed_percentage?
*/
```
This article actually gives another definition for the fixed percentage, which
was already defined in article 2. However, article 3 defines the percentage
conditionnally to the individual having more than 2 children. Catala allows
was already defined in article 2. However, article 3 defines the percentage
conditionnally to the individual having more than 2 children. Catala allows
you precisely to redefine a variable under a condition:
/*
```catala
scope IncomeTaxComputation:
definition fixed_percentage under condition
individual.number_of_children >= 2
consequence equals 15 %
# Writing 15% is just an abbreviation for 0.15
*/
```
When the Catala program will execute, the right definition will be dynamically
chosen by looking at which condition is true. A correctly drafted legislative
source should always ensure that at most one condition is true at all times.
However, if it is not the case, Catala will let you define a precedence on the
chosen by looking at which condition is true. A correctly drafted legislative
source should always ensure that at most one condition is true at all times.
However, if it is not the case, Catala will let you define a precedence on the
conditions, which has to be justified by the law.
### Functions
@@Functions@@+
Catala lets you define functions anywhere in your data. Here's what it looks
like in the metadata definition when we want to define a two-brackets tax
Catala lets you define functions anywhere in your data. Here's what it looks
like in the metadata definition when we want to define a two-brackets tax
computation:
@@Begin metadata@@
/*
> Begin metadata
```catala
declaration structure TwoBrackets:
data breakpoint content money
data rate1 content decimal
@ -209,38 +225,44 @@ declaration structure TwoBrackets:
declaration scope TwoBracketsTaxComputation :
context brackets content TwoBrackets
context tax_formula content money depends on money
*/
@@End metadata@@
```
> End metadata
And in the code:
@Article4@ The tax amount for a two-brackets computation is equal to the amount
#### [Article4]
The tax amount for a two-brackets computation is equal to the amount
of income in each bracket multiplied by the rate of each bracket.
/*
```catala
scope TwoBracketsTaxComputation :
definition tax_formula of income equals
if income <=$ brackets.breakpoint then
income *$ brackets.rate1
else (
brackets.breakpoint *$ brackets.rate1 +$
brackets.breakpoint *$ brackets.rate1 +$
(income -$ brackets.breakpoint) *$ brackets.rate2
)
*/
```
@@Scope inclusion@@+
### Scope inclusion
Now that we've defined our helper scope for computing a two-brackets tax, we
Now that we've defined our helper scope for computing a two-brackets tax, we
want to use it in our main tax computation scope.
@Article 5@ For individuals whose income is greater than $100,000, the income
tax of article 1 is 40% of the income above $100,000. Below $100,000, the
#### [Article 5]
For individuals whose income is greater than $100,000, the income
tax of article 1 is 40% of the income above $100,000. Below $100,000, the
income tax is 20% of the income.
/*
```catala
declaration scope NewIncomeTaxComputation:
context two_brackets scope TwoBracketsTaxComputation
# This line says that we add the item two_brackets to the context.
# However, the "scope" keyword tells that this item is not a piece of data
# However, the "scope" keyword tells that this item is not a piece of data
# but rather a subscope that we can use to compute things.
context individual content Individual
context income_tax content money
@ -251,62 +273,66 @@ scope NewIncomeTaxComputation :
-- rate1: 20%
-- rate2: 40%
}
definition income_tax equals two_brackets.tax_formula of individual.income
*/
definition income_tax equals two_brackets.tax_formula of individual.income
```
@Article 6@
Individuals earning less than $10,000 are exempted of the income tax mentionned
#### [Article 6]
Individuals earning less than $10,000 are exempted of the income tax mentionned
at article 1.
/*
```catala
scope NewIncomeTaxComputation:
definition income_tax under condition
definition income_tax under condition
individual.income <=$ $10,000
consequence equals $0
*/
```
That's it! We've defined a two-brackets tax computation simply by annotating
legislative article by snippets of Catala code. However, attentive readers
may have caught something weird in articles 5 and 6. What happens when the
income of the individual is between $10,000 and $100,000 ?
That's it! We've defined a two-brackets tax computation simply by annotating
legislative article by snippets of Catala code. However, attentive readers
may have caught something weird in articles 5 and 6. What happens when the
income of the individual is between $10,000 and $100,000 ?
The law leaves it unspecified ; our dummy articles are clearly badly drafted.
But Catala can help you find this sort of errors via simple testing or
The law leaves it unspecified ; our dummy articles are clearly badly drafted.
But Catala can help you find this sort of errors via simple testing or
even formal verification. Let's start with the testing.
@@Testing Catala programs@@+
### Testing Catala programs
Testing Catala programs can be done directly into Catala. Indeed, writing test
cases for each Catala scope that you define is a good practice called
"unit testing" in the software engineering community. A test case is defined
cases for each Catala scope that you define is a good practice called
"unit testing" in the software engineering community. A test case is defined
as another scope:
@Testing NewIncomeTaxComputation@
/*
#### [Testing NewIncomeTaxComputation]
```catala
declaration scope Test1:
context tax_computation scope NewIncomeTaxComputation
context income_tax content money
scope Test1:
definition
tax_computation.individual
tax_computation.individual
# We define the argument to the subscope
equals
# The four lines below define a whole structure by giving a value to
# The four lines below define a whole structure by giving a value to
# each of its fields
Individual {
-- income: $230,000
-- number_of_children: 0
}
definition income_tax equals tax_computation.income_tax
# Next, we retrieve the income tax value compute it by the subscope and
# Next, we retrieve the income tax value compute it by the subscope and
# assert that it is equal to the expected value :
# ($230,000-$100,00)*40%+$100,000*20% = $72,000
assertion income_tax = $72,000
*/
```
This test should pass. Let us now consider a failing test case:
/*
```catala
declaration scope Test2:
context tax_computation scope NewIncomeTaxComputation
context income_tax content money
@ -319,24 +345,24 @@ scope Test2:
definition income_tax equals tax_computation.income_tax
assertion income_tax = $0
*/
```
This test case should compute a $0 income tax because of Article 6. But instead,
execution will yield an error saying that there is a conflict between rules.
execution will yield an error saying that there is a conflict between rules.
@@Defining exceptions to rules@@+
### Defining exceptions to rules
Indeed, the definition of the income tax in article 6 conflicts with the
definition of income tax in article 5. But actually, article 6 is just an
exception of article 5. In the law, it is implicit that if article 6 is
Indeed, the definition of the income tax in article 6 conflicts with the
definition of income tax in article 5. But actually, article 6 is just an
exception of article 5. In the law, it is implicit that if article 6 is
applicable, then it takes precedence over article 5.
@Fixing the computation@
#### [Fixing the computation]
This implicit precedence has to be explicitely declared in Catala. Here is a
fixed version of the NewIncomeTaxComputation scope:
/*
```catala
declaration scope NewIncomeTaxComputationFixed:
context two_brackets scope TwoBracketsTaxComputation
context individual content Individual
@ -349,22 +375,22 @@ scope NewIncomeTaxComputationFixed :
-- rate2: 40%
}
# To define an exception to a rule, you have to first label the rule that
# To define an exception to a rule, you have to first label the rule that
# you want to attach the exception to. You can put any snake_case identifier
# for the label
label article_5
definition income_tax equals two_brackets.tax_formula of individual.income
label article_5
definition income_tax equals two_brackets.tax_formula of individual.income
# Then, you can declare the exception by referring back to the label
exception article_5
definition income_tax under condition
definition income_tax under condition
individual.income <=$ $10,000
consequence equals $0
*/
```
And the test that should now work:
/*
```catala
declaration scope Test3:
context tax_computation scope NewIncomeTaxComputationFixed
context income_tax content money
@ -374,17 +400,17 @@ scope Test3:
-- income: $4,000
-- number_of_children: 0
}
definition income_tax equals tax_computation.income_tax
definition income_tax equals tax_computation.income_tax
assertion income_tax = $0
*/
```
@@Conclusion@@+
### Conclusion
This tutorial presents the basic concepts and syntax of the Catala language
features. It is then up to you use them to annotate legislative texts
This tutorial presents the basic concepts and syntax of the Catala language
features. It is then up to you use them to annotate legislative texts
with their algorithmic translation.
There is no single way to write Catala programs, as the program style should be
adapted to the legislation it annotates. However, Catala is a functional
language at heart, so following standard functional programming design patterns
There is no single way to write Catala programs, as the program style should be
adapted to the legislation it annotates. However, Catala is a functional
language at heart, so following standard functional programming design patterns
should help achieve concise and readable code.

View File

@ -1,14 +1,14 @@
@@Inclusion: ../tutoriel_fr.catala_fr@@
> Inclusion: ../tutoriel_fr.catala_fr
@Test@
#### [Test]
/*
```catala
déclaration champ d'application TestUnitaire1:
contexte calcul_impôt champ d'application NouveauCalculImpôtRevenu
champ d'application TestUnitaire1:
définition
calcul_impôt.personne
calcul_impôt.personne
égal à
Personne {
-- revenu: 230 000€
@ -26,4 +26,4 @@ champ d'application TestUnitaire2:
}
assertion calcul_impôt.impôt_revenu = 0,00 €
*/
```

View File

@ -1,12 +1,12 @@
@@Tutoriel d'utilisation du langage Catala@@
## Tutoriel d'utilisation du langage Catala
Bienvenue dans ce tutoriel, son objectif est de vous accompagner dans les
Bienvenue dans ce tutoriel, son objectif est de vous accompagner dans les
fonctionnalités du langage Catala et de vous apprendre à annoter des textes
législatifs avec ce langage. Ce document s'adresse principalement à des développeurs
ou des personnes ayant déjà programmé, même si des juristes avec des appétences
en informatique devraient pouvoir s'en sortir.
@@Programmation littéraire@@+
### Programmation littéraire
Pour commencer à écrire un programme Catala, vous devez partir du texte
d'une source législative qui va justifier le code que vous écrirez.
@ -21,7 +21,7 @@ sans modification dans une sortie PDF ou HTML. Vous pouvez découper votre texte
en de courtes lignes, cela apparaîtera comme un seul paragraphe dans la sortie.
Si vous voulez créer un nouveau paragraphe laisser une ligne vierge dans la source.
Catala vous permet de déclarer des entêtes de section ou de sous-section,
Catala vous permet de déclarer des entêtes de section ou de sous-section,
en les précédant et les suivant de deux arobases. Vous pouvez
diminuer l'importance du titre en augmentant le nombre de "+" après le titre de
l'entête.
@ -29,24 +29,25 @@ l'entête.
L'unité de division fondamentale est l'article, encadré par un simple arobase.
Étudions un exemple ficitif qui définit un impôt sur le revenu.
@Article 1@
#### [Article 1]
L'impôt sur le revenu d'un individu est calculé en tant qu'un pourcentage
fixe des revenus d'une personne pour une année.
/*
```catala
# Bienvenue dans le mode code de Catala.
# Ceci est un commentaire car la ligne débute par le caractère #.
# Nous allons bientôt apprendre ce que l'on doit écrire ici pour traduire
# Nous allons bientôt apprendre ce que l'on doit écrire ici pour traduire
# le sens d'un article de loi en code Catala.
*/
```
Afin de faire cela, nous allons entremêler courts bouts de code et phrases
du texte législatif. Chaque bout de code devra être aussi court que possible
et aussi proche que possible de la phrase qui justifie le code. Ce style
s'appelle programmation littéraire, un paradigme de programmation inventé par le
et aussi proche que possible de la phrase qui justifie le code. Ce style
s'appelle programmation littéraire, un paradigme de programmation inventé par le
célèbre informaticien Donald Knuth dans les années 70.
@@Définir un impôt sur le revenu fictif@@+
### Définir un impôt sur le revenu fictif
Le contenu de l'article 1 utilise beaucoup d'éléments du contexte implicite :
il existe une personne avec un revenu et en même temps un impôt sur le revenu,
@ -55,64 +56,70 @@ pas inscrit en tant que tel dans la loi, nous devons l'expliciter pour le tradui
en code. Concrètement, nous avons besoin d'une section "métadonnées" qui définit
la forme et les types de données contenues dans la loi.
Commençons notre section métadonnées en déclarant l'information sur le type
Commençons notre section métadonnées en déclarant l'information sur le type
personne :
@@Début métadonnées@@
/*
> Début métadonnées
```catala
déclaration structure Personne:
# Le nom de la structure "Personne", doit commencer
# par une lettre majuscule: c'est la convention CamelCase.
donnée revenu contenu argent
# A cette ligne, revenu est le nom du champ de la structure et
# "argent" est le type de de données de ce champ.
# On peut utiliser d'autres types comme : entier, décimal,
# argent, date, durée ou tout autre structure ou énumération
# "argent" est le type de de données de ce champ.
# On peut utiliser d'autres types comme : entier, décimal,
# argent, date, durée ou tout autre structure ou énumération
# que vous aurez déclaré
donnée nombre_enfants contenu entier
# "revenu" and "nombre_enfants" commençent par une lettre minuscule,
# "revenu" and "nombre_enfants" commençent par une lettre minuscule,
# ils adhèrent à la convention snake_case
*/
@@Fin métadonnées@@
```
> Fin métadonnées
Cette structure contient deux champs de de données, "revenu" et "nombre_enfants".
Les structures sont utiles pour regrouper des données qui vont ensemble.
Les structures sont utiles pour regrouper des données qui vont ensemble.
Typiquement, vous aurez une structure pour une entité concrète sur laquelle
s'applique la loi (comme une personne). C'est à vous de décider comment regrouper
les données mais vous devrez viser à optimiser la lisibilité du code.
Parfois, la loi donne une énumération de différentes situations. Ces énumérations
sont modélisés en Catala par le type énumération, comme suit :
@@Début métadonnées@@
/*
> Début métadonnées
```catala
déclaration énumération CréditImpôt:
# Le nom "CréditImpôt" s'écrit aussi en CamelCase
-- AucunCréditImpôt
# Cette ligne indique que "CréditImpôt" peut être en situation
# Cette ligne indique que "CréditImpôt" peut être en situation
# "AucunCréditImpôt"
-- CréditImpôtEnfants contenu entier
-- CréditImpôtEnfants contenu entier
# Cette ligne indique, de manière alternative, que "CréditImpôt" peut aussi
# être une situation "CréditImpôtEnfants". Cette situation porte un contenu
# de type entier qui correspond au nombre d'enfants concernés par le crédit
# d'impôt. Cela signifie que si vous êtes dans la situation
# d'impôt. Cela signifie que si vous êtes dans la situation
# "CréditImpôtEnfants", vous aurez aussi accès à ce nombre d'enfants.
*/
@@Fin métadonnées@@
```
> Fin métadonnées
En informatique, une telle énumération est appelée "type somme" ou simplement
énumération. La combinaison de structures et d'énumération permet au programmeur
Catala de déclarer toutes les formes possibles de données, car cette combinaison
énumération. La combinaison de structures et d'énumération permet au programmeur
Catala de déclarer toutes les formes possibles de données, car cette combinaison
est équivalente à la puissante notion de types de données algébriques.
Nous avons défini et typé les données que le programme va manipuler. Maintenant,
nous devons définir un contexte logique dans lequel ces données vont évoluer.
On effectue cela par la notion de "champs d'application" en Catala.
Les champs d'application sont proches des fonctions en termes de programmation
traditionnelle. Les champs d'application doivent avoir été déclarés
nous devons définir un contexte logique dans lequel ces données vont évoluer.
On effectue cela par la notion de "champs d'application" en Catala.
Les champs d'application sont proches des fonctions en termes de programmation
traditionnelle. Les champs d'application doivent avoir été déclarés
préalablement dans les métadonnées, de la manière suivante:
@@Début métadonnées@@
/*
> Début métadonnées
```catala
déclaration champ d'application CalculImpôtRevenu:
# Les champs d'application utilisent le CamelCase
contexte personne contenu Personne
@ -121,20 +128,23 @@ déclaration champ d'application CalculImpôtRevenu:
# donnée sur laquelle le champ d'application va intervenir
contexte pourcentage_fixe contenu décimal
contexte impôt_revenu contenu argent
*/
@@Fin métadonnées@@
```
> Fin métadonnées
Nous avons maintenant tout ce dont nous avons besoin pour annoter le contenu
de l'article 1 qui a été copié ci-dessous.
@Article 1@
#### [Article 1]
L'impôt sur le revenu pour une personne est défini comme un pourcentage fixe
des revenus de la personne pour une année.
/*
```catala
champ d'application CalculImpôtRevenu:
définition impôt_revenu égal à
personne.revenu *€ pourcentage_fixe
*/
```
Dans le code, nous définissons à l'intérieur de notre champ d'application
le montant d'impôt sur le revenu selon la formule décrit dans l'article.
@ -143,74 +153,79 @@ arithmétiques habituels : addition "+", soustraction "-", multiplication "*"
et division (barre oblique).
Toutefois, dans le code Catala, vous pouvez voir que nous utilisons "*€"
pour multiplier les revenus d'une personne par le pourcentage fixe. Le
pour multiplier les revenus d'une personne par le pourcentage fixe. Le
suffixe € inique que nous effectuons une multiplication sur une somme d'argent.
En effet, en Catala, vous devez rester conscient de la donnée manipulée :
En effet, en Catala, vous devez rester conscient de la donnée manipulée :
est-ce de l'argent ? est-ce un entier ? Utiliser simple "+" ou "*" est ambigu
en termes d'arrondis car l'argent est habituellement arrondi au centime.
en termes d'arrondis car l'argent est habituellement arrondi au centime.
Ainsi, afin d'être clair, nous suffixons ces opérations avec quelque chose
qui indique le type de donnée manipulé. Les suffixes sont "€" pour de l'argent,
"." pour les décimales, arobase (comme dans les adresses mail) pour les dates et
le symbole chapeau pour les durées. Si vous oubliez le suffixe, le vérificateur
de types de Catala va afficher une message d'erreur afin de vous aider à le placer
comme il le faut.
comme il le faut.
Mais dans l'article 1, une question reste sans réponse: quelle est la valeur
Mais dans l'article 1, une question reste sans réponse: quelle est la valeur
de la pourcentage fixe? Souvent, des valeurs précises sont définis ailleurs
dans les sources législatives. Ici, supposons que nous avons:
@Article 2@
#### [Article 2]
Le pourcentage fixe mentionné à l'article 1 est égal à 20%.
/*
```catala
champ d'application CalculImpôtRevenu:
définition pourcentage_fixe égal à 20%
# Ecrire 20% est juste une abbréviation pour 0.20
*/
```
Vous pouvez voir ici que Catala permet des définitions réparties dans toute
l'annotation du texte législatif, afin que chaque définition soit le plus
l'annotation du texte législatif, afin que chaque définition soit le plus
proche possible de sa localisation dans le texte.
@@Définitions conditionnelles@@+
### Définitions conditionnelles
Jusqu'à là tout va bien mais maintenant le texte législatif présente quelques
Jusqu'à là tout va bien mais maintenant le texte législatif présente quelques
difficultés. Supposons que le troisième article dispose :
#### [Article 3]
@Article 3@ Si l'individu a à sa charge deux ou plus enfants alors
Si l'individu a à sa charge deux ou plus enfants alors
le pourcentage fixe mentionné à l'article 1 vaut 15 %.
/*
# Comment redéfinir pourcentage_fixe ?
*/
Cet article donne en réalité une autre définition pour le pourcentage fixe,
```catala
# Comment redéfinir pourcentage_fixe ?
```
Cet article donne en réalité une autre définition pour le pourcentage fixe,
préalablement défini à l'article 2. Toutefois, si l'article 3 définit le pourcentage
de manière conditionnelle pour la personne ayant plus de deux enfants.
de manière conditionnelle pour la personne ayant plus de deux enfants.
Catala permet de redéfinir précisément une variable sous une condition :
/*
```catala
champ d'application CalculImpôtRevenu:
définition pourcentage_fixe sous condition
personne.nombre_enfants >= 2
conséquence égal à 15%
# Ecrire 15% est juste une abbréviation pour 0.15
*/
```
Quand le programme Catala va s'exécuter, la juste définition sera choisie
dynamiquement en déterminant laquelle des condition est vraie dans le contexte.
Une source législative rédigée correctement doit toujours garantir qu'au maximum
une seule condition soit vraie à tout moment. Toutefois, si ce n'est pas le cas,
Catala vous permettra de définir un ordre des priorités sur les conditions,
une seule condition soit vraie à tout moment. Toutefois, si ce n'est pas le cas,
Catala vous permettra de définir un ordre des priorités sur les conditions,
qui doit être justifié par un raisonnement juridique.
@@Fonctions@@+
### Fonctions
Catala vous permet de définir des fonctions partout dans vos données. Voici
à quoi cela ressemble dans la définition des métadonnées quand nous voulons
à quoi cela ressemble dans la définition des métadonnées quand nous voulons
définir un calcul de l'impôt sur le revenu à deux tranches :
@@Début métadonnées@@
/*
> Début métadonnées
```catala
déclaration structure DeuxTranches:
donnée seuil contenu argent
donnée taux1 contenu décimal
@ -219,42 +234,47 @@ déclaration structure DeuxTranches:
déclaration champ d'application CalculImpôtDeuxTranches :
contexte tranches contenu DeuxTranches
contexte formule_imposition contenu argent dépend de argent
*/
@@Fin métadonnées@@
```
> Fin métadonnées
Et dans le code :
@Article4@ Le montant d'impôt pour le calcul à deux tranches
est égal au montant d'impôt dans chaque tranche multiplié
#### [Article4]
Le montant d'impôt pour le calcul à deux tranches
est égal au montant d'impôt dans chaque tranche multiplié
par le taux de chaque branche.
/*
```catala
champ d'application CalculImpôtDeuxTranches :
définition formule_imposition de revenu égal à
si revenu <=€ tranches.seuil alors
revenu *€ tranches.taux1
sinon (
tranches.seuil *€ tranches.taux1 +€
tranches.seuil *€ tranches.taux1 +€
(revenu -€ tranches.seuil) *€ tranches.taux2
)
*/
```
@@Inclusion de champ d'application@@+
### Inclusion de champ d'application
Maintenant que nous avons défini notre champ d'application utilitaire pour
calculer un impôt à deux tranches, nous voulons l'utiliser dans notre champ
d'application principal de calcul de l'impôt.
@Article 5@ Pour les individus dont le revenu est supérieur à 100 000€,
l'impôt sur le revenu de l'article 1 est de 40% du revenu au-dessus de
#### [Article 5]
Pour les individus dont le revenu est supérieur à 100 000€,
l'impôt sur le revenu de l'article 1 est de 40% du revenu au-dessus de
100 000€. En dessous de 100 000€, l'impôt sur le revenu est de 20% du revenu.
/*
```catala
déclaration champ d'application NouveauCalculImpôtRevenu:
contexte deux_tranches champ d'application CalculImpôtDeuxTranches
# Cette ligne indique que nous ajoutons l'élément deux_tranches au contexte.
# Toutefois, les mots clé "champ d'application" indique que l'élément n'est
# pas une donnée mais plutôt un sous-champ d'application qui peut être
# Toutefois, les mots clé "champ d'application" indique que l'élément n'est
# pas une donnée mais plutôt un sous-champ d'application qui peut être
# utilisé pour calculer des choses.
contexte personne contenu Personne
contexte impôt_revenu contenu argent
@ -265,47 +285,50 @@ champ d'application NouveauCalculImpôtRevenu :
-- taux1: 20%
-- taux2: 40%
}
définition impôt_revenu égal à
deux_tranches.formule_imposition de personne.revenu
*/
définition impôt_revenu égal à
deux_tranches.formule_imposition de personne.revenu
```
@Article 6@
Les personnes ayant moins de 10 000€ de revenus sont exemptés de l'impôt
#### [Article 6]
Les personnes ayant moins de 10 000€ de revenus sont exemptés de l'impôt
sur le revenu prévu à l'article 1.
/*
```catala
champ d'application NouveauCalculImpôtRevenu:
définition impôt_revenu sous condition
définition impôt_revenu sous condition
personne.revenu <=€ 10 000€
conséquence égal à 0€
*/
```
Et voilà ! Nous avons défini un calcul d'impôt à deux tranches en annotant
tout simplement un texte législatif par des bouts de code Catala.
Cependant, les lecteurs attentifs auront vu quelque chose de curieux dans les
articles 5 et 6. Que se passe-t-il si le revenu d'une personne se situe entre
tout simplement un texte législatif par des bouts de code Catala.
Cependant, les lecteurs attentifs auront vu quelque chose de curieux dans les
articles 5 et 6. Que se passe-t-il si le revenu d'une personne se situe entre
10 000€ et 100 000€ ?
La loi ne le précise pas; nos articles sont clairement mal rédigés.
Mais Catala vous aide à trouver ce genre d'erreur par de simples tests ou
même la vérification formelle. Commençons par les tests.
@@Tester les programmes Catala@@+
### Tester les programmes Catala
Tester les programmes Catala peut se faire directement en Catala. En effet,
écrire des cas de tests pour chaque champ d'application Catala que vous
définissez est une bonne pratique appelée "tests unitaires" dans la
écrire des cas de tests pour chaque champ d'application Catala que vous
définissez est une bonne pratique appelée "tests unitaires" dans la
communauté du génie logicielle. Les cas de test sont définis dans des
champ d'application :
@Tester NouveauCalculImpotRevenu@
/*
#### [Tester NouveauCalculImpotRevenu]
```catala
déclaration champ d'application Test1:
contexte calcul_impôt champ d'application NouveauCalculImpôtRevenu
contexte impôt_revenu contenu argent
champ d'application Test1:
définition
calcul_impôt.personne
calcul_impôt.personne
# L'on définit le paramètre au sous-champ d'application
égal à
# Les quatre lignes ci-dessous définissent une structure entière
@ -316,15 +339,16 @@ champ d'application Test1:
}
définition impôt_revenu égal à calcul_impôt.impôt_revenu
# Ensuite, nous récupérons le montant d'impôt, calculé par
# sous-champ d'application et nous assertons qu'il vaut bien
# Ensuite, nous récupérons le montant d'impôt, calculé par
# sous-champ d'application et nous assertons qu'il vaut bien
# la valeur attendue :
# (230 000€ - 100 000€) * 40% + 100 000€ * 20% = 72 000€
assertion impôt_revenu = 72 000€
*/
```
Ce test devrait être bon. Maintenant étudions un test en échec :
/*
```catala
déclaration champ d'application Test2:
contexte calcul_impôt champ d'application NouveauCalculImpôtRevenu
contexte impôt_revenu contenu argent
@ -337,26 +361,26 @@ champ d'application Test2:
définition impôt_revenu égal à calcul_impôt.impôt_revenu
assertion impôt_revenu = 0€
*/
```
Ce cas de test devrait calculer un impôt sur le revenu de 0€,
en raison de l'article 6. Mais au lieu de cela, l'exécution produira
une erreur car il y a un conflit entre les règles.
@@Définir des exceptions à des règles@@+
### Définir des exceptions à des règles
En effet, la définition d'un impôt sur le revenu à l'article 6 entre en
En effet, la définition d'un impôt sur le revenu à l'article 6 entre en
conflit avec la définition de l'article 5. Mais en réalité, l'article 6
est une simple exception à l'article 5. Dans la loi, il est implicite que
si l'article 6 est applicable, alors son application est prioritaire
est une simple exception à l'article 5. Dans la loi, il est implicite que
si l'article 6 est applicable, alors son application est prioritaire
sur l'article 5.
@Régler correctement le calcul@
#### [Régler correctement le calcul]
Cette priorité implicite doit être explicitement déclaré en Catala. Voici une
version correcte du champ d'application NouveauCalculImpotRevenu :
/*
```catala
déclaration champ d'application NouveauCalculImpôtRevenuCorrect:
contexte deux_tranches champ d'application CalculImpôtDeuxTranches
contexte personne contenu Personne
@ -373,20 +397,20 @@ champ d'application NouveauCalculImpôtRevenuCorrect :
# Pour définir une exception à une règle, vous devez d'abord étiquetter
# la règle à laquelle vous voulez attacher l'exception. Vous pouvez mettre
# n'importe quel identifiant en snake_case pour l'étiquette.
étiquette article_5
étiquette article_5
définition impôt_revenu égal à
deux_tranches.formule_imposition de personne.revenu
deux_tranches.formule_imposition de personne.revenu
# Puis, vous pouvez déclarez l'exception par référence à l'étiquette
exception article_5
définition impôt_revenu sous condition
définition impôt_revenu sous condition
personne.revenu <=€ 10 000€
conséquence égal à 0€
*/
```
Le test devrait désormais fonctionner :
/*
```catala
déclaration champ d'application Test3:
contexte calcul_impôt champ d'application NouveauCalculImpôtRevenuCorrect
contexte impôt_revenu contenu argent
@ -398,16 +422,16 @@ champ d'application Test3:
}
définition impôt_revenu égal à calcul_impôt.impôt_revenu
assertion impôt_revenu = 0€
*/
```
@@Conclusion@@+
### Conclusion
Ce tutoriel présente les concepts de base et la syntaxe des fonctionnalités
du langage Catala. C'est à vous de les utiliser pour annoter du texte
du langage Catala. C'est à vous de les utiliser pour annoter du texte
législatif avec leur traduction algorithmique.
Il n'y pas une seule bonne façon d'écrire des programmes Catala car le style de
programmation doit être adapté au texte de loi annoté. Cependant, Catala est un
langage basé sur la programmation fonctionnelle, donc suivre les
patrons de conception habituels de la programmation fonctionnelle
devrait aider à obtenir du code concis et lisible.
langage basé sur la programmation fonctionnelle, donc suivre les
patrons de conception habituels de la programmation fonctionnelle
devrait aider à obtenir du code concis et lisible.

View File

@ -1,9 +1,10 @@
@@The US Tax Code@@
## The US Tax Code
> Begin metadata
@@Begin metadata@@
/*
```catala
declaration structure Person:
data id content integer
*/
@@End metadata@@
```
> End metadata

View File

@ -1,8 +1,8 @@
@@Section 1015@@
## Section 1015
@@Begin metadata@@
/*
> Begin metadata
```catala
declaration enumeration AcquisitionMethod:
-- Gift
-- Trust
@ -30,17 +30,19 @@ declaration scope BasisOfGift:
context basis_bonus_after_1976 content money
context transferor content Transferor
context gift_tax_paid content money
*/
@@End metadata@@
```
> End metadata
@(a) Gifts after December 31, 1920@
If the property was acquired by gift after December 31, 1920, the basis shall be
the same as it would be in the hands of the donor or the last preceding owner by
whom it was not acquired by gift, except that if such basis (adjusted for the
period before the date of the gift as provided in section 1016) is greater than
the fair market value of the property at the time of the gift, then for the
### [(a) Gifts after December 31, 1920]
If the property was acquired by gift after December 31, 1920, the basis shall be
the same as it would be in the hands of the donor or the last preceding owner by
whom it was not acquired by gift, except that if such basis (adjusted for the
period before the date of the gift as provided in section 1016) is greater than
the fair market value of the property at the time of the gift, then for the
purpose of determining loss the basis shall be such fair market value.
/*
```catala
scope BasisOfGift:
definition basis_subsection_a equals
if transferor.basis >= value.fair_market of acquisition.moment then
@ -52,18 +54,19 @@ scope BasisOfGift:
acquisition.moment > |12/31/1920| and
acquisition.method = Gift
consequence equals basis_subsection_a
```
*/
If the facts necessary to determine the basis in the hands of the donor or the
last preceding owner are unknown to the donee, the Secretary shall, if
possible, obtain such facts from such donor or last preceding owner, or any
other person cognizant thereof. If the Secretary finds it impossible to obtain
such facts, the basis in the hands of such donor or last preceding owner shall
be the fair market value of such property as found by the Secretary as of the
date or approximate date at which, according to the best information that the
Secretary is able to obtain, such property was acquired by such donor or last
If the facts necessary to determine the basis in the hands of the donor or the
last preceding owner are unknown to the donee, the Secretary shall, if
possible, obtain such facts from such donor or last preceding owner, or any
other person cognizant thereof. If the Secretary finds it impossible to obtain
such facts, the basis in the hands of such donor or last preceding owner shall
be the fair market value of such property as found by the Secretary as of the
date or approximate date at which, according to the best information that the
Secretary is able to obtain, such property was acquired by such donor or last
preceding owner.
/*
```catala
scope BasisOfGift under condition
acquisition.moment > |01/31/1920| and
acquisition.method = Gift:
@ -72,43 +75,47 @@ scope BasisOfGift under condition
match transferor.known_basis with pattern
-- Some of basis : basis
-- None : value.fair_market of transferor.acquisition.moment
*/
```
### [(b) Transfer in trust after December 31, 1920]
@(b) Transfer in trust after December 31, 1920@
If the property was acquired after December 31, 1920, by a transfer in trust
(other than by a transfer in trust by a gift, bequest, or devise), the basis
shall be the same as it would be in the hands of the grantor increased in the
amount of gain or decreased in the amount of loss recognized to the grantor on
such transfer under the law applicable to the year in which the transfer was
If the property was acquired after December 31, 1920, by a transfer in trust
(other than by a transfer in trust by a gift, bequest, or devise), the basis
shall be the same as it would be in the hands of the grantor increased in the
amount of gain or decreased in the amount of loss recognized to the grantor on
such transfer under the law applicable to the year in which the transfer was
made.
/*
```catala
scope BasisOfGift under condition
acquisition.moment > |01/31/1920| and
acquisition.method = Trust:
definition basis equals
transferor.basis + transferor.gain_or_loss of acquisition.moment
*/
```
@(c) Gift or transfer in trust before January 1, 1921@
If the property was acquired by gift or transfer in trust on or before December
31, 1920, the basis shall be the fair market value of such property at the time
### [(c) Gift or transfer in trust before January 1, 1921]
If the property was acquired by gift or transfer in trust on or before December
31, 1920, the basis shall be the fair market value of such property at the time
of such acquisition.
/*
```catala
scope BasisOfGift under condition acquisition.moment <= |01/31/1920|:
definition basis equals
value.fair_market of acquisition.moment
*/
```
@@(d) Increased basis for gift tax paid@@+
### (d) Increased basis for gift tax paid
@(1) In general@ If—
(A) the property is acquired by gift on or after September 2, 1958, the basis
shall be the basis determined under subsection (a), increased (but not above
the fair market value of the property at the time of the gift) by the amount
of gift tax paid with respect to such gift, or
/*
#### [(1) In general]
If— (A) the property is acquired by gift on or after September 2, 1958, the
basis shall be the basis determined under subsection (a), increased (but not
above the fair market value of the property at the time of the gift) by the
amount of gift tax paid with respect to such gift, or
```catala
scope BasisOfGift under condition
acquisition.moment >= |09/02/1958| and
acquisition.method = Gift:
@ -120,15 +127,17 @@ scope BasisOfGift under condition
else
gift_tax_paid
)
*/
(B) the property was acquired by gift before September 2, 1958, and has not been
sold, exchanged, or otherwise disposed of before such date, the basis of the
property shall be increased on such date by the amount of gift tax paid with
respect to such gift, but such increase shall not exceed an amount equal to the
amount by which the fair market value of the property at the time of the gift
exceeded the basis of the property in the hands of the donor at the time of the
```
(B) the property was acquired by gift before September 2, 1958, and has not been
sold, exchanged, or otherwise disposed of before such date, the basis of the
property shall be increased on such date by the amount of gift tax paid with
respect to such gift, but such increase shall not exceed an amount equal to the
amount by which the fair market value of the property at the time of the gift
exceeded the basis of the property in the hands of the donor at the time of the
gift.
/*
```catala
scope BasisOfGift under condition
acquisition.moment < |09/02/1958| and
acquisition.method = Gift and
@ -144,65 +153,74 @@ scope BasisOfGift under condition
else
gift_tax_paid
)
*/
```
@(2) Amount of tax paid with respect to gift@
For purposes of paragraph (1), the amount of gift tax paid with respect to any
gift is an amount which bears the same ratio to the amount of gift tax paid under
chapter 12 with respect to all gifts made by the donor for the calendar year
(or preceding calendar period) in which such gift is made as the amount of such
gift bears to the taxable gifts (as defined in section 2503(a) but computed
without the deduction allowed by section 2521) made by the donor during such
calendar year or period. For purposes of the preceding sentence, the amount of
any gift shall be the amount included with respect to such gift in determining
(for the purposes of section 2503(a)) the total amount of gifts made during the
calendar year or period, reduced by the amount of any deduction allowed with
respect to such gift under section 2522 (relating to charitable deduction) or
#### [(2) Amount of tax paid with respect to gift]
For purposes of paragraph (1), the amount of gift tax paid with respect to any
gift is an amount which bears the same ratio to the amount of gift tax paid under
chapter 12 with respect to all gifts made by the donor for the calendar year
(or preceding calendar period) in which such gift is made as the amount of such
gift bears to the taxable gifts (as defined in section 2503(a) but computed
without the deduction allowed by section 2521) made by the donor during such
calendar year or period. For purposes of the preceding sentence, the amount of
any gift shall be the amount included with respect to such gift in determining
(for the purposes of section 2503(a)) the total amount of gifts made during the
calendar year or period, reduced by the amount of any deduction allowed with
respect to such gift under section 2522 (relating to charitable deduction) or
under section 2523 (relating to marital deduction).
/*
# We don't formalize the amount of gift tax since it would require
```catala
# We don't formalize the amount of gift tax since it would require
#formalizing other sections of the code
*/
```
#### [(3) Gifts treated as made one-half by each spouse]
@(3) Gifts treated as made one-half by each spouse@
For purposes of paragraph (1), where the donor and his spouse elected, under
section 2513 to have the gift considered as made one-half by each, the amount
of gift tax paid with respect to such gift under chapter 12 shall be the sum
of the amounts of tax paid with respect to each half of such gift (computed in
For purposes of paragraph (1), where the donor and his spouse elected, under
section 2513 to have the gift considered as made one-half by each, the amount
of gift tax paid with respect to such gift under chapter 12 shall be the sum
of the amounts of tax paid with respect to each half of such gift (computed in
the manner provided in paragraph (2)).
/*
# Same here
*/
@(4) Treatment as adjustment to basis@
For purposes of section 1016(b), an increase in basis under paragraph (1) shall
```catala
# Same here
```
#### [(4) Treatment as adjustment to basis]
For purposes of section 1016(b), an increase in basis under paragraph (1) shall
be treated as an adjustment under section 1016(a).
/*
# Same here
*/
@(5) Application to gifts before 1955@
With respect to any property acquired by gift before 1955, references in this
subsection to any provision of this title shall be deemed to refer to the
corresponding provision of the Internal Revenue Code of 1939 or prior revenue
```catala
# Same here
```
#### [(5) Application to gifts before 1955]
With respect to any property acquired by gift before 1955, references in this
subsection to any provision of this title shall be deemed to refer to the
corresponding provision of the Internal Revenue Code of 1939 or prior revenue
laws which was effective for the year in which such gift was made.
/*
```catala
# Same here
*/
```
@@(6) Special rule for gifts made after December 31, 1976@@++
#### (6) Special rule for gifts made after December 31, 1976
@(A) In general@
In the case of any gift made after December 31, 1976, the increase in basis
provided by this subsection with respect to any gift for the gift tax paid under
##### [(A) In general]
In the case of any gift made after December 31, 1976, the increase in basis
provided by this subsection with respect to any gift for the gift tax paid under
chapter 12 shall be an amount (not in excess of the amount of tax so paid) which
bears the same ratio to the amount of tax so paid as—
(i) the net appreciation in value of the gift, bears to
(ii) the amount of the gift.
/*
```catala
scope BasisOfGift under condition
acquisition.moment > |09/02/1976| and
acquisition.method = Gift:
@ -212,22 +230,26 @@ scope BasisOfGift under condition
value.net_appreciation /
value.last_acquisition # is it really? "amount" is imprecise
)
*/
```
@(B) Net appreciation@
For purposes of paragraph (1), the net appreciation in value of any gift is the
amount by which the fair market value of the gift exceeds the donors adjusted
##### [(B) Net appreciation]
For purposes of paragraph (1), the net appreciation in value of any gift is the
amount by which the fair market value of the gift exceeds the donors adjusted
basis immediately before the gift.
/*
```catala
scope BasisOfGift:
definition value.net_appreciation equals
value.fair_market_value of acquisition.moment - transferor.basis
*/
```
@(e) Gifts between spouses@
In the case of any property acquired by gift in a transfer described in section
1041(a), the basis of such property in the hands of the transferee shall be
##### [(e) Gifts between spouses]
In the case of any property acquired by gift in a transfer described in section
1041(a), the basis of such property in the hands of the transferee shall be
determined under section 1041(b)(2) and not this section.
/*
```catala
# Same here
*/
```

View File

@ -1,14 +1,15 @@
@@Section 121@@
## Section 121
@@Begin metadata@@
/*
> Begin metadata
```catala
declaration structure Period:
data begin content date
data begin content date
data end content date
declaration scope PeriodMerge:
context periods1 content collection Period
context periods2 content collection Period
context periods1 content collection Period
context periods2 content collection Period
context output content collection Period
scope PeriodMerge:
@ -17,7 +18,7 @@ scope PeriodMerge:
definition periods2 equals []
# TODO: find a way to implement the merging of two collections of date
# periods into a single non-overlapping collection of date periods such
# periods into a single non-overlapping collection of date periods such
# that the output covers both input date ranges.
definition output equals []
@ -26,43 +27,43 @@ declaration structure PreviousSaleWhereSection121aApplied:
declaration enumeration OtherSection121aSale:
-- NoOtherSaleWhereSection121aApplied
-- MostRecentSaleWhereSection121aApplied content
-- NoOtherSaleWhereSection121aApplied
-- MostRecentSaleWhereSection121aApplied content
PreviousSaleWhereSection121aApplied
declaration scope Section121SinglePerson:
context requirements_met condition
context requirements_ownership_met condition
context requirements_met condition
context requirements_ownership_met condition
context requirements_usage_met condition
context date_of_sale_or_exchange content date
context property_ownage content collection Period
# Invariant: the periods in the collection are disjoint
context property_usage_as_principal_residence
context property_usage_as_principal_residence
content collection Period
# Invariant: the periods in the collection are disjoint
context aggregate_periods_from_last_five_years content duration
context aggregate_periods_from_last_five_years content duration
depends on collection Period
context gain_cap content money
context gain_from_sale_or_exchange_of_property content money
context income_excluded_from_gross_income_uncapped content money
context income_excluded_from_gross_income content money
context section_121_b_3_applies condition
context section_121_b_3_applies condition
context other_section_121a_sale content OtherSection121aSale
declaration structure PersonalData:
data property_ownage content collection Period
data property_usage_as_principal_residence
data property_usage_as_principal_residence
content collection Period
data other_section_121a_sale content OtherSection121aSale
declaration structure JointReturn:
data person1 content PersonalData
data person2 content PersonalData
declaration structure JointReturn:
data person1 content PersonalData
data person2 content PersonalData
declaration structure DeadSpouseInfo:
data return content PersonalData
data date_of_spouse_death content date
data death_spouse_info_at_time_of_death content PersonalData
data death_spouse_info_at_time_of_death content PersonalData
declaration enumeration ReturnType:
-- SingleReturn content PersonalData
@ -76,10 +77,10 @@ declaration scope Section121TwoPersons:
context section121Person2 scope Section121SinglePerson
context section121a_requirements_met condition
context section_121_b_2_A_condition condition
context gain_cap_person_1 content money
context gain_cap_person_1 content money
context gain_cap_person_2 content money
context gain_cap content money
context return_type content ReturnType
context return_type content ReturnType
context return_date content date
context date_of_sale_or_exchange content date
context gain_from_sale_or_exchange_of_property content money
@ -89,49 +90,49 @@ declaration scope Section121TwoPersons:
# Defining sub-scopes arguments
scope Section121TwoPersons:
definition section121Person2.date_of_sale_or_exchange equals
definition section121Person2.date_of_sale_or_exchange equals
date_of_sale_or_exchange
definition section121Person1.date_of_sale_or_exchange equals
definition section121Person1.date_of_sale_or_exchange equals
date_of_sale_or_exchange
definition person1 equals match return_type with pattern
definition person1 equals match return_type with pattern
-- SingleReturn of data_person1 : data_person1
-- JointReturn of data_couple : data_couple.person1
-- SingleReturnSurvivingSpouse of data_single: data_single.return
definition person2 equals match return_type with pattern
definition person2 equals match return_type with pattern
-- SingleReturn of data_person2 : data_person2
-- JointReturn of data_couple : data_couple.person2
-- SingleReturnSurvivingSpouse of data_single: data_single.return
definition section121Person1.property_ownage equals person1.property_ownage
definition section121Person1.property_usage_as_principal_residence equals
definition section121Person1.property_usage_as_principal_residence equals
person1.property_usage_as_principal_residence
definition section121Person2.property_ownage equals person2.property_ownage
definition section121Person2.property_usage_as_principal_residence equals
definition section121Person2.property_usage_as_principal_residence equals
person1.property_usage_as_principal_residence
definition section121Person1.gain_from_sale_or_exchange_of_property equals
definition section121Person1.gain_from_sale_or_exchange_of_property equals
gain_from_sale_or_exchange_of_property
definition section121Person2.gain_from_sale_or_exchange_of_property equals
definition section121Person2.gain_from_sale_or_exchange_of_property equals
gain_from_sale_or_exchange_of_property
definition section121Person1.other_section_121a_sale equals
definition section121Person1.other_section_121a_sale equals
person1.other_section_121a_sale
definition section121Person2.other_section_121a_sale equals
person2.other_section_121a_sale
definition gain_cap_person_1 equals section121Person1.gain_cap
definition gain_cap_person_1 equals section121Person1.gain_cap
definition gain_cap_person_2 equals section121Person2.gain_cap
declaration scope Section121TwoPasses:
context first_pass scope Section121TwoPersons
context second_pass scope Section121TwoPersons
context return_type content ReturnType
context return_type content ReturnType
context return_date content date
context date_of_sale_or_exchange content date
context gain_from_sale_or_exchange_of_property content money
@ -140,308 +141,316 @@ declaration scope Section121TwoPasses:
# Defining sub-scopes arguments
scope Section121TwoPasses:
definition first_pass.return_type equals return_type
definition second_pass.return_type equals return_type
definition first_pass.return_date equals return_date
definition second_pass.return_date equals return_date
definition first_pass.return_type equals return_type
definition second_pass.return_type equals return_type
definition first_pass.gain_from_sale_or_exchange_of_property equals
definition first_pass.return_date equals return_date
definition second_pass.return_date equals return_date
definition first_pass.gain_from_sale_or_exchange_of_property equals
gain_from_sale_or_exchange_of_property
definition second_pass.gain_from_sale_or_exchange_of_property equals
definition second_pass.gain_from_sale_or_exchange_of_property equals
gain_from_sale_or_exchange_of_property
definition first_pass.date_of_sale_or_exchange equals date_of_sale_or_exchange
definition second_pass.date_of_sale_or_exchange equals date_of_sale_or_exchange
definition income_excluded_from_gross_income equals
definition income_excluded_from_gross_income equals
second_pass.income_excluded_from_gross_income
*/
@@End metadata@@
```
> End metadata
@(a) Exclusion@
## [(a) Exclusion]
Gross income shall not include gain from the sale or exchange of property if,
during the 5-year period ending on the date of the sale or exchange, such
property has been owned and used by the taxpayer as the taxpayers principal
residence for periods aggregating 2 years or more.
/*
Gross income shall not include gain from the sale or exchange of property if,
during the 5-year period ending on the date of the sale or exchange, such
property has been owned and used by the taxpayer as the taxpayers principal
residence for periods aggregating 2 years or more.
```catala
scope Section121SinglePerson:
# Here we aggregate over all the periods of the collection. For
# Here we aggregate over all the periods of the collection. For
# each period, three cases:
# - either the period began less that 5 years before the
# - either the period began less that 5 years before the
# date_of_sale_or_exchange in which case we count if full
# - either the period ended more that 5 years before the
# date_of_sale_or_exchange in which case we don't count it
# - either the 5 years mark is inside the period and we only
# - either the period ended more that 5 years before the
# date_of_sale_or_exchange in which case we don't count it
# - either the 5 years mark is inside the period and we only
# cound the half after 5 years
definition aggregate_periods_from_last_five_years of periods equals
definition aggregate_periods_from_last_five_years of periods equals
sum duration for period in periods of (
if date_of_sale_or_exchange <=@ period.begin +@ 5 year then
period.end -@ period.begin
else (if date_of_sale_or_exchange >=@ period.end +@ 5 year then
0 day
else (if date_of_sale_or_exchange >=@ period.end +@ 5 year then
0 day
else ((period.end +@ 5 year) -@ date_of_sale_or_exchange))
)
# Regulation 1.121-1(c)(1): 2 years = 730 days
# Regulation 1.121-1(c)(1): the periods of ownage and usage
# Regulation 1.121-1(c)(1): the periods of ownage and usage
# don't have to overlap
rule requirements_ownership_met under condition
rule requirements_ownership_met under condition
aggregate_periods_from_last_five_years of property_ownage >=^ 730 day
consequence fulfilled
consequence fulfilled
rule requirements_usage_met under condition
rule requirements_usage_met under condition
aggregate_periods_from_last_five_years of
property_usage_as_principal_residence >=^ 730 day
consequence fulfilled
rule requirements_met under condition
rule requirements_met under condition
requirements_ownership_met and requirements_usage_met
consequence fulfilled
definition income_excluded_from_gross_income_uncapped equals
if requirements_met then gain_from_sale_or_exchange_of_property
else $0
scope Section121TwoPersons:
definition section121a_requirements_met equals section121Person1.requirements_met
definition income_excluded_from_gross_income_uncapped equals
definition income_excluded_from_gross_income_uncapped equals
section121Person1.income_excluded_from_gross_income_uncapped
*/
```
@@(b) Limitations@@+
### (b) Limitations
@(1) In general@
#### [(1) In general]
The amount of gain excluded from gross income under subsection (a) with
The amount of gain excluded from gross income under subsection (a) with
respect to any sale or exchange shall not exceed $250,000.
/*
```catala
scope Section121SinglePerson:
definition gain_cap equals $250,000
# Big semantics insight for Catala. Here we could want to get rid of
# the "_uncapped" version of the variable. But in the current
# Big semantics insight for Catala. Here we could want to get rid of
# the "_uncapped" version of the variable. But in the current
# semantics we can't do that because we don't allow for recursion.
definition income_excluded_from_gross_income equals
if income_excluded_from_gross_income_uncapped >=$ gain_cap then
definition income_excluded_from_gross_income equals
if income_excluded_from_gross_income_uncapped >=$ gain_cap then
gain_cap
else
else
income_excluded_from_gross_income_uncapped
scope Section121TwoPersons:
definition gain_cap equals section121Person1.gain_cap
scope Section121TwoPersons:
definition gain_cap equals section121Person1.gain_cap
definition income_excluded_from_gross_income equals
if income_excluded_from_gross_income_uncapped >=$ gain_cap then
definition income_excluded_from_gross_income equals
if income_excluded_from_gross_income_uncapped >=$ gain_cap then
gain_cap
else
else
income_excluded_from_gross_income_uncapped
*/
```
@(2) Special rules for joint returns@
#### [(2) Special rules for joint returns]
In the case of a husband and wife who make a joint return for the taxable year
In the case of a husband and wife who make a joint return for the taxable year
of the sale or exchange of the property—
/*
```catala
# Taxable year of the sale or exchange ?=? year when the income is taxed
# Imagine a couple selling the house in 2020 and getting the payment in
# 2021 where they file a joint return. Does (A) apply or not ?
# Imagine a couple selling the house in 2020 and getting the payment in
# 2021 where they file a joint return. Does (A) apply or not ?
# Reasonably it should.
*/
```
@(A) $500,000 Limitation for certain joint returns@
#### [(A) $500,000 Limitation for certain joint returns]
Paragraph (1) shall be applied by substituting “$500,000” for “$250,000” if—
(i) either spouse meets the ownership requirements of subsection (a) with
respect to such property;
(ii) both spouses meet the use requirements of subsection (a) with respect to
(ii) both spouses meet the use requirements of subsection (a) with respect to
such property; and
(iii) neither spouse is ineligible for the benefits of subsection (a) with
(iii) neither spouse is ineligible for the benefits of subsection (a) with
respect to such property by reason of paragraph (3).
/*
```catala
scope Section121TwoPersons:
rule section_121_b_2_A_condition under condition
rule section_121_b_2_A_condition under condition
(return_type with pattern JointReturn of data_couple)
and
# i)
(section121Person1.requirements_ownership_met or
section121Person2.requirements_ownership_met)
and
# ii)
(section121Person1.requirements_usage_met and
# i)
(section121Person1.requirements_ownership_met or
section121Person2.requirements_ownership_met)
and
# ii)
(section121Person1.requirements_usage_met and
section121Person2.requirements_usage_met)
# iii)
and
(not (section121Person1.section_121_b_3_applies))
and
(not (section121Person2.section_121_b_3_applies))
and
(not (section121Person2.section_121_b_3_applies))
consequence fulfilled
exception
rule section121a_requirements_met under condition
section_121_b_2_A_condition
rule section121a_requirements_met under condition
section_121_b_2_A_condition
consequence fulfilled
exception
definition gain_cap under condition
exception
definition gain_cap under condition
section_121_b_2_A_condition
consequence equals $500,000
*/
```
@(B) Other joint returns@
If such spouses do not meet the requirements of subparagraph (A), the limitation
under paragraph (1) shall be the sum of the limitations under paragraph (1) to
which each spouse would be entitled if such spouses had not been married. For
purposes of the preceding sentence, each spouse shall be treated as owning the
#### [(B) Other joint returns]
If such spouses do not meet the requirements of subparagraph (A), the limitation
under paragraph (1) shall be the sum of the limitations under paragraph (1) to
which each spouse would be entitled if such spouses had not been married. For
purposes of the preceding sentence, each spouse shall be treated as owning the
property during the period that either spouse owned the property.
/*
scope Section121TwoPasses under condition
(return_type with pattern JointReturn) and
```catala
scope Section121TwoPasses under condition
(return_type with pattern JointReturn) and
not (first_pass.section_121_b_2_A_condition):
definition second_pass.gain_cap equals
first_pass.gain_cap_person_1 +$
definition second_pass.gain_cap equals
first_pass.gain_cap_person_1 +$
first_pass.gain_cap_person_2
definition period_merge.periods1 equals match return_type with pattern
definition period_merge.periods1 equals match return_type with pattern
-- JointReturn of joint_return: joint_return.person1.property_ownage
-- SingleReturnSurvivingSpouse of dead_spouse_info : [] # does not happen
-- SingleReturn of return : [] # does not happen
definition period_merge.periods2 equals match return_type with pattern
definition period_merge.periods2 equals match return_type with pattern
-- JointReturn of joint_return: joint_return.person2.property_ownage
-- SingleReturnSurvivingSpouse of dead_spouse_info : [] # does not happen
-- SingleReturn of return : [] # does not happen
definition second_pass.person1 equals PersonalData {
-- property_ownage: period_merge.output
-- property_usage_as_principal_residence:
-- property_usage_as_principal_residence:
first_pass.person1.property_usage_as_principal_residence
-- other_section_121a_sale: first_pass.person1.other_section_121a_sale
}
definition second_pass.person2 equals PersonalData {
-- property_ownage: period_merge.output
-- property_usage_as_principal_residence:
-- property_usage_as_principal_residence:
first_pass.person2.property_usage_as_principal_residence
-- other_section_121a_sale: first_pass.person2.other_section_121a_sale
}
*/
@(3) Application to only 1 sale or exchange every 2 years@
```
#### [(3) Application to only 1 sale or exchange every 2 years]
Subsection (a) shall not apply to any sale or exchange by the taxpayer if,
during the 2-year period ending on the date of such sale or exchange, there
Subsection (a) shall not apply to any sale or exchange by the taxpayer if,
during the 2-year period ending on the date of such sale or exchange, there
was any other sale or exchange by the taxpayer to which subsection (a) applied.
/*
scope Section121SinglePerson:
rule section_121_b_3_applies under condition
(other_section_121a_sale with pattern
```catala
scope Section121SinglePerson:
rule section_121_b_3_applies under condition
(other_section_121a_sale with pattern
MostRecentSaleWhereSection121aApplied of other_sale) and
date_of_sale_or_exchange -@ other_sale.date_of_sale_or_exchange <=^ 2 year
consequence fulfilled
exception
definition income_excluded_from_gross_income_uncapped under condition
exception
definition income_excluded_from_gross_income_uncapped under condition
section_121_b_3_applies
consequence equals $0
*/
consequence equals $0
```
@(4) Special rule for certain sales by surviving spouses@
#### [(4) Special rule for certain sales by surviving spouses]
/*
# Sarah: the year when your spouse dies, do you file a joint return or
```catala
# Sarah: the year when your spouse dies, do you file a joint return or
# separate returns?
*/
In the case of a sale or exchange of property by an unmarried individual whose
spouse is deceased on the date of such sale, paragraph (1) shall be applied by
substituting “$500,000” for “$250,000” if such sale occurs not later than 2
years after the date of death of such spouse and the requirements of paragraph
```
In the case of a sale or exchange of property by an unmarried individual whose
spouse is deceased on the date of such sale, paragraph (1) shall be applied by
substituting “$500,000” for “$250,000” if such sale occurs not later than 2
years after the date of death of such spouse and the requirements of paragraph
(2)(A) were met immediately before such date of death.
/*
scope Section121TwoPasses under condition
return_type with pattern SingleReturnSurvivingSpouse of single_data and
```catala
scope Section121TwoPasses under condition
return_type with pattern SingleReturnSurvivingSpouse of single_data and
single_data.date_of_spouse_death <@ date_of_sale_or_exchange and
date_of_sale_or_exchange <=@ single_data.date_of_spouse_death +@ 2 year
date_of_sale_or_exchange <=@ single_data.date_of_spouse_death +@ 2 year
:
definition first_pass.date_of_sale_or_exchange equals
definition first_pass.date_of_sale_or_exchange equals
match return_type with pattern
-- SingleReturnSurvivingSpouse of single_data: single_data.date_of_spouse_death
-- SingleReturn of return: date_of_sale_or_exchange # does not happen
-- JointReturn of return: date_of_sale_or_exchange # does not happen
definition first_pass.return_type equals
match return_type with pattern
-- SingleReturnSurvivingSpouse of single_data:
match return_type with pattern
-- SingleReturnSurvivingSpouse of single_data:
JointReturn content (JointReturn {
-- person1: single_data.return
-- person2: single_data.death_spouse_info_at_time_of_death
})
-- SingleReturn of return: SingleReturn content return # does not happen
-- JointReturn of return: JointReturn content return # does not happen
definition second_pass.gain_cap under condition
definition second_pass.gain_cap under condition
first_pass.section_121_b_2_A_condition
consequence equals $500,000
*/
```
@@(5) Exclusion of gain allocated to nonqualified use@@++
#### (5) Exclusion of gain allocated to nonqualified use
@(A) In general@
##### [(A) In general]
Subsection (a) shall not apply to so much of the gain from the sale or exchange
Subsection (a) shall not apply to so much of the gain from the sale or exchange
of property as is allocated to periods of nonqualified use.
@(B) Gain allocated to periods of nonqualified use@
##### [(B) Gain allocated to periods of nonqualified use]
For purposes of subparagraph (A), gain shall be allocated to periods of
For purposes of subparagraph (A), gain shall be allocated to periods of
nonqualified use based on the ratio which—
(i) the aggregate periods of nonqualified use during the period such property
(i) the aggregate periods of nonqualified use during the period such property
was owned by the taxpayer, bears to
(ii) the period such property was owned by the taxpayer.
@@(C) Period of nonqualified use@@+++
##### (C) Period of nonqualified use
For purposes of this paragraph—
@(i) In general@
###### [(i) In general]
The term “period of nonqualified use” means any period (other than the portion
of any period preceding January 1, 2009) during which the property is not used
as the principal residence of the taxpayer or the taxpayers spouse or former
The term “period of nonqualified use” means any period (other than the portion
of any period preceding January 1, 2009) during which the property is not used
as the principal residence of the taxpayer or the taxpayers spouse or former
spouse.
@(ii) Exceptions@
###### [(ii) Exceptions]
The term “period of nonqualified use” does not include—
(I) any portion of the 5-year period described in subsection (a) which is after
the last date that such property is used as the principal residence of the
(I) any portion of the 5-year period described in subsection (a) which is after
the last date that such property is used as the principal residence of the
taxpayer or the taxpayers spouse,
(II) any period (not to exceed an aggregate period of 10 years) during which the
taxpayer or the taxpayers spouse is serving on qualified official extended duty
(as defined in subsection (d)(9)(C)) described in clause (i), (ii), or (iii) of
(II) any period (not to exceed an aggregate period of 10 years) during which the
taxpayer or the taxpayers spouse is serving on qualified official extended duty
(as defined in subsection (d)(9)(C)) described in clause (i), (ii), or (iii) of
subsection (d)(9)(A), and
(III) any other period of temporary absence (not to exceed an aggregate period
of 2 years) due to change of employment, health conditions, or such other
(III) any other period of temporary absence (not to exceed an aggregate period
of 2 years) due to change of employment, health conditions, or such other
unforeseen circumstances as may be specified by the Secretary.
@(D) Coordination with recognition of gain attributable to depreciation@
###### [(D) Coordination with recognition of gain attributable to depreciation]
For purposes of this paragraph—
(i) subparagraph (A) shall be applied after the application of subsection
(i) subparagraph (A) shall be applied after the application of subsection
(d)(6), and
(ii) subparagraph (B) shall be applied without regard to any gain to which
(ii) subparagraph (B) shall be applied without regard to any gain to which
subsection (d)(6) applies.

View File

@ -1,7 +1,7 @@
@@Section 132@@
## Section 132
@@Begin metadata@@
/*
> Begin metadata
```catala
# We only formalize part (c) here
declaration enumeration DiscountType:
-- Property
@ -19,25 +19,27 @@ declaration scope QualifiedEmployeeDiscount:
context is_services content boolean
scope QualifiedEmployeeDiscount:
definition is_property equals match discount_type with pattern
-- Property: true
definition is_property equals match discount_type with pattern
-- Property: true
-- Services: false
definition is_services equals match discount_type with pattern
-- Property: false
-- Property: false
-- Services: true
*/
@@End metadata@@
```
> End metadata
@@(c) Qualified employee discount defined@@+
### (c) Qualified employee discount defined
For purposes of this section—
@(1) Qualified employee discount@
The term “qualified employee discount” means any employee discount with respect
#### [(1) Qualified employee discount]
The term “qualified employee discount” means any employee discount with respect
to qualified property or services to the extent such discount does not exceed—
(A) in the case of property, the gross profit percentage of the price at which
(A) in the case of property, the gross profit percentage of the price at which
the property is being offered by the employer to customers, or
/*
```catala
scope QualifiedEmployeeDiscount :
definition qualified_employee_discount
under condition is_property consequence
@ -46,10 +48,12 @@ scope QualifiedEmployeeDiscount :
customer_price *$ gross_profit_percentage
then customer_price *$ gross_profit_percentage
else employee_discount
*/
(B) in the case of services, 20 percent of the price at which the services are
```
(B) in the case of services, 20 percent of the price at which the services are
being offered by the employer to customers.
/*
```catala
scope QualifiedEmployeeDiscount :
definition qualified_employee_discount
under condition is_services consequence
@ -64,57 +68,69 @@ scope QualifiedEmployeeDiscount under condition is_services:
# We provide a default value here so that the computations run smooth.
definition aggregate_cost equals $0
definition gross_profit_percentage equals 0%
*/
@@(2) Gross profit percentage@@++
```
#### (2) Gross profit percentage
##### [(A) In general]
@(A) In general@
The term “gross profit percentage” means the percent which—
(i) the excess of the aggregate sales price of property sold by the employer
(i) the excess of the aggregate sales price of property sold by the employer
to customers over the aggregate cost of such property to the employer, is of
(ii) the aggregate sale price of such property.
/*
```catala
scope QualifiedEmployeeDiscount under condition is_property:
assertion customer_price >=$ aggregate_cost
definition gross_profit_percentage equals
(customer_price -$ aggregate_cost) /$ customer_price
*/
@(B) Determination of gross profit percentage@
```
##### [(B) Determination of gross profit percentage]
Gross profit percentage shall be determined on the basis of—
(i) all property offered to customers in the ordinary course of the line of
business of the employer in which the employee is performing services (or a
(i) all property offered to customers in the ordinary course of the line of
business of the employer in which the employee is performing services (or a
reasonable classification of property selected by the employer), and
(ii) the employers experience during a representative period.
/*
```catala
# (i) and (ii) are subjective criteria for determining the gross profit
# percentage ; we do not formalize them
*/
@(3) Employee discount defined@
```
##### [(3) Employee discount defined]
The term “employee discount” means the amount by which—
(A) the price at which the property or services are provided by the employer to
(A) the price at which the property or services are provided by the employer to
an employee for use by such employee, is less than
(B) the price at which such property or services are being offered by the
(B) the price at which such property or services are being offered by the
employer to customers.
/*
```catala
scope QualifiedEmployeeDiscount:
assertion customer_price >=$ employee_price
definition employee_discount equals
customer_price -$ employee_price
*/
@(4) Qualified property or services@
The term “qualified property or services” means any property (other than real
property and other than personal property of a kind held for investment) or
services which are offered for sale to customers in the ordinary course of
the line of business of the employer in which the employee is performing
```
##### [(4) Qualified property or services]
The term “qualified property or services” means any property (other than real
property and other than personal property of a kind held for investment) or
services which are offered for sale to customers in the ordinary course of
the line of business of the employer in which the employee is performing
services.
/*
```catala
# Again, this is for subjectively determining what item qualifies for a
# discount, not formalizing
*/
```

View File

@ -1,17 +1,17 @@
@@Include: ../section_121.catala_en@@
> Include: ../section_121.catala_en
@Testing paragraph (a)@
## [Testing paragraph (a)]
/*
```catala
declaration scope Data:
context period_four_years_recent content Period
context period_one_year_recent content Period
context period_four_years_recent content Period
context period_one_year_recent content Period
context period_two_years_middle content Period
context date_of_sale_or_exchange content date
context gain_from_sale_or_exchange_of_property content money
context return_date content date
context person_ok_1 content PersonalData
context person_ok_2 content PersonalData
context person_ok_1 content PersonalData
context person_ok_2 content PersonalData
context person_ko_1 content PersonalData
context person_ko_2 content PersonalData
@ -38,7 +38,7 @@ scope Data:
}
definition person_ok_2 equals PersonalData {
-- property_ownage: [period_four_years_recent]
-- property_usage_as_principal_residence:
-- property_usage_as_principal_residence:
[period_two_years_middle; period_one_year_recent]
-- other_section_121a_sale: NoOtherSaleWhereSection121aApplied
}
@ -53,9 +53,9 @@ scope Data:
-- property_usage_as_principal_residence: [period_two_years_middle]
-- other_section_121a_sale: NoOtherSaleWhereSection121aApplied
}
####################### Testing Section121SinglePerson #########################
@ -65,7 +65,7 @@ declaration scope Test1:
scope Test1:
definition scope121a.date_of_sale_or_exchange equals data_.date_of_sale_or_exchange
definition scope121a.gain_from_sale_or_exchange_of_property equals
definition scope121a.gain_from_sale_or_exchange_of_property equals
data_.gain_from_sale_or_exchange_of_property
definition scope121a.property_ownage equals [data_.period_four_years_recent]
definition scope121a.property_usage_as_principal_residence equals
@ -79,10 +79,10 @@ declaration scope Test2:
scope Test2:
definition scope121a.date_of_sale_or_exchange equals data_.date_of_sale_or_exchange
definition scope121a.gain_from_sale_or_exchange_of_property equals
definition scope121a.gain_from_sale_or_exchange_of_property equals
data_.gain_from_sale_or_exchange_of_property
definition scope121a.property_ownage equals [data_.period_four_years_recent]
definition scope121a.property_usage_as_principal_residence equals
definition scope121a.property_usage_as_principal_residence equals
[data_.period_one_year_recent]
definition scope121a.other_section_121a_sale equals NoOtherSaleWhereSection121aApplied
assertion not scope121a.requirements_met
@ -93,10 +93,10 @@ declaration scope Test3:
scope Test3:
definition scope121a.date_of_sale_or_exchange equals data_.date_of_sale_or_exchange
definition scope121a.gain_from_sale_or_exchange_of_property equals
definition scope121a.gain_from_sale_or_exchange_of_property equals
data_.gain_from_sale_or_exchange_of_property
definition scope121a.property_ownage equals [data_.period_four_years_recent]
definition scope121a.property_usage_as_principal_residence equals
definition scope121a.property_usage_as_principal_residence equals
[data_.period_two_years_middle]
definition scope121a.other_section_121a_sale equals NoOtherSaleWhereSection121aApplied
assertion not scope121a.requirements_met
@ -107,10 +107,10 @@ declaration scope Test4:
scope Test4:
definition scope121a.date_of_sale_or_exchange equals data_.date_of_sale_or_exchange
definition scope121a.gain_from_sale_or_exchange_of_property equals
definition scope121a.gain_from_sale_or_exchange_of_property equals
data_.gain_from_sale_or_exchange_of_property
definition scope121a.property_ownage equals [data_.period_four_years_recent]
definition scope121a.property_usage_as_principal_residence equals
definition scope121a.property_usage_as_principal_residence equals
[data_.period_two_years_middle; data_.period_one_year_recent]
definition scope121a.other_section_121a_sale equals NoOtherSaleWhereSection121aApplied
assertion scope121a.requirements_met
@ -121,10 +121,10 @@ declaration scope Test5:
context scope121 scope Section121TwoPersons
context data_ scope Data
scope Test5:
scope Test5:
definition scope121.date_of_sale_or_exchange equals data_.date_of_sale_or_exchange
definition scope121.return_date equals data_.return_date
definition scope121.gain_from_sale_or_exchange_of_property equals
definition scope121.gain_from_sale_or_exchange_of_property equals
data_.gain_from_sale_or_exchange_of_property
definition scope121.return_type equals SingleReturn content data_.person_ok_1
assertion scope121.income_excluded_from_gross_income = $250,000
@ -133,14 +133,14 @@ declaration scope Test6:
context scope121 scope Section121TwoPersons
context data_ scope Data
scope Test6:
scope Test6:
definition scope121.date_of_sale_or_exchange equals data_.date_of_sale_or_exchange
definition scope121.return_date equals data_.return_date
definition scope121.gain_from_sale_or_exchange_of_property equals
definition scope121.gain_from_sale_or_exchange_of_property equals
data_.gain_from_sale_or_exchange_of_property
definition scope121.return_type equals JointReturn content (JointReturn {
-- person1: data_.person_ok_1
-- person2: data_.person_ok_2
})
assertion scope121.income_excluded_from_gross_income = $350,000
*/
```

View File

@ -1,9 +1,10 @@
@@Include: ../section_132.catala_en@@
> Include: ../section_132.catala_en
@Test@
/*
### [Test]
```catala
declaration scope TestSection132_1:
context section_132 scope QualifiedEmployeeDiscount
context section_132 scope QualifiedEmployeeDiscount
scope TestSection132_1:
definition section_132.customer_price equals $1500
@ -13,11 +14,11 @@ scope TestSection132_1:
assertion section_132.employee_discount = $500
assertion section_132.gross_profit_percentage = 0.4
assertion section_132.qualified_employee_discount = $500
*/
```
/*
```catala
declaration scope TestSection132_2:
context section_132 scope QualifiedEmployeeDiscount
context section_132 scope QualifiedEmployeeDiscount
scope TestSection132_2:
definition section_132.customer_price equals $1500
@ -27,11 +28,11 @@ scope TestSection132_2:
assertion section_132.employee_discount = $500
assertion section_132.gross_profit_percentage = 0.2
assertion section_132.qualified_employee_discount = $300.00
*/
```
/*
```catala
declaration scope TestSection132_3:
context section_132 scope QualifiedEmployeeDiscount
context section_132 scope QualifiedEmployeeDiscount
scope TestSection132_3:
definition section_132.customer_price equals $1500
@ -39,4 +40,4 @@ scope TestSection132_3:
definition section_132.discount_type equals Services
assertion section_132.employee_discount = $500
assertion section_132.qualified_employee_discount = $300
*/
```

View File

@ -1,9 +1,9 @@
@@Master file@@
# Master file
@@Include: preamble.catala_en@@
> Include: preamble.catala_en
@@Include: section_121.catala_en@@
> Include: section_121.catala_en
@@Include: section_132.catala_en@@
> Include: section_132.catala_en
@@Include: section_1015.catala_en@@
> Include: section_1015.catala_en

View File

@ -151,7 +151,7 @@ let law_article_item_to_html (language : C.backend_lang) (fmt : Format.formatter
let pprinted_c = R.substitute ~rex:syms ~subst:syms_subst (Pos.unmark c) in
Format.fprintf fmt "<div class='code-wrapper'>\n<div class='filename'>%s</div>\n%s\n</div>"
(Pos.get_file (Pos.get_position c))
(pygmentize_code (Pos.same_pos_as ("/*" ^ pprinted_c ^ "*/") c) language)
(pygmentize_code (Pos.same_pos_as ("```catala" ^ pprinted_c ^ "```") c) language)
let rec law_structure_to_html (language : C.backend_lang) (fmt : Format.formatter)
(i : A.law_structure) : unit =

View File

@ -59,6 +59,8 @@ let wrap_latex (source_files : string list) (language : C.backend_lang) (fmt : F
\\newunicodechar{}{$\\geqslant$}\n\
\\newunicodechar{}{$\\rightarrow$}\n\
\\newunicodechar{}{$\\neq$}\n\n\
\\newcommand*\\FancyVerbStartString{```catala}\n\
\\newcommand*\\FancyVerbStopString{```}\n\n\
\\fvset{\n\
numbers=left,\n\
frame=lines,\n\
@ -129,7 +131,7 @@ let law_article_item_to_latex (language : C.backend_lang) (fmt : Format.formatte
| A.CodeBlock (_, c) ->
Format.fprintf fmt
"\\begin{minted}[label={\\hspace*{\\fill}\\texttt{%s}},firstnumber=%d]{%s}\n\
/*%s*/\n\
```catala%s```\n\
\\end{minted}"
(pre_latexify (Filename.basename (Pos.get_file (Pos.get_position c))))
(Pos.get_start_line (Pos.get_position c) - 1)
@ -173,7 +175,7 @@ let rec law_structure_to_latex (language : C.backend_lang) (fmt : Format.formatt
title=\\textcolor{black}{\\texttt{%s}},title after \
break=\\textcolor{black}{\\texttt{%s}},before skip=1em, after skip=1em]\n\
\\begin{minted}[numbersep=9mm, firstnumber=%d, label={\\hspace*{\\fill}\\texttt{%s}}]{%s}\n\
/*%s*/\n\
```catala%s```\n\
\\end{minted}\n\
\\end{tcolorbox}"
metadata_title metadata_title

View File

@ -113,7 +113,7 @@ val no_input : unit -> 'a
(**{1 Operators} *)
(**{ 2 Money} *)
(**{2 Money} *)
val ( *$ ) : money -> decimal -> money

View File

@ -511,6 +511,7 @@ type law_article = {
law_article_name : (string[@opaque]) Pos.marked;
law_article_id : (string[@opaque]) option;
law_article_expiration_date : (string[@opaque]) option;
law_article_precedence : (int[@opaque]);
}
[@@deriving
visitors { variety = "map"; ancestors = [ "Pos.marked_map" ]; name = "law_article_map" },

View File

@ -227,6 +227,7 @@ type law_article = {
law_article_name : (string[@opaque]) Pos.marked;
law_article_id : (string[@opaque]) option;
law_article_expiration_date : (string[@opaque]) option;
law_article_precedence : (int[@opaque]);
}
type law_include =

View File

@ -17,6 +17,7 @@
open Parser
open Sedlexing
open Utils
open Lexer_common
module R = Re.Pcre
(** Boolean reference, used by the lexer as the mutable state to distinguish whether it is lexing
@ -142,7 +143,7 @@ let rec lex_code (lexbuf : lexbuf) : token =
(* Comments *)
update_acc lexbuf;
lex_code lexbuf
| "*/" ->
| "```" ->
(* End of code section *)
is_code := false;
END_CODE !code_string_acc
@ -535,24 +536,24 @@ let lex_law (lexbuf : lexbuf) : token =
let prev_lexeme = Utf8.lexeme lexbuf in
let prev_pos = lexing_positions lexbuf in
match%sedlex lexbuf with
| "/*" ->
| "```catala" ->
is_code := true;
code_string_acc := "";
BEGIN_CODE
| eof -> EOF
| "@@", Star white_space, "Master file", Star white_space, "@@" -> MASTER_FILE
| "@@", Star white_space, "Begin metadata", Star white_space, "@@" -> BEGIN_METADATA
| "@@", Star white_space, "End metadata", Star white_space, "@@" -> END_METADATA
| ( "@@",
| '#', Star white_space, "Master file" -> MASTER_FILE
| '>', Star white_space, "Begin metadata" -> BEGIN_METADATA
| '>', Star white_space, "End metadata" -> END_METADATA
| ( '>',
Star white_space,
"Include:",
Star white_space,
Plus (Compl '@'),
Plus (Compl ('@' | '\n')),
Star white_space,
Opt ('@', Star white_space, "p.", Star white_space, Plus '0' .. '9', Star white_space),
"@@" ) ->
'\n' ) ->
let extract_components =
R.regexp "@@\\s*Include\\:\\s*([^@]+)\\s*(@\\s*p\\.\\s*([0-9]+)|)@@"
R.regexp ">\\s*Include\\:\\s*([^@\\n]+)\\s*(@\\s*p\\.\\s*([0-9]+)|)"
in
let get_component = R.get_substring (R.exec ~rex:extract_components (Utf8.lexeme lexbuf)) in
let name = get_component 1 in
@ -561,23 +562,22 @@ let lex_law (lexbuf : lexbuf) : token =
if Filename.extension name = ".pdf" then
LAW_INCLUDE (Ast.PdfFile ((name, Pos.from_lpos pos), pages))
else LAW_INCLUDE (Ast.CatalaFile (name, Pos.from_lpos pos))
| "@@", Plus (Compl '@'), "@@", Star '+' ->
let extract_code_title = R.regexp "@@([^@]+)@@([\\+]*)" in
let get_match = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in
let get_new_lines = R.regexp "\n" in
let new_lines_count =
try Array.length (R.extract ~rex:get_new_lines (Utf8.lexeme lexbuf)) with Not_found -> 0
| '#', Plus '#', Star white_space, Plus (Compl ('[' | ']' | '\n')), Star white_space, '\n' ->
get_law_heading lexbuf
| ( '#',
Plus '#',
Star white_space,
'[',
Star white_space,
Plus (Compl ']'),
Star white_space,
']',
'\n' ) ->
let extract_article_title = R.regexp "([#]+)\\s*\\[([^@]+)\\]" in
let get_substring =
R.get_substring (R.exec ~rex:extract_article_title (Utf8.lexeme lexbuf))
in
for _i = 1 to new_lines_count do
new_line lexbuf
done;
let law_title = get_match 1 in
let precedence = String.length (get_match 2) in
LAW_HEADING (law_title, precedence)
| "@", Plus (Compl '@'), "@" ->
let extract_article_title = R.regexp "@([^@]+)@" in
let title = R.get_substring (R.exec ~rex:extract_article_title (Utf8.lexeme lexbuf)) 1 in
let title = get_substring 2 in
let get_new_lines = R.regexp "\n" in
let new_lines_count =
try Array.length (R.extract ~rex:get_new_lines (Utf8.lexeme lexbuf)) with Not_found -> 0
@ -586,11 +586,12 @@ let lex_law (lexbuf : lexbuf) : token =
for _i = 1 to new_lines_count - 1 do
new_line lexbuf
done;
let precedence = calc_precedence (get_substring 1) in
LAW_ARTICLE (title, None, None)
| Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf)
LAW_ARTICLE (title, None, None, precedence)
| Plus (Compl ('/' | '#' | '`' | '>')) -> LAW_TEXT (Utf8.lexeme lexbuf)
| _ -> raise_lexer_error (Pos.from_lpos prev_pos) prev_lexeme
(** Entry point of the lexer, distributes to {!val: lex_code} or {!val: lex_law} depending of {!val:
is_code}. *)
let lexer lexbuf = if !is_code then lex_code lexbuf else lex_law lexbuf
let lexer (lexbuf : lexbuf) : token = if !is_code then lex_code lexbuf else lex_law lexbuf

View File

@ -0,0 +1,39 @@
(* This file is part of the Catala compiler, a specification language for tax and social benefits
computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux
<denis.merigoux@inria.fr>
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the License for the specific language governing permissions and limitations under
the License. *)
open Parser
open Sedlexing
module R = Re.Pcre
(* Calculates the precedence according a {!val: matched_regex} of the form : '[#]+'.
@note -2 because both [LAW_ARTICLE] and [LAW_HEADING] start with at least "##" and the number of
'#' remaining corresponds to the precedence. *)
let calc_precedence (matched_regex : string) : int = String.length matched_regex - 2
(* Gets the [LAW_HEADING] token from the current {!val: lexbuf} *)
let get_law_heading (lexbuf : lexbuf) : token =
let extract_code_title = R.regexp "([#]+)\\s*([^#\n]+)\n" in
let get_match = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in
let get_new_lines = R.regexp "\n" in
let new_lines_count =
try Array.length (R.extract ~rex:get_new_lines (Utf8.lexeme lexbuf)) with Not_found -> 0
in
for _i = 1 to new_lines_count do
new_line lexbuf
done;
let law_title = get_match 2 in
let precedence = calc_precedence (get_match 1) in
LAW_HEADING (law_title, precedence)

View File

@ -0,0 +1,19 @@
(* This file is part of the Catala compiler, a specification language for tax and social benefits
computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux
<denis.merigoux@inria.fr>
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the License for the specific language governing permissions and limitations under
the License. *)
val calc_precedence : string -> int
(** Calculates the precedence according a matched regex of the form : '[#]+' *)
val get_law_heading : Sedlexing.lexbuf -> Parser.token
(** Gets the [LAW_HEADING] token from the current [lexbuf] *)

View File

@ -15,6 +15,7 @@
open Parser
open Sedlexing
open Utils
open Lexer_common
module L = Lexer
module R = Re.Pcre
@ -96,7 +97,7 @@ let rec lex_code_en (lexbuf : lexbuf) : token =
(* Comments *)
L.update_acc lexbuf;
lex_code_en lexbuf
| "*/" ->
| "```" ->
(* End of code section *)
L.is_code := false;
END_CODE !L.code_string_acc
@ -489,24 +490,25 @@ let lex_law_en (lexbuf : lexbuf) : token =
let prev_lexeme = Utf8.lexeme lexbuf in
let prev_pos = lexing_positions lexbuf in
match%sedlex lexbuf with
| "/*" ->
| "```catala" ->
L.is_code := true;
L.code_string_acc := "";
BEGIN_CODE
| eof -> EOF
| "@@", Star white_space, "Master file", Star white_space, "@@" -> MASTER_FILE
| "@@", Star white_space, "Begin metadata", Star white_space, "@@" -> BEGIN_METADATA
| "@@", Star white_space, "End metadata", Star white_space, "@@" -> END_METADATA
| ( "@@",
| '#', Star white_space, "Master file" -> MASTER_FILE
| '>', Star white_space, "Begin metadata" -> BEGIN_METADATA
| '>', Star white_space, "End metadata" -> END_METADATA
| ( '>',
Star white_space,
"Include:",
Star white_space,
Plus (Compl '@'),
Plus (Compl ('@' | '\n')),
Star white_space,
Opt ('@', Star white_space, "p.", Star white_space, Plus '0' .. '9', Star white_space),
"@@" ) ->
'\n' ) ->
let extract_components =
R.regexp "@@\\s*Include\\:\\s*([^@]+)\\s*(@\\s*p\\.\\s*([0-9]+)|)@@"
R.regexp ">\\s*Include\\:\\s*([^@\\n]+)\\s*(@\\s*p\\.\\s*([0-9]+)|)"
in
let get_component = R.get_substring (R.exec ~rex:extract_components (Utf8.lexeme lexbuf)) in
let name = get_component 1 in
@ -515,23 +517,22 @@ let lex_law_en (lexbuf : lexbuf) : token =
if Filename.extension name = ".pdf" then
LAW_INCLUDE (Ast.PdfFile ((name, Pos.from_lpos pos), pages))
else LAW_INCLUDE (Ast.CatalaFile (name, Pos.from_lpos pos))
| "@@", Plus (Compl '@'), "@@", Star '+' ->
let extract_code_title = R.regexp "@@([^@]+)@@([\\+]*)" in
let get_match = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in
let get_new_lines = R.regexp "\n" in
let new_lines_count =
try Array.length (R.extract ~rex:get_new_lines (Utf8.lexeme lexbuf)) with Not_found -> 0
| '#', Plus '#', Star white_space, Plus (Compl ('[' | ']' | '\n')), Star white_space, '\n' ->
get_law_heading lexbuf
| ( '#',
Plus '#',
Star white_space,
'[',
Star white_space,
Plus (Compl ']'),
Star white_space,
']',
'\n' ) ->
let extract_article_title = R.regexp "([#]+)\\s*\\[([^\\]]+)\\]" in
let get_substring =
R.get_substring (R.exec ~rex:extract_article_title (Utf8.lexeme lexbuf))
in
for _i = 1 to new_lines_count do
new_line lexbuf
done;
let law_title = get_match 1 in
let precedence = String.length (get_match 2) in
LAW_HEADING (law_title, precedence)
| "@", Plus (Compl '@'), "@" ->
let extract_article_title = R.regexp "@([^@]+)@" in
let title = R.get_substring (R.exec ~rex:extract_article_title (Utf8.lexeme lexbuf)) 1 in
let title = get_substring 2 in
let get_new_lines = R.regexp "\n" in
let new_lines_count =
try Array.length (R.extract ~rex:get_new_lines (Utf8.lexeme lexbuf)) with Not_found -> 0
@ -540,9 +541,13 @@ let lex_law_en (lexbuf : lexbuf) : token =
for _i = 1 to new_lines_count - 1 do
new_line lexbuf
done;
let precedence = calc_precedence (get_substring 1) in
LAW_ARTICLE (title, None, None)
| Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf)
LAW_ARTICLE (title, None, None, precedence)
| Plus (Compl ('/' | '#' | '`' | '>')) -> LAW_TEXT (Utf8.lexeme lexbuf)
| _ -> L.raise_lexer_error (Pos.from_lpos prev_pos) prev_lexeme
let lexer_en lexbuf = if !L.is_code then lex_code_en lexbuf else lex_law_en lexbuf
(** Entry point of the lexer, distributes to {!val: lex_code_en} or {!val: lex_law_en} depending of
{!val: Surface.Lexer.is_code}. *)
let lexer_en (lexbuf : lexbuf) : token =
if !L.is_code then lex_code_en lexbuf else lex_law_en lexbuf

View File

@ -15,6 +15,7 @@
open Parser
open Sedlexing
open Utils
open Lexer_common
module L = Lexer
module R = Re.Pcre
@ -94,7 +95,7 @@ let rec lex_code_fr (lexbuf : lexbuf) : token =
(* Comments *)
L.update_acc lexbuf;
lex_code_fr lexbuf
| "*/" ->
| "```" ->
(* End of code section *)
L.is_code := false;
END_CODE !L.code_string_acc
@ -496,29 +497,27 @@ let lex_law_fr (lexbuf : lexbuf) : token =
let prev_lexeme = Utf8.lexeme lexbuf in
let prev_pos = lexing_positions lexbuf in
match%sedlex lexbuf with
| "/*" ->
| "```catala" ->
L.is_code := true;
L.code_string_acc := "";
BEGIN_CODE
| eof -> EOF
| "@@", Star white_space, "Fichier ma", 0x00EE, "tre", Star white_space, "@@" ->
| '#', Star white_space, "Fichier ma", 0x00EE, "tre" ->
(* 0x00EE is î *)
MASTER_FILE
| "@@", Star white_space, "D", 0xE9, "but m", 0xE9, "tadonn", 0xE9, "es", Star white_space, "@@"
->
BEGIN_METADATA
| "@@", Star white_space, "Fin m", 0xE9, "tadonn", 0xE9, "es", Star white_space, "@@" ->
END_METADATA
| ( "@@",
| '>', Star white_space, 'D', 0xE9, "but m", 0xE9, "tadonn", 0xE9, "es" -> BEGIN_METADATA
| '>', Star white_space, "Fin m", 0xE9, "tadonn", 0xE9, "es" -> END_METADATA
| ( '>',
Star white_space,
"Inclusion:",
Star white_space,
Plus (Compl '@'),
Plus (Compl ('@' | '\n')),
Star white_space,
Opt ('@', Star white_space, "p.", Star white_space, Plus '0' .. '9', Star white_space),
"@@" ) ->
'\n' ) ->
let extract_components =
R.regexp "@@\\s*Inclusion\\:\\s*([^@]+)\\s*(@\\s*p\\.\\s*([0-9]+)|)@@"
R.regexp ">\\s*Inclusion\\:\\s*([^@\\n]+)\\s*(@\\s*p\\.\\s*([0-9]+)|)"
in
let get_component = R.get_substring (R.exec ~rex:extract_components (Utf8.lexeme lexbuf)) in
let jorftext = R.regexp "JORFTEXT\\d{12}" in
@ -530,31 +529,26 @@ let lex_law_fr (lexbuf : lexbuf) : token =
else if Filename.extension name = ".pdf" then
LAW_INCLUDE (Ast.PdfFile ((name, Pos.from_lpos pos), pages))
else LAW_INCLUDE (Ast.CatalaFile (name, Pos.from_lpos pos))
| "@@", Plus (Compl '@'), "@@", Star '+' ->
let extract_code_title = R.regexp "@@([^@]+)@@([\\+]*)" in
let get_match = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in
let get_new_lines = R.regexp "\n" in
let new_lines_count =
try Array.length (R.extract ~rex:get_new_lines (Utf8.lexeme lexbuf)) with Not_found -> 0
in
for _i = 1 to new_lines_count do
new_line lexbuf
done;
let law_title = get_match 1 in
let precedence = String.length (get_match 2) in
LAW_HEADING (law_title, precedence)
| "@", Plus (Compl '@'), "@" ->
| ( '#',
Plus '#',
Star white_space,
'[',
Star white_space,
Plus (Compl ']'),
Star white_space,
']',
'\n' ) ->
let extract_article_title =
R.regexp
"\\@(([^\\|]+)\\|(((LEGIARTI|JORFARTI)[0-9]{12})(\\|([0-2]{2}\\/[0-2]{2}\\/[0-2]{4})|))|[^\\@]+)\\@"
"([#]+)\\s*\\[\\s*(([^\\|]+)\\|(((LEGIARTI|JORFARTI)[0-9]{12})(\\|([0-2]{2}\\/[0-2]{2}\\/[0-2]{4})|))|[^\\@]+)\\]"
in
let get_substring =
R.get_substring (R.exec ~rex:extract_article_title (Utf8.lexeme lexbuf))
in
let title = try get_substring 2 with Not_found -> get_substring 1 in
let article_id = try Some (get_substring 4) with Not_found -> None in
let article_expiration_date = try Some (get_substring 7) with Not_found -> None in
let title = try get_substring 3 with Not_found -> get_substring 2 in
let article_id = try Some (get_substring 5) with Not_found -> None in
let article_expiration_date = try Some (get_substring 8) with Not_found -> None in
let precedence = calc_precedence (get_substring 1) in
let get_new_lines = R.regexp "\n" in
let new_lines_count =
try Array.length (R.extract ~rex:get_new_lines (Utf8.lexeme lexbuf)) with Not_found -> 0
@ -564,8 +558,10 @@ let lex_law_fr (lexbuf : lexbuf) : token =
new_line lexbuf
done;
LAW_ARTICLE (title, article_id, article_expiration_date)
| Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf)
LAW_ARTICLE (title, article_id, article_expiration_date, precedence)
| '#', Plus '#', Star white_space, Plus (Compl ('[' | ']' | '\n')), Star white_space, '\n' ->
get_law_heading lexbuf
| Plus (Compl ('/' | '#' | '`' | '>')) -> LAW_TEXT (Utf8.lexeme lexbuf)
| _ -> L.raise_lexer_error (Pos.from_lpos prev_pos) prev_lexeme
(** Entry point of the lexer, distributes to {!val: lex_code_fr} or {!val: lex_law_fr} depending of

View File

@ -14,15 +14,15 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*)
*)
%{
open Ast
open Utils
%}
open Utils
%}
%token EOF
%token<string * string option * string option> LAW_ARTICLE
%token<string * string option * string option * int> LAW_ARTICLE
%token<string * int> LAW_HEADING
%token<Ast.law_include> LAW_INCLUDE
%token<string> LAW_TEXT
@ -41,7 +41,7 @@
%token LESSER_MONEY GREATER_MONEY LESSER_EQUAL_MONEY GREATER_EQUAL_MONEY
%token LESSER_DATE GREATER_DATE LESSER_EQUAL_DATE GREATER_EQUAL_DATE
%token LESSER_DURATION GREATER_DURATION LESSER_EQUAL_DURATION GREATER_EQUAL_DURATION
%token EXISTS IN SUCH THAT
%token EXISTS IN SUCH THAT
%token DOT AND OR LPAREN RPAREN EQUAL
%token CARDINAL ASSERTION FIXED BY YEAR MONTH DAY
%token PLUS MINUS MULT DIV
@ -130,280 +130,280 @@ struct_or_enum_inject:
| None -> (EnumInject(None, enum, data), Pos.from_lpos $sloc)
| Some c -> (EnumInject(Some enum, c, data), Pos.from_lpos $sloc)
}
| c = constructor fields = struct_inject_content { (StructLit(c, fields), Pos.from_lpos $sloc) }
| c = constructor fields = struct_inject_content { (StructLit(c, fields), Pos.from_lpos $sloc) }
primitive_expression:
| e = small_expression { e }
| CARDINAL {
(Builtin Cardinal, Pos.from_lpos $sloc)
}
| INT_TO_DEC {
(Builtin IntToDec, Pos.from_lpos $sloc)
}
| GET_DAY {
(Builtin GetDay, Pos.from_lpos $sloc)
}
| GET_MONTH {
(Builtin GetMonth, Pos.from_lpos $sloc)
}
| GET_YEAR {
(Builtin GetYear, Pos.from_lpos $sloc)
}
| e = struct_or_enum_inject {
e
}
| LSQUARE l = separated_list(SEMICOLON, expression) RSQUARE {
(ArrayLit l, Pos.from_lpos $sloc)
}
primitive_expression:
| e = small_expression { e }
| CARDINAL {
(Builtin Cardinal, Pos.from_lpos $sloc)
}
num_literal:
| d = INT_LITERAL { (Int d, Pos.from_lpos $sloc) }
| d = DECIMAL_LITERAL {
| INT_TO_DEC {
(Builtin IntToDec, Pos.from_lpos $sloc)
}
| GET_DAY {
(Builtin GetDay, Pos.from_lpos $sloc)
}
| GET_MONTH {
(Builtin GetMonth, Pos.from_lpos $sloc)
}
| GET_YEAR {
(Builtin GetYear, Pos.from_lpos $sloc)
}
| e = struct_or_enum_inject {
e
}
| LSQUARE l = separated_list(SEMICOLON, expression) RSQUARE {
(ArrayLit l, Pos.from_lpos $sloc)
}
num_literal:
| d = INT_LITERAL { (Int d, Pos.from_lpos $sloc) }
| d = DECIMAL_LITERAL {
let (d1, d2) = d in
(Dec (d1, d2), Pos.from_lpos $sloc)
}
}
unit_literal:
| PERCENT { (Percent, Pos.from_lpos $sloc) }
| YEAR { (Year, Pos.from_lpos $sloc)}
| MONTH { (Month, Pos.from_lpos $sloc) }
| DAY { (Day, Pos.from_lpos $sloc) }
unit_literal:
| PERCENT { (Percent, Pos.from_lpos $sloc) }
| YEAR { (Year, Pos.from_lpos $sloc)}
| MONTH { (Month, Pos.from_lpos $sloc) }
| DAY { (Day, Pos.from_lpos $sloc) }
date_int:
| d = INT_LITERAL { (Runtime.integer_to_int d, Pos.from_lpos $sloc) }
date_int:
| d = INT_LITERAL { (Runtime.integer_to_int d, Pos.from_lpos $sloc) }
literal:
| l = num_literal u = option(unit_literal) {
(LNumber (l, u), Pos.from_lpos $sloc)
}
| money = MONEY_AMOUNT {
literal:
| l = num_literal u = option(unit_literal) {
(LNumber (l, u), Pos.from_lpos $sloc)
}
| money = MONEY_AMOUNT {
let (units, cents) = money in
(LMoneyAmount {
money_amount_units = units;
money_amount_cents = cents;
}, Pos.from_lpos $sloc)
}
| VERTICAL d = date_int DIV m = date_int DIV y = date_int VERTICAL {
(LDate {
literal_date_day = (match !Utils.Cli.locale_lang with `En -> m | `Fr -> d);
}
| VERTICAL d = date_int DIV m = date_int DIV y = date_int VERTICAL {
(LDate {
literal_date_day = (match !Utils.Cli.locale_lang with `En -> m | `Fr -> d);
literal_date_month = (match !Utils.Cli.locale_lang with `En -> d | `Fr -> m);
literal_date_year = y;
}, Pos.from_lpos $sloc)
}
| TRUE { (LBool true, Pos.from_lpos $sloc) }
| FALSE { (LBool false, Pos.from_lpos $sloc) }
}
| TRUE { (LBool true, Pos.from_lpos $sloc) }
| FALSE { (LBool false, Pos.from_lpos $sloc) }
compare_op:
| LESSER { (Lt KInt, Pos.from_lpos $sloc) }
| LESSER_EQUAL { (Lte KInt, Pos.from_lpos $sloc) }
| GREATER { (Gt KInt, Pos.from_lpos $sloc) }
| GREATER_EQUAL { (Gte KInt, Pos.from_lpos $sloc) }
| LESSER_DEC { (Lt KDec, Pos.from_lpos $sloc) }
| LESSER_EQUAL_DEC { (Lte KDec, Pos.from_lpos $sloc) }
| GREATER_DEC { (Gt KDec, Pos.from_lpos $sloc) }
| GREATER_EQUAL_DEC { (Gte KDec, Pos.from_lpos $sloc) }
| LESSER_MONEY { (Lt KMoney, Pos.from_lpos $sloc) }
| LESSER_EQUAL_MONEY { (Lte KMoney, Pos.from_lpos $sloc) }
| GREATER_MONEY { (Gt KMoney, Pos.from_lpos $sloc) }
| GREATER_EQUAL_MONEY { (Gte KMoney, Pos.from_lpos $sloc) }
| LESSER_DATE { (Lt KDate, Pos.from_lpos $sloc) }
| LESSER_EQUAL_DATE { (Lte KDate, Pos.from_lpos $sloc) }
| GREATER_DATE { (Gt KDate, Pos.from_lpos $sloc) }
| GREATER_EQUAL_DATE { (Gte KDate, Pos.from_lpos $sloc) }
| LESSER_DURATION { (Lt KDuration, Pos.from_lpos $sloc) }
| LESSER_EQUAL_DURATION { (Lte KDuration, Pos.from_lpos $sloc) }
| GREATER_DURATION { (Gt KDuration, Pos.from_lpos $sloc) }
| GREATER_EQUAL_DURATION { (Gte KDuration, Pos.from_lpos $sloc) }
| EQUAL { (Eq, Pos.from_lpos $sloc) }
| NOT_EQUAL { (Neq, Pos.from_lpos $sloc) }
compare_op:
| LESSER { (Lt KInt, Pos.from_lpos $sloc) }
| LESSER_EQUAL { (Lte KInt, Pos.from_lpos $sloc) }
| GREATER { (Gt KInt, Pos.from_lpos $sloc) }
| GREATER_EQUAL { (Gte KInt, Pos.from_lpos $sloc) }
| LESSER_DEC { (Lt KDec, Pos.from_lpos $sloc) }
| LESSER_EQUAL_DEC { (Lte KDec, Pos.from_lpos $sloc) }
| GREATER_DEC { (Gt KDec, Pos.from_lpos $sloc) }
| GREATER_EQUAL_DEC { (Gte KDec, Pos.from_lpos $sloc) }
| LESSER_MONEY { (Lt KMoney, Pos.from_lpos $sloc) }
| LESSER_EQUAL_MONEY { (Lte KMoney, Pos.from_lpos $sloc) }
| GREATER_MONEY { (Gt KMoney, Pos.from_lpos $sloc) }
| GREATER_EQUAL_MONEY { (Gte KMoney, Pos.from_lpos $sloc) }
| LESSER_DATE { (Lt KDate, Pos.from_lpos $sloc) }
| LESSER_EQUAL_DATE { (Lte KDate, Pos.from_lpos $sloc) }
| GREATER_DATE { (Gt KDate, Pos.from_lpos $sloc) }
| GREATER_EQUAL_DATE { (Gte KDate, Pos.from_lpos $sloc) }
| LESSER_DURATION { (Lt KDuration, Pos.from_lpos $sloc) }
| LESSER_EQUAL_DURATION { (Lte KDuration, Pos.from_lpos $sloc) }
| GREATER_DURATION { (Gt KDuration, Pos.from_lpos $sloc) }
| GREATER_EQUAL_DURATION { (Gte KDuration, Pos.from_lpos $sloc) }
| EQUAL { (Eq, Pos.from_lpos $sloc) }
| NOT_EQUAL { (Neq, Pos.from_lpos $sloc) }
aggregate_func:
| CONTENT MAXIMUM t = typ_base INIT init = primitive_expression {
(Aggregate (AggregateArgExtremum (true, Pos.unmark t, init)), Pos.from_lpos $sloc)
}
| CONTENT MINIMUM t = typ_base INIT init = primitive_expression {
(Aggregate (AggregateArgExtremum (false, Pos.unmark t, init)), Pos.from_lpos $sloc)
}
| MAXIMUM t = typ_base INIT init = primitive_expression {
(Aggregate (AggregateExtremum (true, Pos.unmark t, init)), Pos.from_lpos $sloc)
}
| MINIMUM t = typ_base INIT init = primitive_expression {
(Aggregate (AggregateExtremum (false, Pos.unmark t, init)), Pos.from_lpos $sloc)
}
| SUM t = typ_base { (Aggregate (AggregateSum (Pos.unmark t)), Pos.from_lpos $sloc) }
| CARDINAL { (Aggregate AggregateCount, Pos.from_lpos $sloc) }
| FILTER { (Filter, Pos.from_lpos $sloc ) }
| MAP { (Map, Pos.from_lpos $sloc) }
aggregate_func:
| CONTENT MAXIMUM t = typ_base INIT init = primitive_expression {
(Aggregate (AggregateArgExtremum (true, Pos.unmark t, init)), Pos.from_lpos $sloc)
}
| CONTENT MINIMUM t = typ_base INIT init = primitive_expression {
(Aggregate (AggregateArgExtremum (false, Pos.unmark t, init)), Pos.from_lpos $sloc)
}
| MAXIMUM t = typ_base INIT init = primitive_expression {
(Aggregate (AggregateExtremum (true, Pos.unmark t, init)), Pos.from_lpos $sloc)
}
| MINIMUM t = typ_base INIT init = primitive_expression {
(Aggregate (AggregateExtremum (false, Pos.unmark t, init)), Pos.from_lpos $sloc)
}
| SUM t = typ_base { (Aggregate (AggregateSum (Pos.unmark t)), Pos.from_lpos $sloc) }
| CARDINAL { (Aggregate AggregateCount, Pos.from_lpos $sloc) }
| FILTER { (Filter, Pos.from_lpos $sloc ) }
| MAP { (Map, Pos.from_lpos $sloc) }
aggregate:
| func = aggregate_func FOR i = ident IN e1 = primitive_expression
aggregate:
| func = aggregate_func FOR i = ident IN e1 = primitive_expression
OF e2 = base_expression {
(CollectionOp (func, i, e1, e2), Pos.from_lpos $sloc)
}
(CollectionOp (func, i, e1, e2), Pos.from_lpos $sloc)
}
base_expression:
| e = primitive_expression { e }
| ag = aggregate { ag }
| e1 = primitive_expression OF e2 = base_expression {
(FunCall (e1, e2), Pos.from_lpos $sloc)
}
| e = primitive_expression WITH c = constructor_binding {
(TestMatchCase (e, (c, Pos.from_lpos $sloc)), Pos.from_lpos $sloc)
}
| e1 = primitive_expression IN e2 = base_expression {
(MemCollection (e1, e2), Pos.from_lpos $sloc)
}
base_expression:
| e = primitive_expression { e }
| ag = aggregate { ag }
| e1 = primitive_expression OF e2 = base_expression {
(FunCall (e1, e2), Pos.from_lpos $sloc)
}
| e = primitive_expression WITH c = constructor_binding {
(TestMatchCase (e, (c, Pos.from_lpos $sloc)), Pos.from_lpos $sloc)
}
| e1 = primitive_expression IN e2 = base_expression {
(MemCollection (e1, e2), Pos.from_lpos $sloc)
}
mult_op:
| MULT { (Mult KInt, Pos.from_lpos $sloc) }
| DIV { (Div KInt, Pos.from_lpos $sloc) }
| MULTDEC { (Mult KDec, Pos.from_lpos $sloc) }
| DIVDEC { (Div KDec, Pos.from_lpos $sloc) }
| MULTMONEY { (Mult KMoney, Pos.from_lpos $sloc) }
| DIVMONEY { (Div KMoney, Pos.from_lpos $sloc) }
mult_op:
| MULT { (Mult KInt, Pos.from_lpos $sloc) }
| DIV { (Div KInt, Pos.from_lpos $sloc) }
| MULTDEC { (Mult KDec, Pos.from_lpos $sloc) }
| DIVDEC { (Div KDec, Pos.from_lpos $sloc) }
| MULTMONEY { (Mult KMoney, Pos.from_lpos $sloc) }
| DIVMONEY { (Div KMoney, Pos.from_lpos $sloc) }
mult_expression:
| e = base_expression { e }
| e1 = base_expression binop = mult_op e2 = mult_expression {
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
}
mult_expression:
| e = base_expression { e }
| e1 = base_expression binop = mult_op e2 = mult_expression {
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
}
sum_op:
| PLUSDURATION { (Add KDuration, Pos.from_lpos $sloc) }
| MINUSDURATION { (Sub KDuration, Pos.from_lpos $sloc) }
| PLUSDATE { (Add KDate, Pos.from_lpos $sloc) }
| MINUSDATE { (Sub KDate, Pos.from_lpos $sloc) }
| PLUSMONEY { (Add KMoney, Pos.from_lpos $sloc) }
| MINUSMONEY { (Sub KMoney, Pos.from_lpos $sloc) }
| PLUSDEC { (Add KDec, Pos.from_lpos $sloc) }
| MINUSDEC { (Sub KDec, Pos.from_lpos $sloc) }
| PLUS { (Add KInt, Pos.from_lpos $sloc) }
| MINUS { (Sub KInt, Pos.from_lpos $sloc) }
sum_op:
| PLUSDURATION { (Add KDuration, Pos.from_lpos $sloc) }
| MINUSDURATION { (Sub KDuration, Pos.from_lpos $sloc) }
| PLUSDATE { (Add KDate, Pos.from_lpos $sloc) }
| MINUSDATE { (Sub KDate, Pos.from_lpos $sloc) }
| PLUSMONEY { (Add KMoney, Pos.from_lpos $sloc) }
| MINUSMONEY { (Sub KMoney, Pos.from_lpos $sloc) }
| PLUSDEC { (Add KDec, Pos.from_lpos $sloc) }
| MINUSDEC { (Sub KDec, Pos.from_lpos $sloc) }
| PLUS { (Add KInt, Pos.from_lpos $sloc) }
| MINUS { (Sub KInt, Pos.from_lpos $sloc) }
sum_unop:
| MINUS { (Minus KInt, Pos.from_lpos $sloc) }
| MINUSDEC { (Minus KDec, Pos.from_lpos $sloc) }
| MINUSMONEY { (Minus KMoney, Pos.from_lpos $sloc) }
| MINUSDURATION { (Minus KDuration, Pos.from_lpos $sloc) }
sum_unop:
| MINUS { (Minus KInt, Pos.from_lpos $sloc) }
| MINUSDEC { (Minus KDec, Pos.from_lpos $sloc) }
| MINUSMONEY { (Minus KMoney, Pos.from_lpos $sloc) }
| MINUSDURATION { (Minus KDuration, Pos.from_lpos $sloc) }
sum_expression:
| e = mult_expression { e }
| e1 = mult_expression binop = sum_op e2 = sum_expression {
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
}
| unop = sum_unop e = sum_expression { (Unop (unop, e), Pos.from_lpos $sloc) }
sum_expression:
| e = mult_expression { e }
| e1 = mult_expression binop = sum_op e2 = sum_expression {
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
}
| unop = sum_unop e = sum_expression { (Unop (unop, e), Pos.from_lpos $sloc) }
logical_op:
| AND { (And, Pos.from_lpos $sloc) }
| OR { (Or, Pos.from_lpos $sloc) }
logical_op:
| AND { (And, Pos.from_lpos $sloc) }
| OR { (Or, Pos.from_lpos $sloc) }
logical_unop:
| NOT { (Not, Pos.from_lpos $sloc) }
logical_unop:
| NOT { (Not, Pos.from_lpos $sloc) }
compare_expression:
| e = sum_expression { e }
| e1 = sum_expression binop = compare_op e2 = compare_expression {
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
}
compare_expression:
| e = sum_expression { e }
| e1 = sum_expression binop = compare_op e2 = compare_expression {
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
}
logical_expression:
| e = compare_expression { e }
| unop = logical_unop e = compare_expression { (Unop (unop, e), Pos.from_lpos $sloc) }
| e1 = compare_expression binop = logical_op e2 = logical_expression {
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
}
logical_expression:
| e = compare_expression { e }
| unop = logical_unop e = compare_expression { (Unop (unop, e), Pos.from_lpos $sloc) }
| e1 = compare_expression binop = logical_op e2 = logical_expression {
(Binop (binop, e1, e2), Pos.from_lpos $sloc)
}
maybe_qualified_constructor:
| c_or_path = constructor c = option(preceded(DOT, constructor)) {
match c with
maybe_qualified_constructor:
| c_or_path = constructor c = option(preceded(DOT, constructor)) {
match c with
| None -> (None, c_or_path)
| Some c -> (Some c_or_path, c)
}
}
optional_binding:
| { ([], None)}
| OF i = ident {([], Some i)}
| OF c = maybe_qualified_constructor cs_and_i = constructor_binding {
optional_binding:
| { ([], None)}
| OF i = ident {([], Some i)}
| OF c = maybe_qualified_constructor cs_and_i = constructor_binding {
let (cs, i) = cs_and_i in
(c::cs, i)
}
}
constructor_binding:
| c = maybe_qualified_constructor cs_and_i = optional_binding {
constructor_binding:
| c = maybe_qualified_constructor cs_and_i = optional_binding {
let (cs, i) = cs_and_i in
(c::cs, i)
}
}
match_arm:
| pat = constructor_binding COLON e = logical_expression {
({
(* DM 14/04/2020 : I can't have the $sloc in constructor_binding... *)
match_case_pattern = (pat, Pos.from_lpos $sloc);
match_arm:
| pat = constructor_binding COLON e = logical_expression {
({
(* DM 14/04/2020 : I can't have the $sloc in constructor_binding... *)
match_case_pattern = (pat, Pos.from_lpos $sloc);
match_case_expr = e;
}, Pos.from_lpos $sloc)
}
}, Pos.from_lpos $sloc)
}
match_arms:
| ALT a = match_arm arms = match_arms {
match_arms:
| ALT a = match_arm arms = match_arms {
let (arms, _) = arms in
(a::arms, Pos.from_lpos $sloc)
}
| { ([], Pos.from_lpos $sloc)}
(a::arms, Pos.from_lpos $sloc)
}
| { ([], Pos.from_lpos $sloc)}
for_all_marked:
| FOR ALL { Pos.from_lpos $sloc }
for_all_marked:
| FOR ALL { Pos.from_lpos $sloc }
exists_marked:
| EXISTS { Pos.from_lpos $sloc }
exists_marked:
| EXISTS { Pos.from_lpos $sloc }
forall_prefix:
| pos = for_all_marked i = ident IN e = primitive_expression WE_HAVE {
(pos, i, e)
}
exists_prefix:
| pos = exists_marked i = ident IN e = primitive_expression SUCH THAT {
(pos, i, e)
}
forall_prefix:
| pos = for_all_marked i = ident IN e = primitive_expression WE_HAVE {
(pos, i, e)
}
exists_prefix:
| pos = exists_marked i = ident IN e = primitive_expression SUCH THAT {
(pos, i, e)
}
expression:
| i_in_e1 = exists_prefix e2 = expression {
expression:
| i_in_e1 = exists_prefix e2 = expression {
let (pos, i,e1) = i_in_e1 in
(CollectionOp ((Exists, pos), i, e1, e2), Pos.from_lpos $sloc)
}
| i_in_e1 = forall_prefix e2 = expression {
}
| i_in_e1 = forall_prefix e2 = expression {
let (pos, i,e1) = i_in_e1 in
(CollectionOp ((Forall, pos), i, e1, e2), Pos.from_lpos $sloc)
}
| MATCH e = primitive_expression WITH arms = match_arms {
(MatchWith (e, arms), Pos.from_lpos $sloc)
}
| IF e1 = expression THEN e2 = expression ELSE e3 = base_expression {
(IfThenElse (e1, e2, e3), Pos.from_lpos $sloc)
}
| e = logical_expression { e }
}
| MATCH e = primitive_expression WITH arms = match_arms {
(MatchWith (e, arms), Pos.from_lpos $sloc)
}
| IF e1 = expression THEN e2 = expression ELSE e3 = base_expression {
(IfThenElse (e1, e2, e3), Pos.from_lpos $sloc)
}
| e = logical_expression { e }
condition:
| UNDER_CONDITION e = expression { e }
condition:
| UNDER_CONDITION e = expression { e }
condition_consequence:
| cond = condition CONSEQUENCE { cond }
condition_consequence:
| cond = condition CONSEQUENCE { cond }
rule_expr:
| i = qident p = option(definition_parameters) { (i, p) }
rule_expr:
| i = qident p = option(definition_parameters) { (i, p) }
rule_consequence:
| flag = option(NOT) FILLED {
rule_consequence:
| flag = option(NOT) FILLED {
let b = match flag with Some _ -> false | None -> true in
(b, Pos.from_lpos $sloc)
}
}
rule:
| label = option(label)
rule:
| label = option(label)
except = option(exception_to)
RULE
name_and_param = rule_expr cond = option(condition_consequence)
consequence = rule_consequence {
consequence = rule_consequence {
let (name, param_applied) = name_and_param in
let cons : bool Pos.marked = consequence in
let rule_exception = match except with | None -> NotAnException | Some x -> x in
@ -414,21 +414,21 @@ rule:
rule_condition = cond;
rule_name = name;
rule_consequence = cons;
}, $sloc)
}
}, $sloc)
}
definition_parameters:
| OF i = ident { i }
definition_parameters:
| OF i = ident { i }
label:
| LABEL i = ident { i }
label:
| LABEL i = ident { i }
exception_to:
| EXCEPTION i = option(ident) {
exception_to:
| EXCEPTION i = option(ident) {
match i with | None -> UnlabeledException | Some x -> ExceptionToLabel x }
definition:
| label = option(label)
definition:
| label = option(label)
except = option(exception_to)
DEFINITION
name = qident param = option(definition_parameters)
@ -441,75 +441,75 @@ definition:
definition_parameter = param;
definition_condition = cond;
definition_expr = e;
}, $sloc)
}, $sloc)
}
variation_type:
| INCREASING { (Increasing, Pos.from_lpos $sloc) }
| DECREASING { (Decreasing, Pos.from_lpos $sloc) }
assertion_base:
| e = expression { let (e, _) = e in (e, Pos.from_lpos $sloc) }
assertion:
| cond = option(condition_consequence) base = assertion_base {
(Assertion {
assertion_condition = cond;
assertion_content = base;
})
}
| FIXED q = qident BY i = ident { MetaAssertion (FixedBy (q, i)) }
| VARIES q = qident WITH_V e = base_expression t = option(variation_type) {
MetaAssertion (VariesWith (q, e, t))
}
variation_type:
| INCREASING { (Increasing, Pos.from_lpos $sloc) }
| DECREASING { (Decreasing, Pos.from_lpos $sloc) }
assertion_base:
| e = expression { let (e, _) = e in (e, Pos.from_lpos $sloc) }
assertion:
| cond = option(condition_consequence) base = assertion_base {
(Assertion {
assertion_condition = cond;
assertion_content = base;
})
}
| FIXED q = qident BY i = ident { MetaAssertion (FixedBy (q, i)) }
| VARIES q = qident WITH_V e = base_expression t = option(variation_type) {
MetaAssertion (VariesWith (q, e, t))
}
scope_item:
| r = rule {
scope_item:
| r = rule {
let (r, _) = r in (Rule r, Pos.from_lpos $sloc)
}
| d = definition {
let (d, _) = d in (Definition d, Pos.from_lpos $sloc)
}
| ASSERTION contents = assertion {
(contents, Pos.from_lpos $sloc)
}
}
| d = definition {
let (d, _) = d in (Definition d, Pos.from_lpos $sloc)
}
| ASSERTION contents = assertion {
(contents, Pos.from_lpos $sloc)
}
ident:
| i = IDENT { (i, Pos.from_lpos $sloc) }
ident:
| i = IDENT { (i, Pos.from_lpos $sloc) }
condition_pos:
| CONDITION { Pos.from_lpos $sloc }
condition_pos:
| CONDITION { Pos.from_lpos $sloc }
struct_scope_base:
| DATA i= ident CONTENT t = typ {
let t, pos = t in
(i, (Data t, pos))
}
| pos = condition_pos i = ident {
(i, (Condition, pos))
}
struct_scope_base:
| DATA i= ident CONTENT t = typ {
let t, pos = t in
(i, (Data t, pos))
}
| pos = condition_pos i = ident {
(i, (Condition, pos))
}
struct_scope_func:
| DEPENDS t = typ { t }
struct_scope_func:
| DEPENDS t = typ { t }
struct_scope:
| name_and_typ = struct_scope_base func_typ = option(struct_scope_func) {
let (name, typ) = name_and_typ in
let (typ, typ_pos) = typ in
({
struct_decl_field_name = name;
struct_scope:
| name_and_typ = struct_scope_base func_typ = option(struct_scope_func) {
let (name, typ) = name_and_typ in
let (typ, typ_pos) = typ in
({
struct_decl_field_name = name;
struct_decl_field_typ = match func_typ with
| None -> (Base typ, typ_pos)
| Some (arg_typ, arg_pos) -> (Func {
arg_typ = (Data arg_typ, arg_pos);
return_typ = (typ, typ_pos);
}, Pos.from_lpos $sloc) ;
}, Pos.from_lpos $sloc)
}
}, Pos.from_lpos $sloc) ;
}, Pos.from_lpos $sloc)
}
scope_decl_item:
| CONTEXT i = ident CONTENT t = typ func_typ = option(struct_scope_func) { (ContextData ({
scope_decl_context_item_name = i;
scope_decl_item:
| CONTEXT i = ident CONTENT t = typ func_typ = option(struct_scope_func) { (ContextData ({
scope_decl_context_item_name = i;
scope_decl_context_item_typ =
let (typ, typ_pos) = t in
match func_typ with
@ -517,16 +517,16 @@ scope_decl_item:
| Some (arg_typ, arg_pos) -> (Func {
arg_typ = (Data arg_typ, arg_pos);
return_typ = (Data typ, typ_pos);
}, Pos.from_lpos $sloc);
}), Pos.from_lpos $sloc) }
| CONTEXT i = ident SCOPE c = constructor {
(ContextScope({
scope_decl_context_scope_name = i;
}, Pos.from_lpos $sloc);
}), Pos.from_lpos $sloc) }
| CONTEXT i = ident SCOPE c = constructor {
(ContextScope({
scope_decl_context_scope_name = i;
scope_decl_context_scope_sub_scope = c;
}), Pos.from_lpos $sloc)
}
| CONTEXT i = ident _condition = CONDITION func_typ = option(struct_scope_func) { (ContextData ({
scope_decl_context_item_name = i;
}), Pos.from_lpos $sloc)
}
| CONTEXT i = ident _condition = CONDITION func_typ = option(struct_scope_func) { (ContextData ({
scope_decl_context_item_name = i;
scope_decl_context_item_typ =
match func_typ with
| None -> (Base (Condition), Pos.from_lpos $loc(_condition))
@ -534,135 +534,136 @@ scope_decl_item:
arg_typ = (Data arg_typ, arg_pos);
return_typ = (Condition, Pos.from_lpos $loc(_condition));
}, Pos.from_lpos $sloc);
}), Pos.from_lpos $sloc) }
}), Pos.from_lpos $sloc) }
enum_decl_line_payload:
| CONTENT t = typ { let (t, t_pos) = t in (Base (Data t), t_pos) }
enum_decl_line_payload:
| CONTENT t = typ { let (t, t_pos) = t in (Base (Data t), t_pos) }
enum_decl_line:
| ALT c = constructor t = option(enum_decl_line_payload) { ({
enum_decl_case_name = c;
enum_decl_line:
| ALT c = constructor t = option(enum_decl_line_payload) { ({
enum_decl_case_name = c;
enum_decl_case_typ = t;
}, Pos.from_lpos $sloc) }
}, Pos.from_lpos $sloc) }
constructor:
| c = CONSTRUCTOR { (c, Pos.from_lpos $sloc) }
constructor:
| c = CONSTRUCTOR { (c, Pos.from_lpos $sloc) }
scope_use_condition:
| UNDER_CONDITION e = expression { e }
scope_use_condition:
| UNDER_CONDITION e = expression { e }
code_item:
| SCOPE c = constructor e = option(scope_use_condition) COLON items = nonempty_list(scope_item) {
(ScopeUse {
scope_use_name = c;
code_item:
| SCOPE c = constructor e = option(scope_use_condition) COLON items = nonempty_list(scope_item) {
(ScopeUse {
scope_use_name = c;
scope_use_condition = e;
scope_use_items = items;
}, Pos.from_lpos $sloc)
}
| DECLARATION STRUCT c = constructor COLON scopes = list(struct_scope) {
(StructDecl {
struct_decl_name = c;
}, Pos.from_lpos $sloc)
}
| DECLARATION STRUCT c = constructor COLON scopes = list(struct_scope) {
(StructDecl {
struct_decl_name = c;
struct_decl_fields = scopes;
}, Pos.from_lpos $sloc)
}
| DECLARATION SCOPE c = constructor COLON context = nonempty_list(scope_decl_item) {
(ScopeDecl {
scope_decl_name = c;
}, Pos.from_lpos $sloc)
}
| DECLARATION SCOPE c = constructor COLON context = nonempty_list(scope_decl_item) {
(ScopeDecl {
scope_decl_name = c;
scope_decl_context = context;
}, Pos.from_lpos $sloc)
}
| DECLARATION ENUM c = constructor COLON cases = nonempty_list(enum_decl_line) {
(EnumDecl {
enum_decl_name = c;
}, Pos.from_lpos $sloc)
}
| DECLARATION ENUM c = constructor COLON cases = nonempty_list(enum_decl_line) {
(EnumDecl {
enum_decl_name = c;
enum_decl_cases = cases;
}, Pos.from_lpos $sloc)
}
}, Pos.from_lpos $sloc)
}
code:
| code = list(code_item) { (code, Pos.from_lpos $sloc) }
code:
| code = list(code_item) { (code, Pos.from_lpos $sloc) }
metadata_block:
| BEGIN_CODE option(law_text) code_and_pos = code text = END_CODE option(law_text) END_METADATA {
let (code, pos) = code_and_pos in
(code, (text, pos))
}
metadata_block:
| BEGIN_CODE option(law_text) code_and_pos = code text = END_CODE option(law_text) END_METADATA {
let (code, pos) = code_and_pos in
(code, (text, pos))
}
law_article_item:
| text = law_text { LawText text }
| BEGIN_CODE code_and_pos = code text = END_CODE {
let (code, pos) = code_and_pos in
CodeBlock (code, (text, pos))
}
law_article_item:
| text = law_text { LawText text }
| BEGIN_CODE code_and_pos = code text = END_CODE {
let (code, pos) = code_and_pos in
CodeBlock (code, (text, pos))
}
law_article:
| title = LAW_ARTICLE {
let (title, id, exp_date) = title in {
law_article_name = (title, Pos.from_lpos $sloc);
law_article:
| title = LAW_ARTICLE {
let (title, id, exp_date, precedence) = title in {
law_article_name = (title, Pos.from_lpos $sloc);
law_article_id = id;
law_article_expiration_date = exp_date;
}
}
law_article_precedence = precedence;
}
}
law_heading:
| heading = LAW_HEADING { let (title, precedence) = heading in {
law_heading_name = title;
law_heading:
| heading = LAW_HEADING { let (title, precedence) = heading in {
law_heading_name = title;
law_heading_precedence = precedence;
}
}
}
}
law_articles_items:
| hd = law_article_item tl = law_articles_items{ hd::tl }
| { [] }
law_articles_items:
| hd = law_article_item tl = law_articles_items{ hd::tl }
| { [] }
law_text:
| text = LAW_TEXT { String.trim text }
law_text:
| text = LAW_TEXT { String.trim text }
law_intermediate_text:
| text = law_text { LawStructure (IntermediateText text) }
law_intermediate_text:
| text = law_text { LawStructure (IntermediateText text) }
source_file_article:
| article = law_article items = law_articles_items {
LawStructure (LawArticle (article, items))
}
source_file_article:
| article = law_article items = law_articles_items {
LawStructure (LawArticle (article, items))
}
source_file_item:
| heading = law_heading {
LawStructure (LawHeading (heading, []))
}
| BEGIN_METADATA option(law_text) code = metadata_block {
let (code, source_repr) = code in
LawStructure (MetadataBlock (code, source_repr))
}
| includ = LAW_INCLUDE {
LawStructure (LawInclude includ)
}
source_file_item:
| heading = law_heading {
LawStructure (LawHeading (heading, []))
}
| BEGIN_METADATA option(law_text) code = metadata_block {
let (code, source_repr) = code in
LawStructure (MetadataBlock (code, source_repr))
}
| includ = LAW_INCLUDE {
LawStructure (LawInclude includ)
}
source_file_after_text:
| i = source_file_article f = source_file_after_text {
i::f
}
| i = source_file_item l = list(law_intermediate_text) f = source_file_after_text {
i::l@f
}
| EOF { [] }
source_file_after_text:
| i = source_file_article f = source_file_after_text {
i::f
}
| i = source_file_item l = list(law_intermediate_text) f = source_file_after_text {
i::l@f
}
| EOF { [] }
source_file:
| l = list(law_intermediate_text) f = source_file_after_text { l@f }
source_file:
| l = list(law_intermediate_text) f = source_file_after_text { l@f }
master_file_include:
| includ = LAW_INCLUDE {
match includ with
master_file_include:
| includ = LAW_INCLUDE {
match includ with
| CatalaFile (file, _) -> (file, Pos.from_lpos $sloc)
| _ -> Errors.raise_spanned_error
(Printf.sprintf "Include in master file must be .catala file!")
| _ -> Errors.raise_spanned_error
(Printf.sprintf "Include in master file must be .catala file!")
(Pos.from_lpos $sloc)
}
}
master_file_includes:
| i = master_file_include option(law_text) is = master_file_includes { i::is }
| EOF { [] }
master_file_includes:
| i = master_file_include option(law_text) is = master_file_includes { i::is }
| EOF { [] }
source_file_or_master:
| MASTER_FILE option(law_text) is = master_file_includes { MasterFile is }
| f = source_file { SourceFile (f) }
source_file_or_master:
| MASTER_FILE option(law_text) is = master_file_includes { MasterFile is }
| f = source_file { SourceFile (f) }

View File

@ -13,21 +13,21 @@ ace.define("ace/mode/catala_en_highlighting_rules", ["require", "exports", "modu
"start": [
{
"token": "markup.heading.title",
"regex": "(@@)",
"regex": "([\#]+)",
"push": "main__1"
},
{
"token": "markup.heading.subtitle",
"regex": "(@)",
"regex": "([\#]+\s*\[[^\]]\s*])",
"push": "main__2"
},
{
"token": "entity.law",
"regex": "([^\\/])"
"regex": "([^`])"
},
{
"token": "comment.block.documentation",
"regex": "(\\/\\*)",
"regex": "(```catala)",
"push": "code"
},
{
@ -37,7 +37,7 @@ ace.define("ace/mode/catala_en_highlighting_rules", ["require", "exports", "modu
"code": [
{
"token": "comment.block.documentation",
"regex": "(\\*\\/)",
"regex": "(```)",
"next": "pop"
},
{
@ -103,7 +103,7 @@ ace.define("ace/mode/catala_en_highlighting_rules", ["require", "exports", "modu
"main__1": [
{
"token": "markup.heading.title",
"regex": "(@@[\\+]*)",
"regex": "(\n)",
"next": "pop"
},
{
@ -117,7 +117,7 @@ ace.define("ace/mode/catala_en_highlighting_rules", ["require", "exports", "modu
"main__2": [
{
"token": "markup.heading.subtitle",
"regex": "(@)",
"regex": "(\n)",
"next": "pop"
},
{

View File

@ -13,7 +13,7 @@
'main' : {
'patterns' : [
{
'begin' : '(@@)'
'begin' : '([#]+)'
'beginCaptures' : {
'1' : {
'name' : 'markup.heading.title.catala_en'
@ -24,7 +24,7 @@
'include' : '#main__1'
}
]
'end' : '(@@[\\+]*)'
'end' : '(\n)'
'endCaptures' : {
'1' : {
'name' : 'markup.heading.title.catala_en'
@ -32,7 +32,7 @@
}
}
{
'begin' : '(@)'
'begin' : '([#]+\s*\[[^\]]\s*\])'
'beginCaptures' : {
'1' : {
'name' : 'markup.heading.subtitle.catala_en'
@ -43,7 +43,7 @@
'include' : '#main__2'
}
]
'end' : '(@)'
'end' : '(\n)'
'endCaptures' : {
'1' : {
'name' : 'markup.heading.subtitle.catala_en'
@ -51,11 +51,11 @@
}
}
{
'match' : '([^\\/])'
'match' : '([^`])'
'name' : 'entity.law.catala_en'
}
{
'begin' : '(\\/\\*)'
'begin' : '(```catala)'
'beginCaptures' : {
'1' : {
'name' : 'comment.block.documentation.catala_en'
@ -66,7 +66,7 @@
'include' : '#code'
}
]
'end' : '(\\*\\/)'
'end' : '(```)'
'endCaptures' : {
'1' : {
'name' : 'comment.block.documentation.catala_en'

View File

@ -151,7 +151,7 @@ contexts [] {
main : context {
: inline_push {
regex \= (@@)
regex \= (\#\#)
styles [] = .law_title;
: pop {
regex \= (@@[\+]*)
@ -177,12 +177,12 @@ main : context {
}
: pattern {
regex \= ([^\/])
regex \= ([^`])
styles [] = .law;
}
: push {
regex \= (\/\*)
regex \= (```catala)
styles [] = .code_delimiter;
context [] = code;
}
@ -193,7 +193,7 @@ main : context {
code : context {
: pop {
regex \= (\*\/)
regex \= (```)
styles [] = .code_delimiter;
}

View File

@ -14,15 +14,15 @@ class CatalaEnLexer(RegexLexer):
tokens = {
'root': [
(u'(@@)', bygroups(Generic.Heading), 'main__1'),
(u'(@)', bygroups(Generic.Heading), 'main__2'),
(u'([^\\/\\n\\r])', bygroups(Text)),
(u'(\\/\\*)', bygroups(Text), 'code'),
(u'([\#]+)', bygroups(Generic.Heading), 'main__1'),
(u'([\#]+\s*\[[^\]]\s*])', bygroups(Generic.Heading), 'main__2'),
(u'([^`\\n\\r])', bygroups(Text)),
(u'(```catala)', bygroups(Text), 'code'),
('(\n|\r|\r\n)', Text),
('.', Text),
],
'code': [
(u'(\\*\\/)', bygroups(Text), 'root'),
(u'(```)', bygroups(Text), 'root'),
(u'(\\s*\\#.*$)', bygroups(Comment.Single)),
(u'(context)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)',
bygroups(Keyword.Declaration, Text, Name.Variable)),
@ -44,13 +44,13 @@ class CatalaEnLexer(RegexLexer):
('.', Text),
],
'main__1': [
(u'(@@)', bygroups(Generic.Heading), 'root'),
(u'(\n)', bygroups(Generic.Heading), 'root'),
(u'(.)', bygroups(Generic.Heading)),
('(\n|\r|\r\n)', Text),
('.', Text),
],
'main__2': [
(u'(@)', bygroups(Generic.Heading), 'root'),
(u'(\n)', bygroups(Generic.Heading), 'root'),
(u'(.)', bygroups(Generic.Heading)),
('(\n|\r|\r\n)', Text),
('.', Text),

View File

@ -28,7 +28,7 @@
<array>
<dict>
<key>begin</key>
<string>(@@)</string>
<string>([\#]+)</string>
<key>beginCaptures</key>
<dict>
<key>1</key>
@ -45,7 +45,7 @@
</dict>
</array>
<key>end</key>
<string>(@@[\+]*)</string>
<string>(\n)</string>
<key>endCaptures</key>
<dict>
<key>1</key>
@ -57,7 +57,7 @@
</dict>
<dict>
<key>begin</key>
<string>(@)</string>
<string>([#]+\s*\[^\]]\s*\])</string>
<key>beginCaptures</key>
<dict>
<key>1</key>
@ -74,7 +74,7 @@
</dict>
</array>
<key>end</key>
<string>(@)</string>
<string>(\n)</string>
<key>endCaptures</key>
<dict>
<key>1</key>
@ -86,13 +86,13 @@
</dict>
<dict>
<key>match</key>
<string>([^\/])</string>
<string>([^`])</string>
<key>name</key>
<string>entity.law.catala_en</string>
</dict>
<dict>
<key>begin</key>
<string>(\/\*)</string>
<string>(```catala)</string>
<key>beginCaptures</key>
<dict>
<key>1</key>
@ -109,7 +109,7 @@
</dict>
</array>
<key>end</key>
<string>(\*\/)</string>
<string>(```)</string>
<key>endCaptures</key>
<dict>
<key>1</key>
@ -286,4 +286,3 @@
</dict>
</dict>
</plist>

View File

@ -13,21 +13,21 @@ ace.define("ace/mode/catala_fr_highlighting_rules", ["require", "exports", "modu
"start": [
{
"token": "markup.heading.title",
"regex": "(@@)",
"regex": "([\#]+)",
"push": "main__1"
},
{
"token": "markup.heading.subtitle",
"regex": "(@)",
"regex": "([\#]+\s*\[[^\]]\s*])",
"push": "main__2"
},
{
"token": "entity.law",
"regex": "([^\\/])"
"regex": "([^`])"
},
{
"token": "comment.block.documentation",
"regex": "(\\/\\*)",
"regex": "(```catala)",
"push": "code"
},
{
@ -37,7 +37,7 @@ ace.define("ace/mode/catala_fr_highlighting_rules", ["require", "exports", "modu
"code": [
{
"token": "comment.block.documentation",
"regex": "(\\*\\/)",
"regex": "(```)",
"next": "pop"
},
{
@ -103,7 +103,7 @@ ace.define("ace/mode/catala_fr_highlighting_rules", ["require", "exports", "modu
"main__1": [
{
"token": "markup.heading.title",
"regex": "(@@[\\+]*)",
"regex": "(\n)",
"next": "pop"
},
{
@ -117,7 +117,7 @@ ace.define("ace/mode/catala_fr_highlighting_rules", ["require", "exports", "modu
"main__2": [
{
"token": "markup.heading.subtitle",
"regex": "(@)",
"regex": "(\n)",
"next": "pop"
},
{

View File

@ -13,7 +13,7 @@
'main' : {
'patterns' : [
{
'begin' : '(@@)'
'begin' : '([#]+)'
'beginCaptures' : {
'1' : {
'name' : 'markup.heading.title.catala_fr'
@ -24,7 +24,7 @@
'include' : '#main__1'
}
]
'end' : '(@@[\\+]*)'
'end' : '(\n)'
'endCaptures' : {
'1' : {
'name' : 'markup.heading.title.catala_fr'
@ -32,7 +32,7 @@
}
}
{
'begin' : '(@)'
'begin' : '([#]+\s*\[[^\]]\s*\])'
'beginCaptures' : {
'1' : {
'name' : 'markup.heading.subtitle.catala_fr'
@ -43,7 +43,7 @@
'include' : '#main__2'
}
]
'end' : '(@)'
'end' : '(\n)'
'endCaptures' : {
'1' : {
'name' : 'markup.heading.subtitle.catala_fr'
@ -51,11 +51,11 @@
}
}
{
'match' : '([^\\/])'
'match' : '([^\\`])'
'name' : 'entity.law.catala_fr'
}
{
'begin' : '(\\/\\*)'
'begin' : '(```catala)'
'beginCaptures' : {
'1' : {
'name' : 'comment.block.documentation.catala_fr'
@ -66,7 +66,7 @@
'include' : '#code'
}
]
'end' : '(\\*\\/)'
'end' : '(```)'
'endCaptures' : {
'1' : {
'name' : 'comment.block.documentation.catala_fr'

View File

@ -151,10 +151,10 @@ contexts [] {
main : context {
: inline_push {
regex \= (@@)
regex \= (\#\#)
styles [] = .law_title;
: pop {
regex \= (@@[\+]*)
regex \= (\n)
styles [] = .law_title;
}
: pattern {
@ -177,12 +177,12 @@ main : context {
}
: pattern {
regex \= ([^\/])
regex \= ([^`])
styles [] = .law;
}
: push {
regex \= (\/\*)
regex \= (```catala)
styles [] = .code_delimiter;
context [] = code;
}
@ -193,7 +193,7 @@ main : context {
code : context {
: pop {
regex \= (\*\/)
regex \= (```)
styles [] = .code_delimiter;
}

View File

@ -14,15 +14,15 @@ class CatalaFrLexer(RegexLexer):
tokens = {
'root': [
(u'(@@)', bygroups(Generic.Heading), 'main__1'),
(u'(@)', bygroups(Generic.Heading), 'main__2'),
(u'([^\\/\\n\\r])', bygroups(Text)),
(u'(\\/\\*)', bygroups(Text), 'code'),
(u'([\#]+)', bygroups(Generic.Heading), 'main__1'),
(u'([\#]+\s*\[[^\]]\s*])', bygroups(Generic.Heading), 'main__2'),
(u'([^`\\n\\r])', bygroups(Text)),
(u'(```catala)', bygroups(Text), 'code'),
('(\n|\r|\r\n)', Text),
('.', Text),
],
'code': [
(u'(\\*\\/)', bygroups(Text), 'root'),
(u'(```)', bygroups(Text), 'root'),
(u'(\\s*\\#.*$)', bygroups(Comment.Single)),
(u'(contexte)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)',
bygroups(Keyword.Declaration, String, Name.Variable)),
@ -44,13 +44,13 @@ class CatalaFrLexer(RegexLexer):
('.', Text),
],
'main__1': [
(u'(@@)', bygroups(Generic.Heading), 'root'),
(u'(\n)', bygroups(Generic.Heading), 'root'),
(u'(.)', bygroups(Generic.Heading)),
('(\n|\r|\r\n)', Text),
('.', Text),
],
'main__2': [
(u'(@)', bygroups(Generic.Heading), 'root'),
(u'(\n)', bygroups(Generic.Heading), 'root'),
(u'(.)', bygroups(Generic.Heading)),
('(\n|\r|\r\n)', Text),
('.', Text),

View File

@ -4,13 +4,13 @@
<!-- Generated via Iro -->
<dict>
<key>fileTypes</key>
<array>
<array>
<string>catala_fr</string>
</array>
<key>name</key>
<string>catala_fr</string>
<key>patterns</key>
<array>
<array>
<dict>
<key>include</key>
<string>#main</string>
@ -25,10 +25,10 @@
<key>main</key>
<dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>begin</key>
<string>(@@)</string>
<string>([\#]+)</string>
<key>beginCaptures</key>
<dict>
<key>1</key>
@ -38,14 +38,14 @@
</dict>
</dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>include</key>
<string>#main__1</string>
</dict>
</array>
<key>end</key>
<string>(@@[\+]*)</string>
<string>(\n)</string>
<key>endCaptures</key>
<dict>
<key>1</key>
@ -57,7 +57,7 @@
</dict>
<dict>
<key>begin</key>
<string>(@)</string>
<string>([\#]+\s*\[[^\]]\s*\])</string>
<key>beginCaptures</key>
<dict>
<key>1</key>
@ -67,14 +67,14 @@
</dict>
</dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>include</key>
<string>#main__2</string>
</dict>
</array>
<key>end</key>
<string>(@)</string>
<string>(\n)</string>
<key>endCaptures</key>
<dict>
<key>1</key>
@ -86,13 +86,13 @@
</dict>
<dict>
<key>match</key>
<string>([^\/])</string>
<string>([^`#])</string>
<key>name</key>
<string>entity.law.catala_fr</string>
</dict>
<dict>
<key>begin</key>
<string>(\/\*)</string>
<string>(```catala)</string>
<key>beginCaptures</key>
<dict>
<key>1</key>
@ -102,14 +102,14 @@
</dict>
</dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>include</key>
<string>#code</string>
</dict>
</array>
<key>end</key>
<string>(\*\/)</string>
<string>(```)</string>
<key>endCaptures</key>
<dict>
<key>1</key>
@ -124,7 +124,7 @@
<key>code</key>
<dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>match</key>
<string>(\s*\#.*$)</string>
@ -262,7 +262,7 @@
<key>main__1</key>
<dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>match</key>
<string>(.)</string>
@ -274,7 +274,7 @@
<key>main__2</key>
<dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>match</key>
<string>(.)</string>

View File

@ -13,7 +13,7 @@
'main' : {
'patterns' : [
{
'begin' : '(@@)'
'begin' : '([\#]+)'
'beginCaptures' : {
'1' : {
'name' : 'markup.heading.title.catala_nv'
@ -24,7 +24,7 @@
'include' : '#main__1'
}
]
'end' : '(@@[\\+]*)'
'end' : '(\n)'
'endCaptures' : {
'1' : {
'name' : 'markup.heading.title.catala_nv'
@ -32,7 +32,7 @@
}
}
{
'begin' : '(@)'
'begin' : '([\#]+\s*\[[^\]]\s*\])'
'beginCaptures' : {
'1' : {
'name' : 'markup.heading.subtitle.catala_nv'
@ -43,7 +43,7 @@
'include' : '#main__2'
}
]
'end' : '(@)'
'end' : '(\n)'
'endCaptures' : {
'1' : {
'name' : 'markup.heading.subtitle.catala_nv'
@ -51,11 +51,11 @@
}
}
{
'match' : '([^\\/])'
'match' : '([^`])'
'name' : 'entity.law.catala_nv'
}
{
'begin' : '(\\/\\*)'
'begin' : '(```catala)'
'beginCaptures' : {
'1' : {
'name' : 'comment.block.documentation.catala_nv'
@ -66,7 +66,7 @@
'include' : '#code'
}
]
'end' : '(\\*\\/)'
'end' : '(```)'
'endCaptures' : {
'1' : {
'name' : 'comment.block.documentation.catala_nv'

View File

@ -151,10 +151,10 @@ contexts [] {
main : context {
: inline_push {
regex \= (@@)
regex \= ([\#]+)
styles [] = .law_title;
: pop {
regex \= (@@[\+]*)
regex \= (\n)
styles [] = .law_title;
}
: pattern {
@ -164,10 +164,10 @@ main : context {
}
: inline_push {
regex \= (@)
regex \= ([\#]+\s*\[[^\]]\s*])
styles [] = .law_subtitle;
: pop {
regex \= (@)
regex \= (\n)
styles [] = .law_subtitle;
}
: pattern {
@ -177,12 +177,12 @@ main : context {
}
: pattern {
regex \= ([^\/])
regex \= ([^`])
styles [] = .law;
}
: push {
regex \= (\/\*)
regex \= (```catala)
styles [] = .code_delimiter;
context [] = code;
}
@ -193,7 +193,7 @@ main : context {
code : context {
: pop {
regex \= (\*\/)
regex \= (```)
styles [] = .code_delimiter;
}

View File

@ -14,14 +14,15 @@ class CatalaNvLexer(RegexLexer):
tokens = {
'root': [
(u'(@@)', bygroups(Generic.Heading), 'main__1'),
(u'(@)', bygroups(Generic.Heading), 'main__2'),
(u'([^\\/\\n\\r])', bygroups(Text)),
(u'(\\/\\*)', bygroups(Text), 'code'),
(u'([\#]+)', bygroups(Generic.Heading), 'main__1'),
(u'([\#]+\s*\[[^\]]\s*])', bygroups(Generic.Heading), 'main__2'),
(u'([^`\\n\\r])', bygroups(Text)),
(u'(```catala)', bygroups(Text), 'code'),
('(\n|\r|\r\n)', Text),
('.', Text),
],
'code': [
(u'(```)', bygroups(Text), 'root'),
(u'(\\s*\\#.*$)', bygroups(Comment.Single)),
(u'(param)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)',
bygroups(Keyword.Declaration, Text, Name.Variable)),
@ -44,11 +45,13 @@ class CatalaNvLexer(RegexLexer):
('.', Text),
],
'main__1': [
(u'(\n)', bygroups(Generic.Heading), 'root'),
(u'(.)', bygroups(Generic.Heading)),
('(\n|\r|\r\n)', Text),
('.', Text),
],
'main__2': [
(u'(\n)', bygroups(Generic.Heading), 'root'),
(u'(.)', bygroups(Generic.Heading)),
('(\n|\r|\r\n)', Text),
('.', Text),

View File

@ -4,13 +4,13 @@
<!-- Generated via Iro -->
<dict>
<key>fileTypes</key>
<array>
<array>
<string>catala</string>
</array>
<key>name</key>
<string>catala_nv</string>
<key>patterns</key>
<array>
<array>
<dict>
<key>include</key>
<string>#main</string>
@ -25,10 +25,10 @@
<key>main</key>
<dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>begin</key>
<string>(@@)</string>
<string>([\#]+)</string>
<key>beginCaptures</key>
<dict>
<key>1</key>
@ -38,14 +38,14 @@
</dict>
</dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>include</key>
<string>#main__1</string>
</dict>
</array>
<key>end</key>
<string>(@@[\+]*)</string>
<string>(\n)</string>
<key>endCaptures</key>
<dict>
<key>1</key>
@ -57,7 +57,7 @@
</dict>
<dict>
<key>begin</key>
<string>(@)</string>
<string>([\#]+\s*\[[^\]]\s*\])</string>
<key>beginCaptures</key>
<dict>
<key>1</key>
@ -67,14 +67,14 @@
</dict>
</dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>include</key>
<string>#main__2</string>
</dict>
</array>
<key>end</key>
<string>(@)</string>
<string>(\n)</string>
<key>endCaptures</key>
<dict>
<key>1</key>
@ -86,13 +86,13 @@
</dict>
<dict>
<key>match</key>
<string>([^\/])</string>
<string>([^`])</string>
<key>name</key>
<string>entity.law.catala_nv</string>
</dict>
<dict>
<key>begin</key>
<string>(\/\*)</string>
<string>(```catala)</string>
<key>beginCaptures</key>
<dict>
<key>1</key>
@ -102,14 +102,14 @@
</dict>
</dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>include</key>
<string>#code</string>
</dict>
</array>
<key>end</key>
<string>(\*\/)</string>
<string>(```)</string>
<key>endCaptures</key>
<dict>
<key>1</key>
@ -124,7 +124,7 @@
<key>code</key>
<dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>match</key>
<string>(\s*\#.*$)</string>
@ -262,7 +262,7 @@
<key>main__1</key>
<dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>match</key>
<string>(.)</string>
@ -274,7 +274,7 @@
<key>main__2</key>
<dict>
<key>patterns</key>
<array>
<array>
<dict>
<key>match</key>
<string>(.)</string>
@ -286,4 +286,3 @@
</dict>
</dict>
</plist>

View File

@ -1,11 +1,11 @@
@Article@
## [Article]
/*
```catala
new scope A:
param list content set int
param list_high_count content int
scope A:
def list := [0; 5; 6; 7; 1; 64; 12]
def list_high_count := number for m in list of (m >=$ $7)
*/
def list_high_count := number for m in list of (m >=$ $7)
```

View File

@ -1,14 +1,14 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content set money
param x content set money
scope A:
def x := [$0; $4 +$ $5; $8 *$ 0.65]
new scope B:
param a scope A
param a scope A
param max content money
param min content money
param y content money
@ -19,4 +19,4 @@ scope B:
def min := minimum money init $20 for m in a.x of m +$ $5
def y := sum money for m in a.x of (m +$ $1)
def z := number for m in a.x of (m >=$ $8.95)
*/
```

View File

@ -1,12 +1,12 @@
@Article@
## [Article]
/*
new struct S:
data id content int
```catala
new struct S:
data id content int
data income content money
new scope A:
param x content set S
param x content set S
scope A:
def x := [
@ -16,11 +16,11 @@ scope A:
]
new scope B:
param a scope A
param a scope A
param argmax content S
param argmin content S
scope B:
def argmax := content maximum money init S { -- id: -1 --income: $0 } for m in a.x of (m.income *$ 2.0)
def argmin := content minimum money init S { -- id: -1 --income: $20 } for m in a.x of (m.income +$ $5)
*/
```

View File

@ -1,18 +1,18 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content set money
param x content set money
scope A:
def x := [$0; $4 +$ $5; $8 *$ 0.65]
new scope B:
param a scope A
param a scope A
param y content set money
param z content set bool
scope B:
def y := filter for m in a.x of (m >=$ $4.95)
def z := map for m in a.x of (m >=$ $4.95)
*/
```

View File

@ -1,14 +1,14 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content set int
param x content set int
scope A:
def x := [0; 4+5; 8*8]
new scope B:
param a scope A
param a scope A
param v content int
param w content bool
param y content bool
@ -19,4 +19,4 @@ scope B:
def w := 64 in a.x
def y := exists m in a.x such that m = 9
def z := for all m in a.x we have m > 0
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new scope TestBool :
param foo content bool
param bar content int
@ -9,4 +9,4 @@ scope TestBool :
def bar := 1
def foo [| bar >= 0 |] := true
def foo [| bar < 0 |] := false
*/
```

View File

@ -1,17 +1,17 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content date
param y content date
param y content date
param z content bool
param z2 content bool
param z3 content duration
param z3 content duration
scope A:
def x := |01/01/2019|
def y := |09/30/2002|
def z := y +@ (x -@ y) = x
def z3 := x -@ y
def z3 := x -@ y
def z2 := z3 = 5937 day
*/
```

View File

@ -1,13 +1,13 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content date
param y content date
param y content date
param z content duration
scope A:
def x := |01/01/2019|
def y := |09/30/2002|
def z := x -@ y
*/
```

View File

@ -1,9 +1,9 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content dec
param y content dec
param x content dec
param y content dec
param z content dec
param a content dec
@ -12,4 +12,4 @@ scope A:
def y := -. 4.36829778705320654980
def z := 654265429805103220650980650.5705405106540
def a := x /. y *. (x +. y) *. (x *. x *. z *. z)
*/
```

View File

@ -1,13 +1,13 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content dec
param y content dec
param x content dec
param y content dec
param z content dec
scope A:
def x := 84.648665
def y := 4.368297
def z := x /. y
*/
def z := x /. y
```

View File

@ -1,10 +1,10 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content int
scope A:
def x [|true|] := 1
def x [|true|] := 0
*/
```

View File

@ -1,10 +1,10 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content int
param y content bool
scope A:
def x := 1
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content int
param y content int
@ -10,4 +10,4 @@ scope A:
def x [|y = 2|] := 1
def x [|y = 3|] := 1
def x [|y = 4|] := 1
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new enum E:
-- Case1
@ -12,4 +12,4 @@ new scope A:
scope A:
def e := Case1
*/
```catala

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new enum E:
-- Case1 content int
-- Case2 content bool
@ -11,9 +11,9 @@ new scope A:
param out content bool
scope A:
def out := match e with
def out := match e with
-- Case1 of i : i = 0
-- Case2 of b : b
-- Case2 of b : b
-- Case3 : false
-- Case3 : true
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new enum E:
-- Case1 content int
-- Case2 content bool
@ -11,8 +11,7 @@ new scope A:
param out content bool
scope A:
def out := match e with
def out := match e with
-- Case1 of i : i = 0
-- Case2 of b : b
*/
-- Case2 of b : b
```

View File

@ -1,11 +1,11 @@
[ERROR] The constructor Case3 of enum E is missing from this pattern matching
[ERROR]
[ERROR]
[ERROR] --> test_enum/bad/missing_case.catala
[ERROR] |
[ERROR] 14 | def out := match e with
[ERROR] | ^^^^^^^^^^^^
[ERROR] |
[ERROR] 14 | def out := match e with
[ERROR] | ^^^^^^^^^^^
[ERROR] 15 | -- Case1 of i : i = 0
[ERROR] | ^^^^^^^^^^^^^^^^^^^^^
[ERROR] 16 | -- Case2 of b : b
[ERROR] 16 | -- Case2 of b : b
[ERROR] | ^^^^^^^^^^^^^^^^^^
[ERROR] + Article

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new enum E:
-- Case1 content int
-- Case2
@ -26,4 +26,4 @@ scope A:
scope B:
def x := Case2
def y := x with Case3
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new enum E:
-- Case1
-- Case2
@ -16,4 +16,4 @@ param y content bool
scope A:
def x := Case1
def y := x with Case3
*/
```

View File

@ -1,6 +1,6 @@
@Test@
## [Test]
/*
```catala
new enum E:
-- Case1
-- Case2
@ -15,4 +15,4 @@ param y content bool
scope A:
def x := Case1
def y := x with Case3
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new enum E:
-- Case1 content int
-- Case2
@ -13,4 +13,4 @@ new scope A:
scope A:
def x := Case1 content 2
def y := x with Case3
*/
```

View File

@ -1,12 +1,12 @@
@Article@
## [Article]
/*
```catala
new enum E:
-- Case1 content int
-- Case2 content bool
-- Case3
new enum F:
new enum F:
-- Case4
new scope A:
@ -14,9 +14,9 @@ new scope A:
param out content bool
scope A:
def out := match e with
def out := match e with
-- Case1 of i : i = 0
-- Case2 of b : b
-- Case2 of b : b
-- Case3 : false
-- Case4 : true
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new enum E:
-- Case1
@ -19,4 +19,4 @@ scope A:
def x := match f with
-- F.Case1 of i : i
-- Case2 : 3
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new enum E:
-- Case1 content int
-- Case2
@ -14,4 +14,4 @@ scope A:
def x := Case1 content 2
def y := x with Case1
def z := x with Case2
*/
```

View File

@ -1,17 +1,17 @@
@Article@
## [Article]
/*
```catala
new enum E:
-- Case1 content int
-- Case2
new scope A:
param x content E
param y content int
param y content int
scope A:
def x := Case1 content 2
def y := match x with
def y := match x with
-- Case1 of i : 42
-- Case2 : 43
*/
```

View File

@ -1,6 +1,6 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
@ -9,6 +9,6 @@ scope A:
def x := 1
exception
exception
def x := 2
*/
```

View File

@ -1,14 +1,14 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
param y content int
param y content int
scope A:
label base_y
label base_y
def y := 0
exception base_y
def x := 1
*/
```

View File

@ -1,6 +1,6 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
@ -14,6 +14,6 @@ scope A:
def x := 1
label exception_exception_x
exception exception_x
exception exception_x
def x := 2
*/
```

View File

@ -1,10 +1,10 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
scope A:
exception
exception
def x := 1
*/
```

View File

@ -1,6 +1,6 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
param y content int
@ -8,7 +8,7 @@ new scope A:
scope A:
def x := 0
exception
exception
def x := 1
def y := 2
@ -17,4 +17,4 @@ scope A:
exception
def y := 3
*/
```

View File

@ -1,13 +1,13 @@
[ERROR] This exception can refer to several definitions. Try using labels to disambiguate
[ERROR]
[ERROR]
[ERROR] --> test_exception/bad/ambiguous_unlabeled_exception.catala
[ERROR] |
[ERROR] |
[ERROR] 10 | def x := 1
[ERROR] |
[ERROR] 11 |
[ERROR] |
[ERROR] 12 | exception
[ERROR] | ^^^^^^^^^^
[ERROR] |
[ERROR] 11 |
[ERROR] |
[ERROR] 12 | exception
[ERROR] | ^^^^^^^^^
[ERROR] 13 | def x := 2
[ERROR] | ^^^^^^^^^^^
[ERROR] + Test

View File

@ -1,11 +1,11 @@
[ERROR] This exception does not have a corresponding definition
[ERROR]
[ERROR]
[ERROR] --> test_exception/bad/missing_unlabeled_definition.catala
[ERROR] |
[ERROR] |
[ERROR] 7 | scope A:
[ERROR] |
[ERROR] 8 | exception
[ERROR] | ^^^^^^^^^^
[ERROR] |
[ERROR] 8 | exception
[ERROR] | ^^^^^^^^^
[ERROR] 9 | def x := 1
[ERROR] | ^^^^^^^^^^^
[ERROR] + Test

View File

@ -1,11 +1,11 @@
@Test@
## [Test]
/*
```catala
new scope A:
param y content int
scope A:
label base_y
label base_y
exception base_y
def y := 0
*/
```

View File

@ -1,6 +1,6 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
@ -8,9 +8,9 @@ scope A:
label base_x
def x := 0
exception base_x
exception base_x
def x := 1
exception base_x
exception base_x
def x := 2
*/
```

View File

@ -1,6 +1,6 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
@ -8,6 +8,6 @@ scope A:
label base_x
def x := 0
exception base_x
exception base_x
def x := 1
*/
```

View File

@ -1,6 +1,6 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
@ -9,9 +9,9 @@ scope A:
def x := 0
label exception_x
exception base_x
exception base_x
def x := 1
exception exception_x
exception exception_x
def x := 2
*/
```

View File

@ -1,15 +1,15 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
scope A:
def x := 0
*/
```
/*
```catala
scope A:
exception
def x := 1
*/
```

View File

@ -1,6 +1,6 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
param y content int
@ -8,11 +8,11 @@ new scope A:
scope A:
def x := 0
exception
exception
def x := 1
def y := 2
exception
def y := 3
*/
```

View File

@ -1,12 +1,12 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
scope A:
def x := 0
exception
exception
def x := 1
*/
```

View File

@ -1,6 +1,6 @@
@Test@
## [Test]
/*
```catala
new scope A:
param x content int
param y content int
@ -15,4 +15,4 @@ scope A:
def x := 0
def y := 3
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new scope S:
param f content int fun of int
param b content bool
@ -17,6 +17,6 @@ scope S:
def out := f of 5
scope R:
def s.f of x := x + x * x
def s.f of x := x + x * x
def r := s.out
*/
```

View File

@ -1,9 +1,9 @@
@ Article @
## [ Article ]
/*
```catala
new scope RecursiveFunc:
param f content int fun of int
param f content int fun of int
scope RecursiveFunc:
def f of x := f of x + 1
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new scope S:
param f content int fun of int
param b content bool
@ -17,6 +17,6 @@ scope S:
def out := f of 5
scope R:
def s.f of x := x + x * x
def s.f of x := x + x * x
def r := s.out
*/
```catala

View File

@ -1,13 +1,13 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content money
param y content money
param y content money
param z content money
scope A:
def x := $123.54
def y := $8548,650.96
def z := (x *$ y)
*/
```

View File

@ -1,13 +1,13 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content money
param y content money
param y content money
param z content money
scope A:
def x := $123.54
def y := $8548,650.96
def z := $250,000,000 *$ ((x /$ y) *. 0.2 %)
*/
```

View File

@ -1,6 +1,6 @@
@Article@
## [Article]
/*
```catala
new scope A:
param x content int
param u content bool
@ -28,4 +28,4 @@ scope C:
def a.x := 2
def b.y := 3
def z := 2
*/
```

View File

@ -1,10 +1,10 @@
@ Article @
## [ Article ]
/*
```catala
new scope A :
param x content int
param y content int
param z content int
param x content int
param y content int
param z content int
scope A:
def y [|x < 0|] := - x
@ -12,4 +12,4 @@ scope A:
def z [|y >= 1|] := 10 / y
def z [|y < 1|] := y
def x := z
*/
```

View File

@ -1,9 +1,9 @@
@ Article @
## [ Article ]
/*
```catala
new scope A:
param b scope B
param x content int
param x content int
new scope B:
param a scope A
@ -14,4 +14,4 @@ scope A:
scope B:
def y := a.x
*/
```

Some files were not shown because too many files have changed in this diff Show More