package org.jcnc.snow.compiler.cli;

import org.jcnc.snow.compiler.backend.RegisterAllocator;
import org.jcnc.snow.compiler.backend.VMCodeGenerator;
import org.jcnc.snow.compiler.backend.VMProgramBuilder;
import org.jcnc.snow.compiler.ir.builder.IRProgramBuilder;
import org.jcnc.snow.compiler.ir.core.IRFunction;
import org.jcnc.snow.compiler.ir.core.IRProgram;
import org.jcnc.snow.compiler.lexer.core.LexerEngine;
import org.jcnc.snow.compiler.lexer.token.Token;
import org.jcnc.snow.compiler.parser.ast.base.Node;
import org.jcnc.snow.compiler.parser.context.ParserContext;
import org.jcnc.snow.compiler.parser.core.ParserEngine;
import org.jcnc.snow.compiler.semantic.core.SemanticAnalyzerRunner;
import org.jcnc.snow.vm.engine.VMMode;
import org.jcnc.snow.vm.engine.VirtualMachineEngine;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

/**
 * SnowCompiler CLI —— 读取源文件，编译到 VM 指令并运行。
 */
public class SnowCompiler {

    public static void main(String[] args) throws IOException {
        /* ───── 读取源码 ───── */
        if (args.length == 0 || args[0].isBlank()) {
            System.err.println("Usage: SnowCompiler <source-file>");
            return;
        }
        Path srcPath = Path.of(args[0]);
        if (!Files.exists(srcPath)) {
            System.err.println("File not found: " + srcPath);
            return;
        }
        String source = Files.readString(srcPath, StandardCharsets.UTF_8);

        /* 1. 词法分析 */
        LexerEngine lexer = new LexerEngine(source, srcPath.toString());
        List<Token> tokens = lexer.getAllTokens();

        /* 2. 语法分析 */
        ParserContext ctx = new ParserContext(tokens);
        List<Node> ast = new ParserEngine(ctx).parse();

        /* 3. 语义分析 */
        SemanticAnalyzerRunner.runSemanticAnalysis(ast, false);

        /* 4. AST → IRProgram */
        IRProgram program = new IRProgramBuilder().buildProgram(ast);
        System.out.println("=== IR ===");
        System.out.println(program);

        /* 5. IR → VM 指令（单遍，自动回填 CALL 地址） */
        VMProgramBuilder builder = new VMProgramBuilder();
        for (IRFunction fn : program.functions()) {
            var slotMap = new RegisterAllocator().allocate(fn);
            new VMCodeGenerator(slotMap, builder).generate(fn);
        }
        List<String> finalCode = builder.build();

        System.out.println("== VM code ==");
        finalCode.forEach(System.out::println);

        /* 6. 运行虚拟机 */
        VirtualMachineEngine vm = new VirtualMachineEngine(VMMode.RUN);
        vm.execute(finalCode);
        vm.printStack();
        vm.printLocalVariables();
        System.out.println("Process has ended");
    }
}
