use crate::eval::index::Index;
use crate::expression::Expression;
use std::ops::Range;
use std::sync::Arc;
pub struct Item {
pub expr: Arc<Expression>,
pub resolution: Resolution,
pub cloned_from: Option<Index>,
pub context: Vec<Index>,
pub span: Option<Range<usize>>,
pub document: Option<std::sync::Arc<crate::Document>>,
}
impl Item {
pub fn new(expr: impl Into<Expression>) -> Self {
Item {
expr: Arc::new(expr.into()),
resolution: Default::default(),
cloned_from: None,
context: vec![],
span: None,
document: None,
}
}
pub fn expr(&self) -> Arc<Expression> {
self.expr.clone()
}
pub fn span(&self) -> Option<Range<usize>> {
self.span.clone()
}
}
impl std::fmt::Debug for Item {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use std::fmt::Write;
match &self.resolution {
Resolution::Unresolved => f.write_str("u:")?,
Resolution::Value(value) => f.write_fmt(format_args!("v[{:?}]:", value.kind()))?,
Resolution::Reference(referenced) => {
f.write_fmt(format_args!("r[{referenced}]:"))?;
}
}
self.expr.fmt(f)?;
if self.span.is_some() {
f.write_str("(")?;
self.span.as_ref().unwrap().fmt(f)?;
f.write_char(')')?;
} else {
f.write_char('?')?;
}
if let Some(cloned) = self.cloned_from {
f.write_fmt(format_args!(" source[{cloned}]"))?;
}
f.write_str(" ctx")?;
f.debug_list().entries(self.context.iter()).finish()
}
}
impl<I: Into<Expression>, S: Into<Option<Range<usize>>>> From<(I, S)> for Item {
fn from((expr, span): (I, S)) -> Self {
Self {
expr: Arc::new(expr.into()),
resolution: Resolution::default(),
cloned_from: None,
context: vec![],
span: span.into(),
document: None,
}
}
}
#[derive(Debug, Default, Clone)]
pub enum Resolution {
#[default]
Unresolved,
Value(crate::value::Value),
Reference(Index),
}
impl Resolution {
pub fn as_reference(&self) -> Option<Index> {
match self {
Resolution::Reference(reference) => Some(*reference),
Resolution::Unresolved | Resolution::Value(_) => None,
}
}
pub fn as_value(&self) -> Option<&crate::value::Value> {
match self {
Resolution::Value(value) => Some(value),
Resolution::Reference(_) | Resolution::Unresolved => None,
}
}
}
impl From<Index> for Resolution {
fn from(value: Index) -> Self {
Self::Reference(value)
}
}