You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
9.5 KiB

#include "sem/func.h"
#include <stdexcept>
#include <string>
#include "utils/Log.h"
namespace sem {
// 编译时求值常量表达式
ConstValue EvaluateConstExp(SysYParser::ConstExpContext& ctx) {
return EvaluateExp(*ctx.addExp());
}
// 求值表达式
ConstValue EvaluateExp(SysYParser::AddExpContext& ctx) {
ConstValue result = EvaluateMulExp(*ctx.mulExp(0));
for (size_t i = 1; i < ctx.mulExp().size(); ++i) {
ConstValue rhs = EvaluateMulExp(*ctx.mulExp(i));
if (ctx.AddOp(i-1)->getText() == "+") {
result = AddValues(result, rhs);
} else {
result = SubValues(result, rhs);
}
}
return result;
}
// 求值乘法表达式
ConstValue EvaluateMulExp(SysYParser::MulExpContext& ctx) {
ConstValue result = EvaluateUnaryExp(*ctx.unaryExp(0));
for (size_t i = 1; i < ctx.unaryExp().size(); ++i) {
ConstValue rhs = EvaluateUnaryExp(*ctx.unaryExp(i));
std::string op = ctx.MulOp(i-1)->getText();
if (op == "*") {
result = MulValues(result, rhs);
} else if (op == "/") {
if (IsZero(rhs)) {
throw std::runtime_error(FormatError("sema", "除零错误"));
}
result = DivValues(result, rhs);
} else if (op == "%") {
if (IsZero(rhs)) {
throw std::runtime_error(FormatError("sema", "取模除零错误"));
}
result = ModValues(result, rhs);
}
}
return result;
}
// 求值一元表达式
ConstValue EvaluateUnaryExp(SysYParser::UnaryExpContext& ctx) {
if (ctx.unaryOp()) {
ConstValue operand = EvaluateUnaryExp(*ctx.unaryExp());
std::string op = ctx.unaryOp()->getText();
if (op == "-") {
return NegValue(operand);
} else if (op == "!") {
return NotValue(operand);
} else {
return operand; // "+" 操作符
}
} else if (ctx.primaryExp()) {
return EvaluatePrimaryExp(*ctx.primaryExp());
} else {
throw std::runtime_error(FormatError("sema", "非法常量表达式"));
}
}
// 求值基本表达式
ConstValue EvaluatePrimaryExp(SysYParser::PrimaryExpContext& ctx) {
if (ctx.exp()) {
return EvaluateExp(*ctx.exp()->addExp());
} else if (ctx.lVar()) {
// 处理变量引用(必须是已定义的常量)
auto* ident = ctx.lVar()->Ident();
if (!ident) {
throw std::runtime_error(FormatError("sema", "非法变量引用"));
}
std::string name = ident->getText();
// 这里简化处理,实际应该在符号表中查找常量
// 暂时假设常量已经在前面被处理过
ConstValue val;
val.is_int = true;
val.int_val = 0;
val.float_val = 0.0;
return val;
} else if (ctx.number()) {
// 处理数字字面量
auto* int_const = ctx.number()->IntConst();
auto* float_const = ctx.number()->FloatConst();
ConstValue val;
if (int_const) {
val.is_int = true;
val.int_val = std::stoll(int_const->getText());
val.float_val = static_cast<double>(val.int_val);
} else if (float_const) {
val.is_int = false;
val.float_val = std::stod(float_const->getText());
val.int_val = static_cast<long long>(val.float_val);
} else {
throw std::runtime_error(FormatError("sema", "非法数字字面量"));
}
return val;
} else {
throw std::runtime_error(FormatError("sema", "非法基本表达式"));
}
}
// 辅助函数:检查值是否为零
bool IsZero(const ConstValue& val) {
if (val.is_int) {
return val.int_val == 0;
} else {
return val.float_val == 0.0;
}
}
// 辅助函数:加法
ConstValue AddValues(const ConstValue& lhs, const ConstValue& rhs) {
ConstValue result;
if (lhs.is_int && rhs.is_int) {
result.is_int = true;
result.int_val = lhs.int_val + rhs.int_val;
result.float_val = static_cast<double>(result.int_val);
} else {
result.is_int = false;
result.float_val = (lhs.is_int ? lhs.int_val : lhs.float_val) +
(rhs.is_int ? rhs.int_val : rhs.float_val);
result.int_val = static_cast<long long>(result.float_val);
}
return result;
}
// 辅助函数:减法
ConstValue SubValues(const ConstValue& lhs, const ConstValue& rhs) {
ConstValue result;
if (lhs.is_int && rhs.is_int) {
result.is_int = true;
result.int_val = lhs.int_val - rhs.int_val;
result.float_val = static_cast<double>(result.int_val);
} else {
result.is_int = false;
result.float_val = (lhs.is_int ? lhs.int_val : lhs.float_val) -
(rhs.is_int ? rhs.int_val : rhs.float_val);
result.int_val = static_cast<long long>(result.float_val);
}
return result;
}
// 辅助函数:乘法
ConstValue MulValues(const ConstValue& lhs, const ConstValue& rhs) {
ConstValue result;
if (lhs.is_int && rhs.is_int) {
result.is_int = true;
result.int_val = lhs.int_val * rhs.int_val;
result.float_val = static_cast<double>(result.int_val);
} else {
result.is_int = false;
result.float_val = (lhs.is_int ? lhs.int_val : lhs.float_val) *
(rhs.is_int ? rhs.int_val : rhs.float_val);
result.int_val = static_cast<long long>(result.float_val);
}
return result;
}
// 辅助函数:除法
ConstValue DivValues(const ConstValue& lhs, const ConstValue& rhs) {
ConstValue result;
if (lhs.is_int && rhs.is_int) {
result.is_int = true;
result.int_val = lhs.int_val / rhs.int_val;
result.float_val = static_cast<double>(result.int_val);
} else {
result.is_int = false;
result.float_val = (lhs.is_int ? lhs.int_val : lhs.float_val) /
(rhs.is_int ? rhs.int_val : rhs.float_val);
result.int_val = static_cast<long long>(result.float_val);
}
return result;
}
// 辅助函数:取模
ConstValue ModValues(const ConstValue& lhs, const ConstValue& rhs) {
ConstValue result;
if (!lhs.is_int || !rhs.is_int) {
throw std::runtime_error(FormatError("sema", "取模运算只能用于整数"));
}
result.is_int = true;
result.int_val = lhs.int_val % rhs.int_val;
result.float_val = static_cast<double>(result.int_val);
return result;
}
// 辅助函数:取负
ConstValue NegValue(const ConstValue& val) {
ConstValue result;
result.is_int = val.is_int;
if (val.is_int) {
result.int_val = -val.int_val;
result.float_val = static_cast<double>(result.int_val);
} else {
result.float_val = -val.float_val;
result.int_val = static_cast<long long>(result.float_val);
}
return result;
}
// 辅助函数:逻辑非
ConstValue NotValue(const ConstValue& val) {
ConstValue result;
result.is_int = true;
if (val.is_int) {
result.int_val = !val.int_val;
} else {
result.int_val = !val.float_val;
}
result.float_val = static_cast<double>(result.int_val);
return result;
}
// 检查常量初始化器
size_t CheckConstInitVal(SysYParser::ConstInitValContext& ctx,
const std::vector<size_t>& dimensions,
bool is_int,
size_t total_elements) {
if (ctx.constExp()) {
// 单个常量值
// 求值并检查常量表达式
ConstValue value = EvaluateConstExp(*ctx.constExp());
// 检查类型约束
if (is_int && !value.is_int) {
throw std::runtime_error(FormatError("sema", "整型数组的初始化列表中不能出现浮点型常量"));
}
// 检查值域
if (is_int) {
if (value.int_val < INT_MIN || value.int_val > INT_MAX) {
throw std::runtime_error(FormatError("sema", "整数值超过int类型表示范围"));
}
}
return 1;
} else if (ctx.L_BRACE()) {
// 花括号初始化列表
size_t count = 0;
auto init_vals = ctx.constInitVal();
for (auto* init_val : init_vals) {
// 计算剩余维度的总元素个数
size_t remaining_elements = total_elements;
if (!dimensions.empty()) {
remaining_elements = total_elements / dimensions[0];
}
count += CheckConstInitVal(*init_val,
std::vector<size_t>(dimensions.begin() + 1, dimensions.end()),
is_int,
remaining_elements);
}
// 检查总元素个数
if (count > total_elements) {
throw std::runtime_error(FormatError("sema", "初始化列表元素个数超过数组大小"));
}
return count;
} else {
// 空初始化列表
return 0;
}
}
// 检查变量初始化器
size_t CheckInitVal(SysYParser::InitValContext& ctx,
const std::vector<size_t>& dimensions,
bool is_int,
size_t total_elements) {
if (ctx.exp()) {
// 单个表达式值
// 检查表达式中的变量引用
// 这里不需要编译时求值,只需要检查类型约束
// 类型检查在IR生成阶段进行
return 1;
} else if (ctx.L_BRACE()) {
// 花括号初始化列表
size_t count = 0;
auto init_vals = ctx.initVal();
for (auto* init_val : init_vals) {
// 计算剩余维度的总元素个数
size_t remaining_elements = total_elements;
if (!dimensions.empty()) {
remaining_elements = total_elements / dimensions[0];
}
count += CheckInitVal(*init_val,
std::vector<size_t>(dimensions.begin() + 1, dimensions.end()),
is_int,
remaining_elements);
}
// 检查总元素个数
if (count > total_elements) {
throw std::runtime_error(FormatError("sema", "初始化列表元素个数超过数组大小"));
}
return count;
} else {
// 空初始化列表
return 0;
}
}
} // namespace sem