From 1230f787d661895bf94cc3a5efe1b8caf69c84ea Mon Sep 17 00:00:00 2001 From: Louis Gesbert Date: Wed, 7 Aug 2024 17:43:14 +0200 Subject: [PATCH] Renaming: use in the scalc translation and in Python --- compiler/driver.ml | 67 ++- compiler/driver.mli | 9 +- compiler/lcalc/to_ocaml.ml | 23 +- compiler/lcalc/to_ocaml.mli | 2 +- compiler/plugins/api_web.ml | 16 +- compiler/plugins/json_schema.ml | 3 +- compiler/plugins/python.ml | 3 +- compiler/scalc/from_lcalc.ml | 252 ++++---- compiler/scalc/from_lcalc.mli | 4 +- compiler/scalc/print.ml | 6 +- compiler/scalc/to_c.ml | 216 ++----- compiler/scalc/to_c.mli | 6 +- compiler/scalc/to_python.ml | 199 ++----- compiler/scalc/to_python.mli | 4 + compiler/shared_ast/expr.mli | 6 + compiler/shared_ast/program.ml | 45 +- compiler/shared_ast/program.mli | 10 +- tests/backends/output/simple.c | 482 +++++---------- tests/backends/python_name_clash.catala_en | 122 ++-- .../good/toplevel_defs.catala_en | 560 +++++++++--------- tests/scope/good/nothing.catala_en | 10 +- 21 files changed, 875 insertions(+), 1170 deletions(-) diff --git a/compiler/driver.ml b/compiler/driver.ml index 33143622..862858ca 100644 --- a/compiler/driver.ml +++ b/compiler/driver.ml @@ -228,8 +228,11 @@ module Passes = struct ~check_invariants ~(typed : ty mark) ~closure_conversion - ~monomorphize_types : - typed Lcalc.Ast.program * Scopelang.Dependency.TVertex.t list = + ~monomorphize_types + ~renaming : + typed Lcalc.Ast.program * + Scopelang.Dependency.TVertex.t list * + Expr.Renaming.context option = let prg, type_ordering = dcalc options ~includes ~optimize ~check_invariants ~typed in @@ -275,7 +278,19 @@ module Passes = struct prg, type_ordering) else prg, type_ordering in - prg, type_ordering + match renaming with + | None -> prg, type_ordering, None + | Some renaming -> + let prg, ren_ctx = Program.apply renaming prg in + let type_ordering = + let open Scopelang.Dependency.TVertex in + List.map + (function + | Struct s -> Struct (Expr.Renaming.struct_name ren_ctx s) + | Enum e -> Enum (Expr.Renaming.enum_name ren_ctx e)) + type_ordering + in + prg, type_ordering, Some ren_ctx let scalc options @@ -286,17 +301,30 @@ module Passes = struct ~keep_special_ops ~dead_value_assignment ~no_struct_literals - ~monomorphize_types : - Scalc.Ast.program * Scopelang.Dependency.TVertex.t list = - let prg, type_ordering = + ~monomorphize_types + ~renaming : + Scalc.Ast.program * Scopelang.Dependency.TVertex.t list * Expr.Renaming.context = + let prg, type_ordering, renaming_context = lcalc options ~includes ~optimize ~check_invariants ~typed:Expr.typed - ~closure_conversion ~monomorphize_types + ~closure_conversion ~monomorphize_types ~renaming + in + let renaming_context = match renaming_context with + | None -> Expr.Renaming.get_ctx { + reserved = []; + sanitize_varname = Fun.id; + reset_context_for_closed_terms = true; + skip_constant_binders = true; + constant_binder_name = None; + } + | Some r -> r in debug_pass_name "scalc"; ( Scalc.From_lcalc.translate_program - ~config:{ keep_special_ops; dead_value_assignment; no_struct_literals } + ~config:{ keep_special_ops; dead_value_assignment; no_struct_literals; + renaming_context } prg, - type_ordering ) + type_ordering, + renaming_context ) end module Commands = struct @@ -711,9 +739,9 @@ module Commands = struct closure_conversion monomorphize_types ex_scope_opt = - let prg, _ = + let prg, _, _ = Passes.lcalc options ~includes ~optimize ~check_invariants - ~closure_conversion ~typed ~monomorphize_types + ~closure_conversion ~typed ~monomorphize_types ~renaming:None in let _output_file, with_output = get_output_format options output in with_output @@ -759,9 +787,9 @@ module Commands = struct optimize check_invariants ex_scope_opt = - let prg, _ = + let prg, _, _ = Passes.lcalc options ~includes ~optimize ~check_invariants - ~closure_conversion ~monomorphize_types ~typed + ~closure_conversion ~monomorphize_types ~typed ~renaming:None in Interpreter.load_runtime_modules ~hashf:(Hash.finalise ~closure_conversion ~monomorphize_types) @@ -809,9 +837,10 @@ module Commands = struct check_invariants closure_conversion ex_scope_opt = - let prg, type_ordering = + let prg, type_ordering, _ = Passes.lcalc options ~includes ~optimize ~check_invariants ~typed:Expr.typed ~closure_conversion ~monomorphize_types:false + ~renaming:(Some Lcalc.To_ocaml.renaming) in let output_file, with_output = get_output_format options ~ext:".ml" output @@ -851,10 +880,10 @@ module Commands = struct no_struct_literals monomorphize_types ex_scope_opt = - let prg, _ = + let prg, _, _ = Passes.scalc options ~includes ~optimize ~check_invariants ~closure_conversion ~keep_special_ops ~dead_value_assignment - ~no_struct_literals ~monomorphize_types + ~no_struct_literals ~monomorphize_types ~renaming:None in let _output_file, with_output = get_output_format options output in with_output @@ -900,10 +929,11 @@ module Commands = struct optimize check_invariants closure_conversion = - let prg, type_ordering = + let prg, type_ordering, _ren_ctx = Passes.scalc options ~includes ~optimize ~check_invariants ~closure_conversion ~keep_special_ops:false ~dead_value_assignment:true ~no_struct_literals:false ~monomorphize_types:false + ~renaming:(Some Scalc.To_python.renaming) in let output_file, with_output = @@ -929,11 +959,12 @@ module Commands = struct $ Cli.Flags.closure_conversion) let c options includes output optimize check_invariants = - let prg, type_ordering = + let prg, type_ordering, _ren_ctx = Passes.scalc options ~includes ~optimize ~check_invariants ~closure_conversion:true ~keep_special_ops:true ~dead_value_assignment:false ~no_struct_literals:true ~monomorphize_types:true + ~renaming:(Some Scalc.To_c.renaming) in let output_file, with_output = get_output_format options ~ext:".c" output in Message.debug "Compiling program into C..."; diff --git a/compiler/driver.mli b/compiler/driver.mli index 3184a8e7..47f2bfce 100644 --- a/compiler/driver.mli +++ b/compiler/driver.mli @@ -53,7 +53,9 @@ module Passes : sig typed:'m Shared_ast.mark -> closure_conversion:bool -> monomorphize_types:bool -> - Shared_ast.typed Lcalc.Ast.program * Scopelang.Dependency.TVertex.t list + renaming : Shared_ast.Program.renaming option -> + Shared_ast.typed Lcalc.Ast.program * Scopelang.Dependency.TVertex.t list * + Shared_ast.Expr.Renaming.context option val scalc : Global.options -> @@ -65,7 +67,10 @@ module Passes : sig dead_value_assignment:bool -> no_struct_literals:bool -> monomorphize_types:bool -> - Scalc.Ast.program * Scopelang.Dependency.TVertex.t list + renaming: Shared_ast.Program.renaming option -> + Scalc.Ast.program * Scopelang.Dependency.TVertex.t list * + Shared_ast.Expr.Renaming.context + end module Commands : sig diff --git a/compiler/lcalc/to_ocaml.ml b/compiler/lcalc/to_ocaml.ml index 3a2199fd..d9e5f68e 100644 --- a/compiler/lcalc/to_ocaml.ml +++ b/compiler/lcalc/to_ocaml.ml @@ -130,6 +130,13 @@ let ocaml_keywords = "Oper"; ] +let renaming = + Program.renaming () + ~reserved:ocaml_keywords + (* TODO: add catala runtime built-ins as reserved as well ? *) + ~reset_context_for_closed_terms:true ~skip_constant_binders:true + ~constant_binder_name:(Some "_") ~namespaced_fields_constrs:true + let format_struct_name (fmt : Format.formatter) (v : StructName.t) : unit = (match StructName.path v with | [] -> () @@ -414,6 +421,7 @@ let rec format_expr (ctx : decl_ctx) (fmt : Format.formatter) (e : 'm expr) : Print.runtime_error er format_pos (Expr.pos e) | _ -> . +(* TODO: move [embed_foo] to [Foo.embed] to protect from name clashes *) let format_struct_embedding (fmt : Format.formatter) ((struct_name, struct_fields) : StructName.t * typ StructField.Map.t) = @@ -730,21 +738,6 @@ let format_program ~(hashf : Hash.t -> Hash.full) (p : 'm Ast.program) (type_ordering : Scopelang.Dependency.TVertex.t list) : unit = - let p, ren_ctx = - Program.rename_ids p - ~reserved:ocaml_keywords - (* TODO: add catala runtime built-ins as reserved as well ? *) - ~reset_context_for_closed_terms:true ~skip_constant_binders:true - ~constant_binder_name:(Some "_") ~namespaced_fields_constrs:true - in - let type_ordering = - let open Scopelang.Dependency.TVertex in - List.map - (function - | Struct s -> Struct (Expr.Renaming.struct_name ren_ctx s) - | Enum e -> Enum (Expr.Renaming.enum_name ren_ctx e)) - type_ordering - in Format.pp_open_vbox fmt 0; Format.pp_print_string fmt header; check_and_reexport_used_modules fmt ~hashf diff --git a/compiler/lcalc/to_ocaml.mli b/compiler/lcalc/to_ocaml.mli index ff853298..489343d7 100644 --- a/compiler/lcalc/to_ocaml.mli +++ b/compiler/lcalc/to_ocaml.mli @@ -17,7 +17,7 @@ open Catala_utils open Shared_ast -val ocaml_keywords : string list +val renaming : Program.renaming (** Formats a lambda calculus program into a valid OCaml program *) diff --git a/compiler/plugins/api_web.ml b/compiler/plugins/api_web.ml index e892ba3f..11d3128f 100644 --- a/compiler/plugins/api_web.ml +++ b/compiler/plugins/api_web.ml @@ -475,22 +475,10 @@ let run monomorphize_types _options = let options = Global.enforce_options ~trace:true () in - let prg, type_ordering = + let prg, type_ordering, _ = Driver.Passes.lcalc options ~includes ~optimize ~check_invariants ~closure_conversion ~typed:Expr.typed ~monomorphize_types - in - let prg, ren_ctx = - Program.rename_ids prg ~reserved:To_ocaml.ocaml_keywords - ~reset_context_for_closed_terms:true ~skip_constant_binders:true - ~constant_binder_name:None ~namespaced_fields_constrs:true - in - let type_ordering = - let open Scopelang.Dependency.TVertex in - List.map - (function - | Struct s -> Struct (Expr.Renaming.struct_name ren_ctx s) - | Enum e -> Enum (Expr.Renaming.enum_name ren_ctx e)) - type_ordering + ~renaming:(Some Lcalc.To_ocaml.renaming) in let jsoo_output_file, with_formatter = Driver.Commands.get_output_format options ~ext:"_api_web.ml" output diff --git a/compiler/plugins/json_schema.ml b/compiler/plugins/json_schema.ml index bdfc0e2b..51cda7a7 100644 --- a/compiler/plugins/json_schema.ml +++ b/compiler/plugins/json_schema.ml @@ -213,9 +213,10 @@ let run monomorphize_types ex_scope options = - let prg, _ = + let prg, _, _ = Driver.Passes.lcalc options ~includes ~optimize ~check_invariants ~closure_conversion ~typed:Expr.typed ~monomorphize_types + ~renaming:(Some Lcalc.To_ocaml.renaming) in let output_file, with_output = Driver.Commands.get_output_format options ~ext:"_schema.json" output diff --git a/compiler/plugins/python.ml b/compiler/plugins/python.ml index 1c167290..eedadd49 100644 --- a/compiler/plugins/python.ml +++ b/compiler/plugins/python.ml @@ -24,10 +24,11 @@ open Catala_utils let run includes output optimize check_invariants closure_conversion options = let open Driver.Commands in - let prg, type_ordering = + let prg, type_ordering, _ = Driver.Passes.scalc options ~includes ~optimize ~check_invariants ~closure_conversion ~keep_special_ops:false ~dead_value_assignment:true ~no_struct_literals:false ~monomorphize_types:false + ~renaming:(Some Scalc.To_python.renaming) in let output_file, with_output = get_output_format options ~ext:".py" output in diff --git a/compiler/scalc/from_lcalc.ml b/compiler/scalc/from_lcalc.ml index 41ced7ef..c3326954 100644 --- a/compiler/scalc/from_lcalc.ml +++ b/compiler/scalc/from_lcalc.ml @@ -24,6 +24,7 @@ type translation_config = { keep_special_ops : bool; dead_value_assignment : bool; no_struct_literals : bool; + renaming_context : Expr.Renaming.context; } type 'm ctxt = { @@ -33,6 +34,7 @@ type 'm ctxt = { context_name : string; config : translation_config; program_ctx : A.ctx; + ren_ctx : Expr.Renaming.context; } (* Expressions can spill out side effect, hence this function also returns a @@ -65,6 +67,36 @@ end let ( ++ ) = RevBlock.seq +let unbind ctxt bnd = + let v, body, ren_ctx = Expr.Renaming.unbind_in ctxt.ren_ctx bnd in + v, body, { ctxt with ren_ctx } + +let unmbind ctxt bnd = + let vs, body, ren_ctx = Expr.Renaming.unmbind_in ctxt.ren_ctx bnd in + vs, body, { ctxt with ren_ctx } + +let get_name ctxt s = + let name, ren_ctx = Expr.Renaming.new_id ctxt.ren_ctx s in + name, { ctxt with ren_ctx } + +let fresh_var ~pos ctxt name = + let v, ctxt = get_name ctxt name in + A.VarName.fresh (v, pos), ctxt + +let register_fresh_var ~pos ctxt x = + let v = A.VarName.fresh (Bindlib.name_of x, pos) in + let var_dict = Var.Map.add x v ctxt.var_dict in + v, { ctxt with var_dict } + +let register_fresh_func ~pos ctxt x = + let f = A.FuncName.fresh (Bindlib.name_of x, pos) in + let func_dict = Var.Map.add x f ctxt.func_dict in + f, { ctxt with func_dict } + +let register_fresh_arg ~pos ctxt (x, _) = + let _, ctxt = register_fresh_var ~pos ctxt x in + ctxt + let rec translate_expr_list ctxt args = let stmts, args = List.fold_left @@ -138,19 +170,11 @@ and translate_expr (ctxt : 'm ctxt) (expr : 'm L.expr) : RevBlock.t * A.expr = | EApp { f = EAbs { binder; tys }, binder_mark; args; tys = _ } -> (* This defines multiple local variables at the time *) let binder_pos = Expr.mark_pos binder_mark in - let vars, body = Bindlib.unmbind binder in + let vars, body, ctxt = unmbind ctxt binder in let vars_tau = List.map2 (fun x tau -> x, tau) (Array.to_list vars) tys in let ctxt = - { - ctxt with - var_dict = - List.fold_left - (fun var_dict (x, _) -> - Var.Map.add x - (A.VarName.fresh (Bindlib.name_of x, binder_pos)) - var_dict) - ctxt.var_dict vars_tau; - } + List.fold_left (register_fresh_arg ~pos:binder_pos) + ctxt vars_tau in let local_decls = List.fold_left @@ -215,18 +239,13 @@ and translate_expr (ctxt : 'm ctxt) (expr : 'm L.expr) : RevBlock.t * A.expr = raise (NotAnExpr { needs_a_local_decl = true }) | _ -> . with NotAnExpr { needs_a_local_decl } -> - let tmp_var = - A.VarName.fresh - ( (*This piece of logic is used to make the code more readable. TODO: - should be removed when - https://github.com/CatalaLang/catala/issues/240 is fixed. *) - (match ctxt.inside_definition_of with - | None -> ctxt.context_name - | Some v -> - let v = Mark.remove (A.VarName.get_info v) in - let tmp_rex = Re.Pcre.regexp "^temp_" in - if Re.Pcre.pmatch ~rex:tmp_rex v then v else "temp_" ^ v), - Expr.pos expr ) + let tmp_var, ctxt = + let name = + match ctxt.inside_definition_of with + | None -> ctxt.context_name + | Some v -> A.VarName.to_string v + in + fresh_var ctxt name ~pos:(Expr.pos expr) in let ctxt = { @@ -314,19 +333,12 @@ and translate_statements (ctxt : 'm ctxt) (block_expr : 'm L.expr) : A.block = | EApp { f = EAbs { binder; tys }, binder_mark; args; _ } -> (* This defines multiple local variables at the time *) let binder_pos = Expr.mark_pos binder_mark in - let vars, body = Bindlib.unmbind binder in + let vars, body, ctxt = unmbind ctxt binder in let vars_tau = List.map2 (fun x tau -> x, tau) (Array.to_list vars) tys in let ctxt = - { - ctxt with - var_dict = - List.fold_left - (fun var_dict (x, _) -> - Var.Map.add x - (A.VarName.fresh (Bindlib.name_of x, binder_pos)) - var_dict) - ctxt.var_dict vars_tau; - } + List.fold_left + (register_fresh_arg ~pos:binder_pos) + ctxt vars_tau in let local_decls = List.map @@ -369,26 +381,19 @@ and translate_statements (ctxt : 'm ctxt) (block_expr : 'm L.expr) : A.block = let rest_of_block = translate_statements ctxt body in local_decls @ List.flatten def_blocks @ rest_of_block | EAbs { binder; tys } -> - let vars, body = Bindlib.unmbind binder in - let binder_pos = Expr.pos block_expr in - let vars_tau = List.map2 (fun x tau -> x, tau) (Array.to_list vars) tys in - let closure_name = + let closure_name, ctxt = match ctxt.inside_definition_of with - | None -> A.VarName.fresh (ctxt.context_name, Expr.pos block_expr) - | Some x -> x + | None -> fresh_var ctxt ctxt.context_name ~pos:(Expr.pos block_expr) + | Some x -> x, ctxt in + let vars, body, ctxt = unmbind ctxt binder in + let binder_pos = Expr.pos block_expr in + let vars_tau = List.combine (Array.to_list vars) tys in let ctxt = - { - ctxt with - var_dict = - List.fold_left - (fun var_dict (x, _) -> - Var.Map.add x - (A.VarName.fresh (Bindlib.name_of x, binder_pos)) - var_dict) - ctxt.var_dict vars_tau; - inside_definition_of = None; - } + List.fold_left + (register_fresh_arg ~pos:binder_pos) + { ctxt with inside_definition_of = None } + vars_tau in let new_body = translate_statements ctxt body in [ @@ -419,14 +424,11 @@ and translate_statements (ctxt : 'm ctxt) (block_expr : 'm L.expr) : A.block = (fun _ arg new_args -> match Mark.remove arg with | EAbs { binder; tys } -> - let vars, body = Bindlib.unmbind binder in + let vars, body, ctxt = unmbind ctxt binder in assert (Array.length vars = 1); let var = vars.(0) in - let scalc_var = - A.VarName.fresh (Bindlib.name_of var, Expr.pos arg) - in - let ctxt = - { ctxt with var_dict = Var.Map.add var scalc_var ctxt.var_dict } + let scalc_var, ctxt = + register_fresh_var ctxt var ~pos:(Expr.pos arg) in let new_arg = translate_statements ctxt body in { @@ -556,35 +558,22 @@ and translate_statements (ctxt : 'm ctxt) (block_expr : 'm L.expr) : A.block = | _ -> . let rec translate_scope_body_expr - ~(config : translation_config) - (scope_name : ScopeName.t) - (program_ctx : A.ctx) - (var_dict : ('m L.expr, A.VarName.t) Var.Map.t) - (func_dict : ('m L.expr, A.FuncName.t) Var.Map.t) + ctx (scope_expr : 'm L.expr scope_body_expr) : A.block = let ctx = - { - func_dict; - var_dict; - inside_definition_of = None; - context_name = Mark.remove (ScopeName.get_info scope_name); - config; - program_ctx; - } + { ctx with inside_definition_of = None } in match scope_expr with | Last e -> let block, new_e = translate_expr ctx e in RevBlock.rebuild block ~tail:[A.SReturn (Mark.remove new_e), Mark.get new_e] | Cons (scope_let, next_bnd) -> ( - let let_var, scope_let_next = Bindlib.unbind next_bnd in - let let_var_id = - A.VarName.fresh (Bindlib.name_of let_var, scope_let.scope_let_pos) + let let_var, scope_let_next, ctx1 = unbind ctx next_bnd in + let let_var_id, ctx = + register_fresh_var ctx1 let_var ~pos:scope_let.scope_let_pos in - let new_var_dict = Var.Map.add let_var let_var_id var_dict in let next = - translate_scope_body_expr ~config scope_name program_ctx new_var_dict - func_dict scope_let_next + translate_scope_body_expr ctx scope_let_next in match scope_let.scope_let_kind with | Assertion -> @@ -615,7 +604,7 @@ let rec translate_scope_body_expr scope_let.scope_let_pos ) :: next)) -let translate_program ~(config : translation_config) (p : 'm L.program) : +let translate_program ~(config : translation_config) (p : 'm L.program): A.program = let modules = List.fold_left @@ -630,29 +619,41 @@ let translate_program ~(config : translation_config) (p : 'm L.program) : ModuleName.Map.empty (Program.modules_to_list p.decl_ctx.ctx_modules) in - let ctx = { A.decl_ctx = p.decl_ctx; A.modules } in - let (_, _, rev_items), _vlist = + let program_ctx = { A.decl_ctx = p.decl_ctx; A.modules } in + let ctxt = + { + func_dict = Var.Map.empty; + var_dict = Var.Map.empty; + inside_definition_of = None; + context_name = ""; + config; + program_ctx; + ren_ctx = config.renaming_context; + } + in + let (_, rev_items), _vlist = BoundList.fold_left - ~f:(fun (func_dict, var_dict, rev_items) code_item var -> + ~init:(ctxt, []) + ~f:(fun (ctxt, rev_items) code_item var -> match code_item with | ScopeDef (name, body) -> - let scope_input_var, scope_body_expr = - Bindlib.unbind body.scope_body_expr + let scope_input_var, scope_body_expr, ctxt1 = + unbind ctxt body.scope_body_expr in let input_pos = Mark.get (ScopeName.get_info name) in - let scope_input_var_id = - A.VarName.fresh (Bindlib.name_of scope_input_var, input_pos) - in - let var_dict_local = - Var.Map.add scope_input_var scope_input_var_id var_dict + let scope_input_var_id, ctxt = + register_fresh_var ctxt scope_input_var ~pos:input_pos in let new_scope_body = - translate_scope_body_expr ~config name ctx var_dict_local func_dict + translate_scope_body_expr + { ctxt with + context_name = Mark.remove (ScopeName.get_info name) } scope_body_expr in - let func_id = A.FuncName.fresh (Bindlib.name_of var, Pos.no_pos) in - ( Var.Map.add var func_id func_dict, - var_dict, + let func_id, ctxt1 = + register_fresh_func ctxt1 var ~pos:input_pos + in + ( ctxt1, A.SScope { Ast.scope_body_name = name; @@ -670,40 +671,32 @@ let translate_program ~(config : translation_config) (p : 'm L.program) : }; } :: rev_items ) - | Topdef (name, topdef_ty, (EAbs abs, _)) -> + | Topdef (name, topdef_ty, (EAbs abs, m)) -> (* Toplevel function def *) - let func_id = A.FuncName.fresh (Bindlib.name_of var, Pos.no_pos) in - let args_a, expr = Bindlib.unmbind abs.binder in - let args = Array.to_list args_a in - let args_id = - List.map2 - (fun v ty -> - let pos = Mark.get ty in - (A.VarName.fresh (Bindlib.name_of v, pos), pos), ty) - args abs.tys - in - let block, expr = + let (block, expr), args_id = + let args_a, expr, ctxt = unmbind ctxt abs.binder in + let args = Array.to_list args_a in + let rargs_id, ctxt = + List.fold_left2 + (fun (rargs_id, ctxt) v ty -> + let pos = Mark.get ty in + let id, ctxt = register_fresh_var ctxt v ~pos in + ((id, pos), ty) :: rargs_id, ctxt) + ([], ctxt) args abs.tys + in let ctxt = - { - func_dict; - var_dict = - List.fold_left2 - (fun map arg ((id, _), _) -> Var.Map.add arg id map) - var_dict args args_id; - inside_definition_of = None; + { ctxt with context_name = Mark.remove (TopdefName.get_info name); - config; - program_ctx = ctx; } in - translate_expr ctxt expr + translate_expr ctxt expr, List.rev rargs_id in let body_block = RevBlock.rebuild block ~tail:[A.SReturn (Mark.remove expr), Mark.get expr] in - ( Var.Map.add var func_id func_dict, - var_dict, + let func_id, ctxt = register_fresh_func ctxt var ~pos:(Expr.mark_pos m) in + ( ctxt, A.SFunc { var = func_id; @@ -721,30 +714,28 @@ let translate_program ~(config : translation_config) (p : 'm L.program) : :: rev_items ) | Topdef (name, topdef_ty, expr) -> (* Toplevel constant def *) - let var_id = A.VarName.fresh (Bindlib.name_of var, Pos.no_pos) in let block, expr = let ctxt = - { - func_dict; - var_dict; - inside_definition_of = None; + { ctxt with context_name = Mark.remove (TopdefName.get_info name); - config; - program_ctx = ctx; } in translate_expr ctxt expr in + let var_id, ctxt = + register_fresh_var ctxt var ~pos:(Mark.get (TopdefName.get_info name)) + in (* If the evaluation of the toplevel expr requires preliminary statements, we lift its computation into an auxiliary function *) - let rev_items = + let rev_items, ctxt = if (block :> (A.stmt * Pos.t) list) = [] then - A.SVar { var = var_id; expr; typ = topdef_ty } :: rev_items + A.SVar { var = var_id; expr; typ = topdef_ty } :: rev_items, ctxt else let pos = Mark.get expr in - let func_id = - A.FuncName.fresh (Bindlib.name_of var ^ "_aux", pos) + let func_name, ctxt = + get_name ctxt (A.VarName.to_string var_id ^ "_init") in + let func_id = A.FuncName.fresh (func_name, pos) in (* The list is being built in reverse order *) (* FIXME: find a better way than a function with no parameters... *) A.SVar @@ -765,14 +756,13 @@ let translate_program ~(config : translation_config) (p : 'm L.program) : A.func_return_typ = topdef_ty; }; } - :: rev_items + :: rev_items, + ctxt in - ( func_dict, + ( ctxt, (* No need to add func_id since the function will only be called right here *) - Var.Map.add var var_id var_dict, rev_items )) - ~init:(Var.Map.empty, Var.Map.empty, []) p.code_items in - { ctx; code_items = List.rev rev_items; module_name = p.module_name } + { ctx = program_ctx; code_items = List.rev rev_items; module_name = p.module_name } diff --git a/compiler/scalc/from_lcalc.mli b/compiler/scalc/from_lcalc.mli index fdd3b255..4cd09de7 100644 --- a/compiler/scalc/from_lcalc.mli +++ b/compiler/scalc/from_lcalc.mli @@ -32,7 +32,9 @@ type translation_config = { (** When [no_struct_literals] is true, the translation inserts a temporary variable to hold the initialization of struct literals. This matches what C89 expects. *) + renaming_context : Expr.Renaming.context; } val translate_program : - config:translation_config -> typed Lcalc.Ast.program -> Ast.program + config:translation_config -> typed Lcalc.Ast.program -> + Ast.program diff --git a/compiler/scalc/print.ml b/compiler/scalc/print.ml index 5863678f..a40737c6 100644 --- a/compiler/scalc/print.ml +++ b/compiler/scalc/print.ml @@ -21,10 +21,12 @@ open Ast let needs_parens (_e : expr) : bool = false let format_var_name (fmt : Format.formatter) (v : VarName.t) : unit = - Format.fprintf fmt "%a_%d" VarName.format v (VarName.id v) + VarName.format fmt v + (* Format.fprintf fmt "%a_%d" VarName.format v (VarName.id v) *) let format_func_name (fmt : Format.formatter) (v : FuncName.t) : unit = - Format.fprintf fmt "@{%a_%d@}" FuncName.format v (FuncName.id v) + FuncName.format fmt v + (* Format.fprintf fmt "@{%a_%d@}" FuncName.format v (FuncName.id v) *) let rec format_expr (decl_ctx : decl_ctx) diff --git a/compiler/scalc/to_c.ml b/compiler/scalc/to_c.ml index 3205968d..517db4ae 100644 --- a/compiler/scalc/to_c.ml +++ b/compiler/scalc/to_c.ml @@ -21,109 +21,21 @@ module D = Dcalc.Ast module L = Lcalc.Ast open Ast -let avoid_keywords (s : string) : string = - if - match s with - (* list taken from - https://learn.microsoft.com/en-us/cpp/c-language/c-keywords *) - | "auto" | "break" | "case" | "char" | "const" | "continue" | "default" - | "do" | "double" | "else" | "enum" | "extern" | "float" | "for" | "goto" - | "if" | "inline" | "int" | "long" | "register" | "restrict" | "return" - | "short" | "signed" | "sizeof" | "static" | "struct" | "switch" | "typedef" - | "union" | "unsigned" | "void" | "volatile" | "while" -> - true - | _ -> false - then s ^ "_" - else s +let c_keywords = + [ "auto"; "break"; "case"; "char"; "const"; "continue"; "default"; + "do"; "double"; "else"; "enum"; "extern"; "float"; "for"; "goto"; + "if"; "inline"; "int"; "long"; "register"; "restrict"; "return"; + "short"; "signed"; "sizeof"; "static"; "struct"; "switch"; "typedef"; + "union"; "unsigned"; "void"; "volatile"; "while" ] -let format_struct_name (fmt : Format.formatter) (v : StructName.t) : unit = - Format.fprintf fmt "%s" - (Format.asprintf "%a_struct" StructName.format v - |> String.to_ascii - |> String.to_snake_case - |> avoid_keywords) - -let format_struct_field_name (fmt : Format.formatter) (v : StructField.t) : unit - = - Format.fprintf fmt "%s" - (Format.asprintf "%a_field" StructField.format v - |> String.to_ascii - |> String.to_snake_case - |> avoid_keywords) - -let format_enum_name (fmt : Format.formatter) (v : EnumName.t) : unit = - Format.fprintf fmt "%s_enum" - (Format.asprintf "%a" EnumName.format v - |> String.to_ascii - |> String.to_snake_case - |> avoid_keywords) - -let format_enum_cons_name (fmt : Format.formatter) (v : EnumConstructor.t) : - unit = - Format.fprintf fmt "%s_cons" - (Format.asprintf "%a" EnumConstructor.format v - |> String.to_ascii - |> String.to_snake_case - |> avoid_keywords) - -let format_name_cleaned (fmt : Format.formatter) (s : string) : unit = - s - |> String.to_ascii - |> String.to_snake_case - |> Re.Pcre.substitute ~rex:(Re.Pcre.regexp "\\.") ~subst:(fun _ -> "_dot_") - |> String.to_ascii - |> avoid_keywords - |> Format.fprintf fmt "%s" - -let format_func_name (fmt : Format.formatter) (v : FuncName.t) : unit = - let v_str = Mark.remove (FuncName.get_info v) in - Format.fprintf fmt "%a_func" format_name_cleaned v_str - -module StringMap = String.Map - -module IntMap = Map.Make (struct - include Int - - let format ppf i = Format.pp_print_int ppf i -end) - -(** For each `VarName.t` defined by its string and then by its hash, we keep - track of which local integer id we've given it. This is used to keep - variable naming with low indices rather than one global counter for all - variables. TODO: should be removed when - https://github.com/CatalaLang/catala/issues/240 is fixed. *) -let string_counter_map : int IntMap.t StringMap.t ref = ref StringMap.empty - -let format_var (fmt : Format.formatter) (v : VarName.t) : unit = - let v_str = Mark.remove (VarName.get_info v) in - let id = VarName.id v in - let local_id = - match StringMap.find_opt v_str !string_counter_map with - | Some ids -> ( - match IntMap.find_opt id ids with - | None -> - let max_id = - snd - (List.hd - (List.fast_sort - (fun (_, x) (_, y) -> Int.compare y x) - (IntMap.bindings ids))) - in - string_counter_map := - StringMap.add v_str - (IntMap.add id (max_id + 1) ids) - !string_counter_map; - max_id + 1 - | Some local_id -> local_id) - | None -> - string_counter_map := - StringMap.add v_str (IntMap.singleton id 0) !string_counter_map; - 0 - in - if v_str = "_" then Format.fprintf fmt "dummy_var" - (* special case for the unit pattern TODO escape dummy_var *) - else if local_id = 0 then format_name_cleaned fmt v_str - else Format.fprintf fmt "%a_%d" format_name_cleaned v_str local_id +let renaming = + Program.renaming () + ~reserved:c_keywords + (* TODO: add catala runtime built-ins as reserved as well ? *) + ~reset_context_for_closed_terms:true + ~skip_constant_binders:true + ~constant_binder_name:None + ~namespaced_fields_constrs:false module TypMap = Map.Make (struct type t = naked_typ @@ -156,12 +68,12 @@ let rec format_typ (format_typ decl_ctx (fun fmt -> Format.fprintf fmt "arg_%d" i)) t)) (List.mapi (fun x y -> y, x) ts) - | TStruct s -> Format.fprintf fmt "%a %t" format_struct_name s element_name + | TStruct s -> Format.fprintf fmt "%a %t" StructName.format s element_name | TOption _ -> Message.error ~internal:true "All option types should have been monomorphized before compilation to C." | TDefault t -> format_typ decl_ctx element_name fmt t - | TEnum e -> Format.fprintf fmt "%a %t" format_enum_name e element_name + | TEnum e -> Format.fprintf fmt "%a %t" EnumName.format e element_name | TArrow (t1, t2) -> Format.fprintf fmt "%a(%a)" (format_typ decl_ctx (fun fmt -> Format.fprintf fmt "(*%t)" element_name)) @@ -185,41 +97,41 @@ let format_ctx let format_struct_decl fmt (struct_name, struct_fields) = let fields = StructField.Map.bindings struct_fields in Format.fprintf fmt "@[typedef struct %a {@ %a@]@,} %a;" - format_struct_name struct_name + StructName.format struct_name (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ") (fun fmt (struct_field, struct_field_type) -> Format.fprintf fmt "@[%a;@]" (format_typ ctx (fun fmt -> - format_struct_field_name fmt struct_field)) + StructField.format fmt struct_field)) struct_field_type)) - fields format_struct_name struct_name + fields StructName.format struct_name in let format_enum_decl fmt (enum_name, enum_cons) = if EnumConstructor.Map.is_empty enum_cons then failwith "no constructors in the enum" else Format.fprintf fmt "@[enum %a_code {@,%a@]@,} %a_code;@\n@\n" - format_enum_name enum_name + EnumName.format enum_name (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") (fun fmt (enum_cons, _) -> - Format.fprintf fmt "%a_%a" format_enum_name enum_name - format_enum_cons_name enum_cons)) + Format.fprintf fmt "%a_%a" EnumName.format enum_name + EnumConstructor.format enum_cons)) (EnumConstructor.Map.bindings enum_cons) - format_enum_name enum_name; + EnumName.format enum_name; Format.fprintf fmt "@[typedef struct %a {@ enum %a_code code;@ @[union {@ %a@]@,\ } payload;@]@,\ - } %a;" format_enum_name enum_name format_enum_name enum_name + } %a;" EnumName.format enum_name EnumName.format enum_name (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ") (fun fmt (enum_cons, typ) -> Format.fprintf fmt "%a;" - (format_typ ctx (fun fmt -> format_enum_cons_name fmt enum_cons)) + (format_typ ctx (fun fmt -> EnumConstructor.format fmt enum_cons)) typ)) (EnumConstructor.Map.bindings enum_cons) - format_enum_name enum_name + EnumName.format enum_name in let is_in_type_ordering s = @@ -329,8 +241,8 @@ let _format_string_list (fmt : Format.formatter) (uids : string list) : unit = let rec format_expression (ctx : decl_ctx) (fmt : Format.formatter) (e : expr) : unit = match Mark.remove e with - | EVar v -> format_var fmt v - | EFunc f -> format_func_name fmt f + | EVar v -> VarName.format fmt v + | EFunc f -> FuncName.format fmt f | EStruct { fields = es; _ } -> (* These should only appear when initializing a variable definition *) Format.fprintf fmt "{ %a }" @@ -340,10 +252,10 @@ let rec format_expression (ctx : decl_ctx) (fmt : Format.formatter) (e : expr) : (StructField.Map.bindings es) | EStructFieldAccess { e1; field; _ } -> Format.fprintf fmt "%a.%a" (format_expression ctx) e1 - format_struct_field_name field + StructField.format field | EInj { e1; cons; name = enum_name; _ } -> - Format.fprintf fmt "{%a_%a,@ {%a: %a}}" format_enum_name enum_name - format_enum_cons_name cons format_enum_cons_name cons + Format.fprintf fmt "{%a_%a,@ {%a: %a}}" EnumName.format enum_name + EnumConstructor.format cons EnumConstructor.format cons (format_expression ctx) e1 | EArray _ -> failwith @@ -402,7 +314,7 @@ let rec format_statement "This inner functions should have been hoisted in Scalc" | SLocalDecl { name = v; typ = ty } -> Format.fprintf fmt "@[%a@];" - (format_typ ctx (fun fmt -> format_var fmt (Mark.remove v))) + (format_typ ctx (fun fmt -> VarName.format fmt (Mark.remove v))) ty (* Below we detect array initializations which have special treatment. *) | SLocalInit { name = v; expr = EStruct { fields; name }, _; typ } @@ -421,20 +333,20 @@ let rec format_statement "@[%a;@]@\n\ @[%a.content_field = catala_malloc(sizeof(%a));@]@\n\ %a" - (format_typ ctx (fun fmt -> format_var fmt (Mark.remove v))) - typ format_var (Mark.remove v) format_struct_name name + (format_typ ctx (fun fmt -> VarName.format fmt (Mark.remove v))) + typ VarName.format (Mark.remove v) StructName.format name (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "@\n") (fun fmt (i, arg) -> Format.fprintf fmt "@[%a.content_field[%d] =@ %a;@]" - format_var (Mark.remove v) i (format_expression ctx) arg)) + VarName.format (Mark.remove v) i (format_expression ctx) arg)) (List.mapi (fun i a -> i, a) array_contents) | SLocalInit { name = v; expr = e; typ } -> Format.fprintf fmt "@[%a = %a;@]" - (format_typ ctx (fun fmt -> format_var fmt (Mark.remove v))) + (format_typ ctx (fun fmt -> VarName.format fmt (Mark.remove v))) typ (format_expression ctx) e | SLocalDef { name = v; expr = e; _ } -> - Format.fprintf fmt "@[%a = %a;@]" format_var (Mark.remove v) + Format.fprintf fmt "@[%a = %a;@]" VarName.format (Mark.remove v) (format_expression ctx) e | SRaiseEmpty | STryWEmpty _ -> assert false | SFatalError err -> @@ -457,18 +369,18 @@ let rec format_statement (EnumConstructor.Map.bindings (EnumName.Map.find e_name ctx.ctx_enums)) in let tmp_var = VarName.fresh ("match_arg", Pos.no_pos) in - Format.fprintf fmt "@[%a %a = %a;@]@," format_enum_name e_name - format_var tmp_var (format_expression ctx) e1; + Format.fprintf fmt "@[%a %a = %a;@]@," EnumName.format e_name + VarName.format tmp_var (format_expression ctx) e1; Format.pp_open_vbox fmt 2; - Format.fprintf fmt "@[switch (%a.code) {@]@," format_var tmp_var; + Format.fprintf fmt "@[switch (%a.code) {@]@," VarName.format tmp_var; Format.pp_print_list (fun fmt ({ case_block; payload_var_name; payload_var_typ }, cons_name) -> - Format.fprintf fmt "@[case %a_%a:@ " format_enum_name e_name - format_enum_cons_name cons_name; + Format.fprintf fmt "@[case %a_%a:@ " EnumName.format e_name + EnumConstructor.format cons_name; if not (Type.equal payload_var_typ (TLit TUnit, Pos.no_pos)) then Format.fprintf fmt "%a = %a.payload.%a;@ " - (format_typ ctx (fun fmt -> format_var fmt payload_var_name)) - payload_var_typ format_var tmp_var format_enum_cons_name cons_name; + (format_typ ctx (fun fmt -> VarName.format fmt payload_var_name)) + payload_var_typ VarName.format tmp_var EnumConstructor.format cons_name; Format.fprintf fmt "%a@ break;@]" (format_block ctx) case_block) fmt cases; (* Do we want to add 'default' case with a failure ? *) @@ -514,13 +426,13 @@ let rec format_statement in if exceptions <> [] then begin Format.fprintf fmt "@[%a = {%a_%a,@ {%a: NULL}};@]@," - (format_typ ctx (fun fmt -> format_var fmt exception_acc_var)) - return_typ format_enum_name e_name format_enum_cons_name none_cons - format_enum_cons_name none_cons; + (format_typ ctx (fun fmt -> VarName.format fmt exception_acc_var)) + return_typ EnumName.format e_name EnumConstructor.format none_cons + EnumConstructor.format none_cons; Format.fprintf fmt "%a;@," - (format_typ ctx (fun fmt -> format_var fmt exception_current)) + (format_typ ctx (fun fmt -> VarName.format fmt exception_current)) return_typ; - Format.fprintf fmt "char %a = 0;@," format_var exception_conflict; + Format.fprintf fmt "char %a = 0;@," VarName.format exception_conflict; List.iter (fun except -> Format.fprintf fmt @@ -532,11 +444,11 @@ let rec format_statement %a = %a;@]@,\ }@]@,\ }@," - format_var exception_current (format_expression ctx) except - format_var exception_current format_enum_name e_name - format_enum_cons_name some_cons format_var exception_acc_var - format_enum_name e_name format_enum_cons_name some_cons format_var - exception_conflict format_var exception_acc_var format_var + VarName.format exception_current (format_expression ctx) except + VarName.format exception_current EnumName.format e_name + EnumConstructor.format some_cons VarName.format exception_acc_var + EnumName.format e_name EnumConstructor.format some_cons VarName.format + exception_conflict VarName.format exception_acc_var VarName.format exception_current) exceptions; Format.fprintf fmt @@ -544,14 +456,14 @@ let rec format_statement @[catala_raise_fatal_error(catala_conflict,@ \"%s\",@ %d, %d, \ %d, %d);@]@;\ <1 -2>}@]@," - format_var exception_conflict (Pos.get_file pos) + VarName.format exception_conflict (Pos.get_file pos) (Pos.get_start_line pos) (Pos.get_start_column pos) (Pos.get_end_line pos) (Pos.get_end_column pos); Format.fprintf fmt "@[if (%a.code == %a_%a) {@,%a = %a;@]@,@[} else {@," - format_var exception_acc_var format_enum_name e_name - format_enum_cons_name some_cons format_var variable_defined_in_cons - format_var exception_acc_var + VarName.format exception_acc_var EnumName.format e_name + EnumConstructor.format some_cons VarName.format variable_defined_in_cons + VarName.format exception_acc_var end; Format.fprintf fmt "@[if (%a) {@,\ @@ -560,9 +472,9 @@ let rec format_statement %a.code = %a_%a;@,\ %a.payload.%a = NULL;@]@,\ }" - (format_expression ctx) just (format_block ctx) cons format_var - variable_defined_in_cons format_enum_name e_name format_enum_cons_name - none_cons format_var variable_defined_in_cons format_enum_cons_name + (format_expression ctx) just (format_block ctx) cons VarName.format + variable_defined_in_cons EnumName.format e_name EnumConstructor.format + none_cons VarName.format variable_defined_in_cons EnumConstructor.format none_cons; if exceptions <> [] then Format.fprintf fmt "@]@,}" @@ -591,7 +503,7 @@ let format_program match code_item with | SVar { var; expr; typ } -> Format.fprintf fmt "@[%a = %a;@]" - (format_typ p.ctx.decl_ctx (fun fmt -> format_var fmt var)) + (format_typ p.ctx.decl_ctx (fun fmt -> VarName.format fmt var)) typ (format_expression p.ctx.decl_ctx) expr @@ -599,13 +511,13 @@ let format_program | SScope { scope_body_var = var; scope_body_func = func; _ } -> let { func_params; func_body; func_return_typ } = func in Format.fprintf fmt "@[%a(%a) {@,%a@]@,}" - (format_typ p.ctx.decl_ctx (fun fmt -> format_func_name fmt var)) + (format_typ p.ctx.decl_ctx (fun fmt -> FuncName.format fmt var)) func_return_typ (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") (fun fmt (var, typ) -> (format_typ p.ctx.decl_ctx (fun fmt -> - format_var fmt (Mark.remove var))) + VarName.format fmt (Mark.remove var))) fmt typ)) func_params (format_block p.ctx.decl_ctx) diff --git a/compiler/scalc/to_c.mli b/compiler/scalc/to_c.mli index 1a9a15e5..2b7c6853 100644 --- a/compiler/scalc/to_c.mli +++ b/compiler/scalc/to_c.mli @@ -14,7 +14,11 @@ License for the specific language governing permissions and limitations under the License. *) -(** Formats a lambda calculus program into a valid C89 program *) +(** Formats a statement calculus program into a valid C89 program *) + +open Shared_ast + +val renaming : Program.renaming val format_program : Format.formatter -> Ast.program -> Scopelang.Dependency.TVertex.t list -> unit diff --git a/compiler/scalc/to_python.ml b/compiler/scalc/to_python.ml index 65be82b6..26f33765 100644 --- a/compiler/scalc/to_python.ml +++ b/compiler/scalc/to_python.ml @@ -110,98 +110,23 @@ let format_string_list (fmt : Format.formatter) (uids : string list) : unit = (Re.replace sanitize_quotes ~f:(fun _ -> "\\\"") info))) uids -let avoid_keywords (s : string) : string = - if - match s with - (* list taken from - https://www.programiz.com/python-programming/keyword-list *) - | "False" | "None" | "True" | "and" | "as" | "assert" | "async" | "await" - | "break" | "class" | "continue" | "def" | "del" | "elif" | "else" - | "except" | "finally" | "for" | "from" | "global" | "if" | "import" | "in" - | "is" | "lambda" | "nonlocal" | "not" | "or" | "pass" | "raise" | "return" - | "try" | "while" | "with" | "yield" -> - true - | _ -> false - then s ^ "_" - else s +let python_keywords = + (* list taken from + https://www.programiz.com/python-programming/keyword-list *) + [ "False"; "None"; "True"; "and"; "as"; "assert"; "async"; "await"; + "break"; "class"; "continue"; "def"; "del"; "elif"; "else"; + "except"; "finally"; "for"; "from"; "global"; "if"; "import"; "in"; + "is"; "lambda"; "nonlocal"; "not"; "or"; "pass"; "raise"; "return"; + "try"; "while"; "with"; "yield" ] +(* todo: reserved names should also include built-in types and everything exposed by the runtime. *) -module StringMap = String.Map - -module IntMap = Map.Make (struct - include Int - - let format ppf i = Format.pp_print_int ppf i -end) - -let clean_name (s : string) : string = - s - |> String.to_snake_case - |> Re.Pcre.substitute ~rex:(Re.Pcre.regexp "\\.") ~subst:(fun _ -> "_dot_") - |> avoid_keywords - -let format_name_cleaned (fmt : Format.formatter) (s : string) : unit = - Format.pp_print_string fmt (clean_name s) - -(** For each `VarName.t` defined by its string and then by its hash, we keep - track of which local integer id we've given it. This is used to keep - variable naming with low indices rather than one global counter for all - variables. TODO: should be removed when - https://github.com/CatalaLang/catala/issues/240 is fixed. *) -let string_counter_map : int IntMap.t StringMap.t ref = ref StringMap.empty - -let format_var (fmt : Format.formatter) (v : VarName.t) : unit = - let v_str = clean_name (Mark.remove (VarName.get_info v)) in - let id = VarName.id v in - let local_id = - match StringMap.find_opt v_str !string_counter_map with - | Some ids -> ( - match IntMap.find_opt id ids with - | None -> - let local_id = 1 + IntMap.fold (fun _ -> Int.max) ids 0 in - string_counter_map := - StringMap.add v_str (IntMap.add id local_id ids) !string_counter_map; - local_id - | Some local_id -> local_id) - | None -> - string_counter_map := - StringMap.add v_str (IntMap.singleton id 0) !string_counter_map; - 0 - in - if v_str = "_" then Format.fprintf fmt "_" - (* special case for the unit pattern *) - else if local_id = 0 then Format.pp_print_string fmt v_str - else Format.fprintf fmt "%s_%d" v_str local_id - -let format_path ctx fmt p = - match List.rev p with - | [] -> () - | m :: _ -> - format_var fmt (ModuleName.Map.find m ctx.modules); - Format.pp_print_char fmt '.' - -let format_struct_name ctx (fmt : Format.formatter) (v : StructName.t) : unit = - format_path ctx fmt (StructName.path v); - Format.pp_print_string fmt - (avoid_keywords - (String.to_camel_case - (String.to_ascii (Mark.remove (StructName.get_info v))))) - -let format_struct_field_name (fmt : Format.formatter) (v : StructField.t) : unit - = - Format.pp_print_string fmt - (avoid_keywords (String.to_ascii (StructField.to_string v))) - -let format_enum_name ctx (fmt : Format.formatter) (v : EnumName.t) : unit = - format_path ctx fmt (EnumName.path v); - Format.pp_print_string fmt - (avoid_keywords - (String.to_camel_case - (String.to_ascii (Mark.remove (EnumName.get_info v))))) - -let format_enum_cons_name (fmt : Format.formatter) (v : EnumConstructor.t) : - unit = - Format.pp_print_string fmt - (avoid_keywords (String.to_ascii (EnumConstructor.to_string v))) +let renaming = + Program.renaming () + ~reserved:python_keywords + (* TODO: add catala runtime built-ins as reserved as well ? *) + ~reset_context_for_closed_terms:false ~skip_constant_binders:false + ~constant_binder_name:None ~namespaced_fields_constrs:true + ~f_struct:String.to_camel_case let typ_needs_parens (e : typ) : bool = match Mark.remove e with TArrow _ | TArray _ -> true | _ -> false @@ -226,12 +151,12 @@ let rec format_typ ctx (fmt : Format.formatter) (typ : typ) : unit = ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") (fun fmt t -> Format.fprintf fmt "%a" format_typ_with_parens t)) ts - | TStruct s -> Format.fprintf fmt "%a" (format_struct_name ctx) s + | TStruct s -> StructName.format fmt s | TOption some_typ -> (* We translate the option type with an overloading by Python's [None] *) Format.fprintf fmt "Optional[%a]" format_typ some_typ | TDefault t -> format_typ fmt t - | TEnum e -> Format.fprintf fmt "%a" (format_enum_name ctx) e + | TEnum e -> EnumName.format fmt e | TArrow (t1, t2) -> Format.fprintf fmt "Callable[[%a], %a]" (Format.pp_print_list @@ -243,8 +168,7 @@ let rec format_typ ctx (fmt : Format.formatter) (typ : typ) : unit = | TClosureEnv -> failwith "unimplemented!" let format_func_name (fmt : Format.formatter) (v : FuncName.t) : unit = - let v_str = Mark.remove (FuncName.get_info v) in - format_name_cleaned fmt v_str + FuncName.format fmt v let format_position ppf pos = Format.fprintf ppf @@ -263,19 +187,19 @@ let format_error (ppf : Format.formatter) (err : Runtime.error Mark.pos) : unit let rec format_expression ctx (fmt : Format.formatter) (e : expr) : unit = match Mark.remove e with - | EVar v -> format_var fmt v - | EFunc f -> format_func_name fmt f + | EVar v -> VarName.format fmt v + | EFunc f -> FuncName.format fmt f | EStruct { fields = es; name = s } -> - Format.fprintf fmt "%a(%a)" (format_struct_name ctx) s + Format.fprintf fmt "%a(%a)" StructName.format s (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") (fun fmt (struct_field, e) -> - Format.fprintf fmt "%a = %a" format_struct_field_name struct_field + Format.fprintf fmt "%a = %a" StructField.format struct_field (format_expression ctx) e)) (StructField.Map.bindings es) | EStructFieldAccess { e1; field; _ } -> Format.fprintf fmt "%a.%a" (format_expression ctx) e1 - format_struct_field_name field + StructField.format field | EInj { cons; name = e_name; _ } when EnumName.equal e_name Expr.option_enum && EnumConstructor.equal cons Expr.none_constr -> @@ -287,8 +211,8 @@ let rec format_expression ctx (fmt : Format.formatter) (e : expr) : unit = (* We translate the option type with an overloading by Python's [None] *) format_expression ctx fmt e | EInj { e1 = e; cons; name = enum_name; _ } -> - Format.fprintf fmt "%a(%a_Code.%a,@ %a)" (format_enum_name ctx) enum_name - (format_enum_name ctx) enum_name format_enum_cons_name cons + Format.fprintf fmt "%a(%a_Code.%a,@ %a)" EnumName.format enum_name + EnumName.format enum_name EnumConstructor.format cons (format_expression ctx) e | EArray es -> Format.fprintf fmt "[%a]" @@ -380,26 +304,26 @@ let rec format_expression ctx (fmt : Format.formatter) (e : expr) : unit = | ETupleAccess { e1; index } -> Format.fprintf fmt "%a[%d]" (format_expression ctx) e1 index | EExternal { modname; name } -> - Format.fprintf fmt "%a.%a" format_var (Mark.remove modname) - format_name_cleaned (Mark.remove name) + Format.fprintf fmt "%a.%s" VarName.format (Mark.remove modname) + (Mark.remove name) let rec format_statement ctx (fmt : Format.formatter) (s : stmt Mark.pos) : unit = match Mark.remove s with | SInnerFuncDef { name; func = { func_params; func_body; _ } } -> - Format.fprintf fmt "@[def %a(@[%a@]):@ %a@]" format_var + Format.fprintf fmt "@[def %a(@[%a@]):@ %a@]" VarName.format (Mark.remove name) (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") (fun fmt (var, typ) -> - Format.fprintf fmt "%a:%a" format_var (Mark.remove var) + Format.fprintf fmt "%a:%a" VarName.format (Mark.remove var) (format_typ ctx) typ)) func_params (format_block ctx) func_body | SLocalDecl _ -> 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@]" format_var (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@]" @@ -424,12 +348,12 @@ let rec format_statement ctx (fmt : Format.formatter) (s : stmt Mark.pos) : unit when EnumName.equal e_name Expr.option_enum -> (* We translate the option type with an overloading by Python's [None] *) let tmp_var = VarName.fresh ("perhaps_none_arg", Pos.no_pos) in - Format.fprintf fmt "@[%a = %a@]@," format_var tmp_var + Format.fprintf fmt "@[%a = %a@]@," VarName.format tmp_var (format_expression ctx) e1; - Format.fprintf fmt "@[if %a is None:@ %a@]@," format_var tmp_var + Format.fprintf fmt "@[if %a is None:@ %a@]@," VarName.format tmp_var (format_block ctx) case_none; - Format.fprintf fmt "@[else:@ %a = %a@,%a@]" format_var case_some_var - format_var tmp_var (format_block ctx) case_some + Format.fprintf fmt "@[else:@ %a = %a@,%a@]" VarName.format case_some_var + VarName.format tmp_var (format_block ctx) case_some | SSwitch { switch_expr = e1; enum_name = e_name; switch_cases = cases; _ } -> let cons_map = EnumName.Map.find e_name ctx.decl_ctx.ctx_enums in let cases = @@ -439,15 +363,15 @@ let rec format_statement ctx (fmt : Format.formatter) (s : stmt Mark.pos) : unit (EnumConstructor.Map.bindings cons_map) in let tmp_var = VarName.fresh ("match_arg", Pos.no_pos) in - Format.fprintf fmt "%a = %a@\n@[if %a@]" format_var tmp_var + Format.fprintf fmt "%a = %a@\n@[if %a@]" VarName.format tmp_var (format_expression ctx) e1 (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "@]@\n@[elif ") (fun fmt ({ case_block; payload_var_name; _ }, cons_name) -> Format.fprintf fmt "%a.code == %a_Code.%a:@\n%a = %a.value@\n%a" - format_var tmp_var (format_enum_name ctx) e_name - format_enum_cons_name cons_name format_var payload_var_name - format_var tmp_var (format_block ctx) case_block)) + VarName.format tmp_var (EnumName.format) e_name + EnumConstructor.format cons_name VarName.format payload_var_name + VarName.format tmp_var (format_block ctx) case_block)) cases | SReturn e1 -> Format.fprintf fmt "@[return %a@]" (format_expression ctx) @@ -497,38 +421,38 @@ let format_ctx \ return not (self == other)@,\ @,\ \ def __str__(self) -> str:@,\ - \ @[return \"%a(%a)\".format(%a)@]" (format_struct_name ctx) + \ @[return \"%a(%a)\".format(%a)@]" StructName.format struct_name (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") (fun fmt (struct_field, struct_field_type) -> - Format.fprintf fmt "%a: %a" format_struct_field_name struct_field + Format.fprintf fmt "%a: %a" StructField.format struct_field (format_typ ctx) struct_field_type)) fields (if StructField.Map.is_empty struct_fields then fun fmt _ -> Format.fprintf fmt " pass" else Format.pp_print_list (fun fmt (struct_field, _) -> - Format.fprintf fmt " self.%a = %a" format_struct_field_name - struct_field format_struct_field_name struct_field)) - fields (format_struct_name ctx) struct_name + Format.fprintf fmt " self.%a = %a" StructField.format + struct_field StructField.format struct_field)) + fields StructName.format struct_name (if not (StructField.Map.is_empty struct_fields) then Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " and@ ") (fun fmt (struct_field, _) -> - Format.fprintf fmt "self.%a == other.%a" format_struct_field_name - struct_field format_struct_field_name struct_field) + Format.fprintf fmt "self.%a == other.%a" StructField.format + struct_field StructField.format struct_field) else fun fmt _ -> Format.fprintf fmt "True") - fields (format_struct_name ctx) struct_name + fields StructName.format struct_name (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",") (fun fmt (struct_field, _) -> - Format.fprintf fmt "%a={}" format_struct_field_name struct_field)) + Format.fprintf fmt "%a={}" StructField.format struct_field)) fields (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") (fun fmt (struct_field, _) -> - Format.fprintf fmt "self.%a" format_struct_field_name struct_field)) + Format.fprintf fmt "self.%a" StructField.format struct_field)) fields in let format_enum_decl fmt (enum_name, enum_cons) = @@ -558,14 +482,14 @@ let format_ctx @,\ \ def __str__(self) -> str:@,\ \ @[return \"{}({})\".format(self.code, self.value)@]" - (format_enum_name ctx) enum_name + (EnumName.format) enum_name (Format.pp_print_list (fun fmt (i, enum_cons, _enum_cons_type) -> - Format.fprintf fmt "%a = %d" format_enum_cons_name enum_cons i)) + Format.fprintf fmt "%a = %d" EnumConstructor.format enum_cons i)) (List.mapi (fun i (x, y) -> i, x, y) (EnumConstructor.Map.bindings enum_cons)) - (format_enum_name ctx) enum_name (format_enum_name ctx) enum_name - (format_enum_name ctx) enum_name + (EnumName.format) enum_name EnumName.format enum_name + EnumName.format enum_name in let is_in_type_ordering s = @@ -597,19 +521,9 @@ let format_ctx (e, EnumName.Map.find e ctx.decl_ctx.ctx_enums)) (type_ordering @ scope_structs) -(* FIXME: this is an ugly (and partial) workaround, Python basically has one - namespace and we reserve the name to avoid clashes between func ids and - variable ids. *) -let reserve_func_name = function - | SVar _ -> () - | SFunc { var = v; _ } | SScope { scope_body_var = v; _ } -> - let v_str = clean_name (Mark.remove (FuncName.get_info v)) in - string_counter_map := - StringMap.add v_str (IntMap.singleton (-1) 0) !string_counter_map - let format_code_item ctx fmt = function | SVar { var; expr; typ = _ } -> - Format.fprintf fmt "@[%a = (@,%a@;<0 -4>)@]@," format_var var + Format.fprintf fmt "@[%a = (@,%a@;<0 -4>)@]@," VarName.format var (format_expression ctx) expr | SFunc { var; func } | SScope { scope_body_var = var; scope_body_func = func; _ } -> @@ -619,7 +533,7 @@ let format_code_item ctx fmt = function (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") (fun fmt (var, typ) -> - Format.fprintf fmt "%a:%a" format_var (Mark.remove var) + Format.fprintf fmt "%a:%a" VarName.format (Mark.remove var) (format_typ ctx) typ)) func_params (format_block ctx) func_body @@ -627,7 +541,6 @@ let format_program (fmt : Format.formatter) (p : Ast.program) (type_ordering : Scopelang.Dependency.TVertex.t list) : unit = - List.iter reserve_func_name p.code_items; Format.pp_open_vbox fmt 0; let header = [ @@ -643,7 +556,7 @@ let format_program ModuleName.Map.iter (fun m v -> Format.fprintf fmt "from . import %a as %a@," ModuleName.format m - format_var v) + VarName.format v) p.ctx.modules; Format.pp_print_cut fmt (); format_ctx type_ordering fmt p.ctx; diff --git a/compiler/scalc/to_python.mli b/compiler/scalc/to_python.mli index 1cc4e3fa..d055d0ab 100644 --- a/compiler/scalc/to_python.mli +++ b/compiler/scalc/to_python.mli @@ -16,6 +16,10 @@ (** Formats a lambda calculus program into a valid Python program *) +open Shared_ast + +val renaming : Program.renaming + val format_program : Format.formatter -> Ast.program -> Scopelang.Dependency.TVertex.t list -> unit (** Usage [format_program fmt p type_dependencies_ordering] *) diff --git a/compiler/shared_ast/expr.mli b/compiler/shared_ast/expr.mli index 71c15325..28207ae6 100644 --- a/compiler/shared_ast/expr.mli +++ b/compiler/shared_ast/expr.mli @@ -417,6 +417,12 @@ module Renaming : sig like [String.to_snake_case]). The result is advisory and a numerical suffix may be appended or modified *) + val unmbind_in : + context -> + ?fname:(string -> string) -> + ('e, 'b) Bindlib.mbinder -> + ('e, _) Mark.ed Var.t Array.t * 'b * context + val new_id : context -> string -> string * context val set_rewriters : diff --git a/compiler/shared_ast/program.ml b/compiler/shared_ast/program.ml index c5ec07aa..33062c64 100644 --- a/compiler/shared_ast/program.ml +++ b/compiler/shared_ast/program.ml @@ -114,7 +114,8 @@ let rename_ids ?(f_field = uncap) ?(f_enum = cap) ?(f_constr = cap) - p = + p + = let cfg = { Expr.Renaming.reserved; @@ -283,3 +284,45 @@ let rename_ids let decl_ctx = map_decl_ctx ~f:(Expr.Renaming.typ ctx) decl_ctx in let code_items = Scope.rename_ids ctx p.code_items in { p with decl_ctx; code_items }, ctx + +(* This first-class module wrapping is here to allow a polymorphic renaming function to be passed around *) + +module type Renaming = sig + val apply: + 'e program -> + 'e program * Expr.Renaming.context +end + +type renaming = (module Renaming) + +let apply (module R: Renaming) = R.apply + +let renaming + ~reserved + ~reset_context_for_closed_terms + ~skip_constant_binders + ~constant_binder_name + ~namespaced_fields_constrs + ?f_var + ?f_struct + ?f_field + ?f_enum + ?f_constr + () + = + let module M = struct + let apply p = + rename_ids + ~reserved + ~reset_context_for_closed_terms + ~skip_constant_binders + ~constant_binder_name + ~namespaced_fields_constrs + ?f_var + ?f_struct + ?f_field + ?f_enum + ?f_constr + p + end in + (module M: Renaming) diff --git a/compiler/shared_ast/program.mli b/compiler/shared_ast/program.mli index 6d15cd46..7fd58a3b 100644 --- a/compiler/shared_ast/program.mli +++ b/compiler/shared_ast/program.mli @@ -57,7 +57,11 @@ val modules_to_list : module_tree -> (ModuleName.t * module_intf_id) list (** Returns a list of used modules, in topological order ; the boolean indicates if the module is external *) -val rename_ids : +type renaming + +val apply: renaming -> 'e program -> 'e program * Expr.Renaming.context + +val renaming : reserved:string list -> reset_context_for_closed_terms:bool -> skip_constant_binders:bool -> @@ -68,8 +72,8 @@ val rename_ids : ?f_field:(string -> string) -> ?f_enum:(string -> string) -> ?f_constr:(string -> string) -> - ('a, 't) gexpr program -> - ('a, 't) gexpr program * Expr.Renaming.context + unit -> + renaming (** Renames all idents (variables, types, struct and enum names, fields and constructors) to dispel ambiguities in the target language. Names in [reserved], typically keywords and built-ins, will be avoided ; the meaning diff --git a/tests/backends/output/simple.c b/tests/backends/output/simple.c index a90cc655..c037f057 100644 --- a/tests/backends/output/simple.c +++ b/tests/backends/output/simple.c @@ -4,413 +4,201 @@ #include #include -enum option_2_enum_code { - option_2_enum_none_2_cons, - option_2_enum_some_2_cons -} option_2_enum_code; +enum Option_2_code { + Option_2_None_2, + Option_2_Some_2 +} Option_2_code; -typedef struct option_2_enum { - enum option_2_enum_code code; +typedef struct Option_2 { + enum Option_2_code code; union { - void* /* unit */ none_2_cons; - double some_2_cons; + void* /* unit */ None_2; + double Some_2; } payload; -} option_2_enum; +} Option_2; -typedef struct foo_struct { - char /* bool */ x_field; - double y_field; -} foo_struct; +typedef struct Foo { + char /* bool */ x; + double y; +} Foo; -typedef struct array_3_struct { - double * content_field; - int length_field; -} array_3_struct; +typedef struct Array_3 { + double * content2; + int length2; +} Array_3; -typedef struct array_2_struct { - option_2_enum * content_field; - int length_field; -} array_2_struct; +typedef struct Array_2 { + Option_2 * content1; + int length1; +} Array_2; -enum bar_enum_code { - bar_enum_no_cons, - bar_enum_yes_cons -} bar_enum_code; +enum Bar_code { + Bar_No, + Bar_Yes +} Bar_code; -typedef struct bar_enum { - enum bar_enum_code code; +typedef struct Bar { + enum Bar_code code; union { - void* /* unit */ no_cons; - foo_struct yes_cons; + void* /* unit */ No; + Foo Yes; } payload; -} bar_enum; +} Bar; -typedef struct baz_struct { - double b_field; - array_3_struct c_field; -} baz_struct; +typedef struct Baz { + double b; + Array_3 c; +} Baz; -enum option_3_enum_code { - option_3_enum_none_3_cons, - option_3_enum_some_3_cons -} option_3_enum_code; +enum Option_3_code { + Option_3_None_3, + Option_3_Some_3 +} Option_3_code; -typedef struct option_3_enum { - enum option_3_enum_code code; +typedef struct Option_3 { + enum Option_3_code code; union { - void* /* unit */ none_3_cons; - array_3_struct some_3_cons; + void* /* unit */ None_3; + Array_3 Some_3; } payload; -} option_3_enum; +} Option_3; -enum option_1_enum_code { - option_1_enum_none_1_cons, - option_1_enum_some_1_cons -} option_1_enum_code; +enum Option_1_code { + Option_1_None_1, + Option_1_Some_1 +} Option_1_code; -typedef struct option_1_enum { - enum option_1_enum_code code; +typedef struct Option_1 { + enum Option_1_code code; union { - void* /* unit */ none_1_cons; - bar_enum some_1_cons; + void* /* unit */ None_1; + Bar Some_1; } payload; -} option_1_enum; +} Option_1; -typedef struct array_4_struct { - option_3_enum * content_field; - int length_field; -} array_4_struct; +typedef struct Array_4 { + Option_3 * content3; + int length3; +} Array_4; -typedef struct array_1_struct { - option_1_enum * content_field; - int length_field; -} array_1_struct; +typedef struct Array_1 { + Option_1 * content; + int length; +} Array_1; -typedef struct tuple_1_struct { - option_1_enum (*elt_0_field)(void * /* closure_env */ arg_0_typ, void* /* unit */ arg_1_typ); - void * /* closure_env */ elt_1_field; -} tuple_1_struct; +typedef struct Tuple_1 { + Option_1 (*elt_0)(void * /* closure_env */ arg_0_typ, void* /* unit */ arg_1_typ); + void * /* closure_env */ elt_1; +} Tuple_1; -typedef struct baz_in_struct { - tuple_1_struct a_in_field; -} baz_in_struct; +typedef struct Baz_in { + Tuple_1 a_in; +} Baz_in; -baz_struct baz_func(baz_in_struct baz_in) { - tuple_1_struct a; - a = baz_in.a_in_field; - bar_enum temp_a; - option_1_enum temp_a_1; - tuple_1_struct code_and_env; +Baz baz(Baz_in baz_in) { + Tuple_1 a; + a = baz_in.a_in; + Bar a2; + option_1 a3; + Tuple_1 code_and_env; code_and_env = a; - option_1_enum (*code)(void * /* closure_env */ arg_0_typ, void* /* unit */ arg_1_typ); + Option_1 (*code)(void * /* closure_env */ arg_0_typ, void* /* unit */ arg_1_typ); void * /* closure_env */ env; - code = code_and_env.elt_0_field; - env = code_and_env.elt_1_field; - array_1_struct temp_a_2; - temp_a_2.content_field = catala_malloc(sizeof(array_1_struct)); - temp_a_2.content_field[0] = code(env, NULL); - option_1_enum match_arg = catala_handle_exceptions(temp_a_2); + code = code_and_env.elt_0; + env = code_and_env.elt_1; + Array_1 a4; + a4.content_field = catala_malloc(sizeof(Array_1)); + a4.content_field[0] = code(env, NULL); + Option_1 match_arg = catala_handle_exceptions(a4); switch (match_arg.code) { - case option_1_enum_none_1_cons: + case Option_1_None_1: if (1 /* TRUE */) { - bar_enum temp_a_3; - option_1_enum temp_a_4; - option_1_enum temp_a_5; - array_1_struct temp_a_6; - temp_a_6.content_field = catala_malloc(sizeof(array_1_struct)); + Bar a3; + option_1 a4; + option_1 a6; + Array_1 a7; + a7.content_field = catala_malloc(sizeof(Array_1)); - option_1_enum match_arg_1 = catala_handle_exceptions(temp_a_6); - switch (match_arg_1.code) { - case option_1_enum_none_1_cons: + Option_1 match_arg = catala_handle_exceptions(a7); + switch (match_arg.code) { + case Option_1_None_1: if (1 /* TRUE */) { - bar_enum temp_a_7 = {bar_enum_no_cons, {no_cons: NULL}}; - option_1_enum temp_a_5 = {option_1_enum_some_1_cons, - {some_1_cons: temp_a_7}}; + Bar a6 = {Bar_No, {No: NULL}}; + option_1 a6 = {Option_1_Some_1, {Some_1: a6}}; } else { - option_1_enum temp_a_5 = {option_1_enum_none_1_cons, - {none_1_cons: NULL}}; + option_1 a6 = {Option_1_None_1, {None_1: NULL}}; } break; - case option_1_enum_some_1_cons: - bar_enum x = match_arg_1.payload.some_1_cons; - option_1_enum temp_a_5 = {option_1_enum_some_1_cons, - {some_1_cons: x}}; + case Option_1_Some_1: + Bar x1 = match_arg.payload.Some_1; + option_1 a6 = {Option_1_Some_1, {Some_1: x1}}; break; } - array_1_struct temp_a_8; - temp_a_8.content_field = catala_malloc(sizeof(array_1_struct)); - temp_a_8.content_field[0] = temp_a_5; - option_1_enum match_arg_2 = catala_handle_exceptions(temp_a_8); - switch (match_arg_2.code) { - case option_1_enum_none_1_cons: + Array_1 a5; + a5.content_field = catala_malloc(sizeof(Array_1)); + a5.content_field[0] = a6; + Option_1 match_arg = catala_handle_exceptions(a5); + switch (match_arg.code) { + case Option_1_None_1: if (0 /* FALSE */) { - option_1_enum temp_a_4 = {option_1_enum_none_1_cons, - {none_1_cons: NULL}}; + option_1 a4 = {Option_1_None_1, {None_1: NULL}}; } else { - option_1_enum temp_a_4 = {option_1_enum_none_1_cons, - {none_1_cons: NULL}}; + option_1 a4 = {Option_1_None_1, {None_1: NULL}}; } break; - case option_1_enum_some_1_cons: - bar_enum x_1 = match_arg_2.payload.some_1_cons; - option_1_enum temp_a_4 = {option_1_enum_some_1_cons, - {some_1_cons: x_1}}; + case Option_1_Some_1: + Bar x1 = match_arg.payload.Some_1; + option_1 a4 = {Option_1_Some_1, {Some_1: x1}}; break; } - option_1_enum match_arg_3 = temp_a_4; - switch (match_arg_3.code) { - case option_1_enum_none_1_cons: + Option_1 match_arg = a4; + switch (match_arg.code) { + case Option_1_None_1: catala_raise_fatal_error (catala_no_value, "tests/backends/simple.catala_en", 11, 11, 11, 12); break; - case option_1_enum_some_1_cons: - bar_enum arg = match_arg_3.payload.some_1_cons; - temp_a_3 = arg; + case Option_1_Some_1: + Bar arg = match_arg.payload.Some_1; + a3 = arg; break; } - option_1_enum temp_a_1 = {option_1_enum_some_1_cons, - {some_1_cons: temp_a_3}}; + option_1 a3 = {Option_1_Some_1, {Some_1: a3}}; } else { - option_1_enum temp_a_1 = {option_1_enum_none_1_cons, - {none_1_cons: NULL}}; + option_1 a3 = {Option_1_None_1, {None_1: NULL}}; } break; - case option_1_enum_some_1_cons: - bar_enum x_2 = match_arg.payload.some_1_cons; - option_1_enum temp_a_1 = {option_1_enum_some_1_cons, - {some_1_cons: x_2}}; + case Option_1_Some_1: + Bar x1 = match_arg.payload.Some_1; + option_1 a3 = {Option_1_Some_1, {Some_1: x1}}; break; } - option_1_enum match_arg_4 = temp_a_1; - switch (match_arg_4.code) { - case option_1_enum_none_1_cons: + Option_1 match_arg = a3; + switch (match_arg.code) { + case Option_1_None_1: catala_raise_fatal_error (catala_no_value, "tests/backends/simple.catala_en", 11, 11, 11, 12); break; - case option_1_enum_some_1_cons: - bar_enum arg_1 = match_arg_4.payload.some_1_cons; - temp_a = arg_1; + case Option_1_Some_1: + Bar arg = match_arg.payload.Some_1; + a2 = arg; break; } - bar_enum a_1; - a_1 = temp_a; - double temp_b; - option_2_enum temp_b_1; - option_2_enum temp_b_2; - option_2_enum temp_b_3; - array_2_struct temp_b_4; - temp_b_4.content_field = catala_malloc(sizeof(array_2_struct)); - - option_2_enum match_arg_5 = catala_handle_exceptions(temp_b_4); - switch (match_arg_5.code) { - case option_2_enum_none_2_cons: - char /* bool */ temp_b_5; - bar_enum match_arg_6 = a_1; - switch (match_arg_6.code) { - case bar_enum_no_cons: temp_b_5 = 1 /* TRUE */; break; - case bar_enum_yes_cons: - foo_struct dummy_var = match_arg_6.payload.yes_cons; - temp_b_5 = 0 /* FALSE */; - break; - } - if (temp_b_5) { - option_2_enum temp_b_3 = {option_2_enum_some_2_cons, - {some_2_cons: 42.}}; - - } else { - option_2_enum temp_b_3 = {option_2_enum_none_2_cons, - {none_2_cons: NULL}}; - - } - break; - case option_2_enum_some_2_cons: - double x_3 = match_arg_5.payload.some_2_cons; - option_2_enum temp_b_3 = {option_2_enum_some_2_cons, - {some_2_cons: x_3}}; - break; - } - array_2_struct temp_b_6; - temp_b_6.content_field = catala_malloc(sizeof(array_2_struct)); - temp_b_6.content_field[0] = temp_b_3; - option_2_enum match_arg_7 = catala_handle_exceptions(temp_b_6); - switch (match_arg_7.code) { - case option_2_enum_none_2_cons: - if (0 /* FALSE */) { - option_2_enum temp_b_2 = {option_2_enum_none_2_cons, - {none_2_cons: NULL}}; - - } else { - option_2_enum temp_b_2 = {option_2_enum_none_2_cons, - {none_2_cons: NULL}}; - - } - break; - case option_2_enum_some_2_cons: - double x_4 = match_arg_7.payload.some_2_cons; - option_2_enum temp_b_2 = {option_2_enum_some_2_cons, - {some_2_cons: x_4}}; - break; - } - array_2_struct temp_b_7; - temp_b_7.content_field = catala_malloc(sizeof(array_2_struct)); - temp_b_7.content_field[0] = temp_b_2; - option_2_enum match_arg_8 = catala_handle_exceptions(temp_b_7); - switch (match_arg_8.code) { - case option_2_enum_none_2_cons: - if (1 /* TRUE */) { - option_2_enum temp_b_8; - array_2_struct temp_b_9; - temp_b_9.content_field = catala_malloc(sizeof(array_2_struct)); - - option_2_enum match_arg_9 = catala_handle_exceptions(temp_b_9); - switch (match_arg_9.code) { - case option_2_enum_none_2_cons: - if (1 /* TRUE */) { - double temp_b_10; - bar_enum match_arg_10 = a_1; - switch (match_arg_10.code) { - case bar_enum_no_cons: temp_b_10 = 0.; break; - case bar_enum_yes_cons: - foo_struct foo = match_arg_10.payload.yes_cons; - double temp_b_11; - if (foo.x_field) {temp_b_11 = 1.; } else {temp_b_11 = 0.; } - temp_b_10 = (foo.y_field + temp_b_11); - break; - } - option_2_enum temp_b_8 = {option_2_enum_some_2_cons, - {some_2_cons: temp_b_10}}; - - } else { - option_2_enum temp_b_8 = {option_2_enum_none_2_cons, - {none_2_cons: NULL}}; - - } - break; - case option_2_enum_some_2_cons: - double x_5 = match_arg_9.payload.some_2_cons; - option_2_enum temp_b_8 = {option_2_enum_some_2_cons, - {some_2_cons: x_5}}; - break; - } - array_2_struct temp_b_12; - temp_b_12.content_field = catala_malloc(sizeof(array_2_struct)); - temp_b_12.content_field[0] = temp_b_8; - option_2_enum match_arg_11 = catala_handle_exceptions(temp_b_12); - switch (match_arg_11.code) { - case option_2_enum_none_2_cons: - if (0 /* FALSE */) { - option_2_enum temp_b_1 = {option_2_enum_none_2_cons, - {none_2_cons: NULL}}; - - } else { - option_2_enum temp_b_1 = {option_2_enum_none_2_cons, - {none_2_cons: NULL}}; - - } - break; - case option_2_enum_some_2_cons: - double x_6 = match_arg_11.payload.some_2_cons; - option_2_enum temp_b_1 = {option_2_enum_some_2_cons, - {some_2_cons: x_6}}; - break; - } - - } else { - option_2_enum temp_b_1 = {option_2_enum_none_2_cons, - {none_2_cons: NULL}}; - - } - break; - case option_2_enum_some_2_cons: - double x_7 = match_arg_8.payload.some_2_cons; - option_2_enum temp_b_1 = {option_2_enum_some_2_cons, - {some_2_cons: x_7}}; - break; - } - option_2_enum match_arg_12 = temp_b_1; - switch (match_arg_12.code) { - case option_2_enum_none_2_cons: - catala_raise_fatal_error (catala_no_value, - "tests/backends/simple.catala_en", 12, 10, 12, 11); - break; - case option_2_enum_some_2_cons: - double arg_2 = match_arg_12.payload.some_2_cons; - temp_b = arg_2; - break; - } - double b; - b = temp_b; - array_3_struct temp_c; - option_3_enum temp_c_1; - option_3_enum temp_c_2; - array_4_struct temp_c_3; - temp_c_3.content_field = catala_malloc(sizeof(array_4_struct)); - - option_3_enum match_arg_13 = catala_handle_exceptions(temp_c_3); - switch (match_arg_13.code) { - case option_3_enum_none_3_cons: - if (1 /* TRUE */) { - array_3_struct temp_c_4; - temp_c_4.content_field = catala_malloc(sizeof(array_3_struct)); - temp_c_4.content_field[0] = b; - temp_c_4.content_field[1] = b; - option_3_enum temp_c_2 = {option_3_enum_some_3_cons, - {some_3_cons: temp_c_4}}; - - } else { - option_3_enum temp_c_2 = {option_3_enum_none_3_cons, - {none_3_cons: NULL}}; - - } - break; - case option_3_enum_some_3_cons: - array_3_struct x_8 = match_arg_13.payload.some_3_cons; - option_3_enum temp_c_2 = {option_3_enum_some_3_cons, - {some_3_cons: x_8}}; - break; - } - array_4_struct temp_c_5; - temp_c_5.content_field = catala_malloc(sizeof(array_4_struct)); - temp_c_5.content_field[0] = temp_c_2; - option_3_enum match_arg_14 = catala_handle_exceptions(temp_c_5); - switch (match_arg_14.code) { - case option_3_enum_none_3_cons: - if (0 /* FALSE */) { - option_3_enum temp_c_1 = {option_3_enum_none_3_cons, - {none_3_cons: NULL}}; - - } else { - option_3_enum temp_c_1 = {option_3_enum_none_3_cons, - {none_3_cons: NULL}}; - - } - break; - case option_3_enum_some_3_cons: - array_3_struct x_9 = match_arg_14.payload.some_3_cons; - option_3_enum temp_c_1 = {option_3_enum_some_3_cons, - {some_3_cons: x_9}}; - break; - } - option_3_enum match_arg_15 = temp_c_1; - switch (match_arg_15.code) { - case option_3_enum_none_3_cons: - catala_raise_fatal_error (catala_no_value, - "tests/backends/simple.catala_en", 13, 10, 13, 11); - break; - case option_3_enum_some_3_cons: - array_3_struct arg_3 = match_arg_15.payload.some_3_cons; - temp_c = arg_3; - break; - } - array_3_struct c; - c = temp_c; - baz_struct baz = { b, c }; - return baz; -} + Bar a1; + a1 = a2; + double b2; + option_2 b3; + option_2 b5; + option_2 b7; + ┌─[ERROR]─ +│ +│ Unexpected error: Not_found +│ +└─ +#return code 125# diff --git a/tests/backends/python_name_clash.catala_en b/tests/backends/python_name_clash.catala_en index 16311a4c..62dab911 100644 --- a/tests/backends/python_name_clash.catala_en +++ b/tests/backends/python_name_clash.catala_en @@ -91,85 +91,89 @@ class BIn: def some_name(some_name_in:SomeNameIn): i = some_name_in.i_in - perhaps_none_arg = handle_exceptions([], []) - if perhaps_none_arg is None: + match_arg = handle_exceptions([], []) + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if True: - temp_o = (i + integer_of_string("1")) + o3 = Eoption(Eoption_Code.ESome, (i + integer_of_string("1"))) else: - temp_o = None - else: - x = perhaps_none_arg - temp_o = x - perhaps_none_arg_1 = 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=[] - )], - [temp_o] - ) - if perhaps_none_arg_1 is None: + o3 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + o3 = Eoption(Eoption_Code.ESome, x) + match_arg = 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 match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if False: - temp_o_1 = None + o2 = Eoption(Eoption_Code.ENone, Unit()) else: - temp_o_1 = None - else: - x_1 = perhaps_none_arg_1 - temp_o_1 = x_1 - perhaps_none_arg_2 = temp_o_1 - if perhaps_none_arg_2 is None: + o2 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + o2 = Eoption(Eoption_Code.ESome, x) + match_arg = o2 + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value raise NoValue(SourcePosition( filename="tests/backends/python_name_clash.catala_en", start_line=7, start_column=10, end_line=7, end_column=11, law_headings=[])) - else: - arg = perhaps_none_arg_2 - temp_o_2 = arg - o = temp_o_2 + elif match_arg.code == Eoption_Code.ESome: + arg = match_arg.value + o1 = arg + o = o1 return SomeName(o = o) def b(b_in:BIn): - perhaps_none_arg_3 = handle_exceptions([], []) - if perhaps_none_arg_3 is None: + match_arg = handle_exceptions([], []) + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if True: - temp_result = integer_of_string("1") + result3 = Eoption(Eoption_Code.ESome, integer_of_string("1")) else: - temp_result = None - else: - x_2 = perhaps_none_arg_3 - temp_result = x_2 - perhaps_none_arg_4 = 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=[] - )], - [temp_result] - ) - if perhaps_none_arg_4 is None: + result3 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + result3 = Eoption(Eoption_Code.ESome, x) + match_arg = 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 match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if False: - temp_result_1 = None + result2 = Eoption(Eoption_Code.ENone, Unit()) else: - temp_result_1 = None - else: - x_3 = perhaps_none_arg_4 - temp_result_1 = x_3 - perhaps_none_arg_5 = temp_result_1 - if perhaps_none_arg_5 is None: + result2 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + result2 = Eoption(Eoption_Code.ESome, x) + match_arg = result2 + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value raise NoValue(SourcePosition( filename="tests/backends/python_name_clash.catala_en", start_line=16, start_column=14, end_line=16, end_column=25, law_headings=[])) - else: - arg_1 = perhaps_none_arg_5 - temp_result_2 = arg_1 - result = some_name(SomeNameIn(i_in = temp_result_2)) - result_1 = SomeName(o = result.o) + elif match_arg.code == Eoption_Code.ESome: + arg = match_arg.value + result1 = arg + result = some_name(SomeNameIn(i_in = result1)) + result1 = SomeName(o = result.o) if True: - temp_some_name = result_1 + some_name2 = result1 else: - temp_some_name = result_1 - some_name_1 = temp_some_name - return B(some_name = some_name_1) + some_name2 = result1 + 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 c32d6301..d0ad73e2 100644 --- a/tests/name_resolution/good/toplevel_defs.catala_en +++ b/tests/name_resolution/good/toplevel_defs.catala_en @@ -107,164 +107,164 @@ $ catala test-scope S4 ```catala-test-inline $ catala scalc -let glob1_1 = 44.12 +let glob1 = 44.12 -let glob3_1 (x_2: money) = return to_rat x_2 + 10. +let glob3 (x: money) = return to_rat x + 10. -let glob4_2 (x_3: money) (y_4: decimal) = return to_rat x_3 * y_4 + 10. +let glob4 (x: money) (y: decimal) = return to_rat x * y + 10. -let glob5_aux_3 = - decl x_6 : decimal; - x_6 = to_rat 2 * 3.; - decl y_7 : decimal; - y_7 = 1000.; - return x_6 * y_7 +let glob5_init = + decl x : decimal; + x = to_rat 2 * 3.; + decl y : decimal; + y = 1000.; + return x * y -let glob5_5 = glob5_aux_3 () +let glob5 = glob5_init () -let glob2_8 = A {"y": glob1_1 >= 30., "z": 123. * 17.} +let glob2 = A {"y": glob1 >= 30., "z": 123. * 17.} -let S2_4 (S2_in_9: S2_in) = - decl temp_a_11 : decimal; - decl temp_a_12 : option decimal; - decl temp_a_13 : option decimal; +let S2 (S2_in: S2_in) = + decl a1 : decimal; + decl a2 : option decimal; + decl a3 : option decimal; switch handle_exceptions []: - | ENone __14 → + | ENone _ → if true: - temp_a_13 = ESome glob3_1 ¤44.00 + 100. + a3 = ESome glob3 ¤44.00 + 100. else: - temp_a_13 = ENone () - | ESome x_15 → - temp_a_13 = ESome x_15; - switch handle_exceptions [temp_a_13]: - | ENone __16 → + a3 = ENone () + | ESome x → + a3 = ESome x; + switch handle_exceptions [a3]: + | ENone _ → if false: - temp_a_12 = ENone () + a2 = ENone () else: - temp_a_12 = ENone () - | ESome x_17 → - temp_a_12 = ESome x_17; - switch temp_a_12: - | ENone __18 → + a2 = ENone () + | ESome x → + a2 = ESome x; + switch a2: + | ENone _ → fatal NoValue - | ESome arg_19 → - temp_a_11 = arg_19; - decl a_10 : decimal; - a_10 = temp_a_11; - return S2 {"a": a_10} + | ESome arg → + a1 = arg; + decl a : decimal; + a = a1; + return S2 {"a": a} -let S3_5 (S3_in_20: S3_in) = - decl temp_a_22 : decimal; - decl temp_a_23 : option decimal; - decl temp_a_24 : option decimal; +let S3 (S3_in: S3_in) = + decl a1 : decimal; + decl a2 : option decimal; + decl a3 : option decimal; switch handle_exceptions []: - | ENone __25 → + | ENone _ → if true: - temp_a_24 = ESome 50. + glob4_2 ¤44.00 55. + a3 = ESome 50. + glob4 ¤44.00 55. else: - temp_a_24 = ENone () - | ESome x_26 → - temp_a_24 = ESome x_26; - switch handle_exceptions [temp_a_24]: - | ENone __27 → + a3 = ENone () + | ESome x → + a3 = ESome x; + switch handle_exceptions [a3]: + | ENone _ → if false: - temp_a_23 = ENone () + a2 = ENone () else: - temp_a_23 = ENone () - | ESome x_28 → - temp_a_23 = ESome x_28; - switch temp_a_23: - | ENone __29 → + a2 = ENone () + | ESome x → + a2 = ESome x; + switch a2: + | ENone _ → fatal NoValue - | ESome arg_30 → - temp_a_22 = arg_30; - decl a_21 : decimal; - a_21 = temp_a_22; - return S3 {"a": a_21} + | ESome arg → + a1 = arg; + decl a : decimal; + a = a1; + return S3 {"a": a} -let S4_6 (S4_in_31: S4_in) = - decl temp_a_33 : decimal; - decl temp_a_34 : option decimal; - decl temp_a_35 : option decimal; +let S4 (S4_in: S4_in) = + decl a1 : decimal; + decl a2 : option decimal; + decl a3 : option decimal; switch handle_exceptions []: - | ENone __36 → + | ENone _ → if true: - temp_a_35 = ESome glob5_5 + 1. + a3 = ESome glob5 + 1. else: - temp_a_35 = ENone () - | ESome x_37 → - temp_a_35 = ESome x_37; - switch handle_exceptions [temp_a_35]: - | ENone __38 → + a3 = ENone () + | ESome x → + a3 = ESome x; + switch handle_exceptions [a3]: + | ENone _ → if false: - temp_a_34 = ENone () + a2 = ENone () else: - temp_a_34 = ENone () - | ESome x_39 → - temp_a_34 = ESome x_39; - switch temp_a_34: - | ENone __40 → + a2 = ENone () + | ESome x → + a2 = ESome x; + switch a2: + | ENone _ → fatal NoValue - | ESome arg_41 → - temp_a_33 = arg_41; - decl a_32 : decimal; - a_32 = temp_a_33; - return S4 {"a": a_32} + | ESome arg → + a1 = arg; + decl a : decimal; + a = a1; + return S4 {"a": a} -let S_7 (S_in_42: S_in) = - decl temp_a_54 : decimal; - decl temp_a_55 : option decimal; - decl temp_a_56 : option decimal; +let S (S_in: S_in) = + decl a1 : decimal; + decl a2 : option decimal; + decl a3 : option decimal; switch handle_exceptions []: - | ENone __57 → + | ENone _ → if true: - temp_a_56 = ESome glob1_1 * glob1_1 + a3 = ESome glob1 * glob1 else: - temp_a_56 = ENone () - | ESome x_58 → - temp_a_56 = ESome x_58; - switch handle_exceptions [temp_a_56]: - | ENone __59 → + a3 = ENone () + | ESome x → + a3 = ESome x; + switch handle_exceptions [a3]: + | ENone _ → if false: - temp_a_55 = ENone () + a2 = ENone () else: - temp_a_55 = ENone () - | ESome x_60 → - temp_a_55 = ESome x_60; - switch temp_a_55: - | ENone __61 → + a2 = ENone () + | ESome x → + a2 = ESome x; + switch a2: + | ENone _ → fatal NoValue - | ESome arg_62 → - temp_a_54 = arg_62; - decl a_43 : decimal; - a_43 = temp_a_54; - decl temp_b_45 : A {y: bool; z: decimal}; - decl temp_b_46 : option A {y: bool; z: decimal}; - decl temp_b_47 : option A {y: bool; z: decimal}; + | ESome arg → + a1 = arg; + decl a : decimal; + a = a1; + decl b1 : A {y: bool; z: decimal}; + decl b2 : option A {y: bool; z: decimal}; + decl b3 : option A {y: bool; z: decimal}; switch handle_exceptions []: - | ENone __48 → + | ENone _ → if true: - temp_b_47 = ESome glob2_8 + b3 = ESome glob2 else: - temp_b_47 = ENone () - | ESome x_49 → - temp_b_47 = ESome x_49; - switch handle_exceptions [temp_b_47]: - | ENone __50 → + b3 = ENone () + | ESome x → + b3 = ESome x; + switch handle_exceptions [b3]: + | ENone _ → if false: - temp_b_46 = ENone () + b2 = ENone () else: - temp_b_46 = ENone () - | ESome x_51 → - temp_b_46 = ESome x_51; - switch temp_b_46: - | ENone __52 → + b2 = ENone () + | ESome x → + b2 = ESome x; + switch b2: + | ENone _ → fatal NoValue - | ESome arg_53 → - temp_b_45 = arg_53; - decl b_44 : A {y: bool; z: decimal}; - b_44 = temp_b_45; - return S {"a": a_43, "b": b_44} + | ESome arg → + b1 = arg; + decl b : A {y: bool; z: decimal}; + b = b1; + return S {"a": a, "b": b} ``` ```catala-test-inline @@ -427,18 +427,18 @@ glob1 = (decimal_of_string("44.12")) def glob3(x:Money): return (decimal_of_money(x) + decimal_of_string("10.")) -def glob4(x_1:Money, y:Decimal): - return ((decimal_of_money(x_1) * y) + decimal_of_string("10.")) +def glob4(x:Money, y:Decimal): + return ((decimal_of_money(x) * y) + decimal_of_string("10.")) -def glob5_aux(): - x_2 = (decimal_of_integer(integer_of_string("2")) * +def glob5_init(): + x = (decimal_of_integer(integer_of_string("2")) * decimal_of_string("3.")) - y_1 = decimal_of_string("1000.") - return (x_2 * y_1) + y = decimal_of_string("1000.") + return (x * y) -glob5 = (glob5_aux()) +glob5 = (glob5_init()) -glob2 = ( +glob6 = ( A(y = (glob1 >= decimal_of_string("30.")), z = (decimal_of_string("123.") * @@ -446,202 +446,216 @@ glob2 = ( ) def s2(s2_in:S2In): - perhaps_none_arg = handle_exceptions([], []) - if perhaps_none_arg is None: + match_arg = handle_exceptions([], []) + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if True: - temp_a = (glob3(money_of_cents_string("4400")) + - decimal_of_string("100.")) + a3 = Eoption(Eoption_Code.ESome, + (glob3(money_of_cents_string("4400")) + + decimal_of_string("100."))) else: - temp_a = None - else: - x_3 = perhaps_none_arg - temp_a = x_3 - perhaps_none_arg_1 = 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"] - )], - [temp_a] - ) - if perhaps_none_arg_1 is None: + a3 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + a3 = Eoption(Eoption_Code.ESome, x) + match_arg = 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 match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if False: - temp_a_1 = None + a2 = Eoption(Eoption_Code.ENone, Unit()) else: - temp_a_1 = None - else: - x_4 = perhaps_none_arg_1 - temp_a_1 = x_4 - perhaps_none_arg_2 = temp_a_1 - if perhaps_none_arg_2 is None: + a2 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + a2 = Eoption(Eoption_Code.ESome, x) + match_arg = a2 + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value raise NoValue(SourcePosition( filename="tests/name_resolution/good/toplevel_defs.catala_en", start_line=50, start_column=10, end_line=50, end_column=11, law_headings=["Test toplevel function defs"])) - else: - arg = perhaps_none_arg_2 - temp_a_2 = arg - a = temp_a_2 + elif match_arg.code == Eoption_Code.ESome: + arg = match_arg.value + a1 = arg + a = a1 return S2(a = a) def s3(s3_in:S3In): - perhaps_none_arg_3 = handle_exceptions([], []) - if perhaps_none_arg_3 is None: + match_arg = handle_exceptions([], []) + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if True: - temp_a_3 = (decimal_of_string("50.") + + a3 = Eoption(Eoption_Code.ESome, + (decimal_of_string("50.") + glob4(money_of_cents_string("4400"), - decimal_of_string("55."))) + decimal_of_string("55.")))) else: - temp_a_3 = None - else: - x_5 = perhaps_none_arg_3 - temp_a_3 = x_5 - perhaps_none_arg_4 = 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"] - )], - [temp_a_3] - ) - if perhaps_none_arg_4 is None: + a3 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + a3 = Eoption(Eoption_Code.ESome, x) + match_arg = 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 match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if False: - temp_a_4 = None + a2 = Eoption(Eoption_Code.ENone, Unit()) else: - temp_a_4 = None - else: - x_6 = perhaps_none_arg_4 - temp_a_4 = x_6 - perhaps_none_arg_5 = temp_a_4 - if perhaps_none_arg_5 is None: + a2 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + a2 = Eoption(Eoption_Code.ESome, x) + match_arg = a2 + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value raise NoValue(SourcePosition( filename="tests/name_resolution/good/toplevel_defs.catala_en", start_line=71, start_column=10, end_line=71, end_column=11, law_headings=["Test function def with two args"])) - else: - arg_1 = perhaps_none_arg_5 - temp_a_5 = arg_1 - a_1 = temp_a_5 - return S3(a = a_1) + elif match_arg.code == Eoption_Code.ESome: + arg = match_arg.value + a1 = arg + a = a1 + return S3(a = a) def s4(s4_in:S4In): - perhaps_none_arg_6 = handle_exceptions([], []) - if perhaps_none_arg_6 is None: + match_arg = handle_exceptions([], []) + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if True: - temp_a_6 = (glob5 + decimal_of_string("1.")) + a3 = Eoption(Eoption_Code.ESome, + (glob5 + + decimal_of_string("1."))) else: - temp_a_6 = None - else: - x_7 = perhaps_none_arg_6 - temp_a_6 = x_7 - perhaps_none_arg_7 = 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"] - )], - [temp_a_6] - ) - if perhaps_none_arg_7 is None: + a3 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + a3 = Eoption(Eoption_Code.ESome, x) + match_arg = 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 match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if False: - temp_a_7 = None + a2 = Eoption(Eoption_Code.ENone, Unit()) else: - temp_a_7 = None - else: - x_8 = perhaps_none_arg_7 - temp_a_7 = x_8 - perhaps_none_arg_8 = temp_a_7 - if perhaps_none_arg_8 is None: + a2 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + a2 = Eoption(Eoption_Code.ESome, x) + match_arg = a2 + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value raise NoValue(SourcePosition( filename="tests/name_resolution/good/toplevel_defs.catala_en", start_line=95, start_column=10, end_line=95, end_column=11, law_headings=["Test inline defs in toplevel defs"])) - else: - arg_2 = perhaps_none_arg_8 - temp_a_8 = arg_2 - a_2 = temp_a_8 - return S4(a = a_2) + elif match_arg.code == Eoption_Code.ESome: + arg = match_arg.value + a1 = arg + a = a1 + return S4(a = a) -def s(s_in:SIn): - perhaps_none_arg_9 = handle_exceptions([], []) - if perhaps_none_arg_9 is None: +def s5(s_in:SIn): + match_arg = handle_exceptions([], []) + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if True: - temp_a_9 = (glob1 * glob1) + a3 = Eoption(Eoption_Code.ESome, (glob1 * glob1)) else: - temp_a_9 = None - else: - x_9 = perhaps_none_arg_9 - temp_a_9 = x_9 - perhaps_none_arg_10 = 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"] - )], - [temp_a_9] - ) - if perhaps_none_arg_10 is None: + a3 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + a3 = Eoption(Eoption_Code.ESome, x) + match_arg = 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 match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if False: - temp_a_10 = None + a2 = Eoption(Eoption_Code.ENone, Unit()) else: - temp_a_10 = None - else: - x_10 = perhaps_none_arg_10 - temp_a_10 = x_10 - perhaps_none_arg_11 = temp_a_10 - if perhaps_none_arg_11 is None: + a2 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + a2 = Eoption(Eoption_Code.ESome, x) + match_arg = a2 + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value raise NoValue(SourcePosition( filename="tests/name_resolution/good/toplevel_defs.catala_en", start_line=7, start_column=10, end_line=7, end_column=11, law_headings=["Test basic toplevel values defs"])) - else: - arg_3 = perhaps_none_arg_11 - temp_a_11 = arg_3 - a_3 = temp_a_11 - perhaps_none_arg_12 = handle_exceptions([], []) - if perhaps_none_arg_12 is None: + elif match_arg.code == Eoption_Code.ESome: + arg = match_arg.value + a1 = arg + a = a1 + match_arg = handle_exceptions([], []) + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if True: - temp_b = glob2 + b3 = Eoption(Eoption_Code.ESome, glob6) else: - temp_b = None - else: - x_11 = perhaps_none_arg_12 - temp_b = x_11 - perhaps_none_arg_13 = 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"] - )], - [temp_b] - ) - if perhaps_none_arg_13 is None: + b3 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + b3 = Eoption(Eoption_Code.ESome, x) + match_arg = 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 match_arg.code == Eoption_Code.ENone: + _ = match_arg.value if False: - temp_b_1 = None + b2 = Eoption(Eoption_Code.ENone, Unit()) else: - temp_b_1 = None - else: - x_12 = perhaps_none_arg_13 - temp_b_1 = x_12 - perhaps_none_arg_14 = temp_b_1 - if perhaps_none_arg_14 is None: + b2 = Eoption(Eoption_Code.ENone, Unit()) + elif match_arg.code == Eoption_Code.ESome: + x = match_arg.value + b2 = Eoption(Eoption_Code.ESome, x) + match_arg = b2 + if match_arg.code == Eoption_Code.ENone: + _ = match_arg.value raise NoValue(SourcePosition( filename="tests/name_resolution/good/toplevel_defs.catala_en", start_line=8, start_column=10, end_line=8, end_column=11, law_headings=["Test basic toplevel values defs"])) - else: - arg_4 = perhaps_none_arg_14 - temp_b_2 = arg_4 - b = temp_b_2 - return S(a = a_3, b = b) + elif match_arg.code == Eoption_Code.ESome: + arg = match_arg.value + b1 = arg + b = b1 + return S(a = a, b = b) ``` diff --git a/tests/scope/good/nothing.catala_en b/tests/scope/good/nothing.catala_en index 88548eaa..a8463b5d 100644 --- a/tests/scope/good/nothing.catala_en +++ b/tests/scope/good/nothing.catala_en @@ -39,11 +39,11 @@ $ catala Scalc -s Foo2 -O -t │ 5 │ output bar content integer │ │ ‾‾‾ └─ Test -let Foo2_1 (Foo2_in_1: Foo2_in) = - decl temp_bar_3 : integer; +let Foo2 (Foo2_in: Foo2_in) = + decl bar1 : integer; fatal NoValue; - decl bar_2 : integer; - bar_2 = temp_bar_3; - return Foo2 {"bar": bar_2} + decl bar : integer; + bar = bar1; + return Foo2 {"bar": bar} ```