snapshot before regression test
This commit is contained in:
256
wiki/07-control-flow.md
Normal file
256
wiki/07-control-flow.md
Normal file
@@ -0,0 +1,256 @@
|
||||
# 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);
|
||||
```
|
||||
Reference in New Issue
Block a user