diff --git a/compiler/shared_ast/optimizations.ml b/compiler/shared_ast/optimizations.ml index 80d9fece..a3c57756 100644 --- a/compiler/shared_ast/optimizations.ml +++ b/compiler/shared_ast/optimizations.ml @@ -215,12 +215,15 @@ let rec optimize_expr : when StructName.equal name name1 -> Mark.remove (StructField.Map.find field fields) | EErrorOnEmpty - (EDefault { excepts = []; just = ELit (LBool true), _; cons }, _) - when false - (* FIXME: this optimisation is correct and useful, but currently - breaks expectations of the without-exceptions backend *) -> + ( EDefault + { + excepts = []; + just = ELit (LBool true), _; + cons = EPureDefault e, _; + }, + _ ) -> (* No exceptions, always true *) - Mark.remove cons + Mark.remove e | EErrorOnEmpty ( EDefault { diff --git a/tests/test_func/good/closure_conversion.catala_en b/tests/test_func/good/closure_conversion.catala_en index d60865a6..92b789fd 100644 --- a/tests/test_func/good/closure_conversion.catala_en +++ b/tests/test_func/good/closure_conversion.catala_en @@ -46,29 +46,13 @@ type S = { z: integer; } let topval closure_f : (closure_env, integer) → integer = λ (env: closure_env) (y: integer) → - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → ESome if (from_closure_env env).0 then y else - y)) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg + if (from_closure_env env).0 then y else - y let scope S (S_in: S_in {x_in: bool}): S {z: integer} = let get x : bool = S_in.x_in in let set f : ((closure_env, integer) → integer * closure_env) = (closure_f, to_closure_env (x)) in - let set z : integer = - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → ESome (f.0 f.1 -1))) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg - in + let set z : integer = f.0 f.1 -1 in return { S z = z; } ``` diff --git a/tests/test_func/good/closure_conversion_reduce.catala_en b/tests/test_func/good/closure_conversion_reduce.catala_en index 306bf4ce..3a4c9897 100644 --- a/tests/test_func/good/closure_conversion_reduce.catala_en +++ b/tests/test_func/good/closure_conversion_reduce.catala_en @@ -41,21 +41,12 @@ $ catala Lcalc -s S --avoid-exceptions -O --closure-conversion let scope S (S_in: S_in {x_in: list of integer}): S {y: integer} = let get x : list of integer = S_in.x_in in let set y : integer = - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → - ESome - (reduce - (λ (potential_max_1: integer) (potential_max_2: integer) → - if potential_max_1 < potential_max_2 then potential_max_1 - else potential_max_2) - -1 - x))) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg + reduce + (λ (potential_max_1: integer) (potential_max_2: integer) → + if potential_max_1 < potential_max_2 then potential_max_1 + else potential_max_2) + -1 + x in return { S y = y; } ``` diff --git a/tests/test_func/good/closure_return.catala_en b/tests/test_func/good/closure_return.catala_en index bc5e1593..7e4fabf4 100644 --- a/tests/test_func/good/closure_return.catala_en +++ b/tests/test_func/good/closure_return.catala_en @@ -44,14 +44,7 @@ type S = { f: ((closure_env, integer) → integer * closure_env); } let topval closure_f : (closure_env, integer) → integer = λ (env: closure_env) (y: integer) → - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → ESome if (from_closure_env env).0 then y else - y)) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg + if (from_closure_env env).0 then y else - y let scope S (S_in: S_in {x_in: bool}) : S {f: ((closure_env, integer) → integer * closure_env)} diff --git a/tests/test_func/good/closure_through_scope.catala_en b/tests/test_func/good/closure_through_scope.catala_en index 8c1729df..a23d8bb8 100644 --- a/tests/test_func/good/closure_through_scope.catala_en +++ b/tests/test_func/good/closure_through_scope.catala_en @@ -45,13 +45,7 @@ Invariant Dcalc__Invariants.invariant_default_no_arrow ```catala-test-inline $ catala Lcalc -s T --avoid-exceptions -O --closure-conversion let scope T (T_in: T_in): T {y: integer} = - let sub_set s.x : bool = - match - (handle_default_opt [] (λ (_: unit) → true) (λ (_: unit) → ESome false)) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg - in + let sub_set s.x : bool = false in let call result : S {f: ((closure_env, integer) → integer * closure_env)} = S { S_in x_in = s.x; } @@ -59,16 +53,7 @@ let scope T (T_in: T_in): T {y: integer} = let sub_get s.f : ((closure_env, integer) → integer * closure_env) = result.f in - let set y : integer = - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → ESome (s.f.0 s.f.1 2))) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg - in + let set y : integer = s.f.0 s.f.1 2 in return { T y = y; } ``` diff --git a/tests/test_func/good/scope_call_func_struct_closure.catala_en b/tests/test_func/good/scope_call_func_struct_closure.catala_en index bb838f0a..e2b8f1ec 100644 --- a/tests/test_func/good/scope_call_func_struct_closure.catala_en +++ b/tests/test_func/good/scope_call_func_struct_closure.catala_en @@ -94,14 +94,7 @@ type Foo = { z: integer; } let topval closure_y : (closure_env, integer) → integer = λ (env: closure_env) (z: integer) → - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → ESome ((from_closure_env env).0 + z))) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg + (from_closure_env env).0 + z let scope SubFoo1 (SubFoo1_in: SubFoo1_in {x_in: integer}) : SubFoo1 { @@ -117,14 +110,7 @@ let scope SubFoo1 let topval closure_y : (closure_env, integer) → integer = λ (env: closure_env) (z: integer) → let env1 : (integer * integer) = from_closure_env env in - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → ESome (env1.1 + env1.0 + z))) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg + ((env1.1 + env1.0 + z)) let scope SubFoo2 (SubFoo2_in: SubFoo2_in {x1_in: integer; x2_in: integer}) : SubFoo2 { @@ -160,16 +146,7 @@ let scope Foo (handle_default_opt [b.0 b.1 ()] (λ (_: unit) → true) - (λ (_: unit) → - ESome - (match - (handle_default_opt - [] - (λ (_1: unit) → true) - (λ (_1: unit) → ESome true)) - with - | ENone _1 → raise NoValueProvided - | ESome arg → arg))) + (λ (_: unit) → ESome true)) with | ENone _ → raise NoValueProvided | ESome arg → arg @@ -179,51 +156,26 @@ let scope Foo r: ((closure_env, integer) → integer * closure_env); q: integer } = - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → - ESome - if b then - let f : SubFoo1 = - let result : SubFoo1 = SubFoo1 { SubFoo1_in x_in = 10; } in - { SubFoo1 - x = result.x; - y = (closure_r, to_closure_env (result)); - } - in - { Result r = f.y; q = f.x; } - else - let f : SubFoo2 = - let result : SubFoo2 = - SubFoo2 { SubFoo2_in x1_in = 10; x2_in = 10; } - in - { SubFoo2 - x1 = result.x1; - y = (closure_r, to_closure_env (result)); - } - in - { Result r = f.y; q = f.x1; })) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg + if b then + let f : SubFoo1 = + let result : SubFoo1 = SubFoo1 { SubFoo1_in x_in = 10; } in + { SubFoo1 x = result.x; y = (closure_r, to_closure_env (result)); } + in + { Result r = f.y; q = f.x; } + else + let f : SubFoo2 = + let result : SubFoo2 = + SubFoo2 { SubFoo2_in x1_in = 10; x2_in = 10; } + in + { SubFoo2 x1 = result.x1; y = (closure_r, to_closure_env (result)); } + in + { Result r = f.y; q = f.x1; } in let set z : integer = - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → - ESome - (let code_and_env : - ((closure_env, integer) → integer * closure_env) = - r.r - in - code_and_env.0 code_and_env.1 1))) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg + let code_and_env : ((closure_env, integer) → integer * closure_env) = + r.r + in + code_and_env.0 code_and_env.1 1 in return { Foo z = z; } diff --git a/tests/test_scope/good/191_fix_record_name_confusion.catala_en b/tests/test_scope/good/191_fix_record_name_confusion.catala_en index 0341b3e0..bcc736a9 100644 --- a/tests/test_scope/good/191_fix_record_name_confusion.catala_en +++ b/tests/test_scope/good/191_fix_record_name_confusion.catala_en @@ -69,33 +69,13 @@ end let scope_a (scope_a_in: ScopeA_in.t) : ScopeA.t = - let a_: bool = - try - (handle_default - {filename = ""; start_line=0; start_column=1; - end_line=0; end_column=1; law_headings=[]} ([||]) - (fun (_: unit) -> true) (fun (_: unit) -> true)) - with - EmptyError -> (raise (NoValueProvided - {filename = "tests/test_scope/good/191_fix_record_name_confusion.catala_en"; - start_line=5; start_column=10; end_line=5; end_column=11; - law_headings=["Article"]})) in + let a_: bool = true in {ScopeA.a = a_} let scope_b (scope_b_in: ScopeB_in.t) : ScopeB.t = let result_: ScopeA.t = scope_a (()) in let scope_a_dot_a_: bool = result_.ScopeA.a in - let a_: bool = - try - (handle_default - {filename = ""; start_line=0; start_column=1; - end_line=0; end_column=1; law_headings=[]} ([||]) - (fun (_: unit) -> true) (fun (_: unit) -> scope_a_dot_a_)) - with - EmptyError -> (raise (NoValueProvided - {filename = "tests/test_scope/good/191_fix_record_name_confusion.catala_en"; - start_line=8; start_column=10; end_line=8; end_column=11; - law_headings=["Article"]})) in + let a_: bool = scope_a_dot_a_ in {ScopeB.a = a_} Generating entry points for scopes: ScopeA ScopeB diff --git a/tests/test_scope/good/scope_call3.catala_en b/tests/test_scope/good/scope_call3.catala_en index 8187055f..d51f9fa2 100644 --- a/tests/test_scope/good/scope_call3.catala_en +++ b/tests/test_scope/good/scope_call3.catala_en @@ -57,7 +57,7 @@ $ catala Interpret -t -s HousingComputation --debug [DEBUG] Translating to default calculus... [DEBUG] Typechecking again... [DEBUG] Starting interpretation... -[LOG] ≔ HousingComputation.f: λ (x_90: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨(let result_91 : RentComputation = (#{→ RentComputation.direct} (λ (RentComputation_in_92: RentComputation_in) → let g_93 : integer → integer = #{≔ RentComputation.g} (λ (x1_94: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨x1_94 +! 1⟩⟩ | false ⊢ ∅ ⟩) in let f_95 : integer → integer = #{≔ RentComputation.f} (λ (x1_96: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨#{← RentComputation.g} #{≔ RentComputation.g.output} (#{→ RentComputation.g} g_93) #{≔ RentComputation.g.input0} (x1_96 +! 1)⟩⟩ | false ⊢ ∅ ⟩) in { RentComputation f = f_95; })) #{≔ RentComputation.direct.input} {RentComputation_in} in let result1_97 : RentComputation = { RentComputation f = λ (param0_98: integer) → #{← RentComputation.f} #{≔ RentComputation.f.output} (#{→ RentComputation.f} result_91.f) #{≔ RentComputation.f.input0} param0_98; } in #{← RentComputation.direct} #{≔ RentComputation.direct.output} if #{☛ RentComputation.direct.output} true then result1_97 else result1_97).f x_90⟩⟩ | false ⊢ ∅ ⟩ +[LOG] ≔ HousingComputation.f: λ (x_76: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨(let result_77 : RentComputation = (#{→ RentComputation.direct} (λ (RentComputation_in_78: RentComputation_in) → let g_79 : integer → integer = #{≔ RentComputation.g} (λ (x1_80: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨x1_80 +! 1⟩⟩ | false ⊢ ∅ ⟩) in let f_81 : integer → integer = #{≔ RentComputation.f} (λ (x1_82: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨#{← RentComputation.g} #{≔ RentComputation.g.output} (#{→ RentComputation.g} g_79) #{≔ RentComputation.g.input0} (x1_82 +! 1)⟩⟩ | false ⊢ ∅ ⟩) in { RentComputation f = f_81; })) #{≔ RentComputation.direct.input} {RentComputation_in} in let result1_83 : RentComputation = { RentComputation f = λ (param0_84: integer) → #{← RentComputation.f} #{≔ RentComputation.f.output} (#{→ RentComputation.f} result_77.f) #{≔ RentComputation.f.input0} param0_84; } in #{← RentComputation.direct} #{≔ RentComputation.direct.output} if #{☛ RentComputation.direct.output} true then result1_83 else result1_83).f x_76⟩⟩ | false ⊢ ∅ ⟩ [LOG] ☛ Definition applied: ┌─⯈ tests/test_scope/good/scope_call3.catala_en:8.14-8.20: └─┐ @@ -72,14 +72,14 @@ $ catala Interpret -t -s HousingComputation --debug │ ‾ [LOG] → RentComputation.direct [LOG] ≔ RentComputation.direct.input: {RentComputation_in} -[LOG] ≔ RentComputation.g: λ (x_99: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨x_99 +! 1⟩⟩ | false ⊢ ∅ ⟩ -[LOG] ≔ RentComputation.f: λ (x_100: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨#{← RentComputation.g} #{≔ RentComputation.g.output} (#{→ RentComputation.g} (λ (x1_101: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨x1_101 +! 1⟩⟩ | false ⊢ ∅ ⟩)) #{≔ RentComputation.g.input0} (x_100 +! 1)⟩⟩ | false ⊢ ∅ ⟩ +[LOG] ≔ RentComputation.g: λ (x_85: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨x_85 +! 1⟩⟩ | false ⊢ ∅ ⟩ +[LOG] ≔ RentComputation.f: λ (x_86: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨#{← RentComputation.g} #{≔ RentComputation.g.output} (#{→ RentComputation.g} (λ (x1_87: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨x1_87 +! 1⟩⟩ | false ⊢ ∅ ⟩)) #{≔ RentComputation.g.input0} (x_86 +! 1)⟩⟩ | false ⊢ ∅ ⟩ [LOG] ☛ Definition applied: ┌─⯈ tests/test_scope/good/scope_call3.catala_en:7.29-7.54: └─┐ 7 │ definition f of x equals (output of RentComputation).f of x │ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ -[LOG] ≔ RentComputation.direct.output: { RentComputation f = λ (param0_102: integer) → #{← RentComputation.f} #{≔ RentComputation.f.output} (#{→ RentComputation.f} { RentComputation f = λ (x_103: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨#{← RentComputation.g} #{≔ RentComputation.g.output} (#{→ RentComputation.g} (λ (x1_104: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨x1_104 +! 1⟩⟩ | false ⊢ ∅ ⟩)) #{≔ RentComputation.g.input0} (x_103 +! 1)⟩⟩ | false ⊢ ∅ ⟩; }.f) #{≔ RentComputation.f.input0} param0_102; } +[LOG] ≔ RentComputation.direct.output: { RentComputation f = λ (param0_88: integer) → #{← RentComputation.f} #{≔ RentComputation.f.output} (#{→ RentComputation.f} { RentComputation f = λ (x_89: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨#{← RentComputation.g} #{≔ RentComputation.g.output} (#{→ RentComputation.g} (λ (x1_90: integer) → error_empty ⟨ ⟨#{☛ } true ⊢ ⟨x1_90 +! 1⟩⟩ | false ⊢ ∅ ⟩)) #{≔ RentComputation.g.input0} (x_89 +! 1)⟩⟩ | false ⊢ ∅ ⟩; }.f) #{≔ RentComputation.f.input0} param0_88; } [LOG] ← RentComputation.direct [LOG] → RentComputation.f [LOG] ≔ RentComputation.f.input0: 1 diff --git a/tests/test_scope/good/scope_call4.catala_en b/tests/test_scope/good/scope_call4.catala_en index 3a87e6a7..56b11534 100644 --- a/tests/test_scope/good/scope_call4.catala_en +++ b/tests/test_scope/good/scope_call4.catala_en @@ -102,44 +102,8 @@ $ catala Interpret_Lcalc -s RentComputation --avoid-exceptions --optimize --debu [DEBUG] Starting interpretation... [DEBUG] End of interpretation [RESULT] Computation successful! Results: -[RESULT] -f1 = λ (x: integer) → - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → - ESome - (let x1 : integer = x + 1 in - match - (handle_default_opt - [] - (λ (_1: unit) → true) - (λ (_1: unit) → ESome (x1 + 1))) - with - | ENone _1 → raise NoValueProvided - | ESome arg → arg))) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg -[RESULT] -f2 = λ (x: integer) → - match - (handle_default_opt - [] - (λ (_: unit) → true) - (λ (_: unit) → - ESome - (let x1 : integer = x + 1 in - match - (handle_default_opt - [] - (λ (_1: unit) → true) - (λ (_1: unit) → ESome (x1 + 1))) - with - | ENone _1 → raise NoValueProvided - | ESome arg → arg))) - with - | ENone _ → raise NoValueProvided - | ESome arg → arg +[RESULT] f1 = λ (x: integer) → let x1 : integer = x + 1 in + ((x1 + 1)) +[RESULT] f2 = λ (x: integer) → let x1 : integer = x + 1 in + ((x1 + 1)) ```