// 基于语法树的语义检查与名称绑定。
#pragma once

#include <unordered_map>
#include <vector>
#include <memory>

#include "SysYParser.h"
#include "ir/IR.h"

#define Sema_DEBUG 0

// 表达式信息结构
struct ExprInfo {
    std::shared_ptr<ir::Type> type = nullptr;
    bool is_lvalue = false;
    bool is_const = false;
    bool is_const_int = false;      // 是否是整型常量
    int const_int_value = 0;
    float const_float_value = 0.0f;
    antlr4::ParserRuleContext* node = nullptr;  // 对应的语法树节点
};

// 语义分析上下文：存储分析过程中产生的信息
class SemanticContext {
public:
    // ----- 变量使用绑定（使用 LValContext 而不是 VarContext）-----
    void BindVarUse(SysYParser::LValContext* use,
                    SysYParser::VarDefContext* decl) {
        var_uses_[use] = decl;
    }

    SysYParser::VarDefContext* ResolveVarUse(
        const SysYParser::LValContext* use) const {
        auto it = var_uses_.find(use);
        return it == var_uses_.end() ? nullptr : it->second;
    }

    void BindConstUse(SysYParser::LValContext* use, SysYParser::ConstDefContext* decl) {
        const_uses_[use] = decl;
    }
    SysYParser::ConstDefContext* ResolveConstUse(const SysYParser::LValContext* use) const {
        auto it = const_uses_.find(use);
        return it == const_uses_.end() ? nullptr : it->second;
    }

    // ----- 表达式类型信息存储 -----
    void SetExprType(antlr4::ParserRuleContext* node, const ExprInfo& info) {
        ExprInfo copy = info;
        copy.node = node;
        expr_types_[node] = copy;
    }
    
    ExprInfo* GetExprType(antlr4::ParserRuleContext* node) {
        auto it = expr_types_.find(node);
        return it == expr_types_.end() ? nullptr : &it->second;
    }
    
    const ExprInfo* GetExprType(antlr4::ParserRuleContext* node) const {
        auto it = expr_types_.find(node);
        return it == expr_types_.end() ? nullptr : &it->second;
    }

    // ----- 隐式转换标记（供 IR 生成使用）-----
    struct ConversionInfo {
        antlr4::ParserRuleContext* node;
        std::shared_ptr<ir::Type> from_type;
        std::shared_ptr<ir::Type> to_type;
    };
    
    void AddConversion(antlr4::ParserRuleContext* node,
                       std::shared_ptr<ir::Type> from,
                       std::shared_ptr<ir::Type> to) {
        conversions_.push_back({node, from, to});
    }
    
    const std::vector<ConversionInfo>& GetConversions() const { return conversions_; }

private:
    // 变量使用映射 - 使用 LValContext 作为键
    std::unordered_map<const SysYParser::LValContext*,
                       SysYParser::VarDefContext*> var_uses_;
    
    // 表达式类型映射
    std::unordered_map<antlr4::ParserRuleContext*, ExprInfo> expr_types_;
    
    // 隐式转换列表
    std::vector<ConversionInfo> conversions_;

    std::unordered_map<const SysYParser::LValContext*, SysYParser::ConstDefContext*> const_uses_;
};

// 目前仅检查：
// - 变量先声明后使用
// - 局部变量不允许重复定义
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);