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}