diff --git a/lib/src/analysis/type_analyze.rs b/lib/src/analysis/type_analyze.rs index 7588c24..434903c 100644 --- a/lib/src/analysis/type_analyze.rs +++ b/lib/src/analysis/type_analyze.rs @@ -169,10 +169,10 @@ fn analyze_op_expr_type(op1: &Option, op2: &Option) -> Option let tc2 = op2.as_ref()?.type_class(); // Usertype is not handled - if matches!(tc1, TypeClass::UserType) { + if matches!(tc1, TypeClass::UnknownType) { return None; } - if matches!(tc2, TypeClass::UserType) { + if matches!(tc2, TypeClass::UnknownType) { return None; } diff --git a/lib/src/ast/mod.rs b/lib/src/ast/mod.rs index 5004807..acbcec3 100644 --- a/lib/src/ast/mod.rs +++ b/lib/src/ast/mod.rs @@ -1,10 +1,11 @@ -use crate::parser::{LiteralValue, Operator, StString}; +use crate::parser::LiteralValue; +use crate::prelude::*; use bitflags::bitflags; use smallvec::SmallVec; use std::any::Any; use std::fmt::{self, Debug, Display, Formatter}; use std::hash::{Hash, Hasher}; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; mod message; pub use message::*; @@ -58,7 +59,7 @@ mod global_variable_declaration; pub use global_variable_declaration::GlobalVariableDeclare; mod range_expression; -pub use range_expression::RangeExpression; +pub use range_expression::{Dimensions, RangeExpression}; pub type SmallVec8 = SmallVec<[T; 8]>; pub type SmallVec3 = SmallVec<[T; 3]>; @@ -133,6 +134,15 @@ pub trait TypeTrait: Send + Sync { fn as_any(&self) -> &dyn Any; } +pub trait UserTypeTrait: TypeTrait { + fn get_prototype(&self, scope: Scope) -> Prototype; +} + +pub trait ArrayTypeTrait: TypeTrait { + fn base_type(&self) -> &Type; + fn dimensions(&self) -> &Dimensions; +} + #[derive(Clone)] pub struct Type { inner: Arc, @@ -174,6 +184,15 @@ impl Type { } } +impl From for Type +where + T: TypeTrait + 'static, +{ + fn from(value: T) -> Self { + Type::from_object(value) + } +} + impl Display for Type { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.type_class()) @@ -340,10 +359,12 @@ pub enum TypeClass { LReal, /// 'STRING' string type String, - /// UserType - UserType, + /// UnknownType + UnknownType, /// ArrayType Array, + /// StructType + Struct, } impl Hash for TypeClass { @@ -354,7 +375,7 @@ impl Hash for TypeClass { TypeClass::Byte => 3, TypeClass::UInt => 4, TypeClass::Int => 5, - TypeClass::UserType => 6, + TypeClass::UnknownType => 6, TypeClass::Array => 7, // Some type shouldn't hash directly like ArrayType or UserType _ => unreachable!("TypeClass shouldn't hash: {:?}", self), @@ -380,7 +401,7 @@ impl Display for TypeClass { TypeClass::Real => write!(f, "REAL"), TypeClass::LReal => write!(f, "LREAL"), TypeClass::String => write!(f, "STRING"), - TypeClass::UserType | TypeClass::Array => { + TypeClass::UnknownType | TypeClass::Array | TypeClass::Struct => { unreachable!("UserType or ArrayType can't display without Type object") } } diff --git a/lib/src/ast/operator_expression.rs b/lib/src/ast/operator_expression.rs index 8d35e14..24aeab7 100644 --- a/lib/src/ast/operator_expression.rs +++ b/lib/src/ast/operator_expression.rs @@ -1,4 +1,5 @@ use crate::ast::*; +use crate::parser::Operator; use crate::{impl_ast_display, impl_into_expression}; #[derive(Debug)] diff --git a/lib/src/ast/range_expression.rs b/lib/src/ast/range_expression.rs index b368e0a..a5e0c7b 100644 --- a/lib/src/ast/range_expression.rs +++ b/lib/src/ast/range_expression.rs @@ -1,4 +1,4 @@ -use super::Expression; +use super::{Expression, SmallVec3}; /// Lower..Upper #[derive(Debug)] @@ -9,8 +9,8 @@ pub struct RangeExpression { impl RangeExpression { pub fn new(lower: Expression, upper: Expression) -> Self { - Self { - lower, upper - } + Self { lower, upper } } -} \ No newline at end of file +} + +pub type Dimensions = SmallVec3; diff --git a/lib/src/ast/types.rs b/lib/src/ast/types.rs index 262b382..801bc9d 100644 --- a/lib/src/ast/types.rs +++ b/lib/src/ast/types.rs @@ -29,27 +29,13 @@ builtin_type_impl!(struct LRealType, TypeClass::LReal); builtin_type_impl!(struct StringType, TypeClass::String); #[derive(Debug, Clone, PartialEq, Eq)] -pub struct UserType { +pub struct UnknownType { name: StString, - decl_id: Option, - class: Option, } -impl UserType { +impl UnknownType { pub fn from_name(name: StString) -> Self { - Self { - name, - decl_id: None, - class: None, - } - } - - pub fn from_proto(name: StString, proto_id: usize) -> Self { - Self { - name, - decl_id: Some(proto_id), - class: None, - } + Self { name } } pub fn name(&self) -> &StString { @@ -57,15 +43,21 @@ impl UserType { } } -impl From for Type { - fn from(value: UserType) -> Self { - Type::from_object(value) +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct StructType { + name: StString, + proto: usize, +} + +impl StructType { + pub fn new(name: StString, proto: usize) -> Self { + Self { name, proto } } } -impl TypeTrait for UserType { +impl TypeTrait for StructType { fn class(&self) -> TypeClass { - TypeClass::UserType + TypeClass::Struct } fn as_any(&self) -> &dyn Any { @@ -73,7 +65,17 @@ impl TypeTrait for UserType { } } -impl Display for UserType { +impl TypeTrait for UnknownType { + fn class(&self) -> TypeClass { + TypeClass::UnknownType + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl Display for UnknownType { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.name) } @@ -186,22 +188,27 @@ impl StructDeclare { #[derive(Debug)] pub struct ArrayType { - base_type: Arc>, - dimensions: SmallVec3, + base_type: Type, + dimensions: Dimensions, } impl ArrayType { - pub fn new(base: Type, dimensions: SmallVec3) -> Self { + pub fn new(base: Type, dimensions: Dimensions) -> Self { Self { - base_type: Arc::new(RwLock::new(base)), + base_type: base, dimensions, } } +} - #[inline] - pub fn base_type(&self) -> &Arc> { +impl ArrayTypeTrait for ArrayType { + fn base_type(&self) -> &Type { &self.base_type } + + fn dimensions(&self) -> &Dimensions { + &self.dimensions + } } impl Display for ArrayType { @@ -225,12 +232,6 @@ impl Clone for ArrayType { } } -impl From for Type { - fn from(value: ArrayType) -> Self { - Type::from_object(value) - } -} - impl TypeTrait for ArrayType { fn class(&self) -> TypeClass { TypeClass::Array diff --git a/lib/src/context/module_context.rs b/lib/src/context/module_context.rs index 1835de4..032463a 100644 --- a/lib/src/context/module_context.rs +++ b/lib/src/context/module_context.rs @@ -147,14 +147,10 @@ impl PrototypeImpl { } pub fn create_user_type(&self) -> Option { - // Only Structure types can be created as UserType match self.decl.kind { - DeclKind::Struct(_) | DeclKind::Alias(_) | DeclKind::Enum(_) => {} - _ => return None, + DeclKind::Struct(_) => Some(StructType::new(self.name().clone(), self.id).into()), + _ => None, } - - let user_ty = UserType::from_proto(self.decl.identifier().clone(), self.id); - Some(user_ty.into()) } /// Get return value of prototype diff --git a/lib/src/parser/default_impl/mod.rs b/lib/src/parser/default_impl/mod.rs index 6fcecc0..af0af16 100644 --- a/lib/src/parser/default_impl/mod.rs +++ b/lib/src/parser/default_impl/mod.rs @@ -235,7 +235,7 @@ impl> DefaultParserImpl { TokenKind::Byte => Ok(Some(ByteType::new_type())), TokenKind::Int => Ok(Some(IntType::new_type())), TokenKind::Real => Ok(Some(RealType::new_type())), - TokenKind::Identifier(ident) => Ok(Some(UserType::from_name(ident.clone()).into())), + TokenKind::Identifier(ident) => Ok(Some(UnknownType::from_name(ident.clone()).into())), _ => { self.next = pos; Ok(None) diff --git a/lib/src/parser/lalrpop_impl/st.lalrpop b/lib/src/parser/lalrpop_impl/st.lalrpop index 62f8f1e..49cbe61 100644 --- a/lib/src/parser/lalrpop_impl/st.lalrpop +++ b/lib/src/parser/lalrpop_impl/st.lalrpop @@ -289,7 +289,7 @@ pub Type: Type = { "BOOL" => BoolType::new_type(), "BYTE" => ByteType::new_type(), "REAL" => RealType::new_type(), - "IDENTIFIER" => UserType::from_name(<>).into(), + "IDENTIFIER" => UnknownType::from_name(<>).into(), => arr.into(), }