# neurotron/lang/ir.py
"""
IR (Intermediate Representation) da linguagem Neuro v0.1

Mínimo necessário para compilar o exemplo fib.nl:
- Funções
- Instruções de pilha
- Saltos condicionais
- Chamadas de função
"""

from __future__ import annotations

from dataclasses import dataclass, field
from enum import Enum, auto
from typing import List, Dict, Any


class Op(Enum):
    # Dados
    PUSH_CONST = auto()   # args: [value]
    LOAD_VAR   = auto()   # args: [name]
    STORE_VAR  = auto()   # args: [name] (não usado ainda em fib, mas já previsto)

    # Aritmética / comparação
    ADD        = auto()   # args: []
    SUB        = auto()   # args: []
    LT         = auto()   # args: []

    # Controlo de fluxo
    JUMP           = auto()  # args: [label_name]
    JUMP_IF_FALSE  = auto()  # args: [label_name]
    LABEL          = auto()  # args: [label_name]

    # Funções
    CALL       = auto()   # args: [func_name, nargs]
    RET        = auto()   # args: []


@dataclass
class Instruction:
    op: Op
    args: List[Any] = field(default_factory=list)

    def __repr__(self) -> str:
        if self.args:
            return f"{self.op.name} {', '.join(map(str, self.args))}"
        return f"{self.op.name}"


@dataclass
class FunctionIR:
    """
    IR de uma função.

    name: nome da função (ex: "fib" ou "__main__")
    params: lista de nomes de parâmetros (ex: ["x"])
    instructions: lista linear de instruções, incluindo LABELs.
    """
    name: str
    params: List[str]
    instructions: List[Instruction] = field(default_factory=list)

    def emit(self, op: Op, *args: Any):
        self.instructions.append(Instruction(op, list(args)))


@dataclass
class ModuleIR:
    """
    IR de um módulo inteiro (um programa Neuro).

    functions: mapa nome → FunctionIR
    entrypoint: nome da função de entrada (ex: "__main__")
    """
    functions: Dict[str, FunctionIR] = field(default_factory=dict)
    entrypoint: str = "__main__"

    def add_function(self, fn: FunctionIR):
        if fn.name in self.functions:
            raise ValueError(f"Função IR duplicada: {fn.name}")
        self.functions[fn.name] = fn
