use ocas_atom::Symbol;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BuiltinOp {
Sin,
Cos,
Tan,
Sec,
Csc,
Cot,
Exp,
Log,
Sqrt,
Abs,
}
impl BuiltinOp {
pub fn from_name(name: &str) -> Option<Self> {
match name.to_lowercase().as_str() {
"sin" => Some(Self::Sin),
"cos" => Some(Self::Cos),
"tan" => Some(Self::Tan),
"sec" => Some(Self::Sec),
"csc" => Some(Self::Csc),
"cot" => Some(Self::Cot),
"exp" => Some(Self::Exp),
"log" | "ln" => Some(Self::Log),
"sqrt" => Some(Self::Sqrt),
"abs" => Some(Self::Abs),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Slot {
Param(usize),
Const(usize),
Temp(usize),
}
#[derive(Debug, Clone, PartialEq)]
pub enum Instruction {
Add(Slot, Vec<Slot>),
Mul(Slot, Vec<Slot>),
Pow(Slot, Slot, i64),
Powf(Slot, Slot, Slot),
Fun(Slot, Symbol, Slot),
ExternalFun(Slot, usize, Vec<Slot>),
Assign(Slot, Slot),
}
#[derive(Debug, Clone)]
pub enum Instr {
Add { dst: usize, srcs: Vec<usize> },
Mul { dst: usize, srcs: Vec<usize> },
Pow { dst: usize, base: usize, exp: i64 },
Powf { dst: usize, base: usize, exp: usize },
BuiltinOp {
dst: usize,
op: BuiltinOp,
src: usize,
},
ExternalFun {
dst: usize,
fn_idx: usize,
srcs: Vec<usize>,
},
Copy { dst: usize, src: usize },
}
impl Instr {
pub fn dst(&self) -> usize {
match self {
Instr::Add { dst, .. }
| Instr::Mul { dst, .. }
| Instr::Pow { dst, .. }
| Instr::Powf { dst, .. }
| Instr::BuiltinOp { dst, .. }
| Instr::ExternalFun { dst, .. }
| Instr::Copy { dst, .. } => *dst,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn slot_equality() {
assert_eq!(Slot::Param(0), Slot::Param(0));
assert_ne!(Slot::Param(0), Slot::Const(0));
assert_eq!(Slot::Temp(3), Slot::Temp(3));
}
#[test]
fn instr_dst() {
let add = Instr::Add {
dst: 5,
srcs: vec![1, 2],
};
assert_eq!(add.dst(), 5);
let fun = Instr::BuiltinOp {
dst: 3,
op: BuiltinOp::Sin,
src: 2,
};
assert_eq!(fun.dst(), 3);
}
}