diff --git a/Cargo.lock b/Cargo.lock index ecf86865ae..b391cb8d2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1633,7 +1633,9 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" name = "plc_ast" version = "0.1.0" dependencies = [ - "rusty", + "chrono", + "plc_util", + "serde", ] [[package]] @@ -1689,6 +1691,10 @@ dependencies = [ "encoding_rs_io", ] +[[package]] +name = "plc_util" +version = "0.1.0" + [[package]] name = "polling" version = "2.8.0" @@ -1935,9 +1941,11 @@ dependencies = [ "log", "logos", "num", + "plc_ast", "plc_driver", "plc_project", "plc_source", + "plc_util", "pretty_assertions", "regex", "rusty-derive", @@ -2943,6 +2951,7 @@ dependencies = [ "anyhow", "async-std", "clap 4.3.10", + "plc_ast", "rusty", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index ec59cf275f..ecfe94000c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,8 @@ default = [] verify = [] [dependencies] +plc_ast = { path = "./compiler/plc_ast" } +plc_util = { path = "./compiler/plc_util" } logos = "0.12.0" thiserror = "1.0" clap = { version = "3.0", features = ["derive"] } @@ -62,6 +64,7 @@ members = [ "compiler/plc_diagnostics", "compiler/plc_project", "compiler/plc_source", + "compiler/plc_util", "rusty-derive", ] default-members = [".", "compiler/plc_driver"] diff --git a/compiler/plc_ast/Cargo.toml b/compiler/plc_ast/Cargo.toml index f58f7baadc..28646b4f8f 100644 --- a/compiler/plc_ast/Cargo.toml +++ b/compiler/plc_ast/Cargo.toml @@ -6,4 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -plc = {path = "../..", package = "rusty"} +plc_util = { path = "../plc_util" } +chrono = { version = "0.4", default-features = false } +serde = { version = "1.0", features = ["derive"] } diff --git a/src/ast.rs b/compiler/plc_ast/src/ast.rs similarity index 94% rename from src/ast.rs rename to compiler/plc_ast/src/ast.rs index c7705df12b..387cc37ad7 100644 --- a/src/ast.rs +++ b/compiler/plc_ast/src/ast.rs @@ -1,29 +1,20 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::{ - ast::control_statements::ForLoopStatement, - index::Index, - lexer::IdProvider, - typesystem::{ - DataTypeInformation, BOOL_TYPE, CHAR_TYPE, DATE_TYPE, REAL_TYPE, SINT_TYPE, STRING_TYPE, TIME_TYPE, - USINT_TYPE, VOID_TYPE, - }, -}; -pub use literals::*; -use serde::{Deserialize, Serialize}; + use std::{ - fmt::{Debug, Display, Formatter, Result}, - iter, + fmt::{Debug, Display, Formatter}, ops::Range, - unimplemented, vec, }; -use self::control_statements::{ - AstControlStatement, CaseStatement, ConditionalBlock, IfStatement, LoopStatement, -}; +use serde::{Deserialize, Serialize}; -pub mod control_statements; -pub mod literals; -mod pre_processor; +use crate::{ + control_statements::{ + AstControlStatement, CaseStatement, ConditionalBlock, ForLoopStatement, IfStatement, LoopStatement, + }, + literals::{AstLiteral, StringValue}, + pre_processor, + provider::IdProvider, +}; pub type AstId = usize; @@ -96,21 +87,6 @@ pub enum TypeNature { } impl TypeNature { - pub fn get_smallest_possible_type(&self) -> &str { - match self { - TypeNature::Magnitude | TypeNature::Num | TypeNature::Int => USINT_TYPE, - TypeNature::Real => REAL_TYPE, - TypeNature::Unsigned => USINT_TYPE, - TypeNature::Signed => SINT_TYPE, - TypeNature::Duration => TIME_TYPE, - TypeNature::Bit => BOOL_TYPE, - TypeNature::Chars | TypeNature::Char => CHAR_TYPE, - TypeNature::String => STRING_TYPE, - TypeNature::Date => DATE_TYPE, - _ => "", - } - } - pub fn derives_from(self, other: TypeNature) -> bool { if other == self { true @@ -178,21 +154,6 @@ impl TypeNature { } impl DirectAccessType { - /// Returns true if the current index is in the range for the given type - pub fn is_in_range(&self, access_index: u64, data_type: &DataTypeInformation, index: &Index) -> bool { - (self.get_bit_width() * access_index) < data_type.get_size_in_bits(index) as u64 - } - - /// Returns the range from 0 for the given data type - pub fn get_range(&self, data_type: &DataTypeInformation, index: &Index) -> Range { - 0..((data_type.get_size_in_bits(index) as u64 / self.get_bit_width()) - 1) - } - - /// Returns true if the direct access can be used for the given type - pub fn is_compatible(&self, data_type: &DataTypeInformation, index: &Index) -> bool { - data_type.get_semantic_size(index) as u64 > self.get_bit_width() - } - /// Returns the size of the bitaccess result pub fn get_bit_width(&self) -> u64 { match self { @@ -207,7 +168,7 @@ impl DirectAccessType { } impl Debug for Pou { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let mut str = f.debug_struct("POU"); str.field("name", &self.name) .field("variable_blocks", &self.variable_blocks) @@ -270,7 +231,7 @@ pub enum PouType { } impl Display for PouType { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { PouType::Program => write!(f, "Program"), PouType::Function => write!(f, "Function"), @@ -385,7 +346,7 @@ pub enum VariableBlockType { } impl Display for VariableBlockType { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { VariableBlockType::Local => write!(f, "Local"), VariableBlockType::Temp => write!(f, "Temp"), @@ -415,7 +376,7 @@ pub struct VariableBlock { } impl Debug for VariableBlock { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("VariableBlock") .field("variables", &self.variables) .field("variable_block_type", &self.variable_block_type) @@ -433,7 +394,7 @@ pub struct Variable { } impl Debug for Variable { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let mut var = f.debug_struct("Variable"); var.field("name", &self.name).field("data_type", &self.data_type_declaration); if self.initializer.is_some() { @@ -503,7 +464,7 @@ pub struct SourceRange { } impl Debug for SourceRange { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let mut f = f.debug_struct("SourceRange"); f.field("range", &self.range); if self.file.is_some() { @@ -574,7 +535,7 @@ pub enum DataTypeDeclaration { } impl Debug for DataTypeDeclaration { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { DataTypeDeclaration::DataTypeReference { referenced_type, .. } => { f.debug_struct("DataTypeReference").field("referenced_type", referenced_type).finish() @@ -617,7 +578,7 @@ pub struct UserTypeDeclaration { } impl Debug for UserTypeDeclaration { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("UserTypeDeclaration") .field("data_type", &self.data_type) .field("initializer", &self.initializer) @@ -691,10 +652,9 @@ impl DataType { | DataType::StringType { name, .. } | DataType::SubRangeType { name, .. } => name.as_ref().map(|x| x.as_str()), DataType::GenericType { name, .. } => Some(name.as_str()), - DataType::VarArgs { referenced_type, .. } => referenced_type - .as_ref() - .and_then(|it| DataTypeDeclaration::get_name(it.as_ref())) - .or(Some(VOID_TYPE)), + DataType::VarArgs { referenced_type, .. } => { + referenced_type.as_ref().and_then(|it| DataTypeDeclaration::get_name(it.as_ref())) + } } } @@ -858,7 +818,7 @@ pub enum AstStatement { } impl Debug for AstStatement { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { AstStatement::EmptyStatement { .. } => f.debug_struct("EmptyStatement").finish(), AstStatement::DefaultValue { .. } => f.debug_struct("DefaultValue").finish(), @@ -1184,7 +1144,7 @@ pub enum Operator { } impl Display for Operator { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let symbol = match self { Operator::Plus => "+", Operator::Minus => "-", @@ -1234,7 +1194,7 @@ pub fn flatten_expression_list(list: &AstStatement) -> Vec<&AstStatement> { expressions.iter().by_ref().flat_map(flatten_expression_list).collect() } AstStatement::MultipliedStatement { multiplier, element, .. } => { - iter::repeat(flatten_expression_list(element)).take(*multiplier as usize).flatten().collect() + std::iter::repeat(flatten_expression_list(element)).take(*multiplier as usize).flatten().collect() } _ => vec![list], } @@ -1245,7 +1205,7 @@ pub fn pre_process(unit: &mut CompilationUnit, id_provider: IdProvider) { } impl Operator { /// returns true, if this operator results in a bool value - pub(crate) fn is_bool_type(&self) -> bool { + pub fn is_bool_type(&self) -> bool { matches!( self, Operator::Equal @@ -1259,7 +1219,7 @@ impl Operator { /// returns true, if this operator is a comparison operator /// (=, <>, >, <, >=, <=) - pub(crate) fn is_comparison_operator(&self) -> bool { + pub fn is_comparison_operator(&self) -> bool { matches!( self, Operator::Equal diff --git a/src/ast/control_statements.rs b/compiler/plc_ast/src/control_statements.rs similarity index 90% rename from src/ast/control_statements.rs rename to compiler/plc_ast/src/control_statements.rs index e27f7cb7ce..c13b0b5602 100644 --- a/src/ast/control_statements.rs +++ b/compiler/plc_ast/src/control_statements.rs @@ -1,6 +1,6 @@ -use std::fmt::{Debug, Formatter, Result}; +use std::fmt::{Debug, Formatter}; -use super::AstStatement; +use crate::ast::AstStatement; #[derive(Clone, PartialEq)] pub struct IfStatement { @@ -47,7 +47,7 @@ pub struct ConditionalBlock { } impl Debug for ConditionalBlock { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("ConditionalBlock") .field("condition", &self.condition) .field("body", &self.body) diff --git a/compiler/plc_ast/src/lib.rs b/compiler/plc_ast/src/lib.rs index 8728d407bb..7e7d78a7de 100644 --- a/compiler/plc_ast/src/lib.rs +++ b/compiler/plc_ast/src/lib.rs @@ -2,4 +2,8 @@ //! It is currently only a re-export of the ast module from the root, but these should //! eventually move here -pub use plc::ast::*; +pub mod ast; +pub mod control_statements; +pub mod literals; +mod pre_processor; +pub mod provider; diff --git a/src/ast/literals.rs b/compiler/plc_ast/src/literals.rs similarity index 82% rename from src/ast/literals.rs rename to compiler/plc_ast/src/literals.rs index 16b408efa1..857316c5fb 100644 --- a/src/ast/literals.rs +++ b/compiler/plc_ast/src/literals.rs @@ -1,20 +1,8 @@ use std::fmt::{Debug, Formatter}; -use crate::typesystem::{ - BOOL_TYPE, DATE_AND_TIME_TYPE, DATE_TYPE, DINT_TYPE, INT_TYPE, LINT_TYPE, LREAL_TYPE, SINT_TYPE, - STRING_TYPE, TIME_OF_DAY_TYPE, TIME_TYPE, UDINT_TYPE, UINT_TYPE, ULINT_TYPE, USINT_TYPE, VOID_TYPE, - WSTRING_TYPE, -}; use chrono::NaiveDate; -use super::AstStatement; - -//returns a range with the min and max value of the given type -macro_rules! is_covered_by { - ($t:ty, $e:expr) => { - <$t>::MIN as i128 <= $e as i128 && $e as i128 <= <$t>::MAX as i128 - }; -} +use crate::ast::AstStatement; macro_rules! impl_getters { ($type:ty, [$($name:ident),+], [$($out:ty),+]) => { @@ -237,33 +225,6 @@ impl AstLiteral { AstLiteral::Null } - pub fn get_literal_actual_signed_type_name(&self, signed: bool) -> Option<&str> { - match self { - AstLiteral::Integer(value) => match signed { - _ if *value == 0_i128 || *value == 1_i128 => Some(BOOL_TYPE), - true if is_covered_by!(i8, *value) => Some(SINT_TYPE), - true if is_covered_by!(i16, *value) => Some(INT_TYPE), - true if is_covered_by!(i32, *value) => Some(DINT_TYPE), - true if is_covered_by!(i64, *value) => Some(LINT_TYPE), - - false if is_covered_by!(u8, *value) => Some(USINT_TYPE), - false if is_covered_by!(u16, *value) => Some(UINT_TYPE), - false if is_covered_by!(u32, *value) => Some(UDINT_TYPE), - false if is_covered_by!(u64, *value) => Some(ULINT_TYPE), - _ => Some(VOID_TYPE), - }, - AstLiteral::Bool { .. } => Some(BOOL_TYPE), - AstLiteral::String(StringValue { is_wide: true, .. }) => Some(WSTRING_TYPE), - AstLiteral::String(StringValue { is_wide: false, .. }) => Some(STRING_TYPE), - AstLiteral::Real { .. } => Some(LREAL_TYPE), - AstLiteral::Date { .. } => Some(DATE_TYPE), - AstLiteral::DateAndTime { .. } => Some(DATE_AND_TIME_TYPE), - AstLiteral::Time { .. } => Some(TIME_TYPE), - AstLiteral::TimeOfDay { .. } => Some(TIME_OF_DAY_TYPE), - _ => None, - } - } - pub fn get_literal_value(&self) -> String { match self { AstLiteral::String(StringValue { value, is_wide: true, .. }) => format!(r#""{value}""#), diff --git a/src/ast/pre_processor.rs b/compiler/plc_ast/src/pre_processor.rs similarity index 93% rename from src/ast/pre_processor.rs rename to compiler/plc_ast/src/pre_processor.rs index 6c21e65e3a..b250fe2c41 100644 --- a/src/ast/pre_processor.rs +++ b/compiler/plc_ast/src/pre_processor.rs @@ -1,12 +1,17 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::{ast::DataTypeDeclaration, lexer::IdProvider, typesystem}; +use std::collections::HashMap; -use super::{ - super::ast::{CompilationUnit, UserTypeDeclaration, Variable}, - flatten_expression_list, AstFactory, AstLiteral, AstStatement, DataType, Operator, Pou, SourceRange, +use plc_util::convention::internal_type_name; + +use crate::{ + ast::{ + flatten_expression_list, AstFactory, AstStatement, CompilationUnit, DataType, DataTypeDeclaration, + Operator, Pou, SourceRange, UserTypeDeclaration, Variable, + }, + literals::AstLiteral, + provider::IdProvider, }; -use std::{collections::HashMap, vec}; pub fn pre_process(unit: &mut CompilationUnit, mut id_provider: IdProvider) { //process all local variables from POUs @@ -58,7 +63,7 @@ pub fn pre_process(unit: &mut CompilationUnit, mut id_provider: IdProvider) { { let name: &str = name.as_ref().map(|it| it.as_str()).unwrap_or("undefined"); - let type_name = typesystem::create_internal_type_name("", name); + let type_name = internal_type_name("", name); let type_ref = DataTypeDeclaration::DataTypeReference { referenced_type: type_name.clone(), location: SourceRange::undefined(), //return_type.get_location(), @@ -158,7 +163,8 @@ fn preprocess_generic_structs(pou: &mut Pou) -> Vec { let mut generic_types = HashMap::new(); let mut types = vec![]; for binding in &pou.generics { - let new_name = format!("__{}__{}", pou.name, binding.name); + let new_name = format!("__{}__{}", pou.name, binding.name); // TODO: Naming convention (see plc_util/src/convention.rs) + //Generate a type for the generic let data_type = UserTypeDeclaration { data_type: DataType::GenericType { @@ -185,7 +191,7 @@ fn preprocess_generic_structs(pou: &mut Pou) -> Vec { fn preprocess_return_type(pou: &mut Pou, types: &mut Vec) { if let Some(return_type) = &pou.return_type { if should_generate_implicit(return_type) { - let type_name = format!("__{}_return", &pou.name); + let type_name = format!("__{}_return", &pou.name); // TODO: Naming convention (see plc_util/src/convention.rs) let type_ref = DataTypeDeclaration::DataTypeReference { referenced_type: type_name.clone(), location: return_type.get_location(), @@ -219,8 +225,7 @@ fn pre_process_variable_data_type( variable: &mut Variable, types: &mut Vec, ) { - let new_type_name = - typesystem::create_internal_type_name(format!("{container_name}_").as_str(), variable.name.as_str()); + let new_type_name = internal_type_name(&format!("{container_name}_"), &variable.name); if let DataTypeDeclaration::DataTypeDefinition { mut data_type, location, scope } = variable.replace_data_type_with_reference_to(new_type_name.clone()) { @@ -238,7 +243,7 @@ fn add_nested_datatypes( types: &mut Vec, location: &SourceRange, ) { - let new_type_name = format!("{container_name}_"); + let new_type_name = format!("{container_name}_"); // TODO: Naming convention (see plc_util/src/convention.rs) if let Some(DataTypeDeclaration::DataTypeDefinition { mut data_type, location: inner_location, scope }) = datatype.replace_data_type_with_reference_to(new_type_name.clone(), location) { diff --git a/compiler/plc_ast/src/provider.rs b/compiler/plc_ast/src/provider.rs new file mode 100644 index 0000000000..f5dbf632ec --- /dev/null +++ b/compiler/plc_ast/src/provider.rs @@ -0,0 +1,39 @@ +use std::sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, +}; + +use crate::ast::AstId; + +#[derive(Clone)] +pub struct IdProvider { + current_id: Arc, +} + +impl IdProvider { + pub fn next_id(&mut self) -> AstId { + self.current_id.fetch_add(1, Ordering::Relaxed) + } +} + +impl Default for IdProvider { + fn default() -> Self { + IdProvider { current_id: Arc::new(AtomicUsize::new(1)) } + } +} + +#[cfg(test)] +mod id_tests { + use super::IdProvider; + + #[test] + fn id_provider_generates_unique_ids_over_clones() { + let mut id1 = IdProvider::default(); + let mut id2 = id1.clone(); + + assert_eq!(id1.next_id(), 1); + assert_eq!(id2.next_id(), 2); + assert_eq!(id1.next_id(), 3); + assert_eq!(id2.next_id(), 4); + } +} diff --git a/compiler/plc_driver/src/lib.rs b/compiler/plc_driver/src/lib.rs index 886d8f6010..c1a03460ac 100644 --- a/compiler/plc_driver/src/lib.rs +++ b/compiler/plc_driver/src/lib.rs @@ -15,9 +15,10 @@ use std::{ path::{Path, PathBuf}, }; +use ast::provider::IdProvider; use cli::CompileParameters; use diagnostics::{Diagnostic, Diagnostician}; -use plc::{lexer::IdProvider, output::FormatOption, DebugLevel, ErrorFormat, OptimizationLevel, Threads}; +use plc::{output::FormatOption, DebugLevel, ErrorFormat, OptimizationLevel, Threads}; use project::project::{LibraryInformation, Project}; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use source_code::SourceContainer; diff --git a/compiler/plc_driver/src/pipelines.rs b/compiler/plc_driver/src/pipelines.rs index 1232f98959..837ef2bf5e 100644 --- a/compiler/plc_driver/src/pipelines.rs +++ b/compiler/plc_driver/src/pipelines.rs @@ -6,14 +6,16 @@ use std::{ }; use crate::{CompileOptions, LinkOptions}; -use ast::{CompilationUnit, SourceRange}; +use ast::{ + ast::{pre_process, CompilationUnit, LinkageType, SourceRange}, + provider::IdProvider, +}; use diagnostics::{Diagnostic, Diagnostician}; use encoding_rs::Encoding; use indexmap::IndexSet; use plc::{ codegen::{CodegenContext, GeneratedModule}, index::Index, - lexer::IdProvider, output::FormatOption, parser::parse_file, resolver::{AnnotationMapImpl, AstAnnotations, Dependency, StringLiterals, TypeAnnotator}, @@ -58,7 +60,7 @@ impl ParsedProject { Ok(parse_file( &loaded_source.source, loaded_source.get_location_str(), - ast::LinkageType::Internal, + LinkageType::Internal, id_provider.clone(), diagnostician, )) @@ -79,7 +81,7 @@ impl ParsedProject { Ok(parse_file( &loaded_source.source, loaded_source.get_location_str(), - ast::LinkageType::External, + LinkageType::External, id_provider.clone(), diagnostician, )) @@ -101,7 +103,7 @@ impl ParsedProject { Ok(parse_file( &loaded_source.source, loaded_source.get_location_str(), - ast::LinkageType::External, + LinkageType::External, id_provider.clone(), diagnostician, )) @@ -119,7 +121,7 @@ impl ParsedProject { .into_par_iter() .map(|mut unit| { //Preprocess - ast::pre_process(&mut unit, id_provider.clone()); + pre_process(&mut unit, id_provider.clone()); //import to index let index = plc::index::visitor::visit(&unit); diff --git a/compiler/plc_driver/src/runner.rs b/compiler/plc_driver/src/runner.rs index 3aeacd21b5..7b8f47038e 100644 --- a/compiler/plc_driver/src/runner.rs +++ b/compiler/plc_driver/src/runner.rs @@ -1,9 +1,9 @@ use crate::{pipelines::ParsedProject, CompileOptions}; +use ast::provider::IdProvider; use plc::{ codegen::{CodegenContext, GeneratedModule}, diagnostics::Diagnostician, - lexer::IdProvider, }; use project::project::Project; use source_code::Compilable; diff --git a/compiler/plc_driver/src/tests.rs b/compiler/plc_driver/src/tests.rs index d071e3aceb..1249b0725f 100644 --- a/compiler/plc_driver/src/tests.rs +++ b/compiler/plc_driver/src/tests.rs @@ -1,7 +1,8 @@ use std::{fmt::Debug, path::PathBuf}; +use ast::provider::IdProvider; use diagnostics::{Diagnostic, Diagnostician}; -use plc::{lexer::IdProvider, DebugLevel}; +use plc::DebugLevel; use project::project::Project; use source_code::SourceContainer; diff --git a/compiler/plc_driver/src/tests/external_files.rs b/compiler/plc_driver/src/tests/external_files.rs index f6b63f68f6..ebfbff0245 100644 --- a/compiler/plc_driver/src/tests/external_files.rs +++ b/compiler/plc_driver/src/tests/external_files.rs @@ -1,4 +1,4 @@ -use ast::SourceRange; +use ast::ast::SourceRange; use diagnostics::Diagnostic; use plc::DebugLevel; use source_code::SourceCode; diff --git a/compiler/plc_util/Cargo.toml b/compiler/plc_util/Cargo.toml new file mode 100644 index 0000000000..cf7e1b3f90 --- /dev/null +++ b/compiler/plc_util/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "plc_util" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/compiler/plc_util/src/convention.rs b/compiler/plc_util/src/convention.rs new file mode 100644 index 0000000000..6fcda9ad73 --- /dev/null +++ b/compiler/plc_util/src/convention.rs @@ -0,0 +1,26 @@ +//! This module hosts several function related to naming conventions. + +use std::fmt::Display; + +/// Returns a qualified name in the form of `.`. +pub fn qualified_name + Display>(qualifier: T, name: T) -> String { + format!("{qualifier}.{name}") +} + +/// Returns a name for internally created types in the form of `__`. +pub fn internal_type_name + Display>(prefix: T, original_type_name: T) -> String { + format!("__{prefix}{original_type_name}") +} + +#[cfg(test)] +mod tests { + #[test] + fn qualified_name() { + assert_eq!(super::qualified_name("main", "foo"), "main.foo".to_string()); + } + + #[test] + fn internal_type_name() { + assert_eq!(super::internal_type_name("POINTER_TO_", "foo"), "__POINTER_TO_foo"); + } +} diff --git a/compiler/plc_util/src/lib.rs b/compiler/plc_util/src/lib.rs new file mode 100644 index 0000000000..009c7bfe18 --- /dev/null +++ b/compiler/plc_util/src/lib.rs @@ -0,0 +1 @@ +pub mod convention; diff --git a/src/builtins.rs b/src/builtins.rs index e06caadb33..ef794f0d99 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -6,23 +6,26 @@ use inkwell::{ values::{BasicValue, IntValue}, }; use lazy_static::lazy_static; - -use crate::{ +use plc_ast::{ ast::{ - self, flatten_expression_list, AstLiteral, AstStatement, CompilationUnit, GenericBinding, + self, flatten_expression_list, pre_process, AstStatement, CompilationUnit, GenericBinding, LinkageType, SourceRange, SourceRangeFactory, TypeNature, }, + literals::AstLiteral, + provider::IdProvider, +}; + +use crate::{ codegen::generators::expression_generator::{self, ExpressionCodeGenerator, ExpressionValue}, diagnostics::Diagnostic, index::Index, - lexer::{self, IdProvider}, - parser, + lexer, parser, resolver::{ self, generics::{no_generic_name_resolver, GenericType}, AnnotationMap, StatementAnnotation, TypeAnnotator, VisitorContext, }, - typesystem, + typesystem::{self, get_literal_actual_signed_type_name}, validation::{Validator, Validators}, }; @@ -93,7 +96,7 @@ lazy_static! { return; }; - let params = ast::flatten_expression_list(params); + let params = flatten_expression_list(params); if params.len() > 1 { validator.push_diagnostic(Diagnostic::invalid_parameter_count(1, params.len(), operator.get_location())); @@ -435,7 +438,7 @@ fn generate_variable_length_array_bound_function<'ink>( // e.g. LOWER_BOUND(arr, 1) AstStatement::Literal { kind, .. } => { let AstLiteral::Integer(value) = kind else { - let Some(type_name) = kind.get_literal_actual_signed_type_name(false) else { + let Some(type_name) = get_literal_actual_signed_type_name(kind, false) else { unreachable!("type cannot be VOID") }; return Err(Diagnostic::codegen_error( @@ -541,7 +544,8 @@ pub fn parse_built_ins(id_provider: IdProvider) -> CompilationUnit { "", ) .0; - crate::ast::pre_process(&mut unit, id_provider); + + pre_process(&mut unit, id_provider); unit } diff --git a/src/codegen.rs b/src/codegen.rs index c86539af5a..2cfe4310db 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -24,7 +24,6 @@ use crate::{ DebugLevel, OptimizationLevel, Target, }; -use super::ast::*; use super::index::*; use indexmap::IndexSet; use inkwell::{ @@ -38,6 +37,7 @@ use inkwell::{ passes::PassBuilderOptions, targets::{CodeModel, FileType, InitializationConfig, RelocMode}, }; +use plc_ast::ast::{CompilationUnit, LinkageType, SourceRange}; mod debug; pub(crate) mod generators; diff --git a/src/codegen/debug.rs b/src/codegen/debug.rs index 6f3efe2f3a..85e6bac0e4 100644 --- a/src/codegen/debug.rs +++ b/src/codegen/debug.rs @@ -11,9 +11,9 @@ use inkwell::{ module::Module, values::{BasicMetadataValueEnum, FunctionValue, GlobalValue, PointerValue}, }; +use plc_ast::ast::{LinkageType, SourceRange}; use crate::{ - ast::{LinkageType, SourceRange}, datalayout::{Bytes, DataLayout, MemoryLocation}, diagnostics::Diagnostic, index::{symbol::SymbolLocation, ImplementationType, Index, PouIndexEntry, VariableIndexEntry}, @@ -553,7 +553,7 @@ impl<'ink> DebugBuilder<'ink> { .into(); let data_layout = DataLayout::default(); let debug_type = self.debug_info.create_pointer_type( - &format!("__ref_to_{}", variable.get_type_name()), + &format!("__ref_to_{}", variable.get_type_name()), // TODO: Naming convention (see plc_util/src/convention.rs) original_type, data_layout.p64.bits().into(), data_layout.p64.bits(), diff --git a/src/codegen/generators/data_type_generator.rs b/src/codegen/generators/data_type_generator.rs index 2efec8f310..5f8d134a7e 100644 --- a/src/codegen/generators/data_type_generator.rs +++ b/src/codegen/generators/data_type_generator.rs @@ -1,11 +1,9 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::ast::SourceRange; use crate::codegen::debug::Debug; use crate::index::{Index, VariableIndexEntry, VariableType}; use crate::resolver::{AstAnnotations, Dependency}; -use crate::typesystem::{self, Dimension, StringEncoding, StructSource}; +use crate::typesystem::{self, DataTypeInformation, Dimension, StringEncoding, StructSource}; use crate::Diagnostic; -use crate::{ast::literals::AstLiteral, ast::AstStatement, typesystem::DataTypeInformation}; use crate::{ codegen::{ debug::DebugBuilderEnum, @@ -20,6 +18,8 @@ use inkwell::{ values::{BasicValue, BasicValueEnum}, AddressSpace, }; +use plc_ast::ast::{AstStatement, SourceRange}; +use plc_ast::literals::AstLiteral; /// the data_type_generator generates user defined data-types /// - Structures /// - Enum types diff --git a/src/codegen/generators/expression_generator.rs b/src/codegen/generators/expression_generator.rs index 42c0a73715..f755b0ff5b 100644 --- a/src/codegen/generators/expression_generator.rs +++ b/src/codegen/generators/expression_generator.rs @@ -1,6 +1,5 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder use crate::{ - ast::{self, flatten_expression_list, AstLiteral, AstStatement, DirectAccessType, Operator, SourceRange}, codegen::{ debug::{Debug, DebugBuilderEnum}, llvm_index::LlvmTypedIndex, @@ -26,6 +25,11 @@ use inkwell::{ }, AddressSpace, FloatPredicate, IntPredicate, }; +use plc_ast::{ + ast::{flatten_expression_list, AstStatement, DirectAccessType, Operator, SourceRange}, + literals::AstLiteral, +}; +use plc_util::convention::qualified_name; use std::{collections::HashSet, vec}; use super::{llvm::Llvm, statement_generator::FunctionContext, ADDRESS_SPACE_CONST, ADDRESS_SPACE_GENERIC}; @@ -482,7 +486,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> { .find_implementation(self.index) .ok_or_else(|| Diagnostic::cannot_generate_call_statement(operator))?; - let parameters_list = parameters.as_ref().map(ast::flatten_expression_list).unwrap_or_default(); + let parameters_list = parameters.as_ref().map(flatten_expression_list).unwrap_or_default(); let implementation_name = implementation.get_call_name(); // if the function is builtin, generate a basic value enum for it if let Some(builtin) = self.index.get_builtin_function(implementation_name) { @@ -1021,7 +1025,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> { function_name: &str, context: &AstStatement, ) -> Result, Diagnostic> { - let instance_name = format!("{function_name}_instance"); + let instance_name = format!("{function_name}_instance"); // TODO: Naming convention (see plc_util/src/convention.rs) let function_type = self .llvm_index .find_associated_pou_type(function_name) //Using find instead of get to control the compile error @@ -1351,7 +1355,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> { } _ => { let qualifier_name = self.get_type_hint_for(context)?.get_name(); - let qualified_name = format!("{qualifier_name}.{name}"); + let qualified_name = qualified_name(qualifier_name, name); let implementation = self.index.find_pou_implementation(&qualified_name); if implementation.is_some() { return Ok(qualifier.to_owned()); @@ -2016,7 +2020,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> { let member: &VariableIndexEntry = self.index.find_member(struct_name, variable_name).ok_or_else(|| { Diagnostic::unresolved_reference( - format!("{struct_name}.{variable_name}").as_str(), + &qualified_name(struct_name, variable_name), location.clone(), ) })?; diff --git a/src/codegen/generators/llvm.rs b/src/codegen/generators/llvm.rs index 4bc698ddab..cee2c01c8b 100644 --- a/src/codegen/generators/llvm.rs +++ b/src/codegen/generators/llvm.rs @@ -1,5 +1,4 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::ast::SourceRange; use crate::diagnostics::Diagnostic; use crate::typesystem::{CHAR_TYPE, WCHAR_TYPE}; use inkwell::types::ArrayType; @@ -11,6 +10,7 @@ use inkwell::{ values::{BasicValue, BasicValueEnum, GlobalValue, IntValue, PointerValue}, AddressSpace, }; +use plc_ast::ast::SourceRange; use super::ADDRESS_SPACE_GENERIC; diff --git a/src/codegen/generators/pou_generator.rs b/src/codegen/generators/pou_generator.rs index fd914b7e4b..acc8e41511 100644 --- a/src/codegen/generators/pou_generator.rs +++ b/src/codegen/generators/pou_generator.rs @@ -7,7 +7,6 @@ use super::{ ADDRESS_SPACE_GENERIC, }; use crate::{ - ast::{AstStatement, NewLines}, codegen::{ debug::{Debug, DebugBuilderEnum}, llvm_index::LlvmTypedIndex, @@ -25,10 +24,7 @@ use crate::{ /// - declares a global instance if the POU is a PROGRAM use crate::index::{ImplementationIndexEntry, VariableIndexEntry}; -use crate::{ - ast::{Implementation, PouType, SourceRange}, - index::Index, -}; +use crate::index::Index; use indexmap::{IndexMap, IndexSet}; use inkwell::{ module::Module, @@ -40,6 +36,7 @@ use inkwell::{ types::{BasicType, StructType}, values::PointerValue, }; +use plc_ast::ast::{AstStatement, Implementation, NewLines, PouType, SourceRange}; pub struct PouGenerator<'ink, 'cg> { llvm: Llvm<'ink>, @@ -742,7 +739,7 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> { } else { // renerate return statement let call_name = function_context.linking_context.get_call_name(); - let var_name = format!("{call_name}_ret"); + let var_name = format!("{call_name}_ret"); // TODO: Naming convention (see plc_util/src/convention.rs) let ret_name = ret_v.get_qualified_name(); let value_ptr = local_index.find_loaded_associated_variable_value(ret_name).ok_or_else(|| { diff --git a/src/codegen/generators/statement_generator.rs b/src/codegen/generators/statement_generator.rs index d5e4db688f..95d3a56abb 100644 --- a/src/codegen/generators/statement_generator.rs +++ b/src/codegen/generators/statement_generator.rs @@ -5,10 +5,6 @@ use super::{ pou_generator::PouGenerator, }; use crate::{ - ast::{ - control_statements::{AstControlStatement, ConditionalBlock}, - flatten_expression_list, AstFactory, AstStatement, NewLines, Operator, SourceRange, - }, codegen::{debug::Debug, llvm_typesystem::cast_if_needed}, codegen::{debug::DebugBuilderEnum, LlvmTypedIndex}, diagnostics::{Diagnostic, INTERNAL_LLVM_ERROR}, @@ -22,6 +18,10 @@ use inkwell::{ context::Context, values::{BasicValueEnum, FunctionValue}, }; +use plc_ast::{ + ast::{flatten_expression_list, AstFactory, AstStatement, NewLines, Operator, SourceRange}, + control_statements::{AstControlStatement, ConditionalBlock}, +}; /// the full context when generating statements inside a POU pub struct FunctionContext<'ink, 'b> { diff --git a/src/codegen/generators/variable_generator.rs b/src/codegen/generators/variable_generator.rs index c7a6290426..ed2db49f56 100644 --- a/src/codegen/generators/variable_generator.rs +++ b/src/codegen/generators/variable_generator.rs @@ -2,7 +2,6 @@ /// offers operations to generate global variables use crate::{ - ast::{LinkageType, SourceRange}, codegen::{debug::Debug, llvm_index::LlvmTypedIndex, llvm_typesystem::cast_if_needed}, diagnostics::{Diagnostic, ErrNo}, index::{get_initializer_name, Index, PouIndexEntry, VariableIndexEntry}, @@ -10,6 +9,7 @@ use crate::{ }; use indexmap::IndexSet; use inkwell::{module::Module, values::GlobalValue}; +use plc_ast::ast::{LinkageType, SourceRange}; use super::{ data_type_generator::get_default_for, diff --git a/src/codegen/llvm_index.rs b/src/codegen/llvm_index.rs index c9cd174d49..79ba2ae80c 100644 --- a/src/codegen/llvm_index.rs +++ b/src/codegen/llvm_index.rs @@ -1,8 +1,9 @@ use crate::diagnostics::Diagnostic; // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::ast::SourceRange; use inkwell::types::BasicTypeEnum; use inkwell::values::{BasicValueEnum, FunctionValue, GlobalValue, PointerValue}; +use plc_ast::ast::SourceRange; +use plc_util::convention::qualified_name; use std::collections::HashMap; /// Index view containing declared values for the current context @@ -97,7 +98,7 @@ impl<'ink> LlvmTypedIndex<'ink> { variable_name: &str, target_value: PointerValue<'ink>, ) -> Result<(), Diagnostic> { - let qualified_name = format!("{container_name}.{variable_name}"); + let qualified_name = qualified_name(container_name, variable_name); self.loaded_variable_associations.insert(qualified_name.to_lowercase(), target_value); Ok(()) } diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 58d49aa888..cc2bfc22ba 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -11,11 +11,9 @@ use codespan_reporting::{ term::termcolor::{ColorChoice, StandardStream}, }; use inkwell::support::LLVMString; +use plc_ast::ast::{AstStatement, DataTypeDeclaration, DiagnosticInfo, PouType, SourceRange}; -use crate::{ - ast::{AstStatement, DataTypeDeclaration, DiagnosticInfo, PouType, SourceRange}, - index::VariableType, -}; +use crate::index::VariableType; pub const INTERNAL_LLVM_ERROR: &str = "internal llvm codegen error"; diff --git a/src/hardware_binding.rs b/src/hardware_binding.rs index ce5f13ae62..d38f196dde 100644 --- a/src/hardware_binding.rs +++ b/src/hardware_binding.rs @@ -1,10 +1,10 @@ +use plc_ast::ast::{DirectAccessType, HardwareAccessType}; use serde::{ ser::{SerializeSeq, SerializeStruct}, Serialize, Serializer, }; use crate::{ - ast::{DirectAccessType, HardwareAccessType}, diagnostics::{Diagnostic, ErrNo}, expression_path::ExpressionPath, index::Index, diff --git a/src/index.rs b/src/index.rs index b45faf1ed0..4244458377 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1,15 +1,16 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder use crate::{ - ast::{ - AstStatement, DirectAccessType, GenericBinding, HardwareAccessType, LinkageType, PouType, - SourceRange, TypeNature, - }, builtins::{self, BuiltIn}, datalayout::DataLayout, diagnostics::Diagnostic, typesystem::{self, *}, }; use indexmap::IndexMap; +use plc_ast::ast::{ + AstStatement, DirectAccessType, GenericBinding, HardwareAccessType, LinkageType, PouType, SourceRange, + TypeNature, +}; +use plc_util::convention::qualified_name; use self::{ const_expressions::{ConstExpressions, ConstId}, @@ -175,7 +176,7 @@ impl VariableIndexEntry { VariableIndexEntry { name: name.to_string(), - qualified_name: format!("{container}.{name}"), + qualified_name: qualified_name(container, name), data_type_name: new_type.to_string(), varargs, ..self.to_owned() @@ -262,7 +263,7 @@ impl VariableIndexEntry { } fn has_parent(&self, context: &str) -> bool { - let name = format!("{context}.{}", self.name); + let name = qualified_name(context, &self.name); self.qualified_name.eq_ignore_ascii_case(&name) } } @@ -1039,7 +1040,7 @@ impl Index { /// returns the index entry of the enum-element `element_name` of the enum-type `enum_name` /// or None if the requested Enum-Type or -Element does not exist pub fn find_enum_element(&self, enum_name: &str, element_name: &str) -> Option<&VariableIndexEntry> { - self.enum_qualified_variables.get(&format!("{enum_name}.{element_name}").to_lowercase()) + self.enum_qualified_variables.get(&qualified_name(enum_name, element_name).to_lowercase()) } /// returns the index entry of the enum-element denoted by the given fully `qualified_name` (e.g. "Color.RED") @@ -1275,7 +1276,7 @@ impl Index { pub fn register_program(&mut self, name: &str, location: SymbolLocation, linkage: LinkageType) { let instance_variable = - VariableIndexEntry::create_global(&format!("{}_instance", &name), name, name, location.clone()) + VariableIndexEntry::create_global(&format!("{}_instance", &name), name, name, location.clone()) // TODO: Naming convention (see plc_util/src/convention.rs) .set_linkage(linkage); // self.register_global_variable(name, instance_variable.clone()); let entry = PouIndexEntry::create_program_entry(name, instance_variable, linkage, location); @@ -1316,7 +1317,7 @@ impl Index { let variable_type = member_info.variable_linkage; let data_type_name = member_info.variable_type_name; - let qualified_name = format!("{container_name}.{variable_name}"); + let qualified_name = qualified_name(container_name, variable_name); VariableIndexEntry::new( variable_name, @@ -1339,7 +1340,7 @@ impl Index { initial_value: Option, source_location: SymbolLocation, ) { - let qualified_name = format!("{enum_type_name}.{element_name}"); + let qualified_name = qualified_name(enum_type_name, element_name); let entry = VariableIndexEntry::create_global(element_name, &qualified_name, enum_type_name, source_location) .set_constant(true) diff --git a/src/index/const_expressions.rs b/src/index/const_expressions.rs index 18294edaff..9dd038dfab 100644 --- a/src/index/const_expressions.rs +++ b/src/index/const_expressions.rs @@ -1,7 +1,10 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::ast::{AstLiteral, AstStatement, SourceRange}; use generational_arena::{Arena, Iter}; +use plc_ast::{ + ast::{AstStatement, SourceRange}, + literals::AstLiteral, +}; pub type ConstId = generational_arena::Index; diff --git a/src/index/symbol.rs b/src/index/symbol.rs index 06c9910a41..8937bc0ba1 100644 --- a/src/index/symbol.rs +++ b/src/index/symbol.rs @@ -1,7 +1,7 @@ // Copyright (c) 2022 Ghaith Hachem and Mathias Rieder -use crate::ast::{NewLines, SourceRange}; use indexmap::IndexMap; +use plc_ast::ast::{NewLines, SourceRange}; use std::hash::Hash; /// Location information of a Symbol in the index consisting of the line_number diff --git a/src/index/tests/builtin_tests.rs b/src/index/tests/builtin_tests.rs index 53aabfbb37..13126fbb8d 100644 --- a/src/index/tests/builtin_tests.rs +++ b/src/index/tests/builtin_tests.rs @@ -1,4 +1,6 @@ -use crate::{builtins, lexer::IdProvider, test_utils::tests::index}; +use plc_ast::provider::IdProvider; + +use crate::{builtins, test_utils::tests::index}; #[test] fn builtin_functions_added_to_index() { diff --git a/src/index/tests/generic_tests.rs b/src/index/tests/generic_tests.rs index 54c5343f21..c8de2ca487 100644 --- a/src/index/tests/generic_tests.rs +++ b/src/index/tests/generic_tests.rs @@ -1,6 +1,7 @@ +use plc_ast::ast::{GenericBinding, TypeNature}; use pretty_assertions::assert_eq; -use crate::{ast::GenericBinding, index::PouIndexEntry, test_utils::tests::index}; +use crate::{index::PouIndexEntry, test_utils::tests::index}; #[test] fn generics_saved_in_index() { @@ -14,7 +15,7 @@ fn generics_saved_in_index() { assert!(foo_info.is_generic()); if let PouIndexEntry::Function { generics, .. } = foo_info { let t = &generics[0]; - assert_eq!(&GenericBinding { name: "T".into(), nature: crate::ast::TypeNature::Any }, t); + assert_eq!(&GenericBinding { name: "T".into(), nature: TypeNature::Any }, t); } else { panic!("{foo_info:#?} not a generic function"); } diff --git a/src/index/tests/index_tests.rs b/src/index/tests/index_tests.rs index 92cd123054..b2d0cbc50d 100644 --- a/src/index/tests/index_tests.rs +++ b/src/index/tests/index_tests.rs @@ -1,12 +1,17 @@ +use plc_ast::ast::{ + pre_process, AstStatement, DataType, DataTypeDeclaration, GenericBinding, LinkageType, Operator, + SourceRange, SourceRangeFactory, TypeNature, UserTypeDeclaration, Variable, +}; +use plc_ast::literals::AstLiteral; +use plc_ast::provider::IdProvider; // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder use pretty_assertions::assert_eq; use crate::index::{ArgumentType, PouIndexEntry, SymbolLocation, VariableIndexEntry}; -use crate::lexer::IdProvider; use crate::parser::tests::literal_int; use crate::test_utils::tests::{annotate_with_ids, index, index_with_ids, parse_and_preprocess}; use crate::typesystem::{InternalType, StructSource, TypeSize, INT_TYPE, VOID_TYPE}; -use crate::{ast::*, index::VariableType, typesystem::DataTypeInformation}; +use crate::{index::VariableType, typesystem::DataTypeInformation}; #[test] fn index_not_case_sensitive() { @@ -1334,7 +1339,7 @@ fn global_initializers_are_stored_in_the_const_expression_arena() { "test.st", ); - crate::ast::pre_process(&mut ast, ids); + pre_process(&mut ast, ids); let index = crate::index::visitor::visit(&ast); // THEN I expect the index to contain cosntant expressions (x+1), (y+1) and (z+1) as const expressions @@ -1376,7 +1381,7 @@ fn local_initializers_are_stored_in_the_const_expression_arena() { "test.st", ); - crate::ast::pre_process(&mut ast, ids); + pre_process(&mut ast, ids); let index = crate::index::visitor::visit(&ast); // THEN I expect the index to contain cosntant expressions (x+1), (y+1) and (z+1) as const expressions @@ -1412,7 +1417,7 @@ fn datatype_initializers_are_stored_in_the_const_expression_arena() { "test.st", ); - crate::ast::pre_process(&mut ast, ids); + pre_process(&mut ast, ids); let index = crate::index::visitor::visit(&ast); // THEN I expect the index to contain cosntant expressions (7+x) as const expressions @@ -1439,7 +1444,7 @@ fn array_dimensions_are_stored_in_the_const_expression_arena() { "test.st", ); - crate::ast::pre_process(&mut ast, ids); + pre_process(&mut ast, ids); let index = crate::index::visitor::visit(&ast); // THEN I expect the index to contain constants expressions used in the array-dimensions @@ -1509,7 +1514,7 @@ fn string_dimensions_are_stored_in_the_const_expression_arena() { "test.st", ); - crate::ast::pre_process(&mut ast, ids); + pre_process(&mut ast, ids); let index = crate::index::visitor::visit(&ast); // THEN I expect the index to contain constants expressions used in the string-len diff --git a/src/index/visitor.rs b/src/index/visitor.rs index 86fe3ad05f..9546fad62c 100644 --- a/src/index/visitor.rs +++ b/src/index/visitor.rs @@ -1,14 +1,15 @@ use super::symbol::{SymbolLocation, SymbolLocationFactory}; // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder use super::{HardwareBinding, PouIndexEntry, VariableIndexEntry, VariableType}; -use crate::ast::AstLiteral; -use crate::ast::{ - self, ArgumentProperty, AstStatement, CompilationUnit, DataType, DataTypeDeclaration, Implementation, - Pou, PouType, SourceRange, TypeNature, UserTypeDeclaration, Variable, VariableBlock, VariableBlockType, -}; use crate::diagnostics::Diagnostic; use crate::index::{ArgumentType, Index, MemberInfo}; use crate::typesystem::{self, *}; +use plc_ast::ast::{ + self, ArgumentProperty, AstStatement, CompilationUnit, DataType, DataTypeDeclaration, Implementation, + Pou, PouType, SourceRange, TypeNature, UserTypeDeclaration, Variable, VariableBlock, VariableBlockType, +}; +use plc_ast::literals::AstLiteral; +use plc_util::convention::internal_type_name; pub fn visit(unit: &CompilationUnit) -> Index { let mut index = Index::default(); @@ -64,41 +65,40 @@ pub fn visit_pou(index: &mut Index, pou: &Pou, symbol_location_factory: &SymbolL member_varargs = varargs.clone(); } - if let Some(var_type_name) = var.data_type_declaration.get_name() { - let type_name = if block_type.is_by_ref() { - //register a pointer type for argument - register_byref_pointer_type_for(index, var_type_name) - } else { - var_type_name.to_string() - }; - let initial_value = index.get_mut_const_expressions().maybe_add_constant_expression( - var.initializer.clone(), - type_name.as_str(), - Some(pou.name.clone()), - ); - - let binding = var - .address - .as_ref() - .and_then(|it| HardwareBinding::from_statement(index, it, Some(pou.name.clone()))); - - let entry = index.register_member_variable( - MemberInfo { - container_name: &pou.name, - variable_name: &var.name, - variable_linkage: block_type, - variable_type_name: &type_name, - is_constant: block.constant, - binding, - varargs, - }, - initial_value, - symbol_location_factory.create_symbol_location(&var.location), - count, - ); - members.push(entry); - count += 1; + let var_type_name = var.data_type_declaration.get_name().unwrap_or(VOID_TYPE); + let type_name = if block_type.is_by_ref() { + //register a pointer type for argument + register_byref_pointer_type_for(index, var_type_name) + } else { + var_type_name.to_string() }; + let initial_value = index.get_mut_const_expressions().maybe_add_constant_expression( + var.initializer.clone(), + type_name.as_str(), + Some(pou.name.clone()), + ); + + let binding = var + .address + .as_ref() + .and_then(|it| HardwareBinding::from_statement(index, it, Some(pou.name.clone()))); + + let entry = index.register_member_variable( + MemberInfo { + container_name: &pou.name, + variable_name: &var.name, + variable_linkage: block_type, + variable_type_name: &type_name, + is_constant: block.constant, + binding, + varargs, + }, + initial_value, + symbol_location_factory.create_symbol_location(&var.location), + count, + ); + members.push(entry); + count += 1; } } @@ -269,7 +269,7 @@ fn visit_implementation( /// registers an auto-deref pointer type for the inner_type_name if it does not already exist fn register_byref_pointer_type_for(index: &mut Index, inner_type_name: &str) -> String { //get unique name - let type_name = typesystem::create_internal_type_name("auto_pointer_to_", inner_type_name); + let type_name = internal_type_name("auto_pointer_to_", inner_type_name); //check if type was already created if index.find_effective_type_by_name(type_name.as_str()).is_none() { diff --git a/src/lexer.rs b/src/lexer.rs index ddb43c04e9..2331e1f967 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -3,17 +3,11 @@ use core::ops::Range; use logos::Filter; use logos::Lexer; use logos::Logos; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; -use std::sync::Arc; +use plc_ast::provider::IdProvider; pub use tokens::Token; -use crate::ast::AstId; -use crate::ast::DirectAccessType; -use crate::ast::HardwareAccessType; -use crate::ast::SourceRange; -use crate::ast::SourceRangeFactory; use crate::Diagnostic; +use plc_ast::ast::{AstId, DirectAccessType, HardwareAccessType, SourceRange, SourceRangeFactory}; #[cfg(test)] mod tests; @@ -303,11 +297,11 @@ fn parse_access_type(lexer: &mut Lexer) -> Option { .chars() .nth(1) .and_then(|c| match c.to_ascii_lowercase() { - 'x' => Some(crate::ast::DirectAccessType::Bit), - 'b' => Some(crate::ast::DirectAccessType::Byte), - 'w' => Some(crate::ast::DirectAccessType::Word), - 'd' => Some(crate::ast::DirectAccessType::DWord), - 'l' => Some(crate::ast::DirectAccessType::LWord), + 'x' => Some(DirectAccessType::Bit), + 'b' => Some(DirectAccessType::Byte), + 'w' => Some(DirectAccessType::Word), + 'd' => Some(DirectAccessType::DWord), + 'l' => Some(DirectAccessType::LWord), _ => None, }) .expect("Unknown access type - tokenizer/grammar incomplete?"); @@ -322,10 +316,10 @@ fn parse_hardware_access_type(lexer: &mut Lexer) -> Option<(HardwareAcces .chars() .nth(1) .and_then(|c| match c.to_ascii_lowercase() { - 'i' => Some(crate::ast::HardwareAccessType::Input), - 'q' => Some(crate::ast::HardwareAccessType::Output), - 'm' => Some(crate::ast::HardwareAccessType::Memory), - 'g' => Some(crate::ast::HardwareAccessType::Global), + 'i' => Some(HardwareAccessType::Input), + 'q' => Some(HardwareAccessType::Output), + 'm' => Some(HardwareAccessType::Memory), + 'g' => Some(HardwareAccessType::Global), _ => None, }) .expect("Unknown access type - tokenizer/grammar incomplete?"); @@ -335,12 +329,12 @@ fn parse_hardware_access_type(lexer: &mut Lexer) -> Option<(HardwareAcces .chars() .nth(2) .and_then(|c| match c.to_ascii_lowercase() { - 'x' => Some(crate::ast::DirectAccessType::Bit), - 'b' => Some(crate::ast::DirectAccessType::Byte), - 'w' => Some(crate::ast::DirectAccessType::Word), - 'd' => Some(crate::ast::DirectAccessType::DWord), - 'l' => Some(crate::ast::DirectAccessType::LWord), - '*' => Some(crate::ast::DirectAccessType::Template), + 'x' => Some(DirectAccessType::Bit), + 'b' => Some(DirectAccessType::Byte), + 'w' => Some(DirectAccessType::Word), + 'd' => Some(DirectAccessType::DWord), + 'l' => Some(DirectAccessType::LWord), + '*' => Some(DirectAccessType::Template), _ => None, }) .expect("Unknown access type - tokenizer/grammar incomplete?"); @@ -348,24 +342,6 @@ fn parse_hardware_access_type(lexer: &mut Lexer) -> Option<(HardwareAcces Some((hardware_type, access)) } -#[derive(Clone)] -//TODO: This belongs to the AST -pub struct IdProvider { - current_id: Arc, -} - -impl IdProvider { - pub fn next_id(&mut self) -> AstId { - self.current_id.fetch_add(1, Ordering::Relaxed) - } -} - -impl Default for IdProvider { - fn default() -> Self { - IdProvider { current_id: Arc::new(AtomicUsize::new(1)) } - } -} - #[cfg(test)] pub fn lex(source: &str) -> ParseSession { ParseSession::new(Token::lexer(source), IdProvider::default(), SourceRangeFactory::internal()) @@ -378,22 +354,3 @@ pub fn lex_with_ids( ) -> ParseSession { ParseSession::new(Token::lexer(source), id_provider, location_factory) } - -#[cfg(test)] -mod id_tests { - use super::IdProvider; - - #[test] - fn id_provider_generates_unique_ids_over_clones() { - let mut id1 = IdProvider::default(); - - assert_eq!(id1.next_id(), 1); - - let mut id2 = id1.clone(); - assert_eq!(id2.next_id(), 2); - - assert_eq!(id1.next_id(), 3); - - assert_eq!(id2.next_id(), 4); - } -} diff --git a/src/lexer/tests/lexer_tests.rs b/src/lexer/tests/lexer_tests.rs index 334b7af99a..36c7563d1e 100644 --- a/src/lexer/tests/lexer_tests.rs +++ b/src/lexer/tests/lexer_tests.rs @@ -1,10 +1,9 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder + +use plc_ast::ast::{DirectAccessType, HardwareAccessType, NewLines}; use pretty_assertions::{assert_eq, assert_ne}; -use crate::{ - ast::{DirectAccessType, HardwareAccessType, NewLines}, - lexer::{lex, Token::*}, -}; +use crate::lexer::{lex, Token::*}; #[test] fn generic_properties() { diff --git a/src/lexer/tokens.rs b/src/lexer/tokens.rs index f162df1779..b830474e02 100644 --- a/src/lexer/tokens.rs +++ b/src/lexer/tokens.rs @@ -1,6 +1,6 @@ use logos::Logos; -use crate::ast::{DirectAccessType, HardwareAccessType}; +use plc_ast::ast::{DirectAccessType, HardwareAccessType}; #[derive(Debug, PartialEq, Eq, Logos, Clone)] pub enum Token { diff --git a/src/lib.rs b/src/lib.rs index 2219fbe404..e388711dfc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,6 @@ use resolver::TypeAnnotator; #[cfg(test)] use validation::Validator; -pub mod ast; pub mod builtins; pub mod codegen; mod datalayout; diff --git a/src/parser.rs b/src/parser.rs index 6756218286..41bd3b13f2 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,10 +1,19 @@ +use plc_ast::{ + ast::{ + AccessModifier, ArgumentProperty, AstStatement, CompilationUnit, DataType, DataTypeDeclaration, + DirectAccessType, GenericBinding, HardwareAccessType, Implementation, LinkageType, NewLines, + PolymorphismMode, Pou, PouType, SourceRange, SourceRangeFactory, TypeNature, UserTypeDeclaration, + Variable, VariableBlock, VariableBlockType, + }, + provider::IdProvider, +}; +use plc_util::convention::qualified_name; + // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder use crate::{ - ast::*, diagnostics::Diagnostician, expect_token, - lexer::{self, IdProvider}, - lexer::{ParseSession, Token, Token::*}, + lexer::{self, ParseSession, Token, Token::*}, typesystem::DINT_TYPE, Diagnostic, }; @@ -384,7 +393,7 @@ fn parse_method( variable_blocks.push(parse_variable_block(lexer, LinkageType::Internal)); } - let call_name = format!("{class_name}.{name}"); + let call_name = qualified_name(class_name, &name); let implementation = parse_implementation( lexer, linkage, @@ -498,7 +507,7 @@ fn parse_action( let name = lexer.slice_and_advance(); (name_or_container, name, loc.span(&lexer.last_location())) }; - let call_name = format!("{}.{}", &container, &name); + let call_name = qualified_name(&container, &name); let implementation = parse_implementation( lexer, diff --git a/src/parser/control_parser.rs b/src/parser/control_parser.rs index da60a511bf..ab8727a3ca 100644 --- a/src/parser/control_parser.rs +++ b/src/parser/control_parser.rs @@ -1,6 +1,10 @@ +use plc_ast::{ + ast::{AstFactory, AstStatement}, + control_statements::ConditionalBlock, +}; + // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder use crate::{ - ast::{control_statements::ConditionalBlock, *}, expect_token, lexer::Token::*, parser::{parse_any_in_region, parse_body_in_region}, diff --git a/src/parser/expressions_parser.rs b/src/parser/expressions_parser.rs index d006a461bc..a7477f6762 100644 --- a/src/parser/expressions_parser.rs +++ b/src/parser/expressions_parser.rs @@ -1,13 +1,16 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder use crate::{ - ast::*, lexer::Token::*, lexer::{ParseSession, Token}, parser::parse_any_in_region, Diagnostic, }; use core::str::Split; +use plc_ast::{ + ast::{AstId, AstStatement, DirectAccessType, Operator, SourceRange}, + literals::{AstLiteral, Time}, +}; use regex::{Captures, Regex}; use std::str::FromStr; @@ -401,7 +404,7 @@ pub fn parse_qualified_reference(lexer: &mut ParseSession) -> Result AstStatement { /// helper function to create literal ints pub fn literal_int(value: i128) -> AstStatement { - AstStatement::new_literal(crate::ast::AstLiteral::new_integer(value), 0, SourceRange::undefined()) + AstStatement::new_literal(AstLiteral::new_integer(value), 0, SourceRange::undefined()) } /// helper function to create empty statements diff --git a/src/parser/tests/class_parser_tests.rs b/src/parser/tests/class_parser_tests.rs index 5e4c411234..1403c193fd 100644 --- a/src/parser/tests/class_parser_tests.rs +++ b/src/parser/tests/class_parser_tests.rs @@ -1,4 +1,6 @@ -use crate::{ast::*, test_utils::tests::parse}; +use plc_ast::ast::{AccessModifier, ArgumentProperty, PolymorphismMode, PouType, VariableBlockType}; + +use crate::test_utils::tests::parse; #[test] fn simple_class_with_defaults_can_be_parsed() { diff --git a/src/parser/tests/control_parser_tests.rs b/src/parser/tests/control_parser_tests.rs index c1cfc12c92..8e2e9655bf 100644 --- a/src/parser/tests/control_parser_tests.rs +++ b/src/parser/tests/control_parser_tests.rs @@ -1,7 +1,9 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::ast::control_statements::{AstControlStatement, ForLoopStatement, IfStatement}; -use crate::ast::AstStatement; use crate::test_utils::tests::parse; +use plc_ast::{ + ast::AstStatement, + control_statements::{AstControlStatement, ForLoopStatement, IfStatement}, +}; use pretty_assertions::*; #[test] diff --git a/src/parser/tests/expressions_parser_tests.rs b/src/parser/tests/expressions_parser_tests.rs index 9b28ac3bc7..38867d3eff 100644 --- a/src/parser/tests/expressions_parser_tests.rs +++ b/src/parser/tests/expressions_parser_tests.rs @@ -1,10 +1,12 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::ast::{ - AstLiteral, AstStatement, DataType, DataTypeDeclaration, DirectAccessType, Operator, Pou, SourceRange, -}; use crate::parser::tests::{literal_int, ref_to}; use crate::test_utils::tests::parse; use insta::assert_snapshot; +use plc_ast::ast::{ + AstStatement, DataType, DataTypeDeclaration, DirectAccessType, LinkageType, Operator, Pou, PouType, + SourceRange, +}; +use plc_ast::literals::AstLiteral; use pretty_assertions::*; #[test] @@ -2802,7 +2804,7 @@ fn sized_string_as_function_return() { let expected = Pou { name: "foo".into(), poly_mode: None, - pou_type: crate::ast::PouType::Function, + pou_type: PouType::Function, return_type: Some(DataTypeDeclaration::DataTypeDefinition { data_type: DataType::StringType { name: None, @@ -2820,7 +2822,7 @@ fn sized_string_as_function_return() { location: SourceRange::undefined(), name_location: SourceRange::undefined(), generics: vec![], - linkage: crate::ast::LinkageType::Internal, + linkage: LinkageType::Internal, }; assert_eq!(format!("{:?}", ast.units[0]), format!("{expected:?}")); @@ -2839,7 +2841,7 @@ fn array_type_as_function_return() { let expected = Pou { name: "foo".into(), poly_mode: None, - pou_type: crate::ast::PouType::Function, + pou_type: PouType::Function, return_type: Some(DataTypeDeclaration::DataTypeDefinition { data_type: DataType::ArrayType { referenced_type: Box::new(DataTypeDeclaration::DataTypeReference { @@ -2869,7 +2871,7 @@ fn array_type_as_function_return() { location: SourceRange::undefined(), name_location: SourceRange::undefined(), generics: vec![], - linkage: crate::ast::LinkageType::Internal, + linkage: LinkageType::Internal, }; assert_eq!(format!("{:?}", ast.units[0]), format!("{expected:?}")); diff --git a/src/parser/tests/function_parser_tests.rs b/src/parser/tests/function_parser_tests.rs index f25a165023..3a864b8710 100644 --- a/src/parser/tests/function_parser_tests.rs +++ b/src/parser/tests/function_parser_tests.rs @@ -1,4 +1,8 @@ -use crate::{ast::*, parser::tests::ref_to, test_utils::tests::parse, typesystem::DINT_TYPE, Diagnostic}; +use crate::{parser::tests::ref_to, test_utils::tests::parse, typesystem::DINT_TYPE, Diagnostic}; +use plc_ast::ast::{ + AccessModifier, ArgumentProperty, AstStatement, DataType, DataTypeDeclaration, LinkageType, Pou, PouType, + SourceRange, Variable, VariableBlock, VariableBlockType, +}; use pretty_assertions::*; #[test] @@ -237,7 +241,7 @@ fn varargs_parameters_can_be_parsed() { name_location: SourceRange::undefined(), poly_mode: None, generics: vec![], - linkage: crate::ast::LinkageType::Internal, + linkage: LinkageType::Internal, }; assert_eq!(format!("{expected:#?}"), format!("{x:#?}").as_str()); } @@ -306,7 +310,7 @@ fn sized_varargs_parameters_can_be_parsed() { name_location: SourceRange::undefined(), poly_mode: None, generics: vec![], - linkage: crate::ast::LinkageType::Internal, + linkage: LinkageType::Internal, }; assert_eq!(format!("{expected:#?}"), format!("{x:#?}").as_str()); } diff --git a/src/parser/tests/misc_parser_tests.rs b/src/parser/tests/misc_parser_tests.rs index 8cda2684a3..75c9294172 100644 --- a/src/parser/tests/misc_parser_tests.rs +++ b/src/parser/tests/misc_parser_tests.rs @@ -1,12 +1,17 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::{ - ast::control_statements::{AstControlStatement, ForLoopStatement, IfStatement, LoopStatement}, - Diagnostic, -}; +use crate::Diagnostic; use core::panic; use std::ops::Range; -use crate::{ast::*, parser::tests::empty_stmt, test_utils::tests::parse}; +use crate::{parser::tests::empty_stmt, test_utils::tests::parse}; +use plc_ast::{ + ast::{ + AccessModifier, ArgumentProperty, AstFactory, AstStatement, DataTypeDeclaration, Implementation, + LinkageType, Operator, Pou, PouType, SourceRange, Variable, VariableBlock, VariableBlockType, + }, + control_statements::{AstControlStatement, CaseStatement, ForLoopStatement, IfStatement, LoopStatement}, + literals::AstLiteral, +}; use pretty_assertions::*; #[test] @@ -66,7 +71,7 @@ fn exponent_literals_parsed_as_variables() { location: SourceRange::undefined(), name_location: SourceRange::undefined(), generics: vec![], - linkage: crate::ast::LinkageType::Internal, + linkage: LinkageType::Internal, }; assert_eq!(format!("{expected:#?}"), format!("{pou:#?}").as_str()); let implementation = &parse_result.implementations[0]; @@ -416,13 +421,7 @@ fn ids_are_assigned_to_case_statements() { match &implementation.statements[0] { AstStatement::ControlStatement { - kind: - AstControlStatement::Case(control_statements::CaseStatement { - case_blocks, - else_block, - selector, - .. - }), + kind: AstControlStatement::Case(CaseStatement { case_blocks, else_block, selector, .. }), .. } => { //1st case block diff --git a/src/parser/tests/parse_errors/parse_error_containers_tests.rs b/src/parser/tests/parse_errors/parse_error_containers_tests.rs index aae47950af..97a114a8a7 100644 --- a/src/parser/tests/parse_errors/parse_error_containers_tests.rs +++ b/src/parser/tests/parse_errors/parse_error_containers_tests.rs @@ -1,5 +1,9 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::{ast::*, lexer::Token, test_utils::tests::parse, Diagnostic}; +use crate::{lexer::Token, test_utils::tests::parse, Diagnostic}; +use plc_ast::ast::{ + AccessModifier, AstStatement, DataTypeDeclaration, LinkageType, PouType, SourceRange, Variable, + VariableBlock, VariableBlockType, +}; use pretty_assertions::*; /* @@ -218,6 +222,7 @@ fn unclosed_var_container() { vec![Diagnostic::unexpected_token_found("KeywordEndVar", "'VAR b : INT;'", (82..94).into(),)], diagnostics ); + //check if b was parsed successfully let var_block = &compilation_unit.units[0].variable_blocks[0]; assert_eq!( @@ -232,7 +237,7 @@ fn unclosed_var_container() { location: SourceRange::undefined(), variables: vec![Variable { name: "a".into(), - data_type_declaration: crate::ast::DataTypeDeclaration::DataTypeReference { + data_type_declaration: DataTypeDeclaration::DataTypeReference { referenced_type: "INT".into(), location: SourceRange::undefined(), }, diff --git a/src/parser/tests/parse_errors/parse_error_literals_tests.rs b/src/parser/tests/parse_errors/parse_error_literals_tests.rs index 430c085edb..47aa398ba4 100644 --- a/src/parser/tests/parse_errors/parse_error_literals_tests.rs +++ b/src/parser/tests/parse_errors/parse_error_literals_tests.rs @@ -1,4 +1,9 @@ -use crate::{ast::*, test_utils::tests::parse, Diagnostic}; +use plc_ast::{ + ast::{AstStatement, DataType, SourceRange, UserTypeDeclaration}, + literals::AstLiteral, +}; + +use crate::{test_utils::tests::parse, Diagnostic}; #[test] fn illegal_literal_time_missing_segments_test() { diff --git a/src/parser/tests/parse_errors/parse_error_statements_tests.rs b/src/parser/tests/parse_errors/parse_error_statements_tests.rs index 71aa32a956..39a30483fc 100644 --- a/src/parser/tests/parse_errors/parse_error_statements_tests.rs +++ b/src/parser/tests/parse_errors/parse_error_statements_tests.rs @@ -1,5 +1,9 @@ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder -use crate::{ast::*, lexer::Token, parser::tests::ref_to, test_utils::tests::parse, Diagnostic}; +use crate::{lexer::Token, parser::tests::ref_to, test_utils::tests::parse, Diagnostic}; +use plc_ast::ast::{ + AccessModifier, AstStatement, DataType, DataTypeDeclaration, LinkageType, SourceRange, + UserTypeDeclaration, Variable, VariableBlock, VariableBlockType, +}; use pretty_assertions::*; /* diff --git a/src/parser/tests/parse_generics.rs b/src/parser/tests/parse_generics.rs index 0ad4ffae0d..2c208e0578 100644 --- a/src/parser/tests/parse_generics.rs +++ b/src/parser/tests/parse_generics.rs @@ -1,4 +1,5 @@ -use crate::ast::{DataTypeDeclaration, GenericBinding, TypeNature, Variable}; +use plc_ast::ast::{DataTypeDeclaration, GenericBinding, TypeNature, Variable}; + use crate::test_utils::tests::parse; #[test] diff --git a/src/parser/tests/program_parser_tests.rs b/src/parser/tests/program_parser_tests.rs index 45650107c6..962792e077 100644 --- a/src/parser/tests/program_parser_tests.rs +++ b/src/parser/tests/program_parser_tests.rs @@ -1,4 +1,6 @@ -use crate::{ast::*, test_utils::tests::parse}; +use plc_ast::ast::{LinkageType, PouType}; + +use crate::test_utils::tests::parse; #[test] fn simple_foo_program_can_be_parsed() { diff --git a/src/parser/tests/statement_parser_tests.rs b/src/parser/tests/statement_parser_tests.rs index 3036dbcece..142b7ae473 100644 --- a/src/parser/tests/statement_parser_tests.rs +++ b/src/parser/tests/statement_parser_tests.rs @@ -1,10 +1,6 @@ -use crate::{ - ast::{AstStatement, DataType, DataTypeDeclaration, SourceRange, Variable}, - parser::tests::ref_to, - test_utils::tests::parse, - typesystem::DINT_TYPE, -}; +use crate::{parser::tests::ref_to, test_utils::tests::parse, typesystem::DINT_TYPE}; use insta::assert_snapshot; +use plc_ast::ast::{AstStatement, DataType, DataTypeDeclaration, SourceRange, Variable}; use pretty_assertions::*; #[test] diff --git a/src/parser/tests/type_parser_tests.rs b/src/parser/tests/type_parser_tests.rs index 2c26bcce69..dca02440c2 100644 --- a/src/parser/tests/type_parser_tests.rs +++ b/src/parser/tests/type_parser_tests.rs @@ -1,4 +1,8 @@ -use crate::{ast::*, test_utils::tests::parse, Diagnostic}; +use crate::{test_utils::tests::parse, Diagnostic}; +use plc_ast::{ + ast::{AstStatement, DataType, DataTypeDeclaration, SourceRange, UserTypeDeclaration, Variable}, + literals::AstLiteral, +}; use pretty_assertions::*; #[test] diff --git a/src/parser/tests/variable_parser_tests.rs b/src/parser/tests/variable_parser_tests.rs index bf12458e57..524e7650db 100644 --- a/src/parser/tests/variable_parser_tests.rs +++ b/src/parser/tests/variable_parser_tests.rs @@ -1,7 +1,6 @@ -use crate::{ - ast::{LinkageType, VariableBlock}, - test_utils::tests::parse, -}; +use plc_ast::ast::{LinkageType, VariableBlock}; + +use crate::test_utils::tests::parse; #[test] fn empty_global_vars_can_be_parsed() { diff --git a/src/resolver.rs b/src/resolver.rs index 738df53f68..fb6c404bb4 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -11,19 +11,23 @@ use std::{ }; use indexmap::{IndexMap, IndexSet}; +use plc_ast::{ + ast::{ + self, flatten_expression_list, AstFactory, AstId, AstStatement, CompilationUnit, DataType, + DataTypeDeclaration, DirectAccessType, Operator, Pou, TypeNature, UserTypeDeclaration, Variable, + }, + control_statements::AstControlStatement, + literals::{Array, AstLiteral, StringValue}, + provider::IdProvider, +}; +use plc_util::convention::{internal_type_name, qualified_name}; pub mod const_evaluator; pub mod generics; use crate::{ - ast::{ - self, control_statements::AstControlStatement, flatten_expression_list, Array, AstFactory, AstId, - AstLiteral, AstStatement, CompilationUnit, DataType, DataTypeDeclaration, Operator, Pou, StringValue, - TypeNature, UserTypeDeclaration, Variable, - }, builtins::{self, BuiltIn}, index::{symbol::SymbolLocation, ArgumentType, Index, PouIndexEntry, VariableIndexEntry, VariableType}, - lexer::IdProvider, typesystem::{ self, get_bigger_type, DataTypeInformation, InternalType, StringEncoding, StructSource, BOOL_TYPE, BYTE_TYPE, DATE_AND_TIME_TYPE, DATE_TYPE, DINT_TYPE, DWORD_TYPE, LINT_TYPE, LREAL_TYPE, LWORD_TYPE, @@ -1255,11 +1259,7 @@ impl<'i> TypeAnnotator<'i> { .or_else(|| self.index.find_enum_element(qualifier, name.as_str())) // 3rd try - look for a method qualifier.name .map_or_else( - || { - self.index - .find_pou(format!("{qualifier}.{name}").as_str()) - .map(|it| it.into()) - }, + || self.index.find_pou(&qualified_name(qualifier, name)).map(|it| it.into()), |v| Some(to_variable_annotation(v, self.index, ctx.constant)), ) } else { @@ -1295,16 +1295,14 @@ impl<'i> TypeAnnotator<'i> { .or_else(|| { // try to find a local action with this name self.index - .find_pou(format!("{qualifier}.{name}").as_str()) + .find_pou(&qualified_name(qualifier, name)) .map(StatementAnnotation::from) }) }) .or_else(|| { // ... then try if we find a scoped-pou with that name (maybe it's a call to a local method or action?) ctx.pou.and_then(|pou_name| self.index.find_pou(pou_name)).and_then(|it| { - self.index - .find_pou(format!("{}.{name}", it.get_container()).as_str()) - .map(Into::into) + self.index.find_pou(&qualified_name(it.get_container(), name)).map(Into::into) }) }) .or_else(|| { @@ -1745,21 +1743,21 @@ impl<'i> TypeAnnotator<'i> { } } -fn get_direct_access_type(access: &crate::ast::DirectAccessType) -> &'static str { +fn get_direct_access_type(access: &DirectAccessType) -> &'static str { match access { - crate::ast::DirectAccessType::Bit => BOOL_TYPE, - crate::ast::DirectAccessType::Byte => BYTE_TYPE, - crate::ast::DirectAccessType::Word => WORD_TYPE, - crate::ast::DirectAccessType::DWord => DWORD_TYPE, - crate::ast::DirectAccessType::LWord => LWORD_TYPE, - crate::ast::DirectAccessType::Template => VOID_TYPE, + DirectAccessType::Bit => BOOL_TYPE, + DirectAccessType::Byte => BYTE_TYPE, + DirectAccessType::Word => WORD_TYPE, + DirectAccessType::DWord => DWORD_TYPE, + DirectAccessType::LWord => LWORD_TYPE, + DirectAccessType::Template => VOID_TYPE, } } /// adds a string-type to the given index and returns it's name fn register_string_type(index: &mut Index, is_wide: bool, len: usize) -> String { let prefix = if is_wide { "WSTRING_" } else { "STRING_" }; - let new_type_name = typesystem::create_internal_type_name(prefix, len.to_string().as_str()); + let new_type_name = internal_type_name(prefix, len.to_string().as_str()); if index.find_effective_type_by_name(new_type_name.as_str()).is_none() { index.register_type(crate::typesystem::DataType { @@ -1778,7 +1776,7 @@ fn register_string_type(index: &mut Index, is_wide: bool, len: usize) -> String /// adds a pointer to the given inner_type to the given index and return's its name pub(crate) fn add_pointer_type(index: &mut Index, inner_type_name: String) -> String { - let new_type_name = typesystem::create_internal_type_name("POINTER_TO_", inner_type_name.as_str()); + let new_type_name = internal_type_name("POINTER_TO_", inner_type_name.as_str()); if index.find_effective_type_by_name(new_type_name.as_str()).is_none() { index.register_type(crate::typesystem::DataType { diff --git a/src/resolver/const_evaluator.rs b/src/resolver/const_evaluator.rs index 79af62ee66..930f416249 100644 --- a/src/resolver/const_evaluator.rs +++ b/src/resolver/const_evaluator.rs @@ -1,8 +1,6 @@ use std::collections::VecDeque; use crate::{ - ast::literals::{Array, AstLiteral, StringValue}, - ast::{AstId, AstStatement, Operator, SourceRange}, index::{ const_expressions::{ConstExpression, ConstId, UnresolvableKind}, Index, @@ -740,3 +738,7 @@ macro_rules! compare_expression { } } use compare_expression; +use plc_ast::{ + ast::{AstId, AstStatement, Operator, SourceRange}, + literals::{Array, AstLiteral, StringValue}, +}; diff --git a/src/resolver/generics.rs b/src/resolver/generics.rs index d517f362d8..76c90050c4 100644 --- a/src/resolver/generics.rs +++ b/src/resolver/generics.rs @@ -1,12 +1,16 @@ use std::collections::HashMap; +use plc_ast::ast::{flatten_expression_list, AstStatement, GenericBinding, LinkageType, TypeNature}; + use crate::{ - ast::{self, AstStatement, GenericBinding, LinkageType, TypeNature}, builtins, codegen::generators::expression_generator::get_implicit_call_parameter, index::{symbol::SymbolLocation, Index, PouIndexEntry}, resolver::AnnotationMap, - typesystem::{self, DataType, DataTypeInformation, StringEncoding, STRING_TYPE, WSTRING_TYPE}, + typesystem::{ + self, DataType, DataTypeInformation, StringEncoding, BOOL_TYPE, CHAR_TYPE, DATE_TYPE, REAL_TYPE, + SINT_TYPE, STRING_TYPE, TIME_TYPE, USINT_TYPE, WSTRING_TYPE, + }, }; use super::{AnnotationMapImpl, StatementAnnotation, TypeAnnotator, VisitorContext}; @@ -204,7 +208,7 @@ impl<'i> TypeAnnotator<'i> { // generic. We first resolve the generic type, then create a new pointer type of // the combination let inner_type_name = self.find_or_create_datatype(inner_type_name, generics); - let name = format!("{name}__{inner_type_name}"); + let name = format!("{name}__{inner_type_name}"); // TODO: Naming convention (see plc_util/src/convention.rs) let new_type_info = DataTypeInformation::Pointer { name: name.clone(), inner_type_name, auto_deref: true }; @@ -242,7 +246,7 @@ impl<'i> TypeAnnotator<'i> { // separate variadic and non variadic parameters let mut passed_parameters = Vec::new(); let mut variadic_parameters = Vec::new(); - for (i, p) in ast::flatten_expression_list(s).iter().enumerate() { + for (i, p) in flatten_expression_list(s).iter().enumerate() { if let Ok((location_in_parent, passed_parameter, ..)) = get_implicit_call_parameter(p, &declared_parameters, i) { @@ -359,7 +363,7 @@ impl<'i> TypeAnnotator<'i> { let mut generic_map: HashMap = HashMap::new(); for GenericBinding { name, nature } in generics { let smallest_possible_type = - self.index.find_effective_type_info(nature.get_smallest_possible_type()); + self.index.find_effective_type_info(get_smallest_possible_type(nature)); //Get the current binding if let Some(candidates) = generics_candidates.get(name) { //Find the best suiting type @@ -436,7 +440,7 @@ pub fn generic_name_resolver( .map(|it| { generic_map.get(&it.name).map(|it| it.derived_type.as_str()).unwrap_or_else(|| it.name.as_str()) }) - .fold(qualified_name.to_string(), |accum, s| format!("{accum}__{s}")) + .fold(qualified_name.to_string(), |accum, s| format!("{accum}__{s}")) // TODO: Naming convention (see plc_util/src/convention.rs) } /// This method returns the qualified name, but has the same signature as the generic resover to be used in builtins @@ -447,3 +451,18 @@ pub fn no_generic_name_resolver( ) -> String { generic_name_resolver(qualified_name, &[], &HashMap::new()) } + +pub fn get_smallest_possible_type(nature: &TypeNature) -> &str { + match nature { + TypeNature::Magnitude | TypeNature::Num | TypeNature::Int => USINT_TYPE, + TypeNature::Real => REAL_TYPE, + TypeNature::Unsigned => USINT_TYPE, + TypeNature::Signed => SINT_TYPE, + TypeNature::Duration => TIME_TYPE, + TypeNature::Bit => BOOL_TYPE, + TypeNature::Chars | TypeNature::Char => CHAR_TYPE, + TypeNature::String => STRING_TYPE, + TypeNature::Date => DATE_TYPE, + _ => "", + } +} diff --git a/src/resolver/tests/const_resolver_tests.rs b/src/resolver/tests/const_resolver_tests.rs index a4c4b0118e..b5dd697575 100644 --- a/src/resolver/tests/const_resolver_tests.rs +++ b/src/resolver/tests/const_resolver_tests.rs @@ -1,8 +1,10 @@ -use crate::ast::{Array, AstLiteral, AstStatement, SourceRange}; +use plc_ast::ast::{AstStatement, SourceRange}; +use plc_ast::literals::{Array, AstLiteral}; +use plc_ast::provider::IdProvider; + use crate::index::const_expressions::ConstExpression; use crate::index::Index; -use crate::lexer::IdProvider; use crate::resolver::const_evaluator::{evaluate_constants, UnresolvableConstant}; use crate::resolver::AnnotationMap; use crate::test_utils::tests::{annotate_with_ids, codegen, index, index_with_ids}; diff --git a/src/resolver/tests/resolve_control_statments.rs b/src/resolver/tests/resolve_control_statments.rs index e7aceb4ccd..4f383ac67b 100644 --- a/src/resolver/tests/resolve_control_statments.rs +++ b/src/resolver/tests/resolve_control_statments.rs @@ -1,16 +1,13 @@ use core::panic; -use crate::{ - assert_type_and_hint, - ast::{ - control_statements::{AstControlStatement, ForLoopStatement}, - AstStatement, - }, - lexer::IdProvider, - test_utils::tests::index_with_ids, - TypeAnnotator, +use plc_ast::{ + ast::AstStatement, + control_statements::{AstControlStatement, ForLoopStatement}, + provider::IdProvider, }; +use crate::{assert_type_and_hint, test_utils::tests::index_with_ids, TypeAnnotator}; + #[test] fn binary_expressions_resolves_types() { let id_provider = IdProvider::default(); diff --git a/src/resolver/tests/resolve_expressions_tests.rs b/src/resolver/tests/resolve_expressions_tests.rs index 172228139a..8f5af9bf55 100644 --- a/src/resolver/tests/resolve_expressions_tests.rs +++ b/src/resolver/tests/resolve_expressions_tests.rs @@ -1,15 +1,15 @@ use core::panic; use insta::{assert_debug_snapshot, assert_snapshot}; +use plc_ast::{ + ast::{flatten_expression_list, AstStatement, DataType, Pou, UserTypeDeclaration}, + control_statements::{AstControlStatement, CaseStatement}, + literals::{Array, AstLiteral}, + provider::IdProvider, +}; use crate::{ - ast::{ - self, - control_statements::{AstControlStatement, CaseStatement}, - flatten_expression_list, Array, AstLiteral, AstStatement, DataType, Pou, UserTypeDeclaration, - }, index::{ArgumentType, Index, VariableType}, - lexer::IdProvider, resolver::{AnnotationMap, AnnotationMapImpl, StatementAnnotation}, test_utils::tests::{annotate_with_ids, codegen, index_with_ids}, typesystem::{ @@ -80,8 +80,7 @@ fn binary_expressions_resolves_types_for_mixed_signed_ints() { fn expt_binary_expression() { fn get_params(stmt: &AstStatement) -> (&AstStatement, &AstStatement) { if let AstStatement::CallStatement { parameters, .. } = stmt { - if let &[left, right] = - ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap()).as_slice() + if let &[left, right] = flatten_expression_list(parameters.as_ref().as_ref().unwrap()).as_slice() { return (left, right); } @@ -2565,7 +2564,7 @@ fn literals_passed_to_function_get_annotated() { let call_stmt = &unit.implementations[1].statements[0]; if let AstStatement::CallStatement { parameters, .. } = call_stmt { - let parameters = ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap()); + let parameters = flatten_expression_list(parameters.as_ref().as_ref().unwrap()); assert_type_and_hint!(&annotations, &index, parameters[0], DINT_TYPE, Some(BYTE_TYPE)); assert_type_and_hint!(&annotations, &index, parameters[1], "__STRING_3", Some("STRING")); } else { @@ -3132,7 +3131,7 @@ fn undeclared_varargs_type_hint_promoted_correctly() { let call_stmt = &unit.implementations[1].statements[0]; // THEN types smaller than LREAL/DINT get promoted while booleans and other types stay untouched. if let AstStatement::CallStatement { parameters, .. } = call_stmt { - let parameters = ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap()); + let parameters = flatten_expression_list(parameters.as_ref().as_ref().unwrap()); assert_type_and_hint!(&annotations, &index, parameters[0], REAL_TYPE, Some(LREAL_TYPE)); assert_type_and_hint!(&annotations, &index, parameters[1], LREAL_TYPE, Some(LREAL_TYPE)); assert_type_and_hint!(&annotations, &index, parameters[2], BOOL_TYPE, None); @@ -3174,7 +3173,7 @@ fn passing_a_function_as_param_correctly_resolves_as_variable() { let call_stmt = &unit.implementations[1].statements[0]; // THEN the type of the parameter resolves to the original function type if let AstStatement::CallStatement { parameters, .. } = call_stmt { - let parameters = ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap()); + let parameters = flatten_expression_list(parameters.as_ref().as_ref().unwrap()); assert_type_and_hint!(&annotations, &index, parameters[1], DINT_TYPE, Some(DINT_TYPE)); assert_type_and_hint!(&annotations, &index, parameters[2], DINT_TYPE, Some(DINT_TYPE)); assert_type_and_hint!(&annotations, &index, parameters[3], DINT_TYPE, Some(DINT_TYPE)); @@ -3209,10 +3208,10 @@ fn resolve_return_variable_in_nested_call() { if let AstStatement::Assignment { right, .. } = ass { if let AstStatement::CallStatement { parameters, .. } = right.as_ref() { - let inner_ass = ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap())[0]; + let inner_ass = flatten_expression_list(parameters.as_ref().as_ref().unwrap())[0]; if let AstStatement::Assignment { right, .. } = inner_ass { if let AstStatement::CallStatement { parameters, .. } = right.as_ref() { - let main = ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap())[0]; + let main = flatten_expression_list(parameters.as_ref().as_ref().unwrap())[0]; let a = annotations.get(main).unwrap(); assert_eq!( a, @@ -3491,7 +3490,7 @@ fn parameter_down_cast_test() { // THEN check if downcasts are detected for implicit parameters if let AstStatement::CallStatement { parameters, .. } = &statements[0] { - let parameters = ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap()); + let parameters = flatten_expression_list(parameters.as_ref().as_ref().unwrap()); assert_type_and_hint!(&annotations, &index, parameters[0], INT_TYPE, Some(SINT_TYPE)); // downcast from type to type-hint! assert_type_and_hint!(&annotations, &index, parameters[1], DINT_TYPE, Some(INT_TYPE)); // downcast! assert_type_and_hint!(&annotations, &index, parameters[2], LINT_TYPE, Some(DINT_TYPE)); // downcast! @@ -3501,7 +3500,7 @@ fn parameter_down_cast_test() { // THEN check if downcasts are detected for explicit parameters if let AstStatement::CallStatement { parameters, .. } = &statements[1] { - let parameters = ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap()) + let parameters = flatten_expression_list(parameters.as_ref().as_ref().unwrap()) .iter() .map(|it| { if let AstStatement::Assignment { right, .. } = it { @@ -3544,7 +3543,7 @@ fn mux_generic_with_strings_is_annotated_correctly() { index.import(std::mem::take(&mut annotations.new_index)); if let AstStatement::CallStatement { parameters, .. } = &unit.implementations[0].statements[0] { - let list = ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap()); + let list = flatten_expression_list(parameters.as_ref().as_ref().unwrap()); // MUX(2, str2, str3, str4) // ~ @@ -3686,7 +3685,7 @@ fn action_call_statement_parameters_are_annotated_with_a_type_hint() { index.import(std::mem::take(&mut annotations.new_index)); if let AstStatement::CallStatement { parameters, .. } = &unit.implementations[2].statements[0] { - let list = ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap()); + let list = flatten_expression_list(parameters.as_ref().as_ref().unwrap()); assert_type_and_hint!(&annotations, &index, list[0], "STRING", Some("DINT")); assert_type_and_hint!(&annotations, &index, list[1], "STRING", Some("LWORD")); @@ -3985,7 +3984,7 @@ fn vla_call_statement() { }; let param = parameters.as_ref().clone().unwrap(); - let statement = ast::flatten_expression_list(¶m)[0]; + let statement = flatten_expression_list(¶m)[0]; assert_type_and_hint!(&annotations, &index, statement, "__main_arr", Some("__foo_vla")); } @@ -4020,7 +4019,7 @@ fn vla_call_statement_with_nested_arrays() { }; let param = parameters.as_ref().clone().unwrap(); - let statement = ast::flatten_expression_list(¶m)[0]; + let statement = flatten_expression_list(¶m)[0]; assert_type_and_hint!(&annotations, &index, statement, "__main_arr_", Some("__foo_vla")); } diff --git a/src/resolver/tests/resolve_generic_calls.rs b/src/resolver/tests/resolve_generic_calls.rs index 77c522f079..c2532e10d8 100644 --- a/src/resolver/tests/resolve_generic_calls.rs +++ b/src/resolver/tests/resolve_generic_calls.rs @@ -1,7 +1,10 @@ +use plc_ast::{ + ast::{flatten_expression_list, AstStatement}, + provider::IdProvider, +}; + use crate::{ assert_type_and_hint, - ast::{self, flatten_expression_list, AstStatement}, - lexer::IdProvider, resolver::{AnnotationMap, StatementAnnotation, TypeAnnotator}, test_utils::tests::{annotate_with_ids, index_with_ids}, typesystem::{ @@ -180,7 +183,7 @@ fn generic_call_multi_params_annotated_with_correct_type() { assert_eq!(Some("myFunc__DINT__INT"), annotations.get_call_name(operator)); //parameters should have the correct type if let Some(parameters) = &**parameters { - if let [x, y, z] = ast::flatten_expression_list(parameters)[..] { + if let [x, y, z] = flatten_expression_list(parameters)[..] { if let AstStatement::Assignment { left, right, .. } = x { assert_type_and_hint!(&annotations, &index, left, DINT_TYPE, None); assert_type_and_hint!(&annotations, &index, right, INT_TYPE, Some(DINT_TYPE)); @@ -218,7 +221,7 @@ fn generic_call_multi_params_annotated_with_correct_type() { assert_eq!(Some("myFunc__DINT__INT"), annotations.get_call_name(operator)); //parameters should have the correct type if let Some(parameters) = &**parameters { - if let [x, y, z] = ast::flatten_expression_list(parameters)[..] { + if let [x, y, z] = flatten_expression_list(parameters)[..] { assert_type_and_hint!(&annotations, &index, x, INT_TYPE, Some(DINT_TYPE)); assert_type_and_hint!(&annotations, &index, y, DINT_TYPE, Some(DINT_TYPE)); assert_type_and_hint!(&annotations, &index, z, INT_TYPE, Some(INT_TYPE)); @@ -240,7 +243,7 @@ fn generic_call_multi_params_annotated_with_correct_type() { assert_eq!(Some("myFunc__REAL__SINT"), annotations.get_call_name(operator)); //parameters should have the correct type if let Some(parameters) = &**parameters { - if let [x, y, z] = ast::flatten_expression_list(parameters)[..] { + if let [x, y, z] = flatten_expression_list(parameters)[..] { assert_type_and_hint!(&annotations, &index, x, REAL_TYPE, Some(REAL_TYPE)); assert_type_and_hint!(&annotations, &index, y, DINT_TYPE, Some(REAL_TYPE)); assert_type_and_hint!(&annotations, &index, z, SINT_TYPE, Some(SINT_TYPE)); @@ -286,7 +289,7 @@ fn call_order_of_parameters_does_not_change_annotations() { parameters_list .iter() .find(|it| { - matches!(it, AstStatement::Assignment { left, .. } + matches!(it, AstStatement::Assignment { left, .. } if { matches!(&**left, AstStatement::Reference{name, ..} if {name == expected_name})}) }) .unwrap() @@ -300,7 +303,7 @@ fn call_order_of_parameters_does_not_change_annotations() { assert_eq!(Some("myFunc"), annotations.get_call_name(operator)); //parameters should have the correct type if let Some(parameters) = &**parameters { - let parameters_list = ast::flatten_expression_list(parameters); + let parameters_list = flatten_expression_list(parameters); let [x, y, z] = [ get_parameter_with_name(¶meters_list, "x"), get_parameter_with_name(¶meters_list, "y"), @@ -360,7 +363,7 @@ fn call_order_of_generic_parameters_does_not_change_annotations() { parameters_list .iter() .find(|it| { - matches!(it, AstStatement::Assignment { left, .. } + matches!(it, AstStatement::Assignment { left, .. } if { matches!(&**left, AstStatement::Reference{name, ..} if {name == expected_name})}) }) .unwrap() @@ -374,7 +377,7 @@ fn call_order_of_generic_parameters_does_not_change_annotations() { assert_eq!(Some("myFunc__DINT__INT"), annotations.get_call_name(operator)); //parameters should have the correct type if let Some(parameters) = &**parameters { - let parameters_list = ast::flatten_expression_list(parameters); + let parameters_list = flatten_expression_list(parameters); let [x, y, z] = [ get_parameter_with_name(¶meters_list, "x"), get_parameter_with_name(¶meters_list, "y"), @@ -586,7 +589,7 @@ fn generic_call_gets_cast_to_biggest_type() { assert_type_and_hint!(&annotations, &index, call, LREAL_TYPE, None); //Call returns LREAL if let AstStatement::CallStatement { parameters, .. } = call { - let params = ast::flatten_expression_list(parameters.as_ref().as_ref().unwrap()); + let params = flatten_expression_list(parameters.as_ref().as_ref().unwrap()); assert_type_and_hint!(&annotations, &index, params[0], SINT_TYPE, Some(LREAL_TYPE)); assert_type_and_hint!(&annotations, &index, params[1], DINT_TYPE, Some(LREAL_TYPE)); assert_type_and_hint!(&annotations, &index, params[2], LREAL_TYPE, Some(LREAL_TYPE)); diff --git a/src/resolver/tests/resolve_literals_tests.rs b/src/resolver/tests/resolve_literals_tests.rs index acebc58d42..aa798cc823 100644 --- a/src/resolver/tests/resolve_literals_tests.rs +++ b/src/resolver/tests/resolve_literals_tests.rs @@ -1,8 +1,11 @@ +use plc_ast::{ + ast::{AstStatement, TypeNature}, + provider::IdProvider, +}; + use crate::{ assert_type_and_hint, - ast::AstStatement, index::symbol::SymbolLocation, - lexer::IdProvider, resolver::{AnnotationMap, TypeAnnotator}, test_utils::tests::{annotate_with_ids, index_with_ids}, typesystem::{DataType, DataTypeInformation, StringEncoding, TypeSize, DINT_TYPE}, @@ -51,7 +54,7 @@ fn string_literals_are_annotated() { &DataType { initial_value: None, name: "__STRING_3".into(), - nature: crate::ast::TypeNature::String, + nature: TypeNature::String, information: DataTypeInformation::String { encoding: crate::typesystem::StringEncoding::Utf8, size: crate::typesystem::TypeSize::LiteralInteger(4) @@ -64,7 +67,7 @@ fn string_literals_are_annotated() { &DataType { initial_value: None, name: "__WSTRING_6".into(), - nature: crate::ast::TypeNature::String, + nature: TypeNature::String, information: DataTypeInformation::String { encoding: crate::typesystem::StringEncoding::Utf16, size: crate::typesystem::TypeSize::LiteralInteger(7) diff --git a/src/resolver/tests/resolver_dependency_resolution.rs b/src/resolver/tests/resolver_dependency_resolution.rs index 263fbebe31..a6cf30cdf6 100644 --- a/src/resolver/tests/resolver_dependency_resolution.rs +++ b/src/resolver/tests/resolver_dependency_resolution.rs @@ -1,7 +1,7 @@ +use plc_ast::provider::IdProvider; use source::SourceCode; use crate::{ - lexer::IdProvider, resolver::{Dependency, TypeAnnotator}, test_utils::tests::index_with_ids, }; diff --git a/src/test_utils.rs b/src/test_utils.rs index 879514122d..b537cd5f04 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -3,16 +3,18 @@ pub mod tests { use std::{cell::RefCell, path::PathBuf, rc::Rc, str::FromStr}; + use plc_ast::{ + ast::{pre_process, CompilationUnit, LinkageType, SourceRangeFactory}, + provider::IdProvider, + }; use source::{Compilable, SourceCode, SourceContainer}; use crate::{ - ast::{self, CompilationUnit, SourceRangeFactory}, builtins, codegen::{CodegenContext, GeneratedModule}, diagnostics::{Diagnostic, DiagnosticReporter, ResolvedDiagnostics}, index::{self, Index}, - lexer::{self, IdProvider}, - parser, + lexer, parser, resolver::{const_evaluator::evaluate_constants, AnnotationMapImpl, AstAnnotations, TypeAnnotator}, typesystem::get_builtin_types, DebugLevel, Validator, @@ -43,7 +45,7 @@ pub mod tests { pub fn parse(src: &str) -> (CompilationUnit, Vec) { parser::parse( lexer::lex_with_ids(src, IdProvider::default(), SourceRangeFactory::internal()), - ast::LinkageType::Internal, + LinkageType::Internal, "test.st", ) } @@ -52,10 +54,10 @@ pub mod tests { let id_provider = IdProvider::default(); let (mut unit, diagnostic) = parser::parse( lexer::lex_with_ids(src, id_provider.clone(), SourceRangeFactory::internal()), - ast::LinkageType::Internal, + LinkageType::Internal, "test.st", ); - ast::pre_process(&mut unit, id_provider); + pre_process(&mut unit, id_provider); (unit, diagnostic) } @@ -80,10 +82,10 @@ pub mod tests { }; let (mut unit, ..) = parser::parse( lexer::lex_with_ids(source_str, id_provider.clone(), range_factory), - ast::LinkageType::Internal, + LinkageType::Internal, source_path, ); - ast::pre_process(&mut unit, id_provider); + pre_process(&mut unit, id_provider); index.import(index::visitor::visit(&unit)); (unit, index) } diff --git a/src/tests/adr/annotated_ast.rs b/src/tests/adr/annotated_ast.rs index 496e0325aa..4560fea01e 100644 --- a/src/tests/adr/annotated_ast.rs +++ b/src/tests/adr/annotated_ast.rs @@ -1,7 +1,5 @@ use crate::{ - ast::AstStatement, index::{ArgumentType, VariableType}, - lexer::IdProvider, resolver::{AnnotationMap, StatementAnnotation}, test_utils::tests::{annotate_with_ids, index_with_ids}, }; diff --git a/src/tests/adr/pou_adr.rs b/src/tests/adr/pou_adr.rs index 553939a276..21be3895be 100644 --- a/src/tests/adr/pou_adr.rs +++ b/src/tests/adr/pou_adr.rs @@ -1,7 +1,6 @@ -use crate::{ - lexer::IdProvider, - test_utils::tests::{annotate_with_ids, codegen, index_with_ids}, -}; +use plc_ast::provider::IdProvider; + +use crate::test_utils::tests::{annotate_with_ids, codegen, index_with_ids}; /// # Architecture Design Record: POUs /// diff --git a/src/tests/adr/util_macros.rs b/src/tests/adr/util_macros.rs index bb4ab8523b..08915f8e02 100644 --- a/src/tests/adr/util_macros.rs +++ b/src/tests/adr/util_macros.rs @@ -1,7 +1,7 @@ // some helper macros to get more concise tests: macro_rules! annotate { ($src:expr) => {{ - let id_provider = IdProvider::default(); + let id_provider = plc_ast::provider::IdProvider::default(); let (mut cu, mut index) = index_with_ids($src, id_provider.clone()); let annotations = annotate_with_ids(&cu, &mut index, id_provider); (std::mem::take(&mut cu.implementations[0].statements), annotations, index) @@ -11,7 +11,7 @@ pub(crate) use annotate; macro_rules! deconstruct_assignment { ($src:expr) => {{ - if let AstStatement::Assignment { left, right, .. } = $src { + if let plc_ast::ast::AstStatement::Assignment { left, right, .. } = $src { (left, right) } else { unreachable!(); @@ -22,10 +22,10 @@ pub(crate) use deconstruct_assignment; macro_rules! deconstruct_call_statement { ($src:expr) => {{ - if let crate::ast::AstStatement::CallStatement { operator, parameters, .. } = $src { + if let plc_ast::ast::AstStatement::CallStatement { operator, parameters, .. } = $src { ( operator, - parameters.as_ref().as_ref().map(crate::ast::flatten_expression_list).unwrap_or_default(), + parameters.as_ref().as_ref().map(plc_ast::ast::flatten_expression_list).unwrap_or_default(), ) } else { unreachable!(); @@ -36,7 +36,7 @@ pub(crate) use deconstruct_call_statement; macro_rules! deconstruct_qualified_reference { ($src:expr) => {{ - if let AstStatement::QualifiedReference { elements, .. } = &$src { + if let plc_ast::ast::AstStatement::QualifiedReference { elements, .. } = &$src { elements } else { unreachable!(); @@ -47,7 +47,7 @@ pub(crate) use deconstruct_qualified_reference; macro_rules! deconstruct_binary_expression { ($src:expr) => {{ - if let AstStatement::BinaryExpression { left, right, .. } = &$src { + if let plc_ast::ast::AstStatement::BinaryExpression { left, right, .. } = &$src { (left, right) } else { unreachable!(); diff --git a/src/tests/adr/vla_adr.rs b/src/tests/adr/vla_adr.rs index b403bb9e16..eec46da5f6 100644 --- a/src/tests/adr/vla_adr.rs +++ b/src/tests/adr/vla_adr.rs @@ -4,7 +4,6 @@ //! either a INPUT, OUTPUT or INOUT variable block thereby accepts a 1D array of type DINT as an argument. use crate::{ - lexer::IdProvider, resolver::AnnotationMap, test_utils::tests::{annotate_with_ids, codegen, index_with_ids}, tests::adr::util_macros::{annotate, deconstruct_call_statement}, diff --git a/src/typesystem.rs b/src/typesystem.rs index f19a137b5f..ee0ba3892b 100644 --- a/src/typesystem.rs +++ b/src/typesystem.rs @@ -5,8 +5,12 @@ use std::{ ops::{Range, RangeInclusive}, }; -use crate::{ +use plc_ast::{ ast::{AstStatement, Operator, PouType, TypeNature}, + literals::{AstLiteral, StringValue}, +}; + +use crate::{ datalayout::{Bytes, MemoryLocation}, index::{const_expressions::ConstId, symbol::SymbolLocation, Index, VariableIndexEntry}, }; @@ -1267,11 +1271,39 @@ pub fn get_equals_function_name_for(type_name: &str, operator: &Operator) -> Opt _ => None, }; - suffix.map(|suffix| format!("{type_name}_{suffix}")) + suffix.map(|suffix| format!("{type_name}_{suffix}")) // TODO: Naming convention (see plc_util/src/convention.rs) } -/// returns a name for internally created types using the given prefix and original type name -/// the return name starts with "__" -pub fn create_internal_type_name(prefix: &str, original_type_name: &str) -> String { - format!("__{prefix}{original_type_name}") +pub fn get_literal_actual_signed_type_name(lit: &AstLiteral, signed: bool) -> Option<&str> { + // Returns a range with the min and max value of the given type + macro_rules! is_covered_by { + ($t:ty, $e:expr) => { + <$t>::MIN as i128 <= $e as i128 && $e as i128 <= <$t>::MAX as i128 + }; + } + + match lit { + AstLiteral::Integer(value) => match signed { + _ if *value == 0_i128 || *value == 1_i128 => Some(BOOL_TYPE), + true if is_covered_by!(i8, *value) => Some(SINT_TYPE), + true if is_covered_by!(i16, *value) => Some(INT_TYPE), + true if is_covered_by!(i32, *value) => Some(DINT_TYPE), + true if is_covered_by!(i64, *value) => Some(LINT_TYPE), + + false if is_covered_by!(u8, *value) => Some(USINT_TYPE), + false if is_covered_by!(u16, *value) => Some(UINT_TYPE), + false if is_covered_by!(u32, *value) => Some(UDINT_TYPE), + false if is_covered_by!(u64, *value) => Some(ULINT_TYPE), + _ => Some(VOID_TYPE), + }, + AstLiteral::Bool { .. } => Some(BOOL_TYPE), + AstLiteral::String(StringValue { is_wide: true, .. }) => Some(WSTRING_TYPE), + AstLiteral::String(StringValue { is_wide: false, .. }) => Some(STRING_TYPE), + AstLiteral::Real { .. } => Some(LREAL_TYPE), + AstLiteral::Date { .. } => Some(DATE_TYPE), + AstLiteral::DateAndTime { .. } => Some(DATE_AND_TIME_TYPE), + AstLiteral::Time { .. } => Some(TIME_TYPE), + AstLiteral::TimeOfDay { .. } => Some(TIME_OF_DAY_TYPE), + _ => None, + } } diff --git a/src/typesystem/tests.rs b/src/typesystem/tests.rs index c5ef2fe6bc..c6653ce0ba 100644 --- a/src/typesystem/tests.rs +++ b/src/typesystem/tests.rs @@ -1,5 +1,6 @@ +use plc_ast::ast::{Operator, TypeNature}; + use crate::{ - ast::{Operator, TypeNature}, index::{symbol::SymbolLocation, Index}, test_utils::tests::index, typesystem::{ diff --git a/src/validation.rs b/src/validation.rs index 6caab14fd6..300851c54a 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -1,7 +1,7 @@ +use plc_ast::ast::{AstStatement, CompilationUnit}; use rusty_derive::Validators; use crate::{ - ast::{AstStatement, CompilationUnit}, index::{ const_expressions::{ConstExpression, UnresolvableKind}, Index, PouIndexEntry, diff --git a/src/validation/global.rs b/src/validation/global.rs index 7e03e0719d..26c590fafa 100644 --- a/src/validation/global.rs +++ b/src/validation/global.rs @@ -1,7 +1,7 @@ use itertools::Itertools; +use plc_ast::ast::{PouType, SourceRange}; use crate::{ - ast::{PouType, SourceRange}, diagnostics::Diagnostic, index::{symbol::SymbolMap, Index, PouIndexEntry}, typesystem::{DataTypeInformation, StructSource}, diff --git a/src/validation/pou.rs b/src/validation/pou.rs index 991df6e9a9..4ee54f01c1 100644 --- a/src/validation/pou.rs +++ b/src/validation/pou.rs @@ -1,11 +1,9 @@ +use plc_ast::ast::{Implementation, LinkageType, Pou, PouType}; + use super::{ statement::visit_statement, variable::visit_variable_block, ValidationContext, Validator, Validators, }; -use crate::{ - ast::{Implementation, LinkageType, Pou, PouType}, - resolver::AnnotationMap, - Diagnostic, -}; +use crate::{resolver::AnnotationMap, Diagnostic}; pub fn visit_pou(validator: &mut Validator, pou: &Pou, context: &ValidationContext<'_, T>) { if pou.linkage != LinkageType::External { diff --git a/src/validation/recursive.rs b/src/validation/recursive.rs index fc7c1de83b..8d4ecc25ce 100644 --- a/src/validation/recursive.rs +++ b/src/validation/recursive.rs @@ -1,8 +1,8 @@ use indexmap::IndexSet; use itertools::Itertools; +use plc_ast::ast::PouType; use crate::{ - ast::PouType, diagnostics::Diagnostic, index::{Index, VariableIndexEntry}, typesystem::{DataType, DataTypeInformation, DataTypeInformationProvider, StructSource}, diff --git a/src/validation/statement.rs b/src/validation/statement.rs index 58996741d8..399cac5c50 100644 --- a/src/validation/statement.rs +++ b/src/validation/statement.rs @@ -1,18 +1,20 @@ use std::{collections::HashSet, mem::discriminant}; +use plc_ast::{ + ast::{flatten_expression_list, AstStatement, DirectAccessType, Operator, SourceRange}, + control_statements::{AstControlStatement, ConditionalBlock}, + literals::{Array, AstLiteral, StringValue}, +}; + use super::{validate_for_array_assignment, ValidationContext, Validator, Validators}; use crate::{ - ast::{ - self, control_statements::ConditionalBlock, Array, AstLiteral, AstStatement, DirectAccessType, - Operator, SourceRange, StringValue, - }, builtins::{self, BuiltIn}, codegen::generators::expression_generator::get_implicit_call_parameter, index::{ArgumentType, Index, PouIndexEntry, VariableIndexEntry, VariableType}, resolver::{const_evaluator, AnnotationMap, StatementAnnotation}, typesystem::{ - self, get_equals_function_name_for, DataType, DataTypeInformation, Dimension, StructSource, - BOOL_TYPE, POINTER_SIZE, + self, get_equals_function_name_for, get_literal_actual_signed_type_name, DataType, + DataTypeInformation, Dimension, StructSource, BOOL_TYPE, POINTER_SIZE, }, Diagnostic, }; @@ -120,30 +122,29 @@ pub fn visit_statement( fn validate_control_statement( validator: &mut Validator, - control_statement: &ast::control_statements::AstControlStatement, + control_statement: &AstControlStatement, context: &ValidationContext, ) { match control_statement { - ast::control_statements::AstControlStatement::If(stmt) => { + AstControlStatement::If(stmt) => { stmt.blocks.iter().for_each(|b| { visit_statement(validator, b.condition.as_ref(), context); b.body.iter().for_each(|s| visit_statement(validator, s, context)); }); stmt.else_block.iter().for_each(|e| visit_statement(validator, e, context)); } - ast::control_statements::AstControlStatement::ForLoop(stmt) => { + AstControlStatement::ForLoop(stmt) => { visit_all_statements!(validator, context, &stmt.counter, &stmt.start, &stmt.end); if let Some(by_step) = &stmt.by_step { visit_statement(validator, by_step, context); } stmt.body.iter().for_each(|s| visit_statement(validator, s, context)); } - ast::control_statements::AstControlStatement::WhileLoop(stmt) - | ast::control_statements::AstControlStatement::RepeatLoop(stmt) => { + AstControlStatement::WhileLoop(stmt) | AstControlStatement::RepeatLoop(stmt) => { visit_statement(validator, &stmt.condition, context); stmt.body.iter().for_each(|s| visit_statement(validator, s, context)); } - ast::control_statements::AstControlStatement::Case(stmt) => { + AstControlStatement::Case(stmt) => { validate_case_statement(validator, &stmt.selector, &stmt.case_blocks, &stmt.else_block, context); } } @@ -162,8 +163,7 @@ fn validate_cast_literal( ) { let cast_type = context.index.get_effective_type_or_void_by_name(type_name).get_type_information(); let literal_type = context.index.get_type_information_or_void( - literal - .get_literal_actual_signed_type_name(!cast_type.is_unsigned_int()) + get_literal_actual_signed_type_name(literal, !cast_type.is_unsigned_int()) .or_else(|| context.annotations.get_type_hint(statement, context.index).map(DataType::get_name)) .unwrap_or_else(|| context.annotations.get_type_or_void(statement, context.index).get_name()), ); @@ -220,7 +220,7 @@ fn validate_qualified_reference( let target_type = context.annotations.get_type_or_void(reference, context.index).get_type_information(); if target_type.is_int() { - if !access.is_compatible(target_type, context.index) { + if !helper::is_compatible(access, target_type, context.index) { validator.push_diagnostic(Diagnostic::incompatible_directaccess( &format!("{access:?}"), access.get_bit_width(), @@ -267,11 +267,16 @@ fn validate_access_index( ) { match *access_index { AstStatement::Literal { kind: AstLiteral::Integer(value), .. } => { - if !access_type.is_in_range(value.try_into().unwrap_or_default(), target_type, context.index) { + if !helper::is_in_range( + access_type, + value.try_into().unwrap_or_default(), + target_type, + context.index, + ) { validator.push_diagnostic(Diagnostic::incompatible_directaccess_range( &format!("{access_type:?}"), target_type.get_name(), - access_type.get_range(target_type, context.index), + helper::get_range(access_type, target_type, context.index), location.clone(), )) } @@ -807,7 +812,7 @@ fn validate_call( } let declared_parameters = context.index.get_declared_parameters(pou.get_name()); - let passed_parameters = parameters.as_ref().map(ast::flatten_expression_list).unwrap_or_default(); + let passed_parameters = parameters.as_ref().map(flatten_expression_list).unwrap_or_default(); let mut are_implicit_parameters = true; let mut variable_location_in_parent = vec![]; @@ -975,3 +980,35 @@ fn validate_type_nature( // )) // } // } + +mod helper { + use std::ops::Range; + + use plc_ast::ast::DirectAccessType; + + use crate::{index::Index, typesystem::DataTypeInformation}; + + /// Returns true if the current index is in the range for the given type + pub fn is_in_range( + access: &DirectAccessType, + access_index: u64, + data_type: &DataTypeInformation, + index: &Index, + ) -> bool { + (access.get_bit_width() * access_index) < data_type.get_size_in_bits(index) as u64 + } + + /// Returns the range from 0 for the given data type + pub fn get_range( + access: &DirectAccessType, + data_type: &DataTypeInformation, + index: &Index, + ) -> Range { + 0..((data_type.get_size_in_bits(index) as u64 / access.get_bit_width()) - 1) + } + + /// Returns true if the direct access can be used for the given type + pub fn is_compatible(access: &DirectAccessType, data_type: &DataTypeInformation, index: &Index) -> bool { + data_type.get_semantic_size(index) as u64 > access.get_bit_width() + } +} diff --git a/src/validation/tests/duplicates_validation_test.rs b/src/validation/tests/duplicates_validation_test.rs index d61cb985d8..7a130bd4c6 100644 --- a/src/validation/tests/duplicates_validation_test.rs +++ b/src/validation/tests/duplicates_validation_test.rs @@ -1,9 +1,12 @@ +use plc_ast::{ + ast::{pre_process, CompilationUnit, LinkageType, SourceRangeFactory}, + provider::IdProvider, +}; + use crate::{ assert_validation_snapshot, - ast::{self, CompilationUnit, SourceRangeFactory}, index::{visitor, Index}, - lexer::{self, IdProvider}, - parser, + lexer, parser, resolver::TypeAnnotator, test_utils::tests::parse_and_validate, typesystem, @@ -341,10 +344,10 @@ fn automatically_generated_output_types_in_different_files_dont_cause_duplicatio let mut index = Index::default(); let (mut unit, ..) = parser::parse( lexer::lex_with_ids(src, id_provider.clone(), SourceRangeFactory::internal()), - ast::LinkageType::Internal, + LinkageType::Internal, "test.st", ); - ast::pre_process(&mut unit, id_provider); + pre_process(&mut unit, id_provider); index.import(visitor::visit(&unit)); index } @@ -396,10 +399,10 @@ fn duplicate_with_generic() { let mut index = Index::default(); let (mut unit, ..) = parser::parse( lexer::lex_with_ids(src, id_provider.clone(), SourceRangeFactory::internal()), - ast::LinkageType::Internal, + LinkageType::Internal, file_name, ); - ast::pre_process(&mut unit, id_provider); + pre_process(&mut unit, id_provider); index.import(visitor::visit(&unit)); (index, unit) } diff --git a/src/validation/types.rs b/src/validation/types.rs index ba63beb6a1..8a7ca085e3 100644 --- a/src/validation/types.rs +++ b/src/validation/types.rs @@ -1,5 +1,6 @@ +use plc_ast::ast::{AstStatement, DataType, DataTypeDeclaration, PouType, SourceRange, UserTypeDeclaration}; + use crate::{ - ast::{AstStatement, DataType, DataTypeDeclaration, PouType, SourceRange, UserTypeDeclaration}, index::Index, resolver::AnnotationMap, typesystem::{DataTypeInformation, StructSource}, diff --git a/src/validation/variable.rs b/src/validation/variable.rs index f241f35e92..48b7b19b93 100644 --- a/src/validation/variable.rs +++ b/src/validation/variable.rs @@ -1,10 +1,9 @@ -use crate::{ - ast::{ArgumentProperty, AstStatement, Pou, PouType, Variable, VariableBlock, VariableBlockType}, - index::const_expressions::ConstExpression, - resolver::AnnotationMap, - Diagnostic, +use plc_ast::ast::{ + ArgumentProperty, AstStatement, Pou, PouType, Variable, VariableBlock, VariableBlockType, }; +use crate::{index::const_expressions::ConstExpression, resolver::AnnotationMap, Diagnostic}; + use super::{ statement::validate_enum_variant_assignment, types::{data_type_is_fb_or_class_instance, visit_data_type_declaration}, diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index bd0a3b3cfd..c925bf136a 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -23,3 +23,4 @@ async-std = "1.12.0" tempfile = "3" clap = { version = "4.3.10", features = ["derive"] } plc = { path = "../", package = "rusty" } +plc_ast = { path = "../compiler/plc_ast" } diff --git a/xtask/src/task/lexer.rs b/xtask/src/task/lexer.rs index 1243255f2c..9226dc4e87 100644 --- a/xtask/src/task/lexer.rs +++ b/xtask/src/task/lexer.rs @@ -1,9 +1,7 @@ use std::time::Instant; -use plc::{ - ast::SourceRangeFactory, - lexer::{self, IdProvider}, -}; +use plc::lexer; +use plc_ast::{ast::SourceRangeFactory, provider::IdProvider}; use crate::reporter::DurationWrapper;