A kept when or else-less chain over an Option arm is that Option, flattened one level, unless an Option of it is wanted.
This commit is contained in:
parent
b8e68a48f7
commit
b814aca187
10
TODO.org
10
TODO.org
@ -49,6 +49,12 @@ found. Rules out =if let g = x= over a plain name, which is refused toward these
|
|||||||
CLOSED: [2026-09-26]
|
CLOSED: [2026-09-26]
|
||||||
Decided (138), like Swift: one level per boundary, the literal built at T first; not
|
Decided (138), like Swift: one level per boundary, the literal built at T first; not
|
||||||
inside a container. Rules out implicit unwrapping: a T? where a T is wanted stays refused.
|
inside a container. Rules out implicit unwrapping: a T? where a T is wanted stays refused.
|
||||||
|
** DONE A kept when over an Option body flattens one level
|
||||||
|
CLOSED: [2026-09-26]
|
||||||
|
Decided (140), reversing 125a: a kept =when=, else-less =if=/=elif= or =if let= chain whose
|
||||||
|
arm is already a =T?= is a =T?=, and =T= beside =T?= arms is =T?=; a =T??= arm stays =T??=.
|
||||||
|
Where =T??= is wanted the arm is Some of it. Rules out telling "no branch matched" apart
|
||||||
|
from "a branch gave None" without asking for =T??=.
|
||||||
** TODO The stepper does not step inside an optional chain
|
** TODO The stepper does not step inside an optional chain
|
||||||
=Ast.step_expr= treats a =Chain= as a leaf (its catch-all), so nothing in a chain's
|
=Ast.step_expr= treats a =Chain= as a leaf (its catch-all), so nothing in a chain's
|
||||||
body gets a step point of its own.
|
body gets a step point of its own.
|
||||||
@ -68,8 +74,8 @@ Option or a dyn holds (130); over any other type, and =_=, it is refused toward
|
|||||||
** DONE when as a value, and get as a checked lookup
|
** DONE when as a value, and get as a checked lookup
|
||||||
CLOSED: [2026-09-26]
|
CLOSED: [2026-09-26]
|
||||||
Every one-armed =if= (and a =cond= with no =:else=) is a =when=; kept — a =let= value, a
|
Every one-armed =if= (and a =cond= with no =:else=) is a =when=; kept — a =let= value, a
|
||||||
call's argument, a lambda's return — it is =Option(T)=, nested over an Option body
|
call's argument, a lambda's return — it is =Option(T)=, and body-or-nil where a dyn is
|
||||||
(Rust's =bool::then=), and body-or-nil where a dyn is wanted. A =_=-inferred return's
|
wanted. Over an Option body it was nested (Rust's =bool::then=, 125a); 140 reversed that. A =_=-inferred return's
|
||||||
last form is not kept. =get= over dyn text or vec is nil when out of range; =.field= still traps.
|
last form is not kept. =get= over dyn text or vec is nil when out of range; =.field= still traps.
|
||||||
|
|
||||||
** NEXT str and String
|
** NEXT str and String
|
||||||
|
|||||||
109
lib/check.ml
109
lib/check.ml
@ -8618,12 +8618,31 @@ and check_if_once ctx ~tail ~used ?want loc c t e =
|
|||||||
| Some Types.Dyn -> Some Types.Dyn
|
| Some Types.Dyn -> Some Types.Dyn
|
||||||
| _ -> None
|
| _ -> None
|
||||||
in
|
in
|
||||||
let t = branch ctx (fun () -> in_tail (fun () -> check ctx ?want:tw t)) in
|
let arm w = branch ctx (fun () -> in_tail (fun () -> check ctx ?want:w t)) in
|
||||||
|
(* At an Option want the arm is asked the payload first, and the chain
|
||||||
|
wraps it; refused there, it is asked the Option itself, which it
|
||||||
|
then is (decision 140). So a T?? wanted of a T? arm is Some of it,
|
||||||
|
and the chain's own None stays the outer one. *)
|
||||||
|
let t, at_payload =
|
||||||
|
match want with
|
||||||
|
| Some (Types.Option _) ->
|
||||||
|
(match trial ctx (fun () -> arm tw) with
|
||||||
|
| Ok t -> t, true
|
||||||
|
| Error d ->
|
||||||
|
(match trial ctx (fun () -> arm want) with
|
||||||
|
| Ok t -> t, false
|
||||||
|
| Error _ -> raise (Loc.Error d)))
|
||||||
|
| _ -> arm tw, false
|
||||||
|
in
|
||||||
let rest ~used ?want () =
|
let rest ~used ?want () =
|
||||||
branch ctx (fun () ->
|
branch ctx (fun () ->
|
||||||
ctx.tail <- tail; ctx.used <- used; check ctx ?want e)
|
ctx.tail <- tail; ctx.used <- used; check ctx ?want e)
|
||||||
in
|
in
|
||||||
match t.Tast.ty with
|
match t.Tast.ty with
|
||||||
|
| ty when at_payload && not (Types.equal ty Types.Never) ->
|
||||||
|
let oty = Option.get want in
|
||||||
|
let e = rest ~used:true ~want:oty () in
|
||||||
|
mk loc oty (Tast.If (c, mk loc oty (Tast.Some_ t), e))
|
||||||
| Types.Unit ->
|
| Types.Unit ->
|
||||||
expect ctx loc ~want
|
expect ctx loc ~want
|
||||||
(mk loc Types.Unit (Tast.If (c, t, rest ~used:false ())))
|
(mk loc Types.Unit (Tast.If (c, t, rest ~used:false ())))
|
||||||
@ -8633,32 +8652,14 @@ and check_if_once ctx ~tail ~used ?want loc c t e =
|
|||||||
| Types.Dyn ->
|
| Types.Dyn ->
|
||||||
let e = rest ~used:true ~want:Types.Dyn () in
|
let e = rest ~used:true ~want:Types.Dyn () in
|
||||||
expect ctx loc ~want (mk loc Types.Dyn (Tast.If (c, t, e)))
|
expect ctx loc ~want (mk loc Types.Dyn (Tast.If (c, t, e)))
|
||||||
|
(* An arm that is already an Option is the chain's value as it is,
|
||||||
|
and [None] when no test holds — one level flattened (decision
|
||||||
|
140): an arm's None and no arm running are one answer. *)
|
||||||
|
| Types.Option _ as o ->
|
||||||
|
let e = rest ~used:true ~want:o () in
|
||||||
|
expect ctx loc ~want (mk loc o (Tast.If (c, t, e)))
|
||||||
| ty ->
|
| ty ->
|
||||||
let oty = Types.Option ty in
|
let oty = Types.Option ty in
|
||||||
(* A later arm that is a T? where this one is a T: the arms meet at
|
|
||||||
T? (decision 138), so the chain is a T??, as it is when the T?
|
|
||||||
arm comes first. Tried only where the arm is refused at T. *)
|
|
||||||
let nested =
|
|
||||||
match want, ty with
|
|
||||||
| None, (Types.Option _ | Types.Unit) -> None
|
|
||||||
| None, _ ->
|
|
||||||
(match trial ctx (fun () -> rest ~used:true ~want:oty ()) with
|
|
||||||
| Ok e -> Some (Error e)
|
|
||||||
| Error _ ->
|
|
||||||
let ooty = Types.Option oty in
|
|
||||||
(match trial ctx (fun () -> rest ~used:true ~want:ooty ()) with
|
|
||||||
| Ok e -> Some (Ok e)
|
|
||||||
| Error _ -> None))
|
|
||||||
| _ -> None
|
|
||||||
in
|
|
||||||
match nested with
|
|
||||||
| Some (Ok e) ->
|
|
||||||
let ooty = Types.Option oty in
|
|
||||||
let t = mk loc ooty (Tast.Some_ (mk loc oty (Tast.Some_ t))) in
|
|
||||||
mk loc ooty (Tast.If (c, t, e))
|
|
||||||
| Some (Error e) ->
|
|
||||||
mk loc oty (Tast.If (c, mk loc oty (Tast.Some_ t), e))
|
|
||||||
| None ->
|
|
||||||
let e = rest ~used:true ~want:oty () in
|
let e = rest ~used:true ~want:oty () in
|
||||||
expect ctx loc ~want
|
expect ctx loc ~want
|
||||||
(mk loc oty (Tast.If (c, mk loc oty (Tast.Some_ t), e))))
|
(mk loc oty (Tast.If (c, mk loc oty (Tast.Some_ t), e))))
|
||||||
@ -8899,9 +8900,9 @@ and check_if_once ctx ~tail ~used ?want loc c t e =
|
|||||||
branch evaluates to. Kept — a [let]'s value, an argument, a return, or
|
branch evaluates to. Kept — a [let]'s value, an argument, a return, or
|
||||||
anything else with a type wanted of it — it answers (Option T): [Some] of
|
anything else with a type wanted of it — it answers (Option T): [Some] of
|
||||||
the branch when the test held and [None] when it did not. A branch that
|
the branch when the test held and [None] when it did not. A branch that
|
||||||
is already an Option is not flattened: the answer is (Option (Option T)),
|
is already an Option is that Option, flattened one level (decision 140,
|
||||||
Rust's [bool::then], so [None] from the branch and a failed test stay two
|
Kotlin's [?.] rather than Rust's [bool::then]): [None] from the branch and
|
||||||
answers.
|
a failed test are one answer. A (Option (Option T)) branch stays one.
|
||||||
|
|
||||||
Dyn has no Option. Where a dyn is wanted, or the branch is a dyn, a false
|
Dyn has no Option. Where a dyn is wanted, or the branch is a dyn, a false
|
||||||
test answers nil and a true one the branch's value — one absence, as a
|
test answers nil and a true one the branch's value — one absence, as a
|
||||||
@ -8921,17 +8922,26 @@ and check_when ctx ~used ?want loc c
|
|||||||
| Some Types.Dyn ->
|
| Some Types.Dyn ->
|
||||||
let t = branch_at ~want:Types.Dyn () in
|
let t = branch_at ~want:Types.Dyn () in
|
||||||
mk loc Types.Dyn (Tast.If (c, t, nil ()))
|
mk loc Types.Dyn (Tast.If (c, t, nil ()))
|
||||||
| Some (Types.Option inner) ->
|
| Some (Types.Option inner as oty) ->
|
||||||
let t = branch_at ~want:inner () in
|
(* The payload first, wrapped; refused there, the Option itself, which
|
||||||
let oty = Types.Option inner in
|
the branch then is (decision 140). *)
|
||||||
let some = if t.Tast.ty = Types.Never then t else mk loc oty (Tast.Some_ t) in
|
let t =
|
||||||
mk loc oty (Tast.If (c, some, mk loc oty Tast.None_))
|
match trial ctx (fun () -> branch_at ~want:inner ()) with
|
||||||
|
| Ok t -> if t.Tast.ty = Types.Never then t else mk loc oty (Tast.Some_ t)
|
||||||
|
| Error d ->
|
||||||
|
(match trial ctx (fun () -> branch_at ~want:oty ()) with
|
||||||
|
| Ok t -> if t.Tast.ty = Types.Never then t else expect ctx loc ~want:(Some oty) t
|
||||||
|
| Error _ -> raise (Loc.Error d))
|
||||||
|
in
|
||||||
|
mk loc oty (Tast.If (c, t, mk loc oty Tast.None_))
|
||||||
| None when not used -> stmt (branch_at ())
|
| None when not used -> stmt (branch_at ())
|
||||||
| _ ->
|
| _ ->
|
||||||
let t = branch_at () in
|
let t = branch_at () in
|
||||||
if valueless t then stmt t
|
if valueless t then stmt t
|
||||||
else if Types.equal t.Tast.ty Types.Dyn then
|
else if Types.equal t.Tast.ty Types.Dyn then
|
||||||
expect ctx loc ~want (mk loc Types.Dyn (Tast.If (c, t, nil ())))
|
expect ctx loc ~want (mk loc Types.Dyn (Tast.If (c, t, nil ())))
|
||||||
|
else if (match t.Tast.ty with Types.Option _ -> true | _ -> false) then
|
||||||
|
expect ctx loc ~want (mk loc t.Tast.ty (Tast.If (c, t, mk loc t.Tast.ty Tast.None_)))
|
||||||
else
|
else
|
||||||
let oty = Types.Option t.Tast.ty in
|
let oty = Types.Option t.Tast.ty in
|
||||||
expect ctx loc ~want
|
expect ctx loc ~want
|
||||||
@ -10021,7 +10031,7 @@ and check_array_gen ctx ~want loc dims f =
|
|||||||
~element:(fun idxs -> mk loc elem (Tast.CallPtr (fv, idxs))))
|
~element:(fun idxs -> mk loc elem (Tast.CallPtr (fv, idxs))))
|
||||||
|
|
||||||
and check_match ctx ?(tail = false) ?(used = false) ?(stmt = false) ?(opt = false)
|
and check_match ctx ?(tail = false) ?(used = false) ?(stmt = false) ?(opt = false)
|
||||||
?opt_rest ?want loc scrutinee arms =
|
?(flat = false) ?opt_rest ?want loc scrutinee arms =
|
||||||
(* [stmt] is an [if let] with no else: a statement, Unit whatever its arm
|
(* [stmt] is an [if let] with no else: a statement, Unit whatever its arm
|
||||||
answers, as a one-armed [if] is when nothing keeps it. [opt] is one that
|
answers, as a one-armed [if] is when nothing keeps it. [opt] is one that
|
||||||
is kept: its arm answers [Some], and the arm with no body [None]. *)
|
is kept: its arm answers [Some], and the arm with no body [None]. *)
|
||||||
@ -10030,7 +10040,11 @@ and check_match ctx ?(tail = false) ?(used = false) ?(stmt = false) ?(opt = fals
|
|||||||
let want0 = want in
|
let want0 = want in
|
||||||
let want =
|
let want =
|
||||||
if stmt then None
|
if stmt then None
|
||||||
else if opt then (match want with Some (Types.Option i) -> Some i | _ -> None)
|
else if opt then
|
||||||
|
(match want with
|
||||||
|
| Some (Types.Option _) when flat -> want
|
||||||
|
| Some (Types.Option i) -> Some i
|
||||||
|
| _ -> None)
|
||||||
else want
|
else want
|
||||||
in
|
in
|
||||||
let s = check ctx scrutinee in
|
let s = check ctx scrutinee in
|
||||||
@ -10629,6 +10643,14 @@ and check_match ctx ?(tail = false) ?(used = false) ?(stmt = false) ?(opt = fals
|
|||||||
match r with
|
match r with
|
||||||
| Some e -> e
|
| Some e -> e
|
||||||
| None -> rt a.Ast.aloc Types.Dyn "flan_dyn_nil" [])
|
| None -> rt a.Ast.aloc Types.Dyn "flan_dyn_nil" [])
|
||||||
|
(* Already an Option: the whole, one level flattened (decision 140). *)
|
||||||
|
| Some (Types.Option _ as o) when flat || want0 = None ->
|
||||||
|
opt_result := Some o;
|
||||||
|
let r = rest ~used:true ~want:o () in
|
||||||
|
fill Fun.id (fun a ->
|
||||||
|
match r with
|
||||||
|
| Some e -> e
|
||||||
|
| None -> mk a.Ast.aloc o Tast.None_)
|
||||||
| Some t ->
|
| Some t ->
|
||||||
let oty = Types.Option t in
|
let oty = Types.Option t in
|
||||||
opt_result := Some oty;
|
opt_result := Some oty;
|
||||||
@ -10791,9 +10813,22 @@ and check_if_let ctx ~tail ~used ?want loc scrutinee (arm : Ast.arm) els =
|
|||||||
ctx.tail <- tail; ctx.used <- used; check ctx ?want e))
|
ctx.tail <- tail; ctx.used <- used; check ctx ?want e))
|
||||||
els
|
els
|
||||||
in
|
in
|
||||||
|
(* The arm at the payload first, as [check_when] asks it; refused
|
||||||
|
there, at the Option itself (decision 140). *)
|
||||||
|
let go ~flat () =
|
||||||
|
check_match ctx ~tail ~used:true ~opt:true ~flat ?opt_rest ?want loc scrutinee
|
||||||
|
[ arm; wild [] ]
|
||||||
|
in
|
||||||
expect ctx loc ~want
|
expect ctx loc ~want
|
||||||
(check_match ctx ~tail ~used:true ~opt:true ?opt_rest ?want loc scrutinee
|
(match want with
|
||||||
[ arm; wild [] ]))
|
| Some (Types.Option _) ->
|
||||||
|
(match trial ctx (go ~flat:false) with
|
||||||
|
| Ok r -> r
|
||||||
|
| Error d ->
|
||||||
|
(match trial ctx (go ~flat:true) with
|
||||||
|
| Ok r -> r
|
||||||
|
| Error _ -> raise (Loc.Error d)))
|
||||||
|
| _ -> go ~flat:false ()))
|
||||||
| Some e ->
|
| Some e ->
|
||||||
check_match ctx ~tail ~used ?want loc scrutinee [ arm; wild [ e ] ]
|
check_match ctx ~tail ~used ?want loc scrutinee [ arm; wild [ e ] ]
|
||||||
| None ->
|
| None ->
|
||||||
|
|||||||
@ -252,7 +252,8 @@ Each item: the proposal, then the reason in one line.
|
|||||||
into a `T??` is `Some` of it. A `$t` meeting `$u?` binds `$u` to `T`.
|
into a `T??` is `Some` of it. A `$t` meeting `$u?` binds `$u` to `T`.
|
||||||
Never inside a container (`Vec(i32)` is not a `Vec(i32?)`), and never the
|
Never inside a container (`Vec(i32)` is not a `Vec(i32?)`), and never the
|
||||||
other way: a `T?` where a `T` is wanted still needs `!`, `??`, `x?` or
|
other way: a `T?` where a `T` is wanted still needs `!`, `??`, `x?` or
|
||||||
`as`. A kept chain whose arms are a `T` and a `T?` is a `T??`. **Built.**
|
`as`. A kept chain whose arms are a `T` and a `T?` is a `T?` (decision
|
||||||
|
140, under `when c`). **Built.**
|
||||||
- **Casts and type-taking builtins are calls:** `i32(x)`, `vec-new(u8)`,
|
- **Casts and type-taking builtins are calls:** `i32(x)`, `vec-new(u8)`,
|
||||||
`max-value(u8)`, `the([3 f32], [1 2 3.5])`. A pointer cast is the type
|
`max-value(u8)`, `the([3 f32], [1 2 3.5])`. A pointer cast is the type
|
||||||
called: `Ptr(Color)(p)` reads `((Ptr Color) p)`. **Built.**
|
called: `Ptr(Color)(p)` reads `((Ptr Color) p)`. **Built.**
|
||||||
@ -316,7 +317,13 @@ Each item: the proposal, then the reason in one line.
|
|||||||
A `when` whose value is kept (a `let`'s value, an argument, a return) gives
|
A `when` whose value is kept (a `let`'s value, an argument, a return) gives
|
||||||
`Some(a)` when `c` holds and `None` when it does not; where a `dyn` is
|
`Some(a)` when `c` holds and `None` when it does not; where a `dyn` is
|
||||||
wanted, `a` or `nil`. As a statement it gives nothing. An `if`/`elif` chain
|
wanted, `a` or `nil`. As a statement it gives nothing. An `if`/`elif` chain
|
||||||
with no `else` is the same when kept: `None` when no test holds. **Built.**
|
with no `else` is the same when kept: `None` when no test holds. When `a`
|
||||||
|
is already an Option it is not wrapped again (decision 140): `when c then
|
||||||
|
o` over an `i32?` is an `i32?`, `None` when `c` fails or `o` is `None`, and
|
||||||
|
a chain mixing `T` and `T?` arms is a `T?`. One level only: an arm that is
|
||||||
|
a `T??` gives a `T??`. Where an Option of the arm's type is wanted, as a
|
||||||
|
`T??` over a `T?` arm, the arm is `Some` of its value and a failed test is
|
||||||
|
the outer `None`. `if let` with no `else` follows the same rule. **Built.**
|
||||||
- **`if let P = v`** plus a block reads as `(if-let [P v] then)`; `elif` and
|
- **`if let P = v`** plus a block reads as `(if-let [P v] then)`; `elif` and
|
||||||
`else` follow as for `if`, the rest of the chain being the `if-let`'s else.
|
`else` follow as for `if`, the rest of the chain being the `if-let`'s else.
|
||||||
`elif let P = v` is a further `if-let` nested in that else.
|
`elif let P = v` is a further `if-let` nested in that else.
|
||||||
|
|||||||
@ -40,12 +40,24 @@ fn arms(k: i32, x: i32) -> i32?
|
|||||||
|
|
||||||
fn big(x: i64?) -> i64 = x ?? 0
|
fn big(x: i64?) -> i64 = x ?? 0
|
||||||
|
|
||||||
|
;; A T?? is wanted, so each arm is Some of its value and the chain's None is
|
||||||
|
;; the outer one.
|
||||||
fn chain(a: bool, b: bool, opt: i32?) -> Option(i32?)
|
fn chain(a: bool, b: bool, opt: i32?) -> Option(i32?)
|
||||||
if a
|
if a
|
||||||
1
|
1
|
||||||
elif b
|
elif b
|
||||||
opt
|
opt
|
||||||
|
|
||||||
|
;; Nothing wanted: a T arm beside a T? arm makes the chain a T?, flattened
|
||||||
|
;; one level (decision 140).
|
||||||
|
fn flat(a: bool, b: bool, opt: i32?) -> i32?
|
||||||
|
let r =
|
||||||
|
if a
|
||||||
|
1
|
||||||
|
elif b
|
||||||
|
opt
|
||||||
|
r
|
||||||
|
|
||||||
fn main()
|
fn main()
|
||||||
;; assignment, and a literal at the payload's width
|
;; assignment, and a literal at the payload's width
|
||||||
let s: i64? = None
|
let s: i64? = None
|
||||||
@ -85,14 +97,15 @@ fn main()
|
|||||||
let none: i32? = None
|
let none: i32? = None
|
||||||
let nn2: Option(i32?) = none
|
let nn2: Option(i32?) = none
|
||||||
println(two(nn), two(nn2))
|
println(two(nn), two(nn2))
|
||||||
;; a kept chain: a T arm beside a T? arm makes the chain a T??
|
;; kept chains over T and T? arms
|
||||||
println(two(chain(true, false, none)), two(chain(false, true, none)), two(chain(false, false, none)))
|
println(two(chain(true, false, none)), two(chain(false, true, none)), two(chain(false, false, none)))
|
||||||
|
println(flat(true, false, none) ?? -1, flat(false, true, Some(6)) ?? -1, flat(false, true, none) ?? -1, flat(false, false, none) ?? -1)
|
||||||
let kk =
|
let kk =
|
||||||
if x > 9
|
if x > 9
|
||||||
none
|
none
|
||||||
elif x > 1
|
elif x > 1
|
||||||
1
|
1
|
||||||
println(two(kk))
|
println(kk ?? -1)
|
||||||
;; generics
|
;; generics
|
||||||
println(first(9), first(Some(8)), wrap(3) ?? 0, through(5))
|
println(first(9), first(Some(8)), wrap(3) ?? 0, through(5))
|
||||||
;; a literal local takes the payload's type from an Option use, as it
|
;; a literal local takes the payload's type from an Option use, as it
|
||||||
|
|||||||
@ -21,6 +21,28 @@ fn early(a: Option(i32)) -> Option(i32)
|
|||||||
elif true
|
elif true
|
||||||
3
|
3
|
||||||
|
|
||||||
|
;; An arm that is already an Option is the whole, flattened (decision 140).
|
||||||
|
fn flat(a: Option(i32), o: Option(i32)) -> Option(i32)
|
||||||
|
if let Some(x) = a then o
|
||||||
|
|
||||||
|
;; An Option of it wanted: the arm is Some of its value, and no match is the
|
||||||
|
;; outer None.
|
||||||
|
fn nest(a: Option(i32), o: Option(i32)) -> Option(Option(i32))
|
||||||
|
if let Some(x) = a then o
|
||||||
|
|
||||||
|
fn level(oo: Option(Option(i32)))
|
||||||
|
match oo
|
||||||
|
Some(o) -> if o? then println(o) else println("some none")
|
||||||
|
None -> println("none")
|
||||||
|
|
||||||
|
fn flat_chain(a: Option(i32), k: i32)
|
||||||
|
let r =
|
||||||
|
if let Some(x) = a
|
||||||
|
x
|
||||||
|
elif k > 0
|
||||||
|
None
|
||||||
|
show(r)
|
||||||
|
|
||||||
fn dyn_only(a: Option(i32)) -> dyn
|
fn dyn_only(a: Option(i32)) -> dyn
|
||||||
if let Some(x) = a then x
|
if let Some(x) = a then x
|
||||||
|
|
||||||
@ -40,6 +62,15 @@ fn main()
|
|||||||
show(lead(1, None))
|
show(lead(1, None))
|
||||||
show(early(None))
|
show(early(None))
|
||||||
show(early(Some(1)))
|
show(early(Some(1)))
|
||||||
|
show(flat(Some(1), Some(4)))
|
||||||
|
show(flat(Some(1), None))
|
||||||
|
show(flat(None, Some(4)))
|
||||||
|
level(nest(Some(1), Some(4)))
|
||||||
|
level(nest(Some(1), None))
|
||||||
|
level(nest(None, Some(4)))
|
||||||
|
flat_chain(Some(3), 0)
|
||||||
|
flat_chain(None, 1)
|
||||||
|
flat_chain(None, 0)
|
||||||
println(dyn_only(Some(5)))
|
println(dyn_only(Some(5)))
|
||||||
println(dyn_only(None))
|
println(dyn_only(None))
|
||||||
;; As a statement it is unchanged.
|
;; As a statement it is unchanged.
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
;;;; A when whose value is kept answers an Option: Some of its body when the
|
;;;; A when whose value is kept answers an Option: Some of its body when the
|
||||||
;;;; test holds, None when it does not. As a statement it answers nothing.
|
;;;; test holds, None when it does not. As a statement it answers nothing.
|
||||||
;;;; Where a dyn is wanted it answers the body or nil, since dyn has no
|
;;;; Where a dyn is wanted it answers the body or nil, since dyn has no
|
||||||
;;;; Option. A body that is already an Option is not flattened.
|
;;;; Option. A body that is already an Option is that Option, flattened one
|
||||||
|
;;;; level (decision 140), unless an Option of it is what is wanted.
|
||||||
|
|
||||||
(defn show [o (Option i32)] ()
|
(defn show [o (Option i32)] ()
|
||||||
(match o (Some v) (println v) None (println "none")))
|
(match o (Some v) (println v) None (println "none")))
|
||||||
@ -9,10 +10,13 @@
|
|||||||
;; Returned: the return type is the want.
|
;; Returned: the return type is the want.
|
||||||
(defn half [n i32] (Option i32) (when (= 0 (% n 2)) (/ n 2)))
|
(defn half [n i32] (Option i32) (when (= 0 (% n 2)) (/ n 2)))
|
||||||
|
|
||||||
;; Nested, as Rust's bool::then: None from the body stays apart from a
|
;; An (Option (Option i32)) is wanted, so the body is Some of it and the
|
||||||
;; failed test.
|
;; failed test is the outer None.
|
||||||
(defn wrap [c bool o (Option i32)] (Option (Option i32)) (when c o))
|
(defn wrap [c bool o (Option i32)] (Option (Option i32)) (when c o))
|
||||||
|
|
||||||
|
;; Flattened: None from the body and a failed test are one answer.
|
||||||
|
(defn flat [c bool o (Option i32)] (Option i32) (when c o))
|
||||||
|
|
||||||
(defn level [oo (Option (Option i32))] ()
|
(defn level [oo (Option (Option i32))] ()
|
||||||
(match oo
|
(match oo
|
||||||
(Some o) (match o (Some v) (println v) None (println "some none"))
|
(Some o) (match o (Some v) (println v) None (println "some none"))
|
||||||
@ -45,6 +49,12 @@
|
|||||||
(level (wrap true (Some 1)))
|
(level (wrap true (Some 1)))
|
||||||
(level (wrap true None))
|
(level (wrap true None))
|
||||||
(level (wrap false (Some 1)))
|
(level (wrap false (Some 1)))
|
||||||
|
(show (flat true (Some 4)))
|
||||||
|
(show (flat true None))
|
||||||
|
(show (flat false (Some 4)))
|
||||||
|
(let [o (the (Option i32) (Some 8))
|
||||||
|
f (when true o)]
|
||||||
|
(show f))
|
||||||
(println (dyn-when true))
|
(println (dyn-when true))
|
||||||
(println (dyn-when nil))
|
(println (dyn-when nil))
|
||||||
(show (early None))
|
(show (early None))
|
||||||
|
|||||||
@ -2226,8 +2226,8 @@ let () =
|
|||||||
dyn_if_truthy_out;
|
dyn_if_truthy_out;
|
||||||
(* A kept when is an Option; get is a checked lookup; if let. *)
|
(* A kept when is an Option; get is a checked lookup; if let. *)
|
||||||
let when_value_out =
|
let when_value_out =
|
||||||
"5\nnone\n42\nnone\n9\n1\nsome none\nnone\n5\nnil\n3\nnone\n6\nnone\n20\nnone\n2\n\
|
"5\nnone\n42\nnone\n9\n1\nsome none\nnone\n4\nnone\nnone\n8\n5\nnil\n3\nnone\n6\nnone\n\
|
||||||
a\nnil\ncond stmt\nran\nend\n"
|
20\nnone\n2\na\nnil\ncond stmt\nran\nend\n"
|
||||||
in
|
in
|
||||||
outputs "when as a value" "programs/when-value.flan" when_value_out;
|
outputs "when as a value" "programs/when-value.flan" when_value_out;
|
||||||
outputs ~opt:"-O0" "when as a value, -O0" "programs/when-value.flan" when_value_out;
|
outputs ~opt:"-O0" "when as a value, -O0" "programs/when-value.flan" when_value_out;
|
||||||
@ -2246,7 +2246,8 @@ let () =
|
|||||||
"5\n100\n0\n9\n1\n20\n100\n0\n1\n7\nabsent\nnorth\n6\n-1\n-2\n14\nwhen block\n"
|
"5\n100\n0\n9\n1\n20\n100\n0\n1\n7\nabsent\nnorth\n6\n-1\n-2\n14\nwhen block\n"
|
||||||
in
|
in
|
||||||
let if_let_kept_out =
|
let if_let_kept_out =
|
||||||
"1\n4\nnone\n6\nnone\n9\n2\nnone\n3\nnone\n5\nnil\n7\n"
|
"1\n4\nnone\n6\nnone\n9\n2\nnone\n3\nnone\n4\nnone\nnone\n4\nsome none\nnone\n\
|
||||||
|
3\nnone\nnone\n5\nnil\n7\n"
|
||||||
in
|
in
|
||||||
outputs "a kept if let chain" "programs/if-let-kept.fln" if_let_kept_out;
|
outputs "a kept if let chain" "programs/if-let-kept.fln" if_let_kept_out;
|
||||||
outputs ~opt:"-O0" "a kept if let chain, -O0" "programs/if-let-kept.fln" if_let_kept_out;
|
outputs ~opt:"-O0" "a kept if let chain, -O0" "programs/if-let-kept.fln" if_let_kept_out;
|
||||||
@ -2277,7 +2278,7 @@ let () =
|
|||||||
(* A T where a T? is wanted is Some of it (decision 138). *)
|
(* A T where a T? is wanted is Some of it (decision 138). *)
|
||||||
("autowrap.fln",
|
("autowrap.fln",
|
||||||
"-1\n5 4 2\n7 8 -1\n3 4\n7\n1 0 4\n5\n2 6 0\n2 -1 -1 2\n4\n-1 3 0\n\
|
"-1\n5 4 2\n7 8 -1\n3 4\n7\n1 0 4\n5\n2 6 0\n2 -1 -1 2\n4\n-1 3 0\n\
|
||||||
some some some none\nsome some some none none\nsome some\n9 8 3 5\n\
|
some some some none\nsome some some none none\n1 6 -1 -1\n1\n9 8 3 5\n\
|
||||||
4000000000 4000000000 4 4\n4 4000000000\n3.5 3.5 7 7\n200 200\n-1 5\n1 0\n10\n");
|
4000000000 4000000000 4 4\n4 4000000000\n3.5 3.5 7 7\n200 200\n-1 5\n1 0\n10\n");
|
||||||
(* x? tests and narrows, e? as g names what it found (decision 133). *)
|
(* x? tests and narrows, e? as g names what it found (decision 133). *)
|
||||||
("presence.fln", "true false true\n6\n-1\n3\n101 209 0\n11\n42\n2\nabsent\n6\nfalse true\n3\n6\n15\n"); ("presence-dyn.fln", "true false\n103 209 0\nno pet\nann\n3 2\n") ];
|
("presence.fln", "true false true\n6\n-1\n3\n101 209 0\n11\n42\n2\nabsent\n6\nfalse true\n3\n6\n15\n"); ("presence-dyn.fln", "true false\n103 209 0\nno pet\nann\n3 2\n") ];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user