use std::rc::Rc;

use crate::vm::{
    instruction::{LocalId, MathInstruction},
    value::{Value, ValueString},
};

#[derive(Debug, PartialEq)]
pub enum CompileValue {
    Integer(i64),
    String(ValueString),
    Boolean(bool),
    LocalFunction(u32, usize),
    Local(LocalId),
    Argument(usize),
    Global(Rc<str>),
    Quote(Rc<Value>),
    Stack,
    Nil,
}

// #[derive(Debug, Hash, PartialEq, Eq)]
// pub enum CompileConstant {
//     Integer(i64),
//     LocalFunction(u32, usize),
//     Identifier(Rc<str>),
//     String(ValueString),
//     Value(Rc<Value>),
// }

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum BuiltinFunction {
    Math(MathInstruction),
}

impl BuiltinFunction {
    pub fn from_identifier(identifier: &str) -> Option<Self> {
        match identifier {
            "+" => Some(Self::Math(MathInstruction::Add)),
            "-" => Some(Self::Math(MathInstruction::Sub)),
            "*" => Some(Self::Math(MathInstruction::Mul)),
            "/" => Some(Self::Math(MathInstruction::Div)),
            "%" => Some(Self::Math(MathInstruction::Mod)),
            "&" => Some(Self::Math(MathInstruction::BitwiseAnd)),
            "|" => Some(Self::Math(MathInstruction::BitwiseOr)),
            "^" => Some(Self::Math(MathInstruction::BitwiseXor)),
            "&&" => Some(Self::Math(MathInstruction::And)),
            "||" => Some(Self::Math(MathInstruction::Or)),
            ">" => Some(Self::Math(MathInstruction::Gt)),
            ">=" => Some(Self::Math(MathInstruction::Ge)),
            "=" => Some(Self::Math(MathInstruction::Eq)),
            "/=" => Some(Self::Math(MathInstruction::Ne)),
            "<=" => Some(Self::Math(MathInstruction::Le)),
            "<" => Some(Self::Math(MathInstruction::Lt)),
            _ => None,
        }
    }
}
