实现 12.6 符号表与链接:全局定槽、引用解析、循环检测。
- Linker.h/cpp:收集导出(仅 gvl 文件顶层 VAR_GLOBAL、声明顺序定槽、重复名拒绝) - VAR_EXTERNAL 接同一槽、类型一致;FB 实例必须先声明;字段存在性校验;函数调用图 DFS 环检测 - io.var 必须在 GVL;内建 TON/TOF/CTU 布局冻结;用户 FB 字段 = input/output/var(external 不是字段) - 函数名赋值 = 结果值写入(用例 13 约定);dump_symbols 打印 name kind type address file - linker_test:51 断言(用例 09/10/11/12/16/19 + line1/17 正例),ctest 7/7;20 用例扫描 15 绿 5 按期望拒
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @file Linker.h
|
||||
* @brief 符号表与链接
|
||||
* @author
|
||||
* @date 2026-08-21
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "compiler/Parser.h"
|
||||
#include "compiler/Project.h"
|
||||
|
||||
namespace compiler {
|
||||
|
||||
// 符号种类(与 Doc/初步计划.md 12.1 一致)
|
||||
enum class SymbolKind { Global, External, Local, Input, Output, Pou, FbInstance, Const };
|
||||
|
||||
struct Symbol {
|
||||
SymbolKind kind = SymbolKind::Local;
|
||||
std::string name; // 小写
|
||||
std::string type_name; // bool / int / time / fb 类型名(小写)
|
||||
uint32_t address = 0; // 全局槽号(Global/External);局部暂 0(12.8 分配)
|
||||
std::string source_file;
|
||||
uint32_t line = 0;
|
||||
uint32_t col = 0;
|
||||
};
|
||||
|
||||
// FB 类型字段(实例布局用;v1 字段类型仅 BOOL/INT/TIME)
|
||||
struct FbField {
|
||||
std::string name;
|
||||
TypeKind type = TypeKind::Bool;
|
||||
};
|
||||
|
||||
struct FbLayout {
|
||||
std::string type_name; // 类型名(小写)
|
||||
std::vector<FbField> fields; // 段序:input → output → 内部 var
|
||||
};
|
||||
|
||||
// 一个源文件的 AST(供链接输入)
|
||||
struct SourceUnit {
|
||||
std::string path;
|
||||
Unit ast;
|
||||
};
|
||||
|
||||
// 链接结果
|
||||
struct LinkResult {
|
||||
// 全局槽表:下标即槽号(声明顺序)
|
||||
std::vector<Symbol> globals;
|
||||
std::map<std::string, uint32_t> global_index; // 名 → 槽号
|
||||
|
||||
// 用户 FB 类型布局(按类型名)
|
||||
std::map<std::string, FbLayout> fb_types;
|
||||
|
||||
// 每 POU 的局部符号与 FB 实例
|
||||
struct PouScope {
|
||||
std::string name;
|
||||
PouKind kind = PouKind::Program;
|
||||
std::vector<Symbol> syms; // local/input/output/external/fb_instance
|
||||
std::map<std::string, FbLayout> fb_instances; // 实例名 → 布局
|
||||
};
|
||||
std::vector<PouScope> scopes;
|
||||
|
||||
// 函数表顺序(PROGRAM / FUNCTION / FUNCTION_BLOCK 名,收集序)
|
||||
std::vector<std::string> fn_order;
|
||||
};
|
||||
|
||||
// 链接一个工程:校验 GVL、定全局槽、解析 VAR_EXTERNAL、FB 实例与字段、
|
||||
// 函数循环调用检测、io 校验。失败返回 false,err 前缀 "link error"。
|
||||
bool link_project(const Project& proj, const std::vector<SourceUnit>& units,
|
||||
LinkResult* out, std::string* err);
|
||||
|
||||
// 读取并解析一个 .st 文件成 SourceUnit
|
||||
bool load_unit(const std::string& path, SourceUnit* out, std::string* err);
|
||||
|
||||
// 符号表文本:每行 "name kind type address file"(全局表 + 各 POU 局部表)
|
||||
std::string dump_symbols(const LinkResult& r);
|
||||
}
|
||||
Reference in New Issue
Block a user