# 2023/08/12 工作日志
本次的提交内容很多，架构的改动也很大。让我们来依次介绍。<br>

### 1. 改用VSCode开发
这个项目一直以来都是使用dev-c++开发，现在我正式改用vscode开发，效率更高。<br><br>
不用担心，这个项目可以在没有VSCode的情况下编译运行。

### 2. AST设计
我优化了Ast节点的设计，成功的把33个节点整合到了24个节点。

### 3. 依赖库架构
在以前，我提供了依赖库的模板（以下简称库模板）和基于标准库的依赖库（以下简称标准库）实现方法。<br><br>
但是，每当添加库函数的时候，我需要同时在库模板和标准库添加函数，来保证两者之间的同步，这很麻烦，有的时候也会忘记同步。<br><br>
所以我做了一个决定：删除库模板，只保留标准库。<br><br>
当然，这并不意味着我会放弃“只需要实现依赖库就可以运行STVM”的特性。在项目发布之后，我会根据标准库重新编写库模板，来恢复这一特性。这样，我的项目架构会变得更加精简。

### 4. 依赖库是临时的
由于虚拟机具有GC功能，代码（包括依赖库）都应该向我的内存管理器申请内存。不过由于内存管理器的开发是比较后面的事，所以现在的代码直接向堆申请。<br><br>
故此，现在的依赖库是临时的，我们将在后面把依赖库改装成“向内存管理器申请内存的依赖库”。

### 5. Ast节点定义的代码全部完工
大部分的节点代码来自我的代码生成器（接下来会详细介绍），其他的节点代码都是我手写的。<br><br>

我们先来看一看src/ast目录下每个文件的作用
```C++
ast
|-Ast.hpp       //里面声明了Ast节点的基类，以及各个节点的类型，所有的Ast节点都应该继承这个类
|-LeafAst.cpp   //里面写了例如标识符、字面量等基本节点
|-SfnAst.cpp    //里面写了SFN（后续开发时会详细阐述）节点的定义
|-ExprAst.cpp   //与表达式有关的节点定义
|-CodeLogicAst.cpp  //里面写了如流程控制等与代码逻辑有关的节点
|-code_generator    //这是一个目录，目录里存放着代码生成器的源码
```

如果你尝试阅读Ast节点定义的代码，建议按照以下顺序阅读：

1. Ast.hpp
2. LeafAst.cpp
3. SfnAst.cpp
4. ExprAst.cpp
5. CodeLogic.cpp


如果你想要直接**引用**所有Ast节点，请直接引用Ast.hpp。<br>
注意，所有的Ast都存放在stamon::ast这个命名空间里，所以如果你要**使用**Ast节点，可以写以下代码

```C++
#include"Ast.hpp"   //引用Ast.hpp
using namespace stamon::ast;    //引用Ast的命名空间
```

### 6. 关于Ast代码生成器的原理

**如果你不想了解项目的开发流程，请不要阅读这节内容，也不需要阅读src/ast/code_generator目录下的源码。**

code_generator的目录如下

```C++
|-setting.json      //里面描述了每个节点类的具体信息
|-generator.py      //可以根据setting.json描述的具体信息生成C++代码到code.cpp里
|-code.cpp          //生成出来的C++代码
```

代码生成的流程显而易见：<br>
setting.json（配置件）->generator.py（生成器）->code.cpp（生成结果 ）
<br><br>

注意，生成出来的code.cpp还需要复制粘贴到src/ast目录的源码里。<br><br>

如果你想要尝试着自己生成code.cpp，直接运行generator.py即可，运行它不需要任何额外的参数<br><br>

接下来我们来从里到外的讲一讲setting.json的格式<br><br>

如果你想要声明一个构造函数，应该这么写：

```json
{
    "args": "参数1,参数2,...,参数n",
    "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
}
```

然而，一个类通常有多个构造函数，如果你想描述一个类的所有构造函数，应该这么写

```json
"structure": [
    {
        "args": "参数1,参数2,...,参数n",
        "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
    },
    {
        "args": "参数1,参数2,...,参数n",
        "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
    },
    ...
    {
        "args": "参数1,参数2,...,参数n",
        "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
    }
]
```

是的，用一个列表来存放所有的构造函数<br><br>

当然，一个类不止有构造函数，还有公共成员和私有成员，声明公共成员和私有成员应该这么写：

```json
"private_members": "在这里写私有成员的定义，不需要写 “private:” ",
"public_members": "在这里写公共成员的定义，不需要写 “public:” "
```

描述一个节点类的类名，应该这么写：

```json
"name": "节点的名字（如Expression、Program），不需要加前缀“Ast” "
```

至此，我们已经知道怎么声明构造函数、公共成员、私有成员和类名了，我们用一个字典来存放他们：

```json
{
    "name": "节点的名字（如Expression、Program），不需要加前缀“Ast” ",
    "private_members": "在这里写私有成员的定义，不需要写 “private:” ",
    "public_members": "在这里写公共成员的定义，不需要写 “public:” ",
    "structure": [
        {
            "args": "参数1,参数2,...,参数n",
            "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
        },
        {
            "args": "参数1,参数2,...,参数n",
            "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
        },
        ...
        {
            "args": "参数1,参数2,...,参数n",
            "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
        }
    ]
}
```

现在，我们学会了怎么去声明一个具体的类，但是我们需要声明很多的类，所以我们还要再套一个列表，来存储若干个类。<br><br>
套了列表的代码看起来是这样的：

```json
"ast_class": [
    {
        "name": "节点的名字（如Expression、Program），不需要加前缀“Ast” ",
        "private_members": "在这里写私有成员的定义，不需要写 “private:” ",
        "public_members": "在这里写公共成员的定义，不需要写 “public:” ",
        "structure": [
            {
                "args": "参数1,参数2,...,参数n",
                "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
            },
            {
                "args": "参数1,参数2,...,参数n",
                "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
            },
            ...
            {
                "args": "参数1,参数2,...,参数n",
                "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
            }
        ]
    },
    ...
    {
        "name": "节点的名字（如Expression、Program），不需要加前缀“Ast” ",
        "private_members": "在这里写私有成员的定义，不需要写 “private:” ",
        "public_members": "在这里写公共成员的定义，不需要写 “public:” ",
        "structure": [
            {
                "args": "参数1,参数2,...,参数n",
                "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
            },
            {
                "args": "参数1,参数2,...,参数n",
                "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
            },
            ...
            {
                "args": "参数1,参数2,...,参数n",
                "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
            }
        ]
    }
]
```

我们已经学会了怎么声明若干个节点类，现在我们用一个字典来存放若干个节点类，就大功告成了:

```json
{
    "ast_class": [
        {
            "name": "节点的名字（如Expression、Program），不需要加前缀“Ast” ",
            "private_members": "在这里写私有成员的定义，不需要写 “private:” ",
            "public_members": "在这里写公共成员的定义，不需要写 “public:” ",
            "structure": [
                {
                    "args": "参数1,参数2,...,参数n",
                    "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
                },
                {
                    "args": "参数1,参数2,...,参数n",
                    "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
                },
                ...
                {
                    "args": "参数1,参数2,...,参数n",
                    "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
                }
            ]
        },
        ...
        {
            "name": "节点的名字（如Expression、Program），不需要加前缀“Ast” ",
            "private_members": "在这里写私有成员的定义，不需要写 “private:” ",
            "public_members": "在这里写公共成员的定义，不需要写 “public:” ",
            "structure": [
                {
                    "args": "参数1,参数2,...,参数n",
                    "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
                },
                {
                    "args": "参数1,参数2,...,参数n",
                    "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
                },
                ...
                {
                    "args": "参数1,参数2,...,参数n",
                    "code": "在这里写上构造函数的函数体（不需要用花括号嵌套）"
                }
            ]
        }
    ]
}
```

这就是描述若干个节点类的格式，从构造函数的声明开始一步一步看下来，也不会太复杂。

### 7. 接下来要做的事
1. 完成STVM数据类型的定义
2. 完成STVM内部数据结构的部分定义