Files
TransPyC/wiki/03-variables.md
T

186 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 03 - 变量声明与赋值
Viper 的变量声明使用 Python 的类型注解语法,通过 `t` 模块指定 C 级别的类型信息。
## 带注解的变量声明
使用 `变量名: 类型` 语法声明变量:
```python
x: t.CInt = 0 # int x = 0;
y: t.CUInt32T = 42 # uint32_t y = 42;
name: t.CArray[t.CChar, 64] # char name[64];
ptr: t.CVoid | t.CPtr # void* ptr;
msg: t.CConst | str = "Hello" # const char* msg = "Hello";
```
### 无初始值的声明
**模块级(全局)无初值声明**生成零初始化的全局变量(LLVM `zeroinitializer`,零初始化成立):
```python
count: t.CInt # int count = 0;(zeroinitializer;仅模块级成立)
buffer: t.CArray[t.CChar, 256] # char buffer[256] = {0};
```
**函数内局部无初值声明**仅分配空间、不初始化——值未定义,勿假定为 0,最好预先赋值或用 memset 清除:
```python
tmp: t.CInt # 函数内局部:仅分配未初始化(值未定义,勿假定为 0)
```
### 延迟赋值
变量可以先声明后赋值:
```python
x: t.CInt
x = 10
```
### 指针变量
```python
p: t.CInt | t.CPtr # int* p;
fb: t.CVoid | t.CPtr # void* fb;
str_ptr: t.CConst | t.CChar | t.CPtr # const char* str_ptr;
```
### 指针变量的特殊初始化
使用 `t.CVoid(0, t.CPtr)` 初始化指针为 NULL:
```python
p: t.CVoid | t.CPtr = t.CVoid(0, t.CPtr) # void* p = NULL;
```
或使用 `None`:
```python
p: t.CVoid | t.CPtr = None # void* p = NULL;
```
## 普通赋值
```python
x: t.CInt = 0
x = 42 # x = 42;
```
## 增强赋值
支持所有 Python 增强赋值运算符:
```python
x: t.CInt = 0
x += 1 # x += 1;
x -= 1 # x -= 1;
x *= 2 # x *= 2;
x //= 3 # x /= 3; (整数除法)
x %= 5 # x %= 5;
x <<= 1 # x <<= 1;
x >>= 1 # x >>= 1;
x |= 0xFF # x |= 0xFF;
x &= 0x0F # x &= 0x0F;
x ^= 0xAA # x ^= 0xAA;
```
## 全局变量
模块顶层声明的变量即为全局变量:
```python
kbd_tid: t.CInt = -1 # 全局 int kbd_tid = -1;
BootInfo: bootinfo | t.CPtr # 全局 struct bootinfo* BootInfo;
```
### 静态全局变量
```python
x: t.CStatic | t.CInt = 0 # static int x = 0;
```
### 外部声明
```python
x: t.CExtern | t.CInt # extern int x;
```
> 注:变量级 `static`/`extern` 语义尚未实现(仅函数级);上述声明当前会生成普通(零初始化)全局定义。外部全局与 FFI 函数推荐 `extern` 关键字(期望后续实现变量级语义)。
## 常量定义
使用 `t.CDefine` 定义编译时常量。`t.CDefine` 不是数据类型,而是编译时元指令——常量在 LLVM IR 中不生成全局变量,而是在引用处直接内联展开。详见 [01-overview.md 中 t.CDefine 深度解析](01-overview.md#tcdefine-深度解析)。
```python
MAX_SIZE: t.CDefine = 1024
PAGE_SIZE: t.CDefine = 4096
FA_READ: t.CDefine = 0x01
FA_WRITE: t.CDefine = 0x02
```
## 字符串常量
Viper 中的字符串字面量编译为 C 的字符串常量(`const char*`):
```python
msg: t.CConst | str = "Hello, World!"
serial.puts(msg)
```
也可以直接传递字符串字面量:
```python
serial.puts("Hello, World!")
```
## 类型转换
使用类型构造函数进行显式类型转换:
```python
x: t.CInt = 42
y: t.CUInt32T = t.CUInt32T(x) # (uint32_t)x
f: t.CFloat = float(x) # (float)x
i: t.CInt = int(f) # (int)f
```
### 指针类型转换
```python
ptr: t.CVoid | t.CPtr = some_ptr
int_val: t.CUInt64T = t.CUInt64T(ptr) # (uint64_t)ptr — 指针转整数
```
## 结构体实例化
> 此处不理解参见 ([05-classes.md 中 结构体实例化与初始化](05-classes.md#结构体实例化与初始化))
直接使用类名作为构造函数:
```python
info: fat32_types.fat32_fileinfo
dp: fat32_types.fat32_dirobj
```
带初始化的实例化:
```python
obj: MyClass = MyClass(arg1, arg2)
```
使用 `c.Addr` 获取实例指针:
```python
obj_ptr: MyClass | t.CPtr = c.Addr(MyClass(arg1, arg2))
```
## delete 语句
`del` 语句可用于调用对象的 `__del__` 或 `__delete__` 方法:
```python
del obj # 调用 obj.__del__() 或 obj.__delete__()
del arr[idx] # 调用 arr.__delitem__(idx)
```