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
~(typed : ty mark)
~closure_conversion
~monomorphize_types :
typed Lcalc.Ast.program * Scopelang.Dependency.TVertex.t list =
~monomorphize_types
~renaming :
typed Lcalc.Ast.program *
Scopelang.Dependency.TVertex.t list *
Expr.Renaming.context option =
let prg, type_ordering =
dcalc options ~includes ~optimize ~check_invariants ~typed
in
@ -275,7 +278,19 @@ module Passes = struct
prg, type_ordering)
else prg, type_ordering
in
prg, type_ordering
match renaming with
| None -> prg, type_ordering, None
| Some renaming ->
let prg, ren_ctx = Program.apply renaming prg in
let type_ordering =
let open Scopelang.Dependency.TVertex in
List.map
(function
| Struct s -> Struct (Expr.Renaming.struct_name ren_ctx s)
| Enum e -> Enum (Expr.Renaming.enum_name ren_ctx e))
type_ordering
in
prg, type_ordering, Some ren_ctx
let scalc
options
@ -286,17 +301,30 @@ module Passes = struct
~keep_special_ops
~dead_value_assignment
~no_struct_literals
~monomorphize_types :
Scalc.Ast.program * Scopelang.Dependency.TVertex.t list =
let prg, type_ordering =
~monomorphize_types
~renaming :
Scalc.Ast.program * Scopelang.Dependency.TVertex.t list * Expr.Renaming.context =
let prg, type_ordering, renaming_context =
lcalc options ~includes ~optimize ~check_invariants ~typed:Expr.typed
~closure_conversion ~monomorphize_types
~closure_conversion ~monomorphize_types ~renaming
in
let renaming_context = match renaming_context with
| None -> Expr.Renaming.get_ctx {
reserved = [];
sanitize_varname = Fun.id;
reset_context_for_closed_terms = true;
skip_constant_binders = true;
constant_binder_name = None;
}
| Some r -> r
in
debug_pass_name "scalc";
( Scalc.From_lcalc.translate_program
~config:{ keep_special_ops; dead_value_assignment; no_struct_literals }
~config:{ keep_special_ops; dead_value_assignment; no_struct_literals;
renaming_context }
prg,
type_ordering )
type_ordering,
renaming_context )
end
module Commands = struct
@ -711,9 +739,9 @@ module Commands = struct
closure_conversion
monomorphize_types
ex_scope_opt =
let prg, _ =
let prg, _, _ =
Passes.lcalc options ~includes ~optimize ~check_invariants
~closure_conversion ~typed ~monomorphize_types
~closure_conversion ~typed ~monomorphize_types ~renaming:None
in
let _output_file, with_output = get_output_format options output in
with_output
@ -759,9 +787,9 @@ module Commands = struct
optimize
check_invariants
ex_scope_opt =
let prg, _ =
let prg, _, _ =
Passes.lcalc options ~includes ~optimize ~check_invariants
~closure_conversion ~monomorphize_types ~typed
~closure_conversion ~monomorphize_types ~typed ~renaming:None
in
Interpreter.load_runtime_modules
~hashf:(Hash.finalise ~closure_conversion ~monomorphize_types)
@ -809,9 +837,10 @@ module Commands = struct
check_invariants
closure_conversion
ex_scope_opt =
let prg, type_ordering =
let prg, type_ordering, _ =
Passes.lcalc options ~includes ~optimize ~check_invariants
~typed:Expr.typed ~closure_conversion ~monomorphize_types:false
~renaming:(Some Lcalc.To_ocaml.renaming)
in
let output_file, with_output =
get_output_format options ~ext:".ml" output
@ -851,10 +880,10 @@ module Commands = struct
no_struct_literals
monomorphize_types
ex_scope_opt =
let prg, _ =
let prg, _, _ =
Passes.scalc options ~includes ~optimize ~check_invariants
~closure_conversion ~keep_special_ops ~dead_value_assignment
~no_struct_literals ~monomorphize_types
~no_struct_literals ~monomorphize_types ~renaming:None
in
let _output_file, with_output = get_output_format options output in
with_output
@ -900,10 +929,11 @@ module Commands = struct
optimize
check_invariants
closure_conversion =
let prg, type_ordering =
let prg, type_ordering, _ren_ctx =
Passes.scalc options ~includes ~optimize ~check_invariants
~closure_conversion ~keep_special_ops:false ~dead_value_assignment:true
~no_struct_literals:false ~monomorphize_types:false
~renaming:(Some Scalc.To_python.renaming)
in
let output_file, with_output =
@ -929,11 +959,12 @@ module Commands = struct
$ Cli.Flags.closure_conversion)
let c options includes output optimize check_invariants =
let prg, type_ordering =
let prg, type_ordering, _ren_ctx =
Passes.scalc options ~includes ~optimize ~check_invariants
~closure_conversion:true ~keep_special_ops:true
~dead_value_assignment:false ~no_struct_literals:true
~monomorphize_types:true
~renaming:(Some Scalc.To_c.renaming)
in
let output_file, with_output = get_output_format options ~ext:".c" output in
Message.debug "Compiling program into C...";

View File

@ -53,7 +53,9 @@ module Passes : sig
typed:'m Shared_ast.mark ->
closure_conversion:bool ->
monomorphize_types:bool ->
Shared_ast.typed Lcalc.Ast.program * Scopelang.Dependency.TVertex.t list
renaming : Shared_ast.Program.renaming option ->
Shared_ast.typed Lcalc.Ast.program * Scopelang.Dependency.TVertex.t list *
Shared_ast.Expr.Renaming.context option
val scalc :
Global.options ->
@ -65,7 +67,10 @@ module Passes : sig
dead_value_assignment:bool ->
no_struct_literals:bool ->
monomorphize_types:bool ->
Scalc.Ast.program * Scopelang.Dependency.TVertex.t list
renaming: Shared_ast.Program.renaming option ->
Scalc.Ast.program * Scopelang.Dependency.TVertex.t list *
Shared_ast.Expr.Renaming.context
end
module Commands : sig

View File

@ -130,6 +130,13 @@ let ocaml_keywords =
"Oper";
]
let renaming =
Program.renaming ()
~reserved:ocaml_keywords
(* TODO: add catala runtime built-ins as reserved as well ? *)
~reset_context_for_closed_terms:true ~skip_constant_binders:true
~constant_binder_name:(Some "_") ~namespaced_fields_constrs:true
let format_struct_name (fmt : Format.formatter) (v : StructName.t) : unit =
(match StructName.path v with
| [] -> ()
@ -414,6 +421,7 @@ let rec format_expr (ctx : decl_ctx) (fmt : Format.formatter) (e : 'm expr) :
Print.runtime_error er format_pos (Expr.pos e)
| _ -> .
(* TODO: move [embed_foo] to [Foo.embed] to protect from name clashes *)
let format_struct_embedding
(fmt : Format.formatter)
((struct_name, struct_fields) : StructName.t * typ StructField.Map.t) =
@ -730,21 +738,6 @@ let format_program
~(hashf : Hash.t -> Hash.full)
(p : 'm Ast.program)
(type_ordering : Scopelang.Dependency.TVertex.t list) : unit =
let p, ren_ctx =
Program.rename_ids p
~reserved:ocaml_keywords
(* TODO: add catala runtime built-ins as reserved as well ? *)
~reset_context_for_closed_terms:true ~skip_constant_binders:true
~constant_binder_name:(Some "_") ~namespaced_fields_constrs:true
in
let type_ordering =
let open Scopelang.Dependency.TVertex in
List.map
(function
| Struct s -> Struct (Expr.Renaming.struct_name ren_ctx s)
| Enum e -> Enum (Expr.Renaming.enum_name ren_ctx e))
type_ordering
in
Format.pp_open_vbox fmt 0;
Format.pp_print_string fmt header;
check_and_reexport_used_modules fmt ~hashf

View File

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

View File

@ -475,22 +475,10 @@ let run
monomorphize_types
_options =
let options = Global.enforce_options ~trace:true () in
let prg, type_ordering =
let prg, type_ordering, _ =
Driver.Passes.lcalc options ~includes ~optimize ~check_invariants
~closure_conversion ~typed:Expr.typed ~monomorphize_types
in
let prg, ren_ctx =
Program.rename_ids prg ~reserved:To_ocaml.ocaml_keywords
~reset_context_for_closed_terms:true ~skip_constant_binders:true
~constant_binder_name:None ~namespaced_fields_constrs:true
in
let type_ordering =
let open Scopelang.Dependency.TVertex in
List.map
(function
| Struct s -> Struct (Expr.Renaming.struct_name ren_ctx s)
| Enum e -> Enum (Expr.Renaming.enum_name ren_ctx e))
type_ordering
~renaming:(Some Lcalc.To_ocaml.renaming)
in
let jsoo_output_file, with_formatter =
Driver.Commands.get_output_format options ~ext:"_api_web.ml" output

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,109 +21,21 @@ module D = Dcalc.Ast
module L = Lcalc.Ast
open Ast
let avoid_keywords (s : string) : string =
if
match s with
(* list taken from
https://learn.microsoft.com/en-us/cpp/c-language/c-keywords *)
| "auto" | "break" | "case" | "char" | "const" | "continue" | "default"
| "do" | "double" | "else" | "enum" | "extern" | "float" | "for" | "goto"
| "if" | "inline" | "int" | "long" | "register" | "restrict" | "return"
| "short" | "signed" | "sizeof" | "static" | "struct" | "switch" | "typedef"
| "union" | "unsigned" | "void" | "volatile" | "while" ->
true
| _ -> false
then s ^ "_"
else s
let c_keywords =
[ "auto"; "break"; "case"; "char"; "const"; "continue"; "default";
"do"; "double"; "else"; "enum"; "extern"; "float"; "for"; "goto";
"if"; "inline"; "int"; "long"; "register"; "restrict"; "return";
"short"; "signed"; "sizeof"; "static"; "struct"; "switch"; "typedef";
"union"; "unsigned"; "void"; "volatile"; "while" ]
let format_struct_name (fmt : Format.formatter) (v : StructName.t) : unit =
Format.fprintf fmt "%s"
(Format.asprintf "%a_struct" StructName.format v
|> String.to_ascii
|> String.to_snake_case
|> avoid_keywords)
let format_struct_field_name (fmt : Format.formatter) (v : StructField.t) : unit
=
Format.fprintf fmt "%s"
(Format.asprintf "%a_field" StructField.format v
|> String.to_ascii
|> String.to_snake_case
|> avoid_keywords)
let format_enum_name (fmt : Format.formatter) (v : EnumName.t) : unit =
Format.fprintf fmt "%s_enum"
(Format.asprintf "%a" EnumName.format v
|> String.to_ascii
|> String.to_snake_case
|> avoid_keywords)
let format_enum_cons_name (fmt : Format.formatter) (v : EnumConstructor.t) :
unit =
Format.fprintf fmt "%s_cons"
(Format.asprintf "%a" EnumConstructor.format v
|> String.to_ascii
|> String.to_snake_case
|> avoid_keywords)
let format_name_cleaned (fmt : Format.formatter) (s : string) : unit =
s
|> String.to_ascii
|> String.to_snake_case
|> Re.Pcre.substitute ~rex:(Re.Pcre.regexp "\\.") ~subst:(fun _ -> "_dot_")
|> String.to_ascii
|> avoid_keywords
|> Format.fprintf fmt "%s"
let format_func_name (fmt : Format.formatter) (v : FuncName.t) : unit =
let v_str = Mark.remove (FuncName.get_info v) in
Format.fprintf fmt "%a_func" format_name_cleaned v_str
module StringMap = String.Map
module IntMap = Map.Make (struct
include Int
let format ppf i = Format.pp_print_int ppf i
end)
(** For each `VarName.t` defined by its string and then by its hash, we keep
track of which local integer id we've given it. This is used to keep
variable naming with low indices rather than one global counter for all
variables. TODO: should be removed when
https://github.com/CatalaLang/catala/issues/240 is fixed. *)
let string_counter_map : int IntMap.t StringMap.t ref = ref StringMap.empty
let format_var (fmt : Format.formatter) (v : VarName.t) : unit =
let v_str = Mark.remove (VarName.get_info v) in
let id = VarName.id v in
let local_id =
match StringMap.find_opt v_str !string_counter_map with
| Some ids -> (
match IntMap.find_opt id ids with
| None ->
let max_id =
snd
(List.hd
(List.fast_sort
(fun (_, x) (_, y) -> Int.compare y x)
(IntMap.bindings ids)))
in
string_counter_map :=
StringMap.add v_str
(IntMap.add id (max_id + 1) ids)
!string_counter_map;
max_id + 1
| Some local_id -> local_id)
| None ->
string_counter_map :=
StringMap.add v_str (IntMap.singleton id 0) !string_counter_map;
0
in
if v_str = "_" then Format.fprintf fmt "dummy_var"
(* special case for the unit pattern TODO escape dummy_var *)
else if local_id = 0 then format_name_cleaned fmt v_str
else Format.fprintf fmt "%a_%d" format_name_cleaned v_str local_id
let renaming =
Program.renaming ()
~reserved:c_keywords
(* TODO: add catala runtime built-ins as reserved as well ? *)
~reset_context_for_closed_terms:true
~skip_constant_binders:true
~constant_binder_name:None
~namespaced_fields_constrs:false
module TypMap = Map.Make (struct
type t = naked_typ
@ -156,12 +68,12 @@ let rec format_typ
(format_typ decl_ctx (fun fmt -> Format.fprintf fmt "arg_%d" i))
t))
(List.mapi (fun x y -> y, x) ts)
| TStruct s -> Format.fprintf fmt "%a %t" format_struct_name s element_name
| TStruct s -> Format.fprintf fmt "%a %t" StructName.format s element_name
| TOption _ ->
Message.error ~internal:true
"All option types should have been monomorphized before compilation to C."
| TDefault t -> format_typ decl_ctx element_name fmt t
| TEnum e -> Format.fprintf fmt "%a %t" format_enum_name e element_name
| TEnum e -> Format.fprintf fmt "%a %t" EnumName.format e element_name
| TArrow (t1, t2) ->
Format.fprintf fmt "%a(%a)"
(format_typ decl_ctx (fun fmt -> Format.fprintf fmt "(*%t)" element_name))
@ -185,41 +97,41 @@ let format_ctx
let format_struct_decl fmt (struct_name, struct_fields) =
let fields = StructField.Map.bindings struct_fields in
Format.fprintf fmt "@[<v 2>typedef struct %a {@ %a@]@,} %a;"
format_struct_name struct_name
StructName.format struct_name
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ")
(fun fmt (struct_field, struct_field_type) ->
Format.fprintf fmt "@[<v>%a;@]"
(format_typ ctx (fun fmt ->
format_struct_field_name fmt struct_field))
StructField.format fmt struct_field))
struct_field_type))
fields format_struct_name struct_name
fields StructName.format struct_name
in
let format_enum_decl fmt (enum_name, enum_cons) =
if EnumConstructor.Map.is_empty enum_cons then
failwith "no constructors in the enum"
else
Format.fprintf fmt "@[<v 2>enum %a_code {@,%a@]@,} %a_code;@\n@\n"
format_enum_name enum_name
EnumName.format enum_name
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (enum_cons, _) ->
Format.fprintf fmt "%a_%a" format_enum_name enum_name
format_enum_cons_name enum_cons))
Format.fprintf fmt "%a_%a" EnumName.format enum_name
EnumConstructor.format enum_cons))
(EnumConstructor.Map.bindings enum_cons)
format_enum_name enum_name;
EnumName.format enum_name;
Format.fprintf fmt
"@[<v 2>typedef struct %a {@ enum %a_code code;@ @[<v 2>union {@ %a@]@,\
} payload;@]@,\
} %a;" format_enum_name enum_name format_enum_name enum_name
} %a;" EnumName.format enum_name EnumName.format enum_name
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ")
(fun fmt (enum_cons, typ) ->
Format.fprintf fmt "%a;"
(format_typ ctx (fun fmt -> format_enum_cons_name fmt enum_cons))
(format_typ ctx (fun fmt -> EnumConstructor.format fmt enum_cons))
typ))
(EnumConstructor.Map.bindings enum_cons)
format_enum_name enum_name
EnumName.format enum_name
in
let is_in_type_ordering s =
@ -329,8 +241,8 @@ let _format_string_list (fmt : Format.formatter) (uids : string list) : unit =
let rec format_expression (ctx : decl_ctx) (fmt : Format.formatter) (e : expr) :
unit =
match Mark.remove e with
| EVar v -> format_var fmt v
| EFunc f -> format_func_name fmt f
| EVar v -> VarName.format fmt v
| EFunc f -> FuncName.format fmt f
| EStruct { fields = es; _ } ->
(* These should only appear when initializing a variable definition *)
Format.fprintf fmt "{ %a }"
@ -340,10 +252,10 @@ let rec format_expression (ctx : decl_ctx) (fmt : Format.formatter) (e : expr) :
(StructField.Map.bindings es)
| EStructFieldAccess { e1; field; _ } ->
Format.fprintf fmt "%a.%a" (format_expression ctx) e1
format_struct_field_name field
StructField.format field
| EInj { e1; cons; name = enum_name; _ } ->
Format.fprintf fmt "{%a_%a,@ {%a: %a}}" format_enum_name enum_name
format_enum_cons_name cons format_enum_cons_name cons
Format.fprintf fmt "{%a_%a,@ {%a: %a}}" EnumName.format enum_name
EnumConstructor.format cons EnumConstructor.format cons
(format_expression ctx) e1
| EArray _ ->
failwith
@ -402,7 +314,7 @@ let rec format_statement
"This inner functions should have been hoisted in Scalc"
| SLocalDecl { name = v; typ = ty } ->
Format.fprintf fmt "@[<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
(* Below we detect array initializations which have special treatment. *)
| SLocalInit { name = v; expr = EStruct { fields; name }, _; typ }
@ -421,20 +333,20 @@ let rec format_statement
"@[<hov 2>%a;@]@\n\
@[<hov 2>%a.content_field = catala_malloc(sizeof(%a));@]@\n\
%a"
(format_typ ctx (fun fmt -> format_var fmt (Mark.remove v)))
typ format_var (Mark.remove v) format_struct_name name
(format_typ ctx (fun fmt -> VarName.format fmt (Mark.remove v)))
typ VarName.format (Mark.remove v) StructName.format name
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@\n")
(fun fmt (i, arg) ->
Format.fprintf fmt "@[<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)
| SLocalInit { name = v; expr = e; typ } ->
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
| 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
| SRaiseEmpty | STryWEmpty _ -> assert false
| SFatalError err ->
@ -457,18 +369,18 @@ let rec format_statement
(EnumConstructor.Map.bindings (EnumName.Map.find e_name ctx.ctx_enums))
in
let tmp_var = VarName.fresh ("match_arg", Pos.no_pos) in
Format.fprintf fmt "@[<hov 2>%a %a = %a;@]@," format_enum_name e_name
format_var tmp_var (format_expression ctx) e1;
Format.fprintf fmt "@[<hov 2>%a %a = %a;@]@," EnumName.format e_name
VarName.format tmp_var (format_expression ctx) e1;
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
(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_enum_cons_name cons_name;
Format.fprintf fmt "@[<hv 2>case %a_%a:@ " EnumName.format e_name
EnumConstructor.format cons_name;
if not (Type.equal payload_var_typ (TLit TUnit, Pos.no_pos)) then
Format.fprintf fmt "%a = %a.payload.%a;@ "
(format_typ ctx (fun fmt -> format_var fmt payload_var_name))
payload_var_typ format_var tmp_var format_enum_cons_name cons_name;
(format_typ ctx (fun fmt -> VarName.format fmt payload_var_name))
payload_var_typ VarName.format tmp_var EnumConstructor.format cons_name;
Format.fprintf fmt "%a@ break;@]" (format_block ctx) case_block)
fmt cases;
(* Do we want to add 'default' case with a failure ? *)
@ -514,13 +426,13 @@ let rec format_statement
in
if exceptions <> [] then begin
Format.fprintf fmt "@[<hov 2>%a = {%a_%a,@ {%a: NULL}};@]@,"
(format_typ ctx (fun fmt -> format_var fmt exception_acc_var))
return_typ format_enum_name e_name format_enum_cons_name none_cons
format_enum_cons_name none_cons;
(format_typ ctx (fun fmt -> VarName.format fmt exception_acc_var))
return_typ EnumName.format e_name EnumConstructor.format none_cons
EnumConstructor.format none_cons;
Format.fprintf fmt "%a;@,"
(format_typ ctx (fun fmt -> format_var fmt exception_current))
(format_typ ctx (fun fmt -> VarName.format fmt exception_current))
return_typ;
Format.fprintf fmt "char %a = 0;@," format_var exception_conflict;
Format.fprintf fmt "char %a = 0;@," VarName.format exception_conflict;
List.iter
(fun except ->
Format.fprintf fmt
@ -532,11 +444,11 @@ let rec format_statement
%a = %a;@]@,\
}@]@,\
}@,"
format_var exception_current (format_expression ctx) except
format_var exception_current format_enum_name e_name
format_enum_cons_name some_cons format_var exception_acc_var
format_enum_name e_name format_enum_cons_name some_cons format_var
exception_conflict format_var exception_acc_var format_var
VarName.format exception_current (format_expression ctx) except
VarName.format exception_current EnumName.format e_name
EnumConstructor.format some_cons VarName.format exception_acc_var
EnumName.format e_name EnumConstructor.format some_cons VarName.format
exception_conflict VarName.format exception_acc_var VarName.format
exception_current)
exceptions;
Format.fprintf fmt
@ -544,14 +456,14 @@ let rec format_statement
@[<hov 2>catala_raise_fatal_error(catala_conflict,@ \"%s\",@ %d, %d, \
%d, %d);@]@;\
<1 -2>}@]@,"
format_var exception_conflict (Pos.get_file pos)
VarName.format exception_conflict (Pos.get_file pos)
(Pos.get_start_line pos) (Pos.get_start_column pos)
(Pos.get_end_line pos) (Pos.get_end_column pos);
Format.fprintf fmt
"@[<v 2>if (%a.code == %a_%a) {@,%a = %a;@]@,@[<v 2>} else {@,"
format_var exception_acc_var format_enum_name e_name
format_enum_cons_name some_cons format_var variable_defined_in_cons
format_var exception_acc_var
VarName.format exception_acc_var EnumName.format e_name
EnumConstructor.format some_cons VarName.format variable_defined_in_cons
VarName.format exception_acc_var
end;
Format.fprintf fmt
"@[<v 2>if (%a) {@,\
@ -560,9 +472,9 @@ let rec format_statement
%a.code = %a_%a;@,\
%a.payload.%a = NULL;@]@,\
}"
(format_expression ctx) just (format_block ctx) cons format_var
variable_defined_in_cons format_enum_name e_name format_enum_cons_name
none_cons format_var variable_defined_in_cons format_enum_cons_name
(format_expression ctx) just (format_block ctx) cons VarName.format
variable_defined_in_cons EnumName.format e_name EnumConstructor.format
none_cons VarName.format variable_defined_in_cons EnumConstructor.format
none_cons;
if exceptions <> [] then Format.fprintf fmt "@]@,}"
@ -591,7 +503,7 @@ let format_program
match code_item with
| SVar { var; expr; typ } ->
Format.fprintf fmt "@[<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
(format_expression p.ctx.decl_ctx)
expr
@ -599,13 +511,13 @@ let format_program
| SScope { scope_body_var = var; scope_body_func = func; _ } ->
let { func_params; func_body; func_return_typ } = func in
Format.fprintf fmt "@[<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
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (var, typ) ->
(format_typ p.ctx.decl_ctx (fun fmt ->
format_var fmt (Mark.remove var)))
VarName.format fmt (Mark.remove var)))
fmt typ))
func_params
(format_block p.ctx.decl_ctx)

View File

@ -14,7 +14,11 @@
License for the specific language governing permissions and limitations under
the License. *)
(** Formats a lambda calculus program into a valid C89 program *)
(** Formats a statement calculus program into a valid C89 program *)
open Shared_ast
val renaming : Program.renaming
val format_program :
Format.formatter -> Ast.program -> Scopelang.Dependency.TVertex.t list -> unit

View File

@ -110,98 +110,23 @@ let format_string_list (fmt : Format.formatter) (uids : string list) : unit =
(Re.replace sanitize_quotes ~f:(fun _ -> "\\\"") info)))
uids
let avoid_keywords (s : string) : string =
if
match s with
(* list taken from
https://www.programiz.com/python-programming/keyword-list *)
| "False" | "None" | "True" | "and" | "as" | "assert" | "async" | "await"
| "break" | "class" | "continue" | "def" | "del" | "elif" | "else"
| "except" | "finally" | "for" | "from" | "global" | "if" | "import" | "in"
| "is" | "lambda" | "nonlocal" | "not" | "or" | "pass" | "raise" | "return"
| "try" | "while" | "with" | "yield" ->
true
| _ -> false
then s ^ "_"
else s
let python_keywords =
(* list taken from
https://www.programiz.com/python-programming/keyword-list *)
[ "False"; "None"; "True"; "and"; "as"; "assert"; "async"; "await";
"break"; "class"; "continue"; "def"; "del"; "elif"; "else";
"except"; "finally"; "for"; "from"; "global"; "if"; "import"; "in";
"is"; "lambda"; "nonlocal"; "not"; "or"; "pass"; "raise"; "return";
"try"; "while"; "with"; "yield" ]
(* todo: reserved names should also include built-in types and everything exposed by the runtime. *)
module StringMap = String.Map
module IntMap = Map.Make (struct
include Int
let format ppf i = Format.pp_print_int ppf i
end)
let clean_name (s : string) : string =
s
|> String.to_snake_case
|> Re.Pcre.substitute ~rex:(Re.Pcre.regexp "\\.") ~subst:(fun _ -> "_dot_")
|> avoid_keywords
let format_name_cleaned (fmt : Format.formatter) (s : string) : unit =
Format.pp_print_string fmt (clean_name s)
(** For each `VarName.t` defined by its string and then by its hash, we keep
track of which local integer id we've given it. This is used to keep
variable naming with low indices rather than one global counter for all
variables. TODO: should be removed when
https://github.com/CatalaLang/catala/issues/240 is fixed. *)
let string_counter_map : int IntMap.t StringMap.t ref = ref StringMap.empty
let format_var (fmt : Format.formatter) (v : VarName.t) : unit =
let v_str = clean_name (Mark.remove (VarName.get_info v)) in
let id = VarName.id v in
let local_id =
match StringMap.find_opt v_str !string_counter_map with
| Some ids -> (
match IntMap.find_opt id ids with
| None ->
let local_id = 1 + IntMap.fold (fun _ -> Int.max) ids 0 in
string_counter_map :=
StringMap.add v_str (IntMap.add id local_id ids) !string_counter_map;
local_id
| Some local_id -> local_id)
| None ->
string_counter_map :=
StringMap.add v_str (IntMap.singleton id 0) !string_counter_map;
0
in
if v_str = "_" then Format.fprintf fmt "_"
(* special case for the unit pattern *)
else if local_id = 0 then Format.pp_print_string fmt v_str
else Format.fprintf fmt "%s_%d" v_str local_id
let format_path ctx fmt p =
match List.rev p with
| [] -> ()
| m :: _ ->
format_var fmt (ModuleName.Map.find m ctx.modules);
Format.pp_print_char fmt '.'
let format_struct_name ctx (fmt : Format.formatter) (v : StructName.t) : unit =
format_path ctx fmt (StructName.path v);
Format.pp_print_string fmt
(avoid_keywords
(String.to_camel_case
(String.to_ascii (Mark.remove (StructName.get_info v)))))
let format_struct_field_name (fmt : Format.formatter) (v : StructField.t) : unit
=
Format.pp_print_string fmt
(avoid_keywords (String.to_ascii (StructField.to_string v)))
let format_enum_name ctx (fmt : Format.formatter) (v : EnumName.t) : unit =
format_path ctx fmt (EnumName.path v);
Format.pp_print_string fmt
(avoid_keywords
(String.to_camel_case
(String.to_ascii (Mark.remove (EnumName.get_info v)))))
let format_enum_cons_name (fmt : Format.formatter) (v : EnumConstructor.t) :
unit =
Format.pp_print_string fmt
(avoid_keywords (String.to_ascii (EnumConstructor.to_string v)))
let renaming =
Program.renaming ()
~reserved:python_keywords
(* TODO: add catala runtime built-ins as reserved as well ? *)
~reset_context_for_closed_terms:false ~skip_constant_binders:false
~constant_binder_name:None ~namespaced_fields_constrs:true
~f_struct:String.to_camel_case
let typ_needs_parens (e : typ) : bool =
match Mark.remove e with TArrow _ | TArray _ -> true | _ -> false
@ -226,12 +151,12 @@ let rec format_typ ctx (fmt : Format.formatter) (typ : typ) : unit =
~pp_sep:(fun fmt () -> Format.fprintf fmt ", ")
(fun fmt t -> Format.fprintf fmt "%a" format_typ_with_parens t))
ts
| TStruct s -> Format.fprintf fmt "%a" (format_struct_name ctx) s
| TStruct s -> StructName.format fmt s
| TOption some_typ ->
(* We translate the option type with an overloading by Python's [None] *)
Format.fprintf fmt "Optional[%a]" format_typ some_typ
| TDefault t -> format_typ fmt t
| TEnum e -> Format.fprintf fmt "%a" (format_enum_name ctx) e
| TEnum e -> EnumName.format fmt e
| TArrow (t1, t2) ->
Format.fprintf fmt "Callable[[%a], %a]"
(Format.pp_print_list
@ -243,8 +168,7 @@ let rec format_typ ctx (fmt : Format.formatter) (typ : typ) : unit =
| TClosureEnv -> failwith "unimplemented!"
let format_func_name (fmt : Format.formatter) (v : FuncName.t) : unit =
let v_str = Mark.remove (FuncName.get_info v) in
format_name_cleaned fmt v_str
FuncName.format fmt v
let format_position ppf pos =
Format.fprintf ppf
@ -263,19 +187,19 @@ let format_error (ppf : Format.formatter) (err : Runtime.error Mark.pos) : unit
let rec format_expression ctx (fmt : Format.formatter) (e : expr) : unit =
match Mark.remove e with
| EVar v -> format_var fmt v
| EFunc f -> format_func_name fmt f
| EVar v -> VarName.format fmt v
| EFunc f -> FuncName.format fmt f
| EStruct { fields = es; name = s } ->
Format.fprintf fmt "%a(%a)" (format_struct_name ctx) s
Format.fprintf fmt "%a(%a)" StructName.format s
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (struct_field, e) ->
Format.fprintf fmt "%a = %a" format_struct_field_name struct_field
Format.fprintf fmt "%a = %a" StructField.format struct_field
(format_expression ctx) e))
(StructField.Map.bindings es)
| EStructFieldAccess { e1; field; _ } ->
Format.fprintf fmt "%a.%a" (format_expression ctx) e1
format_struct_field_name field
StructField.format field
| EInj { cons; name = e_name; _ }
when EnumName.equal e_name Expr.option_enum
&& EnumConstructor.equal cons Expr.none_constr ->
@ -287,8 +211,8 @@ let rec format_expression ctx (fmt : Format.formatter) (e : expr) : unit =
(* We translate the option type with an overloading by Python's [None] *)
format_expression ctx fmt e
| EInj { e1 = e; cons; name = enum_name; _ } ->
Format.fprintf fmt "%a(%a_Code.%a,@ %a)" (format_enum_name ctx) enum_name
(format_enum_name ctx) enum_name format_enum_cons_name cons
Format.fprintf fmt "%a(%a_Code.%a,@ %a)" EnumName.format enum_name
EnumName.format enum_name EnumConstructor.format cons
(format_expression ctx) e
| EArray es ->
Format.fprintf fmt "[%a]"
@ -380,26 +304,26 @@ let rec format_expression ctx (fmt : Format.formatter) (e : expr) : unit =
| ETupleAccess { e1; index } ->
Format.fprintf fmt "%a[%d]" (format_expression ctx) e1 index
| EExternal { modname; name } ->
Format.fprintf fmt "%a.%a" format_var (Mark.remove modname)
format_name_cleaned (Mark.remove name)
Format.fprintf fmt "%a.%s" VarName.format (Mark.remove modname)
(Mark.remove name)
let rec format_statement ctx (fmt : Format.formatter) (s : stmt Mark.pos) : unit
=
match Mark.remove s with
| SInnerFuncDef { name; func = { func_params; func_body; _ } } ->
Format.fprintf fmt "@[<v 4>def %a(@[<hov>%a@]):@ %a@]" format_var
Format.fprintf fmt "@[<v 4>def %a(@[<hov>%a@]):@ %a@]" VarName.format
(Mark.remove name)
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (var, typ) ->
Format.fprintf fmt "%a:%a" format_var (Mark.remove var)
Format.fprintf fmt "%a:%a" VarName.format (Mark.remove var)
(format_typ ctx) typ))
func_params (format_block ctx) func_body
| SLocalDecl _ ->
assert false (* We don't need to declare variables in Python *)
| SLocalDef { name = v; expr = e; _ } | SLocalInit { name = v; expr = e; _ }
->
Format.fprintf fmt "@[<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
| STryWEmpty { try_block = try_b; with_block = catch_b } ->
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 ->
(* We translate the option type with an overloading by Python's [None] *)
let tmp_var = VarName.fresh ("perhaps_none_arg", Pos.no_pos) in
Format.fprintf fmt "@[<hv 4>%a = %a@]@," format_var tmp_var
Format.fprintf fmt "@[<hv 4>%a = %a@]@," VarName.format tmp_var
(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.fprintf fmt "@[<v 4>else:@ %a = %a@,%a@]" format_var case_some_var
format_var tmp_var (format_block ctx) case_some
Format.fprintf fmt "@[<v 4>else:@ %a = %a@,%a@]" VarName.format case_some_var
VarName.format tmp_var (format_block ctx) case_some
| SSwitch { switch_expr = e1; enum_name = e_name; switch_cases = cases; _ } ->
let cons_map = EnumName.Map.find e_name ctx.decl_ctx.ctx_enums in
let cases =
@ -439,15 +363,15 @@ let rec format_statement ctx (fmt : Format.formatter) (s : stmt Mark.pos) : unit
(EnumConstructor.Map.bindings cons_map)
in
let tmp_var = VarName.fresh ("match_arg", Pos.no_pos) in
Format.fprintf fmt "%a = %a@\n@[<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.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@]@\n@[<hov 4>elif ")
(fun fmt ({ case_block; payload_var_name; _ }, cons_name) ->
Format.fprintf fmt "%a.code == %a_Code.%a:@\n%a = %a.value@\n%a"
format_var tmp_var (format_enum_name ctx) e_name
format_enum_cons_name cons_name format_var payload_var_name
format_var tmp_var (format_block ctx) case_block))
VarName.format tmp_var (EnumName.format) e_name
EnumConstructor.format cons_name VarName.format payload_var_name
VarName.format tmp_var (format_block ctx) case_block))
cases
| SReturn e1 ->
Format.fprintf fmt "@[<hov 4>return %a@]" (format_expression ctx)
@ -497,38 +421,38 @@ let format_ctx
\ return not (self == other)@,\
@,\
\ 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
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ", ")
(fun fmt (struct_field, struct_field_type) ->
Format.fprintf fmt "%a: %a" format_struct_field_name struct_field
Format.fprintf fmt "%a: %a" StructField.format struct_field
(format_typ ctx) struct_field_type))
fields
(if StructField.Map.is_empty struct_fields then fun fmt _ ->
Format.fprintf fmt " pass"
else
Format.pp_print_list (fun fmt (struct_field, _) ->
Format.fprintf fmt " self.%a = %a" format_struct_field_name
struct_field format_struct_field_name struct_field))
fields (format_struct_name ctx) struct_name
Format.fprintf fmt " self.%a = %a" StructField.format
struct_field StructField.format struct_field))
fields StructName.format struct_name
(if not (StructField.Map.is_empty struct_fields) then
Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt " and@ ")
(fun fmt (struct_field, _) ->
Format.fprintf fmt "self.%a == other.%a" format_struct_field_name
struct_field format_struct_field_name struct_field)
Format.fprintf fmt "self.%a == other.%a" StructField.format
struct_field StructField.format struct_field)
else fun fmt _ -> Format.fprintf fmt "True")
fields (format_struct_name ctx) struct_name
fields StructName.format struct_name
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",")
(fun fmt (struct_field, _) ->
Format.fprintf fmt "%a={}" format_struct_field_name struct_field))
Format.fprintf fmt "%a={}" StructField.format struct_field))
fields
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (struct_field, _) ->
Format.fprintf fmt "self.%a" format_struct_field_name struct_field))
Format.fprintf fmt "self.%a" StructField.format struct_field))
fields
in
let format_enum_decl fmt (enum_name, enum_cons) =
@ -558,14 +482,14 @@ let format_ctx
@,\
\ def __str__(self) -> str:@,\
\ @[<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.fprintf fmt "%a = %d" format_enum_cons_name enum_cons i))
Format.fprintf fmt "%a = %d" EnumConstructor.format enum_cons i))
(List.mapi
(fun i (x, y) -> i, x, y)
(EnumConstructor.Map.bindings enum_cons))
(format_enum_name ctx) enum_name (format_enum_name ctx) enum_name
(format_enum_name ctx) enum_name
(EnumName.format) enum_name EnumName.format enum_name
EnumName.format enum_name
in
let is_in_type_ordering s =
@ -597,19 +521,9 @@ let format_ctx
(e, EnumName.Map.find e ctx.decl_ctx.ctx_enums))
(type_ordering @ scope_structs)
(* FIXME: this is an ugly (and partial) workaround, Python basically has one
namespace and we reserve the name to avoid clashes between func ids and
variable ids. *)
let reserve_func_name = function
| SVar _ -> ()
| SFunc { var = v; _ } | SScope { scope_body_var = v; _ } ->
let v_str = clean_name (Mark.remove (FuncName.get_info v)) in
string_counter_map :=
StringMap.add v_str (IntMap.singleton (-1) 0) !string_counter_map
let format_code_item ctx fmt = function
| SVar { var; expr; typ = _ } ->
Format.fprintf fmt "@[<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
| SFunc { var; func }
| SScope { scope_body_var = var; scope_body_func = func; _ } ->
@ -619,7 +533,7 @@ let format_code_item ctx fmt = function
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (var, typ) ->
Format.fprintf fmt "%a:%a" format_var (Mark.remove var)
Format.fprintf fmt "%a:%a" VarName.format (Mark.remove var)
(format_typ ctx) typ))
func_params (format_block ctx) func_body
@ -627,7 +541,6 @@ let format_program
(fmt : Format.formatter)
(p : Ast.program)
(type_ordering : Scopelang.Dependency.TVertex.t list) : unit =
List.iter reserve_func_name p.code_items;
Format.pp_open_vbox fmt 0;
let header =
[
@ -643,7 +556,7 @@ let format_program
ModuleName.Map.iter
(fun m v ->
Format.fprintf fmt "from . import %a as %a@," ModuleName.format m
format_var v)
VarName.format v)
p.ctx.modules;
Format.pp_print_cut fmt ();
format_ctx type_ordering fmt p.ctx;

View File

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

View File

@ -417,6 +417,12 @@ module Renaming : sig
like [String.to_snake_case]). The result is advisory and a numerical suffix
may be appended or modified *)
val unmbind_in :
context ->
?fname:(string -> string) ->
('e, 'b) Bindlib.mbinder ->
('e, _) Mark.ed Var.t Array.t * 'b * context
val new_id : context -> string -> string * context
val set_rewriters :

View File

@ -114,7 +114,8 @@ let rename_ids
?(f_field = uncap)
?(f_enum = cap)
?(f_constr = cap)
p =
p
=
let cfg =
{
Expr.Renaming.reserved;
@ -283,3 +284,45 @@ let rename_ids
let decl_ctx = map_decl_ctx ~f:(Expr.Renaming.typ ctx) decl_ctx in
let code_items = Scope.rename_ids ctx p.code_items in
{ p with decl_ctx; code_items }, ctx
(* This first-class module wrapping is here to allow a polymorphic renaming function to be passed around *)
module type Renaming = sig
val apply:
'e program ->
'e program * Expr.Renaming.context
end
type renaming = (module Renaming)
let apply (module R: Renaming) = R.apply
let renaming
~reserved
~reset_context_for_closed_terms
~skip_constant_binders
~constant_binder_name
~namespaced_fields_constrs
?f_var
?f_struct
?f_field
?f_enum
?f_constr
()
=
let module M = struct
let apply p =
rename_ids
~reserved
~reset_context_for_closed_terms
~skip_constant_binders
~constant_binder_name
~namespaced_fields_constrs
?f_var
?f_struct
?f_field
?f_enum
?f_constr
p
end in
(module M: Renaming)

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

View File

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

View File

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

View File

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

View File

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