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 {
match self.kind.fields {
OperandKindFields::TypeVar(_) => true,
_ => false,
}
}
pub fn type_var(&self) -> Option<&TypeVar> {
match &self.kind.fields {
OperandKindFields::TypeVar(typevar) => Some(typevar),
_ => None,
}
}
pub fn is_varargs(&self) -> bool {
match self.kind.fields {
OperandKindFields::VariableArgs => true,
_ => false,
}
}
pub fn is_immediate_or_entityref(&self) -> bool {
match self.kind.fields {
OperandKindFields::ImmEnum(_)
| OperandKindFields::ImmValue
| OperandKindFields::EntityRef => true,
_ => false,
}
}
pub fn is_immediate(&self) -> bool {
match self.kind.fields {
OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue => true,
_ => false,
}
}
}
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!(),
}
}
}
impl Into<OperandKind> for &TypeVar {
fn into(self) -> OperandKind {
OperandKind {
rust_field_name: "value",
rust_type: "ir::Value",
fields: OperandKindFields::TypeVar(self.into()),
doc: None,
}
}
}
impl Into<OperandKind> for &OperandKind {
fn into(self) -> OperandKind {
self.clone()
}
}