diff --git a/src/ast.rs b/src/ast.rs index 1beafdb..a2d5b0e 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -214,23 +214,23 @@ pub enum PrimitiveValue { } impl PrimitiveValue { - pub const fn get_type(&self) -> PrimitiveTypes { + pub const fn get_type(&self) -> Type<'a> { match self { - Self::U8(_) => PrimitiveTypes::U8, - Self::U16(_) => PrimitiveTypes::U16, - Self::U32(_) => PrimitiveTypes::U32, - Self::U64(_) => PrimitiveTypes::U64, - Self::I8(_) => PrimitiveTypes::I8, - Self::I16(_) => PrimitiveTypes::I16, - Self::I32(_) => PrimitiveTypes::I32, - Self::I64(_) => PrimitiveTypes::I64, - Self::F32(_) => PrimitiveTypes::F32, - Self::F64(_) => PrimitiveTypes::F64, - Self::Char(_) => PrimitiveTypes::Char, - Self::Bool(_) => PrimitiveTypes::Bool, - Self::String(_) => PrimitiveTypes::String, - Self::Ptr => PrimitiveTypes::Ptr, - Self::None => PrimitiveTypes::None, + Self::U8(_) => Type::Primitive(PrimitiveTypes::U8), + Self::U16(_) => Type::Primitive(PrimitiveTypes::U16), + Self::U32(_) => Type::Primitive(PrimitiveTypes::U32), + Self::U64(_) => Type::Primitive(PrimitiveTypes::U64), + Self::I8(_) => Type::Primitive(PrimitiveTypes::I8), + Self::I16(_) => Type::Primitive(PrimitiveTypes::I16), + Self::I32(_) => Type::Primitive(PrimitiveTypes::I32), + Self::I64(_) => Type::Primitive(PrimitiveTypes::I64), + Self::F32(_) => Type::Primitive(PrimitiveTypes::F32), + Self::F64(_) => Type::Primitive(PrimitiveTypes::F64), + Self::Char(_) => Type::Primitive(PrimitiveTypes::Char), + Self::Bool(_) => Type::Primitive(PrimitiveTypes::Bool), + Self::String(_) => Type::Primitive(PrimitiveTypes::String), + Self::Ptr => Type::Primitive(PrimitiveTypes::Ptr), + Self::None => Type::Primitive(PrimitiveTypes::None), } } } diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 6691ca1..9d5e72d 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -145,17 +145,17 @@ impl<'a, 'ctx> Codegen for Compiler<'a, 'ctx> { todo!() } - fn let_binding(&mut self, _let_decl: &Value, _expr_result: &ExpressionResult) { + fn let_binding(&mut self, _let_decl: &Value, _expr_result: &ExpressionResult<'a>) { todo!() } - fn binding(&mut self, _val: &Value, _expr_result: &ExpressionResult) { + fn binding(&mut self, _val: &Value, _expr_result: &ExpressionResult<'a>) { todo!() } fn call( &self, _call: &ast::FunctionCall<'_>, - _params: Vec, + _params: Vec>, _register_number: u64, ) { todo!() @@ -172,25 +172,25 @@ impl<'a, 'ctx> Codegen for Compiler<'a, 'ctx> { fn expression_operation( &self, _operation: &ast::ExpressionOperations, - _left_value: &ExpressionResult, - _right_value: &ExpressionResult, + _left_value: &ExpressionResult<'a>, + _right_value: &ExpressionResult<'a>, _register_number: u64, ) { todo!() } - fn expression_function_return(&self, _expr_result: &ExpressionResult) { + fn expression_function_return(&self, _expr_result: &ExpressionResult<'a>) { todo!() } - fn jump_function_return(&self, _expr_result: &ExpressionResult) { + fn jump_function_return(&self, _expr_result: &ExpressionResult<'a>) { todo!() } - fn expression_function_return_with_label(&self, _expr_result: &ExpressionResult) { + fn expression_function_return_with_label(&self, _expr_result: &ExpressionResult<'a>) { todo!() } fn if_condition_expression( &mut self, - _expr_result: &ExpressionResult, + _expr_result: &ExpressionResult<'a>, _label_if_begin: &LabelName, _label_if_end: &LabelName, ) { @@ -212,8 +212,8 @@ impl<'a, 'ctx> Codegen for Compiler<'a, 'ctx> { } fn condition_expression( &mut self, - _left_result: &ExpressionResult, - _right_result: &ExpressionResult, + _left_result: &ExpressionResult<'a>, + _right_result: &ExpressionResult<'a>, _condition: &Condition, _register_number: u64, ) { diff --git a/src/codegen.rs b/src/codegen.rs index d03bab6..ee2d458 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -8,12 +8,12 @@ pub trait Codegen { fn constant(&self, const_decl: &ast::Constant<'_>); fn types(&self, type_decl: &ast::StructTypes<'_>); fn function_statement(&mut self, fn_decl: &ast::FunctionStatement<'_>); - fn let_binding(&mut self, let_decl: &Value, expr_result: &ExpressionResult); - fn binding(&mut self, val: &Value, expr_result: &ExpressionResult); + fn let_binding(&mut self, let_decl: &Value, expr_result: &ExpressionResult<'_>); + fn binding(&mut self, val: &Value, expr_result: &ExpressionResult<'_>); fn call( &self, call: &ast::FunctionCall<'_>, - params: Vec, + params: Vec>, register_number: u64, ); fn expression_value(&mut self, expression: &Value, register_number: u64); @@ -21,18 +21,18 @@ pub trait Codegen { fn expression_operation( &self, operation: &ast::ExpressionOperations, - left_value: &ExpressionResult, - right_value: &ExpressionResult, + left_value: &ExpressionResult<'_>, + right_value: &ExpressionResult<'_>, register_number: u64, ); - fn expression_function_return(&self, expr_result: &ExpressionResult); - fn jump_function_return(&self, expr_result: &ExpressionResult); + fn expression_function_return(&self, expr_result: &ExpressionResult<'_>); + fn jump_function_return(&self, expr_result: &ExpressionResult<'_>); fn set_label(&self, label: &LabelName); - fn expression_function_return_with_label(&self, expr_result: &ExpressionResult); + fn expression_function_return_with_label(&self, expr_result: &ExpressionResult<'_>); fn condition_expression( &mut self, - left_result: &ExpressionResult, - right_result: &ExpressionResult, + left_result: &ExpressionResult<'_>, + right_result: &ExpressionResult<'_>, condition: &Condition, register_number: u64, ); @@ -45,7 +45,7 @@ pub trait Codegen { ); fn if_condition_expression( &mut self, - expr_result: &ExpressionResult, + expr_result: &ExpressionResult<'_>, label_if_begin: &LabelName, label_if_end: &LabelName, ); diff --git a/src/semantic.rs b/src/semantic.rs index dc946db..b77736c 100644 --- a/src/semantic.rs +++ b/src/semantic.rs @@ -11,8 +11,9 @@ //! //! Codegen is result of Semantic analyzer and contains prepared data tree //! of generated code for next step - compilation generated raw program code. -use crate::ast::{self, ExpressionOperations, GetName, PrimitiveValue}; +use crate::ast::{self, GetName}; use crate::codegen::Codegen; +use crate::semantic::error::StateErrorResult; use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::rc::Rc; @@ -344,20 +345,32 @@ pub struct GlobalState { /// # State /// Basic entity that contains `Global State` /// and `Codegen` tree. +/// - errors - State analyzing errors #[derive(Debug)] pub struct State { pub global: GlobalState, pub codegen: T, + pub errors: Vec, } -/// # Expression Result -/// Result of expression analyze has to kind: +/// # Expression result +/// Contains analyzing results of expression: +/// - expr_type - result type of expression +/// - expr_value - result value of expression +#[derive(Debug, Clone)] +pub struct ExpressionResult<'a> { + pub expr_type: ast::Type<'a>, + pub expr_value: ExpressionResultValue, +} + +/// # Expression Result Value +/// Result value of expression analyze has to kind: /// - Primitive value /// - Register that contain result of expression /// evaluation or call. -#[derive(Debug)] -pub enum ExpressionResult { - PrimitiveValue(PrimitiveValue), +#[derive(Debug, Clone)] +pub enum ExpressionResultValue { + PrimitiveValue(ast::PrimitiveValue), Register(u64), } @@ -371,9 +384,14 @@ impl> State { constants: HashMap::new(), }, codegen, + errors: Vec::new(), } } + fn add_error(&mut self, err: StateErrorResult) { + self.errors.push(err); + } + /// Run semantic analyzer that covers all flow pub fn run(&mut self, data: &ast::Main<'_>) -> StateResults<()> { // Execute each kind of analyzing and return errors data. @@ -696,7 +714,7 @@ impl> State { )); } // Analyse function parameters expressions and set result to array - let mut params: Vec = vec![]; + let mut params: Vec> = vec![]; for expr in &data.parameters { params.push(self.expression(expr, body_state)?); } @@ -1187,7 +1205,7 @@ impl> State { &mut self, data: &ast::Expression<'_>, body_state: &Rc>, - ) -> StateResult { + ) -> ExpressionResult<'_> { // To analyze expression first time, we set: // left_value - as None // operation - as None @@ -1199,14 +1217,18 @@ impl> State { /// Expression operation semantic logic: /// `OP(lhs, rhs)` + /// Left-value contains optional Exrpression result for left side + /// of expression. pub fn expression_operation( &mut self, - left_value: Option<&ExpressionResult>, + left_value: Option<&ExpressionResult<'_>>, right_expression: &ast::Expression<'_>, - op: Option<&ExpressionOperations>, + op: Option<&ast::ExpressionOperations>, body_state: &Rc>, - ) -> StateResult { - // Get right value from expression. + ) -> ExpressionResult<'_> { + let y = x; + let z = y + 1; + // Get right side value from expression. // If expression return error immediately return error // because next analyzer should use success result. let right_value = match &right_expression.expression_value { @@ -1221,34 +1243,43 @@ impl> State { // Increase register counter before loading value body_state.borrow_mut().inc_register(); // First check value in body state - if let Some(val) = value_from_state { + let ty = if let Some(val) = value_from_state { // If it's value then Load it to register self.codegen .expression_value(&val, body_state.borrow().last_register_number); + &val.inner_type } else if let Some(const_val) = self.global.constants.get(&value.name().into()) { // If value is constant load it to register self.codegen .expression_const(const_val, body_state.borrow().last_register_number); - } + &const_val.inner_type + }; // Return result as register - Ok(ExpressionResult::Register( - body_state.borrow().last_register_number, - )) + ExpressionResult { + expr_type: val_ty, + expr_value: ExpressionResultValue::Register( + body_state.borrow().last_register_number, + ), + } } else { // If value doesn't exist - Err(error::StateErrorResult::new( + self.add_error(StateErrorResult::new( error::StateErrorKind::ValueNotFound, value.name(), 0, 0, - )) + )); + return; } } // Check is expression primitive value ast::ExpressionValue::PrimitiveValue(value) => { // Just return primitive value itself - Ok(ExpressionResult::PrimitiveValue(value.clone())) + ExpressionResult { + expr_type: value.get_type(), + expr_value: ExpressionResult::PrimitiveValue(value.clone()), + } } // Check is expression Function call entity ast::ExpressionValue::FunctionCall(fn_call) => { @@ -1257,8 +1288,12 @@ impl> State { // And result of function always stored in register. let call_result = self.function_call(fn_call, body_state); // Return result as register - call_result - .map(|_| ExpressionResult::Register(body_state.borrow().last_register_number)) + ExpressionResult { + expr_type: 1, + expr_value: ExpressionResultValue::Register( + body_state.borrow().last_register_number, + ), + } } ast::ExpressionValue::StructValue(_value) => { todo!() @@ -1267,27 +1302,33 @@ impl> State { // It's special case for "pure" expression - without operation. // For that check also left side of expression shouldn't exist if left_value.is_none() || op.is_none() { - return Ok(right_value); + return right_value; + } + let left_value = left_value.unwrap(); + if left_value.expr_type != right_value.expr_type { + self.add_error() } // Call expression operation for: OP(left_value, right_value) // and return result of that call as register body_state.borrow_mut().inc_register(); self.codegen.expression_operation( op.unwrap(), - left_value.unwrap(), + left_value, &right_value, body_state.borrow().last_register_number, ); - let expression_result = - ExpressionResult::Register(body_state.borrow().last_register_number); + let expression_result = ExpressionResult { + expr_type: right_value.expr_type, + expr_value: ExpressionResultValue::Register(body_state.borrow().last_register_number), + }; - // Check is for right value exist next operation + // Check is for right value contain next operation if let Some((operation, expr)) = &right_expression.operation { // Recursively call, where current Execution result set as left // side expression self.expression_operation(Some(&expression_result), expr, Some(operation), body_state) } else { - Ok(expression_result) + expression_result } } }