|
|
|
|
@ -400,6 +400,7 @@ public:
|
|
|
|
|
|
|
|
|
|
// 左值表达式(变量引用)
|
|
|
|
|
std::any visitLVal(SysYParser::LValContext* ctx) override {
|
|
|
|
|
std::cout << "[DEBUG] visitLVal: " << ctx->getText() << std::endl;
|
|
|
|
|
if (!ctx || !ctx->Ident()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "非法变量引用"));
|
|
|
|
|
}
|
|
|
|
|
@ -410,54 +411,77 @@ public:
|
|
|
|
|
}
|
|
|
|
|
// 检查数组访问
|
|
|
|
|
bool is_array_access = !ctx->exp().empty();
|
|
|
|
|
std::cout << "[DEBUG] name: " << name
|
|
|
|
|
<< ", is_array_access: " << is_array_access
|
|
|
|
|
<< ", subscript_count: " << ctx->exp().size() << std::endl;
|
|
|
|
|
ExprInfo result;
|
|
|
|
|
// 判断是否为数组类型或指针类型(数组参数)
|
|
|
|
|
bool is_array_or_ptr = false;
|
|
|
|
|
if (sym->type) {
|
|
|
|
|
is_array_or_ptr = sym->type->IsArray() || sym->type->IsPtrInt32() || sym->type->IsPtrFloat();
|
|
|
|
|
std::cout << "[DEBUG] type_kind: " << (int)sym->type->GetKind()
|
|
|
|
|
<< ", is_array: " << sym->type->IsArray()
|
|
|
|
|
<< ", is_ptr: " << (sym->type->IsPtrInt32() || sym->type->IsPtrFloat()) << std::endl;
|
|
|
|
|
}
|
|
|
|
|
// 调试输出
|
|
|
|
|
std::cout << "[DEBUG] visitLVal: " << name
|
|
|
|
|
<< " kind: " << (int)sym->kind
|
|
|
|
|
<< " type_kind: " << (sym->type ? (int)sym->type->GetKind() : -1)
|
|
|
|
|
<< " is_array_or_ptr: " << is_array_or_ptr
|
|
|
|
|
<< " subscript_count: " << ctx->exp().size()
|
|
|
|
|
<< std::endl;
|
|
|
|
|
|
|
|
|
|
if (is_array_or_ptr) {
|
|
|
|
|
if (!is_array_access) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组变量必须使用下标访问: " + name));
|
|
|
|
|
}
|
|
|
|
|
// 获取维度信息
|
|
|
|
|
size_t dim_count = 0;
|
|
|
|
|
std::shared_ptr<ir::Type> elem_type = sym->type;
|
|
|
|
|
if (sym->type->IsArray()) {
|
|
|
|
|
if (auto* arr_type = dynamic_cast<ir::ArrayType*>(sym->type.get())) {
|
|
|
|
|
dim_count = arr_type->GetDimensions().size();
|
|
|
|
|
// 获取元素类型
|
|
|
|
|
elem_type = arr_type->GetElementType();
|
|
|
|
|
std::cout << "[DEBUG] 数组维度: " << dim_count << std::endl;
|
|
|
|
|
}
|
|
|
|
|
} else if (sym->type->IsPtrInt32() || sym->type->IsPtrFloat()) {
|
|
|
|
|
// 指针类型,只接受一个下标
|
|
|
|
|
dim_count = 1;
|
|
|
|
|
// 指针解引用后的类型
|
|
|
|
|
if (sym->type->IsPtrInt32()) {
|
|
|
|
|
elem_type = ir::Type::GetInt32Type();
|
|
|
|
|
} else if (sym->type->IsPtrFloat()) {
|
|
|
|
|
elem_type = ir::Type::GetFloatType();
|
|
|
|
|
}
|
|
|
|
|
std::cout << "[DEBUG] 指针类型, dim_count: 1" << std::endl;
|
|
|
|
|
}
|
|
|
|
|
if (ctx->exp().size() != dim_count) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组下标个数不匹配"));
|
|
|
|
|
}
|
|
|
|
|
for (auto* idx_exp : ctx->exp()) {
|
|
|
|
|
ExprInfo idx = CheckExp(idx_exp);
|
|
|
|
|
if (!idx.type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组下标必须是 int 类型"));
|
|
|
|
|
|
|
|
|
|
if (is_array_access) {
|
|
|
|
|
std::cout << "[DEBUG] 有下标访问,期望维度: " << dim_count
|
|
|
|
|
<< ", 实际下标数: " << ctx->exp().size() << std::endl;
|
|
|
|
|
if (ctx->exp().size() != dim_count) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组下标个数不匹配"));
|
|
|
|
|
}
|
|
|
|
|
for (auto* idx_exp : ctx->exp()) {
|
|
|
|
|
ExprInfo idx = CheckExp(idx_exp);
|
|
|
|
|
if (!idx.type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组下标必须是 int 类型"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
result.type = elem_type;
|
|
|
|
|
result.is_lvalue = true;
|
|
|
|
|
result.is_const = false;
|
|
|
|
|
} else {
|
|
|
|
|
std::cout << "[DEBUG] 无下标访问" << std::endl;
|
|
|
|
|
if (sym->type->IsArray()) {
|
|
|
|
|
std::cout << "[DEBUG] 数组名作为地址,转换为指针" << std::endl;
|
|
|
|
|
if (auto* arr_type = dynamic_cast<ir::ArrayType*>(sym->type.get())) {
|
|
|
|
|
if (arr_type->GetElementType()->IsInt32()) {
|
|
|
|
|
result.type = ir::Type::GetPtrInt32Type();
|
|
|
|
|
} else if (arr_type->GetElementType()->IsFloat()) {
|
|
|
|
|
result.type = ir::Type::GetPtrFloatType();
|
|
|
|
|
} else {
|
|
|
|
|
result.type = ir::Type::GetPtrInt32Type();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
result.type = ir::Type::GetPtrInt32Type();
|
|
|
|
|
}
|
|
|
|
|
result.is_lvalue = false;
|
|
|
|
|
result.is_const = true;
|
|
|
|
|
} else {
|
|
|
|
|
result.type = sym->type;
|
|
|
|
|
result.is_lvalue = true;
|
|
|
|
|
result.is_const = (sym->kind == SymbolKind::Constant);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
result.type = elem_type;
|
|
|
|
|
result.is_lvalue = true;
|
|
|
|
|
result.is_const = false;
|
|
|
|
|
} else {
|
|
|
|
|
if (is_array_access) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "非数组变量不能使用下标: " + name));
|
|
|
|
|
@ -482,10 +506,8 @@ public:
|
|
|
|
|
std::any visitIfStmtInternal(SysYParser::StmtContext* ctx) {
|
|
|
|
|
// 检查条件表达式
|
|
|
|
|
if (ctx->cond()) {
|
|
|
|
|
ExprInfo cond = CheckCond(ctx->cond());
|
|
|
|
|
if (!cond.type || !cond.type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "if 条件必须是 int 类型"));
|
|
|
|
|
}
|
|
|
|
|
ExprInfo cond = CheckCond(ctx->cond()); // CheckCond 已经处理了类型转换
|
|
|
|
|
// 不需要额外检查,因为 CheckCond 已经确保类型正确
|
|
|
|
|
}
|
|
|
|
|
// 处理 then 分支
|
|
|
|
|
if (ctx->stmt().size() > 0) {
|
|
|
|
|
@ -500,17 +522,15 @@ public:
|
|
|
|
|
|
|
|
|
|
// while 语句内部实现
|
|
|
|
|
std::any visitWhileStmtInternal(SysYParser::StmtContext* ctx) {
|
|
|
|
|
if (ctx->cond()) { // 检查条件表达式
|
|
|
|
|
ExprInfo cond = CheckCond(ctx->cond());
|
|
|
|
|
if (!cond.type || !cond.type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "while 条件必须是 int 类型"));
|
|
|
|
|
}
|
|
|
|
|
if (ctx->cond()) {
|
|
|
|
|
ExprInfo cond = CheckCond(ctx->cond()); // CheckCond 已经处理了类型转换
|
|
|
|
|
// 不需要额外检查
|
|
|
|
|
}
|
|
|
|
|
loop_stack_.push_back({true, ctx}); // 进入循环上下文
|
|
|
|
|
if (ctx->stmt().size() > 0) { // 处理循环体
|
|
|
|
|
loop_stack_.push_back({true, ctx});
|
|
|
|
|
if (ctx->stmt().size() > 0) {
|
|
|
|
|
ctx->stmt()[0]->accept(this);
|
|
|
|
|
}
|
|
|
|
|
loop_stack_.pop_back(); // 退出循环上下文
|
|
|
|
|
loop_stack_.pop_back();
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -564,6 +584,7 @@ public:
|
|
|
|
|
|
|
|
|
|
// 主表达式
|
|
|
|
|
std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override {
|
|
|
|
|
std::cout << "[DEBUG] visitPrimaryExp: " << ctx->getText() << std::endl;
|
|
|
|
|
ExprInfo result;
|
|
|
|
|
if (ctx->lVal()) { // 左值表达式
|
|
|
|
|
result = CheckLValue(ctx->lVal());
|
|
|
|
|
@ -595,12 +616,14 @@ public:
|
|
|
|
|
|
|
|
|
|
// 一元表达式
|
|
|
|
|
std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override {
|
|
|
|
|
std::cout << "[DEBUG] visitUnaryExp: " << ctx->getText() << std::endl;
|
|
|
|
|
ExprInfo result;
|
|
|
|
|
if (ctx->primaryExp()) {
|
|
|
|
|
ctx->primaryExp()->accept(this);
|
|
|
|
|
auto* info = sema_.GetExprType(ctx->primaryExp());
|
|
|
|
|
if (info) result = *info;
|
|
|
|
|
} else if (ctx->Ident() && ctx->L_PAREN()) { // 函数调用
|
|
|
|
|
std::cout << "[DEBUG] 函数调用: " << ctx->Ident()->getText() << std::endl;
|
|
|
|
|
result = CheckFuncCall(ctx);
|
|
|
|
|
} else if (ctx->unaryOp()) { // 一元运算
|
|
|
|
|
ctx->unaryExp()->accept(this);
|
|
|
|
|
@ -611,20 +634,37 @@ public:
|
|
|
|
|
} else {
|
|
|
|
|
std::string op = ctx->unaryOp()->getText();
|
|
|
|
|
if (op == "!") {
|
|
|
|
|
if (!operand->type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑非操作数必须是 int 类型"));
|
|
|
|
|
// 逻辑非:要求操作数是 int 类型,或者可以转换为 int 的 float
|
|
|
|
|
if (operand->type->IsInt32()) {
|
|
|
|
|
// 已经是 int,没问题
|
|
|
|
|
} else if (operand->type->IsFloat()) {
|
|
|
|
|
// float 可以隐式转换为 int
|
|
|
|
|
sema_.AddConversion(ctx->unaryExp(), operand->type, ir::Type::GetInt32Type());
|
|
|
|
|
// 更新操作数类型为 int
|
|
|
|
|
operand->type = ir::Type::GetInt32Type();
|
|
|
|
|
operand->is_const_int = true;
|
|
|
|
|
if (operand->is_const && !operand->is_const_int) {
|
|
|
|
|
// 如果原来是 float 常量,转换为 int 常量
|
|
|
|
|
operand->const_int_value = (int)operand->const_float_value;
|
|
|
|
|
operand->is_const_int = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑非操作数必须是 int 类型或可以转换为 int 的 float 类型"));
|
|
|
|
|
}
|
|
|
|
|
result.type = ir::Type::GetInt32Type();
|
|
|
|
|
result.is_lvalue = false;
|
|
|
|
|
result.is_const = operand->is_const;
|
|
|
|
|
if (operand->is_const && operand->is_const_int) {
|
|
|
|
|
result.is_const_int = true;
|
|
|
|
|
result.const_int_value = (operand->const_int_value == 0) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 正负号
|
|
|
|
|
if (!operand->type->IsInt32() && !operand->type->IsFloat()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "正负号操作数必须是算术类型"));
|
|
|
|
|
}
|
|
|
|
|
result.type = operand->type;
|
|
|
|
|
result.is_lvalue = false;
|
|
|
|
|
result.is_const = operand->is_const;
|
|
|
|
|
if (op == "-" && operand->is_const) {
|
|
|
|
|
if (operand->type->IsInt32() && operand->is_const_int) {
|
|
|
|
|
@ -635,7 +675,6 @@ public:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
result.is_lvalue = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sema_.SetExprType(ctx, result);
|
|
|
|
|
@ -808,12 +847,36 @@ public:
|
|
|
|
|
if (!left_info || !right_info) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑与操作数类型推导失败"));
|
|
|
|
|
} else {
|
|
|
|
|
if (!left_info->type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑与左操作数必须是 int 类型"));
|
|
|
|
|
// 处理左操作数
|
|
|
|
|
if (left_info->type->IsInt32()) {
|
|
|
|
|
// 已经是 int,没问题
|
|
|
|
|
} else if (left_info->type->IsFloat()) {
|
|
|
|
|
// float 可以隐式转换为 int
|
|
|
|
|
sema_.AddConversion(ctx->lAndExp(), left_info->type, ir::Type::GetInt32Type());
|
|
|
|
|
left_info->type = ir::Type::GetInt32Type();
|
|
|
|
|
if (left_info->is_const && !left_info->is_const_int) {
|
|
|
|
|
left_info->const_int_value = (int)left_info->const_float_value;
|
|
|
|
|
left_info->is_const_int = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑与左操作数必须是 int 类型或可以转换为 int 的 float 类型"));
|
|
|
|
|
}
|
|
|
|
|
if (!right_info->type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑与右操作数必须是 int 类型"));
|
|
|
|
|
|
|
|
|
|
// 处理右操作数
|
|
|
|
|
if (right_info->type->IsInt32()) {
|
|
|
|
|
// 已经是 int,没问题
|
|
|
|
|
} else if (right_info->type->IsFloat()) {
|
|
|
|
|
// float 可以隐式转换为 int
|
|
|
|
|
sema_.AddConversion(ctx->eqExp(), right_info->type, ir::Type::GetInt32Type());
|
|
|
|
|
right_info->type = ir::Type::GetInt32Type();
|
|
|
|
|
if (right_info->is_const && !right_info->is_const_int) {
|
|
|
|
|
right_info->const_int_value = (int)right_info->const_float_value;
|
|
|
|
|
right_info->is_const_int = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑与右操作数必须是 int 类型或可以转换为 int 的 float 类型"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.type = ir::Type::GetInt32Type();
|
|
|
|
|
result.is_lvalue = false;
|
|
|
|
|
if (left_info->is_const && right_info->is_const &&
|
|
|
|
|
@ -828,6 +891,17 @@ public:
|
|
|
|
|
ctx->eqExp()->accept(this);
|
|
|
|
|
auto* info = sema_.GetExprType(ctx->eqExp());
|
|
|
|
|
if (info) {
|
|
|
|
|
// 对于单个操作数,也需要确保类型是 int(用于条件表达式)
|
|
|
|
|
if (info->type->IsFloat()) {
|
|
|
|
|
sema_.AddConversion(ctx->eqExp(), info->type, ir::Type::GetInt32Type());
|
|
|
|
|
info->type = ir::Type::GetInt32Type();
|
|
|
|
|
if (info->is_const && !info->is_const_int) {
|
|
|
|
|
info->const_int_value = (int)info->const_float_value;
|
|
|
|
|
info->is_const_int = true;
|
|
|
|
|
}
|
|
|
|
|
} else if (!info->type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑与操作数必须是 int 类型或可以转换为 int 的 float 类型"));
|
|
|
|
|
}
|
|
|
|
|
sema_.SetExprType(ctx, *info);
|
|
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
@ -847,12 +921,36 @@ public:
|
|
|
|
|
if (!left_info || !right_info) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑或操作数类型推导失败"));
|
|
|
|
|
} else {
|
|
|
|
|
if (!left_info->type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑或左操作数必须是 int 类型"));
|
|
|
|
|
// 处理左操作数
|
|
|
|
|
if (left_info->type->IsInt32()) {
|
|
|
|
|
// 已经是 int,没问题
|
|
|
|
|
} else if (left_info->type->IsFloat()) {
|
|
|
|
|
// float 可以隐式转换为 int
|
|
|
|
|
sema_.AddConversion(ctx->lOrExp(), left_info->type, ir::Type::GetInt32Type());
|
|
|
|
|
left_info->type = ir::Type::GetInt32Type();
|
|
|
|
|
if (left_info->is_const && !left_info->is_const_int) {
|
|
|
|
|
left_info->const_int_value = (int)left_info->const_float_value;
|
|
|
|
|
left_info->is_const_int = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑或左操作数必须是 int 类型或可以转换为 int 的 float 类型"));
|
|
|
|
|
}
|
|
|
|
|
if (!right_info->type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑或右操作数必须是 int 类型"));
|
|
|
|
|
|
|
|
|
|
// 处理右操作数
|
|
|
|
|
if (right_info->type->IsInt32()) {
|
|
|
|
|
// 已经是 int,没问题
|
|
|
|
|
} else if (right_info->type->IsFloat()) {
|
|
|
|
|
// float 可以隐式转换为 int
|
|
|
|
|
sema_.AddConversion(ctx->lAndExp(), right_info->type, ir::Type::GetInt32Type());
|
|
|
|
|
right_info->type = ir::Type::GetInt32Type();
|
|
|
|
|
if (right_info->is_const && !right_info->is_const_int) {
|
|
|
|
|
right_info->const_int_value = (int)right_info->const_float_value;
|
|
|
|
|
right_info->is_const_int = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑或右操作数必须是 int 类型或可以转换为 int 的 float 类型"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.type = ir::Type::GetInt32Type();
|
|
|
|
|
result.is_lvalue = false;
|
|
|
|
|
if (left_info->is_const && right_info->is_const &&
|
|
|
|
|
@ -867,6 +965,17 @@ public:
|
|
|
|
|
ctx->lAndExp()->accept(this);
|
|
|
|
|
auto* info = sema_.GetExprType(ctx->lAndExp());
|
|
|
|
|
if (info) {
|
|
|
|
|
// 对于单个操作数,也需要确保类型是 int(用于条件表达式)
|
|
|
|
|
if (info->type->IsFloat()) {
|
|
|
|
|
sema_.AddConversion(ctx->lAndExp(), info->type, ir::Type::GetInt32Type());
|
|
|
|
|
info->type = ir::Type::GetInt32Type();
|
|
|
|
|
if (info->is_const && !info->is_const_int) {
|
|
|
|
|
info->const_int_value = (int)info->const_float_value;
|
|
|
|
|
info->is_const_int = true;
|
|
|
|
|
}
|
|
|
|
|
} else if (!info->type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "逻辑或操作数必须是 int 类型或可以转换为 int 的 float 类型"));
|
|
|
|
|
}
|
|
|
|
|
sema_.SetExprType(ctx, *info);
|
|
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
@ -895,6 +1004,7 @@ private:
|
|
|
|
|
if (!ctx || !ctx->addExp()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "无效表达式"));
|
|
|
|
|
}
|
|
|
|
|
std::cout << "[DEBUG] CheckExp: " << ctx->getText() << std::endl;
|
|
|
|
|
ctx->addExp()->accept(this);
|
|
|
|
|
auto* info = sema_.GetExprType(ctx->addExp());
|
|
|
|
|
if (!info) {
|
|
|
|
|
@ -927,7 +1037,13 @@ private:
|
|
|
|
|
if (!info) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "条件表达式类型推导失败"));
|
|
|
|
|
}
|
|
|
|
|
return *info;
|
|
|
|
|
ExprInfo result = *info;
|
|
|
|
|
// 条件表达式的结果必须是 int,如果是 float 则需要转换
|
|
|
|
|
// 注意:lOrExp 已经处理了类型转换,这里只是再检查一次
|
|
|
|
|
if (!result.type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "条件表达式必须是 int 类型"));
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExprInfo CheckLValue(SysYParser::LValContext* ctx) {
|
|
|
|
|
@ -939,15 +1055,18 @@ private:
|
|
|
|
|
if (!sym) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "未定义的变量: " + name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool is_array_access = !ctx->exp().empty();
|
|
|
|
|
bool is_const = (sym->kind == SymbolKind::Constant);
|
|
|
|
|
bool is_array_or_ptr = false;
|
|
|
|
|
|
|
|
|
|
if (sym->type) {
|
|
|
|
|
is_array_or_ptr = sym->type->IsArray() ||
|
|
|
|
|
sym->type->IsPtrInt32() ||
|
|
|
|
|
sym->type->IsPtrFloat();
|
|
|
|
|
is_array_or_ptr = sym->type->IsArray() || sym->type->IsPtrInt32() || sym->type->IsPtrFloat();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t dim_count = 0;
|
|
|
|
|
std::shared_ptr<ir::Type> elem_type = sym->type;
|
|
|
|
|
|
|
|
|
|
if (sym->type && sym->type->IsArray()) {
|
|
|
|
|
if (auto* arr_type = dynamic_cast<ir::ArrayType*>(sym->type.get())) {
|
|
|
|
|
dim_count = arr_type->GetDimensions().size();
|
|
|
|
|
@ -961,18 +1080,39 @@ private:
|
|
|
|
|
elem_type = ir::Type::GetFloatType();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t subscript_count = ctx->exp().size();
|
|
|
|
|
|
|
|
|
|
if (is_array_or_ptr) {
|
|
|
|
|
if (subscript_count != dim_count) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组下标个数不匹配"));
|
|
|
|
|
}
|
|
|
|
|
for (auto* idx_exp : ctx->exp()) {
|
|
|
|
|
ExprInfo idx = CheckExp(idx_exp);
|
|
|
|
|
if (!idx.type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组下标必须是 int 类型"));
|
|
|
|
|
if (subscript_count > 0) {
|
|
|
|
|
// 有下标访问
|
|
|
|
|
if (subscript_count != dim_count) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组下标个数不匹配"));
|
|
|
|
|
}
|
|
|
|
|
for (auto* idx_exp : ctx->exp()) {
|
|
|
|
|
ExprInfo idx = CheckExp(idx_exp);
|
|
|
|
|
if (!idx.type->IsInt32()) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组下标必须是 int 类型"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {elem_type, true, false};
|
|
|
|
|
} else {
|
|
|
|
|
// 没有下标访问
|
|
|
|
|
if (sym->type->IsArray()) {
|
|
|
|
|
// 数组名作为地址(右值)
|
|
|
|
|
if (auto* arr_type = dynamic_cast<ir::ArrayType*>(sym->type.get())) {
|
|
|
|
|
if (arr_type->GetElementType()->IsInt32()) {
|
|
|
|
|
return {ir::Type::GetPtrInt32Type(), false, true};
|
|
|
|
|
} else if (arr_type->GetElementType()->IsFloat()) {
|
|
|
|
|
return {ir::Type::GetPtrFloatType(), false, true};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {ir::Type::GetPtrInt32Type(), false, true};
|
|
|
|
|
} else {
|
|
|
|
|
// 指针类型(如函数参数)可以不带下标使用
|
|
|
|
|
return {sym->type, true, is_const};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {elem_type, true, false};
|
|
|
|
|
} else {
|
|
|
|
|
if (subscript_count > 0) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "非数组变量不能使用下标: " + name));
|
|
|
|
|
@ -986,12 +1126,14 @@ private:
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "非法函数调用"));
|
|
|
|
|
}
|
|
|
|
|
std::string func_name = ctx->Ident()->getText();
|
|
|
|
|
std::cout << "[DEBUG] CheckFuncCall: " << func_name << std::endl;
|
|
|
|
|
auto* func_sym = table_.lookup(func_name);
|
|
|
|
|
if (!func_sym || func_sym->kind != SymbolKind::Function) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "未定义的函数: " + func_name));
|
|
|
|
|
}
|
|
|
|
|
std::vector<ExprInfo> args;
|
|
|
|
|
if (ctx->funcRParams()) {
|
|
|
|
|
std::cout << "[DEBUG] 处理函数调用参数:" << std::endl;
|
|
|
|
|
for (auto* exp : ctx->funcRParams()->exp()) {
|
|
|
|
|
if (exp) {
|
|
|
|
|
args.push_back(CheckExp(exp));
|
|
|
|
|
@ -1002,6 +1144,8 @@ private:
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "参数个数不匹配"));
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = 0; i < std::min(args.size(), func_sym->param_types.size()); ++i) {
|
|
|
|
|
std::cout << "[DEBUG] 检查参数 " << i << ": 实参类型 " << (int)args[i].type->GetKind()
|
|
|
|
|
<< " 形参类型 " << (int)func_sym->param_types[i]->GetKind() << std::endl;
|
|
|
|
|
if (!IsTypeCompatible(args[i].type, func_sym->param_types[i])) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "参数类型不匹配"));
|
|
|
|
|
}
|
|
|
|
|
@ -1162,6 +1306,7 @@ private:
|
|
|
|
|
} else if (param_type->IsFloat()) {
|
|
|
|
|
param_type = ir::Type::GetPtrFloatType();
|
|
|
|
|
}
|
|
|
|
|
std::cout << "[DEBUG] 数组参数: " << name << " 类型转换为指针" << std::endl;
|
|
|
|
|
}
|
|
|
|
|
Symbol sym;
|
|
|
|
|
sym.name = name;
|
|
|
|
|
@ -1171,6 +1316,7 @@ private:
|
|
|
|
|
sym.is_initialized = true;
|
|
|
|
|
sym.var_def_ctx = nullptr;
|
|
|
|
|
table_.addSymbol(sym);
|
|
|
|
|
std::cout << "[DEBUG] 添加参数: " << name << " type_kind: " << (int)param_type->GetKind() << std::endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|