From e187ed7b036005fe0d5bf00a2ff482d71304c04c Mon Sep 17 00:00:00 2001 From: chentianya Date: Fri, 21 Aug 2026 22:16:48 +0800 Subject: [PATCH] =?UTF-8?q?=E9=98=B6=E6=AE=B5=20B=20=E6=AD=A5=E9=AA=A4=205?= =?UTF-8?q?=EF=BC=9A=E7=B1=BB=E5=9E=8B=E5=85=83=E6=95=B0=E6=8D=AE=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=8C=96=EF=BC=88TypeInfo=EF=BC=89=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - TypeInfo.h/cpp:TypeMeta(配置别名 + 内建基元解析),查询大小写不敏感; 提供 width/is_signed/is_float/tag/has_range/value_in_range - Codegen:layout_data 初值按 type_meta 的基元宽度/浮点写(删除手写宽度分支); const_id 的 tag 改查 type_meta - machine_test:+10 断言(BOOL 1B/range[0,1]/tag0、INT 2B 有符号、TIME 8B、大小写不敏感、未定义空) - 验收:line1 224 字节 hash 0xc3fe4ae74ad45900 不变、ctest 12/12 --- compiler/CMakeLists.txt | 3 +- compiler/include/compiler/TypeInfo.h | 41 ++++++++++++++++++++++++++++ compiler/src/Codegen.cpp | 20 +++++++------- compiler/src/TypeInfo.cpp | 41 ++++++++++++++++++++++++++++ tests/src/machine_test.cpp | 33 ++++++++++++++++++++++ 5 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 compiler/include/compiler/TypeInfo.h create mode 100644 compiler/src/TypeInfo.cpp diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt index 966e3d3..08045cf 100644 --- a/compiler/CMakeLists.txt +++ b/compiler/CMakeLists.txt @@ -17,7 +17,8 @@ add_library(compiler STATIC ./src/Codegen.cpp ./src/MachineConfig.cpp ./src/Stb.cpp - ./src/Codec.cpp) + ./src/Codec.cpp + ./src/TypeInfo.cpp) target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(compiler PRIVATE ${CMAKE_SOURCE_DIR}/third_party/tomlplusplus/include) diff --git a/compiler/include/compiler/TypeInfo.h b/compiler/include/compiler/TypeInfo.h new file mode 100644 index 0000000..45157a1 --- /dev/null +++ b/compiler/include/compiler/TypeInfo.h @@ -0,0 +1,41 @@ +/** + * @file TypeInfo.h + * @brief 语言类型元数据(machine.toml 别名 + 内建基元解析) + * @author + * @date 2026-08-21 + * + * @details 类型定义数据化(配置),运算/类型检查语义代码化: + * - 元数据(宽度/符号/浮点/base/range/tag)全部来自 machine.toml + 内建基元表 + * - 查询大小写不敏感(配置名大写,Linker type_name 小写) + */ + +#pragma once + +#include +#include + +#include "compiler/MachineConfig.h" + +namespace compiler { + + // 语言类型元数据 + struct TypeMeta { + const ConfigType* config = nullptr; // 配置类型行(别名 + range + tag) + const PrimType* prim = nullptr; // 内建基元(宽度/符号/浮点) + + uint32_t width() const { return prim ? prim->width : 0; } + bool is_signed() const { return prim ? prim->is_signed : false; } + bool is_float() const { return prim ? prim->is_float : false; } + uint32_t tag() const { return config ? config->tag : 0; } + bool has_range() const { return config ? config->has_range : false; } + bool value_in_range(int64_t v) const { + return !config || !config->has_range || + (v >= config->range_min && v <= config->range_max); + } + + explicit operator bool() const { return config != nullptr && prim != nullptr; } + }; + + // 按语言类型名查元数据(大小写不敏感;未找到返回空 TypeMeta) + TypeMeta type_meta(const MachineConfig& cfg, const std::string& name); +} diff --git a/compiler/src/Codegen.cpp b/compiler/src/Codegen.cpp index 7634283..d330815 100644 --- a/compiler/src/Codegen.cpp +++ b/compiler/src/Codegen.cpp @@ -42,6 +42,7 @@ #include "compiler/Codec.h" #include "compiler/MachineConfig.h" #include "compiler/Stb.h" +#include "compiler/TypeInfo.h" namespace compiler { namespace { @@ -589,20 +590,19 @@ namespace { const int64_t v = has_init ? init : 0; const size_t off = static_cast(s.address) * 8; data_.resize(off + 8, 0); - // 初值按基元宽度写(类型元数据来自配置别名 → base) - const ConfigType* ct = cfg_.find_type(uppercase_of(s.type_name)); - if (ct == nullptr) { + // 初值按类型元数据写(配置别名 → 基元宽度/浮点) + const TypeMeta tm = type_meta(cfg_, s.type_name); + if (!tm) { return fail("no type in machine.toml for '" + s.type_name + "'"); } - const PrimType* prim = MachineConfig::find_prim(ct->base); - if (prim == nullptr) { - return fail("no prim '" + ct->base + "' for type '" + ct->name + "'"); + if (tm.is_float()) { + return fail("float initializer not supported yet"); } - if (prim->width == 2 && !prim->is_float) { + if (tm.width() == 2) { const uint16_t iv = static_cast(v); data_[off] = static_cast(iv & 0xFFu); data_[off + 1] = static_cast((iv >> 8) & 0xFFu); - } else if (prim->width >= 8 && !prim->is_float) { + } else if (tm.width() == 8) { const uint64_t tv = static_cast(v); for (int i = 0; i < 8; ++i) { data_[off + i] = static_cast((tv >> (8 * i)) & 0xFFu); @@ -672,8 +672,8 @@ namespace { * @return const_id(u16) */ uint16_t const_id(const char* type_name, int64_t value) { - const ConfigType* ct = cfg_.find_type(type_name); - const uint32_t tag = ct ? ct->tag : 0; + const TypeMeta tm = type_meta(cfg_, type_name); + const uint32_t tag = tm ? tm.tag() : 0; for (size_t i = 0; i < consts_.size(); ++i) { if (consts_[i].tag == tag && consts_[i].value == static_cast(value)) { return static_cast(i); diff --git a/compiler/src/TypeInfo.cpp b/compiler/src/TypeInfo.cpp new file mode 100644 index 0000000..3c43e5c --- /dev/null +++ b/compiler/src/TypeInfo.cpp @@ -0,0 +1,41 @@ +/** + * @file TypeInfo.cpp + * @brief 语言类型元数据(machine.toml 别名 + 内建基元解析) + * @author + * @date 2026-08-21 + */ + +#include "compiler/TypeInfo.h" + +#include + +namespace compiler { + +namespace { + + std::string lower(const std::string& s) { + std::string out = s; + for (char& ch : out) { + ch = static_cast(std::tolower(static_cast(ch))); + } + return out; + } + +} // namespace + +TypeMeta type_meta(const MachineConfig& cfg, const std::string& name) { + TypeMeta m; + const std::string key = lower(name); + for (const ConfigType& t : cfg.types()) { + if (lower(t.name) == key) { + m.config = &t; + break; + } + } + if (m.config != nullptr) { + m.prim = MachineConfig::find_prim(m.config->base); + } + return m; +} + +} // namespace compiler diff --git a/tests/src/machine_test.cpp b/tests/src/machine_test.cpp index 1cdcb3b..1c83929 100644 --- a/tests/src/machine_test.cpp +++ b/tests/src/machine_test.cpp @@ -10,6 +10,7 @@ #include #include "compiler/MachineConfig.h" +#include "compiler/TypeInfo.h" #ifndef REPO_ROOT #define REPO_ROOT "." @@ -252,10 +253,42 @@ static bool test_positive_min() { return true; } +// ---- 4. 类型元数据(TypeInfo)---- + +static bool test_type_meta() { + compiler::MachineConfig cfg; + std::string err; + CHECK(cfg.load(std::string(REPO_ROOT) + "/compiler/machine.toml", &err)); + + // BOOL:base=uint8 → 1 字节、无符号、非浮点、tag 0、range [0,1] + const compiler::TypeMeta b = compiler::type_meta(cfg, "BOOL"); + CHECK(b && b.width() == 1 && !b.is_signed() && !b.is_float() && b.tag() == 0); + CHECK(b.has_range() && b.value_in_range(0) && b.value_in_range(1)); + CHECK(!b.value_in_range(2) && !b.value_in_range(-1)); + // 大小写不敏感(Linker type_name 是小写) + const compiler::TypeMeta b2 = compiler::type_meta(cfg, "bool"); + CHECK(b2 && b2.tag() == 0 && b2.width() == 1); + + // INT:int16 → 2 字节、有符号、tag 1、无 range + const compiler::TypeMeta i = compiler::type_meta(cfg, "int"); + CHECK(i && i.width() == 2 && i.is_signed() && !i.is_float() && i.tag() == 1); + CHECK(!i.has_range() || i.value_in_range(30000)); + + // TIME:int64 → 8 字节、有符号、tag 2 + const compiler::TypeMeta t = compiler::type_meta(cfg, "TIME"); + CHECK(t && t.width() == 8 && t.is_signed() && !t.is_float() && t.tag() == 2); + + // 未定义类型 → 空 + CHECK(!compiler::type_meta(cfg, "REAL")); + CHECK(!compiler::type_meta(cfg, "")); + return true; +} + int main() { if (!test_positive()) return 1; if (!test_negative()) return 1; if (!test_positive_min()) return 1; + if (!test_type_meta()) return 1; std::printf("machine_test: %d checks passed\n", g_checks); return 0; }