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 Binding, Constant, ConstantName, Function, FunctionCall, FunctionName, FunctionParameter,
25 FunctionStatement, InnerValueName, LabelName, LetBinding, Value, error,
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 && &expr_result.expr_type != ty
475 {
476 self.add_error(error::StateErrorResult::new(
477 error::StateErrorKind::WrongLetType,
478 let_data.to_string(),
479 data.location(),
480 ));
481 return;
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().unwrap_or_else(|| {
956 if_body_state
957 .borrow_mut()
958 .get_and_set_next_label(&"if_end".to_string().into())
959 });
960 // To set if-end as single return point check is it previously set
961 let is_set_label_if_end = label_end.is_some();
962 let is_else = data.else_statement.is_some() || data.else_if_statement.is_some();
963
964 // Analyse if-conditions
965 self.if_condition_calculation(
966 &data.condition,
967 &if_body_state,
968 &label_if_begin,
969 &label_if_else,
970 &label_if_end,
971 is_else,
972 );
973
974 //== If condition main body
975 // Set if-begin label
976 if_body_state.borrow_mut().set_label(label_if_begin);
977 // Analyze if-conditions body kind.
978 // Return flag for current body state, excluding children return claims
979 let return_is_called = match &data.body {
980 ast::IfBodyStatements::If(body) => {
981 // Analyze if-statement body
982 self.if_condition_body(body, &if_body_state, &label_if_end, label_loop)
983 }
984 ast::IfBodyStatements::Loop(body) => {
985 // It's special case for the Loop, when `label_loop` should always be set.
986 // If it doesn't set, it's unexpected behavior and program algorithm error
987 let (label_loop_start, label_loop_end) =
988 label_loop.expect("loop label should be set");
989 // Analyze if-loop-statement body
990 self.if_condition_loop_body(
991 body,
992 &if_body_state,
993 &label_if_end,
994 label_loop_start,
995 label_loop_end,
996 )
997 }
998 };
999 // Codegen for jump to if-end statement - return to program flow.
1000 // If return is set do not add jump-to-end label.
1001 if !return_is_called {
1002 if_body_state.borrow_mut().jump_to(label_if_end.clone());
1003 }
1004
1005 // Check else statements: else, else-if
1006 if is_else {
1007 // Set if-else label
1008 if_body_state.borrow_mut().set_label(label_if_else);
1009
1010 // Analyse if-else body: data.else_statement
1011 if let Some(else_body) = &data.else_statement {
1012 // if-else has own state, different from if-state
1013 let if_else_body_state = Rc::new(RefCell::new(BlockState::new(Some(
1014 function_body_state.clone(),
1015 ))));
1016 function_body_state
1017 .borrow_mut()
1018 .set_child(if_else_body_state.clone());
1019
1020 let return_is_called = match else_body {
1021 ast::IfBodyStatements::If(body) => {
1022 // Analyze if-statement body
1023 self.if_condition_body(body, &if_else_body_state, &label_if_end, label_loop)
1024 }
1025 ast::IfBodyStatements::Loop(body) => {
1026 let (label_loop_start, label_loop_end) =
1027 label_loop.expect("label should be set");
1028 // Analyze if-loop-statement body
1029 self.if_condition_loop_body(
1030 body,
1031 &if_else_body_state,
1032 &label_if_end,
1033 label_loop_start,
1034 label_loop_end,
1035 )
1036 }
1037 };
1038
1039 // Codegen for jump to if-end statement -return to program flow
1040 // If return is set do not add jump-to-end label.
1041 if !return_is_called {
1042 if_body_state.borrow_mut().jump_to(label_if_end.clone());
1043 }
1044 } else if let Some(else_if_statement) = &data.else_if_statement {
1045 // Analyse else-if statement
1046 // Set `label_if_end` to indicate single if-end point
1047 self.if_condition(
1048 else_if_statement,
1049 function_body_state,
1050 &Some(label_if_end.clone()),
1051 label_loop,
1052 );
1053 }
1054 }
1055
1056 // End label for all if statement, should be set only once
1057 if !is_set_label_if_end {
1058 if_body_state.borrow_mut().set_label(label_if_end);
1059 }
1060 }
1061
1062 /// # Loop
1063 /// Loop statement contains logic:
1064 /// - jump to loop
1065 /// - loop body
1066 /// - end of loop
1067 /// - return, break, continue
1068 pub fn loop_statement(
1069 &mut self,
1070 data: &[ast::LoopBodyStatement<'_, I, E>],
1071 function_body_state: &Rc<RefCell<BlockState<I>>>,
1072 ) {
1073 // Create state for loop-body, from parent func state because
1074 // loop-state can contain sub-state, that can be independent from parent
1075 // state
1076 let loop_body_state = Rc::new(RefCell::new(BlockState::new(Some(
1077 function_body_state.clone(),
1078 ))));
1079 function_body_state
1080 .borrow_mut()
1081 .set_child(loop_body_state.clone());
1082 // Get labels name for loop-begin, and loop-end
1083 let label_loop_begin = loop_body_state
1084 .borrow_mut()
1085 .get_and_set_next_label(&"loop_begin".to_string().into());
1086
1087 let label_loop_end = loop_body_state
1088 .borrow_mut()
1089 .get_and_set_next_label(&"loop_end".to_string().into());
1090
1091 loop_body_state
1092 .borrow_mut()
1093 .jump_to(label_loop_begin.clone());
1094 loop_body_state
1095 .borrow_mut()
1096 .set_label(label_loop_begin.clone());
1097
1098 let mut return_is_called = false;
1099 let mut break_is_called = false;
1100 let mut continue_is_called = false;
1101 for body in data {
1102 if return_is_called {
1103 self.add_error(error::StateErrorResult::new(
1104 error::StateErrorKind::ForbiddenCodeAfterReturnDeprecated,
1105 format!("{body:?}"),
1106 CodeLocation::new(1, 1),
1107 ));
1108 }
1109 if break_is_called {
1110 self.add_error(error::StateErrorResult::new(
1111 error::StateErrorKind::ForbiddenCodeAfterBreakDeprecated,
1112 format!("{body:?}"),
1113 CodeLocation::new(1, 1),
1114 ));
1115 }
1116 if continue_is_called {
1117 self.add_error(error::StateErrorResult::new(
1118 error::StateErrorKind::ForbiddenCodeAfterContinueDeprecated,
1119 format!("{body:?}"),
1120 CodeLocation::new(1, 1),
1121 ));
1122 }
1123
1124 match body {
1125 ast::LoopBodyStatement::LetBinding(bind) => {
1126 self.let_binding(bind, &loop_body_state);
1127 }
1128 ast::LoopBodyStatement::Binding(bind) => {
1129 self.binding(bind, &loop_body_state);
1130 }
1131 ast::LoopBodyStatement::FunctionCall(fn_call) => {
1132 self.function_call(fn_call, &loop_body_state);
1133 }
1134 ast::LoopBodyStatement::If(if_condition) => self.if_condition(
1135 if_condition,
1136 &loop_body_state,
1137 &None,
1138 Some((&label_loop_begin, &label_loop_end)),
1139 ),
1140 ast::LoopBodyStatement::Loop(loop_statement) => {
1141 self.loop_statement(loop_statement, &loop_body_state);
1142 }
1143 ast::LoopBodyStatement::Return(expression) => {
1144 let expr_result = self.expression(expression, &loop_body_state);
1145 if let Some(res) = expr_result {
1146 // Jump to return label in codegen and set return
1147 // status to indicate function, that it's manual
1148 // return
1149 loop_body_state.borrow_mut().jump_function_return(res);
1150 loop_body_state.borrow_mut().set_return();
1151 return_is_called = true;
1152 }
1153 }
1154 ast::LoopBodyStatement::Break => {
1155 // Break loop and jump to the end of loop
1156 loop_body_state.borrow_mut().jump_to(label_loop_end.clone());
1157 break_is_called = true;
1158 }
1159 ast::LoopBodyStatement::Continue => {
1160 // Skip next loop step and jump to the start
1161 // of loop
1162 loop_body_state
1163 .borrow_mut()
1164 .jump_to(label_loop_begin.clone());
1165 continue_is_called = true;
1166 }
1167 }
1168 }
1169
1170 // If return is called do not set loop-specific instructions
1171 if !return_is_called {
1172 // Because it's loop jump to loop begin
1173 loop_body_state
1174 .borrow_mut()
1175 .jump_to(label_loop_begin.clone());
1176
1177 // Loop ending
1178 loop_body_state.borrow_mut().set_label(label_loop_end);
1179 }
1180 }
1181
1182 #[allow(clippy::doc_markdown)]
1183 /// ## Expression
1184 /// Is basic entity for state operation and state usage.
1185 /// State correctness verified by expressions call.
1186 /// Expressions folded by operations priority. For that
1187 /// expressions tree folded each leaf of tree by priority operation
1188 /// level. The most striking image is bracketing an expression with
1189 /// a higher priority, and build tree based on that.
1190 ///
1191 /// ## Return
1192 /// `PrimitiveValue` | `TmpRegister`
1193 ///
1194 /// Possible algorithm conditions:
1195 /// 1. PrimitiveValue -> PrimitiveValue
1196 /// 2. Value -> load -> TmpRegister
1197 /// 3. FuncCall -> call -> TmpRegister
1198 /// 4. Operations
1199 /// 4.1. PrimitiveValue
1200 /// - PrimitiveValue -> tmp = OP val1, val2 -> TmpRegister
1201 /// - Value -> tmp1 = load -> OP val1, tmp1 -> TmpRegister
1202 /// - FuncCAll -> tmp1 = call -> OP val1, tmp1 -> TmpRegister
1203 /// 4.2. TmpRegister (with name tmp1)
1204 /// - PrimitiveValue -> tmp2 = OP tmp1, val1 -> TmpRegister
1205 /// - Value -> tmp2 = load -> tmp3 = OP tmp1, tmp2 -> TmpRegister
1206 /// - FuncCall -> tmp2 = call -> tmp3 = OP tmp1, tmp2 -> TmpRegister
1207 /// 4.3. Operations -> recursively invoke 4.2.
1208 pub fn expression(
1209 &mut self,
1210 data: &ast::Expression<'_, I, E>,
1211 body_state: &Rc<RefCell<BlockState<I>>>,
1212 ) -> Option<ExpressionResult> {
1213 // Fold expression operations priority
1214 let expr = Self::expression_operations_priority(data.clone());
1215 // To analyze expression first time, we set:
1216 // left_value - as None
1217 // operation - as None
1218 // And basic expression value is `right_value`, because
1219 // it can contain sub-operations (`left_value` don't contain
1220 // and contain Expression result)
1221 self.expression_operation(None, &expr, None, body_state)
1222 }
1223
1224 /// Expression operation semantic logic:
1225 /// `OP(lhs, rhs)`
1226 /// Left-value contains optional Expression result for left side
1227 /// of expression.
1228 pub fn expression_operation(
1229 &mut self,
1230 left_value: Option<&ExpressionResult>,
1231 right_expression: &ast::Expression<'_, I, E>,
1232 op: Option<&ast::ExpressionOperations>,
1233 body_state: &Rc<RefCell<BlockState<I>>>,
1234 ) -> Option<ExpressionResult> {
1235 // Get right side value from expression.
1236 // If expression return error immediately return error
1237 // because next analyzer should use success result.
1238 let right_value = match &right_expression.expression_value {
1239 ast::ExpressionValue::_marker(..) => unreachable!(),
1240 // Check is expression Value entity
1241 ast::ExpressionValue::ValueName(value) => {
1242 // Get value from block state
1243 let value_from_state = body_state.borrow_mut().get_value_name(&value.name().into());
1244 // Register contains result
1245 body_state.borrow_mut().inc_register();
1246 let last_register_number = body_state.borrow().last_register_number;
1247 // First check value in body state
1248 let ty = if let Some(val) = value_from_state {
1249 body_state
1250 .borrow_mut()
1251 .expression_value(val.clone(), last_register_number);
1252 val.inner_type
1253 } else if let Some(const_val) = self.global.constants.get(&value.name().into()) {
1254 body_state
1255 .borrow_mut()
1256 .expression_const(const_val.clone(), last_register_number);
1257 const_val.constant_type.clone()
1258 } else {
1259 // If value doesn't exist in State or as Constant
1260 self.add_error(error::StateErrorResult::new(
1261 error::StateErrorKind::ValueNotFound,
1262 value.name(),
1263 value.location(),
1264 ));
1265 return None;
1266 };
1267 // Return result as register
1268 ExpressionResult {
1269 expr_type: ty,
1270 expr_value: ExpressionResultValue::Register(
1271 body_state.borrow().last_register_number,
1272 ),
1273 }
1274 }
1275 // Check is expression primitive value
1276 ast::ExpressionValue::PrimitiveValue(value) => {
1277 // Just return primitive value itself
1278 ExpressionResult {
1279 expr_type: value.get_type().into(),
1280 expr_value: ExpressionResultValue::PrimitiveValue(value.clone().into()),
1281 }
1282 }
1283 // Check is expression Function call entity
1284 ast::ExpressionValue::FunctionCall(fn_call) => {
1285 // We shouldn't increment register, because it's
1286 // inside `self.function_call`.
1287 // And result of function always stored in register.
1288 let func_call_ty = self.function_call(fn_call, body_state)?;
1289 // Return result as register
1290 body_state.borrow_mut().inc_register();
1291 ExpressionResult {
1292 expr_type: func_call_ty,
1293 expr_value: ExpressionResultValue::Register(
1294 body_state.borrow().last_register_number,
1295 ),
1296 }
1297 }
1298 ast::ExpressionValue::StructValue(value) => {
1299 let struct_value: ExpressionStructValue = value.clone().into();
1300 // Can be only Value from state, not constant
1301 // Get value from block state
1302 let val = body_state
1303 .borrow_mut()
1304 .get_value_name(&struct_value.name)
1305 .or_else(|| {
1306 // If value doesn't exist
1307 self.add_error(error::StateErrorResult::new(
1308 error::StateErrorKind::ValueNotFound,
1309 value.name.name(),
1310 value.name.location(),
1311 ));
1312 None
1313 })?;
1314 // Check is value type is struct
1315 let ty = val.inner_type.get_struct().or_else(|| {
1316 self.add_error(error::StateErrorResult::new(
1317 error::StateErrorKind::ValueNotStruct,
1318 value.name.name(),
1319 value.name.location(),
1320 ));
1321 None
1322 })?;
1323 // Check is type exists
1324 if !self.check_type_exists(&val.inner_type, &value.name.name(), &value.name) {
1325 return None;
1326 }
1327 if &Type::Struct(ty.clone()) != self.global.types.get(&val.inner_type.name())? {
1328 self.add_error(error::StateErrorResult::new(
1329 error::StateErrorKind::WrongExpressionType,
1330 value.name.name(),
1331 value.name.location(),
1332 ));
1333 return None;
1334 }
1335
1336 let attributes = ty
1337 .attributes
1338 .get(&struct_value.attribute)
1339 .or_else(|| {
1340 self.add_error(error::StateErrorResult::new(
1341 error::StateErrorKind::ValueNotStructField,
1342 value.name.name(),
1343 value.name.location(),
1344 ));
1345 None
1346 })?
1347 .clone();
1348
1349 // Register contains result
1350 body_state.borrow_mut().inc_register();
1351 let last_register_number = body_state.borrow().last_register_number;
1352 body_state.borrow_mut().expression_struct_value(
1353 val.clone(),
1354 attributes.attr_index,
1355 last_register_number,
1356 );
1357
1358 body_state.borrow_mut().inc_register();
1359 ExpressionResult {
1360 expr_type: attributes.attr_type,
1361 expr_value: ExpressionResultValue::Register(
1362 body_state.borrow().last_register_number,
1363 ),
1364 }
1365 }
1366 ast::ExpressionValue::Expression(expr) => {
1367 // Subexpression should be analyzed independently
1368 self.expression(expr, body_state)?
1369 }
1370 ast::ExpressionValue::ExtendedExpression(expr) => expr.expression(self, body_state),
1371 };
1372 // Check left expression side and generate expression operation code
1373 let expression_result = if let (Some(left_value), Some(op)) = (left_value, op) {
1374 if left_value.expr_type != right_value.expr_type {
1375 self.add_error(error::StateErrorResult::new(
1376 error::StateErrorKind::WrongExpressionType,
1377 left_value.expr_type.to_string(),
1378 right_expression.location(),
1379 ));
1380 // Do not fetch other expression flow if type is wrong
1381 return None;
1382 }
1383 // Expression operation is set to register
1384 body_state.borrow_mut().inc_register();
1385 let last_register_number = body_state.borrow().last_register_number;
1386 // Call expression operation for: OP(left_value, right_value)
1387 body_state.borrow_mut().expression_operation(
1388 op.clone().into(),
1389 left_value.clone(),
1390 right_value.clone(),
1391 last_register_number,
1392 );
1393 // Expression result value for Operations is always should be "register"
1394 ExpressionResult {
1395 expr_type: right_value.expr_type,
1396 expr_value: ExpressionResultValue::Register(
1397 body_state.borrow().last_register_number,
1398 ),
1399 }
1400 } else {
1401 right_value
1402 };
1403
1404 // Check is for right value contain next operation
1405 if let Some((operation, expr)) = &right_expression.operation {
1406 // Recursively call, where current Execution result set as left
1407 // side expressionf
1408 self.expression_operation(Some(&expression_result), expr, Some(operation), body_state)
1409 } else {
1410 Some(expression_result)
1411 }
1412 }
1413
1414 /// # Expression operation priority
1415 /// Fold expression priority.
1416 /// Pass expressions tree from max priority level to minimum
1417 /// priority level. If expression priority for concrete branch
1418 /// founded, it's folded to leaf (same as bracketing).
1419 ///
1420 /// ## Return
1421 /// New folded expressions tree.
1422 fn expression_operations_priority(
1423 data: ast::Expression<'_, I, E>,
1424 ) -> ast::Expression<'_, I, E> {
1425 let mut data = data;
1426 for priority in (0..=MAX_PRIORITY_LEVEL_FOR_EXPRESSIONS).rev() {
1427 data = Self::fetch_op_priority(data, priority);
1428 }
1429 data
1430 }
1431
1432 /// Fetch expression operation priories and fold it.
1433 /// Expressions folded by operations priority. For that expressions
1434 /// tree folded each branch of tree to leaf by priority operation
1435 /// level. The most striking image is bracketing an expression with
1436 /// a higher priority, and build tree based on that.
1437 ///
1438 /// For example: expr = expr1 OP1 expr2 - it has 2 branches
1439 /// if expr2 contain subbranch (for example: `expr2 OP2 expr3`) we trying
1440 /// to find priority level for current pass. And if `priority_level == OP1`
1441 /// - fold it to leaf.
1442 /// NOTICE: expr1 can't contain subbranches by design. So we pass
1443 /// expression tree from left to right.
1444 /// If priority level not equal, we just return income expression, or
1445 /// if it has subbranch - launch fetching subbranch
1446 fn fetch_op_priority(
1447 data: ast::Expression<'_, I, E>,
1448 priority_level: u8,
1449 ) -> ast::Expression<'_, I, E> {
1450 // Check is expression contains right side with operation
1451 if let Some((op, expr)) = data.clone().operation {
1452 // Check is right expression contain subbranch (sub operation)
1453 if let Some((next_op, next_expr)) = expr.operation.clone() {
1454 // Check incoming expression operation priority level
1455 if op.priority() == priority_level {
1456 // Fold expression to leaf - creating new expression as value
1457 let expression_value =
1458 ast::ExpressionValue::Expression(Box::new(ast::Expression {
1459 expression_value: data.expression_value,
1460 operation: Some((
1461 op,
1462 Box::new(ast::Expression {
1463 expression_value: expr.expression_value,
1464 operation: None,
1465 }),
1466 )),
1467 }));
1468 // Fetch next expression branch
1469 let new_expr = Self::fetch_op_priority(*next_expr, priority_level);
1470 // Create new expression with folded `expression_value`
1471 ast::Expression {
1472 expression_value,
1473 operation: Some((next_op, Box::new(new_expr))),
1474 }
1475 } else {
1476 // If priority not equal for current level just
1477 // fetch right side of expression for next branches
1478 let new_expr =
1479 if next_op.priority() > op.priority() && next_expr.operation.is_none() {
1480 // Pack expression to leaf
1481 ast::Expression {
1482 expression_value: ast::ExpressionValue::Expression(expr),
1483 operation: None,
1484 }
1485 } else {
1486 Self::fetch_op_priority(*expr, priority_level)
1487 };
1488 // Rebuild expression tree
1489 ast::Expression {
1490 expression_value: data.expression_value,
1491 operation: Some((op, Box::new(new_expr))),
1492 }
1493 }
1494 } else {
1495 data
1496 }
1497 } else {
1498 data
1499 }
1500 }
1501}