toasty_core/stmt/
input.rs

1use crate::{
2    stmt::{Expr, ExprArg, ExprContext, ExprReference, Project, Projection, Resolve, Type, Value},
3    Schema,
4};
5
6pub trait Input {
7    fn resolve_arg(&mut self, expr_arg: &ExprArg, projection: &Projection) -> Option<Expr> {
8        let _ = (expr_arg, projection);
9        None
10    }
11
12    fn resolve_ref(
13        &mut self,
14        expr_reference: &ExprReference,
15        projection: &Projection,
16    ) -> Option<Expr> {
17        let _ = (expr_reference, projection);
18        None
19    }
20}
21
22#[derive(Debug, Default)]
23pub struct ConstInput {}
24
25pub struct TypedInput<'a, I, T = Schema> {
26    cx: ExprContext<'a, T>,
27    tys: &'a [Type],
28    input: I,
29}
30
31impl ConstInput {
32    pub fn new() -> ConstInput {
33        ConstInput {}
34    }
35}
36
37impl Input for ConstInput {}
38
39impl<'a, I, T> TypedInput<'a, I, T> {
40    pub fn new(cx: ExprContext<'a, T>, tys: &'a [Type], input: I) -> Self {
41        TypedInput { cx, tys, input }
42    }
43}
44
45impl<I: Input, T: Resolve> Input for TypedInput<'_, I, T> {
46    fn resolve_arg(&mut self, expr_arg: &ExprArg, projection: &Projection) -> Option<Expr> {
47        let expr = self.input.resolve_arg(expr_arg, projection)?;
48
49        if !expr.is_value_null() {
50            let actual_ty = self.cx.infer_expr_ty(&expr, &[]);
51
52            let mut ty = &self.tys[expr_arg.position];
53
54            for step in projection {
55                ty = match ty {
56                    Type::Record(tys) => &tys[step],
57                    Type::List(item) => item,
58                    _ => todo!("ty={ty:#?}"),
59                };
60            }
61
62            assert!(actual_ty.is_subtype_of(ty), "resolved input did not match requested argument type; expected={ty:#?}; actual={actual_ty:#?}")
63        }
64
65        Some(expr)
66    }
67}
68
69impl Input for &Vec<Value> {
70    fn resolve_arg(&mut self, expr_arg: &ExprArg, projection: &Projection) -> Option<Expr> {
71        Some(self[expr_arg.position].entry(projection).to_expr())
72    }
73}
74
75impl<T, const N: usize> Input for [T; N]
76where
77    for<'a> &'a T: Project,
78{
79    fn resolve_arg(&mut self, expr_arg: &ExprArg, projection: &Projection) -> Option<Expr> {
80        (&self[expr_arg.position]).project(projection)
81    }
82}
83
84impl<T, const N: usize> Input for &[T; N]
85where
86    for<'a> &'a T: Project,
87{
88    fn resolve_arg(&mut self, expr_arg: &ExprArg, projection: &Projection) -> Option<Expr> {
89        (&self[expr_arg.position]).project(projection)
90    }
91}
92
93impl<T> Input for &[T]
94where
95    for<'a> &'a T: Project,
96{
97    fn resolve_arg(&mut self, expr_arg: &ExprArg, projection: &Projection) -> Option<Expr> {
98        (&self[expr_arg.position]).project(projection)
99    }
100}