# 07 - 控制流

Viper 支持 Python 风格的控制流语句，编译为 LLVM IR 的基本块和分支指令。

## 条件语句

### if / elif / else

```python
if x > 0:
    y = 1
elif x == 0:
    y = 0
else:
    y = -1
```

等价 C 代码：
```c
if (x > 0) {
    y = 1;
} else if (x == 0) {
    y = 0;
} else {
    y = -1;
}
```

### 条件表达式

```python
is_dir: t.CInt = 1 if (info.attr & AM_DIR) else 0
```

等价 C 代码：
```c
int is_dir = (info.attr & AM_DIR) ? 1 : 0;
```

### None 检查

```python
if BootInfo != None:
    paging.init(BootInfo.MemmapAddr, BootInfo.MemmapSize)
else:
    paging.init(0, 0)
```

等价 C 代码：
```c
if (BootInfo != NULL) {
    paging_init(BootInfo->MemmapAddr, BootInfo->MemmapSize);
} else {
    paging_init(0, 0);
}
```

## 循环语句

### while 循环

```python
i: t.CInt = 0
while i < 10:
    buf[i] = 0
    i += 1
```

等价 C 代码：
```c
int i = 0;
while (i < 10) {
    buf[i] = 0;
    i += 1;
}
```

### while-else

```python
while i < count:
    if found:
        break
else:
    serial.puts("not found\n")
```

`else` 块在循环正常结束（非 `break` 退出）时执行。

### 无限循环

```python
while True:
    sched.Scheduler._yield()
```

等价 C 代码：
```c
while (1) {
    scheduler_yield();
}
```

### for 循环（range）（关于 for 循环的更多用法，参见 [06-oop.md 中 迭代器协议](06-oop.md#迭代器协议)）

```python
for i in range(10):
    buf[i] = 0

for i in range(5, 10):
    buf[i] = 0

for i in range(0, 100, 2):
    buf[i] = 0
```

等价 C 代码：
```c
for (int i = 0; i < 10; i++) {
    buf[i] = 0;
}

for (int i = 5; i < 10; i++) {
    buf[i] = 0;
}

for (int i = 0; i < 100; i += 2) {
    buf[i] = 0;
}
```

### for 循环（迭代器）

如果类实现了 `__iter__` 和 `__next__` 方法，可以使用 `for ... in` 迭代：

```python
container: Iter = Iter()
for item in container:
    process(item)
```

### for-else

```python
for i in range(count):
    if items[i] == target:
        break
else:
    serial.puts("not found\n")
```

### break 和 continue

```python
while True:
    if done:
        break
    if skip:
        continue
    process()
```

## match 语句

Viper 支持 Python 3.10+ 的 `match` 语句，编译为 C 的 `switch` 语句：

```python
match self.ctype:
    case UI_LABEL:
        self.RenderLabel(sh)
    case UI_BUTTON:
        self.RenderButton(sh)
    case UI_PANEL:
        self.RenderPanel(sh)
    case _:
        pass
```

等价 C 代码：
```c
switch (self->ctype) {
    case UI_LABEL:
        self_RenderLabel(self, sh);
        break;
    case UI_BUTTON:
        self_RenderButton(self, sh);
        break;
    case UI_PANEL:
        self_RenderPanel(self, sh);
        break;
    default:
        break;
}
```

### match 值匹配

```python
match code:
    case 0:
        serial.puts("OK\n")
    case 1:
        serial.puts("Error\n")
    case _:
        serial.puts("Unknown\n")
```

### match 或模式

```python
match value:
    case 1 | 2 | 3:
        serial.puts("small\n")
    case _:
        serial.puts("other\n")
```

### fallthrough（无 break）

默认每个 `case` 自动添加 `break`。如需 fallthrough，使用 `c.NoBreak`：

```python
match value:
    case 1:
        do_one()
        c.NoBreak
    case 2:
        do_two()
```

如果需要提前 break，需要使用 `c.Break()`，因为在 `Python` 中，`match` 分支不支持直接使用 `break`。

## assert 语句
> 避免使用此语句，此语句未经充分测试，在多数情况下，编译器不知道如何展示结果。

```python
assert ptr != None, "null pointer"
```

编译为条件检查和错误报告。

## with 语句

`with` 语句用于资源管理，要求对象实现 `__enter__` 和 `__exit__` 方法：

```python
with File("/test.txt", FA_READ) as f:
    data: t.CInt = f.read()
```

等价 C 代码：
```c
File* f = File_enter(File_new("/test.txt", FA_READ));
int data = File_read(f);
File_exit(f);
```
