use core::fmt;
use crate::{
EntityRef, Op, OpOperandRange, OpOperandRangeMut, RegionRef, Symbol, SymbolPath, SymbolRef,
UnsafeIntrusiveEntityRef, Value, ValueRef,
dialects::builtin::attributes::{Signature, SymbolRefAttr},
};
pub trait CallOpInterface: Op {
fn callable_for_callee(&self) -> Callable;
fn set_callee(&mut self, callable: Callable);
fn arguments(&self) -> OpOperandRange<'_>;
fn arguments_mut(&mut self) -> OpOperandRangeMut<'_>;
fn resolve_in_symbol_table(&self, symbols: &dyn crate::SymbolTable) -> Option<SymbolRef>;
fn resolve(&self) -> Option<SymbolRef>;
}
pub trait CallableOpInterface: Op {
fn get_callable_region(&self) -> Option<RegionRef>;
fn signature(&self) -> Signature;
}
pub trait CallableSymbol: Symbol + CallableOpInterface {}
impl<T: Symbol + CallableOpInterface> CallableSymbol for T {}
pub type CallableSymbolRef = UnsafeIntrusiveEntityRef<dyn CallableSymbol>;
#[doc(hidden)]
pub trait AsCallableSymbolRef {
fn as_callable_symbol_ref(&self) -> SymbolRef;
}
impl AsCallableSymbolRef for CallableSymbolRef {
#[inline]
fn as_callable_symbol_ref(&self) -> SymbolRef {
*self as SymbolRef
}
}
impl<T: CallableSymbol> AsCallableSymbolRef for T {
#[inline(always)]
fn as_callable_symbol_ref(&self) -> SymbolRef {
self.as_symbol_operation()
.as_symbol_ref()
.expect("callable symbols must provide a symbol operation")
}
}
impl<T: CallableSymbol> AsCallableSymbolRef for UnsafeIntrusiveEntityRef<T> {
#[inline(always)]
fn as_callable_symbol_ref(&self) -> SymbolRef {
*self as SymbolRef
}
}
#[derive(Debug, Clone)]
pub enum Callable {
Symbol(SymbolPath),
Value(ValueRef),
}
impl fmt::Display for Callable {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Symbol(path) => fmt::Display::fmt(path, f),
Self::Value(value) => fmt::Display::fmt(value, f),
}
}
}
impl From<&SymbolRefAttr> for Callable {
fn from(value: &SymbolRefAttr) -> Self {
Self::Symbol(value.path().clone())
}
}
impl From<&SymbolPath> for Callable {
fn from(value: &SymbolPath) -> Self {
Self::Symbol(value.clone())
}
}
impl From<SymbolPath> for Callable {
fn from(value: SymbolPath) -> Self {
Self::Symbol(value)
}
}
impl From<ValueRef> for Callable {
fn from(value: ValueRef) -> Self {
Self::Value(value)
}
}
impl Callable {
#[inline(always)]
pub fn new(callable: impl Into<Self>) -> Self {
callable.into()
}
pub fn is_symbol(&self) -> bool {
matches!(self, Self::Symbol(_))
}
pub fn is_value(&self) -> bool {
matches!(self, Self::Value(_))
}
pub fn as_symbol_path(&self) -> Option<&SymbolPath> {
match self {
Self::Symbol(name) => Some(name),
_ => None,
}
}
pub fn as_value(&self) -> Option<EntityRef<'_, dyn Value>> {
match self {
Self::Value(value_ref) => Some(value_ref.borrow()),
_ => None,
}
}
pub fn unwrap_symbol_path(self) -> SymbolPath {
match self {
Self::Symbol(name) => name,
Self::Value(value_ref) => panic!("expected symbol, got {}", value_ref.borrow().id()),
}
}
pub fn unwrap_value_ref(self) -> ValueRef {
match self {
Self::Value(value) => value,
Self::Symbol(ref name) => panic!("expected value, got {name}"),
}
}
}