use std::collections::HashMap;
use crate::cdsl::typevar::TypeVar;
#[derive(Clone, Debug)]
pub(crate) struct Operand {
pub name: &'static str,
pub kind: OperandKind,
doc: Option<&'static str>,
}
impl Operand {
pub fn new(name: &'static str, kind: impl Into<OperandKind>) -> Self {
Self {
name,
doc: None,
kind: kind.into(),
}
}
pub fn with_doc(mut self, doc: &'static str) -> Self {
self.doc = Some(doc);
self
}
pub fn doc(&self) -> &str {
if let Some(doc) = &self.doc {
return doc;
}
match &self.kind.fields {
OperandKindFields::TypeVar(tvar) => &tvar.doc,
_ => self.kind.doc(),
}
}
pub fn is_value(&self) -> bool {
matches!(self.kind.fields, OperandKindFields::TypeVar(_))
}
pub fn type_var(&self) -> Option<&TypeVar> {
match &self.kind.fields {
OperandKindFields::TypeVar(typevar) => Some(typevar),
_ => None,
}
}
pub fn is_varargs(&self) -> bool {
matches!(self.kind.fields, OperandKindFields::VariableArgs)
}
pub fn is_immediate_or_entityref(&self) -> bool {
matches!(
self.kind.fields,
OperandKindFields::ImmEnum(_)
| OperandKindFields::ImmValue
| OperandKindFields::EntityRef
)
}
pub fn is_immediate(&self) -> bool {
matches!(
self.kind.fields,
OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue
)
}
}
pub type EnumValues = HashMap<&'static str, &'static str>;
#[derive(Clone, Debug)]
pub(crate) enum OperandKindFields {
EntityRef,
VariableArgs,
ImmValue,
ImmEnum(EnumValues),
TypeVar(TypeVar),
}
impl OperandKindFields {
pub(crate) fn enum_values(&self) -> Option<&EnumValues> {
match self {
OperandKindFields::ImmEnum(map) => Some(map),
_ => None,
}
}
}
#[derive(Clone, Debug)]
pub(crate) struct OperandKind {
pub rust_type: &'static str,
pub rust_field_name: &'static str,
pub fields: OperandKindFields,
doc: Option<&'static str>,
}
impl OperandKind {
pub fn new(
rust_field_name: &'static str,
rust_type: &'static str,
fields: OperandKindFields,
doc: &'static str,
) -> Self {
Self {
rust_field_name,
rust_type,
fields,
doc: Some(doc),
}
}
fn doc(&self) -> &str {
if let Some(doc) = &self.doc {
return doc;
}
match &self.fields {
OperandKindFields::TypeVar(type_var) => &type_var.doc,
OperandKindFields::ImmEnum(_)
| OperandKindFields::ImmValue
| OperandKindFields::EntityRef
| OperandKindFields::VariableArgs => unreachable!(),
}
}
pub(crate) fn is_block(&self) -> bool {
self.rust_type == "ir::BlockCall"
}
}
impl From<&TypeVar> for OperandKind {
fn from(type_var: &TypeVar) -> Self {
OperandKind {
rust_field_name: "value",
rust_type: "ir::Value",
fields: OperandKindFields::TypeVar(type_var.into()),
doc: None,
}
}
}
impl From<&OperandKind> for OperandKind {
fn from(kind: &OperandKind) -> Self {
kind.clone()
}
}