Skip to content

Commit

Permalink
refactor ast representation of qualified/array/ptr references (PLC-la…
Browse files Browse the repository at this point in the history
…ng#951)

* first implementation of member and access

* improved reference parsing

* fix control statements and tests

* fix statement_parser_tests

* fix type-definition tests (enums)

* fix misc_parser tests

* fix parse-error tests

* working on parenthesized expressions

* parsing works

* we can parse everything again

* improved parsing and resolving

* improved handling of cast-expressions

* improve codegen

* fixed R-value generation of direct-access

* assigning to direct access fixed

* string literals

* all tests working - yay

* cleanup and simplifications

* ADR

* renamed AstStatement::Reference to AstStatement::Identifier

* added validation test

* review improvements
  • Loading branch information
riederm authored Aug 30, 2023
1 parent 187d5ea commit 3c36dd7
Show file tree
Hide file tree
Showing 163 changed files with 6,733 additions and 3,432 deletions.
261 changes: 173 additions & 88 deletions compiler/plc_ast/src/ast.rs

Large diffs are not rendered by default.

44 changes: 28 additions & 16 deletions compiler/plc_ast/src/pre_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,33 +91,40 @@ pub fn pre_process(unit: &mut CompilationUnit, mut id_provider: IdProvider) {
if !matches!(original_elements, AstStatement::EmptyStatement { .. }) =>
{
let mut last_name: Option<String> = None;

fn extract_flat_ref_name(statement: &AstStatement) -> &str {
statement.get_flat_reference_name().expect("expected assignment")
}

let initialized_enum_elements = flatten_expression_list(original_elements)
.iter()
.map(|it| match it {
AstStatement::Reference { name, .. } => (name.clone(), None, it.get_location()),
AstStatement::Assignment { left, right, .. } => {
let name = if let AstStatement::Reference { name, .. } = left.as_ref() {
name.clone()
} else {
unreachable!("expected reference, got {:?}", left.as_ref())
};
//<element-name, initializer, location>
(name, Some(*right.clone()), it.get_location())
(
extract_flat_ref_name(left.as_ref()),
Some(*right.clone()),
it.get_location(),
)
}
_ => unreachable!("expected assignment, got {:?}", it),
_ => (extract_flat_ref_name(it), None, it.get_location()),
})
.map(|(element_name, initializer, location)| {
let enum_literal = initializer.unwrap_or_else(|| {
build_enum_initializer(&last_name, &location, &mut id_provider, enum_name)
});
last_name = Some(element_name.clone());
last_name = Some(element_name.to_string());
AstStatement::Assignment {
id: id_provider.next_id(),
left: Box::new(AstStatement::Reference {
id: id_provider.next_id(),
name: element_name,
location,
}),
left: Box::new(AstFactory::create_member_reference(
AstFactory::create_identifier(
element_name,
&location,
id_provider.next_id(),
),
None,
id_provider.next_id(),
)),
right: Box::new(enum_literal),
}
})
Expand Down Expand Up @@ -147,9 +154,14 @@ fn build_enum_initializer(
) -> AstStatement {
if let Some(last_element) = last_name.as_ref() {
// generate a `enum#last + 1` statement
let enum_ref = AstFactory::create_reference(last_element, location, id_provider.next_id());
let enum_ref = AstFactory::create_identifier(last_element, location, id_provider.next_id());
let type_element = AstFactory::create_member_reference(
AstFactory::create_identifier(enum_name, location, id_provider.next_id()),
None,
id_provider.next_id(),
);
AstFactory::create_binary_expression(
AstFactory::create_cast_statement(enum_name, enum_ref, location, id_provider.next_id()),
AstFactory::create_cast_statement(type_element, enum_ref, location, id_provider.next_id()),
Operator::Plus,
AstStatement::new_literal(AstLiteral::new_integer(1), id_provider.next_id(), location.clone()),
id_provider.next_id(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/plc_driver/src/tests/external_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn calling_external_file_function_without_including_file_results_in_error() {
if let Err(msg) = res {
assert_eq!(
Diagnostic::codegen_error(
r#"cannot generate call statement for "Reference { name: \"external\" }""#,
r#"cannot generate call statement for "ReferenceExpr { kind: Member(Identifier { name: \"external\" }), base: None }""#,
SourceRange::in_file(30..38, "external_file.st")
),
msg
Expand Down
42 changes: 15 additions & 27 deletions compiler/plc_xml/src/xml_parser/block.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,26 @@
use ast::ast::{AstStatement, SourceRange};
use ast::ast::{AstFactory, AstStatement, SourceRange};

use crate::model::{block::Block, fbd::NodeIndex};

use super::ParseSession;

impl Block {
pub(crate) fn transform(&self, session: &ParseSession, index: &NodeIndex) -> AstStatement {
let operator = Box::new(AstStatement::Reference {
name: self.type_name.clone(),
location: SourceRange::undefined(),
id: session.next_id(),
});
let parameters = self
.variables
.iter()
.filter_map(|var| {
// try to transform the element this block variable points to
var.transform(session, index)
})
.collect();

let parameters = if !self.variables.is_empty() {
Box::new(Some(AstStatement::ExpressionList {
expressions: self
.variables
.iter()
.filter_map(|var| {
// try to transform the element this block variable points to
var.transform(session, index)
})
.collect(),
id: session.next_id(),
}))
} else {
Box::new(None)
};

AstStatement::CallStatement {
operator,
AstFactory::create_call_to(
self.type_name.clone(),
parameters,
location: SourceRange::undefined(),
id: session.next_id(),
}
session.next_id(),
session.next_id(),
&SourceRange::undefined(),
)
}
}
6 changes: 3 additions & 3 deletions src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ lazy_static! {
code: |generator, params, location| {
if let [reference] = params {
generator
.generate_element_pointer(reference)
.generate_lvalue(reference)
.map(|it| ExpressionValue::RValue(generator.ptr_as_value(it)))
} else {
Err(Diagnostic::codegen_error(
Expand Down Expand Up @@ -106,7 +106,7 @@ lazy_static! {
code: |generator, params, location| {
if let [reference] = params {
generator
.generate_element_pointer(reference)
.generate_lvalue(reference)
.map(|it| ExpressionValue::RValue(it.as_basic_value_enum()))
} else {
Err(Diagnostic::codegen_error(
Expand Down Expand Up @@ -431,7 +431,7 @@ fn generate_variable_length_array_bound_function<'ink>(
));
};

let vla = generator.generate_element_pointer(params[0]).unwrap();
let vla = generator.generate_lvalue(params[0]).unwrap();
let dim = builder.build_struct_gep(vla, 1, "dim").unwrap();

let accessor = match params[1] {
Expand Down
Loading

0 comments on commit 3c36dd7

Please sign in to comment.