1use super::{
2 BoolExpr, CallArg, CustomFieldAccess, FloatExpr, IntExpr, PanicExpr, StringExpr, TupleExpr,
3 UtfCodepointFunctionExpr, UtfCodepointListExpr,
4};
5use crate::plan::{FunctionInstantiation, HostCallSite, Step, UtfCodepointLocalId};
6use ecow::EcoString;
7use num_bigint::BigInt;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct UtfCodepointExpr {
11 kind: UtfCodepointExprKind,
12}
13
14#[derive(Debug, Clone, PartialEq)]
15pub(crate) enum UtfCodepointExprKind {
16 LocalGet {
17 local: UtfCodepointLocalId,
18 name: EcoString,
19 },
20 Call {
21 function: FunctionInstantiation,
22 args: Vec<CallArg>,
23 site: HostCallSite,
24 },
25 FunctionCall {
26 function: Box<UtfCodepointFunctionExpr>,
27 args: Vec<CallArg>,
28 site: HostCallSite,
29 },
30 TupleIndex {
31 tuple: Box<TupleExpr>,
32 index: usize,
33 },
34 CustomField(CustomFieldAccess),
35 ListIndex {
36 list: Box<UtfCodepointListExpr>,
37 index: usize,
38 },
39 Panic(PanicExpr),
40 BoolCase {
41 subject: Box<BoolExpr>,
42 true_: Box<UtfCodepointExpr>,
43 false_: Box<UtfCodepointExpr>,
44 },
45 IntCase {
46 subject: Box<IntExpr>,
47 clauses: Vec<(BigInt, UtfCodepointExpr)>,
48 fallback: Box<UtfCodepointExpr>,
49 },
50 StringCase {
51 subject: Box<StringExpr>,
52 clauses: Vec<(EcoString, UtfCodepointExpr)>,
53 fallback: Box<UtfCodepointExpr>,
54 },
55 FloatCase {
56 subject: Box<FloatExpr>,
57 clauses: Vec<(f64, UtfCodepointExpr)>,
58 fallback: Box<UtfCodepointExpr>,
59 },
60 Block {
61 steps: Vec<Step>,
62 return_: Box<UtfCodepointExpr>,
63 },
64}
65
66impl UtfCodepointExpr {
67 pub(crate) fn local_get(local: UtfCodepointLocalId, name: EcoString) -> Self {
68 Self::new(UtfCodepointExprKind::LocalGet { local, name })
69 }
70
71 #[cfg(test)]
72 pub(crate) fn call(function: FunctionInstantiation, args: Vec<CallArg>) -> Self {
73 Self::call_at(function, args, HostCallSite::unknown())
74 }
75
76 pub(crate) fn call_at(
77 function: FunctionInstantiation,
78 args: Vec<CallArg>,
79 site: HostCallSite,
80 ) -> Self {
81 Self::new(UtfCodepointExprKind::Call {
82 function,
83 args,
84 site,
85 })
86 }
87
88 #[cfg(test)]
89 pub(crate) fn function_call(function: UtfCodepointFunctionExpr, args: Vec<CallArg>) -> Self {
90 Self::function_call_at(function, args, HostCallSite::unknown())
91 }
92
93 pub(crate) fn function_call_at(
94 function: UtfCodepointFunctionExpr,
95 args: Vec<CallArg>,
96 site: HostCallSite,
97 ) -> Self {
98 Self::new(UtfCodepointExprKind::FunctionCall {
99 function: Box::new(function),
100 args,
101 site,
102 })
103 }
104
105 pub(crate) fn tuple_index(tuple: TupleExpr, index: usize) -> Self {
106 Self::new(UtfCodepointExprKind::TupleIndex {
107 tuple: Box::new(tuple),
108 index,
109 })
110 }
111
112 pub(crate) fn custom_field(access: CustomFieldAccess) -> Self {
113 Self::new(UtfCodepointExprKind::CustomField(access))
114 }
115
116 pub(crate) fn list_index(list: UtfCodepointListExpr, index: usize) -> Self {
117 Self::new(UtfCodepointExprKind::ListIndex {
118 list: Box::new(list),
119 index,
120 })
121 }
122
123 pub(crate) fn panic(panic: PanicExpr) -> Self {
124 Self::new(UtfCodepointExprKind::Panic(panic))
125 }
126
127 pub(crate) fn bool_case(subject: BoolExpr, true_: Self, false_: Self) -> Self {
128 Self::new(UtfCodepointExprKind::BoolCase {
129 subject: Box::new(subject),
130 true_: Box::new(true_),
131 false_: Box::new(false_),
132 })
133 }
134
135 pub(crate) fn int_case(subject: IntExpr, clauses: Vec<(BigInt, Self)>, fallback: Self) -> Self {
136 Self::new(UtfCodepointExprKind::IntCase {
137 subject: Box::new(subject),
138 clauses,
139 fallback: Box::new(fallback),
140 })
141 }
142
143 pub(crate) fn string_case(
144 subject: StringExpr,
145 clauses: Vec<(EcoString, Self)>,
146 fallback: Self,
147 ) -> Self {
148 Self::new(UtfCodepointExprKind::StringCase {
149 subject: Box::new(subject),
150 clauses,
151 fallback: Box::new(fallback),
152 })
153 }
154
155 pub(crate) fn float_case(
156 subject: FloatExpr,
157 clauses: Vec<(f64, Self)>,
158 fallback: Self,
159 ) -> Self {
160 Self::new(UtfCodepointExprKind::FloatCase {
161 subject: Box::new(subject),
162 clauses,
163 fallback: Box::new(fallback),
164 })
165 }
166
167 pub(crate) fn block(steps: Vec<Step>, return_: Self) -> Self {
168 Self::new(UtfCodepointExprKind::Block {
169 steps,
170 return_: Box::new(return_),
171 })
172 }
173
174 pub(crate) fn kind(&self) -> &UtfCodepointExprKind {
175 &self.kind
176 }
177
178 fn new(kind: UtfCodepointExprKind) -> Self {
179 Self { kind }
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::{UtfCodepointExpr, UtfCodepointExprKind};
186 use crate::plan::{
187 BoolExpr, Expr, FunctionInstantiation, FunctionShape, IntExpr, PanicExpr, PanicSite, Step,
188 StringExpr, TupleExpr, TupleLocalId, UtfCodepointFunctionExpr,
189 UtfCodepointFunctionReference, UtfCodepointListExpr, UtfCodepointListItem,
190 UtfCodepointListLocalId, UtfCodepointLocalId, ValueShape, ValueType,
191 monomorphic_function_instantiation,
192 };
193
194 #[test]
195 fn utf_codepoint_expr_kind_accessors() {
196 assert_eq!(
197 value().kind(),
198 &UtfCodepointExprKind::LocalGet {
199 local: UtfCodepointLocalId(0),
200 name: "value".into(),
201 },
202 );
203 assert_eq!(
204 UtfCodepointExpr::call(function_instantiation(), Vec::new()).kind(),
205 &UtfCodepointExprKind::Call {
206 function: function_instantiation(),
207 args: Vec::new(),
208 site: crate::plan::HostCallSite::unknown(),
209 },
210 );
211 assert_eq!(
212 UtfCodepointExpr::function_call(function(), Vec::new()).kind(),
213 &UtfCodepointExprKind::FunctionCall {
214 function: Box::new(function()),
215 args: Vec::new(),
216 site: crate::plan::HostCallSite::unknown(),
217 },
218 );
219 assert_eq!(
220 UtfCodepointExpr::tuple_index(tuple(), 0).kind(),
221 &UtfCodepointExprKind::TupleIndex {
222 tuple: Box::new(tuple()),
223 index: 0,
224 },
225 );
226 assert_eq!(
227 UtfCodepointExpr::list_index(list(), 0).kind(),
228 &UtfCodepointExprKind::ListIndex {
229 list: Box::new(list()),
230 index: 0,
231 },
232 );
233 let panic = PanicExpr::panic_at(None, PanicSite::unknown());
234 assert_eq!(
235 UtfCodepointExpr::panic(panic.clone()).kind(),
236 &UtfCodepointExprKind::Panic(panic),
237 );
238 assert_eq!(
239 UtfCodepointExpr::bool_case(BoolExpr::value(true), value(), value()).kind(),
240 &UtfCodepointExprKind::BoolCase {
241 subject: Box::new(BoolExpr::value(true)),
242 true_: Box::new(value()),
243 false_: Box::new(value()),
244 },
245 );
246 assert_eq!(
247 UtfCodepointExpr::int_case(
248 IntExpr::value(1.into()),
249 vec![(1.into(), value())],
250 value(),
251 )
252 .kind(),
253 &UtfCodepointExprKind::IntCase {
254 subject: Box::new(IntExpr::value(1.into())),
255 clauses: vec![(1.into(), value())],
256 fallback: Box::new(value()),
257 },
258 );
259 assert_eq!(
260 UtfCodepointExpr::string_case(
261 StringExpr::value("one".into()),
262 vec![("one".into(), value())],
263 value(),
264 )
265 .kind(),
266 &UtfCodepointExprKind::StringCase {
267 subject: Box::new(StringExpr::value("one".into())),
268 clauses: vec![("one".into(), value())],
269 fallback: Box::new(value()),
270 },
271 );
272 assert_eq!(
273 UtfCodepointExpr::float_case(
274 crate::plan::FloatExpr::value(1.0),
275 vec![(1.0, value())],
276 value(),
277 )
278 .kind(),
279 &UtfCodepointExprKind::FloatCase {
280 subject: Box::new(crate::plan::FloatExpr::value(1.0)),
281 clauses: vec![(1.0, value())],
282 fallback: Box::new(value()),
283 },
284 );
285 assert_eq!(
286 UtfCodepointExpr::block(
287 vec![Step::evaluate(Expr::int(IntExpr::value(1.into())))],
288 value(),
289 )
290 .kind(),
291 &UtfCodepointExprKind::Block {
292 steps: vec![Step::evaluate(Expr::int(IntExpr::value(1.into())))],
293 return_: Box::new(value()),
294 },
295 );
296 }
297
298 fn value() -> UtfCodepointExpr {
299 UtfCodepointExpr::local_get(UtfCodepointLocalId(0), "value".into())
300 }
301
302 fn function() -> UtfCodepointFunctionExpr {
303 UtfCodepointFunctionExpr::reference(UtfCodepointFunctionReference::new(
304 function_instantiation(),
305 ))
306 }
307
308 fn function_instantiation() -> FunctionInstantiation {
309 monomorphic_function_instantiation(
310 0,
311 FunctionShape::new(vec![ValueShape::UtfCodepoint], ValueShape::UtfCodepoint),
312 )
313 }
314
315 fn tuple() -> TupleExpr {
316 TupleExpr::local_get(
317 TupleLocalId(0),
318 "pair".into(),
319 vec![ValueType::UtfCodepoint],
320 )
321 }
322
323 fn list() -> UtfCodepointListExpr {
324 UtfCodepointListExpr::local_get(
325 UtfCodepointListItem,
326 UtfCodepointListLocalId(0),
327 "values".into(),
328 )
329 }
330}