semantic_analyzer/types/
semantic.rs

1//! # Semantic types
2//! Semantic analyzer result state types.
3//! It contains `SemanticStack` as Semantic results Context data.
4
5use super::condition::{Condition, LogicCondition};
6use super::expression::{ExpressionOperations, ExpressionResult};
7use super::types::StructTypes;
8use super::{Constant, Function, FunctionParameter, FunctionStatement, LabelName, Value};
9use crate::semantic::State;
10use crate::types::block_state::BlockState;
11#[cfg(feature = "codec")]
12use serde::{Deserialize, Serialize};
13use std::cell::RefCell;
14use std::fmt::Debug;
15use std::rc::Rc;
16
17/// Semantic Context trait contain instructions set functions
18/// for Global Stack context. It includes:
19/// - functions
20/// - types
21/// - constants
22pub trait GlobalSemanticContext {
23    fn function_declaration(&mut self, fn_decl: FunctionStatement);
24    fn constant(&mut self, const_decl: Constant);
25    fn types(&mut self, type_decl: StructTypes);
26}
27
28/// Semantic Context trait contain instructions set functions
29/// for the Stack context.
30pub trait SemanticContext {
31    fn expression_value(&mut self, expression: Value, register_number: u64);
32    fn expression_const(&mut self, expression: Constant, register_number: u64);
33    fn expression_struct_value(&mut self, expression: Value, index: u32, register_number: u64);
34    fn expression_operation(
35        &mut self,
36        operation: ExpressionOperations,
37        left_value: ExpressionResult,
38        right_value: ExpressionResult,
39        register_number: u64,
40    );
41    fn call(&mut self, call: Function, params: Vec<ExpressionResult>, register_number: u64);
42    fn let_binding(&mut self, let_decl: Value, expr_result: ExpressionResult);
43    fn binding(&mut self, val: Value, expr_result: ExpressionResult);
44    fn expression_function_return(&mut self, expr_result: ExpressionResult);
45    fn expression_function_return_with_label(&mut self, expr_result: ExpressionResult);
46    fn set_label(&mut self, label: LabelName);
47    fn jump_to(&mut self, label: LabelName);
48    fn if_condition_expression(
49        &mut self,
50        expr_result: ExpressionResult,
51        label_if_begin: LabelName,
52        label_if_end: LabelName,
53    );
54    fn condition_expression(
55        &mut self,
56        left_result: ExpressionResult,
57        right_result: ExpressionResult,
58        condition: Condition,
59        register_number: u64,
60    );
61    fn jump_function_return(&mut self, expr_result: ExpressionResult);
62    fn logic_condition(
63        &mut self,
64        logic_condition: LogicCondition,
65        left_register_result: u64,
66        right_register_result: u64,
67        register_number: u64,
68    );
69    fn if_condition_logic(
70        &mut self,
71        label_if_begin: LabelName,
72        label_if_end: LabelName,
73        result_register: u64,
74    );
75    fn function_arg(&mut self, value: Value, func_arg: FunctionParameter);
76}
77
78/// Extended Semantic Context trait contain instructions set functions
79/// for the Extended Stack context.
80pub trait ExtendedSemanticContext<I: SemanticContextInstruction> {
81    fn extended_expression(&mut self, expr: &I);
82}
83
84/// Semantic Context trait contains custom instruction implementation
85/// to flexibly extend context instructions. It represents ivs derided
86/// traits: `Debug` and `Serialize` + `Deserialize`
87pub trait SemanticContextInstruction: Debug + Clone + PartialEq {}
88
89/// Extended Expression for semantic analyzer.
90pub trait ExtendedExpression<I: SemanticContextInstruction>: Debug + Clone + PartialEq {
91    /// Custom expression. Ast should be received from `GetAst` trait.
92    fn expression(
93        &self,
94        state: &mut State<Self, I>,
95        block_state: &Rc<RefCell<BlockState<I>>>,
96    ) -> ExpressionResult;
97}
98
99/// # Semantic stack
100/// Semantic stack represent stack of Semantic Context results
101#[derive(Debug, Clone, PartialEq)]
102#[cfg_attr(feature = "codec", derive(Serialize, Deserialize))]
103pub struct SemanticStack<I: SemanticContextInstruction>(Vec<SemanticStackContext<I>>);
104
105impl<I: SemanticContextInstruction> Default for SemanticStack<I> {
106    fn default() -> Self {
107        Self::new()
108    }
109}
110
111impl<I: SemanticContextInstruction> SemanticStack<I> {
112    /// Init Semantic stack
113    #[must_use]
114    pub const fn new() -> Self {
115        Self(vec![])
116    }
117
118    /// Push Context data to the stack
119    pub fn push(&mut self, value: SemanticStackContext<I>) {
120        self.0.push(value);
121    }
122
123    /// Get all context stack data as array data
124    #[must_use]
125    pub fn get(self) -> Vec<SemanticStackContext<I>> {
126        self.0
127    }
128}
129
130impl<I: SemanticContextInstruction> GlobalSemanticContext for SemanticStack<I> {
131    /// Push Context to the stack as function declaration data.
132    /// Function declaration instruction.
133    ///
134    /// ## Parameters
135    /// - `fn_decl` - function declaration parameters
136    fn function_declaration(&mut self, fn_decl: FunctionStatement) {
137        self.push(SemanticStackContext::FunctionDeclaration { fn_decl });
138    }
139
140    /// Push Context to the stack as constant data.
141    /// Constant declaration instruction.
142    ///
143    /// ## Parameters
144    /// - `const_decl` - constant declaration parameters
145    fn constant(&mut self, const_decl: Constant) {
146        self.push(SemanticStackContext::Constant { const_decl });
147    }
148
149    /// Push Context to the stack as types data.
150    /// Types declaration instruction.
151    ///
152    /// ## Parameters
153    /// - `type_decl` - type declaration parameters
154    fn types(&mut self, type_decl: StructTypes) {
155        self.push(SemanticStackContext::Types { type_decl });
156    }
157}
158
159impl<I: SemanticContextInstruction> SemanticContext for SemanticStack<I> {
160    /// Push Context to the stack as expression value data.
161    ///
162    /// ## Parameters
163    /// - `expression` - contains expression value
164    /// - `register_number` - register to store result data
165    fn expression_value(&mut self, expression: Value, register_number: u64) {
166        self.push(SemanticStackContext::ExpressionValue {
167            expression,
168            register_number,
169        });
170    }
171
172    /// Push Context to the stack as expression const data.
173    ///
174    /// ## Parameters
175    /// - `expression` - contains expression constant
176    /// - `register_number` - register to store result data
177    fn expression_const(&mut self, expression: Constant, register_number: u64) {
178        self.push(SemanticStackContext::ExpressionConst {
179            expression,
180            register_number,
181        });
182    }
183
184    /// Push Context to the stack as expression struct value data.
185    ///
186    /// ## Parameters
187    /// - `expression` - contains expression value for specific `Structure` attribute
188    /// - `index` - represent attribute index in the `Structure` type
189    /// - `register_number` - register to store result data
190    fn expression_struct_value(&mut self, expression: Value, index: u32, register_number: u64) {
191        self.push(SemanticStackContext::ExpressionStructValue {
192            expression,
193            index,
194            register_number,
195        });
196    }
197
198    /// Push Context to the stack as expression operation data.
199    /// `expression_operation` imply operation between `left_value` and
200    /// `right_value` and store result to `register_number`.
201    ///
202    /// ## Parameters
203    /// - `operation` - specific operation
204    /// - `left_value` - left expression result
205    /// - `right_value` - right expression result
206    /// - `register_number` - register to store result of expression operation
207    fn expression_operation(
208        &mut self,
209        operation: ExpressionOperations,
210        left_value: ExpressionResult,
211        right_value: ExpressionResult,
212        register_number: u64,
213    ) {
214        self.push(SemanticStackContext::ExpressionOperation {
215            operation,
216            left_value,
217            right_value,
218            register_number,
219        });
220    }
221
222    /// Push Context to the stack as function call data.
223    /// Function call instruction with parameters and result data.
224    ///
225    /// ## Parameters
226    /// - `call` - function declaration data
227    /// - `params` - function parameters
228    ///  - `register_number` - register to store result of function call
229    fn call(&mut self, call: Function, params: Vec<ExpressionResult>, register_number: u64) {
230        self.push(SemanticStackContext::Call {
231            call,
232            params,
233            register_number,
234        });
235    }
236
237    /// Push Context to the stack as let-binding data.
238    /// Let binding instruction that "bind" expression result to
239    /// the new value.
240    ///
241    /// ## Parameters
242    /// - `let_decl` - value declaration
243    /// -  `expr_result` - expression result that will be bind to the value
244    fn let_binding(&mut self, let_decl: Value, expr_result: ExpressionResult) {
245        self.push(SemanticStackContext::LetBinding {
246            let_decl,
247            expr_result,
248        });
249    }
250
251    /// Push Context to the stack as binding data.
252    /// Binding instruction that "bind" expression result to
253    /// the old. previously init value.
254    ///
255    /// ## Parameters
256    /// - `val` - value declaration
257    /// -  `expr_result` - expression result that will be bind to the value
258    fn binding(&mut self, val: Value, expr_result: ExpressionResult) {
259        self.push(SemanticStackContext::Binding { val, expr_result });
260    }
261
262    /// Push Context to the stack as expression function return data.
263    /// Return instruction, should be used in the end of functions.
264    /// Alwats should be only once.
265    ///
266    /// ## Parameters
267    /// - `expr_result` - result data for the return
268    fn expression_function_return(&mut self, expr_result: ExpressionResult) {
269        self.push(SemanticStackContext::ExpressionFunctionReturn { expr_result });
270    }
271
272    /// Push Context to the stack as `expression function return with label` data.
273    /// Return instruction with additional logic. Most useful case when
274    /// `return` previously was call from `if-body` or `loop-body.`.
275    /// As additional behavior this `expression_function_return_with_label` should
276    /// set `return` label. It will allow `jump-to-return` case. Also
277    /// before `return` label Codegen, for normal instruction flow, must
278    /// jump to `return` label anyway.
279    ///
280    /// ## Parameters
281    /// - `expr_result` - result data for the return
282    fn expression_function_return_with_label(&mut self, expr_result: ExpressionResult) {
283        self.push(SemanticStackContext::ExpressionFunctionReturnWithLabel { expr_result });
284    }
285
286    /// Push Context to the stack as `set label` data.
287    /// Set label. Useful for any kind of jump operations and conditional flow.
288    ///
289    /// ## Parameters
290    /// - `label` - label name
291    fn set_label(&mut self, label: LabelName) {
292        self.push(SemanticStackContext::SetLabel { label });
293    }
294
295    /// Push Context to the stack as `jump to` data.
296    /// Unconditional direct jump to label.
297    ///
298    /// ## Parameters
299    /// - `label` - label for the jump
300    fn jump_to(&mut self, label: LabelName) {
301        self.push(SemanticStackContext::JumpTo { label });
302    }
303
304    /// Push Context to the stack as `if condition expression` data.
305    /// `if-condition expression` represent if-condition, when if expression
306    /// is "true" jump to `label_if_begin` else `label_if_end`.
307    ///
308    /// ## Parameters
309    /// - `expr_result` - expression result of `if-condition` for
310    /// conditional instruction
311    /// - `label_if_begin` - label for jump if expression is "true"
312    /// - `label_if_end` - label for jump if expression is "false"
313    fn if_condition_expression(
314        &mut self,
315        expr_result: ExpressionResult,
316        label_if_begin: LabelName,
317        label_if_end: LabelName,
318    ) {
319        self.push(SemanticStackContext::IfConditionExpression {
320            expr_result,
321            label_if_begin,
322            label_if_end,
323        });
324    }
325
326    /// Push Context to the stack as `condition expression` data.
327    /// Condition expression between left and right condition calculation.
328    ///
329    /// ## Parameters
330    /// - `left_result` - left expression result
331    /// - `right_result` - right expression result
332    /// - `condition` - condition operation
333    /// - `register_number` - register to store result of expression operation
334    fn condition_expression(
335        &mut self,
336        left_result: ExpressionResult,
337        right_result: ExpressionResult,
338        condition: Condition,
339        register_number: u64,
340    ) {
341        self.push(SemanticStackContext::ConditionExpression {
342            left_result,
343            right_result,
344            condition,
345            register_number,
346        });
347    }
348
349    /// Push Context to the stack as `jump function return` data.
350    /// Jump to function return with expression result data. Label for jumping
351    /// to return position (always end of function) should be always the same
352    /// and should be managed by Codegen.
353    ///
354    /// ## Parameters
355    /// - `expr_result` - expression result for return condition
356    fn jump_function_return(&mut self, expr_result: ExpressionResult) {
357        self.push(SemanticStackContext::JumpFunctionReturn { expr_result });
358    }
359
360    /// Push Context to the stack as `logic condition` data.
361    /// Operate with registers: left and right for specific logic condition.
362    /// Result of calculation stored to `register_number`.
363    ///
364    /// ## Parameters
365    /// - `left_register_result` - result of left condition
366    /// - `right_register_result` - result of right condition
367    /// - `register_number` - register to store instruction result
368    fn logic_condition(
369        &mut self,
370        logic_condition: LogicCondition,
371        left_register_result: u64,
372        right_register_result: u64,
373        register_number: u64,
374    ) {
375        self.push(SemanticStackContext::LogicCondition {
376            logic_condition,
377            left_register_result,
378            right_register_result,
379            register_number,
380        });
381    }
382
383    /// Push Context to the stack as `if condition logic` data.
384    /// `if_condition_logic` instruction read data from `result_register`
385    /// and conditionally jump: if "true' to `label_if_begin` or
386    /// `label_if_end` if "false" (data contained as result after
387    /// reading `result_register`).
388    ///
389    /// ## Parameters
390    /// - `label_if_begin` - label for a jump if `result_register` contains
391    /// result with "true"
392    /// - `label_if_end` - label for a jump if `result_register` contains
393    ///  result with "false". It can be not only `if_end` but any kind (for
394    /// example `if_else`)
395    /// - `result_register` - contains register of previous condition logic
396    /// calculations.
397    fn if_condition_logic(
398        &mut self,
399        label_if_begin: LabelName,
400        label_if_end: LabelName,
401        result_register: u64,
402    ) {
403        self.push(SemanticStackContext::IfConditionLogic {
404            label_if_begin,
405            label_if_end,
406            result_register,
407        });
408    }
409
410    /// Push Context to the stack as `function argument` data.
411    /// This instruction should allocate pointer (if argument type is
412    /// not Ptr) and store argument value to the pointer.
413    ///
414    /// ## Parameters
415    /// - `func_arg` - function parameter data
416    fn function_arg(&mut self, value: Value, func_arg: FunctionParameter) {
417        self.push(SemanticStackContext::FunctionArg { value, func_arg });
418    }
419}
420
421impl<I: SemanticContextInstruction> ExtendedSemanticContext<I> for SemanticStack<I> {
422    /// Extended Expression instruction.
423    /// AS argument trait, that contains instruction method that returns
424    /// instruction parameters.
425    fn extended_expression(&mut self, expr: &I) {
426        self.push(SemanticStackContext::ExtendedExpression(Box::new(
427            expr.clone(),
428        )));
429    }
430}
431
432/// # Semantic stack Context
433/// Context data of Semantic results. Contains type declarations
434/// for specific instructions.
435#[derive(Debug, Clone, PartialEq)]
436#[cfg_attr(
437    feature = "codec",
438    derive(Serialize, Deserialize),
439    serde(tag = "type", content = "content")
440)]
441pub enum SemanticStackContext<I: SemanticContextInstruction> {
442    ExpressionValue {
443        expression: Value,
444        register_number: u64,
445    },
446    ExpressionConst {
447        expression: Constant,
448        register_number: u64,
449    },
450    ExpressionStructValue {
451        expression: Value,
452        index: u32,
453        register_number: u64,
454    },
455    ExpressionOperation {
456        operation: ExpressionOperations,
457        left_value: ExpressionResult,
458        right_value: ExpressionResult,
459        register_number: u64,
460    },
461    Call {
462        call: Function,
463        params: Vec<ExpressionResult>,
464        register_number: u64,
465    },
466    LetBinding {
467        let_decl: Value,
468        expr_result: ExpressionResult,
469    },
470    Binding {
471        val: Value,
472        expr_result: ExpressionResult,
473    },
474    FunctionDeclaration {
475        fn_decl: FunctionStatement,
476    },
477    Constant {
478        const_decl: Constant,
479    },
480    Types {
481        type_decl: StructTypes,
482    },
483    ExpressionFunctionReturn {
484        expr_result: ExpressionResult,
485    },
486    ExpressionFunctionReturnWithLabel {
487        expr_result: ExpressionResult,
488    },
489    SetLabel {
490        label: LabelName,
491    },
492    JumpTo {
493        label: LabelName,
494    },
495    IfConditionExpression {
496        expr_result: ExpressionResult,
497        label_if_begin: LabelName,
498        label_if_end: LabelName,
499    },
500    ConditionExpression {
501        left_result: ExpressionResult,
502        right_result: ExpressionResult,
503        condition: Condition,
504        register_number: u64,
505    },
506    JumpFunctionReturn {
507        expr_result: ExpressionResult,
508    },
509    LogicCondition {
510        logic_condition: LogicCondition,
511        left_register_result: u64,
512        right_register_result: u64,
513        register_number: u64,
514    },
515    IfConditionLogic {
516        label_if_begin: LabelName,
517        label_if_end: LabelName,
518        result_register: u64,
519    },
520    FunctionArg {
521        value: Value,
522        func_arg: FunctionParameter,
523    },
524    ExtendedExpression(Box<I>),
525}