# minic **Repository Path**: aleckstygit/minic ## Basic Information - **Project Name**: minic - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-05 - **Last Updated**: 2026-04-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MiniC 语言介绍 ## 简介 MiniC 是一个轻量级的类C语言解释器和编译器,支持编译和解释执行。语法大部分兼容C语言,适合简单脚本编程。 --- ## 语言特性 ### 常量声明 使用 `let` 关键字声明常量,常量在声明后不可修改。 ```c let float pi = 3.14159; // 声明浮点常量 let int max_value = 100; // 声明整数常量 ``` **注意**: - 常量必须在声明时初始化 - 尝试修改常量会导致编译错误 - 常量在编译时会被检查,确保不可修改 --- ### 数据类型 | 类型 | 说明 | 示例 | |------|------|------| | `char` | 有符号字符 (1字节) | `char c = 'A'` | | `uchar` | 无符号字符 | `uchar uc = 255` | | `short` | 有符号短整型 (2字节) | `short s = 100` | | `ushort` | 无符号短整型 | `ushort us = 200` | | `int` | 有符号整型 (4字节) | `int i = 42` | | `uint` | 无符号整型 | `uint ui = 100` | | `long` | 有符号长整型 (8字节) | `long l = 1000` | | `ulong` | 无符号长整型 | `ulong ul = 2000` | | `float` | 单精度浮点 | `float f = 3.14` | | `double` | 双精度浮点 | `double d = 2.718` | | `string` | 字符串类型(char[] 别名) | `string s = "hello"` | > **注意**:`string` 是 `char[]` 的类型别名,用于声明字符串变量。 > 编译时可通过以下选项禁用特定功能: > - `make SUPPORT_8BYTES=0` 禁用 long/double 类型 > - `make SUPPORT_BIT_OPERATIONS=0` 禁用位操作 > - `make SUPPORT_FLOAT_OPERATIONS=0` 禁用浮点操作 > - `make SUPPORT_ENUM=0` 禁用枚举类型支持 > - `make SUPPORT_STRUCT=0` 禁用结构体类型支持 --- ### 标准库 string(无指针字符串操作) MiniC 支持 `import string` 加载字符串实用库,全部基于字符数组、无指针。标准接口如下: | 函数名 | 用法 | 说明 | |-----------------|-----------------------------------|----------------------------| | `int strlen(s)` | `strlen(a)` | 获取字符串长度 | | `int strcmp(a,b)` | `strcmp(a, b)` | 比较字符串内容,0相等,1不等 | | `void strcpy(dest, src)` | `strcpy(a, b)` | 复制字符串 | | `void strcat(dest, src)` | `strcat(a, b)` | 拼接字符串 | | `int strchr(s, c)` | `strchr(a, 'x')` | 查找字符首次下标 | | `int strfind(s, sub)` | `strfind(c, "abc")` | 查找子串 | | `void strupper(s)` | `strupper(a)` | 转大写 | | `void strlower(s)` | `strlower(a)` | 转小写 | | `void memset(s,c,n)` | `memset(a,'_',3)` | 前n个字符赋值为c | 详见 `examples/demo_string.mc` 和 `test/test_string.mc`。全部纯 MiniC 语法,无指针安全,适合初学者和嵌入式课堂体验。 --- ### 控制流 ```c // if-else if (condition) { // code } else { // code } // while 循环 while (condition) { // code } // for 循环 for (int i = 0; i < 10; i = i + 1) { // code } // do-while 循环 do { // code } while (condition); // switch case switch (expression) { case value1: // code break; case value2: // code break; default: // code break; } // 函数 int add(int a, int b) { return a + b; } // 支持中文函数名 int 加法(int a, int b) { return a + b; } // 常量声明 let float pi = 3.14159; let int max_value = 100; // 支持中文常量名 let float 圆周率 = 3.14159; let int 最大值 = 100; ``` --- ### 运算符 | 类别 | 运算符 | |------|--------| | 算术 | `+`, `-`, `*`, `/`, `%` | | 比较 | `==`, `!=`, `<`, `>`, `<=`, `>=` | | 逻辑 | `&&`, `\|\|`, `!` | | 位运算 | `&`, `\|`, `^`, `~`, `<<`, `>>` | | 赋值 | `=`, `+=`, `-=`, `*=`, `/=` | --- ### 数组 ```c int arr[5]; // 声明数组 arr[0] = 10; // 赋值 int x = arr[2]; // 访问 ``` --- ### 字符串 ```c print("Hello World!"); // 字符串字面量 putc("ABC"); // 输出首字符 'A' ``` --- ### 中文标识符支持 MiniC 支持使用中文字符作为标识符,包括变量名、函数名、常量名和库名: ```c // 中文变量名 int 计数器 = 0; float 圆周率 = 3.14159; // 中文函数名 int 加法(int a, int b) { return a + b; } // 中文常量名 let float 圆周率 = 3.14159; let int 最大值 = 100; // 中文库名 import 数学; ``` --- ### 类型别名 MiniC 支持使用 `set` 关键字声明类型别名,使代码更具可读性: ```c // 声明类型别名 set 整数 is int; set 浮点数 is float; set 布尔 is int; // 使用类型别名声明变量 整数 人数 = 10; 浮点数 温度 = 36.5; 布尔 开关 = 1; // 使用类型别名声明函数 整数 加法(整数 a, 整数 b) { return a + b; } ``` --- ### 枚举类型 MiniC 支持枚举类型,用于定义一组命名常量: ```c enum Color { RED, GREEN, BLUE }; int main() { enum Color c = RED; print(c); // 输出 0 return 0; } ``` --- ### 结构体类型 MiniC 支持结构体类型,用于组合不同类型的数据: ```c struct Point { int x; int y; }; int main() { struct Point p; p.x = 10; p.y = 20; print(p.x); // 输出 10 print(p.y); // 输出 20 return 0; } ``` --- ### 函数重载 MiniC 支持函数重载,允许同一函数名的多个版本,根据参数类型和数量自动调用对应版本: ```c // 函数重载示例 void print(int n) { // 打印整数 } void print(float f) { // 打印浮点数 } void print(char s[]) { // 打印字符串 } int main() { print(42); // 调用 print(int) print(3.14); // 调用 print(float) print("Hello"); // 调用 print(char[]) return 0; } ``` **函数重载原理:** - 函数签名由函数名和参数类型列表组成,用于唯一标识函数 - 编译时根据实参类型自动推断并匹配对应的函数版本 - 支持不同参数类型的重载(如 `print(int)`、`print(float)`、`print(char[])`) - 支持不同参数数量的重载(如 `add(int, int)`、`add(int, int, int)`) --- ## 标准库函数 ### 硬件 I/O 标准库 MiniC 支持基础硬件/单片机外设寄存器操作,接口如下: | 函数 | 用法 | 说明 | |---------------|---------------------------|-------------------------------------| | `int ioread(address)` | `ioread(addr)` | 读取 32 位外设地址(或设备ID)对应寄存器值。| | `void iowrite(address, value)` | `iowrite(addr, val)` | 写入数据到 32 位外设地址。 | #### 外设地址定义 | 外设 | 基地址 | 说明 | |------|--------|------| | 定时器 | 0x40001000 | 定时器寄存器 | | 串口 | 0x40002000 | UART 寄存器 | | GPIO | 0x40003000 | 通用输入输出 | | 键盘 | 0x40004000 | 键盘状态和数据 | | 鼠标 | 0x40005000 | 鼠标移动和按键 | | 显示屏 | 0x40006000 | 屏幕控制 | #### 外设驱动库 (io_periph.mc) 加载 `import io_periph;` 可使用高级外设函数: | 函数 | 用法 | 说明 | |------|------|------| | `timer_init()` | `timer_init()` | 初始化定时器 | | `timer_ticks()` | `timer_ticks()` | 获取毫秒计数 | | `sleep(ms)` | `sleep(1000)` | 延时(毫秒) | | `uart_putc(c)` | `uart_putc('A')` | 串口发送字符 | | `uart_getc()` | `uart_getc()` | 串口接收字符 | | `uart_available()` | `uart_available()` | 检查串口是否有数据 | | `gpio_set_direction(pin, dir)` | `gpio_set_direction(0, 1)` | 设置引脚方向 | | `gpio_write(pin, val)` | `gpio_write(0, 1)` | 写入引脚 | | `gpio_read(pin)` | `gpio_read(0)` | 读取引脚 | | `kbd_read()` | `kbd_read()` | 读取键盘按键 | | `mouse_read()` | `mouse_read()` | 读取鼠标数据 | | `display_clear()` | `display_clear()` | 清除屏幕 | | `display_pixel(x, y, c)` | `display_pixel(10, 10, 65)` | 设置像素 | | `adc_read(ch)` | `adc_read(0)` | 读取ADC通道 | | `dac_write(val)` | `dac_write(128)` | 写入DAC值 | | `dac_on(enable)` | `dac_on(1)` | 开关DAC | | `pwm_period(p)` | `pwm_period(1000)` | 设置PWM周期 | | `pwm_duty(d)` | `pwm_duty(500)` | 设置PWM占空比 | | `pwm_on(enable)` | `pwm_on(1)` | 开关PWM | | `rtc_sec()`, `rtc_min()`, `rtc_hour()` | `rtc_sec()` | 读取时分秒 | | `rtc_day()`, `rtc_month()`, `rtc_year()` | `rtc_day()` | 读取年月日 | | `rtc_set(h, m, s)` | `rtc_set(12, 30, 0)` | 设置时间 | | `wdt_start(t)` | `wdt_start(1000)` | 启动看门狗 | | `wdt_feed()` | `wdt_feed()` | 喂狗 | | `wdt_stop()` | `wdt_stop()` | 停止看门狗 | | `spi_trans(d)` | `spi_trans(0xAA)` | SPI传输 | | `spi_rdy()` | `spi_rdy()` | SPI就绪 | | `i2c_put(addr, data)` | `i2c_put(0x50, 0xAB)` | I2C写 | | `i2c_get(addr)` | `i2c_get(0x50)` | I2C读 | | `i2c_begin(addr)` | `i2c_begin(0x50)` | I2C开始 | | `i2c_end()` | `i2c_end()` | I2C停止 | - `address` 参数为 int 型,需查阅平台文档明确用途。禁止用作普通变量指针。 - 设计保证跨平台安全。编译成字节码/二进制时,调用会转换为底层平台寄存器访问 - **解释器(run模式)下会模拟调用,仅输出调用信息,无实际硬件访问,便于教学和调试** **用例:** ```c import io; let int LED_ADDR = 0x40021018; iowrite(LED_ADDR, 1); // 打开LED(仅示意用) let int v = ioread(LED_ADDR); // 读取LED当前状态 ``` ### 输入输出 | 函数 | 用法 | 说明 | |------|------|------| | `print(x)` | `print(42)` | 输出值并换行 | | `putc(x)` | `putc('A')` | 输出单个字符 | | `getc(var)` | `getc(c)` | 读取单个字符到变量 | | `readint(var)` | `readint(n)` | 读取整数到变量 | | `readfloat(var)` | `readfloat(f)` | 读取浮点数到变量 | | `readstring(var)` | `readstring(s)` | 读取字符串到变量 | **示例:** ```c int main() { print("Hello!"); putc('A'); putc('\n'); int n; readint(n); // 读取整数 print(n); return 0; } ``` --- ### Math 库 引入方式:`import math;` | 函数 | 说明 | 示例 | |------|------|------| | `abs(x)` | 绝对值 | `abs(-5) = 5` | | `max(a, b)` | 最大值 | `max(3, 5) = 5` | | `min(a, b)` | 最小值 | `min(3, 5) = 3` | | `is_even(x)` | 是否偶数 | `is_even(4) = 1` | | `is_odd(x)` | 是否奇数 | `is_odd(3) = 1` | **示例:** ```c import math; int main() { print(abs(-10)); // 输出 10 print(max(5, 3)); // 输出 5 return 0; } ``` --- ### String 库(增强版) 引入方式:`import string;` **基础函数:** | 函数 | 说明 | 示例 | |------|------|------| | `strlen(s)` | 字符串长度 | `strlen("abc") = 3` | | `strcmp(a, b)` | 比较字符串 | `strcmp("a", "a") = 0` | | `strcpy(dest, src)` | 复制字符串 | `strcpy(a, "hello")` | | `strcat(dest, src)` | 拼接字符串 | `strcat(a, " world")` | | `strchr(s, c)` | 查找字符 | `strchr("abc", 'b') = 1` | | `strfind(s, sub)` | 查找子串 | `strfind("abc", "bc") = 1` | | `atoi(s)` | 字符串转整数 | `atoi("42") = 42` | | `itoa(n, s)` | 整数转字符串 | `itoa(42, s)` | **增强函数(新增):** | 函数 | 说明 | 示例 | |------|------|------| | `substring(dest, src, start, len)` | 提取子串 | `substring(d, "hello", 1, 3)` → `"ell"` | | `concat(dest, s1, s2)` | 连接字符串 | `concat(d, "hello", " world")` | | `compare(a, b)` | 比较(-1/0/1) | `compare("a", "b") = -1` | | `startswith(s, prefix)` | 检查前缀 | `startswith("hello", "he") = 1` | | `endswith(s, suffix)` | 检查后缀 | `endswith("hello", "lo") = 1` | | `replace(dest, src, old, new)` | 替换字符 | `replace(d, "hello", 'l', 'x')` → `"hexxo"` | | `split(dest, src, delim, idx)` | 分割字符串 | `split(d, "a,b,c", ',', 1)` → `"b"` | | `count(s, c)` | 统计字符 | `count("hello", 'l') = 2` | | `repeat(dest, s, n)` | 重复字符串 | `repeat(d, "hi", 3)` → `"hihihi"` | | `pad_left(dest, src, c, len)` | 左侧填充 | `pad_left(d, "42", '0', 5)` → `"00042"` | | `pad_right(dest, src, c, len)` | 右侧填充 | `pad_right(d, "hi", '!', 4)` → `"hi!!"` | | `contains(s, sub)` | 检查包含 | `contains("hello", "ell") = 1` | | `to_upper_copy(dest, src)` | 转大写(复制) | `to_upper_copy(d, "hello")` → `"HELLO"` | | `to_lower_copy(dest, src)` | 转小写(复制) | `to_lower_copy(d, "HELLO")` → `"hello"` | **示例:** ```c import string; int main() { char result[50]; /* 提取子串 */ substring(result, "Hello World", 6, 5); print(result); // 输出: World /* 连接字符串 */ concat(result, "Hello", " World"); print(result); // 输出: Hello World /* 检查前缀 */ if (startswith("Hello World", "Hello")) { print("Yes!"); // 输出: Yes! } /* 分割字符串 */ char part[20]; split(part, "apple,banana,cherry", ',', 1); print(part); // 输出: banana return 0; } ``` --- ### Array2D 库(二维数组) 引入方式:`import array2d;` MiniC 使用一维数组模拟二维数组,通过 `array2d` 库提供便捷的二维数组操作。 | 函数 | 说明 | 示例 | |------|------|------| | `array2d_get(arr, row, col, cols)` | 获取元素 | `array2d_get(m, 1, 2, 4)` | | `array2d_set(arr, row, col, cols, val)` | 设置元素 | `array2d_set(m, 1, 2, 4, 42)` | | `array2d_init_zero(arr, rows, cols)` | 初始化为0 | `array2d_init_zero(m, 3, 4)` | | `array2d_init_value(arr, rows, cols, val)` | 初始化为值 | `array2d_init_value(m, 3, 4, 1)` | | `array2d_copy(dest, src, rows, cols)` | 复制数组 | `array2d_copy(d, s, 3, 4)` | | `matrix_add(C, A, B, rows, cols)` | 矩阵加法 | `matrix_add(C, A, B, 3, 4)` | | `matrix_sub(C, A, B, rows, cols)` | 矩阵减法 | `matrix_sub(C, A, B, 3, 4)` | | `matrix_scalar_mul(B, A, rows, cols, s)` | 矩阵数乘 | `matrix_scalar_mul(B, A, 3, 4, 2)` | | `matrix_mul(C, A, B, rA, cA, cB)` | 矩阵乘法 | `matrix_mul(C, A, B, 2, 3, 2)` | | `matrix_transpose(B, A, rows, cols)` | 矩阵转置 | `matrix_transpose(B, A, 2, 3)` | | `matrix_identity(A, n)` | 单位矩阵 | `matrix_identity(I, 3)` | | `matrix_trace(A, n)` | 矩阵迹 | `matrix_trace(A, 3)` | **示例:** ```c import array2d; int main() { /* 声明 3x4 矩阵(使用一维数组存储) */ int matrix[12]; int rows = 3; int cols = 4; /* 初始化 */ array2d_init_zero(matrix, rows, cols); /* 设置元素 */ array2d_set(matrix, 1, 2, cols, 42); /* 获取元素 */ print(array2d_get(matrix, 1, 2, cols)); // 输出: 42 /* 矩阵乘法 */ int A[6]; /* 2x3 */ int B[6]; /* 3x2 */ int C[4]; /* 2x2 结果 */ matrix_mul(C, A, B, 2, 3, 2); return 0; } ``` --- ### Array3D 库(三维数组) 引入方式:`import array3d;` MiniC 使用一维数组模拟三维数组,通过 `array3d` 库提供便捷的三维数组操作。 | 函数 | 说明 | 示例 | |------|------|------| | `array3d_get(arr, d, r, c, rows, cols)` | 获取元素 | `array3d_get(c, 0, 1, 2, 3, 4)` | | `array3d_set(arr, d, r, c, rows, cols, val)` | 设置元素 | `array3d_set(c, 0, 1, 2, 3, 4, 42)` | | `array3d_init_zero(arr, depths, rows, cols)` | 初始化为0 | `array3d_init_zero(c, 2, 3, 4)` | | `array3d_init_value(arr, depths, rows, cols, val)` | 初始化为值 | `array3d_init_value(c, 2, 3, 4, 1)` | | `array3d_copy(dest, src, depths, rows, cols)` | 复制数组 | `array3d_copy(d, s, 2, 3, 4)` | | `array3d_add(C, A, B, d, r, c)` | 三维数组加法 | `array3d_add(C, A, B, 2, 3, 4)` | | `array3d_scalar_mul(B, A, d, r, c, s)` | 三维数组数乘 | `array3d_scalar_mul(B, A, 2, 3, 4, 2)` | | `array3d_get_layer(layer, arr, d, rows, cols)` | 提取层 | `array3d_get_layer(l, c, 0, 3, 4)` | | `array3d_set_layer(arr, layer, d, rows, cols)` | 设置层 | `array3d_set_layer(c, l, 0, 3, 4)` | **示例:** ```c import array3d; int main() { /* 声明 2x3x4 三维数组(使用一维数组存储) */ int cube[24]; int depths = 2; int rows = 3; int cols = 4; /* 初始化 */ array3d_init_zero(cube, depths, rows, cols); /* 设置元素 */ array3d_set(cube, 1, 2, 3, rows, cols, 42); /* 获取元素 */ print(array3d_get(cube, 1, 2, 3, rows, cols)); // 输出: 42 return 0; } ``` --- ### 编译与运行 ```bash # 构建(推荐) make # 备选构建 mkdir build && cd build && cmake .. && make # 清理 make clean # 六种运行模式(支持长参数和短参数) ./minic -r # 解释执行源码(短参数) ./minic --run # 解释执行源码(长参数) ./minic -c # 编译为字节码并执行(短参数) ./minic --compile # 编译为字节码并执行(长参数) ./minic -d # 反汇编查看字节码(短参数) ./minic --disasm # 反汇编查看字节码(长参数) ./minic -a # 编译为汇编文件(短参数) ./minic --asm # 编译为汇编文件(长参数) ./minic -b # 编译为二进制文件(短参数) ./minic --bin # 编译为二进制文件(长参数) ./minic -l # 加载并执行二进制文件(短参数) ./minic --load # 加载并执行二进制文件(长参数) # 启用 debug 模式(打印 token 信息) ./minic -g -r # 启用 debug 模式并解释执行 ./minic --debug -r # 启用 debug 模式并解释执行(长参数) # 查看帮助信息 ./minic -h # 查看帮助信息(短参数) ./minic --help # 查看帮助信息(长参数) # 运行测试 cd build && ctest # 环境变量(可选) # MINIC_LIB: 指定库目录路径,默认搜索 ./lib export MINIC_LIB=/path/to/lib # 示例 ./minic -r examples/factorial.mc ./minic --bin examples/factorial.mc ./minic -l examples/factorial.mb ./minic -g -r examples/factorial.mc # 从任意目录运行,指定库路径 cd /tmp MINIC_LIB=/path/to/miniC_c/lib /path/to/miniC_c/build/minic -r your_file.mc ``` --- ## 示例程序 ### Hello World ```c int main() { print("Hello World!"); return 0; } ``` ### 求和 ```c int main() { int sum = 0; for (int i = 1; i <= 100; i = i + 1) { sum = sum + i; } print(sum); // 输出 5050 return 0; } ``` ### 阶乘 ```c int factorial(int n) { if (n <= 1) { return 1; } return n * factorial(n - 1); } int main() { print(factorial(5)); // 输出 120 return 0; } ``` ### 函数重载示例 ```c // 函数重载示例 void print(int n) { // 打印整数的实现 putc(n + '0'); putc('\n'); } void print(float f) { // 打印浮点数的实现 int int_part = (int)f; int frac_part = (int)((f - int_part) * 1000); putc(int_part + '0'); putc('.'); putc(frac_part / 100 + '0'); putc((frac_part / 10) % 10 + '0'); putc(frac_part % 10 + '0'); putc('\n'); } void print(char s[]) { // 打印字符串的实现 int i = 0; while (s[i] != '\0') { putc(s[i]); i = i + 1; } putc('\n'); } int main() { print(42); // 调用 print(int) print(3.14); // 调用 print(float) print("Hello"); // 调用 print(char[]) return 0; } ``` ### 全汉字 MiniC 程序 ```c // 定义汉字类型别名 set 整数 is int; set 浮点数 is float; set 字符 is char; // 打印整数函数 void 打印整数(整数 n) { if (n >= 10) { 打印整数(n / 10); } putc(n % 10 + '0'); } // 打印数值函数 void 打印数值(浮点数 数值) { // 打印整数部分 整数 整数部分 = (int)数值; 打印整数(整数部分); putc('.'); 整数 小数部分 = (int)((数值 - 整数部分) * 1000); 打印整数(小数部分); putc('\n'); } int main() { // 测试中文变量名 整数 计数器 = 0; 浮点数 圆周率 = 3.14159; // 测试中文函数名 打印数值(圆周率); // 测试中文常量 let 整数 最大值 = 100; 打印整数(最大值); putc('\n'); return 0; } ``` --- ## 文件结构 ``` src/ ├── lexer.c # 词法分析(上位机,支持 UTF-8 中文字符) ├── parser.c # 语法分析(上位机) ├── ast.c # AST 节点(上位机) ├── interpreter.c # 解释执行(上位机) ├── interpreter_env.c # 解释器环境管理 ├── interpreter_expr.c # 解释器表达式处理 ├── interpreter_stmt.c # 解释器语句处理(支持 putc 语句) ├── parser_expr.c # 解析器表达式处理 ├── parser_stmt.c # 解析器语句处理 ├── parser_type.c # 解析器类型处理 ├── compiler.c # 编译为字节码(上位机,使用 CompileCtx 避免全局状态) ├── vm.c # 虚拟机执行字节码(支持递归调用帧,设计简洁适合单片机) ├── main.c # 入口,处理命令行参数和运行模式(支持长参数和短参数,debug 模式) └── lib.c # 标准库(math, string) ``` **架构特点**: - **上位机组件**:词法分析、语法分析、编译器、解释器,可处理复杂逻辑 - **虚拟机**:设计简洁,指令集精简,适合移植到单片机 - **文件格式**:.mc(源码)、.ma(汇编)、.mb(二进制) --- ## 编译优化与统计功能 ### 编译优化 MiniC 实现了智能编译优化功能,自动移除未使用的函数,减小目标代码大小: - **函数调用分析**:从 `main` 函数开始递归追踪所有被调用的函数 - **智能编译**:只编译被标记为使用的函数,忽略未被调用的函数 - **代码精简**:生成的字节码和汇编代码只包含使用的函数,减小目标代码大小 - **编译加速**:减少编译时间,提高编译效率 ### 统计数据输出 编译完成时,MiniC 会输出详细的统计数据,包括: - **Token 统计**:总 Token 数量 - **函数统计**:总函数数和编译的函数数 - **常量统计**:整数、浮点数、字符串常量数量 - **指令统计**:生成的指令数量 - **字节码大小**:最终字节码大小(以字节为单位) **示例输出**: ``` === Token Statistics === Total tokens: 123 ====================== === Compilation Statistics === Functions: 5 (compiled: 3) Constants: 10 (int), 2 (float), 3 (string) Instructions: 45 Bytecode size: 180 bytes ============================= ``` --- ## 限制与未来 - ❌ 指针(暂不支持) - ✅ 字符串变量(支持 char[] 数组) - ✅ 完整标准库(支持 math、string、array、io 库) - ✅ 中文标识符支持(变量名、函数名、常量名和库名) - ✅ 长参数和短参数命令行选项 - ✅ Debug 模式(打印 token 信息) - ✅ 编译优化(自动移除未使用的函数,减小目标代码大小) - ✅ 函数重载(支持同一函数名的多个版本,根据参数类型和数量自动调用) - ✅ 统计数据输出(编译完成时输出详细的统计信息) - ✅ `ioread` 和 `iowrite` 对外接口,实现对单片机的硬件交换数据 - ✅ **异常处理机制**(try-catch-throw) - ✅ **中断处理机制**(5种中断类型:除零、地址越界、栈溢出、外部中断、时钟中断) - ✅ **统一错误处理**(定义了60+个错误码,支持详细错误信息) - ✅ **字符串处理增强**(substring、concat、compare、split 等15+函数) - ✅ **多维数组支持**(通过 array2d 和 array3d 库实现二维和三维数组) --- ## 异常处理 MiniC 支持 try-catch-throw 异常处理机制,用于处理运行时错误: ```c int main() { try { int a = 10; int b = 0; int c = a / b; // 触发除零错误 print(c); } catch { print("Caught exception!"); } return 0; } ``` ### 异常处理特性 - **try 块**:包含可能抛出异常的代码 - **catch 块**:捕获并处理异常 - **throw 语句**:主动抛出异常 - **异常传播**:未捕获的异常会沿着调用栈向上传播 --- ## 中断处理 MiniC 支持 5 种中断类型,用于处理各种运行时事件: | 中断类型 | 说明 | 触发条件 | |---------|------|---------| | `INTERRUPT_DIVIDE_BY_ZERO` | 除以零中断 | 除法或取模运算中除数为0 | | `INTERRUPT_ADDRESS_OUT_OF_BOUNDS` | 地址越界中断 | 数组访问索引超出范围 | | `INTERRUPT_STACK_OVERFLOW` | 堆栈溢出中断 | 栈空间耗尽 | | `INTERRUPT_EXTERNAL` | 外部中断 | 外部硬件信号 | | `INTERRUPT_CLOCK` | 时钟中断 | 定时器触发 | ### 中断处理示例 ```c int main() { try { int arr[5]; arr[10] = 42; // 触发地址越界中断 } catch { print("Caught address out of bounds!"); } return 0; } ``` ### 中断与异常集成 中断可以触发异常处理机制,被 try-catch 块捕获: - 除零中断 → 异常代码 1 - 地址越界中断 → 异常代码 2 - 栈溢出中断 → 异常代码 3 - 外部中断 → 异常代码 4 - 时钟中断 → 异常代码 5 --- ## 错误处理 MiniC 定义了统一的错误码,支持详细的错误信息: ### 错误码分类 - **通用错误**:内存不足、参数无效等 - **词法/语法错误**:非法字符、语法错误等 - **语义错误**:未定义变量、类型不匹配等 - **数组错误**:非数组访问、索引越界等 - **运行时错误**:除零、栈溢出等 - **中断错误**:各种中断类型错误 - **异常错误**:未捕获异常等 ### 错误信息格式 ``` Error [file.mc:10:5]: Division by zero (code: 28) ``` 包含文件名、行号、列号、错误信息和错误码。 --- ## 编译器与解释器一致性 MiniC 确保编译器和解释器的行为一致: - ✅ **数组操作**:编译器和解释器都进行数组类型检查 - ✅ **浮点数打印**:编译器和解释器都支持 float 和 double 打印 - ✅ **错误处理**:统一的错误码和错误信息格式 - ✅ **中断处理**:虚拟机中实现中断检测和处理 --- ## 更新日志 ### 2026-04-12 - **字符串处理增强**:添加15+个新函数 - substring、concat、compare、startswith、endswith - replace、split、count、repeat、pad_left、pad_right - contains、to_upper_copy、to_lower_copy - **多维数组支持**:创建 array2d 和 array3d 库 - 二维数组:array2d_get/set、matrix_add/sub/mul、matrix_transpose 等 - 三维数组:array3d_get/set、array3d_add、array3d_get_layer 等 - **新增测试文件**:test_string_enhanced.mc、test_array2d.mc、test_array3d.mc ### 2026-04-11 - 添加异常处理机制(try-catch-throw) - 添加中断处理机制(5种中断类型) - 统一错误处理(定义60+个错误码) - 修复编译器与解释器一致性问题 - 支持浮点数打印(float 和 double) ### 2026-04-10 - 添加函数重载支持 - 优化编译器(自动移除未使用函数) - 添加统计数据输出 ### 2026-04-09 - 添加双精度浮点数支持 - 添加浮点比较指令 - 添加类型转换支持 ### 2026-04-08 - 初始版本发布 - 支持基本数据类型和控制流 - 支持函数和递归 - 支持数组和字符串 --- **已知限制:** - 字符串字面量中的中文字符可能无法正确打印(putc 函数仅支持单字节字符) - VM 使用调用帧保存/恢复变量,不支持闭包 - `++` / `--` 仅支持后缀形式 --- *MiniC v1.2 - 让 C 语言学习更简单*