semantic_analyzer/semantic.rs
1//! # Semantic analyzer
2//! Semantic analyzer provides algorithms to analyze AST for different
3//! rules and generate `Semantic State stack` stack results. AST represent tree
4//! nodes of language constructions and fully cover all flow of the program
5//! represented through AST. And it's **Turing-complete**.
6//!
7//! ## Semantic State
8//! Semantic State contains basic entities:
9//! - `Global State` - global state of semantic analyzer results.
10//! - `Context` - stack for `Block state` of each functions body state.
11//! - `Errors` - semantic analyzes errors.z
12
13use crate::ast::{self, CodeLocation, GetLocation, GetName, MAX_PRIORITY_LEVEL_FOR_EXPRESSIONS};
14use crate::types::block_state::BlockState;
15use crate::types::expression::{
16 Expression, ExpressionResult, ExpressionResultValue, ExpressionStructValue,
17};
18use crate::types::semantic::{
19 ExtendedExpression, GlobalSemanticContext, SemanticContext, SemanticContextInstruction,
20 SemanticStack,
21};
22use crate::types::types::{Type, TypeName};
23use crate::types::{
24 error, Binding, Constant, ConstantName, Function, FunctionCall, FunctionName,
25 FunctionParameter, FunctionStatement, InnerValueName, LabelName, LetBinding, Value,
26};
27#[cfg(feature = "codec")]
28use serde::{Deserialize, Serialize};
29use std::cell::RefCell;
30use std::collections::HashMap;
31use std::marker::PhantomData;
32use std::rc::Rc;
33
34/// # Global State
35/// Global state can contains state declarations of:
36/// - Constants
37/// - Types
38/// - Functions
39/// And Semantic State context results for Global State context:
40/// - Context
41/// The visibility of Global state limited by current module.
42/// `Context` contains results of `Semantic` stack, as result of
43/// Semantic analyzer for Global State context. It's can be used for
44/// post-verification process, linting, Codegen.
45#[derive(Debug)]
46#[cfg_attr(feature = "codec", derive(Serialize, Deserialize))]
47pub struct GlobalState<I: SemanticContextInstruction> {
48 /// Constants declarations
49 pub constants: HashMap<ConstantName, Constant>,
50 /// Types declarations
51 pub types: HashMap<TypeName, Type>,
52 /// Functions declarations
53 pub functions: HashMap<FunctionName, Function>,
54 /// Context as Semantic Stack Context results contains basic semantic
55 /// result tree for Global context state.
56 pub context: SemanticStack<I>,
57}
58
59/// # State
60/// Basic entity that contains:
61/// - `Global State` - types, constants, functions declaration and
62/// most important - context results of Semantic State stack, that can be
63/// used for post-verification and/or Codegen.
64/// - `Context` stack for `Block state` of each functions body state
65/// - `Error State` contains errors stack as result of Semantic analyzer
66#[derive(Debug)]
67#[cfg_attr(feature = "codec", derive(Serialize))]
68pub struct State<E, I>
69where
70 E: ExtendedExpression<I>,
71 I: SemanticContextInstruction,
72{
73 /// Global State for current State
74 pub global: GlobalState<I>,
75 /// Context for all `Block State` stack that related to concrete functions body.
76 #[cfg_attr(feature = "codec", serde(skip))]
77 pub context: Vec<Rc<RefCell<BlockState<I>>>>,
78 /// Error state results stack
79 pub errors: Vec<error::StateErrorResult>,
80 phantom: PhantomData<E>,
81}
82
83impl<E, I> Default for State<E, I>
84where
85 E: ExtendedExpression<I>,
86 I: SemanticContextInstruction,
87{
88 fn default() -> Self {
89 Self::new()
90 }
91}
92
93impl<E, I> State<E, I>
94where
95 E: ExtendedExpression<I>,
96 I: SemanticContextInstruction,
97{
98 /// Init new `State`
99 #[must_use]
100 pub fn new() -> Self {
101 Self {
102 global: GlobalState {
103 functions: HashMap::new(),
104 types: HashMap::new(),
105 constants: HashMap::new(),
106 context: SemanticStack::new(),
107 },
108 context: Vec::new(),
109 errors: Vec::new(),
110 phantom: PhantomData,
111 }
112 }
113
114 /// Add error to Semantic `Errors State`
115 fn add_error(&mut self, err: error::StateErrorResult) {
116 self.errors.push(err);
117 }
118
119 /// Add `State context` with body state context block
120 fn add_state_context(&mut self, state_body: Rc<RefCell<BlockState<I>>>) {
121 self.context.push(state_body);
122 }
123
124 /// Check is value type exists in `Global State`.
125 /// `Primitive` type always return true. For other cases if type doesn't
126 /// exist in `Global State`, add errors to `Error State` and return `false` result.
127 fn check_type_exists(
128 &mut self,
129 type_name: &Type,
130 val_name: &impl ToString,
131 location: &impl GetLocation,
132 ) -> bool {
133 if let Type::Primitive(_) = type_name {
134 return true;
135 }
136 if !self.global.types.contains_key(&type_name.name()) {
137 self.add_error(error::StateErrorResult::new(
138 error::StateErrorKind::TypeNotFound,
139 val_name.to_string(),
140 location.location(),
141 ));
142 return false;
143 }
144 true
145 }
146
147 /// Run semantic analyzer that covers all flow for AST.
148 /// It's do not return any results, but fill results fir the `Semantic State`.
149 ///
150 pub fn run(&mut self, data: &ast::Main<'_, I, E>) {
151 // Execute each kind of analyzing and return errors data.
152 // For functions - fetch only declaration for fast-forward
153 // identification for using it in functions body.
154
155 // First pass is Imports and Types
156 for main in data {
157 match main {
158 ast::MainStatement::Import(import) => self.import(import),
159 ast::MainStatement::Types(types) => self.types(types),
160 _ => (),
161 }
162 }
163 // Declaration pass for Constants and Functions
164 for main in data {
165 match main {
166 ast::MainStatement::Constant(constant) => self.constant(constant),
167 ast::MainStatement::Function(function) => self.function_declaration(function),
168 _ => (),
169 }
170 }
171
172 // After getting all functions declarations, fetch only functions body
173 for main in data {
174 if let ast::MainStatement::Function(function) = main {
175 self.function_body(function);
176 }
177 }
178 }
179
180 /// Import analyzer (TBD)
181 #[allow(clippy::unused_self, clippy::unnecessary_wraps)]
182 pub fn import(&self, data: &ast::ImportPath<'_>) {
183 if !data.is_empty() {
184 let _name = data[0].name();
185 }
186 }
187
188 /// Types declaration analyzer. Add types to `Global State`.
189 /// Currently only one type kind: Structs. And types can't be part of
190 /// the `Block State`.
191 pub fn types(&mut self, data: &ast::StructTypes<'_>) {
192 if self.global.types.contains_key(&data.name().into()) {
193 self.add_error(error::StateErrorResult::new(
194 error::StateErrorKind::TypeAlreadyExist,
195 data.name(),
196 data.location(),
197 ));
198 return;
199 }
200 let struct_type = Type::Struct(data.clone().into());
201 self.global.types.insert(struct_type.name(), struct_type);
202 self.global.context.types(data.clone().into());
203 }
204
205 /// Check constant value expression.
206 /// If expression contains `Constant` check is constant exists.
207 /// Values doesn't check as it's just `Primitive Values`.
208 /// Also check all expression tree branches.
209 /// If `ConstantValue` doesn't exist add error to `Error State` and `return` false result.
210 pub fn check_constant_value_expression(
211 &mut self,
212 data: &Option<(ast::ExpressionOperations, Box<ast::ConstantExpression<'_>>)>,
213 ) -> bool {
214 // For constant expression skip ExpressionOperations
215 if let Some((_, child_data)) = data {
216 // Check only Constant value
217 match child_data.value.clone() {
218 // Check is ConstantValue already exist in global state
219 ast::ConstantValue::Constant(const_name) => {
220 if !self
221 .global
222 .constants
223 .contains_key(&const_name.clone().into())
224 {
225 self.add_error(error::StateErrorResult::new(
226 error::StateErrorKind::ConstantNotFound,
227 const_name.name(),
228 const_name.location(),
229 ));
230 return false;
231 }
232 self.check_constant_value_expression(&child_data.operation)
233 }
234 ast::ConstantValue::Value(_) => true,
235 }
236 } else {
237 true
238 }
239 }
240
241 /// Constant analyzer. Add it to `Global State`, because constants
242 /// can be only global for `Semantic state`, not for `Block state`.
243 pub fn constant(&mut self, data: &ast::Constant<'_>) {
244 if self.global.constants.contains_key(&data.name().into()) {
245 self.add_error(error::StateErrorResult::new(
246 error::StateErrorKind::ConstantAlreadyExist,
247 data.name(),
248 data.location(),
249 ));
250 return;
251 }
252 if !self.check_constant_value_expression(&data.constant_value.operation) {
253 return;
254 }
255 let const_val: Constant = data.clone().into();
256 if !self.check_type_exists(&const_val.constant_type, &const_val.name, data) {
257 return;
258 }
259 self.global
260 .constants
261 .insert(const_val.name.clone(), const_val.clone());
262 self.global.context.constant(const_val);
263 }
264
265 /// Function declaration analyze. Add it to Global State/M
266 pub fn function_declaration(&mut self, data: &ast::FunctionStatement<'_, I, E>) {
267 if self.global.functions.contains_key(&data.name().into()) {
268 self.add_error(error::StateErrorResult::new(
269 error::StateErrorKind::FunctionAlreadyExist,
270 data.name(),
271 data.location(),
272 ));
273 return;
274 }
275 let func_decl: FunctionStatement = data.clone().into();
276 let mut force_quite =
277 !self.check_type_exists(&func_decl.result_type, &func_decl.name, data);
278
279 // Fetch parameters and check types
280 let parameters = func_decl
281 .parameters
282 .iter()
283 .map(|p| {
284 force_quite = force_quite || !self.check_type_exists(&p.parameter_type, p, data);
285 p.parameter_type.clone()
286 })
287 .collect();
288 // Force quite if errors
289 if force_quite {
290 return;
291 }
292 self.global.functions.insert(
293 data.name().into(),
294 Function {
295 inner_name: func_decl.name,
296 inner_type: func_decl.result_type,
297 parameters,
298 },
299 );
300 self.global
301 .context
302 .function_declaration(data.clone().into());
303 }
304
305 /// Init function parameters.
306 /// It's init function parameters as values, same as let-binding.
307 /// And add instructions to `SemanticStack`.
308 fn init_func_params(
309 &mut self,
310 function_state: &Rc<RefCell<BlockState<I>>>,
311 fn_params: &Vec<ast::FunctionParameter<'_>>,
312 ) {
313 for fn_param in fn_params {
314 let func_param: FunctionParameter = fn_param.clone().into();
315 let arg_name = func_param.clone().to_string();
316
317 // Find value in current state and parent states
318 let value = function_state
319 .borrow()
320 .get_value_name(&arg_name.clone().into());
321 // Calculate `inner_name` as unique for current and all parent states
322 let inner_name: InnerValueName = if value.is_none() {
323 // if value not found in all states check and set
324 // `inner_value` from value name
325 // NOTE: value number not incremented
326 arg_name.clone().into()
327 } else {
328 // Function parameter name can't be with the same name.
329 // Produce error
330 self.add_error(error::StateErrorResult::new(
331 error::StateErrorKind::FunctionArgumentNameDuplicated,
332 arg_name,
333 CodeLocation::new(1, 1),
334 ));
335 return;
336 };
337 // Set value parameters
338 let value = Value {
339 inner_name: inner_name.clone(),
340 inner_type: func_param.parameter_type.clone(),
341 mutable: false,
342 alloca: false,
343 malloc: false,
344 };
345 // Value inserted only to current state by Value name and Value data
346 function_state
347 .borrow_mut()
348 .values
349 .insert(arg_name.into(), value.clone());
350 // Set `inner_name` to current state and all parent states
351 function_state
352 .borrow_mut()
353 .set_inner_value_name(&inner_name);
354
355 function_state.borrow_mut().function_arg(value, func_param);
356 }
357 }
358
359 /// Function body analyze.
360 /// It is basic execution entity for program flow.
361 /// It's operate sub analyze for function elements. It's contain
362 /// Body State for current and child states.
363 pub fn function_body(&mut self, data: &ast::FunctionStatement<'_, I, E>) {
364 // Init empty function body state
365 let body_state = Rc::new(RefCell::new(BlockState::new(None)));
366 self.add_state_context(body_state.clone());
367 // Init function parameters - add to SemanticStackContext
368 self.init_func_params(&body_state, &data.parameters);
369 // Flag to indicate is function return called
370 let mut return_is_called = false;
371 // Fetch function elements and gather errors
372 for body in &data.body {
373 if return_is_called {
374 self.add_error(error::StateErrorResult::new(
375 error::StateErrorKind::ForbiddenCodeAfterReturnDeprecated,
376 format!("{body:?}"),
377 CodeLocation::new(1, 1),
378 ));
379 }
380 match body {
381 ast::BodyStatement::LetBinding(bind) => {
382 self.let_binding(bind, &body_state);
383 }
384 ast::BodyStatement::Binding(bind) => {
385 self.binding(bind, &body_state);
386 }
387 ast::BodyStatement::FunctionCall(fn_call) => {
388 self.function_call(fn_call, &body_state);
389 }
390 ast::BodyStatement::If(if_condition) => {
391 self.if_condition(if_condition, &body_state, &None, None);
392 }
393 ast::BodyStatement::Loop(loop_statement) => {
394 self.loop_statement(loop_statement, &body_state);
395 }
396 ast::BodyStatement::Expression(expression)
397 | ast::BodyStatement::Return(expression) => {
398 let expr_result = self.expression(expression, &body_state);
399 let expr: Expression = expression.clone().into();
400 // Check is return statement previously called
401 if return_is_called {
402 self.add_error(error::StateErrorResult::new(
403 error::StateErrorKind::ReturnAlreadyCalled,
404 expr.to_string(),
405 expression.location(),
406 ));
407 }
408 if let Some(res) = expr_result {
409 // Check expression type and do not exist from flow
410 self.check_type_exists(&res.expr_type, &expr, expression);
411 let fn_ty: Type = data.result_type.clone().into();
412 if fn_ty != res.expr_type {
413 self.add_error(error::StateErrorResult::new(
414 error::StateErrorKind::WrongReturnType,
415 expr.to_string(),
416 expression.location(),
417 ));
418 }
419
420 return_is_called = true;
421 // Check is state contain flag of manual
422 // return from other states, for example:
423 // if-flow, loop-flow
424 if body_state.borrow().manual_return {
425 // First we put expression return calculation for case when
426 // before in the state was return statement. So construct
427 // return expression and jump to return label, set return
428 // label and invoke after that read `return` value from all
429 // previous returns and invoke return instruction itself.
430 body_state
431 .borrow_mut()
432 .expression_function_return_with_label(res);
433 } else {
434 body_state.borrow_mut().expression_function_return(res);
435 }
436 }
437 }
438 }
439 }
440 // Check is function contain return
441 if !return_is_called {
442 self.add_error(error::StateErrorResult::new(
443 error::StateErrorKind::ReturnNotFound,
444 String::new(),
445 data.location(),
446 ));
447 }
448 }
449
450 /// # Let-binding statement
451 /// Analyze let-binding statement:
452 /// 1. Let value bind from expression. First should be analysed
453 /// `expression` for binding value.
454 /// 2. Generate value for current state. Special field `inner_name`
455 /// that used as name for `Codegen` should be unique in current
456 /// state and for all parent states. For that `inner_name` the
457 /// inner value name counter incremented.
458 /// 3. Set `Value` parameters: `inner_name`, type and allocation status
459 /// 4. Insert value to current values state map: value `name` -> `Data`
460 /// 5. Store `inner_name` in current and parent states
461 /// 6. Codegen
462 pub fn let_binding(
463 &mut self,
464 data: &ast::LetBinding<'_, I, E>,
465 function_state: &Rc<RefCell<BlockState<I>>>,
466 ) {
467 // Call value analytics before putting let-value to state
468 let Some(expr_result) = self.expression(&data.value, function_state) else {
469 return;
470 };
471 let let_data: LetBinding = data.clone().into();
472
473 if let Some(ty) = &let_data.value_type {
474 if &expr_result.expr_type != ty {
475 self.add_error(error::StateErrorResult::new(
476 error::StateErrorKind::WrongLetType,
477 let_data.to_string(),
478 data.location(),
479 ));
480 return;
481 }
482 }
483 let let_ty = expr_result.expr_type.clone();
484
485 // Find value in current state and parent states
486 let value = function_state.borrow().get_value_name(&let_data.name);
487 // Calculate `inner_name` as unique for current and all parent states
488 let inner_name = value.map_or_else(
489 || {
490 // if value not found in all states check and set
491 // `inner_value` from value name
492 function_state
493 .borrow()
494 .get_next_inner_name(&let_data.name.clone().into())
495 },
496 |val| {
497 // Increment inner value name counter for shadowed variable
498 // and check variable inner_name for and inner_values in current state
499 function_state.borrow().get_next_inner_name(&val.inner_name)
500 },
501 );
502 // Set value parameters
503 let value = Value {
504 inner_name: inner_name.clone(),
505 inner_type: let_ty,
506 mutable: let_data.mutable,
507 alloca: false,
508 malloc: false,
509 };
510 // Value inserted only to current state by Value name and Value data
511 function_state
512 .borrow_mut()
513 .values
514 .insert(let_data.name, value.clone());
515 // Set `inner_name` to current state and all parent states
516 function_state
517 .borrow_mut()
518 .set_inner_value_name(&inner_name);
519
520 function_state.borrow_mut().let_binding(value, expr_result);
521 }
522
523 /// # Binding statement
524 /// Analyze binding statement for mutable variables:
525 /// 1. Bind from expression. First should be analysed
526 /// `expression` for binding value.
527 /// 2. Read value for current state.
528 /// 3. Update value to current values state map: value `name` -> `Data`
529 /// 4. Codegen with Store action
530 pub fn binding(
531 &mut self,
532 data: &ast::Binding<'_, I, E>,
533 function_state: &Rc<RefCell<BlockState<I>>>,
534 ) {
535 // Call value analytics before putting let-value to state
536 let Some(expr_result) = self.expression(&data.value, function_state) else {
537 return;
538 };
539 let bind_data: Binding = data.clone().into();
540
541 // Find value in current state and parent states
542 let Some(value) = function_state.borrow().get_value_name(&bind_data.name) else {
543 self.add_error(error::StateErrorResult::new(
544 error::StateErrorKind::ValueNotFound,
545 bind_data.to_string(),
546 data.location(),
547 ));
548 return;
549 };
550 // Check is value mutable
551 if !value.mutable {
552 self.add_error(error::StateErrorResult::new(
553 error::StateErrorKind::ValueIsNotMutable,
554 bind_data.to_string(),
555 data.location(),
556 ));
557 return;
558 }
559 function_state.borrow_mut().binding(value, expr_result);
560 }
561
562 /// # Function-call
563 /// Call function with function parameters arguments. Arguments is
564 /// expressions.
565 /// 1. Check is current function name exists in global state of functions
566 /// name.
567 /// 2. Analyse expressions for function parameters
568 /// 3. Inc register
569 /// 4. Generate codegen
570 /// Codegen store always result to register even for void result.
571 ///
572 /// ## Errors
573 /// Return error if function name doesn't exist in global state
574 pub fn function_call(
575 &mut self,
576 data: &ast::FunctionCall<'_, I, E>,
577 body_state: &Rc<RefCell<BlockState<I>>>,
578 ) -> Option<Type> {
579 let func_call_data: FunctionCall = data.clone().into();
580 // Check is function exists in global functions stat
581 let Some(func_data) = self.global.functions.get(&func_call_data.name).cloned() else {
582 self.add_error(error::StateErrorResult::new(
583 error::StateErrorKind::FunctionNotFound,
584 func_call_data.to_string(),
585 data.location(),
586 ));
587 return None;
588 };
589 let fn_type = func_data.inner_type.clone();
590
591 // Analyse function parameters expressions, check their types
592 // and set result to array
593 let mut params: Vec<ExpressionResult> = vec![];
594 for (i, expr) in data.parameters.iter().enumerate() {
595 // Types checked in expression, so we don't need additional check
596 let expr_result = self.expression(expr, body_state)?;
597 if expr_result.expr_type != func_data.parameters[i] {
598 self.add_error(error::StateErrorResult::new(
599 error::StateErrorKind::FunctionParameterTypeWrong,
600 expr_result.expr_type.to_string(),
601 data.location(),
602 ));
603 continue;
604 }
605 params.push(expr_result);
606 }
607
608 // Result of function call is stored to register
609 body_state.borrow_mut().inc_register();
610 let last_register_number = body_state.borrow().last_register_number;
611 // Store always result to register even for void result
612 body_state
613 .borrow_mut()
614 .call(func_data, params, last_register_number);
615 Some(fn_type)
616 }
617
618 /// # condition-expression
619 /// Analyse condition operations.
620 /// ## Return
621 /// Return result register of `condition-expression` calculation.
622 pub fn condition_expression(
623 &mut self,
624 data: &ast::ExpressionLogicCondition<'_, I, E>,
625 function_body_state: &Rc<RefCell<BlockState<I>>>,
626 ) -> u64 {
627 // Analyse left expression of left condition
628 let left_expr = &data.left.left;
629 let left_res = self.expression(left_expr, function_body_state);
630
631 // Analyse right expression of left condition
632 let right_expr = &data.left.right;
633 let right_res = self.expression(right_expr, function_body_state);
634
635 // If some of the `left` or `right` expression is empty just return with error in the state
636 let (Some(left_res), Some(right_res)) = (left_res.clone(), right_res.clone()) else {
637 self.add_error(error::StateErrorResult::new(
638 error::StateErrorKind::ConditionIsEmpty,
639 format!("left={left_res:?}, right={right_res:?}"),
640 data.left.left.location(),
641 ));
642 return function_body_state.borrow().last_register_number;
643 };
644
645 // Currently strict type comparison
646 if left_res.expr_type != right_res.expr_type {
647 self.add_error(error::StateErrorResult::new(
648 error::StateErrorKind::ConditionExpressionWrongType,
649 left_res.expr_type.to_string(),
650 data.left.left.location(),
651 ));
652 return function_body_state.borrow().last_register_number;
653 }
654 if let Type::Primitive(_) = left_res.expr_type {
655 } else {
656 self.add_error(error::StateErrorResult::new(
657 error::StateErrorKind::ConditionExpressionNotSupported,
658 left_res.expr_type.to_string(),
659 data.left.left.location(),
660 ));
661 return function_body_state.borrow().last_register_number;
662 }
663
664 // Increment register
665 function_body_state.borrow_mut().inc_register();
666
667 let register_number = function_body_state.borrow_mut().last_register_number;
668 // Codegen for left condition and set result to register
669 function_body_state.borrow_mut().condition_expression(
670 left_res,
671 right_res,
672 data.left.condition.clone().into(),
673 register_number,
674 );
675
676 // Analyze right condition
677 if let Some(right) = &data.right {
678 let left_register_result = function_body_state.borrow_mut().last_register_number;
679 // Analyse recursively right part of condition
680 let right_register_result = self.condition_expression(&right.1, function_body_state);
681
682 // Increment register
683 function_body_state.borrow_mut().inc_register();
684
685 let register_number = function_body_state.borrow_mut().last_register_number;
686 // Stategen for logical condition for: left [LOGIC-OP] right
687 // The result generated from registers, and stored to
688 // new register
689 function_body_state.borrow_mut().logic_condition(
690 right.0.clone().into(),
691 left_register_result,
692 right_register_result,
693 register_number,
694 );
695 }
696 function_body_state.borrow_mut().last_register_number
697 }
698
699 /// # If-condition body
700 /// Analyze body for ant if condition:
701 /// - if, else, if-else
702 /// NOTE: `label_end` - is always already exists
703 /// ## Return
704 /// Return body statement "return" status
705 pub fn if_condition_body(
706 &mut self,
707 body: &[ast::IfBodyStatement<'_, I, E>],
708 if_body_state: &Rc<RefCell<BlockState<I>>>,
709 label_end: &LabelName,
710 label_loop: Option<(&LabelName, &LabelName)>,
711 ) -> bool {
712 let mut return_is_called = false;
713 for body in body {
714 if return_is_called {
715 self.add_error(error::StateErrorResult::new(
716 error::StateErrorKind::ForbiddenCodeAfterReturnDeprecated,
717 format!("{body:?}"),
718 CodeLocation::new(1, 1),
719 ));
720 }
721 match body {
722 ast::IfBodyStatement::LetBinding(bind) => {
723 self.let_binding(bind, if_body_state);
724 }
725 ast::IfBodyStatement::Binding(bind) => {
726 self.binding(bind, if_body_state);
727 }
728 ast::IfBodyStatement::FunctionCall(fn_call) => {
729 self.function_call(fn_call, if_body_state);
730 }
731 ast::IfBodyStatement::If(if_condition) => {
732 self.if_condition(
733 if_condition,
734 if_body_state,
735 &Some(label_end.clone()),
736 label_loop,
737 );
738 }
739 ast::IfBodyStatement::Loop(loop_statement) => {
740 self.loop_statement(loop_statement, if_body_state);
741 }
742 ast::IfBodyStatement::Return(expression) => {
743 let expr_result = self.expression(expression, if_body_state);
744 if let Some(res) = expr_result {
745 // Jump to return label in codegen and set return
746 // status to indicate function, that it's manual
747 // return
748 if_body_state.borrow_mut().jump_function_return(res);
749 if_body_state.borrow_mut().set_return();
750 return_is_called = true;
751 }
752 }
753 }
754 }
755 return_is_called
756 }
757
758 /// # If-condition loop body
759 /// Analyze body for ant if condition:
760 /// - if, else, if-else
761 /// ## Return
762 /// Return body statement "return" status
763 pub fn if_condition_loop_body(
764 &mut self,
765 body: &[ast::IfLoopBodyStatement<'_, I, E>],
766 if_body_state: &Rc<RefCell<BlockState<I>>>,
767 label_if_end: &LabelName,
768 label_loop_start: &LabelName,
769 label_loop_end: &LabelName,
770 ) -> bool {
771 let mut return_is_called = false;
772 let mut break_is_called = false;
773 let mut continue_is_called = false;
774 for body in body {
775 if return_is_called {
776 self.add_error(error::StateErrorResult::new(
777 error::StateErrorKind::ForbiddenCodeAfterReturnDeprecated,
778 format!("{body:?}"),
779 CodeLocation::new(1, 1),
780 ));
781 }
782 if break_is_called {
783 self.add_error(error::StateErrorResult::new(
784 error::StateErrorKind::ForbiddenCodeAfterBreakDeprecated,
785 format!("{body:?}"),
786 CodeLocation::new(1, 1),
787 ));
788 }
789 if continue_is_called {
790 self.add_error(error::StateErrorResult::new(
791 error::StateErrorKind::ForbiddenCodeAfterContinueDeprecated,
792 format!("{body:?}"),
793 CodeLocation::new(1, 1),
794 ));
795 }
796
797 match body {
798 ast::IfLoopBodyStatement::LetBinding(bind) => {
799 self.let_binding(bind, if_body_state);
800 }
801 ast::IfLoopBodyStatement::Binding(bind) => {
802 self.binding(bind, if_body_state);
803 }
804 ast::IfLoopBodyStatement::FunctionCall(fn_call) => {
805 self.function_call(fn_call, if_body_state);
806 }
807 ast::IfLoopBodyStatement::If(if_condition) => {
808 self.if_condition(
809 if_condition,
810 if_body_state,
811 &Some(label_if_end.clone()),
812 Some((label_loop_start, label_loop_end)),
813 );
814 }
815 ast::IfLoopBodyStatement::Loop(loop_statement) => {
816 self.loop_statement(loop_statement, if_body_state);
817 }
818 ast::IfLoopBodyStatement::Return(expression) => {
819 let expr_result = self.expression(expression, if_body_state);
820 if let Some(res) = expr_result {
821 // Jump to return label in codegen and set return
822 // status to indicate function, that it's manual
823 // return
824 if_body_state.borrow_mut().jump_function_return(res);
825 if_body_state.borrow_mut().set_return();
826 return_is_called = true;
827 }
828 }
829 ast::IfLoopBodyStatement::Continue => {
830 continue_is_called = true;
831 // Skip next loop step and jump to the start
832 // of loop
833 if_body_state.borrow_mut().jump_to(label_loop_start.clone());
834 }
835 ast::IfLoopBodyStatement::Break => {
836 break_is_called = true;
837 // Break loop and jump to the end of loop
838 if_body_state.borrow_mut().jump_to(label_loop_end.clone());
839 }
840 }
841 }
842 return_is_called
843 }
844
845 /// # If conditions calculations
846 /// Calculate conditions for if-condition. It can contain
847 /// simple and logic conditions.
848 pub fn if_condition_calculation(
849 &mut self,
850 condition: &ast::IfCondition<'_, I, E>,
851 if_body_state: &Rc<RefCell<BlockState<I>>>,
852 label_if_begin: &LabelName,
853 label_if_else: &LabelName,
854 label_if_end: &LabelName,
855 is_else: bool,
856 ) {
857 // Analyse if-conditions
858 match condition {
859 // if condition represented just as expression
860 ast::IfCondition::Single(expr) => {
861 // Calculate expression for single if-condition expression
862 let Some(expr_result) = self.expression(expr, if_body_state) else {
863 return;
864 };
865
866 // State for if-condition from expression and if-body start
867 if is_else {
868 if_body_state.borrow_mut().if_condition_expression(
869 expr_result,
870 label_if_begin.clone(),
871 label_if_else.clone(),
872 );
873 } else {
874 if_body_state.borrow_mut().if_condition_expression(
875 expr_result,
876 label_if_begin.clone(),
877 label_if_end.clone(),
878 );
879 }
880 }
881 // If condition contains logic condition expression
882 ast::IfCondition::Logic(expr_logic) => {
883 // Analyse if-condition logic
884 let result_register = self.condition_expression(expr_logic, if_body_state);
885 // State for if-condition-logic with if-body start
886 if is_else {
887 if_body_state.borrow_mut().if_condition_logic(
888 label_if_begin.clone(),
889 label_if_else.clone(),
890 result_register,
891 );
892 } else {
893 if_body_state.borrow_mut().if_condition_logic(
894 label_if_begin.clone(),
895 label_if_end.clone(),
896 result_register,
897 );
898 }
899 }
900 }
901 }
902
903 /// # If-condition
904 /// Analyzing includes all variants for if statements:
905 /// 1. if
906 /// 2. if-else
907 /// 3. if-else-if
908 /// It creates own state, with parent function-state. in that case
909 /// if-state independent from parent state, but csn get access to
910 /// parent state.
911 /// If condition can't contain `else` and `if-else` on the
912 /// same time.
913 ///
914 /// Special case for `label_end` - it should be set from previous
915 /// context, and main goal is to end all of if-condition nodes in
916 /// the same flow with same `if-end` label. It's especially important
917 /// for `else-if` condition.
918 ///
919 /// ## Panics
920 /// `label_loop` is must be set, it's special case for the Loop,
921 /// when `label_loop` should always be set. If it doesn't set, it's
922 /// unexpected behavior and program algorithm error
923 pub fn if_condition(
924 &mut self,
925 data: &ast::IfStatement<'_, I, E>,
926 function_body_state: &Rc<RefCell<BlockState<I>>>,
927 label_end: &Option<LabelName>,
928 label_loop: Option<(&LabelName, &LabelName)>,
929 ) {
930 // It can't contain `else` and `if-else` on the same time
931 if let (Some(_), Some(stm)) = (&data.else_statement, &data.else_if_statement) {
932 self.add_error(error::StateErrorResult::new(
933 error::StateErrorKind::IfElseDuplicated,
934 String::from("if-condition"),
935 stm.location(),
936 ));
937 }
938 // Create state for if-body, from parent function state because
939 // if-state can contain sub-state, that can be independent from parent
940 // state
941 let if_body_state = Rc::new(RefCell::new(BlockState::new(Some(
942 function_body_state.clone(),
943 ))));
944 function_body_state
945 .borrow_mut()
946 .set_child(if_body_state.clone());
947 // Get labels name for if-begin, and if-end
948 let label_if_begin = if_body_state
949 .borrow_mut()
950 .get_and_set_next_label(&"if_begin".to_string().into());
951 let label_if_else = if_body_state
952 .borrow_mut()
953 .get_and_set_next_label(&"if_else".to_string().into());
954 // Set if-end label from previous context
955 let label_if_end = label_end.clone().map_or_else(
956 || {
957 if_body_state
958 .borrow_mut()
959 .get_and_set_next_label(&"if_end".to_string().into())
960 },
961 |label| label,
962 );
963 // To set if-end as single return point check is it previously set
964 let is_set_label_if_end = label_end.is_some();
965 let is_else = data.else_statement.is_some() || data.else_if_statement.is_some();
966
967 // Analyse if-conditions
968 self.if_condition_calculation(
969 &data.condition,
970 &if_body_state,
971 &label_if_begin,
972 &label_if_else,
973 &label_if_end,
974 is_else,
975 );
976
977 //== If condition main body
978 // Set if-begin label
979 if_body_state.borrow_mut().set_label(label_if_begin);
980 // Analyze if-conditions body kind.
981 // Return flag for current body state, excluding children return claims
982 let return_is_called = match &data.body {
983 ast::IfBodyStatements::If(body) => {
984 // Analyze if-statement body
985 self.if_condition_body(body, &if_body_state, &label_if_end, label_loop)
986 }
987 ast::IfBodyStatements::Loop(body) => {
988 // It's special case for the Loop, when `label_loop` should always be set.
989 // If it doesn't set, it's unexpected behavior and program algorithm error
990 let (label_loop_start, label_loop_end) =
991 label_loop.expect("loop label should be set");
992 // Analyze if-loop-statement body
993 self.if_condition_loop_body(
994 body,
995 &if_body_state,
996 &label_if_end,
997 label_loop_start,
998 label_loop_end,
999 )
1000 }
1001 };
1002 // Codegen for jump to if-end statement - return to program flow.
1003 // If return is set do not add jump-to-end label.
1004 if !return_is_called {
1005 if_body_state.borrow_mut().jump_to(label_if_end.clone());
1006 }
1007
1008 // Check else statements: else, else-if
1009 if is_else {
1010 // Set if-else label
1011 if_body_state.borrow_mut().set_label(label_if_else);
1012
1013 // Analyse if-else body: data.else_statement
1014 if let Some(else_body) = &data.else_statement {
1015 // if-else has own state, different from if-state
1016 let if_else_body_state = Rc::new(RefCell::new(BlockState::new(Some(
1017 function_body_state.clone(),
1018 ))));
1019 function_body_state
1020 .borrow_mut()
1021 .set_child(if_else_body_state.clone());
1022
1023 let return_is_called = match else_body {
1024 ast::IfBodyStatements::If(body) => {
1025 // Analyze if-statement body
1026 self.if_condition_body(body, &if_else_body_state, &label_if_end, label_loop)
1027 }
1028 ast::IfBodyStatements::Loop(body) => {
1029 let (label_loop_start, label_loop_end) =
1030 label_loop.expect("label should be set");
1031 // Analyze if-loop-statement body
1032 self.if_condition_loop_body(
1033 body,
1034 &if_else_body_state,
1035 &label_if_end,
1036 label_loop_start,
1037 label_loop_end,
1038 )
1039 }
1040 };
1041
1042 // Codegen for jump to if-end statement -return to program flow
1043 // If return is set do not add jump-to-end label.
1044 if !return_is_called {
1045 if_body_state.borrow_mut().jump_to(label_if_end.clone());
1046 }
1047 } else if let Some(else_if_statement) = &data.else_if_statement {
1048 // Analyse else-if statement
1049 // Set `label_if_end` to indicate single if-end point
1050 self.if_condition(
1051 else_if_statement,
1052 function_body_state,
1053 &Some(label_if_end.clone()),
1054 label_loop,
1055 );
1056 }
1057 }
1058
1059 // End label for all if statement, should be set only once
1060 if !is_set_label_if_end {
1061 if_body_state.borrow_mut().set_label(label_if_end);
1062 }
1063 }
1064
1065 /// # Loop
1066 /// Loop statement contains logic:
1067 /// - jump to loop
1068 /// - loop body
1069 /// - end of loop
1070 /// - return, break, continue
1071 pub fn loop_statement(
1072 &mut self,
1073 data: &[ast::LoopBodyStatement<'_, I, E>],
1074 function_body_state: &Rc<RefCell<BlockState<I>>>,
1075 ) {
1076 // Create state for loop-body, from parent func state because
1077 // loop-state can contain sub-state, that can be independent from parent
1078 // state
1079 let loop_body_state = Rc::new(RefCell::new(BlockState::new(Some(
1080 function_body_state.clone(),
1081 ))));
1082 function_body_state
1083 .borrow_mut()
1084 .set_child(loop_body_state.clone());
1085 // Get labels name for loop-begin, and loop-end
1086 let label_loop_begin = loop_body_state
1087 .borrow_mut()
1088 .get_and_set_next_label(&"loop_begin".to_string().into());
1089
1090 let label_loop_end = loop_body_state
1091 .borrow_mut()
1092 .get_and_set_next_label(&"loop_end".to_string().into());
1093
1094 loop_body_state
1095 .borrow_mut()
1096 .jump_to(label_loop_begin.clone());
1097 loop_body_state
1098 .borrow_mut()
1099 .set_label(label_loop_begin.clone());
1100
1101 let mut return_is_called = false;
1102 let mut break_is_called = false;
1103 let mut continue_is_called = false;
1104 for body in data {
1105 if return_is_called {
1106 self.add_error(error::StateErrorResult::new(
1107 error::StateErrorKind::ForbiddenCodeAfterReturnDeprecated,
1108 format!("{body:?}"),
1109 CodeLocation::new(1, 1),
1110 ));
1111 }
1112 if break_is_called {
1113 self.add_error(error::StateErrorResult::new(
1114 error::StateErrorKind::ForbiddenCodeAfterBreakDeprecated,
1115 format!("{body:?}"),
1116 CodeLocation::new(1, 1),
1117 ));
1118 }
1119 if continue_is_called {
1120 self.add_error(error::StateErrorResult::new(
1121 error::StateErrorKind::ForbiddenCodeAfterContinueDeprecated,
1122 format!("{body:?}"),
1123 CodeLocation::new(1, 1),
1124 ));
1125 }
1126
1127 match body {
1128 ast::LoopBodyStatement::LetBinding(bind) => {
1129 self.let_binding(bind, &loop_body_state);
1130 }
1131 ast::LoopBodyStatement::Binding(bind) => {
1132 self.binding(bind, &loop_body_state);
1133 }
1134 ast::LoopBodyStatement::FunctionCall(fn_call) => {
1135 self.function_call(fn_call, &loop_body_state);
1136 }
1137 ast::LoopBodyStatement::If(if_condition) => self.if_condition(
1138 if_condition,
1139 &loop_body_state,
1140 &None,
1141 Some((&label_loop_begin, &label_loop_end)),
1142 ),
1143 ast::LoopBodyStatement::Loop(loop_statement) => {
1144 self.loop_statement(loop_statement, &loop_body_state);
1145 }
1146 ast::LoopBodyStatement::Return(expression) => {
1147 let expr_result = self.expression(expression, &loop_body_state);
1148 if let Some(res) = expr_result {
1149 // Jump to return label in codegen and set return
1150 // status to indicate function, that it's manual
1151 // return
1152 loop_body_state.borrow_mut().jump_function_return(res);
1153 loop_body_state.borrow_mut().set_return();
1154 return_is_called = true;
1155 }
1156 }
1157 ast::LoopBodyStatement::Break => {
1158 // Break loop and jump to the end of loop
1159 loop_body_state.borrow_mut().jump_to(label_loop_end.clone());
1160 break_is_called = true;
1161 }
1162 ast::LoopBodyStatement::Continue => {
1163 // Skip next loop step and jump to the start
1164 // of loop
1165 loop_body_state
1166 .borrow_mut()
1167 .jump_to(label_loop_begin.clone());
1168 continue_is_called = true;
1169 }
1170 }
1171 }
1172
1173 // If return is called do not set loop-specific instructions
1174 if !return_is_called {
1175 // Because it's loop jump to loop begin
1176 loop_body_state
1177 .borrow_mut()
1178 .jump_to(label_loop_begin.clone());
1179
1180 // Loop ending
1181 loop_body_state.borrow_mut().set_label(label_loop_end);
1182 }
1183 }
1184
1185 #[allow(clippy::doc_markdown)]
1186 /// ## Expression
1187 /// Is basic entity for state operation and state usage.
1188 /// State correctness verified by expressions call.
1189 /// Expressions folded by operations priority. For that
1190 /// expressions tree folded each leaf of tree by priority operation
1191 /// level. The most striking image is bracketing an expression with
1192 /// a higher priority, and build tree based on that.
1193 ///
1194 /// ## Return
1195 /// `PrimitiveValue` | `TmpRegister`
1196 ///
1197 /// Possible algorithm conditions:
1198 /// 1. PrimitiveValue -> PrimitiveValue
1199 /// 2. Value -> load -> TmpRegister
1200 /// 3. FuncCall -> call -> TmpRegister
1201 /// 4. Operations
1202 /// 4.1. PrimitiveValue
1203 /// - PrimitiveValue -> tmp = OP val1, val2 -> TmpRegister
1204 /// - Value -> tmp1 = load -> OP val1, tmp1 -> TmpRegister
1205 /// - FuncCAll -> tmp1 = call -> OP val1, tmp1 -> TmpRegister
1206 /// 4.2. TmpRegister (with name tmp1)
1207 /// - PrimitiveValue -> tmp2 = OP tmp1, val1 -> TmpRegister
1208 /// - Value -> tmp2 = load -> tmp3 = OP tmp1, tmp2 -> TmpRegister
1209 /// - FuncCall -> tmp2 = call -> tmp3 = OP tmp1, tmp2 -> TmpRegister
1210 /// 4.3. Operations -> recursively invoke 4.2.
1211 pub fn expression(
1212 &mut self,
1213 data: &ast::Expression<'_, I, E>,
1214 body_state: &Rc<RefCell<BlockState<I>>>,
1215 ) -> Option<ExpressionResult> {
1216 // Fold expression operations priority
1217 let expr = Self::expression_operations_priority(data.clone());
1218 // To analyze expression first time, we set:
1219 // left_value - as None
1220 // operation - as None
1221 // And basic expression value is `right_value`, because
1222 // it can contain sub-operations (`left_value` don't contain
1223 // and contain Expression result)
1224 self.expression_operation(None, &expr, None, body_state)
1225 }
1226
1227 /// Expression operation semantic logic:
1228 /// `OP(lhs, rhs)`
1229 /// Left-value contains optional Expression result for left side
1230 /// of expression.
1231 #[allow(clippy::too_many_lines)]
1232 pub fn expression_operation(
1233 &mut self,
1234 left_value: Option<&ExpressionResult>,
1235 right_expression: &ast::Expression<'_, I, E>,
1236 op: Option<&ast::ExpressionOperations>,
1237 body_state: &Rc<RefCell<BlockState<I>>>,
1238 ) -> Option<ExpressionResult> {
1239 // Get right side value from expression.
1240 // If expression return error immediately return error
1241 // because next analyzer should use success result.
1242 let right_value = match &right_expression.expression_value {
1243 ast::ExpressionValue::_marker(..) => unreachable!(),
1244 // Check is expression Value entity
1245 ast::ExpressionValue::ValueName(value) => {
1246 // Get value from block state
1247 let value_from_state = body_state.borrow_mut().get_value_name(&value.name().into());
1248 // Register contains result
1249 body_state.borrow_mut().inc_register();
1250 let last_register_number = body_state.borrow().last_register_number;
1251 // First check value in body state
1252 let ty = if let Some(val) = value_from_state {
1253 body_state
1254 .borrow_mut()
1255 .expression_value(val.clone(), last_register_number);
1256 val.inner_type
1257 } else if let Some(const_val) = self.global.constants.get(&value.name().into()) {
1258 body_state
1259 .borrow_mut()
1260 .expression_const(const_val.clone(), last_register_number);
1261 const_val.constant_type.clone()
1262 } else {
1263 // If value doesn't exist in State or as Constant
1264 self.add_error(error::StateErrorResult::new(
1265 error::StateErrorKind::ValueNotFound,
1266 value.name(),
1267 value.location(),
1268 ));
1269 return None;
1270 };
1271 // Return result as register
1272 ExpressionResult {
1273 expr_type: ty,
1274 expr_value: ExpressionResultValue::Register(
1275 body_state.borrow().last_register_number,
1276 ),
1277 }
1278 }
1279 // Check is expression primitive value
1280 ast::ExpressionValue::PrimitiveValue(value) => {
1281 // Just return primitive value itself
1282 ExpressionResult {
1283 expr_type: value.get_type().into(),
1284 expr_value: ExpressionResultValue::PrimitiveValue(value.clone().into()),
1285 }
1286 }
1287 // Check is expression Function call entity
1288 ast::ExpressionValue::FunctionCall(fn_call) => {
1289 // We shouldn't increment register, because it's
1290 // inside `self.function_call`.
1291 // And result of function always stored in register.
1292 let func_call_ty = self.function_call(fn_call, body_state)?;
1293 // Return result as register
1294 body_state.borrow_mut().inc_register();
1295 ExpressionResult {
1296 expr_type: func_call_ty,
1297 expr_value: ExpressionResultValue::Register(
1298 body_state.borrow().last_register_number,
1299 ),
1300 }
1301 }
1302 ast::ExpressionValue::StructValue(value) => {
1303 let struct_value: ExpressionStructValue = value.clone().into();
1304 // Can be only Value from state, not constant
1305 // Get value from block state
1306 let val = body_state
1307 .borrow_mut()
1308 .get_value_name(&struct_value.name)
1309 .or_else(|| {
1310 // If value doesn't exist
1311 self.add_error(error::StateErrorResult::new(
1312 error::StateErrorKind::ValueNotFound,
1313 value.name.name(),
1314 value.name.location(),
1315 ));
1316 None
1317 })?;
1318 // Check is value type is struct
1319 let ty = val.inner_type.get_struct().or_else(|| {
1320 self.add_error(error::StateErrorResult::new(
1321 error::StateErrorKind::ValueNotStruct,
1322 value.name.name(),
1323 value.name.location(),
1324 ));
1325 None
1326 })?;
1327 // Check is type exists
1328 if !self.check_type_exists(&val.inner_type, &value.name.name(), &value.name) {
1329 return None;
1330 }
1331 if &Type::Struct(ty.clone()) != self.global.types.get(&val.inner_type.name())? {
1332 self.add_error(error::StateErrorResult::new(
1333 error::StateErrorKind::WrongExpressionType,
1334 value.name.name(),
1335 value.name.location(),
1336 ));
1337 return None;
1338 }
1339
1340 let attributes = ty
1341 .attributes
1342 .get(&struct_value.attribute)
1343 .or_else(|| {
1344 self.add_error(error::StateErrorResult::new(
1345 error::StateErrorKind::ValueNotStructField,
1346 value.name.name(),
1347 value.name.location(),
1348 ));
1349 None
1350 })?
1351 .clone();
1352
1353 // Register contains result
1354 body_state.borrow_mut().inc_register();
1355 let last_register_number = body_state.borrow().last_register_number;
1356 body_state.borrow_mut().expression_struct_value(
1357 val.clone(),
1358 attributes.attr_index,
1359 last_register_number,
1360 );
1361
1362 body_state.borrow_mut().inc_register();
1363 ExpressionResult {
1364 expr_type: attributes.attr_type,
1365 expr_value: ExpressionResultValue::Register(
1366 body_state.borrow().last_register_number,
1367 ),
1368 }
1369 }
1370 ast::ExpressionValue::Expression(expr) => {
1371 // Subexpression should be analyzed independently
1372 self.expression(expr, body_state)?
1373 }
1374 ast::ExpressionValue::ExtendedExpression(expr) => expr.expression(self, body_state),
1375 };
1376 // Check left expression side and generate expression operation code
1377 let expression_result = if let (Some(left_value), Some(op)) = (left_value, op) {
1378 if left_value.expr_type != right_value.expr_type {
1379 self.add_error(error::StateErrorResult::new(
1380 error::StateErrorKind::WrongExpressionType,
1381 left_value.expr_type.to_string(),
1382 right_expression.location(),
1383 ));
1384 // Do not fetch other expression flow if type is wrong
1385 return None;
1386 }
1387 // Expression operation is set to register
1388 body_state.borrow_mut().inc_register();
1389 let last_register_number = body_state.borrow().last_register_number;
1390 // Call expression operation for: OP(left_value, right_value)
1391 body_state.borrow_mut().expression_operation(
1392 op.clone().into(),
1393 left_value.clone(),
1394 right_value.clone(),
1395 last_register_number,
1396 );
1397 // Expression result value for Operations is always should be "register"
1398 ExpressionResult {
1399 expr_type: right_value.expr_type,
1400 expr_value: ExpressionResultValue::Register(
1401 body_state.borrow().last_register_number,
1402 ),
1403 }
1404 } else {
1405 right_value
1406 };
1407
1408 // Check is for right value contain next operation
1409 if let Some((operation, expr)) = &right_expression.operation {
1410 // Recursively call, where current Execution result set as left
1411 // side expressionf
1412 self.expression_operation(Some(&expression_result), expr, Some(operation), body_state)
1413 } else {
1414 Some(expression_result)
1415 }
1416 }
1417
1418 /// # Expression operation priority
1419 /// Fold expression priority.
1420 /// Pass expressions tree from max priority level to minimum
1421 /// priority level. If expression priority for concrete branch
1422 /// founded, it's folded to leaf (same as bracketing).
1423 ///
1424 /// ## Return
1425 /// New folded expressions tree.
1426 fn expression_operations_priority(
1427 data: ast::Expression<'_, I, E>,
1428 ) -> ast::Expression<'_, I, E> {
1429 let mut data = data;
1430 for priority in (0..=MAX_PRIORITY_LEVEL_FOR_EXPRESSIONS).rev() {
1431 data = Self::fetch_op_priority(data, priority);
1432 }
1433 data
1434 }
1435
1436 /// Fetch expression operation priories and fold it.
1437 /// Expressions folded by operations priority. For that expressions
1438 /// tree folded each branch of tree to leaf by priority operation
1439 /// level. The most striking image is bracketing an expression with
1440 /// a higher priority, and build tree based on that.
1441 ///
1442 /// For example: expr = expr1 OP1 expr2 - it has 2 branches
1443 /// if expr2 contain subbranch (for example: `expr2 OP2 expr3`) we trying
1444 /// to find priority level for current pass. And if `priority_level == OP1`
1445 /// - fold it to leaf.
1446 /// NOTICE: expr1 can't contain subbranches by design. So we pass
1447 /// expression tree from left to right.
1448 /// If priority level not equal, we just return income expression, or
1449 /// if it has subbranch - launch fetching subbranch
1450 fn fetch_op_priority(
1451 data: ast::Expression<'_, I, E>,
1452 priority_level: u8,
1453 ) -> ast::Expression<'_, I, E> {
1454 // Check is expression contains right side with operation
1455 if let Some((op, expr)) = data.clone().operation {
1456 // Check is right expression contain subbranch (sub operation)
1457 if let Some((next_op, next_expr)) = expr.operation.clone() {
1458 // Check incoming expression operation priority level
1459 if op.priority() == priority_level {
1460 // Fold expression to leaf - creating new expression as value
1461 let expression_value =
1462 ast::ExpressionValue::Expression(Box::new(ast::Expression {
1463 expression_value: data.expression_value,
1464 operation: Some((
1465 op,
1466 Box::new(ast::Expression {
1467 expression_value: expr.expression_value,
1468 operation: None,
1469 }),
1470 )),
1471 }));
1472 // Fetch next expression branch
1473 let new_expr = Self::fetch_op_priority(*next_expr, priority_level);
1474 // Create new expression with folded `expression_value`
1475 ast::Expression {
1476 expression_value,
1477 operation: Some((next_op, Box::new(new_expr))),
1478 }
1479 } else {
1480 // If priority not equal for current level just
1481 // fetch right side of expression for next branches
1482 let new_expr =
1483 if next_op.priority() > op.priority() && next_expr.operation.is_none() {
1484 // Pack expression to leaf
1485 ast::Expression {
1486 expression_value: ast::ExpressionValue::Expression(expr),
1487 operation: None,
1488 }
1489 } else {
1490 Self::fetch_op_priority(*expr, priority_level)
1491 };
1492 // Rebuild expression tree
1493 ast::Expression {
1494 expression_value: data.expression_value,
1495 operation: Some((op, Box::new(new_expr))),
1496 }
1497 }
1498 } else {
1499 data
1500 }
1501 } else {
1502 data
1503 }
1504 }
1505}