use std::fmt;
use std::fmt::Debug;
use std::fmt::Formatter;
use crate::eval::Arguments;
use crate::eval::Evaluator;
use crate::eval::runtime::frame_span::FrameSpan;
use crate::values::FrozenValue;
use crate::values::FrozenValueTyped;
use crate::values::Heap;
use crate::values::Value;
use crate::values::ValueLike;
use crate::values::function::BoundMethodGen;
use crate::values::function::NativeAttribute;
use crate::values::function::NativeMethod;
#[derive(Clone)]
pub(crate) enum UnboundValue {
Method(FrozenValueTyped<'static, NativeMethod>),
Attr(FrozenValueTyped<'static, NativeAttribute>),
}
impl Debug for UnboundValue {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("MaybeUnboundValue").finish_non_exhaustive()
}
}
impl UnboundValue {
#[inline]
pub(crate) fn to_frozen_value(&self) -> FrozenValue {
match self {
UnboundValue::Method(m) => m.to_frozen_value(),
UnboundValue::Attr(a) => a.to_frozen_value(),
}
}
#[inline]
pub(crate) fn bind<'v>(&self, this: Value<'v>, heap: Heap<'v>) -> crate::Result<Value<'v>> {
match self {
UnboundValue::Method(m) => {
Ok(heap.alloc_complex(BoundMethodGen::new(this.to_value(), *m)))
}
UnboundValue::Attr(a) => a.invoke(this, heap),
}
}
#[inline]
pub(crate) fn invoke_method<'v>(
&self,
this: Value<'v>,
span: &'static FrameSpan,
args: &Arguments<'v, '_>,
eval: &mut Evaluator<'v, '_, '_>,
) -> crate::Result<Value<'v>> {
eval.with_call_stack(
self.to_frozen_value().to_value(),
Some(span),
|eval| match self {
UnboundValue::Method(m) => m.function.invoke(eval, this, args),
UnboundValue::Attr(a) => a.invoke(this, eval.heap()),
},
)
}
}