// 极简符号表：记录局部变量定义点。
#pragma once

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

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

// 符号种类
enum class SymbolKind {
    Variable,
    Function,
    Parameter,
    Constant
};

// 符号条目
struct Symbol {
    std::string name;
    SymbolKind kind;
    std::shared_ptr<ir::Type> type;     // 指向 Type 对象的智能指针
    int scope_level = 0;            // 定义时的作用域深度
    int stack_offset = -1;          // 局部变量/参数栈偏移（全局变量为 -1）
    bool is_initialized = false;    // 是否已初始化
    bool is_builtin = false;               // 是否为库函数

    // 对于数组参数，存储维度信息
    std::vector<int> array_dims;  // 数组各维长度（参数数组的第一维可能为0表示省略）
    bool is_array_param = false;   // 是否是数组参数

    // 对于函数，额外存储参数列表（类型已包含在函数类型中，这里仅用于快速访问）
    std::vector<std::shared_ptr<ir::Type>> param_types;

    // 对于常量，存储常量值（这里支持 int32 和 float）
    union ConstantValue {
        int i32;
        float f32;
    } const_value;
    bool is_int_const = true;       // 标记常量类型，用于区分 int 和 float

    // 关联的语法树节点（用于报错位置或进一步分析）
    SysYParser::VarDefContext* var_def_ctx = nullptr;
    SysYParser::ConstDefContext* const_def_ctx = nullptr;
    SysYParser::FuncFParamContext* param_def_ctx = nullptr;
    SysYParser::FuncDefContext* func_def_ctx = nullptr;
};

class SymbolTable {
  public:
    SymbolTable();
    ~SymbolTable() = default;

    // ----- 作用域管理 -----
    void enterScope();               // 进入新作用域
    void exitScope();                // 退出当前作用域
    int currentScopeLevel() const { return static_cast<int>(scopes_.size()) - 1; }

    // ----- 符号操作（推荐使用）-----
    bool addSymbol(const Symbol& sym);                     // 添加符号到当前作用域
    Symbol* lookup(const std::string& name);               // 从当前作用域向外查找
    Symbol* lookupCurrent(const std::string& name);        // 仅在当前作用域查找
    const Symbol* lookup(const std::string& name) const;
    const Symbol* lookupCurrent(const std::string& name) const;

    // ----- 与原接口兼容（保留原有功能）-----
    void Add(const std::string& name, SysYParser::VarDefContext* decl);
    bool Contains(const std::string& name) const;
    SysYParser::VarDefContext* Lookup(const std::string& name) const;

    // ----- 辅助函数：从语法树节点构造 Type -----
    static std::shared_ptr<ir::Type> getTypeFromFuncDef(SysYParser::FuncDefContext* ctx);

    void registerBuiltinFunctions();
    
    // 对常量表达式求值（返回整数值，用于数组维度等）
    int EvaluateConstExp(SysYParser::ConstExpContext* ctx) const;

    // 对常量表达式求值（返回浮点值，用于全局初始化）
    float EvaluateConstExpFloat(SysYParser::ConstExpContext* ctx) const;

    // 对常量初始化列表求值，返回一系列常量值（扁平化）
    struct ConstValue {
        enum Kind { INT, FLOAT };
        Kind kind;
        union {
            int int_val;
            float float_val;
        };
    };
    void fillArray(
        std::vector<ConstValue>& values,               
        size_t& index,                                 
        SysYParser::ConstInitValContext* ctx,          
        const std::vector<int>& dims,                  
        size_t dim_idx,                                
        std::shared_ptr<ir::Type> base_type) const;
    void fillZero(std::vector<ConstValue>& values, size_t& index,
                            const std::vector<int>& dims, size_t dim_idx,
                            std::shared_ptr<ir::Type> base_type) const;

    std::vector<ConstValue> EvaluateConstInitVal(
        SysYParser::ConstInitValContext* ctx,
        const std::vector<int>& dims,
        std::shared_ptr<ir::Type> base_type) const;
    
    int EvaluateConstExpression(SysYParser::ExpContext* ctx) const;

  private:
    // 作用域栈：每个元素是一个从名字到符号的映射
    std::vector<std::unordered_map<std::string, Symbol>> scopes_;

    static constexpr int GLOBAL_SCOPE = 0;  // 全局作用域索引
    
    ConstValue EvaluateAddExp(SysYParser::AddExpContext* ctx) const;
    ConstValue EvaluateMulExp(SysYParser::MulExpContext* ctx) const;
    ConstValue EvaluateUnaryExp(SysYParser::UnaryExpContext* ctx) const;
    ConstValue EvaluatePrimaryExp(SysYParser::PrimaryExpContext* ctx) const;

    std::shared_ptr<ir::Type> getTypeFromVarDef(SysYParser::VarDefContext* ctx) const;
};
