use crate::convert::RewriteResult;
use crate::ir::Attribute;
use crate::ir::Operation;
use crate::ir::OperationName;
use crate::ir::Region;
use crate::ir::Values;
use anyhow::Result;
use std::fmt::Display;
use std::fmt::Formatter;
use std::sync::Arc;
use std::sync::RwLock;
pub trait Op {
fn operation_name() -> OperationName
where
Self: Sized;
fn verify(&self) -> Result<()> {
Ok(())
}
fn from_operation_without_verify(
operation: Arc<RwLock<Operation>>,
name: OperationName,
) -> Result<Self>
where
Self: Sized;
fn from_operation(operation: Arc<RwLock<Operation>>) -> Result<Self>
where
Self: Sized,
{
let name = Self::operation_name();
let op = Self::from_operation_without_verify(operation, name)?;
op.verify()?;
Ok(op)
}
fn as_any(&self) -> &dyn std::any::Any;
fn operation(&self) -> &Arc<RwLock<Operation>>;
fn region(&self) -> Option<Arc<RwLock<Region>>> {
let operation = self.operation().read().unwrap();
operation.region()
}
fn assignments(&self) -> Result<Values> {
let operation = self.operation();
let operation = operation.read().unwrap();
let results = operation.results();
Ok(results.clone())
}
fn canonicalize(&self) -> RewriteResult {
RewriteResult::Unchanged
}
fn is_terminator(&self) -> bool {
false
}
fn attribute(&self, key: &str) -> Option<Arc<dyn Attribute>> {
let operation = self.operation().read().unwrap();
let attributes = operation.attributes();
let attributes = attributes.map();
let attributes = attributes.read().unwrap();
let value = attributes.get(key)?;
Some(value.clone())
}
fn insert_before(&self, earlier: Arc<RwLock<dyn Op>>) {
let operation = self.operation().read().unwrap();
let block = operation.parent().unwrap();
let block = block.read().unwrap();
let later = self.operation().clone();
block.insert_before(earlier, later);
}
fn replace(&self, new: Arc<RwLock<dyn Op>>) {
let results = {
let old_operation = self.operation().try_read().unwrap();
old_operation.results()
};
{
for result in results.try_read().unwrap().iter() {
let mut result = result.try_write().unwrap();
result.set_defining_op(Some(new.clone()));
}
let new_read = new.try_read().unwrap();
let mut new_operation = new_read.operation().try_write().unwrap();
new_operation.set_results(results.clone());
}
let old_operation = self.operation().try_read().unwrap();
match old_operation.parent() {
Some(parent) => {
let parent = parent.try_read().unwrap();
parent.replace(self.operation().clone(), new.clone());
}
None => {}
}
}
fn ops(&self) -> Vec<Arc<RwLock<dyn Op>>> {
let mut result = Vec::new();
let region = self.region();
if let Some(region) = region {
for block in region.read().unwrap().blocks() {
let block = block.read().unwrap();
let ops = block.ops();
let ops = ops.read().unwrap();
for op in ops.iter() {
result.push(op.clone());
}
}
}
result
}
fn display(&self, f: &mut Formatter<'_>, indent: i32) -> std::fmt::Result {
let operation = self.operation().read().unwrap();
let spaces = crate::ir::spaces(indent);
write!(f, "{spaces}")?;
operation.display(f, indent)
}
}
impl Display for dyn Op {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.display(f, 0)
}
}