block labels

This commit is contained in:
2026-06-28 08:51:01 +02:00
parent 3e54c6f9ad
commit eaa66511a0
7 changed files with 352 additions and 60 deletions
+75
View File
@@ -174,6 +174,72 @@ loop_none_first :: func() i32 {
return 2
}
# --- labels: value blocks + outer-loop yield/break (milestone 20.7) -----------
# A labeled value block: `yield :blk` exits the block (past a nested `if`) with a
# value. Every path must yield.
lblock :: func(sel i32) i32 {
r :: blk: {
base :: 10
if (sel == 0) {
yield :blk base
} else {
yield :blk base * 2
}
}
return r
}
# An early `yield :blk` skips the rest of the block; the value is captured before
# the block's defer runs.
lblock_defer :: func() i32 {
r :: blk: {
n i32 = 5
defer n = 999
if (true) yield :blk n
yield :blk 0
}
return r # 5, not 999
}
# A labeled block whose `{T, none}` yields resolve the result to an optional.
lblock_optional :: func(present i32) i32 {
r :: blk: {
if (present == 0) yield :blk none
yield :blk 8
}
if r |v| {
return v
}
return -1
}
# `yield :outer v` exits an OUTER value loop from inside an inner loop.
yield_outer :: func(target i32) i32 {
found :: for 0..3 |row| outer: {
for 0..3 |col| {
if (row * 3 + col == target) yield :outer (row * 10 + col)
}
yield none
}
if found |v| {
return v
}
return -1
}
# Plain `break :outer` exits an outer loop from an inner loop.
break_outer :: func() i32 {
count i32 = 0
for 0..3 |a| outer: {
for 0..3 |b| {
count += 1
if (a == 1 and b == 1) break :outer
}
}
return count # 5
}
main :: func() i32 {
if (basic() != 42) return 101
if (typed() != 100) return 102
@@ -201,5 +267,14 @@ main :: func() i32 {
if (orelse_value(none) != 7) return 121
if (loop_none_first() != 0) return 122
if (lblock(0) != 10) return 123
if (lblock(1) != 20) return 124
if (lblock_defer() != 5) return 125
if (lblock_optional(0) != -1) return 126
if (lblock_optional(1) != 8) return 127
if (yield_outer(4) != 11) return 128
if (yield_outer(99) != -1) return 129
if (break_outer() != 5) return 130
return 42
}