use super::meta::{Frames, OpMeta};
use crate::OpCode;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct OperatorInfo {
pub name: &'static str,
pub aliases: &'static [&'static str],
pub family: &'static str,
pub feature: Option<&'static str>,
pub min_args: usize,
pub max_args: Option<usize>,
pub reads_context: bool,
pub effect: &'static str,
pub cost: &'static str,
pub scoped_arg: Option<ScopedArg>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ScopedArg {
Index(usize),
LastOfMany,
}
impl OperatorInfo {
pub(crate) fn of(op: OpCode) -> Option<Self> {
let entry = op.catalogue_entry();
let (name, aliases) = entry.names.split_first()?;
let meta: &OpMeta = op.meta();
let arity = op.arity();
Some(OperatorInfo {
name,
aliases,
family: entry.family,
feature: entry.feature(),
min_args: arity.min as usize,
max_args: arity.max.map(usize::from),
reads_context: meta.reads_context,
effect: meta.effect.name(),
cost: meta.cost.name(),
scoped_arg: match meta.frames {
Frames::None => None,
Frames::At(i) => Some(ScopedArg::Index(i as usize)),
Frames::LastIfMulti => Some(ScopedArg::LastOfMany),
},
})
}
}
pub(crate) fn operators_in(families: u32) -> impl Iterator<Item = OperatorInfo> {
OpCode::ALL
.iter()
.filter(move |op| op.in_families(families))
.filter_map(|op| OperatorInfo::of(*op))
}