Renaming: use in the scalc translation and in Python

This commit is contained in:
Louis Gesbert 2024-08-07 17:43:14 +02:00
parent d23544de39
commit 1230f787d6
21 changed files with 875 additions and 1170 deletions

View File

@ -228,8 +228,11 @@ module Passes = struct
~check_invariants ~check_invariants
~(typed : ty mark) ~(typed : ty mark)
~closure_conversion ~closure_conversion
~monomorphize_types : ~monomorphize_types
typed Lcalc.Ast.program * Scopelang.Dependency.TVertex.t list = ~renaming :
typed Lcalc.Ast.program *
Scopelang.Dependency.TVertex.t list *
Expr.Renaming.context option =
let prg, type_ordering = let prg, type_ordering =
dcalc options ~includes ~optimize ~check_invariants ~typed dcalc options ~includes ~optimize ~check_invariants ~typed
in in
@ -275,7 +278,19 @@ module Passes = struct
prg, type_ordering) prg, type_ordering)
else prg, type_ordering else prg, type_ordering
in 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 let scalc
options options
@ -286,17 +301,30 @@ module Passes = struct
~keep_special_ops ~keep_special_ops
~dead_value_assignment ~dead_value_assignment
~no_struct_literals ~no_struct_literals
~monomorphize_types : ~monomorphize_types
Scalc.Ast.program * Scopelang.Dependency.TVertex.t list = ~renaming :
let prg, type_ordering = 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 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 in
debug_pass_name "scalc"; debug_pass_name "scalc";
( Scalc.From_lcalc.translate_program ( 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, prg,
type_ordering ) type_ordering,
renaming_context )
end end
module Commands = struct module Commands = struct
@ -711,9 +739,9 @@ module Commands = struct
closure_conversion closure_conversion
monomorphize_types monomorphize_types
ex_scope_opt = ex_scope_opt =
let prg, _ = let prg, _, _ =
Passes.lcalc options ~includes ~optimize ~check_invariants Passes.lcalc options ~includes ~optimize ~check_invariants
~closure_conversion ~typed ~monomorphize_types ~closure_conversion ~typed ~monomorphize_types ~renaming:None
in in
let _output_file, with_output = get_output_format options output in let _output_file, with_output = get_output_format options output in
with_output with_output
@ -759,9 +787,9 @@ module Commands = struct
optimize optimize
check_invariants check_invariants
ex_scope_opt = ex_scope_opt =
let prg, _ = let prg, _, _ =
Passes.lcalc options ~includes ~optimize ~check_invariants Passes.lcalc options ~includes ~optimize ~check_invariants
~closure_conversion ~monomorphize_types ~typed ~closure_conversion ~monomorphize_types ~typed ~renaming:None
in in
Interpreter.load_runtime_modules Interpreter.load_runtime_modules
~hashf:(Hash.finalise ~closure_conversion ~monomorphize_types) ~hashf:(Hash.finalise ~closure_conversion ~monomorphize_types)
@ -809,9 +837,10 @@ module Commands = struct
check_invariants check_invariants
closure_conversion closure_conversion
ex_scope_opt = ex_scope_opt =
let prg, type_ordering = let prg, type_ordering, _ =
Passes.lcalc options ~includes ~optimize ~check_invariants Passes.lcalc options ~includes ~optimize ~check_invariants
~typed:Expr.typed ~closure_conversion ~monomorphize_types:false ~typed:Expr.typed ~closure_conversion ~monomorphize_types:false
~renaming:(Some Lcalc.To_ocaml.renaming)
in in
let output_file, with_output = let output_file, with_output =
get_output_format options ~ext:".ml" output get_output_format options ~ext:".ml" output
@ -851,10 +880,10 @@ module Commands = struct
no_struct_literals no_struct_literals
monomorphize_types monomorphize_types
ex_scope_opt = ex_scope_opt =
let prg, _ = let prg, _, _ =
Passes.scalc options ~includes ~optimize ~check_invariants Passes.scalc options ~includes ~optimize ~check_invariants
~closure_conversion ~keep_special_ops ~dead_value_assignment ~closure_conversion ~keep_special_ops ~dead_value_assignment
~no_struct_literals ~monomorphize_types ~no_struct_literals ~monomorphize_types ~renaming:None
in in
let _output_file, with_output = get_output_format options output in let _output_file, with_output = get_output_format options output in
with_output with_output
@ -900,10 +929,11 @@ module Commands = struct
optimize optimize
check_invariants check_invariants
closure_conversion = closure_conversion =
let prg, type_ordering = let prg, type_ordering, _ren_ctx =
Passes.scalc options ~includes ~optimize ~check_invariants Passes.scalc options ~includes ~optimize ~check_invariants
~closure_conversion ~keep_special_ops:false ~dead_value_assignment:true ~closure_conversion ~keep_special_ops:false ~dead_value_assignment:true
~no_struct_literals:false ~monomorphize_types:false ~no_struct_literals:false ~monomorphize_types:false
~renaming:(Some Scalc.To_python.renaming)
in in
let output_file, with_output = let output_file, with_output =
@ -929,11 +959,12 @@ module Commands = struct
$ Cli.Flags.closure_conversion) $ Cli.Flags.closure_conversion)
let c options includes output optimize check_invariants = 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 Passes.scalc options ~includes ~optimize ~check_invariants
~closure_conversion:true ~keep_special_ops:true ~closure_conversion:true ~keep_special_ops:true
~dead_value_assignment:false ~no_struct_literals:true ~dead_value_assignment:false ~no_struct_literals:true
~monomorphize_types:true ~monomorphize_types:true
~renaming:(Some Scalc.To_c.renaming)
in in
let output_file, with_output = get_output_format options ~ext:".c" output in let output_file, with_output = get_output_format options ~ext:".c" output in
Message.debug "Compiling program into C..."; Message.debug "Compiling program into C...";

View File

@ -53,7 +53,9 @@ module Passes : sig
typed:'m Shared_ast.mark -> typed:'m Shared_ast.mark ->
closure_conversion:bool -> closure_conversion:bool ->
monomorphize_types: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 : val scalc :
Global.options -> Global.options ->
@ -65,7 +67,10 @@ module Passes : sig
dead_value_assignment:bool -> dead_value_assignment:bool ->
no_struct_literals:bool -> no_struct_literals:bool ->
monomorphize_types: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 end
module Commands : sig module Commands : sig

View File

@ -130,6 +130,13 @@ let ocaml_keywords =
"Oper"; "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 = let format_struct_name (fmt : Format.formatter) (v : StructName.t) : unit =
(match StructName.path v with (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) 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 let format_struct_embedding
(fmt : Format.formatter) (fmt : Format.formatter)
((struct_name, struct_fields) : StructName.t * typ StructField.Map.t) = ((struct_name, struct_fields) : StructName.t * typ StructField.Map.t) =
@ -730,21 +738,6 @@ let format_program
~(hashf : Hash.t -> Hash.full) ~(hashf : Hash.t -> Hash.full)
(p : 'm Ast.program) (p : 'm Ast.program)
(type_ordering : Scopelang.Dependency.TVertex.t list) : unit = (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_open_vbox fmt 0;
Format.pp_print_string fmt header; Format.pp_print_string fmt header;
check_and_reexport_used_modules fmt ~hashf check_and_reexport_used_modules fmt ~hashf

View File

@ -17,7 +17,7 @@
open Catala_utils open Catala_utils
open Shared_ast open Shared_ast
val ocaml_keywords : string list val renaming : Program.renaming
(** Formats a lambda calculus program into a valid OCaml program *) (** Formats a lambda calculus program into a valid OCaml program *)

View File

@ -475,22 +475,10 @@ let run
monomorphize_types monomorphize_types
_options = _options =
let options = Global.enforce_options ~trace:true () in let options = Global.enforce_options ~trace:true () in
let prg, type_ordering = let prg, type_ordering, _ =
Driver.Passes.lcalc options ~includes ~optimize ~check_invariants Driver.Passes.lcalc options ~includes ~optimize ~check_invariants
~closure_conversion ~typed:Expr.typed ~monomorphize_types ~closure_conversion ~typed:Expr.typed ~monomorphize_types
in ~renaming:(Some Lcalc.To_ocaml.renaming)
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
in in
let jsoo_output_file, with_formatter = let jsoo_output_file, with_formatter =
Driver.Commands.get_output_format options ~ext:"_api_web.ml" output Driver.Commands.get_output_format options ~ext:"_api_web.ml" output

View File

@ -213,9 +213,10 @@ let run
monomorphize_types monomorphize_types
ex_scope ex_scope
options = options =
let prg, _ = let prg, _, _ =
Driver.Passes.lcalc options ~includes ~optimize ~check_invariants Driver.Passes.lcalc options ~includes ~optimize ~check_invariants
~closure_conversion ~typed:Expr.typed ~monomorphize_types ~closure_conversion ~typed:Expr.typed ~monomorphize_types
~renaming:(Some Lcalc.To_ocaml.renaming)
in in
let output_file, with_output = let output_file, with_output =
Driver.Commands.get_output_format options ~ext:"_schema.json" output Driver.Commands.get_output_format options ~ext:"_schema.json" output

View File

@ -24,10 +24,11 @@ open Catala_utils
let run includes output optimize check_invariants closure_conversion options = let run includes output optimize check_invariants closure_conversion options =
let open Driver.Commands in let open Driver.Commands in
let prg, type_ordering = let prg, type_ordering, _ =
Driver.Passes.scalc options ~includes ~optimize ~check_invariants Driver.Passes.scalc options ~includes ~optimize ~check_invariants
~closure_conversion ~keep_special_ops:false ~dead_value_assignment:true ~closure_conversion ~keep_special_ops:false ~dead_value_assignment:true
~no_struct_literals:false ~monomorphize_types:false ~no_struct_literals:false ~monomorphize_types:false
~renaming:(Some Scalc.To_python.renaming)
in in
let output_file, with_output = get_output_format options ~ext:".py" output in let output_file, with_output = get_output_format options ~ext:".py" output in

View File

@ -24,6 +24,7 @@ type translation_config = {
keep_special_ops : bool; keep_special_ops : bool;
dead_value_assignment : bool; dead_value_assignment : bool;
no_struct_literals : bool; no_struct_literals : bool;
renaming_context : Expr.Renaming.context;
} }
type 'm ctxt = { type 'm ctxt = {
@ -33,6 +34,7 @@ type 'm ctxt = {
context_name : string; context_name : string;
config : translation_config; config : translation_config;
program_ctx : A.ctx; program_ctx : A.ctx;
ren_ctx : Expr.Renaming.context;
} }
(* Expressions can spill out side effect, hence this function also returns a (* Expressions can spill out side effect, hence this function also returns a
@ -65,6 +67,36 @@ end
let ( ++ ) = RevBlock.seq 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 rec translate_expr_list ctxt args =
let stmts, args = let stmts, args =
List.fold_left 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 = _ } -> | EApp { f = EAbs { binder; tys }, binder_mark; args; tys = _ } ->
(* This defines multiple local variables at the time *) (* This defines multiple local variables at the time *)
let binder_pos = Expr.mark_pos binder_mark in 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 vars_tau = List.map2 (fun x tau -> x, tau) (Array.to_list vars) tys in
let ctxt = let ctxt =
{ List.fold_left (register_fresh_arg ~pos:binder_pos)
ctxt with ctxt vars_tau
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;
}
in in
let local_decls = let local_decls =
List.fold_left 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 }) raise (NotAnExpr { needs_a_local_decl = true })
| _ -> . | _ -> .
with NotAnExpr { needs_a_local_decl } -> with NotAnExpr { needs_a_local_decl } ->
let tmp_var = let tmp_var, ctxt =
A.VarName.fresh let name =
( (*This piece of logic is used to make the code more readable. TODO: match ctxt.inside_definition_of with
should be removed when | None -> ctxt.context_name
https://github.com/CatalaLang/catala/issues/240 is fixed. *) | Some v -> A.VarName.to_string v
(match ctxt.inside_definition_of with in
| None -> ctxt.context_name fresh_var ctxt name ~pos:(Expr.pos expr)
| 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 )
in in
let ctxt = 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; _ } -> | EApp { f = EAbs { binder; tys }, binder_mark; args; _ } ->
(* This defines multiple local variables at the time *) (* This defines multiple local variables at the time *)
let binder_pos = Expr.mark_pos binder_mark in 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 vars_tau = List.map2 (fun x tau -> x, tau) (Array.to_list vars) tys in
let ctxt = let ctxt =
{ List.fold_left
ctxt with (register_fresh_arg ~pos:binder_pos)
var_dict = ctxt vars_tau
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;
}
in in
let local_decls = let local_decls =
List.map 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 let rest_of_block = translate_statements ctxt body in
local_decls @ List.flatten def_blocks @ rest_of_block local_decls @ List.flatten def_blocks @ rest_of_block
| EAbs { binder; tys } -> | EAbs { binder; tys } ->
let vars, body = Bindlib.unmbind binder in let closure_name, ctxt =
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 =
match ctxt.inside_definition_of with match ctxt.inside_definition_of with
| None -> A.VarName.fresh (ctxt.context_name, Expr.pos block_expr) | None -> fresh_var ctxt ctxt.context_name ~pos:(Expr.pos block_expr)
| Some x -> x | Some x -> x, ctxt
in 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 = let ctxt =
{ List.fold_left
ctxt with (register_fresh_arg ~pos:binder_pos)
var_dict = { ctxt with inside_definition_of = None }
List.fold_left vars_tau
(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;
}
in in
let new_body = translate_statements ctxt body 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 -> (fun _ arg new_args ->
match Mark.remove arg with match Mark.remove arg with
| EAbs { binder; tys } -> | EAbs { binder; tys } ->
let vars, body = Bindlib.unmbind binder in let vars, body, ctxt = unmbind ctxt binder in
assert (Array.length vars = 1); assert (Array.length vars = 1);
let var = vars.(0) in let var = vars.(0) in
let scalc_var = let scalc_var, ctxt =
A.VarName.fresh (Bindlib.name_of var, Expr.pos arg) register_fresh_var ctxt var ~pos:(Expr.pos arg)
in
let ctxt =
{ ctxt with var_dict = Var.Map.add var scalc_var ctxt.var_dict }
in in
let new_arg = translate_statements ctxt body 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 let rec translate_scope_body_expr
~(config : translation_config) ctx
(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)
(scope_expr : 'm L.expr scope_body_expr) : A.block = (scope_expr : 'm L.expr scope_body_expr) : A.block =
let ctx = let ctx =
{ { ctx with inside_definition_of = None }
func_dict;
var_dict;
inside_definition_of = None;
context_name = Mark.remove (ScopeName.get_info scope_name);
config;
program_ctx;
}
in in
match scope_expr with match scope_expr with
| Last e -> | Last e ->
let block, new_e = translate_expr ctx e in let block, new_e = translate_expr ctx e in
RevBlock.rebuild block ~tail:[A.SReturn (Mark.remove new_e), Mark.get new_e] RevBlock.rebuild block ~tail:[A.SReturn (Mark.remove new_e), Mark.get new_e]
| Cons (scope_let, next_bnd) -> ( | Cons (scope_let, next_bnd) -> (
let let_var, scope_let_next = Bindlib.unbind next_bnd in let let_var, scope_let_next, ctx1 = unbind ctx next_bnd in
let let_var_id = let let_var_id, ctx =
A.VarName.fresh (Bindlib.name_of let_var, scope_let.scope_let_pos) register_fresh_var ctx1 let_var ~pos:scope_let.scope_let_pos
in in
let new_var_dict = Var.Map.add let_var let_var_id var_dict in
let next = let next =
translate_scope_body_expr ~config scope_name program_ctx new_var_dict translate_scope_body_expr ctx scope_let_next
func_dict scope_let_next
in in
match scope_let.scope_let_kind with match scope_let.scope_let_kind with
| Assertion -> | Assertion ->
@ -615,7 +604,7 @@ let rec translate_scope_body_expr
scope_let.scope_let_pos ) scope_let.scope_let_pos )
:: next)) :: next))
let translate_program ~(config : translation_config) (p : 'm L.program) : let translate_program ~(config : translation_config) (p : 'm L.program):
A.program = A.program =
let modules = let modules =
List.fold_left List.fold_left
@ -630,29 +619,41 @@ let translate_program ~(config : translation_config) (p : 'm L.program) :
ModuleName.Map.empty ModuleName.Map.empty
(Program.modules_to_list p.decl_ctx.ctx_modules) (Program.modules_to_list p.decl_ctx.ctx_modules)
in in
let ctx = { A.decl_ctx = p.decl_ctx; A.modules } in let program_ctx = { A.decl_ctx = p.decl_ctx; A.modules } in
let (_, _, rev_items), _vlist = 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 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 match code_item with
| ScopeDef (name, body) -> | ScopeDef (name, body) ->
let scope_input_var, scope_body_expr = let scope_input_var, scope_body_expr, ctxt1 =
Bindlib.unbind body.scope_body_expr unbind ctxt body.scope_body_expr
in in
let input_pos = Mark.get (ScopeName.get_info name) in let input_pos = Mark.get (ScopeName.get_info name) in
let scope_input_var_id = let scope_input_var_id, ctxt =
A.VarName.fresh (Bindlib.name_of scope_input_var, input_pos) register_fresh_var ctxt scope_input_var ~pos:input_pos
in
let var_dict_local =
Var.Map.add scope_input_var scope_input_var_id var_dict
in in
let new_scope_body = 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 scope_body_expr
in in
let func_id = A.FuncName.fresh (Bindlib.name_of var, Pos.no_pos) in let func_id, ctxt1 =
( Var.Map.add var func_id func_dict, register_fresh_func ctxt1 var ~pos:input_pos
var_dict, in
( ctxt1,
A.SScope A.SScope
{ {
Ast.scope_body_name = name; Ast.scope_body_name = name;
@ -670,40 +671,32 @@ let translate_program ~(config : translation_config) (p : 'm L.program) :
}; };
} }
:: rev_items ) :: rev_items )
| Topdef (name, topdef_ty, (EAbs abs, _)) -> | Topdef (name, topdef_ty, (EAbs abs, m)) ->
(* Toplevel function def *) (* Toplevel function def *)
let func_id = A.FuncName.fresh (Bindlib.name_of var, Pos.no_pos) in let (block, expr), args_id =
let args_a, expr = Bindlib.unmbind abs.binder in let args_a, expr, ctxt = unmbind ctxt abs.binder in
let args = Array.to_list args_a in let args = Array.to_list args_a in
let args_id = let rargs_id, ctxt =
List.map2 List.fold_left2
(fun v ty -> (fun (rargs_id, ctxt) v ty ->
let pos = Mark.get ty in let pos = Mark.get ty in
(A.VarName.fresh (Bindlib.name_of v, pos), pos), ty) let id, ctxt = register_fresh_var ctxt v ~pos in
args abs.tys ((id, pos), ty) :: rargs_id, ctxt)
in ([], ctxt) args abs.tys
let block, expr = in
let ctxt = let ctxt =
{ { ctxt with
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;
context_name = Mark.remove (TopdefName.get_info name); context_name = Mark.remove (TopdefName.get_info name);
config;
program_ctx = ctx;
} }
in in
translate_expr ctxt expr translate_expr ctxt expr, List.rev rargs_id
in in
let body_block = let body_block =
RevBlock.rebuild block RevBlock.rebuild block
~tail:[A.SReturn (Mark.remove expr), Mark.get expr] ~tail:[A.SReturn (Mark.remove expr), Mark.get expr]
in in
( Var.Map.add var func_id func_dict, let func_id, ctxt = register_fresh_func ctxt var ~pos:(Expr.mark_pos m) in
var_dict, ( ctxt,
A.SFunc A.SFunc
{ {
var = func_id; var = func_id;
@ -721,30 +714,28 @@ let translate_program ~(config : translation_config) (p : 'm L.program) :
:: rev_items ) :: rev_items )
| Topdef (name, topdef_ty, expr) -> | Topdef (name, topdef_ty, expr) ->
(* Toplevel constant def *) (* Toplevel constant def *)
let var_id = A.VarName.fresh (Bindlib.name_of var, Pos.no_pos) in
let block, expr = let block, expr =
let ctxt = let ctxt =
{ { ctxt with
func_dict;
var_dict;
inside_definition_of = None;
context_name = Mark.remove (TopdefName.get_info name); context_name = Mark.remove (TopdefName.get_info name);
config;
program_ctx = ctx;
} }
in in
translate_expr ctxt expr translate_expr ctxt expr
in 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 (* If the evaluation of the toplevel expr requires preliminary
statements, we lift its computation into an auxiliary function *) statements, we lift its computation into an auxiliary function *)
let rev_items = let rev_items, ctxt =
if (block :> (A.stmt * Pos.t) list) = [] then 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 else
let pos = Mark.get expr in let pos = Mark.get expr in
let func_id = let func_name, ctxt =
A.FuncName.fresh (Bindlib.name_of var ^ "_aux", pos) get_name ctxt (A.VarName.to_string var_id ^ "_init")
in in
let func_id = A.FuncName.fresh (func_name, pos) in
(* The list is being built in reverse order *) (* The list is being built in reverse order *)
(* FIXME: find a better way than a function with no parameters... *) (* FIXME: find a better way than a function with no parameters... *)
A.SVar A.SVar
@ -765,14 +756,13 @@ let translate_program ~(config : translation_config) (p : 'm L.program) :
A.func_return_typ = topdef_ty; A.func_return_typ = topdef_ty;
}; };
} }
:: rev_items :: rev_items,
ctxt
in in
( func_dict, ( ctxt,
(* No need to add func_id since the function will only be called (* No need to add func_id since the function will only be called
right here *) right here *)
Var.Map.add var var_id var_dict,
rev_items )) rev_items ))
~init:(Var.Map.empty, Var.Map.empty, [])
p.code_items p.code_items
in 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 }

View File

@ -32,7 +32,9 @@ type translation_config = {
(** When [no_struct_literals] is true, the translation inserts a temporary (** When [no_struct_literals] is true, the translation inserts a temporary
variable to hold the initialization of struct literals. This matches variable to hold the initialization of struct literals. This matches
what C89 expects. *) what C89 expects. *)
renaming_context : Expr.Renaming.context;
} }
val translate_program : val translate_program :
config:translation_config -> typed Lcalc.Ast.program -> Ast.program config:translation_config -> typed Lcalc.Ast.program ->
Ast.program

View File

@ -21,10 +21,12 @@ open Ast
let needs_parens (_e : expr) : bool = false let needs_parens (_e : expr) : bool = false
let format_var_name (fmt : Format.formatter) (v : VarName.t) : unit = 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 = let format_func_name (fmt : Format.formatter) (v : FuncName.t) : unit =
Format.fprintf fmt "@{<green>%a_%d@}" FuncName.format v (FuncName.id v) FuncName.format fmt v
(* Format.fprintf fmt "@{<green>%a_%d@}" FuncName.format v (FuncName.id v) *)
let rec format_expr let rec format_expr
(decl_ctx : decl_ctx) (decl_ctx : decl_ctx)

View File

@ -21,109 +21,21 @@ module D = Dcalc.Ast
module L = Lcalc.Ast module L = Lcalc.Ast
open Ast open Ast
let avoid_keywords (s : string) : string = let c_keywords =
if [ "auto"; "break"; "case"; "char"; "const"; "continue"; "default";
match s with "do"; "double"; "else"; "enum"; "extern"; "float"; "for"; "goto";
(* list taken from "if"; "inline"; "int"; "long"; "register"; "restrict"; "return";
https://learn.microsoft.com/en-us/cpp/c-language/c-keywords *) "short"; "signed"; "sizeof"; "static"; "struct"; "switch"; "typedef";
| "auto" | "break" | "case" | "char" | "const" | "continue" | "default" "union"; "unsigned"; "void"; "volatile"; "while" ]
| "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 format_struct_name (fmt : Format.formatter) (v : StructName.t) : unit = let renaming =
Format.fprintf fmt "%s" Program.renaming ()
(Format.asprintf "%a_struct" StructName.format v ~reserved:c_keywords
|> String.to_ascii (* TODO: add catala runtime built-ins as reserved as well ? *)
|> String.to_snake_case ~reset_context_for_closed_terms:true
|> avoid_keywords) ~skip_constant_binders:true
~constant_binder_name:None
let format_struct_field_name (fmt : Format.formatter) (v : StructField.t) : unit ~namespaced_fields_constrs:false
=
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
module TypMap = Map.Make (struct module TypMap = Map.Make (struct
type t = naked_typ type t = naked_typ
@ -156,12 +68,12 @@ let rec format_typ
(format_typ decl_ctx (fun fmt -> Format.fprintf fmt "arg_%d" i)) (format_typ decl_ctx (fun fmt -> Format.fprintf fmt "arg_%d" i))
t)) t))
(List.mapi (fun x y -> y, x) ts) (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 _ -> | TOption _ ->
Message.error ~internal:true Message.error ~internal:true
"All option types should have been monomorphized before compilation to C." "All option types should have been monomorphized before compilation to C."
| TDefault t -> format_typ decl_ctx element_name fmt t | 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) -> | TArrow (t1, t2) ->
Format.fprintf fmt "%a(%a)" Format.fprintf fmt "%a(%a)"
(format_typ decl_ctx (fun fmt -> Format.fprintf fmt "(*%t)" element_name)) (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 format_struct_decl fmt (struct_name, struct_fields) =
let fields = StructField.Map.bindings struct_fields in let fields = StructField.Map.bindings struct_fields in
Format.fprintf fmt "@[<v 2>typedef struct %a {@ %a@]@,} %a;" Format.fprintf fmt "@[<v 2>typedef struct %a {@ %a@]@,} %a;"
format_struct_name struct_name StructName.format struct_name
(Format.pp_print_list (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ") ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ")
(fun fmt (struct_field, struct_field_type) -> (fun fmt (struct_field, struct_field_type) ->
Format.fprintf fmt "@[<v>%a;@]" Format.fprintf fmt "@[<v>%a;@]"
(format_typ ctx (fun fmt -> (format_typ ctx (fun fmt ->
format_struct_field_name fmt struct_field)) StructField.format fmt struct_field))
struct_field_type)) struct_field_type))
fields format_struct_name struct_name fields StructName.format struct_name
in in
let format_enum_decl fmt (enum_name, enum_cons) = let format_enum_decl fmt (enum_name, enum_cons) =
if EnumConstructor.Map.is_empty enum_cons then if EnumConstructor.Map.is_empty enum_cons then
failwith "no constructors in the enum" failwith "no constructors in the enum"
else else
Format.fprintf fmt "@[<v 2>enum %a_code {@,%a@]@,} %a_code;@\n@\n" Format.fprintf fmt "@[<v 2>enum %a_code {@,%a@]@,} %a_code;@\n@\n"
format_enum_name enum_name EnumName.format enum_name
(Format.pp_print_list (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (enum_cons, _) -> (fun fmt (enum_cons, _) ->
Format.fprintf fmt "%a_%a" format_enum_name enum_name Format.fprintf fmt "%a_%a" EnumName.format enum_name
format_enum_cons_name enum_cons)) EnumConstructor.format enum_cons))
(EnumConstructor.Map.bindings enum_cons) (EnumConstructor.Map.bindings enum_cons)
format_enum_name enum_name; EnumName.format enum_name;
Format.fprintf fmt Format.fprintf fmt
"@[<v 2>typedef struct %a {@ enum %a_code code;@ @[<v 2>union {@ %a@]@,\ "@[<v 2>typedef struct %a {@ enum %a_code code;@ @[<v 2>union {@ %a@]@,\
} payload;@]@,\ } 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 (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ") ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ")
(fun fmt (enum_cons, typ) -> (fun fmt (enum_cons, typ) ->
Format.fprintf fmt "%a;" 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)) typ))
(EnumConstructor.Map.bindings enum_cons) (EnumConstructor.Map.bindings enum_cons)
format_enum_name enum_name EnumName.format enum_name
in in
let is_in_type_ordering s = 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) : let rec format_expression (ctx : decl_ctx) (fmt : Format.formatter) (e : expr) :
unit = unit =
match Mark.remove e with match Mark.remove e with
| EVar v -> format_var fmt v | EVar v -> VarName.format fmt v
| EFunc f -> format_func_name fmt f | EFunc f -> FuncName.format fmt f
| EStruct { fields = es; _ } -> | EStruct { fields = es; _ } ->
(* These should only appear when initializing a variable definition *) (* These should only appear when initializing a variable definition *)
Format.fprintf fmt "{ %a }" Format.fprintf fmt "{ %a }"
@ -340,10 +252,10 @@ let rec format_expression (ctx : decl_ctx) (fmt : Format.formatter) (e : expr) :
(StructField.Map.bindings es) (StructField.Map.bindings es)
| EStructFieldAccess { e1; field; _ } -> | EStructFieldAccess { e1; field; _ } ->
Format.fprintf fmt "%a.%a" (format_expression ctx) e1 Format.fprintf fmt "%a.%a" (format_expression ctx) e1
format_struct_field_name field StructField.format field
| EInj { e1; cons; name = enum_name; _ } -> | EInj { e1; cons; name = enum_name; _ } ->
Format.fprintf fmt "{%a_%a,@ {%a: %a}}" format_enum_name enum_name Format.fprintf fmt "{%a_%a,@ {%a: %a}}" EnumName.format enum_name
format_enum_cons_name cons format_enum_cons_name cons EnumConstructor.format cons EnumConstructor.format cons
(format_expression ctx) e1 (format_expression ctx) e1
| EArray _ -> | EArray _ ->
failwith failwith
@ -402,7 +314,7 @@ let rec format_statement
"This inner functions should have been hoisted in Scalc" "This inner functions should have been hoisted in Scalc"
| SLocalDecl { name = v; typ = ty } -> | SLocalDecl { name = v; typ = ty } ->
Format.fprintf fmt "@[<hov 2>%a@];" Format.fprintf fmt "@[<hov 2>%a@];"
(format_typ ctx (fun fmt -> format_var fmt (Mark.remove v))) (format_typ ctx (fun fmt -> VarName.format fmt (Mark.remove v)))
ty ty
(* Below we detect array initializations which have special treatment. *) (* Below we detect array initializations which have special treatment. *)
| SLocalInit { name = v; expr = EStruct { fields; name }, _; typ } | SLocalInit { name = v; expr = EStruct { fields; name }, _; typ }
@ -421,20 +333,20 @@ let rec format_statement
"@[<hov 2>%a;@]@\n\ "@[<hov 2>%a;@]@\n\
@[<hov 2>%a.content_field = catala_malloc(sizeof(%a));@]@\n\ @[<hov 2>%a.content_field = catala_malloc(sizeof(%a));@]@\n\
%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_var (Mark.remove v) format_struct_name name typ VarName.format (Mark.remove v) StructName.format name
(Format.pp_print_list (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@\n") ~pp_sep:(fun fmt () -> Format.fprintf fmt "@\n")
(fun fmt (i, arg) -> (fun fmt (i, arg) ->
Format.fprintf fmt "@[<hov 2>%a.content_field[%d] =@ %a;@]" Format.fprintf fmt "@[<hov 2>%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) (List.mapi (fun i a -> i, a) array_contents)
| SLocalInit { name = v; expr = e; typ } -> | SLocalInit { name = v; expr = e; typ } ->
Format.fprintf fmt "@[<hov 2>%a = %a;@]" Format.fprintf fmt "@[<hov 2>%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 typ (format_expression ctx) e
| SLocalDef { name = v; expr = e; _ } -> | SLocalDef { name = v; expr = e; _ } ->
Format.fprintf fmt "@[<hov 2>%a = %a;@]" format_var (Mark.remove v) Format.fprintf fmt "@[<hov 2>%a = %a;@]" VarName.format (Mark.remove v)
(format_expression ctx) e (format_expression ctx) e
| SRaiseEmpty | STryWEmpty _ -> assert false | SRaiseEmpty | STryWEmpty _ -> assert false
| SFatalError err -> | SFatalError err ->
@ -457,18 +369,18 @@ let rec format_statement
(EnumConstructor.Map.bindings (EnumName.Map.find e_name ctx.ctx_enums)) (EnumConstructor.Map.bindings (EnumName.Map.find e_name ctx.ctx_enums))
in in
let tmp_var = VarName.fresh ("match_arg", Pos.no_pos) in let tmp_var = VarName.fresh ("match_arg", Pos.no_pos) in
Format.fprintf fmt "@[<hov 2>%a %a = %a;@]@," format_enum_name e_name Format.fprintf fmt "@[<hov 2>%a %a = %a;@]@," EnumName.format e_name
format_var tmp_var (format_expression ctx) e1; VarName.format tmp_var (format_expression ctx) e1;
Format.pp_open_vbox fmt 2; Format.pp_open_vbox fmt 2;
Format.fprintf fmt "@[<hov 4>switch (%a.code) {@]@," format_var tmp_var; Format.fprintf fmt "@[<hov 4>switch (%a.code) {@]@," VarName.format tmp_var;
Format.pp_print_list Format.pp_print_list
(fun fmt ({ case_block; payload_var_name; payload_var_typ }, cons_name) -> (fun fmt ({ case_block; payload_var_name; payload_var_typ }, cons_name) ->
Format.fprintf fmt "@[<hv 2>case %a_%a:@ " format_enum_name e_name Format.fprintf fmt "@[<hv 2>case %a_%a:@ " EnumName.format e_name
format_enum_cons_name cons_name; EnumConstructor.format cons_name;
if not (Type.equal payload_var_typ (TLit TUnit, Pos.no_pos)) then if not (Type.equal payload_var_typ (TLit TUnit, Pos.no_pos)) then
Format.fprintf fmt "%a = %a.payload.%a;@ " Format.fprintf fmt "%a = %a.payload.%a;@ "
(format_typ ctx (fun fmt -> format_var fmt payload_var_name)) (format_typ ctx (fun fmt -> VarName.format fmt payload_var_name))
payload_var_typ format_var tmp_var format_enum_cons_name cons_name; payload_var_typ VarName.format tmp_var EnumConstructor.format cons_name;
Format.fprintf fmt "%a@ break;@]" (format_block ctx) case_block) Format.fprintf fmt "%a@ break;@]" (format_block ctx) case_block)
fmt cases; fmt cases;
(* Do we want to add 'default' case with a failure ? *) (* Do we want to add 'default' case with a failure ? *)
@ -514,13 +426,13 @@ let rec format_statement
in in
if exceptions <> [] then begin if exceptions <> [] then begin
Format.fprintf fmt "@[<hov 2>%a = {%a_%a,@ {%a: NULL}};@]@," Format.fprintf fmt "@[<hov 2>%a = {%a_%a,@ {%a: NULL}};@]@,"
(format_typ ctx (fun fmt -> format_var fmt exception_acc_var)) (format_typ ctx (fun fmt -> VarName.format fmt exception_acc_var))
return_typ format_enum_name e_name format_enum_cons_name none_cons return_typ EnumName.format e_name EnumConstructor.format none_cons
format_enum_cons_name none_cons; EnumConstructor.format none_cons;
Format.fprintf fmt "%a;@," 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; return_typ;
Format.fprintf fmt "char %a = 0;@," format_var exception_conflict; Format.fprintf fmt "char %a = 0;@," VarName.format exception_conflict;
List.iter List.iter
(fun except -> (fun except ->
Format.fprintf fmt Format.fprintf fmt
@ -532,11 +444,11 @@ let rec format_statement
%a = %a;@]@,\ %a = %a;@]@,\
}@]@,\ }@]@,\
}@," }@,"
format_var exception_current (format_expression ctx) except VarName.format exception_current (format_expression ctx) except
format_var exception_current format_enum_name e_name VarName.format exception_current EnumName.format e_name
format_enum_cons_name some_cons format_var exception_acc_var EnumConstructor.format some_cons VarName.format exception_acc_var
format_enum_name e_name format_enum_cons_name some_cons format_var EnumName.format e_name EnumConstructor.format some_cons VarName.format
exception_conflict format_var exception_acc_var format_var exception_conflict VarName.format exception_acc_var VarName.format
exception_current) exception_current)
exceptions; exceptions;
Format.fprintf fmt Format.fprintf fmt
@ -544,14 +456,14 @@ let rec format_statement
@[<hov 2>catala_raise_fatal_error(catala_conflict,@ \"%s\",@ %d, %d, \ @[<hov 2>catala_raise_fatal_error(catala_conflict,@ \"%s\",@ %d, %d, \
%d, %d);@]@;\ %d, %d);@]@;\
<1 -2>}@]@," <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_start_line pos) (Pos.get_start_column pos)
(Pos.get_end_line pos) (Pos.get_end_column pos); (Pos.get_end_line pos) (Pos.get_end_column pos);
Format.fprintf fmt Format.fprintf fmt
"@[<v 2>if (%a.code == %a_%a) {@,%a = %a;@]@,@[<v 2>} else {@," "@[<v 2>if (%a.code == %a_%a) {@,%a = %a;@]@,@[<v 2>} else {@,"
format_var exception_acc_var format_enum_name e_name VarName.format exception_acc_var EnumName.format e_name
format_enum_cons_name some_cons format_var variable_defined_in_cons EnumConstructor.format some_cons VarName.format variable_defined_in_cons
format_var exception_acc_var VarName.format exception_acc_var
end; end;
Format.fprintf fmt Format.fprintf fmt
"@[<v 2>if (%a) {@,\ "@[<v 2>if (%a) {@,\
@ -560,9 +472,9 @@ let rec format_statement
%a.code = %a_%a;@,\ %a.code = %a_%a;@,\
%a.payload.%a = NULL;@]@,\ %a.payload.%a = NULL;@]@,\
}" }"
(format_expression ctx) just (format_block ctx) cons format_var (format_expression ctx) just (format_block ctx) cons VarName.format
variable_defined_in_cons format_enum_name e_name format_enum_cons_name variable_defined_in_cons EnumName.format e_name EnumConstructor.format
none_cons format_var variable_defined_in_cons format_enum_cons_name none_cons VarName.format variable_defined_in_cons EnumConstructor.format
none_cons; none_cons;
if exceptions <> [] then Format.fprintf fmt "@]@,}" if exceptions <> [] then Format.fprintf fmt "@]@,}"
@ -591,7 +503,7 @@ let format_program
match code_item with match code_item with
| SVar { var; expr; typ } -> | SVar { var; expr; typ } ->
Format.fprintf fmt "@[<v 2>%a = %a;@]" Format.fprintf fmt "@[<v 2>%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 typ
(format_expression p.ctx.decl_ctx) (format_expression p.ctx.decl_ctx)
expr expr
@ -599,13 +511,13 @@ let format_program
| SScope { scope_body_var = var; scope_body_func = func; _ } -> | SScope { scope_body_var = var; scope_body_func = func; _ } ->
let { func_params; func_body; func_return_typ } = func in let { func_params; func_body; func_return_typ } = func in
Format.fprintf fmt "@[<v 2>%a(%a) {@,%a@]@,}" Format.fprintf fmt "@[<v 2>%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 func_return_typ
(Format.pp_print_list (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (var, typ) -> (fun fmt (var, typ) ->
(format_typ p.ctx.decl_ctx (fun fmt -> (format_typ p.ctx.decl_ctx (fun fmt ->
format_var fmt (Mark.remove var))) VarName.format fmt (Mark.remove var)))
fmt typ)) fmt typ))
func_params func_params
(format_block p.ctx.decl_ctx) (format_block p.ctx.decl_ctx)

View File

@ -14,7 +14,11 @@
License for the specific language governing permissions and limitations under License for the specific language governing permissions and limitations under
the License. *) 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 : val format_program :
Format.formatter -> Ast.program -> Scopelang.Dependency.TVertex.t list -> unit Format.formatter -> Ast.program -> Scopelang.Dependency.TVertex.t list -> unit

View File

@ -110,98 +110,23 @@ let format_string_list (fmt : Format.formatter) (uids : string list) : unit =
(Re.replace sanitize_quotes ~f:(fun _ -> "\\\"") info))) (Re.replace sanitize_quotes ~f:(fun _ -> "\\\"") info)))
uids uids
let avoid_keywords (s : string) : string = let python_keywords =
if (* list taken from
match s with https://www.programiz.com/python-programming/keyword-list *)
(* list taken from [ "False"; "None"; "True"; "and"; "as"; "assert"; "async"; "await";
https://www.programiz.com/python-programming/keyword-list *) "break"; "class"; "continue"; "def"; "del"; "elif"; "else";
| "False" | "None" | "True" | "and" | "as" | "assert" | "async" | "await" "except"; "finally"; "for"; "from"; "global"; "if"; "import"; "in";
| "break" | "class" | "continue" | "def" | "del" | "elif" | "else" "is"; "lambda"; "nonlocal"; "not"; "or"; "pass"; "raise"; "return";
| "except" | "finally" | "for" | "from" | "global" | "if" | "import" | "in" "try"; "while"; "with"; "yield" ]
| "is" | "lambda" | "nonlocal" | "not" | "or" | "pass" | "raise" | "return" (* todo: reserved names should also include built-in types and everything exposed by the runtime. *)
| "try" | "while" | "with" | "yield" ->
true
| _ -> false
then s ^ "_"
else s
module StringMap = String.Map let renaming =
Program.renaming ()
module IntMap = Map.Make (struct ~reserved:python_keywords
include Int (* TODO: add catala runtime built-ins as reserved as well ? *)
~reset_context_for_closed_terms:false ~skip_constant_binders:false
let format ppf i = Format.pp_print_int ppf i ~constant_binder_name:None ~namespaced_fields_constrs:true
end) ~f_struct:String.to_camel_case
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 typ_needs_parens (e : typ) : bool = let typ_needs_parens (e : typ) : bool =
match Mark.remove e with TArrow _ | TArray _ -> true | _ -> false 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 ", ") ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ")
(fun fmt t -> Format.fprintf fmt "%a" format_typ_with_parens t)) (fun fmt t -> Format.fprintf fmt "%a" format_typ_with_parens t))
ts ts
| TStruct s -> Format.fprintf fmt "%a" (format_struct_name ctx) s | TStruct s -> StructName.format fmt s
| TOption some_typ -> | TOption some_typ ->
(* We translate the option type with an overloading by Python's [None] *) (* We translate the option type with an overloading by Python's [None] *)
Format.fprintf fmt "Optional[%a]" format_typ some_typ Format.fprintf fmt "Optional[%a]" format_typ some_typ
| TDefault t -> format_typ fmt t | 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) -> | TArrow (t1, t2) ->
Format.fprintf fmt "Callable[[%a], %a]" Format.fprintf fmt "Callable[[%a], %a]"
(Format.pp_print_list (Format.pp_print_list
@ -243,8 +168,7 @@ let rec format_typ ctx (fmt : Format.formatter) (typ : typ) : unit =
| TClosureEnv -> failwith "unimplemented!" | TClosureEnv -> failwith "unimplemented!"
let format_func_name (fmt : Format.formatter) (v : FuncName.t) : unit = let format_func_name (fmt : Format.formatter) (v : FuncName.t) : unit =
let v_str = Mark.remove (FuncName.get_info v) in FuncName.format fmt v
format_name_cleaned fmt v_str
let format_position ppf pos = let format_position ppf pos =
Format.fprintf ppf 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 = let rec format_expression ctx (fmt : Format.formatter) (e : expr) : unit =
match Mark.remove e with match Mark.remove e with
| EVar v -> format_var fmt v | EVar v -> VarName.format fmt v
| EFunc f -> format_func_name fmt f | EFunc f -> FuncName.format fmt f
| EStruct { fields = es; name = s } -> | 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 (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (struct_field, e) -> (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)) (format_expression ctx) e))
(StructField.Map.bindings es) (StructField.Map.bindings es)
| EStructFieldAccess { e1; field; _ } -> | EStructFieldAccess { e1; field; _ } ->
Format.fprintf fmt "%a.%a" (format_expression ctx) e1 Format.fprintf fmt "%a.%a" (format_expression ctx) e1
format_struct_field_name field StructField.format field
| EInj { cons; name = e_name; _ } | EInj { cons; name = e_name; _ }
when EnumName.equal e_name Expr.option_enum when EnumName.equal e_name Expr.option_enum
&& EnumConstructor.equal cons Expr.none_constr -> && 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] *) (* We translate the option type with an overloading by Python's [None] *)
format_expression ctx fmt e format_expression ctx fmt e
| EInj { e1 = e; cons; name = enum_name; _ } -> | EInj { e1 = e; cons; name = enum_name; _ } ->
Format.fprintf fmt "%a(%a_Code.%a,@ %a)" (format_enum_name ctx) enum_name Format.fprintf fmt "%a(%a_Code.%a,@ %a)" EnumName.format enum_name
(format_enum_name ctx) enum_name format_enum_cons_name cons EnumName.format enum_name EnumConstructor.format cons
(format_expression ctx) e (format_expression ctx) e
| EArray es -> | EArray es ->
Format.fprintf fmt "[%a]" Format.fprintf fmt "[%a]"
@ -380,26 +304,26 @@ let rec format_expression ctx (fmt : Format.formatter) (e : expr) : unit =
| ETupleAccess { e1; index } -> | ETupleAccess { e1; index } ->
Format.fprintf fmt "%a[%d]" (format_expression ctx) e1 index Format.fprintf fmt "%a[%d]" (format_expression ctx) e1 index
| EExternal { modname; name } -> | EExternal { modname; name } ->
Format.fprintf fmt "%a.%a" format_var (Mark.remove modname) Format.fprintf fmt "%a.%s" VarName.format (Mark.remove modname)
format_name_cleaned (Mark.remove name) (Mark.remove name)
let rec format_statement ctx (fmt : Format.formatter) (s : stmt Mark.pos) : unit let rec format_statement ctx (fmt : Format.formatter) (s : stmt Mark.pos) : unit
= =
match Mark.remove s with match Mark.remove s with
| SInnerFuncDef { name; func = { func_params; func_body; _ } } -> | SInnerFuncDef { name; func = { func_params; func_body; _ } } ->
Format.fprintf fmt "@[<v 4>def %a(@[<hov>%a@]):@ %a@]" format_var Format.fprintf fmt "@[<v 4>def %a(@[<hov>%a@]):@ %a@]" VarName.format
(Mark.remove name) (Mark.remove name)
(Format.pp_print_list (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (var, typ) -> (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)) (format_typ ctx) typ))
func_params (format_block ctx) func_body func_params (format_block ctx) func_body
| SLocalDecl _ -> | SLocalDecl _ ->
assert false (* We don't need to declare variables in Python *) assert false (* We don't need to declare variables in Python *)
| SLocalDef { name = v; expr = e; _ } | SLocalInit { name = v; expr = e; _ } | SLocalDef { name = v; expr = e; _ } | SLocalInit { name = v; expr = e; _ }
-> ->
Format.fprintf fmt "@[<hv 4>%a = %a@]" format_var (Mark.remove v) Format.fprintf fmt "@[<hv 4>%a = %a@]" VarName.format (Mark.remove v)
(format_expression ctx) e (format_expression ctx) e
| STryWEmpty { try_block = try_b; with_block = catch_b } -> | STryWEmpty { try_block = try_b; with_block = catch_b } ->
Format.fprintf fmt "@[<v 4>try:@ %a@]@,@[<v 4>except Empty:@ %a@]" Format.fprintf fmt "@[<v 4>try:@ %a@]@,@[<v 4>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 -> when EnumName.equal e_name Expr.option_enum ->
(* We translate the option type with an overloading by Python's [None] *) (* We translate the option type with an overloading by Python's [None] *)
let tmp_var = VarName.fresh ("perhaps_none_arg", Pos.no_pos) in let tmp_var = VarName.fresh ("perhaps_none_arg", Pos.no_pos) in
Format.fprintf fmt "@[<hv 4>%a = %a@]@," format_var tmp_var Format.fprintf fmt "@[<hv 4>%a = %a@]@," VarName.format tmp_var
(format_expression ctx) e1; (format_expression ctx) e1;
Format.fprintf fmt "@[<v 4>if %a is None:@ %a@]@," format_var tmp_var Format.fprintf fmt "@[<v 4>if %a is None:@ %a@]@," VarName.format tmp_var
(format_block ctx) case_none; (format_block ctx) case_none;
Format.fprintf fmt "@[<v 4>else:@ %a = %a@,%a@]" format_var case_some_var Format.fprintf fmt "@[<v 4>else:@ %a = %a@,%a@]" VarName.format case_some_var
format_var tmp_var (format_block ctx) case_some VarName.format tmp_var (format_block ctx) case_some
| SSwitch { switch_expr = e1; enum_name = e_name; switch_cases = cases; _ } -> | 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 cons_map = EnumName.Map.find e_name ctx.decl_ctx.ctx_enums in
let cases = let cases =
@ -439,15 +363,15 @@ let rec format_statement ctx (fmt : Format.formatter) (s : stmt Mark.pos) : unit
(EnumConstructor.Map.bindings cons_map) (EnumConstructor.Map.bindings cons_map)
in in
let tmp_var = VarName.fresh ("match_arg", Pos.no_pos) in let tmp_var = VarName.fresh ("match_arg", Pos.no_pos) in
Format.fprintf fmt "%a = %a@\n@[<hov 4>if %a@]" format_var tmp_var Format.fprintf fmt "%a = %a@\n@[<hov 4>if %a@]" VarName.format tmp_var
(format_expression ctx) e1 (format_expression ctx) e1
(Format.pp_print_list (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@]@\n@[<hov 4>elif ") ~pp_sep:(fun fmt () -> Format.fprintf fmt "@]@\n@[<hov 4>elif ")
(fun fmt ({ case_block; payload_var_name; _ }, cons_name) -> (fun fmt ({ case_block; payload_var_name; _ }, cons_name) ->
Format.fprintf fmt "%a.code == %a_Code.%a:@\n%a = %a.value@\n%a" Format.fprintf fmt "%a.code == %a_Code.%a:@\n%a = %a.value@\n%a"
format_var tmp_var (format_enum_name ctx) e_name VarName.format tmp_var (EnumName.format) e_name
format_enum_cons_name cons_name format_var payload_var_name EnumConstructor.format cons_name VarName.format payload_var_name
format_var tmp_var (format_block ctx) case_block)) VarName.format tmp_var (format_block ctx) case_block))
cases cases
| SReturn e1 -> | SReturn e1 ->
Format.fprintf fmt "@[<hov 4>return %a@]" (format_expression ctx) Format.fprintf fmt "@[<hov 4>return %a@]" (format_expression ctx)
@ -497,38 +421,38 @@ let format_ctx
\ return not (self == other)@,\ \ return not (self == other)@,\
@,\ @,\
\ def __str__(self) -> str:@,\ \ def __str__(self) -> str:@,\
\ @[<hov 4>return \"%a(%a)\".format(%a)@]" (format_struct_name ctx) \ @[<hov 4>return \"%a(%a)\".format(%a)@]" StructName.format
struct_name struct_name
(Format.pp_print_list (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ")
(fun fmt (struct_field, struct_field_type) -> (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)) (format_typ ctx) struct_field_type))
fields fields
(if StructField.Map.is_empty struct_fields then fun fmt _ -> (if StructField.Map.is_empty struct_fields then fun fmt _ ->
Format.fprintf fmt " pass" Format.fprintf fmt " pass"
else else
Format.pp_print_list (fun fmt (struct_field, _) -> Format.pp_print_list (fun fmt (struct_field, _) ->
Format.fprintf fmt " self.%a = %a" format_struct_field_name Format.fprintf fmt " self.%a = %a" StructField.format
struct_field format_struct_field_name struct_field)) struct_field StructField.format struct_field))
fields (format_struct_name ctx) struct_name fields StructName.format struct_name
(if not (StructField.Map.is_empty struct_fields) then (if not (StructField.Map.is_empty struct_fields) then
Format.pp_print_list Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt " and@ ") ~pp_sep:(fun fmt () -> Format.fprintf fmt " and@ ")
(fun fmt (struct_field, _) -> (fun fmt (struct_field, _) ->
Format.fprintf fmt "self.%a == other.%a" format_struct_field_name Format.fprintf fmt "self.%a == other.%a" StructField.format
struct_field format_struct_field_name struct_field) struct_field StructField.format struct_field)
else fun fmt _ -> Format.fprintf fmt "True") else fun fmt _ -> Format.fprintf fmt "True")
fields (format_struct_name ctx) struct_name fields StructName.format struct_name
(Format.pp_print_list (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",") ~pp_sep:(fun fmt () -> Format.fprintf fmt ",")
(fun fmt (struct_field, _) -> (fun fmt (struct_field, _) ->
Format.fprintf fmt "%a={}" format_struct_field_name struct_field)) Format.fprintf fmt "%a={}" StructField.format struct_field))
fields fields
(Format.pp_print_list (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (struct_field, _) -> (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 fields
in in
let format_enum_decl fmt (enum_name, enum_cons) = let format_enum_decl fmt (enum_name, enum_cons) =
@ -558,14 +482,14 @@ let format_ctx
@,\ @,\
\ def __str__(self) -> str:@,\ \ def __str__(self) -> str:@,\
\ @[<hov 4>return \"{}({})\".format(self.code, self.value)@]" \ @[<hov 4>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.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 (List.mapi
(fun i (x, y) -> i, x, y) (fun i (x, y) -> i, x, y)
(EnumConstructor.Map.bindings enum_cons)) (EnumConstructor.Map.bindings enum_cons))
(format_enum_name ctx) enum_name (format_enum_name ctx) enum_name (EnumName.format) enum_name EnumName.format enum_name
(format_enum_name ctx) enum_name EnumName.format enum_name
in in
let is_in_type_ordering s = let is_in_type_ordering s =
@ -597,19 +521,9 @@ let format_ctx
(e, EnumName.Map.find e ctx.decl_ctx.ctx_enums)) (e, EnumName.Map.find e ctx.decl_ctx.ctx_enums))
(type_ordering @ scope_structs) (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 let format_code_item ctx fmt = function
| SVar { var; expr; typ = _ } -> | SVar { var; expr; typ = _ } ->
Format.fprintf fmt "@[<hv 4>%a = (@,%a@;<0 -4>)@]@," format_var var Format.fprintf fmt "@[<hv 4>%a = (@,%a@;<0 -4>)@]@," VarName.format var
(format_expression ctx) expr (format_expression ctx) expr
| SFunc { var; func } | SFunc { var; func }
| SScope { scope_body_var = var; scope_body_func = 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 (Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (var, typ) -> (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)) (format_typ ctx) typ))
func_params (format_block ctx) func_body func_params (format_block ctx) func_body
@ -627,7 +541,6 @@ let format_program
(fmt : Format.formatter) (fmt : Format.formatter)
(p : Ast.program) (p : Ast.program)
(type_ordering : Scopelang.Dependency.TVertex.t list) : unit = (type_ordering : Scopelang.Dependency.TVertex.t list) : unit =
List.iter reserve_func_name p.code_items;
Format.pp_open_vbox fmt 0; Format.pp_open_vbox fmt 0;
let header = let header =
[ [
@ -643,7 +556,7 @@ let format_program
ModuleName.Map.iter ModuleName.Map.iter
(fun m v -> (fun m v ->
Format.fprintf fmt "from . import %a as %a@," ModuleName.format m Format.fprintf fmt "from . import %a as %a@," ModuleName.format m
format_var v) VarName.format v)
p.ctx.modules; p.ctx.modules;
Format.pp_print_cut fmt (); Format.pp_print_cut fmt ();
format_ctx type_ordering fmt p.ctx; format_ctx type_ordering fmt p.ctx;

View File

@ -16,6 +16,10 @@
(** Formats a lambda calculus program into a valid Python program *) (** Formats a lambda calculus program into a valid Python program *)
open Shared_ast
val renaming : Program.renaming
val format_program : val format_program :
Format.formatter -> Ast.program -> Scopelang.Dependency.TVertex.t list -> unit Format.formatter -> Ast.program -> Scopelang.Dependency.TVertex.t list -> unit
(** Usage [format_program fmt p type_dependencies_ordering] *) (** Usage [format_program fmt p type_dependencies_ordering] *)

View File

@ -417,6 +417,12 @@ module Renaming : sig
like [String.to_snake_case]). The result is advisory and a numerical suffix like [String.to_snake_case]). The result is advisory and a numerical suffix
may be appended or modified *) 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 new_id : context -> string -> string * context
val set_rewriters : val set_rewriters :

View File

@ -114,7 +114,8 @@ let rename_ids
?(f_field = uncap) ?(f_field = uncap)
?(f_enum = cap) ?(f_enum = cap)
?(f_constr = cap) ?(f_constr = cap)
p = p
=
let cfg = let cfg =
{ {
Expr.Renaming.reserved; 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 decl_ctx = map_decl_ctx ~f:(Expr.Renaming.typ ctx) decl_ctx in
let code_items = Scope.rename_ids ctx p.code_items in let code_items = Scope.rename_ids ctx p.code_items in
{ p with decl_ctx; code_items }, ctx { 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)

View File

@ -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 (** Returns a list of used modules, in topological order ; the boolean indicates
if the module is external *) 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 -> reserved:string list ->
reset_context_for_closed_terms:bool -> reset_context_for_closed_terms:bool ->
skip_constant_binders:bool -> skip_constant_binders:bool ->
@ -68,8 +72,8 @@ val rename_ids :
?f_field:(string -> string) -> ?f_field:(string -> string) ->
?f_enum:(string -> string) -> ?f_enum:(string -> string) ->
?f_constr:(string -> string) -> ?f_constr:(string -> string) ->
('a, 't) gexpr program -> unit ->
('a, 't) gexpr program * Expr.Renaming.context renaming
(** Renames all idents (variables, types, struct and enum names, fields and (** Renames all idents (variables, types, struct and enum names, fields and
constructors) to dispel ambiguities in the target language. Names in constructors) to dispel ambiguities in the target language. Names in
[reserved], typically keywords and built-ins, will be avoided ; the meaning [reserved], typically keywords and built-ins, will be avoided ; the meaning

View File

@ -4,413 +4,201 @@
#include <stdlib.h> #include <stdlib.h>
#include <runtime.c> #include <runtime.c>
enum option_2_enum_code { enum Option_2_code {
option_2_enum_none_2_cons, Option_2_None_2,
option_2_enum_some_2_cons Option_2_Some_2
} option_2_enum_code; } Option_2_code;
typedef struct option_2_enum { typedef struct Option_2 {
enum option_2_enum_code code; enum Option_2_code code;
union { union {
void* /* unit */ none_2_cons; void* /* unit */ None_2;
double some_2_cons; double Some_2;
} payload; } payload;
} option_2_enum; } Option_2;
typedef struct foo_struct { typedef struct Foo {
char /* bool */ x_field; char /* bool */ x;
double y_field; double y;
} foo_struct; } Foo;
typedef struct array_3_struct { typedef struct Array_3 {
double * content_field; double * content2;
int length_field; int length2;
} array_3_struct; } Array_3;
typedef struct array_2_struct { typedef struct Array_2 {
option_2_enum * content_field; Option_2 * content1;
int length_field; int length1;
} array_2_struct; } Array_2;
enum bar_enum_code { enum Bar_code {
bar_enum_no_cons, Bar_No,
bar_enum_yes_cons Bar_Yes
} bar_enum_code; } Bar_code;
typedef struct bar_enum { typedef struct Bar {
enum bar_enum_code code; enum Bar_code code;
union { union {
void* /* unit */ no_cons; void* /* unit */ No;
foo_struct yes_cons; Foo Yes;
} payload; } payload;
} bar_enum; } Bar;
typedef struct baz_struct { typedef struct Baz {
double b_field; double b;
array_3_struct c_field; Array_3 c;
} baz_struct; } Baz;
enum option_3_enum_code { enum Option_3_code {
option_3_enum_none_3_cons, Option_3_None_3,
option_3_enum_some_3_cons Option_3_Some_3
} option_3_enum_code; } Option_3_code;
typedef struct option_3_enum { typedef struct Option_3 {
enum option_3_enum_code code; enum Option_3_code code;
union { union {
void* /* unit */ none_3_cons; void* /* unit */ None_3;
array_3_struct some_3_cons; Array_3 Some_3;
} payload; } payload;
} option_3_enum; } Option_3;
enum option_1_enum_code { enum Option_1_code {
option_1_enum_none_1_cons, Option_1_None_1,
option_1_enum_some_1_cons Option_1_Some_1
} option_1_enum_code; } Option_1_code;
typedef struct option_1_enum { typedef struct Option_1 {
enum option_1_enum_code code; enum Option_1_code code;
union { union {
void* /* unit */ none_1_cons; void* /* unit */ None_1;
bar_enum some_1_cons; Bar Some_1;
} payload; } payload;
} option_1_enum; } Option_1;
typedef struct array_4_struct { typedef struct Array_4 {
option_3_enum * content_field; Option_3 * content3;
int length_field; int length3;
} array_4_struct; } Array_4;
typedef struct array_1_struct { typedef struct Array_1 {
option_1_enum * content_field; Option_1 * content;
int length_field; int length;
} array_1_struct; } Array_1;
typedef struct tuple_1_struct { typedef struct Tuple_1 {
option_1_enum (*elt_0_field)(void * /* closure_env */ arg_0_typ, void* /* unit */ arg_1_typ); Option_1 (*elt_0)(void * /* closure_env */ arg_0_typ, void* /* unit */ arg_1_typ);
void * /* closure_env */ elt_1_field; void * /* closure_env */ elt_1;
} tuple_1_struct; } Tuple_1;
typedef struct baz_in_struct { typedef struct Baz_in {
tuple_1_struct a_in_field; Tuple_1 a_in;
} baz_in_struct; } Baz_in;
baz_struct baz_func(baz_in_struct baz_in) { Baz baz(Baz_in baz_in) {
tuple_1_struct a; Tuple_1 a;
a = baz_in.a_in_field; a = baz_in.a_in;
bar_enum temp_a; Bar a2;
option_1_enum temp_a_1; option_1 a3;
tuple_1_struct code_and_env; Tuple_1 code_and_env;
code_and_env = a; 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; void * /* closure_env */ env;
code = code_and_env.elt_0_field; code = code_and_env.elt_0;
env = code_and_env.elt_1_field; env = code_and_env.elt_1;
array_1_struct temp_a_2; Array_1 a4;
temp_a_2.content_field = catala_malloc(sizeof(array_1_struct)); a4.content_field = catala_malloc(sizeof(Array_1));
temp_a_2.content_field[0] = code(env, NULL); a4.content_field[0] = code(env, NULL);
option_1_enum match_arg = catala_handle_exceptions(temp_a_2); Option_1 match_arg = catala_handle_exceptions(a4);
switch (match_arg.code) { switch (match_arg.code) {
case option_1_enum_none_1_cons: case Option_1_None_1:
if (1 /* TRUE */) { if (1 /* TRUE */) {
bar_enum temp_a_3; Bar a3;
option_1_enum temp_a_4; option_1 a4;
option_1_enum temp_a_5; option_1 a6;
array_1_struct temp_a_6; Array_1 a7;
temp_a_6.content_field = catala_malloc(sizeof(array_1_struct)); a7.content_field = catala_malloc(sizeof(Array_1));
option_1_enum match_arg_1 = catala_handle_exceptions(temp_a_6); Option_1 match_arg = catala_handle_exceptions(a7);
switch (match_arg_1.code) { switch (match_arg.code) {
case option_1_enum_none_1_cons: case Option_1_None_1:
if (1 /* TRUE */) { if (1 /* TRUE */) {
bar_enum temp_a_7 = {bar_enum_no_cons, {no_cons: NULL}}; Bar a6 = {Bar_No, {No: NULL}};
option_1_enum temp_a_5 = {option_1_enum_some_1_cons, option_1 a6 = {Option_1_Some_1, {Some_1: a6}};
{some_1_cons: temp_a_7}};
} else { } else {
option_1_enum temp_a_5 = {option_1_enum_none_1_cons, option_1 a6 = {Option_1_None_1, {None_1: NULL}};
{none_1_cons: NULL}};
} }
break; break;
case option_1_enum_some_1_cons: case Option_1_Some_1:
bar_enum x = match_arg_1.payload.some_1_cons; Bar x1 = match_arg.payload.Some_1;
option_1_enum temp_a_5 = {option_1_enum_some_1_cons, option_1 a6 = {Option_1_Some_1, {Some_1: x1}};
{some_1_cons: x}};
break; break;
} }
array_1_struct temp_a_8; Array_1 a5;
temp_a_8.content_field = catala_malloc(sizeof(array_1_struct)); a5.content_field = catala_malloc(sizeof(Array_1));
temp_a_8.content_field[0] = temp_a_5; a5.content_field[0] = a6;
option_1_enum match_arg_2 = catala_handle_exceptions(temp_a_8); Option_1 match_arg = catala_handle_exceptions(a5);
switch (match_arg_2.code) { switch (match_arg.code) {
case option_1_enum_none_1_cons: case Option_1_None_1:
if (0 /* FALSE */) { if (0 /* FALSE */) {
option_1_enum temp_a_4 = {option_1_enum_none_1_cons, option_1 a4 = {Option_1_None_1, {None_1: NULL}};
{none_1_cons: NULL}};
} else { } else {
option_1_enum temp_a_4 = {option_1_enum_none_1_cons, option_1 a4 = {Option_1_None_1, {None_1: NULL}};
{none_1_cons: NULL}};
} }
break; break;
case option_1_enum_some_1_cons: case Option_1_Some_1:
bar_enum x_1 = match_arg_2.payload.some_1_cons; Bar x1 = match_arg.payload.Some_1;
option_1_enum temp_a_4 = {option_1_enum_some_1_cons, option_1 a4 = {Option_1_Some_1, {Some_1: x1}};
{some_1_cons: x_1}};
break; break;
} }
option_1_enum match_arg_3 = temp_a_4; Option_1 match_arg = a4;
switch (match_arg_3.code) { switch (match_arg.code) {
case option_1_enum_none_1_cons: case Option_1_None_1:
catala_raise_fatal_error (catala_no_value, catala_raise_fatal_error (catala_no_value,
"tests/backends/simple.catala_en", 11, 11, 11, 12); "tests/backends/simple.catala_en", 11, 11, 11, 12);
break; break;
case option_1_enum_some_1_cons: case Option_1_Some_1:
bar_enum arg = match_arg_3.payload.some_1_cons; Bar arg = match_arg.payload.Some_1;
temp_a_3 = arg; a3 = arg;
break; break;
} }
option_1_enum temp_a_1 = {option_1_enum_some_1_cons, option_1 a3 = {Option_1_Some_1, {Some_1: a3}};
{some_1_cons: temp_a_3}};
} else { } else {
option_1_enum temp_a_1 = {option_1_enum_none_1_cons, option_1 a3 = {Option_1_None_1, {None_1: NULL}};
{none_1_cons: NULL}};
} }
break; break;
case option_1_enum_some_1_cons: case Option_1_Some_1:
bar_enum x_2 = match_arg.payload.some_1_cons; Bar x1 = match_arg.payload.Some_1;
option_1_enum temp_a_1 = {option_1_enum_some_1_cons, option_1 a3 = {Option_1_Some_1, {Some_1: x1}};
{some_1_cons: x_2}};
break; break;
} }
option_1_enum match_arg_4 = temp_a_1; Option_1 match_arg = a3;
switch (match_arg_4.code) { switch (match_arg.code) {
case option_1_enum_none_1_cons: case Option_1_None_1:
catala_raise_fatal_error (catala_no_value, catala_raise_fatal_error (catala_no_value,
"tests/backends/simple.catala_en", 11, 11, 11, 12); "tests/backends/simple.catala_en", 11, 11, 11, 12);
break; break;
case option_1_enum_some_1_cons: case Option_1_Some_1:
bar_enum arg_1 = match_arg_4.payload.some_1_cons; Bar arg = match_arg.payload.Some_1;
temp_a = arg_1; a2 = arg;
break; break;
} }
bar_enum a_1; Bar a1;
a_1 = temp_a; a1 = a2;
double temp_b; double b2;
option_2_enum temp_b_1; option_2 b3;
option_2_enum temp_b_2; option_2 b5;
option_2_enum temp_b_3; option_2 b7;
array_2_struct temp_b_4; [ERROR]
temp_b_4.content_field = catala_malloc(sizeof(array_2_struct));
Unexpected error: Not_found
option_2_enum match_arg_5 = catala_handle_exceptions(temp_b_4);
switch (match_arg_5.code) {
case option_2_enum_none_2_cons: #return code 125#
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;
}

View File

@ -91,85 +91,89 @@ class BIn:
def some_name(some_name_in:SomeNameIn): def some_name(some_name_in:SomeNameIn):
i = some_name_in.i_in i = some_name_in.i_in
perhaps_none_arg = handle_exceptions([], []) match_arg = handle_exceptions([], [])
if perhaps_none_arg is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
if True: if True:
temp_o = (i + integer_of_string("1")) o3 = Eoption(Eoption_Code.ESome, (i + integer_of_string("1")))
else: else:
temp_o = None o3 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x = perhaps_none_arg x = match_arg.value
temp_o = x o3 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_1 = handle_exceptions( match_arg = handle_exceptions(
[SourcePosition( [SourcePosition(
filename="tests/backends/python_name_clash.catala_en", filename="tests/backends/python_name_clash.catala_en",
start_line=10, start_column=23, start_line=10, start_column=23,
end_line=10, end_column=28, law_headings=[] end_line=10, end_column=28, law_headings=[])],
)], [o3]
[temp_o] )
) if match_arg.code == Eoption_Code.ENone:
if perhaps_none_arg_1 is None: _ = match_arg.value
if False: if False:
temp_o_1 = None o2 = Eoption(Eoption_Code.ENone, Unit())
else: else:
temp_o_1 = None o2 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_1 = perhaps_none_arg_1 x = match_arg.value
temp_o_1 = x_1 o2 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_2 = temp_o_1 match_arg = o2
if perhaps_none_arg_2 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
raise NoValue(SourcePosition( raise NoValue(SourcePosition(
filename="tests/backends/python_name_clash.catala_en", filename="tests/backends/python_name_clash.catala_en",
start_line=7, start_column=10, start_line=7, start_column=10,
end_line=7, end_column=11, law_headings=[])) end_line=7, end_column=11, law_headings=[]))
else: elif match_arg.code == Eoption_Code.ESome:
arg = perhaps_none_arg_2 arg = match_arg.value
temp_o_2 = arg o1 = arg
o = temp_o_2 o = o1
return SomeName(o = o) return SomeName(o = o)
def b(b_in:BIn): def b(b_in:BIn):
perhaps_none_arg_3 = handle_exceptions([], []) match_arg = handle_exceptions([], [])
if perhaps_none_arg_3 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
if True: if True:
temp_result = integer_of_string("1") result3 = Eoption(Eoption_Code.ESome, integer_of_string("1"))
else: else:
temp_result = None result3 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_2 = perhaps_none_arg_3 x = match_arg.value
temp_result = x_2 result3 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_4 = handle_exceptions( match_arg = handle_exceptions(
[SourcePosition( [SourcePosition(
filename="tests/backends/python_name_clash.catala_en", filename="tests/backends/python_name_clash.catala_en",
start_line=16, start_column=33, start_line=16, start_column=33,
end_line=16, end_column=34, law_headings=[] end_line=16, end_column=34, law_headings=[])],
)], [result3]
[temp_result] )
) if match_arg.code == Eoption_Code.ENone:
if perhaps_none_arg_4 is None: _ = match_arg.value
if False: if False:
temp_result_1 = None result2 = Eoption(Eoption_Code.ENone, Unit())
else: else:
temp_result_1 = None result2 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_3 = perhaps_none_arg_4 x = match_arg.value
temp_result_1 = x_3 result2 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_5 = temp_result_1 match_arg = result2
if perhaps_none_arg_5 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
raise NoValue(SourcePosition( raise NoValue(SourcePosition(
filename="tests/backends/python_name_clash.catala_en", filename="tests/backends/python_name_clash.catala_en",
start_line=16, start_column=14, start_line=16, start_column=14,
end_line=16, end_column=25, law_headings=[])) end_line=16, end_column=25, law_headings=[]))
else: elif match_arg.code == Eoption_Code.ESome:
arg_1 = perhaps_none_arg_5 arg = match_arg.value
temp_result_2 = arg_1 result1 = arg
result = some_name(SomeNameIn(i_in = temp_result_2)) result = some_name(SomeNameIn(i_in = result1))
result_1 = SomeName(o = result.o) result1 = SomeName(o = result.o)
if True: if True:
temp_some_name = result_1 some_name2 = result1
else: else:
temp_some_name = result_1 some_name2 = result1
some_name_1 = temp_some_name some_name1 = some_name2
return B(some_name = some_name_1) return B(some_name = some_name1)
``` ```
The above should *not* show `some_name = temp_some_name`, but instead `some_name_1 = ...` The above should *not* show `some_name = temp_some_name`, but instead `some_name_1 = ...`

View File

@ -107,164 +107,164 @@ $ catala test-scope S4
```catala-test-inline ```catala-test-inline
$ catala scalc $ 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 = let glob5_init =
decl x_6 : decimal; decl x : decimal;
x_6 = to_rat 2 * 3.; x = to_rat 2 * 3.;
decl y_7 : decimal; decl y : decimal;
y_7 = 1000.; y = 1000.;
return x_6 * y_7 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) = let S2 (S2_in: S2_in) =
decl temp_a_11 : decimal; decl a1 : decimal;
decl temp_a_12 : option decimal; decl a2 : option decimal;
decl temp_a_13 : option decimal; decl a3 : option decimal;
switch handle_exceptions []: switch handle_exceptions []:
| ENone __14 | ENone _ →
if true: if true:
temp_a_13 = ESome glob3_1 ¤44.00 + 100. a3 = ESome glob3 ¤44.00 + 100.
else: else:
temp_a_13 = ENone () a3 = ENone ()
| ESome x_15 | ESome x →
temp_a_13 = ESome x_15; a3 = ESome x;
switch handle_exceptions [temp_a_13]: switch handle_exceptions [a3]:
| ENone __16 | ENone _ →
if false: if false:
temp_a_12 = ENone () a2 = ENone ()
else: else:
temp_a_12 = ENone () a2 = ENone ()
| ESome x_17 | ESome x →
temp_a_12 = ESome x_17; a2 = ESome x;
switch temp_a_12: switch a2:
| ENone __18 | ENone _ →
fatal NoValue fatal NoValue
| ESome arg_19 | ESome arg →
temp_a_11 = arg_19; a1 = arg;
decl a_10 : decimal; decl a : decimal;
a_10 = temp_a_11; a = a1;
return S2 {"a": a_10} return S2 {"a": a}
let S3_5 (S3_in_20: S3_in) = let S3 (S3_in: S3_in) =
decl temp_a_22 : decimal; decl a1 : decimal;
decl temp_a_23 : option decimal; decl a2 : option decimal;
decl temp_a_24 : option decimal; decl a3 : option decimal;
switch handle_exceptions []: switch handle_exceptions []:
| ENone __25 | ENone _ →
if true: if true:
temp_a_24 = ESome 50. + glob4_2 ¤44.00 55. a3 = ESome 50. + glob4 ¤44.00 55.
else: else:
temp_a_24 = ENone () a3 = ENone ()
| ESome x_26 | ESome x →
temp_a_24 = ESome x_26; a3 = ESome x;
switch handle_exceptions [temp_a_24]: switch handle_exceptions [a3]:
| ENone __27 | ENone _ →
if false: if false:
temp_a_23 = ENone () a2 = ENone ()
else: else:
temp_a_23 = ENone () a2 = ENone ()
| ESome x_28 | ESome x →
temp_a_23 = ESome x_28; a2 = ESome x;
switch temp_a_23: switch a2:
| ENone __29 | ENone _ →
fatal NoValue fatal NoValue
| ESome arg_30 | ESome arg →
temp_a_22 = arg_30; a1 = arg;
decl a_21 : decimal; decl a : decimal;
a_21 = temp_a_22; a = a1;
return S3 {"a": a_21} return S3 {"a": a}
let S4_6 (S4_in_31: S4_in) = let S4 (S4_in: S4_in) =
decl temp_a_33 : decimal; decl a1 : decimal;
decl temp_a_34 : option decimal; decl a2 : option decimal;
decl temp_a_35 : option decimal; decl a3 : option decimal;
switch handle_exceptions []: switch handle_exceptions []:
| ENone __36 | ENone _ →
if true: if true:
temp_a_35 = ESome glob5_5 + 1. a3 = ESome glob5 + 1.
else: else:
temp_a_35 = ENone () a3 = ENone ()
| ESome x_37 | ESome x →
temp_a_35 = ESome x_37; a3 = ESome x;
switch handle_exceptions [temp_a_35]: switch handle_exceptions [a3]:
| ENone __38 | ENone _ →
if false: if false:
temp_a_34 = ENone () a2 = ENone ()
else: else:
temp_a_34 = ENone () a2 = ENone ()
| ESome x_39 | ESome x →
temp_a_34 = ESome x_39; a2 = ESome x;
switch temp_a_34: switch a2:
| ENone __40 | ENone _ →
fatal NoValue fatal NoValue
| ESome arg_41 | ESome arg →
temp_a_33 = arg_41; a1 = arg;
decl a_32 : decimal; decl a : decimal;
a_32 = temp_a_33; a = a1;
return S4 {"a": a_32} return S4 {"a": a}
let S_7 (S_in_42: S_in) = let S (S_in: S_in) =
decl temp_a_54 : decimal; decl a1 : decimal;
decl temp_a_55 : option decimal; decl a2 : option decimal;
decl temp_a_56 : option decimal; decl a3 : option decimal;
switch handle_exceptions []: switch handle_exceptions []:
| ENone __57 | ENone _ →
if true: if true:
temp_a_56 = ESome glob1_1 * glob1_1 a3 = ESome glob1 * glob1
else: else:
temp_a_56 = ENone () a3 = ENone ()
| ESome x_58 | ESome x →
temp_a_56 = ESome x_58; a3 = ESome x;
switch handle_exceptions [temp_a_56]: switch handle_exceptions [a3]:
| ENone __59 | ENone _ →
if false: if false:
temp_a_55 = ENone () a2 = ENone ()
else: else:
temp_a_55 = ENone () a2 = ENone ()
| ESome x_60 | ESome x →
temp_a_55 = ESome x_60; a2 = ESome x;
switch temp_a_55: switch a2:
| ENone __61 | ENone _ →
fatal NoValue fatal NoValue
| ESome arg_62 | ESome arg →
temp_a_54 = arg_62; a1 = arg;
decl a_43 : decimal; decl a : decimal;
a_43 = temp_a_54; a = a1;
decl temp_b_45 : A {y: bool; z: decimal}; decl b1 : A {y: bool; z: decimal};
decl temp_b_46 : option A {y: bool; z: decimal}; decl b2 : option A {y: bool; z: decimal};
decl temp_b_47 : option A {y: bool; z: decimal}; decl b3 : option A {y: bool; z: decimal};
switch handle_exceptions []: switch handle_exceptions []:
| ENone __48 | ENone _ →
if true: if true:
temp_b_47 = ESome glob2_8 b3 = ESome glob2
else: else:
temp_b_47 = ENone () b3 = ENone ()
| ESome x_49 | ESome x →
temp_b_47 = ESome x_49; b3 = ESome x;
switch handle_exceptions [temp_b_47]: switch handle_exceptions [b3]:
| ENone __50 | ENone _ →
if false: if false:
temp_b_46 = ENone () b2 = ENone ()
else: else:
temp_b_46 = ENone () b2 = ENone ()
| ESome x_51 | ESome x →
temp_b_46 = ESome x_51; b2 = ESome x;
switch temp_b_46: switch b2:
| ENone __52 | ENone _ →
fatal NoValue fatal NoValue
| ESome arg_53 | ESome arg →
temp_b_45 = arg_53; b1 = arg;
decl b_44 : A {y: bool; z: decimal}; decl b : A {y: bool; z: decimal};
b_44 = temp_b_45; b = b1;
return S {"a": a_43, "b": b_44} return S {"a": a, "b": b}
``` ```
```catala-test-inline ```catala-test-inline
@ -427,18 +427,18 @@ glob1 = (decimal_of_string("44.12"))
def glob3(x:Money): def glob3(x:Money):
return (decimal_of_money(x) + decimal_of_string("10.")) return (decimal_of_money(x) + decimal_of_string("10."))
def glob4(x_1:Money, y:Decimal): def glob4(x:Money, y:Decimal):
return ((decimal_of_money(x_1) * y) + decimal_of_string("10.")) return ((decimal_of_money(x) * y) + decimal_of_string("10."))
def glob5_aux(): def glob5_init():
x_2 = (decimal_of_integer(integer_of_string("2")) * x = (decimal_of_integer(integer_of_string("2")) *
decimal_of_string("3.")) decimal_of_string("3."))
y_1 = decimal_of_string("1000.") y = decimal_of_string("1000.")
return (x_2 * y_1) return (x * y)
glob5 = (glob5_aux()) glob5 = (glob5_init())
glob2 = ( glob6 = (
A(y = (glob1 >= A(y = (glob1 >=
decimal_of_string("30.")), decimal_of_string("30.")),
z = (decimal_of_string("123.") * z = (decimal_of_string("123.") *
@ -446,202 +446,216 @@ glob2 = (
) )
def s2(s2_in:S2In): def s2(s2_in:S2In):
perhaps_none_arg = handle_exceptions([], []) match_arg = handle_exceptions([], [])
if perhaps_none_arg is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
if True: if True:
temp_a = (glob3(money_of_cents_string("4400")) + a3 = Eoption(Eoption_Code.ESome,
decimal_of_string("100.")) (glob3(money_of_cents_string("4400")) +
decimal_of_string("100.")))
else: else:
temp_a = None a3 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_3 = perhaps_none_arg x = match_arg.value
temp_a = x_3 a3 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_1 = handle_exceptions( match_arg = handle_exceptions(
[SourcePosition( [SourcePosition(
filename="tests/name_resolution/good/toplevel_defs.catala_en", filename="tests/name_resolution/good/toplevel_defs.catala_en",
start_line=53, start_column=24, start_line=53, start_column=24,
end_line=53, end_column=43, end_line=53, end_column=43,
law_headings=["Test toplevel function defs"] law_headings=["Test toplevel function defs"])],
)], [a3]
[temp_a] )
) if match_arg.code == Eoption_Code.ENone:
if perhaps_none_arg_1 is None: _ = match_arg.value
if False: if False:
temp_a_1 = None a2 = Eoption(Eoption_Code.ENone, Unit())
else: else:
temp_a_1 = None a2 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_4 = perhaps_none_arg_1 x = match_arg.value
temp_a_1 = x_4 a2 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_2 = temp_a_1 match_arg = a2
if perhaps_none_arg_2 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
raise NoValue(SourcePosition( raise NoValue(SourcePosition(
filename="tests/name_resolution/good/toplevel_defs.catala_en", filename="tests/name_resolution/good/toplevel_defs.catala_en",
start_line=50, start_column=10, start_line=50, start_column=10,
end_line=50, end_column=11, end_line=50, end_column=11,
law_headings=["Test toplevel function defs"])) law_headings=["Test toplevel function defs"]))
else: elif match_arg.code == Eoption_Code.ESome:
arg = perhaps_none_arg_2 arg = match_arg.value
temp_a_2 = arg a1 = arg
a = temp_a_2 a = a1
return S2(a = a) return S2(a = a)
def s3(s3_in:S3In): def s3(s3_in:S3In):
perhaps_none_arg_3 = handle_exceptions([], []) match_arg = handle_exceptions([], [])
if perhaps_none_arg_3 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
if True: if True:
temp_a_3 = (decimal_of_string("50.") + a3 = Eoption(Eoption_Code.ESome,
(decimal_of_string("50.") +
glob4(money_of_cents_string("4400"), glob4(money_of_cents_string("4400"),
decimal_of_string("55."))) decimal_of_string("55."))))
else: else:
temp_a_3 = None a3 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_5 = perhaps_none_arg_3 x = match_arg.value
temp_a_3 = x_5 a3 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_4 = handle_exceptions( match_arg = handle_exceptions(
[SourcePosition( [SourcePosition(
filename="tests/name_resolution/good/toplevel_defs.catala_en", filename="tests/name_resolution/good/toplevel_defs.catala_en",
start_line=74, start_column=24, start_line=74, start_column=24,
end_line=74, end_column=47, end_line=74, end_column=47,
law_headings=["Test function def with two args"] law_headings=["Test function def with two args"])],
)], [a3]
[temp_a_3] )
) if match_arg.code == Eoption_Code.ENone:
if perhaps_none_arg_4 is None: _ = match_arg.value
if False: if False:
temp_a_4 = None a2 = Eoption(Eoption_Code.ENone, Unit())
else: else:
temp_a_4 = None a2 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_6 = perhaps_none_arg_4 x = match_arg.value
temp_a_4 = x_6 a2 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_5 = temp_a_4 match_arg = a2
if perhaps_none_arg_5 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
raise NoValue(SourcePosition( raise NoValue(SourcePosition(
filename="tests/name_resolution/good/toplevel_defs.catala_en", filename="tests/name_resolution/good/toplevel_defs.catala_en",
start_line=71, start_column=10, start_line=71, start_column=10,
end_line=71, end_column=11, end_line=71, end_column=11,
law_headings=["Test function def with two args"])) law_headings=["Test function def with two args"]))
else: elif match_arg.code == Eoption_Code.ESome:
arg_1 = perhaps_none_arg_5 arg = match_arg.value
temp_a_5 = arg_1 a1 = arg
a_1 = temp_a_5 a = a1
return S3(a = a_1) return S3(a = a)
def s4(s4_in:S4In): def s4(s4_in:S4In):
perhaps_none_arg_6 = handle_exceptions([], []) match_arg = handle_exceptions([], [])
if perhaps_none_arg_6 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
if True: if True:
temp_a_6 = (glob5 + decimal_of_string("1.")) a3 = Eoption(Eoption_Code.ESome,
(glob5 +
decimal_of_string("1.")))
else: else:
temp_a_6 = None a3 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_7 = perhaps_none_arg_6 x = match_arg.value
temp_a_6 = x_7 a3 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_7 = handle_exceptions( match_arg = handle_exceptions(
[SourcePosition( [SourcePosition(
filename="tests/name_resolution/good/toplevel_defs.catala_en", filename="tests/name_resolution/good/toplevel_defs.catala_en",
start_line=98, start_column=24, start_line=98, start_column=24,
end_line=98, end_column=34, end_line=98, end_column=34,
law_headings=["Test inline defs in toplevel defs"] law_headings=["Test inline defs in toplevel defs"])],
)], [a3]
[temp_a_6] )
) if match_arg.code == Eoption_Code.ENone:
if perhaps_none_arg_7 is None: _ = match_arg.value
if False: if False:
temp_a_7 = None a2 = Eoption(Eoption_Code.ENone, Unit())
else: else:
temp_a_7 = None a2 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_8 = perhaps_none_arg_7 x = match_arg.value
temp_a_7 = x_8 a2 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_8 = temp_a_7 match_arg = a2
if perhaps_none_arg_8 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
raise NoValue(SourcePosition( raise NoValue(SourcePosition(
filename="tests/name_resolution/good/toplevel_defs.catala_en", filename="tests/name_resolution/good/toplevel_defs.catala_en",
start_line=95, start_column=10, start_line=95, start_column=10,
end_line=95, end_column=11, end_line=95, end_column=11,
law_headings=["Test inline defs in toplevel defs"])) law_headings=["Test inline defs in toplevel defs"]))
else: elif match_arg.code == Eoption_Code.ESome:
arg_2 = perhaps_none_arg_8 arg = match_arg.value
temp_a_8 = arg_2 a1 = arg
a_2 = temp_a_8 a = a1
return S4(a = a_2) return S4(a = a)
def s(s_in:SIn): def s5(s_in:SIn):
perhaps_none_arg_9 = handle_exceptions([], []) match_arg = handle_exceptions([], [])
if perhaps_none_arg_9 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
if True: if True:
temp_a_9 = (glob1 * glob1) a3 = Eoption(Eoption_Code.ESome, (glob1 * glob1))
else: else:
temp_a_9 = None a3 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_9 = perhaps_none_arg_9 x = match_arg.value
temp_a_9 = x_9 a3 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_10 = handle_exceptions( match_arg = handle_exceptions(
[SourcePosition( [SourcePosition(
filename="tests/name_resolution/good/toplevel_defs.catala_en", filename="tests/name_resolution/good/toplevel_defs.catala_en",
start_line=18, start_column=24, start_line=18, start_column=24,
end_line=18, end_column=37, end_line=18, end_column=37,
law_headings=["Test basic toplevel values defs"] law_headings=["Test basic toplevel values defs"])],
)], [a3]
[temp_a_9] )
) if match_arg.code == Eoption_Code.ENone:
if perhaps_none_arg_10 is None: _ = match_arg.value
if False: if False:
temp_a_10 = None a2 = Eoption(Eoption_Code.ENone, Unit())
else: else:
temp_a_10 = None a2 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_10 = perhaps_none_arg_10 x = match_arg.value
temp_a_10 = x_10 a2 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_11 = temp_a_10 match_arg = a2
if perhaps_none_arg_11 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
raise NoValue(SourcePosition( raise NoValue(SourcePosition(
filename="tests/name_resolution/good/toplevel_defs.catala_en", filename="tests/name_resolution/good/toplevel_defs.catala_en",
start_line=7, start_column=10, start_line=7, start_column=10,
end_line=7, end_column=11, end_line=7, end_column=11,
law_headings=["Test basic toplevel values defs"])) law_headings=["Test basic toplevel values defs"]))
else: elif match_arg.code == Eoption_Code.ESome:
arg_3 = perhaps_none_arg_11 arg = match_arg.value
temp_a_11 = arg_3 a1 = arg
a_3 = temp_a_11 a = a1
perhaps_none_arg_12 = handle_exceptions([], []) match_arg = handle_exceptions([], [])
if perhaps_none_arg_12 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
if True: if True:
temp_b = glob2 b3 = Eoption(Eoption_Code.ESome, glob6)
else: else:
temp_b = None b3 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_11 = perhaps_none_arg_12 x = match_arg.value
temp_b = x_11 b3 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_13 = handle_exceptions( match_arg = handle_exceptions(
[SourcePosition( [SourcePosition(
filename="tests/name_resolution/good/toplevel_defs.catala_en", filename="tests/name_resolution/good/toplevel_defs.catala_en",
start_line=19, start_column=24, start_line=19, start_column=24,
end_line=19, end_column=29, end_line=19, end_column=29,
law_headings=["Test basic toplevel values defs"] law_headings=["Test basic toplevel values defs"])],
)], [b3]
[temp_b] )
) if match_arg.code == Eoption_Code.ENone:
if perhaps_none_arg_13 is None: _ = match_arg.value
if False: if False:
temp_b_1 = None b2 = Eoption(Eoption_Code.ENone, Unit())
else: else:
temp_b_1 = None b2 = Eoption(Eoption_Code.ENone, Unit())
else: elif match_arg.code == Eoption_Code.ESome:
x_12 = perhaps_none_arg_13 x = match_arg.value
temp_b_1 = x_12 b2 = Eoption(Eoption_Code.ESome, x)
perhaps_none_arg_14 = temp_b_1 match_arg = b2
if perhaps_none_arg_14 is None: if match_arg.code == Eoption_Code.ENone:
_ = match_arg.value
raise NoValue(SourcePosition( raise NoValue(SourcePosition(
filename="tests/name_resolution/good/toplevel_defs.catala_en", filename="tests/name_resolution/good/toplevel_defs.catala_en",
start_line=8, start_column=10, start_line=8, start_column=10,
end_line=8, end_column=11, end_line=8, end_column=11,
law_headings=["Test basic toplevel values defs"])) law_headings=["Test basic toplevel values defs"]))
else: elif match_arg.code == Eoption_Code.ESome:
arg_4 = perhaps_none_arg_14 arg = match_arg.value
temp_b_2 = arg_4 b1 = arg
b = temp_b_2 b = b1
return S(a = a_3, b = b) return S(a = a, b = b)
``` ```

View File

@ -39,11 +39,11 @@ $ catala Scalc -s Foo2 -O -t
│ 5 │ output bar content integer │ 5 │ output bar content integer
│ │ ‾‾‾ │ │ ‾‾‾
└─ Test └─ Test
let Foo2_1 (Foo2_in_1: Foo2_in) = let Foo2 (Foo2_in: Foo2_in) =
decl temp_bar_3 : integer; decl bar1 : integer;
fatal NoValue; fatal NoValue;
decl bar_2 : integer; decl bar : integer;
bar_2 = temp_bar_3; bar = bar1;
return Foo2 {"bar": bar_2} return Foo2 {"bar": bar}
``` ```