use thiserror::Error;

use crate::ir::types::IRType;

#[derive(Debug, Clone, Error)]
pub enum IRError {
    #[error("variable `{0}` not found")]
    VariableNotFound(String),
    #[error("variable `{0}` has already been defined")]
    VariableHasBeenDefined(String),
    #[error("function `{0}` not found")]
    FunctionNotFound(String),
    #[error("function `{0}` has already been defined")]
    FunctionHasBeenDefined(String),
    #[error("incompatible operands: {0} and {1}")]
    IncompatiableOperand(IRType, IRType),
    #[error("invalid operand type: {0}")]
    InvalidOperand(IRType),
    #[error("too few arguments: expected {0}, got {1}")]
    TooFewArguments(usize, usize),
    #[error("too many arguments: expected {0}, got {1}")]
    TooManyArguments(usize, usize),
    #[error("type mismatch, expected {0}, got {1}")]
    TypeMismatch(IRType, IRType),
    #[error("invalid assignment target")]
    InvalidAssignmentTarget,
    #[error("break statement outside of loop")]
    BreakOutsideLoop,
    #[error("continue statement outside of loop")]
    ContinueOutsideLoop,
    #[error("invalid parameter type: {0}")]
    InvalidParameterType(IRType),
    #[error("return expression on void function")]
    ReturnExpressionOnVoidFunction,
}