1use crate::path::PathPrefix;
2use crate::value::{Kind, Value};
3use std::collections::{HashMap, hash_map::Entry};
4
5use super::{TypeDef, parser::ast::Ident, type_def::Details, value::Collection};
6
7#[derive(Debug, Clone)]
8pub struct TypeInfo {
9 pub state: TypeState,
10 pub result: TypeDef,
11}
12
13impl TypeInfo {
14 #[must_use]
15 pub fn new(state: impl Into<TypeState>, result: TypeDef) -> Self {
16 Self {
17 state: state.into(),
18 result,
19 }
20 }
21
22 #[must_use]
23 pub fn map_result(self, f: impl FnOnce(TypeDef) -> TypeDef) -> Self {
24 Self {
25 state: self.state,
26 result: f(self.result),
27 }
28 }
29}
30
31impl From<&TypeState> for TypeState {
32 fn from(state: &TypeState) -> Self {
33 state.clone()
34 }
35}
36
37#[allow(clippy::module_name_repetitions)]
38#[derive(Debug, Clone, Default)]
39pub struct TypeState {
40 pub local: LocalEnv,
41 pub external: ExternalEnv,
42}
43
44impl TypeState {
45 #[must_use]
46 pub fn merge(self, other: Self) -> Self {
47 Self {
48 local: self.local.merge(other.local),
49 external: self.external.merge(other.external),
50 }
51 }
52}
53
54#[derive(Debug, Default, Clone, PartialEq)]
56pub struct LocalEnv {
57 pub(crate) bindings: HashMap<Ident, Details>,
58}
59
60impl LocalEnv {
61 pub(crate) fn variable_idents(&self) -> impl Iterator<Item = &Ident> + '_ {
62 self.bindings.keys()
63 }
64
65 pub(crate) fn variable(&self, ident: &Ident) -> Option<&Details> {
66 self.bindings.get(ident)
67 }
68
69 pub(crate) fn insert_variable(&mut self, ident: Ident, details: Details) {
70 self.bindings.insert(ident, details);
71 }
72
73 pub(crate) fn remove_variable(&mut self, ident: &Ident) -> Option<Details> {
74 self.bindings.remove(ident)
75 }
76
77 pub(crate) fn apply_child_scope(mut self, child: Self) -> Self {
79 for (ident, child_details) in child.bindings {
80 if let Some(self_details) = self.bindings.get_mut(&ident) {
81 *self_details = child_details;
82 }
83 }
84
85 self
86 }
87
88 pub(crate) fn merge(mut self, other: Self) -> Self {
92 for (ident, other_details) in other.bindings {
93 if let Some(self_details) = self.bindings.get_mut(&ident) {
94 *self_details = self_details.clone().merge(other_details);
95 } else {
96 self.bindings.insert(ident, other_details);
97 }
98 }
99 self
100 }
101}
102
103#[derive(Debug, Clone)]
105pub struct ExternalEnv {
106 target: Details,
108
109 metadata: Kind,
111}
112
113impl Default for ExternalEnv {
114 fn default() -> Self {
115 Self::new_with_kind(
116 Kind::object(Collection::any()),
117 Kind::object(Collection::any()),
118 )
119 }
120}
121
122impl ExternalEnv {
123 #[must_use]
124 pub fn merge(self, other: Self) -> Self {
125 Self {
126 target: self.target.merge(other.target),
127 metadata: self.metadata.union(other.metadata),
128 }
129 }
130
131 #[must_use]
134 pub fn new_with_kind(target: Kind, metadata: Kind) -> Self {
135 Self {
136 target: Details {
137 type_def: target.into(),
138 value: None,
139 },
140 metadata,
141 }
142 }
143
144 pub(crate) fn target(&self) -> &Details {
145 &self.target
146 }
147
148 pub fn target_kind(&self) -> &Kind {
149 self.target().type_def.kind()
150 }
151
152 pub fn kind(&self, prefix: PathPrefix) -> Kind {
153 match prefix {
154 PathPrefix::Event => self.target_kind(),
155 PathPrefix::Metadata => self.metadata_kind(),
156 }
157 .clone()
158 }
159
160 pub fn metadata_kind(&self) -> &Kind {
161 &self.metadata
162 }
163
164 pub(crate) fn update_target(&mut self, details: Details) {
165 self.target = details;
166 }
167
168 pub fn update_metadata(&mut self, kind: Kind) {
169 self.metadata = kind;
170 }
171}
172
173#[allow(clippy::module_name_repetitions)]
175#[derive(Debug, Default)]
176pub struct RuntimeState {
177 variables: HashMap<Ident, Value>,
179}
180
181impl RuntimeState {
182 #[must_use]
183 pub fn is_empty(&self) -> bool {
184 self.variables.is_empty()
185 }
186
187 pub fn clear(&mut self) {
188 self.variables.clear();
189 }
190
191 #[must_use]
192 pub fn variable(&self, ident: &Ident) -> Option<&Value> {
193 self.variables.get(ident)
194 }
195
196 pub fn variable_mut(&mut self, ident: &Ident) -> Option<&mut Value> {
197 self.variables.get_mut(ident)
198 }
199
200 pub(crate) fn insert_variable(&mut self, ident: Ident, value: Value) {
201 self.variables.insert(ident, value);
202 }
203
204 pub(crate) fn remove_variable(&mut self, ident: &Ident) {
205 self.variables.remove(ident);
206 }
207
208 pub(crate) fn swap_variable(&mut self, ident: Ident, value: Value) -> Option<Value> {
209 match self.variables.entry(ident) {
210 Entry::Occupied(mut v) => Some(std::mem::replace(v.get_mut(), value)),
211 Entry::Vacant(v) => {
212 v.insert(value);
213 None
214 }
215 }
216 }
217}