package org.jcnc.snow.compiler.semantic.analyzers.statement;

import org.jcnc.snow.compiler.parser.ast.FunctionNode;
import org.jcnc.snow.compiler.parser.ast.LoopNode;
import org.jcnc.snow.compiler.semantic.analyzers.base.StatementAnalyzer;
import org.jcnc.snow.compiler.semantic.core.Context;
import org.jcnc.snow.compiler.semantic.core.ModuleInfo;
import org.jcnc.snow.compiler.semantic.error.SemanticError;
import org.jcnc.snow.compiler.semantic.symbol.SymbolTable;
import org.jcnc.snow.compiler.semantic.type.BuiltinType;
import org.jcnc.snow.compiler.semantic.type.Type;

/**
 * {@code LoopAnalyzer} 是用于分析 {@link LoopNode} 循环结构的语义分析器。
 * <p>
 * 支持的循环结构包括典型的 C 风格 for-loop：由初始化语句、条件表达式、更新语句和循环体组成。
 * <p>
 * 分析流程如下：
 * <ol>
 *   <li>分析初始化语句 {@code initializer}；</li>
 *   <li>分析并验证条件表达式 {@code condition} 类型是否为 {@link BuiltinType#INT}；</li>
 *   <li>分析更新语句 {@code update}；</li>
 *   <li>递归分析循环体 {@code body} 中的每个子语句；</li>
 *   <li>所有阶段若发现语义错误均记录至 {@link Context#getErrors()}，并写入日志。</li>
 * </ol>
 */
public class LoopAnalyzer implements StatementAnalyzer<LoopNode> {

    /**
     * 执行循环结构的语义分析。
     *
     * @param ctx    当前语义分析上下文，提供模块信息、错误记录、日志输出和分析器注册表等服务。
     * @param mi     当前模块信息（本方法中未直接使用，保留用于接口一致性）。
     * @param fn     当前函数节点（本方法中未直接使用，保留用于可能的上下文分析扩展）。
     * @param locals 当前作用域的符号表，记录变量类型及其可见性。
     * @param ln     待分析的 {@link LoopNode} 节点，包含初始化语句、条件表达式、更新语句和循环体。
     */
    @Override
    public void analyze(Context ctx,
                        ModuleInfo mi,
                        FunctionNode fn,
                        SymbolTable locals,
                        LoopNode ln) {

        // 1. 分析初始化语句
        ctx.log("检查 loop 循环");
        var initAnalyzer = ctx.getRegistry().getStatementAnalyzer(ln.initializer());
        if (initAnalyzer != null) {
            initAnalyzer.analyze(ctx, mi, fn, locals, ln.initializer());
        }

        // 2. 分析条件表达式并检查类型
        var condAnalyzer = ctx.getRegistry().getExpressionAnalyzer(ln.condition());
        Type cond = condAnalyzer.analyze(ctx, mi, fn, locals, ln.condition());
        if (cond != BuiltinType.INT) {
            ctx.getErrors().add(new SemanticError(
                    ln,
                    "loop 条件必须为 int 类型(表示真假)"
            ));
            ctx.log("错误: loop 条件类型不为 int");
        }

        // 3. 分析更新语句
        var updateAnalyzer = ctx.getRegistry().getStatementAnalyzer(ln.update());
        if (updateAnalyzer != null) {
            updateAnalyzer.analyze(ctx, mi, fn, locals, ln.update());
        }

        // 4. 递归分析循环体中的每个语句
        for (var stmt : ln.body()) {
            var stAnalyzer = ctx.getRegistry().getStatementAnalyzer(stmt);
            if (stAnalyzer != null) {
                stAnalyzer.analyze(ctx, mi, fn, locals, stmt);
            }
        }
    }
}
