本次更新改动了非常多的文件。 本次更新升级了异常处理系统。
本次更新发行2.4.49
版本。
再三审查后,我认为他是不必要的。
升级异常处理系统的想法诞生于以下背景: 1. 以往的异常处理系统,使用一个字符串来存储异常信息,这种简单做法带来的缺点就是,无法准确快速的获取更详细的信息(例如异常抛出者、异常类型、异常位置)。 2. 以往的异常处理系统,并没有封装文件编解码的异常生成函数,而只封装了编译端和虚拟端的异常生成函数(且两者并不完全统一)。 3. 随着项目的发展,日志系统的开发被认为是需要的。
对异常处理系统的升级,主要分为以下阶段:
在Exception.hpp
中设立STMInfo
。以此代替存储异常信息的字符串。事实上,STMInfo
也可以存储程序运行信息和调试信息,这是将异常处理统一到日志系统的第一步。
STMInfo
更详细的分别存储了异常的各类信息(例如信息发出者,信息发出位置)。STMInfo
也提供了toString()
方法来将异常格式化为字符串。从而让各种异常信息规范化。
以下是STMInfo
的节选代码片段,通过这个片段,我们可以了解STMInfo
存储了哪些信息:
; // 信息发送者
String sender; // 信息类型
String type; // 信息内容
String message; // 信息位置 String position
推荐调用下面这个构造函数来新建STMInfo:
(
STMInfoconst String &Sender,
const String &Type,
const String &Message,
const String &Position
);
在设计完STMInfo
之后,用于异常抛出的STMException
类也进行了改造,将抛出信息的数据类型从原本的字符串改造为STMInfo
。对应的简便宏也做出了调整,具体宏定义如下:
#define THROW(info) ex->Throw(info);
#define CATCH if (ex->isError)
#define WARN(info) ex->Warn(info);
#define ISWARNING (ex->isWarning)
将异常信息的生成函数迁移到stamon::exception
命名空间中。stamon::exception
的子命名空间存储着不同功能的异常信息生成函数。例如stamon::exception::compiler
中存储着编译端的异常信息生成函数。
一个异常信息生成函数的原型通常符合下面的描述:
inline STMInfo 函数名(String position, String 相关参数,...);
函数的返回值一般为STMInfo
类型,函数的第一个参数一般为异常发生的位置,相关参数取决于具体需求,有些函数只有position
参数。
例如AstFileReader.cpp
中出现的代码为例,使用异常生成函数生成一个STMInfo
,然后使用THROW
宏抛出:
(exception::astfilereader::RedundantRootNode("read()")); THROW
而RedundantRootNode
的函数原型如下:
inline STMInfo RedundantEndNodeError(String position);
将异常生成函数和对应的解释转写到JSON
,并用Python编写代码生成脚本。使用
配置+生成脚本
的方式,开发者可以快速的创建异常处理生成函数,并且生成脚本也可以自动生成异常信息处理文档。
在JSON
中声明一个异常信息生成函数,需要按照以下格式填写参数:
{
"type": "异常信息名", // 异常类型
"arg": ["参数1","参数2","..."],
// 参数列表可以为空,生成的参数皆为String类型
"msg": ["一段信息","$参数1","..."],
// 信息列表
// 如果一段信息的开头有“$”符号,则代表这是一个参数
// 否则脚本会把它当作一个字符串字面量
// 脚本会把这些信息和参数拼接在一起
"doc": "该文件存在未知的常量,请检查编码文件或重新编译。"
// 对这个异常的解释和解决措施,脚本会把他整理到文档中
}
一个JSON
配置文件的文件名就是异常信息生成函数要存储的命名空间,例如astrunner.json
中的异常信息生成函数都存在于stamon::exception::astrunner
中。
一个JSON
文件的总体格式如下:
{
"name": "生成的文件名",
"error": [ "一系列异常信息生成函数..." ],
// 函数的格式已在上面说明
"warning": [ "一系列异常信息生成函数..." ]
// warning的函数格式同error
}
我们挑选了较为简短的sfn.json
为例,其代码如下:
{
"name": "SFNException.cpp",
"error": [
{
"type": "SFNError",
"arg": ["msg"],
"msg": ["$msg"],
"doc": "SFN产生的综合性错误。"
}
],
"warning": [
{
"type": "SFNWarning",
"arg": ["msg"],
"msg": ["$msg"],
"doc": "SFN产生的综合性警告。"
}
]
}
交给脚本后,生成SFNException.cpp
,其代码如下:
/*
Name: SFNException.cpp
License: Apache 2.0
Author: CLimber-Rong
Date: 13/07/2025 17:43
Description: 报错信息函数,由codegen.py自动生成
*/
#pragma once
#include "String.hpp"
#include "Exception.hpp"
namespace stamon::exception::sfn {
inline STMInfo SFNError(String position, String msg) {
return STMInfo(String("sfn"), String("SFNError"), msg, position);
}
inline STMInfo SFNWarning(String position, String msg) {
return STMInfo(String("sfn"), String("SFNWarning"), msg, position);
}
}
自动化脚本和配置文件位于src/exception/codegen/
目录,其中,codegen.py
是生成脚本。
生成的文档会被命名为Stamon异常信息修复指南.md
,并存入doc
目录下。
codegen.py
中的setting_list
变量进行对应的修改。setting_list
是一个列表,其成员由一系列元组组成。元组由两个元素构成,第一个元素是配置文件名(不包括.json
后缀),第二个元素是该文件的作者(用于生成文件头注释)。doc_path
变量。src/exception/codegen
目录下运行codegen.py
(该文件依赖time
和json
库)