mirror of
https://github.com/CatalaLang/catala.git
synced 2024-09-20 00:41:05 +03:00
181 lines
4.7 KiB
Plaintext
181 lines
4.7 KiB
Plaintext
```catala
|
|
declaration structure Result:
|
|
data r content integer depends on z content integer
|
|
data q content integer
|
|
|
|
declaration scope SubFoo1:
|
|
input output x content integer
|
|
output y content integer depends on z content integer
|
|
|
|
declaration scope SubFoo2:
|
|
input output x1 content integer
|
|
input x2 content integer
|
|
output y content integer depends on z content integer
|
|
|
|
|
|
declaration scope Foo:
|
|
context b content boolean
|
|
internal r content Result
|
|
output z content integer
|
|
|
|
scope SubFoo1:
|
|
definition y of z equals x + z
|
|
|
|
scope SubFoo2:
|
|
definition y of z equals x1 + x2 + z
|
|
|
|
|
|
scope Foo:
|
|
definition b equals true
|
|
definition r equals
|
|
if b then
|
|
let f equals output of SubFoo1 with { -- x: 10 } in
|
|
Result { --r: f.y --q: f.x }
|
|
else
|
|
let f equals output of SubFoo2 with { -- x1: 10 -- x2: 10 } in
|
|
Result { --r: f.y --q: f.x1 }
|
|
definition z equals r.r of 1
|
|
```
|
|
|
|
This test case is tricky because it creates a situation where the type of the
|
|
two closures in Foo.r are different even with optimizations enabled.
|
|
|
|
|
|
|
|
```catala-test-inline
|
|
$ catala Typecheck --check-invariants
|
|
┌─[RESULT]─
|
|
│ All invariant checks passed
|
|
└─
|
|
┌─[RESULT]─
|
|
│ Typechecking successful!
|
|
└─
|
|
```
|
|
|
|
```catala-test-inline
|
|
$ catala Lcalc -O --closure-conversion
|
|
type Eoption = | ENone of unit | ESome of any
|
|
|
|
type Result = {
|
|
r: ((closure_env, integer) → integer, closure_env);
|
|
q: integer;
|
|
}
|
|
type SubFoo1_in = { x_in: integer; }
|
|
type SubFoo1 = {
|
|
x: integer;
|
|
y: ((closure_env, integer) → integer, closure_env);
|
|
}
|
|
type SubFoo2_in = { x1_in: integer; x2_in: integer; }
|
|
type SubFoo2 = {
|
|
x1: integer;
|
|
y: ((closure_env, integer) → integer, closure_env);
|
|
}
|
|
type Foo_in = { b_in: ((closure_env, unit) → option bool, closure_env); }
|
|
type Foo = { z: integer; }
|
|
|
|
let topval closure_y1 : (closure_env, integer) → integer =
|
|
λ (env: closure_env) (z: integer) →
|
|
(from_closure_env env).0 + z
|
|
|
|
let scope SubFoo1
|
|
(SubFoo1_in: SubFoo1_in {x_in: integer})
|
|
: SubFoo1 {
|
|
x: integer;
|
|
y: ((closure_env, integer) → integer, closure_env)
|
|
}
|
|
=
|
|
let get x : integer = SubFoo1_in.x_in in
|
|
let set y : ((closure_env, integer) → integer, closure_env) =
|
|
(closure_y1, to_closure_env (x))
|
|
in
|
|
return { SubFoo1 x = x; y = y; }
|
|
|
|
let topval closure_y1 : (closure_env, integer) → integer =
|
|
λ (env: closure_env) (z: integer) →
|
|
let env1 : (integer, integer) = from_closure_env env in
|
|
((env1.1 + env1.0 + z))
|
|
|
|
let scope SubFoo2
|
|
(SubFoo2_in: SubFoo2_in {x1_in: integer; x2_in: integer})
|
|
: SubFoo2 {
|
|
x1: integer;
|
|
y: ((closure_env, integer) → integer, closure_env)
|
|
}
|
|
=
|
|
let get x1 : integer = SubFoo2_in.x1_in in
|
|
let get x2 : integer = SubFoo2_in.x2_in in
|
|
let set y : ((closure_env, integer) → integer, closure_env) =
|
|
(closure_y1, to_closure_env (x2, x1))
|
|
in
|
|
return { SubFoo2 x1 = x1; y = y; }
|
|
|
|
let topval closure_r2 : (closure_env, integer) → integer =
|
|
λ (env: closure_env) (param0: integer) →
|
|
let code_and_env : ((closure_env, integer) → integer, closure_env) =
|
|
(from_closure_env env).0.y
|
|
in
|
|
code_and_env.0 code_and_env.1 param0
|
|
|
|
let topval closure_r1 : (closure_env, integer) → integer =
|
|
λ (env: closure_env) (param0: integer) →
|
|
let code_and_env : ((closure_env, integer) → integer, closure_env) =
|
|
(from_closure_env env).0.y
|
|
in
|
|
code_and_env.0 code_and_env.1 param0
|
|
|
|
let scope Foo
|
|
(Foo_in: Foo_in {b_in: ((closure_env, unit) → option bool, closure_env)})
|
|
: Foo {z: integer}
|
|
=
|
|
let get b : ((closure_env, unit) → option bool, closure_env) =
|
|
Foo_in.b_in
|
|
in
|
|
let set b : bool =
|
|
match
|
|
(match (handle_exceptions [b.0 b.1 ()]) with
|
|
| ENone → ESome true
|
|
| ESome x → ESome x)
|
|
with
|
|
| ENone → error NoValue
|
|
| ESome arg → arg
|
|
in
|
|
let set r :
|
|
Result {
|
|
r: ((closure_env, integer) → integer, closure_env);
|
|
q: integer
|
|
} =
|
|
if b then
|
|
let f : SubFoo1 =
|
|
let result : SubFoo1 = SubFoo1 { SubFoo1_in x_in = 10; } in
|
|
{ SubFoo1 x = result.x; y = (closure_r1, 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_r2, to_closure_env (result));
|
|
}
|
|
in
|
|
{ Result r = f.y; q = f.x1; }
|
|
in
|
|
let set z : integer =
|
|
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; }
|
|
|
|
```
|
|
|
|
```catala-test-inline
|
|
$ catala Interpret --lcalc -s Foo -O --closure-conversion
|
|
┌─[RESULT]─
|
|
│ z = 11
|
|
└─
|
|
```
|