# 09 - 异常处理

Viper 支持 Python 风格的 `try/except/finally` 异常处理，编译为基于 jmp_buf 和错误码的 C 级别异常处理机制。

## 异常处理机制

Viper 的异常处理不使用 C++ 风格的零开销异常，而是通过函数参数传递错误码和错误消息实现。编译器自动为可能抛出异常的函数添加 `__eh_msg_out__` 和 `__eh_code_out__` 参数。

## try / except

```python
try:
    result = risky_operation()
except ValueError:
    serial.puts("ValueError occurred\n")
except OSError:
    serial.puts("OSError occurred\n")
except Exception:
    serial.puts("Unknown error\n")
```

### 内置异常类型

Viper 预定义了以下异常类型及其错误码：

| 异常类型 | 错误码 |
|---------|--------|
| `ValueError` | 1 |
| `TypeError` | 2 |
| `RuntimeError` | 3 |
| `ZeroDivisionError` | 4 |
| `IndexError` | 5 |
| `KeyError` | 6 |
| `IOError` | 7 |
| `OSError` | 8 |
| `AssertionError` | 9 |
| `Exception` | 99 |

### 自定义异常

```python
class DiskFullError(Exception):
    pass

class ReadOnlyError(DiskFullError):
    pass
```

自定义异常会自动分配递增的错误码（从 100 开始），并支持继承匹配。

### 多异常捕获

```python
try:
    result = operation()
except (ValueError, TypeError):
    serial.puts("Value or Type error\n")
```

### 获取异常信息

```python
try:
    result = operation()
except Exception as e:
    serial.puts("Error occurred\n")
```

## try / finally

```python
try:
    result = operation()
finally:
    cleanup()
```

`finally` 块无论是否发生异常都会执行。

## try / except / finally

```python
try:
    result = operation()
except ValueError:
    handle_value_error()
finally:
    cleanup()
```

## raise 语句

### 抛出异常

```python
raise ValueError("invalid value")
```

### 抛出自定义异常

```python
raise MyCustomError("something went wrong")
```

### 重新抛出异常

```python
raise
```

### StopIteration

`StopIteration` 有特殊处理，用于迭代器协议：

```python
raise StopIteration
```

## 异常处理的编译实现

### 函数签名变换

可能抛出异常的函数会自动添加错误输出参数：

```python
def risky_operation() -> t.CInt:
    if error:
        raise ValueError("bad value")
    return 0
```

编译后等价于：

```c
int risky_operation(char** __eh_msg_out__, int* __eh_code_out__) {
    if (error) {
        *__eh_code_out__ = 1;  // ValueError code
        *__eh_msg_out__ = "bad value";
        return 0;
    }
    return 0;
}
```

### 调用点变换

```python
try:
    result = risky_operation()
except ValueError:
    handle_error()
```

编译后等价于：

```c
char* __eh_msg = NULL;
int __eh_code = 0;
int result = risky_operation(&__eh_msg, &__eh_code);
if (__eh_msg != NULL) {
    if (__eh_code == 1) {  // ValueError
        handle_error();
    }
}
```

## 异常继承匹配

异常匹配支持继承体系。捕获父类异常时，子类异常也会被匹配：

```python
class FileSystemError(Exception):
    pass

class FileNotFoundError(FileSystemError):
    pass

class PermissionError(FileSystemError):
    pass

try:
    operation()
except FileSystemError:
    # 也会捕获 FileNotFoundError 和 PermissionError
    handle_fs_error()
```
