|
|
|
|
@ -398,104 +398,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", "非法变量引用"));
|
|
|
|
|
}
|
|
|
|
|
std::string name = ctx->Ident()->getText();
|
|
|
|
|
auto* sym = table_.lookup(name);
|
|
|
|
|
if (!sym) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "使用了未定义的变量: " + name));
|
|
|
|
|
}
|
|
|
|
|
// 检查数组访问
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_array_or_ptr) {
|
|
|
|
|
// 获取维度信息
|
|
|
|
|
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 (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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (is_array_access) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "非数组变量不能使用下标: " + name));
|
|
|
|
|
}
|
|
|
|
|
result.type = sym->type;
|
|
|
|
|
result.is_lvalue = true;
|
|
|
|
|
result.is_const = (sym->kind == SymbolKind::Constant);
|
|
|
|
|
if (result.is_const && sym->type && !sym->type->IsArray()) {
|
|
|
|
|
if (sym->is_int_const) {
|
|
|
|
|
result.is_const_int = true;
|
|
|
|
|
result.const_int_value = sym->const_value.i32;
|
|
|
|
|
} else {
|
|
|
|
|
result.const_float_value = sym->const_value.f32;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ExprInfo result = CheckLValue(ctx);
|
|
|
|
|
sema_.SetExprType(ctx, result);
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
@ -1056,21 +959,30 @@ private:
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t dim_count = 0;
|
|
|
|
|
std::shared_ptr<ir::Type> elem_type = sym->type;
|
|
|
|
|
std::vector<int> dims;
|
|
|
|
|
|
|
|
|
|
// 获取维度信息
|
|
|
|
|
if (sym->type && sym->type->IsArray()) {
|
|
|
|
|
if (auto* arr_type = dynamic_cast<ir::ArrayType*>(sym->type.get())) {
|
|
|
|
|
dim_count = arr_type->GetDimensions().size();
|
|
|
|
|
dims = arr_type->GetDimensions();
|
|
|
|
|
dim_count = dims.size();
|
|
|
|
|
elem_type = arr_type->GetElementType();
|
|
|
|
|
}
|
|
|
|
|
} else if (sym->is_array_param) {
|
|
|
|
|
// 数组参数,使用保存的维度信息
|
|
|
|
|
dims = sym->array_dims;
|
|
|
|
|
dim_count = dims.size();
|
|
|
|
|
// 元素类型是基本类型
|
|
|
|
|
if (sym->type->IsPtrInt32()) {
|
|
|
|
|
elem_type = ir::Type::GetInt32Type();
|
|
|
|
|
} else if (sym->type->IsPtrFloat()) {
|
|
|
|
|
elem_type = ir::Type::GetFloatType();
|
|
|
|
|
}
|
|
|
|
|
} else if (sym->type && (sym->type->IsPtrInt32() || sym->type->IsPtrFloat())) {
|
|
|
|
|
// 普通指针,只能有一个下标
|
|
|
|
|
dim_count = 1;
|
|
|
|
|
if (sym->type->IsPtrInt32()) {
|
|
|
|
|
elem_type = ir::Type::GetInt32Type();
|
|
|
|
|
@ -1081,23 +993,53 @@ private:
|
|
|
|
|
|
|
|
|
|
size_t subscript_count = ctx->exp().size();
|
|
|
|
|
|
|
|
|
|
if (is_array_or_ptr) {
|
|
|
|
|
if (dim_count > 0 || sym->is_array_param || sym->type->IsArray() ||
|
|
|
|
|
sym->type->IsPtrInt32() || sym->type->IsPtrFloat()) {
|
|
|
|
|
if (subscript_count > 0) {
|
|
|
|
|
// 有下标访问
|
|
|
|
|
if (subscript_count != dim_count) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组下标个数不匹配"));
|
|
|
|
|
if (subscript_count > dim_count && dim_count > 0) {
|
|
|
|
|
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};
|
|
|
|
|
|
|
|
|
|
if (subscript_count == dim_count) {
|
|
|
|
|
// 完全索引,返回元素类型
|
|
|
|
|
return {elem_type, true, false};
|
|
|
|
|
} else {
|
|
|
|
|
// 部分索引,返回子数组的指针类型
|
|
|
|
|
// 计算剩余维度的元素类型
|
|
|
|
|
std::shared_ptr<ir::Type> remaining_type = sym->type;
|
|
|
|
|
if (sym->is_array_param) {
|
|
|
|
|
// 对于数组参数,我们需要返回指向剩余维度的指针
|
|
|
|
|
if (elem_type->IsInt32()) {
|
|
|
|
|
return {ir::Type::GetPtrInt32Type(), false, false};
|
|
|
|
|
} else if (elem_type->IsFloat()) {
|
|
|
|
|
return {ir::Type::GetPtrFloatType(), false, false};
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (size_t i = 0; i < subscript_count && remaining_type->IsArray(); i++) {
|
|
|
|
|
if (auto* arr_type = dynamic_cast<ir::ArrayType*>(remaining_type.get())) {
|
|
|
|
|
remaining_type = arr_type->GetElementType();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (remaining_type->IsInt32()) {
|
|
|
|
|
return {ir::Type::GetPtrInt32Type(), false, false};
|
|
|
|
|
} else if (remaining_type->IsFloat()) {
|
|
|
|
|
return {ir::Type::GetPtrFloatType(), false, false};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {ir::Type::GetPtrInt32Type(), false, false};
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 没有下标访问
|
|
|
|
|
if (sym->type->IsArray()) {
|
|
|
|
|
// 数组名作为地址(右值)
|
|
|
|
|
if (sym->type && 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};
|
|
|
|
|
@ -1106,8 +1048,15 @@ private:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {ir::Type::GetPtrInt32Type(), false, true};
|
|
|
|
|
} else if (sym->is_array_param) {
|
|
|
|
|
// 数组参数名作为地址
|
|
|
|
|
if (sym->type->IsPtrInt32()) {
|
|
|
|
|
return {ir::Type::GetPtrInt32Type(), false, true};
|
|
|
|
|
} else {
|
|
|
|
|
return {ir::Type::GetPtrFloatType(), false, true};
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 指针类型(如函数参数)可以不带下标使用
|
|
|
|
|
// 普通变量或指针
|
|
|
|
|
return {sym->type, true, is_const};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -1280,6 +1229,20 @@ private:
|
|
|
|
|
table_.addSymbol(sym);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 在 SemaVisitor 类中添加
|
|
|
|
|
int EvaluateConstantAddExp(SysYParser::AddExpContext* ctx) {
|
|
|
|
|
if (!ctx) return 0;
|
|
|
|
|
// 使用常量求值器
|
|
|
|
|
// 这里需要访问 ConstEvaluator,但 SemaVisitor 可能没有直接访问
|
|
|
|
|
// 我们可以直接使用 CheckAddExp 并检查常量
|
|
|
|
|
ExprInfo info = CheckAddExp(ctx);
|
|
|
|
|
if (info.is_const && info.is_const_int) {
|
|
|
|
|
return info.const_int_value;
|
|
|
|
|
}
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "常量表达式求值失败"));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CollectFunctionParams(SysYParser::FuncFParamsContext* ctx) {
|
|
|
|
|
if (!ctx) return;
|
|
|
|
|
for (auto* param : ctx->funcFParam()) {
|
|
|
|
|
@ -1297,15 +1260,42 @@ private:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!param_type) param_type = ir::Type::GetInt32Type();
|
|
|
|
|
|
|
|
|
|
bool is_array = !param->L_BRACK().empty();
|
|
|
|
|
std::vector<int> dims;
|
|
|
|
|
|
|
|
|
|
if (is_array) {
|
|
|
|
|
// 第一维是 [],没有表达式,所以维度为0(表示省略)
|
|
|
|
|
dims.push_back(0);
|
|
|
|
|
|
|
|
|
|
// 后续维度有表达式
|
|
|
|
|
// 注意:exp() 返回的是 ExpContext 列表,对应后面的维度表达式
|
|
|
|
|
for (auto* exp_ctx : param->exp()) {
|
|
|
|
|
// 使用常量求值器直接求值
|
|
|
|
|
// 创建一个临时的 ConstExpContext
|
|
|
|
|
// 由于 ConstExpContext 只是 addExp 的包装,我们可以直接使用 addExp
|
|
|
|
|
auto* addExp = exp_ctx->addExp();
|
|
|
|
|
if (!addExp) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "无效的数组维度表达式"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 求值常量表达式
|
|
|
|
|
// 我们需要一个函数来求值常量表达式
|
|
|
|
|
int dim = EvaluateConstantAddExp(addExp);
|
|
|
|
|
if (dim <= 0) {
|
|
|
|
|
throw std::runtime_error(FormatError("sema", "数组维度必须为正整数"));
|
|
|
|
|
}
|
|
|
|
|
dims.push_back(dim);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 数组参数退化为指针
|
|
|
|
|
if (param_type->IsInt32()) {
|
|
|
|
|
param_type = ir::Type::GetPtrInt32Type();
|
|
|
|
|
} else if (param_type->IsFloat()) {
|
|
|
|
|
param_type = ir::Type::GetPtrFloatType();
|
|
|
|
|
}
|
|
|
|
|
std::cout << "[DEBUG] 数组参数: " << name << " 类型转换为指针" << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Symbol sym;
|
|
|
|
|
sym.name = name;
|
|
|
|
|
sym.kind = SymbolKind::Parameter;
|
|
|
|
|
@ -1313,8 +1303,14 @@ private:
|
|
|
|
|
sym.scope_level = table_.currentScopeLevel();
|
|
|
|
|
sym.is_initialized = true;
|
|
|
|
|
sym.var_def_ctx = nullptr;
|
|
|
|
|
sym.is_array_param = is_array;
|
|
|
|
|
sym.array_dims = dims;
|
|
|
|
|
table_.addSymbol(sym);
|
|
|
|
|
std::cout << "[DEBUG] 添加参数: " << name << " type_kind: " << (int)param_type->GetKind() << std::endl;
|
|
|
|
|
|
|
|
|
|
std::cout << "[DEBUG] 添加参数: " << name << " type_kind: " << (int)param_type->GetKind()
|
|
|
|
|
<< " is_array: " << is_array << " dims: ";
|
|
|
|
|
for (int d : dims) std::cout << d << " ";
|
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|