expand yield to if-statements and loops
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
# Milestone 20: `yield` and value blocks.
|
||||
# Milestones 20 / 20.5: `yield`, value blocks, and value if/loops.
|
||||
#
|
||||
# A `{ ... }` on the right of a declaration or assignment is a value block: its
|
||||
# final `yield <expr>` supplies the value (the block analogue of `return`). The
|
||||
# yielded value is captured before the block's defers run. Each section returns a
|
||||
# distinct code on failure; success falls through to 42.
|
||||
# A `{ ... }`, an `if`, or a labeled `for`/`while` on the right of a declaration
|
||||
# or assignment is a *value source*: `yield <expr>` supplies the value (the block
|
||||
# analogue of `return`). Every path must yield. Each section returns a distinct
|
||||
# code on failure; success falls through to 42.
|
||||
|
||||
# --- value blocks (milestone 20) ---------------------------------------------
|
||||
|
||||
# Untyped `::`: the local's type is the yield's natural type.
|
||||
basic :: func() i32 {
|
||||
@@ -43,10 +45,109 @@ reassign :: func() i32 {
|
||||
return r
|
||||
}
|
||||
|
||||
# --- value if-statements (milestone 20.5) ------------------------------------
|
||||
|
||||
# Untyped `::` over an `else if` chain; the first branch fixes the type.
|
||||
vif_untyped :: func(sel i32) i32 {
|
||||
r :: if (sel == 0) {
|
||||
yield 10
|
||||
} else if (sel == 1) {
|
||||
yield 20
|
||||
} else {
|
||||
yield 30
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
# Typed `T =`: every branch coerces to the annotation.
|
||||
vif_typed :: func(sel i32) i32 {
|
||||
r i32 = if (sel == 0) { yield 100 } else { yield 200 }
|
||||
return r
|
||||
}
|
||||
|
||||
# Assigned into an existing local.
|
||||
vif_reassign :: func(sel i32) i32 {
|
||||
r i32 = 0
|
||||
r = if (sel == 0) { yield 7 } else { yield 9 }
|
||||
return r
|
||||
}
|
||||
|
||||
# A branch is a full value block: leading statements + a defer captured before
|
||||
# the yield.
|
||||
vif_defer :: func() i32 {
|
||||
r :: if (true) {
|
||||
n i32 = 5
|
||||
defer n = 999
|
||||
yield n
|
||||
} else {
|
||||
yield 0
|
||||
}
|
||||
return r # 5
|
||||
}
|
||||
|
||||
# --- value loops (milestone 20.5) --------------------------------------------
|
||||
|
||||
# Labeled `for` used as a value: `yield :blk i` exits early with a value, the
|
||||
# trailing `yield none` supplies the value when the loop completes. The `{i,
|
||||
# none}` yields resolve the result to an optional.
|
||||
loop_search :: func() i32 {
|
||||
# first i in 0..10 whose square exceeds 40 (6*6=36 no, 7*7=49 yes -> 7).
|
||||
idx :: for 0..10 |i| blk: {
|
||||
if (i * i > 40) yield :blk i
|
||||
yield none
|
||||
}
|
||||
if idx |found| {
|
||||
if (found == 7) return 0
|
||||
return 1
|
||||
}
|
||||
return 2
|
||||
}
|
||||
|
||||
# Same loop, but nothing matches -> the fall-through `yield none` is the result.
|
||||
loop_none :: func() i32 {
|
||||
idx :: for 0..10 |i| blk: {
|
||||
if (i > 100) yield :blk i
|
||||
yield none
|
||||
}
|
||||
if idx |found| {
|
||||
_ = found
|
||||
return 1 # should be unreachable: no match
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
# Labeled `while` value loop (label follows the `: update` clause).
|
||||
loop_while :: func() i32 {
|
||||
n i32 = 0
|
||||
found :: while n < 100 : n += 1 blk: {
|
||||
if (n == 8) yield :blk n
|
||||
yield none
|
||||
}
|
||||
if found |v| {
|
||||
if (v == 8) return 0
|
||||
return 1
|
||||
}
|
||||
return 2
|
||||
}
|
||||
|
||||
main :: func() i32 {
|
||||
if (basic() != 42) return 101
|
||||
if (typed() != 100) return 102
|
||||
if (spill() != 5) return 103
|
||||
if (reassign() != 7) return 104
|
||||
|
||||
if (vif_untyped(0) != 10) return 105
|
||||
if (vif_untyped(1) != 20) return 106
|
||||
if (vif_untyped(2) != 30) return 107
|
||||
if (vif_typed(0) != 100) return 108
|
||||
if (vif_typed(1) != 200) return 109
|
||||
if (vif_reassign(0) != 7) return 110
|
||||
if (vif_reassign(9) != 9) return 111
|
||||
if (vif_defer() != 5) return 112
|
||||
|
||||
if (loop_search() != 0) return 113
|
||||
if (loop_none() != 0) return 114
|
||||
if (loop_while() != 0) return 115
|
||||
|
||||
return 42
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user