diff --git a/compiler/desugared/ast.ml b/compiler/desugared/ast.ml index 8716f3c6..ff077139 100644 --- a/compiler/desugared/ast.ml +++ b/compiler/desugared/ast.ml @@ -144,27 +144,31 @@ module Rule = struct | Some _, None -> 1 end -let empty_rule (pos : Pos.t) (have_parameter : typ list option) : rule = +let empty_rule + (pos : Pos.t) + (parameters : (Uid.MarkedString.info * typ) list option) : rule = { rule_just = Expr.box (ELit (LBool false), Untyped { pos }); rule_cons = Expr.box (ELit LEmptyError, Untyped { pos }); rule_parameter = - (match have_parameter with - | Some typs -> Some (List.map (fun typ -> Var.make "dummy", typ) typs) - | None -> None); + Option.map + (List.map (fun (lbl, typ) -> Var.make (Marked.unmark lbl), typ)) + parameters; rule_exception = BaseCase; rule_id = RuleName.fresh ("empty", pos); rule_label = Unlabeled; } -let always_false_rule (pos : Pos.t) (have_parameter : typ list option) : rule = +let always_false_rule + (pos : Pos.t) + (parameters : (Uid.MarkedString.info * typ) list option) : rule = { rule_just = Expr.box (ELit (LBool true), Untyped { pos }); rule_cons = Expr.box (ELit (LBool false), Untyped { pos }); rule_parameter = - (match have_parameter with - | Some typs -> Some (List.map (fun typ -> Var.make "dummy", typ) typs) - | None -> None); + Option.map + (List.map (fun (lbl, typ) -> Var.make (Marked.unmark lbl), typ)) + parameters; rule_exception = BaseCase; rule_id = RuleName.fresh ("always_false", pos); rule_label = Unlabeled; @@ -181,6 +185,7 @@ type meta_assertion = type scope_def = { scope_def_rules : rule RuleName.Map.t; scope_def_typ : typ; + scope_def_parameters : (Uid.MarkedString.info * typ) list option; scope_def_is_condition : bool; scope_def_io : io; } diff --git a/compiler/desugared/ast.mli b/compiler/desugared/ast.mli index 48b33f6c..1aee92dd 100644 --- a/compiler/desugared/ast.mli +++ b/compiler/desugared/ast.mli @@ -67,8 +67,10 @@ type rule = { module Rule : Set.OrderedType with type t = rule -val empty_rule : Pos.t -> typ list option -> rule -val always_false_rule : Pos.t -> typ list option -> rule +val empty_rule : Pos.t -> (Uid.MarkedString.info * typ) list option -> rule + +val always_false_rule : + Pos.t -> (Uid.MarkedString.info * typ) list option -> rule type assertion = expr boxed type variation_typ = Increasing | Decreasing @@ -102,6 +104,7 @@ type io = { type scope_def = { scope_def_rules : rule RuleName.Map.t; scope_def_typ : typ; + scope_def_parameters : (Uid.MarkedString.info * Shared_ast.typ) list option; scope_def_is_condition : bool; scope_def_io : io; } diff --git a/compiler/desugared/from_surface.ml b/compiler/desugared/from_surface.ml index 466ed5a3..6ddd0aab 100644 --- a/compiler/desugared/from_surface.ml +++ b/compiler/desugared/from_surface.ml @@ -1240,6 +1240,8 @@ let init_scope_defs Ast.scope_def_rules = RuleName.Map.empty; Ast.scope_def_typ = v_sig.var_sig_typ; Ast.scope_def_is_condition = v_sig.var_sig_is_condition; + Ast.scope_def_parameters = + (match v_sig.var_sig_parameters with [] -> None | ps -> Some ps); Ast.scope_def_io = attribute_to_io v_sig.var_sig_io; } scope_def_map @@ -1253,6 +1255,10 @@ let init_scope_defs Ast.scope_def_rules = RuleName.Map.empty; Ast.scope_def_typ = v_sig.var_sig_typ; Ast.scope_def_is_condition = v_sig.var_sig_is_condition; + Ast.scope_def_parameters = + (match v_sig.var_sig_parameters with + | [] -> None + | ps -> Some ps); Ast.scope_def_io = (* The first state should have the input I/O of the original variable, and the last state should have the output I/O @@ -1296,6 +1302,10 @@ let init_scope_defs Ast.scope_def_rules = RuleName.Map.empty; Ast.scope_def_typ = v_sig.var_sig_typ; Ast.scope_def_is_condition = v_sig.var_sig_is_condition; + Ast.scope_def_parameters = + (match v_sig.var_sig_parameters with + | [] -> None + | ps -> Some ps); Ast.scope_def_io = attribute_to_io v_sig.var_sig_io; } scope_def_map) diff --git a/compiler/desugared/name_resolution.ml b/compiler/desugared/name_resolution.ml index d3cf1855..31529e80 100644 --- a/compiler/desugared/name_resolution.ml +++ b/compiler/desugared/name_resolution.ml @@ -55,6 +55,7 @@ type enum_context = typ EnumConstructor.Map.t type var_sig = { var_sig_typ : typ; var_sig_is_condition : bool; + var_sig_parameters : (Uid.MarkedString.info * Shared_ast.typ) list; var_sig_io : Surface.Ast.scope_decl_context_io; var_sig_states_idmap : StateName.t IdentName.Map.t; var_sig_states_list : StateName.t list; @@ -360,6 +361,11 @@ let process_data_decl state_uid :: states_list )) decl.scope_decl_context_item_states (IdentName.Map.empty, []) in + let var_sig_parameters = + List.map + (fun (lbl, typ) -> lbl, process_type ctxt typ) + decl.scope_decl_context_item_parameters + in { ctxt with scopes = ScopeName.Map.add scope scope_ctxt ctxt.scopes; @@ -368,6 +374,7 @@ let process_data_decl { var_sig_typ = data_typ; var_sig_is_condition = is_cond; + var_sig_parameters; var_sig_io = decl.scope_decl_context_item_attribute; var_sig_states_idmap = states_idmap; var_sig_states_list = states_list; diff --git a/compiler/desugared/name_resolution.mli b/compiler/desugared/name_resolution.mli index 736a0e75..b89f89db 100644 --- a/compiler/desugared/name_resolution.mli +++ b/compiler/desugared/name_resolution.mli @@ -55,6 +55,7 @@ type enum_context = typ EnumConstructor.Map.t type var_sig = { var_sig_typ : typ; var_sig_is_condition : bool; + var_sig_parameters : (Uid.MarkedString.info * Shared_ast.typ) list; var_sig_io : Surface.Ast.scope_decl_context_io; var_sig_states_idmap : StateName.t IdentName.Map.t; var_sig_states_list : StateName.t list; diff --git a/compiler/scopelang/from_desugared.ml b/compiler/scopelang/from_desugared.ml index dffb6b66..2ab3f62e 100644 --- a/compiler/scopelang/from_desugared.ml +++ b/compiler/scopelang/from_desugared.ml @@ -18,6 +18,7 @@ open Catala_utils open Shared_ast +module D = Desugared.Ast (** {1 Expression translation}*) @@ -212,7 +213,7 @@ let rec rule_tree_to_expr ~(is_reentrant_var : bool) (ctx : ctx) (def_pos : Pos.t) - (is_func : Desugared.Ast.expr Var.t list option) + (params : Desugared.Ast.expr Var.t list option) (tree : rule_tree) : untyped Ast.expr boxed = let emark = Untyped { pos = def_pos } in let exceptions, base_rules = @@ -224,7 +225,7 @@ let rec rule_tree_to_expr let substitute_parameter (e : Desugared.Ast.expr boxed) (rule : Desugared.Ast.rule) : Desugared.Ast.expr boxed = - match is_func, rule.Desugared.Ast.rule_parameter with + match params, rule.Desugared.Ast.rule_parameter with | Some new_params, Some old_params_with_types -> let old_params, _ = List.split old_params_with_types in let old_params = Array.of_list old_params in @@ -240,7 +241,7 @@ let rec rule_tree_to_expr (* should not happen *) in let ctx = - match is_func with + match params with | None -> ctx | Some new_params -> ListLabels.fold_left new_params ~init:ctx ~f:(fun ctx new_param -> @@ -296,7 +297,7 @@ let rec rule_tree_to_expr in let exceptions = List.map - (rule_tree_to_expr ~toplevel:false ~is_reentrant_var ctx def_pos is_func) + (rule_tree_to_expr ~toplevel:false ~is_reentrant_var ctx def_pos params) exceptions in let default = @@ -304,7 +305,7 @@ let rec rule_tree_to_expr (Expr.elit (LBool true) emark) default_containing_base_cases emark in - match is_func, (List.hd base_rules).Desugared.Ast.rule_parameter with + match params, (List.hd base_rules).Desugared.Ast.rule_parameter with | None, None -> default | Some new_params, Some ls -> let _, tys = List.split ls in @@ -334,135 +335,123 @@ let translate_def (ctx : ctx) (def_info : Desugared.Ast.ScopeDef.t) (def : Desugared.Ast.rule RuleName.Map.t) + (params : (Uid.MarkedString.info * typ) list option) (typ : typ) (io : Desugared.Ast.io) ~(is_cond : bool) ~(is_subscope_var : bool) : untyped Ast.expr boxed = (* Here, we have to transform this list of rules into a default tree. *) - let is_def_func = - match Marked.unmark typ with TArrow (_, _) -> true | _ -> false + let check_params pvars = + match params, pvars with + | None, None -> true + | None, Some _ | Some _, None -> false + | Some pdefs, Some pvars -> ( + try + List.for_all2 + (fun (lbl, ty1) (var, ty2) -> + String.equal (Marked.unmark lbl) (Bindlib.name_of var) + && Type.equal ty1 ty2) + pdefs pvars + with Invalid_argument _ -> false) in - let is_rule_func _ (r : Desugared.Ast.rule) : bool = - Option.is_some r.Desugared.Ast.rule_parameter + let wrong_params = + RuleName.Map.bindings + (RuleName.Map.filter + (fun _ r -> not (check_params r.D.rule_parameter)) + def) in - let all_rules_func = RuleName.Map.for_all is_rule_func def in - let all_rules_not_func = - RuleName.Map.for_all (fun n r -> not (is_rule_func n r)) def - in - let is_def_func_param_typ : typ list option = - if is_def_func && all_rules_func then - match Marked.unmark typ with - | TArrow (t_param, _) -> Some t_param - | _ -> - Errors.raise_spanned_error (Marked.get_mark typ) - "The definitions of %a are function but it doesn't have a function \ - type" - Desugared.Ast.ScopeDef.format_t def_info - else if (not is_def_func) && all_rules_not_func then None - else - let spans = - List.map - (fun (_, r) -> - ( Some "This definition is a function:", - Expr.pos r.Desugared.Ast.rule_cons )) - (RuleName.Map.bindings (RuleName.Map.filter is_rule_func def)) - @ List.map - (fun (_, r) -> - ( Some "This definition is not a function:", - Expr.pos r.Desugared.Ast.rule_cons )) - (RuleName.Map.bindings - (RuleName.Map.filter (fun n r -> not (is_rule_func n r)) def)) - in - Errors.raise_multispanned_error spans - "some definitions of the same variable are functions while others \ - aren't" - in - let top_list = def_map_to_tree def_info def in - let is_input = - match Marked.unmark io.Desugared.Ast.io_input with - | OnlyInput -> true - | _ -> false - in - let is_reentrant = - match Marked.unmark io.Desugared.Ast.io_input with - | Reentrant -> true - | _ -> false - in - let top_value : Desugared.Ast.rule option = - if is_cond && ((not is_subscope_var) || (is_subscope_var && is_input)) then - (* We add the bottom [false] value for conditions, only for the scope - where the condition is declared. Except when the variable is an input, - where we want the [false] to be added at each caller parent scope. *) - Some - (Desugared.Ast.always_false_rule - (Desugared.Ast.ScopeDef.get_position def_info) - is_def_func_param_typ) - else None - in - if - RuleName.Map.cardinal def = 0 - && is_subscope_var - (* Here we have a special case for the empty definitions. Indeed, we could - use the code for the regular case below that would create a convoluted - default always returning empty error, and this would be correct. But it - gets more complicated with functions. Indeed, if we create an empty - definition for a subscope argument whose type is a function, we get - something like [fun () -> (fun real_param -> < ... >)] that is passed as - an argument to the subscope. The sub-scope de-thunks but the de-thunking - does not return empty error, signalling there is not reentrant variable, - because functions are values! So the subscope does not see that there is - not reentrant variable and does not pick its internal definition instead. - See [test/test_scope/subscope_function_arg_not_defined.catala_en] for a - test case exercising that subtlety. - - To avoid this complication we special case here and put an empty error - for all subscope variables that are not defined. It covers the subtlety - with functions described above but also conditions with the false default - value. *) - && not (is_cond && is_input) - (* However, this special case suffers from an exception: when a condition is - defined as an OnlyInput to a subscope, since the [false] default value - will not be provided by the calee scope, it has to be placed in the - caller. *) - then - let m = Untyped { pos = Desugared.Ast.ScopeDef.get_position def_info } in - let empty_error = Expr.elit LEmptyError m in - match is_def_func_param_typ with - | Some tys -> - Expr.make_abs - (Array.init (List.length tys) (fun _ -> Var.make "_")) - empty_error tys (Expr.mark_pos m) - | _ -> empty_error + if wrong_params <> [] then + Errors.raise_multispanned_error + ((Some "Declared here", Marked.get_mark typ) + :: List.map + (fun (r, _) -> None, Marked.get_mark (RuleName.get_info r)) + wrong_params) + "The arguments of these definitions don't match the declaration." else - rule_tree_to_expr ~toplevel:true ~is_reentrant_var:is_reentrant ctx - (Desugared.Ast.ScopeDef.get_position def_info) - (Option.map - (fun l -> - ListLabels.mapi l ~f:(fun i _ -> - Var.make ("param" ^ string_of_int i))) - is_def_func_param_typ) - (match top_list, top_value with - | [], None -> - (* In this case, there are no rules to define the expression and no - default value so we put an empty rule. *) - Leaf - [Desugared.Ast.empty_rule (Marked.get_mark typ) is_def_func_param_typ] - | [], Some top_value -> - (* In this case, there are no rules to define the expression but a - default value so we put it. *) - Leaf [top_value] - | _, Some top_value -> - (* When there are rules + a default value, we put the rules as - exceptions to the default value *) - Node (top_list, [top_value]) - | [top_tree], None -> top_tree - | _, None -> - Node - ( top_list, - [ - Desugared.Ast.empty_rule (Marked.get_mark typ) - is_def_func_param_typ; - ] )) + let top_list = def_map_to_tree def_info def in + let is_input = + match Marked.unmark io.Desugared.Ast.io_input with + | OnlyInput -> true + | _ -> false + in + let is_reentrant = + match Marked.unmark io.Desugared.Ast.io_input with + | Reentrant -> true + | _ -> false + in + let top_value : Desugared.Ast.rule option = + if is_cond && ((not is_subscope_var) || (is_subscope_var && is_input)) + then + (* We add the bottom [false] value for conditions, only for the scope + where the condition is declared. Except when the variable is an + input, where we want the [false] to be added at each caller parent + scope. *) + Some + (Desugared.Ast.always_false_rule + (Desugared.Ast.ScopeDef.get_position def_info) + params) + else None + in + if + RuleName.Map.cardinal def = 0 + && is_subscope_var + (* Here we have a special case for the empty definitions. Indeed, we could + use the code for the regular case below that would create a convoluted + default always returning empty error, and this would be correct. But it + gets more complicated with functions. Indeed, if we create an empty + definition for a subscope argument whose type is a function, we get + something like [fun () -> (fun real_param -> < ... >)] that is passed + as an argument to the subscope. The sub-scope de-thunks but the + de-thunking does not return empty error, signalling there is not + reentrant variable, because functions are values! So the subscope does + not see that there is not reentrant variable and does not pick its + internal definition instead. See + [test/test_scope/subscope_function_arg_not_defined.catala_en] for a + test case exercising that subtlety. + + To avoid this complication we special case here and put an empty error + for all subscope variables that are not defined. It covers the subtlety + with functions described above but also conditions with the false + default value. *) + && not (is_cond && is_input) + (* However, this special case suffers from an exception: when a condition + is defined as an OnlyInput to a subscope, since the [false] default + value will not be provided by the calee scope, it has to be placed in + the caller. *) + then + let m = Untyped { pos = Desugared.Ast.ScopeDef.get_position def_info } in + let empty_error = Expr.elit LEmptyError m in + match params with + | Some ps -> + let labels, tys = List.split ps in + Expr.make_abs + (Array.of_list + (List.map (fun lbl -> Var.make (Marked.unmark lbl)) labels)) + empty_error tys (Expr.mark_pos m) + | _ -> empty_error + else + rule_tree_to_expr ~toplevel:true ~is_reentrant_var:is_reentrant ctx + (Desugared.Ast.ScopeDef.get_position def_info) + (Option.map + (List.map (fun (lbl, _) -> Var.make (Marked.unmark lbl))) + params) + (match top_list, top_value with + | [], None -> + (* In this case, there are no rules to define the expression and no + default value so we put an empty rule. *) + Leaf [Desugared.Ast.empty_rule (Marked.get_mark typ) params] + | [], Some top_value -> + (* In this case, there are no rules to define the expression but a + default value so we put it. *) + Leaf [top_value] + | _, Some top_value -> + (* When there are rules + a default value, we put the rules as + exceptions to the default value *) + Node (top_list, [top_value]) + | [top_tree], None -> top_tree + | _, None -> + Node + (top_list, [Desugared.Ast.empty_rule (Marked.get_mark typ) params])) let translate_rule ctx (scope : Desugared.Ast.scope) = function | Desugared.Dependency.Vertex.Var (var, state) -> ( @@ -471,9 +460,10 @@ let translate_rule ctx (scope : Desugared.Ast.scope) = function (Desugared.Ast.ScopeDef.Var (var, state)) scope.scope_defs in - let var_def = scope_def.scope_def_rules in - let var_typ = scope_def.scope_def_typ in - let is_cond = scope_def.scope_def_is_condition in + let var_def = scope_def.D.scope_def_rules in + let var_params = scope_def.D.scope_def_parameters in + let var_typ = scope_def.D.scope_def_typ in + let is_cond = scope_def.D.scope_def_is_condition in match Marked.unmark scope_def.Desugared.Ast.scope_def_io.io_input with | OnlyInput when not (RuleName.Map.is_empty var_def) -> (* If the variable is tagged as input, then it shall not be redefined. *) @@ -492,8 +482,8 @@ let translate_rule ctx (scope : Desugared.Ast.scope) = function let expr_def = translate_def ctx (Desugared.Ast.ScopeDef.Var (var, state)) - var_def var_typ scope_def.Desugared.Ast.scope_def_io ~is_cond - ~is_subscope_var:false + var_def var_params var_typ scope_def.Desugared.Ast.scope_def_io + ~is_cond ~is_subscope_var:false in let scope_var = match ScopeVar.Map.find var ctx.scope_var_mapping, state with @@ -577,8 +567,8 @@ let translate_rule ctx (scope : Desugared.Ast.scope) = function (* Now that all is good, we can proceed with translating this redefinition to a proper Scopelang term. *) let expr_def = - translate_def ctx def_key def def_typ - scope_def.Desugared.Ast.scope_def_io ~is_cond + translate_def ctx def_key def scope_def.D.scope_def_parameters + def_typ scope_def.Desugared.Ast.scope_def_io ~is_cond ~is_subscope_var:true in let subscop_real_name = diff --git a/compiler/surface/ast.ml b/compiler/surface/ast.ml index 46fb6012..98383217 100644 --- a/compiler/surface/ast.ml +++ b/compiler/surface/ast.ml @@ -683,6 +683,7 @@ type scope_decl_context_scope = { type scope_decl_context_data = { scope_decl_context_item_name : lident Marked.pos; scope_decl_context_item_typ : typ; + scope_decl_context_item_parameters : (lident Marked.pos * typ) list; scope_decl_context_item_attribute : scope_decl_context_io; scope_decl_context_item_states : lident Marked.pos list; } diff --git a/compiler/surface/parser.mly b/compiler/surface/parser.mly index 70cd860b..75105b01 100644 --- a/compiler/surface/parser.mly +++ b/compiler/surface/parser.mly @@ -539,6 +539,8 @@ let scope_decl_item := ContextData { scope_decl_context_item_name = i; scope_decl_context_item_attribute = attr; + scope_decl_context_item_parameters = + List.map (fun (lbl, (base_t, m)) -> lbl, (Base base_t, m)) args_typ; scope_decl_context_item_typ = type_from_args args_typ t; scope_decl_context_item_states = states; } @@ -561,6 +563,8 @@ let scope_decl_item := ContextData { scope_decl_context_item_name = i; scope_decl_context_item_attribute = attr; + scope_decl_context_item_parameters = + List.map (fun (lbl, (base_t, m)) -> lbl, (Base base_t, m)) args; scope_decl_context_item_typ = Ast.type_from_args args (Condition, pos_condition); scope_decl_context_item_states = states; diff --git a/tests/test_func/bad/param_inconsistency.catala_en b/tests/test_func/bad/param_inconsistency.catala_en index cfa976d6..effdb689 100644 --- a/tests/test_func/bad/param_inconsistency.catala_en +++ b/tests/test_func/bad/param_inconsistency.catala_en @@ -14,15 +14,13 @@ scope S: ```catala-test-inline $ catala typecheck -[ERROR] Inconsistent function definition for f1, the arguments differ +[ERROR] The arguments of these definitions don't match the declaration. -First definition here -┌─⯈ tests/test_func/bad/param_inconsistency.catala_en:8.2-9.41: +Declared here +┌─⯈ tests/test_func/bad/param_inconsistency.catala_en:4.22-29: └─┐ -8 │ definition f1 of x under condition cond - │ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ -9 │ consequence equals decimal of (x * 2) - │ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +4 │ internal f1 content decimal depends on x content integer + │ ‾‾‾‾‾‾‾ ┌─⯈ tests/test_func/bad/param_inconsistency.catala_en:10.2-11.28: diff --git a/tests/test_func/bad/param_inconsistency2.catala_en b/tests/test_func/bad/param_inconsistency2.catala_en index dce187bb..01b9438b 100644 --- a/tests/test_func/bad/param_inconsistency2.catala_en +++ b/tests/test_func/bad/param_inconsistency2.catala_en @@ -13,13 +13,13 @@ scope S: ```catala-test-inline $ catala typecheck -[ERROR] Inconsistent function definition for f1, the arguments differ +[ERROR] The arguments of these definitions don't match the declaration. -First definition here -┌─⯈ tests/test_func/bad/param_inconsistency2.catala_en:8.2-46: +Declared here +┌─⯈ tests/test_func/bad/param_inconsistency2.catala_en:4.22-29: └─┐ -8 │ definition f1 of x equals decimal of (x * 2) - │ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +4 │ internal f1 content decimal depends on x content integer + │ ‾‾‾‾‾‾‾ ┌─⯈ tests/test_func/bad/param_inconsistency2.catala_en:9.2-10.28: diff --git a/tests/test_func/bad/param_inconsistency3.catala_en b/tests/test_func/bad/param_inconsistency3.catala_en index a14b455b..1188b89e 100644 --- a/tests/test_func/bad/param_inconsistency3.catala_en +++ b/tests/test_func/bad/param_inconsistency3.catala_en @@ -13,13 +13,13 @@ scope S: ```catala-test-inline $ catala typecheck -[ERROR] Inconsistent function definition for f1, the arguments differ +[ERROR] The arguments of these definitions don't match the declaration. -First definition here -┌─⯈ tests/test_func/bad/param_inconsistency3.catala_en:8.2-46: +Declared here +┌─⯈ tests/test_func/bad/param_inconsistency3.catala_en:4.22-29: └─┐ -8 │ definition f1 of x equals decimal of (x * 2) - │ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +4 │ internal f1 content decimal depends on x content integer + │ ‾‾‾‾‾‾‾ ┌─⯈ tests/test_func/bad/param_inconsistency3.catala_en:9.2-10.28: diff --git a/tests/test_func/good/context_func.catala_en b/tests/test_func/good/context_func.catala_en index e6cb6d76..00c085e5 100644 --- a/tests/test_func/good/context_func.catala_en +++ b/tests/test_func/good/context_func.catala_en @@ -19,7 +19,7 @@ scope B: $ catala Scopelang -s B let scope B (b: bool|input) = let a.f : integer → integer = - λ (param0: integer) → ⟨b && param0 >! 0 ⊢ param0 -! 1⟩; + λ (x: integer) → ⟨b && x >! 0 ⊢ x -! 1⟩; call A[a] ``` @@ -29,8 +29,8 @@ let A = λ (A_in: A_in {"f_in": integer → integer}) → let f : integer → integer = A_in."f_in" in let f1 : integer → integer = - λ (param0: integer) → error_empty - ⟨f param0 | true ⊢ ⟨true ⊢ param0 +! 1⟩⟩ in + λ (x: integer) → error_empty + ⟨f x | true ⊢ ⟨true ⊢ x +! 1⟩⟩ in A { } ``` @@ -40,7 +40,7 @@ let B = λ (B_in: B_in {"b_in": bool}) → let b : bool = B_in."b_in" in let a.f : integer → integer = - λ (param0: integer) → ⟨b && param0 >! 0 ⊢ param0 -! 1⟩ in + λ (x: integer) → ⟨b && x >! 0 ⊢ x -! 1⟩ in let result : A {} = A (A_in { "f_in"= a.f }) in B { } ``` diff --git a/tests/test_scope/good/scope_call3.catala_en b/tests/test_scope/good/scope_call3.catala_en index e21a6996..24ab279b 100644 --- a/tests/test_scope/good/scope_call3.catala_en +++ b/tests/test_scope/good/scope_call3.catala_en @@ -43,7 +43,7 @@ $ catala Interpret -t -s HousingComputation 7 │ definition f of x equals (output of RentComputation).f of x │ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ -[LOG] ≔ RentComputation.direct.output: RentComputation { "f"= λ (param0: integer) → RentComputation { "f"= λ (param01: integer) → error_empty ⟨true ⊢ λ (param02: integer) → error_empty ⟨true ⊢ param02 +! 1⟩ param01 +! 1⟩ }."f" param0 } +[LOG] ≔ RentComputation.direct.output: RentComputation { "f"= λ (param0: integer) → RentComputation { "f"= λ (x: integer) → error_empty ⟨true ⊢ λ (x1: integer) → error_empty ⟨true ⊢ x1 +! 1⟩ x +! 1⟩ }."f" param0 } [LOG] ← RentComputation.direct [LOG] → RentComputation.f [LOG] ≔ RentComputation.f.input0: 1 @@ -70,20 +70,20 @@ $ catala Interpret -t -s HousingComputation [LOG] ≔ HousingComputation.result: 3 [RESULT] Computation successful! Results: [RESULT] f = - λ (param0: integer) → error_empty + λ (x: integer) → error_empty ⟨true ⊢ let result : RentComputation {"f": integer → integer} = λ (RentComputation_in: RentComputation_in {}) → let g : integer → integer = error_empty - (λ (param01: integer) → error_empty - ⟨true ⊢ param01 +! 1⟩) in + (λ (x1: integer) → error_empty ⟨true ⊢ x1 +! 1⟩) + in let f : integer → integer = error_empty - (λ (param01: integer) → error_empty - ⟨true ⊢ g param01 +! 1⟩) in + (λ (x1: integer) → error_empty + ⟨true ⊢ g x1 +! 1⟩) in RentComputation { "f"= f } RentComputation_in { } in let result1 : RentComputation {"f": integer → integer} = RentComputation { "f"= - λ (param01: integer) → result."f" param01 } in - if true then result1 else ∅ ."f" param0⟩ + λ (param0: integer) → result."f" param0 } in + if true then result1 else ∅ ."f" x⟩ [RESULT] result = 3 ```