1use super::{
2 BoolExpr, CallArg, CustomFieldAccess, FloatFunctionExpr, FloatListExpr, IntExpr, PanicExpr,
3 StringExpr, TupleExpr,
4};
5use crate::plan::{
6 ConstantFloatReference, FloatLocalId, FunctionInstantiation, HostCallSite, Step,
7};
8use ecow::EcoString;
9use num_bigint::BigInt;
10
11#[derive(Debug, Clone, PartialEq)]
12pub struct FloatExpr {
13 kind: FloatExprKind,
14}
15
16#[derive(Debug, Clone, PartialEq)]
17pub(crate) enum FloatExprKind {
18 Value(f64),
19 Constant(ConstantFloatReference),
20 LocalGet {
21 local: FloatLocalId,
22 name: EcoString,
23 },
24 Call {
25 function: FunctionInstantiation,
26 args: Vec<CallArg>,
27 site: HostCallSite,
28 },
29 FunctionCall {
30 function: Box<FloatFunctionExpr>,
31 args: Vec<CallArg>,
32 site: HostCallSite,
33 },
34 TupleIndex {
35 tuple: Box<TupleExpr>,
36 index: usize,
37 },
38 CustomField(CustomFieldAccess),
39 ListIndex {
40 list: Box<FloatListExpr>,
41 index: usize,
42 },
43 Panic(PanicExpr),
44 Add {
45 left: Box<FloatExpr>,
46 right: Box<FloatExpr>,
47 },
48 Sub {
49 left: Box<FloatExpr>,
50 right: Box<FloatExpr>,
51 },
52 Mult {
53 left: Box<FloatExpr>,
54 right: Box<FloatExpr>,
55 },
56 Div {
57 left: Box<FloatExpr>,
58 right: Box<FloatExpr>,
59 },
60 BoolCase {
61 subject: Box<BoolExpr>,
62 true_: Box<FloatExpr>,
63 false_: Box<FloatExpr>,
64 },
65 IntCase {
66 subject: Box<IntExpr>,
67 clauses: Vec<(BigInt, FloatExpr)>,
68 fallback: Box<FloatExpr>,
69 },
70 StringCase {
71 subject: Box<StringExpr>,
72 clauses: Vec<(EcoString, FloatExpr)>,
73 fallback: Box<FloatExpr>,
74 },
75 FloatCase {
76 subject: Box<FloatExpr>,
77 clauses: Vec<(f64, FloatExpr)>,
78 fallback: Box<FloatExpr>,
79 },
80 Block {
81 steps: Vec<Step>,
82 return_: Box<FloatExpr>,
83 },
84}
85
86impl FloatExpr {
87 pub(crate) fn value(value: f64) -> Self {
88 Self {
89 kind: FloatExprKind::Value(value),
90 }
91 }
92
93 pub(in crate::plan::module) fn constant(reference: ConstantFloatReference) -> Self {
94 Self {
95 kind: FloatExprKind::Constant(reference),
96 }
97 }
98
99 pub(crate) fn local_get(local: FloatLocalId, name: EcoString) -> Self {
100 Self {
101 kind: FloatExprKind::LocalGet { local, name },
102 }
103 }
104
105 #[cfg(test)]
106 pub(crate) fn call(function: FunctionInstantiation, args: Vec<CallArg>) -> Self {
107 Self::call_at(function, args, HostCallSite::unknown())
108 }
109
110 pub(crate) fn call_at(
111 function: FunctionInstantiation,
112 args: Vec<CallArg>,
113 site: HostCallSite,
114 ) -> Self {
115 Self {
116 kind: FloatExprKind::Call {
117 function,
118 args,
119 site,
120 },
121 }
122 }
123
124 #[cfg(test)]
125 pub(crate) fn function_call(function: FloatFunctionExpr, args: Vec<CallArg>) -> Self {
126 Self::function_call_at(function, args, HostCallSite::unknown())
127 }
128
129 pub(crate) fn function_call_at(
130 function: FloatFunctionExpr,
131 args: Vec<CallArg>,
132 site: HostCallSite,
133 ) -> Self {
134 Self {
135 kind: FloatExprKind::FunctionCall {
136 function: Box::new(function),
137 args,
138 site,
139 },
140 }
141 }
142
143 pub(crate) fn tuple_index(tuple: TupleExpr, index: usize) -> Self {
144 Self {
145 kind: FloatExprKind::TupleIndex {
146 tuple: Box::new(tuple),
147 index,
148 },
149 }
150 }
151
152 pub(crate) fn custom_field(access: CustomFieldAccess) -> Self {
153 Self {
154 kind: FloatExprKind::CustomField(access),
155 }
156 }
157
158 pub(crate) fn list_index(list: impl Into<FloatListExpr>, index: usize) -> Self {
159 Self {
160 kind: FloatExprKind::ListIndex {
161 list: Box::new(list.into()),
162 index,
163 },
164 }
165 }
166
167 pub(crate) fn panic(panic: PanicExpr) -> Self {
168 Self {
169 kind: FloatExprKind::Panic(panic),
170 }
171 }
172
173 pub(crate) fn add(left: FloatExpr, right: FloatExpr) -> Self {
174 Self {
175 kind: FloatExprKind::Add {
176 left: Box::new(left),
177 right: Box::new(right),
178 },
179 }
180 }
181
182 pub(crate) fn sub(left: FloatExpr, right: FloatExpr) -> Self {
183 Self {
184 kind: FloatExprKind::Sub {
185 left: Box::new(left),
186 right: Box::new(right),
187 },
188 }
189 }
190
191 pub(crate) fn mult(left: FloatExpr, right: FloatExpr) -> Self {
192 Self {
193 kind: FloatExprKind::Mult {
194 left: Box::new(left),
195 right: Box::new(right),
196 },
197 }
198 }
199
200 pub(crate) fn div(left: FloatExpr, right: FloatExpr) -> Self {
201 Self {
202 kind: FloatExprKind::Div {
203 left: Box::new(left),
204 right: Box::new(right),
205 },
206 }
207 }
208
209 pub(crate) fn bool_case(subject: BoolExpr, true_: FloatExpr, false_: FloatExpr) -> Self {
210 Self {
211 kind: FloatExprKind::BoolCase {
212 subject: Box::new(subject),
213 true_: Box::new(true_),
214 false_: Box::new(false_),
215 },
216 }
217 }
218
219 pub(crate) fn int_case(
220 subject: IntExpr,
221 clauses: Vec<(BigInt, FloatExpr)>,
222 fallback: FloatExpr,
223 ) -> Self {
224 Self {
225 kind: FloatExprKind::IntCase {
226 subject: Box::new(subject),
227 clauses,
228 fallback: Box::new(fallback),
229 },
230 }
231 }
232
233 pub(crate) fn string_case(
234 subject: StringExpr,
235 clauses: Vec<(EcoString, FloatExpr)>,
236 fallback: FloatExpr,
237 ) -> Self {
238 Self {
239 kind: FloatExprKind::StringCase {
240 subject: Box::new(subject),
241 clauses,
242 fallback: Box::new(fallback),
243 },
244 }
245 }
246
247 pub(crate) fn float_case(
248 subject: FloatExpr,
249 clauses: Vec<(f64, FloatExpr)>,
250 fallback: FloatExpr,
251 ) -> Self {
252 Self {
253 kind: FloatExprKind::FloatCase {
254 subject: Box::new(subject),
255 clauses,
256 fallback: Box::new(fallback),
257 },
258 }
259 }
260
261 pub(crate) fn block(steps: Vec<Step>, return_: FloatExpr) -> Self {
262 Self {
263 kind: FloatExprKind::Block {
264 steps,
265 return_: Box::new(return_),
266 },
267 }
268 }
269
270 pub(crate) fn kind(&self) -> &FloatExprKind {
271 &self.kind
272 }
273}
274
275#[cfg(test)]
276mod tests {
277 use super::{FloatExpr, FloatExprKind};
278 use crate::plan::{
279 BoolExpr, Expr, FloatFunctionReference, FloatLocalId, FunctionInstantiation, FunctionShape,
280 IntExpr, Step, TupleExpr, ValueShape, ValueType, monomorphic_function_instantiation,
281 };
282 use num_bigint::BigInt;
283
284 #[test]
285 fn float_expr_kind_accessors() {
286 assert_eq!(FloatExpr::value(1.0).kind(), &FloatExprKind::Value(1.0),);
287 assert_eq!(
288 FloatExpr::local_get(FloatLocalId(0), "value".into()).kind(),
289 &FloatExprKind::LocalGet {
290 local: FloatLocalId(0),
291 name: "value".into(),
292 },
293 );
294 assert_eq!(
295 FloatExpr::call(function_instantiation(), Vec::new()).kind(),
296 &FloatExprKind::Call {
297 function: function_instantiation(),
298 args: Vec::new(),
299 site: crate::plan::HostCallSite::unknown(),
300 },
301 );
302 assert_eq!(
303 FloatExpr::function_call(function_expr(), Vec::new()).kind(),
304 &FloatExprKind::FunctionCall {
305 function: Box::new(function_expr()),
306 args: Vec::new(),
307 site: crate::plan::HostCallSite::unknown(),
308 },
309 );
310 assert_eq!(
311 FloatExpr::tuple_index(tuple_expr(), 0).kind(),
312 &FloatExprKind::TupleIndex {
313 tuple: Box::new(tuple_expr()),
314 index: 0,
315 },
316 );
317 assert_eq!(
318 FloatExpr::add(FloatExpr::value(1.0), FloatExpr::value(2.0)).kind(),
319 &FloatExprKind::Add {
320 left: Box::new(FloatExpr::value(1.0)),
321 right: Box::new(FloatExpr::value(2.0)),
322 },
323 );
324 assert_eq!(
325 FloatExpr::sub(FloatExpr::value(1.0), FloatExpr::value(2.0)).kind(),
326 &FloatExprKind::Sub {
327 left: Box::new(FloatExpr::value(1.0)),
328 right: Box::new(FloatExpr::value(2.0)),
329 },
330 );
331 assert_eq!(
332 FloatExpr::mult(FloatExpr::value(1.0), FloatExpr::value(2.0)).kind(),
333 &FloatExprKind::Mult {
334 left: Box::new(FloatExpr::value(1.0)),
335 right: Box::new(FloatExpr::value(2.0)),
336 },
337 );
338 assert_eq!(
339 FloatExpr::div(FloatExpr::value(1.0), FloatExpr::value(2.0)).kind(),
340 &FloatExprKind::Div {
341 left: Box::new(FloatExpr::value(1.0)),
342 right: Box::new(FloatExpr::value(2.0)),
343 },
344 );
345 assert_eq!(
346 FloatExpr::bool_case(
347 BoolExpr::value(true),
348 FloatExpr::value(1.0),
349 FloatExpr::value(0.0)
350 )
351 .kind(),
352 &FloatExprKind::BoolCase {
353 subject: Box::new(BoolExpr::value(true)),
354 true_: Box::new(FloatExpr::value(1.0)),
355 false_: Box::new(FloatExpr::value(0.0)),
356 },
357 );
358 assert_eq!(
359 FloatExpr::int_case(
360 IntExpr::value(1.into()),
361 vec![(1.into(), FloatExpr::value(10.0))],
362 FloatExpr::value(0.0)
363 )
364 .kind(),
365 &FloatExprKind::IntCase {
366 subject: Box::new(IntExpr::value(1.into())),
367 clauses: vec![(BigInt::from(1), FloatExpr::value(10.0))],
368 fallback: Box::new(FloatExpr::value(0.0)),
369 },
370 );
371 assert_eq!(
372 FloatExpr::float_case(
373 FloatExpr::value(1.0),
374 vec![(1.0, FloatExpr::value(10.0))],
375 FloatExpr::value(0.0)
376 )
377 .kind(),
378 &FloatExprKind::FloatCase {
379 subject: Box::new(FloatExpr::value(1.0)),
380 clauses: vec![(1.0, FloatExpr::value(10.0))],
381 fallback: Box::new(FloatExpr::value(0.0)),
382 },
383 );
384 assert_eq!(
385 FloatExpr::string_case(
386 crate::plan::StringExpr::value("a".into()),
387 vec![("a".into(), FloatExpr::value(10.0))],
388 FloatExpr::value(0.0)
389 )
390 .kind(),
391 &FloatExprKind::StringCase {
392 subject: Box::new(crate::plan::StringExpr::value("a".into())),
393 clauses: vec![("a".into(), FloatExpr::value(10.0))],
394 fallback: Box::new(FloatExpr::value(0.0)),
395 },
396 );
397 assert_eq!(
398 FloatExpr::block(
399 vec![Step::evaluate(Expr::float(FloatExpr::value(1.0)))],
400 FloatExpr::value(2.0),
401 )
402 .kind(),
403 &FloatExprKind::Block {
404 steps: vec![Step::evaluate(Expr::float(FloatExpr::value(1.0)))],
405 return_: Box::new(FloatExpr::value(2.0)),
406 },
407 );
408 }
409
410 fn function_expr() -> crate::plan::FloatFunctionExpr {
411 crate::plan::FloatFunctionExpr::reference(FloatFunctionReference::new(
412 function_instantiation(),
413 ))
414 }
415
416 fn function_instantiation() -> FunctionInstantiation {
417 monomorphic_function_instantiation(0, FunctionShape::new(Vec::new(), ValueShape::Float))
418 }
419
420 fn tuple_expr() -> TupleExpr {
421 TupleExpr::value(
422 vec![Expr::float(FloatExpr::value(1.0))],
423 vec![ValueType::Float],
424 )
425 }
426}