Skip to main content

geam_core/plan/module/expression/function/
float.rs

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