fix(sem)修正标量常量当作数组处理的问题

feature/sem
mxr 2 weeks ago
parent 6cc1908515
commit bff9a5d296

@ -88,6 +88,9 @@ class SymbolTable {
float float_val;
};
};
void flattenInit(SysYParser::ConstInitValContext* ctx,
std::vector<ConstValue>& out,
std::shared_ptr<ir::Type> base_type) const;
std::vector<ConstValue> EvaluateConstInitVal(
SysYParser::ConstInitValContext* ctx,
const std::vector<int>& dims,

@ -5,6 +5,15 @@
#include <string>
#include <cmath>
#define DEBUG_SYMBOL_TABLE
#ifdef DEBUG_SYMBOL_TABLE
#include <iostream>
#define DEBUG_MSG(msg) std::cerr << "[SymbolTable Debug] " << msg << std::endl
#else
#define DEBUG_MSG(msg)
#endif
// ---------- 构造函数 ----------
SymbolTable::SymbolTable() {
scopes_.emplace_back(); // 初始化全局作用域
@ -551,45 +560,100 @@ float SymbolTable::EvaluateConstExpFloat(SysYParser::ConstExpContext* ctx) const
}
}
std::vector<SymbolTable::ConstValue> SymbolTable::EvaluateConstInitVal(
SysYParser::ConstInitValContext* ctx,
const std::vector<int>& dims,
std::shared_ptr<ir::Type> base_type) const
{
std::vector<ConstValue> result;
if (!ctx) return result;
void SymbolTable::flattenInit(SysYParser::ConstInitValContext* ctx,
std::vector<ConstValue>& out,
std::shared_ptr<ir::Type> base_type) const {
if (!ctx) return;
// 获取当前初始化列表的文本(用于调试)
std::string ctxText;
if (ctx->constExp()) {
ctxText = ctx->constExp()->getText();
} else {
ctxText = "{ ... }";
}
if (ctx->constExp()) {
ConstValue val = EvaluateAddExp(ctx->constExp()->addExp());
// 根据基础类型进行可能的隐式转换
DEBUG_MSG("处理常量表达式: " << ctxText
<< " 类型=" << (val.kind == ConstValue::INT ? "INT" : "FLOAT")
<< " 值=" << (val.kind == ConstValue::INT ? std::to_string(val.int_val) : std::to_string(val.float_val))
<< " 目标类型=" << (base_type->IsInt32() ? "Int32" : "Float"));
// 整型数组不能接受浮点常量
if (base_type->IsInt32() && val.kind == ConstValue::FLOAT) {
int i = static_cast<int>(val.float_val);
if (std::abs(val.float_val - i) > 1e-6) {
throw std::runtime_error("常量初始化:浮点常量不能隐式转换为整数");
}
val.kind = ConstValue::INT;
val.int_val = i;
} else if (base_type->IsFloat() && val.kind == ConstValue::INT) {
DEBUG_MSG("错误:整型数组遇到浮点常量,值=" << val.float_val);
throw std::runtime_error("常量初始化:整型数组不能使用浮点常量");
}
// 浮点数组接受整型常量,并隐式转换
if (base_type->IsFloat() && val.kind == ConstValue::INT) {
DEBUG_MSG("浮点数组接收整型常量,隐式转换为浮点: " << val.int_val);
val.kind = ConstValue::FLOAT;
val.float_val = static_cast<float>(val.int_val);
}
result.push_back(val);
out.push_back(val);
} else {
// 嵌套初始化列表
if (dims.empty()) {
throw std::runtime_error("常量初始化:非数组使用初始化列表");
DEBUG_MSG("进入花括号初始化列表: " << ctxText);
// 花括号初始化列表:递归展开所有子项
for (auto* sub : ctx->constInitVal()) {
flattenInit(sub, out, base_type);
}
std::vector<int> sub_dims(dims.begin() + 1, dims.end());
int expected_count = 1;
for (int d : sub_dims) expected_count *= d;
for (auto* sub_init : ctx->constInitVal()) {
auto sub_vals = EvaluateConstInitVal(sub_init, sub_dims, base_type);
if (sub_vals.size() != static_cast<size_t>(expected_count)) {
throw std::runtime_error("常量初始化:子列表元素数量不匹配");
}
result.insert(result.end(), sub_vals.begin(), sub_vals.end());
DEBUG_MSG("退出花括号初始化列表");
}
}
std::vector<SymbolTable::ConstValue> SymbolTable::EvaluateConstInitVal(
SysYParser::ConstInitValContext* ctx,
const std::vector<int>& dims,
std::shared_ptr<ir::Type> base_type) const {
// ========== 1. 标量常量dims 为空)==========
if (dims.empty()) {
if (!ctx || !ctx->constExp()) {
throw std::runtime_error("标量常量初始化必须使用单个表达式");
}
ConstValue val = EvaluateAddExp(ctx->constExp()->addExp());
// 类型兼容性检查
/*
if (base_type->IsInt32() && val.kind == ConstValue::FLOAT) {
throw std::runtime_error("整型常量不能使用浮点常量初始化");
}
if (base_type->IsFloat() && val.kind == ConstValue::INT) {
val.kind = ConstValue::FLOAT;
val.float_val = static_cast<float>(val.int_val);
}
*/
return {val}; // 返回包含单个值的向量
}
return result;
// ========== 2. 数组常量dims 非空)==========
// 计算数组总元素个数
size_t total = 1;
for (int d : dims) total *= d;
// 展平初始化列表(递归处理花括号)
std::vector<ConstValue> flat;
flattenInit(ctx, flat, base_type);
// 检查数量是否超过数组容量
if (flat.size() > total) {
throw std::runtime_error("常量初始化:提供的初始值数量超过数组元素总数");
}
// 不足的部分补零
if (flat.size() < total) {
ConstValue zero;
if (base_type->IsInt32()) {
zero.kind = ConstValue::INT;
zero.int_val = 0;
} else {
zero.kind = ConstValue::FLOAT;
zero.float_val = 0.0f;
}
flat.resize(total, zero);
}
return flat;
}
Loading…
Cancel
Save