Skip to main content

veryl_analyzer/conv/
var.rs

1use crate::analyzer_error::InvalidSelectKind;
2use crate::conv::checker::separator::check_separator;
3use crate::conv::{Context, Conv};
4use crate::ir::{self, IrResult, VarPath, VarPathSelect, VarSelect, VarSelectOp};
5use crate::symbol_path::{GenericSymbol, GenericSymbolPath};
6use crate::{AnalyzerError, ir_error};
7use veryl_parser::token_range::TokenRange;
8use veryl_parser::veryl_grammar_trait::*;
9
10impl Conv<&Identifier> for VarPath {
11    fn conv(_context: &mut Context, value: &Identifier) -> IrResult<Self> {
12        Ok(VarPath(vec![value.text()]))
13    }
14}
15
16impl Conv<&ScopedIdentifier> for VarPath {
17    fn conv(_context: &mut Context, value: &ScopedIdentifier) -> IrResult<Self> {
18        let mut path = Vec::new();
19        match value.scoped_identifier_group.as_ref() {
20            ScopedIdentifierGroup::DollarIdentifier(x) => {
21                path.push(x.dollar_identifier.dollar_identifier_token.token.text);
22            }
23            ScopedIdentifierGroup::IdentifierScopedIdentifierOpt(x) => {
24                path.push(x.identifier.identifier_token.token.text);
25            }
26        }
27
28        for x in &value.scoped_identifier_list {
29            path.push(x.identifier.identifier_token.token.text);
30        }
31
32        Ok(VarPath(path))
33    }
34}
35
36impl Conv<&SelectOperator> for VarSelectOp {
37    fn conv(_context: &mut Context, value: &SelectOperator) -> IrResult<Self> {
38        let ret = match value {
39            SelectOperator::Colon(_) => VarSelectOp::Colon,
40            SelectOperator::PlusColon(_) => VarSelectOp::PlusColon,
41            SelectOperator::MinusColon(_) => VarSelectOp::MinusColon,
42            SelectOperator::Step(_) => VarSelectOp::Step,
43        };
44        Ok(ret)
45    }
46}
47
48fn check_select_type(context: &mut Context, expr: &mut ir::Expression, value: &Expression) {
49    let token: TokenRange = value.into();
50    let comptime = expr.eval_comptime(context, None);
51    if comptime.r#type.is_type() {
52        context.insert_error(AnalyzerError::invalid_factor(
53            None,
54            &comptime.r#type.to_string(),
55            &token,
56            &[],
57        ));
58    }
59}
60
61impl Conv<&ScopedIdentifier> for VarPathSelect {
62    fn conv(context: &mut Context, value: &ScopedIdentifier) -> IrResult<Self> {
63        let var_path: VarPath = Conv::conv(context, value)?;
64        let token: TokenRange = value.into();
65        Ok(VarPathSelect(var_path, VarSelect::default(), token))
66    }
67}
68
69impl Conv<&ExpressionIdentifier> for VarPathSelect {
70    fn conv(context: &mut Context, value: &ExpressionIdentifier) -> IrResult<Self> {
71        check_separator(context, value);
72
73        let mut path: VarPath = Conv::conv(context, value.scoped_identifier.as_ref())?;
74        let mut generic_path: GenericSymbolPath = value.scoped_identifier.as_ref().into();
75        let mut select = VarSelect::default();
76        let token: TokenRange = value.into();
77        let mut end: Option<(VarSelectOp, ir::Expression)> = None;
78
79        context.select_dims.push(0);
80
81        for x in &value.expression_identifier_list {
82            if end.is_some() {
83                context.insert_error(AnalyzerError::invalid_select(
84                    &InvalidSelectKind::SelectAfterRange,
85                    &token,
86                    &[],
87                ));
88                return Err(ir_error!(token));
89            }
90            context
91                .select_paths
92                .push((path.clone(), generic_path.clone()));
93            let mut expr = Conv::conv(context, x.select.expression.as_ref())?;
94            check_select_type(context, &mut expr, &x.select.expression);
95            select.push(expr);
96            if let Some(x) = &x.select.select_opt {
97                let op = Conv::conv(context, x.select_operator.as_ref())?;
98                let mut expr = Conv::conv(context, x.expression.as_ref())?;
99                check_select_type(context, &mut expr, &x.expression);
100                end = Some((op, expr));
101            }
102            context.select_paths.pop();
103            context.inc_select_dim();
104        }
105
106        for x in &value.expression_identifier_list0 {
107            path.push(x.identifier.identifier_token.token.text);
108            generic_path.paths.push(GenericSymbol {
109                base: x.identifier.identifier_token.token,
110                arguments: vec![],
111            });
112            context
113                .select_paths
114                .push((path.clone(), generic_path.clone()));
115            for x in &x.expression_identifier_list0_list {
116                if end.is_some() {
117                    context.insert_error(AnalyzerError::invalid_select(
118                        &InvalidSelectKind::SelectAfterRange,
119                        &token,
120                        &[],
121                    ));
122                    return Err(ir_error!(token));
123                }
124                let mut expr = Conv::conv(context, x.select.expression.as_ref())?;
125                check_select_type(context, &mut expr, &x.select.expression);
126                select.push(expr);
127                if let Some(x) = &x.select.select_opt {
128                    let op = Conv::conv(context, x.select_operator.as_ref())?;
129                    let mut expr = Conv::conv(context, x.expression.as_ref())?;
130                    check_select_type(context, &mut expr, &x.expression);
131                    end = Some((op, expr));
132                }
133                context.inc_select_dim();
134            }
135            context.select_paths.pop();
136        }
137
138        context.select_dims.pop();
139
140        select.1 = end;
141
142        Ok(VarPathSelect(path, select, token))
143    }
144}
145
146impl Conv<&HierarchicalIdentifier> for VarPathSelect {
147    fn conv(context: &mut Context, value: &HierarchicalIdentifier) -> IrResult<Self> {
148        let mut path: VarPath = Conv::conv(context, value.identifier.as_ref())?;
149        let mut generic_path: GenericSymbolPath = value.identifier.as_ref().into();
150        let mut select = VarSelect::default();
151        let token: TokenRange = value.into();
152        let mut end: Option<(VarSelectOp, ir::Expression)> = None;
153
154        for x in &value.hierarchical_identifier_list {
155            if end.is_some() {
156                context.insert_error(AnalyzerError::invalid_select(
157                    &InvalidSelectKind::SelectAfterRange,
158                    &token,
159                    &[],
160                ));
161                return Err(ir_error!(token));
162            }
163            context
164                .select_paths
165                .push((path.clone(), generic_path.clone()));
166            let mut expr = Conv::conv(context, x.select.expression.as_ref())?;
167            check_select_type(context, &mut expr, &x.select.expression);
168            select.push(expr);
169            if let Some(x) = &x.select.select_opt {
170                let op = Conv::conv(context, x.select_operator.as_ref())?;
171                let mut expr = Conv::conv(context, x.expression.as_ref())?;
172                check_select_type(context, &mut expr, &x.expression);
173                end = Some((op, expr));
174            }
175            context.select_paths.pop();
176        }
177
178        for x in &value.hierarchical_identifier_list0 {
179            path.push(x.identifier.identifier_token.token.text);
180            generic_path.paths.push(GenericSymbol {
181                base: x.identifier.identifier_token.token,
182                arguments: vec![],
183            });
184            context
185                .select_paths
186                .push((path.clone(), generic_path.clone()));
187            for x in &x.hierarchical_identifier_list0_list {
188                if end.is_some() {
189                    context.insert_error(AnalyzerError::invalid_select(
190                        &InvalidSelectKind::SelectAfterRange,
191                        &token,
192                        &[],
193                    ));
194                    return Err(ir_error!(token));
195                }
196                let mut expr = Conv::conv(context, x.select.expression.as_ref())?;
197                check_select_type(context, &mut expr, &x.select.expression);
198                select.push(expr);
199                if let Some(x) = &x.select.select_opt {
200                    let op = Conv::conv(context, x.select_operator.as_ref())?;
201                    let mut expr = Conv::conv(context, x.expression.as_ref())?;
202                    check_select_type(context, &mut expr, &x.expression);
203                    end = Some((op, expr));
204                }
205            }
206            context.select_paths.pop();
207        }
208
209        select.1 = end;
210
211        Ok(VarPathSelect(path, select, token))
212    }
213}
214
215impl Conv<&Expression> for Vec<VarPathSelect> {
216    fn conv(context: &mut Context, value: &Expression) -> IrResult<Self> {
217        let mut ret = vec![];
218
219        if let Some(x) = value.unwrap_factor() {
220            match x {
221                Factor::IdentifierFactor(x) => {
222                    let x: VarPathSelect =
223                        Conv::conv(context, x.identifier_factor.expression_identifier.as_ref())?;
224                    ret.push(x);
225                }
226                Factor::LBraceConcatenationListRBrace(x) => {
227                    let items: Vec<_> = x.concatenation_list.as_ref().into();
228                    for item in items {
229                        let mut x: Vec<VarPathSelect> =
230                            Conv::conv(context, item.expression.as_ref())?;
231                        ret.append(&mut x);
232                    }
233                }
234                _ => (),
235            }
236        }
237
238        Ok(ret)
239    }
240}