123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202(* 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. *)(** Ssource files to be compiled *)letsource_files:stringlistref=ref[](** Prints debug information *)letdebug_flag=reffalse(* Styles the terminal output *)letstyle_flag=reftrue(* Max number of digits to show for decimal results *)letmax_prec_digits=ref20lettrace_flag=reffalseopenCmdlinerletfile=Arg.(required&pos1(somefile)None&info[]~docv:"FILE"~doc:"Catala master file to be compiled")letdebug=Arg.(value&flag&info["debug";"d"]~doc:"Prints debug information")letunstyled=Arg.(value&flag&info["unstyled"]~doc:"Removes styling from terminal output")lettrace_opt=Arg.(value&flag&info["trace";"t"]~doc:"Displays a trace of the intepreter's computation")letwrap_weaved_output=Arg.(value&flag&info["wrap";"w"]~doc:"Wraps literate programming output with a minimal preamble")letbackend=Arg.(required&pos0(somestring)None&info[]~docv:"BACKEND"~doc:"Backend selection among: LaTeX, Makefile, Html, Interpret")typebackend_option=Latex|Makefile|Html|Runletlanguage=Arg.(value&opt(somestring)None&info["l";"language"]~docv:"LANG"~doc:"Input language among: en, fr, non-verbose (default non-verbose)")letmax_prec_digits_opt=Arg.(value&opt(someint)None&info["p";"max_digits_printed"]~docv:"LANG"~doc:"Maximum number of significant digits printed for decimal results (default 20)")letex_scope=Arg.(value&opt(somestring)None&info["s";"scope"]~docv:"SCOPE"~doc:"Scope to be executed")typefrontend_lang=[`Fr|`En|`NonVerbose]typebackend_lang=[`Fr|`En]letto_backend_lang(lang:frontend_lang):backend_lang=matchlangwith`En|`NonVerbose->`En|`Fr->`Frletoutput=Arg.(value&opt(somestring)None&info["output";"o"]~docv:"OUTPUT"~doc:"$(i, OUTPUT) is the file that will contain the extracted output (for compiler backends)")letpygmentize_loc=Arg.(value&opt(somestring)None&info["pygmentize"]~docv:"PYGMENTIZE"~doc:"Location of a custom pygmentize executable for LaTeX source code highlighting")letcatala_tf=Term.(constf$file$debug$unstyled$wrap_weaved_output$pygmentize_loc$backend$language$max_prec_digits_opt$trace_opt$ex_scope$output)letinfo=letdoc="Compiler for Catala, a specification language for tax and social benefits computation rules."inletman=[`SManpage.s_description;`P"Catala is a domain-specific language for deriving faithful-by-construction algorithms \
from legislative texts.";`SManpage.s_authors;`P"Denis Merigoux <denis.merigoux@inria.fr>";`P"Nicolas Chataing <nicolas.chataing@ens.fr>";`SManpage.s_examples;`P"Typical usage:";`Pre"catala LaTeX file.catala";`SManpage.s_bugs;`P"Please file bug reports at https://github.com/CatalaLang/catala/issues";]inletexits=Term.default_exits@[Term.exit_info~doc:"on error."1]inTerm.info"catala"~version:(matchBuild_info.V1.version()with|None->"n/a"|Somev->Build_info.V1.Version.to_stringv)~doc~exits~man(**{1 Terminal formatting}*)(**{2 Markers}*)letprint_with_style(styles:ANSITerminal.stylelist)(str:('a,unit,string)format)=if!style_flagthenANSITerminal.sprintfstylesstrelsePrintf.sprintfstr(** Prints [\[DEBUG\]] in purple on the terminal standard output *)letdebug_marker()=print_with_style[ANSITerminal.Bold;ANSITerminal.magenta]"[DEBUG] "(** Prints [\[ERROR\]] in red on the terminal error output *)leterror_marker()=print_with_style[ANSITerminal.Bold;ANSITerminal.red]"[ERROR] "(** Prints [\[WARNING\]] in yellow on the terminal standard output *)letwarning_marker()=print_with_style[ANSITerminal.Bold;ANSITerminal.yellow]"[WARNING] "(** Prints [\[RESULT\]] in green on the terminal standard output *)letresult_marker()=print_with_style[ANSITerminal.Bold;ANSITerminal.green]"[RESULT] "(** Prints [\[LOG\]] in red on the terminal error output *)letlog_marker()=print_with_style[ANSITerminal.Bold;ANSITerminal.black]"[LOG] "(**{2 Printers}*)(** All the printers below print their argument after the correct marker *)letconcat_with_line_depending_prefix_and_suffix(prefix:int->string)(suffix:int->string)(ss:stringlist)=matchsswith|hd::rest->letout,_=List.fold_left(fun(acc,i)s->((acc^prefixi^s^ifi=List.lengthss-1then""elsesuffixi),i+1))((prefix0^hd^if0=List.lengthss-1then""elsesuffix0),1)restinout|[]->prefix0(** The int argument of the prefix corresponds to the line number, starting at 0 *)letadd_prefix_to_each_line(s:string)(prefix:int->string)=concat_with_line_depending_prefix_and_suffix(funi->prefixi)(fun_->"\n")(String.split_on_char'\n's)letdebug_print(s:string)=if!debug_flagthenbeginPrintf.printf"%s\n"(add_prefix_to_each_lines(fun_->debug_marker()));flushstdout;flushstdoutendleterror_print(s:string)=Printf.eprintf"%s\n"(add_prefix_to_each_lines(fun_->error_marker()));flushstderr;flushstderrletwarning_print(s:string)=Printf.printf"%s\n"(add_prefix_to_each_lines(fun_->warning_marker()));flushstdout;flushstdoutletresult_print(s:string)=Printf.printf"%s\n"(add_prefix_to_each_lines(fun_->result_marker()));flushstdout;flushstdoutletlog_print(s:string)=Printf.printf"%s\n"(add_prefix_to_each_lines(fun_->log_marker()));flushstdout;flushstdout