From 9fa5f91e3aa19a6c3d562ae419f7a82c13c5eb1d Mon Sep 17 00:00:00 2001 From: Louis Gesbert Date: Fri, 9 Aug 2024 11:10:47 +0200 Subject: [PATCH] Python printer: add some parens to be safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I can't find where the line cut triggering the error at https://github.com/CatalaLang/catala/actions/runs/10304111306/job/28522272547?pr=666 came from: ``` /home/ocaml/french-law/_python_venv/lib/python3.12/site-packages/french_law/Aides_logement.py:27785: error: invalid syntax [syntax] ``` the file at this point contains: ``` def traitement_aide_finale_montee_en_charge_saint_pierre_miquelon1( aide_finale4:Money): → traitement_aide_finale_montee_en_charge_saint_pierre_miquelon4 = handle_exceptions( [], [] ) ``` This workaround adds parens after `=`, which ensures the syntax will be correct. --- compiler/scalc/to_python.ml | 6 +- tests/backends/python_name_clash.catala_en | 74 ++++---- .../good/toplevel_defs.catala_en | 175 +++++++++--------- 3 files changed, 129 insertions(+), 126 deletions(-) diff --git a/compiler/scalc/to_python.ml b/compiler/scalc/to_python.ml index 189271e5..0a02f0f8 100644 --- a/compiler/scalc/to_python.ml +++ b/compiler/scalc/to_python.ml @@ -356,7 +356,7 @@ let rec format_statement ctx (fmt : Format.formatter) (s : stmt Mark.pos) : unit assert false (* We don't need to declare variables in Python *) | SLocalDef { name = v; expr = e; _ } | SLocalInit { name = v; expr = e; _ } -> - Format.fprintf fmt "@[%a = %a@]" VarName.format (Mark.remove v) + Format.fprintf fmt "@[%a = (%a)@]" VarName.format (Mark.remove v) (format_expression ctx) e | STryWEmpty { try_block = try_b; with_block = catch_b } -> Format.fprintf fmt "@[try:@ %a@]@,@[except Empty:@ %a@]" @@ -420,9 +420,7 @@ let rec format_statement ctx (fmt : Format.formatter) (s : stmt Mark.pos) : unit and format_block ctx (fmt : Format.formatter) (b : block) : unit = Format.pp_open_vbox fmt 0; - Format.pp_print_list - ~pp_sep:(fun fmt () -> Format.fprintf fmt "@,") - (format_statement ctx) fmt + Format.pp_print_list (format_statement ctx) fmt (List.filter (fun s -> match Mark.remove s with SLocalDecl _ -> false | _ -> true) b); diff --git a/tests/backends/python_name_clash.catala_en b/tests/backends/python_name_clash.catala_en index 5423b029..d3d31afc 100644 --- a/tests/backends/python_name_clash.catala_en +++ b/tests/backends/python_name_clash.catala_en @@ -90,31 +90,31 @@ class BIn: def some_name(some_name_in:SomeNameIn): - i = some_name_in.i_in - o4 = handle_exceptions([], []) + i = (some_name_in.i_in) + o4 = (handle_exceptions([], [])) if o4 is None: if True: - o3 = (i + integer_of_string("1")) + o3 = ((i + integer_of_string("1"))) else: - o3 = None + o3 = (None) else: x = o4 - o3 = x - o5 = handle_exceptions( - [SourcePosition( - filename="tests/backends/python_name_clash.catala_en", - start_line=10, start_column=23, end_line=10, end_column=28, - law_headings=[])], - [o3] - ) + o3 = (x) + o5 = (handle_exceptions( + [SourcePosition( + filename="tests/backends/python_name_clash.catala_en", + start_line=10, start_column=23, + end_line=10, end_column=28, law_headings=[])], + [o3] + )) if o5 is None: if False: - o2 = None + o2 = (None) else: - o2 = None + o2 = (None) else: x = o5 - o2 = x + o2 = (x) if o2 is None: raise NoValue(SourcePosition( filename="tests/backends/python_name_clash.catala_en", @@ -122,35 +122,35 @@ def some_name(some_name_in:SomeNameIn): end_line=7, end_column=11, law_headings=[])) else: arg = o2 - o1 = arg - o = o1 + o1 = (arg) + o = (o1) return SomeName(o = o) def b(b_in:BIn): - result4 = handle_exceptions([], []) + result4 = (handle_exceptions([], [])) if result4 is None: if True: - result3 = integer_of_string("1") + result3 = (integer_of_string("1")) else: - result3 = None + result3 = (None) else: x = result4 - result3 = x - result5 = handle_exceptions( - [SourcePosition( - filename="tests/backends/python_name_clash.catala_en", - start_line=16, start_column=33, - end_line=16, end_column=34, law_headings=[])], - [result3] - ) + result3 = (x) + result5 = (handle_exceptions( + [SourcePosition( + filename="tests/backends/python_name_clash.catala_en", + start_line=16, start_column=33, + end_line=16, end_column=34, law_headings=[])], + [result3] + )) if result5 is None: if False: - result2 = None + result2 = (None) else: - result2 = None + result2 = (None) else: x = result5 - result2 = x + result2 = (x) if result2 is None: raise NoValue(SourcePosition( filename="tests/backends/python_name_clash.catala_en", @@ -158,14 +158,14 @@ def b(b_in:BIn): end_line=16, end_column=25, law_headings=[])) else: arg = result2 - result1 = arg - result = some_name(SomeNameIn(i_in = result1)) - result6 = SomeName(o = result.o) + result1 = (arg) + result = (some_name(SomeNameIn(i_in = result1))) + result6 = (SomeName(o = result.o)) if True: - some_name2 = result6 + some_name2 = (result6) else: - some_name2 = result6 - some_name1 = some_name2 + some_name2 = (result6) + some_name1 = (some_name2) return B(some_name = some_name1) ``` The above should *not* show `some_name = temp_some_name`, but instead `some_name_1 = ...` diff --git a/tests/name_resolution/good/toplevel_defs.catala_en b/tests/name_resolution/good/toplevel_defs.catala_en index 9232b6a7..c0249c91 100644 --- a/tests/name_resolution/good/toplevel_defs.catala_en +++ b/tests/name_resolution/good/toplevel_defs.catala_en @@ -441,9 +441,9 @@ def glob4(x:Money, y:Decimal): return ((decimal_of_money(x) * y) + decimal_of_string("10.")) def glob5_init(): - x = (decimal_of_integer(integer_of_string("2")) * - decimal_of_string("3.")) - y = decimal_of_string("1000.") + x = ((decimal_of_integer(integer_of_string("2")) * + decimal_of_string("3."))) + y = (decimal_of_string("1000.")) return (x * y) glob5 = (glob5_init()) @@ -456,31 +456,32 @@ glob6 = ( ) def s2(s2_in:S2In): - a4 = handle_exceptions([], []) + a4 = (handle_exceptions([], [])) if a4 is None: if True: - a3 = (glob3(money_of_cents_string("4400")) + - decimal_of_string("100.")) + a3 = ((glob3(money_of_cents_string("4400")) + + decimal_of_string("100."))) else: - a3 = None + a3 = (None) else: x = a4 - a3 = x - a5 = handle_exceptions( - [SourcePosition( - filename="tests/name_resolution/good/toplevel_defs.catala_en", - start_line=53, start_column=24, end_line=53, end_column=43, - law_headings=["Test toplevel function defs"])], - [a3] - ) + a3 = (x) + a5 = (handle_exceptions( + [SourcePosition( + filename="tests/name_resolution/good/toplevel_defs.catala_en", + start_line=53, start_column=24, + end_line=53, end_column=43, + law_headings=["Test toplevel function defs"])], + [a3] + )) if a5 is None: if False: - a2 = None + a2 = (None) else: - a2 = None + a2 = (None) else: x = a5 - a2 = x + a2 = (x) if a2 is None: raise NoValue(SourcePosition( filename="tests/name_resolution/good/toplevel_defs.catala_en", @@ -489,37 +490,38 @@ def s2(s2_in:S2In): law_headings=["Test toplevel function defs"])) else: arg = a2 - a1 = arg - a = a1 + a1 = (arg) + a = (a1) return S2(a = a) def s3(s3_in:S3In): - a4 = handle_exceptions([], []) + a4 = (handle_exceptions([], [])) if a4 is None: if True: - a3 = (decimal_of_string("50.") + + a3 = ((decimal_of_string("50.") + glob4(money_of_cents_string("4400"), - decimal_of_string("55."))) + decimal_of_string("55.")))) else: - a3 = None + a3 = (None) else: x = a4 - a3 = x - a5 = handle_exceptions( - [SourcePosition( - filename="tests/name_resolution/good/toplevel_defs.catala_en", - start_line=74, start_column=24, end_line=74, end_column=47, - law_headings=["Test function def with two args"])], - [a3] - ) + a3 = (x) + a5 = (handle_exceptions( + [SourcePosition( + filename="tests/name_resolution/good/toplevel_defs.catala_en", + start_line=74, start_column=24, + end_line=74, end_column=47, + law_headings=["Test function def with two args"])], + [a3] + )) if a5 is None: if False: - a2 = None + a2 = (None) else: - a2 = None + a2 = (None) else: x = a5 - a2 = x + a2 = (x) if a2 is None: raise NoValue(SourcePosition( filename="tests/name_resolution/good/toplevel_defs.catala_en", @@ -528,35 +530,36 @@ def s3(s3_in:S3In): law_headings=["Test function def with two args"])) else: arg = a2 - a1 = arg - a = a1 + a1 = (arg) + a = (a1) return S3(a = a) def s4(s4_in:S4In): - a4 = handle_exceptions([], []) + a4 = (handle_exceptions([], [])) if a4 is None: if True: - a3 = (glob5 + decimal_of_string("1.")) + a3 = ((glob5 + decimal_of_string("1."))) else: - a3 = None + a3 = (None) else: x = a4 - a3 = x - a5 = handle_exceptions( - [SourcePosition( - filename="tests/name_resolution/good/toplevel_defs.catala_en", - start_line=98, start_column=24, end_line=98, end_column=34, - law_headings=["Test inline defs in toplevel defs"])], - [a3] - ) + a3 = (x) + a5 = (handle_exceptions( + [SourcePosition( + filename="tests/name_resolution/good/toplevel_defs.catala_en", + start_line=98, start_column=24, + end_line=98, end_column=34, + law_headings=["Test inline defs in toplevel defs"])], + [a3] + )) if a5 is None: if False: - a2 = None + a2 = (None) else: - a2 = None + a2 = (None) else: x = a5 - a2 = x + a2 = (x) if a2 is None: raise NoValue(SourcePosition( filename="tests/name_resolution/good/toplevel_defs.catala_en", @@ -565,35 +568,36 @@ def s4(s4_in:S4In): law_headings=["Test inline defs in toplevel defs"])) else: arg = a2 - a1 = arg - a = a1 + a1 = (arg) + a = (a1) return S4(a = a) def s5(s_in:SIn): - a4 = handle_exceptions([], []) + a4 = (handle_exceptions([], [])) if a4 is None: if True: - a3 = (glob1 * glob1) + a3 = ((glob1 * glob1)) else: - a3 = None + a3 = (None) else: x = a4 - a3 = x - a5 = handle_exceptions( - [SourcePosition( - filename="tests/name_resolution/good/toplevel_defs.catala_en", - start_line=18, start_column=24, end_line=18, end_column=37, - law_headings=["Test basic toplevel values defs"])], - [a3] - ) + a3 = (x) + a5 = (handle_exceptions( + [SourcePosition( + filename="tests/name_resolution/good/toplevel_defs.catala_en", + start_line=18, start_column=24, + end_line=18, end_column=37, + law_headings=["Test basic toplevel values defs"])], + [a3] + )) if a5 is None: if False: - a2 = None + a2 = (None) else: - a2 = None + a2 = (None) else: x = a5 - a2 = x + a2 = (x) if a2 is None: raise NoValue(SourcePosition( filename="tests/name_resolution/good/toplevel_defs.catala_en", @@ -602,32 +606,33 @@ def s5(s_in:SIn): law_headings=["Test basic toplevel values defs"])) else: arg = a2 - a1 = arg - a = a1 - b4 = handle_exceptions([], []) + a1 = (arg) + a = (a1) + b4 = (handle_exceptions([], [])) if b4 is None: if True: - b3 = glob6 + b3 = (glob6) else: - b3 = None + b3 = (None) else: x = b4 - b3 = x - b5 = handle_exceptions( - [SourcePosition( - filename="tests/name_resolution/good/toplevel_defs.catala_en", - start_line=19, start_column=24, end_line=19, end_column=29, - law_headings=["Test basic toplevel values defs"])], - [b3] - ) + b3 = (x) + b5 = (handle_exceptions( + [SourcePosition( + filename="tests/name_resolution/good/toplevel_defs.catala_en", + start_line=19, start_column=24, + end_line=19, end_column=29, + law_headings=["Test basic toplevel values defs"])], + [b3] + )) if b5 is None: if False: - b2 = None + b2 = (None) else: - b2 = None + b2 = (None) else: x = b5 - b2 = x + b2 = (x) if b2 is None: raise NoValue(SourcePosition( filename="tests/name_resolution/good/toplevel_defs.catala_en", @@ -636,7 +641,7 @@ def s5(s_in:SIn): law_headings=["Test basic toplevel values defs"])) else: arg = b2 - b1 = arg - b = b1 + b1 = (arg) + b = (b1) return S(a = a, b = b) ```