Skip to main content

geam_core/plan/module/expression/
float.rs

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}