Skip to main content

sql_fun_sqlast/sem/scalar_expr/
indirect.rs

1mod array_index;
2mod array_slice;
3mod member_ref;
4
5use sql_fun_core::IVec;
6
7use crate::{
8    sem::{
9        AnalysisError, FromClause, ParseContext, SemScalarExpr, TypeReference, WithClause,
10        analyze_scaler_expr,
11    },
12    syn::{ListOpt, Opt, ScanToken},
13};
14
15use self::{array_index::ArrayIndex, array_slice::ArraySlice, member_ref::MemberRef};
16use super::{AnalyzeScalarExpr, SemScalarExprNode};
17
18/// Indirect expression
19#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
20pub enum IndirectionExpr {
21    /// Array element index access expression
22    ArrayIndex(Box<ArrayIndex>),
23    /// Array range slice
24    ArraySlice(Box<ArraySlice>),
25    /// composite type member
26    MemberRef(Box<MemberRef>),
27}
28
29impl IndirectionExpr {
30    fn analyze_indicies<TParseContext>(
31        context: TParseContext,
32        with_clause: &WithClause,
33        from_clause: &FromClause,
34        arg: SemScalarExpr,
35        indicies: crate::syn::AIndices,
36        tokens: &IVec<ScanToken>,
37    ) -> Result<(Self, TParseContext), AnalysisError>
38    where
39        TParseContext: ParseContext,
40    {
41        if indicies.get_is_slice() {
42            ArraySlice::analyze_slice(context, with_clause, from_clause, arg, indicies, tokens)
43        } else {
44            ArrayIndex::analyze_index(context, with_clause, from_clause, arg, &indicies, tokens)
45        }
46    }
47}
48
49impl SemScalarExprNode for IndirectionExpr {
50    fn get_type(&self) -> Option<TypeReference> {
51        match &self {
52            IndirectionExpr::ArrayIndex(ind) => ind.item_type().clone(),
53            IndirectionExpr::ArraySlice(slice) => slice.array_type().clone(),
54            IndirectionExpr::MemberRef(mem_ref) => mem_ref.member_type().clone(),
55        }
56    }
57
58    fn is_not_null(&self) -> Option<bool> {
59        match &self {
60            IndirectionExpr::ArrayIndex(ind) => ind.array().is_not_null(),
61            IndirectionExpr::ArraySlice(slice) => slice.array_is_not_null(),
62            IndirectionExpr::MemberRef(mem_ref) => mem_ref.base_is_not_null(),
63        }
64    }
65}
66
67impl<TParseContext> AnalyzeScalarExpr<TParseContext, crate::syn::AIndirection> for IndirectionExpr
68where
69    TParseContext: ParseContext,
70{
71    fn analyze_scalar_expr(
72        mut context: TParseContext,
73        with_clause: &WithClause,
74        from_clause: &FromClause,
75        syn: crate::syn::AIndirection,
76        tokens: &IVec<ScanToken>,
77    ) -> Result<(SemScalarExpr, TParseContext), AnalysisError> {
78        let Some(arg) = syn.get_arg().as_inner() else {
79            AnalysisError::raise_unexpected_none("aindirection.arg")?
80        };
81
82        let Some(indirection) = syn.get_indirection().as_inner() else {
83            AnalysisError::raise_unexpected_none("aindirection.indirection")?
84        };
85        let (mut arg, new_context) =
86            analyze_scaler_expr(context, with_clause, from_clause, arg, tokens)?;
87        context = new_context;
88
89        for item in indirection {
90            if let Some(indicies) = item.as_a_indices().as_inner() {
91                let (new_arg, new_context) = Self::analyze_indicies(
92                    context,
93                    with_clause,
94                    from_clause,
95                    arg,
96                    indicies,
97                    tokens,
98                )?;
99                context = new_context;
100                arg = SemScalarExpr::Indirection(new_arg);
101            } else if let Some(member) = item.as_string().get_sval() {
102                arg = SemScalarExpr::Indirection(MemberRef::member_reference(
103                    arg,
104                    member,
105                    &mut context,
106                )?);
107            } else {
108                AnalysisError::raise_unexpected_input(&format!("indirection item: {item:?}"))?;
109            }
110        }
111        Ok((arg, context))
112    }
113}