阶段 B 步骤 5:类型元数据配置化(TypeInfo)。
- 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
This commit is contained in:
@@ -17,7 +17,8 @@ add_library(compiler STATIC
|
|||||||
./src/Codegen.cpp
|
./src/Codegen.cpp
|
||||||
./src/MachineConfig.cpp
|
./src/MachineConfig.cpp
|
||||||
./src/Stb.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 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
target_include_directories(compiler PRIVATE ${CMAKE_SOURCE_DIR}/third_party/tomlplusplus/include)
|
target_include_directories(compiler PRIVATE ${CMAKE_SOURCE_DIR}/third_party/tomlplusplus/include)
|
||||||
|
|||||||
@@ -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 <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
+10
-10
@@ -42,6 +42,7 @@
|
|||||||
#include "compiler/Codec.h"
|
#include "compiler/Codec.h"
|
||||||
#include "compiler/MachineConfig.h"
|
#include "compiler/MachineConfig.h"
|
||||||
#include "compiler/Stb.h"
|
#include "compiler/Stb.h"
|
||||||
|
#include "compiler/TypeInfo.h"
|
||||||
|
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace {
|
namespace {
|
||||||
@@ -589,20 +590,19 @@ namespace {
|
|||||||
const int64_t v = has_init ? init : 0;
|
const int64_t v = has_init ? init : 0;
|
||||||
const size_t off = static_cast<size_t>(s.address) * 8;
|
const size_t off = static_cast<size_t>(s.address) * 8;
|
||||||
data_.resize(off + 8, 0);
|
data_.resize(off + 8, 0);
|
||||||
// 初值按基元宽度写(类型元数据来自配置别名 → base)
|
// 初值按类型元数据写(配置别名 → 基元宽度/浮点)
|
||||||
const ConfigType* ct = cfg_.find_type(uppercase_of(s.type_name));
|
const TypeMeta tm = type_meta(cfg_, s.type_name);
|
||||||
if (ct == nullptr) {
|
if (!tm) {
|
||||||
return fail("no type in machine.toml for '" + s.type_name + "'");
|
return fail("no type in machine.toml for '" + s.type_name + "'");
|
||||||
}
|
}
|
||||||
const PrimType* prim = MachineConfig::find_prim(ct->base);
|
if (tm.is_float()) {
|
||||||
if (prim == nullptr) {
|
return fail("float initializer not supported yet");
|
||||||
return fail("no prim '" + ct->base + "' for type '" + ct->name + "'");
|
|
||||||
}
|
}
|
||||||
if (prim->width == 2 && !prim->is_float) {
|
if (tm.width() == 2) {
|
||||||
const uint16_t iv = static_cast<uint16_t>(v);
|
const uint16_t iv = static_cast<uint16_t>(v);
|
||||||
data_[off] = static_cast<uint8_t>(iv & 0xFFu);
|
data_[off] = static_cast<uint8_t>(iv & 0xFFu);
|
||||||
data_[off + 1] = static_cast<uint8_t>((iv >> 8) & 0xFFu);
|
data_[off + 1] = static_cast<uint8_t>((iv >> 8) & 0xFFu);
|
||||||
} else if (prim->width >= 8 && !prim->is_float) {
|
} else if (tm.width() == 8) {
|
||||||
const uint64_t tv = static_cast<uint64_t>(v);
|
const uint64_t tv = static_cast<uint64_t>(v);
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
data_[off + i] = static_cast<uint8_t>((tv >> (8 * i)) & 0xFFu);
|
data_[off + i] = static_cast<uint8_t>((tv >> (8 * i)) & 0xFFu);
|
||||||
@@ -672,8 +672,8 @@ namespace {
|
|||||||
* @return const_id(u16)
|
* @return const_id(u16)
|
||||||
*/
|
*/
|
||||||
uint16_t const_id(const char* type_name, int64_t value) {
|
uint16_t const_id(const char* type_name, int64_t value) {
|
||||||
const ConfigType* ct = cfg_.find_type(type_name);
|
const TypeMeta tm = type_meta(cfg_, type_name);
|
||||||
const uint32_t tag = ct ? ct->tag : 0;
|
const uint32_t tag = tm ? tm.tag() : 0;
|
||||||
for (size_t i = 0; i < consts_.size(); ++i) {
|
for (size_t i = 0; i < consts_.size(); ++i) {
|
||||||
if (consts_[i].tag == tag && consts_[i].value == static_cast<uint64_t>(value)) {
|
if (consts_[i].tag == tag && consts_[i].value == static_cast<uint64_t>(value)) {
|
||||||
return static_cast<uint16_t>(i);
|
return static_cast<uint16_t>(i);
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* @file TypeInfo.cpp
|
||||||
|
* @brief 语言类型元数据(machine.toml 别名 + 内建基元解析)
|
||||||
|
* @author
|
||||||
|
* @date 2026-08-21
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "compiler/TypeInfo.h"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::string lower(const std::string& s) {
|
||||||
|
std::string out = s;
|
||||||
|
for (char& ch : out) {
|
||||||
|
ch = static_cast<char>(std::tolower(static_cast<unsigned char>(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
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "compiler/MachineConfig.h"
|
#include "compiler/MachineConfig.h"
|
||||||
|
#include "compiler/TypeInfo.h"
|
||||||
|
|
||||||
#ifndef REPO_ROOT
|
#ifndef REPO_ROOT
|
||||||
#define REPO_ROOT "."
|
#define REPO_ROOT "."
|
||||||
@@ -252,10 +253,42 @@ static bool test_positive_min() {
|
|||||||
return true;
|
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() {
|
int main() {
|
||||||
if (!test_positive()) return 1;
|
if (!test_positive()) return 1;
|
||||||
if (!test_negative()) return 1;
|
if (!test_negative()) return 1;
|
||||||
if (!test_positive_min()) return 1;
|
if (!test_positive_min()) return 1;
|
||||||
|
if (!test_type_meta()) return 1;
|
||||||
std::printf("machine_test: %d checks passed\n", g_checks);
|
std::printf("machine_test: %d checks passed\n", g_checks);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user