Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Semantic validation #201

Merged
merged 10 commits into from
Aug 18, 2021
13 changes: 13 additions & 0 deletions a.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
; ModuleID = 'main'
source_filename = "main"

%prg_interface = type { %__prg_my_struct }
%__prg_my_struct = type {}

@prg_instance = global %prg_interface zeroinitializer

define void @prg(%prg_interface* %0) {
entry:
%my_struct = getelementptr inbounds %prg_interface, %prg_interface* %0, i32 0, i32 0
ret void
}
12 changes: 8 additions & 4 deletions examples/simple_program.st
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
TYPE MyType:
PROGRAM
END_PROGRAM
END_TYPE
TYPE the_struct : STRUCT END_STRUCT END_TYPE

PROGRAM prg
VAR
my_struct : STRUCT
END_STRUCT
END_VAR
END_PROGRAM
67 changes: 58 additions & 9 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
use crate::compile_error::CompileError;
use std::{
fmt::{Debug, Display, Formatter, Result},
iter, result, unimplemented,
iter,
ops::Range,
result, unimplemented,
};
mod pre_processor;

Expand Down Expand Up @@ -178,6 +180,7 @@ impl Variable {
) -> DataTypeDeclaration {
let new_data_type = DataTypeDeclaration::DataTypeReference {
referenced_type: type_name,
location: self.data_type.get_location(),
};
std::mem::replace(&mut self.data_type, new_data_type)
}
Expand Down Expand Up @@ -208,6 +211,10 @@ impl SourceRange {
pub fn sub_range(&self, start: usize, len: usize) -> SourceRange {
SourceRange::new((self.get_start() + start)..(self.get_start() + len))
}

pub fn to_range(&self) -> Range<usize> {
self.range.clone()
}
}

impl From<std::ops::Range<usize>> for SourceRange {
Expand All @@ -216,27 +223,67 @@ impl From<std::ops::Range<usize>> for SourceRange {
}
}

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, PartialEq)]
pub enum DataTypeDeclaration {
DataTypeReference { referenced_type: String },
DataTypeDefinition { data_type: DataType },
DataTypeReference {
referenced_type: String,
location: SourceRange,
},
DataTypeDefinition {
data_type: DataType,
location: SourceRange,
},
}

impl Debug for DataTypeDeclaration {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self {
DataTypeDeclaration::DataTypeReference {
referenced_type, ..
} => f
.debug_struct("DataTypeReference")
.field("referenced_type", referenced_type)
.finish(),
DataTypeDeclaration::DataTypeDefinition { data_type, .. } => f
.debug_struct("DataTypeDefinition")
.field("data_type", data_type)
.finish(),
}
}
}

impl DataTypeDeclaration {
pub fn get_name(&self) -> Option<&str> {
match self {
DataTypeDeclaration::DataTypeReference { referenced_type } => {
Some(referenced_type.as_str())
}
DataTypeDeclaration::DataTypeDefinition { data_type } => data_type.get_name(),
DataTypeDeclaration::DataTypeReference {
referenced_type, ..
} => Some(referenced_type.as_str()),
DataTypeDeclaration::DataTypeDefinition { data_type, .. } => data_type.get_name(),
}
}

pub fn get_location(&self) -> SourceRange {
match self {
DataTypeDeclaration::DataTypeReference { location, .. } => location.clone(),
DataTypeDeclaration::DataTypeDefinition { location, .. } => location.clone(),
}
}
}

#[derive(PartialEq, Debug)]
#[derive(PartialEq)]
pub struct UserTypeDeclaration {
pub data_type: DataType,
pub initializer: Option<Statement>,
pub location: SourceRange,
}

impl Debug for UserTypeDeclaration {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
f.debug_struct("UserTypeDeclaration")
.field("data_type", &self.data_type)
.field("initializer", &self.initializer)
.finish()
}
}

#[derive(Clone, PartialEq)]
Expand Down Expand Up @@ -347,6 +394,7 @@ impl DataType {
pub fn replace_data_type_with_reference_to(
&mut self,
type_name: String,
location: &SourceRange,
) -> Option<DataTypeDeclaration> {
if let DataType::ArrayType {
referenced_type, ..
Expand All @@ -357,6 +405,7 @@ impl DataType {
}
let new_data_type = DataTypeDeclaration::DataTypeReference {
referenced_type: type_name,
location: location.clone(),
};
let old_data_type = std::mem::replace(referenced_type, Box::new(new_data_type));
Some(*old_data_type)
Expand Down
30 changes: 23 additions & 7 deletions src/ast/pre_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use crate::ast::UserTypeDeclaration;
// Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
use std::vec;

use super::super::ast::{CompilationUnit, DataType, DataTypeDeclaration, Variable};
use super::{
super::ast::{CompilationUnit, DataType, DataTypeDeclaration, Variable},
SourceRange,
};

pub fn pre_process(unit: &mut CompilationUnit) {
//process all local variables from POUs
Expand Down Expand Up @@ -53,6 +56,7 @@ fn should_generate_implicit_type(variable: &Variable) -> bool {
DataTypeDeclaration::DataTypeReference { .. } => false,
DataTypeDeclaration::DataTypeDefinition {
data_type: DataType::VarArgs { .. },
..
} => false,
DataTypeDeclaration::DataTypeDefinition { .. } => true,
}
Expand All @@ -64,15 +68,18 @@ fn pre_process_variable_data_type(
types: &mut Vec<UserTypeDeclaration>,
) {
let new_type_name = format!("__{}_{}", container_name, variable.name);
if let DataTypeDeclaration::DataTypeDefinition { mut data_type } =
variable.replace_data_type_with_reference_to(new_type_name.clone())
if let DataTypeDeclaration::DataTypeDefinition {
mut data_type,
location,
} = variable.replace_data_type_with_reference_to(new_type_name.clone())
{
// create index entry
add_nested_datatypes(new_type_name.as_str(), &mut data_type, types);
add_nested_datatypes(new_type_name.as_str(), &mut data_type, types, &location);
data_type.set_name(new_type_name);
types.push(UserTypeDeclaration {
data_type,
initializer: None,
location,
});
}
//make sure it gets generated
Expand All @@ -82,16 +89,25 @@ fn add_nested_datatypes(
container_name: &str,
datatype: &mut DataType,
types: &mut Vec<UserTypeDeclaration>,
location: &SourceRange,
) {
let new_type_name = format!("{}_", container_name);
if let Some(DataTypeDeclaration::DataTypeDefinition { mut data_type }) =
datatype.replace_data_type_with_reference_to(new_type_name.clone())
if let Some(DataTypeDeclaration::DataTypeDefinition {
mut data_type,
location: inner_location,
}) = datatype.replace_data_type_with_reference_to(new_type_name.clone(), location)
{
data_type.set_name(new_type_name.clone());
add_nested_datatypes(new_type_name.as_str(), &mut data_type, types);
add_nested_datatypes(
new_type_name.as_str(),
&mut data_type,
types,
&inner_location,
);
types.push(UserTypeDeclaration {
data_type,
initializer: None,
location: location.clone(),
});
}
}
45 changes: 40 additions & 5 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use indexmap::IndexMap;

use crate::{
ast::{Implementation, SourceRange, Statement},
ast::{Implementation, PouType, SourceRange, Statement},
compile_error::CompileError,
typesystem::*,
};
Expand Down Expand Up @@ -85,10 +85,21 @@ pub enum DataTypeType {
AliasType, // a Custom-Alias-dataType
}

#[derive(Debug, Clone)]
#[derive(Clone)]
pub enum ImplementationType {
Program,
Function,
FunctionBlock,
Action,
Class,
Method,
}

#[derive(Clone)]
pub struct ImplementationIndexEntry {
call_name: String,
type_name: String,
implementation_type: ImplementationType,
}

impl ImplementationIndexEntry {
Expand All @@ -98,13 +109,31 @@ impl ImplementationIndexEntry {
pub fn get_type_name(&self) -> &str {
&self.type_name
}
pub fn get_implementation_type(&self) -> &ImplementationType {
&self.implementation_type
}
}

impl From<&Implementation> for ImplementationIndexEntry {
fn from(implementation: &Implementation) -> Self {
let pou_type = &implementation.pou_type;
ImplementationIndexEntry {
call_name: implementation.name.clone(),
type_name: implementation.type_name.clone(),
implementation_type: pou_type.into(),
}
}
}

impl From<&PouType> for ImplementationType {
fn from(it: &PouType) -> Self {
match it {
PouType::Program => ImplementationType::Program,
PouType::Function => ImplementationType::Function,
PouType::FunctionBlock => ImplementationType::FunctionBlock,
PouType::Action => ImplementationType::Action,
PouType::Class => ImplementationType::Class,
PouType::Method => ImplementationType::Method,
}
}
}
Expand All @@ -114,7 +143,7 @@ impl From<&Implementation> for ImplementationIndexEntry {
/// The index contains information about all referencable elements.
///
///
#[derive(Debug)]
#[derive()]
pub struct Index {
/// all global variables
global_variables: IndexMap<String, VariableIndexEntry>,
Expand All @@ -139,7 +168,7 @@ impl Index {
types: IndexMap::new(),
implementations: IndexMap::new(),
void_type: DataType {
name: "void".to_string(),
name: VOID_TYPE.into(),
initial_value: None,
information: DataTypeInformation::Void,
},
Expand Down Expand Up @@ -334,12 +363,18 @@ impl Index {
&self.implementations
}

pub fn register_implementation(&mut self, call_name: &str, type_name: &str) {
pub fn register_implementation(
&mut self,
call_name: &str,
type_name: &str,
impl_type: ImplementationType,
) {
self.implementations.insert(
call_name.into(),
ImplementationIndexEntry {
call_name: call_name.into(),
type_name: type_name.into(),
implementation_type: impl_type,
},
);
}
Expand Down
Loading