Skip to content

Commit d6e68cf

Browse files
mhaselghaith
andauthored
feat(cfc): Sink/source connections (#956)
* add sink-source connection-mark desugaring * Add tests for the desugaring functionality * refactor: Change the desugaring algorithm to be simpler * refactor: change requests --------- Co-authored-by: Ghaith Hachem <ghaith.hachem@gmail.com>
1 parent 12b8226 commit d6e68cf

File tree

68 files changed

+3135
-483
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+3135
-483
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ serde_json = "1"
3232
toml = "0.5"
3333
lazy_static = "1.4.0"
3434
shell-words = "1.1.0"
35-
itertools = "0.11"
3635
plc_derive = { path = "./compiler/plc_derive" }
3736
lld_rs = "140.0.0"
3837
which = "4.2.5"
3938
log.workspace = true
4039
inkwell.workspace = true
4140
chrono.workspace = true
41+
itertools.workspace = true
4242

4343
[dev-dependencies]
4444
num = "0.4"
@@ -77,3 +77,4 @@ encoding_rs = "0.8"
7777
encoding_rs_io = "0.1"
7878
log = "0.4"
7979
chrono = { version = "0.4", default-features = false }
80+
itertools = "0.11"

compiler/plc_diagnostics/src/diagnostics.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,30 @@ impl Diagnostic {
744744
err_no: ErrNo::cfc__unexpected_node,
745745
}
746746
}
747+
748+
pub fn unconnected_source(connector_name: &str, range: SourceLocation) -> Diagnostic {
749+
Diagnostic::SemanticError {
750+
message: format!("Source '{connector_name}' is not connected."),
751+
range: vec![range],
752+
err_no: ErrNo::cfc__unconnected_source,
753+
}
754+
}
755+
756+
pub fn sink_without_associated_source(connector_name: &str, range: SourceLocation) -> Diagnostic {
757+
Diagnostic::SemanticError {
758+
message: format!("Expected a corresponding source-connection mark for sink '{connector_name}', but could not find one."),
759+
range: vec![range],
760+
err_no: ErrNo::cfc__no_associated_connector,
761+
}
762+
}
763+
764+
pub fn cyclic_connection(message: String, range: SourceLocation) -> Diagnostic {
765+
Diagnostic::SemanticError {
766+
message: format!("Sink is connected to itself. Found the following recursion: {message}"),
767+
range: vec![range],
768+
err_no: ErrNo::cfc__cyclic_connection,
769+
}
770+
}
747771
}
748772

749773
#[cfg(test)]

compiler/plc_diagnostics/src/errno.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ pub enum ErrNo {
9292
cfc__empty_control_statement,
9393
cfc__undefined_node,
9494
cfc__unexpected_node,
95+
cfc__unconnected_source,
96+
cfc__cyclic_connection,
97+
cfc__no_associated_connector,
9598
}
9699

97100
impl Display for ErrNo {

compiler/plc_xml/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ plc = { path = "../..", package = "rusty" }
1515
ast = { path = "../plc_ast/", package = "plc_ast" }
1616
plc_diagnostics = { path = "../plc_diagnostics" }
1717
plc_source = { path = "../plc_source" }
18+
itertools.workspace = true
1819

1920
[features]
2021
default = []

compiler/plc_xml/src/model/action.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use std::borrow::Cow;
2+
13
#[derive(Debug)]
2-
pub(crate) struct Action {
3-
pub name: String,
4-
pub type_name: String,
4+
pub(crate) struct Action<'xml> {
5+
pub name: Cow<'xml, str>,
6+
pub type_name: Cow<'xml, str>,
57
}

compiler/plc_xml/src/model/block.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
1-
use std::collections::HashMap;
1+
use std::{borrow::Cow, collections::HashMap};
22

33
use quick_xml::events::Event;
44

55
use crate::{error::Error, extensions::GetOrErr, reader::PeekableReader, xml_parser::Parseable};
66

77
use super::variables::BlockVariable;
88

9-
#[derive(Debug, PartialEq)]
10-
pub(crate) struct Block {
9+
#[derive(Debug, PartialEq, Eq, Hash)]
10+
pub(crate) struct Block<'xml> {
1111
pub local_id: usize,
12-
pub type_name: String,
13-
pub instance_name: Option<String>,
12+
pub type_name: Cow<'xml, str>,
13+
pub instance_name: Option<Cow<'xml, str>>,
1414
pub execution_order_id: Option<usize>,
1515
pub variables: Vec<BlockVariable>,
1616
}
1717

18-
impl Block {
18+
impl<'xml> Block<'xml> {
1919
pub fn new(mut hm: HashMap<String, String>, variables: Vec<BlockVariable>) -> Result<Self, Error> {
2020
Ok(Self {
2121
local_id: hm.get_or_err("localId").map(|it| it.parse())??,
22-
type_name: hm.get_or_err("typeName")?,
23-
instance_name: hm.remove("instanceName"),
22+
type_name: Cow::from(hm.get_or_err("typeName")?),
23+
instance_name: hm.remove("instanceName").map(Cow::from),
2424
execution_order_id: hm.get("executionOrderId").map(|it| it.parse()).transpose()?,
2525
variables,
2626
})
2727
}
2828
}
2929

30-
impl Parseable for Block {
30+
impl<'xml> Parseable for Block<'xml> {
3131
type Item = Self;
3232

3333
fn visit(reader: &mut PeekableReader) -> Result<Self::Item, Error> {

compiler/plc_xml/src/model/body.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use super::fbd::FunctionBlockDiagram;
44
use crate::{error::Error, reader::PeekableReader, xml_parser::Parseable};
55

66
#[derive(Debug, Default)]
7-
pub(crate) struct Body {
8-
pub function_block_diagram: Option<FunctionBlockDiagram>,
7+
pub(crate) struct Body<'xml> {
8+
pub function_block_diagram: Option<FunctionBlockDiagram<'xml>>,
99
}
1010

11-
impl Body {
12-
fn new(fbd: Option<FunctionBlockDiagram>) -> Result<Self, Error> {
11+
impl<'xml> Body<'xml> {
12+
fn new(fbd: Option<FunctionBlockDiagram<'xml>>) -> Result<Self, Error> {
1313
Ok(Self { function_block_diagram: fbd })
1414
}
1515

@@ -18,7 +18,7 @@ impl Body {
1818
}
1919
}
2020

21-
impl Parseable for Body {
21+
impl<'xml> Parseable for Body<'xml> {
2222
type Item = Self;
2323

2424
fn visit(reader: &mut PeekableReader) -> Result<Self::Item, Error> {

compiler/plc_xml/src/model/connector.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::{borrow::Cow, collections::HashMap};
22

33
use quick_xml::events::Event;
44

@@ -9,42 +9,42 @@ use crate::{
99
xml_parser::Parseable,
1010
};
1111

12-
#[derive(Debug, PartialEq)]
13-
pub(crate) struct Connector {
12+
#[derive(Debug, PartialEq, Eq, Hash)]
13+
pub(crate) struct Connector<'xml> {
1414
pub kind: ConnectorKind,
15-
pub name: String,
15+
pub name: Cow<'xml, str>,
1616
pub local_id: usize,
1717
pub ref_local_id: Option<usize>,
18-
pub formal_parameter: Option<String>,
18+
pub formal_parameter: Option<Cow<'xml, str>>,
1919
}
2020

21-
impl Connector {
21+
impl<'xml> Connector<'xml> {
2222
pub fn new(mut hm: HashMap<String, String>, kind: ConnectorKind) -> Result<Self, Error> {
2323
Ok(Self {
2424
kind,
25-
name: hm.get_or_err("name")?,
25+
name: Cow::from(hm.get_or_err("name")?),
2626
local_id: hm.get_or_err("localId").map(|it| it.parse())??,
2727
ref_local_id: hm.get("refLocalId").map(|it| it.parse()).transpose()?,
28-
formal_parameter: hm.remove("formalParameter"),
28+
formal_parameter: hm.remove("formalParameter").map(Cow::from),
2929
})
3030
}
3131
}
3232

33-
#[derive(Debug, PartialEq)]
33+
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
3434
pub(crate) enum ConnectorKind {
3535
Source,
3636
Sink,
3737
}
3838

39-
impl Parseable for Connector {
39+
impl<'xml> Parseable for Connector<'xml> {
4040
type Item = Self;
4141

4242
fn visit(reader: &mut PeekableReader) -> Result<Self::Item, Error> {
4343
let next = reader.peek()?;
4444
let kind = match &next {
4545
Event::Start(tag) | Event::Empty(tag) => match tag.name().as_ref() {
46-
b"connector" => ConnectorKind::Sink,
47-
b"continuation" => ConnectorKind::Source,
46+
b"connector" => ConnectorKind::Source,
47+
b"continuation" => ConnectorKind::Sink,
4848
_ => return Err(Error::UnexpectedElement(tag.name().try_to_string()?)),
4949
},
5050

compiler/plc_xml/src/model/control.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{collections::HashMap, str::FromStr};
1+
use std::{borrow::Cow, collections::HashMap, str::FromStr};
22

33
use quick_xml::events::Event;
44

@@ -9,21 +9,21 @@ use crate::{
99
xml_parser::Parseable,
1010
};
1111

12-
#[derive(Debug, PartialEq)]
13-
pub(crate) struct Control {
12+
#[derive(Debug, PartialEq, Eq, Hash)]
13+
pub(crate) struct Control<'xml> {
1414
pub kind: ControlKind,
15-
pub name: Option<String>,
15+
pub name: Option<Cow<'xml, str>>,
1616
pub local_id: usize,
1717
pub ref_local_id: Option<usize>,
1818
pub execution_order_id: Option<usize>,
1919
pub negated: bool,
2020
}
2121

22-
impl Control {
22+
impl<'xml> Control<'xml> {
2323
pub fn new(mut hm: HashMap<String, String>, kind: ControlKind) -> Result<Self, Error> {
2424
Ok(Self {
2525
kind,
26-
name: hm.remove("label"),
26+
name: hm.remove("label").map(Cow::from),
2727
local_id: hm.get_or_err("localId").map(|it| it.parse())??,
2828
ref_local_id: hm.get("refLocalId").map(|it| it.parse()).transpose()?,
2929
execution_order_id: hm.get("executionOrderId").map(|it| it.parse()).transpose()?,
@@ -32,7 +32,7 @@ impl Control {
3232
}
3333
}
3434

35-
#[derive(Debug, PartialEq)]
35+
#[derive(Debug, PartialEq, Clone, Eq, Hash, Copy)]
3636
pub(crate) enum ControlKind {
3737
Jump,
3838
Label,
@@ -52,7 +52,7 @@ impl FromStr for ControlKind {
5252
}
5353
}
5454

55-
impl Parseable for Control {
55+
impl<'xml> Parseable for Control<'xml> {
5656
type Item = Self;
5757

5858
fn visit(reader: &mut PeekableReader) -> Result<Self::Item, Error> {

0 commit comments

Comments
 (0)