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}