阶段3-1:编译器语言层 V2 完成(19 类型/字面量扩展/禁隐式转换/配置驱动 FB)

Lexer V2:
- 19 类型关键字(BOOL..DT);FB 名不再设关键字(IDENT)
- FLOAT_LIT(1.5/2.5e3)、进制前缀(2#/8#/16# 换算十进制)
- 日期字面量 D#/TOD#/DT#(历法换算 1970 纪元、闰年、值域检查)

Parser V2:
- TypeRef 字符串化(TypeKind{Scalar,FbBuiltin,FbUser},名字小写)
- ExprKind 增 LitReal/LitDate/LitTod/LitDt;Expr.double_value
- IDENT 类型统一 FbUser(内建判定在 Linker 查 fb 表)

Typecheck V2:
- TType 19 + Unresolved(字面量未定型)
- 禁隐式转换(赋值/算术/比较严格同型)
- resolve_to:未定型→消费点定型+值域检查(BOOL 0/1、无符号负数、
  溢出、浮点仅 REAL/LREAL);算术按 kind 允许(TIME 仅 ±)
- Call 实参按函数参数类型;check_project 加 cfg

Linker V2:
- FbField.type_name 字符串化;内建 FB 布局查 machine.toml [[fb]] 表
  (删 8 个硬编码布局,带缓存);link_project 加 cfg

Codegen V2:
- 浮点/日期字面量(LOADK func 8/4/4/6;LitReal 按 REAL 装载,LREAL TODO)
- 算术/比较 func 按操作数类型(expr_func)
- TypeKind 连锁适配

main.cpp:link/check 传 cfg;--disasm 头 22 字段逐行中文注释(L5)
+ slots 节;StbView 补 offset_const/offset_funcs

测试适配:parser/linker/typecheck/vm/cases 适配新接口与 V2 语义。
ctest 11/13(vm_cycles/cases_all 待阶段 4)。codegen_test 仍剥离(阶段 3-2 重写)。
This commit is contained in:
2026-08-26 09:29:31 +08:00
parent 6ab2195a6b
commit 6be2873c88
16 changed files with 863 additions and 336 deletions
+26 -13
View File
@@ -37,8 +37,24 @@ namespace compiler {
VAR_EXTERNAL, ///< 外部变量段起始
END_VAR, ///< 变量段结束
BOOL, ///< 布尔类型
INT, ///< 整数类型
TIME, ///< 时间类型
BYTE, ///< 位串类型(8 位)
WORD, ///< 位串类型(16 位)
DWORD, ///< 位串类型(32 位)
LWORD, ///< 位串类型(64 位)
SINT, ///< 有符号整数(8 位)
INT, ///< 有符号整数(16 位)
DINT, ///< 有符号整数(32 位)
LINT, ///< 有符号整数(64 位)
USINT, ///< 无符号整数(8 位)
UINT, ///< 无符号整数(16 位)
UDINT, ///< 无符号整数(32 位)
ULINT, ///< 无符号整数(64 位)
TIME, ///< 时间类型(毫秒)
REAL, ///< 浮点类型(32 位)
LREAL, ///< 浮点类型(64 位)
DATE, ///< 日期类型(天数)
TOD, ///< 时刻类型(当日毫秒)
DT, ///< 日期时刻类型(64 位)
IF, ///< IF 关键字
ELSIF, ///< ELSIF 关键字
ELSE, ///< ELSE 关键字
@@ -52,18 +68,14 @@ namespace compiler {
NOT, ///< 逻辑非(前缀)
TRUE, ///< 布尔真字面量
FALSE, ///< 布尔假字面量
TON, ///< 内建 FB 类型名
TOF, ///< 内建 FB 类型名
TP, ///< 内建 FB 类型名
CTU, ///< 内建 FB 类型名
CTD, ///< 内建 FB 类型名
CTUD, ///< 内建 FB 类型名
R_TRIG, ///< 内建 FB 类型名
F_TRIG, ///< 内建 FB 类型名
// 字面量
IDENT, ///< 标识符(text = 小写名)
INT_LIT, ///< 整数字面量(int_value
IDENT, ///< 标识符(text = 小写名;含 FB 类型名,Typecheck 查表
INT_LIT, ///< 整数字面量(int_value;含进制 2#/8#/16# 已换算
FLOAT_LIT, ///< 浮点字面量(double_value
TIME_LIT, ///< 时间字面量(int_value = 毫秒)
DATE_LIT, ///< 日期字面量(int_value = 天数,1970 纪元)
TOD_LIT, ///< 时刻字面量(int_value = 当日毫秒)
DT_LIT, ///< 日期时刻字面量(int64 = date<<32|tod
// 符号
ASSIGN, ///< :=(赋值)
EQ, ///< =(等于)
@@ -92,7 +104,8 @@ namespace compiler {
struct Token {
Tok type; ///< token 类型
std::string text; ///< 标识符/关键字的小写文本;字面量原文
int64_t int_value; ///< INT_LIT / TIME_LIT(毫秒)的字面量值
int64_t int_value; ///< INT_LIT / TIME_LIT / DATE_LIT / TOD_LIT / DT_LIT 的字面量值
double double_value; ///< FLOAT_LIT 的字面量值
std::string source_file; ///< 来源文件名
uint32_t line; ///< 起始行(从 1 起)
uint32_t col; ///< 起始列(从 1 起)
+4 -3
View File
@@ -19,6 +19,7 @@
#include <string>
#include <vector>
#include "compiler/MachineConfig.h"
#include "compiler/Parser.h"
#include "compiler/Project.h"
@@ -51,11 +52,11 @@ namespace compiler {
};
/**
* @brief FB 类型字段(实例布局用;v1 字段类型仅 BOOL/INT/TIME)。
* @brief FB 类型字段(实例布局用;V2 字段类型为标量类型名小写)。
*/
struct FbField {
std::string name; ///< 字段名
TypeKind type = TypeKind::Bool; ///< 字段类型(仅标量
std::string type_name; ///< 字段类型名(小写,如 "bool"/"time"
};
/**
@@ -108,7 +109,7 @@ namespace compiler {
* @return true 成功;false 失败(err 已写)
*/
bool link_project(const Project& proj, const std::vector<SourceUnit>& units,
LinkResult* out, std::string* err);
const MachineConfig& cfg, LinkResult* out, std::string* err);
/**
* @brief 读取并解析一个 .st 文件成 SourceUnit。
+10 -5
View File
@@ -25,14 +25,14 @@ namespace compiler {
* FbBuiltin=内建 FB 类型(TON/TOF/TP/CTU/CTD/CTUD/R_TRIG/F_TRIG);
* FbUser=用户 FB 类型(存在性由 12.6 链接层校验)。
*/
enum class TypeKind { Bool, Int, Time, FbBuiltin, FbUser };
enum class TypeKind { Scalar, FbBuiltin, FbUser };
/**
* @brief 类型引用:种类 + (用户 FB 的)类型名。
*/
struct TypeRef {
TypeKind kind = TypeKind::Bool; ///< 类型种类
std::string name; ///< FbUser 时为用户 FB 类型名(小写)
TypeKind kind = TypeKind::Scalar; ///< 类型种类Scalar=标量 19 型 / FbBuiltin / FbUser
std::string name; ///< 类型名(小写:标量 = machine.toml type 键;FB = fb 表名或用户声明名
};
// ---- 变量段 ----
@@ -75,8 +75,12 @@ namespace compiler {
*/
enum class ExprKind {
LitBool, ///< 布尔字面量(int_value 0/1
LitInt, ///< 整数字面量(int_value
LitInt, ///< 整数字面量(int_value,含进制已换算
LitReal, ///< 浮点字面量(double_value
LitTime, ///< 时间字面量(int_value 毫秒)
LitDate, ///< 日期字面量(int_value 天数,1970 纪元)
LitTod, ///< 时刻字面量(int_value 当日毫秒)
LitDt, ///< 日期时刻字面量(int64 = date<<32|tod
VarRef, ///< 变量引用(name
Field, ///< FB 字段访问(name.field
Not, ///< 逻辑非(operand
@@ -104,7 +108,8 @@ namespace compiler {
BinOp op = BinOp::Eq; ///< 二目运算(Cmp/Add/Sub/Mul/Div 用)
std::string name; ///< VarRef / Field 对象 / Call 函数名
std::string field; ///< Field 字段名
int64_t int_value = 0; ///< 字面量值(BOOL 0/1、INT、TIME 毫秒
int64_t int_value = 0; ///< 字面量值(BOOL 0/1、INT、TIME ms、DATE 天、TOD ms、DT
double double_value = 0; ///< LitReal 字面量值
std::unique_ptr<Expr> lhs; ///< 二目左操作数
std::unique_ptr<Expr> rhs; ///< 二目右操作数
std::unique_ptr<Expr> operand; ///< Not / Neg 的操作数
+11
View File
@@ -164,6 +164,10 @@ namespace compiler {
uint32_t n_consts() const { return n_consts_; }
/// 函数表行数(头 @48)。
uint32_t n_funcs() const { return n_funcs_; }
/// 常量表段偏移(头 @52)。
uint32_t offset_const() const { return offs_of_const(); }
/// 函数表段偏移(头 @56)。
uint32_t offset_funcs() const { return static_cast<uint32_t>(get_le32_(56)); }
/// 字节码段偏移(头 @60)。
uint32_t offset_code() const { return offset_code_; }
/// 槽表段偏移(头 @64)。
@@ -207,6 +211,13 @@ namespace compiler {
/// 常量表偏移(from 已校验的段起点)。
uint32_t offs_of_const() const;
/// 读头内 u32(小端;内部辅助)。
uint32_t get_le32_(size_t off) const {
return static_cast<uint32_t>(buf_[off])
| (static_cast<uint32_t>(buf_[off + 1]) << 8)
| (static_cast<uint32_t>(buf_[off + 2]) << 16)
| (static_cast<uint32_t>(buf_[off + 3]) << 24);
}
const uint8_t* buf_; ///< 映像缓冲(不拥有)
size_t len_; ///< 缓冲字节数
+11 -7
View File
@@ -15,19 +15,23 @@
#include <vector>
#include "compiler/Linker.h"
#include "compiler/MachineConfig.h"
#include "compiler/Parser.h"
#include "compiler/Project.h"
namespace compiler {
/**
* @brief 表达式求值类型(v1 三型,无隐式宽化)。
* @details 各成员含义:
* - Bool:布尔量(逻辑运算 / 条件表达式)
* - Int:整数(算术运算)
* - Time:时间量(仅比较,无算术);INT 与 TIME 不混用
* @brief 表达式求值类型(V219 标量 + 未定型)。
* @details 无隐式转换(赋值/算术/比较严格同型);字面量未定型(Unresolved),
* 由消费点(赋值目标/实参/条件/另一操作数)按上下文定型 + 值域检查;
* BOOL 编译器强制 0/1。
*/
enum class TType { Bool, Int, Time };
enum class TType {
Bool, Byte, Word, Dword, Lword, Sint, Int, Dint, Lint,
Usint, Uint, Udint, Ulint, Time, Real, Lreal, Date, Tod, Dt,
Unresolved, ///< 字面量未定型(待消费点定型)
};
/**
* @brief 对工程做类型检查(在链接成功后调用)。
@@ -39,5 +43,5 @@ namespace compiler {
* @return true 全部通过;false 失败(err 已写)
*/
bool check_project(const Project& proj, const std::vector<SourceUnit>& units,
const LinkResult& link, std::string* err);
const LinkResult& link, const MachineConfig& cfg, std::string* err);
}