TzdTools 是一个自定义编程语言 TzdLang 的开发工具链,包含语言解释器、VSCode 扩展支持和丰富的标准库。
TzdLang 是一门面向对象的编程语言,具有现代语言特性,包括:
- 类继承和多态
- 异常处理机制
- 线程支持
- 动态类型系统
- JIT 编译支持
TzdTools/
├── README.md # 项目说明文档
├── bench.py # Python 性能基准测试
├── bench.tzd # TzdLang 性能基准测试
├── TzdLang_Reference.pdf # 语言参考手册
├── TzdTools/ # C++ 源代码和构建产物
│ ├── stdlib/ # 标准库
│ │ ├── core/ # 核心功能库
│ │ └── thread/ # 线程支持库
│ └── x64/ # 构建输出目录
│ ├── Release/ # 发布版本
│ └── Debug/ # 调试版本
├── vscodePlugin/ # VSCode 扩展
│ └── tzdlang/ # TzdLang VSCode 扩展
├── examples/ # 示例代码
├── test_*.tzd # 测试文件
└── Generated/ # ANTLR 生成的代码
项目使用 C++ 开发,需要 Visual Studio 2019 或更高版本:
# 使用 Visual Studio 打开解决方案
# 或在命令行中构建
msbuild TzdTools.sln /p:Configuration=Release /p:Platform=x64项目包含完整的 VSCode 扩展支持:
- 安装扩展 (直接使用 .vsix 文件或开发模式)
- 配置 TzdTools.exe 路径
- 享受语法高亮、代码补全和调试功能
// 变量声明
var int x = 10;
var string name = "TzdLang";
// 函数定义
fun greet(name) {
print("Hello, " + name + "!");
}
// 类定义
class Person {
var string name;
Person(name) {
this.name = name;
}
fun introduce() {
print("I am " + this.name);
}
}
注意:for 循环的第一个表达式不能指定类型,包括 var
正确的 for 循环语法:
// 正确的语法
for (i = 0; i < 5; i = i + 1) {
print(i);
}
// 正确的语法
for (j = 0; j < 10; j++) {
if (j == 3) break;
print(j);
}
// 错误的语法(不支持)
for (var i = 0; i < 5; i++) {
// 这种写法会报错
}
while 循环和 break 语句
// while 循环
var i = 0;
while (i < 5) {
print("i = " + i);
i = i + 1;
}
// 使用 break 退出循环
for (j = 0; j < 10; j++) {
if (j == 3) break;
print(j);
}
class Animal {
var string name;
Animal(name) { this.name = name; }
fun speak() { print(this.name + " says ..."); }
}
class Dog extends Animal {
Dog(name) : super(name) {}
fun speak() { print(this.name + " barks! woof!"); }
}
fun testOop() {
var d = new Dog("Buddy");
d.speak(); // 输出: Buddy barks! woof!
}
import "core/Error.tzd";
fun runDemo() {
try {
throw new Error("test error", "TEST");
} catch (err) {
print("caught: " + err.code + " " + err.message);
}
}
import "thread/Thread.tzd";
fun worker() {
for (i = 0; i < 5; i++) {
print("Thread: " + i);
sleep(1000);
}
}
var t = new Thread(worker);
t.start();
t.join();
TzdLang 支持完整的调试功能,包括:
断点管理
- 设置断点:通过调试器界面或命令行
- 清除断点:支持按文件和行号删除
- 条件断点:支持基于条件的断点触发
调试控制
continue- 继续执行到下一个断点step into- 进入当前函数调用step over- 跳过当前函数调用step out- 退出当前函数调用pause- 暂停执行
状态检查
- 堆栈跟踪:显示函数调用堆栈
- 变量查看:检查当前作用域的变量值
- 表达式求值:实时计算表达式值
fun greet(name) {
print("Greeting started...");
msg = "Hello " + name;
print(msg);
print("Greeting ended.");
}
print("Main script started.");
greet("TzdLang");
print("Main script ended.");
fun testPerformance() {
var start = clock();
var i = 0;
while (i < 50000) {
if (i == 10000) { print("进度: 20%"); }
if (i == 20000) { print("进度: 40%"); }
if (i == 30000) { print("进度: 60%"); }
if (i == 40000) { print("进度: 80%"); }
i = i + 1;
}
var end = clock();
print("完成,耗时: " + ((end - start) / 1000.0) + " s");
}
fun testException() {
var i = 0;
while (i < 100000) {
if (i == 10) {
throw "测试异常";
}
i = i + 1;
}
}
testException();
- TzdLang: 运行当前脚本 (F5) - 运行当前打开的 .tzd 文件
- TzdLang: 重新设置 TzdTools 路径 - 配置解释器路径
- TzdLang: Hello World - 显示问候信息
完整的集成调试支持,包括:
调试控制
- 启动调试:F5 或运行按钮
- 暂停/继续:暂停执行和继续运行
- 单步执行:
- Step Into (F11) - 进入函数
- Step Over (F10) - 跳过函数
- Step Out (Shift+F11) - 退出函数
- 断点管理:
- 点击行号设置断点
- 右键菜单管理断点
- 条件断点支持
调试信息显示
- 变量监视:实时查看变量值
- 调用堆栈:显示函数调用层次
- 输出控制台:显示程序输出和调试信息
- 错误提示:语法和运行时错误提示
{
"tzdlang.toolsPath": "C:/path/to/TzdTools.exe"
}- 语法高亮
- 代码自动补全
- 错误检查
- 完整的调试支持
- 一键运行
- 断点管理
- 堆栈跟踪
- 变量监视
基本调试
- 打开 .tzd 文件
- 设置断点(点击行号)
- 按 F5 启动调试
- 使用调试控制按钮控制执行
- 查看变量值和堆栈信息
调试配置
{
"version": "0.2.0",
"configurations": [
{
"name": "TzdLang Debug",
"type": "tzdlang",
"request": "launch",
"program": "${file}",
"stopOnEntry": true,
"console": "integratedTerminal"
}
]
}项目包含丰富的测试用例,涵盖语言的各个方面:
test_loop.tzd- while 循环语法测试test_bool.tzd- 布尔值和条件表达式测试test_func_loop.tzd- 函数和循环组合测试test_break.tzd- break 语句测试test_1k_loop.tzd- 基础循环性能测试
test_script.tzd- 脚本功能测试(继承、多态、异常处理)test_error_demo.tzd- 错误处理演示test_feat.tzd- 语言功能特性测试test_debug.tzd- 调试功能演示test_throw_while.tzd- 循环中的异常处理
test_progress_while.tzd- 大型循环进度监控test_100k_while.tzd- 大型循环性能测试test_100k_exit_no_semicolon.tzd- 退出语句测试test_no_loop.tzd- 无循环代码测试
examples/test.tzd- 基础面向对象功能演示test_script.tzd- 类继承和方法重写
bench.tzd- 基本性能基准测试bench_func.tzd- 函数调用性能测试math_loop.tzd- 数学计算性能测试
# 运行所有测试
TzdTools.exe --runMainTzd=test_all.tzd
# 运行单个测试
TzdTools.exe --runMainTzd=test_loop.tzd
# 运行性能测试
TzdTools.exe --runMainTzd=bench.tzd项目包含 Python 和 TzdLang 的对比基准测试:
# Python 版本
python bench.py
# TzdLang 版本
TzdTools.exe --runMainTzd=bench.tzd
# 函数调用性能测试
TzdTools.exe --runMainTzd=bench_func.tzd
# 数学计算性能测试
TzdTools.exe --runMainTzd=math_loop.tzd项目使用 Visual Studio 2019 或更高版本构建:
# 构建发布版本
msbuild TzdTools.sln /p:Configuration=Release /p:Platform=x64
# 构建调试版本
msbuild TzdTools.sln /p:Configuration=Debug /p:Platform=x64
# 清理构建文件
msbuild TzdTools.sln /p:Clean=true使用 ANTLR4 生成的解析器:
# 生成词法分析器和语法分析器
antlr4 -Dlanguage=Cpp -no-listener -visitor TzdLang.g4
# 生成访问者模式的代码
antlr4 -Dlanguage=Cpp -visitor TzdLang.g4
# 生成监听器模式的代码
antlr4 -Dlanguage=Cpp -listener TzdLang.g4命令行调试
# 启动调试模式
TzdTools.exe --debug --runMainTzd=script.tzd
# 连接调试客户端
TzdTools.exe --debug-server --port=8080
# 堆栈跟踪
TzdTools.exe --stack-trace --runMainTzd=script.tzd调试命令系统
break <file>:<line>- 设置断点clear <file>:<line>- 清除断点continue- 继续执行step- 单步执行next- 下一步finish- 完成当前函数where- 显示堆栈print <expr>- 打印表达式值
VSCode 扩展开发
# 安装依赖
cd vscodePlugin/tzdlang
npm install
# 构建扩展
npm run compile
# 运行测试
npm test
# 打包扩展
npm run vsce-packageIDE 配置
{
"files.associations": {
"*.tzd": "tzdlang",
"*.tzdlang": "tzdlang"
},
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true
}
}Error.tzd - 错误处理和异常机制
// 自定义异常
throw new Error("错误消息", "错误代码");
// 异常捕获
try {
// 可能抛出异常的代码
riskyOperation();
} catch (err) {
print("错误: " + err.message + " (代码: " + err.code + ")");
}
DatabaseConnectionError.tzd - 数据库连接错误处理
// 数据库连接错误处理
import "core/DatabaseConnectionError.tzd";
try {
// 数据库操作
db.connect();
} catch (err) {
if (err in DatabaseConnectionError) {
print("数据库连接失败: " + err.message);
}
}
Thread.tzd - 多线程支持
import "thread/Thread.tzd";
// 创建线程
fun workerThread() {
for (var i = 0; i < 5; i++) {
print("工作线程: " + i);
sleep(1000);
}
}
var t = new Thread(workerThread);
t.start(); // 启动线程
t.join(); // 等待线程完成
// 导入标准库
import "core/Error.tzd";
import "thread/Thread.tzd";
// 使用标准库功能
fun main() {
// 使用异常处理
try {
throw new Error("测试错误", "TEST_ERROR");
} catch (err) {
print("捕获错误: " + err.message);
}
// 使用线程
var thread = new Thread(fun() {
print("在线程中执行");
});
thread.start();
thread.join();
}
TzdLang 的 JIT 编译器基于 LLVM ORC JIT,经过多轮深度优化,在多项基准测试中超越 JDK HotSpot。
# 必须使用 VS Community 18 (MSVC v144) 构建
# 构建后如遇增量检测失败,删除 .obj 文件强制重编译
del x64\Release\TzdJit.obj
"C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" TzdTools.vcxproj /p:Configuration=Release /p:Platform=x64 /t:Build /m# 多操作基准测试(循环、递归、Ackermann、素数、函数调用等)
TzdTools.exe --runMainTzd=bench_compare.tzd
# 对象操作基准测试(创建、字段读取)
TzdTools.exe --runMainTzd=bench_object.tzd
# 与 Java 对比
javac BenchCompare.java && java BenchCompare| 操作 | TzdLang | JDK | 倍率 |
|---|---|---|---|
| 函数调用 callOverhead(1M) | 0.002s | 0.005s | TzdLang 快 2.5x |
| 嵌套循环 nestedLoop(1k×1k) | 0.003s | 0.005s | TzdLang 快 1.7x |
| 简单循环 sumLoop(1M) | 0.002s | 0.003s | TzdLang 快 1.5x |
| Ackermann(3,6) | 0.001s | 0.001s | TzdLang 快 1.2x |
| Newton 平方根 | 0.000006s | 0.000008s | TzdLang 快 1.3x |
| fib(35) 递归 | 0.197s | 0.061s | JDK 快 3.2x |
| 素数 primes(10k) | 0.218s | 0.003s | JDK 快 72x |
| 对象字段读取 field(100k) | 0.002s | 0.0005s | JDK 快 4x |
inlineStoreNativeToPtr— 直接通过offsetofGEP+Store 写 TzdValue 的 type 和 dVal 字段,消除rt_store_native_to_ptr函数调用
- 为每个函数生成原生 double worker:
double fib_worker_native(ptr interp, double n) - 自递归直接传 double 参数,完全消除 TzdValue arg array 分配、
rt_init_tzd_value、rt_store_native_to_ptr、rt_to_double_fast baseName提取支持_worker_native后缀(14 字符)+ 版本号剥离
AlwaysInline属性标记 native workerAlwaysInlinerPass(模块级 pass)内联自递归和跨函数调用mem2reg+EarlyCSE+DCE函数级优化
s_compiledNativeWorkers编译时映射表,跳过rt_call_sub_fast字符串查找%运算自适应整数特化:FPToSI+SRem(单指令idiv)替代fmod(库调用)
visitEqualityExpr原生 double 快速路径:==和!=直接CreateFCmpOEQ/ONE,消除 2 次堆分配 + 4 次外部调用clock()静态初始化顺序修复AlwaysInlinerPass从 CGSCC 改为模块级(修复 API 不匹配)- 数组索引
visitIndexExpr始终返回TzdValue*指针(修复对象数组 bug) visitVarDeclStmt使用CreateEntryBlockAlloca(使 mem2reg 可提升数值局部变量)
rt_tzd_get_member+rt_to_double_fast标记ReadOnly属性,LLVM CSE/LICM 消除循环中冗余字段读取rt_store_field_ptr轻量字段存储(拆分自rt_tzd_store_member,配合 readonly get_member 可被 CSE)rt_tzd_call_method标记NoCallback+WillReturnvisitNewExpr跳过rt_set_location调试开销- 数组指针存储修复(
arr[i] = object使用 boxed 路径)
TzdLang 脚本
│
▼
ANTLR4 解析 → AST
│
▼
TzdCompiler (AST → LLVM IR)
├── 每个函数生成 3 个版本:
│ 1. Entry function (void entry(ptr interp, ptr retVal)) — 供 C++ 解释器调用
│ 2. Worker function (double worker(ptr, ptr, ptr)) — 正常执行
│ 3. Native worker (double worker_native(ptr, double...)) — 原生 double 自递归
│
▼
LLVM 优化管线
├── AlwaysInlinerPass (模块级 — 内联 AlwaysInline 函数)
├── PromotePass (mem2reg — alloca → SSA 寄存器)
├── EarlyCSEPass (公共子表达式消除 — 利用 ReadOnly 属性)
└── DCEPass (死代码消除)
│
▼
LLVM IR → 目标代码 (预编译为 .obj 避免 CRT 析构栈溢出)
│
▼
JIT 执行 (LLJIT + ObjectLayer)
- 预编译方式:IR → Object file(泄漏 Module 避免 CRT ABI 不匹配的析构栈溢出)
- 分析管理器泄漏:
ModuleAnalysisManager等析构会栈溢出,故泄漏为static堆对象 - NoInline on Worker:正常 worker 标记
NoInline防止过度内联;native worker 标记AlwaysInline - Native worker 仅在 argCount > 0 时创建:0 参数函数无特化收益
- 栈大小 256MB:
/STACK:"268435456"应对深度递归
- 脚本开发
- 教育和演示
- 性能测试
- 原型开发
- 语言研究
[在此添加许可证信息]
- Fork 项目
- 创建功能分支
- 提交更改
- 发起 Pull Request
如有问题或建议,请提交 Issue 或联系开发者。
TzdLang - 现代化的编程语言开发工具链