graphcal_compiler/registry/
runtime_value.rs1use indexmap::IndexMap;
4
5use crate::dag_id::DagId;
6use crate::registry::declared_type::{IndexTypeRef, StructTypeRef};
7use crate::syntax::names::{
8 FieldName, IndexName, IndexVariantName, ResolvedIndexVariant, StructTypeName,
9};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum RuntimeValueKind {
14 Scalar,
15 Bool,
16 Int,
17 Label {
18 index_name: IndexTypeRef,
19 variant: IndexVariantName,
20 },
21 Struct {
22 type_name: StructTypeRef,
23 },
24 Indexed {
25 index_name: IndexTypeRef,
26 },
27 RangeLabel,
28 Datetime,
29}
30
31impl std::fmt::Display for RuntimeValueKind {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 match self {
34 Self::Scalar => write!(f, "Scalar"),
35 Self::Bool => write!(f, "Bool"),
36 Self::Int => write!(f, "Int"),
37 Self::Label {
38 index_name,
39 variant,
40 } => {
41 let display_index = index_name.display_name();
42 write!(f, "label `{}`", variant.qualified_by(&display_index))
43 }
44 Self::Struct { type_name } => write!(f, "struct `{type_name}`"),
45 Self::Indexed { index_name } => write!(f, "indexed value `{index_name}[...]`"),
46 Self::RangeLabel => write!(f, "RangeLabel"),
47 Self::Datetime => write!(f, "Datetime"),
48 }
49 }
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
54pub struct RuntimeValueError {
55 pub expected: &'static str,
57 pub context: String,
59 pub actual: RuntimeValueKind,
61}
62
63impl std::fmt::Display for RuntimeValueError {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 write!(
66 f,
67 "expected {} for {}, got {}",
68 self.expected, self.context, self.actual
69 )
70 }
71}
72
73impl std::error::Error for RuntimeValueError {}
74
75#[derive(Debug, Clone)]
77pub enum RuntimeValue {
78 Scalar(f64),
79 Bool(bool),
80 Int(i64),
81 Label {
86 index_name: IndexTypeRef,
87 variant: IndexVariantName,
88 },
89 Struct {
90 type_name: StructTypeRef,
96 fields: IndexMap<FieldName, Self>,
97 },
98 Indexed {
100 index_name: IndexTypeRef,
101 entries: IndexMap<IndexVariantName, Self>,
102 },
103 RangeLabel {
106 step_index: usize,
107 value: f64,
108 },
109 Datetime(hifitime::Epoch),
111}
112
113impl RuntimeValue {
114 #[must_use]
116 pub fn label_with_owner(
117 owner: DagId,
118 index_name: IndexName,
119 variant: IndexVariantName,
120 ) -> Self {
121 Self::Label {
122 index_name: IndexTypeRef::with_owner(owner, index_name),
123 variant,
124 }
125 }
126
127 #[must_use]
129 pub fn resolved_label(resolved: &ResolvedIndexVariant) -> Self {
130 Self::Label {
131 index_name: IndexTypeRef::from_resolved(resolved.index().clone()),
132 variant: resolved.variant().clone(),
133 }
134 }
135
136 #[must_use]
138 pub fn struct_with_owner(
139 owner: DagId,
140 type_name: StructTypeName,
141 fields: IndexMap<FieldName, Self>,
142 ) -> Self {
143 Self::Struct {
144 type_name: StructTypeRef::with_owner(owner, type_name),
145 fields,
146 }
147 }
148
149 #[must_use]
151 pub fn indexed_with_owner(
152 owner: DagId,
153 index_name: IndexName,
154 entries: IndexMap<IndexVariantName, Self>,
155 ) -> Self {
156 Self::Indexed {
157 index_name: IndexTypeRef::with_owner(owner, index_name),
158 entries,
159 }
160 }
161
162 #[must_use]
164 pub fn kind(&self) -> RuntimeValueKind {
165 match self {
166 Self::Scalar(_) => RuntimeValueKind::Scalar,
167 Self::Bool(_) => RuntimeValueKind::Bool,
168 Self::Int(_) => RuntimeValueKind::Int,
169 Self::Label {
170 index_name,
171 variant,
172 } => RuntimeValueKind::Label {
173 index_name: index_name.clone(),
174 variant: variant.clone(),
175 },
176 Self::Struct { type_name, .. } => RuntimeValueKind::Struct {
177 type_name: type_name.clone(),
178 },
179 Self::Indexed { index_name, .. } => RuntimeValueKind::Indexed {
180 index_name: index_name.clone(),
181 },
182 Self::RangeLabel { .. } => RuntimeValueKind::RangeLabel,
183 Self::Datetime(_) => RuntimeValueKind::Datetime,
184 }
185 }
186
187 pub fn expect_scalar(&self, context: &str) -> Result<f64, RuntimeValueError> {
190 match self {
191 Self::Scalar(v) | Self::RangeLabel { value: v, .. } => Ok(*v),
192 other => Err(RuntimeValueError {
193 expected: "scalar",
194 context: context.to_string(),
195 actual: other.kind(),
196 }),
197 }
198 }
199
200 pub fn expect_bool(&self, context: &str) -> Result<bool, RuntimeValueError> {
203 match self {
204 Self::Bool(b) => Ok(*b),
205 other => Err(RuntimeValueError {
206 expected: "Bool",
207 context: context.to_string(),
208 actual: other.kind(),
209 }),
210 }
211 }
212}