feat: 初始化 Vety 项目并实现基础功能

- 添加虚拟机、解析器、AST 打印等核心模块
- 实现基本的语法解析和虚拟机执行简单语句
- 添加原生函数支持和简单的错误处理
- 创建测试框架和示例代码
- 编写项目文档和 README 文件
main
Natuie 2025-04-04 22:58:12 +08:00
parent b92a5aea72
commit dcc6d354a2
46 changed files with 5086 additions and 2 deletions

5
.gitignore vendored
View File

@ -50,3 +50,8 @@ modules.order
Module.symvers
Mkfile.old
dkms.conf
build/
.history/
cmake-build-debug/
.idea/
.vscode/

14
CMakeLists.txt Normal file
View File

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.28)
project(vety C)
set(CMAKE_C_STANDARD 11)
#
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
#
add_subdirectory(utils)
add_subdirectory(parser)
add_subdirectory(vm)

116
README.md
View File

@ -1,2 +1,114 @@
# vety-language
vety
# Vety 编程语言
Vety 是一个现代化的静态类型编程语言,专注于简洁性、安全性和高性能。它结合了多种现代编程语言的优秀特性,提供了优雅的语法和强大的类型系统。
## 主要特性
- **静态类型系统**:提供强大的类型检查和类型推导
- **现代化语法**:简洁直观的语法设计
- **函数注解**:支持 `@test`、`@debug` 等注解
- **变量声明**:支持 `let``const` 声明
- **复杂数据类型**:支持数组、映射等数据结构
- **表达式语法**:支持条件表达式、三元运算符等
- **错误处理**:内置的异常处理机制
- **内存安全**:自动内存管理
上面你就看看就行了,基本都没实现。
## 注意
现在只是暂存代码和测试,现在啥也没完成。
## 测试
``` bash
cmake --build build --target vety
./build/vety
```
## 项目结构
```
Vety
├── demo # 示例代码
├── doc # 文档
├── lib # vt库文件
├── parser # 语法分析器
├── test # 测试
├── utils # 工具
├── vm # 虚拟机
├── CMakeLists.txt # cmake文件
├── README.md # 项目说明
```
## 语法示例
### 基础语法
```vety
// 变量声明
let a: i32 = 1
const b: i32 = 2
// 数组
let arr: i32[] = [64, 34, 25, 12, 22, 11, 90]
// Map对象
let m: any = {
a: 6,
b: 9,
c: {
d: 9
}
}
// 函数定义
func add(a: i32, b: i32): i32 {
return a + b
}
```
### 控制流
```vety
// if 语句
if (condition) {
// ...
} else if (condition2) {
// ...
} else {
// ...
}
// for 循环
for (let i: i32 = 0; i < n; i++) {
// ...
}
// while 循环
while (condition) {
// ...
}
```
### 错误处理
```vety
try {
// 可能抛出异常的代码
} catch (e) {
// 处理异常
}
```
## 安装
目前 Vety 正在积极开发中,安装步骤将在稳定版本发布后提供。
## 使用文档
详细的语言规范和 API 文档正在编写中。
## 贡献
Vety是一个开源项目我们欢迎社区贡献。如果你发现了bug或有改进建议请提交issue或pull request。
## 许可证
MIT License

43
demo/annotate.vt Normal file
View File

@ -0,0 +1,43 @@
// 测试基础注解
@Test
func testFunction() {
// 函数体
}
// 测试带参数的注解
@Author("John Doe")
@Version(1.35)
let projectVersion = 4;
@Config(key="debug_mode", enabled=true)
let debugSettings = {
logLevel: "verbose",
timeout: 5000
};
// 测试嵌套注解
@Deprecated("Use newMethod instead")
func oldMethod() {
// 已弃用方法
}
// 测试参数化注解组合
@Metrics(track=true, category="performance")
@Retry(maxAttempts=3)
func networkCall() {
// 网络调用逻辑
}
// 测试无参数注解
@ReadOnly
var configData = [1, 2, 3];
// 测试复杂参数结构
@DatabaseConnection(
host="localhost",
port=5432,
options={ssl: true, poolSize: 5}
)
func connectToDatabase() {
// 数据库连接逻辑
}

5
demo/array.vt Normal file
View File

@ -0,0 +1,5 @@
// 数组字面量示例
let arr = [1, 2, 3, 4, 5];
let arr1: int32[] = [1, 2, 3, 4, 5];
let arr2: i32[8] = [1, 2, 3, 4, 5,6,6,8];
let numbers: array = [1, 2, 3, 4, 5]

3
demo/assignment.vt Normal file
View File

@ -0,0 +1,3 @@
let b:i32 = 6 + 5;
let c:i32 = 1 - 2 +3 +(1/8);

15
demo/control_stmt.vt Normal file
View File

@ -0,0 +1,15 @@
if (a >= 6 and a <= 10) {
print("a is between 6 and 10");
} else if (a >= 11 && a <= 15) {
print("a is between 11 and 15");
} else if (a >= 16 && a <= 20) {
print("a is between 16 and 20");
} else {
print("a is not between 6 and 20");
}
if (a == 6 or a == 10) {
print("a is 6 or 10");
} else {
print("a is not 6 or 10");
}

3
demo/float.vt Normal file
View File

@ -0,0 +1,3 @@
let f = 6.555;
let f1 = 6444848484.5554484897874;
let f2 = 58555.48484 +55.444 - 7.88 *44 - 4 /9.22 *(5.666+3)

BIN
demo/lang.ast Normal file

Binary file not shown.

50
demo/lexer_test.vt Normal file
View File

@ -0,0 +1,50 @@
// 测试多进制数字解析
let binary = 0b1010 // 二进制数字
let octal = 0755 // 八进制数字
let hex = 0xFF // 十六进制数字
// 测试浮点数和科学计数法
let float_num = 3.14159
let scientific = 1.23e-4
let big_num = 6.022E23
// 测试注解语法
@deprecated
func old_function() {
return 0
}
// 测试函数调用和命名参数
func test_function(name: string, age: i32) {
pri32("Name: ", name)
pri32("Age: ", age)
}
// 测试函数调用
test_function(name= "Alice", age= 25)
// 测试字符串字面量
let message = "Hello, World!"
// 测试布尔值
let is_active = true;
let is_done = false;
// 测试数组和映射
let numbers = [1, 2, 3, 4, 5]
let user = {
"name": "Bob",
"age": 30,
"scores": [85, 92, 78]
}
// 测试注释
/* 这是一个
多行注释
测试 */
// 测试运算符
let a = 10
let b = 20
let result = (a + b) * 2
let compare = a <= b && b >= 15

23
demo/loop.vt Normal file
View File

@ -0,0 +1,23 @@
let a:i32 = 4;
let b:i32 = 3;
let c:i32 = 56;
for (let i:i32 = 0; i < 10; i++) {
pri32(i);
}
while (true) {
pri32("infinite loop");
}
while (a > 0 and (b > 0 or c > 0)) {
pri32("infinite loop");
}
for (let i:i32 = 0; i < 10; i++) {
if (i == 5) {
break;
} else if (i == 3) {
continue;
}
}

47
demo/main.vt Normal file
View File

@ -0,0 +1,47 @@
let a: i32 = 1
const b: i32 = 2
let m:any = {
a:6,
b:9,
c: {
d:9
}
}
let a1:i32[] = [1,2,2,3]
func test(msg: i32): i32 {
print("a is 1")
return 0
}
@test(debug=6)
func add(a: i32, b: i32):i32 {
return a + b;
}
// 冒泡排序
func bubbleSort(arr: array, n: i32): void {
for(let i:i32 = 0; i < n-1; i++) {
for (let j:i32 = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
let temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
let arr: i32[] = [64, 34, 25, 12, 22, 11, 90];
let b1:i32 = 4, c:i32 = 5;
@test(debug=6)
@debug(a=1,4)
func add1(a: i32, b: i32[]):i32[] {
return a + b;
}
print("hi");

20
demo/map.vt Normal file
View File

@ -0,0 +1,20 @@
// map字面量示例
let map = {
name: "John",
age: 30,
isStudent: false
};
let map1 = {
b: "a",
w: {
w:2,
p:3
}
}
let map2 = {
a: { b:{ c: { d: 9 } } }
}
let map3 = {a:1,w:3,}

64
demo/operators.vt Normal file
View File

@ -0,0 +1,64 @@
// 位运算符示例
let a = 5 // 二进制: 0101
let b = 3 // 二进制: 0011
// 按位与运算
let and_result = a & b // 结果: 1 (0001)
// 按位或运算
let or_result = a | b // 结果: 7 (0111)
// 按位异或运算
let xor_result = a ^ b // 结果: 6 (0110)
// 按位取反运算
let not_result = ~a // 结果: -6
// 左移运算
let shl_result = a << 1 // 结果: 10 (1010)
// 右移运算
let shr_result = a >> 1 // 结果: 2 (0010)
// 自增自减运算符
let i = 0
i++ // i = 1
i-- // i = 0
++i // i = 1
--i // i = 0
// 复合赋值运算符
let x = 10
x += 5 // x = 15
x -= 3 // x = 12
x *= 2 // x = 24
x /= 4 // x = 6
x %= 4 // x = 2
// 位运算复合赋值运算符
let y = 12 // 二进制: 1100
y &= 10 // y = 8 (1000)
y |= 5 // y = 13 (1101)
y ^= 9 // y = 4 (0100)
y <<= 2 // y = 16 (10000)
y >>= 1 // y = 8 (1000)
// 三元表达式示例
let age = 20
let canVote = age >= 18 ? "可以投票" : "不能投票"
let score = 85
let result = score >= 90 ? "优秀" : (score >= 60 ? "及格" : "不及格")
// 打印结果
print("按位与结果: " + and_result)
print("按位或结果: " + or_result)
print("按位异或结果: " + xor_result)
print("按位取反结果: " + not_result)
print("左移结果: " + shl_result)
print("右移结果: " + shr_result)
print("最终i的值: " + i)
print("最终x的值: " + x)
print("位运算复合赋值后y的值: " + y)
print("投票权: " + canVote)
print("考试结果: " + result)

26
demo/pi.vt Normal file
View File

@ -0,0 +1,26 @@
func calculate_pi(terms: i32): f64 {
let sum: f64 = 0;
for (let i: i32 = 0; i < terms; i++) {
let term: f64 = 1.0 / (2 * i + 1);
if (i % 2 == 0) {
sum = sum + term;
} else {
sum = sum - term;
}
if (i % 100000 == 0) {
print(term);
}
}
return sum * 4; // 确保乘以4得到正确π值
}
func main(): i32 {
let terms: i32 = 1000000;
let pi: f64 = calculate_pi(terms);
let output: string = "Calculated π: " + pi.toString() + " (using " + terms.toString() + " terms)";
print(output);
return 0;
}

42
demo/test_example.vt Normal file
View File

@ -0,0 +1,42 @@
// 测试程序
// 简单函数定义
func add(i32: a, i32: b):i32 {
return a + b;
}
// 冒泡排序
func bubbleSort(arr: array, n: i32): void {
for(let i32:i = 0; i < n-1; i++) {
for (let j32:j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
let temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
// 主函数
func main():i32 {
let x:i32 = 10;
let y:i32 = 20;
let result = add(x, y);
// 测试表达式
let z:i32 = (x + y) * 2;
// 测试条件语句
if (z > 50) {
z = z - 10;
} else {
z = z + 10;
}
println("Hello, World!");
println("Result:", result);
print(bubbleSort(arr, n));
return z;
}

11
demo/try-catch.vt Normal file
View File

@ -0,0 +1,11 @@
// try-catch结构示例
try {
let result = 10 / 0;
println(result);
throw 9;
} catch (e) {
println("捕获到异常: " + e);
}
try {} catch(e) {}

132
doc/00_guide.md Normal file
View File

@ -0,0 +1,132 @@
# Vety语言入门指南
## 简介
Vety是一门现代化的编程语言旨在提供简洁、高效且安全的编程体验。它结合了静态类型系统的安全性和动态语言的灵活性使开发者能够快速构建可靠的应用程序。
## 设计理念
- **简洁性**:语法简单直观,减少不必要的复杂性
- **类型安全**:强大的静态类型系统,在编译时捕获潜在错误
- **性能优先**:高效的运行时性能,适合构建各类应用
- **原生集成**:良好的原生函数支持,易于与现有系统集成
- **模块化**:强大的模块系统,支持代码复用和组织
## 快速开始
### 1. 基本语法
```vety
// 变量声明
let message: string = "Hello, Vety!"
let number: i32 = 42
// 函数定义
func add(a: i32, b: i32): i32 {
return a + b
}
// 条件语句
if (number > 0) {
print("Positive number")
} else {
print("Non-positive number")
}
// 循环
for (i: i32 = 0; i < 5; i++) {
print(i)
}
```
### 2. 类型系统
Vety提供了丰富的内置类型
- **基本类型**
- `i32`32位整数
- `i64`64位整数
- `f64`64位浮点数
- `bool`:布尔值
- `string`:字符串
- `void`:无返回值
- **复合类型**
- `array<T>`:数组
- `map<K, V>`:映射
- 自定义结构体
### 3. 错误处理
Vety使用try-catch机制处理错误
```vety
try {
let result = some_risky_operation()
} catch(e) {
print("操作失败")
}
```
### 4. 模块系统
```vety
// 导入标准库模块
import io
import math
// 使用模块功能
let random_number = math.random(1, 100)
io.print("随机数:" + random_number)
```
### 5. 内置函数
Vety提供了一系列实用的内置函数
- `print()`:输出信息
- `read_line()`:读取用户输入
- `len()`:获取集合长度
- `type_of()`:获取值的类型
## 最佳实践
1. **命名规范**
- 变量和函数使用小写字母和下划线
- 类型名使用大驼峰命名法
2. **代码组织**
- 相关功能放在同一模块中
- 适当使用注释说明代码功能
3. **错误处理**
- 合理使用try-catch处理异常
- 提供有意义的错误信息
4. **性能优化**
- 避免不必要的内存分配
- 合理使用循环和递归
## 下一步
- 阅读更详细的[语法指南](01_basic_syntax.md)
- 了解[控制流](02_control_flow.md)
- 学习[函数和模块](03_functions_and_modules.md)
- 探索[复合类型](04_composite_types.md)
## 示例项目
查看`demo`目录中的示例代码了解更多Vety语言的实际应用
- `hello.vt`:基本语法示例
- `array.vt`:数组操作示例
- `function.vt`:函数使用示例
- `try-catch.vt`:错误处理示例
## 贡献
Vety是一个开源项目我们欢迎社区贡献。如果你发现了bug或有改进建议请提交issue或pull request。
## 许可证
Vety使用MIT许可证详细信息请查看LICENSE文件。

137
doc/01_basic_syntax.md Normal file
View File

@ -0,0 +1,137 @@
# Vety语言基础语法
## 1. 变量声明
Vety语言使用`let`关键字声明变量,使用`const`关键字声明常量。
```vety
// 变量声明
let name: string = "Vety"
let age: i32 = 1
// 常量声明
const PI: f64 = 3.14159
```
## 2. 基本数据类型
### 2.1 整数类型
Vety提供了有符号和无符号整数类型
- 有符号整数:
- `i8`: 8位有符号整数 (-128 到 127)
- `i16`: 16位有符号整数 (-32,768 到 32,767)
- `i32`: 32位有符号整数 (-2,147,483,648 到 2,147,483,647)
- `i64`: 64位有符号整数
- 无符号整数:
- `u8`: 8位无符号整数 (0 到 255)
- `u16`: 16位无符号整数 (0 到 65,535)
- `u32`: 32位无符号整数 (0 到 4,294,967,295)
- `u64`: 64位无符号整数
```vety
let age: i32 = 25
let distance: u64 = 1000000
```
### 2.2 浮点数类型
- `f32`: 32位浮点数
- `f64`: 64位浮点数
```vety
let pi: f32 = 3.14159
let e: f64 = 2.71828
```
### 2.3 布尔类型
`bool`类型表示布尔值,可以是`true`或`false`。
```vety
let is_valid: bool = true
let has_error: bool = false
```
### 2.4 字符串类型
`string`类型用于表示文本数据。字符串使用双引号(")包围。
```vety
let message: string = "Hello, Vety!"
let name: string = "John"
```
字符串支持转义字符:
- `\n`: 换行
- `\t`: 制表符
- `\r`: 回车
- `\"`: 双引号
- `\\`: 反斜杠
### 2.5 void类型
`void`类型表示没有返回值的函数的返回类型。
```vety
func print_message(): void {
// 函数体
}
```
## 3. 类型推断
Vety支持类型推断当变量的类型可以从初始值推断出来时可以省略类型注解
```vety
let name = "Vety" // 推断为string类型
let age = 25 // 推断为i32类型
let is_valid = true // 推断为bool类型
```
## 4. 基本运算符
### 4.1 算术运算符
- `+`: 加法
- `-`: 减法
- `*`: 乘法
- `/`: 除法
- `%`: 取模
### 4.2 比较运算符
- `==`: 等于
- `!=`: 不等于
- `<`: 小于
- `>`: 大于
- `<=`: 小于等于
- `>=`: 大于等于
### 4.3 逻辑运算符
- `&&`: 逻辑与
- `||`: 逻辑或
- `!`: 逻辑非
### 4.4 位运算符
- `&`: 按位与
- `|`: 按位或
- `^`: 按位异或
- `~`: 按位取反
## 5. 注释
Vety支持两种注释方式
```vety
// 单行注释
/*
多行注释
可以跨越多行
*/
```

131
doc/02_control_flow.md Normal file
View File

@ -0,0 +1,131 @@
# Vety语言控制流程
## 1. 条件语句
### 1.1 if-else语句
Vety使用`if`和`else`关键字进行条件控制:
```vety
let score: i32 = 85
if (score >= 90) {
print("优秀")
} else if (score >= 80) {
print("良好")
} else if (score >= 60) {
print("及格")
} else {
print("不及格")
}
```
条件表达式必须是布尔类型Vety不会进行隐式的真值转换。
### 1.2 条件表达式的组合
可以使用逻辑运算符组合多个条件:
```vety
let age: i32 = 25
let has_ticket: bool = true
if (age >= 18 && has_ticket) {
print("允许入场")
} else {
print("不允许入场")
}
```
## 2. 循环语句
### 2.1 while循环
`while`循环在条件为真时重复执行代码块:
```vety
let count: i32 = 0
while (count < 5) {
print(count)
count = count + 1
}
```
### 2.2 for循环
Vety的`for`循环支持遍历数组和范围:
```vety
// 遍历数组
let numbers: array = [1, 2, 3, 4, 5]
for (let i: i32 = 0; i < numbers.len; i++) {
print(numbers[i])
}
```
## 3. 循环控制
### 3.1 break语句
使用`break`语句可以提前退出循环:
```vety
let i: i32 = 0
while (true) {
if (i >= 5) {
break
}
print(i)
i = i + 1
}
```
### 3.2 continue语句
使用`continue`语句可以跳过当前循环的剩余部分,直接进入下一次循环:
```vety
for (let i: i32 = 0; i < 10; i++) {
if (i % 2 == 0) {
continue // 跳过偶数
}
print(i) // 只打印奇数
}
```
## 4. 错误处理
### 4.1 try-catch语句
Vety使用`try`和`catch`进行错误处理:
```vety
try {
// 可能产生错误的代码
let result = dangerous_operation()
} catch(e) {
// 错误处理代码
print("操作失败")
}
```
### 4.2 错误传播
函数可以使用返回值来传播错误:
```vety
func divide(a: i32, b: i32): i32 {
if b == 0 {
throw "除数不能为零"
}
return a / b
}
try {
let result = divide(10, 0)
} catch(e) {
print("除法运算失败")
}
```

View File

@ -0,0 +1,142 @@
# Vety语言函数和模块
## 1. 函数定义
### 1.1 基本函数定义
使用`func`关键字定义函数:
```vety
func add(a: i32, b: i32): i32 {
return a + b
}
// 无返回值的函数
func print_message(msg: string): void {
print(msg)
}
```
### 1.2 函数参数
函数参数必须指定类型:
```vety
func greet(name: string, age: i32): string {
return "Hello, " + name + "! You are " + age + " years old."
}
```
### 1.3 返回值
- 函数必须指定返回值类型
- 使用`return`语句返回值
- 如果函数不需要返回值,使用`void`类型
```vety
func calculate_area(width: f64, height: f64): f64 {
return width * height
}
```
## 2. 原生函数
使用`native`关键字声明原生函数,这些函数由底层实现:
```vety
native func print(message: string): void
native func read_line(): string
```
## 3. 模块系统
### 3.1 导入模块
使用`import`关键字导入其他模块:
```vety
import io // 导入标准库的io模块
import math // 导入数学模块
```
### 3.2 模块别名
可以使用`as`关键字为导入的模块指定别名:
```vety
import module_name as alias_name
```
## 4. 函数调用
### 4.1 基本调用
```vety
let result = add(5, 3)
print("Hello, World!")
```
### 4.2 模块函数调用
```vety
let current_time = time.now() // 调用模块中的函数
let random_number = math.random(1, 100)
```
## 5. 注解
使用`@`符号添加函数注解:
```vety
@deprecated
func old_function(): void {
// 已废弃的函数
}
@test
func test_feature(): void {
// 测试函数
}
```
## 6. 错误处理
函数可以抛出错误,调用者需要处理这些错误:
```vety
func divide(a: f64, b: f64): f64 {
if (b == 0) {
throw "Division by zero"
}
return a / b
}
try {
let result = divide(10.0, 0.0)
} catch(e) {
print("除法运算失败")
}
```
## 7. 最佳实践
- 函数名使用小写字母和下划线
- 函数应该只做一件事情
- 参数数量不宜过多
- 适当添加注释说明函数功能
- 处理所有可能的错误情况
```vety
// 好的函数示例
func calculate_average(numbers: array<): f64 {
if (numbers.length == 0) {
throw "Empty array"
}
let sum: f64 = 0.0
for num in numbers {
sum = sum + num
}
return sum / numbers.length
}
```

180
doc/04_composite_types.md Normal file
View File

@ -0,0 +1,180 @@
# Vety语言复合数据类型
## 1. 数组Array
### 1.1 数组声明
数组是相同类型元素的有序集合,使用方括号`[]`表示:
```vety
// 显式类型声明
let numbers: array = [1, 2, 3, 4, 5]
// 空数组
let empty_array: array = []
// 类型推断
let fruits = ["apple", "banana", "orange"]
```
### 1.2 数组访问
使用索引访问数组元素索引从0开始
```vety
let numbers = [10, 20, 30, 40, 50]
// 访问元素
let first = numbers[0] // 10
let second = numbers[1] // 20
// 修改元素
numbers[2] = 35 // [10, 20, 35, 40, 50]
```
### 1.3 数组操作
```vety
// 获取数组长度
let length = numbers.length
// 遍历数组
for num in numbers {
print(num)
}
// 使用索引遍历
for (let i = 0; i < numbers.length; i++) {
print(numbers[i])
}
```
## 2. 映射Map
### 2.1 映射声明
映射是键值对的集合,键和值可以是不同类型:
```vety
// 显式类型声明
let scores: map<string, i32> = {
"Alice": 95,
"Bob": 87,
"Charlie": 92
}
// 空映射
let empty_map: map<string, bool> = {}
// 类型推断
let config = {
"debug": true,
"port": 8080,
"host": "localhost"
}
```
### 2.2 映射访问
使用键访问映射中的值:
```vety
let scores = {"Alice": 95, "Bob": 87}
// 访问值
let alice_score = scores["Alice"] // 95
// 修改值
scores["Bob"] = 90 // {"Alice": 95, "Bob": 90}
// 添加新键值对
scores["Charlie"] = 88 // {"Alice": 95, "Bob": 90, "Charlie": 88}
```
### 2.3 映射操作
```vety
// 检查键是否存在
if "Alice" in scores {
print("Found Alice's score")
}
// 遍历映射
for key in scores {
let value = scores[key]
print(key + ": " + value)
}
```
## 3. 复合类型嵌套
数组和映射可以相互嵌套,创建更复杂的数据结构:
### 3.1 数组的数组
```vety
// 二维数组
let matrix: array<array<i32>> = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
// 访问嵌套元素
let value = matrix[1][2] // 6
```
### 3.2 映射的数组
```vety
// 用户列表
let users: array<map<string, string>> = [
{"name": "Alice", "email": "alice@example.com"},
{"name": "Bob", "email": "bob@example.com"}
]
// 访问嵌套数据
let first_user_email = users[0]["email"]
```
### 3.3 映射的映射
```vety
// 嵌套配置
let config: map<string, map<string, string>> = {
"database": {
"host": "localhost",
"port": "5432",
"name": "mydb"
},
"server": {
"host": "0.0.0.0",
"port": "8080"
}
}
// 访问嵌套值
let db_host = config["database"]["host"]
```
## 4. 最佳实践
- 选择合适的数据结构
- 注意类型一致性
- 处理边界情况
- 合理使用嵌套
```vety
// 好的实践示例
func process_scores(scores: map<string, i32>): f64 {
if scores.length == 0 {
return 0.0
}
let total: i32 = 0
for name in scores {
total = total + scores[name]
}
return total / scores.length
}
```

1
lib/io.vt Normal file
View File

@ -0,0 +1 @@
native func print(msg: string);

24
parser/CMakeLists.txt Normal file
View File

@ -0,0 +1,24 @@
#
add_library(vety_parser
lexer.c
lexer.h
ast.c
ast.h
parser.c
parser.h
error.c
error.h
ast_printer.c
ast_printer.h
)
#
target_include_directories(vety_parser PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/utils
)
#
target_link_libraries(vety_parser
vety_utils
)

40
parser/ast.c Normal file
View File

@ -0,0 +1,40 @@
//
// Created by Natuie on 2025/3/22.
//
#include <malloc.h>
#include <stdio.h>
#include "ast.h"
// 创建一个节点
ASTNode *create_node(NodeType type) {
ASTNode *node = malloc(sizeof(ASTNode));
node->type = type;
node->value = NULL;
node->line = 0;
node->column = 0;
node->children = NULL;
node->children_count = 0;
return node;
}
// 添加子节点
ASTNode add_child(ASTNode *parent, ASTNode *child) {
parent->children = realloc(parent->children, (parent->children_count + 1) * sizeof(ASTNode *));
if (parent->children == NULL) {
fprintf(stderr, "Memory allocation error\n");
exit(1);
}
parent->children[parent->children_count] = child;
parent->children_count++;
return *parent;
}
void set_node_position(ASTNode *node, int line, int column) {
node->line = line;
node->column = column;
}
void set_node_value(ASTNode *node, char *value) {
node->value = value;
}

146
parser/ast.h Normal file
View File

@ -0,0 +1,146 @@
//
// Created by Natuie on 2025/3/22.
//
#ifndef VETY_AST_H
#define VETY_AST_H
// 节点类型枚举
typedef enum {
// 程序结构
NODE_PROGRAM, // 程序根节点
NODE_BLOCK, // 代码块
NODE_EMPTY_BLOCK, // 空代码块
// 声明
NODE_VAR_DECL, // 变量声明
NODE_VAR_DECL_LIST, // 多变量声明列表
NODE_FUNC_DECL, // 函数声明
NODE_PARAM_LIST, // 参数列表
NODE_PARAM, // 单个参数
// 语句
NODE_IF_STMT, // if语句
NODE_ELSE_IF, // else if分支
NODE_ELSE_BLOCK, // else分支
NODE_WHILE_STMT, // while循环语句
NODE_FOR_STMT, // for循环语句
NODE_FOR_INIT, // for循环初始化部分
NODE_FOR_CONDITION, // for循环条件部分
NODE_FOR_UPDATE, // for循环更新部分
NODE_BREAK_STMT, // break语句
NODE_CONTINUE_STMT, // continue语句
NODE_RETURN_STMT, // return语句
NODE_EXPR_STMT, // 表达式语句
NODE_IMPORT_STMT, // import语句
NODE_IMPORT_PATH, // import路径
NODE_IMPORT_ALIAS, // import别名
NODE_REQUEST_STMT, // 请求语句
// 表达式
NODE_BINARY_EXPR, // 二元表达式
NODE_UNARY_EXPR, // 一元表达式
NODE_POSTFIX_EXPR, // 后缀表达式
NODE_CALL_EXPR, // 函数调用
NODE_MEMBER_EXPR, // 成员访问表达式
NODE_INDEX_EXPR, // 索引表达式
NODE_TERNARY_EXPR, // 三元表达式
// 标识符和字面量
NODE_IDENTIFIER, // 标识符
NODE_INT_LITERAL, // 整数字面量
NODE_FLOAT_LITERAL, // 浮点数字面量
NODE_STRING_LITERAL, // 字符串字面量
NODE_BOOL_LITERAL, // 布尔字面量
// 复合类型
NODE_ARRAY_TYPE, // 数组类型
NODE_ARRAY_LITERAL, // 数组字面量
NODE_ARRAY_ITEM, // 数组元素
NODE_MAP_LITERAL, // map字面量
NODE_MAP_ENTRY, // map条目
// 类型系统
NODE_TYPE_IDENTIFIER, // 类型标识符
NODE_TYPE_GENERIC, // 泛型类型 (如Array<T>)
NODE_GENERIC_PARAMS, // 泛型参数
NODE_TYPE_UNION, // 联合类型
NODE_CAST_EXPR, // 类型转换
// 注解系统
NODE_ANNOTATION, // 注解
NODE_ANNOTATIONS, // 注解列表
NODE_POS_ARG, // 位置参数
NODE_NAMED_ARG, // 命名参数
// 错误处理
NODE_TRY_STMT, // try语句
NODE_CATCH_BLOCK, // catch块
NODE_THROW_STMT, // throw语句
NODE_ERROR_NODE, // 错误节点
} NodeType;
// 操作符类型枚举
typedef enum {
OP_UNKNOWN,
// 算术运算符
OP_ADD, // +
OP_SUB, // -
OP_MUL, // *
OP_DIV, // /
OP_MOD, // %
// 逻辑运算符
OP_AND, // and
OP_OR, // or
OP_NOT, // not
// 比较运算符
OP_EQ, // ==
OP_NE, // !=
OP_LT, // <
OP_GT, // >
OP_LE, // <=
OP_GE, // >=
// 位运算符
OP_BITAND, // &
OP_BITOR, // |
OP_BITXOR, // ^
OP_BITNOT, // ~
OP_SHL, // <<
OP_SHR, // >>
// 赋值运算符
OP_ASSIGN, // =
OP_PLUS_ASSIGN, // +=
OP_MINUS_ASSIGN, // -=
OP_MUL_ASSIGN, // *=
OP_DIV_ASSIGN, // /=
OP_MOD_ASSIGN, // %=
OP_BITAND_ASSIGN, // &=
OP_BITOR_ASSIGN, // |=
OP_BITXOR_ASSIGN, // ^=
OP_SHL_ASSIGN, // <<=
OP_SHR_ASSIGN, // >>=
// 三元运算符
OP_TERNARY, // ? :
} OperatorType;
typedef struct ASTNode{
int line; // 行号
int column; // 列号
int children_count; // 子节点数量
char *value; // 值
NodeType type;
OperatorType op_type; // 操作符类型
struct ASTNode **children;
} ASTNode;
ASTNode *create_node(NodeType type);
ASTNode add_child(ASTNode *parent, ASTNode *child);
void set_node_position(ASTNode *node, int line, int column);
#endif //VETY_AST_H

94
parser/ast_printer.c Normal file
View File

@ -0,0 +1,94 @@
#include "ast_printer.h"
#include "parser.h"
#include <stdio.h>
#include <stdlib.h>
static void print_indent(int level, int is_last) {
for(int i=0; i<level; i++) {
printf(" ");
}
printf(is_last ? BRANCH_CORNER HORIZONTAL_LINE HORIZONTAL_LINE " " : NODE_CORNER HORIZONTAL_LINE HORIZONTAL_LINE " ");
}
static void print_node(const char* type, const char* value, int level, int is_last) {
print_indent(level, is_last);
printf(COLOR_TYPE "%s" COLOR_RESET, type);
if(value) {
printf(": " COLOR_LITERAL "%s" COLOR_RESET, value);
}
}
static void print_ast_recursive(ASTNode *node, int level, int is_last) {
if(!node) return;
switch(node->type) {
case NODE_PROGRAM: print_node("PROGRAM", node->value, level, is_last); break;
case NODE_VAR_DECL: print_node("VAR_DECL", node->value, level, is_last); break;
case NODE_FUNC_DECL: print_node("FUNC_DECL", node->value, level, is_last); break;
case NODE_PARAM: print_node("PARAM", node->value, level, is_last); break;
case NODE_BLOCK: print_node("BLOCK", node->value, level, is_last); break;
case NODE_IF_STMT: print_node("IF_STMT", node->value, level, is_last); break;
case NODE_WHILE_STMT: print_node("WHILE_STMT", node->value, level, is_last); break;
case NODE_FOR_STMT: print_node("FOR_STMT", node->value, level, is_last); break;
case NODE_BREAK_STMT: print_node("BREAK_STMT", node->value, level, is_last); break;
case NODE_CONTINUE_STMT: print_node("CONTINUE_STMT", node->value, level, is_last); break;
case NODE_RETURN_STMT: print_node("RETURN_STMT", node->value, level, is_last); break;
case NODE_EXPR_STMT: print_node("EXPR_STMT", node->value, level, is_last); break;
case NODE_IMPORT_STMT: print_node("IMPORT_STMT", node->value, level, is_last); break;
case NODE_REQUEST_STMT: print_node("REQUEST_STMT", node->value, level, is_last); break;
case NODE_BINARY_EXPR: print_node("BINARY_EXPR", node->value, level, is_last); break;
case NODE_UNARY_EXPR: print_node("UNARY_EXPR", node->value, level, is_last); break;
case NODE_POSTFIX_EXPR: print_node("POSTFIX_EXPR", node->value, level, is_last); break;
case NODE_CALL_EXPR: print_node("CALL_EXPR", node->value, level, is_last); break;
case NODE_MEMBER_EXPR: print_node("MEMBER_EXPR", node->value, level, is_last); break;
case NODE_IDENTIFIER: print_node("IDENTIFIER", node->value, level, is_last); break;
case NODE_INT_LITERAL: print_node("INT_LITERAL", node->value, level, is_last); break;
case NODE_FLOAT_LITERAL: print_node("FLOAT_LITERAL", node->value, level, is_last); break;
case NODE_STRING_LITERAL: print_node("STRING_LITERAL", node->value, level, is_last); break;
case NODE_BOOL_LITERAL: print_node("BOOL_LITERAL", node->value, level, is_last); break;
case NODE_ARRAY_LITERAL: print_node("ARRAY_LITERAL", node->value, level, is_last); break;
case NODE_MAP_LITERAL: print_node("MAP_LITERAL", node->value, level, is_last); break;
case NODE_INDEX_EXPR: print_node("INDEX_EXPR", node->value, level, is_last); break;
case NODE_ANNOTATION: print_node("ANNOTATION", node->value, level, is_last); break;
case NODE_ANNOTATIONS: print_node("ANNOTATIONS", node->value, level, is_last); break;
case NODE_NAMED_ARG: print_node("NAMED_ARG", node->value, level, is_last); break;
case NODE_TRY_STMT: print_node("TRY_STMT", node->value, level, is_last); break;
case NODE_CATCH_BLOCK: print_node("CATCH_BLOCK", node->value, level, is_last); break;
case NODE_MAP_ENTRY: print_node("MAP_ENTRY", node->value, level, is_last); break;
case NODE_THROW_STMT: print_node("THROW_STMT", node->value, level, is_last); break;
case NODE_TYPE_IDENTIFIER: print_node("TYPE_IDENTIFIER", node->value, level, is_last); break;
case NODE_ELSE_IF: print_node("ELSE_IF", node->value, level, is_last); break;
case NODE_ELSE_BLOCK: print_node("ELSE_BLOCK", node->value, level, is_last); break;
case NODE_FOR_INIT: print_node("FOR_INIT", node->value, level, is_last); break;
case NODE_FOR_CONDITION: print_node("FOR_CONDITION", node->value, level, is_last); break;
case NODE_FOR_UPDATE: print_node("FOR_UPDATE", node->value, level, is_last); break;
case NODE_VAR_DECL_LIST: print_node("VAR_DECL_LIST", node->value, level, is_last); break;
case NODE_PARAM_LIST: print_node("PARAM_LIST", node->value, level, is_last); break;
case NODE_ARRAY_ITEM: print_node("ARRAY_ITEM", node->value, level, is_last); break;
case NODE_POS_ARG: print_node("POS_ARG", node->value, level, is_last); break;
case NODE_EMPTY_BLOCK: print_node("EMPTY_BLOCK", node->value, level, is_last); break;
case NODE_ERROR_NODE: print_node("ERROR_NODE", node->value, level, is_last); break;
case NODE_TYPE_GENERIC: print_node("TYPE_GENERIC", node->value, level, is_last); break;
case NODE_TYPE_UNION: print_node("TYPE_UNION", node->value, level, is_last); break;
case NODE_IMPORT_PATH: print_node("IMPORT_PATH", node->value, level, is_last); break;
case NODE_IMPORT_ALIAS: print_node("IMPORT_ALIAS", node->value, level, is_last); break;
case NODE_CAST_EXPR: print_node("CAST_EXPR", node->value, level, is_last); break;
case NODE_GENERIC_PARAMS: print_node("GENERIC_PARAMS", node->value, level, is_last); break;
case NODE_TERNARY_EXPR: print_node("TERNARY_EXPR", node->value, level, is_last); break;
case NODE_ARRAY_TYPE: print_node("ARRAY_TYPE", node->value, level, is_last); break;
default:
print_node("UNKNOWN_NODE", node->value, level, is_last);
break;
}
printf(COLOR_COMMENT " (%d:%d)" COLOR_RESET "\n", node->line, node->column);
for(int i = 0; i < node->children_count; i++) {
print_ast_recursive(node->children[i], level + 1, i == node->children_count - 1);
}
}
void ast_pretty_print(ASTNode *node) {
printf(COLOR_KEY "AST Tree:\n" COLOR_RESET);
print_ast_recursive(node, 0, 1);
}

24
parser/ast_printer.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef AST_PRINTER_H
#define AST_PRINTER_H
#include "ast.h"
// Unicode符号定义
#define VERTICAL_LINE "│" // │
#define HORIZONTAL_LINE "─" // ─
#define BRANCH_CORNER "└" // └
#define NODE_CORNER "├" // ├
// ANSI颜色代码
#define COLOR_RESET "\033[0m"
#define COLOR_KEY "\033[94m" // 蓝色
#define COLOR_TYPE "\033[93m" // 黄色
#define COLOR_LITERAL "\033[92m" // 绿色
#define COLOR_COMMENT "\033[90m" // 灰色
#define COLOR_CYAN "\033[36m"
#define COLOR_ERROR "\033[91m" // 红色
// 打印入口函数
void ast_pretty_print(ASTNode *node);
#endif // AST_PRINTER_H

97
parser/error.c Normal file
View File

@ -0,0 +1,97 @@
//
// Created for error reporting
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parser.h"
#include "../utils/file.h"
// ANSI 转义序列颜色代码
#define ANSI_COLOR_RED "\033[31m"
#define ANSI_COLOR_YELLOW "\033[33m"
#define ANSI_COLOR_CYAN "\033[36m"
#define ANSI_COLOR_RESET "\033[0m"
// 获取指定行的代码
static char* get_line_at(const char* source, int line_number) {
if (source == NULL || line_number <= 0) return NULL;
int current_line = 1;
const char* line_start = source;
const char* p = source;
// 找到指定行的起始位置
while (*p != '\0') {
if (current_line == line_number) {
line_start = p;
break;
}
if (*p == '\n') {
current_line++;
}
p++;
}
// 如果没找到指定行返回NULL
if (current_line != line_number) return NULL;
// 找到行的结束位置
p = line_start;
while (*p != '\0' && *p != '\n') p++;
// 复制行内容
int length = p - line_start;
char* line = (char*)malloc(length + 1);
if (line == NULL) return NULL;
strncpy(line, line_start, length);
line[length] = '\0';
return line;
}
// 在指定位置打印错误指示箭头
static void print_error_indicator(int column) {
// 打印错误指示箭头
fprintf(stderr, " | " ANSI_COLOR_RED);
for (int i = 1; i < column; i++) {
fprintf(stderr, "~");
}
// 打印错误指示箭头
fprintf(stderr, "^" ANSI_COLOR_RESET "\n");
}
// 在当前token位置报告错误
void parser_error_at_current(Parser* parser, const char* message) {
parser_error_at(parser, &parser->current_token, message);
exit(0);
}
void parser_error_at(Parser* parser, Token* token, const char* message) {
if (parser->had_error) return;
// 添加错误到errors数组
parser->error_count++;
parser->errors = realloc(parser->errors, sizeof(*parser->errors) * parser->error_count);
parser->errors[parser->error_count - 1].message = strdup(message);
parser->errors[parser->error_count - 1].line = token->line;
parser->errors[parser->error_count - 1].column = token->column;
// 打印错误位置和消息
fprintf(stderr, ANSI_COLOR_CYAN "%s" ANSI_COLOR_RESET ":"
ANSI_COLOR_YELLOW "%d:%d" ANSI_COLOR_RESET ": "
ANSI_COLOR_RED "Syntax error: %s" ANSI_COLOR_RESET "\n",
parser->filename, token->line, token->column, message);
char* source = read_file(parser->filename);
if (source != NULL) {
char* line = get_line_at(source, token->line);
if (line != NULL) {
fprintf(stderr, "%4d | %s\n", token->line, line);
print_error_indicator(token->column);
free(line);
}
free(source);
}
}

15
parser/error.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef VETY_ERROR_H
#define VETY_ERROR_H
#include "parser.h"
// 在当前token位置报告错误
void parser_error_at_current(Parser* parser, const char* message);
// 在上一个token位置报告错误
void parser_error(Parser* parser, const char* message);
// 在指定token位置报告错误
void parser_error_at(Parser* parser, Token* token, const char* message);
#endif // VETY_ERROR_H

556
parser/lexer.c Normal file
View File

@ -0,0 +1,556 @@
//
// Created by Natuie on 2025/3/22.
//
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include "lexer.h"
void lexer_init(Lexer *lexer, char *source) {
lexer->source = source;
lexer->current_pos = 0;
lexer->line = 1;
lexer->column = 1;
}
void lexer_free(Lexer *lexer) {
free(lexer->source);
}
// 跳过空白字符
void skip_whitespace_and_comments(Lexer *lexer) {
while (1) {
char c = lexer->source[lexer->current_pos];
if (c == ' ' || c == '\t' || c == '\r') {
lexer->current_pos++;
lexer->column++;
} else if (c == '\n') {
lexer->current_pos++;
lexer->line++;
lexer->column = 1;
} else if (c == '/' && lexer->source[lexer->current_pos+1] == '/') {
lexer->current_pos += 2; // 跳过"//"
lexer->column += 2;
while (lexer->source[lexer->current_pos] != '\n' &&
lexer->source[lexer->current_pos] != '\0') {
lexer->current_pos++;
lexer->column++;
}
// 处理换行符
if (lexer->source[lexer->current_pos] == '\n') {
lexer->current_pos++;
lexer->line++;
lexer->column = 1;
} else {
// 文件末尾
break;
}
} else if (c == '/' && lexer->source[lexer->current_pos+1] == '*') {
lexer->current_pos += 2; // 跳过"/*"
lexer->column += 2;
int in_comment = 1;
while (in_comment && lexer->source[lexer->current_pos] != '\0') {
c = lexer->source[lexer->current_pos];
if (c == '\n') {
lexer->line++;
lexer->column = 1;
} else if (c == '*' && lexer->source[lexer->current_pos+1] == '/') {
// 结束注释
lexer->current_pos += 2;
lexer->column += 2;
in_comment = 0;
} else {
lexer->column++;
}
lexer->current_pos++;
}
} else {
break;
}
}
}
// 读取标识符
Token read_identifier(Lexer *lexer) {
Token token;
int pos = 0;
token.type = TOKEN_IDENTIFIER;
token.line = lexer->line;
token.column = lexer->column;
while (isalnum(lexer->source[lexer->current_pos]) ||
(lexer->source[lexer->current_pos] == '_')) {
if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
}
token.value[pos] = '\0';
// 关键字识别
if (strcmp(token.value, "func") == 0) token.type = TOKEN_FUNC;
else if (strcmp(token.value, "let") == 0) token.type = TOKEN_LET;
else if (strcmp(token.value, "const") == 0) token.type = TOKEN_CONST;
else if (strcmp(token.value, "i8") == 0) token.type = TOKEN_TYPE_I8;
else if (strcmp(token.value, "i16") == 0) token.type = TOKEN_TYPE_I16;
else if (strcmp(token.value, "i32") == 0) token.type = TOKEN_TYPE_I32;
else if (strcmp(token.value, "i64") == 0) token.type = TOKEN_TYPE_I64;
else if (strcmp(token.value, "u8") == 0) token.type = TOKEN_TYPE_U8;
else if (strcmp(token.value, "u16") == 0) token.type = TOKEN_TYPE_U16;
else if (strcmp(token.value, "u32") == 0) token.type = TOKEN_TYPE_U32;
else if (strcmp(token.value, "u64") == 0) token.type = TOKEN_TYPE_U64;
else if (strcmp(token.value, "f32") == 0) token.type = TOKEN_TYPE_F32;
else if (strcmp(token.value, "f64") == 0) token.type = TOKEN_TYPE_F64;
else if (strcmp(token.value, "void") == 0) token.type = TOKEN_TYPE_VOID;
else if (strcmp(token.value, "any") == 0) token.type = TOKEN_TYPE_ANY;
else if (strcmp(token.value, "int") == 0) token.type = TOKEN_INT;
else if (strcmp(token.value, "float") == 0) token.type = TOKEN_FLOAT;
else if (strcmp(token.value, "string") == 0) token.type = TOKEN_STRING;
else if (strcmp(token.value, "bool") == 0) token.type = TOKEN_BOOL;
else if (strcmp(token.value, "array") == 0) token.type = TOKEN_ARRAY;
else if (strcmp(token.value, "map") == 0) token.type = TOKEN_MAP;
else if (strcmp(token.value, "true") == 0) token.type = TOKEN_TRUE;
else if (strcmp(token.value, "false") == 0) token.type = TOKEN_FALSE;
else if (strcmp(token.value, "if") == 0) token.type = TOKEN_IF;
else if (strcmp(token.value, "else") == 0) token.type = TOKEN_ELSE;
else if (strcmp(token.value, "while") == 0) token.type = TOKEN_WHILE;
else if (strcmp(token.value, "for") == 0) token.type = TOKEN_FOR;
else if (strcmp(token.value, "break") == 0) token.type = TOKEN_BREAK;
else if (strcmp(token.value, "continue") == 0) token.type = TOKEN_CONTINUE;
else if (strcmp(token.value, "return") == 0) token.type = TOKEN_RETURN;
else if (strcmp(token.value, "import") == 0) token.type = TOKEN_IMPORT;
else if (strcmp(token.value, "as") == 0) token.type = TOKEN_AS;
else if (strcmp(token.value, "and") == 0) token.type = TOKEN_AND;
else if (strcmp(token.value, "or") == 0) token.type = TOKEN_OR;
else if (strcmp(token.value, "in") == 0) token.type = TOKEN_IN;
else if (strcmp(token.value, "native") == 0) token.type = TOKEN_NATIVE;
else if (strcmp(token.value, "try") == 0) token.type = TOKEN_TRY;
else if (strcmp(token.value, "catch") == 0) token.type = TOKEN_CATCH;
else if (strcmp(token.value, "throw") == 0) token.type = TOKEN_THROW;
else token.type = TOKEN_IDENTIFIER;
return token;
}
// 读取数字
Token read_number(Lexer *lexer) {
Token token;
int pos = 0;
int has_dot = 0;
int has_exp = 0;
int base = 10; // 默认十进制
token.line = lexer->line;
token.column = lexer->column;
// 检查是否是特殊进制数
if (lexer->source[lexer->current_pos] == '0') {
char next = lexer->source[lexer->current_pos + 1];
if (next == 'b' || next == 'B') { // 二进制
base = 2;
token.value[pos++] = '0';
token.value[pos++] = next;
lexer->current_pos += 2;
lexer->column += 2;
// 读取二进制数字
while (lexer->source[lexer->current_pos] == '0' ||
lexer->source[lexer->current_pos] == '1') {
if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
}
if (pos <= 2) { // 只有前缀没有数字
fprintf(stderr, "Error: Invalid binary number at line %d, column %d\n",
lexer->line, lexer->column);
token.type = TOKEN_ERROR;
return token;
}
} else if (next == 'x' || next == 'X') { // 十六进制
base = 16;
token.value[pos++] = '0';
token.value[pos++] = next;
lexer->current_pos += 2;
lexer->column += 2;
// 读取十六进制数字
while (isxdigit(lexer->source[lexer->current_pos])) {
if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
}
if (pos <= 2) { // 只有前缀没有数字
fprintf(stderr, "Error: Invalid hexadecimal number at line %d, column %d\n",
lexer->line, lexer->column);
token.type = TOKEN_ERROR;
return token;
}
} else { // 八进制
base = 8;
token.value[pos++] = '0';
lexer->current_pos++; // 跳过0
lexer->column++;
// 读取后续的八进制数字
while (lexer->source[lexer->current_pos] >= '0' &&
lexer->source[lexer->current_pos] <= '7') {
if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
}
// 检查是否后续字符是数字但超出八进制范围
if (isdigit(lexer->source[lexer->current_pos])) {
fprintf(stderr, "Error: Invalid octal number at line %d, column %d\n",
lexer->line, lexer->column);
token.type = TOKEN_ERROR;
return token;
}
}
}
// 如果不是特殊进制,按照十进制处理
if (base == 10) {
// 读取整数部分
while (isdigit(lexer->source[lexer->current_pos])) {
if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
}
// 处理小数点和小数部分
if (lexer->source[lexer->current_pos] == '.') {
has_dot = 1;
if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
// 检查小数点后是否有数字
if (!isdigit(lexer->source[lexer->current_pos])) {
fprintf(stderr, "Error: Expected digit after decimal point at line %d, column %d\n",
lexer->line, lexer->column);
token.type = TOKEN_ERROR;
return token;
}
// 读取小数部分
while (isdigit(lexer->source[lexer->current_pos])) {
if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
}
}
// 处理科学计数法
if (lexer->source[lexer->current_pos] == 'e' || lexer->source[lexer->current_pos] == 'E') {
has_exp = 1;
if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
// 处理指数的符号
if (lexer->source[lexer->current_pos] == '+' || lexer->source[lexer->current_pos] == '-') {
if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
}
// 读取指数部分
if (!isdigit(lexer->source[lexer->current_pos])) {
// 错误处理:科学计数法后面必须有数字
fprintf(stderr, "Error: Invalid scientific notation at line %d, column %d\n",
lexer->line, lexer->column);
token.type = TOKEN_ERROR;
return token;
}
while (isdigit(lexer->source[lexer->current_pos])) {
if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
}
}
}
token.value[pos] = '\0';
token.type = (has_dot || has_exp) ? TOKEN_FLOAT_LITERAL : TOKEN_INT_LITERAL;
return token;
}
// 读取字符串
Token read_string(Lexer *lexer) {
Token token;
int pos = 0;
token.type = TOKEN_STRING_LITERAL;
token.line = lexer->line;
token.column = lexer->column;
lexer->current_pos++; // 跳过引号
lexer->column++;
while (lexer->source[lexer->current_pos] != '"') {
if (lexer->source[lexer->current_pos] == '\0') {
token.type = TOKEN_ERROR;
strcpy(token.value, "Unterminated string literal");
return token;
}
if (lexer->source[lexer->current_pos] == '\\') {
lexer->current_pos++;
lexer->column++;
if (pos >= 255) continue;
switch (lexer->source[lexer->current_pos]) {
case 'n': token.value[pos++] = '\n'; break;
case 't': token.value[pos++] = '\t'; break;
case 'r': token.value[pos++] = '\r'; break;
case '\"': token.value[pos++] = '\"'; break;
case '\\': token.value[pos++] = '\\'; break;
default:
fprintf(stderr, "Error: Invalid escape sequence '\\%c' at line %d, column %d\n",
lexer->source[lexer->current_pos], lexer->line, lexer->column);
token.type = TOKEN_ERROR;
return token;
}
} else if (pos < 255) {
token.value[pos++] = lexer->source[lexer->current_pos];
}
lexer->current_pos++;
lexer->column++;
}
token.value[pos] = '\0';
if (lexer->source[lexer->current_pos] == '"') {
lexer->current_pos++;
lexer->column++;
} else {
token.type = TOKEN_ERROR;
strcpy(token.value, "Unterminated string literal");
}
return token;
}
Token lexer_next_token(Lexer *lexer) {
skip_whitespace_and_comments(lexer);
char c = lexer->source[lexer->current_pos];
Token token;
token.line = lexer->line;
token.column = lexer->column;
token.value[0] = '\0';
if (c == '\0') {
token.type = TOKEN_EOF;
return token;
} else if (isalpha(c) || (c == '_')) {
return read_identifier(lexer);
} else if (isdigit(c)) {
return read_number(lexer);
} else if (c == '"') {
return read_string(lexer);
} else {
token.value[0] = c;
token.value[1] = '\0';
lexer->current_pos++;
lexer->column++;
// 处理双字符和三字符操作符
char next_c = lexer->source[lexer->current_pos];
char next_next_c = (next_c != '\0') ? lexer->source[lexer->current_pos + 1] : '\0';
// 处理三字符操作符
if (c == '<' && next_c == '<' && next_next_c == '=') {
token.value[1] = '<';
token.value[2] = '=';
token.value[3] = '\0';
lexer->current_pos += 2;
lexer->column += 2;
token.type = TOKEN_SHL_ASSIGN;
return token;
} else if (c == '>' && next_c == '>' && next_next_c == '=') {
token.value[1] = '>';
token.value[2] = '=';
token.value[3] = '\0';
lexer->current_pos += 2;
lexer->column += 2;
token.type = TOKEN_SHR_ASSIGN;
return token;
}
// 处理双字符操作符
if (c == '=' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_EQ_EQ;
return token;
} else if (c == '!' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_NE;
return token;
} else if (c == '<' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_LE;
return token;
} else if (c == '>' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_GE;
return token;
} else if (c == '+' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_PLUS_ASSIGN;
return token;
} else if (c == '-' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_MINUS_ASSIGN;
return token;
} else if (c == '*' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_MUL_ASSIGN;
return token;
} else if (c == '/' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_DIV_ASSIGN;
return token;
} else if (c == '%' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_MOD_ASSIGN;
return token;
} else if (c == '&' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_BITAND_ASSIGN;
return token;
} else if (c == '|' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_BITOR_ASSIGN;
return token;
} else if (c == '^' && next_c == '=') {
token.value[1] = '=';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_BITXOR_ASSIGN;
return token;
} else if (c == '<' && next_c == '<') {
token.value[1] = '<';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_SHL;
return token;
} else if (c == '>' && next_c == '>') {
token.value[1] = '>';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_SHR;
return token;
} else if (c == '+' && next_c == '+') {
token.value[1] = '+';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_PLUS_PLUS;
return token;
} else if (c == '-' && next_c == '-') {
token.value[1] = '-';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_MINUS_MINUS;
return token;
} else if (c == '&' && next_c == '&') {
token.value[1] = '&';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_AND;
return token;
} else if (c == '|' && next_c == '|') {
token.value[1] = '|';
token.value[2] = '\0';
lexer->current_pos++;
lexer->column++;
token.type = TOKEN_OR;
return token;
}
switch (c) {
case ':': token.type = TOKEN_COLON; break;
case '=': token.type = TOKEN_EQ; break;
case '(': token.type = TOKEN_LPAREN; break;
case ')': token.type = TOKEN_RPAREN; break;
case '{': token.type = TOKEN_LBRACE; break;
case '}': token.type = TOKEN_RBRACE; break;
case '[': token.type = TOKEN_LBRACKET; break;
case ']': token.type = TOKEN_RBRACKET; break;
case ',': token.type = TOKEN_COMMA; break;
case ';': token.type = TOKEN_SEMICOLON; break;
case '+': token.type = TOKEN_PLUS; break;
case '-': token.type = TOKEN_MINUS; break;
case '*': token.type = TOKEN_STAR; break;
case '/': token.type = TOKEN_SLASH; break;
case '.': token.type = TOKEN_DOT; break;
case '<': token.type = TOKEN_LT; break;
case '>': token.type = TOKEN_GT; break;
case '!': token.type = TOKEN_BANG; break;
case '|': token.type = TOKEN_BITOR; break;
case '&': token.type = TOKEN_BITAND; break;
case '^': token.type = TOKEN_BITXOR; break;
case '%': token.type = TOKEN_MOD; break;
case '@': token.type = TOKEN_AT; break;
case '~': token.type = TOKEN_TILDE; break;
case '?': token.type = TOKEN_QUESTION; break;
default:
token.type = TOKEN_ERROR;
sprintf(token.value, "Unexpected character: %c", c);
}
return token;
}
}

132
parser/lexer.h Normal file
View File

@ -0,0 +1,132 @@
//
// Created by Natuie on 2025/3/22.
//
#ifndef VETY_LEXER_H
#define VETY_LEXER_H
typedef enum {
TOKEN_EOF, // 文件结束
TOKEN_IDENTIFIER, // 标识符
TOKEN_INT, // 整数
TOKEN_FLOAT, // 浮点数
TOKEN_STRING, // 字符串
TOKEN_KEYWORD, // 关键字
TOKEN_ASSIGN, // 赋值
TOKEN_PLUS, // 加号
TOKEN_MINUS, // 减号
TOKEN_MUL, // 乘号
TOKEN_DIV, // 除号
TOKEN_MOD, // 取模
TOKEN_PLUS_PLUS, // 自增
TOKEN_MINUS_MINUS, // 自减
TOKEN_PLUS_ASSIGN, // +=
TOKEN_MINUS_ASSIGN, // -=
TOKEN_MUL_ASSIGN, // *=
TOKEN_DIV_ASSIGN, // /=
TOKEN_MOD_ASSIGN, // %=
TOKEN_LPAREN, // 左括号
TOKEN_RPAREN, // 右括号
TOKEN_LBRACE, // 左花括号
TOKEN_RBRACE, // 右花括号
TOKEN_LBRACKET, // 左中括号
TOKEN_RBRACKET, // 右中括号
TOKEN_COMMA, // 逗号
TOKEN_SEMICOLON, // 分号
TOKEN_COLON, // 冒号
TOKEN_DOT, // 点号
TOKEN_QUESTION, // 问号
TOKEN_LT, // 小于号
TOKEN_GT, // 大于号
TOKEN_LE, // 小于等于号
TOKEN_GE, // 大于等于号
TOKEN_EQ, // 等于号
TOKEN_EQ_EQ, // 等于等于号
TOKEN_NE, // 不等于号
TOKEN_AND, // 与运算符
TOKEN_OR, // 或运算符
TOKEN_NOT, // 非运算符
TOKEN_BITAND, // 按位与运算符
TOKEN_BITOR, // 按位或运算符
TOKEN_BITXOR, // 按位异或运算符
TOKEN_TILDE, // ~
TOKEN_SHL, // 左移运算符
TOKEN_SHR, // 右移运算符
TOKEN_BITAND_ASSIGN, // &=
TOKEN_BITOR_ASSIGN, // |=
TOKEN_BITXOR_ASSIGN, // ^=
TOKEN_SHL_ASSIGN, // <<=
TOKEN_SHR_ASSIGN, // >>=
TOKEN_IF, // if 关键字
TOKEN_ELSE, // else 关键字
TOKEN_WHILE, // while 关键字
TOKEN_FOR, // for 关键字
TOKEN_RETURN, // return 关键字
TOKEN_BREAK, // break 关键字
TOKEN_CONTINUE, // continue 关键字
TOKEN_LET, // let 关键字
TOKEN_CONST, // const 关键字
TOKEN_TRUE, // true 关键字
TOKEN_FALSE, // false 关键字
TOKEN_NULL, // null 关键字
TOKEN_IMPORT, // import 关键字
TOKEN_AS, // as 关键字
TOKEN_IN, // in 关键字
TOKEN_NATIVE, // native 关键字
TOKEN_FUNC, // func 关键字
TOKEN_BOOL, // bool 关键字
TOKEN_MAP, // map 关键字
TOKEN_ARRAY, // array 关键字
// 类型关键字
TOKEN_TYPE_I8, // i8类型
TOKEN_TYPE_I16, // i16类型
TOKEN_TYPE_I32, // i32类型
TOKEN_TYPE_I64, // i64类型
TOKEN_TYPE_U8, // u8类型
TOKEN_TYPE_U16, // u16类型
TOKEN_TYPE_U32, // u32类型
TOKEN_TYPE_U64, // u64类型
TOKEN_TYPE_F32, // f32类型
TOKEN_TYPE_F64, // f64类型
TOKEN_TYPE_ANY, // any类型
TOKEN_TYPE_VOID, // void类型
TOKEN_INT_LITERAL, // 整数字面量
TOKEN_FLOAT_LITERAL, // 浮点数字面量
TOKEN_STRING_LITERAL, // 字符串字面量
TOKEN_BOOL_LITERAL, // 布尔字面量
TOKEN_STAR, // 星号
TOKEN_SLASH, // 斜杠
TOKEN_BANG, // 感叹号
TOKEN_AT, // 注解符号
TOKEN_TRY, // try关键字
TOKEN_CATCH, // catch关键字
TOKEN_ERROR, // 错误
TOKEN_THROW, // throw关键字
} TokenType;
typedef struct {
TokenType type;
char value[256];
int line;
int column;
} Token;
typedef struct {
char *source;
int length;
int line;
int column;
int current_pos;
} Lexer;
void skip_whitespace_and_comments(Lexer *lexer);
Token read_identifier(Lexer *lexer);
Token read_number(Lexer *lexer);
Token read_string(Lexer *lexer);
void lexer_init(Lexer *lexer, char *source);
void lexer_free(Lexer *lexer);
Token lexer_next_token(Lexer *lexer);
Token lexer_back_token(Lexer *lexer);
#endif //VETY_LEXER_H

1365
parser/parser.c Normal file

File diff suppressed because it is too large Load Diff

70
parser/parser.h Normal file
View File

@ -0,0 +1,70 @@
//
// Created by Natuie on 2025/3/22.
//
#ifndef VETY_PARSER_H
#define VETY_PARSER_H
#include "lexer.h"
#include "ast.h"
// 运算符优先级枚举
typedef enum {
PREC_NONE, // 无优先级
PREC_ASSIGNMENT, // =, +=, etc
PREC_TERNARY, // ?:
PREC_OR, // ||
PREC_AND, // &&
PREC_EQUALITY, // ==, !=
PREC_COMPARISON, // <, >, <=, >=
PREC_BITWISE, // |, &, ^
PREC_SHIFT, // <<, >>
PREC_TERM, // +, -
PREC_FACTOR, // *, /, %
PREC_UNARY, // !, -, ~
PREC_CALL, // (), [], .
PREC_CAST, // as
PREC_PRIMARY // 基本表达式
} OperatorPrecedence;
typedef struct {
Lexer *lexer;
Token current_token;
Token previous_token;
char *filename;
int had_error; // 标记是否发生错误
int error_count; // 错误计数
struct {
char* message;
int line;
int column;
} *errors; // 错误信息数组
} Parser;
void parser_init(Parser* parser, Lexer* lexer, char* filename);
void parser_free(Parser* parser);
Token consume_token(Parser* parser);
int match_token(Parser* parser, TokenType type);
Token expect_token(Parser* parser, TokenType type);
ASTNode* parse_statement(Parser* parser);
int get_precedence(TokenType type);
ASTNode* parse_unary(Parser* parser);
ASTNode* parse_expression(Parser* parser);
ASTNode* parse_expression_with_precedence(Parser* parser, int precedence);
ASTNode* parse_primary(Parser* parser);
ASTNode* parse_block(Parser* parser);
ASTNode* parse_program(Parser* parser);
ASTNode* parse_var_declaration(Parser* parser);
ASTNode* parse_function_declaration(Parser* parser);
ASTNode* parse_import_statement(Parser* parser);
ASTNode* parse_break_statement(Parser* parser);
ASTNode* parse_continue_statement(Parser* parser);
ASTNode* parse_expression_statement(Parser* parser);
ASTNode* parse_while_statement(Parser* parser);
ASTNode* parse_for_statement(Parser* parser);
ASTNode* parse_if_statement(Parser* parser);
ASTNode* parse_return_statement(Parser* parser);
ASTNode* parse_throw_statement(Parser* parser);
ASTNode* parse_annotation(Parser* parser);
#endif //VETY_PARSER_H

37
test/Makefile Normal file
View File

@ -0,0 +1,37 @@
CC = gcc
CFLAGS = -Wall -Wextra -g -I../parser -I../utils
OBJ_DIR = ../build/test
TARGET = $(OBJ_DIR)/test
SRCS = test.c ../parser/parser.c ../parser/lexer.c ../parser/ast.c ../parser/ast_printer.c ../parser/error.c ../utils/file.c ../utils/log.c
# 将源文件转换为目标文件列表
OBJS = $(SRCS:%.c=$(OBJ_DIR)/%.o)
# 创建目录的函数
create_dirs := $(shell if not exist "$(OBJ_DIR)" mkdir "$(OBJ_DIR)" && \
if not exist "$(OBJ_DIR)\..\parser" mkdir "$(OBJ_DIR)\..\parser" && \
if not exist "$(OBJ_DIR)\..\utils" mkdir "$(OBJ_DIR)\..\utils")
# 默认目标
all: $(TARGET)
# 链接目标文件生成可执行文件
$(TARGET): $(OBJS)
$(CC) $(OBJS) -o $(TARGET)
# 编译源文件为目标文件的规则
$(OBJ_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# 清理规则
clean:
del /F /Q $(OBJ_DIR)\*.o
del /F /Q $(TARGET).exe
# 运行测试
test: $(TARGET)
$(TARGET)
.PHONY: all clean test

22
test/main.vt Normal file
View File

@ -0,0 +1,22 @@
import io
// 主函数
func main():i32 {
print("hi");
return 0;
}
let arr: int[6] = [1, 2, 3];
let dict: map<K, V> = {
"a": 1,
"b": 2,
"c": 3
};
let a: int = 1;
printf(a);
let x = data as i8;
let y = ((a + b) as i32);
printf(66 as string);
printf((data as string));
printfss(5 + data as string);
printfss(data + string2);
//printfss(data as string);

92
test/test.c Normal file
View File

@ -0,0 +1,92 @@
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "../parser/parser.h"
#include "../parser/ast_printer.h"
#include "../utils/file.h"
#define DEMO_DIR "../demo/"
#define VT_EXT ".vt"
#define PASS_SYMBOL "✓" // Unicode checkmark
// Function to test a single .vt file
void test_single_file(const char* filename, int isPT) {
printf("Testing file: %s \n", filename);
// 初始化词法分析器和语法分析器
FILE* file = fopen(filename, "r");
if (!file) {
printf("Error opening file: %s\n", filename);
return;
}
char* source = read_file(filename);
Lexer lexer;
lexer_init(&lexer, source);
Parser parser;
parser_init(&parser, &lexer, (char*)filename);
// 解析整个文件
ASTNode* ast = parse_program(&parser);
printf(" => ");
if (parser.had_error) {
printf("\n");
} else {
printf("%s\n", PASS_SYMBOL);
if (isPT) ast_pretty_print(ast);
}
// 清理资源
fclose(file);
}
// Function to test all .vt files in demo directory
void test_all_demo_files() {
DIR *dir;
struct dirent *entry;
dir = opendir(DEMO_DIR);
if (dir == NULL) {
perror("Error opening demo directory");
return;
}
printf("Testing all .vt files in demo directory:\n");
while ((entry = readdir(dir)) != NULL) {
char path[256];
snprintf(path, sizeof(path), "%s%s", DEMO_DIR, entry->d_name);
struct stat file_stat;
if (stat(path, &file_stat) == 0 && S_ISREG(file_stat.st_mode)) {
char *ext = strrchr(entry->d_name, '.');
if (ext && strcmp(ext, VT_EXT) == 0) {
char* filepath = malloc(strlen(DEMO_DIR) + strlen(entry->d_name) + 1);
if (filepath == NULL) {
perror("Memory allocation failed");
continue;
}
strcpy(filepath, DEMO_DIR);
strcat(filepath, entry->d_name);
test_single_file(filepath, 0);
}
}
}
closedir(dir);
}
int main() {
system("chcp 65001");
test_all_demo_files();
test_single_file("main.vt", 1);
//test_single_file("../demo/operators.vt", 1);
// Example of testing single file
// test_single_file("example.vt");
return 0;
}

11
utils/CMakeLists.txt Normal file
View File

@ -0,0 +1,11 @@
#
add_library(vety_utils STATIC
file.c
file.h
../vm/main.c
)
#
target_include_directories(vety_utils PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

68
utils/file.c Normal file
View File

@ -0,0 +1,68 @@
//
// Created by Natuie on 2025/3/22.
//
#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>
#include <string.h>
#include "file.h"
// 读取文件
char* read_file(const char* filename) {
FILE* file = fopen(filename, "r");
if (!file) {
fprintf(stderr, "Failed to read file: %s\n", filename);
return NULL;
}
// 获取文件大小
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
rewind(file);
// 分配内存
char* buffer = (char*)malloc(file_size + 1);
if (!buffer) {
fprintf(stderr, "内存分配失败\n");
fclose(file);
return NULL;
}
// 读取文件内容
size_t read_size = fread(buffer, 1, file_size, file);
buffer[read_size] = '\0'; // 添加字符串结束符
fclose(file);
return buffer;
}
// 文件是否存在
bool file_exists(const char* filename) {
FILE* file = fopen(filename, "r");
if (file) {
fclose(file);
return true;
}
return false;
}
// 构建目录
// 处理'./'与'../'还有'/'等目录相加
char* build_path(const char* path1, const char* path2) {
size_t len1 = strlen(path1);
size_t len2 = strlen(path2);
char* result = (char*)malloc(len1 + len2 + 2); // 加上可能的'/'和'\0'
if (!result) {
fprintf(stderr, "内存分配失败\n");
return NULL;
}
strcpy(result, path1);
if (path1[len1 - 1] != '/') {
strcat(result, "/");
}
strcat(result, path2);
return result;
}

12
utils/file.h Normal file
View File

@ -0,0 +1,12 @@
//
// Created by Natuie on 2025/3/22.
//
#ifndef VETY_FILE_H
#define VETY_FILE_H
#include <stdbool.h>
char* read_file(const char* filename);
bool file_exists(const char* filename);
#endif //VETY_FILE_H

24
vm/CMakeLists.txt Normal file
View File

@ -0,0 +1,24 @@
#
add_library(vety_vm
vm.c
vm.h
native.c
native.h
)
#
add_executable(vety
main.c
)
#
target_include_directories(vety PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/utils
)
#
target_link_libraries(vety
vety_vm
vety_utils
)

153
vm/main.c Normal file
View File

@ -0,0 +1,153 @@
#include "vm.h"
#include "native.h"
#include "file.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
int main() {
system("chcp 65001");
char* filepath = "../main.vt";
// 创建虚拟机实例
VM* vm = vm_create();
if (!vm) {
fprintf(stderr, "Failed to create VM\n");
return 1;
}
// 注册原生函数
vm_register_native_function(vm, "print", native_print_const);
// 定义一个使用嵌套if语句的程序
uint8_t code[] = {
// 外层if: 比较R0和R1
OP_LOAD_CONST, R0, 0, // R0 = 10
OP_LOAD_CONST, R1, 1, // R1 = 20
OP_CMP_NE, R2, R0, R1, // R2 = R0 != R1
OP_JMP_IF_FALSE, R2, 0, 50, // 如果R2为假跳转到外层else分支
// 外层if的then分支
OP_MOV_IMM, R3, 2,
OP_NATIVE_CALL, 0, 1, R3,
// 内层if: 比较R0是否小于R1
OP_CMP_LT, R4, R0, R1,
OP_JMP_IF_FALSE, R4, 0, 39,
OP_MOV_IMM, R3, 4,
OP_NATIVE_CALL, 0, 1, R3,
OP_JMP, 0, 45, // 跳过内层else分支
// 内层else分支
OP_MOV_IMM, R3, 5,
OP_NATIVE_CALL, 0, 1, R3,
OP_END_IF, // 内层if结束
OP_JMP, 0, 58, // 跳过外层else分支
// 外层else分支
OP_MOV_IMM, R3, 3,
OP_NATIVE_CALL, 0, 1, R3,
OP_END_IF, // 外层if结束
OP_HALT // 程序结束
};
Program program = {
.code_size = sizeof(code),
.constants.entries = (Constant[]){
{.type = TYPE_INT64, .value = {.int64_val = 10}}, // 常量0: 10
{.type = TYPE_INT64, .value = {.int64_val = 20}}, // 常量1: 20
{.type = TYPE_STRING, .value = {.string_val = {.value = "Numbers are equal\n", .len = 18}}},
{.type = TYPE_STRING, .value = {.string_val = {.value = "Numbers are not equal\n", .len = 22}}},
{.type = TYPE_STRING, .value = {.string_val = {.value = "First number is smaller\n", .len = 22}}}
},
.constants.count = 5,
.constants.capacity = 10
};
// 加载程序到虚拟机
program.code = code;
vm_load(vm, &program);
// 执行程序
vm_eval(vm);
if (0) return 0; //是否打印
// 打印字节码
print_bytecode(program);
// 在vm_eval调用之前添加以下代码
printf("-------------------------------------------\n\n");
// 检查执行是否出错
if (vm->error != VM_SUCCESS) {
fprintf(stderr, "执行错误: %s\n", vm_get_error_message(vm));
fprintf(stderr, "指令位置: %lu\n", vm->error_ip);
fprintf(stderr, "操作码: 0x%02X\n", vm->error_opcode);
vm_destroy(vm);
return 1;
}
printf("-------------------------------------------\n");
// 打印常量池
printf("常量池:\n");
printf("索引 | 类型 | 值\n");
printf("-------------------------------------------\n");
for (int i = 0; i < program.constants.count; i++) {
Constant constant = program.constants.entries[i];
switch (constant.type) {
case TYPE_INT64:
printf("%d | i64 | %lld \n", i, constant.value.int64_val);
break;
case TYPE_STRING:
printf("%d | string | \"%s\" \n", i, constant.value.string_val.value);
break;
default:
break;
}
}
printf("-------------------------------------------\n\n");
// 栈
printf("栈:\n");
printf("索引 | 值\n");
printf("-------------------------------------------\n");
for (int i = 0; i < vm->sp; i++) {
printf("%d | %llu \n", i, vm->stack[i]);
}
if (vm->sp == 0) printf("空栈\n");
printf("-------------------------------------------\n\n");
// 打印寄存器
printf("寄存器:\n");
printf("索引 | 值\n");
printf("-------------------------------------------\n");
for (int i = 0; i < 5; i++) {
printf("%d | %llu \n", i, vm->registers[i]);
}
printf("-------------------------------------------\n\n");
// 打印函数表
printf("函数表:\n");
printf("索引 | 地址 | 局部变量个数 | 参数个数 \n");
printf("------------------------------------------------------------------\n");
for (int i = 0; i < vm->function_count; i++) {
Function function = vm->functions[i];
printf("%d(%s) | %llu | %d | %d \n", i, function.name, function.code_offset, function.local_count, function.param_count);
}
// 打印原生函数表
printf("-------------------------------------------\n\n");
printf("原生函数表:\n");
printf("索引 | 函数名\n");
printf("-------------------------------------------\n");
for (int i = 0; i < vm->native_function_count; i++) {
printf("%d | %s \n", i, vm->native_functions[i].name);
}
printf("-------------------------------------------\n\n");
vm_destroy(vm);
return 0;
}

54
vm/native.c Normal file
View File

@ -0,0 +1,54 @@
#include "vm.h"
#include "native.h"
#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif
Value native_print_const(VM* vm, Value* argv, uint8_t argc) {
if (argc != 1) {
fprintf(stderr, "print_const requires exactly 1 argument, got %d\n", argc);
return (Value){.int64_val = -1};
}
uint64_t idx = argv[0].int64_val;
if (!vm->program || idx >= vm->program->constants.count) {
fprintf(stderr, "Invalid constant index or no program loaded\n");
return (Value){.int64_val = -1};
}
Constant c = vm->program->constants.entries[idx];
switch (c.type) {
case TYPE_BOOL:
print(c.value.bool_val ? "true" : "false");
break;
case TYPE_CHAR:
print(&c.value.char_val);
break;
case TYPE_FLOAT32:
printf("%f", c.value.float32_val);
break;
case TYPE_FLOAT64:
printf("%f", c.value.float64_val);
break;
case TYPE_INT16:
printf("%d", c.value.int16_val);
break;
case TYPE_STRING:
print(c.value.string_val.value);
break;
default:
printf("%d\n", c.value.int64_val);
break;
}
return (Value) {.int32_val = 0};
}
void print(const char *str) {
#ifdef _WIN32
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD written;
WriteFile(hConsole, str, strlen(str), &written, NULL);
#else
write(1, str, strlen(str));
#endif
}

5
vm/native.h Normal file
View File

@ -0,0 +1,5 @@
#ifndef NATIVE_H
#define NATIVE_H
Value native_print_const(VM* vm, Value* argv, uint8_t argc);
void print(const char *str);
#endif // NATIVE_H

618
vm/vm.c Normal file
View File

@ -0,0 +1,618 @@
#include "vm.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
const char* vm_error_to_string(VMError error) {
switch (error) {
case VM_SUCCESS: return "No error";
case VM_ERROR_STACK_OVERFLOW: return "Stack overflow";
case VM_ERROR_STACK_UNDERFLOW: return "Stack underflow";
case VM_ERROR_INVALID_OPCODE: return "Invalid opcode";
case VM_ERROR_INVALID_REGISTER: return "Invalid register access";
case VM_ERROR_INVALID_CONSTANT: return "Invalid constant index";
case VM_ERROR_INVALID_JUMP: return "Invalid jump address";
case VM_ERROR_INVALID_NATIVE_FUNCTION: return "Invalid native function";
case VM_ERROR_MEMORY_ALLOCATION: return "Memory allocation failed";
case VM_ERROR_DIVISION_BY_ZERO: return "Division by zero";
case VM_ERROR_INVALID_FRAME: return "Invalid frame operation";
default: return "Unknown error";
}
}
void vm_set_error(VM* vm, VMError error, const char* message, uint64_t ip, uint8_t opcode) {
if (!vm) return;
vm->error = error;
vm->error_ip = ip;
vm->error_opcode = opcode;
// 格式化错误消息,包含位置和操作码信息
char full_message[256];
snprintf(full_message, sizeof(full_message),
"[IP: %lu, Opcode: 0x%02X] %s",
ip, opcode, message ? message : vm_error_to_string(error));
strncpy(vm->error_message, full_message, sizeof(vm->error_message) - 1);
vm->error_message[sizeof(vm->error_message) - 1] = '\0';
}
VMError vm_get_error(VM* vm) {
return vm ? vm->error : VM_ERROR_INVALID_REGISTER;
}
const char* vm_get_error_message(VM* vm) {
return vm ? vm->error_message : "Invalid VM instance";
}
VM* vm_create() {
VM* vm = (VM*)malloc(sizeof(VM));
if (!vm) return NULL;
// 初始化寄存器
memset(vm->registers, 0, sizeof(uint64_t) * REGISTER_COUNT);
// 初始化栈
vm->sp = 0;
vm->ip = 0;
vm->frame_count = 0;
vm->frames = NULL;
// 初始化程序
vm->program = NULL;
// 初始化全局变量表
vm->global_count = 0;
memset(vm->globals, 0, sizeof(GlobalVar) * GLOBAL_VAR_COUNT);
// 初始化函数表
vm->native_functions = malloc(sizeof(NativeFunction) * 10); // 增加初始容量
vm->native_function_count = 0;
vm->functions = NULL;
vm->function_count = 0;
// 初始化错误状态
vm->error = VM_SUCCESS;
vm->error_ip = 0;
vm->error_opcode = 0;
memset(vm->error_message, 0, sizeof(vm->error_message));
vm->block_count = 0;
return vm;
}
void vm_destroy(VM* vm) {
if (!vm) return;
// 释放程序内存
if (vm->program) {
if (vm->program->constants.entries) {
// 释放常量池中的字符串
for (uint64_t i = 0; i < vm->program->constants.count; i++) {
if (vm->program->constants.entries[i].type == TYPE_STRING) {
//free(vm->program->constants.entries[i].value.string_val.value);
}
}
//free(vm->program->constants.entries);
}
//free(vm->program);
}
// 释放全局变量表中的字符串
for (size_t i = 0; i < vm->global_count; i++) {
free(vm->globals[i].name);
if (vm->globals[i].type == TYPE_STRING) {
free(vm->globals[i].value.string_val.value);
}
}
// 释放函数表
if (vm->native_functions) {
for (size_t i = 0; i < vm->native_function_count; i++) {
free(vm->native_functions[i].name);
}
free(vm->native_functions);
}
if (vm->functions) {
for (size_t i = 0; i < vm->function_count; i++) {
free(vm->functions[i].name);
}
free(vm->functions);
}
// 释放栈帧
free(vm->frames);
free(vm);
}
void vm_set_register(VM* vm, uint64_t index, uint64_t value) {
if (!vm || index >= REGISTER_COUNT) {
// 无效的寄存器访问
fprintf(stderr, "Invalid register access\n");
return;
}
vm->registers[index] = value;
}
uint64_t vm_get_register(VM* vm, uint64_t index) {
if (!vm || index >= REGISTER_COUNT) {
// 无效的寄存器访问
fprintf(stderr, "Invalid register access\n");
return 0;
}
return vm->registers[index];
}
void vm_push(VM* vm, uint64_t value) {
if (!vm || vm->sp >= STACK_SIZE) {
// 栈溢出处理
fprintf(stderr, "Stack overflow\n");
return;
}
vm->stack[vm->sp++] = value;
}
uint64_t vm_pop(VM* vm) {
if (!vm || vm->sp == 0) {
// 栈下溢处理
fprintf(stderr, "Stack underflow\n");
return 0;
}
return vm->stack[--vm->sp];
}
uint64_t vm_peek(VM* vm, uint64_t offset) {
if (!vm || vm->sp <= offset) {
// 无效的栈访问
fprintf(stderr, "Invalid stack access\n");
return 0;
}
return vm->stack[vm->sp - 1 - offset];
}
int vm_register_native_function(VM* vm, const char* name, Value (*func)(VM* vm, Value* args, uint8_t argc)) {
if (!vm || !name || !func) {
fprintf(stderr, "Invalid parameters for native function registration\n");
return -1;
}
// 检查函数是否已经注册
for (size_t i = 0; i < vm->native_function_count; i++) {
if (strcmp(vm->native_functions[i].name, name) == 0) {
// 函数已存在,更新函数指针
vm->native_functions[i].func = func;
return i;
}
}
// 如果需要,扩展原生函数表
if (vm->native_function_count % 10 == 0 && vm->native_function_count > 0) {
size_t new_size = (vm->native_function_count + 10) * sizeof(NativeFunction);
NativeFunction* new_functions = realloc(vm->native_functions, new_size);
if (!new_functions) {
fprintf(stderr, "Failed to allocate memory for native functions\n");
return -1;
}
vm->native_functions = new_functions;
}
// 添加新函数
size_t idx = vm->native_function_count;
vm->native_functions[idx].name = strdup(name);
vm->native_functions[idx].func = func;
vm->native_function_count++;
return idx;
}
void vm_load(VM* vm, Program *program) {
if (!vm || !program) return;
vm->program = program;
// 重置虚拟机状态
vm->ip = 0;
vm->sp = 0;
vm->frame_count = 0;
// 初始化全局变量表
vm->global_count = 0;
memset(vm->globals, 0, sizeof(GlobalVar) * GLOBAL_VAR_COUNT);
// 初始化函数表
vm->functions = NULL;
vm->function_count = 0;
}
void vm_eval(VM* vm) {
vm->error = VM_SUCCESS;
if (!vm || !vm->program) {
vm_set_error(vm, VM_ERROR_INVALID_REGISTER, "Invalid VM or no program loaded", 0, 0);
return;
}
uint8_t dst_reg = 0;
uint8_t src_reg1 = 0;
uint8_t src_reg2 = 0;
uint8_t cond_reg = 0;
while (vm->ip < vm->program->code_size) {
uint8_t opcode = vm->program->code[vm->ip++];
switch (opcode) {
case OP_LOAD_CONST: {
uint8_t dst_reg = vm->program->code[vm->ip++];
uint8_t const_idx = vm->program->code[vm->ip++];
if (const_idx >= vm->program->constants.count) {
vm_set_error(vm, VM_ERROR_INVALID_CONSTANT,
"Invalid constant index",
vm->ip - 3, opcode);
return;
}
Constant constant = vm->program->constants.entries[const_idx];
switch (constant.type) {
case TYPE_INT8:
vm->registers[dst_reg] = constant.value.int8_val;
break;
case TYPE_INT16:
vm->registers[dst_reg] = constant.value.int16_val;
break;
case TYPE_INT32:
vm->registers[dst_reg] = constant.value.int32_val;
break;
case TYPE_INT64:
vm->registers[dst_reg] = constant.value.int64_val;
break;
case TYPE_BOOL:
vm->registers[dst_reg] = constant.value.bool_val;
break;
case TYPE_CHAR:
vm->registers[dst_reg] = constant.value.char_val;
break;
default:
vm_set_error(vm, VM_ERROR_INVALID_CONSTANT,
"Unsupported constant type",
vm->ip - 3, opcode);
return;
}
break;
}
case OP_GLOBAL_LOAD: {
uint8_t dst_reg = vm->program->code[vm->ip++];
uint8_t global_idx = vm->program->code[vm->ip++];
if (global_idx >= vm->global_count) {
fprintf(stderr, "Invalid global variable index: %d\n", global_idx);
return;
}
vm->registers[dst_reg] = vm->globals[global_idx].value.int32_val;
break;
}
case OP_GLOBAL_STORE: {
uint8_t src_reg = vm->program->code[vm->ip++];
uint8_t global_idx = vm->program->code[vm->ip++];
if (global_idx >= vm->global_count) {
fprintf(stderr, "Invalid global variable index: %d\n", global_idx);
return;
}
vm->globals[global_idx].value.int32_val = vm->registers[src_reg];
break;
}
case OP_LOAD_LOCAL: {
if (vm->frame_count == 0) {
fprintf(stderr, "No active frame for local variable access\n");
return;
}
uint8_t dst_reg = vm->program->code[vm->ip++];
uint8_t local_idx = vm->program->code[vm->ip++];
Frame* frame = &vm->frames[vm->frame_count - 1];
vm->registers[dst_reg] = frame->locals[local_idx];
break;
}
case OP_STORE_LOCAL: {
if (vm->frame_count == 0) {
fprintf(stderr, "No active frame for local variable access\n");
return;
}
uint8_t src_reg = vm->program->code[vm->ip++];
uint8_t local_idx = vm->program->code[vm->ip++];
Frame* frame = &vm->frames[vm->frame_count - 1];
frame->locals[local_idx] = vm->registers[src_reg];
break;
}
case OP_FUNC_DEF: {
uint8_t func_name_idx = vm->program->code[vm->ip++];
uint8_t param_count = vm->program->code[vm->ip++];
uint8_t local_count = vm->program->code[vm->ip++];
uint16_t instruction_count = (vm->program->code[vm->ip] << 8) | vm->program->code[vm->ip + 1];
vm->ip += 2; // Skip instruction count bytes
// 扩展函数表
size_t new_size = (vm->function_count + 1) * sizeof(Function);
Function* new_functions = realloc(vm->functions, new_size);
if (!new_functions) {
fprintf(stderr, "Failed to allocate memory for function\n");
return;
}
vm->functions = new_functions;
Function* func = &vm->functions[vm->function_count++];
func->name = strdup(vm->program->constants.entries[func_name_idx].value.string_val.value);
func->code_offset = vm->ip;
func->param_count = param_count;
func->local_count = local_count;
func->instructions_count = instruction_count;
// 跳过函数体
vm->ip += instruction_count;
break;
}
case OP_CALL: {
uint8_t func_idx = vm->program->code[vm->ip++];
if (func_idx >= vm->function_count) {
fprintf(stderr, "Invalid function index: %d\n", func_idx);
return;
}
Function* func = &vm->functions[func_idx];
// 创建新的栈帧
vm->frames = realloc(vm->frames, (vm->frame_count + 1) * sizeof(Frame));
if (!vm->frames) {
fprintf(stderr, "Failed to allocate memory for frame\n");
return;
}
Frame* frame = &vm->frames[vm->frame_count++];
frame->ip = vm->ip;
frame->locals = calloc(func->local_count, sizeof(uint64_t));
frame->stack = calloc(STACK_FRAME_SIZE, sizeof(uint64_t));
frame->sp = 0;
// 保存当前IP并跳转到函数代码
vm->ip = func->code_offset;
break;
}
case OP_RETURN: {
if (vm->frame_count == 0) {
fprintf(stderr, "No frame to return from\n");
return;
}
// 恢复前一个栈帧
Frame* frame = &vm->frames[--vm->frame_count];
vm->ip = frame->ip;
// 释放栈帧资源
free(frame->locals);
free(frame->stack);
break;
}
case OP_ADD: {
dst_reg = vm->program->code[vm->ip++];
uint8_t src_reg1 = vm->program->code[vm->ip++];
uint8_t src_reg2 = vm->program->code[vm->ip++];
vm->registers[dst_reg] = vm->registers[src_reg1] + vm->registers[src_reg2];
break;
}
case OP_JMP: {
uint16_t offset = (vm->program->code[vm->ip] << 8) | vm->program->code[vm->ip + 1];
if (offset >= vm->program->code_size) {
vm_set_error(vm, VM_ERROR_INVALID_JUMP,
"Invalid jump address",
vm->ip, opcode);
return;
}
vm->ip = offset;
vm->ip += 2; // 跳过偏移量字节
break;
}
case OP_JMP_IF_FALSE: {
cond_reg = vm->program->code[vm->ip++];
uint16_t offset = (vm->program->code[vm->ip] << 8) | vm->program->code[vm->ip + 1];
vm->ip += 2;
if (!vm->registers[cond_reg]) {
// 条件为假时,跳转到指定位置
if (offset >= vm->program->code_size) {
vm_set_error(vm, VM_ERROR_INVALID_JUMP,
"Invalid jump address",
vm->ip - 3, opcode);
return;
}
vm->ip = offset;
// 跳过此块中的所有嵌套if直到找到匹配的END_IF
vm->block_count++;
}
break;
}
case OP_END_IF: {
// 处理if块的结束
if (vm->block_count > 0) {
vm->block_count--;
}
break;
}
case OP_JMP_IF_TRUE: {
cond_reg = vm->program->code[vm->ip++];
uint16_t offset = (vm->program->code[vm->ip] << 8) | vm->program->code[vm->ip + 1];
if (vm->registers[cond_reg]) {
vm->ip = offset;
} else {
vm->ip += 2;
}
break;
}
case OP_CMP_EQ: {
dst_reg = vm->program->code[vm->ip++];
uint8_t src_reg1 = vm->program->code[vm->ip++];
uint8_t src_reg2 = vm->program->code[vm->ip++];
vm->registers[dst_reg] = vm->registers[src_reg1] == vm->registers[src_reg2];
break;
}
case OP_CMP_NE: {
dst_reg = vm->program->code[vm->ip++];
uint8_t src_reg1 = vm->program->code[vm->ip++];
uint8_t src_reg2 = vm->program->code[vm->ip++];
vm->registers[dst_reg] = vm->registers[src_reg1] != vm->registers[src_reg2];
break;
}
case OP_CMP_LT: {
dst_reg = vm->program->code[vm->ip++];
uint8_t src_reg1 = vm->program->code[vm->ip++];
uint8_t src_reg2 = vm->program->code[vm->ip++];
vm->registers[dst_reg] = vm->registers[src_reg1] < vm->registers[src_reg2];
break;
}
case OP_CMP_LE: {
dst_reg = vm->program->code[vm->ip++];
uint8_t src_reg1 = vm->program->code[vm->ip++];
uint8_t src_reg2 = vm->program->code[vm->ip++];
vm->registers[dst_reg] = vm->registers[src_reg1] <= vm->registers[src_reg2];
break;
}
case OP_CMP_GT: {
dst_reg = vm->program->code[vm->ip++];
uint8_t src_reg1 = vm->program->code[vm->ip++];
uint8_t src_reg2 = vm->program->code[vm->ip++];
vm->registers[dst_reg] = vm->registers[src_reg1] > vm->registers[src_reg2];
break;
}
case OP_CMP_GE: {
dst_reg = vm->program->code[vm->ip++];
uint8_t src_reg1 = vm->program->code[vm->ip++];
uint8_t src_reg2 = vm->program->code[vm->ip++];
vm->registers[dst_reg] = vm->registers[src_reg1] >= vm->registers[src_reg2];
break;
}
case OP_NATIVE_CALL: {
uint8_t func_idx = vm->program->code[vm->ip++];
uint8_t argc = vm->program->code[vm->ip++];
if (func_idx >= vm->native_function_count) {
vm_set_error(vm, VM_ERROR_INVALID_NATIVE_FUNCTION,
"Invalid native function index",
vm->ip - 2, opcode);
return;
}
// 准备参数数组
Value args[argc];
for (int i = 0; i < argc; i++) {
uint8_t arg_reg = vm->program->code[vm->ip++];
args[i].int64_val = vm->registers[arg_reg];
}
// 调用原生函数
NativeFunction* func = &vm->native_functions[func_idx];
Value result = func->func(vm, args, argc);
vm->registers[R0] = result.int64_val;
break;
}
case OP_HALT:
return;
case OP_MOV: {
uint8_t dst_reg = vm->program->code[vm->ip++];
uint8_t src_reg = vm->program->code[vm->ip++];
vm->registers[dst_reg] = vm->registers[src_reg];
break;
}
case OP_MOV_IMM: {
uint8_t dst_reg = vm->program->code[vm->ip++];
uint8_t imm = vm->program->code[vm->ip++];
vm->registers[dst_reg] = imm;
break;
}
default:
vm_set_error(vm, VM_ERROR_INVALID_OPCODE,
"Unknown instruction",
vm->ip - 1, opcode);
return;
}
// 检查每条指令执行后是否有错误
if (vm->error != VM_SUCCESS) {
return;
}
}
}
void print_bytecode(Program program) {
printf("字节码指令:\n");
printf("地址 | 操作码 | 操作数\n");
printf("-------------------------------------------\n");
int indent = 0;
for (size_t i = 0; i < program.code_size;) {
for (int j = 0; j < indent; j++) printf(" ");
printf("0x%04d | ", i);
uint8_t opcode = program.code[i++];
switch (opcode) {
case OP_BLOCK_START:
printf("BLOCK_START\n");
indent++;
break;
case OP_BLOCK_END:
indent--;
printf("BLOCK_END\n");
break;
case OP_LOAD_CONST:
printf("LOAD_CONST R%d, %d\n", program.code[i], program.code[i+1]);
i += 2;
break;
case OP_MOV:
printf("MOV R%d, %d\n", program.code[i], program.code[i+1]);
i += 2;
break;
case OP_MOV_IMM:
printf("MOV_IMM R%d, %d\n", program.code[i], program.code[i+1]);
i += 2;
break;
case OP_ADD:
printf("ADD R%d, R%d, R%d\n",
program.code[i], program.code[i+1], program.code[i+2]);
i += 3;
break;
case OP_CMP_EQ:
printf("CMP_EQ R%d, R%d, R%d\n",
program.code[i], program.code[i+1], program.code[i+2]);
i += 3;
break;
case OP_JMP_IF_FALSE:
printf("JMP_IF_FALSE");
for (int j = 0; j < indent; j++) printf(" ");
printf(" R%d, %d, %d\n",
program.code[i], program.code[i+1], program.code[i+2]);
i += 3;
indent++; // 增加缩进层级
break;
case OP_JMP:
printf("JMP %d, %d\n", program.code[i], program.code[i+1]);
i += 2;
break;
case OP_NATIVE_CALL:
printf("NATIVE_CALL %d, %d, R%d\n",
program.code[i], program.code[i+1], program.code[i+2]);
i += 3;
break;
case OP_HALT:
printf("HALT\n");
break;
case OP_END_IF:
indent--; // 减少缩进层级
printf("END_IF");
for (int j = 0; j < indent; j++) printf(" ");
printf("\n");
break;
default:
printf("UNKNOWN 0x%02X\n", opcode);
i++;
break;
}
}
}

219
vm/vm.h Normal file
View File

@ -0,0 +1,219 @@
#ifndef VETY_VM_H
#define VETY_VM_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define MEMORY_SIZE 1024 * 1024 // 虚拟机内存大小
#define REGISTER_COUNT 64 // 虚拟机寄存器数量
#define STACK_SIZE 64 // 虚拟机栈大小
#define STACK_FRAME_SIZE 64 // 虚拟机栈帧大小
#define STACK_LOCAL_SIZE 64
#define CONSTANT_POOL_SIZE 64 // 虚拟机常量池大小
#define GLOBAL_VAR_COUNT 64 // 虚拟机全局变量数量
enum {
OP_PUSH,
OP_POP,
OP_MOV, // 移动寄存器到寄存器
OP_MOV_IMM, // 移动立即数到寄存器
OP_LOAD_CONST, // 加载常量到寄存器
OP_STORE_CONST, // 存储寄存器值到常量池
OP_GLOBAL_LOAD, // 加载全局变量到寄存器
OP_GLOBAL_STORE, // 存储寄存器值到全局变量
OP_LOAD_LOCAL, // 加载局部变量到寄存器
OP_STORE_LOCAL, // 存储寄存器值到局部变量
OP_FUNC_DEF, // 函数定义
OP_CALL, // 调用函数
OP_NATIVE_CALL, // 调用本地函数
OP_RETURN, // 函数返回
OP_ADD, // 加法运算
OP_SUB, // 减法运算
OP_MUL, // 乘法运算
OP_DIV, // 除法运算
OP_JMP, // 无条件跳转
OP_JMP_IF_FALSE, // 条件跳转(如果为假)
OP_JMP_IF_TRUE, // 条件跳转(如果为真)
OP_CMP_EQ, // 比较相等
OP_CMP_NE, // 比较不相等
OP_CMP_LT, // 比较小于
OP_CMP_LE, // 比较小于等于
OP_CMP_GT, // 比较大于
OP_CMP_GE, // 比较大于等于
OP_BLOCK_START, // 块开始
OP_BLOCK_END, // 块结束
OP_END_IF, // 结束if语句
OP_HALT, // 停止执行
OP_IF_START, // if块开始
OP_ELSE, // else块
OP_IF_END // if块结束
};
typedef enum {
TYPE_INT8,
TYPE_INT16,
TYPE_INT32,
TYPE_INT64,
TYPE_FLOAT32,
TYPE_FLOAT64,
TYPE_STRING,
TYPE_BOOL,
TYPE_CHAR,
TYPE_OBJECT,
} VarType;
typedef union {
int8_t int8_val;
int16_t int16_val;
int32_t int32_val;
int64_t int64_val;
float float32_val;
double float64_val;
uint8_t bool_val;
char char_val;
void* object_val;
struct {
uint64_t len;
char* value;
} string_val;
struct {
uint64_t code_offset;
uint16_t* arity;
} func_val;
} Value;
typedef struct {
VarType type;
Value value;
} Constant;
typedef struct {
Constant* entries;
uint64_t count;
uint64_t capacity;
} ConstantPool;
typedef struct Frame {
uint64_t ip; // 指令指针
uint64_t* locals;
uint64_t *stack;
uint64_t sp;
struct Frame* parent; // 父作用域
uint8_t scope_depth; // 作用域深度
} Frame;
typedef struct {
char* name;
Value value;
VarType type;
} GlobalVar;
typedef struct VM VM;
typedef struct {
char* name;
Value (*func)(VM*, Value* args, uint8_t argc);
} NativeFunction;
typedef struct {
char* name;
uint64_t code_offset;
uint8_t param_count;
uint8_t local_count;
uint8_t instructions_count;
} Function;
typedef struct {
uint8_t* code;
size_t code_size;
ConstantPool constants;
size_t constants_size;
} Program;
enum {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31};
// 错误类型定义
typedef enum {
VM_SUCCESS = 0,
VM_ERROR_STACK_OVERFLOW,
VM_ERROR_STACK_UNDERFLOW,
VM_ERROR_INVALID_OPCODE,
VM_ERROR_INVALID_REGISTER,
VM_ERROR_INVALID_CONSTANT,
VM_ERROR_INVALID_JUMP,
VM_ERROR_INVALID_NATIVE_FUNCTION,
VM_ERROR_MEMORY_ALLOCATION,
VM_ERROR_DIVISION_BY_ZERO,
VM_ERROR_INVALID_FRAME,
} VMError;
// 修改虚拟机结构体
typedef struct BlockInfo {
uint64_t start_ip;
uint64_t end_ip;
} BlockInfo;
typedef struct VM {
Program* program;
ConstantPool constants;
uint64_t registers[REGISTER_COUNT];
size_t frame_count;
Frame* frames;
uint64_t stack[STACK_SIZE];
uint64_t sp;
uint64_t ip;
// 全局变量表
GlobalVar globals[GLOBAL_VAR_COUNT];
size_t global_count;
// 本地函数表
NativeFunction* native_functions;
size_t native_function_count;
// 用户定义函数表
Function* functions;
size_t function_count;
// 错误处理
VMError error;
char error_message[256];
uint64_t error_ip; // 错误发生的指令位置
uint8_t error_opcode; // 错误发生时的操作码
// 块追踪
BlockInfo block_stack[STACK_SIZE];
uint64_t block_count;
// if语句跟踪
uint64_t if_stack[256]; // 存储if语句开始位置
uint64_t else_stack[256]; // 存储else语句位置
int if_sp; // if栈指针
} VM;
// 虚拟机创建
VM *vm_create();
void vm_destroy(VM *vm);
void vm_load(VM* vm, Program *program);
void vm_eval(VM *vm);
// 栈
void vm_push(VM *vm, uint64_t value);
uint64_t vm_pop(VM *vm);
uint64_t vm_peek(VM *vm, uint64_t offset);
int vm_register_native_function(VM* vm, const char* name, Value (*func)(VM*, Value* args, uint8_t argc)); // 更新函数声明
// 错误处理函数
const char* vm_error_to_string(VMError error);
void vm_set_error(VM* vm, VMError error, const char* message, uint64_t ip, uint8_t opcode);
VMError vm_get_error(VM* vm);
const char* vm_get_error_message(VM* vm);
void print_bytecode(Program program);
#endif //VETY_VM_H