编辑器、调试信息、可观测性与测试
1. 工具体验是语言的一部分#
目录包含专用脚本编辑器、SanScriptParser2、Visual Studio 语言支持相关工程、通用 C# 文法和游戏内 debugger。它们承担补全、符号解析、工程依赖、编译、错误跳转和调试,不应将 C# parser 误认成输出游戏字节码的实际编译器。[S1]
多个语言前端并存说明团队投入了长期工具维护;也带来漂移风险,例如编辑器仍有 HSM 开关,而当前主文法不能确认对应语法。新语言最好让 IDE 和编译器共享语义模型,而不是复制关键词表与类型规则。
2. 从源码位置到运行状态#
编译器输出 .scd 调试信息,包含类型、全局/静态/局部变量、源码文件与行到 PC 的映射等。游戏调试器加载 .scd,检查版本和匹配关系,依据这些信息显示变量和定位代码。[S2]
优化、分页填充、函数按需生成都会使源行与 opcode 不再一一对应。调试器必须面对一个源行映射多个 PC、某些行没有运行指令以及不同脚本实例共享程序代码等情况。
断点既可对单个线程设置,也可对某程序的多个线程设置,并有是否停止游戏等行为选择。单步可使用 PC 范围和临时断点。WAIT 导致跨帧执行,调试器需要展示“正在等待什么”,不能只显示某个调用栈顶。[S2]
3. 性能观测已有明确分层#
VM 的 profiling 记录脚本函数的排除子调用时间、指令数以及 Native 时间,还记录峰值和更新次数;游戏 CScriptDebug 提供 profile overview、排序和脚本内存显示。[S3]
这直接支持一个重要分析方法:把脚本解释执行成本与 Native 成本分开。一个函数只有很少 opcode,也可能通过一次 Native 创建大量对象;另一方面,高频小 Native 的封送和重复查找也可能累计显著成本。
PROFILE 配置使用 -final -forcename,显示作者尝试在裁剪调试逻辑的同时保留过程名。不能把它等同纯 Release 或纯 Debug,应把构建选项记录在每次剖析旁边。[S4]
4. 数据调试与作者工作流#
DEBUGONLY、#IF IS_DEBUG_BUILD、TWEAK、Widget 命令允许开发者暴露参数、检查状态和进行游戏内调试。autosave_controller.sc 用 Widget 显示保存请求、完成状态和调试阻断开关,说明工具直接嵌入内容开发流程。[S5]
这类工作流对策划生产力可能比复杂语言特性更有价值:修改参数、快速定位当前状态、重启局部场景、看见 Native 失败原因。新语言应在第一版就提供错误源码位置、可读调用栈、实例列表、资源归属和内存预算。
5. 已有测试与其证据边界#
编译器目录有大量小测试以及 good.txt 基准输出。check.bat 组织编译、反汇编、运行和输出 diff,还保留 C++ 生成/旧平台检查步骤;本次未运行该脚本。当前 sc.cpp 又把编译后执行开关设为 0,说明旧测试驱动与当前执行路径需要重新核对。[S6]
代表性文件:
| 测试 | 可阅读的主题 |
|---|---|
| test01.sc | 基础数值、VECTOR、时间运算和 WAIT |
| test21.sc | 嵌套结构及引用修改 |
| test47.sc | CATCH/THROW 恢复 |
| test68.sc | TYPEDEF、函数地址和间接调用 |
| test98.sc | SIZE_OF、数组与结构大小 |
| net_jacking_soaktest.sc | 联机创建、广播、机器人及终止 |
存在测试文件不等于当前版本全部通过;有些测试也可能用于验证诊断或历史功能。本文只用它们帮助识别设计意图与可测试主题。
6. 新语言应建立的测试矩阵#
| 层 | 关键测试 | 验收关注点 |
|---|---|---|
| Lexer/parser | 大小写、转义、嵌套、缺失 END、残缺源码 | 编译器和 IDE 一致且错误定位正确 |
| 类型/ABI | 默认参数、句柄子类型、引用写回、向量、数组长度 | 不兼容调用被拒绝,大小/对齐匹配 |
| 语义 | 短路副作用、循环上界、除零、溢出、NaN/负零 | 参考解释器、优化前后和发布内核一致 |
| 控制流 | 深调用、间接调用、挂起后恢复、取消 | 帧与资源不损坏,故障定位可靠 |
| 加载安全 | 错 opcode、坏跳转、错误栈高度、失配 Native | 拒绝不合法产物,不破坏宿主 |
| 资源生命周期 | 模型失败、实例终止、资源转移、卸载 | 引用收敛,无遗留归属 |
| 兼容性 | 存档增删字段、Native 版本、模块更新 | 明确兼容或明确拒绝 |
| 网络 | 迟加入、丢包、迁移、断线、重复消息 | 权威、恢复与去重符合契约 |
可增加基于语法/typed AST 的生成测试和多 VM 差分测试。但不建议只用“编译输出和自身快照相同”作为唯一正确性证据:错误编译器也会稳定生成相同错误。
7. 对开发体验的具体建议#
统一机器可读诊断与稳定错误码,支持 include/宏展开来源;调试文件绑定模块内容哈希;Profiler 关联脚本函数、Native、对象创建量与网络消息量。对关键错误直接展示脚本名、源码行、参数摘要和资源归属。
热重载在 UI 上必须说明是重启实例还是保留状态迁移。对大项目,提供 include 依赖扇出、每个头文件引入的静态槽数和“为什么重新编译”的解释,比单纯增加语法高亮更能解决实际瓶颈。
源码证据#
- S1 — SanScriptParser2;独立 C# 文法。
- S2 — debugger.cpp:调试信息检查;SetBreakpoint。
- S3 — VM profiling;游戏概览。
- S4 — PROFILE 参数。
- S5 — autosave Widget。
- S6 — check.bat;sc.cpp 的运行开关。
- 测试源码:test01、test21、test47、test68、test98。