open_vaf/ast_lowering/ast_to_hir_fold/
statements.rs1use log::*;
12
13use crate::ast::{BranchAccess, ModuleItem, ParameterType};
14use crate::ast_lowering::ast_to_hir_fold::expression::StatementExpressionFolder;
15use crate::ast_lowering::ast_to_hir_fold::{
16 DeclarationHandler, ExpressionFolder, Fold, VerilogContext,
17};
18use crate::ast_lowering::branch_resolution::BranchResolver;
19use crate::ast_lowering::error::{Error, NotAllowedInFunction, Type};
20
21use crate::hir::{Condition, Module, Statement};
22use crate::ir::hir::{DisciplineAccess, Function, FunctionArg, WhileLoop};
23use crate::ir::ids::IdRange;
24use crate::ir::NumericalParameterRangeExclude;
25use crate::ir::*;
26use crate::parser::error::Unsupported;
27use crate::symbol::Ident;
28use crate::symbol_table::SymbolDeclaration;
29use crate::{ast, Hir};
30use std::mem::take;
31
32pub struct Statements<'lt, H: DeclarationHandler> {
34 pub(super) branch_resolver: BranchResolver,
35 pub(super) state: VerilogContext,
36 pub(super) base: Fold<'lt>,
37 pub(super) declaration_handler: &'lt mut H,
38}
39
40impl<'lt, H: DeclarationHandler> Statements<'lt, H> {
41 pub fn fold(mut self) -> Result<Hir, Vec<Error>> {
42 for module in self.base.ast.modules.iter() {
43 self.base
44 .resolver
45 .enter_scope(&module.contents.symbol_table);
46
47 for decl in module.contents.symbol_table.values().copied() {
48 match decl {
49 SymbolDeclaration::Nature(_)
50 | SymbolDeclaration::Module(_)
51 | SymbolDeclaration::Discipline(_) => {
52 unreachable_unchecked!("Parser cant create this")
53 }
54
55 SymbolDeclaration::Branch(_)
56 | SymbolDeclaration::Port(_)
57 | SymbolDeclaration::Net(_)
58 | SymbolDeclaration::Block(_) => (), SymbolDeclaration::Function(function) => self.fold_function(function),
61 SymbolDeclaration::Variable(variable) => {
62 self.state.insert(VerilogContext::CONSTANT);
63 self.fold_variable(variable);
64 self.state.remove(VerilogContext::CONSTANT);
65 }
66 SymbolDeclaration::Parameter(parameter) => {
67 self.state.insert(VerilogContext::CONSTANT);
68 self.fold_parameter(parameter);
69 self.state.remove(VerilogContext::CONSTANT);
70 }
71 }
72 }
73
74 let analog_stmts_start = self.base.hir.statements.len_idx();
75
76 for module_item in module.contents.children.iter() {
77 match module_item {
78 ModuleItem::AnalogStmt(statement) => {
79 self.fold_statement(*statement);
80 }
81 ModuleItem::GenerateStatement => unimplemented!("Generate Statement"),
82 }
83 }
84
85 self.base.resolver.exit_scope();
86 self.base.hir.modules.push(module.map_with(|old| Module {
87 name: old.name,
88 port_list: old.port_list.clone(),
89 analog: IdRange(analog_stmts_start..self.base.hir.statements.len_idx()),
90 }));
91 }
92
93 if self.base.errors.is_empty() {
94 Ok(self.base.hir)
95 } else {
96 Err(self.base.errors)
97 }
98 }
99
100 pub fn fold_function(&mut self, id: FunctionId) {
101 let function = &self.base.ast[id].contents;
102 let args = function
103 .args
104 .iter()
105 .filter_map(|arg| {
106 if let Some(SymbolDeclaration::Variable(local_var)) =
107 function.declarations.get(&arg.name.name).copied()
108 {
109 Some(FunctionArg {
110 local_var,
111 input: arg.input,
112 output: arg.output,
113 })
114 } else {
115 self.base.errors.push(Error {
116 error_type: Type::TypeDeclarationMissing(arg.name.name),
117 source: arg.name.span,
118 });
119 None
120 }
121 })
122 .collect();
123
124 self.state.insert(VerilogContext::FUNCTION);
125 self.base.resolver.enter_function(&function.declarations);
126
127 for declaration in function.declarations.values().copied() {
128 match declaration {
129 SymbolDeclaration::Block(_) => { }
130 SymbolDeclaration::Variable(var) => self.fold_variable(var),
131 SymbolDeclaration::Parameter(param) => self.fold_parameter(param),
132 SymbolDeclaration::Module(_)
133 | SymbolDeclaration::Branch(_)
134 | SymbolDeclaration::Net(_)
135 | SymbolDeclaration::Port(_)
136 | SymbolDeclaration::Function(_)
137 | SymbolDeclaration::Discipline(_)
138 | SymbolDeclaration::Nature(_) => {
139 unreachable_unchecked!("Parser doesn't allow this")
140 }
141 }
142 }
143
144 self.fold_variable(function.return_variable);
145
146 let start = self.base.hir.statements.len_idx();
147 self.fold_statement(function.body);
148 self.base.hir[id] = self.base.ast[id].map(Function {
149 name: function.name,
150 args,
151 return_variable: function.return_variable,
152 body: IdRange(start..self.base.hir.statements.len_idx()),
153 });
154 self.base.resolver.exit_function();
155 self.state.remove(VerilogContext::FUNCTION);
156 }
157
158 fn fold_statement(&mut self, id: StatementId) {
163 match self.base.ast[id] {
164 ast::Statement::Block(id) => {
165 if let Some(scope) = &self.base.ast[id].contents.scope {
166 if self.state.contains(VerilogContext::FUNCTION) {
167 self.base.error(Error {
168 source: scope.name.span,
169 error_type: Type::NotAllowedInFunction(
170 NotAllowedInFunction::NamedBlocks,
171 ),
172 });
173 }
174
175 self.base.resolver.enter_scope(&scope.symbols);
176 self.state.insert(VerilogContext::CONSTANT);
177
178 for decl in scope.symbols.values().copied() {
179 match decl {
180 SymbolDeclaration::Nature(_) => unreachable_unchecked!("Natures can't be declared inside blocks so the parser won't ever place this here"),
181 SymbolDeclaration::Module(_)=>unreachable_unchecked!("Module cant be declared inside blocks so the parser won't ever place this here"),
182 SymbolDeclaration::Discipline(_) => unreachable_unchecked!("Discipline can't be declared inside blocks so the parser won't ever place this here"),
183 SymbolDeclaration::Function(_) => unreachable_unchecked!("Functions can't be declared inside blocks so the parser won't ever place this here"),
184 SymbolDeclaration::Branch(_) => unreachable_unchecked!("Functions can't be declared inside blocks so the parser won't ever place this here"),
185 SymbolDeclaration::Block(_) => (),SymbolDeclaration::Port(_) =>unreachable_unchecked!("Port can't be declared inside blocks so the parser won't ever place this here"),
187 SymbolDeclaration::Net(_) =>unreachable_unchecked!("Net( can't be declared inside blocks so the parser won't ever place this here"),
188 SymbolDeclaration::Variable(variableid) => {self.fold_variable(variableid);},
189 SymbolDeclaration::Parameter(parameter_id) => {self.fold_parameter(parameter_id);},
190 }
191 }
192
193 self.state.remove(VerilogContext::CONSTANT);
194 self.fold_block(id);
195 self.base.resolver.exit_scope();
196 } else {
197 self.fold_block(id);
198 }
199 }
200
201 ast::Statement::Condition(ref condition) => {
202 let start = self.base.hir.statements.push(Statement::ConditionStart {
203 condition_info_and_end: id, });
205 if let Some(contents) = self.fold_condition(&condition.contents) {
206 let end = self
207 .base
208 .hir
209 .statements
210 .push(Statement::Condition(condition.map(contents)));
211 self.base.hir[start] = Statement::ConditionStart {
212 condition_info_and_end: end,
213 };
214 }
215 }
216
217 ast::Statement::While(while_loop) => {
218 let start = self.base.hir.statements.push(Statement::WhileStart {
219 while_info_and_start: id, });
221
222 let condition = self.fold_expression(while_loop.contents.condition);
223 let body_start = self.base.hir.statements.len_idx();
224 self.fold_statement(while_loop.contents.body);
225 if let Some(condition) = condition {
226 let end = self
227 .base
228 .hir
229 .statements
230 .push(Statement::While(while_loop.copy_as(WhileLoop {
231 condition,
232 body: IdRange(body_start..self.base.hir.statements.len_idx()),
233 })));
234 self.base.hir[start] = Statement::WhileStart {
235 while_info_and_start: end,
236 }
237 }
238 }
239
240 ast::Statement::Assign(ref attr, ref ident, value) => {
241 resolve_hierarchical!(self.base; ident as Variable(id) => {
242 if let Some(value) = self.fold_expression(value){
243 self.base.hir.statements.push(Statement::Assignment(*attr, id, value));
244 }
245 })
246 }
247
248 ast::Statement::Contribute(attr, ref nature_name, ref branch, value) => {
249 if self.state.contains(VerilogContext::FUNCTION) {
250 self.base.error(Error {
251 source: nature_name.span.extend(self.base.ast[value].source),
252 error_type: Type::NotAllowedInFunction(NotAllowedInFunction::Contribute),
253 });
254 }
255
256 if let Some((discipline_access, branch, value)) =
257 self.fold_contribute(nature_name, branch, value)
258 {
259 self.base.hir.statements.push(Statement::Contribute(
260 attr,
261 discipline_access,
262 branch,
263 value,
264 ));
265 }
266 }
267
268 ast::Statement::FunctionCall(attr, ref name, ref parameters) => {
269 let parameters = parameters
270 .iter()
271 .copied()
272 .filter_map(|expr| self.fold_expression(expr))
273 .collect();
274
275 resolve_hierarchical!(self.base; name as
276 Function(fid) => {
277 self.base.hir.statements.push(Statement::FunctionCall(attr,fid,parameters));
278 }
279 )
280 }
281 ast::Statement::DisplayTask(_, _) => {
282 warn!("All display task such as $display are currently ignored. Display tasks will be implemented in the future");
284 }
285 }
286 }
287
288 fn fold_contribute(
289 &mut self,
290 nature_name: &Ident,
291 branch: &Node<BranchAccess>,
292 value: ExpressionId,
293 ) -> Option<(DisciplineAccess, BranchId, ExpressionId)> {
294 let (branch, discipline) = self
295 .branch_resolver
296 .resolve_branch_access(&mut self.base, branch)?;
297
298 let nature = self.branch_resolver.resolve_discipline_access(
299 &mut self.base,
300 nature_name,
301 discipline,
302 )?;
303
304 let value = self.fold_expression(value)?;
305 Some((nature, branch, value))
306 }
307
308 fn fold_condition(&mut self, node: &ast::Condition) -> Option<Condition> {
310 let condition = self.fold_expression(node.condition);
311
312 let if_body_start = self.base.hir.statements.len_idx();
313
314 self.fold_statement(node.if_statement);
315 let main_condition_statements = IdRange(if_body_start..self.base.hir.statements.len_idx());
316
317 let else_statements_start = self.base.hir.statements.len_idx();
318 if let Some(statement) = node.else_statement {
319 self.fold_statement(statement);
320 }
321
322 Some(Condition {
323 condition: condition?,
324 if_statements: main_condition_statements,
325 else_statements: IdRange(else_statements_start..self.base.hir.statements.len_idx()),
326 })
327 }
328
329 fn fold_expression(&mut self, expr: ExpressionId) -> Option<ExpressionId> {
331 StatementExpressionFolder {
332 state: self.state,
333 branch_resolver: &mut self.branch_resolver,
334 }
335 .fold(expr, &mut self.base)
336 }
337
338 fn fold_block(&mut self, block: BlockId) {
339 for statement in self.base.ast[block].contents.statements.iter().copied() {
340 self.fold_statement(statement);
341 }
342 }
343
344 fn fold_variable(&mut self, id: VariableId) {
347 self.base.hir[id].contents.default_value = self.base.hir[id]
348 .contents
349 .default_value
350 .and_then(|expr| self.fold_expression(expr));
351
352 self.declaration_handler
353 .handle_declaration(&mut self.base, SymbolDeclaration::Variable(id))
354 }
355
356 fn fold_parameter(&mut self, id: ParameterId) {
357 if let Some(expr) = self.fold_expression(self.base.hir[id].contents.default_value) {
358 self.base.hir[id].contents.default_value = expr
359 }
360
361 if let ParameterType::Numerical {
362 parameter_type,
363 ref mut from_ranges,
364 ref mut excluded,
365 } = self.base.hir[id].contents.parameter_type
366 {
367 let mut from_ranges = take(from_ranges);
368 let mut excluded = take(excluded);
369
370 for range in from_ranges.iter_mut() {
371 if let Some(expr) = self.fold_expression(range.start.bound) {
372 range.start.bound = expr;
373 }
374 if let Some(expr) = self.fold_expression(range.end.bound) {
375 range.end.bound = expr;
376 }
377 }
378
379 for exclude in excluded.iter_mut() {
380 match exclude {
381 NumericalParameterRangeExclude::Value(val) => {
382 if let Some(expr) = self.fold_expression(*val) {
383 *val = expr;
384 }
385 }
386
387 NumericalParameterRangeExclude::Range(range) => {
388 if let Some(expr) = self.fold_expression(range.start.bound) {
389 range.start.bound = expr;
390 }
391 if let Some(expr) = self.fold_expression(range.end.bound) {
392 range.end.bound = expr;
393 }
394 }
395 }
396 }
397
398 self.base.hir[id].contents.parameter_type = ParameterType::Numerical {
399 parameter_type,
400 excluded,
401 from_ranges,
402 }
403 } else {
404 self.base.error(Error {
405 error_type: Type::Unsupported(Unsupported::StringParameters),
406 source: self.base.ast[id].source,
407 })
408 }
409
410 self.declaration_handler
411 .handle_declaration(&mut self.base, SymbolDeclaration::Parameter(id))
412 }
413}