# 2025/07/13 工作日志

本次更新改动了非常多的文件。
本次更新升级了异常处理系统。
本次更新发行``2.4.49``版本。

### 忽略.vscode目录

再三审查后，我认为他是不必要的。

### 升级异常处理系统

升级异常处理系统的想法诞生于以下背景：
1. 以往的异常处理系统，使用一个字符串来存储异常信息，这种简单做法带来的缺点就是，无法准确快速的获取更详细的信息（例如异常抛出者、异常类型、异常位置）。
2. 以往的异常处理系统，并没有封装文件编解码的异常生成函数，而只封装了编译端和虚拟端的异常生成函数（且两者并不完全统一）。
3. 随着项目的发展，日志系统的开发被认为是需要的。

对异常处理系统的升级，主要分为以下阶段:

##### 改装存储异常信息的载体

在``Exception.hpp``中设立``STMInfo``。以此代替存储异常信息的字符串。事实上，``STMInfo``也可以存储程序运行信息和调试信息，这是将异常处理统一到日志系统的第一步。

``STMInfo``更详细的分别存储了异常的各类信息（例如信息发出者，信息发出位置）。``STMInfo``也提供了``toString()``方法来将异常格式化为字符串。从而让各种异常信息规范化。

以下是``STMInfo``的节选代码片段，通过这个片段，我们可以了解``STMInfo``存储了哪些信息：

```C++
String sender; // 信息发送者
String type; // 信息类型
String message; // 信息内容
String position; // 信息位置
```

推荐调用下面这个构造函数来新建STMInfo：

```C++
STMInfo(
    const String &Sender,
    const String &Type,
    const String &Message,
    const String &Position
);
```

在设计完``STMInfo``之后，用于异常抛出的``STMException``类也进行了改造，将抛出信息的数据类型从原本的字符串改造为``STMInfo``。对应的简便宏也做出了调整，具体宏定义如下：

```C++
#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``中存储着编译端的异常信息生成函数。

一个异常信息生成函数的原型通常符合下面的描述：

```C++
inline STMInfo 函数名(String position, String 相关参数,...);
```

函数的返回值一般为``STMInfo``类型，函数的第一个参数一般为异常发生的位置，相关参数取决于具体需求，有些函数只有``position``参数。

例如``AstFileReader.cpp``中出现的代码为例，使用异常生成函数生成一个``STMInfo``，然后使用``THROW``宏抛出：

```C++
THROW(exception::astfilereader::RedundantRootNode("read()"));
```

而``RedundantRootNode``的函数原型如下：

```C++
inline STMInfo RedundantEndNodeError(String position);
```

##### 使用自动化脚本生成异常信息函数的代码及文档

将异常生成函数和对应的解释转写到``JSON``，并用Python编写代码生成脚本。使用 **配置+生成脚本** 的方式，开发者可以快速的创建异常处理生成函数，并且生成脚本也可以自动生成异常信息处理文档。

在``JSON``中声明一个异常信息生成函数，需要按照以下格式填写参数：

```json
{
    "type": "异常信息名",   // 异常类型
    "arg": ["参数1","参数2","..."],
    // 参数列表可以为空，生成的参数皆为String类型
    "msg": ["一段信息","$参数1","..."],
    // 信息列表
    // 如果一段信息的开头有“$”符号，则代表这是一个参数
    // 否则脚本会把它当作一个字符串字面量
    // 脚本会把这些信息和参数拼接在一起
    "doc": "该文件存在未知的常量，请检查编码文件或重新编译。"
    // 对这个异常的解释和解决措施，脚本会把他整理到文档中
}
```

一个``JSON``配置文件的文件名就是异常信息生成函数要存储的命名空间，例如``astrunner.json``中的异常信息生成函数都存在于``stamon::exception::astrunner``中。

一个``JSON``文件的总体格式如下：

```json
{
    "name": "生成的文件名",
    "error": [ "一系列异常信息生成函数..." ],
    // 函数的格式已在上面说明
    "warning": [ "一系列异常信息生成函数..." ]
    // warning的函数格式同error
}
```

我们挑选了较为简短的``sfn.json``为例，其代码如下：

```json
{
  "name": "SFNException.cpp",
  "error": [
    {
      "type": "SFNError",
      "arg": ["msg"],
      "msg": ["$msg"],
      "doc": "SFN产生的综合性错误。"
    }
  ],
  "warning": [
    {
      "type": "SFNWarning",
      "arg": ["msg"],
      "msg": ["$msg"],
      "doc": "SFN产生的综合性警告。"
    }
  ]
}
```

交给脚本后，生成``SFNException.cpp``，其代码如下：

```c++
/*
	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``变量。
* 如果想要运行自动化脚本，则直接使用Python解释器，在``src/exception/codegen``目录下运行``codegen.py``（该文件依赖``time``和``json``库）