Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions language/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ vsce package
```

### 1.4 Publish CLI

NOTE: Previous versions have been published under the name `bcs-engineering-dsl` on my personal npm account. To avoid confusion, you might want to publish under a different name.

```bash
Expand Down Expand Up @@ -75,3 +76,14 @@ In addition to the standard libraries provided by Beckhoff, the following librar
- `Tc3_DALI`: Please note that this library integration is not fully tested.

## 4 Future Work
- Add support for more target platforms (e.g., Siemens, Codesys)
- Add and test support for more bus systems (e.g., EtherCAT, Profinet)
- Add a more sophisticated module system (e.g., support multiple files, packages, imports, etc.)
- Support structs of structs
- Support not only statefull FBs, but also stateless functions
- Support FB properties (besides inputs, outputs, locals, and logic)
- Support better scoping e.g. true block scoping for variables
- Support UseStmt within FB logic
- Look into debugging DSLs
- Look into moving the framework to a web-based solution (both the DSL and the deployment tool)
- Look into graphical modeling
Binary file not shown.
6 changes: 3 additions & 3 deletions language/example/etherCAT/control.bcsctrl
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ control EtherCATController {
}
unit AdjustLightLevelByMode {
switch (mode){
case OperatingMode.COMFORT: {
case OperatingMode.COMFORT {
lightLevel = 100;
}
case OperatingMode.ECO: {
case OperatingMode.ECO {
lightLevel = 50;
}
default: {
default {
lightLevel = 0;
}
}
Expand Down
10 changes: 5 additions & 5 deletions language/example/exhaustive/exhaustive_control.bcsctrl
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ control ExhaustiveController {
var extractedBool: BOOL = arr1[2];
var extractedInt: INT = arr2[3];
var extractedReal: REAL = arr3[4];
var extractedBoolArray: BOOL[5] = arr4[2];
var extractedBoolArray: BOOL[5] = arr4[2]; // Note: not supported in generator
var extractedBoolArrayElement: BOOL = arr4[2][3];
var extractedMode: Mode = arr5[1];

Expand All @@ -100,8 +100,8 @@ control ExhaustiveController {
arr2[0] = arr2[1] + arr2[2] - arr2[3] * arr2[4] / 2;
arr3[0] = arr3[1] + arr3[2] - arr3[3] * arr3[4] / 2.0;
arr4[0][0] = arr4[1][1] && arr4[2][2] || arr4[3][3] && arr4[4][4];
arr4[1] = [true, false, true, false, true];
arr4[1] = arr1;
arr4[1] = [true, false, true, false, true]; // Note: not supported in generator
arr4[1] = arr1; // Note: not supported in generator
}

struct Rectangle {
Expand Down Expand Up @@ -149,7 +149,7 @@ control ExhaustiveController {

// 6. Separate struct initialization after declaration
var p: Point;
p = { x: 1.0, y: 2.0 };
p = { x: 1.0, y: 2.0 }; // Note: not supported in generator

// 7. Array element accessed and modified
var tempX: REAL;
Expand All @@ -160,7 +160,7 @@ control ExhaustiveController {
// 8. Valid reassignment of structs
var c1: Circle = { radius: 5.0 };
var c2: Circle;
c2 = { radius: 10.0 };
c2 = { radius: 10.0 }; // Note: not supported in generator
var newRadius: REAL = c2.radius;
}

Expand Down
2 changes: 1 addition & 1 deletion language/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.0.24",
"version": "0.0.25",
"name": "bcs-engineering-dsl",
"displayName": "BCS Engineering DSL",
"icon": "icon.png",
Expand Down
22 changes: 7 additions & 15 deletions language/railroad/svg/bcs-control/CaseOption.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 7 additions & 15 deletions language/railroad/svg/bcs-control/DefaultOption.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions language/src/language/bcs-control.langium
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,11 @@ SwitchStmt:
;

CaseOption:
'case' (literals+=CaseLiteral (',' literals+=CaseLiteral)*) ':' Block
'case' (literals+=CaseLiteral (',' literals+=CaseLiteral)*) Block
;

DefaultOption:
'default' ':' Block
'default' Block
;

ExpressionStmt:
Expand Down
4 changes: 2 additions & 2 deletions language/src/language/bcs-hardware.langium
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Bus:

Box:
'box' name=ID '{'
'product:' product=ID // e.g. EK1100, CU1128
'product:' product=ID // e.g. EK1100, CU1128
('revision:' rev=StringLiteral)? // optional explicit rev
modules+=Module*
'}'
Expand All @@ -74,7 +74,7 @@ Module:

NetworkSettings:
'network' '{'
'hostname:' hostname=StringLiteral // e.g. "CX-301714"
'hostname:' hostname=StringLiteral // e.g. "CX-301714"
'ipAddress:' ipAddress=StringLiteral // e.g. "192.168.1.100" TODO: IPLiteral
'}'
;
Expand Down
12 changes: 6 additions & 6 deletions language/src/language/control/utils/type-inference-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -577,9 +577,9 @@ export class TypeInferenceUtils {
accept: ValidationAcceptor,
expr: any
): string | undefined {
const numericTypes = ["INT", "REAL"];
const numericTypes = new Set(["INT", "REAL"]);

if (!numericTypes.includes(left) || !numericTypes.includes(right)) {
if (!numericTypes.has(left) || !numericTypes.has(right)) {
accept(
"error",
`Arithmetic operator '${op}' requires numeric operands, but got '${left}' and '${right}'.`,
Expand All @@ -588,11 +588,11 @@ export class TypeInferenceUtils {
return undefined;
}

// If either operand is REAL, result is REAL
if (left === "REAL" || right === "REAL") {
return "REAL";
// If either operand is INT, result is INT
if (left === "INT" || right === "INT") {
return "INT";
}

return "INT";
return "REAL";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,19 @@ control NestedControlTestController {

// Different processing based on state
switch (iState) {
case ProcessState.INIT: {
case ProcessState.INIT {
// Initialization processing
tempSum = tempSum + iValues[i] * 0.8;
}
case ProcessState.PROCESSING: {
case ProcessState.PROCESSING {
// Normal processing - with nested if
if (iValues[i] > iThreshold * 2.0) {
tempSum = tempSum + iValues[i] * 1.5;
} else {
tempSum = tempSum + iValues[i];
}
}
default: {
default {
// Should not happen, but handle anyway
tempSum = tempSum + iValues[i] * 0.5;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ control SwitchTestController {
adjustedTemp = iTemperature * 1.05;

switch (iMode) {
case OperationMode.IDLE: {
case OperationMode.IDLE {
oHeatingValue = 0.0;
oCoolingValue = 0.0;
oStatusMessage = "System idle";
}
case OperationMode.HEATING: {
case OperationMode.HEATING {
oHeatingValue = adjustedTemp;
oCoolingValue = 0.0;
oStatusMessage = "Heating active";
}
case OperationMode.COOLING: {
case OperationMode.COOLING {
oHeatingValue = 0.0;
oCoolingValue = adjustedTemp;
oStatusMessage = "Cooling active";
}
default: {
default {
oHeatingValue = 0.0;
oCoolingValue = 0.0;
oStatusMessage = "Error state";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ control InvalidTestController {
heater = 5.5;

// Intentional type mismatch of sensor assign to local variable
temp = windowContact;
temp = WindowContact.value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ controller InvalidTestController {
channels: 8
}

datapoint windowContact {
datapoint WindowContact {
portgroup: DigitalInputs
channels: {
channel value: BOOL link "Channel 1^Input"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,23 @@ control InvalidSwitchTestController {
unit TestUnit {
var status_should_fail: Status; // Moved to unit level
switch (mode_should_fail){
case Status.OFF:{
case Status.OFF{
// Nested variable declarations no longer allowed
status_should_fail = Status.ON;
}
case Mode.ECO:{
case Mode.ECO{
// Nested variable declarations no longer allowed
status_should_fail = Status.OFF;
}
case Mode.ECO:{
case Mode.ECO{
// Nested variable declarations no longer allowed
status_should_fail = Status.ON;
}
case true:{
case true{
// Nested variable declarations no longer allowed
status_should_fail = Status.OFF;
}
default:{
default{
// Nested variable declarations no longer allowed
status_should_fail = Status.ON;
}
Expand Down
2 changes: 1 addition & 1 deletion language/test/validating/validating.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ describe("BCS Control Validation Tests", () => {

expect(allDiagnostics.length).toBe(1);
const expectedMessages = [
"Condition in 'when (...)' of unit 'Test' must be of type BOOL, but got 'REAL'.",
"Condition in 'when (...)' of unit 'Test' must be of type BOOL, but got 'INT'.",
];

expectedMessages.forEach((msg) => {
Expand Down