Big refactoring, better pdf build reproducibility

This commit is contained in:
Denis Merigoux 2020-04-17 12:29:30 +02:00
parent 08a2514232
commit 72bf4d01cb
15 changed files with 106 additions and 66 deletions

1
.gitmodules vendored
View File

@ -2,3 +2,4 @@
path = syntax_highlighting/pygments/pygments path = syntax_highlighting/pygments/pygments
url = git@github.com:pygments/pygments.git url = git@github.com:pygments/pygments.git
branch = master branch = master
ignore = dirty

View File

@ -4,13 +4,40 @@ build: format
install: install:
dune build @install dune build @install
format: format:
dune build @fmt --auto-promote | true dune build @fmt --auto-promote | true
test: build ALLOCATIONS_FAMILIALES_DIR=examples/allocations_familiales
dune exec src/main.exe -- --debug --backend LaTeX --output \
test/allocations_familiales.tex test/allocations_familiales.catala PYGMENTS_DIR=syntax_highlighting/pygments
PYGMENTIZE=$(PYGMENTS_DIR)/pygments/env/bin/pygmentize
ifdef $(PVC)
PVC_OPTION=-pvc
else
PVC_OPTION=
endif
LATEXMK=latexmk $(PVC_OPTION) -g -pdf -halt-on-error -shell-escape
%.tex: %.catala
dune exec src/main.exe -- --wrap_latex --debug --backend LaTeX \
--output $@ \
$^
%.pdf: %.tex $(PYGMENTIZE)
cd $(@D) && $(LATEXMK) $(%F)
$(PYGMENTIZE): $(PYGMENTS_DIR)/set_up_pygments.sh $(PYGMENTS_DIR)/catala.py
chmod +x $<
$<
allocations_familiales: $(ALLOCATIONS_FAMILIALES_DIR)/allocations_familiales.pdf
inspect: inspect:
gitinspector -f ml,mli,mly,iro,tex,catala,md,ir --grading gitinspector -f ml,mli,mly,iro,tex,catala,md,ir --grading

View File

@ -40,7 +40,7 @@
Impôts, allocations et pensions de retraite partagent un point commun : les règles de calcul des montants de ces transferts sociaux sont définies dans des textes législatifs. Ce sont ces textes en langage naturel, votés par le parlement ou décrétés par le gouvernement, qui servent de référence aux administrations et entreprises qui ont besoin de calculer ces montants de transferts. Cependant, ces calculs sont largement effectués automatiquement : il existe donc des programmes informatiques qui suivent les règles définies par la loi pour calculer le montant des transferts sociaux. Dès lors se pose la question suivante : comment être sûr que ces programmes informatiques, écrits dans des langages de programmation, implémentent fidèlement les règles décrites en langage naturel dans les textes législatifs ? Après avoir résumé l'état de l'art en la matière, nous proposons et décrivons un processus nouveau permettant d'atteindre une garantie de conformité bien supérieure. Nous illustrons ensuite la manière dont ce processus fonctionne sur l'exemple des allocations familiales. En fin de document, un questionnaire vous permet de nous transmettre vos remarques sur notre démarche et sur le processus. Impôts, allocations et pensions de retraite partagent un point commun : les règles de calcul des montants de ces transferts sociaux sont définies dans des textes législatifs. Ce sont ces textes en langage naturel, votés par le parlement ou décrétés par le gouvernement, qui servent de référence aux administrations et entreprises qui ont besoin de calculer ces montants de transferts. Cependant, ces calculs sont largement effectués automatiquement : il existe donc des programmes informatiques qui suivent les règles définies par la loi pour calculer le montant des transferts sociaux. Dès lors se pose la question suivante : comment être sûr que ces programmes informatiques, écrits dans des langages de programmation, implémentent fidèlement les règles décrites en langage naturel dans les textes législatifs ? Après avoir résumé l'état de l'art en la matière, nous proposons et décrivons un processus nouveau permettant d'atteindre une garantie de conformité bien supérieure. Nous illustrons ensuite la manière dont ce processus fonctionne sur l'exemple des allocations familiales. En fin de document, un questionnaire vous permet de nous transmettre vos remarques sur notre démarche et sur le processus.
\input{../doc/motivation} \input{../../doc/motivation}
\section{Implémentation des allocations familiales} \section{Implémentation des allocations familiales}
@ -50,7 +50,7 @@ Afin de mettre en pratique ces nouveaux concepts, nous vous proposons un exemple
\subsection{Guide de lecture} \subsection{Guide de lecture}
\input{../doc/reading_guide} \input{../../doc/reading_guide}
\subsection{Corpus législatif annoté} \subsection{Corpus législatif annoté}
@ -58,12 +58,12 @@ Les numéros de ligne à gauche servent uniquement de référence, leur numérot
n'est pas consécutive ici car elle respecte celle du fichier source à partir n'est pas consécutive ici car elle respecte celle du fichier source à partir
duquel a été généré ce document. duquel a été généré ce document.
\input{allocations_familiales} % \input{allocations_familiales}
\clearpage \clearpage
\section{Questionnaire de satisfaction} \section{Questionnaire de satisfaction}
\input{../doc/questionnaire} \input{../../doc/questionnaire}
\end{document} \end{document}

View File

@ -1,4 +1,4 @@
(lang dune 2.1) (lang dune 2.2)
(name catala) (name catala)
(version 0.1) (version 0.1)
(generate_opam_files true) (generate_opam_files true)

View File

@ -9,3 +9,4 @@ wrapper*.pdf
allocations_familiales*.tex allocations_familiales*.tex
_minted* _minted*
*.toc *.toc
*.pyg

View File

@ -25,11 +25,14 @@ let files =
let debug = Arg.(value & flag & info [ "debug"; "d" ] ~doc:"Prints debug information") let debug = Arg.(value & flag & info [ "debug"; "d" ] ~doc:"Prints debug information")
let wrap_latex_output =
Arg.(value & flag & info [ "wrap_latex"; "w" ] ~doc:"Wraps LaTeX output with preamble")
let backend = let backend =
Arg.( Arg.(
required required
& opt (some string) None & opt (some string) None
& info [ "backend"; "b" ] ~docv:"BACKEND" ~doc:"Backend selection: TeX") & info [ "backend"; "b" ] ~docv:"BACKEND" ~doc:"Backend selection: LaTeX")
let output = let output =
Arg.( Arg.(
@ -40,7 +43,7 @@ let output =
"$(i, OUTPUT) is the file that will contain the extracted function (for compiler \ "$(i, OUTPUT) is the file that will contain the extracted function (for compiler \
backends)") backends)")
let catala_t f = Term.(const f $ files $ debug $ backend $ output) let catala_t f = Term.(const f $ files $ debug $ wrap_latex_output $ backend $ output)
let info = let info =
let doc = let doc =

View File

@ -16,8 +16,8 @@ open Cli
module I = Ir module I = Ir
(** Entry function for the executable. Returns a negative number in case of error. *) (** Entry function for the executable. Returns a negative number in case of error. *)
let driver (source_files : string list) (debug : bool) (backend : string) (output_file : string) : let driver (source_files : string list) (debug : bool) (wrap_latex_output : bool) (backend : string)
int = (output_file : string) : int =
Cli.debug_flag := debug; Cli.debug_flag := debug;
Cli.debug_print "Reading files..."; Cli.debug_print "Reading files...";
let program = ref [] in let program = ref [] in
@ -44,8 +44,12 @@ let driver (source_files : string list) (debug : bool) (backend : string) (outpu
let weaved_output = let weaved_output =
String.concat "\n\n" (List.map (fun file -> Weave.ast_to_latex file) !program) String.concat "\n\n" (List.map (fun file -> Weave.ast_to_latex file) !program)
in in
let weaved_output =
if wrap_latex_output then Weave.wrap_latex weaved_output source_files else weaved_output
in
Cli.debug_print (Printf.sprintf "Writing to %s" output_file); Cli.debug_print (Printf.sprintf "Writing to %s" output_file);
let oc = open_out output_file in let oc = open_out output_file in
Printf.fprintf oc "%s" weaved_output; Printf.fprintf oc "%s" weaved_output;
close_out oc; close_out oc;
0 0

View File

@ -24,8 +24,51 @@ let pre_latexify (s : string) =
let s = R.substitute ~rex:percent ~subst:(fun _ -> "\\%") s in let s = R.substitute ~rex:percent ~subst:(fun _ -> "\\%") s in
let premier = R.regexp "1er" in let premier = R.regexp "1er" in
let s = R.substitute ~rex:premier ~subst:(fun _ -> "1\\textsuperscript{er}") s in let s = R.substitute ~rex:premier ~subst:(fun _ -> "1\\textsuperscript{er}") s in
let underscore = R.regexp "\\_" in
let s = R.substitute ~rex:underscore ~subst:(fun _ -> "\\_") s in
s s
let wrap_latex (code : string) (source_files : string list) =
Printf.sprintf
"\\documentclass[11pt, french, a4paper]{article}\n\n\
\\usepackage[T1]{fontenc}\n\
\\usepackage[utf8]{inputenc}\n\
\\usepackage[french]{babel}\n\
\\usepackage{lmodern}\n\
\\usepackage{minted}\n\
\\usepackage{textcomp}\n\
\\usepackage[hidelinks]{hyperref}\n\
\\usepackage[dvipsnames]{xcolor}\n\
\\usepackage{fullpage}\n\
\\usepackage[many]{tcolorbox}\n\n\
\\fvset{\n\
commandchars=\\\\\\{\\},\n\
numbers=left,\n\
framesep=3mm,\n\
frame=leftline,\n\
firstnumber=last,\n\
codes={\\catcode`\\$=3\\catcode`\\^=7}\n\
}\n\n\
\\title{\n\
Implémentation de texte législatif\n\
}\n\
\\author{\n\
Document généré par Catala version %s\n\
}\n\
\\begin{document}\n\
\\maketitle\n\n\
Fichiers sources tissés dans ce document : \n\
\\begin{itemize}%s\\end{itemize}\n\n\
\\[\\star\\star\\star\\]\\\\\n\
%s\n\n\
\\end{document}"
( match Build_info.V1.version () with
| None -> "n/a"
| Some v -> Build_info.V1.Version.to_string v )
(String.concat ","
(List.map (fun f -> Printf.sprintf "\\item\\texttt{%s}" (pre_latexify f)) source_files))
code
let source_file_item_to_latex (i : A.source_file_item) : string = let source_file_item_to_latex (i : A.source_file_item) : string =
match i with match i with
| A.LawHeading (title, precedence) -> | A.LawHeading (title, precedence) ->

View File

@ -0,0 +1,14 @@
#! /usr/bin/env bash
cd "$(dirname "$0")"
ln -s -f $(pwd)/catala.py pygments/pygments/lexers/catala.py
if grep -q "CatalaLexer" pygments/pygments/lexers/_mapping.py
then
:
else
sed -i "78i\\ 'CatalaLexer': ('pygments.lexers.catala', 'Catala', ('catala'), ('*.catala'), ('text/x-catala',))," pygments/pygments/lexers/_mapping.py
fi
cd pygments
virtualenv -p python3 env
source env/bin/activate
python3 setup.py install

View File

@ -1,5 +0,0 @@
build:
latexmk -g -pdf -halt-on-error -shell-escape wrapper.tex
build-thin:
latexmk -g -pdf -halt-on-error -shell-escape wrapper-thin.tex

View File

@ -1,48 +0,0 @@
\documentclass[11pt, french, a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[french]{babel}
\usepackage{lmodern}
\usepackage{minted}
\usepackage{textcomp}
\usepackage[hidelinks]{hyperref}
\usepackage[dvipsnames]{xcolor}
\usepackage{fullpage}
\usepackage[many]{tcolorbox}
\usepackage{draftwatermark}
\SetWatermarkText{Brouillon}
\SetWatermarkScale{1}
\SetWatermarkColor[gray]{0.85}
\fvset{
commandchars=\\\{\},
numbers=left,
framesep=3mm,
frame=leftline,
firstnumber=last,
codes={\catcode`\$=3\catcode`\^=7}
}
\title{
Proposition d'implémentation en programmation
littéraire du calcul des allocations familiales
}
\author{
Denis \bsc{Merigoux}\\Inria\and
Liane \bsc{Huttner}\\Université Panthéon-Sorbonne\and
Nicolas \bsc{Chataing}\\Inria -- École Normale Supérieure\and
}
\begin{document}
\maketitle
Les numéros de ligne à gauche servent uniquement de référence, leur numérotation
n'est pas consécutive ici car elle respecte celle du fichier source à partir
duquel a été généré ce document.
\input{allocations_familiales}
\end{document}