use indexmap::IndexMap;
use crate::dag_id::DagId;
use crate::registry::declared_type::{IndexTypeRef, StructTypeRef};
use crate::syntax::names::{
FieldName, IndexName, IndexVariantName, ResolvedIndexVariant, StructTypeName,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RuntimeValueKind {
Scalar,
Bool,
Int,
Label {
index_name: IndexTypeRef,
variant: IndexVariantName,
},
Struct {
type_name: StructTypeRef,
},
Indexed {
index_name: IndexTypeRef,
},
RangeLabel,
Datetime,
}
impl std::fmt::Display for RuntimeValueKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Scalar => write!(f, "Scalar"),
Self::Bool => write!(f, "Bool"),
Self::Int => write!(f, "Int"),
Self::Label {
index_name,
variant,
} => {
let display_index = index_name.display_name();
write!(f, "label `{}`", variant.qualified_by(&display_index))
}
Self::Struct { type_name } => write!(f, "struct `{type_name}`"),
Self::Indexed { index_name } => write!(f, "indexed value `{index_name}[...]`"),
Self::RangeLabel => write!(f, "RangeLabel"),
Self::Datetime => write!(f, "Datetime"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RuntimeValueError {
pub expected: &'static str,
pub context: String,
pub actual: RuntimeValueKind,
}
impl std::fmt::Display for RuntimeValueError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"expected {} for {}, got {}",
self.expected, self.context, self.actual
)
}
}
impl std::error::Error for RuntimeValueError {}
#[derive(Debug, Clone)]
pub enum RuntimeValue {
Scalar(f64),
Bool(bool),
Int(i64),
Label {
index_name: IndexTypeRef,
variant: IndexVariantName,
},
Struct {
type_name: StructTypeRef,
fields: IndexMap<FieldName, Self>,
},
Indexed {
index_name: IndexTypeRef,
entries: IndexMap<IndexVariantName, Self>,
},
RangeLabel {
step_index: usize,
value: f64,
},
Datetime(hifitime::Epoch),
}
impl RuntimeValue {
#[must_use]
pub fn label_with_owner(
owner: DagId,
index_name: IndexName,
variant: IndexVariantName,
) -> Self {
Self::Label {
index_name: IndexTypeRef::with_owner(owner, index_name),
variant,
}
}
#[must_use]
pub fn resolved_label(resolved: &ResolvedIndexVariant) -> Self {
Self::Label {
index_name: IndexTypeRef::from_resolved(resolved.index().clone()),
variant: resolved.variant().clone(),
}
}
#[must_use]
pub fn struct_with_owner(
owner: DagId,
type_name: StructTypeName,
fields: IndexMap<FieldName, Self>,
) -> Self {
Self::Struct {
type_name: StructTypeRef::with_owner(owner, type_name),
fields,
}
}
#[must_use]
pub fn indexed_with_owner(
owner: DagId,
index_name: IndexName,
entries: IndexMap<IndexVariantName, Self>,
) -> Self {
Self::Indexed {
index_name: IndexTypeRef::with_owner(owner, index_name),
entries,
}
}
#[must_use]
pub fn kind(&self) -> RuntimeValueKind {
match self {
Self::Scalar(_) => RuntimeValueKind::Scalar,
Self::Bool(_) => RuntimeValueKind::Bool,
Self::Int(_) => RuntimeValueKind::Int,
Self::Label {
index_name,
variant,
} => RuntimeValueKind::Label {
index_name: index_name.clone(),
variant: variant.clone(),
},
Self::Struct { type_name, .. } => RuntimeValueKind::Struct {
type_name: type_name.clone(),
},
Self::Indexed { index_name, .. } => RuntimeValueKind::Indexed {
index_name: index_name.clone(),
},
Self::RangeLabel { .. } => RuntimeValueKind::RangeLabel,
Self::Datetime(_) => RuntimeValueKind::Datetime,
}
}
pub fn expect_scalar(&self, context: &str) -> Result<f64, RuntimeValueError> {
match self {
Self::Scalar(v) | Self::RangeLabel { value: v, .. } => Ok(*v),
other => Err(RuntimeValueError {
expected: "scalar",
context: context.to_string(),
actual: other.kind(),
}),
}
}
pub fn expect_bool(&self, context: &str) -> Result<bool, RuntimeValueError> {
match self {
Self::Bool(b) => Ok(*b),
other => Err(RuntimeValueError {
expected: "Bool",
context: context.to_string(),
actual: other.kind(),
}),
}
}
}