From 459cfab0ea3c1d9f4f5e56940875d048a6855b3d Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sat, 14 Mar 2026 21:49:48 +0100 Subject: [PATCH 001/115] Current library state --- .../TestModels/sysml-trace.sysml | 113 ++++++++++++++++++ .../sysmlv2-frontend/Library/Actions.oxsts | 15 ++- .../sysmlv2-frontend/Library/States.oxsts | 6 +- .../sysmlv2-frontend/Library/Triggers.oxsts | 4 +- .../Library/Verification.oxsts | 4 +- .../TestModels/crossroads.sysml | 2 +- .../TestModels/sysml-trace.sysml | 113 ++++++++++++++++++ .../sysmlv2-frontend/models26.example.oxsts | 62 ++++++++++ 8 files changed, 306 insertions(+), 13 deletions(-) create mode 100644 subprojects/frontends/gamma/gamma-semantics/TestModels/sysml-trace.sysml create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/sysml-trace.sysml create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-frontend/models26.example.oxsts diff --git a/subprojects/frontends/gamma/gamma-semantics/TestModels/sysml-trace.sysml b/subprojects/frontends/gamma/gamma-semantics/TestModels/sysml-trace.sysml new file mode 100644 index 00000000..8da0ecc6 --- /dev/null +++ b/subprojects/frontends/gamma/gamma-semantics/TestModels/sysml-trace.sysml @@ -0,0 +1,113 @@ +package Model { + part def MySystem { + attribute x : ScalarValues::Integer default 0; + action myBehavior { + first startShot; + succession __unnamed1 first startShot then m; + merge m; + succession __unnamed2 first m then myStep; + action myStep assign x := x + 1; + succession __unnamed3 first myStep then d; + decide d; + succession repeat first d if x < 2 then m; + succession finish first d if x >= 2 then done; + } + } + part def ExecutedSystem :> MySystem { + private import Occurrences::HappensJustBefore; + private import Occurrences::HappensWhile; + :>> timeSlices : MySystem; + :>> snapshots : MySystem; + action :>> myBehavior { + first startShot; + succession :> __unnamed1 first startShot then m1; + merge m1 :> m; + succession :> __unnamed2 first m1 then myStep1; + succession :> __unnamed3 first myStep1 then d1; + decide d1 :> d; + succession repeat1 :> repeat first d1 if x < 2 then m2; + merge m2 :> m; + succession :> __unnamed2 first m2 then myStep2; + succession :> __unnamed3 first myStep2 then d2; + decide d2 :> d; + succession finish1 :> finish first d2 if x >= 2 then done; + action myStep1 :> myStep; + action myStep2 :> myStep; + } + timeslice before_myBehavior { + attribute :>> x = 0; + } + succession : HappensJustBefore first before_myBehavior then myBehavior_starts; + snapshot myBehavior_starts { + attribute :>> x = 0; + } + succession : HappensWhile first myBehavior.startShot then myBehavior_starts; + succession : HappensJustBefore first myBehavior_starts then between_start_and_m1; + timeslice between_start_and_m1 { + attribute :>> x = 0; + } + succession : HappensJustBefore first between_start_and_m1 then m1_performing; + timeslice m1_performing { + attribute :>> x = 0; + } + succession : HappensWhile first myBehavior.m1 then m1_performing; + succession : HappensJustBefore first m1_performing then between_m1_and_myStep1; + timeslice between_m1_and_myStep1 { + attribute :>> x = 0; + } + succession : HappensJustBefore first between_m1_and_myStep1 then myStep1_performing; + timeslice myStep1_performing { + attribute :>> x = 0; + } + succession : HappensWhile first myBehavior.myStep1 then myStep1_performing; + succession : HappensJustBefore first myStep1_performing then between_myStep1_and_d1; + timeslice between_myStep1_and_d1 { + attribute :>> x = 1; + } + succession : HappensJustBefore first between_myStep1_and_d1 then d1_performing; + timeslice d1_performing { + attribute :>> x = 1; + } + succession : HappensWhile first myBehavior.d1 then d1_performing; + succession : HappensJustBefore first d1_performing then between_d1_and_m2; + timeslice between_d1_and_m2 { + attribute :>> x = 1; + } + succession : HappensJustBefore first between_d1_and_m2 then m2_performing; + timeslice m2_performing { + attribute :>> x = 1; + } + succession : HappensWhile first myBehavior.m2 then m2_performing; + succession : HappensJustBefore first m2_performing then between_m2_and_myStep2; + timeslice between_m2_and_myStep2 { + attribute :>> x = 1; + } + succession : HappensJustBefore first between_m2_and_myStep2 then myStep2_performing; + timeslice myStep2_performing { + attribute :>> x = 1; + } + succession : HappensWhile first myBehavior.myStep2 then myStep2_performing; + succession : HappensJustBefore first myStep2_performing then between_myStep2_and_d2; + timeslice between_myStep2_and_d2 { + attribute :>> x = 2; + } + succession : HappensJustBefore first between_myStep2_and_d2 then d2_performing; + timeslice d2_performing { + attribute :>> x = 2; + } + succession : HappensWhile first myBehavior.d2 then d2_performing; + succession : HappensJustBefore first d2_performing then between_d2_and_done; + timeslice between_d2_and_done { + attribute :>> x = 2; + } + succession : HappensJustBefore first between_d2_and_done then myBehavior_done; + snapshot myBehavior_done { + attribute :>> x = 2; + } + succession : HappensWhile first myBehavior.done then myBehavior_done; + succession : HappensJustBefore first myBehavior_done then after_myBehavior; + timeslice after_myBehavior { + attribute :>> x = 2; + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Actions.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Actions.oxsts index bab88d4c..d0be1e65 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Actions.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Actions.oxsts @@ -11,13 +11,18 @@ import semantifyr::sysml::expressions import semantifyr::sysml::ports import semantifyr::sysml::items -abstract class Action +abstract class Action { + // @Trace + tran execute() { + + } +} class SendAction : Action { refers viaPort: Port refers payload: Item - redefine tran { + redefine tran execute() { inline viaPort.setOutgoingItem(payload) } } @@ -25,16 +30,16 @@ class SendAction : Action { class AssignmentAction : Action { refers attribute: Attribute contains expression: Expression - redefine tran { + redefine tran execute() { inline attribute.set(expression.evaluate()) } } class CompositeAction : Action { contains children: Action[0..*] - redefine tran { + redefine tran execute() { inline for (child in children) { - inline child.main() + inline child.execute() } } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/States.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/States.oxsts index 298216f0..5dff2cb2 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/States.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/States.oxsts @@ -152,14 +152,14 @@ class State : AbstractState { inline transition.initialize() } - inline entryAction.main() + inline entryAction.execute() } } tran deactivate() { inline if (parent != nothing) { if (parent.getActiveState() == self) { - inline exitAction.main() + inline exitAction.execute() inline parent.setActiveState(nothing) } @@ -193,7 +193,7 @@ class Transition { tran performTransition() { inline from.exit(parentState) - inline action.main() + inline action.execute() inline to.enter(parentState) } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Triggers.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Triggers.oxsts index 0761cec2..449a0be5 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Triggers.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Triggers.oxsts @@ -15,7 +15,7 @@ import semantifyr::sysml::actions abstract class AcceptAction { prop isTriggered(): bool { - return true // should be abstract, but no good way to specify defaults atm + return true // should be abstract, but no good way to specify defaults at the moment } tran passTime() { @@ -48,7 +48,7 @@ class AcceptTimeoutAction : AcceptAction { redefine tran passTime() { if (remainingTime > 0) { remainingTime := remainingTime - 1 - assume (remainingTime >= 0) + // assume (remainingTime >= 0) } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts index 69a88435..9122a854 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts @@ -24,8 +24,8 @@ class VerificationCaseDefinition { contains subject: Part contains objective: Requirement - refers deltaTimeMin: int = 1 - refers deltaTimeMax: int = 1 + // refers deltaTimeMin: int = 1 + // refers deltaTimeMax: int = 1 redefine init { inline subject.init() diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/crossroads.sysml b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/crossroads.sysml index edad930c..da4919a9 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/crossroads.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/crossroads.sysml @@ -78,7 +78,7 @@ part def CentralController { send Police() via controlB; } exit action { - send Police() via controlA; + // send Police() via controlA; send Police() via controlB; } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/sysml-trace.sysml b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/sysml-trace.sysml new file mode 100644 index 00000000..8da0ecc6 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/sysml-trace.sysml @@ -0,0 +1,113 @@ +package Model { + part def MySystem { + attribute x : ScalarValues::Integer default 0; + action myBehavior { + first startShot; + succession __unnamed1 first startShot then m; + merge m; + succession __unnamed2 first m then myStep; + action myStep assign x := x + 1; + succession __unnamed3 first myStep then d; + decide d; + succession repeat first d if x < 2 then m; + succession finish first d if x >= 2 then done; + } + } + part def ExecutedSystem :> MySystem { + private import Occurrences::HappensJustBefore; + private import Occurrences::HappensWhile; + :>> timeSlices : MySystem; + :>> snapshots : MySystem; + action :>> myBehavior { + first startShot; + succession :> __unnamed1 first startShot then m1; + merge m1 :> m; + succession :> __unnamed2 first m1 then myStep1; + succession :> __unnamed3 first myStep1 then d1; + decide d1 :> d; + succession repeat1 :> repeat first d1 if x < 2 then m2; + merge m2 :> m; + succession :> __unnamed2 first m2 then myStep2; + succession :> __unnamed3 first myStep2 then d2; + decide d2 :> d; + succession finish1 :> finish first d2 if x >= 2 then done; + action myStep1 :> myStep; + action myStep2 :> myStep; + } + timeslice before_myBehavior { + attribute :>> x = 0; + } + succession : HappensJustBefore first before_myBehavior then myBehavior_starts; + snapshot myBehavior_starts { + attribute :>> x = 0; + } + succession : HappensWhile first myBehavior.startShot then myBehavior_starts; + succession : HappensJustBefore first myBehavior_starts then between_start_and_m1; + timeslice between_start_and_m1 { + attribute :>> x = 0; + } + succession : HappensJustBefore first between_start_and_m1 then m1_performing; + timeslice m1_performing { + attribute :>> x = 0; + } + succession : HappensWhile first myBehavior.m1 then m1_performing; + succession : HappensJustBefore first m1_performing then between_m1_and_myStep1; + timeslice between_m1_and_myStep1 { + attribute :>> x = 0; + } + succession : HappensJustBefore first between_m1_and_myStep1 then myStep1_performing; + timeslice myStep1_performing { + attribute :>> x = 0; + } + succession : HappensWhile first myBehavior.myStep1 then myStep1_performing; + succession : HappensJustBefore first myStep1_performing then between_myStep1_and_d1; + timeslice between_myStep1_and_d1 { + attribute :>> x = 1; + } + succession : HappensJustBefore first between_myStep1_and_d1 then d1_performing; + timeslice d1_performing { + attribute :>> x = 1; + } + succession : HappensWhile first myBehavior.d1 then d1_performing; + succession : HappensJustBefore first d1_performing then between_d1_and_m2; + timeslice between_d1_and_m2 { + attribute :>> x = 1; + } + succession : HappensJustBefore first between_d1_and_m2 then m2_performing; + timeslice m2_performing { + attribute :>> x = 1; + } + succession : HappensWhile first myBehavior.m2 then m2_performing; + succession : HappensJustBefore first m2_performing then between_m2_and_myStep2; + timeslice between_m2_and_myStep2 { + attribute :>> x = 1; + } + succession : HappensJustBefore first between_m2_and_myStep2 then myStep2_performing; + timeslice myStep2_performing { + attribute :>> x = 1; + } + succession : HappensWhile first myBehavior.myStep2 then myStep2_performing; + succession : HappensJustBefore first myStep2_performing then between_myStep2_and_d2; + timeslice between_myStep2_and_d2 { + attribute :>> x = 2; + } + succession : HappensJustBefore first between_myStep2_and_d2 then d2_performing; + timeslice d2_performing { + attribute :>> x = 2; + } + succession : HappensWhile first myBehavior.d2 then d2_performing; + succession : HappensJustBefore first d2_performing then between_d2_and_done; + timeslice between_d2_and_done { + attribute :>> x = 2; + } + succession : HappensJustBefore first between_d2_and_done then myBehavior_done; + snapshot myBehavior_done { + attribute :>> x = 2; + } + succession : HappensWhile first myBehavior.done then myBehavior_done; + succession : HappensJustBefore first myBehavior_done then after_myBehavior; + timeslice after_myBehavior { + attribute :>> x = 2; + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/models26.example.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/models26.example.oxsts new file mode 100644 index 00000000..acef9f39 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/models26.example.oxsts @@ -0,0 +1,62 @@ +package models26::example + +import semantifyr::sysml::expressions +import semantifyr::sysml::actions +import semantifyr::sysml::attributes + +@semantifyr::verification::VerificationCase(semantifyr::verification::VerificationResult::UNSAFE) +class IncrementAttribute { + + contains x: IntegerAttribute { + redefine refers defaultValue: int = 10 + } + contains y: IntegerAttribute { + redefine refers defaultValue: int = 100 + } + contains xLTy : LessThanOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: IntegerAttribute = x + } + redefine contains right: AttributeReferenceExpression { + redefine refers attribute: IntegerAttribute = y + } + } + contains composite: CompositeAction { + contains incX: AssignmentAction subsets children { + redefine refers attribute: IntegerAttribute = x + redefine contains expression: PlusOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: IntegerAttribute = x + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 10 + } + } + } + contains decY: AssignmentAction subsets children { + redefine refers attribute: IntegerAttribute = y + redefine contains expression: MinusOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: IntegerAttribute = y + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 10 + } + } + } + } + + redefine init { + inline x.init() + inline y.init() + } + + redefine tran { + inline composite.execute() + } + + prop { + return xLTy.evaluate() + } + +} From 2d8eec248bc585773aa9d77b320a34cabc863d01 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 15 Mar 2026 01:15:49 +0100 Subject: [PATCH 002/115] Fixed spacecraft model flow --- .../sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml index 36017277..074d07d1 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml @@ -157,7 +157,7 @@ part def Mission { bind commandPort = groundStation.commandPort; - flow from groundStation.commandPort to spacecraft.commandPort; + flow from groundStation.spacecraftCommandPort to spacecraft.commandPort; flow from spacecraft.dataPort to groundStation.dataPort; } From b36d57d471b4047b71b5b34a21cb62f628c8f2ba Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 15 Mar 2026 01:18:49 +0100 Subject: [PATCH 003/115] Reformatted spacecraft model --- .../TestModels/spacecraft.sysml | 71 ++++++++++--------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml index 074d07d1..50329edb 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml @@ -3,24 +3,27 @@ private import ScalarValues::Boolean; private import SI::s; part def GroundStation { - port commandPort : CommandPort; - port spacecraftCommandPort : ~CommandPort; - port dataPort : ~DataPort; + port commandPort: CommandPort; + port spacecraftCommandPort: ~CommandPort; + port dataPort: ~DataPort; - attribute receivedData : Integer default 0; + attribute receivedData: Integer default 0; exhibit state Behaviour { + transition first start then Idle; + state Idle; - transition first start then Idle; + transition first Idle accept after 30 [s] then Operation; + transition first Idle accept : StartCommand via commandPort then Operation; state Operation { entry send PingCommand() via spacecraftCommandPort; - state Waiting; - transition first start then Waiting; + state Waiting; + transition first Waiting accept Data via dataPort @@ -29,21 +32,19 @@ part def GroundStation { then Waiting; } - transition first Idle accept after 30 [s] then Operation; - transition first Idle accept : StartCommand via commandPort then Operation; - transition first Operation accept after 10 [s] then Operation; + transition first Operation accept : StopCommand via commandPort then Idle; } } -part def Spacecraft { - attribute batteryCharge : Integer default 100; - attribute recharging : Boolean default false; - attribute data : Integer default 100; +part def Spacecraft { + port commandPort: CommandPort; + port dataPort: DataPort; - port commandPort : CommandPort; - port dataPort : DataPort; + attribute batteryCharge: Integer default 100; + attribute recharging: Boolean default false; + attribute data: Integer default 100; exhibit state Behaviour parallel { state Communication { @@ -134,7 +135,7 @@ part def Spacecraft { item def Data { // Internal attributes are not yet supported! - //attribute value : Integer; + //attribute value: Integer; } item def Command; @@ -143,17 +144,17 @@ item def StopCommand :> Command; item def StartCommand :> Command; port def CommandPort { - in item command : Command; + in item command: Command; } port def DataPort { - out item data : Data; + out item data: Data; } part def Mission { - port commandPort : CommandPort; + port commandPort: CommandPort; - part groundStation : GroundStation; - part spacecraft : Spacecraft; + part groundStation: GroundStation; + part spacecraft: Spacecraft; bind commandPort = groundStation.commandPort; @@ -162,7 +163,7 @@ part def Mission { } verification def StationBehaviorIdleReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { @@ -176,7 +177,7 @@ verification def StationBehaviorIdleReachable { } verification def StationBehaviorOperationReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { @@ -190,7 +191,7 @@ verification def StationBehaviorOperationReachable { } verification def StationBehaviorOperationWaitingReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { @@ -206,7 +207,7 @@ verification def StationBehaviorOperationWaitingReachable { // verification def SpacecraftBehaviorCommunicationReachable { -// subject mission : Mission; +// subject mission: Mission; // objective { // verify requirement { @@ -220,7 +221,7 @@ verification def StationBehaviorOperationWaitingReachable { // } verification def SpacecraftBehaviorCommunicationWaitingPingReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { @@ -234,7 +235,7 @@ verification def SpacecraftBehaviorCommunicationWaitingPingReachable { } verification def SpacecraftBehaviorCommunicationTransmittingReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { @@ -248,7 +249,7 @@ verification def SpacecraftBehaviorCommunicationTransmittingReachable { } verification def SpacecraftBehaviorCommunicationTransmittingSendDataReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { @@ -262,7 +263,7 @@ verification def SpacecraftBehaviorCommunicationTransmittingSendDataReachable { } verification def SpacecraftBehaviorCommunicationTransmittingSendDataSendingReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { @@ -276,7 +277,7 @@ verification def SpacecraftBehaviorCommunicationTransmittingSendDataSendingReach } verification def SpacecraftBehaviorCommunicationTransmittingConsumePowerReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { @@ -290,7 +291,7 @@ verification def SpacecraftBehaviorCommunicationTransmittingConsumePowerReachabl } verification def SpacecraftBehaviorCommunicationTransmittingConsumePowerConsumingReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { @@ -304,7 +305,7 @@ verification def SpacecraftBehaviorCommunicationTransmittingConsumePowerConsumin } // verification def SpacecraftBehaviorBatteryReachable { -// subject mission : Mission; +// subject mission: Mission; // objective { // verify requirement { @@ -318,7 +319,7 @@ verification def SpacecraftBehaviorCommunicationTransmittingConsumePowerConsumin // } verification def SpacecraftBehaviorBatteryNotRechargingReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { @@ -332,7 +333,7 @@ verification def SpacecraftBehaviorBatteryNotRechargingReachable { } verification def SpacecraftBehaviorBatteryRechargingReachable { - subject mission : Mission; + subject mission: Mission; objective { verify requirement { From 3b1f6f68537cf07e4c7f1efd2c2fec815579a8b8 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 15 Mar 2026 01:19:42 +0100 Subject: [PATCH 004/115] Added additional verification cases --- .../TestModels/spacecraft.sysml | 312 ++++++++++++++++++ 1 file changed, 312 insertions(+) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml index 50329edb..998dd01e 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml @@ -345,3 +345,315 @@ verification def SpacecraftBehaviorBatteryRechargingReachable { } } } + +verification def GroundStateReceivedData0 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 0 + ) + } + } + } +} + +verification def GroundStateReceivedData10 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 10 + ) + } + } + } +} + +verification def GroundStateReceivedData20 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 30 + ) + } + } + } +} + +verification def GroundStateReceivedData30 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 30 + ) + } + } + } +} + +verification def GroundStateReceivedData40 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 40 + ) + } + } + } +} + +verification def GroundStateReceivedData50 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 50 + ) + } + } + } +} + +verification def GroundStateReceivedData60 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 60 + ) + } + } + } +} + +verification def GroundStateReceivedData70 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 70 + ) + } + } + } +} + +/* Takes too long for the 5 minute timeout +verification def GroundStateReceivedData80 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 80 + ) + } + } + } +} + +verification def GroundStateReceivedData90 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 90 + ) + } + } + } +} + +verification def GroundStateReceivedData100 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 100 + ) + } + } + } +} +*/ + +verification def SpacecraftData100 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 100 + ) + } + } + } +} + +verification def SpacecraftData90 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 90 + ) + } + } + } +} + +verification def SpacecraftData80 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 80 + ) + } + } + } +} + +verification def SpacecraftData70 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 70 + ) + } + } + } +} + +verification def SpacecraftData60 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 60 + ) + } + } + } +} + +verification def SpacecraftData50 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 50 + ) + } + } + } +} + +verification def SpacecraftData40 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 40 + ) + } + } + } +} + +verification def SpacecraftData30 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 30 + ) + } + } + } +} + +/* Takes too long for the 5 minute timeout +verification def SpacecraftData20 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 20 + ) + } + } + } +} + +verification def SpacecraftData10 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 10 + ) + } + } + } +} + +verification def SpacecraftData0 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 0 + ) + } + } + } +} +*/ From 23dc71746ff1fb81f581e28d3265ad0d1a0fca54 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 15 Mar 2026 01:21:39 +0100 Subject: [PATCH 005/115] Some refactorings --- .../sysmlv2-frontend/Library/Actions.oxsts | 15 +++++---------- .../sysmlv2/sysmlv2-frontend/Library/Parts.oxsts | 14 ++++++++++++++ .../sysmlv2/sysmlv2-frontend/Library/Ports.oxsts | 7 +++++++ .../sysmlv2/sysmlv2-frontend/Library/States.oxsts | 6 +++--- .../sysmlv2-frontend/Library/Triggers.oxsts | 3 +-- .../sysmlv2-frontend/Library/Verification.oxsts | 6 +----- 6 files changed, 31 insertions(+), 20 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Actions.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Actions.oxsts index d0be1e65..bab88d4c 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Actions.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Actions.oxsts @@ -11,18 +11,13 @@ import semantifyr::sysml::expressions import semantifyr::sysml::ports import semantifyr::sysml::items -abstract class Action { - // @Trace - tran execute() { - - } -} +abstract class Action class SendAction : Action { refers viaPort: Port refers payload: Item - redefine tran execute() { + redefine tran { inline viaPort.setOutgoingItem(payload) } } @@ -30,16 +25,16 @@ class SendAction : Action { class AssignmentAction : Action { refers attribute: Attribute contains expression: Expression - redefine tran execute() { + redefine tran { inline attribute.set(expression.evaluate()) } } class CompositeAction : Action { contains children: Action[0..*] - redefine tran execute() { + redefine tran { inline for (child in children) { - inline child.execute() + inline child.main() } } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Parts.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Parts.oxsts index fc558f90..8a44f970 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Parts.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Parts.oxsts @@ -73,6 +73,20 @@ class Part { inline resetInputEvents() } + + tran executeMainComponent() { + inline resetOutputEvents() + + inline for (part in parts) { + inline part.main() + } + + inline executeExhibitState() + + inline for (flow in flows) { + inline flow.main() + } + } } class Flow { diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Ports.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Ports.oxsts index bae2f731..b926b8f3 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Ports.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Ports.oxsts @@ -25,6 +25,10 @@ abstract class Port { return incomingItem == item } + prop hasOutgoingItem(item: Item): bool { + return outgoingItem == item + } + tran assumeHasIncomingItem(item: Item) { assume (hasIncomingItem(item)) } @@ -47,6 +51,9 @@ abstract class Port { tran havocIncomingItem() { havoc (incomingItem) + inline if (actualInputItems != nothing) { + assume (incomingItem != nothing) + } } tran havocOutgoingItem() { diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/States.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/States.oxsts index 5dff2cb2..298216f0 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/States.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/States.oxsts @@ -152,14 +152,14 @@ class State : AbstractState { inline transition.initialize() } - inline entryAction.execute() + inline entryAction.main() } } tran deactivate() { inline if (parent != nothing) { if (parent.getActiveState() == self) { - inline exitAction.execute() + inline exitAction.main() inline parent.setActiveState(nothing) } @@ -193,7 +193,7 @@ class Transition { tran performTransition() { inline from.exit(parentState) - inline action.execute() + inline action.main() inline to.enter(parentState) } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Triggers.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Triggers.oxsts index 449a0be5..46ed9ec7 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Triggers.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Triggers.oxsts @@ -15,7 +15,7 @@ import semantifyr::sysml::actions abstract class AcceptAction { prop isTriggered(): bool { - return true // should be abstract, but no good way to specify defaults at the moment + return true // should be abstract, but no good way to specify defaults atm } tran passTime() { @@ -48,7 +48,6 @@ class AcceptTimeoutAction : AcceptAction { redefine tran passTime() { if (remainingTime > 0) { remainingTime := remainingTime - 1 - // assume (remainingTime >= 0) } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts index 9122a854..6e5fe29e 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts @@ -24,17 +24,13 @@ class VerificationCaseDefinition { contains subject: Part contains objective: Requirement - // refers deltaTimeMin: int = 1 - // refers deltaTimeMax: int = 1 - redefine init { inline subject.init() } redefine tran { inline subject.havocInputEvents() - inline subject.main() - // inline subject.resetOutputEvents() + inline subject.executeMainComponent() inline subject.passTime() } From 2178ad7a84f14bf02648d2cf5ee516c9ebfa3491 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 15 Mar 2026 01:25:30 +0100 Subject: [PATCH 006/115] Updated Theta to 6.27.17 --- .../src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt index 8ceab34c..0e7f8c70 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt @@ -23,7 +23,7 @@ import kotlinx.coroutines.withContext class DockerBasedThetaXstsExecutor : ThetaXstsExecutor() { private val imageName = "ftsrg/theta-xsts-cli" - private val version = "6.27.0" + private val version = "6.27.17" private val config = DefaultDockerClientConfig.createDefaultConfigBuilder().build() private val httpClient = ApacheDockerHttpClient.Builder() .dockerHost(config.dockerHost) From 9ff8952b6d6a96bcd7eaea3f2f1bc044bf3b31e4 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 15 Mar 2026 21:43:30 +0100 Subject: [PATCH 007/115] Implemented EF and AG CTL operators --- .../src/main/kotlin/ThetaVerifier.kt | 12 +- .../kotlin/execution/ThetaPorfolioExecutor.kt | 38 +++- .../xsts/OxstsExpressionTransformer.kt | 16 ++ .../gamma-semantics/Library/Expressions.oxsts | 16 ++ .../Library/Verification.oxsts | 2 +- .../TestModels/Crossroads.gamma | 146 +++++++++++---- .../gamma-semantics/TestModels/Simple.gamma | 26 +-- .../TestModels/Spacecraft.gamma | 27 +-- .../TestModels/sysml-trace.sysml | 113 ------------ .../src/main/kotlin/GammaToOxstsSerializer.kt | 29 ++- .../frontends/gamma/lang/Gamma.xtext | 19 +- .../Library/Expressions.oxsts | 16 ++ .../Library/Verification.oxsts | 2 +- .../TestModels/Verification.sysml | 10 +- .../TestModels/crossroads.sysml | 138 ++++++++++++++- .../sysmlv2-frontend/models26.example.oxsts | 6 +- .../bme/mit/semantifyr/oxsts/lang/Oxsts.xtext | 14 ++ .../lang/formatting2/OxstsFormatter.java | 8 + .../builtin/BuiltinAnnotationHandler.java | 22 --- .../lang/library/builtin/BuiltinLibrary.java | 11 -- .../builtin/BuiltinSymbolResolver.java | 15 +- .../VerificationCaseExpectedResult.java | 13 -- .../ConstantExpressionEvaluator.java | 10 ++ .../MetaConstantExpressionEvaluator.java | 10 ++ .../typesystem/ExpressionTypeEvaluator.java | 10 ++ .../lang/serializer/ExpressionSerializer.java | 10 ++ .../oxsts/lang/utils/ExpressionVisitor.java | 12 ++ .../oxsts/lang/library/semantifyr.oxsts | 59 ++++++- .../library/semantifyr/verification.oxsts | 7 - subprojects/oxsts.model/model/oxsts.aird | 166 +++++++++++++++++- subprojects/oxsts.model/model/oxsts.ecore | 6 + subprojects/oxsts.model/model/oxsts.genmodel | 5 + .../optimization/ExpressionOptimizer.kt | 59 +++++++ .../inliner/ExpressionCallInliner.kt | 10 ++ .../inliner/OxstsCallInliner.kt | 18 ++ .../syntaxes/gamma.tmLanguage.json | 2 +- 36 files changed, 787 insertions(+), 296 deletions(-) delete mode 100644 subprojects/frontends/gamma/gamma-semantics/TestModels/sysml-trace.sysml delete mode 100644 subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/VerificationCaseExpectedResult.java delete mode 100644 subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr/verification.oxsts diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index 6121f1c1..7303690f 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -18,8 +18,9 @@ import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaVerifica import hu.bme.mit.semantifyr.backends.theta.verification.transformation.xsts.OxstsTransformer import hu.bme.mit.semantifyr.backends.theta.wrapper.utils.CexReader import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltinAnnotationHandler -import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.VerificationCaseExpectedResult +import hu.bme.mit.semantifyr.oxsts.model.oxsts.AG import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration +import hu.bme.mit.semantifyr.oxsts.model.oxsts.EF import hu.bme.mit.semantifyr.oxsts.model.oxsts.InlinedOxsts import hu.bme.mit.semantifyr.semantics.transformation.ProgressContext import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped @@ -69,8 +70,6 @@ open class ThetaVerifier : AbstractOxstsVerifier() { } override fun verify(progressContext: ProgressContext, classDeclaration: ClassDeclaration): VerificationCaseRunResult { - val expected = builtinAnnotationHandler.getExpectedResults(classDeclaration) - progressContext.reportProgress("Inlining class") val inlinedOxsts = inlineClass(progressContext, classDeclaration) @@ -99,11 +98,14 @@ open class ThetaVerifier : AbstractOxstsVerifier() { backAnnotateWitness(inlinedOxstsWitness) } - if (expected == VerificationCaseExpectedResult.SAFE && result is ThetaUnsafeVerificationResult) { + // Because of the Temporal bubbling optimizations these are the only options + val property = inlinedOxsts.property.expression + + if (property is AG && result is ThetaUnsafeVerificationResult) { return VerificationCaseRunResult(VerificationResult.Failed, "Expected Safe result, got Unsafe instead!") } - if (expected == VerificationCaseExpectedResult.UNSAFE && result is ThetaSafeVerificationResult) { + if (property is EF && result is ThetaSafeVerificationResult) { return VerificationCaseRunResult(VerificationResult.Failed, "Expected Unsafe result, got Safe instead!") } diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt index 72215074..fc9f7ef2 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt @@ -18,12 +18,16 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.joinAll import kotlinx.coroutines.runBlocking import kotlinx.coroutines.supervisorScope +import org.slf4j.LoggerFactory import java.nio.file.Path import java.util.concurrent.TimeUnit import kotlin.coroutines.cancellation.CancellationException import kotlin.io.path.absolute class ThetaPortfolioRunner { + + private val logger = LoggerFactory.getLogger(ThetaPortfolioRunner::class.java) + val parameters = listOf( "CEGAR --domain EXPL --flatten-depth 0 --refinement SEQ_ITP --maxenum 250 --initprec CTRL --stacktrace", "CEGAR --domain EXPL_PRED_COMBINED --flatten-depth 0 --autoexpl NEWOPERANDS --initprec CTRL --stacktrace", @@ -32,6 +36,7 @@ class ThetaPortfolioRunner { ) val timeout = 5L val timeUnit = TimeUnit.MINUTES + val checkAllResults = false @Inject private lateinit var thetaVerificationExecutor: ThetaVerificationExecutor @@ -47,13 +52,42 @@ class ThetaPortfolioRunner { try { jobs.awaitFirstSuccess() } finally { - jobs.forEach { - it.cancel() + if (checkAllResults) { + checkAllModelCheckerResults(jobs) } + cancelAllModelCheckers(jobs) + jobs.joinAll() } } + private suspend fun checkAllModelCheckerResults(jobs: List>) { + var safe = false + var unsafe = false + + jobs.forEach { + val result = it.await() + + if (result is ThetaSafeVerificationResult) { + logger.debug("Safe result for ${result.runtimeDetails.id}") + safe = true + } else if (result is ThetaUnsafeVerificationResult) { + logger.debug("Unsafe result for ${result.runtimeDetails.id}") + unsafe = true + } + } + + if (safe && unsafe) { + logger.error("Conflicting results!") + } + } + + private fun cancelAllModelCheckers(jobs: List>) { + jobs.forEach { + it.cancel() + } + } + private fun CoroutineScope.startCancellationChecker(progressContext: ProgressContext): Deferred { return async(Dispatchers.IO) { while (true) { diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsExpressionTransformer.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsExpressionTransformer.kt index 9d783634..6ff04adb 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsExpressionTransformer.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsExpressionTransformer.kt @@ -8,6 +8,7 @@ package hu.bme.mit.semantifyr.backends.theta.verification.transformation.xsts import com.google.inject.Inject import hu.bme.mit.semantifyr.oxsts.lang.utils.ExpressionVisitor +import hu.bme.mit.semantifyr.oxsts.model.oxsts.AG import hu.bme.mit.semantifyr.oxsts.model.oxsts.ArithmeticBinaryOperator import hu.bme.mit.semantifyr.oxsts.model.oxsts.ArithmeticOp import hu.bme.mit.semantifyr.oxsts.model.oxsts.ArithmeticUnaryOperator @@ -17,6 +18,7 @@ import hu.bme.mit.semantifyr.oxsts.model.oxsts.BooleanOperator import hu.bme.mit.semantifyr.oxsts.model.oxsts.CallSuffixExpression import hu.bme.mit.semantifyr.oxsts.model.oxsts.ComparisonOp import hu.bme.mit.semantifyr.oxsts.model.oxsts.ComparisonOperator +import hu.bme.mit.semantifyr.oxsts.model.oxsts.EF import hu.bme.mit.semantifyr.oxsts.model.oxsts.Element import hu.bme.mit.semantifyr.oxsts.model.oxsts.ElementReference import hu.bme.mit.semantifyr.oxsts.model.oxsts.EnumLiteral @@ -141,6 +143,20 @@ class OxstsExpressionTransformer : ExpressionVisitor() { } } + override fun visit(expression: AG): XstsExpression { + // AG is implicit in XSTS + return visit(expression.body) + } + + override fun visit(expression: EF): XstsExpression { + // De-morgan: EF f === not AG not f + // the outermost negation is handled on the verifier-side + // and AG is implicit -> not f is enough + return XstsFactory.createNegationOperator().also { + it.body = visit(expression.body) + } + } + override fun visit(expression: ArrayLiteral): XstsExpression { error("No equivalent in XSTS!") } diff --git a/subprojects/frontends/gamma/gamma-semantics/Library/Expressions.oxsts b/subprojects/frontends/gamma/gamma-semantics/Library/Expressions.oxsts index a9e827df..c97d08fb 100644 --- a/subprojects/frontends/gamma/gamma-semantics/Library/Expressions.oxsts +++ b/subprojects/frontends/gamma/gamma-semantics/Library/Expressions.oxsts @@ -117,3 +117,19 @@ class UnaryMinusExpression : UnaryOperatorExpression { return -body.evaluate() } } + +abstract class TemporalOperatorExpression : Expression { + contains body: Expression[1] +} + +class Eventually : TemporalOperatorExpression { + redefine prop evaluate(): any { + return EF body.evaluate() + } +} + +class MustAlways : TemporalOperatorExpression { + redefine prop evaluate(): any { + return AG body.evaluate() + } +} diff --git a/subprojects/frontends/gamma/gamma-semantics/Library/Verification.oxsts b/subprojects/frontends/gamma/gamma-semantics/Library/Verification.oxsts index 0e697091..460a0da2 100644 --- a/subprojects/frontends/gamma/gamma-semantics/Library/Verification.oxsts +++ b/subprojects/frontends/gamma/gamma-semantics/Library/Verification.oxsts @@ -19,6 +19,6 @@ class GammaVerificationCase { } prop { - return !(propertyExpression.evaluate()) + return propertyExpression.evaluate() } } diff --git a/subprojects/frontends/gamma/gamma-semantics/TestModels/Crossroads.gamma b/subprojects/frontends/gamma/gamma-semantics/TestModels/Crossroads.gamma index d5a6ba1b..43403713 100644 --- a/subprojects/frontends/gamma/gamma-semantics/TestModels/Crossroads.gamma +++ b/subprojects/frontends/gamma/gamma-semantics/TestModels/Crossroads.gamma @@ -150,123 +150,191 @@ sync component CrossroadSystem [ // CentralController verification cases -@Reachable verification case ControllerOperatingReachable { component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating) } + property { EF isActive (system.controller.Main.Operating) } } -@Reachable verification case ControllerOperatingBothYellowReachable { component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.BothYellow) } + property { EF isActive (system.controller.Main.Operating.OperatingRegion.BothYellow) } } -@Reachable verification case ControllerOperatingBothRedReachable { component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.BothRed) } + property { EF isActive (system.controller.Main.Operating.OperatingRegion.BothRed) } } -@Reachable verification case ControllerOperatingStoppingAReachable { component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.StoppingA) } + property { EF isActive (system.controller.Main.Operating.OperatingRegion.StoppingA) } } -@Reachable verification case ControllerOperatingStoppingBReachable { component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.StoppingB) } + property { EF isActive (system.controller.Main.Operating.OperatingRegion.StoppingB) } } -@Reachable verification case ControllerOperatingTrafficOnAReachable { component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.TrafficOnA) } + property { EF isActive (system.controller.Main.Operating.OperatingRegion.TrafficOnA) } } -@Reachable verification case ControllerOperatingTrafficOnBReachable { component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.TrafficOnB) } + property { EF isActive (system.controller.Main.Operating.OperatingRegion.TrafficOnB) } } -@Reachable verification case ControllerInterruptedReachable { component system : CrossroadSystem - invariant { isActive (system.controller.Main.Interrupted) } + property { EF isActive (system.controller.Main.Interrupted) } } // TrafficLightController A verification cases -@Reachable verification case ACanBeYellow { component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Normal.NormalRegion.Yellow) } + property { EF isActive (system.trafficLightA.Main.Normal.NormalRegion.Yellow) } } -@Reachable verification case ACanBeRed { component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Normal.NormalRegion.Red) } + property { EF isActive (system.trafficLightA.Main.Normal.NormalRegion.Red) } } -@Reachable verification case ACanBeGreen { component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Normal.NormalRegion.Green) } + property { EF isActive (system.trafficLightA.Main.Normal.NormalRegion.Green) } } -@Reachable verification case ACanBeBlinkingYellow { component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Interrupted.InterruptedRegion.Yellow) } + property { EF isActive (system.trafficLightA.Main.Interrupted.InterruptedRegion.Yellow) } } -@Reachable verification case ACanBeBlinkingBlack { component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Interrupted.InterruptedRegion.Black) } + property { EF isActive (system.trafficLightA.Main.Interrupted.InterruptedRegion.Black) } } // TrafficLightController B verification cases -@Reachable verification case BCanBeYellow { component system : CrossroadSystem - invariant { isActive (system.trafficLightB.Main.Normal.NormalRegion.Yellow) } + property { EF isActive (system.trafficLightB.Main.Normal.NormalRegion.Yellow) } } -@Reachable verification case BCanBeRed { component system : CrossroadSystem - invariant { isActive (system.trafficLightB.Main.Normal.NormalRegion.Red) } + property { EF isActive (system.trafficLightB.Main.Normal.NormalRegion.Red) } } -@Reachable verification case BCanBeGreen { component system : CrossroadSystem - invariant { isActive (system.trafficLightB.Main.Normal.NormalRegion.Green) } + property { EF isActive (system.trafficLightB.Main.Normal.NormalRegion.Green) } } -@Reachable verification case BCanBeBlinkingYellow { component system : CrossroadSystem - invariant { isActive (system.trafficLightB.Main.Interrupted.InterruptedRegion.Yellow) } + property { EF isActive (system.trafficLightB.Main.Interrupted.InterruptedRegion.Yellow) } } -@Reachable verification case BCanBeBlinkingBlack { component system : CrossroadSystem - invariant { isActive (system.trafficLightB.Main.Interrupted.InterruptedRegion.Black) } + property { EF isActive (system.trafficLightB.Main.Interrupted.InterruptedRegion.Black) } } // Combined safety verification cases -@Unreachable -verification case BothCannotBeGreen { +verification case ReachableRedRed { component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Normal.NormalRegion.Green) && isActive (system.trafficLightB.Main.Normal.NormalRegion.Green) } + property { + EF ( + isActive (system.trafficLightA.Main.Normal.NormalRegion.Red) + && isActive (system.trafficLightB.Main.Normal.NormalRegion.Red) + ) + } +} + +verification case ReachableRedGreen { + component system : CrossroadSystem + property { + EF ( + isActive (system.trafficLightA.Main.Normal.NormalRegion.Red) + && isActive (system.trafficLightB.Main.Normal.NormalRegion.Green) + ) + } +} + +verification case ReachableRedYellow { + component system : CrossroadSystem + property { + EF ( + isActive (system.trafficLightA.Main.Normal.NormalRegion.Red) + && isActive (system.trafficLightB.Main.Normal.NormalRegion.Yellow) + ) + } +} + + +verification case ReachableGreenRed { + component system : CrossroadSystem + property { + EF ( + isActive (system.trafficLightA.Main.Normal.NormalRegion.Green) + && isActive (system.trafficLightB.Main.Normal.NormalRegion.Red) + ) + } +} + +verification case UnreachableGreenGreen { + component system : CrossroadSystem + property { + AG not ( + isActive (system.trafficLightA.Main.Normal.NormalRegion.Green) + && isActive (system.trafficLightB.Main.Normal.NormalRegion.Green) + ) + } +} + +verification case UnreachableGreenYellow { + component system : CrossroadSystem + property { + /* AG */ not ( + isActive (system.trafficLightA.Main.Normal.NormalRegion.Green) + && isActive (system.trafficLightB.Main.Normal.NormalRegion.Yellow) + ) + } +} + + +verification case ReachableYellowRed { + component system : CrossroadSystem + property { + EF ( + isActive (system.trafficLightA.Main.Normal.NormalRegion.Yellow) + && isActive (system.trafficLightB.Main.Normal.NormalRegion.Red) + ) + } +} + +verification case UnreachableYellowGreen { + component system : CrossroadSystem + property { + /* AG */ not (EF ( + isActive (system.trafficLightA.Main.Normal.NormalRegion.Yellow) + && isActive (system.trafficLightB.Main.Normal.NormalRegion.Green) + )) + } +} + +verification case ReachableYellowYellow { + component system : CrossroadSystem + property { + EF ( + isActive (system.trafficLightA.Main.Normal.NormalRegion.Yellow) + && isActive (system.trafficLightB.Main.Normal.NormalRegion.Yellow) + ) + } } diff --git a/subprojects/frontends/gamma/gamma-semantics/TestModels/Simple.gamma b/subprojects/frontends/gamma/gamma-semantics/TestModels/Simple.gamma index 879ee6ef..1504e286 100644 --- a/subprojects/frontends/gamma/gamma-semantics/TestModels/Simple.gamma +++ b/subprojects/frontends/gamma/gamma-semantics/TestModels/Simple.gamma @@ -52,59 +52,51 @@ sync component System[ channel [ leader.workerControl ] -> [ worker.control ] } -@Reachable verification case LeaderStatechartIdleReachable { component system : System - invariant { isActive (system.leader.Main.Idle) } + property { EF isActive (system.leader.Main.Idle) } } -@Reachable verification case LeaderStatechartOperationalReachable { component system : System - invariant { isActive (system.leader.Main.Operational) } + property { EF isActive (system.leader.Main.Operational) } } -@Reachable verification case LeaderStatechartStoppedReachable { component system : System - invariant { isActive (system.leader.Main.Stopped) } + property { EF isActive (system.leader.Main.Stopped) } } -@Unreachable verification case LeaderStatechartUnreachable { component system : System - invariant { isActive (system.leader.Main.Unreachable) } + property { /* AG */ not isActive (system.leader.Main.Unreachable) } } -@Reachable verification case WorkerStatechartIdleReachable { component system : System - invariant { isActive (system.worker.Main.Idle) } + property { EF isActive (system.worker.Main.Idle) } } -@Reachable verification case WorkerStatechartOperationalReachable { component system : System - invariant { isActive (system.worker.Main.Operational) } + property { EF isActive (system.worker.Main.Operational) } } -@Reachable verification case WorkerStatechartStoppedReachable { component system : System - invariant { isActive (system.worker.Main.Stopped) } + property { EF isActive (system.worker.Main.Stopped) } } -@Unreachable -verification case WorkerStatechartUnrachable { +verification case WorkerStatechartUnreachable { component system : System - invariant { isActive (system.worker.Main.Unreachable) } + property { /* AG */ not isActive (system.worker.Main.Unreachable) } } diff --git a/subprojects/frontends/gamma/gamma-semantics/TestModels/Spacecraft.gamma b/subprojects/frontends/gamma/gamma-semantics/TestModels/Spacecraft.gamma index 21108ec0..f6af7717 100644 --- a/subprojects/frontends/gamma/gamma-semantics/TestModels/Spacecraft.gamma +++ b/subprojects/frontends/gamma/gamma-semantics/TestModels/Spacecraft.gamma @@ -114,65 +114,56 @@ sync component SpaceMission [ channel [ station.connection ] -> [ spacecraft.connection ] } -@Reachable verification case Station_IdleReachable { component mission : SpaceMission - invariant { isActive (mission.station.Main.Idle) } + property { EF isActive (mission.station.Main.Idle) } } -@Reachable verification case Station_OperationReachable { component mission : SpaceMission - invariant { isActive (mission.station.Main.Operation) } + property { EF isActive (mission.station.Main.Operation) } } -@Reachable verification case Station_OperationReceiveDataWaitingReachable { component mission : SpaceMission - invariant { isActive (mission.station.Main.Operation.ReceiveData.Waiting) } + property { EF isActive (mission.station.Main.Operation.ReceiveData.Waiting) } } -@Reachable verification case Spacecraft_CommunicationWaitingPingReachable { component mission : SpaceMission - invariant { isActive (mission.spacecraft.Communication.WaitingPing) } + property { EF isActive (mission.spacecraft.Communication.WaitingPing) } } -@Reachable verification case Spacecraft_CommunicationTransmittingReachable { component mission : SpaceMission - invariant { isActive (mission.spacecraft.Communication.Transmitting) } + property { EF isActive (mission.spacecraft.Communication.Transmitting) } } -@Reachable verification case Spacecraft_CommunicationTransmittingSendDataSendingReachable { component mission : SpaceMission - invariant { isActive (mission.spacecraft.Communication.Transmitting.SendData.Sending) } + property { EF isActive (mission.spacecraft.Communication.Transmitting.SendData.Sending) } } -@Reachable verification case Spacecraft_CommunicationTransmittingConsumePowerConsumingReachable { component mission : SpaceMission - invariant { isActive (mission.spacecraft.Communication.Transmitting.ConsumePower.Consuming) } + property { EF isActive (mission.spacecraft.Communication.Transmitting.ConsumePower.Consuming) } } -@Reachable verification case Spacecraft_BatteryNotRechargingReachable { component mission : SpaceMission - invariant { isActive (mission.spacecraft.Battery.NotRecharging) } + property { EF isActive (mission.spacecraft.Battery.NotRecharging) } } -@Reachable verification case Spacecraft_BatteryRechargingReachable { component mission : SpaceMission - invariant { isActive (mission.spacecraft.Battery.Recharging) } + property { EF isActive (mission.spacecraft.Battery.Recharging) } } diff --git a/subprojects/frontends/gamma/gamma-semantics/TestModels/sysml-trace.sysml b/subprojects/frontends/gamma/gamma-semantics/TestModels/sysml-trace.sysml deleted file mode 100644 index 8da0ecc6..00000000 --- a/subprojects/frontends/gamma/gamma-semantics/TestModels/sysml-trace.sysml +++ /dev/null @@ -1,113 +0,0 @@ -package Model { - part def MySystem { - attribute x : ScalarValues::Integer default 0; - action myBehavior { - first startShot; - succession __unnamed1 first startShot then m; - merge m; - succession __unnamed2 first m then myStep; - action myStep assign x := x + 1; - succession __unnamed3 first myStep then d; - decide d; - succession repeat first d if x < 2 then m; - succession finish first d if x >= 2 then done; - } - } - part def ExecutedSystem :> MySystem { - private import Occurrences::HappensJustBefore; - private import Occurrences::HappensWhile; - :>> timeSlices : MySystem; - :>> snapshots : MySystem; - action :>> myBehavior { - first startShot; - succession :> __unnamed1 first startShot then m1; - merge m1 :> m; - succession :> __unnamed2 first m1 then myStep1; - succession :> __unnamed3 first myStep1 then d1; - decide d1 :> d; - succession repeat1 :> repeat first d1 if x < 2 then m2; - merge m2 :> m; - succession :> __unnamed2 first m2 then myStep2; - succession :> __unnamed3 first myStep2 then d2; - decide d2 :> d; - succession finish1 :> finish first d2 if x >= 2 then done; - action myStep1 :> myStep; - action myStep2 :> myStep; - } - timeslice before_myBehavior { - attribute :>> x = 0; - } - succession : HappensJustBefore first before_myBehavior then myBehavior_starts; - snapshot myBehavior_starts { - attribute :>> x = 0; - } - succession : HappensWhile first myBehavior.startShot then myBehavior_starts; - succession : HappensJustBefore first myBehavior_starts then between_start_and_m1; - timeslice between_start_and_m1 { - attribute :>> x = 0; - } - succession : HappensJustBefore first between_start_and_m1 then m1_performing; - timeslice m1_performing { - attribute :>> x = 0; - } - succession : HappensWhile first myBehavior.m1 then m1_performing; - succession : HappensJustBefore first m1_performing then between_m1_and_myStep1; - timeslice between_m1_and_myStep1 { - attribute :>> x = 0; - } - succession : HappensJustBefore first between_m1_and_myStep1 then myStep1_performing; - timeslice myStep1_performing { - attribute :>> x = 0; - } - succession : HappensWhile first myBehavior.myStep1 then myStep1_performing; - succession : HappensJustBefore first myStep1_performing then between_myStep1_and_d1; - timeslice between_myStep1_and_d1 { - attribute :>> x = 1; - } - succession : HappensJustBefore first between_myStep1_and_d1 then d1_performing; - timeslice d1_performing { - attribute :>> x = 1; - } - succession : HappensWhile first myBehavior.d1 then d1_performing; - succession : HappensJustBefore first d1_performing then between_d1_and_m2; - timeslice between_d1_and_m2 { - attribute :>> x = 1; - } - succession : HappensJustBefore first between_d1_and_m2 then m2_performing; - timeslice m2_performing { - attribute :>> x = 1; - } - succession : HappensWhile first myBehavior.m2 then m2_performing; - succession : HappensJustBefore first m2_performing then between_m2_and_myStep2; - timeslice between_m2_and_myStep2 { - attribute :>> x = 1; - } - succession : HappensJustBefore first between_m2_and_myStep2 then myStep2_performing; - timeslice myStep2_performing { - attribute :>> x = 1; - } - succession : HappensWhile first myBehavior.myStep2 then myStep2_performing; - succession : HappensJustBefore first myStep2_performing then between_myStep2_and_d2; - timeslice between_myStep2_and_d2 { - attribute :>> x = 2; - } - succession : HappensJustBefore first between_myStep2_and_d2 then d2_performing; - timeslice d2_performing { - attribute :>> x = 2; - } - succession : HappensWhile first myBehavior.d2 then d2_performing; - succession : HappensJustBefore first d2_performing then between_d2_and_done; - timeslice between_d2_and_done { - attribute :>> x = 2; - } - succession : HappensJustBefore first between_d2_and_done then myBehavior_done; - snapshot myBehavior_done { - attribute :>> x = 2; - } - succession : HappensWhile first myBehavior.done then myBehavior_done; - succession : HappensJustBefore first myBehavior_done then after_myBehavior; - timeslice after_myBehavior { - attribute :>> x = 2; - } - } -} diff --git a/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaToOxstsSerializer.kt b/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaToOxstsSerializer.kt index 9a1ec621..19e47696 100644 --- a/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaToOxstsSerializer.kt +++ b/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaToOxstsSerializer.kt @@ -6,6 +6,7 @@ package hu.bme.mit.semantifyr.frontends.gamma.semantics +import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.AG import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.Action import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.ArithmeticBinaryOperator import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.ArithmeticOp @@ -19,6 +20,7 @@ import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.ComparisonOp import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.ComparisonOperator import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.ComponentDeclaration import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.ComponentInstance +import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.EF import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.ElementReferenceExpression import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.EntryTransition import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.EventDeclaration @@ -45,6 +47,7 @@ import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.State import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.StateTransition import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.StatechartDeclaration import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.SyncComponentDeclaration +import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.TemporalOperator import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.TimeoutDeclaration import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.TimeoutTrigger import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.Transition @@ -64,7 +67,6 @@ class GammaToOxstsSerializer { fun transformToOxsts(gammaPackage: GammaModelPackage) = indent { appendLine("package ${gammaPackage.name}") appendLine() - appendLine("import semantifyr::verification") appendLine("import semantifyr::gamma::expressions") appendLine("import semantifyr::gamma::variables") appendLine("import semantifyr::gamma::statecharts") @@ -333,15 +335,11 @@ class GammaToOxstsSerializer { } private fun IndentationAwareStringWriter.serialize(verificationCase: VerificationCaseDeclaration) { - if (verificationCase.isReachable) { - appendLine("@VerificationCase(VerificationResult::UNSAFE)") - } else { - appendLine("@VerificationCase(VerificationResult::SAFE)") - } + appendLine("@VerificationCase") appendIndent("class ${verificationCase.name} : GammaVerificationCase") { appendLine("contains ${verificationCase.component.name}: ${verificationCase.component.component.name} redefines component") - serialize(verificationCase.invariant, "propertyExpression") + serialize(verificationCase.expression, "propertyExpression") } } @@ -349,6 +347,7 @@ class GammaToOxstsSerializer { is ArithmeticBinaryOperator -> serialize(expression, redefines) is ArithmeticUnaryOperator -> serialize(expression, redefines) is BooleanOperator -> serialize(expression, redefines) + is TemporalOperator -> serialize(expression, redefines) is ComparisonOperator -> serialize(expression, redefines) is LiteralExpression -> serialize(expression, redefines) is NegationOperator -> serialize(expression, redefines) @@ -404,6 +403,22 @@ class GammaToOxstsSerializer { serializeOperator(expression.left, expression.right, getOpName(expression.op), redefines) } + private fun IndentationAwareStringWriter.serialize(expression: TemporalOperator, redefines: String) { + when (expression) { + is AG -> serialize(expression, redefines) + is EF -> serialize(expression, redefines) + else -> error("Unknown type of temporal expression: $expression") + } + } + + private fun IndentationAwareStringWriter.serialize(expression: AG, redefines: String) { + serializeOperator(expression.body, "MustAlways", redefines) + } + + private fun IndentationAwareStringWriter.serialize(expression: EF, redefines: String) { + serializeOperator(expression.body, "Eventually", redefines) + } + private fun IndentationAwareStringWriter.serialize(expression: ComparisonOperator, redefines: String) { serializeOperator(expression.left, expression.right, getOpName(expression.op), redefines) } diff --git a/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/Gamma.xtext b/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/Gamma.xtext index f1dd765a..19163409 100644 --- a/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/Gamma.xtext +++ b/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/Gamma.xtext @@ -179,10 +179,9 @@ Channel: ; VerificationCaseDeclaration: - (reachable?='@Reachable' | '@Unreachable') 'verification' 'case' name=Identifier '{' component = ComponentInstance - 'invariant' '{' invariant=Expression '}' + 'property' '{' expression=Expression '}' '}' ; @@ -192,6 +191,20 @@ Expression: OperatorExpression returns Expression: BooleanOperator + | TemporalOperator +; + +TemporalOperator: + AG + | EF +; + +AG: + 'AG' body=BooleanOperator +; + +EF: + 'EF' body=BooleanOperator ; enum BooleanOp: @@ -242,7 +255,7 @@ UnaryOperator returns Expression: ; NegationOperator: - '!' body=UnaryOperator + ('!' | 'not') body=UnaryOperator ; enum UnaryOp: diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Expressions.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Expressions.oxsts index 744cd400..41d74027 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Expressions.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Expressions.oxsts @@ -116,3 +116,19 @@ class UnaryMinusExpression : UnaryOperatorExpression { return -operand.evaluate() } } + +abstract class TemporalOperatorExpression : Expression { + contains body: Expression[1] +} + +class Eventually : TemporalOperatorExpression { + redefine prop evaluate(): any { + return EF body.evaluate() + } +} + +class MustAlways : TemporalOperatorExpression { + redefine prop evaluate(): any { + return AG body.evaluate() + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts index 6e5fe29e..80ec6cfb 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts @@ -35,6 +35,6 @@ class VerificationCaseDefinition { } prop { - return !objective.evaluate() + return objective.evaluate() } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/Verification.sysml b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/Verification.sysml index 530b635b..a278103d 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/Verification.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/Verification.sysml @@ -1,17 +1,11 @@ private import ScalarValues::Boolean; -/* - * Verification constraints with this calculation will be transformed into a 'UNSAFE' expecting verification case. - */ -calc def eventually { +calc def eventually { in op: Boolean[1]; return : Boolean[1]; } -/* - * Verification constraints with this calculation will be transformed into a 'SAFE' expecting verification case. - */ -calc def never { +calc def mustAlways { in op: Boolean[1]; return : Boolean[1]; } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/crossroads.sysml b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/crossroads.sysml index da4919a9..71c3f9b9 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/crossroads.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/crossroads.sysml @@ -31,6 +31,7 @@ part def CentralController { state BothYellow; + // switch A to Red, B to Red transition first BothYellow accept after 1[s] do action { send Toggle() via controlA; send Toggle() via controlB; @@ -38,18 +39,21 @@ part def CentralController { state BothRed; + // switch A to Green transition first BothRed accept after 2[s] do action { send Toggle() via controlA; } then TrafficOnA; state TrafficOnA; + // switch A to Yellow transition first TrafficOnA accept after 2[s] do action { send Toggle() via controlA; } then StoppingA; state StoppingA; + // switch A to Red, B to Green transition first StoppingA accept after 1[s] do action { send Toggle() via controlA; send Toggle() via controlB; @@ -57,12 +61,14 @@ part def CentralController { state TrafficOnB; + // switch B to Yellow transition first TrafficOnB accept after 2[s] do action { send Toggle() via controlB; } then StoppingB; state StoppingB; + // switch A to Green, B to Red transition first StoppingB accept after 1[s] do action { send Toggle() via controlA; send Toggle() via controlB; @@ -78,7 +84,7 @@ part def CentralController { send Police() via controlB; } exit action { - // send Police() via controlA; + send Police() via controlA; send Police() via controlB; } } @@ -136,12 +142,16 @@ part def TrafficLightController { part def CrossroadSystem { port control : ~CentralControl; + // port lightControlA : LightControl; + // port lightControlB : LightControl; part controller: CentralController; part trafficLightA: TrafficLightController; part trafficLightB: TrafficLightController; bind control = controller.control; + // bind lightControlA = trafficLightA.lightControl; + // bind lightControlB = trafficLightB.lightControl; flow from controller.controlA to trafficLightA.control; flow from controller.controlB to trafficLightB.control; @@ -461,13 +471,74 @@ verification def TrafficLightBBehaviorInterruptedBlackReachable { -verification def BothCannotBeGreen { +verification def ReachableRedRed { + subject system : CrossroadSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.trafficLightA.Behaviour.Normal.Red) + and isStateActive(system.trafficLightB.Behaviour.Normal.Red) + ) + } + } + } +} + +verification def ReachableRedGreen { + subject system : CrossroadSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.trafficLightA.Behaviour.Normal.Red) + and isStateActive(system.trafficLightB.Behaviour.Normal.Green) + ) + } + } + } +} + +verification def ReachableRedYellow { + subject system : CrossroadSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.trafficLightA.Behaviour.Normal.Red) + and isStateActive(system.trafficLightB.Behaviour.Normal.Yellow) + ) + } + } + } +} + + +verification def ReachableGreenRed { subject system : CrossroadSystem; objective { verify requirement { require constraint { - never( + eventually( + isStateActive(system.trafficLightA.Behaviour.Normal.Green) + and isStateActive(system.trafficLightB.Behaviour.Normal.Red) + ) + } + } + } +} + +verification def UnreachableGreenGreen { + subject system : CrossroadSystem; + + objective { + verify requirement { + require constraint { + not eventually( isStateActive(system.trafficLightA.Behaviour.Normal.Green) and isStateActive(system.trafficLightB.Behaviour.Normal.Green) ) @@ -475,3 +546,64 @@ verification def BothCannotBeGreen { } } } + +verification def UnreachableGreenYellow { + subject system : CrossroadSystem; + + objective { + verify requirement { + require constraint { + not eventually( + isStateActive(system.trafficLightA.Behaviour.Normal.Green) + and isStateActive(system.trafficLightB.Behaviour.Normal.Yellow) + ) + } + } + } +} + + +verification def ReachableYellowRed { + subject system : CrossroadSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.trafficLightA.Behaviour.Normal.Yellow) + and isStateActive(system.trafficLightB.Behaviour.Normal.Red) + ) + } + } + } +} + +verification def UnreachableYellowGreen { + subject system : CrossroadSystem; + + objective { + verify requirement { + require constraint { + not eventually( + isStateActive(system.trafficLightA.Behaviour.Normal.Yellow) + and isStateActive(system.trafficLightB.Behaviour.Normal.Green) + ) + } + } + } +} + +verification def ReachableYellowYellow { + subject system : CrossroadSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.trafficLightA.Behaviour.Normal.Yellow) + and isStateActive(system.trafficLightB.Behaviour.Normal.Yellow) + ) + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/models26.example.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/models26.example.oxsts index acef9f39..3772127d 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/models26.example.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/models26.example.oxsts @@ -4,7 +4,7 @@ import semantifyr::sysml::expressions import semantifyr::sysml::actions import semantifyr::sysml::attributes -@semantifyr::verification::VerificationCase(semantifyr::verification::VerificationResult::UNSAFE) +@VerificationCase class IncrementAttribute { contains x: IntegerAttribute { @@ -52,11 +52,11 @@ class IncrementAttribute { } redefine tran { - inline composite.execute() + inline composite.main() } prop { - return xLTy.evaluate() + return EF xLTy.evaluate() } } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/Oxsts.xtext b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/Oxsts.xtext index 1bbc4bce..e69e6804 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/Oxsts.xtext +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/Oxsts.xtext @@ -399,6 +399,20 @@ Expression: OperatorExpression returns Expression: BooleanOperator + | TemporalOperator +; + +TemporalOperator returns Expression: + AG + | EF +; + +AG: + 'AG' body=BooleanOperator +; + +EF: + 'EF' body=BooleanOperator ; enum BooleanOp: diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/formatting2/OxstsFormatter.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/formatting2/OxstsFormatter.java index 6794b284..f097967f 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/formatting2/OxstsFormatter.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/formatting2/OxstsFormatter.java @@ -416,6 +416,14 @@ protected void format(BooleanOperator booleanOperator, IFormattableDocument docu document.format(booleanOperator.getRight()); } + protected void format(TemporalOperator temporalOperator, IFormattableDocument document) { + allRegionsFor(temporalOperator).keywords( + "EF", "AG" + ).forEach(r -> document.append(r, this::oneSpace)); + + document.format(temporalOperator.getBody()); + } + protected void format(ArithmeticUnaryOperator unaryOperator, IFormattableDocument document) { document.set(previousHiddenRegion(unaryOperator.getBody()), this::noSpace); diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinAnnotationHandler.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinAnnotationHandler.java index 8eed8dd0..dedbb33b 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinAnnotationHandler.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinAnnotationHandler.java @@ -39,28 +39,6 @@ public boolean isVerificationCase(ClassDeclaration classDeclaration) { return OxstsUtils.isAnnotatedWith(classDeclaration, verificationCaseAnnotation); } - public VerificationCaseExpectedResult getExpectedResults(ClassDeclaration classDeclaration) { - var annotationDeclaration = builtinSymbolResolver.verificationCaseAnnotation(classDeclaration); - var annotation = OxstsUtils.getAnnotation(classDeclaration, annotationDeclaration); - var expectedResultsParameter = builtinSymbolResolver.verificationCaseAnnotationExpectedResults(classDeclaration); - - var value = OxstsUtils.getAnnotationValue(annotation, expectedResultsParameter); - - if (value instanceof ElementReference elementReference) { - if ("SAFE".equals(elementReference.getElement().getName())) { - return VerificationCaseExpectedResult.SAFE; - } - if ("UNSAFE".equals(elementReference.getElement().getName())) { - return VerificationCaseExpectedResult.UNSAFE; - } - if ("UNKNOWN".equals(elementReference.getElement().getName())) { - return VerificationCaseExpectedResult.UNKNOWN; - } - } - - return null; - } - public String getVerificationCaseSummary(ClassDeclaration classDeclaration) { var verificationCaseAnnotation = builtinSymbolResolver.verificationCaseAnnotation(classDeclaration); var verificationCaseAnnotationSummary = builtinSymbolResolver.verificationCaseAnnotationSummary(classDeclaration); diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinLibrary.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinLibrary.java index 450b8617..b59f5e18 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinLibrary.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinLibrary.java @@ -18,10 +18,8 @@ public class BuiltinLibrary extends ResourceBasedOxstsLibrary { public static final QualifiedName BUILTIN_LIBRARY_NAME = QualifiedName.create("semantifyr"); - public static final QualifiedName BUILTIN_VERIFICATION_LIBRARY_NAME = BUILTIN_LIBRARY_NAME.append("verification"); private URI builtinLibraryUri; - private URI builtinVerificationLibraryUri; public BuiltinLibrary() { super(getHomePath().resolve(".semantifyr").resolve("builtin")); @@ -35,14 +33,6 @@ public URI getBuiltinResourceUri() { return builtinLibraryUri; } - public URI getBuiltinVerificationResourceUri() { - if (builtinVerificationLibraryUri == null) { - builtinVerificationLibraryUri = resolveUri(BUILTIN_VERIFICATION_LIBRARY_NAME); - } - - return builtinVerificationLibraryUri; - } - @Override public Iterable getImplicitImports() { return List.of( @@ -57,7 +47,6 @@ protected static Path getHomePath() { @Override protected void saveResources() { saveResource("hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr.oxsts", Path.of("semantifyr.oxsts")); - saveResource("hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr/verification.oxsts", Path.of("semantifyr/verification.oxsts")); } @Override diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinSymbolResolver.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinSymbolResolver.java index 61ccc22e..00d76f81 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinSymbolResolver.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinSymbolResolver.java @@ -24,8 +24,7 @@ public class BuiltinSymbolResolver { public static final QualifiedName SHARED_ANNOTATION_NAME = BuiltinLibrary.BUILTIN_LIBRARY_NAME.append("Shared"); public static final QualifiedName TRACE_ANNOTATION_NAME = BuiltinLibrary.BUILTIN_LIBRARY_NAME.append("Trace"); - public static final QualifiedName VERIFICATION_CASE_ANNOTATION_NAME = BuiltinLibrary.BUILTIN_VERIFICATION_LIBRARY_NAME.append("VerificationCase"); - public static final String VERIFICATION_CASE_EXPECTED_RESULTS_NAME = "expected"; + public static final QualifiedName VERIFICATION_CASE_ANNOTATION_NAME = BuiltinLibrary.BUILTIN_LIBRARY_NAME.append("VerificationCase"); public static final String VERIFICATION_CASE_SUMMARY_NAME = "summary"; public static final QualifiedName ANYTHING_NAME = BuiltinLibrary.BUILTIN_LIBRARY_NAME.append("Anything"); @@ -66,12 +65,7 @@ public AnnotationDeclaration traceAnnotation(EObject context) { } public AnnotationDeclaration verificationCaseAnnotation(EObject context) { - return findInBuiltinVerification(context, AnnotationDeclaration.class, VERIFICATION_CASE_ANNOTATION_NAME); - } - - public ParameterDeclaration verificationCaseAnnotationExpectedResults(EObject context) { - var verificationCase = verificationCaseAnnotation(context); - return findInParameters(verificationCase, ParameterDeclaration.class, VERIFICATION_CASE_EXPECTED_RESULTS_NAME); + return findInBuiltin(context, AnnotationDeclaration.class, VERIFICATION_CASE_ANNOTATION_NAME); } public ParameterDeclaration verificationCaseAnnotationSummary(EObject context) { @@ -181,11 +175,6 @@ protected T findInBuiltin(EObject context, Class type return findInResource(builtinResource, type, name); } - protected T findInBuiltinVerification(EObject context, Class type, QualifiedName name) { - var builtinResource = libraryResourceResolver.resolveResource(builtinLibrary.getBuiltinVerificationResourceUri(), context); - return findInResource(builtinResource, type, name); - } - protected T findInResource(Resource resource, Class type, QualifiedName name) { return namedElementResolver.findQualifiedElement(resource, type, name); } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/VerificationCaseExpectedResult.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/VerificationCaseExpectedResult.java deleted file mode 100644 index 88905c23..00000000 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/VerificationCaseExpectedResult.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package hu.bme.mit.semantifyr.oxsts.lang.library.builtin; - -public enum VerificationCaseExpectedResult { - SAFE, - UNSAFE, - UNKNOWN -} diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ConstantExpressionEvaluator.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ConstantExpressionEvaluator.java index b1768ad0..3c2eaafa 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ConstantExpressionEvaluator.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ConstantExpressionEvaluator.java @@ -128,6 +128,16 @@ protected ExpressionEvaluation visit(NegationOperator expression) { throw new IllegalArgumentException("Expression body is not a boolean expression!"); } + @Override + protected ExpressionEvaluation visit(AG expression) { + throw new IllegalArgumentException("AG expressions are not constant evaluable!"); + } + + @Override + protected ExpressionEvaluation visit(EF expression) { + throw new IllegalArgumentException("EF expressions are not constant evaluable!"); + } + @Override protected ExpressionEvaluation visit(ArrayLiteral expression) { return new ArrayEvaluation(expression.getValues().stream().map(this::evaluate).toList()); diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/MetaConstantExpressionEvaluator.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/MetaConstantExpressionEvaluator.java index df78768b..dc65283e 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/MetaConstantExpressionEvaluator.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/MetaConstantExpressionEvaluator.java @@ -40,6 +40,16 @@ protected NamedElement visit(NegationOperator expressionNegationOperator) { throw new IllegalStateException("This expression is not a meta-expression!"); } + @Override + protected NamedElement visit(AG expression) { + throw new IllegalStateException("This expression is not a meta-expression!"); + } + + @Override + protected NamedElement visit(EF expression) { + throw new IllegalStateException("This expression is not a meta-expression!"); + } + @Override protected NamedElement visit(ArrayLiteral expression) { throw new IllegalStateException("This expression is not a meta-expression!"); diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/typesystem/ExpressionTypeEvaluator.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/typesystem/ExpressionTypeEvaluator.java index 303ca6b6..af53c3ae 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/typesystem/ExpressionTypeEvaluator.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/typesystem/ExpressionTypeEvaluator.java @@ -63,6 +63,16 @@ protected TypeEvaluation visit(NegationOperator expression) { return new ImmutableTypeEvaluation(builtinSymbolResolver.boolDatatype(expression)); } + @Override + protected TypeEvaluation visit(AG expression) { + return new ImmutableTypeEvaluation(builtinSymbolResolver.boolDatatype(expression)); + } + + @Override + protected TypeEvaluation visit(EF expression) { + return new ImmutableTypeEvaluation(builtinSymbolResolver.boolDatatype(expression)); + } + @Override protected TypeEvaluation visit(ArrayLiteral expression) { return new ImmutableTypeEvaluation(builtinSymbolResolver.anyDatatype(expression), RangeEvaluation.of(expression.getValues().size())); diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/serializer/ExpressionSerializer.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/serializer/ExpressionSerializer.java index fd34c1f0..37bbe1a8 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/serializer/ExpressionSerializer.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/serializer/ExpressionSerializer.java @@ -87,6 +87,16 @@ protected String visit(NegationOperator expression) { return "! " + visit(expression.getBody()); } + @Override + protected String visit(AG expression) { + return "AG " + visit(expression.getBody()); + } + + @Override + protected String visit(EF expression) { + return "EF " + visit(expression.getBody()); + } + @Override protected String visit(ArrayLiteral expression) { var values = expression.getValues().stream().map(this::visit).toList(); diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/ExpressionVisitor.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/ExpressionVisitor.java index 49b904d0..c007622f 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/ExpressionVisitor.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/ExpressionVisitor.java @@ -23,6 +23,7 @@ protected T visit(OperatorExpression expression) { return switch (expression) { case BinaryOperator binaryOperator -> visit(binaryOperator); case UnaryOperator unaryOperator -> visit(unaryOperator); + case TemporalOperator temporalOperator -> visit(temporalOperator); default -> throw new IllegalStateException("Unexpected value: " + expression); }; } @@ -53,6 +54,17 @@ protected T visit(UnaryOperator expression) { protected abstract T visit(ArithmeticUnaryOperator expression); protected abstract T visit(NegationOperator expression); + protected T visit(TemporalOperator expression) { + return switch (expression) { + case AG ag -> visit(ag); + case EF ef -> visit(ef); + default -> throw new IllegalStateException("Unexpected value: " + expression); + }; + } + + protected abstract T visit(AG expression); + protected abstract T visit(EF expression); + protected T visit(LiteralExpression expression) { return switch (expression) { case ArrayLiteral literalInfinity -> visit(literalInfinity); diff --git a/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr.oxsts b/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr.oxsts index 65d2ea31..54e36a4c 100644 --- a/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr.oxsts +++ b/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr.oxsts @@ -1,12 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +/* + * The Semantifyr base library. + */ package semantifyr -extern datatype any; -extern datatype int; -extern datatype real; -extern datatype bool; -extern datatype string; +/* + * The any datatype is the base type of all other types. + */ +extern datatype any + +/* + * Integer numbers. + */ +extern datatype int + +/* + * Floating point numbers. Most verification backends do not support it. + */ +extern datatype real + +/* + * Boolean true or false values. + */ +extern datatype bool -annotation Control; +/* + * String datatypes. Most verification backends do not support it. + */ +extern datatype string + +/* + * The Control annotation signals that this variable might be important to track during verification. + */ +annotation Control /* * Anything is the implicit supertype of all classes. @@ -15,11 +46,27 @@ class Anything { // contains children: Anything[0..*] opposite parent; // container parent: Anything[0..1] opposite children; + /* + * The base main transition. + */ tran { } + + /* + * The base init transition. + */ init { } + + /* + * The base havoc transition. + */ havoc { } } +/* + * Classes annotated with VerificationCase can be verified with the Semantifyr toolchain. The optional summary string specifies how this verification case should be presented. + */ +annotation VerificationCase(summary: string[0..1]) + /* * Instances contained in Containment features annotated with @Shared are shared across all instances of the containing class. */ diff --git a/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr/verification.oxsts b/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr/verification.oxsts deleted file mode 100644 index dc4f82fe..00000000 --- a/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr/verification.oxsts +++ /dev/null @@ -1,7 +0,0 @@ -package semantifyr::verification - -enum VerificationResult { - SAFE, UNSAFE, UNKNOWN -} - -annotation VerificationCase(expected: VerificationResult, summary: string) diff --git a/subprojects/oxsts.model/model/oxsts.aird b/subprojects/oxsts.model/model/oxsts.aird index 951f73a2..316fc867 100644 --- a/subprojects/oxsts.model/model/oxsts.aird +++ b/subprojects/oxsts.model/model/oxsts.aird @@ -9,7 +9,7 @@ - + @@ -1187,6 +1187,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1678,6 +1705,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1715,7 +1803,7 @@ - + KEEP_LOCATION @@ -1739,7 +1827,7 @@ - + KEEP_LOCATION @@ -2647,6 +2735,78 @@ + + + + + italic + + + + + + + + + + bold + + + + + + + + + + + + italic + + + + + + + + + + + + + + + + + + + + + + + + + + + + italic + + + + + + + + + + + + italic + + + + + diff --git a/subprojects/oxsts.model/model/oxsts.ecore b/subprojects/oxsts.model/model/oxsts.ecore index f6d66f56..1f33fe23 100644 --- a/subprojects/oxsts.model/model/oxsts.ecore +++ b/subprojects/oxsts.model/model/oxsts.ecore @@ -362,4 +362,10 @@ + + + + + diff --git a/subprojects/oxsts.model/model/oxsts.genmodel b/subprojects/oxsts.model/model/oxsts.genmodel index 67701765..aab5e5cd 100644 --- a/subprojects/oxsts.model/model/oxsts.genmodel +++ b/subprojects/oxsts.model/model/oxsts.genmodel @@ -281,5 +281,10 @@ + + + + + diff --git a/subprojects/semantics/src/main/kotlin/optimization/ExpressionOptimizer.kt b/subprojects/semantics/src/main/kotlin/optimization/ExpressionOptimizer.kt index 372abe56..0113fd16 100644 --- a/subprojects/semantics/src/main/kotlin/optimization/ExpressionOptimizer.kt +++ b/subprojects/semantics/src/main/kotlin/optimization/ExpressionOptimizer.kt @@ -10,8 +10,10 @@ import com.google.inject.Inject import hu.bme.mit.semantifyr.oxsts.lang.semantics.expression.ConstantExpressionEvaluatorProvider import hu.bme.mit.semantifyr.oxsts.lang.semantics.expression.ExpressionEvaluation import hu.bme.mit.semantifyr.oxsts.lang.utils.OxstsUtils +import hu.bme.mit.semantifyr.oxsts.model.oxsts.AG import hu.bme.mit.semantifyr.oxsts.model.oxsts.BooleanOp import hu.bme.mit.semantifyr.oxsts.model.oxsts.BooleanOperator +import hu.bme.mit.semantifyr.oxsts.model.oxsts.EF import hu.bme.mit.semantifyr.oxsts.model.oxsts.Element import hu.bme.mit.semantifyr.oxsts.model.oxsts.Expression import hu.bme.mit.semantifyr.oxsts.model.oxsts.LiteralInteger @@ -21,6 +23,7 @@ import hu.bme.mit.semantifyr.oxsts.model.oxsts.UnaryOperator import hu.bme.mit.semantifyr.semantics.expression.ConstantExpressionEvaluationTransformer import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped import hu.bme.mit.semantifyr.semantics.transformation.serializer.CompilationStateManager +import hu.bme.mit.semantifyr.semantics.utils.OxstsFactory import hu.bme.mit.semantifyr.semantics.utils.eAllOfType import org.eclipse.xtext.EcoreUtil2 @@ -45,6 +48,8 @@ class ExpressionOptimizer : AbstractLoopedOptimizer() { || rewriteRedundantAnd(element) || rewriteDuplicateNegation(element) || rewriteConstantExpression(element) + || bubbleEF(element) + || bubbleAG(element) } // FIXME: replace with constant evaluator! @@ -177,6 +182,60 @@ class ExpressionOptimizer : AbstractLoopedOptimizer() { EcoreUtil2.replace(redundantNegation, internalNegation.body) +// compilationStateManager.commitModelState() + + return true + } + + private fun bubbleEF(element: Element): Boolean { + val redundantNegation = element.eAllOfType().firstOrNull { + it.body is EF + } + + if (redundantNegation == null) { + return false + } + + // not EF f => AG not f + + val ef = redundantNegation.body as EF + val internalExpression = ef.body + + val ag = OxstsFactory.createAG().also { + it.body = OxstsFactory.createNegationOperator().also { + it.body = internalExpression + } + } + + EcoreUtil2.replace(redundantNegation, ag) + +// compilationStateManager.commitModelState() + + return true + } + + private fun bubbleAG(element: Element): Boolean { + val redundantNegation = element.eAllOfType().firstOrNull { + it.body is AG + } + + if (redundantNegation == null) { + return false + } + + // not AG f => EF not f + + val ag = redundantNegation.body as AG + val internalExpression = ag.body + + val ef = OxstsFactory.createEF().also { + it.body = OxstsFactory.createNegationOperator().also { + it.body = internalExpression + } + } + + EcoreUtil2.replace(redundantNegation, ef) + // compilationStateManager.commitModelState() return true diff --git a/subprojects/semantics/src/main/kotlin/transformation/inliner/ExpressionCallInliner.kt b/subprojects/semantics/src/main/kotlin/transformation/inliner/ExpressionCallInliner.kt index ec941b6e..ff3e2166 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/inliner/ExpressionCallInliner.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/inliner/ExpressionCallInliner.kt @@ -10,12 +10,14 @@ import com.google.inject.Inject import com.google.inject.assistedinject.Assisted import com.google.inject.assistedinject.AssistedInject import hu.bme.mit.semantifyr.oxsts.lang.utils.ExpressionVisitor +import hu.bme.mit.semantifyr.oxsts.model.oxsts.AG import hu.bme.mit.semantifyr.oxsts.model.oxsts.ArithmeticBinaryOperator import hu.bme.mit.semantifyr.oxsts.model.oxsts.ArithmeticUnaryOperator import hu.bme.mit.semantifyr.oxsts.model.oxsts.ArrayLiteral import hu.bme.mit.semantifyr.oxsts.model.oxsts.BooleanOperator import hu.bme.mit.semantifyr.oxsts.model.oxsts.CallSuffixExpression import hu.bme.mit.semantifyr.oxsts.model.oxsts.ComparisonOperator +import hu.bme.mit.semantifyr.oxsts.model.oxsts.EF import hu.bme.mit.semantifyr.oxsts.model.oxsts.ElementReference import hu.bme.mit.semantifyr.oxsts.model.oxsts.Expression import hu.bme.mit.semantifyr.oxsts.model.oxsts.FeatureDeclaration @@ -108,6 +110,14 @@ class ExpressionCallInliner @AssistedInject constructor( processorQueue.addFirst(expression.body) } + override fun visit(expression: AG) { + processorQueue.addFirst(expression.body) + } + + override fun visit(expression: EF) { + processorQueue.addFirst(expression.body) + } + override fun visit(expression: ArrayLiteral) { for (index in expression.values.indices.reversed()) { processorQueue.addFirst(expression.values[index]) diff --git a/subprojects/semantics/src/main/kotlin/transformation/inliner/OxstsCallInliner.kt b/subprojects/semantics/src/main/kotlin/transformation/inliner/OxstsCallInliner.kt index 6844e4a6..7ae13e4b 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/inliner/OxstsCallInliner.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/inliner/OxstsCallInliner.kt @@ -10,9 +10,12 @@ import com.google.inject.Inject import hu.bme.mit.semantifyr.oxsts.model.oxsts.InlinedOxsts import hu.bme.mit.semantifyr.oxsts.model.oxsts.Instance import hu.bme.mit.semantifyr.oxsts.model.oxsts.PropertyDeclaration +import hu.bme.mit.semantifyr.oxsts.model.oxsts.TemporalOperator import hu.bme.mit.semantifyr.oxsts.model.oxsts.TransitionDeclaration import hu.bme.mit.semantifyr.semantics.optimization.InlinedOxstsOperationOptimizer import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped +import hu.bme.mit.semantifyr.semantics.utils.OxstsFactory +import hu.bme.mit.semantifyr.semantics.utils.eAllOfType @CompilationScoped class OxstsCallInliner { @@ -32,6 +35,21 @@ class OxstsCallInliner { inlineExpressionCalls(inlinedOxsts.rootInstance, inlinedOxsts.property) inlinedOxstsOperationOptimizer.optimize(inlinedOxsts) + + ensureTemporalExpressions(inlinedOxsts) + } + + private fun ensureTemporalExpressions(inlinedOxsts: InlinedOxsts) { + if (inlinedOxsts.property.expression !is TemporalOperator) { + // all expressions are implicitly AG expressions + inlinedOxsts.property.expression = OxstsFactory.createAG().also { + it.body = inlinedOxsts.property.expression + } + } + + if (inlinedOxsts.eAllOfType().count() > 1) { + error("Temporal operators may only appear inside property blocks!") + } } private fun inlineOperationCalls(rootInstance: Instance, transition: TransitionDeclaration) { diff --git a/subprojects/semantifyr-vscode/syntaxes/gamma.tmLanguage.json b/subprojects/semantifyr-vscode/syntaxes/gamma.tmLanguage.json index a9deeac9..01348893 100644 --- a/subprojects/semantifyr-vscode/syntaxes/gamma.tmLanguage.json +++ b/subprojects/semantifyr-vscode/syntaxes/gamma.tmLanguage.json @@ -23,7 +23,7 @@ "patterns": [ { "name": "keyword.control.xsts", - "match": "\\b(invariant|var|assign|and|or|package|sync|statechart|timeout|region|state|entry|exit|transition|when|in|event|out|raise|set|component|channel|port|interface|verification|reachable|case|@Safe|@Unsafe|requires|provides|to|bind|isActive)\\b" + "match": "\\b(property|var|assign|and|or|package|sync|statechart|timeout|region|state|entry|exit|transition|when|in|event|out|raise|set|component|channel|port|interface|verification|reachable|case|requires|provides|to|bind|isActive|not|EF|AG)\\b" } ] }, From 10d9277dce7f19863461ff92642d7df6ad986669 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 10:41:02 +0100 Subject: [PATCH 008/115] Extracted resource set cloning from compilation scope manager --- .../commands/AbstractCommandHandler.java | 8 +- .../ide/utils/CompilationScopeRunner.java | 62 ++++++++ .../oxsts/lang/ide/utils/EObjectRunnable.java | 14 ++ .../lang/ide/utils/ResourceRunnable.java | 14 ++ .../lang/ide/utils/ResourceSetRunnable.java | 14 ++ .../main/kotlin/reader/SemantifyrLoader.kt | 75 ++------- .../scope/CompilationScopeContext.kt | 5 +- .../scope/CompilationScopeManager.kt | 147 ------------------ .../src/main/kotlin/utils/EcoreUtils.kt | 8 + .../main/kotlin/utils/ResourceSetLoader.kt | 78 ++++++++++ 10 files changed, 214 insertions(+), 211 deletions(-) create mode 100644 subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/CompilationScopeRunner.java create mode 100644 subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/EObjectRunnable.java create mode 100644 subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceRunnable.java create mode 100644 subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceSetRunnable.java delete mode 100644 subprojects/semantics/src/main/kotlin/transformation/injection/scope/CompilationScopeManager.kt create mode 100644 subprojects/semantics/src/main/kotlin/utils/ResourceSetLoader.kt diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/AbstractCommandHandler.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/AbstractCommandHandler.java index bb7c1c97..5b4596d9 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/AbstractCommandHandler.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/AbstractCommandHandler.java @@ -9,8 +9,8 @@ import com.google.inject.Inject; import hu.bme.mit.semantifyr.oxsts.lang.ide.server.concurrent.SemantifyrRequestManager; import hu.bme.mit.semantifyr.oxsts.lang.ide.server.concurrent.WorkManager; -import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScopeManager; -import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.EObjectRunnable; +import hu.bme.mit.semantifyr.oxsts.lang.ide.utils.CompilationScopeRunner; +import hu.bme.mit.semantifyr.oxsts.lang.ide.utils.EObjectRunnable; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.lsp4j.ExecuteCommandParams; @@ -34,7 +34,7 @@ public abstract class AbstractCommandHandler implements CommandHandler { protected SemantifyrRequestManager semantifyrRequestManager; @Inject - protected CompilationScopeManager compilationScopeManager; + protected CompilationScopeRunner compilationScopeRunner; @Inject private IResourceServiceProvider.Registry resourceServiceProviderRegistry; @@ -66,7 +66,7 @@ public Object execute(ExecuteCommandParams params, ILanguageServerAccess access, protected abstract Object execute(T argument, ILanguageServerAccess access, CommandProgressContext progressContext); protected void runLongRunningInCompilationScope(TArg eObject, EObjectRunnable runnable) { - compilationScopeManager.runInCompilationScope(eObject, (copied) -> { + compilationScopeRunner.runInCompilationScope(eObject, (copied) -> { semantifyrRequestManager.releaseReadLock(); try { runnable.run(copied); diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/CompilationScopeRunner.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/CompilationScopeRunner.java new file mode 100644 index 00000000..27ae9cc0 --- /dev/null +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/CompilationScopeRunner.java @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.oxsts.lang.ide.utils; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader; +import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.SemantifyrScopes; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import static hu.bme.mit.semantifyr.semantics.utils.EcoreUtilsKt.unload; + +@Singleton +public class CompilationScopeRunner { + + @Inject + private SemantifyrLoader semantifyrLoader; + + private void useResourceSetInCompilationScope(ResourceSet resourceSet, Runnable block) { + try { + SemantifyrScopes.runInScope(block); + } finally { + unload(resourceSet); + } + } + + public void runInCompilationScope(ResourceSet resourceSet, ResourceSetRunnable runnable) { + ResourceSet compilationResourceSet = semantifyrLoader.cloneOxstsPackagesInResourceSet(resourceSet); + + useResourceSetInCompilationScope(compilationResourceSet, () -> + runnable.run(compilationResourceSet) + ); + } + + public void runInCompilationScope(Resource resource, ResourceRunnable runnable) { + ResourceSet compilationResourceSet = semantifyrLoader.cloneOxstsPackagesInResourceSet(resource.getResourceSet()); + Resource compilationResource = compilationResourceSet.getResource(resource.getURI(), true); + + useResourceSetInCompilationScope(compilationResourceSet, () -> + runnable.run(compilationResource) + ); + } + + public void runInCompilationScope(T eObject, EObjectRunnable runnable) { + ResourceSet compilationResourceSet = semantifyrLoader.cloneOxstsPackagesInResourceSet(eObject.eResource().getResourceSet()); + + @SuppressWarnings("unchecked") + T compilationEObject = (T) compilationResourceSet.getEObject(EcoreUtil.getURI(eObject), true); + + useResourceSetInCompilationScope(compilationResourceSet, () -> + runnable.run(compilationEObject) + ); + } + +} diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/EObjectRunnable.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/EObjectRunnable.java new file mode 100644 index 00000000..a87cfbb0 --- /dev/null +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/EObjectRunnable.java @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.oxsts.lang.ide.utils; + +import org.eclipse.emf.ecore.EObject; + +@FunctionalInterface +public interface EObjectRunnable { + void run(T eObject); +} diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceRunnable.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceRunnable.java new file mode 100644 index 00000000..aaa5f8e9 --- /dev/null +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceRunnable.java @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.oxsts.lang.ide.utils; + +import org.eclipse.emf.ecore.resource.Resource; + +@FunctionalInterface +public interface ResourceRunnable { + void run(Resource resource); +} diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceSetRunnable.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceSetRunnable.java new file mode 100644 index 00000000..3f4a0653 --- /dev/null +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceSetRunnable.java @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.oxsts.lang.ide.utils; + +import org.eclipse.emf.ecore.resource.ResourceSet; + +@FunctionalInterface +public interface ResourceSetRunnable { + void run(ResourceSet resourceSet); +} diff --git a/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt b/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt index a04197a2..6e2daf85 100644 --- a/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt +++ b/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt @@ -4,7 +4,7 @@ * SPDX-License-Identifier: EPL-2.0 */ -package hu.bme.mit.semantifyr.semantics.loading +package hu.bme.mit.semantifyr.semantics.reader import com.google.inject.Inject import com.google.inject.Provider @@ -12,21 +12,13 @@ import hu.bme.mit.semantifyr.oxsts.lang.library.LibraryAdapterFinder import hu.bme.mit.semantifyr.oxsts.lang.utils.ResourceUriProvider import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.OxstsModelPackage -import hu.bme.mit.semantifyr.semantics.utils.error +import hu.bme.mit.semantifyr.semantics.utils.ResourceSetLoader import hu.bme.mit.semantifyr.semantics.utils.info import hu.bme.mit.semantifyr.semantics.utils.loggerFactory -import hu.bme.mit.semantifyr.semantics.utils.warn -import org.eclipse.emf.common.util.URI import org.eclipse.emf.ecore.resource.Resource import org.eclipse.emf.ecore.resource.ResourceSet -import org.eclipse.xtext.EcoreUtil2 -import org.eclipse.xtext.diagnostics.Severity import org.eclipse.xtext.resource.XtextResourceSet -import org.eclipse.xtext.util.CancelIndicator -import org.eclipse.xtext.validation.CheckMode -import org.eclipse.xtext.validation.IResourceValidator import java.nio.file.Path -import kotlin.io.path.absolutePathString class SemantifyrModelContext( val resourceSet: ResourceSet, @@ -49,7 +41,7 @@ class SemantifyrLoader { private lateinit var resourceSetProvider: Provider @Inject - private lateinit var resourceValidator: IResourceValidator + private lateinit var resourceSetLoader: ResourceSetLoader @Inject private lateinit var libraryAdapterFinder: LibraryAdapterFinder @@ -72,7 +64,7 @@ class SemantifyrLoader { fun loadStandaloneModelContext(model: Path): SemantifyrModelContext { val resourceSet = createResourceSet() val resource = loadFile(resourceSet, model) - resolveAndValidate(resourceSet) + resourceSetLoader.resolveAndValidate(resourceSet) return SemantifyrModelContext( resourceSet, listOf(resource) @@ -82,61 +74,28 @@ class SemantifyrLoader { fun loadStandaloneModel(model: Path): Resource { val resourceSet = createResourceSet() val resource = loadFile(resourceSet, model) - resolveAndValidate(resourceSet) + resourceSetLoader.resolveAndValidate(resourceSet) return resource } - private fun resolveAndValidate(resourceSet: ResourceSet) { - EcoreUtil2.resolveAll(resourceSet) - for (resource in resourceSet.resources) { - validateResource(resource) - } - } - - fun validateResource(resource: Resource) { - val issues = resourceValidator.validate(resource, CheckMode.ALL, CancelIndicator.NullImpl) - - if (resource.errors.any()) { - logger.error { "Errors found in file (${resource.uri.toFileString()})" } - - for (error in resource.errors) { - logger.error(error.message) - } - - error("Errors found in file (${resource.uri.toFileString()})}") - } - if (resource.warnings.any()) { - logger.warn { "Warnings found in file (${resource.uri.toFileString()})" } + fun cloneOxstsPackagesInResourceSet(resourceSet: ResourceSet): ResourceSet { + val clone = createResourceSet() - for (warning in resource.warnings) { - logger.warn(warning.message) + // For some reason resourceSet.resources may change in the loop leading to concurrent modification + val resourcesCopy = resourceSet.resources.toList() + for (resource in resourcesCopy) { + if (resource.contents.singleOrNull() is OxstsModelPackage) { + openResource(clone, resource) } } - if (issues.any()) { - logger.info { "Issues found in file (${resource.uri.toFileString()})" } - - for (issue in issues) { - when (issue.severity) { - Severity.INFO -> { - logger.info { "${issue.uriToProblem.toFileString()}[${issue.lineNumber}:${issue.column}] ${issue.message}" } - } - Severity.WARNING -> { - logger.warn { "${issue.uriToProblem.toFileString()}[${issue.lineNumber}:${issue.column}] ${issue.message}" } - } + resourceSetLoader.resolveAndValidate(clone) - Severity.ERROR -> { - logger.error { "${issue.uriToProblem.toFileString()}[${issue.lineNumber}:${issue.column}] ${issue.message}" } - } - - else -> {} - } - } + return clone + } - if (issues.any { it.severity == Severity.ERROR || it.severity == Severity.WARNING }) { - error("Issues found in file!") - } - } + private fun openResource(resourceSet: ResourceSet, resource: Resource): Resource { + return resourceSet.getResource(resource.uri, true) } } diff --git a/subprojects/semantics/src/main/kotlin/transformation/injection/scope/CompilationScopeContext.kt b/subprojects/semantics/src/main/kotlin/transformation/injection/scope/CompilationScopeContext.kt index a0075078..1f803e70 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/injection/scope/CompilationScopeContext.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/injection/scope/CompilationScopeContext.kt @@ -66,7 +66,8 @@ object SemantifyrScopes { } - fun runInScope(block: () -> Unit) { + @JvmStatic + fun runInScope(block: Runnable) { val context = CompilationScopeContext() val current = threadLocalContext.get() if (current != null) { @@ -74,7 +75,7 @@ object SemantifyrScopes { } try { threadLocalContext.set(context) - block() + block.run() } finally { threadLocalContext.set(null) } diff --git a/subprojects/semantics/src/main/kotlin/transformation/injection/scope/CompilationScopeManager.kt b/subprojects/semantics/src/main/kotlin/transformation/injection/scope/CompilationScopeManager.kt deleted file mode 100644 index 88d8de0f..00000000 --- a/subprojects/semantics/src/main/kotlin/transformation/injection/scope/CompilationScopeManager.kt +++ /dev/null @@ -1,147 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package hu.bme.mit.semantifyr.semantics.transformation.injection.scope - -import com.google.inject.Inject -import com.google.inject.Provider -import com.google.inject.Singleton -import hu.bme.mit.semantifyr.oxsts.lang.library.LibraryAdapterFinder -import hu.bme.mit.semantifyr.oxsts.model.oxsts.OxstsModelPackage -import org.eclipse.emf.ecore.EObject -import org.eclipse.emf.ecore.resource.Resource -import org.eclipse.emf.ecore.resource.ResourceSet -import org.eclipse.emf.ecore.util.EcoreUtil -import org.eclipse.xtext.EcoreUtil2 -import org.eclipse.xtext.diagnostics.Severity -import org.eclipse.xtext.resource.XtextResourceSet -import org.eclipse.xtext.util.CancelIndicator -import org.eclipse.xtext.validation.CheckMode -import org.eclipse.xtext.validation.IResourceValidator - -@FunctionalInterface -interface ResourceSetRunnable { - - fun run(resourceSet: ResourceSet) - -} - -@FunctionalInterface -interface ResourceRunnable { - - fun run(resource: Resource) - -} - -@FunctionalInterface -interface EObjectRunnable { - - fun run(eObject: T) - -} - -@Singleton -class CompilationScopeManager { - - @Inject - private lateinit var resourceSetProvider: Provider - - @Inject - private lateinit var libraryAdapterFinder: LibraryAdapterFinder - - @Inject - private lateinit var resourceValidator: IResourceValidator - - private fun createResourceSet(): XtextResourceSet { - val resourceSet = resourceSetProvider.get() - libraryAdapterFinder.getOrInstall(resourceSet) - return resourceSet - } - - private fun unloadResourceSet(resourceSet: ResourceSet) { - resourceSet.resources.forEach { - it.unload() - } - resourceSet.resources.clear() - } - - private fun runCompilationScope(resourceSet: ResourceSet, block: () -> Unit) { - try { - SemantifyrScopes.runInScope(block) - } finally { - unloadResourceSet(resourceSet) - } - } - - fun runInCompilationScope(resourceSet: ResourceSet, runnable: ResourceSetRunnable) { - val compilationResourceSet = copyResourceSet(resourceSet) - - runCompilationScope(compilationResourceSet) { - runnable.run(compilationResourceSet) - } - } - - fun runInCompilationScope(resource: Resource, runnable: ResourceRunnable) { - val compilationResourceSet = copyResourceSet(resource.resourceSet) - val compilationResource = openResource(compilationResourceSet, resource) - - runCompilationScope(compilationResourceSet) { - runnable.run(compilationResource) - } - } - - fun runInCompilationScope(eObject: T, runnable: EObjectRunnable) { - val compilationResourceSet = copyResourceSet(eObject.eResource().resourceSet) - @Suppress("UNCHECKED_CAST") - val compilationEObject = compilationResourceSet.getEObject(EcoreUtil.getURI(eObject), true) as T - - runCompilationScope(compilationResourceSet) { - runnable.run(compilationEObject) - } - } - - private fun copyResourceSet(resourceSet: ResourceSet): ResourceSet { - val compilationResourceSet = createResourceSet() - - // For some reason resourceSet.resources may change in the loop leading to concurrent modification - val resourcesCopy = resourceSet.resources.toList() - for (resource in resourcesCopy) { - if (resource.contents.singleOrNull() is OxstsModelPackage) { - openResource(compilationResourceSet, resource) - } - } - - resolveAndValidate(compilationResourceSet) - - return compilationResourceSet - } - - private fun openResource(resourceSet: ResourceSet, resource: Resource): Resource { - return resourceSet.getResource(resource.uri, true) - } - - private fun resolveAndValidate(resourceSet: ResourceSet) { - EcoreUtil2.resolveAll(resourceSet) - for (resource in resourceSet.resources) { - validateResource(resource) - } - } - - fun validateResource(resource: Resource) { - if (resource.errors.any()) { - error("Errors found in file (${resource.uri.toFileString()})}") - } - - val issues = resourceValidator.validate(resource, CheckMode.ALL, CancelIndicator.NullImpl) - - if (issues.any()) { - if (issues.any { it.severity == Severity.ERROR || it.severity == Severity.WARNING }) { - error("Issues found in file!") - } - } - } - -} diff --git a/subprojects/semantics/src/main/kotlin/utils/EcoreUtils.kt b/subprojects/semantics/src/main/kotlin/utils/EcoreUtils.kt index 9f2803dd..74df17ec 100644 --- a/subprojects/semantics/src/main/kotlin/utils/EcoreUtils.kt +++ b/subprojects/semantics/src/main/kotlin/utils/EcoreUtils.kt @@ -7,8 +7,16 @@ package hu.bme.mit.semantifyr.semantics.utils import org.eclipse.emf.ecore.EObject +import org.eclipse.emf.ecore.resource.ResourceSet import org.eclipse.xtext.EcoreUtil2 fun T.copy(): T = EcoreUtil2.copy(this) inline fun EObject.eAllOfType() = EcoreUtil2.eAll(this).asSequence().filterIsInstance() + +fun ResourceSet.unload() { + resources.forEach { + it.unload() + } + resources.clear() +} diff --git a/subprojects/semantics/src/main/kotlin/utils/ResourceSetLoader.kt b/subprojects/semantics/src/main/kotlin/utils/ResourceSetLoader.kt new file mode 100644 index 00000000..19b0a804 --- /dev/null +++ b/subprojects/semantics/src/main/kotlin/utils/ResourceSetLoader.kt @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.semantics.utils + +import com.google.inject.Inject +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.emf.ecore.resource.ResourceSet +import org.eclipse.xtext.EcoreUtil2 +import org.eclipse.xtext.diagnostics.Severity +import org.eclipse.xtext.util.CancelIndicator +import org.eclipse.xtext.validation.CheckMode +import org.eclipse.xtext.validation.IResourceValidator + +class ResourceSetLoader { + + private val logger by loggerFactory() + + @Inject + private lateinit var resourceValidator: IResourceValidator + + fun resolveAndValidate(resourceSet: ResourceSet) { + EcoreUtil2.resolveAll(resourceSet) + for (resource in resourceSet.resources) { + validateResource(resource) + } + } + + fun validateResource(resource: Resource) { + val issues = resourceValidator.validate(resource, CheckMode.ALL, CancelIndicator.NullImpl) + + if (resource.errors.any()) { + logger.error { "Errors found in file (${resource.uri.toFileString()})" } + + for (error in resource.errors) { + logger.error(error.message) + } + + error("Errors found in file (${resource.uri.toFileString()})}") + } + if (resource.warnings.any()) { + logger.warn { "Warnings found in file (${resource.uri.toFileString()})" } + + for (warning in resource.warnings) { + logger.warn(warning.message) + } + } + if (issues.any()) { + logger.info { "Issues found in file (${resource.uri.toFileString()})" } + + for (issue in issues) { + when (issue.severity) { + Severity.INFO -> { + logger.info { "${issue.uriToProblem.toFileString()}[${issue.lineNumber}:${issue.column}] ${issue.message}" } + } + + Severity.WARNING -> { + logger.warn { "${issue.uriToProblem.toFileString()}[${issue.lineNumber}:${issue.column}] ${issue.message}" } + } + + Severity.ERROR -> { + logger.error { "${issue.uriToProblem.toFileString()}[${issue.lineNumber}:${issue.column}] ${issue.message}" } + } + + else -> {} + } + } + + if (issues.any { it.severity == Severity.ERROR || it.severity == Severity.WARNING }) { + error("Issues found in file!") + } + } + } + +} From 399dddc3f78b5549a758e7476a83d7cbe1bc22c6 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 15:30:38 +0100 Subject: [PATCH 009/115] Implemented Semantifyr loader for verification related tasks --- .../oxsts/lang/ide/OxstsIdeSetup.java | 4 +- .../commands/AbstractCommandHandler.java | 8 +- .../ide/utils/CompilationScopeRunner.java | 62 ----------- .../oxsts/lang/ide/utils/EObjectRunnable.java | 14 --- .../lang/ide/utils/ResourceRunnable.java | 14 --- .../lang/ide/utils/ResourceSetRunnable.java | 14 --- .../kotlin/OxstsSemanticsStandaloneSetup.kt | 8 +- .../main/kotlin/reader/SemantifyrLoader.kt | 87 ++++++++++----- .../kotlin/transformation/ProgressContext.kt | 14 +++ .../main/kotlin/utils/ResourceSetLoader.kt | 2 +- .../src/main/kotlin/utils/SemantifyrUtils.kt | 12 ++ .../verification/CompilationScopeHelper.kt | 71 ++++++++++++ .../kotlin/OxstsSemanticsInjectorProvider.kt | 44 ++++++++ .../SemantifyrVerificationCaseHelper.kt | 104 ++++++++++++++++++ 14 files changed, 313 insertions(+), 145 deletions(-) delete mode 100644 subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/CompilationScopeRunner.java delete mode 100644 subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/EObjectRunnable.java delete mode 100644 subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceRunnable.java delete mode 100644 subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceSetRunnable.java create mode 100644 subprojects/semantics/src/main/kotlin/verification/CompilationScopeHelper.kt create mode 100644 subprojects/semantics/src/testFixtures/kotlin/OxstsSemanticsInjectorProvider.kt create mode 100644 subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationCaseHelper.kt diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/OxstsIdeSetup.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/OxstsIdeSetup.java index 1077f45b..5bbfafc5 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/OxstsIdeSetup.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/OxstsIdeSetup.java @@ -11,7 +11,7 @@ import hu.bme.mit.semantifyr.oxsts.lang.OxstsStandaloneSetup; import hu.bme.mit.semantifyr.oxsts.lang.ide.client.OxstsLanguageClient; import hu.bme.mit.semantifyr.oxsts.lang.ide.server.OxstsServerModule; -import hu.bme.mit.semantifyr.semantics.OxstsSemanticsModule; +import hu.bme.mit.semantifyr.semantics.OxstsSemanticsRuntimeModule; import org.eclipse.lsp4j.jsonrpc.Launcher; import org.eclipse.xtext.ide.server.LanguageServerImpl; import org.eclipse.xtext.util.Modules2; @@ -29,7 +29,7 @@ public class OxstsIdeSetup extends OxstsStandaloneSetup { @Override public Injector createInjector() { - return Guice.createInjector(Modules2.mixin(new OxstsServerModule(), new OxstsSemanticsModule(), new OxstsIdeModule())); + return Guice.createInjector(Modules2.mixin(new OxstsServerModule(), new OxstsSemanticsRuntimeModule(), new OxstsIdeModule())); } public static void main(String[] args) throws InterruptedException, ExecutionException, IOException { diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/AbstractCommandHandler.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/AbstractCommandHandler.java index 5b4596d9..a6a0b287 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/AbstractCommandHandler.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/AbstractCommandHandler.java @@ -9,8 +9,8 @@ import com.google.inject.Inject; import hu.bme.mit.semantifyr.oxsts.lang.ide.server.concurrent.SemantifyrRequestManager; import hu.bme.mit.semantifyr.oxsts.lang.ide.server.concurrent.WorkManager; -import hu.bme.mit.semantifyr.oxsts.lang.ide.utils.CompilationScopeRunner; -import hu.bme.mit.semantifyr.oxsts.lang.ide.utils.EObjectRunnable; +import hu.bme.mit.semantifyr.semantics.verification.CompilationScopeHelper; +import hu.bme.mit.semantifyr.semantics.verification.EObjectRunnable; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.lsp4j.ExecuteCommandParams; @@ -34,7 +34,7 @@ public abstract class AbstractCommandHandler implements CommandHandler { protected SemantifyrRequestManager semantifyrRequestManager; @Inject - protected CompilationScopeRunner compilationScopeRunner; + protected CompilationScopeHelper compilationScopeHelper; @Inject private IResourceServiceProvider.Registry resourceServiceProviderRegistry; @@ -66,7 +66,7 @@ public Object execute(ExecuteCommandParams params, ILanguageServerAccess access, protected abstract Object execute(T argument, ILanguageServerAccess access, CommandProgressContext progressContext); protected void runLongRunningInCompilationScope(TArg eObject, EObjectRunnable runnable) { - compilationScopeRunner.runInCompilationScope(eObject, (copied) -> { + compilationScopeHelper.runInCompilationScope(eObject, (copied) -> { semantifyrRequestManager.releaseReadLock(); try { runnable.run(copied); diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/CompilationScopeRunner.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/CompilationScopeRunner.java deleted file mode 100644 index 27ae9cc0..00000000 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/CompilationScopeRunner.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package hu.bme.mit.semantifyr.oxsts.lang.ide.utils; - -import com.google.inject.Inject; -import com.google.inject.Singleton; -import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader; -import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.SemantifyrScopes; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.resource.ResourceSet; -import org.eclipse.emf.ecore.util.EcoreUtil; - -import static hu.bme.mit.semantifyr.semantics.utils.EcoreUtilsKt.unload; - -@Singleton -public class CompilationScopeRunner { - - @Inject - private SemantifyrLoader semantifyrLoader; - - private void useResourceSetInCompilationScope(ResourceSet resourceSet, Runnable block) { - try { - SemantifyrScopes.runInScope(block); - } finally { - unload(resourceSet); - } - } - - public void runInCompilationScope(ResourceSet resourceSet, ResourceSetRunnable runnable) { - ResourceSet compilationResourceSet = semantifyrLoader.cloneOxstsPackagesInResourceSet(resourceSet); - - useResourceSetInCompilationScope(compilationResourceSet, () -> - runnable.run(compilationResourceSet) - ); - } - - public void runInCompilationScope(Resource resource, ResourceRunnable runnable) { - ResourceSet compilationResourceSet = semantifyrLoader.cloneOxstsPackagesInResourceSet(resource.getResourceSet()); - Resource compilationResource = compilationResourceSet.getResource(resource.getURI(), true); - - useResourceSetInCompilationScope(compilationResourceSet, () -> - runnable.run(compilationResource) - ); - } - - public void runInCompilationScope(T eObject, EObjectRunnable runnable) { - ResourceSet compilationResourceSet = semantifyrLoader.cloneOxstsPackagesInResourceSet(eObject.eResource().getResourceSet()); - - @SuppressWarnings("unchecked") - T compilationEObject = (T) compilationResourceSet.getEObject(EcoreUtil.getURI(eObject), true); - - useResourceSetInCompilationScope(compilationResourceSet, () -> - runnable.run(compilationEObject) - ); - } - -} diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/EObjectRunnable.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/EObjectRunnable.java deleted file mode 100644 index a87cfbb0..00000000 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/EObjectRunnable.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package hu.bme.mit.semantifyr.oxsts.lang.ide.utils; - -import org.eclipse.emf.ecore.EObject; - -@FunctionalInterface -public interface EObjectRunnable { - void run(T eObject); -} diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceRunnable.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceRunnable.java deleted file mode 100644 index aaa5f8e9..00000000 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceRunnable.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package hu.bme.mit.semantifyr.oxsts.lang.ide.utils; - -import org.eclipse.emf.ecore.resource.Resource; - -@FunctionalInterface -public interface ResourceRunnable { - void run(Resource resource); -} diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceSetRunnable.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceSetRunnable.java deleted file mode 100644 index 3f4a0653..00000000 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/utils/ResourceSetRunnable.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package hu.bme.mit.semantifyr.oxsts.lang.ide.utils; - -import org.eclipse.emf.ecore.resource.ResourceSet; - -@FunctionalInterface -public interface ResourceSetRunnable { - void run(ResourceSet resourceSet); -} diff --git a/subprojects/semantics/src/main/kotlin/OxstsSemanticsStandaloneSetup.kt b/subprojects/semantics/src/main/kotlin/OxstsSemanticsStandaloneSetup.kt index 8108d398..7ef53776 100644 --- a/subprojects/semantics/src/main/kotlin/OxstsSemanticsStandaloneSetup.kt +++ b/subprojects/semantics/src/main/kotlin/OxstsSemanticsStandaloneSetup.kt @@ -20,7 +20,7 @@ import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.Semantifyr import hu.bme.mit.semantifyr.semantics.transformation.inliner.ExpressionCallInliner import hu.bme.mit.semantifyr.semantics.transformation.inliner.OperationCallInliner -class OxstsSemanticsModule : OxstsRuntimeModule() { +open class OxstsSemanticsRuntimeModule : OxstsRuntimeModule() { override fun configure(binder: Binder) { binder.bindScope(CompilationScoped::class.java, SemantifyrScopes.COMPILATION) @@ -35,15 +35,15 @@ class OxstsSemanticsModule : OxstsRuntimeModule() { } -class OxstsSemanticsStandaloneSetup : OxstsStandaloneSetup() { +open class OxstsSemanticsStandaloneSetup : OxstsStandaloneSetup() { override fun createInjector(): Injector { - return Guice.createInjector(OxstsSemanticsModule()) + return Guice.createInjector(OxstsSemanticsRuntimeModule()) } } -object StandaloneSemantifyrModule { +object StandaloneOxstsSemanticsRuntimeModule { val injector: Injector by lazy { OxstsSemanticsStandaloneSetup().createInjectorAndDoEMFRegistration() diff --git a/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt b/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt index 6e2daf85..3949bae1 100644 --- a/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt +++ b/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt @@ -13,6 +13,7 @@ import hu.bme.mit.semantifyr.oxsts.lang.utils.ResourceUriProvider import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.OxstsModelPackage import hu.bme.mit.semantifyr.semantics.utils.ResourceSetLoader +import hu.bme.mit.semantifyr.semantics.utils.SemantifyrUtils.modelPathsUnder import hu.bme.mit.semantifyr.semantics.utils.info import hu.bme.mit.semantifyr.semantics.utils.loggerFactory import org.eclipse.emf.ecore.resource.Resource @@ -22,16 +23,9 @@ import java.nio.file.Path class SemantifyrModelContext( val resourceSet: ResourceSet, - val modelResource: List -) { - fun streamClasses(): Sequence { - return modelResource.asSequence().mapNotNull { - it.contents.first() as? OxstsModelPackage - }.flatMap { - it.declarations - }.filterIsInstance(ClassDeclaration::class.java) - } -} + val libraryResources: List, + val modelResources: List, +) class SemantifyrLoader { @@ -55,27 +49,12 @@ class SemantifyrLoader { return resourceSet } - private fun loadFile(resourceSet: ResourceSet, path: Path): Resource { - logger.info { "Reading file: $path" } - val resource = resourceSet.getResource(resourceUriProvider.createFileUri(path), true) - return resource - } - - fun loadStandaloneModelContext(model: Path): SemantifyrModelContext { - val resourceSet = createResourceSet() - val resource = loadFile(resourceSet, model) - resourceSetLoader.resolveAndValidate(resourceSet) - return SemantifyrModelContext( - resourceSet, - listOf(resource) - ) + fun loadStandaloneModel(path: Path): SemantifyrModelContext { + return startContext().loadModel(path).buildAndResolve() } - fun loadStandaloneModel(model: Path): Resource { - val resourceSet = createResourceSet() - val resource = loadFile(resourceSet, model) - resourceSetLoader.resolveAndValidate(resourceSet) - return resource + fun startContext(): SemantifyrLoaderContext { + return SemantifyrLoaderContext() } fun cloneOxstsPackagesInResourceSet(resourceSet: ResourceSet): ResourceSet { @@ -89,7 +68,7 @@ class SemantifyrLoader { } } - resourceSetLoader.resolveAndValidate(clone) + resourceSetLoader.resolveAllAndValidate(clone) return clone } @@ -98,4 +77,52 @@ class SemantifyrLoader { return resourceSet.getResource(resource.uri, true) } + inner class SemantifyrLoaderContext { + val resourceSet = createResourceSet() + val libraryResources = mutableListOf() + val modelResources = mutableListOf() + + fun buildAndResolve(): SemantifyrModelContext { + resourceSetLoader.resolveAllAndValidate(resourceSet) + + return SemantifyrModelContext(resourceSet, libraryResources, modelResources) + } + + fun loadModel(path: Path): SemantifyrLoaderContext { + val resource = loadFile(resourceSet, path) + modelResources += resource + + return this + } + + fun loadModels(path: Path): SemantifyrLoaderContext { + for (modelPath in modelPathsUnder(path)) { + loadModel(modelPath) + } + + return this + } + + fun loadLibrary(path: Path): SemantifyrLoaderContext { + val resource = loadFile(resourceSet, path) + libraryResources += resource + + return this + } + + fun loadLibraries(path: Path): SemantifyrLoaderContext { + for (libraryPath in modelPathsUnder(path)) { + loadLibrary(libraryPath) + } + + return this + } + + private fun loadFile(resourceSet: ResourceSet, path: Path): Resource { + logger.info { "Reading file: $path" } + return resourceSet.getResource(resourceUriProvider.createFileUri(path), true) + } + + } + } diff --git a/subprojects/semantics/src/main/kotlin/transformation/ProgressContext.kt b/subprojects/semantics/src/main/kotlin/transformation/ProgressContext.kt index 52645c31..db23ea7f 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/ProgressContext.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/ProgressContext.kt @@ -14,4 +14,18 @@ interface ProgressContext { fun reportProgress(message: String) + object NoOp : ProgressContext { + override fun checkIsCancelled() { + // NO-OP + } + + override fun reportProgress(message: String, percentage: Int) { + // NO-OP + } + + override fun reportProgress(message: String) { + // NO-OP + } + } + } diff --git a/subprojects/semantics/src/main/kotlin/utils/ResourceSetLoader.kt b/subprojects/semantics/src/main/kotlin/utils/ResourceSetLoader.kt index 19b0a804..47b705cf 100644 --- a/subprojects/semantics/src/main/kotlin/utils/ResourceSetLoader.kt +++ b/subprojects/semantics/src/main/kotlin/utils/ResourceSetLoader.kt @@ -22,7 +22,7 @@ class ResourceSetLoader { @Inject private lateinit var resourceValidator: IResourceValidator - fun resolveAndValidate(resourceSet: ResourceSet) { + fun resolveAllAndValidate(resourceSet: ResourceSet) { EcoreUtil2.resolveAll(resourceSet) for (resource in resourceSet.resources) { validateResource(resource) diff --git a/subprojects/semantics/src/main/kotlin/utils/SemantifyrUtils.kt b/subprojects/semantics/src/main/kotlin/utils/SemantifyrUtils.kt index 508f2488..9a5b683f 100644 --- a/subprojects/semantics/src/main/kotlin/utils/SemantifyrUtils.kt +++ b/subprojects/semantics/src/main/kotlin/utils/SemantifyrUtils.kt @@ -6,7 +6,13 @@ package hu.bme.mit.semantifyr.semantics.utils +import hu.bme.mit.semantifyr.oxsts.lang.library.OxstsLibrary import hu.bme.mit.semantifyr.oxsts.model.oxsts.LocalVarDeclarationOperation +import java.nio.file.Path +import kotlin.io.path.PathWalkOption +import kotlin.io.path.isRegularFile +import kotlin.io.path.name +import kotlin.io.path.walk object SemantifyrUtils { const val LOCAL_VAR_SUFFIX = $$$$"$$$local" @@ -19,4 +25,10 @@ object SemantifyrUtils { return xstsName.contains(LOCAL_VAR_SUFFIX) } + fun modelPathsUnder(path: Path): Sequence { + return path.walk(PathWalkOption.FOLLOW_LINKS).filter { + it.isRegularFile() && it.name.endsWith(OxstsLibrary.FILE_NAME_SUFFIX) + } + } + } diff --git a/subprojects/semantics/src/main/kotlin/verification/CompilationScopeHelper.kt b/subprojects/semantics/src/main/kotlin/verification/CompilationScopeHelper.kt new file mode 100644 index 00000000..911e73bb --- /dev/null +++ b/subprojects/semantics/src/main/kotlin/verification/CompilationScopeHelper.kt @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.semantics.verification + +import com.google.inject.Inject +import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader +import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.SemantifyrScopes.runInScope +import hu.bme.mit.semantifyr.semantics.utils.unload +import org.eclipse.emf.ecore.EObject +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.emf.ecore.resource.ResourceSet +import org.eclipse.emf.ecore.util.EcoreUtil + +fun interface EObjectRunnable { + fun run(eObject: T) +} + +fun interface ResourceRunnable { + fun run(resource: Resource) +} + +fun interface ResourceSetRunnable { + fun run(resourceSet: ResourceSet) +} + +class CompilationScopeHelper { + + @Inject + private lateinit var semantifyrLoader: SemantifyrLoader + + private fun useResourceSetInCompilationScope(resourceSet: ResourceSet, block: Runnable) { + try { + runInScope(block) + } finally { + resourceSet.unload() + } + } + + fun runInCompilationScope(resourceSet: ResourceSet, runnable: ResourceSetRunnable) { + val compilationResourceSet = semantifyrLoader.cloneOxstsPackagesInResourceSet(resourceSet) + + useResourceSetInCompilationScope(compilationResourceSet) { + runnable.run(compilationResourceSet) + } + } + + fun runInCompilationScope(resource: Resource, runnable: ResourceRunnable) { + val compilationResourceSet = semantifyrLoader.cloneOxstsPackagesInResourceSet(resource.resourceSet) + val compilationResource = compilationResourceSet.getResource(resource.uri, true) + + useResourceSetInCompilationScope(compilationResourceSet) { + runnable.run(compilationResource) + } + } + + fun runInCompilationScope(eObject: T, runnable: EObjectRunnable) { + val compilationResourceSet = semantifyrLoader.cloneOxstsPackagesInResourceSet(eObject.eResource().resourceSet) + + @Suppress("UNCHECKED_CAST") + val compilationEObject = compilationResourceSet.getEObject(EcoreUtil.getURI(eObject), true) as T + + useResourceSetInCompilationScope(compilationResourceSet) { + runnable.run(compilationEObject) + } + } + +} diff --git a/subprojects/semantics/src/testFixtures/kotlin/OxstsSemanticsInjectorProvider.kt b/subprojects/semantics/src/testFixtures/kotlin/OxstsSemanticsInjectorProvider.kt new file mode 100644 index 00000000..d4fa7cae --- /dev/null +++ b/subprojects/semantics/src/testFixtures/kotlin/OxstsSemanticsInjectorProvider.kt @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.semantics + +import com.google.inject.Guice +import com.google.inject.Injector +import hu.bme.mit.semantifyr.oxsts.lang.tests.OxstsInjectorProvider +import org.eclipse.xtext.testing.InjectWith +import org.eclipse.xtext.testing.extensions.InjectionExtension +import org.junit.jupiter.api.extension.ExtendWith + +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +@ExtendWith(InjectionExtension::class) +@InjectWith(OxstsSemanticsInjectorProvider::class) +annotation class InjectWithOxstsSemantics + +class OxstsSemanticsInjectorProvider : OxstsInjectorProvider() { + + override fun internalCreateInjector(): Injector { + return object : OxstsSemanticsStandaloneSetup() { + override fun createInjector(): Injector { + return Guice.createInjector(createRuntimeModule()) + } + }.createInjectorAndDoEMFRegistration() + } + + override fun createRuntimeModule(): OxstsSemanticsRuntimeModule { + // make it work also with Maven/Tycho and OSGI + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=493672 + // allows for bindClassLoaderToInstance to get the class loader of the bundle + // containing the instance of the injector provider (possibly inherited) + return object : OxstsSemanticsRuntimeModule() { + override fun bindClassLoaderToInstance(): ClassLoader { + return this@OxstsSemanticsInjectorProvider.javaClass.classLoader + } + } + } + +} diff --git a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationCaseHelper.kt b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationCaseHelper.kt new file mode 100644 index 00000000..1781e20a --- /dev/null +++ b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationCaseHelper.kt @@ -0,0 +1,104 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.semantics + +import com.google.inject.Inject +import com.google.inject.Provider +import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltInLibraryUtils +import hu.bme.mit.semantifyr.oxsts.lang.naming.OxstsQualifiedNameProvider +import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration +import hu.bme.mit.semantifyr.oxsts.model.oxsts.OxstsModelPackage +import hu.bme.mit.semantifyr.semantics.reader.SemantifyrModelContext +import hu.bme.mit.semantifyr.semantics.transformation.ProgressContext +import hu.bme.mit.semantifyr.semantics.utils.info +import hu.bme.mit.semantifyr.semantics.verification.CompilationScopeHelper +import hu.bme.mit.semantifyr.semantics.verification.OxstsVerifier +import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult +import hu.bme.mit.semantifyr.semantics.verification.VerificationResult +import org.junit.jupiter.api.Assertions +import org.slf4j.Logger +import kotlin.streams.asSequence + +abstract class BaseSemantifyrVerificationTest { + + abstract val logger: Logger + + val loggerContext = object : ProgressContext { + override fun checkIsCancelled() { + // never cancelled + } + + override fun reportProgress(message: String, percentage: Int) { + logger.info { "$message - $percentage%" } + } + + override fun reportProgress(message: String) { + logger.info { message } + } + + } + + @Inject + lateinit var oxstsQualifiedNameProvider: OxstsQualifiedNameProvider + + @Inject + lateinit var builtInLibraryUtils: BuiltInLibraryUtils + + @Inject + lateinit var compilationScopeHelper: CompilationScopeHelper + + abstract val oxstsVerifierProvider: Provider + + fun runVerification(classDeclaration: ClassDeclaration): VerificationCaseRunResult { + logger.info { + "Verifying class: ${oxstsQualifiedNameProvider.getFullyQualifiedNameString(classDeclaration)}" + } + + return oxstsVerifierProvider.get().verify(loggerContext, classDeclaration) + } + + fun collectVerificationCases(model: SemantifyrModelContext): Sequence { + return model.modelResources.asSequence().map { + it.contents.single() + }.filterIsInstance().flatMap { + builtInLibraryUtils.streamTestCases(it).asSequence() + } + } + + fun verifyVerificationCases(model: SemantifyrModelContext) { + logger.info { "Collecting verification cases" } + + val verificationCases = collectVerificationCases(model).toList() + + for (verificationCase in verificationCases) { + compilationScopeHelper.runInCompilationScope(verificationCase) { + val result = runVerification(it) + + Assertions.assertEquals(result.result, VerificationResult.Passed) + } + } + } + + fun verifyVerificationCase(model: SemantifyrModelContext, qualifiedName: String) { + logger.info { "Looking for $qualifiedName" } + + val verificationCase = collectVerificationCases(model).firstOrNull { + oxstsQualifiedNameProvider.getFullyQualifiedNameString(it) == qualifiedName + } + + if (verificationCase == null) { + error("$qualifiedName can not be found!") + } + + compilationScopeHelper.runInCompilationScope(verificationCase) { + val result = runVerification(it) + + Assertions.assertEquals(result.result, VerificationResult.Passed) + } + } + +} From 28f49e7deae6c23bad3644a82843019f09917f6a Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 15:31:08 +0100 Subject: [PATCH 010/115] Extracted test case streaming --- ...scoverVerificationCasesCommandHandler.java | 18 +++++------ .../library/builtin/BuiltInLibraryUtils.java | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltInLibraryUtils.java diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/DiscoverVerificationCasesCommandHandler.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/DiscoverVerificationCasesCommandHandler.java index 78d28ca9..1c4fd6d0 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/DiscoverVerificationCasesCommandHandler.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/DiscoverVerificationCasesCommandHandler.java @@ -8,6 +8,7 @@ import com.google.gson.JsonPrimitive; import com.google.inject.Inject; +import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltInLibraryUtils; import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltinAnnotationHandler; import hu.bme.mit.semantifyr.oxsts.lang.naming.OxstsQualifiedNameProvider; import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration; @@ -24,6 +25,9 @@ public class DiscoverVerificationCasesCommandHandler extends AbstractCommandHand @Inject private BuiltinAnnotationHandler builtinAnnotationHandler; + @Inject + private BuiltInLibraryUtils builtInLibraryUtils; + @Inject private OxstsQualifiedNameProvider oxstsQualifiedNameProvider; @@ -61,17 +65,9 @@ protected Object execute(Resource arguments, ILanguageServerAccess access, Comma } var verificationCases = new ArrayList(); - - for (var declaration : oxstsModel.getDeclarations()) { - if (!(declaration instanceof ClassDeclaration classDeclaration)) { - continue; - } - - if (builtinAnnotationHandler.isVerificationCase(classDeclaration)) { - verificationCases.add(createCase(classDeclaration)); - verificationCases.add(createCase(classDeclaration)); - } - } + builtInLibraryUtils.streamTestCases(oxstsModel).forEach(testCase -> + verificationCases.add(createCase(testCase)) + ); return verificationCases; } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltInLibraryUtils.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltInLibraryUtils.java new file mode 100644 index 00000000..ba0e62c9 --- /dev/null +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltInLibraryUtils.java @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.oxsts.lang.library.builtin; + +import com.google.inject.Inject; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.OxstsModelPackage; + +import java.util.stream.Stream; + +public class BuiltInLibraryUtils { + + @Inject + private BuiltinAnnotationHandler builtinAnnotationHandler; + + public Stream streamTestCases(OxstsModelPackage oxstsModelPackage) { + return oxstsModelPackage.getDeclarations().stream().filter(d -> + d instanceof ClassDeclaration + ).map(d -> + (ClassDeclaration) d + ).filter(classDeclaration -> + builtinAnnotationHandler.isVerificationCase(classDeclaration) + ); + } + +} From bffa943d8dd6e2a070534b8a98e51eb2f55bc627 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 15:31:27 +0100 Subject: [PATCH 011/115] Fixed relative path bug --- .../mit/semantifyr/oxsts/lang/utils/ResourceUriProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/ResourceUriProvider.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/ResourceUriProvider.java index b51647d9..969d5c20 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/ResourceUriProvider.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/ResourceUriProvider.java @@ -19,7 +19,7 @@ public class ResourceUriProvider { // To be consistent with the LSP server implementation we need to ensure our URIs have an empty authority public URI createFileUri(Path path) { - var fileUri = URI.createFileURI(path.toString()); + var fileUri = URI.createFileURI(path.toAbsolutePath().toString()); return uriExtensions.withEmptyAuthority(fileUri); } From 5c441ddf229b7832210fb917775f0c442dad2286 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 15:31:41 +0100 Subject: [PATCH 012/115] Added logging runtime --- subprojects/oxsts.lang/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subprojects/oxsts.lang/build.gradle.kts b/subprojects/oxsts.lang/build.gradle.kts index 9ca9d643..e5bac7cd 100644 --- a/subprojects/oxsts.lang/build.gradle.kts +++ b/subprojects/oxsts.lang/build.gradle.kts @@ -10,6 +10,8 @@ plugins { dependencies { api(project(":oxsts.model")) + + testRuntimeOnly(libs.slf4j.log4j) } xtext { From d73f7b626d18d752137132cd66bcf6f58f931a2b Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 15:32:09 +0100 Subject: [PATCH 013/115] Renamed sysmlv2-frontend to sysmlv2-semantics --- .../{sysmlv2-frontend => sysmlv2-semantics}/Library/Actions.oxsts | 0 .../Library/Attributes.oxsts | 0 .../Library/Expressions.oxsts | 0 .../{sysmlv2-frontend => sysmlv2-semantics}/Library/Items.oxsts | 0 .../{sysmlv2-frontend => sysmlv2-semantics}/Library/Parts.oxsts | 0 .../{sysmlv2-frontend => sysmlv2-semantics}/Library/Ports.oxsts | 0 .../{sysmlv2-frontend => sysmlv2-semantics}/Library/States.oxsts | 0 .../Library/Triggers.oxsts | 0 .../Library/Verification.oxsts | 0 .../{sysmlv2-frontend => sysmlv2-semantics}/TestModels/.gitignore | 0 .../TestModels/Verification.sysml | 0 .../TestModels/crossroads.sysml | 0 .../TestModels/spacecraft.sysml | 0 .../TestModels/stm21.sysml | 0 .../TestModels/stm31.sysml | 0 .../TestModels/sysml-trace.sysml | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/Library/Actions.oxsts (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/Library/Attributes.oxsts (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/Library/Expressions.oxsts (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/Library/Items.oxsts (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/Library/Parts.oxsts (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/Library/Ports.oxsts (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/Library/States.oxsts (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/Library/Triggers.oxsts (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/Library/Verification.oxsts (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/TestModels/.gitignore (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/TestModels/Verification.sysml (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/TestModels/crossroads.sysml (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/TestModels/spacecraft.sysml (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/TestModels/stm21.sysml (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/TestModels/stm31.sysml (100%) rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics}/TestModels/sysml-trace.sysml (100%) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Actions.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Actions.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Actions.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Actions.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Attributes.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Attributes.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Attributes.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Attributes.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Expressions.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Expressions.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Expressions.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Expressions.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Items.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Items.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Items.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Items.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Parts.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Parts.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Parts.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Parts.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Ports.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Ports.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Ports.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Ports.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/States.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/States.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/States.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/States.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Triggers.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Triggers.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Triggers.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Triggers.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Verification.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/Library/Verification.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Verification.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/.gitignore b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/.gitignore similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/.gitignore rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/.gitignore diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/Verification.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/Verification.sysml similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/Verification.sysml rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/Verification.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/crossroads.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/crossroads.sysml similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/crossroads.sysml rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/crossroads.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/spacecraft.sysml similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/spacecraft.sysml rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/spacecraft.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/stm21.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm21.sysml similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/stm21.sysml rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm21.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/stm31.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm31.sysml similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/stm31.sysml rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm31.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/sysml-trace.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/sysml-trace.sysml similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/TestModels/sysml-trace.sysml rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/sysml-trace.sysml From 4cb6841160d9d257632b85e1596b21658c2942c2 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 15:33:00 +0100 Subject: [PATCH 014/115] Extracted gamma transformation from gamma-cli --- .../main/kotlin/commands/CompileCommand.kt | 17 ++--------- .../src/main/kotlin/GammaTransformer.kt | 29 +++++++++++++++++++ .../GammaToOxstsSerializer.kt | 8 ++--- 3 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaTransformer.kt rename subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/{ => serialization}/GammaToOxstsSerializer.kt (97%) diff --git a/subprojects/frontends/gamma/gamma-cli/src/main/kotlin/commands/CompileCommand.kt b/subprojects/frontends/gamma/gamma-cli/src/main/kotlin/commands/CompileCommand.kt index 99d36f43..859e0bed 100644 --- a/subprojects/frontends/gamma/gamma-cli/src/main/kotlin/commands/CompileCommand.kt +++ b/subprojects/frontends/gamma/gamma-cli/src/main/kotlin/commands/CompileCommand.kt @@ -10,10 +10,7 @@ import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.file -import hu.bme.mit.semantifyr.frontends.gamma.semantics.reader.GammaReader -import hu.bme.mit.semantifyr.frontends.gamma.semantics.GammaToOxstsSerializer -import hu.bme.mit.semantifyr.frontends.gamma.lang.GammaStandaloneSetup -import java.io.File +import hu.bme.mit.semantifyr.frontends.gamma.semantics.StandaloneGammaTransformer class CompileCommand : CliktCommand("compile") { @@ -21,16 +18,8 @@ class CompileCommand : CliktCommand("compile") { val outputPath by option("-o", "--output").file(mustExist = false, canBeFile = true) override fun run() { - val injector = GammaStandaloneSetup().createInjectorAndDoEMFRegistration() - val reader = injector.getInstance(GammaReader::class.java) - - val gammaModel = reader.readGammaFile(modelPath) - - val serializer = injector.getInstance(GammaToOxstsSerializer::class.java) - val oxstsModel = serializer.transformToOxsts(gammaModel) - val outputFile = outputPath ?: File(modelPath.absolutePath.replace(".gamma", ".oxsts")) - - outputFile.writeText(oxstsModel) + val transformer = StandaloneGammaTransformer() + transformer.transformModel(modelPath, outputPath) } } diff --git a/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaTransformer.kt b/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaTransformer.kt new file mode 100644 index 00000000..351c28e7 --- /dev/null +++ b/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaTransformer.kt @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.frontends.gamma.semantics + +import hu.bme.mit.semantifyr.frontends.gamma.lang.GammaStandaloneSetup +import hu.bme.mit.semantifyr.frontends.gamma.semantics.reader.GammaReader +import hu.bme.mit.semantifyr.frontends.gamma.semantics.serialization.GammaToOxstsSerializer +import java.io.File + +class StandaloneGammaTransformer { + + fun transformModel(modelPath: File, outputPath: File? = null) { + val injector = GammaStandaloneSetup().createInjectorAndDoEMFRegistration() + val reader = injector.getInstance(GammaReader::class.java) + + val gammaModel = reader.readGammaFile(modelPath) + + val serializer = injector.getInstance(GammaToOxstsSerializer::class.java) + val oxstsModel = serializer.transformToOxsts(gammaModel) + val outputFile = outputPath ?: File(modelPath.absolutePath.replace(".gamma", ".oxsts")) + + outputFile.writeText(oxstsModel) + } + +} diff --git a/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaToOxstsSerializer.kt b/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/serialization/GammaToOxstsSerializer.kt similarity index 97% rename from subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaToOxstsSerializer.kt rename to subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/serialization/GammaToOxstsSerializer.kt index 19e47696..b6d0d419 100644 --- a/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/GammaToOxstsSerializer.kt +++ b/subprojects/frontends/gamma/gamma-semantics/src/main/kotlin/serialization/GammaToOxstsSerializer.kt @@ -1,10 +1,10 @@ /* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors * * SPDX-License-Identifier: EPL-2.0 */ -package hu.bme.mit.semantifyr.frontends.gamma.semantics +package hu.bme.mit.semantifyr.frontends.gamma.semantics.serialization import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.AG import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.Action @@ -56,10 +56,6 @@ import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.TypeReference import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.UnaryOp import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.VariableDeclaration import hu.bme.mit.semantifyr.frontends.gamma.lang.gamma.VerificationCaseDeclaration -import hu.bme.mit.semantifyr.frontends.gamma.semantics.serialization.EObjectNameProvider -import hu.bme.mit.semantifyr.frontends.gamma.semantics.serialization.IndentationAwareStringWriter -import hu.bme.mit.semantifyr.frontends.gamma.semantics.serialization.appendIndent -import hu.bme.mit.semantifyr.frontends.gamma.semantics.serialization.indent import org.eclipse.xtext.nodemodel.util.NodeModelUtils class GammaToOxstsSerializer { From 1dd7f01d6410f1ee2ed6a0da777bcc91b6736bf7 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 15:34:55 +0100 Subject: [PATCH 015/115] Added shutdown hook for verifiers. Added JVM shutdown hook to ensure started verifiers are always terminated when the JVM is terminated gracefully. Ungraceful termination can not be supported, however, in such cases we can expect the terminator to handle our started processes. --- .../kotlin/execution/ThetaPorfolioExecutor.kt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt index fc9f7ef2..5eadb002 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt @@ -49,15 +49,27 @@ class ThetaPortfolioRunner { } } + // since verification is expensive, this hook ensures all verifiers are disposed of upon termination. + // putting it here to prevent forgetting it in the specific verifier executors. + // executors must only ensure to handle cancellation correctly. + val shutdownThread = Thread { + runBlocking { + cancelAllModelCheckers(jobs) + } + } + + Runtime.getRuntime().addShutdownHook(shutdownThread) + try { jobs.awaitFirstSuccess() } finally { if (checkAllResults) { checkAllModelCheckerResults(jobs) } + cancelAllModelCheckers(jobs) - jobs.joinAll() + Runtime.getRuntime().removeShutdownHook(shutdownThread) } } @@ -82,10 +94,11 @@ class ThetaPortfolioRunner { } } - private fun cancelAllModelCheckers(jobs: List>) { + private suspend fun cancelAllModelCheckers(jobs: List>) { jobs.forEach { it.cancel() } + jobs.joinAll() } private fun CoroutineScope.startCancellationChecker(progressContext: ProgressContext): Deferred { From d60f8c0127bc2525d7fa93856dddb09b197d0514 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 15:35:38 +0100 Subject: [PATCH 016/115] Added verification unit tests --- .../gradle/conventions/jvm.gradle.kts | 38 +- gradle/libs.versions.toml | 3 +- settings.gradle.kts | 1 + .../theta/xsts-verifier/build.gradle.kts | 5 + .../test/kotlin/ThetaXstsVerificationTests.kt | 38 + .../test-models/Simple/.gitignore | 1 + .../test-models/Simple/simple.oxsts | 35 + .../gamma/gamma-semantics/build.gradle.kts | 5 + .../src/test/kotlin/GammaVerificationTests.kt | 65 ++ .../sysmlv2-semantics/build.gradle.kts | 21 + .../sysmlv2-semantics/models/.gitignore | 9 + .../sysmlv2-semantics/models/crossroads.oxsts | 769 ++++++++++++++++ .../models}/models26.example.oxsts | 0 .../sysmlv2-semantics/models/spacecraft.oxsts | 845 ++++++++++++++++++ .../sysmlv2-semantics/models/stm21.oxsts | 113 +++ .../sysmlv2-semantics/models/stm31.oxsts | 158 ++++ .../src/test/kotlin/SysMLVerificationTests.kt | 62 ++ 17 files changed, 2163 insertions(+), 5 deletions(-) create mode 100644 subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt create mode 100644 subprojects/backends/theta/xsts-verifier/test-models/Simple/.gitignore create mode 100644 subprojects/backends/theta/xsts-verifier/test-models/Simple/simple.oxsts create mode 100644 subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/.gitignore create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts rename subprojects/frontends/sysmlv2/{sysmlv2-frontend => sysmlv2-semantics/models}/models26.example.oxsts (100%) create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm21.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm31.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts index 0c0e1324..0d6e6bcb 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts @@ -38,9 +38,20 @@ java.toolchain { languageVersion = JavaLanguageVersion.of(25) } +/* + * Simple Build service that acts as a lock or throttling device preventing parallel execution + */ +abstract class VerificationTestService : BuildService +val verificationTestServiceName = "verificationTestService" +val verificationTestServiceProvider = gradle.sharedServices.registerIfAbsent(verificationTestServiceName, VerificationTestService::class) { + // only allow at most 1 verification task per Gradle build + maxParallelUsages.set(1) +} + tasks { test { useJUnitPlatform { + excludeTags("verification") excludeTags("slow") } @@ -52,17 +63,38 @@ tasks { finalizedBy(tasks.jacocoTestReport) } - val allTests by tasks.registering(Test::class) { - useJUnitPlatform() + val verificationTest by tasks.registering(Test::class) { + group = "verification" + + useJUnitPlatform { + includeTags("verification") + excludeTags("slow") + } + + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + usesService(verificationTestServiceProvider) minHeapSize = "512m" maxHeapSize = "4G" testLogging.showStandardStreams = true + testLogging.exceptionFormat = TestExceptionFormat.FULL - finalizedBy(tasks.jacocoTestReport) + maxParallelForks = 1 + + shouldRunAfter(test) + finalizedBy(jacocoTestReport) } jacocoTestReport { inputs.files(test.get().outputs) + inputs.files(verificationTest.get().outputs) + + executionData(test.get(), verificationTest.get()) + } + + check { + inputs.files(verificationTest.get().outputs) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3c1c3f38..f7a2febd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,6 @@ ecore = "2.41.0" junit = "6.0.3" assertj = "3.27.7" -junitplatform = "6.0.3" mockito = "5.21.0" mwe2 = "2.25.0" slf4j = "2.0.17" @@ -24,7 +23,7 @@ node = "7.1.0" [libraries] ecore = { group = "org.eclipse.emf", name = "org.eclipse.emf.ecore", version.ref = "ecore" } ecore-codegen = { group = "org.eclipse.emf", name = "org.eclipse.emf.codegen.ecore", version.ref = "ecore" } -junit-platform-launcher = { group = "org.junit.platform", name = "junit-platform-launcher", version.ref = "junitplatform" } +junit-platform-launcher = { group = "org.junit.platform", name = "junit-platform-launcher", version.ref = "junit" } junit-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit" } junit-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit" } junit-params = { group = "org.junit.jupiter", name = "junit-jupiter-params", version.ref = "junit" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 1e488361..3da9ecb6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -31,4 +31,5 @@ fun includeDirectory(dirPath: String) { } includeDirectory("subprojects/frontends/gamma") +includeDirectory("subprojects/frontends/sysmlv2") includeDirectory("subprojects/backends/theta") diff --git a/subprojects/backends/theta/xsts-verifier/build.gradle.kts b/subprojects/backends/theta/xsts-verifier/build.gradle.kts index 6eaa1edd..59568525 100644 --- a/subprojects/backends/theta/xsts-verifier/build.gradle.kts +++ b/subprojects/backends/theta/xsts-verifier/build.gradle.kts @@ -17,4 +17,9 @@ dependencies { api(project(":semantics")) api(project(":xsts.lang")) api(project(":theta-wrapper")) + + testRuntimeOnly(libs.slf4j.log4j) + + testFixturesApi(project(":semantics")) + testFixturesApi(testFixtures(project(":semantics"))) } diff --git a/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt b/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt new file mode 100644 index 00000000..f2484864 --- /dev/null +++ b/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.backends.theta.verification + +import com.google.inject.Inject +import com.google.inject.Provider +import hu.bme.mit.semantifyr.semantics.BaseSemantifyrVerificationTest +import hu.bme.mit.semantifyr.semantics.InjectWithOxstsSemantics +import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader +import hu.bme.mit.semantifyr.semantics.utils.loggerFactory +import org.junit.jupiter.api.Tag +import org.junit.jupiter.api.Test +import kotlin.io.path.Path + +@Tag("verification") +@InjectWithOxstsSemantics +class ThetaXstsVerificationTests : BaseSemantifyrVerificationTest() { + + override val logger by loggerFactory() + + @Inject + lateinit var semantifyrLoader: SemantifyrLoader + + @Inject + override lateinit var oxstsVerifierProvider: Provider + + @Test + fun `Simple Model Verification Cases Should Pass`() { + val model = semantifyrLoader.loadStandaloneModel(Path("test-models/Simple/simple.oxsts")) + + verifyVerificationCases(model) + } + +} diff --git a/subprojects/backends/theta/xsts-verifier/test-models/Simple/.gitignore b/subprojects/backends/theta/xsts-verifier/test-models/Simple/.gitignore new file mode 100644 index 00000000..ab234747 --- /dev/null +++ b/subprojects/backends/theta/xsts-verifier/test-models/Simple/.gitignore @@ -0,0 +1 @@ +simple diff --git a/subprojects/backends/theta/xsts-verifier/test-models/Simple/simple.oxsts b/subprojects/backends/theta/xsts-verifier/test-models/Simple/simple.oxsts new file mode 100644 index 00000000..c3ce1649 --- /dev/null +++ b/subprojects/backends/theta/xsts-verifier/test-models/Simple/simple.oxsts @@ -0,0 +1,35 @@ +package semantifyr::theta::xsts::simple + +@VerificationCase +class Incrementing { + // x is zero initially + var x: int := 0 + + // initialize it to 1 as the first step + redefine init { + x := 1 + } + + // increment on every step + redefine tran { + x := x + 1 + } + + // assert that x will reach 10 + prop { + return EF x == 10 + } +} + +@VerificationCase +class Decrementing { + var x: int := 10 + + redefine tran { + x := x - 1 + } + + prop { + return EF x == 0 + } +} diff --git a/subprojects/frontends/gamma/gamma-semantics/build.gradle.kts b/subprojects/frontends/gamma/gamma-semantics/build.gradle.kts index 27674f2f..d644c9f1 100644 --- a/subprojects/frontends/gamma/gamma-semantics/build.gradle.kts +++ b/subprojects/frontends/gamma/gamma-semantics/build.gradle.kts @@ -16,6 +16,11 @@ repositories { dependencies { api(project(":gamma.lang")) + testRuntimeOnly(libs.slf4j.log4j) + testFixturesApi(project(":gamma.lang")) testFixturesApi(testFixtures(project(":gamma.lang"))) + + testFixturesApi(project(":xsts-verifier")) + testFixturesApi(testFixtures(project(":xsts-verifier"))) } diff --git a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt new file mode 100644 index 00000000..1394a0d3 --- /dev/null +++ b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.frontends.gamma.semantics + +import com.google.inject.Inject +import com.google.inject.Provider +import hu.bme.mit.semantifyr.backends.theta.verification.ThetaVerifier +import hu.bme.mit.semantifyr.semantics.BaseSemantifyrVerificationTest +import hu.bme.mit.semantifyr.semantics.InjectWithOxstsSemantics +import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader +import hu.bme.mit.semantifyr.semantics.utils.loggerFactory +import org.junit.jupiter.api.Tag +import org.junit.jupiter.api.Test +import java.nio.file.Path +import kotlin.io.path.Path + +@Tag("verification") +@InjectWithOxstsSemantics +class GammaVerificationTests : BaseSemantifyrVerificationTest() { + + override val logger by loggerFactory() + + @Inject + lateinit var semantifyrLoader: SemantifyrLoader + + @Inject + override lateinit var oxstsVerifierProvider: Provider + + val transformer = StandaloneGammaTransformer() + + fun testGammaModel(gammaModelPath: Path) { + val gammaModel = gammaModelPath.toFile() + val oxstsModelPath = Path(gammaModel.absolutePath.replace(".gamma", ".oxsts")) + val oxstsModel = oxstsModelPath.toFile() + + transformer.transformModel(gammaModel, oxstsModel) + + val model = semantifyrLoader.startContext() + .loadLibraries(Path("Library")) + .loadModel(oxstsModelPath) + .buildAndResolve() + + verifyVerificationCases(model) + } + + @Test + fun `Simple Model Verification Cases Should Pass`() { + testGammaModel(Path("TestModels/Simple.gamma")) + } + + @Test + fun `Crossroads Model Verification Cases Should Pass`() { + testGammaModel(Path("TestModels/Crossroads.gamma")) + } + + @Test + fun `Spacecraft Model Verification Cases Should Pass`() { + testGammaModel(Path("TestModels/Spacecraft.gamma")) + } + +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts new file mode 100644 index 00000000..a6e643c0 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2025 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +plugins { + id("hu.bme.mit.semantifyr.gradle.conventions.jvm") + alias(libs.plugins.kotlin.jvm) +} + +repositories { + mavenCentral() +} + +dependencies { + testRuntimeOnly(libs.slf4j.log4j) + + testFixturesApi(project(":xsts-verifier")) + testFixturesApi(testFixtures(project(":xsts-verifier"))) +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/.gitignore b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/.gitignore new file mode 100644 index 00000000..454fdb08 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/.gitignore @@ -0,0 +1,9 @@ +**/*.oxsts +**/*.xsts +**/*.cex +**/theta.err +**/theta.out +**/trace.json +**/mapping.json + +!./* diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts new file mode 100644 index 00000000..4cf53d35 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts @@ -0,0 +1,769 @@ +package semantifyr::sysml::model + +import semantifyr::sysml::expressions +import semantifyr::sysml::attributes +import semantifyr::sysml::states +import semantifyr::sysml::parts +import semantifyr::sysml::ports +import semantifyr::sysml::items +import semantifyr::sysml::actions +import semantifyr::sysml::triggers +import semantifyr::sysml::verification + +class Police : Item +global containment global_Police: Police[1] +class Toggle : Item +global containment global_Toggle: Toggle[1] +class RedL : Item +global containment global_RedL: RedL[1] +class YellowL : Item +global containment global_YellowL: YellowL[1] +class GreenL : Item +global containment global_GreenL: GreenL[1] +class NoneL : Item +global containment global_NoneL: NoneL[1] +class CentralControl : NormalPort { + refers police: Police subsets outgoingItems = global_Police + refers toggle: Toggle subsets outgoingItems = global_Toggle +} +class ConjugatedCentralControl : ConjugatedPort { + refers police: Police subsets outgoingItems = global_Police + refers toggle: Toggle subsets outgoingItems = global_Toggle +} +class LightControl : NormalPort { + refers red: RedL subsets outgoingItems = global_RedL + refers yellow: YellowL subsets outgoingItems = global_YellowL + refers green: GreenL subsets outgoingItems = global_GreenL + refers none: NoneL subsets outgoingItems = global_NoneL +} +class ConjugatedLightControl : ConjugatedPort { + refers red: RedL subsets outgoingItems = global_RedL + refers yellow: YellowL subsets outgoingItems = global_YellowL + refers green: GreenL subsets outgoingItems = global_GreenL + refers none: NoneL subsets outgoingItems = global_NoneL +} +class CentralController : Part { + contains control: ConjugatedCentralControl subsets ports + contains controlA: CentralControl subsets ports + contains controlB: CentralControl subsets ports + contains Behaviour: State redefines exhibitState { + contains UnnamedTransitionUsage0: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = Operating +} + contains Operating: State subsets states { + contains UnnamedTransitionUsage1: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = BothYellow +} + contains BothYellow: State subsets states + contains UnnamedTransitionUsage2: Transition subsets transitions { + redefine refers from: StateNode = BothYellow + redefine refers to: StateNode = BothRed + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 1 + } + redefine contains action: CompositeAction { + contains UnnamedSendActionUsage0: SendAction subsets children { + redefine refers viaPort: Port = controlA + redefine refers payload: Item = global_Toggle + } + contains UnnamedSendActionUsage1: SendAction subsets children { + redefine refers viaPort: Port = controlB + redefine refers payload: Item = global_Toggle + } + } + } + contains BothRed: State subsets states + contains UnnamedTransitionUsage3: Transition subsets transitions { + redefine refers from: StateNode = BothRed + redefine refers to: StateNode = TrafficOnA + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 2 + } + redefine contains action: CompositeAction { + contains UnnamedSendActionUsage2: SendAction subsets children { + redefine refers viaPort: Port = controlA + redefine refers payload: Item = global_Toggle + } + } + } + contains TrafficOnA: State subsets states + contains UnnamedTransitionUsage4: Transition subsets transitions { + redefine refers from: StateNode = TrafficOnA + redefine refers to: StateNode = StoppingA + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 2 + } + redefine contains action: CompositeAction { + contains UnnamedSendActionUsage3: SendAction subsets children { + redefine refers viaPort: Port = controlA + redefine refers payload: Item = global_Toggle + } + } + } + contains StoppingA: State subsets states + contains UnnamedTransitionUsage5: Transition subsets transitions { + redefine refers from: StateNode = StoppingA + redefine refers to: StateNode = TrafficOnB + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 1 + } + redefine contains action: CompositeAction { + contains UnnamedSendActionUsage4: SendAction subsets children { + redefine refers viaPort: Port = controlA + redefine refers payload: Item = global_Toggle + } + contains UnnamedSendActionUsage5: SendAction subsets children { + redefine refers viaPort: Port = controlB + redefine refers payload: Item = global_Toggle + } + } + } + contains TrafficOnB: State subsets states + contains UnnamedTransitionUsage6: Transition subsets transitions { + redefine refers from: StateNode = TrafficOnB + redefine refers to: StateNode = StoppingB + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 2 + } + redefine contains action: CompositeAction { + contains UnnamedSendActionUsage6: SendAction subsets children { + redefine refers viaPort: Port = controlB + redefine refers payload: Item = global_Toggle + } + } + } + contains StoppingB: State subsets states + contains UnnamedTransitionUsage7: Transition subsets transitions { + redefine refers from: StateNode = StoppingB + redefine refers to: StateNode = TrafficOnA + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 1 + } + redefine contains action: CompositeAction { + contains UnnamedSendActionUsage7: SendAction subsets children { + redefine refers viaPort: Port = controlA + redefine refers payload: Item = global_Toggle + } + contains UnnamedSendActionUsage8: SendAction subsets children { + redefine refers viaPort: Port = controlB + redefine refers payload: Item = global_Toggle + } + } + } + } + contains UnnamedTransitionUsage8: Transition subsets transitions { + redefine refers from: StateNode = Operating + redefine refers to: StateNode = Interrupted + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = control + redefine refers payload: Item = global_Police + } + } + contains UnnamedTransitionUsage9: Transition subsets transitions { + redefine refers from: StateNode = Interrupted + redefine refers to: StateNode = Operating + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = control + redefine refers payload: Item = global_Police + } + } + contains Interrupted: State subsets states { + redefine contains entryAction: CompositeAction { + contains UnnamedSendActionUsage9: SendAction subsets children { + redefine refers viaPort: Port = controlA + redefine refers payload: Item = global_Police + } + contains UnnamedSendActionUsage10: SendAction subsets children { + redefine refers viaPort: Port = controlB + redefine refers payload: Item = global_Police + } + } + redefine contains exitAction: CompositeAction { + contains UnnamedSendActionUsage11: SendAction subsets children { + redefine refers viaPort: Port = controlA + redefine refers payload: Item = global_Police + } + contains UnnamedSendActionUsage12: SendAction subsets children { + redefine refers viaPort: Port = controlB + redefine refers payload: Item = global_Police + } + } + } + } +} +class TrafficLightController : Part { + contains control: ConjugatedCentralControl subsets ports + contains lightControl: LightControl subsets ports + contains Behaviour: State redefines exhibitState { + contains UnnamedTransitionUsage10: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = Normal +} + contains Normal: State subsets states { + contains UnnamedTransitionUsage11: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = Yellow +} + contains Yellow: State subsets states { + redefine contains entryAction: SendAction { + redefine refers viaPort: Port = lightControl + redefine refers payload: Item = global_YellowL + } + } + contains UnnamedTransitionUsage12: Transition subsets transitions { + redefine refers from: StateNode = Yellow + redefine refers to: StateNode = Red + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = control + redefine refers payload: Item = global_Toggle + } + } + contains Red: State subsets states { + redefine contains entryAction: SendAction { + redefine refers viaPort: Port = lightControl + redefine refers payload: Item = global_RedL + } + } + contains UnnamedTransitionUsage13: Transition subsets transitions { + redefine refers from: StateNode = Red + redefine refers to: StateNode = Green + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = control + redefine refers payload: Item = global_Toggle + } + } + contains Green: State subsets states { + redefine contains entryAction: SendAction { + redefine refers viaPort: Port = lightControl + redefine refers payload: Item = global_GreenL + } + } + contains UnnamedTransitionUsage14: Transition subsets transitions { + redefine refers from: StateNode = Green + redefine refers to: StateNode = Yellow + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = control + redefine refers payload: Item = global_Toggle + } + } + } + contains UnnamedTransitionUsage15: Transition subsets transitions { + redefine refers from: StateNode = Normal + redefine refers to: StateNode = Interrupted + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = control + redefine refers payload: Item = global_Police + } + } + contains UnnamedTransitionUsage16: Transition subsets transitions { + redefine refers from: StateNode = Interrupted + redefine refers to: StateNode = Normal + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = control + redefine refers payload: Item = global_Police + } + } + contains Interrupted: State subsets states { + contains UnnamedTransitionUsage17: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = Yellow +} + contains Yellow: State subsets states { + redefine contains entryAction: SendAction { + redefine refers viaPort: Port = lightControl + redefine refers payload: Item = global_YellowL + } + } + contains UnnamedTransitionUsage18: Transition subsets transitions { + redefine refers from: StateNode = Yellow + redefine refers to: StateNode = Black + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 1 + } + } + contains UnnamedTransitionUsage19: Transition subsets transitions { + redefine refers from: StateNode = Black + redefine refers to: StateNode = Yellow + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 1 + } + } + contains Black: State subsets states { + redefine contains entryAction: SendAction { + redefine refers viaPort: Port = lightControl + redefine refers payload: Item = global_NoneL + } + } + } + } +} +class CrossroadSystem : Part { + contains controller: CentralController subsets parts + contains trafficLightA: TrafficLightController subsets parts + contains trafficLightB: TrafficLightController subsets parts + refers control: ConjugatedCentralControl subsets ports = controller.control + contains UnnamedFlowConnectionUsage0: Flow subsets flows { + redefine refers inputPort: Port = controller.controlA + redefine refers outputPort: Port = trafficLightA.control + } + contains UnnamedFlowConnectionUsage1: Flow subsets flows { + redefine refers inputPort: Port = controller.controlB + redefine refers outputPort: Port = trafficLightB.control + } +} +@VerificationCase +class ControllerOperatingReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.controller.Behaviour.Operating + } + } + } + } +} +@VerificationCase +class ControllerOperatingBothYellowReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.controller.Behaviour.Operating.BothYellow + } + } + } + } +} +@VerificationCase +class ControllerOperatingBothRedReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.controller.Behaviour.Operating.BothRed + } + } + } + } +} +@VerificationCase +class ControllerOperatingTrafficOnAReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.controller.Behaviour.Operating.TrafficOnA + } + } + } + } +} +@VerificationCase +class ControllerOperatingStoppingAReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.controller.Behaviour.Operating.StoppingA + } + } + } + } +} +@VerificationCase +class ControllerOperatingTrafficOnBReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.controller.Behaviour.Operating.TrafficOnB + } + } + } + } +} +@VerificationCase +class ControllerOperatingStoppingBReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.controller.Behaviour.Operating.StoppingB + } + } + } + } +} +@VerificationCase +class ControllerInterruptedReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.controller.Behaviour.Interrupted + } + } + } + } +} +@VerificationCase +class TrafficLightABehaviorNormalReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal + } + } + } + } +} +@VerificationCase +class TrafficLightABehaviorNormalYellowReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Yellow + } + } + } + } +} +@VerificationCase +class TrafficLightABehaviorNormalRedReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Red + } + } + } + } +} +@VerificationCase +class TrafficLightABehaviorNormalGreenReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Green + } + } + } + } +} +@VerificationCase +class TrafficLightABehaviorInterruptedReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Interrupted + } + } + } + } +} +@VerificationCase +class TrafficLightABehaviorInterruptedYellowReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Interrupted.Yellow + } + } + } + } +} +@VerificationCase +class TrafficLightABehaviorInterruptedBlackReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Interrupted.Black + } + } + } + } +} +@VerificationCase +class TrafficLightBBehaviorNormalReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal + } + } + } + } +} +@VerificationCase +class TrafficLightBBehaviorNormalYellowReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Yellow + } + } + } + } +} +@VerificationCase +class TrafficLightBBehaviorNormalRedReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Red + } + } + } + } +} +@VerificationCase +class TrafficLightBBehaviorNormalGreenReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Green + } + } + } + } +} +@VerificationCase +class TrafficLightBBehaviorInterruptedReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Interrupted + } + } + } + } +} +@VerificationCase +class TrafficLightBBehaviorInterruptedYellowReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Interrupted.Yellow + } + } + } + } +} +@VerificationCase +class TrafficLightBBehaviorInterruptedBlackReachable : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Interrupted.Black + } + } + } + } +} +@VerificationCase +class ReachableRedRed : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: AndOperatorExpression { + redefine contains left: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Red + } + redefine contains right: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Red + } + } + } + } + } +} +@VerificationCase +class ReachableRedGreen : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: AndOperatorExpression { + redefine contains left: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Red + } + redefine contains right: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Green + } + } + } + } + } +} +@VerificationCase +class ReachableRedYellow : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: AndOperatorExpression { + redefine contains left: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Red + } + redefine contains right: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Yellow + } + } + } + } + } +} +@VerificationCase +class ReachableGreenRed : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: AndOperatorExpression { + redefine contains left: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Green + } + redefine contains right: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Red + } + } + } + } + } +} +@VerificationCase +class UnreachableGreenGreen : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: UnaryNotExpression { + redefine contains operand: Eventually { + redefine contains body: AndOperatorExpression { + redefine contains left: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Green + } + redefine contains right: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Green + } + } + } + } + } + } +} +@VerificationCase +class UnreachableGreenYellow : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: UnaryNotExpression { + redefine contains operand: Eventually { + redefine contains body: AndOperatorExpression { + redefine contains left: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Green + } + redefine contains right: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Yellow + } + } + } + } + } + } +} +@VerificationCase +class ReachableYellowRed : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: AndOperatorExpression { + redefine contains left: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Yellow + } + redefine contains right: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Red + } + } + } + } + } +} +@VerificationCase +class UnreachableYellowGreen : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: UnaryNotExpression { + redefine contains operand: Eventually { + redefine contains body: AndOperatorExpression { + redefine contains left: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Yellow + } + redefine contains right: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Green + } + } + } + } + } + } +} +@VerificationCase +class ReachableYellowYellow : VerificationCaseDefinition { + contains system: CrossroadSystem[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: AndOperatorExpression { + redefine contains left: IsStateActiveExpression { + redefine refers state: State = system.trafficLightA.Behaviour.Normal.Yellow + } + redefine contains right: IsStateActiveExpression { + redefine refers state: State = system.trafficLightB.Behaviour.Normal.Yellow + } + } + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/models26.example.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/models26.example.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-frontend/models26.example.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/models/models26.example.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts new file mode 100644 index 00000000..c1bca098 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts @@ -0,0 +1,845 @@ +package semantifyr::sysml::model + +import semantifyr::sysml::expressions +import semantifyr::sysml::attributes +import semantifyr::sysml::states +import semantifyr::sysml::parts +import semantifyr::sysml::ports +import semantifyr::sysml::items +import semantifyr::sysml::actions +import semantifyr::sysml::triggers +import semantifyr::sysml::verification + +class GroundStation : Part { + contains commandPort: CommandPort subsets ports + contains spacecraftCommandPort: ConjugatedCommandPort subsets ports + contains dataPort: ConjugatedDataPort subsets ports + contains receivedData: IntegerAttribute subsets attributes { + redefine refers defaultValue: int = 0 + } + contains Behaviour: State redefines exhibitState { + contains UnnamedTransitionUsage0: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = Idle +} + contains Idle: State subsets states + contains UnnamedTransitionUsage1: Transition subsets transitions { + redefine refers from: StateNode = Idle + redefine refers to: StateNode = Operation + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 30 + } + } + contains UnnamedTransitionUsage2: Transition subsets transitions { + redefine refers from: StateNode = Idle + redefine refers to: StateNode = Operation + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = commandPort + redefine refers payload: Item = global_StartCommand + } + } + contains Operation: State subsets states { + redefine contains entryAction: SendAction { + redefine refers viaPort: Port = spacecraftCommandPort + redefine refers payload: Item = global_PingCommand + } + contains UnnamedTransitionUsage3: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = Waiting +} + contains Waiting: State subsets states + contains UnnamedTransitionUsage4: Transition subsets transitions { + redefine refers from: StateNode = Waiting + redefine refers to: StateNode = Waiting + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = dataPort + redefine refers payload: Item = global_Data + } + redefine contains guard: Guard { + redefine contains expression: LessThanOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 100 + } + } + } + redefine contains action: AssignmentAction { + redefine refers attribute: Attribute = receivedData + redefine contains expression: PlusOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 10 + } + } + } + } + } + contains UnnamedTransitionUsage5: Transition subsets transitions { + redefine refers from: StateNode = Operation + redefine refers to: StateNode = Operation + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 10 + } + } + contains UnnamedTransitionUsage6: Transition subsets transitions { + redefine refers from: StateNode = Operation + redefine refers to: StateNode = Idle + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = commandPort + redefine refers payload: Item = global_StopCommand + } + } + } +} +class Spacecraft : Part { + contains commandPort: CommandPort subsets ports + contains dataPort: DataPort subsets ports + contains batteryCharge: IntegerAttribute subsets attributes { + redefine refers defaultValue: int = 100 + } + contains recharging: BooleanAttribute subsets attributes { + redefine refers defaultValue: bool = false + } + contains data: IntegerAttribute subsets attributes { + redefine refers defaultValue: int = 100 + } + contains Behaviour: ParallelState redefines exhibitState { + contains Communication: State subsets states { + contains WaitingPing: State subsets states + contains UnnamedTransitionUsage7: Transition subsets transitions { + redefine refers from: StateNode = Transmitting.SendData.Sending + redefine refers to: StateNode = WaitingPing + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 4 + } + redefine contains guard: Guard { + redefine contains expression: OrOperatorExpression { + redefine contains left: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 0 + } + } + redefine contains right: LessThanOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 + } + } + } + } + } + contains UnnamedTransitionUsage8: Transition subsets transitions { + redefine refers from: StateNode = Transmitting.ConsumePower.Consuming + redefine refers to: StateNode = WaitingPing + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 4 + } + redefine contains guard: Guard { + redefine contains expression: LessThanOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 + } + } + } + } + contains Transmitting: ParallelState subsets states { + contains SendData: State subsets states { + contains Sending: State subsets states + contains UnnamedTransitionUsage9: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = Sending +} + contains UnnamedTransitionUsage10: Transition subsets transitions { + redefine refers from: StateNode = Sending + redefine refers to: StateNode = Sending + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 4 + } + redefine contains guard: Guard { + redefine contains expression: UnaryNotExpression { + redefine contains operand: OrOperatorExpression { + redefine contains left: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 0 + } + } + redefine contains right: LessThanOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 + } + } + } + } + } + redefine contains action: CompositeAction { + contains UnnamedAssignmentActionUsage0: AssignmentAction subsets children { + redefine refers attribute: Attribute = data + redefine contains expression: MinusOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 10 + } + } + } + contains UnnamedSendActionUsage0: SendAction subsets children { + redefine refers viaPort: Port = dataPort + redefine refers payload: Item = global_Data + } + } + } + } + contains ConsumePower: State subsets states { + contains Consuming: State subsets states + contains UnnamedTransitionUsage11: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = Consuming +} + contains UnnamedTransitionUsage12: Transition subsets transitions { + redefine refers from: StateNode = Consuming + redefine refers to: StateNode = Consuming + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 2 + } + redefine contains guard: Guard { + redefine contains expression: UnaryNotExpression { + redefine contains operand: LessThanOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 + } + } + } + } + redefine contains action: AssignmentAction { + redefine refers attribute: Attribute = batteryCharge + redefine contains expression: MinusOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 10 + } + } + } + } + } + } + contains UnnamedTransitionUsage13: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = WaitingPing +} + contains UnnamedTransitionUsage14: Transition subsets transitions { + redefine refers from: StateNode = WaitingPing + redefine refers to: StateNode = Transmitting + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = commandPort + redefine refers payload: Item = global_PingCommand + } + redefine contains guard: Guard { + redefine contains expression: AndOperatorExpression { + redefine contains left: EqualityOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = recharging + } + redefine contains right: LiteralBooleanExpression { + redefine refers value: bool = false + } + } + redefine contains right: UnaryNotExpression { + redefine contains operand: OrOperatorExpression { + redefine contains left: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 0 + } + } + redefine contains right: LessThanOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 + } + } + } + } + } + } + } + } + contains Battery: State subsets states { + contains NotRecharging: State subsets states { + redefine contains entryAction: AssignmentAction { + redefine refers attribute: Attribute = recharging + redefine contains expression: LiteralBooleanExpression { + redefine refers value: bool = false + } + } + } + contains Recharging: State subsets states { + redefine contains entryAction: AssignmentAction { + redefine refers attribute: Attribute = recharging + redefine contains expression: LiteralBooleanExpression { + redefine refers value: bool = true + } + } + } + contains UnnamedTransitionUsage15: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = NotRecharging +} + contains UnnamedTransitionUsage16: Transition subsets transitions { + redefine refers from: StateNode = NotRecharging + redefine refers to: StateNode = Recharging + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 3 + } + redefine contains guard: Guard { + redefine contains expression: LessThanOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 80 + } + } + } + } + contains UnnamedTransitionUsage17: Transition subsets transitions { + redefine refers from: StateNode = Recharging + redefine refers to: StateNode = Recharging + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 3 + } + redefine contains guard: Guard { + redefine contains expression: LessThanOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 100 + } + } + } + redefine contains action: AssignmentAction { + redefine refers attribute: Attribute = batteryCharge + redefine contains expression: PlusOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 10 + } + } + } + } + contains UnnamedTransitionUsage18: Transition subsets transitions { + redefine refers from: StateNode = Recharging + redefine refers to: StateNode = NotRecharging + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 3 + } + redefine contains guard: Guard { + redefine contains expression: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 100 + } + } + } + } + } + } +} +class Data : Item +global containment global_Data: Data[1] +class Command : Item +global containment global_Command: Command[1] +class PingCommand : Item +global containment global_PingCommand: PingCommand[1] +class StopCommand : Item +global containment global_StopCommand: StopCommand[1] +class StartCommand : Item +global containment global_StartCommand: StartCommand[1] +class CommandPort : NormalPort { + refers command: Command subsets incomingItems = global_Command +} +class ConjugatedCommandPort : ConjugatedPort { + refers command: Command subsets incomingItems = global_Command +} +class DataPort : NormalPort { + refers data: Data subsets outgoingItems = global_Data +} +class ConjugatedDataPort : ConjugatedPort { + refers data: Data subsets outgoingItems = global_Data +} +class Mission : Part { + contains groundStation: GroundStation subsets parts + contains spacecraft: Spacecraft subsets parts + refers commandPort: CommandPort subsets ports = groundStation.commandPort + contains UnnamedFlowConnectionUsage0: Flow subsets flows { + redefine refers inputPort: Port = groundStation.spacecraftCommandPort + redefine refers outputPort: Port = spacecraft.commandPort + } + contains UnnamedFlowConnectionUsage1: Flow subsets flows { + redefine refers inputPort: Port = spacecraft.dataPort + redefine refers outputPort: Port = groundStation.dataPort + } +} +@VerificationCase +class StationBehaviorIdleReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.groundStation.Behaviour.Idle + } + } + } + } +} +@VerificationCase +class StationBehaviorOperationReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.groundStation.Behaviour.Operation + } + } + } + } +} +@VerificationCase +class StationBehaviorOperationWaitingReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.groundStation.Behaviour.Operation.Waiting + } + } + } + } +} +@VerificationCase +class SpacecraftBehaviorCommunicationWaitingPingReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.spacecraft.Behaviour.Communication.WaitingPing + } + } + } + } +} +@VerificationCase +class SpacecraftBehaviorCommunicationTransmittingReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.spacecraft.Behaviour.Communication.Transmitting + } + } + } + } +} +@VerificationCase +class SpacecraftBehaviorCommunicationTransmittingSendDataReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.spacecraft.Behaviour.Communication.Transmitting.SendData + } + } + } + } +} +@VerificationCase +class SpacecraftBehaviorCommunicationTransmittingSendDataSendingReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.spacecraft.Behaviour.Communication.Transmitting.SendData.Sending + } + } + } + } +} +@VerificationCase +class SpacecraftBehaviorCommunicationTransmittingConsumePowerReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.spacecraft.Behaviour.Communication.Transmitting.ConsumePower + } + } + } + } +} +@VerificationCase +class SpacecraftBehaviorCommunicationTransmittingConsumePowerConsumingReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.spacecraft.Behaviour.Communication.Transmitting.ConsumePower.Consuming + } + } + } + } +} +@VerificationCase +class SpacecraftBehaviorBatteryNotRechargingReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.spacecraft.Behaviour.Battery.NotRecharging + } + } + } + } +} +@VerificationCase +class SpacecraftBehaviorBatteryRechargingReachable : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = mission.spacecraft.Behaviour.Battery.Recharging + } + } + } + } +} +@VerificationCase +class GroundStateReceivedData0 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 0 + } + } + } + } + } +} +@VerificationCase +class GroundStateReceivedData10 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 10 + } + } + } + } + } +} +@VerificationCase +class GroundStateReceivedData20 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 30 + } + } + } + } + } +} +@VerificationCase +class GroundStateReceivedData30 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 30 + } + } + } + } + } +} +@VerificationCase +class GroundStateReceivedData40 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 + } + } + } + } + } +} +@VerificationCase +class GroundStateReceivedData50 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 50 + } + } + } + } + } +} +@VerificationCase +class GroundStateReceivedData60 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 60 + } + } + } + } + } +} +@VerificationCase +class GroundStateReceivedData70 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 70 + } + } + } + } + } +} +@VerificationCase +class SpacecraftData100 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 100 + } + } + } + } + } +} +@VerificationCase +class SpacecraftData90 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 90 + } + } + } + } + } +} +@VerificationCase +class SpacecraftData80 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 80 + } + } + } + } + } +} +@VerificationCase +class SpacecraftData70 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 70 + } + } + } + } + } +} +@VerificationCase +class SpacecraftData60 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 60 + } + } + } + } + } +} +@VerificationCase +class SpacecraftData50 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 50 + } + } + } + } + } +} +@VerificationCase +class SpacecraftData40 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 + } + } + } + } + } +} +@VerificationCase +class SpacecraftData30 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 30 + } + } + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm21.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm21.oxsts new file mode 100644 index 00000000..5c5253d6 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm21.oxsts @@ -0,0 +1,113 @@ +package semantifyr::sysml::model + +import semantifyr::sysml::expressions +import semantifyr::sysml::attributes +import semantifyr::sysml::states +import semantifyr::sysml::parts +import semantifyr::sysml::ports +import semantifyr::sysml::items +import semantifyr::sysml::actions +import semantifyr::sysml::triggers +import semantifyr::sysml::verification + +class F : Item +global containment global_F: F[1] +class G : Item +global containment global_G: G[1] +class InputEvents : NormalPort { + refers f: F subsets incomingItems = global_F + refers g: G subsets incomingItems = global_G +} +class ConjugatedInputEvents : ConjugatedPort { + refers f: F subsets incomingItems = global_F + refers g: G subsets incomingItems = global_G +} +class Stm21 : Part { + contains input: InputEvents subsets ports + contains Behaviour: ParallelState redefines exhibitState { + contains R1: State subsets states { + contains S11: State subsets states + contains S12: State subsets states + contains UnnamedTransitionUsage0: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = S11 +} + contains UnnamedTransitionUsage1: Transition subsets transitions { + redefine refers from: StateNode = S11 + redefine refers to: StateNode = S12 + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = input + redefine refers payload: Item = global_F + } + } + } + contains R2: State subsets states { + contains S13: State subsets states + contains S14: State subsets states + contains UnnamedTransitionUsage2: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = S13 +} + contains UnnamedTransitionUsage3: Transition subsets transitions { + redefine refers from: StateNode = S13 + redefine refers to: StateNode = S14 + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = input + redefine refers payload: Item = global_G + } + } + } + } +} +@VerificationCase +class S11Reachable : VerificationCaseDefinition { + contains system: Stm21[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.Behaviour.R1.S11 + } + } + } + } +} +@VerificationCase +class S12Reachable : VerificationCaseDefinition { + contains system: Stm21[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.Behaviour.R1.S12 + } + } + } + } +} +@VerificationCase +class S13Reachable : VerificationCaseDefinition { + contains system: Stm21[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.Behaviour.R2.S13 + } + } + } + } +} +@VerificationCase +class S14Reachable : VerificationCaseDefinition { + contains system: Stm21[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.Behaviour.R2.S14 + } + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm31.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm31.oxsts new file mode 100644 index 00000000..edd77e01 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm31.oxsts @@ -0,0 +1,158 @@ +package semantifyr::sysml::model + +import semantifyr::sysml::expressions +import semantifyr::sysml::attributes +import semantifyr::sysml::states +import semantifyr::sysml::parts +import semantifyr::sysml::ports +import semantifyr::sysml::items +import semantifyr::sysml::actions +import semantifyr::sysml::triggers +import semantifyr::sysml::verification + +class A : Item +global containment global_A: A[1] +class B : Item +global containment global_B: B[1] +class C : Item +global containment global_C: C[1] +class D : Item +global containment global_D: D[1] +class X : Item +global containment global_X: X[1] +class E : Item +global containment global_E: E[1] +class OutputEvents : NormalPort { + refers a: A subsets outgoingItems = global_A + refers b: B subsets outgoingItems = global_B + refers c: C subsets outgoingItems = global_C + refers d: D subsets outgoingItems = global_D + refers x: X subsets outgoingItems = global_X +} +class ConjugatedOutputEvents : ConjugatedPort { + refers a: A subsets outgoingItems = global_A + refers b: B subsets outgoingItems = global_B + refers c: C subsets outgoingItems = global_C + refers d: D subsets outgoingItems = global_D + refers x: X subsets outgoingItems = global_X +} +class InputEvents : NormalPort { + refers e: E subsets incomingItems = global_E +} +class ConjugatedInputEvents : ConjugatedPort { + refers e: E subsets incomingItems = global_E +} +class Stm31 : Part { + contains i: IntegerAttribute subsets attributes { + redefine refers defaultValue: int = 0 + } + contains input: InputEvents subsets ports + contains output: OutputEvents subsets ports + contains Behaviour: State redefines exhibitState { + contains S1: State subsets states { + redefine contains entryAction: CompositeAction { + contains UnnamedSendActionUsage0: SendAction subsets children { + redefine refers viaPort: Port = output + redefine refers payload: Item = global_A + } + } + redefine contains exitAction: CompositeAction { + contains UnnamedAssignmentActionUsage0: AssignmentAction subsets children { + redefine refers attribute: Attribute = i + redefine contains expression: PlusOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = i + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 1 + } + } + } + contains UnnamedSendActionUsage1: SendAction subsets children { + redefine refers viaPort: Port = output + redefine refers payload: Item = global_B + } + } + } + contains S2: State subsets states { + redefine contains entryAction: CompositeAction { + contains UnnamedAssignmentActionUsage1: AssignmentAction subsets children { + redefine refers attribute: Attribute = i + redefine contains expression: MultiplicationOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = i + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 2 + } + } + } + contains UnnamedSendActionUsage2: SendAction subsets children { + redefine refers viaPort: Port = output + redefine refers payload: Item = global_C + } + } + redefine contains exitAction: CompositeAction { + contains UnnamedSendActionUsage3: SendAction subsets children { + redefine refers viaPort: Port = output + redefine refers payload: Item = global_D + } + } + } + contains UnnamedTransitionUsage0: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = S1 +} + contains UnnamedTransitionUsage1: Transition subsets transitions { + redefine refers from: StateNode = S1 + redefine refers to: StateNode = S2 + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = input + redefine refers payload: Item = global_E + } + redefine contains action: CompositeAction { + contains UnnamedAssignmentActionUsage2: AssignmentAction subsets children { + redefine refers attribute: Attribute = i + redefine contains expression: PlusOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = i + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 1 + } + } + } + contains UnnamedSendActionUsage4: SendAction subsets children { + redefine refers viaPort: Port = output + redefine refers payload: Item = global_D + } + } + } + } +} +@VerificationCase +class S1Reachable : VerificationCaseDefinition { + contains system: Stm31[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.Behaviour.S1 + } + } + } + } +} +@VerificationCase +class S2Reachable : VerificationCaseDefinition { + contains system: Stm31[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: IsStateActiveExpression { + redefine refers state: State = system.Behaviour.S2 + } + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt new file mode 100644 index 00000000..2b0dc709 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.frontends.sysml.semantics + +import com.google.inject.Inject +import com.google.inject.Provider +import hu.bme.mit.semantifyr.backends.theta.verification.ThetaVerifier +import hu.bme.mit.semantifyr.semantics.BaseSemantifyrVerificationTest +import hu.bme.mit.semantifyr.semantics.InjectWithOxstsSemantics +import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader +import hu.bme.mit.semantifyr.semantics.utils.loggerFactory +import org.junit.jupiter.api.Tag +import org.junit.jupiter.api.Test +import java.nio.file.Path +import kotlin.io.path.Path + +@Tag("verification") +@InjectWithOxstsSemantics +class SysMLVerificationTests : BaseSemantifyrVerificationTest() { + + override val logger by loggerFactory() + + @Inject + lateinit var semantifyrLoader: SemantifyrLoader + + @Inject + override lateinit var oxstsVerifierProvider: Provider + + fun testSysMLModel(modelPath: Path) { + val model = semantifyrLoader.startContext() + .loadLibraries(Path("Library")) + .loadModel(modelPath) + .buildAndResolve() + + verifyVerificationCases(model) + } + + @Test + fun `STM21 Model Verification Cases Should Pass`() { + testSysMLModel(Path("models/stm21.oxsts")) + } + + @Test + fun `STM31 Model Verification Cases Should Pass`() { + testSysMLModel(Path("models/stm31.oxsts")) + } + + @Test + fun `Crossroads Model Verification Cases Should Pass`() { + testSysMLModel(Path("models/crossroads.oxsts")) + } + + @Test + fun `Spacecraft Model Verification Cases Should Pass`() { + testSysMLModel(Path("models/spacecraft.oxsts")) + } + +} From de1c6289e332ea8d4e290b31b62790b6641357e1 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 21:33:19 +0100 Subject: [PATCH 017/115] Added timeout to verification call --- .../src/main/kotlin/ThetaVerifier.kt | 22 +++++++++++++------ .../kotlin/execution/ThetaPorfolioExecutor.kt | 19 +++++++++++----- .../commands/VerifyOxstsCommandHandler.java | 3 ++- .../main/kotlin/verification/OxstsVerifier.kt | 8 ++++++- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index 7303690f..e99461a3 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -29,6 +29,7 @@ import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult import hu.bme.mit.semantifyr.semantics.verification.VerificationResult import hu.bme.mit.semantifyr.xsts.lang.xsts.XstsModel import java.io.File +import java.util.concurrent.TimeUnit import kotlin.io.path.Path @CompilationScoped @@ -37,9 +38,6 @@ open class ThetaVerifier : AbstractOxstsVerifier() { @Inject private lateinit var oxstsTransformer: OxstsTransformer - @Inject - private lateinit var builtinAnnotationHandler: BuiltinAnnotationHandler - @Inject private lateinit var cexReader: CexReader @@ -59,17 +57,27 @@ open class ThetaVerifier : AbstractOxstsVerifier() { return oxstsTransformer.transform(inlinedOxsts, progressContext) } - protected fun verifyXsts(progressContext: ProgressContext, xstsModel: XstsModel): ThetaVerificationResult { + protected fun verifyXsts( + progressContext: ProgressContext, + xstsModel: XstsModel, + timeout: Long, + timeUnit: TimeUnit, + ): ThetaVerificationResult { xstsModel.eResource().save(emptyMap()) val path = xstsModel.eResource().uri.path().removeSuffix(".xsts") val name = path.split(File.separator).last() val workingDirectory = path.replaceAfterLast(File.separator, "") - return thetaPortfolioRunner.run(workingDirectory, name, progressContext) + return thetaPortfolioRunner.run(workingDirectory, name, progressContext, timeout, timeUnit) } - override fun verify(progressContext: ProgressContext, classDeclaration: ClassDeclaration): VerificationCaseRunResult { + override fun verify( + progressContext: ProgressContext, + classDeclaration: ClassDeclaration, + timeout: Long, + timeUnit: TimeUnit, + ): VerificationCaseRunResult { progressContext.reportProgress("Inlining class") val inlinedOxsts = inlineClass(progressContext, classDeclaration) @@ -82,7 +90,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { progressContext.checkIsCancelled() progressContext.reportProgress("Running Theta Portfolio") - val result = verifyXsts(progressContext, xstsModel) + val result = verifyXsts(progressContext, xstsModel, timeout, timeUnit) if (result is ThetaErrorVerificationResult) { return VerificationCaseRunResult(VerificationResult.Failed, result.failureMessage) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt index 5eadb002..58dc41b9 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt @@ -34,14 +34,17 @@ class ThetaPortfolioRunner { "CEGAR --domain PRED_CART --flatten-depth 0 --refinement SEQ_ITP --stacktrace", "BOUNDED --flatten-depth 0 --variant KINDUCTION --stacktrace", ) - val timeout = 5L - val timeUnit = TimeUnit.MINUTES val checkAllResults = false @Inject private lateinit var thetaVerificationExecutor: ThetaVerificationExecutor - private suspend fun runWorkflow(workingDirectory: String, name: String) = supervisorScope { + private suspend fun runWorkflow( + workingDirectory: String, + name: String, + timeout: Long, + timeUnit: TimeUnit + ) = supervisorScope { val jobs = parameters.indices.map { index -> async { val thetaVerificationSpecification = ThetaVerificationSpecification(workingDirectory, name, index, parameters[index], timeout, timeUnit) @@ -115,12 +118,18 @@ class ThetaPortfolioRunner { } } - fun run(workingDirectory: String, name: String, progressContext: ProgressContext) = runBlocking { + fun run( + workingDirectory: String, + name: String, + progressContext: ProgressContext, + timeout: Long, + timeUnit: TimeUnit, + ) = runBlocking { val absoluteDirectory = Path.of(workingDirectory).absolute().toString() val cancellationChecker = startCancellationChecker(progressContext) - val result = runWorkflow(absoluteDirectory, name) + val result = runWorkflow(absoluteDirectory, name, timeout, timeUnit) cancellationChecker.cancel() diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java index c283818b..634da64a 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; @Singleton public class VerifyOxstsCommandHandler extends AbstractCommandHandler { @@ -70,7 +71,7 @@ protected Object execute(ClassDeclaration arguments, ILanguageServerAccess acces progressContext.checkIsCancelled(); compilationStateManagerProvider.get().setSerializeSteps(false); - result.complete(oxstsVerifierProvider.get().verify(progressContext, classDelcaration)); + result.complete(oxstsVerifierProvider.get().verify(progressContext, classDelcaration, 3, TimeUnit.MINUTES)); }); } catch (Exception e) { result.completeExceptionally(e); diff --git a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt index 6e37a20c..3111df77 100644 --- a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt +++ b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt @@ -16,6 +16,7 @@ import hu.bme.mit.semantifyr.semantics.transformation.backannotation.InlinedOxst import hu.bme.mit.semantifyr.semantics.transformation.backannotation.OxstsClassAssumptionWitnessTransformer import hu.bme.mit.semantifyr.semantics.transformation.tracer.TraceSerializer import org.eclipse.emf.common.util.URI +import java.util.concurrent.TimeUnit data class VerificationCaseRunResult( val result: VerificationResult, @@ -28,7 +29,12 @@ enum class VerificationResult { interface OxstsVerifier { - fun verify(progressContext: ProgressContext, classDeclaration: ClassDeclaration): VerificationCaseRunResult + fun verify( + progressContext: ProgressContext, + classDeclaration: ClassDeclaration, + timeout: Long = 10L, + timeUnit: TimeUnit = TimeUnit.MINUTES + ): VerificationCaseRunResult } From c7cb916a014d799a9f787b3ee887e5306d722b58 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 21:55:40 +0100 Subject: [PATCH 018/115] Added verification case tagging --- .../sysmlv2-semantics/models/spacecraft.oxsts | 118 ++++++++++++++++++ .../builtin/BuiltinAnnotationHandler.java | 22 ++++ .../builtin/BuiltinSymbolResolver.java | 12 ++ .../oxsts/lang/utils/OxstsUtils.java | 10 ++ .../oxsts/lang/library/semantifyr.oxsts | 5 + 5 files changed, 167 insertions(+) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts index c1bca098..c953e746 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts @@ -843,3 +843,121 @@ class SpacecraftData30 : VerificationCaseDefinition { } } } + +// manually added slow verification cases + +@Tag("slow") +@VerificationCase +class GroundStateReceivedData80 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 80 + } + } + } + } + } +} +@Tag("slow") +@VerificationCase +class GroundStateReceivedData90 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 90 + } + } + } + } + } +} +@Tag("slow") +@VerificationCase +class GroundStateReceivedData100 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.groundStation.receivedData + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 100 + } + } + } + } + } +} + +@Tag("slow") +@VerificationCase +class SpacecraftData20 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 20 + } + } + } + } + } +} +@Tag("slow") +@VerificationCase +class SpacecraftData10 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 10 + } + } + } + } + } +} +@Tag("slow") +@VerificationCase +class SpacecraftData00 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: Eventually { + redefine contains body: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 00 + } + } + } + } + } +} diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinAnnotationHandler.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinAnnotationHandler.java index dedbb33b..babceb78 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinAnnotationHandler.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinAnnotationHandler.java @@ -52,6 +52,28 @@ public String getVerificationCaseSummary(ClassDeclaration classDeclaration) { return null; } + public boolean isTaggedWith(ClassDeclaration classDeclaration, String category) { + var tagAnnotation = builtinSymbolResolver.tagAnnotation(classDeclaration); + var tagAnnotationCategory = builtinSymbolResolver.tagAnnotationCategory(classDeclaration); + var annotations = OxstsUtils.getAnnotations(classDeclaration, tagAnnotation); + + assert annotations != null; + + var values = annotations.map(annotation -> + OxstsUtils.getAnnotationValue(annotation, tagAnnotationCategory) + ).filter(value -> + value instanceof LiteralString + ).map(value -> + ((LiteralString) value).getValue() + ); + + return values.anyMatch(category::equals); + } + + public boolean isNotTaggedWith(ClassDeclaration classDeclaration, String category) { + return ! isTaggedWith(classDeclaration, category); + } + public boolean isTransitionTraced(TransitionDeclaration transitionDeclaration) { var traceAnnotation = builtinSymbolResolver.traceAnnotation(transitionDeclaration); diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinSymbolResolver.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinSymbolResolver.java index 00d76f81..0988905a 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinSymbolResolver.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/builtin/BuiltinSymbolResolver.java @@ -27,6 +27,9 @@ public class BuiltinSymbolResolver { public static final QualifiedName VERIFICATION_CASE_ANNOTATION_NAME = BuiltinLibrary.BUILTIN_LIBRARY_NAME.append("VerificationCase"); public static final String VERIFICATION_CASE_SUMMARY_NAME = "summary"; + public static final QualifiedName TAG_ANNOTATION_NAME = BuiltinLibrary.BUILTIN_LIBRARY_NAME.append("Tag"); + public static final String TAG_ANNOTATION_CATEGORY_NAME = "category"; + public static final QualifiedName ANYTHING_NAME = BuiltinLibrary.BUILTIN_LIBRARY_NAME.append("Anything"); // public static final String ANYTHING_CHILDREN_NAME = "children"; // public static final String ANYTHING_PARENT_NAME = "parent"; @@ -73,6 +76,15 @@ public ParameterDeclaration verificationCaseAnnotationSummary(EObject context) { return findInParameters(verificationCase, ParameterDeclaration.class, VERIFICATION_CASE_SUMMARY_NAME); } + public AnnotationDeclaration tagAnnotation(EObject context) { + return findInBuiltin(context, AnnotationDeclaration.class, TAG_ANNOTATION_NAME); + } + + public ParameterDeclaration tagAnnotationCategory(EObject context) { + var tag = tagAnnotation(context); + return findInParameters(tag, ParameterDeclaration.class, TAG_ANNOTATION_CATEGORY_NAME); + } + public ClassDeclaration anythingClass(EObject context) { return findInBuiltin(context, ClassDeclaration.class, ANYTHING_NAME); } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OxstsUtils.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OxstsUtils.java index 16025984..a9a7cf10 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OxstsUtils.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OxstsUtils.java @@ -141,6 +141,16 @@ public static Annotation getAnnotation(AnnotatedElement element, AnnotationDecla return annotationContainer.getAnnotations().stream().filter(a -> a.getDeclaration() == annotationDeclaration).findFirst().orElse(null); } + public static Stream getAnnotations(AnnotatedElement element, AnnotationDeclaration annotationDeclaration) { + var annotationContainer = element.getAnnotation(); + + if (annotationContainer == null) { + return null; + } + + return annotationContainer.getAnnotations().stream().filter(a -> a.getDeclaration() == annotationDeclaration); + } + public static Expression getAnnotationValue(Annotation annotation, ParameterDeclaration parameterDeclaration) { var argument = annotation.getArguments().stream().filter(a -> a.getParameter() == parameterDeclaration).findFirst().orElse(null); diff --git a/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr.oxsts b/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr.oxsts index 54e36a4c..4fcee4f8 100644 --- a/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr.oxsts +++ b/subprojects/oxsts.lang/src/main/resources/hu/bme/mit/semantifyr/oxsts/lang/library/semantifyr.oxsts @@ -67,6 +67,11 @@ class Anything { */ annotation VerificationCase(summary: string[0..1]) +/* + * Tags allow categorizing verification cases, e.g., into slow for long-running cases. + */ +annotation Tag(category: string) + /* * Instances contained in Containment features annotated with @Shared are shared across all instances of the containing class. */ From 11d7928e6f48438de3690d3f3ed440818a5a151f Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 16 Mar 2026 21:55:57 +0100 Subject: [PATCH 019/115] Improved verification case test finding --- README.md | 5 +- .../gradle/conventions/jvm.gradle.kts | 38 +++- .../test/kotlin/ThetaXstsVerificationTests.kt | 35 +++- .../src/test/kotlin/GammaVerificationTests.kt | 119 +++++++++--- .../src/test/kotlin/SysMLVerificationTests.kt | 115 ++++++++++-- .../SemantifyrVerificationCaseHelper.kt | 104 ----------- .../kotlin/SemantifyrVerificationHelper.kt | 174 ++++++++++++++++++ 7 files changed, 429 insertions(+), 161 deletions(-) delete mode 100644 subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationCaseHelper.kt create mode 100644 subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt diff --git a/README.md b/README.md index fe06f16e..fc013231 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,10 @@ A framework to support the declarative definition of engineering model semantics Use Java 25 for building. -Run `gradlew build` to assemble the whole project, and execute all automated test, including regression testing and formal verifications. The required environment (e.g., Theta binaries) is automatically constructed by Gradle. Tests should run in a few minutes. +Run `gradlew build` to assemble and test the project, including regression testing and formal verifications. The required environment (e.g., Theta binaries) is automatically constructed by Gradle. Tests should run in 10-20 minutes. -To execute all tests (even extremely slow, several days long tests!), run `gradlew allTests`. +To execute slow verification cases (several days long tests!), run `gradlew testSlowVerificationCases`. +Or run `gradlew allTests` for all tests. NOTE: Verification tests use Docker to run Theta. To run the build locally, ensure you have docker installed! diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts index 0d6e6bcb..44a1e125 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts @@ -49,6 +49,7 @@ val verificationTestServiceProvider = gradle.sharedServices.registerIfAbsent(ver } tasks { + // TODO: refactor tests to use test suites test { useJUnitPlatform { excludeTags("verification") @@ -63,7 +64,7 @@ tasks { finalizedBy(tasks.jacocoTestReport) } - val verificationTest by tasks.registering(Test::class) { + val testVerificationCases by tasks.registering(Test::class) { group = "verification" useJUnitPlatform { @@ -87,14 +88,43 @@ tasks { finalizedBy(jacocoTestReport) } + val testSlowVerificationCases by tasks.registering(Test::class) { + group = "verification" + + useJUnitPlatform { +// includeTags("verification") + includeTags("slow") + } + + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + usesService(verificationTestServiceProvider) + + minHeapSize = "512m" + maxHeapSize = "4G" + testLogging.showStandardStreams = true + testLogging.exceptionFormat = TestExceptionFormat.FULL + + maxParallelForks = 1 + } + + val allTests by tasks.registering(DefaultTask::class) { + group = "verification" + + dependsOn(test) + dependsOn(testVerificationCases) + dependsOn(testSlowVerificationCases) + } + jacocoTestReport { inputs.files(test.get().outputs) - inputs.files(verificationTest.get().outputs) + inputs.files(testVerificationCases.get().outputs) - executionData(test.get(), verificationTest.get()) + executionData(test.get(), testVerificationCases.get()) } check { - inputs.files(verificationTest.get().outputs) + inputs.files(testVerificationCases.get().outputs) } } diff --git a/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt b/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt index f2484864..e459d3ee 100644 --- a/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt +++ b/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt @@ -8,31 +8,50 @@ package hu.bme.mit.semantifyr.backends.theta.verification import com.google.inject.Inject import com.google.inject.Provider +import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration import hu.bme.mit.semantifyr.semantics.BaseSemantifyrVerificationTest import hu.bme.mit.semantifyr.semantics.InjectWithOxstsSemantics +import hu.bme.mit.semantifyr.semantics.SemantifyrVerificationHelper +import hu.bme.mit.semantifyr.semantics.StandaloneOxstsSemanticsRuntimeModule import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader import hu.bme.mit.semantifyr.semantics.utils.loggerFactory import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource +import java.util.stream.Stream import kotlin.io.path.Path +import kotlin.streams.asStream @Tag("verification") @InjectWithOxstsSemantics class ThetaXstsVerificationTests : BaseSemantifyrVerificationTest() { - override val logger by loggerFactory() + companion object { - @Inject - lateinit var semantifyrLoader: SemantifyrLoader + private val semantifyrVerificationHelper = StandaloneOxstsSemanticsRuntimeModule.getInstance() + + @JvmStatic + fun `Simple Model Verification Cases Should Pass`(): Stream { + val model = semantifyrVerificationHelper.semantifyrLoader.startContext() + .loadModels(Path("test-models/Simple/simple.oxsts")) + .buildAndResolve() + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + + } + + override val logger by loggerFactory() @Inject override lateinit var oxstsVerifierProvider: Provider - @Test - fun `Simple Model Verification Cases Should Pass`() { - val model = semantifyrLoader.loadStandaloneModel(Path("test-models/Simple/simple.oxsts")) - - verifyVerificationCases(model) + @ParameterizedTest + @MethodSource + fun `Simple Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) } } diff --git a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt index 1394a0d3..12f7012d 100644 --- a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt +++ b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt @@ -9,19 +9,90 @@ package hu.bme.mit.semantifyr.frontends.gamma.semantics import com.google.inject.Inject import com.google.inject.Provider import hu.bme.mit.semantifyr.backends.theta.verification.ThetaVerifier +import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration import hu.bme.mit.semantifyr.semantics.BaseSemantifyrVerificationTest import hu.bme.mit.semantifyr.semantics.InjectWithOxstsSemantics +import hu.bme.mit.semantifyr.semantics.SemantifyrVerificationHelper +import hu.bme.mit.semantifyr.semantics.StandaloneOxstsSemanticsRuntimeModule import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader +import hu.bme.mit.semantifyr.semantics.reader.SemantifyrModelContext import hu.bme.mit.semantifyr.semantics.utils.loggerFactory +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Tag -import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource import java.nio.file.Path +import java.util.concurrent.TimeUnit +import java.util.stream.Stream import kotlin.io.path.Path +import kotlin.streams.asStream @Tag("verification") @InjectWithOxstsSemantics class GammaVerificationTests : BaseSemantifyrVerificationTest() { + + + companion object { + + private val semantifyrVerificationHelper = StandaloneOxstsSemanticsRuntimeModule.getInstance() + + @JvmStatic + fun `Gamma Semantic Library Verification Cases Should Pass`(): Stream { + val model = semantifyrVerificationHelper.semantifyrLoader.startContext() + .loadModels(Path("Library")) + .buildAndResolve() + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + + val transformer = StandaloneGammaTransformer() + + fun loadModel(model: String): SemantifyrModelContext { + val gammaModelPath = Path(model) + val gammaModel = gammaModelPath.toFile() + val oxstsModelPath = Path(gammaModel.absolutePath.replace(".gamma", ".oxsts")) + val oxstsModel = oxstsModelPath.toFile() + + transformer.transformModel(gammaModel, oxstsModel) + + return semantifyrVerificationHelper.semantifyrLoader.startContext() + .loadLibraries(Path("Library")) + .loadModel(oxstsModelPath) + .buildAndResolve() + } + + @JvmStatic + fun `Simple Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/Simple.gamma") + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + + @JvmStatic + fun `Crossroads Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/Crossroads.gamma") + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + + @JvmStatic + fun `Spacecraft Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/Spacecraft.gamma") + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + + @JvmStatic + fun `Slow Spacecraft Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/Spacecraft.gamma") + + return semantifyrVerificationHelper.collectSlowVerificationCases(model).asStream() + } + + } + override val logger by loggerFactory() @Inject @@ -30,36 +101,38 @@ class GammaVerificationTests : BaseSemantifyrVerificationTest() { @Inject override lateinit var oxstsVerifierProvider: Provider - val transformer = StandaloneGammaTransformer() - - fun testGammaModel(gammaModelPath: Path) { - val gammaModel = gammaModelPath.toFile() - val oxstsModelPath = Path(gammaModel.absolutePath.replace(".gamma", ".oxsts")) - val oxstsModel = oxstsModelPath.toFile() - transformer.transformModel(gammaModel, oxstsModel) - - val model = semantifyrLoader.startContext() - .loadLibraries(Path("Library")) - .loadModel(oxstsModelPath) - .buildAndResolve() + @ParameterizedTest + @MethodSource + @Disabled("There are no semantic library verification cases just yet.") + fun `Gamma Semantic Library Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) + } - verifyVerificationCases(model) + @ParameterizedTest + @MethodSource + fun `Simple Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) } - @Test - fun `Simple Model Verification Cases Should Pass`() { - testGammaModel(Path("TestModels/Simple.gamma")) + @ParameterizedTest + @MethodSource + fun `Crossroads Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) } - @Test - fun `Crossroads Model Verification Cases Should Pass`() { - testGammaModel(Path("TestModels/Crossroads.gamma")) + @ParameterizedTest + @MethodSource + fun `Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) } - @Test - fun `Spacecraft Model Verification Cases Should Pass`() { - testGammaModel(Path("TestModels/Spacecraft.gamma")) + @Tag("slow") + @ParameterizedTest + @MethodSource + @Disabled("There are no slow crossroads verification cases just yet.") + fun `Slow Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase, 30, TimeUnit.MINUTES) } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt index 2b0dc709..aa0e5090 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt @@ -9,19 +9,85 @@ package hu.bme.mit.semantifyr.frontends.sysml.semantics import com.google.inject.Inject import com.google.inject.Provider import hu.bme.mit.semantifyr.backends.theta.verification.ThetaVerifier +import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration import hu.bme.mit.semantifyr.semantics.BaseSemantifyrVerificationTest import hu.bme.mit.semantifyr.semantics.InjectWithOxstsSemantics +import hu.bme.mit.semantifyr.semantics.SemantifyrVerificationHelper +import hu.bme.mit.semantifyr.semantics.StandaloneOxstsSemanticsRuntimeModule import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader +import hu.bme.mit.semantifyr.semantics.reader.SemantifyrModelContext import hu.bme.mit.semantifyr.semantics.utils.loggerFactory +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Tag -import org.junit.jupiter.api.Test -import java.nio.file.Path +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource +import java.util.concurrent.TimeUnit +import java.util.stream.Stream import kotlin.io.path.Path +import kotlin.streams.asStream @Tag("verification") @InjectWithOxstsSemantics class SysMLVerificationTests : BaseSemantifyrVerificationTest() { + companion object { + + private val semantifyrVerificationHelper = StandaloneOxstsSemanticsRuntimeModule.getInstance() + + @JvmStatic + fun `SysML Semantic Library Verification Cases Should Pass`(): Stream { + val model = semantifyrVerificationHelper.semantifyrLoader.startContext() + .loadModels(Path("Library")) + .buildAndResolve() + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + + private fun loadModel(path: String): SemantifyrModelContext { + return semantifyrVerificationHelper.semantifyrLoader.startContext() + .loadLibraries(Path("Library")) + .loadModel(Path(path)) + .buildAndResolve() + } + + @JvmStatic + fun `STM21 Model Verification Cases Should Pass`(): Stream { + val model = loadModel("models/stm21.oxsts") + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + + @JvmStatic + fun `STM31 Model Verification Cases Should Pass`(): Stream { + val model = loadModel("models/stm31.oxsts") + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + + @JvmStatic + fun `Crossroads Model Verification Cases Should Pass`(): Stream { + val model = loadModel("models/crossroads.oxsts") + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + + @JvmStatic + fun `Spacecraft Model Verification Cases Should Pass`(): Stream { + val model = loadModel("models/spacecraft.oxsts") + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + + @JvmStatic + fun `Slow Spacecraft Model Verification Cases Should Pass`(): Stream { + val model = loadModel("models/spacecraft.oxsts") + + return semantifyrVerificationHelper.collectSlowVerificationCases(model).asStream() + } + + } + override val logger by loggerFactory() @Inject @@ -30,33 +96,42 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { @Inject override lateinit var oxstsVerifierProvider: Provider - fun testSysMLModel(modelPath: Path) { - val model = semantifyrLoader.startContext() - .loadLibraries(Path("Library")) - .loadModel(modelPath) - .buildAndResolve() + @ParameterizedTest + @MethodSource + @Disabled("There are no semantic library verification cases just yet.") + fun `SysML Semantic Library Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) + } - verifyVerificationCases(model) + @ParameterizedTest + @MethodSource + fun `STM21 Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) } - @Test - fun `STM21 Model Verification Cases Should Pass`() { - testSysMLModel(Path("models/stm21.oxsts")) + @ParameterizedTest + @MethodSource + fun `STM31 Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) } - @Test - fun `STM31 Model Verification Cases Should Pass`() { - testSysMLModel(Path("models/stm31.oxsts")) + @ParameterizedTest + @MethodSource + fun `Crossroads Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) } - @Test - fun `Crossroads Model Verification Cases Should Pass`() { - testSysMLModel(Path("models/crossroads.oxsts")) + @ParameterizedTest + @MethodSource + fun `Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) } - @Test - fun `Spacecraft Model Verification Cases Should Pass`() { - testSysMLModel(Path("models/spacecraft.oxsts")) + @Tag("slow") + @ParameterizedTest + @MethodSource + fun `Slow Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase, 30, TimeUnit.MINUTES) } } diff --git a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationCaseHelper.kt b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationCaseHelper.kt deleted file mode 100644 index 1781e20a..00000000 --- a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationCaseHelper.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package hu.bme.mit.semantifyr.semantics - -import com.google.inject.Inject -import com.google.inject.Provider -import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltInLibraryUtils -import hu.bme.mit.semantifyr.oxsts.lang.naming.OxstsQualifiedNameProvider -import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration -import hu.bme.mit.semantifyr.oxsts.model.oxsts.OxstsModelPackage -import hu.bme.mit.semantifyr.semantics.reader.SemantifyrModelContext -import hu.bme.mit.semantifyr.semantics.transformation.ProgressContext -import hu.bme.mit.semantifyr.semantics.utils.info -import hu.bme.mit.semantifyr.semantics.verification.CompilationScopeHelper -import hu.bme.mit.semantifyr.semantics.verification.OxstsVerifier -import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult -import hu.bme.mit.semantifyr.semantics.verification.VerificationResult -import org.junit.jupiter.api.Assertions -import org.slf4j.Logger -import kotlin.streams.asSequence - -abstract class BaseSemantifyrVerificationTest { - - abstract val logger: Logger - - val loggerContext = object : ProgressContext { - override fun checkIsCancelled() { - // never cancelled - } - - override fun reportProgress(message: String, percentage: Int) { - logger.info { "$message - $percentage%" } - } - - override fun reportProgress(message: String) { - logger.info { message } - } - - } - - @Inject - lateinit var oxstsQualifiedNameProvider: OxstsQualifiedNameProvider - - @Inject - lateinit var builtInLibraryUtils: BuiltInLibraryUtils - - @Inject - lateinit var compilationScopeHelper: CompilationScopeHelper - - abstract val oxstsVerifierProvider: Provider - - fun runVerification(classDeclaration: ClassDeclaration): VerificationCaseRunResult { - logger.info { - "Verifying class: ${oxstsQualifiedNameProvider.getFullyQualifiedNameString(classDeclaration)}" - } - - return oxstsVerifierProvider.get().verify(loggerContext, classDeclaration) - } - - fun collectVerificationCases(model: SemantifyrModelContext): Sequence { - return model.modelResources.asSequence().map { - it.contents.single() - }.filterIsInstance().flatMap { - builtInLibraryUtils.streamTestCases(it).asSequence() - } - } - - fun verifyVerificationCases(model: SemantifyrModelContext) { - logger.info { "Collecting verification cases" } - - val verificationCases = collectVerificationCases(model).toList() - - for (verificationCase in verificationCases) { - compilationScopeHelper.runInCompilationScope(verificationCase) { - val result = runVerification(it) - - Assertions.assertEquals(result.result, VerificationResult.Passed) - } - } - } - - fun verifyVerificationCase(model: SemantifyrModelContext, qualifiedName: String) { - logger.info { "Looking for $qualifiedName" } - - val verificationCase = collectVerificationCases(model).firstOrNull { - oxstsQualifiedNameProvider.getFullyQualifiedNameString(it) == qualifiedName - } - - if (verificationCase == null) { - error("$qualifiedName can not be found!") - } - - compilationScopeHelper.runInCompilationScope(verificationCase) { - val result = runVerification(it) - - Assertions.assertEquals(result.result, VerificationResult.Passed) - } - } - -} diff --git a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt new file mode 100644 index 00000000..7f21bcb4 --- /dev/null +++ b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt @@ -0,0 +1,174 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.semantics + +import com.google.inject.Inject +import com.google.inject.Provider +import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltInLibraryUtils +import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltinAnnotationHandler +import hu.bme.mit.semantifyr.oxsts.lang.naming.OxstsQualifiedNameProvider +import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration +import hu.bme.mit.semantifyr.oxsts.model.oxsts.OxstsModelPackage +import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader +import hu.bme.mit.semantifyr.semantics.reader.SemantifyrModelContext +import hu.bme.mit.semantifyr.semantics.transformation.ProgressContext +import hu.bme.mit.semantifyr.semantics.utils.info +import hu.bme.mit.semantifyr.semantics.utils.loggerFactory +import hu.bme.mit.semantifyr.semantics.verification.CompilationScopeHelper +import hu.bme.mit.semantifyr.semantics.verification.OxstsVerifier +import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult +import hu.bme.mit.semantifyr.semantics.verification.VerificationResult +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Named +import org.junit.jupiter.params.provider.Arguments +import org.slf4j.Logger +import java.util.concurrent.TimeUnit +import kotlin.streams.asSequence + +/** + * Helper class to be instantiated from a Global injector such as StandaloneOxstsSemanticsRuntimeModule#injector + */ +class SemantifyrVerificationHelper { + + private val logger by loggerFactory() + + @Inject + lateinit var oxstsQualifiedNameProvider: OxstsQualifiedNameProvider + + @Inject + lateinit var builtInLibraryUtils: BuiltInLibraryUtils + + @Inject + lateinit var builtinAnnotationHandler: BuiltinAnnotationHandler + + @Inject + lateinit var semantifyrLoader: SemantifyrLoader + + private fun rawCollectVerificationCases(model: SemantifyrModelContext): Sequence { + return model.modelResources.asSequence().map { + it.contents.single() + }.filterIsInstance().flatMap { + builtInLibraryUtils.streamTestCases(it).asSequence() + } + } + + private fun ClassDeclaration.named(): Arguments { + return Arguments.of(Named.of(oxstsQualifiedNameProvider.getFullyQualifiedNameString(this), this)) + } + + private fun Sequence.named(): Sequence { + return map { + it.named() + } + } + + fun collectSlowVerificationCases(model: SemantifyrModelContext): Sequence { + logger.info { "Collecting verification cases tagged with 'slow'" } + + return rawCollectVerificationCases(model).filter { + builtinAnnotationHandler.isTaggedWith(it, "slow") + }.named() + } + + fun collectNotSlowVerificationCases(model: SemantifyrModelContext): Sequence { + logger.info { "Collecting verification cases not tagged with 'slow'" } + + return rawCollectVerificationCases(model).filter { + builtinAnnotationHandler.isNotTaggedWith(it, "slow") + }.named() + } + + fun collectVerificationCases( + model: SemantifyrModelContext, + including: List = emptyList(), + excluding: List = emptyList(), + ): Sequence { + logger.info { "Collecting verification cases" } + + var verificationCases = rawCollectVerificationCases(model) + + if (including.any()) { + logger.info { "Including tags ${including.joinToString(",")}" } + verificationCases = verificationCases.filter { + // allow all classes that are tagged by at least one in the including list + including.map { tag -> + builtinAnnotationHandler.isTaggedWith(it, tag) + }.reduce { a, b -> + a || b + } + } + } + + if (excluding.any()) { + logger.info { "Excluding tags ${including.joinToString(",")}" } + verificationCases = verificationCases.filterNot { + // disallow all classes that are tagged by at least one in the including list + excluding.map { tag -> + builtinAnnotationHandler.isTaggedWith(it, tag) + }.reduce { a, b -> + a || b + } + } + } + + return verificationCases.named() + } + +} + +abstract class BaseSemantifyrVerificationTest { + + abstract val logger: Logger + + val loggerContext = object : ProgressContext { + override fun checkIsCancelled() { + // never cancelled + } + + override fun reportProgress(message: String, percentage: Int) { + logger.info { "$message - $percentage%" } + } + + override fun reportProgress(message: String) { + logger.info { message } + } + + } + + @Inject + lateinit var oxstsQualifiedNameProvider: OxstsQualifiedNameProvider + + @Inject + lateinit var compilationScopeHelper: CompilationScopeHelper + + abstract val oxstsVerifierProvider: Provider + + fun executeVerificationCase( + classDeclaration: ClassDeclaration, + timeout: Long = 10L, + timeUnit: TimeUnit = TimeUnit.MINUTES + ): VerificationCaseRunResult { + logger.info { + "Verifying class: ${oxstsQualifiedNameProvider.getFullyQualifiedNameString(classDeclaration)}" + } + + return oxstsVerifierProvider.get().verify(loggerContext, classDeclaration, timeout, timeUnit) + } + + fun checkVerificationCase( + verificationCase: ClassDeclaration, + timeout: Long = 10L, + timeUnit: TimeUnit = TimeUnit.MINUTES + ) { + compilationScopeHelper.runInCompilationScope(verificationCase) { + val result = executeVerificationCase(it, timeout, timeUnit) + + Assertions.assertEquals(VerificationResult.Passed, result.result) + } + } + +} From d1c30a071eb713ea3a36fef6067151fb72ff41b1 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 17 Mar 2026 15:24:25 +0100 Subject: [PATCH 020/115] Slightly better error handling --- .../lang/ide/server/commands/VerifyOxstsCommandHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java index 634da64a..1653c6c8 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java @@ -88,7 +88,7 @@ protected Object execute(ClassDeclaration arguments, ILanguageServerAccess acces return new VerificationCaseRunResultDto(res, runResult.getMessage()); } catch (Exception e) { - throw new RuntimeException(e); + return new VerificationCaseRunResultDto("error", e.getMessage()); } } From 67ef7cc4f022e9321ccebed87ee22365deb01d49 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 17 Mar 2026 15:24:35 +0100 Subject: [PATCH 021/115] Fixed the spacecraft model --- .../TestModels/spacecraft.sysml | 153 ++++++++++++------ 1 file changed, 107 insertions(+), 46 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/spacecraft.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/spacecraft.sysml index 998dd01e..ed3d3c96 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/spacecraft.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/spacecraft.sysml @@ -34,7 +34,7 @@ part def GroundStation { transition first Operation accept after 10 [s] then Operation; - transition first Operation accept : StopCommand via commandPort then Idle; + // transition first Operation accept : StopCommand via commandPort then Idle; } } @@ -48,30 +48,26 @@ part def Spacecraft { exhibit state Behaviour parallel { state Communication { - state WaitingPing; + transition first start then WaitingPing; - transition - first Transmitting.SendData.Sending - accept after 4 [s] - if (data <= 0) or (batteryCharge < 40) - then WaitingPing; + state WaitingPing; transition - first Transmitting.ConsumePower.Consuming - accept after 4 [s] - if batteryCharge < 40 - then WaitingPing; + first WaitingPing + accept : PingCommand via commandPort + if (recharging == false and not (data <= 0 or batteryCharge <= 40)) + then Transmitting; state Transmitting parallel { state SendData { - state Sending; - transition first start then Sending; + state Sending; + transition first Sending accept after 4 [s] - if not (data <= 0 or batteryCharge < 40) + if not (data <= 0 or batteryCharge <= 40) do action { assign data := data - 10; send Data() via dataPort; @@ -79,28 +75,35 @@ part def Spacecraft { then Sending; } state ConsumePower { - state Consuming; - transition first start then Consuming; + state Consuming; + transition first Consuming accept after 2 [s] - if not (batteryCharge < 40) + if not (batteryCharge <= 40) do assign batteryCharge := batteryCharge - 10 then Consuming; } } - transition first start then WaitingPing; transition - first WaitingPing - accept : PingCommand via commandPort - if (recharging == false and not (data <= 0 or batteryCharge < 40)) - then Transmitting; + first Transmitting + accept after 4 [s] + if data <= 0 or batteryCharge <= 40 + then WaitingPing; + + transition + first Transmitting + accept after 4 [s] + if batteryCharge <= 40 + then WaitingPing; } state Battery { + transition first start then NotRecharging; + state NotRecharging { entry assign recharging := false; } @@ -108,8 +111,6 @@ part def Spacecraft { state Recharging { entry assign recharging := true; } - - transition first start then NotRecharging; transition first NotRecharging @@ -346,7 +347,7 @@ verification def SpacecraftBehaviorBatteryRechargingReachable { } } -verification def GroundStateReceivedData0 { +verification def GroundStationReceivedDataCanReach0 { subject mission: Mission; objective { @@ -360,7 +361,7 @@ verification def GroundStateReceivedData0 { } } -verification def GroundStateReceivedData10 { +verification def GroundStationReceivedDataCanReach10 { subject mission: Mission; objective { @@ -374,7 +375,7 @@ verification def GroundStateReceivedData10 { } } -verification def GroundStateReceivedData20 { +verification def GroundStationReceivedDataCanReach20 { subject mission: Mission; objective { @@ -388,7 +389,7 @@ verification def GroundStateReceivedData20 { } } -verification def GroundStateReceivedData30 { +verification def GroundStationReceivedDataCanReach30 { subject mission: Mission; objective { @@ -402,7 +403,7 @@ verification def GroundStateReceivedData30 { } } -verification def GroundStateReceivedData40 { +verification def GroundStationReceivedDataCanReach40 { subject mission: Mission; objective { @@ -416,7 +417,7 @@ verification def GroundStateReceivedData40 { } } -verification def GroundStateReceivedData50 { +verification def GroundStationReceivedDataCanReach50 { subject mission: Mission; objective { @@ -430,7 +431,7 @@ verification def GroundStateReceivedData50 { } } -verification def GroundStateReceivedData60 { +verification def GroundStationReceivedDataCanReach60 { subject mission: Mission; objective { @@ -444,7 +445,7 @@ verification def GroundStateReceivedData60 { } } -verification def GroundStateReceivedData70 { +verification def GroundStationReceivedDataCanReach70 { subject mission: Mission; objective { @@ -459,7 +460,7 @@ verification def GroundStateReceivedData70 { } /* Takes too long for the 5 minute timeout -verification def GroundStateReceivedData80 { +verification def GroundStationReceivedDataCanReach80 { subject mission: Mission; objective { @@ -473,7 +474,7 @@ verification def GroundStateReceivedData80 { } } -verification def GroundStateReceivedData90 { +verification def GroundStationReceivedDataCanReach90 { subject mission: Mission; objective { @@ -487,7 +488,7 @@ verification def GroundStateReceivedData90 { } } -verification def GroundStateReceivedData100 { +verification def GroundStationReceivedDataCanReach100 { subject mission: Mission; objective { @@ -502,7 +503,7 @@ verification def GroundStateReceivedData100 { } */ -verification def SpacecraftData100 { +verification def SpacecraftDataCanReach100 { subject mission: Mission; objective { @@ -516,7 +517,7 @@ verification def SpacecraftData100 { } } -verification def SpacecraftData90 { +verification def SpacecraftDataCanReach90 { subject mission: Mission; objective { @@ -530,7 +531,7 @@ verification def SpacecraftData90 { } } -verification def SpacecraftData80 { +verification def SpacecraftDataCanReach80 { subject mission: Mission; objective { @@ -544,7 +545,7 @@ verification def SpacecraftData80 { } } -verification def SpacecraftData70 { +verification def SpacecraftDataCanReach70 { subject mission: Mission; objective { @@ -558,7 +559,7 @@ verification def SpacecraftData70 { } } -verification def SpacecraftData60 { +verification def SpacecraftDataCanReach60 { subject mission: Mission; objective { @@ -572,7 +573,7 @@ verification def SpacecraftData60 { } } -verification def SpacecraftData50 { +verification def SpacecraftDataCanReach50 { subject mission: Mission; objective { @@ -586,7 +587,7 @@ verification def SpacecraftData50 { } } -verification def SpacecraftData40 { +verification def SpacecraftDataCanReach40 { subject mission: Mission; objective { @@ -600,7 +601,7 @@ verification def SpacecraftData40 { } } -verification def SpacecraftData30 { +verification def SpacecraftDataCanReach30 { subject mission: Mission; objective { @@ -615,7 +616,7 @@ verification def SpacecraftData30 { } /* Takes too long for the 5 minute timeout -verification def SpacecraftData20 { +verification def SpacecraftDataCanReach20 { subject mission: Mission; objective { @@ -629,7 +630,7 @@ verification def SpacecraftData20 { } } -verification def SpacecraftData10 { +verification def SpacecraftDataCanReach10 { subject mission: Mission; objective { @@ -643,7 +644,7 @@ verification def SpacecraftData10 { } } -verification def SpacecraftData0 { +verification def SpacecraftDataCanReach0 { subject mission: Mission; objective { @@ -657,3 +658,63 @@ verification def SpacecraftData0 { } } */ + +verification def SpacecraftBatteryAlwaysAbove0 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + mission.spacecraft.batteryCharge >= 0 + } + } + } +} + +verification def SpacecraftBatteryAlwaysAbove10 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + mission.spacecraft.batteryCharge >= 10 + } + } + } +} + +verification def SpacecraftBatteryAlwaysAbove20 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + mission.spacecraft.batteryCharge >= 20 + } + } + } +} + +verification def SpacecraftBatteryAlwaysAbove30 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + mission.spacecraft.batteryCharge >= 30 + } + } + } +} + +verification def SpacecraftBatteryAlwaysAbove40 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + mission.spacecraft.batteryCharge >= 40 + } + } + } +} From 33a3a8728ac42161ab561e966d9b62222749294a Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 17 Mar 2026 15:34:26 +0100 Subject: [PATCH 022/115] Updated the tested spacecraft semantifyr model --- .../sysmlv2-semantics/models/spacecraft.oxsts | 298 +++++++++++------- 1 file changed, 185 insertions(+), 113 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts index c953e746..6e10d557 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts @@ -21,7 +21,7 @@ class GroundStation : Part { contains UnnamedTransitionUsage0: Transition subsets transitions { redefine refers from: StateNode = start redefine refers to: StateNode = Idle -} + } contains Idle: State subsets states contains UnnamedTransitionUsage1: Transition subsets transitions { redefine refers from: StateNode = Idle @@ -46,7 +46,7 @@ class GroundStation : Part { contains UnnamedTransitionUsage3: Transition subsets transitions { redefine refers from: StateNode = start redefine refers to: StateNode = Waiting -} + } contains Waiting: State subsets states contains UnnamedTransitionUsage4: Transition subsets transitions { redefine refers from: StateNode = Waiting @@ -85,14 +85,6 @@ class GroundStation : Part { redefine refers afterTime: int = 10 } } - contains UnnamedTransitionUsage6: Transition subsets transitions { - redefine refers from: StateNode = Operation - redefine refers to: StateNode = Idle - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = commandPort - redefine refers payload: Item = global_StopCommand - } - } } } class Spacecraft : Part { @@ -109,59 +101,59 @@ class Spacecraft : Part { } contains Behaviour: ParallelState redefines exhibitState { contains Communication: State subsets states { + contains UnnamedTransitionUsage6: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = WaitingPing + } contains WaitingPing: State subsets states contains UnnamedTransitionUsage7: Transition subsets transitions { - redefine refers from: StateNode = Transmitting.SendData.Sending - redefine refers to: StateNode = WaitingPing - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 4 + redefine refers from: StateNode = WaitingPing + redefine refers to: StateNode = Transmitting + redefine contains acceptAction: AcceptItemAction { + redefine refers viaPort: Port = commandPort + redefine refers payload: Item = global_PingCommand } redefine contains guard: Guard { - redefine contains expression: OrOperatorExpression { - redefine contains left: LessThanOrEqualsOperatorExpression { + redefine contains expression: AndOperatorExpression { + redefine contains left: EqualityOperatorExpression { redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = data + redefine refers attribute: Attribute = recharging } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 0 + redefine contains right: LiteralBooleanExpression { + redefine refers value: bool = false } } - redefine contains right: LessThanOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 + redefine contains right: UnaryNotExpression { + redefine contains operand: OrOperatorExpression { + redefine contains left: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = data + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 0 + } + } + redefine contains right: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 + } + } } } } } } - contains UnnamedTransitionUsage8: Transition subsets transitions { - redefine refers from: StateNode = Transmitting.ConsumePower.Consuming - redefine refers to: StateNode = WaitingPing - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 4 - } - redefine contains guard: Guard { - redefine contains expression: LessThanOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 - } - } - } - } contains Transmitting: ParallelState subsets states { contains SendData: State subsets states { - contains Sending: State subsets states - contains UnnamedTransitionUsage9: Transition subsets transitions { + contains UnnamedTransitionUsage8: Transition subsets transitions { redefine refers from: StateNode = start redefine refers to: StateNode = Sending -} - contains UnnamedTransitionUsage10: Transition subsets transitions { + } + contains Sending: State subsets states + contains UnnamedTransitionUsage9: Transition subsets transitions { redefine refers from: StateNode = Sending redefine refers to: StateNode = Sending redefine contains acceptAction: AcceptTimeoutAction { @@ -178,7 +170,7 @@ class Spacecraft : Part { redefine refers value: int = 0 } } - redefine contains right: LessThanOperatorExpression { + redefine contains right: LessThanOrEqualsOperatorExpression { redefine contains left: AttributeReferenceExpression { redefine refers attribute: Attribute = batteryCharge } @@ -209,12 +201,12 @@ class Spacecraft : Part { } } contains ConsumePower: State subsets states { - contains Consuming: State subsets states - contains UnnamedTransitionUsage11: Transition subsets transitions { + contains UnnamedTransitionUsage10: Transition subsets transitions { redefine refers from: StateNode = start redefine refers to: StateNode = Consuming -} - contains UnnamedTransitionUsage12: Transition subsets transitions { + } + contains Consuming: State subsets states + contains UnnamedTransitionUsage11: Transition subsets transitions { redefine refers from: StateNode = Consuming redefine refers to: StateNode = Consuming redefine contains acceptAction: AcceptTimeoutAction { @@ -222,7 +214,7 @@ class Spacecraft : Part { } redefine contains guard: Guard { redefine contains expression: UnaryNotExpression { - redefine contains operand: LessThanOperatorExpression { + redefine contains operand: LessThanOrEqualsOperatorExpression { redefine contains left: AttributeReferenceExpression { redefine refers attribute: Attribute = batteryCharge } @@ -246,52 +238,56 @@ class Spacecraft : Part { } } } - contains UnnamedTransitionUsage13: Transition subsets transitions { - redefine refers from: StateNode = start + contains UnnamedTransitionUsage12: Transition subsets transitions { + redefine refers from: StateNode = Transmitting redefine refers to: StateNode = WaitingPing -} - contains UnnamedTransitionUsage14: Transition subsets transitions { - redefine refers from: StateNode = WaitingPing - redefine refers to: StateNode = Transmitting - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = commandPort - redefine refers payload: Item = global_PingCommand + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 4 } redefine contains guard: Guard { - redefine contains expression: AndOperatorExpression { - redefine contains left: EqualityOperatorExpression { + redefine contains expression: OrOperatorExpression { + redefine contains left: LessThanOrEqualsOperatorExpression { redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = recharging + redefine refers attribute: Attribute = data } - redefine contains right: LiteralBooleanExpression { - redefine refers value: bool = false + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 0 } } - redefine contains right: UnaryNotExpression { - redefine contains operand: OrOperatorExpression { - redefine contains left: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 0 - } - } - redefine contains right: LessThanOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 - } - } + redefine contains right: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 } } } } } + contains UnnamedTransitionUsage13: Transition subsets transitions { + redefine refers from: StateNode = Transmitting + redefine refers to: StateNode = WaitingPing + redefine contains acceptAction: AcceptTimeoutAction { + redefine refers afterTime: int = 4 + } + redefine contains guard: Guard { + redefine contains expression: LessThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 + } + } + } + } } contains Battery: State subsets states { + contains UnnamedTransitionUsage14: Transition subsets transitions { + redefine refers from: StateNode = start + redefine refers to: StateNode = NotRecharging + } contains NotRecharging: State subsets states { redefine contains entryAction: AssignmentAction { redefine refers attribute: Attribute = recharging @@ -309,10 +305,6 @@ class Spacecraft : Part { } } contains UnnamedTransitionUsage15: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = NotRecharging -} - contains UnnamedTransitionUsage16: Transition subsets transitions { redefine refers from: StateNode = NotRecharging redefine refers to: StateNode = Recharging redefine contains acceptAction: AcceptTimeoutAction { @@ -329,7 +321,7 @@ class Spacecraft : Part { } } } - contains UnnamedTransitionUsage17: Transition subsets transitions { + contains UnnamedTransitionUsage16: Transition subsets transitions { redefine refers from: StateNode = Recharging redefine refers to: StateNode = Recharging redefine contains acceptAction: AcceptTimeoutAction { @@ -357,7 +349,7 @@ class Spacecraft : Part { } } } - contains UnnamedTransitionUsage18: Transition subsets transitions { + contains UnnamedTransitionUsage17: Transition subsets transitions { redefine refers from: StateNode = Recharging redefine refers to: StateNode = NotRecharging redefine contains acceptAction: AcceptTimeoutAction { @@ -556,7 +548,7 @@ class SpacecraftBehaviorBatteryRechargingReachable : VerificationCaseDefinition } } @VerificationCase -class GroundStateReceivedData0 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach0 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -574,7 +566,7 @@ class GroundStateReceivedData0 : VerificationCaseDefinition { } } @VerificationCase -class GroundStateReceivedData10 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach10 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -592,7 +584,7 @@ class GroundStateReceivedData10 : VerificationCaseDefinition { } } @VerificationCase -class GroundStateReceivedData20 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach20 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -610,7 +602,7 @@ class GroundStateReceivedData20 : VerificationCaseDefinition { } } @VerificationCase -class GroundStateReceivedData30 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach30 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -628,7 +620,7 @@ class GroundStateReceivedData30 : VerificationCaseDefinition { } } @VerificationCase -class GroundStateReceivedData40 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach40 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -646,7 +638,7 @@ class GroundStateReceivedData40 : VerificationCaseDefinition { } } @VerificationCase -class GroundStateReceivedData50 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach50 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -664,7 +656,7 @@ class GroundStateReceivedData50 : VerificationCaseDefinition { } } @VerificationCase -class GroundStateReceivedData60 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach60 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -682,7 +674,7 @@ class GroundStateReceivedData60 : VerificationCaseDefinition { } } @VerificationCase -class GroundStateReceivedData70 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach70 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -700,7 +692,7 @@ class GroundStateReceivedData70 : VerificationCaseDefinition { } } @VerificationCase -class SpacecraftData100 : VerificationCaseDefinition { +class SpacecraftDataCanReach100 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -718,7 +710,7 @@ class SpacecraftData100 : VerificationCaseDefinition { } } @VerificationCase -class SpacecraftData90 : VerificationCaseDefinition { +class SpacecraftDataCanReach90 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -736,7 +728,7 @@ class SpacecraftData90 : VerificationCaseDefinition { } } @VerificationCase -class SpacecraftData80 : VerificationCaseDefinition { +class SpacecraftDataCanReach80 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -754,7 +746,7 @@ class SpacecraftData80 : VerificationCaseDefinition { } } @VerificationCase -class SpacecraftData70 : VerificationCaseDefinition { +class SpacecraftDataCanReach70 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -772,7 +764,7 @@ class SpacecraftData70 : VerificationCaseDefinition { } } @VerificationCase -class SpacecraftData60 : VerificationCaseDefinition { +class SpacecraftDataCanReach60 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -790,7 +782,7 @@ class SpacecraftData60 : VerificationCaseDefinition { } } @VerificationCase -class SpacecraftData50 : VerificationCaseDefinition { +class SpacecraftDataCanReach50 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -808,7 +800,7 @@ class SpacecraftData50 : VerificationCaseDefinition { } } @VerificationCase -class SpacecraftData40 : VerificationCaseDefinition { +class SpacecraftDataCanReach40 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -826,7 +818,7 @@ class SpacecraftData40 : VerificationCaseDefinition { } } @VerificationCase -class SpacecraftData30 : VerificationCaseDefinition { +class SpacecraftDataCanReach30 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -843,12 +835,92 @@ class SpacecraftData30 : VerificationCaseDefinition { } } } +@VerificationCase +class SpacecraftBatteryAlwaysAbove0 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 0 + } + } + } + } +} +@VerificationCase +class SpacecraftBatteryAlwaysAbove10 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 10 + } + } + } + } +} +@VerificationCase +class SpacecraftBatteryAlwaysAbove20 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 20 + } + } + } + } +} +@VerificationCase +class SpacecraftBatteryAlwaysAbove30 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 30 + } + } + } + } +} +@VerificationCase +class SpacecraftBatteryAlwaysAbove40 : VerificationCaseDefinition { + contains mission: Mission[1] redefines subject + redefine contains objective: Requirement[1] { + redefine contains verifyRequirement : Constraint[1] { + redefine contains requiredConstraint: GreaterThanOrEqualsOperatorExpression { + redefine contains left: AttributeReferenceExpression { + redefine refers attribute: Attribute = mission.spacecraft.batteryCharge + } + redefine contains right: LiteralIntegerExpression { + redefine refers value: int = 40 + } + } + } + } +} // manually added slow verification cases @Tag("slow") @VerificationCase -class GroundStateReceivedData80 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach80 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -867,7 +939,7 @@ class GroundStateReceivedData80 : VerificationCaseDefinition { } @Tag("slow") @VerificationCase -class GroundStateReceivedData90 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach90 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -886,7 +958,7 @@ class GroundStateReceivedData90 : VerificationCaseDefinition { } @Tag("slow") @VerificationCase -class GroundStateReceivedData100 : VerificationCaseDefinition { +class GroundStationReceivedDataCanReach100 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -906,7 +978,7 @@ class GroundStateReceivedData100 : VerificationCaseDefinition { @Tag("slow") @VerificationCase -class SpacecraftData20 : VerificationCaseDefinition { +class SpacecraftDataCanReach20 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -925,7 +997,7 @@ class SpacecraftData20 : VerificationCaseDefinition { } @Tag("slow") @VerificationCase -class SpacecraftData10 : VerificationCaseDefinition { +class SpacecraftDataCanReach10 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -944,7 +1016,7 @@ class SpacecraftData10 : VerificationCaseDefinition { } @Tag("slow") @VerificationCase -class SpacecraftData00 : VerificationCaseDefinition { +class SpacecraftDataCanReach0 : VerificationCaseDefinition { contains mission: Mission[1] redefines subject redefine contains objective: Requirement[1] { redefine contains verifyRequirement : Constraint[1] { @@ -954,7 +1026,7 @@ class SpacecraftData00 : VerificationCaseDefinition { redefine refers attribute: Attribute = mission.spacecraft.data } redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 00 + redefine refers value: int = 0 } } } From f8e7b8e78864e18363ecdcb95bd3f16eae8a375e Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 17 Mar 2026 15:34:39 +0100 Subject: [PATCH 023/115] Increased the slow test timeout --- README.md | 3 ++- .../gamma-semantics/src/test/kotlin/GammaVerificationTests.kt | 2 +- .../src/test/kotlin/SysMLVerificationTests.kt | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fc013231..049321db 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,8 @@ Use Java 25 for building. Run `gradlew build` to assemble and test the project, including regression testing and formal verifications. The required environment (e.g., Theta binaries) is automatically constructed by Gradle. Tests should run in 10-20 minutes. -To execute slow verification cases (several days long tests!), run `gradlew testSlowVerificationCases`. +To execute slow verification cases (the longest may take ~1 hour), run `gradlew testSlowVerificationCases`. + Or run `gradlew allTests` for all tests. NOTE: Verification tests use Docker to run Theta. To run the build locally, ensure you have docker installed! diff --git a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt index 12f7012d..b1c58b88 100644 --- a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt +++ b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt @@ -132,7 +132,7 @@ class GammaVerificationTests : BaseSemantifyrVerificationTest() { @MethodSource @Disabled("There are no slow crossroads verification cases just yet.") fun `Slow Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { - checkVerificationCase(verificationCase, 30, TimeUnit.MINUTES) + checkVerificationCase(verificationCase, 60, TimeUnit.MINUTES) } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt index aa0e5090..6b77ec4e 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt @@ -131,7 +131,7 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { @ParameterizedTest @MethodSource fun `Slow Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { - checkVerificationCase(verificationCase, 30, TimeUnit.MINUTES) + checkVerificationCase(verificationCase, 60, TimeUnit.MINUTES) } } From f38750bf1045196dbaf1c02d4ee318f4362bb23b Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 17 Mar 2026 15:35:11 +0100 Subject: [PATCH 024/115] Added CI build check for all tests. --- .github/workflows/verification.yml | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/verification.yml diff --git a/.github/workflows/verification.yml b/.github/workflows/verification.yml new file mode 100644 index 00000000..9e08dcac --- /dev/null +++ b/.github/workflows/verification.yml @@ -0,0 +1,37 @@ + +name: Continuous Integration +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] +env: + CI: true +jobs: + build: + permissions: + contents: read + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + # - macos-13 + runs-on: ${{ matrix.os }} + steps: + # - name: Setup Docker on MacOS + # uses: douglascamata/setup-docker-macos-action@v1-alpha + # if: ${{ matrix.os == 'macos-13' }} + - name: Test Docker + run: docker run hello-world + - name: Checkout code + uses: actions/checkout@v6 + - name: Set up JDK + uses: actions/setup-java@v5 + with: + java-version: 25 + distribution: adopt + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v5 + - name: Run verification tests + run: ./gradlew allTests --continue From f78bb3982a5eeafd2ea19f67ef997f7b26adf27d Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 17 Mar 2026 15:37:07 +0100 Subject: [PATCH 025/115] Fixed incorrect name and license. --- .github/workflows/verification.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/verification.yml b/.github/workflows/verification.yml index 9e08dcac..8a4f6e6d 100644 --- a/.github/workflows/verification.yml +++ b/.github/workflows/verification.yml @@ -1,5 +1,8 @@ +# SPDX-FileCopyrightText: 2023-2024 The Semantifyr Authors +# +# SPDX-License-Identifier: EPL-2.0 -name: Continuous Integration +name: All Verification Tests on: push: branches: [ "main" ] From 6401a80c81ae4a201aae8a65472860aae387ae5d Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 17 Mar 2026 17:38:49 +0100 Subject: [PATCH 026/115] Increased default verification timeout during tests --- .../src/testFixtures/kotlin/SemantifyrVerificationHelper.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt index 7f21bcb4..6e79d214 100644 --- a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt +++ b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt @@ -149,7 +149,7 @@ abstract class BaseSemantifyrVerificationTest { fun executeVerificationCase( classDeclaration: ClassDeclaration, - timeout: Long = 10L, + timeout: Long = 30L, timeUnit: TimeUnit = TimeUnit.MINUTES ): VerificationCaseRunResult { logger.info { @@ -161,7 +161,7 @@ abstract class BaseSemantifyrVerificationTest { fun checkVerificationCase( verificationCase: ClassDeclaration, - timeout: Long = 10L, + timeout: Long = 30L, timeUnit: TimeUnit = TimeUnit.MINUTES ) { compilationScopeHelper.runInCompilationScope(verificationCase) { From 9e6c31d539bb65455a7464df0f72d469a898b6f7 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 18:23:51 +0100 Subject: [PATCH 027/115] Added theta shell autodownload --- .github/workflows/build.yml | 10 +- .github/workflows/verification.yml | 9 +- .../gradle/conventions/jvm.gradle.kts | 12 +++ gradle.properties | 2 +- .../theta/theta-wrapper/build.gradle.kts | 93 +++++++++++++++++++ .../theta-wrapper/scripts/theta-xsts-cli | 8 ++ .../theta-wrapper/scripts/theta-xsts-cli.cmd | 10 ++ .../execution/ShellBasedThetaXstsExecutor.kt | 38 ++++++-- .../execution/ThetaXstsExecutorProvider.kt | 6 +- subprojects/semantics/build.gradle.kts | 8 -- 10 files changed, 164 insertions(+), 32 deletions(-) create mode 100755 subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli create mode 100644 subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ce2effb0..f91b4028 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,14 +19,10 @@ jobs: matrix: os: - ubuntu-latest -# - macos-13 + - windows-latest + - macos-latest runs-on: ${{ matrix.os }} steps: -# - name: Setup Docker on MacOS -# uses: douglascamata/setup-docker-macos-action@v1-alpha -# if: ${{ matrix.os == 'macos-13' }} - - name: Test Docker - run: docker run hello-world - name: Checkout code uses: actions/checkout@v6 - name: Set up JDK @@ -43,8 +39,10 @@ jobs: cache: 'npm' cache-dependency-path: 'subprojects/semantifyr-vscode/package-lock.json' - name: Gradle build + shell: bash run: ./gradlew build - name: Bundle Extension + shell: bash run: ./gradlew bundleExtension - name: Upload Artifacts if: ${{ matrix.os == 'ubuntu-latest' }} diff --git a/.github/workflows/verification.yml b/.github/workflows/verification.yml index 8a4f6e6d..f285057d 100644 --- a/.github/workflows/verification.yml +++ b/.github/workflows/verification.yml @@ -19,14 +19,10 @@ jobs: matrix: os: - ubuntu-latest - # - macos-13 + - windows-latest + - macos-latest runs-on: ${{ matrix.os }} steps: - # - name: Setup Docker on MacOS - # uses: douglascamata/setup-docker-macos-action@v1-alpha - # if: ${{ matrix.os == 'macos-13' }} - - name: Test Docker - run: docker run hello-world - name: Checkout code uses: actions/checkout@v6 - name: Set up JDK @@ -37,4 +33,5 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v5 - name: Run verification tests + shell: bash run: ./gradlew allTests --continue diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts index 44a1e125..0e4c376b 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts @@ -128,3 +128,15 @@ tasks { inputs.files(testVerificationCases.get().outputs) } } + +val thetaCliDir = project(":theta-wrapper").layout.buildDirectory.dir("theta-xsts-cli") + +listOf("testVerificationCases", "testSlowVerificationCases").forEach { taskName -> + tasks.named(taskName) { + dependsOn(":theta-wrapper:prepareThetaXstsCli") + + val thetaCliPath = thetaCliDir.get().asFile.absolutePath + val existingPath = environment["PATH"] ?: System.getenv("PATH") ?: "" + environment("PATH", "$thetaCliPath${File.pathSeparator}$existingPath") + } +} diff --git a/gradle.properties b/gradle.properties index aaae39b2..20e8c084 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ org.gradle.jvmargs=-Xmx2048M org.gradle.cache=true org.gradle.configuration-cache=true org.gradle.parallel=true -thetaVersion=6.5.2 +thetaXstsCliVersion=6.27.14 diff --git a/subprojects/backends/theta/theta-wrapper/build.gradle.kts b/subprojects/backends/theta/theta-wrapper/build.gradle.kts index 831c2ba5..67ae24fa 100644 --- a/subprojects/backends/theta/theta-wrapper/build.gradle.kts +++ b/subprojects/backends/theta/theta-wrapper/build.gradle.kts @@ -9,8 +9,51 @@ plugins { alias(libs.plugins.kotlin.jvm) } +val thetaXstsCliVersion: String by project +val thetaCliOutputDir = project.layout.buildDirectory.dir("theta-xsts-cli") + +val currentOs = when { + System.getProperty("os.name").lowercase().contains("win") -> "windows" + System.getProperty("os.name").lowercase().contains("mac") -> "osx" + else -> "linux" +} +val currentArch = when (System.getProperty("os.arch")) { + "aarch64" -> "arm64" + else -> "x64" +} +val nativeExt = when (currentOs) { + "windows" -> "dll" + "osx" -> "dylib" + else -> "so" +} + repositories { mavenCentral() + exclusiveContent { + forRepository { + ivy { + name = "Theta GitHub Releases" + url = uri("https://github.com/ftsrg/theta/releases/download/") + patternLayout { + artifact("v[revision]/[artifact].[ext]") + } + metadataSources { artifact() } + } + } + filter { includeGroup("hu.bme.mit.ftsrg.theta") } + } +} + +val thetaCliJarClasspath by configurations.creating { + isTransitive = false + isCanBeConsumed = false + isCanBeResolved = true +} + +val thetaNativeLibs by configurations.creating { + isTransitive = false + isCanBeConsumed = false + isCanBeResolved = true } dependencies { @@ -20,4 +63,54 @@ dependencies { implementation(libs.kotlinx.coroutines.core) implementation(libs.docker.java.core) implementation(libs.docker.java.transport) + + thetaCliJarClasspath("hu.bme.mit.ftsrg.theta:theta-xsts-cli:${thetaXstsCliVersion}@jar") + + // Z3 — available on all platforms and architectures + thetaNativeLibs("org.sosy-lab:javasmt-solver-z3:4.14.0:libz3-$currentArch@$nativeExt") + thetaNativeLibs("org.sosy-lab:javasmt-solver-z3:4.14.0:libz3java-$currentArch@$nativeExt") + + when (currentOs) { + "linux" if currentArch == "x64" -> { + thetaNativeLibs("org.sosy-lab:javasmt-solver-mathsat5:5.6.11-sosy1:libmathsat5j-x64@so") + thetaNativeLibs("org.sosy-lab:javasmt-solver-cvc5:1.2.1-g8594a8e4dc:libcvc5jni-x64@so") + thetaNativeLibs("org.sosy-lab:javasmt-solver-bitwuzla:0.7.0-13.1-g595512ae:libbitwuzlaj-x64@so") + thetaNativeLibs("org.sosy-lab:javasmt-solver-opensmt:2.9.0-gef441e1c:libopensmtj-x64@so") +// thetaNativeLibs("org.sosy-lab:javasmt-solver-cvc4:1.8-prerelease-2020-06-24-g7825d8f28:libcvc4-x64@so") +// thetaNativeLibs("org.sosy-lab:javasmt-solver-cvc4:1.8-prerelease-2020-06-24-g7825d8f28:libcvc4jni-x64@so") +// thetaNativeLibs("org.sosy-lab:javasmt-solver-cvc4:1.8-prerelease-2020-06-24-g7825d8f28:libcvc4parser-x64@so") + } + "windows" if currentArch == "x64" -> { + thetaNativeLibs("org.sosy-lab:javasmt-solver-mathsat5:5.6.11-sosy1:mathsat5j-x64@dll") + thetaNativeLibs("org.sosy-lab:javasmt-solver-mathsat5:5.6.11-sosy1:mathsat-x64@dll") + thetaNativeLibs("org.sosy-lab:javasmt-solver-mathsat5:5.6.11-sosy1:mpir-x64@dll") + thetaNativeLibs("org.sosy-lab:javasmt-solver-cvc5:1.2.1-g8594a8e4dc:libcvc5jni-x64@dll") + thetaNativeLibs("org.sosy-lab:javasmt-solver-bitwuzla:0.7.0-13.1-g595512ae:libbitwuzlaj-x64@dll") + } + } +} + +val syncThetaJar by tasks.registering(Sync::class) { + from(thetaCliJarClasspath) + into(thetaCliOutputDir.get().dir("jars")) + rename { "theta-xsts-cli.jar" } +} + +val syncThetaLibs by tasks.registering(Sync::class) { + from(thetaNativeLibs) + into(thetaCliOutputDir.get().dir("lib")) +} + +val syncThetaScripts by tasks.registering(Sync::class) { + from(project.layout.projectDirectory.file("scripts")) + into(thetaCliOutputDir.get()) + preserve { + include("lib", "jars") + } +} + +val prepareThetaXstsCli by tasks.registering { + dependsOn(syncThetaJar) + dependsOn(syncThetaLibs) + dependsOn(syncThetaScripts) } diff --git a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli new file mode 100755 index 00000000..b88eb8fb --- /dev/null +++ b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli @@ -0,0 +1,8 @@ +#!/bin/bash +set -e +SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if [ "$1" = "--version" ]; then + LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss512M -Xmx4G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" CEGAR --version + exit +fi +LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss512M -Xmx4G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" diff --git a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd new file mode 100644 index 00000000..4c82f807 --- /dev/null +++ b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd @@ -0,0 +1,10 @@ +@echo off +setlocal +set SCRIPTDIR=%~dp0 +set PATH=%SCRIPTDIR%lib;%PATH% +set VERIFIER_NAME=Theta +if "%1"=="--version" ( + java -Xss512M -Xmx4G "-Djava.library.path=%SCRIPTDIR%lib" -jar "%SCRIPTDIR%jars\theta-xsts-cli.jar" CEGAR --version + exit /b %ERRORLEVEL% +) +java -Xss512M -Xmx4G "-Djava.library.path=%SCRIPTDIR%lib" -jar "%SCRIPTDIR%jars\theta-xsts-cli.jar" %* diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ShellBasedThetaXstsExecutor.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ShellBasedThetaXstsExecutor.kt index 3d7a2957..e92de78d 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ShellBasedThetaXstsExecutor.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ShellBasedThetaXstsExecutor.kt @@ -20,11 +20,14 @@ import java.io.OutputStream class ShellBasedThetaXstsExecutor : ThetaXstsExecutor() { - override fun check(): Boolean { - val process = ProcessBuilder("theta-xsts-cli", "--version").start() - val exitCode = process.waitFor() + private val isWindows = System.getProperty("os.name").lowercase().contains("windows") - return exitCode == 0 + override fun check(): Boolean { + return try { + thetaProcessBuilder("--version").start().waitFor() == 0 + } catch (e: Exception) { + false + } } fun CoroutineScope.startReaderJob(inputStream: InputStream, outputStream: OutputStream) = launch(Dispatchers.IO) { @@ -67,13 +70,32 @@ class ShellBasedThetaXstsExecutor : ThetaXstsExecutor() { } private fun createProcessBuilder(thetaExecutionSpecification: ThetaExecutionSpecification): ProcessBuilder { - return ProcessBuilder( - "theta-xsts-cli", - *thetaExecutionSpecification.command.toTypedArray() - ) + return thetaProcessBuilder(thetaExecutionSpecification.command) .directory(thetaExecutionSpecification.workingDirectory) + } + + private fun thetaProcessBuilder(vararg args: String): ProcessBuilder { + val args = thetaCmd(args.toList()) + + return ProcessBuilder(args) + .redirectOutput(ProcessBuilder.Redirect.PIPE) + .redirectError(ProcessBuilder.Redirect.PIPE) + } + + private fun thetaProcessBuilder(args: List): ProcessBuilder { + val args = thetaCmd(args) + + return ProcessBuilder(args) .redirectOutput(ProcessBuilder.Redirect.PIPE) .redirectError(ProcessBuilder.Redirect.PIPE) } + private fun thetaCmd(args: List): List { + return if (isWindows) { + listOf("cmd", "/c", "theta-xsts-cli") + args + } else { + listOf("theta-xsts-cli") + args + } + } + } diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt index 8e39949e..f052ff04 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt @@ -29,9 +29,9 @@ class ThetaXstsExecutorProvider { } private fun resolveExecutor(): ThetaXstsExecutor { - if (dockerBasedThetaXstsExecutor.check()) { - return dockerBasedThetaXstsExecutor - } +// if (dockerBasedThetaXstsExecutor.check()) { +// return dockerBasedThetaXstsExecutor +// } if (shellBasedThetaXstsExecutor.check()) { return shellBasedThetaXstsExecutor diff --git a/subprojects/semantics/build.gradle.kts b/subprojects/semantics/build.gradle.kts index 974d4de3..f7d2cb5f 100644 --- a/subprojects/semantics/build.gradle.kts +++ b/subprojects/semantics/build.gradle.kts @@ -10,14 +10,6 @@ plugins { kotlin("plugin.serialization") } -tasks.withType(Test::class.java) { - inputs.dir("TestModels") - - if (environment["thetaVersion"] == null) { - environment("thetaVersion", findProperty("thetaVersion")!!) - } -} - repositories { mavenCentral() maven("https://repo.eclipse.org/content/groups/viatra/") From 6f19a1f661f098b8f02c7fd675736b2355fbd947 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 20:03:27 +0100 Subject: [PATCH 028/115] Fixed executor check crashing without Docker --- .../theta/theta-wrapper/build.gradle.kts | 69 ++++++++++++------- .../execution/DockerBasedThetaXstsExecutor.kt | 44 ++++++------ .../execution/ThetaXstsExecutorProvider.kt | 6 +- 3 files changed, 73 insertions(+), 46 deletions(-) diff --git a/subprojects/backends/theta/theta-wrapper/build.gradle.kts b/subprojects/backends/theta/theta-wrapper/build.gradle.kts index 67ae24fa..1e2a3763 100644 --- a/subprojects/backends/theta/theta-wrapper/build.gradle.kts +++ b/subprojects/backends/theta/theta-wrapper/build.gradle.kts @@ -10,7 +10,6 @@ plugins { } val thetaXstsCliVersion: String by project -val thetaCliOutputDir = project.layout.buildDirectory.dir("theta-xsts-cli") val currentOs = when { System.getProperty("os.name").lowercase().contains("win") -> "windows" @@ -42,6 +41,19 @@ repositories { } filter { includeGroup("hu.bme.mit.ftsrg.theta") } } + exclusiveContent { + forRepository { + ivy { + name = "Theta GitHub Raw" + url = uri("https://raw.githubusercontent.com/ftsrg/theta/") + patternLayout { + artifact("v[revision]/lib/[artifact].[ext]") + } + metadataSources { artifact() } + } + } + filter { includeGroup("hu.bme.mit.ftsrg.theta.lib") } + } } val thetaCliJarClasspath by configurations.creating { @@ -56,6 +68,12 @@ val thetaNativeLibs by configurations.creating { isCanBeResolved = true } +val thetaZ3LegacyLibs by configurations.creating { + isTransitive = false + isCanBeConsumed = false + isCanBeResolved = true +} + dependencies { api(project(":cex.lang")) api(libs.guice) @@ -76,9 +94,6 @@ dependencies { thetaNativeLibs("org.sosy-lab:javasmt-solver-cvc5:1.2.1-g8594a8e4dc:libcvc5jni-x64@so") thetaNativeLibs("org.sosy-lab:javasmt-solver-bitwuzla:0.7.0-13.1-g595512ae:libbitwuzlaj-x64@so") thetaNativeLibs("org.sosy-lab:javasmt-solver-opensmt:2.9.0-gef441e1c:libopensmtj-x64@so") -// thetaNativeLibs("org.sosy-lab:javasmt-solver-cvc4:1.8-prerelease-2020-06-24-g7825d8f28:libcvc4-x64@so") -// thetaNativeLibs("org.sosy-lab:javasmt-solver-cvc4:1.8-prerelease-2020-06-24-g7825d8f28:libcvc4jni-x64@so") -// thetaNativeLibs("org.sosy-lab:javasmt-solver-cvc4:1.8-prerelease-2020-06-24-g7825d8f28:libcvc4parser-x64@so") } "windows" if currentArch == "x64" -> { thetaNativeLibs("org.sosy-lab:javasmt-solver-mathsat5:5.6.11-sosy1:mathsat5j-x64@dll") @@ -88,29 +103,37 @@ dependencies { thetaNativeLibs("org.sosy-lab:javasmt-solver-bitwuzla:0.7.0-13.1-g595512ae:libbitwuzlaj-x64@dll") } } -} -val syncThetaJar by tasks.registering(Sync::class) { - from(thetaCliJarClasspath) - into(thetaCliOutputDir.get().dir("jars")) - rename { "theta-xsts-cli.jar" } + // Z3 legacy — a custom Z3 4.5.0 fork with renamed library symbols, committed to the theta repo + thetaZ3LegacyLibs("hu.bme.mit.ftsrg.theta.lib:libz3legacy:${thetaXstsCliVersion}@$nativeExt") + thetaZ3LegacyLibs("hu.bme.mit.ftsrg.theta.lib:libz3javalegacy:${thetaXstsCliVersion}@$nativeExt") } -val syncThetaLibs by tasks.registering(Sync::class) { - from(thetaNativeLibs) - into(thetaCliOutputDir.get().dir("lib")) -} +val prepareThetaXstsCli by tasks.registering(Sync::class) { + from(thetaNativeLibs) { + into("lib") + val arch = currentArch + rename { filename -> + val ext = filename.substringAfterLast('.') + val base = filename.substringBeforeLast('.').substringBeforeLast("-$arch") + "${base.substringAfterLast('-')}.$ext" + } + } -val syncThetaScripts by tasks.registering(Sync::class) { - from(project.layout.projectDirectory.file("scripts")) - into(thetaCliOutputDir.get()) - preserve { - include("lib", "jars") + from(thetaZ3LegacyLibs) { + into("lib") + rename { filename -> + val ext = filename.substringAfterLast('.') + "${filename.substringBeforeLast('.').substringBeforeLast('-')}.$ext" + } } -} -val prepareThetaXstsCli by tasks.registering { - dependsOn(syncThetaJar) - dependsOn(syncThetaLibs) - dependsOn(syncThetaScripts) + from(thetaCliJarClasspath) { + into("jars") + rename { "theta-xsts-cli.jar" } + } + + from(project.layout.projectDirectory.file("scripts")) + + into(project.layout.buildDirectory.dir("theta-xsts-cli")) } diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt index 0e7f8c70..fdcf9f56 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt @@ -24,29 +24,33 @@ class DockerBasedThetaXstsExecutor : ThetaXstsExecutor() { private val imageName = "ftsrg/theta-xsts-cli" private val version = "6.27.17" - private val config = DefaultDockerClientConfig.createDefaultConfigBuilder().build() - private val httpClient = ApacheDockerHttpClient.Builder() - .dockerHost(config.dockerHost) - .sslConfig(config.sslConfig).build() - private val dockerClient = DockerClientImpl.getInstance(config, httpClient); + private val dockerClient by lazy { + try { + val config = DefaultDockerClientConfig.createDefaultConfigBuilder().build() + val httpClient = ApacheDockerHttpClient.Builder() + .dockerHost(config.dockerHost) + .sslConfig(config.sslConfig).build() + DockerClientImpl.getInstance(config, httpClient) + } catch (_: Exception) { + null + } + } override fun initialize() { val imageId = "$imageName:$version" try { - dockerClient.inspectImageCmd(imageId).exec() + dockerClient!!.inspectImageCmd(imageId).exec() } catch (e: NotFoundException) { - dockerClient.pullImageCmd(imageName).withTag(version).start().awaitCompletion() + dockerClient!!.pullImageCmd(imageName).withTag(version).start().awaitCompletion() } } override fun check(): Boolean { - try { - dockerClient.infoCmd().exec() - - return true - } catch (_: Exception) { - return false - } + return try { + dockerClient?.infoCmd()?.exec() != null + } catch (_: Exception) { + false + } } override suspend fun execute(thetaExecutionSpecification: ThetaExecutionSpecification) = coroutineScope { @@ -69,7 +73,7 @@ class DockerBasedThetaXstsExecutor : ThetaXstsExecutor() { val hostConfig = HostConfig.newHostConfig() .withBinds(Bind(thetaExecutionSpecification.workingDirectory.absolutePath, Volume("/host/working_directory"))) - val container = dockerClient.createContainerCmd("$imageName:$version") + val container = dockerClient!!.createContainerCmd("$imageName:$version") .withHostConfig(hostConfig) .withWorkingDir("/host/working_directory") .withCmd(thetaExecutionSpecification.command) @@ -80,18 +84,18 @@ class DockerBasedThetaXstsExecutor : ThetaXstsExecutor() { } private suspend fun runContainer(thetaExecutionSpecification: ThetaExecutionSpecification, container: CreateContainerResponse): WaitResponse { - dockerClient.startContainerCmd(container.id).exec() + dockerClient!!.startContainerCmd(container.id).exec() return withTimeout(thetaExecutionSpecification) { runAsync(Dispatchers.IO) { - dockerClient.waitContainerCmd(container.id).exec(it) + dockerClient!!.waitContainerCmd(container.id).exec(it) } } } private fun stopContainer(container: CreateContainerResponse) { try { - dockerClient.stopContainerCmd(container.id).exec() + dockerClient!!.stopContainerCmd(container.id).exec() } catch (_: Exception) { // swallow exceptions } @@ -99,7 +103,7 @@ class DockerBasedThetaXstsExecutor : ThetaXstsExecutor() { private suspend fun saveContainerLogs(thetaExecutionSpecification: ThetaExecutionSpecification, container: CreateContainerResponse) = withContext(Dispatchers.IO) { try { - dockerClient.logContainerCmd(container.id) + dockerClient!!.logContainerCmd(container.id) .withStdOut(true) .withStdErr(true) .withTailAll() @@ -112,7 +116,7 @@ class DockerBasedThetaXstsExecutor : ThetaXstsExecutor() { private fun destroyContainer(container: CreateContainerResponse) { try { - dockerClient.removeContainerCmd(container.id).withForce(true).exec() + dockerClient!!.removeContainerCmd(container.id).withForce(true).exec() } catch (_: Exception) { // swallow exceptions } diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt index f052ff04..8e39949e 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt @@ -29,9 +29,9 @@ class ThetaXstsExecutorProvider { } private fun resolveExecutor(): ThetaXstsExecutor { -// if (dockerBasedThetaXstsExecutor.check()) { -// return dockerBasedThetaXstsExecutor -// } + if (dockerBasedThetaXstsExecutor.check()) { + return dockerBasedThetaXstsExecutor + } if (shellBasedThetaXstsExecutor.check()) { return shellBasedThetaXstsExecutor From fe774c2bc27e6cca9a31a40acd1c4b8c522b0554 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 18:26:58 +0100 Subject: [PATCH 029/115] Fixed Theta erroring when .err file has warnings --- .../xsts-verifier/src/main/kotlin/ThetaVerifier.kt | 3 +-- .../main/kotlin/execution/ThetaVerificationExecutor.kt | 10 +++++----- .../src/main/kotlin/verification/OxstsVerifier.kt | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index e99461a3..dc702e10 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -17,7 +17,6 @@ import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaUnsafeVe import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaVerificationResult import hu.bme.mit.semantifyr.backends.theta.verification.transformation.xsts.OxstsTransformer import hu.bme.mit.semantifyr.backends.theta.wrapper.utils.CexReader -import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltinAnnotationHandler import hu.bme.mit.semantifyr.oxsts.model.oxsts.AG import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.EF @@ -93,7 +92,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { val result = verifyXsts(progressContext, xstsModel, timeout, timeUnit) if (result is ThetaErrorVerificationResult) { - return VerificationCaseRunResult(VerificationResult.Failed, result.failureMessage) + return VerificationCaseRunResult(VerificationResult.Errored, result.failureMessage) } if (result.hasWitness) { diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt index 9ad59401..4dbf3961 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt @@ -8,6 +8,7 @@ package hu.bme.mit.semantifyr.backends.theta.verification.execution import com.google.inject.Inject import hu.bme.mit.semantifyr.backends.theta.verification.utils.ensureExistsOutputStream +import hu.bme.mit.semantifyr.backends.theta.wrapper.execution.ThetaExecutionResult import hu.bme.mit.semantifyr.backends.theta.wrapper.execution.ThetaExecutionSpecification import hu.bme.mit.semantifyr.backends.theta.wrapper.execution.ThetaXstsExecutorProvider import hu.bme.mit.semantifyr.semantics.verification.VerificationDispatcher @@ -46,9 +47,8 @@ class ThetaErrorVerificationResult(runtimeDetails: ThetaVerificationSpecificatio val failureMessage = "Theta execution failed, see: ${runtimeDetails.workingDirectory}/${runtimeDetails.errPath}" } -fun ThetaVerificationSpecification.toVerificationResult(): ThetaVerificationResult { - val errorFile = File(workingDirectory, errPath) - if (errorFile.exists() && errorFile.useLines { it.any { it.isNotEmpty() } }) { +fun ThetaVerificationSpecification.toVerificationResult(executionResult: ThetaExecutionResult): ThetaVerificationResult { + if (executionResult.exitCode != 0) { return ThetaErrorVerificationResult(this) } @@ -108,11 +108,11 @@ class ThetaVerificationExecutor { writer.appendLine() writer.flush() - verificationDispatcher.execute { + val result = verificationDispatcher.execute { thetaExecutor.execute(thetaExecutionSpecification) } - return thetaVerificationSpecification.toVerificationResult() + return thetaVerificationSpecification.toVerificationResult(result) } } diff --git a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt index 3111df77..86295b13 100644 --- a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt +++ b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt @@ -24,7 +24,7 @@ data class VerificationCaseRunResult( ) enum class VerificationResult { - Passed, Failed + Passed, Failed, Errored } interface OxstsVerifier { From 1f0d11b6a77877b5cffee8c0e41f0dc0668e5aa5 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 20:04:02 +0100 Subject: [PATCH 030/115] Slightly better error handling --- .../theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index dc702e10..5a4c71df 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -92,7 +92,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { val result = verifyXsts(progressContext, xstsModel, timeout, timeUnit) if (result is ThetaErrorVerificationResult) { - return VerificationCaseRunResult(VerificationResult.Errored, result.failureMessage) + error(result.failureMessage) } if (result.hasWitness) { From 85b8f945c84431d92c1b7d6dc7fa28129a01557c Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 20:14:12 +0100 Subject: [PATCH 031/115] Rename verification build to run-verification --- .github/workflows/verification.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/verification.yml b/.github/workflows/verification.yml index f285057d..50468cdc 100644 --- a/.github/workflows/verification.yml +++ b/.github/workflows/verification.yml @@ -11,7 +11,7 @@ on: env: CI: true jobs: - build: + run-verification: permissions: contents: read strategy: From 8af1df8dd27a2ee15464b97cac65d0bb3259520b Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 20:26:28 +0100 Subject: [PATCH 032/115] Fixed xtext generation on Windows --- .../kotlin/hu/bme/mit/semantifyr/gradle/xtext.gradle.kts | 6 +++--- subprojects/backends/theta/cex.lang/build.gradle.kts | 4 ++-- subprojects/backends/theta/xsts.lang/build.gradle.kts | 4 ++-- subprojects/frontends/gamma/gamma.lang/build.gradle.kts | 4 ++-- subprojects/oxsts.lang/build.gradle.kts | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/xtext.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/xtext.gradle.kts index 65e05178..d5e719db 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/xtext.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/xtext.gradle.kts @@ -66,7 +66,7 @@ val generateXtextLanguage by tasks.registering(JavaExec::class) { outputs.dir(extension.testFixtureGenPath) outputs.dir(extension.ideOutput) - args(extension.mweFile.asFile.get(), "-p", "rootPath=/$projectDir/..") + args(extension.mweFile.get(), "-p", "rootPath=/$projectDir/..") } artifacts { @@ -99,7 +99,7 @@ tasks { interface XtextPluginConfiguration { val genPath: DirectoryProperty val testFixtureGenPath: DirectoryProperty - val mweFile: RegularFileProperty - val xtextFile: RegularFileProperty + val mweFile: Property + val xtextFile: Property val ideOutput: DirectoryProperty } diff --git a/subprojects/backends/theta/cex.lang/build.gradle.kts b/subprojects/backends/theta/cex.lang/build.gradle.kts index 2faa38cb..dd410a2c 100644 --- a/subprojects/backends/theta/cex.lang/build.gradle.kts +++ b/subprojects/backends/theta/cex.lang/build.gradle.kts @@ -9,6 +9,6 @@ plugins { } xtext { - mweFile = layout.projectDirectory.file("src/main/java/hu/bme/mit/semantifyr/cex/lang/GenerateCex.mwe2") - xtextFile = layout.projectDirectory.file("src/main/java/hu/bme/mit/semantifyr/cex/lang/Cex.xtext") + mweFile = "src/main/java/hu/bme/mit/semantifyr/cex/lang/GenerateCex.mwe2" + xtextFile = "src/main/java/hu/bme/mit/semantifyr/cex/lang/Cex.xtext" } diff --git a/subprojects/backends/theta/xsts.lang/build.gradle.kts b/subprojects/backends/theta/xsts.lang/build.gradle.kts index 5a6ffb2b..ab7f7a28 100644 --- a/subprojects/backends/theta/xsts.lang/build.gradle.kts +++ b/subprojects/backends/theta/xsts.lang/build.gradle.kts @@ -9,6 +9,6 @@ plugins { } xtext { - mweFile = layout.projectDirectory.file("src/main/java/hu/bme/mit/semantifyr/xsts/lang/GenerateXsts.mwe2") - xtextFile = layout.projectDirectory.file("src/main/java/hu/bme/mit/semantifyr/xsts/lang/Xsts.xtext") + mweFile = "src/main/java/hu/bme/mit/semantifyr/xsts/lang/GenerateXsts.mwe2" + xtextFile = "src/main/java/hu/bme/mit/semantifyr/xsts/lang/Xsts.xtext" } diff --git a/subprojects/frontends/gamma/gamma.lang/build.gradle.kts b/subprojects/frontends/gamma/gamma.lang/build.gradle.kts index abffab5c..9744e873 100644 --- a/subprojects/frontends/gamma/gamma.lang/build.gradle.kts +++ b/subprojects/frontends/gamma/gamma.lang/build.gradle.kts @@ -9,6 +9,6 @@ plugins { } xtext { - mweFile = layout.projectDirectory.file("src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/GenerateGamma.mwe2") - xtextFile = layout.projectDirectory.file("src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/Gamma.xtext") + mweFile = "src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/GenerateGamma.mwe2" + xtextFile = "src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/Gamma.xtext" } diff --git a/subprojects/oxsts.lang/build.gradle.kts b/subprojects/oxsts.lang/build.gradle.kts index e5bac7cd..f16667e0 100644 --- a/subprojects/oxsts.lang/build.gradle.kts +++ b/subprojects/oxsts.lang/build.gradle.kts @@ -15,8 +15,8 @@ dependencies { } xtext { - mweFile = layout.projectDirectory.file("src/main/java/hu/bme/mit/semantifyr/oxsts/lang/GenerateOxsts.mwe2") - xtextFile = layout.projectDirectory.file("src/main/java/hu/bme/mit/semantifyr/oxsts/lang/Oxsts.xtext") + mweFile = "src/main/java/hu/bme/mit/semantifyr/oxsts/lang/GenerateOxsts.mwe2" + xtextFile = "src/main/java/hu/bme/mit/semantifyr/oxsts/lang/Oxsts.xtext" } val syncModel by tasks.registering(Sync::class) { From 3f51ec4580bd211752b4f54e806921512a805406 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 21:19:32 +0100 Subject: [PATCH 033/115] Docker is only valid if we can run the image --- .../src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt index fdcf9f56..6b4b75fc 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt @@ -47,7 +47,9 @@ class DockerBasedThetaXstsExecutor : ThetaXstsExecutor() { override fun check(): Boolean { return try { - dockerClient?.infoCmd()?.exec() != null + // try to initialize, if success we have docker :) + initialize() + true } catch (_: Exception) { false } From 4f1732e1bbc5f0b3c7c8e6e061285c25aaf23c5a Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 21:27:08 +0100 Subject: [PATCH 034/115] Removed the incorrect startScript --- .../mit/semantifyr/gradle/conventions/application.gradle.kts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/application.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/application.gradle.kts index 857f6463..104b5cf5 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/application.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/application.gradle.kts @@ -11,10 +11,6 @@ plugins { application } -tasks.startScripts { - classpath = files("%APP_HOME%/lib/*") -} - val distributionOutput by configurations.creating { isCanBeConsumed = true isCanBeResolved = false From a9e0785aade441267b01ed13c9e983d48b675eb9 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 21:54:42 +0100 Subject: [PATCH 035/115] Inter-project dependency is correctly configured now --- .../gradle/conventions/jvm.gradle.kts | 83 +------------- .../gradle/conventions/theta.gradle.kts | 108 ++++++++++++++++++ .../theta/theta-wrapper/build.gradle.kts | 11 ++ .../theta/xsts-verifier/build.gradle.kts | 1 + .../gamma/gamma-semantics/build.gradle.kts | 3 +- .../sysmlv2-semantics/build.gradle.kts | 3 +- .../semantifyr-vscode-server/build.gradle.kts | 16 +++ 7 files changed, 141 insertions(+), 84 deletions(-) create mode 100644 buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts index 0e4c376b..b4a89ba5 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts @@ -38,16 +38,6 @@ java.toolchain { languageVersion = JavaLanguageVersion.of(25) } -/* - * Simple Build service that acts as a lock or throttling device preventing parallel execution - */ -abstract class VerificationTestService : BuildService -val verificationTestServiceName = "verificationTestService" -val verificationTestServiceProvider = gradle.sharedServices.registerIfAbsent(verificationTestServiceName, VerificationTestService::class) { - // only allow at most 1 verification task per Gradle build - maxParallelUsages.set(1) -} - tasks { // TODO: refactor tests to use test suites test { @@ -64,79 +54,8 @@ tasks { finalizedBy(tasks.jacocoTestReport) } - val testVerificationCases by tasks.registering(Test::class) { - group = "verification" - - useJUnitPlatform { - includeTags("verification") - excludeTags("slow") - } - - testClassesDirs = sourceSets.test.get().output.classesDirs - classpath = sourceSets.test.get().runtimeClasspath - - usesService(verificationTestServiceProvider) - - minHeapSize = "512m" - maxHeapSize = "4G" - testLogging.showStandardStreams = true - testLogging.exceptionFormat = TestExceptionFormat.FULL - - maxParallelForks = 1 - - shouldRunAfter(test) - finalizedBy(jacocoTestReport) - } - - val testSlowVerificationCases by tasks.registering(Test::class) { - group = "verification" - - useJUnitPlatform { -// includeTags("verification") - includeTags("slow") - } - - testClassesDirs = sourceSets.test.get().output.classesDirs - classpath = sourceSets.test.get().runtimeClasspath - - usesService(verificationTestServiceProvider) - - minHeapSize = "512m" - maxHeapSize = "4G" - testLogging.showStandardStreams = true - testLogging.exceptionFormat = TestExceptionFormat.FULL - - maxParallelForks = 1 - } - - val allTests by tasks.registering(DefaultTask::class) { - group = "verification" - - dependsOn(test) - dependsOn(testVerificationCases) - dependsOn(testSlowVerificationCases) - } - jacocoTestReport { inputs.files(test.get().outputs) - inputs.files(testVerificationCases.get().outputs) - - executionData(test.get(), testVerificationCases.get()) - } - - check { - inputs.files(testVerificationCases.get().outputs) - } -} - -val thetaCliDir = project(":theta-wrapper").layout.buildDirectory.dir("theta-xsts-cli") - -listOf("testVerificationCases", "testSlowVerificationCases").forEach { taskName -> - tasks.named(taskName) { - dependsOn(":theta-wrapper:prepareThetaXstsCli") - - val thetaCliPath = thetaCliDir.get().asFile.absolutePath - val existingPath = environment["PATH"] ?: System.getenv("PATH") ?: "" - environment("PATH", "$thetaCliPath${File.pathSeparator}$existingPath") + executionData(test.get()) } } diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts new file mode 100644 index 00000000..d1165efd --- /dev/null +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.gradle.conventions + +import org.gradle.api.tasks.testing.logging.TestExceptionFormat + +plugins { + id("hu.bme.mit.semantifyr.gradle.conventions.jvm") +} + +val thetaClasspath by configurations.creating { + isCanBeConsumed = false + isCanBeResolved = true +} + +dependencies { + thetaClasspath(project(":theta-wrapper", configuration = "thetaOutput")) +} + +/* + * Simple Build service that acts as a lock or throttling device preventing parallel execution + */ +abstract class VerificationTestService : BuildService +val verificationTestServiceName = "verificationTestService" +val verificationTestServiceProvider = gradle.sharedServices.registerIfAbsent(verificationTestServiceName, VerificationTestService::class) { + // only allow at most 1 verification task per Gradle build + maxParallelUsages.set(1) +} + +tasks { + val testVerificationCases by tasks.registering(Test::class) { + inputs.files(thetaClasspath) + + group = "verification" + + useJUnitPlatform { + includeTags("verification") + excludeTags("slow") + } + + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + usesService(verificationTestServiceProvider) + + minHeapSize = "512m" + maxHeapSize = "4G" + testLogging.showStandardStreams = true + testLogging.exceptionFormat = TestExceptionFormat.FULL + + maxParallelForks = 1 + + val thetaCliPath = project(":theta-wrapper").layout.buildDirectory.dir("theta-xsts-cli").get().asFile.absolutePath + val existingPath = environment["PATH"] ?: System.getenv("PATH") ?: "" + environment("PATH", "$thetaCliPath${File.pathSeparator}$existingPath") + + shouldRunAfter(test) + finalizedBy(jacocoTestReport) + } + + val testSlowVerificationCases by tasks.registering(Test::class) { + inputs.files(thetaClasspath) + + group = "verification" + + useJUnitPlatform { +// includeTags("verification") + includeTags("slow") + } + + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + usesService(verificationTestServiceProvider) + + minHeapSize = "512m" + maxHeapSize = "4G" + testLogging.showStandardStreams = true + testLogging.exceptionFormat = TestExceptionFormat.FULL + + val thetaCliPath = project(":theta-wrapper").layout.buildDirectory.dir("theta-xsts-cli").get().asFile.absolutePath + val existingPath = environment["PATH"] ?: System.getenv("PATH") ?: "" + environment("PATH", "$thetaCliPath${File.pathSeparator}$existingPath") + + maxParallelForks = 1 + } + + val allTests by tasks.registering(DefaultTask::class) { + group = "verification" + + dependsOn(test) + dependsOn(testVerificationCases) + dependsOn(testSlowVerificationCases) + } + + jacocoTestReport { + inputs.files(testVerificationCases.get().outputs) + executionData(testVerificationCases.get()) + } + + check { + inputs.files(testVerificationCases.get().outputs) + } +} diff --git a/subprojects/backends/theta/theta-wrapper/build.gradle.kts b/subprojects/backends/theta/theta-wrapper/build.gradle.kts index 1e2a3763..8481dcff 100644 --- a/subprojects/backends/theta/theta-wrapper/build.gradle.kts +++ b/subprojects/backends/theta/theta-wrapper/build.gradle.kts @@ -74,6 +74,11 @@ val thetaZ3LegacyLibs by configurations.creating { isCanBeResolved = true } +val thetaOutput by configurations.creating { + isCanBeConsumed = true + isCanBeResolved = false +} + dependencies { api(project(":cex.lang")) api(libs.guice) @@ -137,3 +142,9 @@ val prepareThetaXstsCli by tasks.registering(Sync::class) { into(project.layout.buildDirectory.dir("theta-xsts-cli")) } + +artifacts { + add(thetaOutput.name, layout.buildDirectory.dir("theta-xsts-cli")) { + builtBy(prepareThetaXstsCli) + } +} diff --git a/subprojects/backends/theta/xsts-verifier/build.gradle.kts b/subprojects/backends/theta/xsts-verifier/build.gradle.kts index 59568525..2f115ed1 100644 --- a/subprojects/backends/theta/xsts-verifier/build.gradle.kts +++ b/subprojects/backends/theta/xsts-verifier/build.gradle.kts @@ -6,6 +6,7 @@ plugins { id("hu.bme.mit.semantifyr.gradle.conventions.jvm") + id("hu.bme.mit.semantifyr.gradle.conventions.theta") alias(libs.plugins.kotlin.jvm) } diff --git a/subprojects/frontends/gamma/gamma-semantics/build.gradle.kts b/subprojects/frontends/gamma/gamma-semantics/build.gradle.kts index d644c9f1..852c44c1 100644 --- a/subprojects/frontends/gamma/gamma-semantics/build.gradle.kts +++ b/subprojects/frontends/gamma/gamma-semantics/build.gradle.kts @@ -6,7 +6,8 @@ plugins { id("hu.bme.mit.semantifyr.gradle.conventions.application") - alias(libs.plugins.kotlin.jvm) + id("hu.bme.mit.semantifyr.gradle.conventions.theta") + kotlin("jvm") } repositories { diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts index a6e643c0..c534c15d 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts @@ -6,7 +6,8 @@ plugins { id("hu.bme.mit.semantifyr.gradle.conventions.jvm") - alias(libs.plugins.kotlin.jvm) + id("hu.bme.mit.semantifyr.gradle.conventions.theta") + kotlin("jvm") } repositories { diff --git a/subprojects/semantifyr-vscode-server/build.gradle.kts b/subprojects/semantifyr-vscode-server/build.gradle.kts index 1120fab0..1729f98b 100644 --- a/subprojects/semantifyr-vscode-server/build.gradle.kts +++ b/subprojects/semantifyr-vscode-server/build.gradle.kts @@ -13,8 +13,15 @@ val distributionClasspath by configurations.creating { isCanBeResolved = true } +val thetaClasspath by configurations.creating { + isCanBeConsumed = false + isCanBeResolved = true +} + dependencies { distributionClasspath(project(":semantifyr-vscode", configuration = "distributionOutput")) + + thetaClasspath(project(":theta-wrapper", configuration = "thetaOutput")) } val cloneDistribution by tasks.registering(Copy::class) { @@ -27,6 +34,15 @@ val cloneDistribution by tasks.registering(Copy::class) { into("extensions") } +val cloneTheta by tasks.registering(Sync::class) { + inputs.files(thetaClasspath) + + from (thetaClasspath) + + into("theta-xsts-cli") +} + val prepareDockerBuild by tasks.registering() { inputs.files(cloneDistribution.get().outputs) + inputs.files(cloneTheta.get().outputs) } From e23af6d9e5e53ce73fd70fd233b99916771abed3 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 22:12:55 +0100 Subject: [PATCH 036/115] Run formatting --- .../sysmlv2/sysmlv2-semantics/models/crossroads.oxsts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts index 4cf53d35..d48d3ae8 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts @@ -50,12 +50,12 @@ class CentralController : Part { contains UnnamedTransitionUsage0: Transition subsets transitions { redefine refers from: StateNode = start redefine refers to: StateNode = Operating -} + } contains Operating: State subsets states { contains UnnamedTransitionUsage1: Transition subsets transitions { redefine refers from: StateNode = start redefine refers to: StateNode = BothYellow -} + } contains BothYellow: State subsets states contains UnnamedTransitionUsage2: Transition subsets transitions { redefine refers from: StateNode = BothYellow @@ -200,12 +200,12 @@ class TrafficLightController : Part { contains UnnamedTransitionUsage10: Transition subsets transitions { redefine refers from: StateNode = start redefine refers to: StateNode = Normal -} + } contains Normal: State subsets states { contains UnnamedTransitionUsage11: Transition subsets transitions { redefine refers from: StateNode = start redefine refers to: StateNode = Yellow -} + } contains Yellow: State subsets states { redefine contains entryAction: SendAction { redefine refers viaPort: Port = lightControl @@ -269,7 +269,7 @@ class TrafficLightController : Part { contains UnnamedTransitionUsage17: Transition subsets transitions { redefine refers from: StateNode = start redefine refers to: StateNode = Yellow -} + } contains Yellow: State subsets states { redefine contains entryAction: SendAction { redefine refers viaPort: Port = lightControl From 0e720090e2e6dc6c14727d1badc2ef2643da0fd1 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 22:13:13 +0100 Subject: [PATCH 037/115] Simplified inline-if calls --- .../sysmlv2-semantics/Library/States.oxsts | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/States.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/States.oxsts index 298216f0..b3e89bd5 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/States.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/States.oxsts @@ -121,11 +121,13 @@ class State : AbstractState { } redefine tran enterRecursive(commonState: StateNode) { - inline if (commonState != parent) { - inline parent?.enterRecursive(commonState) - } + inline if (parent != nothing) { + inline if (commonState != parent) { + inline parent.enterRecursive(commonState) + } - inline activate() + inline activate() + } } redefine tran enter(commonState: StateNode) { inline enterRecursive(commonState) @@ -133,10 +135,12 @@ class State : AbstractState { } redefine tran exitRecursive(commonState: StateNode) { - inline deactivate() + inline if (parent != nothing) { + inline deactivate() - inline if (commonState != parent) { - inline parent?.exitRecursive(commonState) + inline if (commonState != parent) { + inline parent?.exitRecursive(commonState) + } } } redefine tran exit(commonState: StateNode) { @@ -145,24 +149,20 @@ class State : AbstractState { } tran activate() { - inline if (parent != nothing) { - inline parent.setActiveState(self) - - inline for (transition in outgoingTransitions) { - inline transition.initialize() - } + inline parent.setActiveState(self) - inline entryAction.main() + inline for (transition in outgoingTransitions) { + inline transition.initialize() } + + inline entryAction.main() } tran deactivate() { - inline if (parent != nothing) { - if (parent.getActiveState() == self) { - inline exitAction.main() + if (parent.getActiveState() == self) { + inline exitAction.main() - inline parent.setActiveState(nothing) - } + inline parent.setActiveState(nothing) } } From 3592642ffaf1ea6dad4498e839de69d7474b1d6e Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 22:59:20 +0100 Subject: [PATCH 038/115] Added domain-based instance collection --- .../lang/semantics/InheritanceHandler.java | 28 +++++++++++-- .../kotlin/expression/InstanceCollector.kt | 40 +++++++++++++++++++ .../instantiation/OxstsInflator.kt | 12 ++++++ 3 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 subprojects/semantics/src/main/kotlin/expression/InstanceCollector.kt diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/InheritanceHandler.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/InheritanceHandler.java index f761f065..67cc68e1 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/InheritanceHandler.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/InheritanceHandler.java @@ -11,15 +11,17 @@ import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltinSymbolResolver; import hu.bme.mit.semantifyr.oxsts.lang.utils.OnResourceSetChangeEvictingCache; import hu.bme.mit.semantifyr.oxsts.model.oxsts.*; -import org.eclipse.xtext.util.IResourceScopeCache; import org.eclipse.xtext.util.Tuples; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; @Singleton public class InheritanceHandler { - private static final String CACHE_KEY = "hu.bme.mit.semantifyr.oxsts.lang.semantics.InheritanceHandler.CACHE_KEY"; + private static final String BASE_CACHE_KEY = "hu.bme.mit.semantifyr.oxsts.lang.semantics.InheritanceHandler"; + private static final String SUPER_CACHE_KEY = BASE_CACHE_KEY + ".SUPER_CACHE_KEY"; + private static final String TRANSITIVE_SUPER_CACHE_KEY = BASE_CACHE_KEY + ".TRANSITIVE_SUPER_CACHE_KEY"; @Inject private OnResourceSetChangeEvictingCache cache; @@ -34,7 +36,11 @@ public class InheritanceHandler { protected BuiltinSymbolResolver builtinSymbolResolver; public List getSuperDomains(DomainDeclaration declaration) { - return cache.get(Tuples.create(CACHE_KEY, declaration), declaration.eResource(), () -> computeSuperDomains(declaration)); + return cache.get(Tuples.create(SUPER_CACHE_KEY, declaration), declaration.eResource(), () -> computeSuperDomains(declaration)); + } + + public List getTransitiveSuperDomains(DomainDeclaration declaration) { + return cache.get(Tuples.create(TRANSITIVE_SUPER_CACHE_KEY, declaration), declaration.eResource(), () -> computeTransitiveSuperDomains(declaration)); } protected List computeSuperDomains(DomainDeclaration domainDeclaration) { @@ -83,4 +89,20 @@ protected List computeSuperDomains(FeatureDeclarati return superDomains; } + protected List computeTransitiveSuperDomains(DomainDeclaration domainDeclaration) { + var foundSuperDomains = new HashSet(); + + var superDomains = getSuperDomains(domainDeclaration); + + for (var superDomain : superDomains) { + if (foundSuperDomains.add(superDomain)) { + // cached transitive super domains + var localTransitiveSuperDomains = getTransitiveSuperDomains(superDomain); + foundSuperDomains.addAll(localTransitiveSuperDomains); + } + } + + return foundSuperDomains.stream().toList(); + } + } diff --git a/subprojects/semantics/src/main/kotlin/expression/InstanceCollector.kt b/subprojects/semantics/src/main/kotlin/expression/InstanceCollector.kt new file mode 100644 index 00000000..b29a1579 --- /dev/null +++ b/subprojects/semantics/src/main/kotlin/expression/InstanceCollector.kt @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.semantics.expression + +import com.google.inject.Inject +import hu.bme.mit.semantifyr.oxsts.lang.semantics.InheritanceHandler +import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration +import hu.bme.mit.semantifyr.oxsts.model.oxsts.Instance +import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped +import hu.bme.mit.semantifyr.semantics.utils.treeSequence + +@CompilationScoped +class InstanceCollector { + + private val cache = mutableMapOf, Set>() + + // TODO: will be replaced by a query-based collector (Refinery) + + @Inject + private lateinit var inheritanceHandler: InheritanceHandler + + fun instancesOfType(instance: Instance, classDeclaration: ClassDeclaration): Set { + return cache.getOrPut(Pair(instance, classDeclaration)) { + collectInstancesOfType(instance, classDeclaration) + } + } + + private fun collectInstancesOfType(instance: Instance, classDeclaration: ClassDeclaration): Set { + return instance.treeSequence().filter { + inheritanceHandler.getTransitiveSuperDomains(it.domain).any { + it == classDeclaration + } + }.toSet() + } + +} diff --git a/subprojects/semantics/src/main/kotlin/transformation/instantiation/OxstsInflator.kt b/subprojects/semantics/src/main/kotlin/transformation/instantiation/OxstsInflator.kt index e14e8984..6b2b4edb 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/instantiation/OxstsInflator.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/instantiation/OxstsInflator.kt @@ -11,6 +11,7 @@ import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltinSymbolResolver import hu.bme.mit.semantifyr.oxsts.lang.semantics.MultiplicityRangeEvaluator import hu.bme.mit.semantifyr.oxsts.lang.semantics.typesystem.ExpressionTypeEvaluatorProvider import hu.bme.mit.semantifyr.oxsts.model.oxsts.ArithmeticUnaryOperator +import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.ElementReference import hu.bme.mit.semantifyr.oxsts.model.oxsts.Expression import hu.bme.mit.semantifyr.oxsts.model.oxsts.FeatureDeclaration @@ -24,6 +25,7 @@ import hu.bme.mit.semantifyr.oxsts.model.oxsts.ReferenceExpression import hu.bme.mit.semantifyr.oxsts.model.oxsts.UnaryOp import hu.bme.mit.semantifyr.oxsts.model.oxsts.VariableDeclaration import hu.bme.mit.semantifyr.semantics.expression.DeflatedExpressionEvaluationTransformer +import hu.bme.mit.semantifyr.semantics.expression.InstanceCollector import hu.bme.mit.semantifyr.semantics.expression.InstanceReferenceProvider import hu.bme.mit.semantifyr.semantics.expression.MetaStaticExpressionEvaluatorProvider import hu.bme.mit.semantifyr.semantics.expression.StaticExpressionEvaluatorProvider @@ -88,6 +90,9 @@ class OxstsInflator { @Inject private lateinit var expressionTypeEvaluatorProvider: ExpressionTypeEvaluatorProvider + @Inject + private lateinit var instanceCollector: InstanceCollector + private val variableInstanceDomain = mutableMapOf>() // private val domainInstanceDomain = mutableMapOf>() @@ -151,6 +156,13 @@ class OxstsInflator { variable.typeSpecification.domain = builtinAnything } + if (variable.typeSpecification.domain is ClassDeclaration) { + val classDeclaration = variable.typeSpecification.domain as ClassDeclaration + val instances = instanceCollector.instancesOfType(inlinedOxsts.rootInstance, classDeclaration) + variableInstanceDomain[variable] = instances + variable.typeSpecification.domain = builtinAnything + } + variable.name = "$instanceName$INSTANCE_NAME_SEPARATOR${variable.name}" variableHolders[variable] = instance From a0920038b8490c36f29acd7605b7777e1b064b13 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 22:59:29 +0100 Subject: [PATCH 039/115] Added todo comment --- .../transformation/serializer/CompilationStateManager.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/subprojects/semantics/src/main/kotlin/transformation/serializer/CompilationStateManager.kt b/subprojects/semantics/src/main/kotlin/transformation/serializer/CompilationStateManager.kt index 16521121..167c6470 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/serializer/CompilationStateManager.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/serializer/CompilationStateManager.kt @@ -17,6 +17,14 @@ import java.io.File @CompilationScoped class CompilationStateManager { + // TODO: implement structured artifact management: the full base path is the output artifacts + // Make it extendable. Clean on initialization, etc. The Compilation scope manager should create the initial artifact mangaer. And also, probably, it should be configurable in the verification engine builder, so the path where the base path will be located can be configured + // base path: + // - inlined -- inlined oxsts files + // - verification -- verification outputs + // - metrics -- metric data + // - bare files + private lateinit var basePath: File private lateinit var inlinedOxsts: InlinedOxsts From 7f68577237e6b980472a42b4fa7a7b9db49b6977 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 20 Mar 2026 23:14:16 +0100 Subject: [PATCH 040/115] Updated checked constraint --- .../sysmlv2/sysmlv2-semantics/TestModels/crossroads.sysml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/crossroads.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/crossroads.sysml index 71c3f9b9..2a89492c 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/crossroads.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/crossroads.sysml @@ -538,10 +538,10 @@ verification def UnreachableGreenGreen { objective { verify requirement { require constraint { - not eventually( + mustAlways( not( isStateActive(system.trafficLightA.Behaviour.Normal.Green) and isStateActive(system.trafficLightB.Behaviour.Normal.Green) - ) + ) ) } } } From a9aab0276ab8be102995b7a8eedf5071d9b15c66 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 09:30:21 +0100 Subject: [PATCH 041/115] Added sysmlv2-frontend as a submodule --- .gitmodules | 3 + .../sysmlv2/sysmlv2-frontend/build.gradle.kts | 82 +++++++++++++++++++ .../sysmlv2/sysmlv2-frontend/sysml-2ls | 1 + .../semantifyr-vscode-server/build.gradle.kts | 3 +- 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts create mode 160000 subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..c7d92687 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls"] + path = subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls + url = git@github.com:arminzavada/sysml-2ls.git diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts new file mode 100644 index 00000000..205f11ab --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2023-2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +import com.github.gradle.node.pnpm.task.PnpmTask +import kotlin.io.path.isSymbolicLink + +plugins { + base + alias(libs.plugins.gradle.node) +} + +val isCi: Boolean = System.getenv("CI") != null + +node { + version = "22.14.0" + download = !isCi + nodeProjectDir = project.layout.projectDirectory.dir("sysml-2ls") +} + +val distributionOutput by configurations.creating { + isCanBeConsumed = true + isCanBeResolved = false +} + +val buildExtension by tasks.registering(PnpmTask::class) { + dependsOn(tasks.pnpmInstall) // node_modules directory is not reliable + inputs.files(fileTree("sysml-2ls") { + include("**/src/**/*.ts") + include("**/tsconfig.json") + include("**/package.json") + include("**/package-lock.json") + include("**/scripts/*.*") + include("**/scripts/*.*") + }) + outputs.files(fileTree("sysml-2ls") { + exclude("**/node_modules/**") + include("**/lib/**") + include("**/dist/**") + }) + + pnpmCommand.set( + listOf( + "run", + "build", + ) + ) +} + +val bundleExtension by tasks.registering(PnpmTask::class) { + dependsOn(buildExtension) + outputs.file( + fileTree("sysml-2ls") { + include("packages/syside-vscode/*.vsix") + } + ) + + pnpmCommand.set( + listOf( + "run", + "vscode:package", + ) + ) +} + +tasks { + assemble { + inputs.files(buildExtension.get().outputs) + } + + clean { + delete("dist") + } +} + +artifacts { + add(distributionOutput.name, layout.buildDirectory) { + builtBy(bundleExtension) + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls new file mode 160000 index 00000000..d0a7cb7e --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls @@ -0,0 +1 @@ +Subproject commit d0a7cb7e1f574898ff9a3db4ad24a9b8fa195c8d diff --git a/subprojects/semantifyr-vscode-server/build.gradle.kts b/subprojects/semantifyr-vscode-server/build.gradle.kts index 1729f98b..45b4163b 100644 --- a/subprojects/semantifyr-vscode-server/build.gradle.kts +++ b/subprojects/semantifyr-vscode-server/build.gradle.kts @@ -20,11 +20,12 @@ val thetaClasspath by configurations.creating { dependencies { distributionClasspath(project(":semantifyr-vscode", configuration = "distributionOutput")) + distributionClasspath(project(":sysmlv2-frontend", configuration = "distributionOutput")) thetaClasspath(project(":theta-wrapper", configuration = "thetaOutput")) } -val cloneDistribution by tasks.registering(Copy::class) { +val cloneDistribution by tasks.registering(Sync::class) { inputs.files(distributionClasspath) from (distributionClasspath.map { From acc30340f3b226d8abe14f151aa1737844c88e36 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 10:41:22 +0100 Subject: [PATCH 042/115] Updated used libraries --- .../examples/gamma/Library/Components.oxsts | 16 ++++++-- .../examples/gamma/Library/Expressions.oxsts | 16 ++++++++ .../examples/gamma/Library/Statecharts.oxsts | 6 +-- .../examples/gamma/Library/Verification.oxsts | 2 +- .../examples/sysml/Library/Attributes.oxsts | 4 +- .../examples/sysml/Library/Expressions.oxsts | 16 ++++++++ .../examples/sysml/Library/Parts.oxsts | 14 +++++++ .../examples/sysml/Library/Ports.oxsts | 25 ++++-------- .../examples/sysml/Library/States.oxsts | 40 +++++++++---------- .../examples/sysml/Library/Verification.oxsts | 8 +--- 10 files changed, 95 insertions(+), 52 deletions(-) diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Components.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Components.oxsts index cee95194..6bf8d340 100644 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Components.oxsts +++ b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Components.oxsts @@ -14,6 +14,12 @@ abstract class Component { contains ports: Port[0..*] contains timeouts: Timeout[0..*] + redefine tran { + inline schedule() + } + + abstract tran schedule() + tran resetInputEvents() { inline for (port in ports) { inline port.resetInputEvent() @@ -43,14 +49,18 @@ class Channel { refers inputPort: Port[1] refers outputPort: Port[1] + tran doTransferEvent() { + inline outputPort.setInputEvent(inputPort.outputEvent) + } + redefine tran { if (inputPort.hasOutput()) { - inline outputPort.setInputEvent(inputPort.outputEvent) + inline doTransferEvent() } } } -class CompositeComponent : Component { +abstract class CompositeComponent : Component { contains components: Component[0..*] contains channels: Channel[0..*] @@ -72,7 +82,7 @@ class SyncComponent : CompositeComponent { } } - redefine tran { + redefine tran schedule() { inline resetOutputEvents() inline for (component in components) { diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Expressions.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Expressions.oxsts index a9e827df..c97d08fb 100644 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Expressions.oxsts +++ b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Expressions.oxsts @@ -117,3 +117,19 @@ class UnaryMinusExpression : UnaryOperatorExpression { return -body.evaluate() } } + +abstract class TemporalOperatorExpression : Expression { + contains body: Expression[1] +} + +class Eventually : TemporalOperatorExpression { + redefine prop evaluate(): any { + return EF body.evaluate() + } +} + +class MustAlways : TemporalOperatorExpression { + redefine prop evaluate(): any { + return AG body.evaluate() + } +} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Statecharts.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Statecharts.oxsts index 1217de5c..2a4138f2 100644 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Statecharts.oxsts +++ b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Statecharts.oxsts @@ -30,7 +30,7 @@ class TransitionScheduler { } tran fireTransitionsTopDown() { - var anyRegionExecuted := false + var anyRegionExecuted: bool := false inline for (region in innerRegions) { choice { inline region.fireLocalTransitions() @@ -49,7 +49,7 @@ class TransitionScheduler { } tran fireTransitionsBottomUp() { - var anyRegionExecuted := false + var anyRegionExecuted: bool := false inline for (region in innerRegions) { choice { // fire state transitions if inner transitions are not enabled (bottom-up) @@ -84,7 +84,7 @@ class Statechart : Component { } } - redefine tran { + redefine tran schedule() { inline resetOutputEvents() choice { diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Verification.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Verification.oxsts index 0e697091..460a0da2 100644 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Verification.oxsts +++ b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Verification.oxsts @@ -19,6 +19,6 @@ class GammaVerificationCase { } prop { - return !(propertyExpression.evaluate()) + return propertyExpression.evaluate() } } diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Attributes.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Attributes.oxsts index 36c08513..710db4e3 100644 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Attributes.oxsts +++ b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Attributes.oxsts @@ -11,7 +11,7 @@ abstract class Attribute { class IntegerAttribute : Attribute { refers defaultValue: int = 0 - var value := defaultValue + var value: int := defaultValue redefine init { value := defaultValue @@ -29,7 +29,7 @@ class IntegerAttribute : Attribute { class BooleanAttribute : Attribute { refers defaultValue: bool = false - var value := defaultValue + var value: bool := defaultValue redefine init { value := defaultValue diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Expressions.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Expressions.oxsts index 744cd400..41d74027 100644 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Expressions.oxsts +++ b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Expressions.oxsts @@ -116,3 +116,19 @@ class UnaryMinusExpression : UnaryOperatorExpression { return -operand.evaluate() } } + +abstract class TemporalOperatorExpression : Expression { + contains body: Expression[1] +} + +class Eventually : TemporalOperatorExpression { + redefine prop evaluate(): any { + return EF body.evaluate() + } +} + +class MustAlways : TemporalOperatorExpression { + redefine prop evaluate(): any { + return AG body.evaluate() + } +} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Parts.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Parts.oxsts index fc558f90..8a44f970 100644 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Parts.oxsts +++ b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Parts.oxsts @@ -73,6 +73,20 @@ class Part { inline resetInputEvents() } + + tran executeMainComponent() { + inline resetOutputEvents() + + inline for (part in parts) { + inline part.main() + } + + inline executeExhibitState() + + inline for (flow in flows) { + inline flow.main() + } + } } class Flow { diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Ports.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Ports.oxsts index bae2f731..f3a34892 100644 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Ports.oxsts +++ b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Ports.oxsts @@ -3,15 +3,8 @@ package semantifyr::sysml::ports import semantifyr::sysml::items abstract class Port { - refers items: Item[0..*] - refers incomingItems: Item[0..*] subsets items - refers outgoingItems: Item[0..*] subsets items - - refers actualInputItems: Item[0..*] = incomingItems - refers actualOutputItems: Item[0..*] = outgoingItems - - var incomingItem: actualInputItems[0..1] := nothing - var outgoingItem: actualOutputItems[0..1] := nothing + var incomingItem: Item[0..1] := nothing + var outgoingItem: Item[0..1] := nothing prop hasIncoming(): bool { return incomingItem != nothing @@ -25,6 +18,10 @@ abstract class Port { return incomingItem == item } + prop hasOutgoingItem(item: Item): bool { + return outgoingItem == item + } + tran assumeHasIncomingItem(item: Item) { assume (hasIncomingItem(item)) } @@ -54,11 +51,5 @@ abstract class Port { } } -class NormalPort : Port { - -} - -class ConjugatedPort : Port { - redefine refers actualInputItems: Item[0..*] = outgoingItems - redefine refers actualOutputItems: Item[0..*] = incomingItems -} +class NormalPort : Port +class ConjugatedPort : Port diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/States.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/States.oxsts index 37f7d8e1..b3e89bd5 100644 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/States.oxsts +++ b/subprojects/semantifyr-vscode-server/examples/sysml/Library/States.oxsts @@ -121,11 +121,13 @@ class State : AbstractState { } redefine tran enterRecursive(commonState: StateNode) { - inline if (commonState != parent) { - inline parent?.enterRecursive(commonState) - } + inline if (parent != nothing) { + inline if (commonState != parent) { + inline parent.enterRecursive(commonState) + } - inline activate() + inline activate() + } } redefine tran enter(commonState: StateNode) { inline enterRecursive(commonState) @@ -133,10 +135,12 @@ class State : AbstractState { } redefine tran exitRecursive(commonState: StateNode) { - inline deactivate() + inline if (parent != nothing) { + inline deactivate() - inline if (commonState != parent) { - inline parent?.exitRecursive(commonState) + inline if (commonState != parent) { + inline parent?.exitRecursive(commonState) + } } } redefine tran exit(commonState: StateNode) { @@ -145,24 +149,20 @@ class State : AbstractState { } tran activate() { - inline if (parent != nothing) { - inline parent.setActiveState(self) - - inline for (transition in outgoingTransitions) { - inline transition.initialize() - } + inline parent.setActiveState(self) - inline entryAction.main() + inline for (transition in outgoingTransitions) { + inline transition.initialize() } + + inline entryAction.main() } tran deactivate() { - inline if (parent != nothing) { - if (parent.getActiveState() == self) { - inline exitAction.main() + if (parent.getActiveState() == self) { + inline exitAction.main() - inline parent.setActiveState(nothing) - } + inline parent.setActiveState(nothing) } } @@ -223,7 +223,7 @@ class ParallelState : AbstractState { } redefine tran fireTransitions() { - var anyStateExecuted := false + var anyStateExecuted: bool := false inline for (state in states) { choice { diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Verification.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Verification.oxsts index 69a88435..80ec6cfb 100644 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Verification.oxsts +++ b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Verification.oxsts @@ -24,21 +24,17 @@ class VerificationCaseDefinition { contains subject: Part contains objective: Requirement - refers deltaTimeMin: int = 1 - refers deltaTimeMax: int = 1 - redefine init { inline subject.init() } redefine tran { inline subject.havocInputEvents() - inline subject.main() - // inline subject.resetOutputEvents() + inline subject.executeMainComponent() inline subject.passTime() } prop { - return !objective.evaluate() + return objective.evaluate() } } From b0bf3dca1bdc484767074dc5df1817d12b3d9dfc Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 10:46:31 +0100 Subject: [PATCH 043/115] Clone libraries automatically --- .../semantifyr-vscode-server/.gitignore | 1 + .../semantifyr-vscode-server/build.gradle.kts | 41 ++- .../examples/gamma/Library/Actions.oxsts | 41 --- .../examples/gamma/Library/Components.oxsts | 98 ----- .../examples/gamma/Library/Events.oxsts | 29 -- .../examples/gamma/Library/Expressions.oxsts | 135 ------- .../examples/gamma/Library/Ports.oxsts | 70 ---- .../examples/gamma/Library/Statecharts.oxsts | 312 ---------------- .../examples/gamma/Library/Triggers.oxsts | 37 -- .../examples/gamma/Library/Variables.oxsts | 44 --- .../examples/gamma/Library/Verification.oxsts | 24 -- .../examples/sysml/Library/Actions.oxsts | 48 --- .../examples/sysml/Library/Attributes.oxsts | 52 --- .../examples/sysml/Library/Expressions.oxsts | 134 ------- .../examples/sysml/Library/Items.oxsts | 9 - .../examples/sysml/Library/Parts.oxsts | 101 ------ .../examples/sysml/Library/Ports.oxsts | 55 --- .../examples/sysml/Library/States.oxsts | 337 ------------------ .../examples/sysml/Library/Triggers.oxsts | 62 ---- .../examples/sysml/Library/Verification.oxsts | 40 --- 20 files changed, 37 insertions(+), 1633 deletions(-) delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/Library/Actions.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/Library/Components.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/Library/Events.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/Library/Expressions.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/Library/Ports.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/Library/Statecharts.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/Library/Triggers.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/Library/Variables.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/Library/Verification.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/Library/Actions.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/Library/Attributes.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/Library/Expressions.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/Library/Items.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/Library/Parts.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/Library/Ports.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/Library/States.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/Library/Triggers.oxsts delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/Library/Verification.oxsts diff --git a/subprojects/semantifyr-vscode-server/.gitignore b/subprojects/semantifyr-vscode-server/.gitignore index 0ef18421..9c1d2811 100644 --- a/subprojects/semantifyr-vscode-server/.gitignore +++ b/subprojects/semantifyr-vscode-server/.gitignore @@ -1 +1,2 @@ extensions/ +examples/*/Library/ diff --git a/subprojects/semantifyr-vscode-server/build.gradle.kts b/subprojects/semantifyr-vscode-server/build.gradle.kts index 45b4163b..b0a7981a 100644 --- a/subprojects/semantifyr-vscode-server/build.gradle.kts +++ b/subprojects/semantifyr-vscode-server/build.gradle.kts @@ -4,8 +4,12 @@ * SPDX-License-Identifier: EPL-2.0 */ +import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage +import com.bmuschko.gradle.docker.tasks.image.DockerPushImage + plugins { base + alias(libs.plugins.bmuschko.docker) } val distributionClasspath by configurations.creating { @@ -28,9 +32,7 @@ dependencies { val cloneDistribution by tasks.registering(Sync::class) { inputs.files(distributionClasspath) - from (distributionClasspath.map { - fileTree(it) - }) + from (distributionClasspath) into("extensions") } @@ -43,7 +45,36 @@ val cloneTheta by tasks.registering(Sync::class) { into("theta-xsts-cli") } +val cloneGammaLibrary by tasks.registering(Sync::class) { + from (project(":gamma-semantics").layout.projectDirectory.dir("Library")) + into ("examples/gamma/Library") +} + +val cloneSysMLLibrary by tasks.registering(Sync::class) { + from (project(":sysmlv2-semantics").layout.projectDirectory.dir("Library")) + into ("examples/sysml/Library") +} + +val cloneLibraries by tasks.registering { + dependsOn(cloneGammaLibrary) + dependsOn(cloneSysMLLibrary) +} + val prepareDockerBuild by tasks.registering() { - inputs.files(cloneDistribution.get().outputs) - inputs.files(cloneTheta.get().outputs) + dependsOn(cloneDistribution) + dependsOn(cloneTheta) + dependsOn(cloneLibraries) +} + +val dockerBuildImage by tasks.registering(DockerBuildImage::class) { + dependsOn(prepareDockerBuild) + inputDir.set(projectDir) + images.add("ftsrgbot/semantifyr-vscode-server:${project.version}") + images.add("ftsrgbot/semantifyr-vscode-server:preview") +} + +val dockerPushImage by tasks.registering(DockerPushImage::class) { + dependsOn(dockerBuildImage) + images.add("ftsrgbot/semantifyr-vscode-server:${project.version}") + images.add("ftsrgbot/semantifyr-vscode-server:preview") } diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Actions.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Actions.oxsts deleted file mode 100644 index 8627fc3a..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Actions.oxsts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package semantifyr::gamma::actions - -import semantifyr::gamma::variables -import semantifyr::gamma::expressions -import semantifyr::gamma::events -import semantifyr::gamma::ports - -abstract class Action - -class RaiseEventAction : Action { - refers port: Port[1] - refers event: Event[1] - - redefine tran { - inline port.setOutputEvent(event) - } -} - -class SetTimeoutAction : Action { - refers timeout: Timeout[1] - contains expression: Expression[1] - - redefine tran { - timeout.remainingTime := expression.evaluate() - } -} - -class AssignmentAction : Action { - refers variable: Variable[1] - contains expression: Expression[1] - - redefine tran { - inline variable.set(expression.evaluate()) - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Components.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Components.oxsts deleted file mode 100644 index 6bf8d340..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Components.oxsts +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package semantifyr::gamma::components - -import semantifyr::gamma::events -import semantifyr::gamma::ports - -abstract class Component { - - contains ports: Port[0..*] - contains timeouts: Timeout[0..*] - - redefine tran { - inline schedule() - } - - abstract tran schedule() - - tran resetInputEvents() { - inline for (port in ports) { - inline port.resetInputEvent() - } - } - - tran havocInputEvents() { - inline for (port in ports) { - inline port.havocInputEvent() - } - } - - tran resetOutputEvents() { - inline for (port in ports) { - inline port.resetOutputEvent() - } - } - - tran passTime() { - inline for (timeout in timeouts) { - inline timeout.passTime() - } - } -} - -class Channel { - refers inputPort: Port[1] - refers outputPort: Port[1] - - tran doTransferEvent() { - inline outputPort.setInputEvent(inputPort.outputEvent) - } - - redefine tran { - if (inputPort.hasOutput()) { - inline doTransferEvent() - } - } -} - -abstract class CompositeComponent : Component { - contains components: Component[0..*] - contains channels: Channel[0..*] - - redefine tran passTime() { - inline for (timeout in timeouts) { - inline timeout.passTime() - } - - inline for (component in components) { - inline component.passTime() - } - } -} - -class SyncComponent : CompositeComponent { - redefine init { - inline for (component in components) { - inline component.init() - } - } - - redefine tran schedule() { - inline resetOutputEvents() - - inline for (component in components) { - inline component.main() - } - - inline for (channel in channels) { - inline channel.main() - } - - inline resetInputEvents() - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Events.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Events.oxsts deleted file mode 100644 index dfb33ac3..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Events.oxsts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package semantifyr::gamma::events - -class Event - -class Timeout { - refers deltaTime: int = 1 - - var remainingTime: int := 0 - - tran passTime() { - if (remainingTime > 0) { - remainingTime := remainingTime - deltaTime - } - } - - prop isUp(): bool { - return remainingTime <= 0 - } - - tran assumeIsUp() { - assume (remainingTime <= 0) - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Expressions.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Expressions.oxsts deleted file mode 100644 index c97d08fb..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Expressions.oxsts +++ /dev/null @@ -1,135 +0,0 @@ -package semantifyr::gamma::expressions - -abstract class Expression { - abstract prop evaluate(): any -} - -abstract class LiteralExpression : Expression -class LiteralBooleanExpression : LiteralExpression { - refers value: bool[1] - redefine prop evaluate(): bool { - return value - } -} - -class LiteralIntegerExpression : LiteralExpression { - refers value: int[1] - redefine prop evaluate(): int { - return value - } -} - -abstract class BinaryOperatorExpression : Expression { - contains left: Expression[1] - contains right: Expression[1] -} - -class LessThanOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() < right.evaluate() - } -} - -class LessThanOrEqualsOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() <= right.evaluate() - } -} - -class GreaterThanOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() > right.evaluate() - } -} - -class GreaterThanOrEqualsOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() >= right.evaluate() - } -} - -class PlusOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): any { - return left.evaluate() + right.evaluate() - } -} - -class MinusOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): any { - return left.evaluate() - right.evaluate() - } -} - -class MultiplyOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): any { - return left.evaluate() * right.evaluate() - } -} - -class DivideOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): any { - return left.evaluate() / right.evaluate() - } -} - -class EqualityOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() == right.evaluate() - } -} - -class InequalityOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() != right.evaluate() - } -} - -class OrOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() || right.evaluate() - } -} - -class AndOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() && right.evaluate() - } -} - -abstract class UnaryOperatorExpression : Expression { - contains body: Expression[1] -} - -class UnaryNotExpression : UnaryOperatorExpression { - redefine prop evaluate(): bool { - return !body.evaluate() - } -} - -class UnaryPlusExpression : UnaryOperatorExpression { - redefine prop evaluate(): any { - return body.evaluate() - } -} - -class UnaryMinusExpression : UnaryOperatorExpression { - redefine prop evaluate(): any { - return -body.evaluate() - } -} - -abstract class TemporalOperatorExpression : Expression { - contains body: Expression[1] -} - -class Eventually : TemporalOperatorExpression { - redefine prop evaluate(): any { - return EF body.evaluate() - } -} - -class MustAlways : TemporalOperatorExpression { - redefine prop evaluate(): any { - return AG body.evaluate() - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Ports.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Ports.oxsts deleted file mode 100644 index 9ae97007..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Ports.oxsts +++ /dev/null @@ -1,70 +0,0 @@ -package semantifyr::gamma::ports - -import semantifyr::gamma::events - -class Interface { - contains events: Event[0..*] - contains inputEvents: Event[0..*] subsets events - contains outputEvents: Event[0..*] subsets events -} - -class Port { - contains interface: Interface[1] - - refers inputEvents: Event[0..*] - refers outputEvents: Event[0..*] - - var inputEvent: inputEvents[0..1] := nothing - var outputEvent: outputEvents[0..1] := nothing - - prop hasInput(): bool { - return inputEvent != nothing - } - - prop hasOutput(): bool { - return outputEvent != nothing - } - - prop hasInputEvent(event: Event): bool { - return inputEvent == event - } - - tran assumeHasInputEvent(event: Event) { - assume (hasInputEvent(event)) - } - - tran setInputEvent(event: Event) { - inputEvent := event - } - - tran setOutputEvent(event: Event) { - outputEvent := event - } - - tran resetInputEvent() { - inputEvent := nothing - } - - tran resetOutputEvent() { - outputEvent := nothing - } - - tran havocInputEvent() { - havoc (inputEvent) - } - - tran havocOutputEvent() { - havoc (outputEvent) - } -} - -class RequiredPort : Port { - // required ports flip the direction - redefine refers inputEvents: Event[0..*] = interface.outputEvents - redefine refers outputEvents: Event[0..*] = interface.inputEvents -} - -class ProvidedPort : Port { - redefine refers inputEvents: Event[0..*] = interface.inputEvents - redefine refers outputEvents: Event[0..*] = interface.outputEvents -} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Statecharts.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Statecharts.oxsts deleted file mode 100644 index 2a4138f2..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Statecharts.oxsts +++ /dev/null @@ -1,312 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package semantifyr::gamma::statecharts - -import semantifyr::gamma::expressions -import semantifyr::gamma::variables -import semantifyr::gamma::components -import semantifyr::gamma::triggers -import semantifyr::gamma::actions -import semantifyr::gamma::events - -enum RegionSchedule { - TopDown, - BottomUp -} - -class TransitionScheduler { - refers innerRegions: Region[0..*] - - tran fireTransitions(regionSchedule: RegionSchedule) { - inline if (regionSchedule == RegionSchedule::BottomUp) { - inline fireTransitionsBottomUp() - } else { - inline fireTransitionsTopDown() - } - } - - tran fireTransitionsTopDown() { - var anyRegionExecuted: bool := false - inline for (region in innerRegions) { - choice { - inline region.fireLocalTransitions() - anyRegionExecuted := true - } or { - // fire state transitions if local transitions are not enabled (top-down) - inline region.assumeNoLocalTransitionEnabled() - inline region.fireInnerTransitions(RegionSchedule::TopDown) - anyRegionExecuted := true - } or { - // do nothing, if no transition is enabled - inline region.assumeNoTransitionEnabled() - } - } - assume (anyRegionExecuted) // at least one inner "parallel" region must be executed - } - - tran fireTransitionsBottomUp() { - var anyRegionExecuted: bool := false - inline for (region in innerRegions) { - choice { - // fire state transitions if inner transitions are not enabled (bottom-up) - inline region.assumeNoInnerTransitionEnabled() - inline region.fireLocalTransitions() - anyRegionExecuted := true - } or { - inline region.fireInnerTransitions(RegionSchedule::BottomUp) - anyRegionExecuted := true - } or { - // do nothing, if no transition is enabled - inline region.assumeNoTransitionEnabled() - } - } - assume (anyRegionExecuted) // at least one inner "parallel" region must be executed - } - -} - -class Statechart : Component { - contains regions: Region[0..*] - contains variables: Variable[0..*] - refers regionSchedule: RegionSchedule = RegionSchedule::BottomUp - - contains transitionScheduler: TransitionScheduler { - redefine refers innerRegions: Region[0..*] = regions - } - - redefine init { - inline for (region in regions) { - inline region.activateRecursive() - } - } - - redefine tran schedule() { - inline resetOutputEvents() - - choice { - inline transitionScheduler.fireTransitions(regionSchedule) - } or { - inline assumeNoTransitionEnabled() - // only do nothing, if the statechart cannot do anything, i.e., no fireable transitions - } - - inline resetInputEvents() - } - - // TODO: would be easier to implement if we had ...any { } and ...all { } lambda functions that could compose expressions - - tran assumeNoTransitionEnabled() { - inline for (region in regions) { - inline region.assumeNoTransitionEnabled() - } - } -} - -class Region { - contains states: State[0..*] opposite parentRegion - container parentState: State[0..1] opposite regions - - contains abstractTransitions: AbstractTransition[0..*] - contains transitions: Transition[0..*] subsets abstractTransitions opposite parentRegion - contains entryTransitions: EntryTransition[0..*] subsets abstractTransitions - - @Control - var activeState: states[0..1] := nothing - - tran activateRecursive() { - inline for (transition in entryTransitions) { - inline transition.main() - } - } - tran deactivateRecursive() { - inline for (state in states) { - inline state.deactivateRecursive() - } - } - - tran fireLocalTransitions() { - inline for choice (transition in transitions) { - inline transition.main() - } else { - assume (false) - } - } - - tran fireInnerTransitions(regionSchedule: RegionSchedule) { - inline for choice (state in states) { - inline state.fireTransitions(regionSchedule) - } else { - assume (false) - } - } - - tran assumeNoLocalTransitionEnabled() { - inline for (transition in transitions) { - assume (! transition.isEnabled()) - } - } - - tran assumeNoInnerTransitionEnabled() { - inline for (state in states) { - inline state.assumeNoTransitionEnabled() - } - } - - tran assumeNoTransitionEnabled() { - inline assumeNoLocalTransitionEnabled() - inline assumeNoInnerTransitionEnabled() - } - -} - -class State { - container parentRegion: Region[1] opposite states - contains regions: Region[0..*] opposite parentState - - refers parentState: State[0..1] = parentRegion.parentState // as pattern parentState - contains entryActions: Action[0..*] - contains exitActions: Action[0..*] - - contains transitionScheduler: TransitionScheduler { - redefine refers innerRegions: Region[0..*] = regions - } - - prop isActive(): bool { - return parentRegion.activeState == self - } - tran deactivateRecursive() { - inline for (region in regions) { - inline region.deactivateRecursive() - } - - if (parentRegion.activeState == self) { - parentRegion.activeState := nothing - - inline for (exitAction in exitActions) { - inline exitAction.main() - } - } - } - tran exitRecursive(commonRegion: Region) { - inline for (exitAction in exitActions) { - inline exitAction.main() - } - - parentRegion.activeState := nothing - - inline if (commonRegion != parentRegion) { - inline if (parentState != nothing) { - inline parentState.exitRecursive(commonRegion) - } - } - } - tran exit(commonRegion: Region) { - inline exitRecursive(commonRegion) - - inline for (region in regions) { - inline region.deactivateRecursive() - } - } - tran enterRecursive(commonRegion : Region) { - inline if (commonRegion != parentRegion) { - inline if (parentState != nothing) { - inline parentState.enterRecursive(commonRegion) - } - } - - parentRegion.activeState := self - - inline for (action in entryActions) { - inline action.main() - } - } - tran enter(commonRegion: Region) { - inline enterRecursive(commonRegion) - - inline for (region in regions) { - inline region.activateRecursive() - } - } - tran fireTransitions(regionSchedule: RegionSchedule) { - inline if (regions == nothing) { - assume (false) - } else { - inline transitionScheduler.fireTransitions(regionSchedule) - } - } - - tran assumeNoTransitionEnabled() { - inline for (region in regions) { - inline region.assumeNoTransitionEnabled() - } - } -} - -class Guard { - contains expression: Expression[1] - - prop isOpen(): bool { - return expression.evaluate() - } -} - -abstract class AbstractTransition { - container parentRegion: Region[1] opposite transitions - - refers to: State[1] - - abstract prop isEnabled(): bool - - tran fire() { - inline to.enter(parentRegion) - } - - redefine tran { - assume (isEnabled()) - inline fire() - } -} - -class EntryTransition : AbstractTransition { - redefine prop isEnabled(): bool { - return true - } -} - -class Transition : AbstractTransition { - refers from: State[1] - - contains trigger: Trigger[1] - contains guard: Guard[1] { // default guard is true - redefine contains expression: LiteralBooleanExpression { - redefine refers value: bool = true - } - } - - contains actions: Action[0..*] - - redefine prop isEnabled(): bool { - return trigger.isTriggered() && from.isActive() && guard.isOpen() - } - - redefine tran fire() { - inline from.exit(parentRegion) - inline for (action in actions) { - inline action.main() - } - inline to.enter(parentRegion) - } -} - -class IsStateActiveExpression : Expression { - refers state: State - - redefine prop evaluate(): bool { - return state.isActive() - } - -} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Triggers.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Triggers.oxsts deleted file mode 100644 index fe1b1b8e..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Triggers.oxsts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package semantifyr::gamma::triggers - -import semantifyr::gamma::events -import semantifyr::gamma::ports - -abstract class Trigger { - abstract prop isTriggered(): bool - - tran assumeIsTriggered() { - assume (isTriggered()) - } -} - -class EventTrigger : Trigger { - refers port: Port[1] - refers event: Event[1] - - redefine prop isTriggered(): bool { - return port.hasInputEvent(event) - } - -} - -class TimeoutTrigger : Trigger { - refers timeout: Timeout[1] - - redefine prop isTriggered(): bool { - return timeout.isUp() - } - -} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Variables.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Variables.oxsts deleted file mode 100644 index bbdccb78..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Variables.oxsts +++ /dev/null @@ -1,44 +0,0 @@ -package semantifyr::gamma::variables - -import semantifyr::gamma::expressions - -abstract class Variable { - abstract prop evaluate(): any - - abstract tran set(value: any) -} - -class IntegerVariable : Variable { - refers defaultValue: int = 0 - - var variable: int := defaultValue - - redefine prop evaluate(): int { - return variable - } - - redefine tran set(value: int) { - variable := value - } -} - -class BooleanVariable : Variable { - refers defaultValue: bool = false - - var variable: bool := defaultValue - - redefine prop evaluate(): bool { - return variable - } - - redefine tran set(value: bool) { - variable := value - } -} - -class VariableExpression : Expression { - refers variable: Variable - redefine prop evaluate(): any { - return variable.evaluate() - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Verification.oxsts b/subprojects/semantifyr-vscode-server/examples/gamma/Library/Verification.oxsts deleted file mode 100644 index 460a0da2..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/Library/Verification.oxsts +++ /dev/null @@ -1,24 +0,0 @@ -package semantifyr::gamma::verification - -import semantifyr::gamma::components -import semantifyr::gamma::expressions - -class GammaVerificationCase { - contains component: Component - contains propertyExpression: Expression - - redefine init { - inline component.init() - } - - redefine tran { - inline component.havocInputEvents() - inline component.main() - inline component.resetOutputEvents() - inline component.passTime() - } - - prop { - return propertyExpression.evaluate() - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Actions.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Actions.oxsts deleted file mode 100644 index bab88d4c..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Actions.oxsts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package semantifyr::sysml::actions - -import semantifyr::sysml::attributes -import semantifyr::sysml::expressions -import semantifyr::sysml::ports -import semantifyr::sysml::items - -abstract class Action - -class SendAction : Action { - refers viaPort: Port - refers payload: Item - - redefine tran { - inline viaPort.setOutgoingItem(payload) - } -} - -class AssignmentAction : Action { - refers attribute: Attribute - contains expression: Expression - redefine tran { - inline attribute.set(expression.evaluate()) - } -} - -class CompositeAction : Action { - contains children: Action[0..*] - redefine tran { - inline for (child in children) { - inline child.main() - } - } -} - -class Guard { - contains expression: Expression - - prop isOpen(): bool { - return expression.evaluate() - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Attributes.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Attributes.oxsts deleted file mode 100644 index 710db4e3..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Attributes.oxsts +++ /dev/null @@ -1,52 +0,0 @@ -package semantifyr::sysml::attributes - -import semantifyr::sysml::expressions - -abstract class Attribute { - abstract prop evaluate(): any - - abstract tran set(value: any) -} - -class IntegerAttribute : Attribute { - refers defaultValue: int = 0 - - var value: int := defaultValue - - redefine init { - value := defaultValue - } - - redefine prop evaluate(): int { - return value - } - - redefine tran set(value: int) { - self.value := value - } -} - -class BooleanAttribute : Attribute { - refers defaultValue: bool = false - - var value: bool := defaultValue - - redefine init { - value := defaultValue - } - - redefine prop evaluate(): bool { - return value - } - - redefine tran set(value: bool) { - self.value := value - } -} - -class AttributeReferenceExpression : Expression { - refers attribute: Attribute - redefine prop evaluate(): any { - return attribute.evaluate() - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Expressions.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Expressions.oxsts deleted file mode 100644 index 41d74027..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Expressions.oxsts +++ /dev/null @@ -1,134 +0,0 @@ -package semantifyr::sysml::expressions - -abstract class Expression { - abstract prop evaluate(): any -} - -abstract class LiteralExpression : Expression -class LiteralBooleanExpression : LiteralExpression { - refers value: bool[1] - redefine prop evaluate(): bool { - return value - } -} -class LiteralIntegerExpression : LiteralExpression { - refers value: int[1] - redefine prop evaluate(): int { - return value - } -} - -abstract class BinaryOperatorExpression : Expression { - contains left: Expression[1] - contains right: Expression[1] -} - -class LessThanOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() < right.evaluate() - } -} - -class LessThanOrEqualsOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() <= right.evaluate() - } -} - -class GreaterThanOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() > right.evaluate() - } -} - -class GreaterThanOrEqualsOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() >= right.evaluate() - } -} - -class PlusOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): any { - return left.evaluate() + right.evaluate() - } -} - -class MinusOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): any { - return left.evaluate() - right.evaluate() - } -} - -class MultiplicationOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): any { - return left.evaluate() * right.evaluate() - } -} - -class DivisionOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): any { - return left.evaluate() / right.evaluate() - } -} - -class EqualityOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() == right.evaluate() - } -} - -class InequalityOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() != right.evaluate() - } -} - -class OrOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() || right.evaluate() - } -} - -class AndOperatorExpression : BinaryOperatorExpression { - redefine prop evaluate(): bool { - return left.evaluate() && right.evaluate() - } -} - -abstract class UnaryOperatorExpression : Expression { - contains operand: Expression[1] -} - -class UnaryNotExpression : UnaryOperatorExpression { - redefine prop evaluate(): bool { - return !operand.evaluate() - } -} - -class UnaryPlusExpression : UnaryOperatorExpression { - redefine prop evaluate(): any { - return operand.evaluate() - } -} - -class UnaryMinusExpression : UnaryOperatorExpression { - redefine prop evaluate(): any { - return -operand.evaluate() - } -} - -abstract class TemporalOperatorExpression : Expression { - contains body: Expression[1] -} - -class Eventually : TemporalOperatorExpression { - redefine prop evaluate(): any { - return EF body.evaluate() - } -} - -class MustAlways : TemporalOperatorExpression { - redefine prop evaluate(): any { - return AG body.evaluate() - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Items.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Items.oxsts deleted file mode 100644 index 6d77acb5..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Items.oxsts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package semantifyr::sysml::items - -class Item diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Parts.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Parts.oxsts deleted file mode 100644 index 8a44f970..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Parts.oxsts +++ /dev/null @@ -1,101 +0,0 @@ -package semantifyr::sysml::parts - -import semantifyr::sysml::attributes -import semantifyr::sysml::ports -import semantifyr::sysml::states - -class Part { - contains parts: Part[0..*] - contains attributes: Attribute[0..*] - contains ports: Port[0..*] - contains exhibitState: AbstractState[0..1] - contains flows: Flow[0..*] - - tran resetInputEvents() { - inline for (port in ports) { - inline port.resetIncomingItem() - } - } - - tran havocInputEvents() { - inline for (port in ports) { - inline port.havocIncomingItem() - } - } - - tran resetOutputEvents() { - inline for (port in ports) { - inline port.resetOutgoingItem() - } - } - - tran passTime() { - inline for (part in parts) { - inline part.passTime() - } - - inline exhibitState?.passTime() - } - - tran executeExhibitState() { - choice { - inline exhibitState?.fireTransitions() - } or { - // do nothing, if no transition is enabled - inline exhibitState?.assumeNoTransitionEnabled() - } - } - - redefine init { - inline for (attribute in attributes) { - inline attribute.init() - } - - inline exhibitState?.activateRecursive() - - inline for (part in parts) { - inline part.init() - } - } - - redefine tran { - inline resetOutputEvents() - - inline for (part in parts) { - inline part.main() - } - - inline executeExhibitState() - - inline for (flow in flows) { - inline flow.main() - } - - inline resetInputEvents() - } - - tran executeMainComponent() { - inline resetOutputEvents() - - inline for (part in parts) { - inline part.main() - } - - inline executeExhibitState() - - inline for (flow in flows) { - inline flow.main() - } - } -} - -class Flow { - refers inputPort: Port[1] - refers outputPort: Port[1] - - redefine tran { - if (inputPort.hasOutgoing()) { - inline outputPort.setIncomingItem(inputPort.outgoingItem) - } - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Ports.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Ports.oxsts deleted file mode 100644 index f3a34892..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Ports.oxsts +++ /dev/null @@ -1,55 +0,0 @@ -package semantifyr::sysml::ports - -import semantifyr::sysml::items - -abstract class Port { - var incomingItem: Item[0..1] := nothing - var outgoingItem: Item[0..1] := nothing - - prop hasIncoming(): bool { - return incomingItem != nothing - } - - prop hasOutgoing(): bool { - return outgoingItem != nothing - } - - prop hasIncomingItem(item: Item): bool { - return incomingItem == item - } - - prop hasOutgoingItem(item: Item): bool { - return outgoingItem == item - } - - tran assumeHasIncomingItem(item: Item) { - assume (hasIncomingItem(item)) - } - - tran setIncomingItem(item: Item) { - incomingItem := item - } - - tran setOutgoingItem(item: Item) { - outgoingItem := item - } - - tran resetIncomingItem() { - incomingItem := nothing - } - - tran resetOutgoingItem() { - outgoingItem := nothing - } - - tran havocIncomingItem() { - havoc (incomingItem) - } - - tran havocOutgoingItem() { - havoc (outgoingItem) - } -} - -class NormalPort : Port -class ConjugatedPort : Port diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/States.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/States.oxsts deleted file mode 100644 index b3e89bd5..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/States.oxsts +++ /dev/null @@ -1,337 +0,0 @@ -package semantifyr::sysml::states - -import semantifyr::sysml::actions -import semantifyr::sysml::triggers -import semantifyr::sysml::expressions - -abstract class StateNode { - derived refers incomingTransitions: Transition[0..*] opposite to - derived refers outgoingTransitions: Transition[0..*] opposite from - - abstract prop isActive(): bool - - abstract tran enter(commonState: StateNode) - abstract tran exit(commonState: StateNode) -} - -abstract class AbstractState : StateNode { - container parent: AbstractState[0..1] opposite states - contains states: AbstractState[0..*] opposite parent - - redefine prop isActive(): bool { - return parent?.isInnerStateActive(self) - } - - abstract prop getActiveState(): AbstractState - - abstract prop isInnerStateActive(state: AbstractState): bool - - abstract tran fireTransitions() - abstract tran assumeNoTransitionEnabled() - abstract tran activateRecursive() - abstract tran deactivateRecursive(deactivate: bool) - abstract tran passTime() - - abstract tran enterRecursive(commonState: StateNode) - abstract tran exitRecursive(commonState: StateNode) - - abstract tran setActiveState(state: AbstractState) -} - -class State : AbstractState { - contains start: EntryState[1] - - contains transitions: Transition[0..*] opposite parentState - contains entryAction: Action[1] - contains exitAction: Action[1] - - var activeState: states[0..1] := nothing - - redefine prop isInnerStateActive(state: AbstractState): bool { - return state == activeState - } - - redefine prop getActiveState(): AbstractState { - return activeState - } - - redefine tran setActiveState(state: AbstractState) { - activeState := state - } - - redefine tran fireTransitions() { - choice { - inline assumeNoInnerTransitionEnabled() - inline fireLocalTransitions() - } or { - inline fireInnerTransitions() - } - } - tran fireLocalTransitions() { - inline for choice (transition in transitions) { - inline transition.fire() - } else { - assume (false) - } - } - tran fireInnerTransitions() { - inline for choice (state in states) { - inline state.fireTransitions() - } else { - assume (false) - } - } - - redefine tran assumeNoTransitionEnabled() { - inline assumeNoLocalTransitionEnabled() - inline assumeNoInnerTransitionEnabled() - } - tran assumeNoLocalTransitionEnabled() { - inline for (transition in transitions) { - assume (!transition.isEnabled()) - } - } - tran assumeNoInnerTransitionEnabled() { - inline for (state in states) { - inline state.assumeNoTransitionEnabled() - } - } - - redefine tran activateRecursive() { - inline start.enter() - } - - redefine tran deactivateRecursive(_deactivate: bool) { - inline for (state in states) { - inline state.deactivateRecursive(true) - } - - inline if (_deactivate) { - inline deactivate() - } - } - - redefine tran passTime() { - inline for (transition in transitions) { - inline transition.passTime() - } - inline for (state in states) { - inline state.passTime() - } - } - - redefine tran enterRecursive(commonState: StateNode) { - inline if (parent != nothing) { - inline if (commonState != parent) { - inline parent.enterRecursive(commonState) - } - - inline activate() - } - } - redefine tran enter(commonState: StateNode) { - inline enterRecursive(commonState) - inline activateRecursive() - } - - redefine tran exitRecursive(commonState: StateNode) { - inline if (parent != nothing) { - inline deactivate() - - inline if (commonState != parent) { - inline parent?.exitRecursive(commonState) - } - } - } - redefine tran exit(commonState: StateNode) { - inline deactivateRecursive(false) - inline exitRecursive(commonState) - } - - tran activate() { - inline parent.setActiveState(self) - - inline for (transition in outgoingTransitions) { - inline transition.initialize() - } - - inline entryAction.main() - } - - tran deactivate() { - if (parent.getActiveState() == self) { - inline exitAction.main() - - inline parent.setActiveState(nothing) - } - } - -} - -class Transition { - container parentState: State[1] opposite transitions - - refers from: StateNode[1] opposite outgoingTransitions - refers to: StateNode[1] opposite incomingTransitions - - contains action: Action - contains acceptAction: AcceptAction - contains guard: Guard[1] { // default guard is true - redefine contains expression: LiteralBooleanExpression { - redefine refers value: bool = true - } - } - - tran fire() { - assume (isEnabled()) - inline performTransition() - } - - prop isEnabled(): bool { - return acceptAction.isTriggered() && from.isActive() && guard.isOpen() - } - - tran performTransition() { - inline from.exit(parentState) - inline action.main() - inline to.enter(parentState) - } - - tran passTime() { - inline acceptAction.passTime() - } - - tran initialize() { - inline acceptAction.initialize() - } - -} - -class ParallelState : AbstractState { - contains start: EntryState[1] - - redefine prop getActiveState(): AbstractState { - return nothing - } - - redefine tran setActiveState(state: AbstractState) { - - } - - redefine prop isInnerStateActive(state: AbstractState): bool { - return isActive() - } - - redefine tran fireTransitions() { - var anyStateExecuted: bool := false - - inline for (state in states) { - choice { - anyStateExecuted := true - - inline state.fireTransitions() - } or { - inline state.assumeNoTransitionEnabled() - } - } - - assume (anyStateExecuted) - } - - redefine tran assumeNoTransitionEnabled() { - inline for (state in states) { - inline state.assumeNoTransitionEnabled() - } - } - - redefine tran activateRecursive() { - inline for (state in states) { - inline state.activateRecursive() - } - } - - redefine tran deactivateRecursive(_deactivate: bool) { - inline for (state in states) { - inline state.deactivateRecursive(true) - } - - inline if (_deactivate) { - inline deactivate() - } - } - - redefine tran passTime() { - inline for (state in states) { - inline state.passTime() - } - } - - redefine tran enterRecursive(commonState: StateNode) { - inline if (commonState != parent) { - inline parent?.enterRecursive(commonState) - } - - inline activate() - } - redefine tran enter(commonState: StateNode) { - inline enterRecursive(commonState) - inline activateRecursive() - } - - redefine tran exitRecursive(commonState: StateNode) { - inline deactivate() - - inline if (commonState != parent) { - inline parent?.exitRecursive(commonState) - } - } - redefine tran exit(commonState: StateNode) { - inline deactivateRecursive(false) - inline exitRecursive(commonState) - } - - tran activate() { - inline if (parent != nothing) { - inline parent.setActiveState(self) - - inline for (transition in outgoingTransitions) { - inline transition.initialize() - } - } - } - - tran deactivate() { - inline if (parent != nothing) { - if (parent.getActiveState() == self) { - inline parent.setActiveState(nothing) - } - } - } - -} - -class EntryState : StateNode { - - redefine prop isActive(): bool { - return false - } - - redefine tran enter() { - inline for choice (transition in outgoingTransitions) { - inline transition.performTransition() - } - } - - redefine tran exit() { - - } - -} - -class IsStateActiveExpression : Expression { - refers state: State - - redefine prop evaluate(): bool { - return state.isActive() - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Triggers.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Triggers.oxsts deleted file mode 100644 index 0761cec2..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Triggers.oxsts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package semantifyr::sysml::triggers - -import semantifyr::sysml::attributes -import semantifyr::sysml::expressions -import semantifyr::sysml::ports -import semantifyr::sysml::items -import semantifyr::sysml::actions - -abstract class AcceptAction { - - prop isTriggered(): bool { - return true // should be abstract, but no good way to specify defaults atm - } - - tran passTime() { - } - - tran assumeIsTriggered() { - assume (isTriggered()) - } - - tran initialize() { - } -} - -class AcceptItemAction : AcceptAction { - - refers viaPort: Port - refers payload: Item - - redefine prop isTriggered(): bool { - return viaPort.hasIncomingItem(payload) - } -} - -class AcceptTimeoutAction : AcceptAction { - - refers afterTime: int = 1 - - var remainingTime: int := 0 - - redefine tran passTime() { - if (remainingTime > 0) { - remainingTime := remainingTime - 1 - assume (remainingTime >= 0) - } - } - - redefine prop isTriggered(): bool { - return remainingTime <= 0 - } - - redefine tran initialize() { - remainingTime := afterTime - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Verification.oxsts b/subprojects/semantifyr-vscode-server/examples/sysml/Library/Verification.oxsts deleted file mode 100644 index 80ec6cfb..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/Library/Verification.oxsts +++ /dev/null @@ -1,40 +0,0 @@ -package semantifyr::sysml::verification - -import semantifyr::sysml::parts -import semantifyr::sysml::states -import semantifyr::sysml::expressions - -class Constraint : Expression { - contains requiredConstraint: Expression - - redefine prop evaluate(): bool { - return requiredConstraint.evaluate() - } -} - -class Requirement : Constraint { - contains verifyRequirement: Constraint - - redefine prop evaluate(): bool { - return verifyRequirement.evaluate() - } -} - -class VerificationCaseDefinition { - contains subject: Part - contains objective: Requirement - - redefine init { - inline subject.init() - } - - redefine tran { - inline subject.havocInputEvents() - inline subject.executeMainComponent() - inline subject.passTime() - } - - prop { - return objective.evaluate() - } -} From f9871c4959a3f983f32072971bd228845bd5e773 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 10:46:55 +0100 Subject: [PATCH 044/115] Implemented EF and AG CTL operators Finalized frontend build --- gradle.properties | 1 + .../frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 2 +- subprojects/semantifyr-vscode/build.gradle.kts | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 20e8c084..5304bf4b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,3 +8,4 @@ org.gradle.cache=true org.gradle.configuration-cache=true org.gradle.parallel=true thetaXstsCliVersion=6.27.14 +version=0.1.0 diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index 205f11ab..4de35ac2 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -76,7 +76,7 @@ tasks { } artifacts { - add(distributionOutput.name, layout.buildDirectory) { + add(distributionOutput.name, bundleExtension.get().outputs.files.singleFile) { builtBy(bundleExtension) } } diff --git a/subprojects/semantifyr-vscode/build.gradle.kts b/subprojects/semantifyr-vscode/build.gradle.kts index 2390b7a1..7bb0dc58 100644 --- a/subprojects/semantifyr-vscode/build.gradle.kts +++ b/subprojects/semantifyr-vscode/build.gradle.kts @@ -83,7 +83,7 @@ val bundleExtension by tasks.registering(NpmTask::class) { ) ) - outputs.dir(project.layout.buildDirectory) + outputs.file(project.layout.buildDirectory.file("semantifyr-0.0.1.vsix")) } tasks { @@ -98,7 +98,7 @@ tasks { } artifacts { - add(distributionOutput.name, layout.buildDirectory) { + add(distributionOutput.name, project.layout.buildDirectory.file("semantifyr-0.0.1.vsix")) { builtBy(bundleExtension) } } From b6c3c3a3854be724ffd57bcce4efe83ace1bf03e Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 11:09:59 +0100 Subject: [PATCH 045/115] Sync the sysml-2ls cli to the semantics --- .../sysmlv2/sysmlv2-frontend/build.gradle.kts | 22 +++++++++++++++++++ .../sysmlv2/sysmlv2-frontend/sysml-2ls | 2 +- .../sysmlv2-semantics/build.gradle.kts | 16 ++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index 4de35ac2..af2774f9 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -25,6 +25,11 @@ val distributionOutput by configurations.creating { isCanBeResolved = false } +val cliOutput by configurations.creating { + isCanBeConsumed = true + isCanBeResolved = false +} + val buildExtension by tasks.registering(PnpmTask::class) { dependsOn(tasks.pnpmInstall) // node_modules directory is not reliable inputs.files(fileTree("sysml-2ls") { @@ -65,6 +70,20 @@ val bundleExtension by tasks.registering(PnpmTask::class) { ) } +val bundleCli by tasks.registering(PnpmTask::class) { + dependsOn(buildExtension) + outputs.file("sysml-2ls/packages/syside-cli/out/index.js") + + workingDir = project.layout.projectDirectory.dir("sysml-2ls/packages/syside-cli") + + pnpmCommand.set( + listOf( + "run", + "esbuild", + ) + ) +} + tasks { assemble { inputs.files(buildExtension.get().outputs) @@ -79,4 +98,7 @@ artifacts { add(distributionOutput.name, bundleExtension.get().outputs.files.singleFile) { builtBy(bundleExtension) } + add(cliOutput.name, bundleCli.get().outputs.files.singleFile) { + builtBy(bundleCli) + } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls index d0a7cb7e..eef38e33 160000 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls @@ -1 +1 @@ -Subproject commit d0a7cb7e1f574898ff9a3db4ad24a9b8fa195c8d +Subproject commit eef38e33afc1503b2d571f4b23c2962fa5328a67 diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts index c534c15d..4325d931 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts @@ -10,6 +10,11 @@ plugins { kotlin("jvm") } +val cliClasspath by configurations.creating { + isCanBeConsumed = false + isCanBeResolved = true +} + repositories { mavenCentral() } @@ -19,4 +24,15 @@ dependencies { testFixturesApi(project(":xsts-verifier")) testFixturesApi(testFixtures(project(":xsts-verifier"))) + + cliClasspath(project(":sysmlv2-frontend", configuration = "cliOutput")) +} + +val prepareCli by tasks.registering(Sync::class) { + from (cliClasspath) + into ("build/cli") +} + +tasks.withType(Test::class) { + dependsOn(prepareCli) } From 48956f4736132ea9bff8ca1a9d21ed20175cc975 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 11:10:10 +0100 Subject: [PATCH 046/115] Added docker plugin --- gradle/libs.versions.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f7a2febd..8dd043f0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,6 +19,7 @@ viatra = "2.9.1" dockerJava = "3.7.0" guice = "7.0.0" node = "7.1.0" +bmuschkoDocker = "9.4.0" [libraries] ecore = { group = "org.eclipse.emf", name = "org.eclipse.emf.ecore", version.ref = "ecore" } @@ -58,3 +59,4 @@ docker-java-transport = { group = "com.github.docker-java" , name = "docker-java kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } gradle-node = { id = "com.github.node-gradle.node", version.ref = "node" } +bmuschko-docker = { id = "com.bmuschko.docker-remote-api", version.ref = "bmuschkoDocker" } From 175b1eeb76454d33277b67cb0a1a52463ef96832 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 11:10:38 +0100 Subject: [PATCH 047/115] Added the semantifyr extensions to cli --- subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls index eef38e33..dc480b04 160000 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls @@ -1 +1 @@ -Subproject commit eef38e33afc1503b2d571f4b23c2962fa5328a67 +Subproject commit dc480b0423513d01aa0afb31be58fcd3338f7b65 From e22bfb3fefdfcb1c258a25a0837c2ad1e18a7570 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 11:28:47 +0100 Subject: [PATCH 048/115] Fixed cli not being automatically run --- subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls index dc480b04..412cca06 160000 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls @@ -1 +1 @@ -Subproject commit dc480b0423513d01aa0afb31be58fcd3338f7b65 +Subproject commit 412cca0644b86503e0252bf1691b3966c6f8a88a From 0c5c894b2e0b1b7ecea76dd6b40eab7962fa6726 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 12:47:51 +0100 Subject: [PATCH 049/115] Automated SysML compilation during tests --- .../sysmlv2/sysmlv2-frontend/build.gradle.kts | 23 +- .../sysmlv2/sysmlv2-frontend/sysml-2ls | 2 +- .../sysmlv2-semantics/Library/Ports.oxsts | 24 +- .../sysmlv2-semantics/models/.gitignore | 9 - .../sysmlv2-semantics/models/crossroads.oxsts | 769 ------------ .../models/models26.example.oxsts | 62 - .../sysmlv2-semantics/models/spacecraft.oxsts | 1035 ----------------- .../sysmlv2-semantics/models/stm21.oxsts | 113 -- .../sysmlv2-semantics/models/stm31.oxsts | 158 --- .../sysml/semantics/SysMLTransformer.kt | 28 + .../semantics}/SysMLVerificationTests.kt | 23 +- 11 files changed, 69 insertions(+), 2177 deletions(-) delete mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/.gitignore delete mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts delete mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/models26.example.oxsts delete mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts delete mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm21.oxsts delete mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm31.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLTransformer.kt rename subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/{ => hu/bme/mit/semantifyr/frontends/sysml/semantics}/SysMLVerificationTests.kt (85%) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index af2774f9..f95e8da4 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -71,7 +71,15 @@ val bundleExtension by tasks.registering(PnpmTask::class) { } val bundleCli by tasks.registering(PnpmTask::class) { - dependsOn(buildExtension) + dependsOn(tasks.pnpmInstall) // node_modules directory is not reliable + inputs.files(fileTree("sysml-2ls") { + include("**/src/**/*.ts") + include("**/tsconfig.json") + include("**/package.json") + include("**/package-lock.json") + include("**/scripts/*.*") + include("**/scripts/*.*") + }) outputs.file("sysml-2ls/packages/syside-cli/out/index.js") workingDir = project.layout.projectDirectory.dir("sysml-2ls/packages/syside-cli") @@ -94,11 +102,20 @@ tasks { } } +val assembleCliBundle by tasks.registering(Sync::class) { + dependsOn(bundleCli) + from(file("sysml-2ls/packages/syside-cli/out/index.js")) + from(project.layout.projectDirectory.dir("sysml-2ls/packages/syside-vscode/sysml.library")) { + into("sysml.library") + } + into(project.layout.buildDirectory.dir("cli-bundle")) +} + artifacts { add(distributionOutput.name, bundleExtension.get().outputs.files.singleFile) { builtBy(bundleExtension) } - add(cliOutput.name, bundleCli.get().outputs.files.singleFile) { - builtBy(bundleCli) + add(cliOutput.name, project.layout.buildDirectory.dir("cli-bundle").get().asFile) { + builtBy(assembleCliBundle) } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls index 412cca06..e9d67577 160000 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls @@ -1 +1 @@ -Subproject commit 412cca0644b86503e0252bf1691b3966c6f8a88a +Subproject commit e9d675777390deabae2e620722288a2177271ab6 diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Ports.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Ports.oxsts index b926b8f3..f3a34892 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Ports.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Ports.oxsts @@ -3,15 +3,8 @@ package semantifyr::sysml::ports import semantifyr::sysml::items abstract class Port { - refers items: Item[0..*] - refers incomingItems: Item[0..*] subsets items - refers outgoingItems: Item[0..*] subsets items - - refers actualInputItems: Item[0..*] = incomingItems - refers actualOutputItems: Item[0..*] = outgoingItems - - var incomingItem: actualInputItems[0..1] := nothing - var outgoingItem: actualOutputItems[0..1] := nothing + var incomingItem: Item[0..1] := nothing + var outgoingItem: Item[0..1] := nothing prop hasIncoming(): bool { return incomingItem != nothing @@ -51,9 +44,6 @@ abstract class Port { tran havocIncomingItem() { havoc (incomingItem) - inline if (actualInputItems != nothing) { - assume (incomingItem != nothing) - } } tran havocOutgoingItem() { @@ -61,11 +51,5 @@ abstract class Port { } } -class NormalPort : Port { - -} - -class ConjugatedPort : Port { - redefine refers actualInputItems: Item[0..*] = outgoingItems - redefine refers actualOutputItems: Item[0..*] = incomingItems -} +class NormalPort : Port +class ConjugatedPort : Port diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/.gitignore b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/.gitignore deleted file mode 100644 index 454fdb08..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -**/*.oxsts -**/*.xsts -**/*.cex -**/theta.err -**/theta.out -**/trace.json -**/mapping.json - -!./* diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts deleted file mode 100644 index d48d3ae8..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/crossroads.oxsts +++ /dev/null @@ -1,769 +0,0 @@ -package semantifyr::sysml::model - -import semantifyr::sysml::expressions -import semantifyr::sysml::attributes -import semantifyr::sysml::states -import semantifyr::sysml::parts -import semantifyr::sysml::ports -import semantifyr::sysml::items -import semantifyr::sysml::actions -import semantifyr::sysml::triggers -import semantifyr::sysml::verification - -class Police : Item -global containment global_Police: Police[1] -class Toggle : Item -global containment global_Toggle: Toggle[1] -class RedL : Item -global containment global_RedL: RedL[1] -class YellowL : Item -global containment global_YellowL: YellowL[1] -class GreenL : Item -global containment global_GreenL: GreenL[1] -class NoneL : Item -global containment global_NoneL: NoneL[1] -class CentralControl : NormalPort { - refers police: Police subsets outgoingItems = global_Police - refers toggle: Toggle subsets outgoingItems = global_Toggle -} -class ConjugatedCentralControl : ConjugatedPort { - refers police: Police subsets outgoingItems = global_Police - refers toggle: Toggle subsets outgoingItems = global_Toggle -} -class LightControl : NormalPort { - refers red: RedL subsets outgoingItems = global_RedL - refers yellow: YellowL subsets outgoingItems = global_YellowL - refers green: GreenL subsets outgoingItems = global_GreenL - refers none: NoneL subsets outgoingItems = global_NoneL -} -class ConjugatedLightControl : ConjugatedPort { - refers red: RedL subsets outgoingItems = global_RedL - refers yellow: YellowL subsets outgoingItems = global_YellowL - refers green: GreenL subsets outgoingItems = global_GreenL - refers none: NoneL subsets outgoingItems = global_NoneL -} -class CentralController : Part { - contains control: ConjugatedCentralControl subsets ports - contains controlA: CentralControl subsets ports - contains controlB: CentralControl subsets ports - contains Behaviour: State redefines exhibitState { - contains UnnamedTransitionUsage0: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = Operating - } - contains Operating: State subsets states { - contains UnnamedTransitionUsage1: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = BothYellow - } - contains BothYellow: State subsets states - contains UnnamedTransitionUsage2: Transition subsets transitions { - redefine refers from: StateNode = BothYellow - redefine refers to: StateNode = BothRed - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 1 - } - redefine contains action: CompositeAction { - contains UnnamedSendActionUsage0: SendAction subsets children { - redefine refers viaPort: Port = controlA - redefine refers payload: Item = global_Toggle - } - contains UnnamedSendActionUsage1: SendAction subsets children { - redefine refers viaPort: Port = controlB - redefine refers payload: Item = global_Toggle - } - } - } - contains BothRed: State subsets states - contains UnnamedTransitionUsage3: Transition subsets transitions { - redefine refers from: StateNode = BothRed - redefine refers to: StateNode = TrafficOnA - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 2 - } - redefine contains action: CompositeAction { - contains UnnamedSendActionUsage2: SendAction subsets children { - redefine refers viaPort: Port = controlA - redefine refers payload: Item = global_Toggle - } - } - } - contains TrafficOnA: State subsets states - contains UnnamedTransitionUsage4: Transition subsets transitions { - redefine refers from: StateNode = TrafficOnA - redefine refers to: StateNode = StoppingA - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 2 - } - redefine contains action: CompositeAction { - contains UnnamedSendActionUsage3: SendAction subsets children { - redefine refers viaPort: Port = controlA - redefine refers payload: Item = global_Toggle - } - } - } - contains StoppingA: State subsets states - contains UnnamedTransitionUsage5: Transition subsets transitions { - redefine refers from: StateNode = StoppingA - redefine refers to: StateNode = TrafficOnB - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 1 - } - redefine contains action: CompositeAction { - contains UnnamedSendActionUsage4: SendAction subsets children { - redefine refers viaPort: Port = controlA - redefine refers payload: Item = global_Toggle - } - contains UnnamedSendActionUsage5: SendAction subsets children { - redefine refers viaPort: Port = controlB - redefine refers payload: Item = global_Toggle - } - } - } - contains TrafficOnB: State subsets states - contains UnnamedTransitionUsage6: Transition subsets transitions { - redefine refers from: StateNode = TrafficOnB - redefine refers to: StateNode = StoppingB - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 2 - } - redefine contains action: CompositeAction { - contains UnnamedSendActionUsage6: SendAction subsets children { - redefine refers viaPort: Port = controlB - redefine refers payload: Item = global_Toggle - } - } - } - contains StoppingB: State subsets states - contains UnnamedTransitionUsage7: Transition subsets transitions { - redefine refers from: StateNode = StoppingB - redefine refers to: StateNode = TrafficOnA - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 1 - } - redefine contains action: CompositeAction { - contains UnnamedSendActionUsage7: SendAction subsets children { - redefine refers viaPort: Port = controlA - redefine refers payload: Item = global_Toggle - } - contains UnnamedSendActionUsage8: SendAction subsets children { - redefine refers viaPort: Port = controlB - redefine refers payload: Item = global_Toggle - } - } - } - } - contains UnnamedTransitionUsage8: Transition subsets transitions { - redefine refers from: StateNode = Operating - redefine refers to: StateNode = Interrupted - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = control - redefine refers payload: Item = global_Police - } - } - contains UnnamedTransitionUsage9: Transition subsets transitions { - redefine refers from: StateNode = Interrupted - redefine refers to: StateNode = Operating - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = control - redefine refers payload: Item = global_Police - } - } - contains Interrupted: State subsets states { - redefine contains entryAction: CompositeAction { - contains UnnamedSendActionUsage9: SendAction subsets children { - redefine refers viaPort: Port = controlA - redefine refers payload: Item = global_Police - } - contains UnnamedSendActionUsage10: SendAction subsets children { - redefine refers viaPort: Port = controlB - redefine refers payload: Item = global_Police - } - } - redefine contains exitAction: CompositeAction { - contains UnnamedSendActionUsage11: SendAction subsets children { - redefine refers viaPort: Port = controlA - redefine refers payload: Item = global_Police - } - contains UnnamedSendActionUsage12: SendAction subsets children { - redefine refers viaPort: Port = controlB - redefine refers payload: Item = global_Police - } - } - } - } -} -class TrafficLightController : Part { - contains control: ConjugatedCentralControl subsets ports - contains lightControl: LightControl subsets ports - contains Behaviour: State redefines exhibitState { - contains UnnamedTransitionUsage10: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = Normal - } - contains Normal: State subsets states { - contains UnnamedTransitionUsage11: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = Yellow - } - contains Yellow: State subsets states { - redefine contains entryAction: SendAction { - redefine refers viaPort: Port = lightControl - redefine refers payload: Item = global_YellowL - } - } - contains UnnamedTransitionUsage12: Transition subsets transitions { - redefine refers from: StateNode = Yellow - redefine refers to: StateNode = Red - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = control - redefine refers payload: Item = global_Toggle - } - } - contains Red: State subsets states { - redefine contains entryAction: SendAction { - redefine refers viaPort: Port = lightControl - redefine refers payload: Item = global_RedL - } - } - contains UnnamedTransitionUsage13: Transition subsets transitions { - redefine refers from: StateNode = Red - redefine refers to: StateNode = Green - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = control - redefine refers payload: Item = global_Toggle - } - } - contains Green: State subsets states { - redefine contains entryAction: SendAction { - redefine refers viaPort: Port = lightControl - redefine refers payload: Item = global_GreenL - } - } - contains UnnamedTransitionUsage14: Transition subsets transitions { - redefine refers from: StateNode = Green - redefine refers to: StateNode = Yellow - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = control - redefine refers payload: Item = global_Toggle - } - } - } - contains UnnamedTransitionUsage15: Transition subsets transitions { - redefine refers from: StateNode = Normal - redefine refers to: StateNode = Interrupted - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = control - redefine refers payload: Item = global_Police - } - } - contains UnnamedTransitionUsage16: Transition subsets transitions { - redefine refers from: StateNode = Interrupted - redefine refers to: StateNode = Normal - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = control - redefine refers payload: Item = global_Police - } - } - contains Interrupted: State subsets states { - contains UnnamedTransitionUsage17: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = Yellow - } - contains Yellow: State subsets states { - redefine contains entryAction: SendAction { - redefine refers viaPort: Port = lightControl - redefine refers payload: Item = global_YellowL - } - } - contains UnnamedTransitionUsage18: Transition subsets transitions { - redefine refers from: StateNode = Yellow - redefine refers to: StateNode = Black - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 1 - } - } - contains UnnamedTransitionUsage19: Transition subsets transitions { - redefine refers from: StateNode = Black - redefine refers to: StateNode = Yellow - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 1 - } - } - contains Black: State subsets states { - redefine contains entryAction: SendAction { - redefine refers viaPort: Port = lightControl - redefine refers payload: Item = global_NoneL - } - } - } - } -} -class CrossroadSystem : Part { - contains controller: CentralController subsets parts - contains trafficLightA: TrafficLightController subsets parts - contains trafficLightB: TrafficLightController subsets parts - refers control: ConjugatedCentralControl subsets ports = controller.control - contains UnnamedFlowConnectionUsage0: Flow subsets flows { - redefine refers inputPort: Port = controller.controlA - redefine refers outputPort: Port = trafficLightA.control - } - contains UnnamedFlowConnectionUsage1: Flow subsets flows { - redefine refers inputPort: Port = controller.controlB - redefine refers outputPort: Port = trafficLightB.control - } -} -@VerificationCase -class ControllerOperatingReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.controller.Behaviour.Operating - } - } - } - } -} -@VerificationCase -class ControllerOperatingBothYellowReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.controller.Behaviour.Operating.BothYellow - } - } - } - } -} -@VerificationCase -class ControllerOperatingBothRedReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.controller.Behaviour.Operating.BothRed - } - } - } - } -} -@VerificationCase -class ControllerOperatingTrafficOnAReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.controller.Behaviour.Operating.TrafficOnA - } - } - } - } -} -@VerificationCase -class ControllerOperatingStoppingAReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.controller.Behaviour.Operating.StoppingA - } - } - } - } -} -@VerificationCase -class ControllerOperatingTrafficOnBReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.controller.Behaviour.Operating.TrafficOnB - } - } - } - } -} -@VerificationCase -class ControllerOperatingStoppingBReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.controller.Behaviour.Operating.StoppingB - } - } - } - } -} -@VerificationCase -class ControllerInterruptedReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.controller.Behaviour.Interrupted - } - } - } - } -} -@VerificationCase -class TrafficLightABehaviorNormalReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal - } - } - } - } -} -@VerificationCase -class TrafficLightABehaviorNormalYellowReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Yellow - } - } - } - } -} -@VerificationCase -class TrafficLightABehaviorNormalRedReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Red - } - } - } - } -} -@VerificationCase -class TrafficLightABehaviorNormalGreenReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Green - } - } - } - } -} -@VerificationCase -class TrafficLightABehaviorInterruptedReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Interrupted - } - } - } - } -} -@VerificationCase -class TrafficLightABehaviorInterruptedYellowReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Interrupted.Yellow - } - } - } - } -} -@VerificationCase -class TrafficLightABehaviorInterruptedBlackReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Interrupted.Black - } - } - } - } -} -@VerificationCase -class TrafficLightBBehaviorNormalReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal - } - } - } - } -} -@VerificationCase -class TrafficLightBBehaviorNormalYellowReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Yellow - } - } - } - } -} -@VerificationCase -class TrafficLightBBehaviorNormalRedReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Red - } - } - } - } -} -@VerificationCase -class TrafficLightBBehaviorNormalGreenReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Green - } - } - } - } -} -@VerificationCase -class TrafficLightBBehaviorInterruptedReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Interrupted - } - } - } - } -} -@VerificationCase -class TrafficLightBBehaviorInterruptedYellowReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Interrupted.Yellow - } - } - } - } -} -@VerificationCase -class TrafficLightBBehaviorInterruptedBlackReachable : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Interrupted.Black - } - } - } - } -} -@VerificationCase -class ReachableRedRed : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: AndOperatorExpression { - redefine contains left: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Red - } - redefine contains right: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Red - } - } - } - } - } -} -@VerificationCase -class ReachableRedGreen : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: AndOperatorExpression { - redefine contains left: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Red - } - redefine contains right: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Green - } - } - } - } - } -} -@VerificationCase -class ReachableRedYellow : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: AndOperatorExpression { - redefine contains left: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Red - } - redefine contains right: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Yellow - } - } - } - } - } -} -@VerificationCase -class ReachableGreenRed : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: AndOperatorExpression { - redefine contains left: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Green - } - redefine contains right: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Red - } - } - } - } - } -} -@VerificationCase -class UnreachableGreenGreen : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: UnaryNotExpression { - redefine contains operand: Eventually { - redefine contains body: AndOperatorExpression { - redefine contains left: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Green - } - redefine contains right: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Green - } - } - } - } - } - } -} -@VerificationCase -class UnreachableGreenYellow : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: UnaryNotExpression { - redefine contains operand: Eventually { - redefine contains body: AndOperatorExpression { - redefine contains left: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Green - } - redefine contains right: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Yellow - } - } - } - } - } - } -} -@VerificationCase -class ReachableYellowRed : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: AndOperatorExpression { - redefine contains left: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Yellow - } - redefine contains right: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Red - } - } - } - } - } -} -@VerificationCase -class UnreachableYellowGreen : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: UnaryNotExpression { - redefine contains operand: Eventually { - redefine contains body: AndOperatorExpression { - redefine contains left: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Yellow - } - redefine contains right: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Green - } - } - } - } - } - } -} -@VerificationCase -class ReachableYellowYellow : VerificationCaseDefinition { - contains system: CrossroadSystem[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: AndOperatorExpression { - redefine contains left: IsStateActiveExpression { - redefine refers state: State = system.trafficLightA.Behaviour.Normal.Yellow - } - redefine contains right: IsStateActiveExpression { - redefine refers state: State = system.trafficLightB.Behaviour.Normal.Yellow - } - } - } - } - } -} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/models26.example.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/models26.example.oxsts deleted file mode 100644 index 3772127d..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/models26.example.oxsts +++ /dev/null @@ -1,62 +0,0 @@ -package models26::example - -import semantifyr::sysml::expressions -import semantifyr::sysml::actions -import semantifyr::sysml::attributes - -@VerificationCase -class IncrementAttribute { - - contains x: IntegerAttribute { - redefine refers defaultValue: int = 10 - } - contains y: IntegerAttribute { - redefine refers defaultValue: int = 100 - } - contains xLTy : LessThanOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: IntegerAttribute = x - } - redefine contains right: AttributeReferenceExpression { - redefine refers attribute: IntegerAttribute = y - } - } - contains composite: CompositeAction { - contains incX: AssignmentAction subsets children { - redefine refers attribute: IntegerAttribute = x - redefine contains expression: PlusOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: IntegerAttribute = x - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 10 - } - } - } - contains decY: AssignmentAction subsets children { - redefine refers attribute: IntegerAttribute = y - redefine contains expression: MinusOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: IntegerAttribute = y - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 10 - } - } - } - } - - redefine init { - inline x.init() - inline y.init() - } - - redefine tran { - inline composite.main() - } - - prop { - return EF xLTy.evaluate() - } - -} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts deleted file mode 100644 index 6e10d557..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/spacecraft.oxsts +++ /dev/null @@ -1,1035 +0,0 @@ -package semantifyr::sysml::model - -import semantifyr::sysml::expressions -import semantifyr::sysml::attributes -import semantifyr::sysml::states -import semantifyr::sysml::parts -import semantifyr::sysml::ports -import semantifyr::sysml::items -import semantifyr::sysml::actions -import semantifyr::sysml::triggers -import semantifyr::sysml::verification - -class GroundStation : Part { - contains commandPort: CommandPort subsets ports - contains spacecraftCommandPort: ConjugatedCommandPort subsets ports - contains dataPort: ConjugatedDataPort subsets ports - contains receivedData: IntegerAttribute subsets attributes { - redefine refers defaultValue: int = 0 - } - contains Behaviour: State redefines exhibitState { - contains UnnamedTransitionUsage0: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = Idle - } - contains Idle: State subsets states - contains UnnamedTransitionUsage1: Transition subsets transitions { - redefine refers from: StateNode = Idle - redefine refers to: StateNode = Operation - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 30 - } - } - contains UnnamedTransitionUsage2: Transition subsets transitions { - redefine refers from: StateNode = Idle - redefine refers to: StateNode = Operation - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = commandPort - redefine refers payload: Item = global_StartCommand - } - } - contains Operation: State subsets states { - redefine contains entryAction: SendAction { - redefine refers viaPort: Port = spacecraftCommandPort - redefine refers payload: Item = global_PingCommand - } - contains UnnamedTransitionUsage3: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = Waiting - } - contains Waiting: State subsets states - contains UnnamedTransitionUsage4: Transition subsets transitions { - redefine refers from: StateNode = Waiting - redefine refers to: StateNode = Waiting - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = dataPort - redefine refers payload: Item = global_Data - } - redefine contains guard: Guard { - redefine contains expression: LessThanOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 100 - } - } - } - redefine contains action: AssignmentAction { - redefine refers attribute: Attribute = receivedData - redefine contains expression: PlusOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 10 - } - } - } - } - } - contains UnnamedTransitionUsage5: Transition subsets transitions { - redefine refers from: StateNode = Operation - redefine refers to: StateNode = Operation - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 10 - } - } - } -} -class Spacecraft : Part { - contains commandPort: CommandPort subsets ports - contains dataPort: DataPort subsets ports - contains batteryCharge: IntegerAttribute subsets attributes { - redefine refers defaultValue: int = 100 - } - contains recharging: BooleanAttribute subsets attributes { - redefine refers defaultValue: bool = false - } - contains data: IntegerAttribute subsets attributes { - redefine refers defaultValue: int = 100 - } - contains Behaviour: ParallelState redefines exhibitState { - contains Communication: State subsets states { - contains UnnamedTransitionUsage6: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = WaitingPing - } - contains WaitingPing: State subsets states - contains UnnamedTransitionUsage7: Transition subsets transitions { - redefine refers from: StateNode = WaitingPing - redefine refers to: StateNode = Transmitting - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = commandPort - redefine refers payload: Item = global_PingCommand - } - redefine contains guard: Guard { - redefine contains expression: AndOperatorExpression { - redefine contains left: EqualityOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = recharging - } - redefine contains right: LiteralBooleanExpression { - redefine refers value: bool = false - } - } - redefine contains right: UnaryNotExpression { - redefine contains operand: OrOperatorExpression { - redefine contains left: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 0 - } - } - redefine contains right: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 - } - } - } - } - } - } - } - contains Transmitting: ParallelState subsets states { - contains SendData: State subsets states { - contains UnnamedTransitionUsage8: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = Sending - } - contains Sending: State subsets states - contains UnnamedTransitionUsage9: Transition subsets transitions { - redefine refers from: StateNode = Sending - redefine refers to: StateNode = Sending - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 4 - } - redefine contains guard: Guard { - redefine contains expression: UnaryNotExpression { - redefine contains operand: OrOperatorExpression { - redefine contains left: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 0 - } - } - redefine contains right: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 - } - } - } - } - } - redefine contains action: CompositeAction { - contains UnnamedAssignmentActionUsage0: AssignmentAction subsets children { - redefine refers attribute: Attribute = data - redefine contains expression: MinusOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 10 - } - } - } - contains UnnamedSendActionUsage0: SendAction subsets children { - redefine refers viaPort: Port = dataPort - redefine refers payload: Item = global_Data - } - } - } - } - contains ConsumePower: State subsets states { - contains UnnamedTransitionUsage10: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = Consuming - } - contains Consuming: State subsets states - contains UnnamedTransitionUsage11: Transition subsets transitions { - redefine refers from: StateNode = Consuming - redefine refers to: StateNode = Consuming - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 2 - } - redefine contains guard: Guard { - redefine contains expression: UnaryNotExpression { - redefine contains operand: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 - } - } - } - } - redefine contains action: AssignmentAction { - redefine refers attribute: Attribute = batteryCharge - redefine contains expression: MinusOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 10 - } - } - } - } - } - } - contains UnnamedTransitionUsage12: Transition subsets transitions { - redefine refers from: StateNode = Transmitting - redefine refers to: StateNode = WaitingPing - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 4 - } - redefine contains guard: Guard { - redefine contains expression: OrOperatorExpression { - redefine contains left: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 0 - } - } - redefine contains right: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 - } - } - } - } - } - contains UnnamedTransitionUsage13: Transition subsets transitions { - redefine refers from: StateNode = Transmitting - redefine refers to: StateNode = WaitingPing - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 4 - } - redefine contains guard: Guard { - redefine contains expression: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 - } - } - } - } - } - contains Battery: State subsets states { - contains UnnamedTransitionUsage14: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = NotRecharging - } - contains NotRecharging: State subsets states { - redefine contains entryAction: AssignmentAction { - redefine refers attribute: Attribute = recharging - redefine contains expression: LiteralBooleanExpression { - redefine refers value: bool = false - } - } - } - contains Recharging: State subsets states { - redefine contains entryAction: AssignmentAction { - redefine refers attribute: Attribute = recharging - redefine contains expression: LiteralBooleanExpression { - redefine refers value: bool = true - } - } - } - contains UnnamedTransitionUsage15: Transition subsets transitions { - redefine refers from: StateNode = NotRecharging - redefine refers to: StateNode = Recharging - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 3 - } - redefine contains guard: Guard { - redefine contains expression: LessThanOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 80 - } - } - } - } - contains UnnamedTransitionUsage16: Transition subsets transitions { - redefine refers from: StateNode = Recharging - redefine refers to: StateNode = Recharging - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 3 - } - redefine contains guard: Guard { - redefine contains expression: LessThanOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 100 - } - } - } - redefine contains action: AssignmentAction { - redefine refers attribute: Attribute = batteryCharge - redefine contains expression: PlusOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 10 - } - } - } - } - contains UnnamedTransitionUsage17: Transition subsets transitions { - redefine refers from: StateNode = Recharging - redefine refers to: StateNode = NotRecharging - redefine contains acceptAction: AcceptTimeoutAction { - redefine refers afterTime: int = 3 - } - redefine contains guard: Guard { - redefine contains expression: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 100 - } - } - } - } - } - } -} -class Data : Item -global containment global_Data: Data[1] -class Command : Item -global containment global_Command: Command[1] -class PingCommand : Item -global containment global_PingCommand: PingCommand[1] -class StopCommand : Item -global containment global_StopCommand: StopCommand[1] -class StartCommand : Item -global containment global_StartCommand: StartCommand[1] -class CommandPort : NormalPort { - refers command: Command subsets incomingItems = global_Command -} -class ConjugatedCommandPort : ConjugatedPort { - refers command: Command subsets incomingItems = global_Command -} -class DataPort : NormalPort { - refers data: Data subsets outgoingItems = global_Data -} -class ConjugatedDataPort : ConjugatedPort { - refers data: Data subsets outgoingItems = global_Data -} -class Mission : Part { - contains groundStation: GroundStation subsets parts - contains spacecraft: Spacecraft subsets parts - refers commandPort: CommandPort subsets ports = groundStation.commandPort - contains UnnamedFlowConnectionUsage0: Flow subsets flows { - redefine refers inputPort: Port = groundStation.spacecraftCommandPort - redefine refers outputPort: Port = spacecraft.commandPort - } - contains UnnamedFlowConnectionUsage1: Flow subsets flows { - redefine refers inputPort: Port = spacecraft.dataPort - redefine refers outputPort: Port = groundStation.dataPort - } -} -@VerificationCase -class StationBehaviorIdleReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.groundStation.Behaviour.Idle - } - } - } - } -} -@VerificationCase -class StationBehaviorOperationReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.groundStation.Behaviour.Operation - } - } - } - } -} -@VerificationCase -class StationBehaviorOperationWaitingReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.groundStation.Behaviour.Operation.Waiting - } - } - } - } -} -@VerificationCase -class SpacecraftBehaviorCommunicationWaitingPingReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.spacecraft.Behaviour.Communication.WaitingPing - } - } - } - } -} -@VerificationCase -class SpacecraftBehaviorCommunicationTransmittingReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.spacecraft.Behaviour.Communication.Transmitting - } - } - } - } -} -@VerificationCase -class SpacecraftBehaviorCommunicationTransmittingSendDataReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.spacecraft.Behaviour.Communication.Transmitting.SendData - } - } - } - } -} -@VerificationCase -class SpacecraftBehaviorCommunicationTransmittingSendDataSendingReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.spacecraft.Behaviour.Communication.Transmitting.SendData.Sending - } - } - } - } -} -@VerificationCase -class SpacecraftBehaviorCommunicationTransmittingConsumePowerReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.spacecraft.Behaviour.Communication.Transmitting.ConsumePower - } - } - } - } -} -@VerificationCase -class SpacecraftBehaviorCommunicationTransmittingConsumePowerConsumingReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.spacecraft.Behaviour.Communication.Transmitting.ConsumePower.Consuming - } - } - } - } -} -@VerificationCase -class SpacecraftBehaviorBatteryNotRechargingReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.spacecraft.Behaviour.Battery.NotRecharging - } - } - } - } -} -@VerificationCase -class SpacecraftBehaviorBatteryRechargingReachable : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = mission.spacecraft.Behaviour.Battery.Recharging - } - } - } - } -} -@VerificationCase -class GroundStationReceivedDataCanReach0 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 0 - } - } - } - } - } -} -@VerificationCase -class GroundStationReceivedDataCanReach10 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 10 - } - } - } - } - } -} -@VerificationCase -class GroundStationReceivedDataCanReach20 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 30 - } - } - } - } - } -} -@VerificationCase -class GroundStationReceivedDataCanReach30 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 30 - } - } - } - } - } -} -@VerificationCase -class GroundStationReceivedDataCanReach40 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 - } - } - } - } - } -} -@VerificationCase -class GroundStationReceivedDataCanReach50 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 50 - } - } - } - } - } -} -@VerificationCase -class GroundStationReceivedDataCanReach60 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 60 - } - } - } - } - } -} -@VerificationCase -class GroundStationReceivedDataCanReach70 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 70 - } - } - } - } - } -} -@VerificationCase -class SpacecraftDataCanReach100 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 100 - } - } - } - } - } -} -@VerificationCase -class SpacecraftDataCanReach90 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 90 - } - } - } - } - } -} -@VerificationCase -class SpacecraftDataCanReach80 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 80 - } - } - } - } - } -} -@VerificationCase -class SpacecraftDataCanReach70 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 70 - } - } - } - } - } -} -@VerificationCase -class SpacecraftDataCanReach60 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 60 - } - } - } - } - } -} -@VerificationCase -class SpacecraftDataCanReach50 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 50 - } - } - } - } - } -} -@VerificationCase -class SpacecraftDataCanReach40 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 - } - } - } - } - } -} -@VerificationCase -class SpacecraftDataCanReach30 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 30 - } - } - } - } - } -} -@VerificationCase -class SpacecraftBatteryAlwaysAbove0 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 0 - } - } - } - } -} -@VerificationCase -class SpacecraftBatteryAlwaysAbove10 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 10 - } - } - } - } -} -@VerificationCase -class SpacecraftBatteryAlwaysAbove20 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 20 - } - } - } - } -} -@VerificationCase -class SpacecraftBatteryAlwaysAbove30 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 30 - } - } - } - } -} -@VerificationCase -class SpacecraftBatteryAlwaysAbove40 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.batteryCharge - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 40 - } - } - } - } -} - -// manually added slow verification cases - -@Tag("slow") -@VerificationCase -class GroundStationReceivedDataCanReach80 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 80 - } - } - } - } - } -} -@Tag("slow") -@VerificationCase -class GroundStationReceivedDataCanReach90 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 90 - } - } - } - } - } -} -@Tag("slow") -@VerificationCase -class GroundStationReceivedDataCanReach100 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: GreaterThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.groundStation.receivedData - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 100 - } - } - } - } - } -} - -@Tag("slow") -@VerificationCase -class SpacecraftDataCanReach20 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 20 - } - } - } - } - } -} -@Tag("slow") -@VerificationCase -class SpacecraftDataCanReach10 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 10 - } - } - } - } - } -} -@Tag("slow") -@VerificationCase -class SpacecraftDataCanReach0 : VerificationCaseDefinition { - contains mission: Mission[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: LessThanOrEqualsOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = mission.spacecraft.data - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 0 - } - } - } - } - } -} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm21.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm21.oxsts deleted file mode 100644 index 5c5253d6..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm21.oxsts +++ /dev/null @@ -1,113 +0,0 @@ -package semantifyr::sysml::model - -import semantifyr::sysml::expressions -import semantifyr::sysml::attributes -import semantifyr::sysml::states -import semantifyr::sysml::parts -import semantifyr::sysml::ports -import semantifyr::sysml::items -import semantifyr::sysml::actions -import semantifyr::sysml::triggers -import semantifyr::sysml::verification - -class F : Item -global containment global_F: F[1] -class G : Item -global containment global_G: G[1] -class InputEvents : NormalPort { - refers f: F subsets incomingItems = global_F - refers g: G subsets incomingItems = global_G -} -class ConjugatedInputEvents : ConjugatedPort { - refers f: F subsets incomingItems = global_F - refers g: G subsets incomingItems = global_G -} -class Stm21 : Part { - contains input: InputEvents subsets ports - contains Behaviour: ParallelState redefines exhibitState { - contains R1: State subsets states { - contains S11: State subsets states - contains S12: State subsets states - contains UnnamedTransitionUsage0: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = S11 -} - contains UnnamedTransitionUsage1: Transition subsets transitions { - redefine refers from: StateNode = S11 - redefine refers to: StateNode = S12 - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = input - redefine refers payload: Item = global_F - } - } - } - contains R2: State subsets states { - contains S13: State subsets states - contains S14: State subsets states - contains UnnamedTransitionUsage2: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = S13 -} - contains UnnamedTransitionUsage3: Transition subsets transitions { - redefine refers from: StateNode = S13 - redefine refers to: StateNode = S14 - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = input - redefine refers payload: Item = global_G - } - } - } - } -} -@VerificationCase -class S11Reachable : VerificationCaseDefinition { - contains system: Stm21[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.Behaviour.R1.S11 - } - } - } - } -} -@VerificationCase -class S12Reachable : VerificationCaseDefinition { - contains system: Stm21[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.Behaviour.R1.S12 - } - } - } - } -} -@VerificationCase -class S13Reachable : VerificationCaseDefinition { - contains system: Stm21[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.Behaviour.R2.S13 - } - } - } - } -} -@VerificationCase -class S14Reachable : VerificationCaseDefinition { - contains system: Stm21[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.Behaviour.R2.S14 - } - } - } - } -} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm31.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm31.oxsts deleted file mode 100644 index edd77e01..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/models/stm31.oxsts +++ /dev/null @@ -1,158 +0,0 @@ -package semantifyr::sysml::model - -import semantifyr::sysml::expressions -import semantifyr::sysml::attributes -import semantifyr::sysml::states -import semantifyr::sysml::parts -import semantifyr::sysml::ports -import semantifyr::sysml::items -import semantifyr::sysml::actions -import semantifyr::sysml::triggers -import semantifyr::sysml::verification - -class A : Item -global containment global_A: A[1] -class B : Item -global containment global_B: B[1] -class C : Item -global containment global_C: C[1] -class D : Item -global containment global_D: D[1] -class X : Item -global containment global_X: X[1] -class E : Item -global containment global_E: E[1] -class OutputEvents : NormalPort { - refers a: A subsets outgoingItems = global_A - refers b: B subsets outgoingItems = global_B - refers c: C subsets outgoingItems = global_C - refers d: D subsets outgoingItems = global_D - refers x: X subsets outgoingItems = global_X -} -class ConjugatedOutputEvents : ConjugatedPort { - refers a: A subsets outgoingItems = global_A - refers b: B subsets outgoingItems = global_B - refers c: C subsets outgoingItems = global_C - refers d: D subsets outgoingItems = global_D - refers x: X subsets outgoingItems = global_X -} -class InputEvents : NormalPort { - refers e: E subsets incomingItems = global_E -} -class ConjugatedInputEvents : ConjugatedPort { - refers e: E subsets incomingItems = global_E -} -class Stm31 : Part { - contains i: IntegerAttribute subsets attributes { - redefine refers defaultValue: int = 0 - } - contains input: InputEvents subsets ports - contains output: OutputEvents subsets ports - contains Behaviour: State redefines exhibitState { - contains S1: State subsets states { - redefine contains entryAction: CompositeAction { - contains UnnamedSendActionUsage0: SendAction subsets children { - redefine refers viaPort: Port = output - redefine refers payload: Item = global_A - } - } - redefine contains exitAction: CompositeAction { - contains UnnamedAssignmentActionUsage0: AssignmentAction subsets children { - redefine refers attribute: Attribute = i - redefine contains expression: PlusOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = i - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 1 - } - } - } - contains UnnamedSendActionUsage1: SendAction subsets children { - redefine refers viaPort: Port = output - redefine refers payload: Item = global_B - } - } - } - contains S2: State subsets states { - redefine contains entryAction: CompositeAction { - contains UnnamedAssignmentActionUsage1: AssignmentAction subsets children { - redefine refers attribute: Attribute = i - redefine contains expression: MultiplicationOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = i - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 2 - } - } - } - contains UnnamedSendActionUsage2: SendAction subsets children { - redefine refers viaPort: Port = output - redefine refers payload: Item = global_C - } - } - redefine contains exitAction: CompositeAction { - contains UnnamedSendActionUsage3: SendAction subsets children { - redefine refers viaPort: Port = output - redefine refers payload: Item = global_D - } - } - } - contains UnnamedTransitionUsage0: Transition subsets transitions { - redefine refers from: StateNode = start - redefine refers to: StateNode = S1 -} - contains UnnamedTransitionUsage1: Transition subsets transitions { - redefine refers from: StateNode = S1 - redefine refers to: StateNode = S2 - redefine contains acceptAction: AcceptItemAction { - redefine refers viaPort: Port = input - redefine refers payload: Item = global_E - } - redefine contains action: CompositeAction { - contains UnnamedAssignmentActionUsage2: AssignmentAction subsets children { - redefine refers attribute: Attribute = i - redefine contains expression: PlusOperatorExpression { - redefine contains left: AttributeReferenceExpression { - redefine refers attribute: Attribute = i - } - redefine contains right: LiteralIntegerExpression { - redefine refers value: int = 1 - } - } - } - contains UnnamedSendActionUsage4: SendAction subsets children { - redefine refers viaPort: Port = output - redefine refers payload: Item = global_D - } - } - } - } -} -@VerificationCase -class S1Reachable : VerificationCaseDefinition { - contains system: Stm31[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.Behaviour.S1 - } - } - } - } -} -@VerificationCase -class S2Reachable : VerificationCaseDefinition { - contains system: Stm31[1] redefines subject - redefine contains objective: Requirement[1] { - redefine contains verifyRequirement : Constraint[1] { - redefine contains requiredConstraint: Eventually { - redefine contains body: IsStateActiveExpression { - redefine refers state: State = system.Behaviour.S2 - } - } - } - } -} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLTransformer.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLTransformer.kt new file mode 100644 index 00000000..cc23a257 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLTransformer.kt @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.frontends.sysml.semantics + +import java.io.File + +class StandaloneSysMLTransformer { + + fun transformModel(modelPath: File, outputPath: File? = null) { + val outputFile = outputPath ?: File(modelPath.absolutePath.replace(".sysml", ".oxsts")) + + val process = ProcessBuilder("node", "build/cli/index.js", "compile", modelPath.absolutePath, "build/cli/sysml.library", "-o", outputFile.absolutePath) + .redirectErrorStream(true) + .start() + + val output = process.inputStream.bufferedReader().readText() + val exitCode = process.waitFor() + + if (exitCode != 0) { + error("SysML compilation failed with exit code $exitCode:\n$output") + } + } + +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt similarity index 85% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index 6b77ec4e..a3314236 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -44,44 +44,53 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() } - private fun loadModel(path: String): SemantifyrModelContext { + val transformer = StandaloneSysMLTransformer() + + private fun loadModel(model: String): SemantifyrModelContext { + val sysmlModelPath = Path(model) + val sysmlModel = sysmlModelPath.toFile() + val oxstsModelPath = Path(sysmlModel.absolutePath.replace(".sysml", ".oxsts")) + val oxstsModel = oxstsModelPath.toFile() + + transformer.transformModel(sysmlModel, oxstsModel) + return semantifyrVerificationHelper.semantifyrLoader.startContext() .loadLibraries(Path("Library")) - .loadModel(Path(path)) + .loadModel(oxstsModelPath) .buildAndResolve() } @JvmStatic fun `STM21 Model Verification Cases Should Pass`(): Stream { - val model = loadModel("models/stm21.oxsts") + val model = loadModel("TestModels/stm21.sysml") return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() } @JvmStatic fun `STM31 Model Verification Cases Should Pass`(): Stream { - val model = loadModel("models/stm31.oxsts") + val model = loadModel("TestModels/stm31.sysml") return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() } @JvmStatic fun `Crossroads Model Verification Cases Should Pass`(): Stream { - val model = loadModel("models/crossroads.oxsts") + val model = loadModel("TestModels/crossroads.sysml") return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() } @JvmStatic fun `Spacecraft Model Verification Cases Should Pass`(): Stream { - val model = loadModel("models/spacecraft.oxsts") + val model = loadModel("TestModels/spacecraft.sysml") return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() } @JvmStatic fun `Slow Spacecraft Model Verification Cases Should Pass`(): Stream { - val model = loadModel("models/spacecraft.oxsts") + val model = loadModel("TestModels/spacecraft.sysml") return semantifyrVerificationHelper.collectSlowVerificationCases(model).asStream() } From f6de0586c796a7e04c0217f3ee9d4207e53c86ec Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 12:51:09 +0100 Subject: [PATCH 050/115] Added build task as dependency. Technically not needed, as building only outputs the .js files from tsc, however, it would be difficult to correctly specify the inputs of this task, and a depdency does not hurt here either way. At least bundling will not start if the project can not be built anyway. --- .../frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index f95e8da4..f66013d8 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -71,7 +71,9 @@ val bundleExtension by tasks.registering(PnpmTask::class) { } val bundleCli by tasks.registering(PnpmTask::class) { - dependsOn(tasks.pnpmInstall) // node_modules directory is not reliable + // not needed, but it would be difficult to exclude the outputs of building the extension + dependsOn(buildExtension) + dependsOn(tasks.pnpmInstall) inputs.files(fileTree("sysml-2ls") { include("**/src/**/*.ts") include("**/tsconfig.json") From 00ab31918b5c2c5b344d6fc0a68f8b1693775a74 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 12:53:21 +0100 Subject: [PATCH 051/115] Added license to .gitmodules file --- .gitmodules | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitmodules b/.gitmodules index c7d92687..e69aec2f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2026 The Semantifyr Authors +# +# SPDX-License-Identifier: EPL-2.0 + [submodule "subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls"] path = subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls url = git@github.com:arminzavada/sysml-2ls.git From e1324057b4fd46e5876d48849156870ae506f605 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 12:55:34 +0100 Subject: [PATCH 052/115] Specified the .vsix file directly --- .../frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index f66013d8..e809ec22 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -56,11 +56,7 @@ val buildExtension by tasks.registering(PnpmTask::class) { val bundleExtension by tasks.registering(PnpmTask::class) { dependsOn(buildExtension) - outputs.file( - fileTree("sysml-2ls") { - include("packages/syside-vscode/*.vsix") - } - ) + outputs.file("sysml-2ls/packages/syside-vscode/sysml-2ls-0.9.0.vsix") pnpmCommand.set( listOf( From df8e48ae90fa959911f6dae52a0501cb4d3cc342 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 14:12:48 +0100 Subject: [PATCH 053/115] Checkout action should use submodules --- .github/workflows/build.yml | 2 ++ .github/workflows/verification.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f91b4028..cd815148 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,6 +25,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v6 + with: + submodules: true - name: Set up JDK uses: actions/setup-java@v5 with: diff --git a/.github/workflows/verification.yml b/.github/workflows/verification.yml index 50468cdc..e68804c5 100644 --- a/.github/workflows/verification.yml +++ b/.github/workflows/verification.yml @@ -25,6 +25,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v6 + with: + submodules: true - name: Set up JDK uses: actions/setup-java@v5 with: From 35681911f360b6782773625b4078325ecdcd2ed5 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 14:21:16 +0100 Subject: [PATCH 054/115] Removed setup-node step. Multiple inner subprojects are not supported, especially using npm and pnpm in parallel. --- .github/workflows/build.yml | 6 ------ .../frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 4 +--- subprojects/semantifyr-vscode/build.gradle.kts | 4 +--- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cd815148..76f8669b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,12 +34,6 @@ jobs: distribution: adopt - name: Setup Gradle uses: gradle/actions/setup-gradle@v5 - - name: Setup Node - uses: actions/setup-node@v6 - with: - node-version: 22 - cache: 'npm' - cache-dependency-path: 'subprojects/semantifyr-vscode/package-lock.json' - name: Gradle build shell: bash run: ./gradlew build diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index e809ec22..2dc1d3a4 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -12,11 +12,9 @@ plugins { alias(libs.plugins.gradle.node) } -val isCi: Boolean = System.getenv("CI") != null - node { version = "22.14.0" - download = !isCi + download = true nodeProjectDir = project.layout.projectDirectory.dir("sysml-2ls") } diff --git a/subprojects/semantifyr-vscode/build.gradle.kts b/subprojects/semantifyr-vscode/build.gradle.kts index 7bb0dc58..6dcc8568 100644 --- a/subprojects/semantifyr-vscode/build.gradle.kts +++ b/subprojects/semantifyr-vscode/build.gradle.kts @@ -11,11 +11,9 @@ plugins { alias(libs.plugins.gradle.node) } -val isCi: Boolean = System.getenv("CI") != null - node { version = "22.14.0" - download = !isCi + download = true } val distributionOutput by configurations.creating { From 365d2b3ac065de37e2f12d7bdaabccd8d3730160 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 14:52:41 +0100 Subject: [PATCH 055/115] Disabled slow tests for now. --- .../frontends/sysml/semantics/SysMLVerificationTests.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index a3314236..1361a29b 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -136,6 +136,7 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { checkVerificationCase(verificationCase) } + @Disabled("The frontend does not add the @Tag('slow') yet") @Tag("slow") @ParameterizedTest @MethodSource From 0cef7d1c035b35fc7a55cf76edc47f86102a6a92 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 16:02:43 +0100 Subject: [PATCH 056/115] Removed sysml-2ls submodule --- .github/workflows/build.yml | 2 - .gitmodules | 7 ---- .../sysmlv2/sysmlv2-frontend/.gitignore | 5 +++ .../sysmlv2/sysmlv2-frontend/README.md | 1 + .../sysmlv2/sysmlv2-frontend/build.gradle.kts | 19 +++++++++- .../sysmlv2-frontend/scripts/checkout.cmd | 37 +++++++++++++++++++ .../sysmlv2-frontend/scripts/checkout.sh | 27 ++++++++++++++ .../sysmlv2/sysmlv2-frontend/sysml-2ls | 1 - 8 files changed, 88 insertions(+), 11 deletions(-) delete mode 100644 .gitmodules create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-frontend/.gitignore create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-frontend/README.md create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd create mode 100755 subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh delete mode 160000 subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 76f8669b..5f1b4969 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,8 +25,6 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v6 - with: - submodules: true - name: Set up JDK uses: actions/setup-java@v5 with: diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69aec2f..00000000 --- a/.gitmodules +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: 2026 The Semantifyr Authors -# -# SPDX-License-Identifier: EPL-2.0 - -[submodule "subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls"] - path = subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls - url = git@github.com:arminzavada/sysml-2ls.git diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/.gitignore b/subprojects/frontends/sysmlv2/sysmlv2-frontend/.gitignore new file mode 100644 index 00000000..1cdc7762 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/.gitignore @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2026 The Semantifyr Authors +# +# SPDX-License-Identifier: EPL-2.0 + +sysml-2ls/ diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/README.md b/subprojects/frontends/sysmlv2/sysmlv2-frontend/README.md new file mode 100644 index 00000000..61806eee --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/README.md @@ -0,0 +1 @@ +Please do not modify the contents of the 'sysml-2ls' directory directly! Instead, clone it separately, then publish a PR with your changes. diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index 2dc1d3a4..f0358ee0 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -5,13 +5,26 @@ */ import com.github.gradle.node.pnpm.task.PnpmTask -import kotlin.io.path.isSymbolicLink plugins { base alias(libs.plugins.gradle.node) } +val sysml2lsCommit = "e9d675777390deabae2e620722288a2177271ab6" +val sysml2lsUrl = "git@github.com:arminzavada/sysml-2ls.git" +val sysml2lsDir = layout.projectDirectory.dir("sysml-2ls").asFile + +val checkoutSysml2ls by tasks.registering(Exec::class) { + inputs.property("sysml2lsUrl", sysml2lsUrl) + inputs.property("sysml2lsCommit", sysml2lsCommit) + outputs.dir(layout.projectDirectory.dir("sysml-2ls").dir(".git")) + + val isWindows = System.getProperty("os.name").lowercase().contains("win") + val script = if (isWindows) "scripts\\checkout.cmd" else "scripts/checkout.sh" + commandLine(script, sysml2lsDir.absolutePath, sysml2lsUrl, sysml2lsCommit) +} + node { version = "22.14.0" download = true @@ -28,6 +41,10 @@ val cliOutput by configurations.creating { isCanBeResolved = false } +tasks.pnpmInstall { + dependsOn(checkoutSysml2ls) +} + val buildExtension by tasks.registering(PnpmTask::class) { dependsOn(tasks.pnpmInstall) // node_modules directory is not reliable inputs.files(fileTree("sysml-2ls") { diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd new file mode 100644 index 00000000..59b7aa29 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd @@ -0,0 +1,37 @@ +@echo off + +rem SPDX-FileCopyrightText: 2026 The Semantifyr Authors +rem +rem SPDX-License-Identifier: EPL-2.0 + +setlocal + +set TARGET_DIR=%1 +set REMOTE_URL=%2 +set COMMIT=%3 + +if "%TARGET_DIR%"=="" goto usage +if "%REMOTE_URL%"=="" goto usage +if "%COMMIT%"=="" goto usage +goto main + +:usage +echo Usage: checkout.cmd ^ ^ ^ +exit /b 1 + +:main +if not exist "%TARGET_DIR%\.git" ( + git clone "%REMOTE_URL%" "%TARGET_DIR%" + if errorlevel 1 exit /b 1 +) + +cd /d "%TARGET_DIR%" +if errorlevel 1 exit /b 1 + +git fetch origin "%COMMIT%" +if errorlevel 1 exit /b 1 + +git checkout "%COMMIT%" +if errorlevel 1 exit /b 1 + +endlocal diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh new file mode 100755 index 00000000..6f7a4335 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env sh + +# +# SPDX-FileCopyrightText: 2026 The Semantifyr Authors +# +# SPDX-License-Identifier: EPL-2.0 +# + +set -e + +TARGET_DIR="$1" +REMOTE_URL="$2" +COMMIT="$3" + +if [ -z "$TARGET_DIR" ] || [ -z "$REMOTE_URL" ] || [ -z "$COMMIT" ]; then + echo "Usage: checkout.sh " + exit 1 +fi + +if [ ! -d "$TARGET_DIR/.git" ]; then + git clone "$REMOTE_URL" "$TARGET_DIR" +fi + +cd "$TARGET_DIR" + +git fetch origin "$COMMIT" +git checkout "$COMMIT" diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls b/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls deleted file mode 160000 index e9d67577..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/sysml-2ls +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e9d675777390deabae2e620722288a2177271ab6 From c1a7d360f7a06ef30419e0723e7bf51d43c39e2f Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 17:39:21 +0100 Subject: [PATCH 057/115] Updated the sysml-2ls module build --- .../sysmlv2/sysmlv2-frontend/.gitignore | 5 - .../sysmlv2/sysmlv2-frontend/build.gradle.kts | 122 ++++++++++++------ .../sysmlv2-frontend/scripts/checkout.cmd | 16 +-- .../sysmlv2-frontend/scripts/checkout.sh | 13 +- 4 files changed, 95 insertions(+), 61 deletions(-) delete mode 100644 subprojects/frontends/sysmlv2/sysmlv2-frontend/.gitignore diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/.gitignore b/subprojects/frontends/sysmlv2/sysmlv2-frontend/.gitignore deleted file mode 100644 index 1cdc7762..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-FileCopyrightText: 2026 The Semantifyr Authors -# -# SPDX-License-Identifier: EPL-2.0 - -sysml-2ls/ diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index f0358ee0..913d1e52 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -5,30 +5,35 @@ */ import com.github.gradle.node.pnpm.task.PnpmTask +import com.github.gradle.node.task.NodeTask +import org.apache.tools.ant.taskdefs.condition.Os plugins { base alias(libs.plugins.gradle.node) } -val sysml2lsCommit = "e9d675777390deabae2e620722288a2177271ab6" -val sysml2lsUrl = "git@github.com:arminzavada/sysml-2ls.git" -val sysml2lsDir = layout.projectDirectory.dir("sysml-2ls").asFile - -val checkoutSysml2ls by tasks.registering(Exec::class) { - inputs.property("sysml2lsUrl", sysml2lsUrl) - inputs.property("sysml2lsCommit", sysml2lsCommit) - outputs.dir(layout.projectDirectory.dir("sysml-2ls").dir(".git")) - - val isWindows = System.getProperty("os.name").lowercase().contains("win") - val script = if (isWindows) "scripts\\checkout.cmd" else "scripts/checkout.sh" - commandLine(script, sysml2lsDir.absolutePath, sysml2lsUrl, sysml2lsCommit) -} +val sysmlCommit = "e9d675777390deabae2e620722288a2177271ab6" +val sysmlUrl = "git@github.com:arminzavada/sysml-2ls.git" +val sysmlDir = layout.buildDirectory.dir("sysml-2ls").get() node { version = "22.14.0" download = true - nodeProjectDir = project.layout.projectDirectory.dir("sysml-2ls") + nodeProjectDir = sysmlDir +} + +abstract class PnpmService : BuildService +val pnpmService = gradle.sharedServices.registerIfAbsent("pnpmService", NpmService::class.java) { + maxParallelUsages.set(1) +} + +// node tasks must not run in parallel, as pnpm is sensitive to that +tasks.withType().configureEach { + usesService(pnpmService) +} +tasks.withType().configureEach { + usesService(pnpmService) } val distributionOutput by configurations.creating { @@ -41,13 +46,45 @@ val cliOutput by configurations.creating { isCanBeResolved = false } +val checkoutSysml by tasks.registering(Exec::class) { + inputs.property("sysmlUrl", sysmlUrl) + inputs.property("sysmlCommit", sysmlCommit) + inputs.dir("scripts") + outputs.dir(sysmlDir.dir(".git")) + + val script = if (Os.isFamily(Os.FAMILY_WINDOWS)) { + "scripts\\checkout.cmd" + } else { + "scripts/checkout.sh" + } + + commandLine(script, sysmlDir.asFile.absolutePath, sysmlUrl, sysmlCommit) +} + tasks.pnpmInstall { - dependsOn(checkoutSysml2ls) + usesService(pnpmService) + + dependsOn(checkoutSysml) +} + +val checkoutLibrary by tasks.registering(PnpmTask::class) { + dependsOn(tasks.pnpmInstall) // node_modules directory is not reliable + inputs.file(sysmlDir.file("packages/syside-languageserver/scripts/clone-sysml-release.mjs")) + outputs.dir(sysmlDir.dir("SysML-v2-Release")) + + pnpmCommand = listOf( + "run", + "prepare-validation", + ) } val buildExtension by tasks.registering(PnpmTask::class) { dependsOn(tasks.pnpmInstall) // node_modules directory is not reliable - inputs.files(fileTree("sysml-2ls") { + inputs.file(sysmlDir.file("package.json")) + inputs.file(sysmlDir.file("tsconfig.json")) + inputs.file(sysmlDir.file("tsconfig.build.json")) + inputs.file(sysmlDir.file("tsconfig.eslint.json")) + inputs.files(fileTree(sysmlDir.dir("packages")) { include("**/src/**/*.ts") include("**/tsconfig.json") include("**/package.json") @@ -55,7 +92,7 @@ val buildExtension by tasks.registering(PnpmTask::class) { include("**/scripts/*.*") include("**/scripts/*.*") }) - outputs.files(fileTree("sysml-2ls") { + outputs.files(fileTree(sysmlDir.dir("packages")) { exclude("**/node_modules/**") include("**/lib/**") include("**/dist/**") @@ -71,7 +108,19 @@ val buildExtension by tasks.registering(PnpmTask::class) { val bundleExtension by tasks.registering(PnpmTask::class) { dependsOn(buildExtension) - outputs.file("sysml-2ls/packages/syside-vscode/sysml-2ls-0.9.0.vsix") + inputs.file(sysmlDir.file("package.json")) + inputs.file(sysmlDir.file("tsconfig.json")) + inputs.file(sysmlDir.file("tsconfig.build.json")) + inputs.file(sysmlDir.file("tsconfig.eslint.json")) + inputs.files(fileTree(sysmlDir.dir("packages")) { + include("**/src/**/*.ts") + include("**/tsconfig.json") + include("**/package.json") + include("**/package-lock.json") + include("**/scripts/*.*") + include("**/scripts/*.*") + }) + outputs.file(sysmlDir.file("packages/syside-vscode/sysml-2ls-0.9.0.vsix")) pnpmCommand.set( listOf( @@ -81,11 +130,13 @@ val bundleExtension by tasks.registering(PnpmTask::class) { ) } -val bundleCli by tasks.registering(PnpmTask::class) { - // not needed, but it would be difficult to exclude the outputs of building the extension - dependsOn(buildExtension) +val buildCli by tasks.registering(PnpmTask::class) { dependsOn(tasks.pnpmInstall) - inputs.files(fileTree("sysml-2ls") { + inputs.file(sysmlDir.file("package.json")) + inputs.file(sysmlDir.file("tsconfig.json")) + inputs.file(sysmlDir.file("tsconfig.build.json")) + inputs.file(sysmlDir.file("tsconfig.eslint.json")) + inputs.files(fileTree(sysmlDir.dir("packages")) { include("**/src/**/*.ts") include("**/tsconfig.json") include("**/package.json") @@ -93,9 +144,9 @@ val bundleCli by tasks.registering(PnpmTask::class) { include("**/scripts/*.*") include("**/scripts/*.*") }) - outputs.file("sysml-2ls/packages/syside-cli/out/index.js") + outputs.file(sysmlDir.file("packages/syside-cli/out/index.js")) - workingDir = project.layout.projectDirectory.dir("sysml-2ls/packages/syside-cli") + workingDir = sysmlDir.dir("packages/syside-cli") pnpmCommand.set( listOf( @@ -105,20 +156,13 @@ val bundleCli by tasks.registering(PnpmTask::class) { ) } -tasks { - assemble { - inputs.files(buildExtension.get().outputs) - } - - clean { - delete("dist") - } -} - -val assembleCliBundle by tasks.registering(Sync::class) { - dependsOn(bundleCli) - from(file("sysml-2ls/packages/syside-cli/out/index.js")) - from(project.layout.projectDirectory.dir("sysml-2ls/packages/syside-vscode/sysml.library")) { +val bundleCli by tasks.registering(Sync::class) { + dependsOn(checkoutLibrary) + dependsOn(buildCli) + from(sysmlDir.file("packages/syside-cli/out/index.js")) + from(sysmlDir.dir("SysML-v2-Release")) { + include("*.sysml") + include("*.kerml") into("sysml.library") } into(project.layout.buildDirectory.dir("cli-bundle")) @@ -129,6 +173,6 @@ artifacts { builtBy(bundleExtension) } add(cliOutput.name, project.layout.buildDirectory.dir("cli-bundle").get().asFile) { - builtBy(assembleCliBundle) + builtBy(bundleCli) } } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd index 59b7aa29..0f0de754 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd @@ -20,18 +20,14 @@ echo Usage: checkout.cmd ^ ^ ^ exit /b 1 :main -if not exist "%TARGET_DIR%\.git" ( - git clone "%REMOTE_URL%" "%TARGET_DIR%" - if errorlevel 1 exit /b 1 -) - cd /d "%TARGET_DIR%" -if errorlevel 1 exit /b 1 - -git fetch origin "%COMMIT%" -if errorlevel 1 exit /b 1 +git init +echo Adding remote +git remote add origin "%REMOTE_URL%" || rem +echo Fetch latest +git fetch +echo Checkout commit git checkout "%COMMIT%" -if errorlevel 1 exit /b 1 endlocal diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh index 6f7a4335..ad72351d 100755 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh @@ -6,8 +6,6 @@ # SPDX-License-Identifier: EPL-2.0 # -set -e - TARGET_DIR="$1" REMOTE_URL="$2" COMMIT="$3" @@ -17,11 +15,12 @@ if [ -z "$TARGET_DIR" ] || [ -z "$REMOTE_URL" ] || [ -z "$COMMIT" ]; then exit 1 fi -if [ ! -d "$TARGET_DIR/.git" ]; then - git clone "$REMOTE_URL" "$TARGET_DIR" -fi - cd "$TARGET_DIR" -git fetch origin "$COMMIT" +git init +echo "Adding remote" +git remote add origin "$REMOTE_URL" || true +echo "Fetch latest" +git fetch +echo "Checkout commit" git checkout "$COMMIT" From 6333f9cd7e9e2f00cb13fabc64b489882fe0e80b Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 17:41:59 +0100 Subject: [PATCH 058/115] Added npm service to semantifyr-vscode as well --- .../sysmlv2/sysmlv2-frontend/build.gradle.kts | 2 +- subprojects/semantifyr-vscode/build.gradle.kts | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index 913d1e52..fb509552 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -24,7 +24,7 @@ node { } abstract class PnpmService : BuildService -val pnpmService = gradle.sharedServices.registerIfAbsent("pnpmService", NpmService::class.java) { +val pnpmService = gradle.sharedServices.registerIfAbsent("pnpmService", PnpmService::class.java) { maxParallelUsages.set(1) } diff --git a/subprojects/semantifyr-vscode/build.gradle.kts b/subprojects/semantifyr-vscode/build.gradle.kts index 6dcc8568..8e66f211 100644 --- a/subprojects/semantifyr-vscode/build.gradle.kts +++ b/subprojects/semantifyr-vscode/build.gradle.kts @@ -5,6 +5,7 @@ */ import com.github.gradle.node.npm.task.NpmTask +import com.github.gradle.node.task.NodeTask plugins { base @@ -16,6 +17,19 @@ node { download = true } +abstract class NpmService : BuildService +val npmService = gradle.sharedServices.registerIfAbsent("npmService", NpmService::class.java) { + maxParallelUsages.set(1) +} + +// node tasks must not run in parallel, as pnpm is sensitive to that +tasks.withType().configureEach { + usesService(npmService) +} +tasks.withType().configureEach { + usesService(npmService) +} + val distributionOutput by configurations.creating { isCanBeConsumed = true isCanBeResolved = false From 563a3d948e81d603bc54de3bcb67e79c23578acd Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 17:56:00 +0100 Subject: [PATCH 059/115] Updated sysml-2ls --- subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index fb509552..7086447e 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -13,7 +13,7 @@ plugins { alias(libs.plugins.gradle.node) } -val sysmlCommit = "e9d675777390deabae2e620722288a2177271ab6" +val sysmlCommit = "aecd217b0ebf5877c92fa3d16a79e98c73417b69" val sysmlUrl = "git@github.com:arminzavada/sysml-2ls.git" val sysmlDir = layout.buildDirectory.dir("sysml-2ls").get() From cef99344694a04e2569868e3a7bca157a795b951 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 17:56:11 +0100 Subject: [PATCH 060/115] Fixed library cloning --- .../frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index 7086447e..b46bd0c5 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -160,9 +160,9 @@ val bundleCli by tasks.registering(Sync::class) { dependsOn(checkoutLibrary) dependsOn(buildCli) from(sysmlDir.file("packages/syside-cli/out/index.js")) - from(sysmlDir.dir("SysML-v2-Release")) { - include("*.sysml") - include("*.kerml") + from(fileTree(sysmlDir.dir("SysML-v2-Release/sysml.library"))) { + include("**/*.sysml") + include("**/*.kerml") into("sysml.library") } into(project.layout.buildDirectory.dir("cli-bundle")) From 138d73cb0ac0ad480e1b9a3276f2cd9740c52b8b Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 18:00:42 +0100 Subject: [PATCH 061/115] Set https repo url instead of ssh --- subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index b46bd0c5..ff665634 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -14,7 +14,7 @@ plugins { } val sysmlCommit = "aecd217b0ebf5877c92fa3d16a79e98c73417b69" -val sysmlUrl = "git@github.com:arminzavada/sysml-2ls.git" +val sysmlUrl = "https://github.com/arminzavada/sysml-2ls.git" val sysmlDir = layout.buildDirectory.dir("sysml-2ls").get() node { From a20184c5cd732ea65c0a43e3e430e221c10c481b Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 20:09:05 +0100 Subject: [PATCH 062/115] Removed accidental second client --- subprojects/semantifyr-vscode/src/extension.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/subprojects/semantifyr-vscode/src/extension.ts b/subprojects/semantifyr-vscode/src/extension.ts index 7f432ada..a81dc96a 100644 --- a/subprojects/semantifyr-vscode/src/extension.ts +++ b/subprojects/semantifyr-vscode/src/extension.ts @@ -14,8 +14,6 @@ export async function activate(context: ExtensionContext) { await startClients(context); registerCommands(context); - - await startClients(context); } export async function deactivate() { From 297ceb22ed599bd60a0b20f1cfb5f3cf8e97a549 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 20:09:14 +0100 Subject: [PATCH 063/115] Removed unused commands --- subprojects/semantifyr-vscode/src/commands.ts | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/subprojects/semantifyr-vscode/src/commands.ts b/subprojects/semantifyr-vscode/src/commands.ts index 634340e0..45d6d219 100644 --- a/subprojects/semantifyr-vscode/src/commands.ts +++ b/subprojects/semantifyr-vscode/src/commands.ts @@ -61,64 +61,8 @@ async function waitForProcess( }); } -function registerCompileTargetCommand(context: ExtensionContext, compilerExecutable: string) { - context.subscriptions.push( - vscode.commands.registerCommand('semantifyr.compileTarget', async (targetName: string, document: vscode.TextDocument) => { - const documentPath = document.uri.fsPath; - const documentDirectory = path.dirname(documentPath); - const outputFile = path.join(documentDirectory, `${targetName}.xsts`); - const workspaceFolders = vscode.workspace.workspaceFolders; - const workspaceFolder = workspaceFolders ? workspaceFolders[0].uri.fsPath : documentDirectory; - const args = `${compilerExecutable} compile ${documentPath} ${workspaceFolder} ${targetName} -o ${outputFile}`; - await waitForProcess( - childProcess.exec(args), - `Compiling target: ${targetName}`, - `Success! Compiled ${targetName} to ${outputFile}`, - (error) => `Error compiling target: ${error.message}.` - ) - }) - ); -} - -function registerVerifyTargetCommand(context: ExtensionContext, compilerExecutable: string) { - context.subscriptions.push( - vscode.commands.registerCommand('semantifyr.verifyTarget', async (targetName: string, document: vscode.TextDocument, generateWitness: boolean) => { - const documentPath = document.uri.fsPath; - const documentDirectory = path.dirname(documentPath); - const workspaceFolders = vscode.workspace.workspaceFolders; - const workspaceFolder = workspaceFolders ? workspaceFolders[0].uri.fsPath : documentDirectory; - - let args = `${compilerExecutable} verify ${documentPath} ${workspaceFolder} ${targetName}`; - if (generateWitness) { - args += " --witness"; - } - await waitForProcess( - childProcess.exec(args), - `Verifying target: ${targetName}`, - `Success! Verified target: ${targetName}.`, - (error) => `Error verifying target: ${error.message}.` - ); - }) - ); -} - -function registerVerifyXstsCommand(context: ExtensionContext, compilerExecutable: string) { - context.subscriptions.push( - vscode.commands.registerCommand('semantifyr.verifyXsts', async (uri: vscode.Uri) => { - const documentPath = uri.fsPath; - const args = `${compilerExecutable} verify-xsts ${documentPath}`; - - await waitForProcess( - childProcess.exec(args), - `Verifying XSTS model: ${documentPath}`, - `Success! Verified XSTS model: ${documentPath}.`, - (error) => `Error verifying XSTS model: ${error.message}.` - ); - }) - ); -} function registerCompileGammaCommand(context: ExtensionContext, gammaExecutable: string) { context.subscriptions.push( @@ -136,36 +80,9 @@ function registerCompileGammaCommand(context: ExtensionContext, gammaExecutable: ); } -function registerVerifyGammaCommand(context: ExtensionContext, gammaExecutable: string) { - context.subscriptions.push( - vscode.commands.registerCommand('gamma.verify', async (verificationCase: string, document: vscode.TextDocument, generateWitness: boolean) => { - const documentPath = document.uri.fsPath; - const documentDirectory = path.dirname(documentPath); - const workspaceFolders = vscode.workspace.workspaceFolders; - const workspaceFolder = workspaceFolders ? workspaceFolders[0].uri.fsPath : documentDirectory; - - let args = `${gammaExecutable} verify ${documentPath} ${verificationCase} ${workspaceFolder}`; - if (generateWitness) { - args += " --witness"; - } - - await waitForProcess( - childProcess.exec(args), - `Verifying verification case: ${verificationCase}`, - `Success! Verified verification case: ${verificationCase}.`, - (error) => `Error verifying verification case: ${error.message}.` - ); - }) - ); -} export function registerCommands(context: ExtensionContext) { - const compilerExecutable = path.join(context.extensionPath, 'bin', 'semantifyr', 'bin', `semantifyr-cli${executablePostfix}`); const gammaExecutable = path.join(context.extensionPath, 'bin', 'gamma-cli', 'bin', `gamma-cli${executablePostfix}`); - registerCompileTargetCommand(context, compilerExecutable); - registerVerifyTargetCommand(context, compilerExecutable); registerCompileGammaCommand(context, gammaExecutable); - registerVerifyGammaCommand(context, gammaExecutable); - registerVerifyXstsCommand(context, compilerExecutable); } From e9806991db85057f0ae6a93cf95a17ec418c141a Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 20:14:10 +0100 Subject: [PATCH 064/115] Only bundle semantifyr extension --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5f1b4969..4e537d01 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,7 @@ jobs: run: ./gradlew build - name: Bundle Extension shell: bash - run: ./gradlew bundleExtension + run: ./gradlew :semantifyr-vscode:bundleExtension - name: Upload Artifacts if: ${{ matrix.os == 'ubuntu-latest' }} uses: actions/upload-artifact@v7 From bcf6f8c61ad513b12f40956af6ffa55f0dc7edb9 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 20:17:24 +0100 Subject: [PATCH 065/115] Added error redirect --- subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 2 +- .../frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index ff665634..72ad3be9 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -13,7 +13,7 @@ plugins { alias(libs.plugins.gradle.node) } -val sysmlCommit = "aecd217b0ebf5877c92fa3d16a79e98c73417b69" +val sysmlCommit = "48a149d73370a3212a24d58436fa58127556b4c0" // Added error redirect val sysmlUrl = "https://github.com/arminzavada/sysml-2ls.git" val sysmlDir = layout.buildDirectory.dir("sysml-2ls").get() diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh index ad72351d..c2015b9b 100755 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh @@ -19,7 +19,7 @@ cd "$TARGET_DIR" git init echo "Adding remote" -git remote add origin "$REMOTE_URL" || true +git remote add origin "$REMOTE_URL" 2> /dev/null || true echo "Fetch latest" git fetch echo "Checkout commit" From 205045f65a19fbce7b2d8ae6ae8b4636c9529070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zavada=20=C3=81rmin?= Date: Tue, 24 Mar 2026 20:31:47 +0100 Subject: [PATCH 066/115] Fixed clone script on Windows --- .../frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 8 ++++---- .../sysmlv2/sysmlv2-frontend/scripts/checkout.cmd | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index 72ad3be9..13d2ae4d 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -52,13 +52,13 @@ val checkoutSysml by tasks.registering(Exec::class) { inputs.dir("scripts") outputs.dir(sysmlDir.dir(".git")) - val script = if (Os.isFamily(Os.FAMILY_WINDOWS)) { - "scripts\\checkout.cmd" + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine("cmd.exe", "/d", "/c", "scripts\\checkout.cmd", sysmlDir.asFile.absolutePath, sysmlUrl, sysmlCommit) } else { - "scripts/checkout.sh" + commandLine("cmd.exe", "scripts/checkout.sh", sysmlDir.asFile.absolutePath, sysmlUrl, sysmlCommit) } - commandLine(script, sysmlDir.asFile.absolutePath, sysmlUrl, sysmlCommit) + } tasks.pnpmInstall { diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd index 0f0de754..c3dfe0fc 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd @@ -24,7 +24,7 @@ cd /d "%TARGET_DIR%" git init echo Adding remote -git remote add origin "%REMOTE_URL%" || rem +git remote add origin "%REMOTE_URL%" 2> nul || rem echo Fetch latest git fetch echo Checkout commit From c8d260314e94072e7999c8034c118a94de59f3ea Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 21:01:30 +0100 Subject: [PATCH 067/115] Upgraded sysmlv2-frontend --- .../frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index 13d2ae4d..cf291e5a 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -13,7 +13,7 @@ plugins { alias(libs.plugins.gradle.node) } -val sysmlCommit = "48a149d73370a3212a24d58436fa58127556b4c0" // Added error redirect +val sysmlCommit = "f469c8e21fd61348858e7b8cb1a726a6792b57e3" // Improved cloning logic val sysmlUrl = "https://github.com/arminzavada/sysml-2ls.git" val sysmlDir = layout.buildDirectory.dir("sysml-2ls").get() @@ -55,10 +55,8 @@ val checkoutSysml by tasks.registering(Exec::class) { if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine("cmd.exe", "/d", "/c", "scripts\\checkout.cmd", sysmlDir.asFile.absolutePath, sysmlUrl, sysmlCommit) } else { - commandLine("cmd.exe", "scripts/checkout.sh", sysmlDir.asFile.absolutePath, sysmlUrl, sysmlCommit) + commandLine("scripts/checkout.sh", sysmlDir.asFile.absolutePath, sysmlUrl, sysmlCommit) } - - } tasks.pnpmInstall { From 15121fb9867c0d8e0e05d70c22c6703018edc917 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 21:32:04 +0100 Subject: [PATCH 068/115] Test models are also cloned --- .../semantifyr-vscode-server/.gitignore | 2 +- .../semantifyr-vscode-server/build.gradle.kts | 22 + .../gamma/TestModels/Crossroads.gamma | 272 ---------- .../examples/gamma/TestModels/Simple.gamma | 110 ---- .../gamma/TestModels/Spacecraft.gamma | 178 ------- .../sysml/TestModels/Verification.sysml | 25 - .../sysml/TestModels/crossroads.sysml | 477 ------------------ .../sysml/TestModels/spacecraft.sysml | 346 ------------- .../examples/sysml/TestModels/stm21.sysml | 92 ---- .../examples/sysml/TestModels/stm31.sysml | 85 ---- 10 files changed, 23 insertions(+), 1586 deletions(-) delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Crossroads.gamma delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Simple.gamma delete mode 100644 subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Spacecraft.gamma delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/TestModels/Verification.sysml delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/TestModels/crossroads.sysml delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/TestModels/spacecraft.sysml delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/TestModels/stm21.sysml delete mode 100644 subprojects/semantifyr-vscode-server/examples/sysml/TestModels/stm31.sysml diff --git a/subprojects/semantifyr-vscode-server/.gitignore b/subprojects/semantifyr-vscode-server/.gitignore index 9c1d2811..637e2d8a 100644 --- a/subprojects/semantifyr-vscode-server/.gitignore +++ b/subprojects/semantifyr-vscode-server/.gitignore @@ -1,2 +1,2 @@ extensions/ -examples/*/Library/ +examples/ diff --git a/subprojects/semantifyr-vscode-server/build.gradle.kts b/subprojects/semantifyr-vscode-server/build.gradle.kts index b0a7981a..2e8f1336 100644 --- a/subprojects/semantifyr-vscode-server/build.gradle.kts +++ b/subprojects/semantifyr-vscode-server/build.gradle.kts @@ -60,21 +60,43 @@ val cloneLibraries by tasks.registering { dependsOn(cloneSysMLLibrary) } +val cloneGammaTestModels by tasks.registering(Sync::class) { + from (project(":gamma-semantics").layout.projectDirectory.dir("TestModels")) { + include("*.gamma") + } + into ("examples/gamma/TestModels") +} + +val cloneSysMLTestModels by tasks.registering(Sync::class) { + from (project(":sysmlv2-semantics").layout.projectDirectory.dir("TestModels")) { + include("*.sysml") + } + into ("examples/sysml/TestModels") +} + +val cloneTestModels by tasks.registering { + dependsOn(cloneGammaTestModels) + dependsOn(cloneSysMLTestModels) +} + val prepareDockerBuild by tasks.registering() { dependsOn(cloneDistribution) dependsOn(cloneTheta) dependsOn(cloneLibraries) + dependsOn(cloneTestModels) } val dockerBuildImage by tasks.registering(DockerBuildImage::class) { dependsOn(prepareDockerBuild) inputDir.set(projectDir) images.add("ftsrgbot/semantifyr-vscode-server:${project.version}") + images.add("ftsrgbot/semantifyr-vscode-server:testing") images.add("ftsrgbot/semantifyr-vscode-server:preview") } val dockerPushImage by tasks.registering(DockerPushImage::class) { dependsOn(dockerBuildImage) images.add("ftsrgbot/semantifyr-vscode-server:${project.version}") + images.add("ftsrgbot/semantifyr-vscode-server:testing") images.add("ftsrgbot/semantifyr-vscode-server:preview") } diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Crossroads.gamma b/subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Crossroads.gamma deleted file mode 100644 index d5a6ba1b..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Crossroads.gamma +++ /dev/null @@ -1,272 +0,0 @@ -package Crossroads - -interface CentralControl { - out event police - out event toggle -} - -// TODO: add enum value -interface LightControl { - out event red - out event yellow - out event green - out event none -} - -statechart CentralController[ - port control : requires CentralControl, - port controlA : provides CentralControl, - port controlB : provides CentralControl -] { - timeout toggleTimeout - - region Main { - entry transition to Operating - - state Operating { - region OperatingRegion { - entry transition to BothYellow - - state BothYellow { - entry / set toggleTimeout := 1 s; - } - - transition BothYellow to BothRed when timeout toggleTimeout / raise controlA.toggle; raise controlB.toggle; // switch A to Red, B to Red - - state BothRed { - entry / set toggleTimeout := 2 s; - } - - transition BothRed to TrafficOnA when timeout toggleTimeout / raise controlA.toggle; // switch A to Green - - state TrafficOnA { - entry / set toggleTimeout := 2 s; - } - - transition TrafficOnA to StoppingA when timeout toggleTimeout / raise controlA.toggle; // switch A to Yellow - - state StoppingA { - entry / set toggleTimeout := 1 s; - } - - transition StoppingA to TrafficOnB when timeout toggleTimeout / raise controlA.toggle; raise controlB.toggle; // switch A to Red, B to Green - - state TrafficOnB { - entry / set toggleTimeout := 2 s; - } - - transition TrafficOnB to StoppingB when timeout toggleTimeout / raise controlB.toggle; // switch B to Yellow - - state StoppingB { - entry / set toggleTimeout := 1 s; - } - - transition StoppingB to TrafficOnA when timeout toggleTimeout / raise controlA.toggle; raise controlB.toggle; // switch A to Green, B to Red - } - } - - transition Operating to Interrupted when event control.police - transition Interrupted to Operating when event control.police - - state Interrupted { - entry / raise controlA.police; raise controlB.police; - exit / raise controlA.police; raise controlB.police; - } - } -} - -statechart TrafficLightController[ - port control : requires CentralControl, - port lightControl : provides LightControl -] { - timeout blinkingTimeout - - region Main { - entry transition to Normal - - state Normal { - region NormalRegion { - entry transition to Yellow - - state Yellow { - entry / raise lightControl.yellow; - } - - transition Yellow to Red when event control.toggle - - state Red { - entry / raise lightControl.red; - } - - transition Red to Green when event control.toggle - - state Green { - entry / raise lightControl.green; - } - - transition Green to Yellow when event control.toggle - } - } - - transition Normal to Interrupted when event control.police - transition Interrupted to Normal when event control.police - - state Interrupted { - region InterruptedRegion { - entry transition to Yellow - - state Yellow { - entry / set blinkingTimeout := 1 s; raise lightControl.yellow; - } - - transition Black to Yellow when timeout blinkingTimeout - transition Yellow to Black when timeout blinkingTimeout - - state Black { - entry / set blinkingTimeout := 1 s; raise lightControl.none; - } - } - } - } -} - -sync component CrossroadSystem [ - port control : requires CentralControl/*, - port lightControlA : provides LightControl, - port lightControlB : provides LightControl*/ -] { - component controller : CentralController - component trafficLightA : TrafficLightController - component trafficLightB : TrafficLightController - - bind control -> controller.control - //bind lightControlA -> trafficLightA.lightControl - //bind lightControlB -> trafficLightB.lightControl - - channel [ controller.controlA ] -> [ trafficLightA.control ] - channel [ controller.controlB ] -> [ trafficLightB.control ] -} - -// CentralController verification cases - - -@Reachable -verification case ControllerOperatingReachable { - component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating) } -} - -@Reachable -verification case ControllerOperatingBothYellowReachable { - component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.BothYellow) } -} - -@Reachable -verification case ControllerOperatingBothRedReachable { - component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.BothRed) } -} - -@Reachable -verification case ControllerOperatingStoppingAReachable { - component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.StoppingA) } -} - -@Reachable -verification case ControllerOperatingStoppingBReachable { - component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.StoppingB) } -} - -@Reachable -verification case ControllerOperatingTrafficOnAReachable { - component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.TrafficOnA) } -} - -@Reachable -verification case ControllerOperatingTrafficOnBReachable { - component system : CrossroadSystem - invariant { isActive (system.controller.Main.Operating.OperatingRegion.TrafficOnB) } -} - - -@Reachable -verification case ControllerInterruptedReachable { - component system : CrossroadSystem - invariant { isActive (system.controller.Main.Interrupted) } -} - -// TrafficLightController A verification cases - -@Reachable -verification case ACanBeYellow { - component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Normal.NormalRegion.Yellow) } -} - -@Reachable -verification case ACanBeRed { - component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Normal.NormalRegion.Red) } -} - -@Reachable -verification case ACanBeGreen { - component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Normal.NormalRegion.Green) } -} - -@Reachable -verification case ACanBeBlinkingYellow { - component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Interrupted.InterruptedRegion.Yellow) } -} - -@Reachable -verification case ACanBeBlinkingBlack { - component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Interrupted.InterruptedRegion.Black) } -} - -// TrafficLightController B verification cases - -@Reachable -verification case BCanBeYellow { - component system : CrossroadSystem - invariant { isActive (system.trafficLightB.Main.Normal.NormalRegion.Yellow) } -} - -@Reachable -verification case BCanBeRed { - component system : CrossroadSystem - invariant { isActive (system.trafficLightB.Main.Normal.NormalRegion.Red) } -} - -@Reachable -verification case BCanBeGreen { - component system : CrossroadSystem - invariant { isActive (system.trafficLightB.Main.Normal.NormalRegion.Green) } -} - -@Reachable -verification case BCanBeBlinkingYellow { - component system : CrossroadSystem - invariant { isActive (system.trafficLightB.Main.Interrupted.InterruptedRegion.Yellow) } -} - -@Reachable -verification case BCanBeBlinkingBlack { - component system : CrossroadSystem - invariant { isActive (system.trafficLightB.Main.Interrupted.InterruptedRegion.Black) } -} - -// Combined safety verification cases - -@Unreachable -verification case BothCannotBeGreen { - component system : CrossroadSystem - invariant { isActive (system.trafficLightA.Main.Normal.NormalRegion.Green) && isActive (system.trafficLightB.Main.Normal.NormalRegion.Green) } -} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Simple.gamma b/subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Simple.gamma deleted file mode 100644 index 879ee6ef..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Simple.gamma +++ /dev/null @@ -1,110 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package Simple - -interface Control { - out event start - out event stop -} - -statechart LeaderStatechart [ - port control : requires Control, - port workerControl : provides Control -] { - region Main { - state Idle - state Operational - state Stopped - state Unreachable - - entry transition to Idle - transition Idle to Operational when event control.start / raise workerControl.start; - transition Operational to Stopped when event control.stop / raise workerControl.stop; - } -} - -statechart WorkerStatechart [ - port control : requires Control -] { - region Main { - state Idle - state Operational - state Stopped - state Unreachable - - entry transition to Idle - transition Idle to Operational when event control.start - transition Operational to Stopped when event control.stop - } -} - -sync component System[ - port control : requires Control -] { - component leader : LeaderStatechart - component worker : WorkerStatechart - - bind control -> leader.control - channel [ leader.workerControl ] -> [ worker.control ] -} - -@Reachable -verification case LeaderStatechartIdleReachable { - component system : System - - invariant { isActive (system.leader.Main.Idle) } -} - -@Reachable -verification case LeaderStatechartOperationalReachable { - component system : System - - invariant { isActive (system.leader.Main.Operational) } -} - -@Reachable -verification case LeaderStatechartStoppedReachable { - component system : System - - invariant { isActive (system.leader.Main.Stopped) } -} - -@Unreachable -verification case LeaderStatechartUnreachable { - component system : System - - invariant { isActive (system.leader.Main.Unreachable) } -} - - -@Reachable -verification case WorkerStatechartIdleReachable { - component system : System - - invariant { isActive (system.worker.Main.Idle) } -} - -@Reachable -verification case WorkerStatechartOperationalReachable { - component system : System - - invariant { isActive (system.worker.Main.Operational) } -} - -@Reachable -verification case WorkerStatechartStoppedReachable { - component system : System - - invariant { isActive (system.worker.Main.Stopped) } -} - -@Unreachable -verification case WorkerStatechartUnrachable { - component system : System - - invariant { isActive (system.worker.Main.Unreachable) } -} diff --git a/subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Spacecraft.gamma b/subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Spacecraft.gamma deleted file mode 100644 index 21108ec0..00000000 --- a/subprojects/semantifyr-vscode-server/examples/gamma/TestModels/Spacecraft.gamma +++ /dev/null @@ -1,178 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package Spacecraft - -interface Control { - out event start - out event shutdown -} - -interface Data { - out event data - in event ping -} - -statechart Station [ - port control : requires Control, - port connection : requires Data -] { - timeout pingTimeout - timeout startTimeout - - var receivedData: Integer := 0 - - region Main { - state Idle { - entry / set startTimeout := 30 s; - } - state Operation { - entry / set pingTimeout := 10 s; raise connection.ping; - - region ReceiveData { - state Waiting - - entry transition to Waiting - transition Waiting to Waiting when event connection.data [receivedData > 10 or receivedData < 100] / raise connection.ping; assign receivedData := receivedData + 10; - } - } - - entry transition to Idle - transition Idle to Operation when event control.start - transition Idle to Operation when timeout startTimeout - transition Operation to Idle when event control.shutdown - transition Operation to Operation when timeout pingTimeout - } -} - -statechart Spacecraft[ - port connection : provides Data -] { - timeout checkBatteryTimeout - timeout rechargeTimeout - timeout consumeTimeout - timeout transmitTimeout - - var batteryCharge : Integer := 100 - var recharging : Boolean := false - var data : Integer := 100 - - region Communication { - state WaitingPing - state Transmitting { - region SendData { - state Sending { - entry / set transmitTimeout := 4 s; - } - - entry transition to Sending - transition Sending to Sending when timeout transmitTimeout [! (data <= 0 or batteryCharge < 40)] / assign data := data - 10; raise connection.data; - } - region ConsumePower { - state Consuming { - entry / set consumeTimeout := 2 s; - } - - entry transition to Consuming - transition Consuming to Consuming when timeout consumeTimeout [! (batteryCharge < 40)] / assign batteryCharge := batteryCharge - 10; - } - } - - entry transition to WaitingPing - transition WaitingPing to Transmitting when event connection.ping [recharging == false && ! (data <= 0 || batteryCharge < 40)] - transition Transmitting to WaitingPing when timeout consumeTimeout [batteryCharge < 40] - transition Transmitting to WaitingPing when timeout transmitTimeout [data <= 0 || batteryCharge < 40] - } - - region Battery { - state NotRecharging { - entry / set checkBatteryTimeout := 3 s; assign recharging := false; - } - - state Recharging { - entry / set rechargeTimeout := 3 s; assign recharging := true; - } - - entry transition to NotRecharging - transition NotRecharging to Recharging when timeout checkBatteryTimeout [batteryCharge < 80] - transition Recharging to Recharging when timeout rechargeTimeout [batteryCharge < 100] / assign batteryCharge := batteryCharge + 10; - transition Recharging to NotRecharging when timeout rechargeTimeout [batteryCharge >= 100] - } -} - -sync component SpaceMission [ - port control : requires Control -] { - component station : Station - component spacecraft : Spacecraft - - bind control -> station.control - - channel [ station.connection ] -> [ spacecraft.connection ] -} - -@Reachable -verification case Station_IdleReachable { - component mission : SpaceMission - - invariant { isActive (mission.station.Main.Idle) } -} - -@Reachable -verification case Station_OperationReachable { - component mission : SpaceMission - - invariant { isActive (mission.station.Main.Operation) } -} - -@Reachable -verification case Station_OperationReceiveDataWaitingReachable { - component mission : SpaceMission - - invariant { isActive (mission.station.Main.Operation.ReceiveData.Waiting) } -} - -@Reachable -verification case Spacecraft_CommunicationWaitingPingReachable { - component mission : SpaceMission - - invariant { isActive (mission.spacecraft.Communication.WaitingPing) } -} - -@Reachable -verification case Spacecraft_CommunicationTransmittingReachable { - component mission : SpaceMission - - invariant { isActive (mission.spacecraft.Communication.Transmitting) } -} - -@Reachable -verification case Spacecraft_CommunicationTransmittingSendDataSendingReachable { - component mission : SpaceMission - - invariant { isActive (mission.spacecraft.Communication.Transmitting.SendData.Sending) } -} - -@Reachable -verification case Spacecraft_CommunicationTransmittingConsumePowerConsumingReachable { - component mission : SpaceMission - - invariant { isActive (mission.spacecraft.Communication.Transmitting.ConsumePower.Consuming) } -} - -@Reachable -verification case Spacecraft_BatteryNotRechargingReachable { - component mission : SpaceMission - - invariant { isActive (mission.spacecraft.Battery.NotRecharging) } -} - -@Reachable -verification case Spacecraft_BatteryRechargingReachable { - component mission : SpaceMission - - invariant { isActive (mission.spacecraft.Battery.Recharging) } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/Verification.sysml b/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/Verification.sysml deleted file mode 100644 index 530b635b..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/Verification.sysml +++ /dev/null @@ -1,25 +0,0 @@ -private import ScalarValues::Boolean; - -/* - * Verification constraints with this calculation will be transformed into a 'UNSAFE' expecting verification case. - */ -calc def eventually { - in op: Boolean[1]; - return : Boolean[1]; -} - -/* - * Verification constraints with this calculation will be transformed into a 'SAFE' expecting verification case. - */ -calc def never { - in op: Boolean[1]; - return : Boolean[1]; -} - -/* - * Evaluates to true iff the specified state is currently active. - */ -calc def isStateActive { - in s: SysML::StateUsage[1]; - return : Boolean[1]; -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/crossroads.sysml b/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/crossroads.sysml deleted file mode 100644 index edad930c..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/crossroads.sysml +++ /dev/null @@ -1,477 +0,0 @@ -private import SI::s; - -item def Police; -item def Toggle; -item def RedL; -item def YellowL; -item def GreenL; -item def NoneL; - -port def CentralControl { - out item police : Police; - out item toggle : Toggle; -} -port def LightControl { - out item red : RedL; - out item yellow : YellowL; - out item green : GreenL; - out item none : NoneL; -} - -part def CentralController { - port control : ~CentralControl; - port controlA : CentralControl; - port controlB : CentralControl; - - exhibit state Behaviour { - transition first start then Operating; - - state Operating { - transition first start then BothYellow; - - state BothYellow; - - transition first BothYellow accept after 1[s] do action { - send Toggle() via controlA; - send Toggle() via controlB; - } then BothRed; - - state BothRed; - - transition first BothRed accept after 2[s] do action { - send Toggle() via controlA; - } then TrafficOnA; - - state TrafficOnA; - - transition first TrafficOnA accept after 2[s] do action { - send Toggle() via controlA; - } then StoppingA; - - state StoppingA; - - transition first StoppingA accept after 1[s] do action { - send Toggle() via controlA; - send Toggle() via controlB; - } then TrafficOnB; - - state TrafficOnB; - - transition first TrafficOnB accept after 2[s] do action { - send Toggle() via controlB; - } then StoppingB; - - state StoppingB; - - transition first StoppingB accept after 1[s] do action { - send Toggle() via controlA; - send Toggle() via controlB; - } then TrafficOnA; - } - - transition first Operating accept Police via control then Interrupted; - transition first Interrupted accept Police via control then Operating; - - state Interrupted { - entry action { - send Police() via controlA; - send Police() via controlB; - } - exit action { - send Police() via controlA; - send Police() via controlB; - } - } - } -} - -part def TrafficLightController { - port control : ~CentralControl; - port lightControl : LightControl; - - exhibit state Behaviour { - transition first start then Normal; - - state Normal { - transition first start then Yellow; - - state Yellow { - entry send YellowL() via lightControl; - } - - transition first Yellow accept Toggle via control then Red; - - state Red { - entry send RedL() via lightControl; - } - - transition first Red accept Toggle via control then Green; - - state Green { - entry send GreenL() via lightControl; - } - - transition first Green accept Toggle via control then Yellow; - } - - transition first Normal accept Police via control then Interrupted; - transition first Interrupted accept Police via control then Normal; - - state Interrupted { - transition first start then Yellow; - - state Yellow { - entry send YellowL() via lightControl; - } - - transition first Yellow accept after 1 [s] then Black; - transition first Black accept after 1 [s] then Yellow; - - state Black { - entry send NoneL() via lightControl; - } - } - } -} - -part def CrossroadSystem { - port control : ~CentralControl; - - part controller: CentralController; - part trafficLightA: TrafficLightController; - part trafficLightB: TrafficLightController; - - bind control = controller.control; - - flow from controller.controlA to trafficLightA.control; - flow from controller.controlB to trafficLightB.control; -} - -verification def ControllerOperatingReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.controller.Behaviour.Operating) - ) - } - } - } -} - -verification def ControllerOperatingBothYellowReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.controller.Behaviour.Operating.BothYellow) - ) - } - } - } -} - -verification def ControllerOperatingBothRedReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.controller.Behaviour.Operating.BothRed) - ) - } - } - } -} - -verification def ControllerOperatingTrafficOnAReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.controller.Behaviour.Operating.TrafficOnA) - ) - } - } - } -} - -verification def ControllerOperatingStoppingAReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.controller.Behaviour.Operating.StoppingA) - ) - } - } - } -} - -verification def ControllerOperatingTrafficOnBReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.controller.Behaviour.Operating.TrafficOnB) - ) - } - } - } -} - -verification def ControllerOperatingStoppingBReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.controller.Behaviour.Operating.StoppingB) - ) - } - } - } -} - -verification def ControllerInterruptedReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.controller.Behaviour.Interrupted) - ) - } - } - } -} - - - -verification def TrafficLightABehaviorNormalReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightA.Behaviour.Normal) - ) - } - } - } -} - -verification def TrafficLightABehaviorNormalYellowReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightA.Behaviour.Normal.Yellow) - ) - } - } - } -} - -verification def TrafficLightABehaviorNormalRedReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightA.Behaviour.Normal.Red) - ) - } - } - } -} - -verification def TrafficLightABehaviorNormalGreenReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightA.Behaviour.Normal.Green) - ) - } - } - } -} - -verification def TrafficLightABehaviorInterruptedReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightA.Behaviour.Interrupted) - ) - } - } - } -} - -verification def TrafficLightABehaviorInterruptedYellowReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightA.Behaviour.Interrupted.Yellow) - ) - } - } - } -} - -verification def TrafficLightABehaviorInterruptedBlackReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightA.Behaviour.Interrupted.Black) - ) - } - } - } -} - - - -verification def TrafficLightBBehaviorNormalReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightB.Behaviour.Normal) - ) - } - } - } -} - -verification def TrafficLightBBehaviorNormalYellowReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightB.Behaviour.Normal.Yellow) - ) - } - } - } -} - -verification def TrafficLightBBehaviorNormalRedReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightB.Behaviour.Normal.Red) - ) - } - } - } -} - -verification def TrafficLightBBehaviorNormalGreenReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightB.Behaviour.Normal.Green) - ) - } - } - } -} - -verification def TrafficLightBBehaviorInterruptedReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightB.Behaviour.Interrupted) - ) - } - } - } -} - -verification def TrafficLightBBehaviorInterruptedYellowReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightB.Behaviour.Interrupted.Yellow) - ) - } - } - } -} - -verification def TrafficLightBBehaviorInterruptedBlackReachable { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.trafficLightB.Behaviour.Interrupted.Black) - ) - } - } - } -} - - - -verification def BothCannotBeGreen { - subject system : CrossroadSystem; - - objective { - verify requirement { - require constraint { - never( - isStateActive(system.trafficLightA.Behaviour.Normal.Green) - and isStateActive(system.trafficLightB.Behaviour.Normal.Green) - ) - } - } - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/spacecraft.sysml b/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/spacecraft.sysml deleted file mode 100644 index 36017277..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/spacecraft.sysml +++ /dev/null @@ -1,346 +0,0 @@ -private import ScalarValues::Integer; -private import ScalarValues::Boolean; -private import SI::s; - -part def GroundStation { - port commandPort : CommandPort; - port spacecraftCommandPort : ~CommandPort; - port dataPort : ~DataPort; - - attribute receivedData : Integer default 0; - - exhibit state Behaviour { - state Idle; - - transition first start then Idle; - - state Operation { - entry send PingCommand() via spacecraftCommandPort; - - state Waiting; - - transition first start then Waiting; - - transition - first Waiting - accept Data via dataPort - if receivedData < 100 - do assign receivedData := receivedData + 10 - then Waiting; - } - - transition first Idle accept after 30 [s] then Operation; - transition first Idle accept : StartCommand via commandPort then Operation; - - transition first Operation accept after 10 [s] then Operation; - transition first Operation accept : StopCommand via commandPort then Idle; - } -} - -part def Spacecraft { - attribute batteryCharge : Integer default 100; - attribute recharging : Boolean default false; - attribute data : Integer default 100; - - port commandPort : CommandPort; - port dataPort : DataPort; - - exhibit state Behaviour parallel { - state Communication { - state WaitingPing; - - transition - first Transmitting.SendData.Sending - accept after 4 [s] - if (data <= 0) or (batteryCharge < 40) - then WaitingPing; - - transition - first Transmitting.ConsumePower.Consuming - accept after 4 [s] - if batteryCharge < 40 - then WaitingPing; - - state Transmitting parallel { - state SendData { - state Sending; - - transition first start then Sending; - - transition - first Sending - accept after 4 [s] - if not (data <= 0 or batteryCharge < 40) - do action { - assign data := data - 10; - send Data() via dataPort; - } - then Sending; - } - state ConsumePower { - state Consuming; - - transition first start then Consuming; - - transition - first Consuming - accept after 2 [s] - if not (batteryCharge < 40) - do assign batteryCharge := batteryCharge - 10 - then Consuming; - } - } - - transition first start then WaitingPing; - transition - first WaitingPing - accept : PingCommand via commandPort - if (recharging == false and not (data <= 0 or batteryCharge < 40)) - then Transmitting; - } - - state Battery { - state NotRecharging { - entry assign recharging := false; - } - - state Recharging { - entry assign recharging := true; - } - - transition first start then NotRecharging; - - transition - first NotRecharging - accept after 3 [s] - if batteryCharge < 80 - then Recharging; - - transition - first Recharging - accept after 3 [s] - if batteryCharge < 100 - do assign batteryCharge := batteryCharge + 10 - then Recharging; - - transition - first Recharging - accept after 3 [s] - if batteryCharge >= 100 - then NotRecharging; - } - } -} - -item def Data { - // Internal attributes are not yet supported! - //attribute value : Integer; -} - -item def Command; -item def PingCommand :> Command; -item def StopCommand :> Command; -item def StartCommand :> Command; - -port def CommandPort { - in item command : Command; -} -port def DataPort { - out item data : Data; -} - -part def Mission { - port commandPort : CommandPort; - - part groundStation : GroundStation; - part spacecraft : Spacecraft; - - bind commandPort = groundStation.commandPort; - - flow from groundStation.commandPort to spacecraft.commandPort; - flow from spacecraft.dataPort to groundStation.dataPort; -} - -verification def StationBehaviorIdleReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.groundStation.Behaviour.Idle) - ) - } - } - } -} - -verification def StationBehaviorOperationReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.groundStation.Behaviour.Operation) - ) - } - } - } -} - -verification def StationBehaviorOperationWaitingReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.groundStation.Behaviour.Operation.Waiting) - ) - } - } - } -} - - - -// verification def SpacecraftBehaviorCommunicationReachable { -// subject mission : Mission; - -// objective { -// verify requirement { -// require constraint { -// eventually( -// isStateActive(mission.spacecraft.Behaviour.Communication) -// ) -// } -// } -// } -// } - -verification def SpacecraftBehaviorCommunicationWaitingPingReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.spacecraft.Behaviour.Communication.WaitingPing) - ) - } - } - } -} - -verification def SpacecraftBehaviorCommunicationTransmittingReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.spacecraft.Behaviour.Communication.Transmitting) - ) - } - } - } -} - -verification def SpacecraftBehaviorCommunicationTransmittingSendDataReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.spacecraft.Behaviour.Communication.Transmitting.SendData) - ) - } - } - } -} - -verification def SpacecraftBehaviorCommunicationTransmittingSendDataSendingReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.spacecraft.Behaviour.Communication.Transmitting.SendData.Sending) - ) - } - } - } -} - -verification def SpacecraftBehaviorCommunicationTransmittingConsumePowerReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.spacecraft.Behaviour.Communication.Transmitting.ConsumePower) - ) - } - } - } -} - -verification def SpacecraftBehaviorCommunicationTransmittingConsumePowerConsumingReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.spacecraft.Behaviour.Communication.Transmitting.ConsumePower.Consuming) - ) - } - } - } -} - -// verification def SpacecraftBehaviorBatteryReachable { -// subject mission : Mission; - -// objective { -// verify requirement { -// require constraint { -// eventually( -// isStateActive(mission.spacecraft.Behaviour.Battery) -// ) -// } -// } -// } -// } - -verification def SpacecraftBehaviorBatteryNotRechargingReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.spacecraft.Behaviour.Battery.NotRecharging) - ) - } - } - } -} - -verification def SpacecraftBehaviorBatteryRechargingReachable { - subject mission : Mission; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(mission.spacecraft.Behaviour.Battery.Recharging) - ) - } - } - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/stm21.sysml b/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/stm21.sysml deleted file mode 100644 index 2ae208fc..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/stm21.sysml +++ /dev/null @@ -1,92 +0,0 @@ -private import ScalarValues::Integer; -private import ScalarValues::Boolean; - -item def F; -item def G; - -port def InputEvents { - in item f : F; - in item g : G; -} - -part def Stm21 { - port input : InputEvents; - - exhibit state Behaviour parallel { - state R1 { - state S11; - state S12; - - transition first start then S11; - transition - first S11 - accept : F via input - then S12; - } - state R2 { - state S13; - state S14; - transition first start then S13; - transition - first S13 - accept : G via input - then S14; - } - } -} - -verification def S11Reachable { - subject system : Stm21; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.R1.S11) - ) - } - } - } -} - -verification def S12Reachable { - subject system : Stm21; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.R1.S12) - ) - } - } - } -} - -verification def S13Reachable { - subject system : Stm21; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.R2.S13) - ) - } - } - } -} - -verification def S14Reachable { - subject system : Stm21; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.R2.S14) - ) - } - } - } -} diff --git a/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/stm31.sysml b/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/stm31.sysml deleted file mode 100644 index f14c0889..00000000 --- a/subprojects/semantifyr-vscode-server/examples/sysml/TestModels/stm31.sysml +++ /dev/null @@ -1,85 +0,0 @@ -private import ScalarValues::Integer; - -item def A; -item def B; -item def C; -item def D; -item def X; -item def E; - -port def OutputEvents { - out item a : A; - out item b : B; - out item c : C; - out item d : D; - out item x : X; -} - -port def InputEvents { - in item e : E; -} - -part def Stm31 { - attribute i : Integer default 0; - port input : InputEvents; - port output : OutputEvents; - - exhibit state Behaviour { - state S1 { - entry action { - send A() via output; - } - exit action { - assign i := i+1; - send B() via output; - } - } - state S2 { - entry action { - assign i := i*2; - send C() via output; - } - exit action { - send D() via output; - } - } - transition first start then S1; - - transition - first S1 - accept : E via input - do action { - assign i := i + 1; - send D() via output; - } - then S2; - } -} - -verification def S1Reachable { - subject system : Stm31; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.S1) - ) - } - } - } -} - -verification def S2Reachable { - subject system : Stm31; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.S2) - ) - } - } - } -} From 639cf261393db66f5f60dbd13aeb2c53293c36c5 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 22:39:10 +0100 Subject: [PATCH 069/115] Updated vscode server --- subprojects/semantifyr-vscode-server/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/semantifyr-vscode-server/Dockerfile b/subprojects/semantifyr-vscode-server/Dockerfile index 2137505b..cba3337d 100644 --- a/subprojects/semantifyr-vscode-server/Dockerfile +++ b/subprojects/semantifyr-vscode-server/Dockerfile @@ -6,7 +6,7 @@ RUN apt-get update && \ apt-get install -y --no-install-recommends libgomp1 libmpfr-dev openjdk-25-jre && \ apt-get clean && sudo rm -rf /var/lib/apt/lists/* -ARG OVS_VER=v1.106.3 +ARG OVS_VER=v1.109.5 RUN wget -q https://github.com/gitpod-io/openvscode-server/releases/download/openvscode-server-${OVS_VER}/openvscode-server-${OVS_VER}-linux-x64.tar.gz \ && tar xzf openvscode-server-${OVS_VER}-linux-x64.tar.gz \ && mv openvscode-server-${OVS_VER}-linux-x64 /opt/openvscode-server \ From cd2a36528c9bc0c13865583aef73371717225cc2 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Tue, 24 Mar 2026 22:40:09 +0100 Subject: [PATCH 070/115] Changed ordering of providers --- .../main/kotlin/execution/ThetaXstsExecutorProvider.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt index 8e39949e..0b1a2d1d 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutorProvider.kt @@ -29,14 +29,15 @@ class ThetaXstsExecutorProvider { } private fun resolveExecutor(): ThetaXstsExecutor { - if (dockerBasedThetaXstsExecutor.check()) { - return dockerBasedThetaXstsExecutor - } - if (shellBasedThetaXstsExecutor.check()) { return shellBasedThetaXstsExecutor } + // docker-based executor.check is still unreliable... FIXME + if (dockerBasedThetaXstsExecutor.check()) { + return dockerBasedThetaXstsExecutor + } + throw IllegalStateException("Could not find any working Theta Xsts executor.") } From 46303766887595d4f5c23d550d466d0894f439c0 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Wed, 25 Mar 2026 08:59:43 +0100 Subject: [PATCH 071/115] Theta verifier is supposed to throw an exception when errored --- .../theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt | 5 ----- .../src/main/kotlin/execution/ThetaVerificationExecutor.kt | 5 +---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index 5a4c71df..4cc4fc36 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -10,7 +10,6 @@ import com.google.inject.Inject import hu.bme.mit.semantifyr.backends.theta.verification.backannotation.witness.cex.CexAssumptionWitnessTransformer import hu.bme.mit.semantifyr.backends.theta.verification.backannotation.witness.oxsts.InlinedOxstsAssumptionWitnessTransformer import hu.bme.mit.semantifyr.backends.theta.verification.backannotation.witness.xsts.XstsAssumptionWitnessTransformer -import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaErrorVerificationResult import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaPortfolioRunner import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaSafeVerificationResult import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaUnsafeVerificationResult @@ -91,10 +90,6 @@ open class ThetaVerifier : AbstractOxstsVerifier() { val result = verifyXsts(progressContext, xstsModel, timeout, timeUnit) - if (result is ThetaErrorVerificationResult) { - error(result.failureMessage) - } - if (result.hasWitness) { progressContext.reportProgress("Creating witness") val cexPath = Path(result.runtimeDetails.workingDirectory, result.runtimeDetails.cexPath) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt index 4dbf3961..b8d285f6 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt @@ -43,13 +43,10 @@ sealed class ThetaVerificationResult( class ThetaUnknownVerificationResult(runtimeDetails: ThetaVerificationSpecification) : ThetaVerificationResult(runtimeDetails) class ThetaSafeVerificationResult(runtimeDetails: ThetaVerificationSpecification) : ThetaVerificationResult(runtimeDetails) class ThetaUnsafeVerificationResult(runtimeDetails: ThetaVerificationSpecification) : ThetaVerificationResult(runtimeDetails) -class ThetaErrorVerificationResult(runtimeDetails: ThetaVerificationSpecification) : ThetaVerificationResult(runtimeDetails) { - val failureMessage = "Theta execution failed, see: ${runtimeDetails.workingDirectory}/${runtimeDetails.errPath}" -} fun ThetaVerificationSpecification.toVerificationResult(executionResult: ThetaExecutionResult): ThetaVerificationResult { if (executionResult.exitCode != 0) { - return ThetaErrorVerificationResult(this) + error("Theta execution failed: $this") } val logFile = File(workingDirectory, logPath) From dc33d943a9aae1b0c0e9049160dabe5c2dbc9724 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Wed, 25 Mar 2026 08:59:57 +0100 Subject: [PATCH 072/115] Run the mjs file directly --- .../frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index cf291e5a..f4e95826 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -65,15 +65,12 @@ tasks.pnpmInstall { dependsOn(checkoutSysml) } -val checkoutLibrary by tasks.registering(PnpmTask::class) { +val checkoutLibrary by tasks.registering(NodeTask::class) { dependsOn(tasks.pnpmInstall) // node_modules directory is not reliable inputs.file(sysmlDir.file("packages/syside-languageserver/scripts/clone-sysml-release.mjs")) outputs.dir(sysmlDir.dir("SysML-v2-Release")) - pnpmCommand = listOf( - "run", - "prepare-validation", - ) + script = sysmlDir.file("packages/syside-languageserver/scripts/clone-sysml-release.mjs") } val buildExtension by tasks.registering(PnpmTask::class) { From df20b3822e806d95d2e65e9e108bf8b7c8d59e7e Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Thu, 26 Mar 2026 09:19:05 +0100 Subject: [PATCH 073/115] Added additional test cases --- .../TestModels/Crossroads.gamma | 20 +++ .../TestModels/Spacecraft.gamma | 170 +++++++++++++++++- 2 files changed, 188 insertions(+), 2 deletions(-) diff --git a/subprojects/frontends/gamma/gamma-semantics/TestModels/Crossroads.gamma b/subprojects/frontends/gamma/gamma-semantics/TestModels/Crossroads.gamma index 43403713..fcda728c 100644 --- a/subprojects/frontends/gamma/gamma-semantics/TestModels/Crossroads.gamma +++ b/subprojects/frontends/gamma/gamma-semantics/TestModels/Crossroads.gamma @@ -193,6 +193,16 @@ verification case ControllerInterruptedReachable { // TrafficLightController A verification cases +verification case ANormalReachable { + component system : CrossroadSystem + property { EF isActive (system.trafficLightA.Main.Normal) } +} + +verification case AInterruptedReachable { + component system : CrossroadSystem + property { EF isActive (system.trafficLightA.Main.Interrupted) } +} + verification case ACanBeYellow { component system : CrossroadSystem property { EF isActive (system.trafficLightA.Main.Normal.NormalRegion.Yellow) } @@ -220,6 +230,16 @@ verification case ACanBeBlinkingBlack { // TrafficLightController B verification cases +verification case BNormalReachable { + component system : CrossroadSystem + property { EF isActive (system.trafficLightB.Main.Normal) } +} + +verification case BInterruptedReachable { + component system : CrossroadSystem + property { EF isActive (system.trafficLightB.Main.Interrupted) } +} + verification case BCanBeYellow { component system : CrossroadSystem property { EF isActive (system.trafficLightB.Main.Normal.NormalRegion.Yellow) } diff --git a/subprojects/frontends/gamma/gamma-semantics/TestModels/Spacecraft.gamma b/subprojects/frontends/gamma/gamma-semantics/TestModels/Spacecraft.gamma index f6af7717..894b5f8a 100644 --- a/subprojects/frontends/gamma/gamma-semantics/TestModels/Spacecraft.gamma +++ b/subprojects/frontends/gamma/gamma-semantics/TestModels/Spacecraft.gamma @@ -16,6 +16,7 @@ interface Data { in event ping } +@RegionSchedule=bottom-up statechart Station [ port control : requires Control, port connection : requires Data @@ -36,18 +37,19 @@ statechart Station [ state Waiting entry transition to Waiting - transition Waiting to Waiting when event connection.data [receivedData > 10 or receivedData < 100] / raise connection.ping; assign receivedData := receivedData + 10; + transition Waiting to Waiting when event connection.data [receivedData < 100] / raise connection.ping; assign receivedData := receivedData + 10; } } entry transition to Idle transition Idle to Operation when event control.start transition Idle to Operation when timeout startTimeout - transition Operation to Idle when event control.shutdown + // transition Operation to Idle when event control.shutdown transition Operation to Operation when timeout pingTimeout } } +@RegionSchedule=bottom-up statechart Spacecraft[ port connection : provides Data ] { @@ -167,3 +169,167 @@ verification case Spacecraft_BatteryRechargingReachable { property { EF isActive (mission.spacecraft.Battery.Recharging) } } + +/* +verification case Station_ReceivedDataCanReach0 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 0) } +} + +verification case Station_ReceivedDataCanReach10 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 10) } +} + +verification case Station_ReceivedDataCanReach20 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 20) } +} + +verification case Station_ReceivedDataCanReach30 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 30) } +} + +verification case Station_ReceivedDataCanReach40 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 40) } +} + +verification case Station_ReceivedDataCanReach50 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 50) } +} + +verification case Station_ReceivedDataCanReach60 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 60) } +} + +verification case Station_ReceivedDataCanReach70 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 70) } +} + +verification case Station_ReceivedDataCanReach80 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 80) } +} + +verification case Station_ReceivedDataCanReach90 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 90) } +} + +verification case Station_ReceivedDataCanReach100 { + component mission : SpaceMission + + property { EF (mission.station.receivedData >= 100) } +} + +verification case Spacecraft_DataCanReach100 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 100) } +} + +verification case Spacecraft_DataCanReach90 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 90) } +} + +verification case Spacecraft_DataCanReach80 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 80) } +} + +verification case Spacecraft_DataCanReach70 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 70) } +} + +verification case Spacecraft_DataCanReach60 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 60) } +} + +verification case Spacecraft_DataCanReach50 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 50) } +} + +verification case Spacecraft_DataCanReach40 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 40) } +} + +verification case Spacecraft_DataCanReach30 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 30) } +} + +verification case Spacecraft_DataCanReach20 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 20) } +} + +verification case Spacecraft_DataCanReach10 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 10) } +} + +verification case Spacecraft_DataCanReach0 { + component mission : SpaceMission + + property { EF (mission.spacecraft.data <= 0) } +} + +verification case Spacecraft_BatteryAlwaysAbove0 { + component mission : SpaceMission + + property { AG (mission.spacecraft.batteryCharge >= 0) } +} + +verification case Spacecraft_BatteryAlwaysAbove10 { + component mission : SpaceMission + + property { AG (mission.spacecraft.batteryCharge >= 10) } +} + +verification case Spacecraft_BatteryAlwaysAbove20 { + component mission : SpaceMission + + property { AG (mission.spacecraft.batteryCharge >= 20) } +} + +verification case Spacecraft_BatteryAlwaysAbove30 { + component mission : SpaceMission + + property { AG (mission.spacecraft.batteryCharge >= 30) } +} + +verification case Spacecraft_BatteryAlwaysAbove40 { + component mission : SpaceMission + + property { AG (mission.spacecraft.batteryCharge >= 40) } +} +*/ From fe059a2e79b9f5b24ac16a982e1f85e9ffdd824a Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Thu, 26 Mar 2026 09:19:28 +0100 Subject: [PATCH 074/115] Fixed checkout of partial repo --- .../frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd | 2 +- .../frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd index c3dfe0fc..26ac08d4 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.cmd @@ -28,6 +28,6 @@ git remote add origin "%REMOTE_URL%" 2> nul || rem echo Fetch latest git fetch echo Checkout commit -git checkout "%COMMIT%" +git reset "%COMMIT%" --hard endlocal diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh index c2015b9b..1c037db8 100755 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/scripts/checkout.sh @@ -23,4 +23,4 @@ git remote add origin "$REMOTE_URL" 2> /dev/null || true echo "Fetch latest" git fetch echo "Checkout commit" -git checkout "$COMMIT" +git reset "$COMMIT" --hard From 4a5bfbff51be89e117f971521a60477c5fb8e9a9 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Thu, 26 Mar 2026 09:20:16 +0100 Subject: [PATCH 075/115] Added additional verification cases and full spacecraft --- .../TestModels/compressedspacecraft.sysml | 716 ++++++++++++++++++ .../TestModels/spacecraft.sysml | 14 +- .../TestModels/sysml-trace.sysml | 113 --- .../sysml/semantics/SysMLVerificationTests.kt | 19 +- 4 files changed, 728 insertions(+), 134 deletions(-) create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/compressedspacecraft.sysml delete mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/sysml-trace.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/compressedspacecraft.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/compressedspacecraft.sysml new file mode 100644 index 00000000..4b0fa337 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/compressedspacecraft.sysml @@ -0,0 +1,716 @@ +private import ScalarValues::Integer; +private import ScalarValues::Boolean; +private import SI::s; + +part def GroundStation { + port commandPort: CommandPort; + port spacecraftCommandPort: ~CommandPort; + port dataPort: ~DataPort; + + attribute receivedData: Integer default 0; + + exhibit state Behaviour { + transition first start then Idle; + + state Idle; + + transition first Idle accept after 30 [s] then Operation; + transition first Idle accept : StartCommand via commandPort then Operation; + + state Operation { + entry send PingCommand() via spacecraftCommandPort; + + transition first start then Waiting; + + state Waiting; + + transition + first Waiting + accept Data via dataPort + if receivedData < 100 + do assign receivedData := receivedData + 10 + then Waiting; + } + + transition first Operation accept after 10 [s] then Operation; + + // transition first Operation accept : StopCommand via commandPort then Idle; + } +} + +part def Spacecraft { + port commandPort: CommandPort; + port dataPort: DataPort; + + attribute batteryCharge: Integer default 100; + attribute recharging: Boolean default false; + attribute data: Integer default 100; + + exhibit state Behaviour parallel { + state Communication { + transition first start then WaitingPing; + + state WaitingPing; + + transition + first WaitingPing + accept : PingCommand via commandPort + if (recharging == false and not (data <= 0 or batteryCharge <= 40)) + then Transmitting; + + state Transmitting parallel { + state SendData { + transition first start then Sending; + + state Sending; + + transition + first Sending + accept after 4 [s] + if not (data <= 0 or batteryCharge <= 40) + do action { + assign data := data - 10; + send Data() via dataPort; + } + then Sending; + } + state ConsumePower { + transition first start then Consuming; + + state Consuming; + + transition + first Consuming + accept after 2 [s] + if not (batteryCharge <= 40) + do assign batteryCharge := batteryCharge - 10 + then Consuming; + } + } + + transition + first Transmitting + accept after 4 [s] + if data <= 0 or batteryCharge <= 40 + then WaitingPing; + + transition + first Transmitting + accept after 4 [s] + if batteryCharge <= 40 + then WaitingPing; + } + + state Battery { + transition first start then NotRecharging; + + state NotRecharging { + entry assign recharging := false; + } + + state Recharging { + entry assign recharging := true; + } + + transition + first NotRecharging + accept after 3 [s] + if batteryCharge < 80 + then Recharging; + + transition + first Recharging + accept after 3 [s] + if batteryCharge < 100 + do assign batteryCharge := batteryCharge + 10 + then Recharging; + + transition + first Recharging + accept after 3 [s] + if batteryCharge >= 100 + then NotRecharging; + } + } +} + +item def Data { + // Internal attributes are not yet supported! + //attribute value: Integer; +} + +item def Command; +item def PingCommand :> Command; +item def StopCommand :> Command; +item def StartCommand :> Command; + +port def CommandPort { + in item command: Command; +} +port def DataPort { + out item data: Data; +} + +part def Mission { + port commandPort: CommandPort; + + part groundStation: GroundStation; + part spacecraft: Spacecraft; + + bind commandPort = groundStation.commandPort; + + flow from groundStation.spacecraftCommandPort to spacecraft.commandPort; + flow from spacecraft.dataPort to groundStation.dataPort; +} + +verification def StationBehaviorIdleReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.groundStation.Behaviour.Idle) + ) + } + } + } +} + +verification def StationBehaviorOperationReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.groundStation.Behaviour.Operation) + ) + } + } + } +} + +verification def StationBehaviorOperationWaitingReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.groundStation.Behaviour.Operation.Waiting) + ) + } + } + } +} + + + +// verification def SpacecraftBehaviorCommunicationReachable { +// subject mission: Mission; + +// objective { +// verify requirement { +// require constraint { +// eventually( +// isStateActive(mission.spacecraft.Behaviour.Communication) +// ) +// } +// } +// } +// } + +verification def SpacecraftBehaviorCommunicationWaitingPingReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.spacecraft.Behaviour.Communication.WaitingPing) + ) + } + } + } +} + +verification def SpacecraftBehaviorCommunicationTransmittingReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.spacecraft.Behaviour.Communication.Transmitting) + ) + } + } + } +} + +verification def SpacecraftBehaviorCommunicationTransmittingSendDataReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.spacecraft.Behaviour.Communication.Transmitting.SendData) + ) + } + } + } +} + +verification def SpacecraftBehaviorCommunicationTransmittingSendDataSendingReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.spacecraft.Behaviour.Communication.Transmitting.SendData.Sending) + ) + } + } + } +} + +verification def SpacecraftBehaviorCommunicationTransmittingConsumePowerReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.spacecraft.Behaviour.Communication.Transmitting.ConsumePower) + ) + } + } + } +} + +verification def SpacecraftBehaviorCommunicationTransmittingConsumePowerConsumingReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.spacecraft.Behaviour.Communication.Transmitting.ConsumePower.Consuming) + ) + } + } + } +} + +// verification def SpacecraftBehaviorBatteryReachable { +// subject mission: Mission; + +// objective { +// verify requirement { +// require constraint { +// eventually( +// isStateActive(mission.spacecraft.Behaviour.Battery) +// ) +// } +// } +// } +// } + +verification def SpacecraftBehaviorBatteryNotRechargingReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.spacecraft.Behaviour.Battery.NotRecharging) + ) + } + } + } +} + +verification def SpacecraftBehaviorBatteryRechargingReachable { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(mission.spacecraft.Behaviour.Battery.Recharging) + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach0 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 0 + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach10 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 10 + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach20 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 20 + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach30 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 30 + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach40 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 40 + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach50 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 50 + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach60 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 60 + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach70 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 70 + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach80 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 80 + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach90 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 90 + ) + } + } + } +} + +verification def GroundStationReceivedDataCanReach100 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.groundStation.receivedData >= 100 + ) + } + } + } +} + +verification def SpacecraftDataCanReach100 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 100 + ) + } + } + } +} + +verification def SpacecraftDataCanReach90 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 90 + ) + } + } + } +} + +verification def SpacecraftDataCanReach80 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 80 + ) + } + } + } +} + +verification def SpacecraftDataCanReach70 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 70 + ) + } + } + } +} + +verification def SpacecraftDataCanReach60 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 60 + ) + } + } + } +} + +verification def SpacecraftDataCanReach50 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 50 + ) + } + } + } +} + +verification def SpacecraftDataCanReach40 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 40 + ) + } + } + } +} + +verification def SpacecraftDataCanReach30 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 30 + ) + } + } + } +} + +verification def SpacecraftDataCanReach20 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 20 + ) + } + } + } +} + +verification def SpacecraftDataCanReach10 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 10 + ) + } + } + } +} + +verification def SpacecraftDataCanReach0 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + eventually( + mission.spacecraft.data <= 0 + ) + } + } + } +} + +verification def SpacecraftBatteryAlwaysAbove0 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + mission.spacecraft.batteryCharge >= 0 + } + } + } +} + +verification def SpacecraftBatteryAlwaysAbove10 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + mission.spacecraft.batteryCharge >= 10 + } + } + } +} + +verification def SpacecraftBatteryAlwaysAbove20 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + mission.spacecraft.batteryCharge >= 20 + } + } + } +} + +verification def SpacecraftBatteryAlwaysAbove30 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + mission.spacecraft.batteryCharge >= 30 + } + } + } +} + +verification def SpacecraftBatteryAlwaysAbove40 { + subject mission: Mission; + + objective { + verify requirement { + require constraint { + mission.spacecraft.batteryCharge >= 40 + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/spacecraft.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/spacecraft.sysml index ed3d3c96..e8da013a 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/spacecraft.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/spacecraft.sysml @@ -28,7 +28,7 @@ part def GroundStation { first Waiting accept Data via dataPort if receivedData < 100 - do assign receivedData := receivedData + 10 + do assign receivedData := receivedData + 1 then Waiting; } @@ -69,7 +69,7 @@ part def Spacecraft { accept after 4 [s] if not (data <= 0 or batteryCharge <= 40) do action { - assign data := data - 10; + assign data := data - 1; send Data() via dataPort; } then Sending; @@ -83,7 +83,7 @@ part def Spacecraft { first Consuming accept after 2 [s] if not (batteryCharge <= 40) - do assign batteryCharge := batteryCharge - 10 + do assign batteryCharge := batteryCharge - 1 then Consuming; } } @@ -122,7 +122,7 @@ part def Spacecraft { first Recharging accept after 3 [s] if batteryCharge < 100 - do assign batteryCharge := batteryCharge + 10 + do assign batteryCharge := batteryCharge + 1 then Recharging; transition @@ -382,7 +382,7 @@ verification def GroundStationReceivedDataCanReach20 { verify requirement { require constraint { eventually( - mission.groundStation.receivedData >= 30 + mission.groundStation.receivedData >= 20 ) } } @@ -459,7 +459,6 @@ verification def GroundStationReceivedDataCanReach70 { } } -/* Takes too long for the 5 minute timeout verification def GroundStationReceivedDataCanReach80 { subject mission: Mission; @@ -501,7 +500,6 @@ verification def GroundStationReceivedDataCanReach100 { } } } -*/ verification def SpacecraftDataCanReach100 { subject mission: Mission; @@ -615,7 +613,6 @@ verification def SpacecraftDataCanReach30 { } } -/* Takes too long for the 5 minute timeout verification def SpacecraftDataCanReach20 { subject mission: Mission; @@ -657,7 +654,6 @@ verification def SpacecraftDataCanReach0 { } } } -*/ verification def SpacecraftBatteryAlwaysAbove0 { subject mission: Mission; diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/sysml-trace.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/sysml-trace.sysml deleted file mode 100644 index 8da0ecc6..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/sysml-trace.sysml +++ /dev/null @@ -1,113 +0,0 @@ -package Model { - part def MySystem { - attribute x : ScalarValues::Integer default 0; - action myBehavior { - first startShot; - succession __unnamed1 first startShot then m; - merge m; - succession __unnamed2 first m then myStep; - action myStep assign x := x + 1; - succession __unnamed3 first myStep then d; - decide d; - succession repeat first d if x < 2 then m; - succession finish first d if x >= 2 then done; - } - } - part def ExecutedSystem :> MySystem { - private import Occurrences::HappensJustBefore; - private import Occurrences::HappensWhile; - :>> timeSlices : MySystem; - :>> snapshots : MySystem; - action :>> myBehavior { - first startShot; - succession :> __unnamed1 first startShot then m1; - merge m1 :> m; - succession :> __unnamed2 first m1 then myStep1; - succession :> __unnamed3 first myStep1 then d1; - decide d1 :> d; - succession repeat1 :> repeat first d1 if x < 2 then m2; - merge m2 :> m; - succession :> __unnamed2 first m2 then myStep2; - succession :> __unnamed3 first myStep2 then d2; - decide d2 :> d; - succession finish1 :> finish first d2 if x >= 2 then done; - action myStep1 :> myStep; - action myStep2 :> myStep; - } - timeslice before_myBehavior { - attribute :>> x = 0; - } - succession : HappensJustBefore first before_myBehavior then myBehavior_starts; - snapshot myBehavior_starts { - attribute :>> x = 0; - } - succession : HappensWhile first myBehavior.startShot then myBehavior_starts; - succession : HappensJustBefore first myBehavior_starts then between_start_and_m1; - timeslice between_start_and_m1 { - attribute :>> x = 0; - } - succession : HappensJustBefore first between_start_and_m1 then m1_performing; - timeslice m1_performing { - attribute :>> x = 0; - } - succession : HappensWhile first myBehavior.m1 then m1_performing; - succession : HappensJustBefore first m1_performing then between_m1_and_myStep1; - timeslice between_m1_and_myStep1 { - attribute :>> x = 0; - } - succession : HappensJustBefore first between_m1_and_myStep1 then myStep1_performing; - timeslice myStep1_performing { - attribute :>> x = 0; - } - succession : HappensWhile first myBehavior.myStep1 then myStep1_performing; - succession : HappensJustBefore first myStep1_performing then between_myStep1_and_d1; - timeslice between_myStep1_and_d1 { - attribute :>> x = 1; - } - succession : HappensJustBefore first between_myStep1_and_d1 then d1_performing; - timeslice d1_performing { - attribute :>> x = 1; - } - succession : HappensWhile first myBehavior.d1 then d1_performing; - succession : HappensJustBefore first d1_performing then between_d1_and_m2; - timeslice between_d1_and_m2 { - attribute :>> x = 1; - } - succession : HappensJustBefore first between_d1_and_m2 then m2_performing; - timeslice m2_performing { - attribute :>> x = 1; - } - succession : HappensWhile first myBehavior.m2 then m2_performing; - succession : HappensJustBefore first m2_performing then between_m2_and_myStep2; - timeslice between_m2_and_myStep2 { - attribute :>> x = 1; - } - succession : HappensJustBefore first between_m2_and_myStep2 then myStep2_performing; - timeslice myStep2_performing { - attribute :>> x = 1; - } - succession : HappensWhile first myBehavior.myStep2 then myStep2_performing; - succession : HappensJustBefore first myStep2_performing then between_myStep2_and_d2; - timeslice between_myStep2_and_d2 { - attribute :>> x = 2; - } - succession : HappensJustBefore first between_myStep2_and_d2 then d2_performing; - timeslice d2_performing { - attribute :>> x = 2; - } - succession : HappensWhile first myBehavior.d2 then d2_performing; - succession : HappensJustBefore first d2_performing then between_d2_and_done; - timeslice between_d2_and_done { - attribute :>> x = 2; - } - succession : HappensJustBefore first between_d2_and_done then myBehavior_done; - snapshot myBehavior_done { - attribute :>> x = 2; - } - succession : HappensWhile first myBehavior.done then myBehavior_done; - succession : HappensJustBefore first myBehavior_done then after_myBehavior; - timeslice after_myBehavior { - attribute :>> x = 2; - } - } -} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index 1361a29b..8494c9df 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -22,7 +22,6 @@ import org.junit.jupiter.api.Tag import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource -import java.util.concurrent.TimeUnit import java.util.stream.Stream import kotlin.io.path.Path import kotlin.streams.asStream @@ -82,26 +81,23 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { } @JvmStatic - fun `Spacecraft Model Verification Cases Should Pass`(): Stream { - val model = loadModel("TestModels/spacecraft.sysml") + fun `Compressed Spacecraft Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/compressedspacecraft.sysml") return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() } @JvmStatic - fun `Slow Spacecraft Model Verification Cases Should Pass`(): Stream { + fun `Full Spacecraft Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/spacecraft.sysml") - return semantifyrVerificationHelper.collectSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() } } override val logger by loggerFactory() - @Inject - lateinit var semantifyrLoader: SemantifyrLoader - @Inject override lateinit var oxstsVerifierProvider: Provider @@ -132,16 +128,15 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { @ParameterizedTest @MethodSource - fun `Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + fun `Compressed Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { checkVerificationCase(verificationCase) } - @Disabled("The frontend does not add the @Tag('slow') yet") @Tag("slow") @ParameterizedTest @MethodSource - fun `Slow Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { - checkVerificationCase(verificationCase, 60, TimeUnit.MINUTES) + fun `Full Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) } } From 0724e3f523fcae6b6cbce65332b60bd0f82cdf12 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Thu, 26 Mar 2026 10:53:44 +0100 Subject: [PATCH 076/115] Enhanced artifact management --- .../theta/theta-wrapper/build.gradle.kts | 2 +- .../theta/xsts-verifier/build.gradle.kts | 5 +- .../src/main/kotlin/ThetaArtifactManager.kt | 80 ++++++++++++ .../src/main/kotlin/ThetaVerifier.kt | 120 ++++++++++++++---- .../transformation/xsts/OxstsTransformer.kt | 8 +- .../test-models/Simple/.gitignore | 2 +- .../gamma-semantics/TestModels/.gitignore | 9 +- .../sysmlv2-semantics/TestModels/.gitignore | 10 +- .../InlinedOxstsModelCreator.kt | 7 +- .../transformation/OxstsClassInliner.kt | 5 + .../instantiation/OxstsInflator.kt | 2 +- .../serializer/ArtifactManager.kt | 32 +++++ .../serializer/CompilationStateManager.kt | 27 +--- .../serializer/DomainMappingSerializer.kt | 10 +- .../serializer/InlinedArtifactManager.kt | 36 ++++++ .../transformation/tracer/TraceSerializer.kt | 10 +- .../main/kotlin/verification/OxstsVerifier.kt | 10 +- subprojects/semantifyr-cli/build.gradle.kts | 2 +- 18 files changed, 294 insertions(+), 83 deletions(-) create mode 100644 subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt create mode 100644 subprojects/semantics/src/main/kotlin/transformation/serializer/ArtifactManager.kt create mode 100644 subprojects/semantics/src/main/kotlin/transformation/serializer/InlinedArtifactManager.kt diff --git a/subprojects/backends/theta/theta-wrapper/build.gradle.kts b/subprojects/backends/theta/theta-wrapper/build.gradle.kts index 8481dcff..d6e6d6df 100644 --- a/subprojects/backends/theta/theta-wrapper/build.gradle.kts +++ b/subprojects/backends/theta/theta-wrapper/build.gradle.kts @@ -6,7 +6,7 @@ plugins { id("hu.bme.mit.semantifyr.gradle.conventions.jvm") - alias(libs.plugins.kotlin.jvm) + kotlin("jvm") } val thetaXstsCliVersion: String by project diff --git a/subprojects/backends/theta/xsts-verifier/build.gradle.kts b/subprojects/backends/theta/xsts-verifier/build.gradle.kts index 2f115ed1..073702d5 100644 --- a/subprojects/backends/theta/xsts-verifier/build.gradle.kts +++ b/subprojects/backends/theta/xsts-verifier/build.gradle.kts @@ -7,7 +7,8 @@ plugins { id("hu.bme.mit.semantifyr.gradle.conventions.jvm") id("hu.bme.mit.semantifyr.gradle.conventions.theta") - alias(libs.plugins.kotlin.jvm) + kotlin("jvm") + kotlin("plugin.serialization") } repositories { @@ -19,6 +20,8 @@ dependencies { api(project(":xsts.lang")) api(project(":theta-wrapper")) + implementation(libs.kotlinx.serialization.json) + testRuntimeOnly(libs.slf4j.log4j) testFixturesApi(project(":semantics")) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt new file mode 100644 index 00000000..9152ab0d --- /dev/null +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.backends.theta.verification + +import com.google.inject.Inject +import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped +import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager +import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult +import org.eclipse.emf.common.util.URI +import java.io.File +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.encodeToStream +import kotlin.time.Duration +import kotlin.time.Instant + +@Serializable +data class VerificationReport( + var className: String, + var modelPath: String, + var startedAt: Instant, + var result: VerificationCaseRunResult, + var timeout: Duration +) + +@Serializable +data class VerificationTimeMetrics( + var inliningMs: Duration = Duration.ZERO, + var xstsTransformationMs: Duration = Duration.ZERO, + var verificationMs: Duration = Duration.ZERO, + var backAnnotationMs: Duration = Duration.ZERO, + var totalMs: Duration = Duration.ZERO, +) + +@CompilationScoped +class ThetaArtifactManager { + + @Inject + private lateinit var artifactManager: ArtifactManager + + val xstsFile: File + get() = artifactManager.resolve("inlined.xsts") + + val xstsUri: URI + get() = URI.createFileURI(xstsFile.absolutePath) + + fun serialize(data: VerificationTimeMetrics) { + val file = artifactManager.resolve("metrics${File.separator}verification-metrics.json") + file.parentFile.mkdirs() + + val json = Json { + prettyPrint = true + prettyPrintIndent = " " + } + + file.outputStream().buffered().use { + json.encodeToStream(data, it) + } + } + + fun serialize(data: VerificationReport) { + val file = artifactManager.resolve("report.json") + file.parentFile.mkdirs() + + val json = Json { + prettyPrint = true + prettyPrintIndent = " " + explicitNulls = false + } + + file.outputStream().buffered().use { + json.encodeToStream(data, it) + } + } + +} diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index 4cc4fc36..613e4b0b 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -16,12 +16,14 @@ import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaUnsafeVe import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaVerificationResult import hu.bme.mit.semantifyr.backends.theta.verification.transformation.xsts.OxstsTransformer import hu.bme.mit.semantifyr.backends.theta.wrapper.utils.CexReader +import hu.bme.mit.semantifyr.oxsts.lang.naming.OxstsQualifiedNameProvider import hu.bme.mit.semantifyr.oxsts.model.oxsts.AG import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.EF import hu.bme.mit.semantifyr.oxsts.model.oxsts.InlinedOxsts import hu.bme.mit.semantifyr.semantics.transformation.ProgressContext import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped +import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.verification.AbstractOxstsVerifier import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult import hu.bme.mit.semantifyr.semantics.verification.VerificationResult @@ -29,6 +31,11 @@ import hu.bme.mit.semantifyr.xsts.lang.xsts.XstsModel import java.io.File import java.util.concurrent.TimeUnit import kotlin.io.path.Path +import kotlin.time.Clock +import kotlin.time.measureTime +import kotlin.time.measureTimedValue +import kotlin.time.toDuration +import kotlin.time.toDurationUnit @CompilationScoped open class ThetaVerifier : AbstractOxstsVerifier() { @@ -36,6 +43,9 @@ open class ThetaVerifier : AbstractOxstsVerifier() { @Inject private lateinit var oxstsTransformer: OxstsTransformer + @Inject + private lateinit var oxstsQualifiedNameProvider: OxstsQualifiedNameProvider + @Inject private lateinit var cexReader: CexReader @@ -51,6 +61,12 @@ open class ThetaVerifier : AbstractOxstsVerifier() { @Inject private lateinit var thetaPortfolioRunner: ThetaPortfolioRunner + @Inject + private lateinit var artifactManager: ArtifactManager + + @Inject + private lateinit var thetaArtifactManager: ThetaArtifactManager + protected fun transformToXsts(progressContext: ProgressContext, inlinedOxsts: InlinedOxsts): XstsModel { return oxstsTransformer.transform(inlinedOxsts, progressContext) } @@ -63,9 +79,8 @@ open class ThetaVerifier : AbstractOxstsVerifier() { ): ThetaVerificationResult { xstsModel.eResource().save(emptyMap()) - val path = xstsModel.eResource().uri.path().removeSuffix(".xsts") - val name = path.split(File.separator).last() - val workingDirectory = path.replaceAfterLast(File.separator, "") + val workingDirectory = thetaArtifactManager.xstsFile.parent + val name = thetaArtifactManager.xstsFile.nameWithoutExtension return thetaPortfolioRunner.run(workingDirectory, name, progressContext, timeout, timeUnit) } @@ -76,42 +91,93 @@ open class ThetaVerifier : AbstractOxstsVerifier() { timeout: Long, timeUnit: TimeUnit, ): VerificationCaseRunResult { - progressContext.reportProgress("Inlining class") + // TODO: the artifact manager should be created with this base path already initialized -> see scope helper + val filePath = File(classDeclaration.eResource().uri.toFileString()) + val parentPath = filePath.parentFile + val outPath = parentPath.resolve("out") + val basePath = outPath.resolve(filePath.nameWithoutExtension + File.separator + classDeclaration.name) + artifactManager.initialize(basePath) - val inlinedOxsts = inlineClass(progressContext, classDeclaration) + val startedAt = Clock.System.now() - progressContext.checkIsCancelled() - progressContext.reportProgress("Transforming to Xsts") + val result = doRunVerification(progressContext, classDeclaration, timeout, timeUnit) - val xstsModel = transformToXsts(progressContext, inlinedOxsts) + val verificationReport = VerificationReport( + oxstsQualifiedNameProvider.getFullyQualifiedNameString(classDeclaration), + classDeclaration.eResource().uri.toFileString(), + startedAt, + result, + timeout.toDuration(timeUnit.toDurationUnit()) + ) - progressContext.checkIsCancelled() - progressContext.reportProgress("Running Theta Portfolio") + thetaArtifactManager.serialize(verificationReport) + + return result + } - val result = verifyXsts(progressContext, xstsModel, timeout, timeUnit) + private fun doRunVerification( + progressContext: ProgressContext, + classDeclaration: ClassDeclaration, + timeout: Long, + timeUnit: TimeUnit + ): VerificationCaseRunResult { + val verificationTimeMetrics = VerificationTimeMetrics() - if (result.hasWitness) { - progressContext.reportProgress("Creating witness") - val cexPath = Path(result.runtimeDetails.workingDirectory, result.runtimeDetails.cexPath) - val cexModel = cexReader.loadCexModel(cexPath) - val cexWitness = cexAssumptionWitnessTransformer.transform(cexModel) - val xstsWitness = xstsAssumptionWitnessTransformer.transform(xstsModel, cexWitness) - val inlinedOxstsWitness = inlinedOxstsAssumptionWitnessTransformer.transform(inlinedOxsts, xstsWitness) - backAnnotateWitness(inlinedOxstsWitness) + progressContext.reportProgress("Inlining class") + val (inlinedOxsts, inliningDuration) = measureTimedValue { + inlineClass(progressContext, classDeclaration) } + verificationTimeMetrics.inliningMs = inliningDuration - // Because of the Temporal bubbling optimizations these are the only options - val property = inlinedOxsts.property.expression - - if (property is AG && result is ThetaUnsafeVerificationResult) { - return VerificationCaseRunResult(VerificationResult.Failed, "Expected Safe result, got Unsafe instead!") + progressContext.checkIsCancelled() + progressContext.reportProgress("Transforming to Xsts") + val (xstsModel, xstsDuration) = measureTimedValue { + transformToXsts(progressContext, inlinedOxsts) } + verificationTimeMetrics.xstsTransformationMs = xstsDuration - if (property is EF && result is ThetaSafeVerificationResult) { - return VerificationCaseRunResult(VerificationResult.Failed, "Expected Unsafe result, got Safe instead!") + progressContext.checkIsCancelled() + progressContext.reportProgress("Running Theta Portfolio") + val (result, verifyDuration) = measureTimedValue { + try { + // Because of the Temporal bubbling optimizations these are the only options + val property = inlinedOxsts.property.expression + + val result = verifyXsts(progressContext, xstsModel, timeout, timeUnit) + + if (result.hasWitness) { + progressContext.reportProgress("Creating witness") + val backAnnotationDuration = measureTime { + val cexPath = Path(result.runtimeDetails.workingDirectory, result.runtimeDetails.cexPath) + val cexModel = cexReader.loadCexModel(cexPath) + val cexWitness = cexAssumptionWitnessTransformer.transform(cexModel) + val xstsWitness = xstsAssumptionWitnessTransformer.transform(xstsModel, cexWitness) + val inlinedOxstsWitness = inlinedOxstsAssumptionWitnessTransformer.transform(inlinedOxsts, xstsWitness) + backAnnotateWitness(inlinedOxstsWitness) + } + verificationTimeMetrics.backAnnotationMs = backAnnotationDuration + } + + when (property) { + is AG if result is ThetaUnsafeVerificationResult -> { + VerificationCaseRunResult(VerificationResult.Failed, "Expected Safe result, got Unsafe instead!") + } + is EF if result is ThetaSafeVerificationResult -> { + VerificationCaseRunResult(VerificationResult.Failed, "Expected Unsafe result, got Safe instead!") + } + else -> { + VerificationCaseRunResult(VerificationResult.Passed) + } + } + } catch (e: Exception) { + VerificationCaseRunResult(VerificationResult.Errored, e.message) + } } + verificationTimeMetrics.verificationMs = verifyDuration + + thetaArtifactManager.serialize(verificationTimeMetrics) - return VerificationCaseRunResult(VerificationResult.Passed) + return result } } diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsTransformer.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsTransformer.kt index 96199530..fe6f476b 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsTransformer.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsTransformer.kt @@ -11,11 +11,11 @@ import hu.bme.mit.semantifyr.oxsts.model.oxsts.EnumDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.InlinedOxsts import hu.bme.mit.semantifyr.oxsts.model.oxsts.PropertyDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.TransitionDeclaration +import hu.bme.mit.semantifyr.backends.theta.verification.ThetaArtifactManager import hu.bme.mit.semantifyr.semantics.transformation.ProgressContext import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped import hu.bme.mit.semantifyr.xsts.lang.XstsStandaloneSetup import hu.bme.mit.semantifyr.xsts.lang.xsts.XstsModel -import org.eclipse.emf.common.util.URI private typealias XstsTransition = hu.bme.mit.semantifyr.xsts.lang.xsts.Transition private typealias XstsProperty = hu.bme.mit.semantifyr.xsts.lang.xsts.Property @@ -39,6 +39,9 @@ class OxstsTransformer { @Inject private lateinit var traceOperationTransformer: TraceOperationTransformer + @Inject + private lateinit var thetaArtifactManager: ThetaArtifactManager + fun transform(inlinedOxsts: InlinedOxsts, progressContext: ProgressContext): XstsModel { val xsts = createEmptyXsts(inlinedOxsts) @@ -76,8 +79,7 @@ class OxstsTransformer { XstsStandaloneSetup.doSetup(); val resourceSet = inlinedOxsts.eResource().resourceSet - val path = inlinedOxsts.eResource().uri.toString().replace(".oxsts", ".xsts") - val uri = URI.createURI(path) + val uri = thetaArtifactManager.xstsUri val xstsModel = XstsFactory.createXstsModel() diff --git a/subprojects/backends/theta/xsts-verifier/test-models/Simple/.gitignore b/subprojects/backends/theta/xsts-verifier/test-models/Simple/.gitignore index ab234747..1fcb1529 100644 --- a/subprojects/backends/theta/xsts-verifier/test-models/Simple/.gitignore +++ b/subprojects/backends/theta/xsts-verifier/test-models/Simple/.gitignore @@ -1 +1 @@ -simple +out diff --git a/subprojects/frontends/gamma/gamma-semantics/TestModels/.gitignore b/subprojects/frontends/gamma/gamma-semantics/TestModels/.gitignore index a16e7626..741d7b70 100644 --- a/subprojects/frontends/gamma/gamma-semantics/TestModels/.gitignore +++ b/subprojects/frontends/gamma/gamma-semantics/TestModels/.gitignore @@ -1,7 +1,2 @@ -**/*.oxsts -**/*.xsts -**/*.cex -**/theta.err -**/theta.out -**/trace.json -**/mapping.json +out/ +*.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/.gitignore b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/.gitignore index 748c74c1..741d7b70 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/.gitignore +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/.gitignore @@ -1,8 +1,2 @@ -**/*.oxsts -**/*.xsts -**/*.cex -**/*.trace -**/theta.err -**/theta.out -**/trace.json -**/mapping.json +out/ +*.oxsts diff --git a/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt b/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt index 2a9e639a..bd8cf757 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt @@ -16,6 +16,7 @@ import hu.bme.mit.semantifyr.oxsts.model.oxsts.TransitionDeclaration import hu.bme.mit.semantifyr.semantics.expression.RedefinitionAwareReferenceResolver import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped import hu.bme.mit.semantifyr.semantics.transformation.instantiation.InstanceManager +import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.utils.OxstsFactory import org.eclipse.emf.common.util.URI import java.io.File @@ -32,15 +33,17 @@ class InlinedOxstsModelCreator { @Inject private lateinit var redefinitionAwareReferenceResolver: RedefinitionAwareReferenceResolver + @Inject + private lateinit var artifactManager: ArtifactManager + fun createInlinedOxsts(classDeclaration: ClassDeclaration): InlinedOxsts { val resourceSet = classDeclaration.eResource().resourceSet - val path = classDeclaration.eResource().uri.toString().replace(".oxsts", "${File.separator}${classDeclaration.name}${File.separator}inlined.oxsts") + val path = artifactManager.resolve("inlined.oxsts").path val uri = URI.createURI(path) val inlinedOxsts = OxstsFactory.createInlinedOxsts() inlinedOxsts.classDeclaration = classDeclaration - resourceSet.getResource(uri, false)?.delete(mutableMapOf()) resourceSet.createResource(uri).contents += inlinedOxsts initializeInlinedOxstsModel(inlinedOxsts) diff --git a/subprojects/semantics/src/main/kotlin/transformation/OxstsClassInliner.kt b/subprojects/semantics/src/main/kotlin/transformation/OxstsClassInliner.kt index 7a87b82a..80263a72 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/OxstsClassInliner.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/OxstsClassInliner.kt @@ -12,7 +12,9 @@ import hu.bme.mit.semantifyr.oxsts.model.oxsts.InlinedOxsts import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped import hu.bme.mit.semantifyr.semantics.transformation.inliner.OxstsCallInliner import hu.bme.mit.semantifyr.semantics.transformation.instantiation.OxstsInflator +import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.transformation.serializer.CompilationStateManager +import java.io.File @CompilationScoped class OxstsClassInliner { @@ -29,6 +31,9 @@ class OxstsClassInliner { @Inject private lateinit var oxstsInliningManager: CompilationStateManager + @Inject + private lateinit var artifactManager: ArtifactManager + fun inline(progressContext: ProgressContext, classDeclaration: ClassDeclaration): InlinedOxsts { val inlinedOxsts = inlinedOxstsModelCreator.createInlinedOxsts(classDeclaration) diff --git a/subprojects/semantics/src/main/kotlin/transformation/instantiation/OxstsInflator.kt b/subprojects/semantics/src/main/kotlin/transformation/instantiation/OxstsInflator.kt index 6b2b4edb..6b1d3c88 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/instantiation/OxstsInflator.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/instantiation/OxstsInflator.kt @@ -117,7 +117,7 @@ class OxstsInflator { compilationStateManager.commitModelState() - domainMappingSerializer.serializeMapping(inlinedOxsts) + domainMappingSerializer.serializeMapping() } private fun pullDownVariables(inlinedOxsts: InlinedOxsts) { diff --git a/subprojects/semantics/src/main/kotlin/transformation/serializer/ArtifactManager.kt b/subprojects/semantics/src/main/kotlin/transformation/serializer/ArtifactManager.kt new file mode 100644 index 00000000..b92d2022 --- /dev/null +++ b/subprojects/semantics/src/main/kotlin/transformation/serializer/ArtifactManager.kt @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.semantics.transformation.serializer + +import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped +import org.eclipse.emf.common.util.URI +import java.io.File + +@CompilationScoped +class ArtifactManager { + + private lateinit var basePath: File + + fun initialize(basePath: File) { + this.basePath = basePath + basePath.deleteRecursively() + basePath.mkdirs() + } + + fun resolve(relativePath: String): File { + return basePath.resolve(relativePath) + } + + fun resolveUri(relativePath: String): URI { + return URI.createFileURI(resolve(relativePath).absolutePath) + } + +} diff --git a/subprojects/semantics/src/main/kotlin/transformation/serializer/CompilationStateManager.kt b/subprojects/semantics/src/main/kotlin/transformation/serializer/CompilationStateManager.kt index 167c6470..de9d2505 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/serializer/CompilationStateManager.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/serializer/CompilationStateManager.kt @@ -17,16 +17,6 @@ import java.io.File @CompilationScoped class CompilationStateManager { - // TODO: implement structured artifact management: the full base path is the output artifacts - // Make it extendable. Clean on initialization, etc. The Compilation scope manager should create the initial artifact mangaer. And also, probably, it should be configurable in the verification engine builder, so the path where the base path will be located can be configured - // base path: - // - inlined -- inlined oxsts files - // - verification -- verification outputs - // - metrics -- metric data - // - bare files - - private lateinit var basePath: File - private lateinit var inlinedOxsts: InlinedOxsts private lateinit var progressContext: ProgressContext @@ -35,13 +25,14 @@ class CompilationStateManager { @Inject private lateinit var serializer: ISerializer + @Inject + private lateinit var inlinedArtifactManager: InlinedArtifactManager + var isSerializeSteps = false fun initialize(inlinedOxsts: InlinedOxsts, progressContext: ProgressContext) { this.inlinedOxsts = inlinedOxsts this.progressContext = progressContext - basePath = File(inlinedOxsts.eResource().uri.toFileString().replace(".oxsts", "${File.separator}steps")) - basePath.deleteRecursively() commitModelState() } @@ -59,23 +50,19 @@ class CompilationStateManager { } fun commitInflated() { - val modelFile = basePath.resolve("inlfated.oxsts") - serializeInto(modelFile) + serializeInto(inlinedArtifactManager.inflatedOxstsFile) } fun commitInlined() { - val modelFile = basePath.resolve("inlined.oxsts") - serializeInto(modelFile) + serializeInto(inlinedArtifactManager.inlinedOxstsFile) } fun commitDeflated() { - val modelFile = basePath.resolve("deflated.oxsts") - serializeInto(modelFile) + serializeInto(inlinedArtifactManager.deflatedOxstsFile) } fun serializeStep() { - val modelFile = basePath.resolve("step${id++}.oxsts") - serializeInto(modelFile) + serializeInto(inlinedArtifactManager.stepOxstsFile(id++)) } fun serializeInto(modelFile: File) { diff --git a/subprojects/semantics/src/main/kotlin/transformation/serializer/DomainMappingSerializer.kt b/subprojects/semantics/src/main/kotlin/transformation/serializer/DomainMappingSerializer.kt index 996bf0c3..fcb96584 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/serializer/DomainMappingSerializer.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/serializer/DomainMappingSerializer.kt @@ -8,14 +8,12 @@ package hu.bme.mit.semantifyr.semantics.transformation.serializer import com.google.inject.Inject import hu.bme.mit.semantifyr.oxsts.lang.serializer.ExpressionSerializer -import hu.bme.mit.semantifyr.oxsts.model.oxsts.InlinedOxsts import hu.bme.mit.semantifyr.semantics.expression.DeflatedExpressionEvaluationTransformer import hu.bme.mit.semantifyr.semantics.expression.InstanceReferenceProvider import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import kotlinx.serialization.json.encodeToStream -import java.io.File @Serializable data class DomainIdMapping( @@ -47,7 +45,10 @@ class DomainMappingSerializer { @Inject private lateinit var expressionSerializer: ExpressionSerializer - fun serializeMapping(inlinedOxsts: InlinedOxsts) { + @Inject + private lateinit var artifactManager: ArtifactManager + + fun serializeMapping() { val instanceIds = deflatedEvaluationTransformer.evaluateMapping() val data = SerializableDomainMapping( @@ -59,8 +60,7 @@ class DomainMappingSerializer { }, ) - val path = inlinedOxsts.eResource().uri.path().replace("inlined.oxsts", "mapping.json") - val file = File(path) + val file = artifactManager.resolve("mapping.json") val json = Json { prettyPrint = true diff --git a/subprojects/semantics/src/main/kotlin/transformation/serializer/InlinedArtifactManager.kt b/subprojects/semantics/src/main/kotlin/transformation/serializer/InlinedArtifactManager.kt new file mode 100644 index 00000000..54cafb2d --- /dev/null +++ b/subprojects/semantics/src/main/kotlin/transformation/serializer/InlinedArtifactManager.kt @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.semantics.transformation.serializer + +import com.google.inject.Inject +import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped +import java.io.File + +@CompilationScoped +class InlinedArtifactManager { + + @Inject + private lateinit var artifactManager: ArtifactManager + + private val directory: File by lazy { + artifactManager.resolve("inlined").also { it.mkdirs() } + } + + val inflatedOxstsFile: File + get() = directory.resolve("inflated.oxsts") + + val inlinedOxstsFile: File + get() = directory.resolve("inlined.oxsts") + + val deflatedOxstsFile: File + get() = directory.resolve("deflated.oxsts") + + fun stepOxstsFile(id: Int): File { + return directory.resolve("step$id.oxsts") + } + +} diff --git a/subprojects/semantics/src/main/kotlin/transformation/tracer/TraceSerializer.kt b/subprojects/semantics/src/main/kotlin/transformation/tracer/TraceSerializer.kt index 9e7e6553..e7cf8aaf 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/tracer/TraceSerializer.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/tracer/TraceSerializer.kt @@ -14,10 +14,11 @@ import hu.bme.mit.semantifyr.semantics.transformation.backannotation.OxstsClassA import hu.bme.mit.semantifyr.semantics.transformation.backannotation.OxstsClassAssumptionWitness import hu.bme.mit.semantifyr.semantics.transformation.backannotation.OxstsClassAssumptionWitnessState import hu.bme.mit.semantifyr.semantics.transformation.backannotation.OxstsClassAssumptionWitnessStateValue +import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped +import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import kotlinx.serialization.json.encodeToStream -import java.io.File @Serializable data class SerializableTraceArgument( @@ -51,6 +52,7 @@ data class SerializableTraceData( val steps: List, ) +@CompilationScoped class TraceSerializer { @Inject @@ -65,6 +67,9 @@ class TraceSerializer { @Inject private lateinit var expressionSerializer: ExpressionSerializer + @Inject + private lateinit var artifactManager: ArtifactManager + private fun transformInlinedOxstsAssumptionActivatedTrace(trace: OxstsClassAssumptionActivatedTrace): SerializableTrace { val transitionCallTrace = transitionCallTracer.getTransitionCallTrace(trace.traceOperation) @@ -114,8 +119,7 @@ class TraceSerializer { fun serialize(inlinedOxstsAssumptionWitness: OxstsClassAssumptionWitness) { val data = transformWitness(inlinedOxstsAssumptionWitness) - val path = inlinedOxstsAssumptionWitness.inlinedOxsts.eResource().uri.path().replace("inlined.oxsts", "trace.json") - val file = File(path) + val file = artifactManager.resolve("trace.json") val json = Json { prettyPrint = true diff --git a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt index 86295b13..154f349d 100644 --- a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt +++ b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt @@ -14,10 +14,12 @@ import hu.bme.mit.semantifyr.semantics.transformation.ProgressContext import hu.bme.mit.semantifyr.semantics.transformation.backannotation.AssumptionWitnessBackAnnotator import hu.bme.mit.semantifyr.semantics.transformation.backannotation.InlinedOxstsAssumptionWitness import hu.bme.mit.semantifyr.semantics.transformation.backannotation.OxstsClassAssumptionWitnessTransformer +import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.transformation.tracer.TraceSerializer -import org.eclipse.emf.common.util.URI +import kotlinx.serialization.Serializable import java.util.concurrent.TimeUnit +@Serializable data class VerificationCaseRunResult( val result: VerificationResult, val message: String? = null @@ -52,6 +54,9 @@ abstract class AbstractOxstsVerifier : OxstsVerifier { @Inject private lateinit var traceSerializer: TraceSerializer + @Inject + private lateinit var artifactManager: ArtifactManager + open fun inlineClass(progressContext: ProgressContext, classDeclaration: ClassDeclaration): InlinedOxsts { return oxstsClassInliner.inline(progressContext, classDeclaration) } @@ -63,8 +68,7 @@ abstract class AbstractOxstsVerifier : OxstsVerifier { traceSerializer.serialize(classWitness) val resourceSet = inlinedOxstsAssumptionWitness.inlinedOxsts.eResource().resourceSet - val path = inlinedOxstsAssumptionWitness.inlinedOxsts.eResource().uri.toString().replace("inlined.oxsts", "witness.oxsts") - val uri = URI.createURI(path) + val uri = artifactManager.resolveUri("witness.oxsts") resourceSet.getResource(uri, false)?.delete(mutableMapOf()) val resource = resourceSet.createResource(uri) resource.contents += witness diff --git a/subprojects/semantifyr-cli/build.gradle.kts b/subprojects/semantifyr-cli/build.gradle.kts index d3261cd1..bf72a0db 100644 --- a/subprojects/semantifyr-cli/build.gradle.kts +++ b/subprojects/semantifyr-cli/build.gradle.kts @@ -6,7 +6,7 @@ plugins { id("hu.bme.mit.semantifyr.gradle.conventions.application") - alias(libs.plugins.kotlin.jvm) + kotlin("jvm") } repositories { From a9a4b5821963a5b401e1024fe3a6b45238a078db Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Thu, 26 Mar 2026 11:27:33 +0100 Subject: [PATCH 077/115] Added portfolio configuration --- .../kotlin/execution/ThetaXstsExecutor.kt | 7 +++--- .../src/main/kotlin/ThetaArtifactManager.kt | 24 ++++++++++++++++++- .../src/main/kotlin/ThetaVerifier.kt | 21 ++++++++-------- .../backannotation/ThetaSummaryGenerator.kt | 3 +++ .../kotlin/execution/ThetaPorfolioExecutor.kt | 23 +++++++++++++----- .../execution/ThetaVerificationExecutor.kt | 7 +++--- .../src/test/kotlin/GammaVerificationTests.kt | 4 +++- .../commands/VerifyOxstsCommandHandler.java | 3 ++- .../main/kotlin/verification/OxstsVerifier.kt | 13 ++++++++-- .../kotlin/SemantifyrVerificationHelper.kt | 13 +++++----- 10 files changed, 85 insertions(+), 33 deletions(-) diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutor.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutor.kt index 2f77b79d..4c5892d5 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutor.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutor.kt @@ -11,6 +11,8 @@ import org.apache.commons.io.output.NullOutputStream import java.io.File import java.io.OutputStream import java.util.concurrent.TimeUnit +import kotlin.time.Duration +import kotlin.time.DurationUnit import kotlin.time.toDuration import kotlin.time.toDurationUnit @@ -23,8 +25,7 @@ class ThetaExecutionSpecification( val command: List, val logStream: OutputStream = NullOutputStream.INSTANCE, val errorStream: OutputStream = NullOutputStream.INSTANCE, - val timeout: Long = 3, - val timeUnit: TimeUnit = TimeUnit.MINUTES + val timeout: Duration, ) abstract class ThetaXstsExecutor { @@ -38,7 +39,7 @@ abstract class ThetaXstsExecutor { abstract suspend fun execute(thetaExecutionSpecification: ThetaExecutionSpecification): ThetaExecutionResult protected suspend inline fun withTimeout(thetaExecutionSpecification: ThetaExecutionSpecification, crossinline block: suspend () -> T): T { - return withTimeout(thetaExecutionSpecification.timeout.toDuration(thetaExecutionSpecification.timeUnit.toDurationUnit())) { + return withTimeout(thetaExecutionSpecification.timeout) { block() } } diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt index 9152ab0d..293bc135 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt @@ -7,6 +7,7 @@ package hu.bme.mit.semantifyr.backends.theta.verification import com.google.inject.Inject +import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaVerificationSpecification import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult @@ -23,8 +24,15 @@ data class VerificationReport( var className: String, var modelPath: String, var startedAt: Instant, + var totalDuration: Duration, var result: VerificationCaseRunResult, - var timeout: Duration + var timeout: Duration, +) + +@Serializable +data class VerificationPortfolioResult( + val winningSpecification: ThetaVerificationSpecification, + val allArguments: List, ) @Serializable @@ -77,4 +85,18 @@ class ThetaArtifactManager { } } + fun serialize(data: VerificationPortfolioResult) { + val file = artifactManager.resolve("metrics${File.separator}portfolio.json") + file.parentFile.mkdirs() + + val json = Json { + prettyPrint = true + prettyPrintIndent = " " + } + + file.outputStream().buffered().use { + json.encodeToStream(data, it) + } + } + } diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index 613e4b0b..d35db5df 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -32,6 +32,7 @@ import java.io.File import java.util.concurrent.TimeUnit import kotlin.io.path.Path import kotlin.time.Clock +import kotlin.time.Duration import kotlin.time.measureTime import kotlin.time.measureTimedValue import kotlin.time.toDuration @@ -74,22 +75,20 @@ open class ThetaVerifier : AbstractOxstsVerifier() { protected fun verifyXsts( progressContext: ProgressContext, xstsModel: XstsModel, - timeout: Long, - timeUnit: TimeUnit, + timeout: Duration ): ThetaVerificationResult { xstsModel.eResource().save(emptyMap()) val workingDirectory = thetaArtifactManager.xstsFile.parent val name = thetaArtifactManager.xstsFile.nameWithoutExtension - return thetaPortfolioRunner.run(workingDirectory, name, progressContext, timeout, timeUnit) + return thetaPortfolioRunner.run(workingDirectory, name, progressContext, timeout) } override fun verify( progressContext: ProgressContext, classDeclaration: ClassDeclaration, - timeout: Long, - timeUnit: TimeUnit, + timeout: Duration ): VerificationCaseRunResult { // TODO: the artifact manager should be created with this base path already initialized -> see scope helper val filePath = File(classDeclaration.eResource().uri.toFileString()) @@ -100,14 +99,17 @@ open class ThetaVerifier : AbstractOxstsVerifier() { val startedAt = Clock.System.now() - val result = doRunVerification(progressContext, classDeclaration, timeout, timeUnit) + val (result, duration) = measureTimedValue { + doRunVerification(progressContext, classDeclaration, timeout) + } val verificationReport = VerificationReport( oxstsQualifiedNameProvider.getFullyQualifiedNameString(classDeclaration), classDeclaration.eResource().uri.toFileString(), startedAt, + duration, result, - timeout.toDuration(timeUnit.toDurationUnit()) + timeout ) thetaArtifactManager.serialize(verificationReport) @@ -118,8 +120,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { private fun doRunVerification( progressContext: ProgressContext, classDeclaration: ClassDeclaration, - timeout: Long, - timeUnit: TimeUnit + timeout: Duration ): VerificationCaseRunResult { val verificationTimeMetrics = VerificationTimeMetrics() @@ -143,7 +144,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { // Because of the Temporal bubbling optimizations these are the only options val property = inlinedOxsts.property.expression - val result = verifyXsts(progressContext, xstsModel, timeout, timeUnit) + val result = verifyXsts(progressContext, xstsModel, timeout) if (result.hasWitness) { progressContext.reportProgress("Creating witness") diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/ThetaSummaryGenerator.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/ThetaSummaryGenerator.kt index 37de90c6..3c2170e1 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/ThetaSummaryGenerator.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/ThetaSummaryGenerator.kt @@ -26,6 +26,8 @@ import hu.bme.mit.semantifyr.xsts.lang.xsts.XstsModel import org.eclipse.emf.common.util.URI import java.io.File import kotlin.io.path.pathString +import kotlin.time.DurationUnit +import kotlin.time.toDuration class ThetaSummaryGenerator { @@ -93,6 +95,7 @@ class ThetaSummaryGenerator { command, logStream, errorStream, + 10.toDuration(DurationUnit.MINUTES) ) val result = verificationDispatcher.runBlocking { diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt index 58dc41b9..2a92c332 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt @@ -7,6 +7,8 @@ package hu.bme.mit.semantifyr.backends.theta.verification.execution import com.google.inject.Inject +import hu.bme.mit.semantifyr.backends.theta.verification.ThetaArtifactManager +import hu.bme.mit.semantifyr.backends.theta.verification.VerificationPortfolioResult import hu.bme.mit.semantifyr.backends.theta.verification.utils.awaitFirstSuccess import hu.bme.mit.semantifyr.semantics.transformation.ProgressContext import kotlinx.coroutines.CoroutineScope @@ -23,6 +25,7 @@ import java.nio.file.Path import java.util.concurrent.TimeUnit import kotlin.coroutines.cancellation.CancellationException import kotlin.io.path.absolute +import kotlin.time.Duration class ThetaPortfolioRunner { @@ -39,15 +42,17 @@ class ThetaPortfolioRunner { @Inject private lateinit var thetaVerificationExecutor: ThetaVerificationExecutor + @Inject + private lateinit var thetaArtifactManager: ThetaArtifactManager + private suspend fun runWorkflow( workingDirectory: String, name: String, - timeout: Long, - timeUnit: TimeUnit + timeout: Duration ) = supervisorScope { val jobs = parameters.indices.map { index -> async { - val thetaVerificationSpecification = ThetaVerificationSpecification(workingDirectory, name, index, parameters[index], timeout, timeUnit) + val thetaVerificationSpecification = ThetaVerificationSpecification(workingDirectory, name, index, parameters[index], timeout) thetaVerificationExecutor.execute(thetaVerificationSpecification) } } @@ -122,17 +127,23 @@ class ThetaPortfolioRunner { workingDirectory: String, name: String, progressContext: ProgressContext, - timeout: Long, - timeUnit: TimeUnit, + timeout: Duration ) = runBlocking { val absoluteDirectory = Path.of(workingDirectory).absolute().toString() val cancellationChecker = startCancellationChecker(progressContext) - val result = runWorkflow(absoluteDirectory, name, timeout, timeUnit) + val result = runWorkflow(absoluteDirectory, name, timeout) cancellationChecker.cancel() + thetaArtifactManager.serialize( + VerificationPortfolioResult( + result.runtimeDetails, + parameters + ) + ) + result } diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt index b8d285f6..d5bb9b4b 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt @@ -12,16 +12,18 @@ import hu.bme.mit.semantifyr.backends.theta.wrapper.execution.ThetaExecutionResu import hu.bme.mit.semantifyr.backends.theta.wrapper.execution.ThetaExecutionSpecification import hu.bme.mit.semantifyr.backends.theta.wrapper.execution.ThetaXstsExecutorProvider import hu.bme.mit.semantifyr.semantics.verification.VerificationDispatcher +import kotlinx.serialization.Serializable import java.io.File import java.util.concurrent.TimeUnit +import kotlin.time.Duration +@Serializable class ThetaVerificationSpecification( val workingDirectory: String, val name: String, val id: Int, val parameter: String, - val timeout: Long = 3, - val timeUnit: TimeUnit = TimeUnit.MINUTES + val timeout: Duration, ) { val modelFileName = "$name.xsts" val cexFileName = "out.cex" @@ -91,7 +93,6 @@ class ThetaVerificationExecutor { logStream, errorStream, timeout, - timeUnit, ) } diff --git a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt index b1c58b88..cd6d5c4d 100644 --- a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt +++ b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt @@ -27,6 +27,8 @@ import java.util.concurrent.TimeUnit import java.util.stream.Stream import kotlin.io.path.Path import kotlin.streams.asStream +import kotlin.time.DurationUnit +import kotlin.time.toDuration @Tag("verification") @InjectWithOxstsSemantics @@ -132,7 +134,7 @@ class GammaVerificationTests : BaseSemantifyrVerificationTest() { @MethodSource @Disabled("There are no slow crossroads verification cases just yet.") fun `Slow Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { - checkVerificationCase(verificationCase, 60, TimeUnit.MINUTES) + checkVerificationCase(verificationCase, 60.toDuration(DurationUnit.MINUTES)) } } diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java index 1653c6c8..b0f115bd 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java @@ -20,6 +20,7 @@ import org.eclipse.xtext.ide.server.ILanguageServerAccess; import org.eclipse.xtext.util.CancelIndicator; +import java.time.Duration; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -71,7 +72,7 @@ protected Object execute(ClassDeclaration arguments, ILanguageServerAccess acces progressContext.checkIsCancelled(); compilationStateManagerProvider.get().setSerializeSteps(false); - result.complete(oxstsVerifierProvider.get().verify(progressContext, classDelcaration, 3, TimeUnit.MINUTES)); + result.complete(oxstsVerifierProvider.get().verify(progressContext, classDelcaration, Duration.ofMinutes(5))); }); } catch (Exception e) { result.completeExceptionally(e); diff --git a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt index 154f349d..a4fa7f1e 100644 --- a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt +++ b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt @@ -18,6 +18,8 @@ import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.transformation.tracer.TraceSerializer import kotlinx.serialization.Serializable import java.util.concurrent.TimeUnit +import kotlin.time.Duration +import kotlin.time.toKotlinDuration @Serializable data class VerificationCaseRunResult( @@ -34,8 +36,7 @@ interface OxstsVerifier { fun verify( progressContext: ProgressContext, classDeclaration: ClassDeclaration, - timeout: Long = 10L, - timeUnit: TimeUnit = TimeUnit.MINUTES + timeout: Duration ): VerificationCaseRunResult } @@ -75,4 +76,12 @@ abstract class AbstractOxstsVerifier : OxstsVerifier { resource.save(emptyMap()) } + fun verify( + progressContext: ProgressContext, + classDeclaration: ClassDeclaration, + timeout: java.time.Duration + ): VerificationCaseRunResult { + return verify(progressContext, classDeclaration, timeout.toKotlinDuration()) + } + } diff --git a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt index 6e79d214..939928b6 100644 --- a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt +++ b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt @@ -28,6 +28,9 @@ import org.junit.jupiter.params.provider.Arguments import org.slf4j.Logger import java.util.concurrent.TimeUnit import kotlin.streams.asSequence +import kotlin.time.Duration +import kotlin.time.DurationUnit +import kotlin.time.toDuration /** * Helper class to be instantiated from a Global injector such as StandaloneOxstsSemanticsRuntimeModule#injector @@ -149,23 +152,21 @@ abstract class BaseSemantifyrVerificationTest { fun executeVerificationCase( classDeclaration: ClassDeclaration, - timeout: Long = 30L, - timeUnit: TimeUnit = TimeUnit.MINUTES + timeout: Duration = 30.toDuration(DurationUnit.MINUTES) ): VerificationCaseRunResult { logger.info { "Verifying class: ${oxstsQualifiedNameProvider.getFullyQualifiedNameString(classDeclaration)}" } - return oxstsVerifierProvider.get().verify(loggerContext, classDeclaration, timeout, timeUnit) + return oxstsVerifierProvider.get().verify(loggerContext, classDeclaration, timeout) } fun checkVerificationCase( verificationCase: ClassDeclaration, - timeout: Long = 30L, - timeUnit: TimeUnit = TimeUnit.MINUTES + timeout: Duration = 30.toDuration(DurationUnit.MINUTES) ) { compilationScopeHelper.runInCompilationScope(verificationCase) { - val result = executeVerificationCase(it, timeout, timeUnit) + val result = executeVerificationCase(it, timeout) Assertions.assertEquals(VerificationResult.Passed, result.result) } From 54bc8a35dcf7269e7c69449b3401becf31ad223e Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Thu, 26 Mar 2026 12:24:35 +0100 Subject: [PATCH 078/115] Performed code reformating --- .github/workflows/build.yml | 36 ++-- CONTRIBUTORS.md | 6 +- README.md | 2 +- .../gradle/conventions/jvm.gradle.kts | 1 - .../gradle/conventions/theta.gradle.kts | 1 + .../mit/semantifyr/gradle/xtext.gradle.kts | 1 - gradle/libs.versions.toml | 4 +- .../cex/lang/CexStandaloneSetup.java | 6 +- .../cex/lang/validation/CexValidator.java | 4 +- .../kotlin/execution/ThetaXstsExecutor.kt | 4 - .../src/main/kotlin/ThetaArtifactManager.kt | 4 +- .../src/main/kotlin/ThetaVerifier.kt | 5 +- .../backannotation/ThetaSummaryGenerator.kt | 4 +- .../witness/cex/CexAssumptionWitness.kt | 8 +- ...nlinedOxstsAssumptionWitnessTransformer.kt | 8 +- .../witness/xsts/XstsAssumptionWitness.kt | 8 +- .../kotlin/execution/ThetaPorfolioExecutor.kt | 5 +- .../execution/ThetaVerificationExecutor.kt | 2 +- .../transformation/xsts/OxstsTransformer.kt | 2 +- .../xsts/OxstsVariableTransformer.kt | 2 - .../test/kotlin/ThetaXstsVerificationTests.kt | 2 - .../xsts/lang/XstsStandaloneSetup.java | 5 - .../resource/XstsResourceDescription.java | 3 +- .../xsts/lang/validation/XstsValidator.java | 4 +- .../src/test/kotlin/GammaVerificationTests.kt | 4 - .../gamma/lang/ide/GammaIdeSetup.java | 2 +- .../gamma/lang/GammaStandaloneSetup.java | 6 +- .../lang/formatting2/GammaFormatter.java | 2 +- .../sysmlv2/sysmlv2-frontend/build.gradle.kts | 73 +++++---- .../sysmlv2-semantics/build.gradle.kts | 4 +- .../sysml/semantics/SysMLVerificationTests.kt | 1 - .../oxsts/lang/ide/OxstsIdeSetup.java | 8 +- .../OxstsIdeContentProposalProvider.java | 6 +- .../OxstsSemanticHighlightingCalculator.java | 106 ++++++------ .../lang/ide/server/OxstsLanguageServer.java | 4 +- .../codelens/OxstsCodeLensProvider.java | 4 +- .../NavigateToRedefinersCommandHandler.java | 1 - .../server/commands/OxstsCommandService.java | 2 +- .../commands/VerifyOxstsCommandHandler.java | 1 - .../concurrent/SemantifyrRequestManager.java | 5 +- .../lang/conversion/IDValueConverter.java | 16 +- .../conversion/IdentifierValueConverter.java | 56 +++---- .../conversion/QUOTED_IDValueConverter.java | 8 +- .../oxsts/lang/debugging/TypeRenderer.java | 5 +- .../library/ResourceBasedOxstsLibrary.java | 1 + .../resource/OxstsResourceDescription.java | 5 +- .../scoping/OxstsGlobalScopeProvider.java | 4 +- .../scoping/domain/DeclarationHolder.java | 6 +- .../domain/MergedDomainMemberCollection.java | 2 +- .../oxsts/lang/scoping/imports/Import.java | 2 +- .../selectables/TrimPrefixSelectable.java | 4 +- .../semantics/MultiplicityRangeEvaluator.java | 5 +- .../oxsts/lang/semantics/OppositeHandler.java | 1 - .../lang/semantics/RedefinersFinder.java | 3 +- .../oxsts/lang/semantics/SubsetHandler.java | 2 - .../ConstantExpressionEvaluator.java | 4 +- .../expression/ExpressionEvaluator.java | 2 +- .../lang/serializer/ExpressionSerializer.java | 1 + .../OnResourceSetChangeEvictingCache.java | 9 +- .../oxsts/lang/utils/OxstsUtils.java | 6 +- .../lang/tests/SimpleOxstsParsingTest.java | 40 ++--- .../StaticElementValueEvaluatorProvider.kt | 1 - .../StaticExpressionEvaluatorProvider.kt | 1 - ...stantFalseAssumptionPropagatorOptimizer.kt | 6 +- .../optimization/ExpressionOptimizer.kt | 14 +- .../InlinedOxstsOperationOptimizer.kt | 8 +- .../OperationFlattenerOptimizer.kt | 4 +- .../RedundantOperationRemoverOptimizer.kt | 10 +- .../kotlin/optimization/VariableOptimizer.kt | 14 +- .../main/kotlin/reader/SemantifyrLoader.kt | 1 - .../InlinedOxstsModelCreator.kt | 2 - .../transformation/OxstsClassInliner.kt | 1 - .../OxstsClassAssumptionWitnessTransformer.kt | 6 +- .../inliner/OperationCallInliner.kt | 2 +- .../serializer/DomainMappingSerializer.kt | 2 +- .../transformation/tracer/TraceSerializer.kt | 8 +- .../tracer/TransitionCallTracer.kt | 2 +- .../src/main/kotlin/utils/OxstsFactory.kt | 1 + .../main/kotlin/verification/OxstsVerifier.kt | 1 - .../src/main/resources/log4j2.properties | 10 +- .../kotlin/SemantifyrVerificationHelper.kt | 1 - subprojects/semantifyr-cli/build.gradle.kts | 38 ----- .../src/main/kotlin/SemantifyrCli.kt | 24 --- .../main/kotlin/commands/CompileCommand.kt | 53 ------ .../src/main/kotlin/commands/VerifyCommand.kt | 113 ------------- .../src/main/resources/log4j2.properties | 8 - .../semantifyr-vscode-server/build.gradle.kts | 20 +-- .../semantifyr-vscode/.vscode/extensions.json | 4 +- .../semantifyr-vscode/.vscode/launch.json | 154 +++++++++--------- .../semantifyr-vscode/.vscode/settings.json | 14 +- .../semantifyr-vscode/.vscode/tasks.json | 34 ++-- .../semantifyr-vscode/build.gradle.kts | 13 +- .../language-configuration.json | 118 ++++++++++---- subprojects/semantifyr-vscode/package.json | 24 ++- .../syntaxes/oxsts.tmLanguage.json | 12 +- subprojects/semantifyr-vscode/tsconfig.json | 47 +++--- 96 files changed, 568 insertions(+), 741 deletions(-) delete mode 100644 subprojects/semantifyr-cli/build.gradle.kts delete mode 100644 subprojects/semantifyr-cli/src/main/kotlin/SemantifyrCli.kt delete mode 100644 subprojects/semantifyr-cli/src/main/kotlin/commands/CompileCommand.kt delete mode 100644 subprojects/semantifyr-cli/src/main/kotlin/commands/VerifyCommand.kt delete mode 100644 subprojects/semantifyr-cli/src/main/resources/log4j2.properties diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4e537d01..50854604 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,30 +23,18 @@ jobs: - macos-latest runs-on: ${{ matrix.os }} steps: - - name: Checkout code - uses: actions/checkout@v6 - - name: Set up JDK - uses: actions/setup-java@v5 - with: - java-version: 25 - distribution: adopt - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 - - name: Gradle build - shell: bash - run: ./gradlew build - - name: Bundle Extension - shell: bash - run: ./gradlew :semantifyr-vscode:bundleExtension - - name: Upload Artifacts - if: ${{ matrix.os == 'ubuntu-latest' }} - uses: actions/upload-artifact@v7 - with: - path: | - **/build/vscode/ - **/build/distributions/ - **/build/reports/ - **/build/test-results/ + - name: Checkout code + uses: actions/checkout@v6 + - name: Set up JDK + uses: actions/setup-java@v5 + with: + java-version: 25 + distribution: adopt + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v5 + - name: Gradle build + shell: bash + run: ./gradlew build reuse-check: name: REUSE Compliance Check diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index dc6f4c44..2a31c5c9 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -11,6 +11,6 @@ **Project leader** Vince, Molnár Contributors (in alphabetical order): - - - Ármin, Zavada - - Marussy, Kristóf + +- Ármin, Zavada +- Marussy, Kristóf diff --git a/README.md b/README.md index 049321db..c3185bb3 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Use Java 25 for building. Run `gradlew build` to assemble and test the project, including regression testing and formal verifications. The required environment (e.g., Theta binaries) is automatically constructed by Gradle. Tests should run in 10-20 minutes. -To execute slow verification cases (the longest may take ~1 hour), run `gradlew testSlowVerificationCases`. +To execute slow verification cases (the longest may take ~1 hour), run `gradlew testSlowVerificationCases`. Or run `gradlew allTests` for all tests. diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts index b4a89ba5..d680032b 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts @@ -8,7 +8,6 @@ package hu.bme.mit.semantifyr.gradle.conventions import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.api.tasks.testing.logging.TestExceptionFormat -import org.gradle.kotlin.dsl.registering plugins { `java-library` diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts index d1165efd..56d38a71 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts @@ -25,6 +25,7 @@ dependencies { * Simple Build service that acts as a lock or throttling device preventing parallel execution */ abstract class VerificationTestService : BuildService + val verificationTestServiceName = "verificationTestService" val verificationTestServiceProvider = gradle.sharedServices.registerIfAbsent(verificationTestServiceName, VerificationTestService::class) { // only allow at most 1 verification task per Gradle build diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/xtext.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/xtext.gradle.kts index d5e719db..04e27589 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/xtext.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/xtext.gradle.kts @@ -7,7 +7,6 @@ package hu.bme.mit.semantifyr.gradle import org.gradle.accessors.dm.LibrariesForLibs -import org.gradle.kotlin.dsl.the plugins { id("hu.bme.mit.semantifyr.gradle.mwe2") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8dd043f0..96263fa6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -52,8 +52,8 @@ viatra-query-runtime = { group = "org.eclipse.viatra", name = "viatra-query-runt viatra-transformation-runtime = { group = "org.eclipse.viatra", name = "viatra-transformation-runtime", version.ref = "viatra" } guice = { group = "com.google.inject", name = "guice", version.ref = "guice" } guice-extensions-assistedinject = { group = "com.google.inject.extensions", name = "guice-assistedinject", version.ref = "guice" } -docker-java-core = { group = "com.github.docker-java" , name = "docker-java-core", version.ref = "dockerJava" } -docker-java-transport = { group = "com.github.docker-java" , name = "docker-java-transport-httpclient5", version.ref = "dockerJava" } +docker-java-core = { group = "com.github.docker-java", name = "docker-java-core", version.ref = "dockerJava" } +docker-java-transport = { group = "com.github.docker-java", name = "docker-java-transport-httpclient5", version.ref = "dockerJava" } [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } diff --git a/subprojects/backends/theta/cex.lang/src/main/java/hu/bme/mit/semantifyr/cex/lang/CexStandaloneSetup.java b/subprojects/backends/theta/cex.lang/src/main/java/hu/bme/mit/semantifyr/cex/lang/CexStandaloneSetup.java index dc248d91..46d8f542 100644 --- a/subprojects/backends/theta/cex.lang/src/main/java/hu/bme/mit/semantifyr/cex/lang/CexStandaloneSetup.java +++ b/subprojects/backends/theta/cex.lang/src/main/java/hu/bme/mit/semantifyr/cex/lang/CexStandaloneSetup.java @@ -9,7 +9,7 @@ */ public class CexStandaloneSetup extends CexStandaloneSetupGenerated { - public static void doSetup() { - new CexStandaloneSetup().createInjectorAndDoEMFRegistration(); - } + public static void doSetup() { + new CexStandaloneSetup().createInjectorAndDoEMFRegistration(); + } } diff --git a/subprojects/backends/theta/cex.lang/src/main/java/hu/bme/mit/semantifyr/cex/lang/validation/CexValidator.java b/subprojects/backends/theta/cex.lang/src/main/java/hu/bme/mit/semantifyr/cex/lang/validation/CexValidator.java index 75b450b2..dc30b827 100644 --- a/subprojects/backends/theta/cex.lang/src/main/java/hu/bme/mit/semantifyr/cex/lang/validation/CexValidator.java +++ b/subprojects/backends/theta/cex.lang/src/main/java/hu/bme/mit/semantifyr/cex/lang/validation/CexValidator.java @@ -10,7 +10,7 @@ * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation */ public class CexValidator extends AbstractCexValidator { - + // public static final String INVALID_NAME = "invalidName"; // // @Check @@ -21,5 +21,5 @@ public class CexValidator extends AbstractCexValidator { // INVALID_NAME); // } // } - + } diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutor.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutor.kt index 4c5892d5..8169c442 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutor.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ThetaXstsExecutor.kt @@ -10,11 +10,7 @@ import kotlinx.coroutines.withTimeout import org.apache.commons.io.output.NullOutputStream import java.io.File import java.io.OutputStream -import java.util.concurrent.TimeUnit import kotlin.time.Duration -import kotlin.time.DurationUnit -import kotlin.time.toDuration -import kotlin.time.toDurationUnit class ThetaExecutionResult( val exitCode: Int, diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt index 293bc135..3f13bbc6 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt @@ -11,11 +11,11 @@ import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaVerifica import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult -import org.eclipse.emf.common.util.URI -import java.io.File import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import kotlinx.serialization.json.encodeToStream +import org.eclipse.emf.common.util.URI +import java.io.File import kotlin.time.Duration import kotlin.time.Instant diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index d35db5df..9fbd6f10 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -29,14 +29,11 @@ import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult import hu.bme.mit.semantifyr.semantics.verification.VerificationResult import hu.bme.mit.semantifyr.xsts.lang.xsts.XstsModel import java.io.File -import java.util.concurrent.TimeUnit import kotlin.io.path.Path import kotlin.time.Clock import kotlin.time.Duration import kotlin.time.measureTime import kotlin.time.measureTimedValue -import kotlin.time.toDuration -import kotlin.time.toDurationUnit @CompilationScoped open class ThetaVerifier : AbstractOxstsVerifier() { @@ -109,7 +106,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { startedAt, duration, result, - timeout + timeout, ) thetaArtifactManager.serialize(verificationReport) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/ThetaSummaryGenerator.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/ThetaSummaryGenerator.kt index 3c2170e1..390a5e9c 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/ThetaSummaryGenerator.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/ThetaSummaryGenerator.kt @@ -84,7 +84,7 @@ class ThetaSummaryGenerator { "--model", "inlined.xsts", "--flatten-depth", "0", "--stacktrace", - "--trace-dir", "traces" + "--trace-dir", "traces", ) val logStream = workingDirectory.resolve("tracing/log.out").ensureExistsOutputStream() @@ -95,7 +95,7 @@ class ThetaSummaryGenerator { command, logStream, errorStream, - 10.toDuration(DurationUnit.MINUTES) + 10.toDuration(DurationUnit.MINUTES), ) val result = verificationDispatcher.runBlocking { diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/cex/CexAssumptionWitness.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/cex/CexAssumptionWitness.kt index 8ea11d68..1cf4ba31 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/cex/CexAssumptionWitness.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/cex/CexAssumptionWitness.kt @@ -22,7 +22,7 @@ class CexAssumptionWitnessStateVariableValue( private fun ExplVariableValue.toCexVariable(): CexAssumptionWitnessStateVariableValue { return CexAssumptionWitnessStateVariableValue( variable, - value + value, ) } @@ -37,7 +37,7 @@ private fun XstsState.toCexState(): CexAssumptionWitnessState { require(state is ExplStateValue) return CexAssumptionWitnessState( - state.variableValues.map { it.toCexVariable() } + state.variableValues.map { it.toCexVariable() }, ) } @@ -46,7 +46,7 @@ class CexAssumptionWitness( override val initializedState: CexAssumptionWitnessState?, override val transitionStates: List, override val nextStateMap: Map>, -): AssumptionWitness() +) : AssumptionWitness() private val XstsState.isTran get() = isPostInit && isLastInternal @@ -91,7 +91,7 @@ class CexAssumptionWitnessTransformer { initialCexState, initializedCexState, cexStates, - nextStateMap + nextStateMap, ) } diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/oxsts/InlinedOxstsAssumptionWitnessTransformer.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/oxsts/InlinedOxstsAssumptionWitnessTransformer.kt index c097e6b6..d5497ee9 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/oxsts/InlinedOxstsAssumptionWitnessTransformer.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/oxsts/InlinedOxstsAssumptionWitnessTransformer.kt @@ -43,7 +43,7 @@ class InlinedOxstsAssumptionWitnessTransformer { InlinedOxstsAssumptionWitnessState( transformStateValues(stateVariableValues), - transformTraceValues(traceVariableValues) + transformTraceValues(traceVariableValues), ) } @@ -58,7 +58,7 @@ class InlinedOxstsAssumptionWitnessTransformer { it.value is LiteralBoolean && it.value.isValue }.map { InlinedOxstsAssumptionActivatedTrace( - traceOperationTransformer.getTraceOperation(it.variableDeclaration as TopLevelVariableDeclaration) + traceOperationTransformer.getTraceOperation(it.variableDeclaration as TopLevelVariableDeclaration), ) } } @@ -73,7 +73,7 @@ class InlinedOxstsAssumptionWitnessTransformer { return InlinedOxstsAssumptionWitnessStateValue( variable, - xstsExpressionToOxstsExpressionTransformer.transform(variableValue.value) + xstsExpressionToOxstsExpressionTransformer.transform(variableValue.value), ) } @@ -100,7 +100,7 @@ class InlinedOxstsAssumptionWitnessTransformer { initializedState, transitionStates, nextStateMap, - inlinedOxsts + inlinedOxsts, ) } diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/xsts/XstsAssumptionWitness.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/xsts/XstsAssumptionWitness.kt index 816068d8..023dee3e 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/xsts/XstsAssumptionWitness.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/backannotation/witness/xsts/XstsAssumptionWitness.kt @@ -32,7 +32,7 @@ class XstsAssumptionWitness( override val transitionStates: List, override val nextStateMap: Map>, val xstsModel: XstsModel -): AssumptionWitness() +) : AssumptionWitness() class XstsAssumptionWitnessTransformer { @@ -47,7 +47,7 @@ class XstsAssumptionWitnessTransformer { SemantifyrUtils.isLocalVar(it.variableName) }.map { transform(it) - } + }, ) } @@ -61,7 +61,7 @@ class XstsAssumptionWitnessTransformer { return XstsAssumptionWitnessStateVariableValue( variable, - cexExpressionToXstsExpressionTransformer.transform(variableValue.value) + cexExpressionToXstsExpressionTransformer.transform(variableValue.value), ) } @@ -88,7 +88,7 @@ class XstsAssumptionWitnessTransformer { initializedState, transitionStates, nextStateMap, - xstsModel + xstsModel, ) } diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt index 2a92c332..b5bb05a3 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt @@ -22,7 +22,6 @@ import kotlinx.coroutines.runBlocking import kotlinx.coroutines.supervisorScope import org.slf4j.LoggerFactory import java.nio.file.Path -import java.util.concurrent.TimeUnit import kotlin.coroutines.cancellation.CancellationException import kotlin.io.path.absolute import kotlin.time.Duration @@ -140,8 +139,8 @@ class ThetaPortfolioRunner { thetaArtifactManager.serialize( VerificationPortfolioResult( result.runtimeDetails, - parameters - ) + parameters, + ), ) result diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt index d5bb9b4b..45c474d4 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt @@ -14,7 +14,6 @@ import hu.bme.mit.semantifyr.backends.theta.wrapper.execution.ThetaXstsExecutorP import hu.bme.mit.semantifyr.semantics.verification.VerificationDispatcher import kotlinx.serialization.Serializable import java.io.File -import java.util.concurrent.TimeUnit import kotlin.time.Duration @Serializable @@ -42,6 +41,7 @@ sealed class ThetaVerificationResult( ) { val hasWitness = File(runtimeDetails.workingDirectory, runtimeDetails.cexPath).exists() } + class ThetaUnknownVerificationResult(runtimeDetails: ThetaVerificationSpecification) : ThetaVerificationResult(runtimeDetails) class ThetaSafeVerificationResult(runtimeDetails: ThetaVerificationSpecification) : ThetaVerificationResult(runtimeDetails) class ThetaUnsafeVerificationResult(runtimeDetails: ThetaVerificationSpecification) : ThetaVerificationResult(runtimeDetails) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsTransformer.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsTransformer.kt index fe6f476b..c88b1789 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsTransformer.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsTransformer.kt @@ -7,11 +7,11 @@ package hu.bme.mit.semantifyr.backends.theta.verification.transformation.xsts import com.google.inject.Inject +import hu.bme.mit.semantifyr.backends.theta.verification.ThetaArtifactManager import hu.bme.mit.semantifyr.oxsts.model.oxsts.EnumDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.InlinedOxsts import hu.bme.mit.semantifyr.oxsts.model.oxsts.PropertyDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.TransitionDeclaration -import hu.bme.mit.semantifyr.backends.theta.verification.ThetaArtifactManager import hu.bme.mit.semantifyr.semantics.transformation.ProgressContext import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped import hu.bme.mit.semantifyr.xsts.lang.XstsStandaloneSetup diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsVariableTransformer.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsVariableTransformer.kt index e804f772..6b22c0a5 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsVariableTransformer.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/transformation/xsts/OxstsVariableTransformer.kt @@ -8,8 +8,6 @@ package hu.bme.mit.semantifyr.backends.theta.verification.transformation.xsts import com.google.inject.Inject import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltinAnnotationHandler -import hu.bme.mit.semantifyr.oxsts.lang.semantics.typesystem.ExpressionTypeEvaluatorProvider -import hu.bme.mit.semantifyr.oxsts.model.oxsts.DomainDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.LocalVarDeclarationOperation import hu.bme.mit.semantifyr.oxsts.model.oxsts.VariableDeclaration import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped diff --git a/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt b/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt index e459d3ee..9ef13458 100644 --- a/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt +++ b/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt @@ -13,10 +13,8 @@ import hu.bme.mit.semantifyr.semantics.BaseSemantifyrVerificationTest import hu.bme.mit.semantifyr.semantics.InjectWithOxstsSemantics import hu.bme.mit.semantifyr.semantics.SemantifyrVerificationHelper import hu.bme.mit.semantifyr.semantics.StandaloneOxstsSemanticsRuntimeModule -import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader import hu.bme.mit.semantifyr.semantics.utils.loggerFactory import org.junit.jupiter.api.Tag -import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource diff --git a/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/XstsStandaloneSetup.java b/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/XstsStandaloneSetup.java index 4e43a2e9..6a70640e 100644 --- a/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/XstsStandaloneSetup.java +++ b/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/XstsStandaloneSetup.java @@ -6,11 +6,6 @@ package hu.bme.mit.semantifyr.xsts.lang; - -import com.google.inject.Injector; -import hu.bme.mit.semantifyr.xsts.lang.xsts.XstsPackage; -import org.eclipse.emf.ecore.EPackage; - /** * Initialization support for running Xtext languages without Equinox extension registry. */ diff --git a/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/resource/XstsResourceDescription.java b/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/resource/XstsResourceDescription.java index 5332b5b6..3e8b1df1 100644 --- a/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/resource/XstsResourceDescription.java +++ b/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/resource/XstsResourceDescription.java @@ -16,7 +16,8 @@ import org.eclipse.xtext.util.IResourceScopeCache; import java.io.IOException; -import java.util.*; +import java.util.Collections; +import java.util.List; import static com.google.common.collect.Lists.newArrayList; diff --git a/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/validation/XstsValidator.java b/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/validation/XstsValidator.java index 84a00b9d..3e8c3923 100644 --- a/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/validation/XstsValidator.java +++ b/subprojects/backends/theta/xsts.lang/src/main/java/hu/bme/mit/semantifyr/xsts/lang/validation/XstsValidator.java @@ -5,8 +5,8 @@ /** - * This class contains custom validation rules. - * + * This class contains custom validation rules. + *

* See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation */ public class XstsValidator extends AbstractXstsValidator { diff --git a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt index cd6d5c4d..74b10555 100644 --- a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt +++ b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt @@ -22,8 +22,6 @@ import org.junit.jupiter.api.Tag import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource -import java.nio.file.Path -import java.util.concurrent.TimeUnit import java.util.stream.Stream import kotlin.io.path.Path import kotlin.streams.asStream @@ -34,8 +32,6 @@ import kotlin.time.toDuration @InjectWithOxstsSemantics class GammaVerificationTests : BaseSemantifyrVerificationTest() { - - companion object { private val semantifyrVerificationHelper = StandaloneOxstsSemanticsRuntimeModule.getInstance() diff --git a/subprojects/frontends/gamma/gamma.lang.ide/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/ide/GammaIdeSetup.java b/subprojects/frontends/gamma/gamma.lang.ide/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/ide/GammaIdeSetup.java index 24994f93..18a708d4 100644 --- a/subprojects/frontends/gamma/gamma.lang.ide/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/ide/GammaIdeSetup.java +++ b/subprojects/frontends/gamma/gamma.lang.ide/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/ide/GammaIdeSetup.java @@ -73,5 +73,5 @@ private static void runOnPort(int port) throws IOException, ExecutionException, } } } - + } diff --git a/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/GammaStandaloneSetup.java b/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/GammaStandaloneSetup.java index 5fd7fcc6..51dc0aa0 100644 --- a/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/GammaStandaloneSetup.java +++ b/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/GammaStandaloneSetup.java @@ -24,7 +24,7 @@ public Injector createInjectorAndDoEMFRegistration() { return super.createInjectorAndDoEMFRegistration(); } - public static void doSetup() { - new GammaStandaloneSetup().createInjectorAndDoEMFRegistration(); - } + public static void doSetup() { + new GammaStandaloneSetup().createInjectorAndDoEMFRegistration(); + } } diff --git a/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/formatting2/GammaFormatter.java b/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/formatting2/GammaFormatter.java index 23572efc..4cedaff0 100644 --- a/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/formatting2/GammaFormatter.java +++ b/subprojects/frontends/gamma/gamma.lang/src/main/java/hu/bme/mit/semantifyr/frontends/gamma/lang/formatting2/GammaFormatter.java @@ -9,5 +9,5 @@ import org.eclipse.xtext.formatting2.AbstractJavaFormatter; public class GammaFormatter extends AbstractJavaFormatter { - + } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index f4e95826..e4e028f2 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -24,6 +24,7 @@ node { } abstract class PnpmService : BuildService + val pnpmService = gradle.sharedServices.registerIfAbsent("pnpmService", PnpmService::class.java) { maxParallelUsages.set(1) } @@ -79,25 +80,29 @@ val buildExtension by tasks.registering(PnpmTask::class) { inputs.file(sysmlDir.file("tsconfig.json")) inputs.file(sysmlDir.file("tsconfig.build.json")) inputs.file(sysmlDir.file("tsconfig.eslint.json")) - inputs.files(fileTree(sysmlDir.dir("packages")) { - include("**/src/**/*.ts") - include("**/tsconfig.json") - include("**/package.json") - include("**/package-lock.json") - include("**/scripts/*.*") - include("**/scripts/*.*") - }) - outputs.files(fileTree(sysmlDir.dir("packages")) { - exclude("**/node_modules/**") - include("**/lib/**") - include("**/dist/**") - }) + inputs.files( + fileTree(sysmlDir.dir("packages")) { + include("**/src/**/*.ts") + include("**/tsconfig.json") + include("**/package.json") + include("**/package-lock.json") + include("**/scripts/*.*") + include("**/scripts/*.*") + }, + ) + outputs.files( + fileTree(sysmlDir.dir("packages")) { + exclude("**/node_modules/**") + include("**/lib/**") + include("**/dist/**") + }, + ) pnpmCommand.set( listOf( "run", "build", - ) + ), ) } @@ -107,21 +112,23 @@ val bundleExtension by tasks.registering(PnpmTask::class) { inputs.file(sysmlDir.file("tsconfig.json")) inputs.file(sysmlDir.file("tsconfig.build.json")) inputs.file(sysmlDir.file("tsconfig.eslint.json")) - inputs.files(fileTree(sysmlDir.dir("packages")) { - include("**/src/**/*.ts") - include("**/tsconfig.json") - include("**/package.json") - include("**/package-lock.json") - include("**/scripts/*.*") - include("**/scripts/*.*") - }) + inputs.files( + fileTree(sysmlDir.dir("packages")) { + include("**/src/**/*.ts") + include("**/tsconfig.json") + include("**/package.json") + include("**/package-lock.json") + include("**/scripts/*.*") + include("**/scripts/*.*") + }, + ) outputs.file(sysmlDir.file("packages/syside-vscode/sysml-2ls-0.9.0.vsix")) pnpmCommand.set( listOf( "run", "vscode:package", - ) + ), ) } @@ -131,14 +138,16 @@ val buildCli by tasks.registering(PnpmTask::class) { inputs.file(sysmlDir.file("tsconfig.json")) inputs.file(sysmlDir.file("tsconfig.build.json")) inputs.file(sysmlDir.file("tsconfig.eslint.json")) - inputs.files(fileTree(sysmlDir.dir("packages")) { - include("**/src/**/*.ts") - include("**/tsconfig.json") - include("**/package.json") - include("**/package-lock.json") - include("**/scripts/*.*") - include("**/scripts/*.*") - }) + inputs.files( + fileTree(sysmlDir.dir("packages")) { + include("**/src/**/*.ts") + include("**/tsconfig.json") + include("**/package.json") + include("**/package-lock.json") + include("**/scripts/*.*") + include("**/scripts/*.*") + }, + ) outputs.file(sysmlDir.file("packages/syside-cli/out/index.js")) workingDir = sysmlDir.dir("packages/syside-cli") @@ -147,7 +156,7 @@ val buildCli by tasks.registering(PnpmTask::class) { listOf( "run", "esbuild", - ) + ), ) } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts index 4325d931..1599454f 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts @@ -29,8 +29,8 @@ dependencies { } val prepareCli by tasks.registering(Sync::class) { - from (cliClasspath) - into ("build/cli") + from(cliClasspath) + into("build/cli") } tasks.withType(Test::class) { diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index 8494c9df..117ac3ac 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -14,7 +14,6 @@ import hu.bme.mit.semantifyr.semantics.BaseSemantifyrVerificationTest import hu.bme.mit.semantifyr.semantics.InjectWithOxstsSemantics import hu.bme.mit.semantifyr.semantics.SemantifyrVerificationHelper import hu.bme.mit.semantifyr.semantics.StandaloneOxstsSemanticsRuntimeModule -import hu.bme.mit.semantifyr.semantics.reader.SemantifyrLoader import hu.bme.mit.semantifyr.semantics.reader.SemantifyrModelContext import hu.bme.mit.semantifyr.semantics.utils.loggerFactory import org.junit.jupiter.api.Disabled diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/OxstsIdeSetup.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/OxstsIdeSetup.java index 5bbfafc5..8228fee0 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/OxstsIdeSetup.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/OxstsIdeSetup.java @@ -27,10 +27,10 @@ */ public class OxstsIdeSetup extends OxstsStandaloneSetup { - @Override - public Injector createInjector() { - return Guice.createInjector(Modules2.mixin(new OxstsServerModule(), new OxstsSemanticsRuntimeModule(), new OxstsIdeModule())); - } + @Override + public Injector createInjector() { + return Guice.createInjector(Modules2.mixin(new OxstsServerModule(), new OxstsSemanticsRuntimeModule(), new OxstsIdeModule())); + } public static void main(String[] args) throws InterruptedException, ExecutionException, IOException { Files.deleteIfExists(Path.of("oxsts.lsp.log")); diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/editor/contentassist/OxstsIdeContentProposalProvider.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/editor/contentassist/OxstsIdeContentProposalProvider.java index 62104b4f..85a0ee1d 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/editor/contentassist/OxstsIdeContentProposalProvider.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/editor/contentassist/OxstsIdeContentProposalProvider.java @@ -31,9 +31,9 @@ public class OxstsIdeContentProposalProvider extends IdeContentProposalProvider @Override protected void _createProposals(RuleCall ruleCall, ContentAssistContext context, IIdeContentProposalAcceptor acceptor) { if ( - this.oxstsGrammarAccess.getIdentifierRule().equals(ruleCall.getRule()) - && context.getCurrentModel() instanceof RedefinableDeclaration redefinableDeclaration - && redefinableDeclaration.isRedefine() + this.oxstsGrammarAccess.getIdentifierRule().equals(ruleCall.getRule()) + && context.getCurrentModel() instanceof RedefinableDeclaration redefinableDeclaration + && redefinableDeclaration.isRedefine() ) { // we should redefine some existing element var containerDomain = EcoreUtil2.getContainerOfType(redefinableDeclaration.eContainer(), DomainDeclaration.class); diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/editor/syntaxcoloring/OxstsSemanticHighlightingCalculator.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/editor/syntaxcoloring/OxstsSemanticHighlightingCalculator.java index 4045688c..3e36fa33 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/editor/syntaxcoloring/OxstsSemanticHighlightingCalculator.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/editor/syntaxcoloring/OxstsSemanticHighlightingCalculator.java @@ -22,66 +22,66 @@ @Singleton public class OxstsSemanticHighlightingCalculator extends DefaultSemanticHighlightingCalculator { - @Inject - private OperationCanceledManager operationCanceledManager; + @Inject + private OperationCanceledManager operationCanceledManager; - @Override - protected boolean highlightElement(EObject object, IHighlightedPositionAcceptor acceptor, CancelIndicator cancelIndicator) { - highlightElementName(object, acceptor, cancelIndicator); - highlightElementCrossReferences(object, acceptor, cancelIndicator); - return false; - } + @Override + protected boolean highlightElement(EObject object, IHighlightedPositionAcceptor acceptor, CancelIndicator cancelIndicator) { + highlightElementName(object, acceptor, cancelIndicator); + highlightElementCrossReferences(object, acceptor, cancelIndicator); + return false; + } - protected void highlightElementName(EObject object, IHighlightedPositionAcceptor acceptor, CancelIndicator cancelIndicator) { - if (!(object instanceof NamedElement)) { - return; - } + protected void highlightElementName(EObject object, IHighlightedPositionAcceptor acceptor, CancelIndicator cancelIndicator) { + if (!(object instanceof NamedElement)) { + return; + } operationCanceledManager.checkCanceled(cancelIndicator); - var highlightClass = getHighlightClass(object, null); - if (highlightClass != null) { - highlightFeature(acceptor, object, OxstsPackage.Literals.NAMED_ELEMENT__NAME, highlightClass); - } - } + var highlightClass = getHighlightClass(object, null); + if (highlightClass != null) { + highlightFeature(acceptor, object, OxstsPackage.Literals.NAMED_ELEMENT__NAME, highlightClass); + } + } - protected void highlightElementCrossReferences(EObject object, IHighlightedPositionAcceptor acceptor, CancelIndicator cancelIndicator) { - for (var reference : object.eClass().getEAllReferences()) { - if (reference.isContainment()) { - continue; - } - operationCanceledManager.checkCanceled(cancelIndicator); - if (reference.isMany()) { - highlightManyValues(object, reference, acceptor); - } else { - highlightSingleValue(object, reference, acceptor); - } - } - } + protected void highlightElementCrossReferences(EObject object, IHighlightedPositionAcceptor acceptor, CancelIndicator cancelIndicator) { + for (var reference : object.eClass().getEAllReferences()) { + if (reference.isContainment()) { + continue; + } + operationCanceledManager.checkCanceled(cancelIndicator); + if (reference.isMany()) { + highlightManyValues(object, reference, acceptor); + } else { + highlightSingleValue(object, reference, acceptor); + } + } + } - protected void highlightSingleValue(EObject owner, EReference reference, IHighlightedPositionAcceptor acceptor) { - var value = (EObject) owner.eGet(reference); - var highlightClass = getHighlightClass(value, reference); - if (highlightClass != null) { - highlightFeature(acceptor, owner, reference, highlightClass); - } - } + protected void highlightSingleValue(EObject owner, EReference reference, IHighlightedPositionAcceptor acceptor) { + var value = (EObject) owner.eGet(reference); + var highlightClass = getHighlightClass(value, reference); + if (highlightClass != null) { + highlightFeature(acceptor, owner, reference, highlightClass); + } + } - protected void highlightManyValues(EObject owner, EReference reference, IHighlightedPositionAcceptor acceptor) { - @SuppressWarnings("unchecked") - var values = (EList) owner.eGet(reference); - var nodes = NodeModelUtils.findNodesForFeature(owner, reference); - int size = Math.min(values.size(), nodes.size()); - for (var i = 0; i < size; i++) { - var valueInList = values.get(i); - var node = nodes.get(i); - var highlightClass = getHighlightClass(valueInList, reference); - if (highlightClass != null) { - highlightNode(acceptor, node, highlightClass); - } - } - } + protected void highlightManyValues(EObject owner, EReference reference, IHighlightedPositionAcceptor acceptor) { + @SuppressWarnings("unchecked") + var values = (EList) owner.eGet(reference); + var nodes = NodeModelUtils.findNodesForFeature(owner, reference); + int size = Math.min(values.size(), nodes.size()); + for (var i = 0; i < size; i++) { + var valueInList = values.get(i); + var node = nodes.get(i); + var highlightClass = getHighlightClass(valueInList, reference); + if (highlightClass != null) { + highlightNode(acceptor, node, highlightClass); + } + } + } // TODO: add modifiers: e.g., 'abstract' for abstract classes, 'defaultLibrary' for builtins, etc - protected String getHighlightClass(EObject eObject, EReference reference) { + protected String getHighlightClass(EObject eObject, EReference reference) { if (eObject == null) return null; return switch (eObject) { case InlinedOxsts ignored -> SemanticTokenTypes.Namespace; @@ -105,6 +105,6 @@ protected String getHighlightClass(EObject eObject, EReference reference) { default -> null; }; - } + } } diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/OxstsLanguageServer.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/OxstsLanguageServer.java index cd43277a..ff9d7a2a 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/OxstsLanguageServer.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/OxstsLanguageServer.java @@ -9,7 +9,9 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import hu.bme.mit.semantifyr.oxsts.lang.ide.server.concurrent.WorkManager; -import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.InitializeParams; +import org.eclipse.lsp4j.InitializeResult; +import org.eclipse.lsp4j.WorkDoneProgressCancelParams; import org.eclipse.xtext.ide.server.LanguageServerImpl; import java.util.concurrent.CompletableFuture; diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/codelens/OxstsCodeLensProvider.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/codelens/OxstsCodeLensProvider.java index 17143177..d19a27a7 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/codelens/OxstsCodeLensProvider.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/codelens/OxstsCodeLensProvider.java @@ -12,7 +12,9 @@ import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltinAnnotationHandler; import hu.bme.mit.semantifyr.oxsts.lang.semantics.RedefinersFinder; import hu.bme.mit.semantifyr.oxsts.lang.semantics.RedefinitionHandler; -import hu.bme.mit.semantifyr.oxsts.model.oxsts.*; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.InlinedOxsts; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.RedefinableDeclaration; import org.eclipse.lsp4j.*; import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.ide.server.Document; diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/NavigateToRedefinersCommandHandler.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/NavigateToRedefinersCommandHandler.java index c9d59751..87529198 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/NavigateToRedefinersCommandHandler.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/NavigateToRedefinersCommandHandler.java @@ -12,7 +12,6 @@ import hu.bme.mit.semantifyr.oxsts.lang.ide.client.NavigateToParams; import hu.bme.mit.semantifyr.oxsts.lang.ide.client.OxstsLanguageClient; import hu.bme.mit.semantifyr.oxsts.lang.semantics.RedefinersFinder; -import hu.bme.mit.semantifyr.oxsts.lang.semantics.RedefinitionHandler; import hu.bme.mit.semantifyr.oxsts.model.oxsts.RedefinableDeclaration; import org.eclipse.lsp4j.Location; import org.eclipse.xtext.ide.server.ILanguageServerAccess; diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/OxstsCommandService.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/OxstsCommandService.java index 3f5ee46d..b990dae4 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/OxstsCommandService.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/OxstsCommandService.java @@ -8,7 +8,7 @@ import com.google.inject.Inject; import com.google.inject.Singleton; -import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.ExecuteCommandParams; import org.eclipse.xtext.ide.server.ILanguageServerAccess; import org.eclipse.xtext.ide.server.commands.IExecutableCommandService; import org.eclipse.xtext.util.CancelIndicator; diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java index b0f115bd..29550d3b 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/commands/VerifyOxstsCommandHandler.java @@ -23,7 +23,6 @@ import java.time.Duration; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; @Singleton public class VerifyOxstsCommandHandler extends AbstractCommandHandler { diff --git a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/concurrent/SemantifyrRequestManager.java b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/concurrent/SemantifyrRequestManager.java index e51db2e6..0831dda0 100644 --- a/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/concurrent/SemantifyrRequestManager.java +++ b/subprojects/oxsts.lang.ide/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/ide/server/concurrent/SemantifyrRequestManager.java @@ -10,12 +10,13 @@ import hu.bme.mit.semantifyr.oxsts.lang.ide.server.concurrent.jobs.AbstractJob; import hu.bme.mit.semantifyr.oxsts.lang.ide.server.concurrent.jobs.ReadJob; import hu.bme.mit.semantifyr.oxsts.lang.ide.server.concurrent.jobs.WriteJob; -import org.eclipse.xtext.ide.server.concurrent.*; +import org.eclipse.xtext.ide.server.concurrent.AbstractRequestManager; import org.eclipse.xtext.service.OperationCanceledManager; import org.eclipse.xtext.util.CancelIndicator; import org.eclipse.xtext.xbase.lib.Functions; -import java.util.concurrent.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/IDValueConverter.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/IDValueConverter.java index 3615c142..9038e49e 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/IDValueConverter.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/IDValueConverter.java @@ -12,14 +12,14 @@ public class IDValueConverter extends AbstractIDValueConverter { - @Override - protected Set computeValuesToEscape(Grammar grammar) { - return Set.of(); - } + @Override + protected Set computeValuesToEscape(Grammar grammar) { + return Set.of(); + } - @Override - protected boolean mustEscape(String value) { - return false; - } + @Override + protected boolean mustEscape(String value) { + return false; + } } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/IdentifierValueConverter.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/IdentifierValueConverter.java index 4b1fc179..adf6a9e6 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/IdentifierValueConverter.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/IdentifierValueConverter.java @@ -22,46 +22,46 @@ import static org.eclipse.xtext.EcoreUtil2.typeSelect; public class IdentifierValueConverter implements IValueConverter { - private final Set keywords; + private final Set keywords; @Inject - private QUOTED_IDValueConverter quotedIdValueConverter; + private QUOTED_IDValueConverter quotedIdValueConverter; - @Inject - public IdentifierValueConverter(OxstsGrammarAccess grammarAccess, QUOTED_IDValueConverter quotedIdValueConverter) { - this.quotedIdValueConverter = quotedIdValueConverter; - quotedIdValueConverter.setRule(grammarAccess.getQUOTED_IDRule()); + @Inject + public IdentifierValueConverter(OxstsGrammarAccess grammarAccess, QUOTED_IDValueConverter quotedIdValueConverter) { + this.quotedIdValueConverter = quotedIdValueConverter; + quotedIdValueConverter.setRule(grammarAccess.getQUOTED_IDRule()); - keywords = new LinkedHashSet<>(GrammarUtil.getAllKeywords(grammarAccess.getGrammar())); + keywords = new LinkedHashSet<>(GrammarUtil.getAllKeywords(grammarAccess.getGrammar())); List list = typeSelect(eAllContentsAsList(grammarAccess.getKEYWORDRule()), Keyword.class); for (Keyword keyword : list) { keywords.remove(keyword.getValue()); } - } + } - @Override - public String toValue(String string, INode node) throws ValueConverterException { - if (string == null) { - return null; - } - if (NamingUtil.isQuotedId(string)) { - return quotedIdValueConverter.toValue(string, node); - } - return string; - } + @Override + public String toValue(String string, INode node) throws ValueConverterException { + if (string == null) { + return null; + } + if (NamingUtil.isQuotedId(string)) { + return quotedIdValueConverter.toValue(string, node); + } + return string; + } - @Override - public String toString(String value) throws ValueConverterException { - if (value == null) { - throw new ValueConverterException("Identifier may not be null.", null, null); - } - if (NamingUtil.isSimpleId(value) && !keywords.contains(value)) { - return value; - } + @Override + public String toString(String value) throws ValueConverterException { + if (value == null) { + throw new ValueConverterException("Identifier may not be null.", null, null); + } + if (NamingUtil.isSimpleId(value) && !keywords.contains(value)) { + return value; + } if (NamingUtil.isQuotedId(value)) { return value; } - return quotedIdValueConverter.toString(value); - } + return quotedIdValueConverter.toString(value); + } } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/QUOTED_IDValueConverter.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/QUOTED_IDValueConverter.java index 55ef8e84..066bfc17 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/QUOTED_IDValueConverter.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/QUOTED_IDValueConverter.java @@ -9,8 +9,8 @@ import org.eclipse.xtext.util.Strings; public class QUOTED_IDValueConverter extends STRINGValueConverter { - @Override - protected String toEscapedString(String value) { - return '\'' + Strings.convertToJavaString(value, false) + '\''; - } + @Override + protected String toEscapedString(String value) { + return '\'' + Strings.convertToJavaString(value, false) + '\''; + } } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/debugging/TypeRenderer.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/debugging/TypeRenderer.java index 5e3a9b9a..72bddc15 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/debugging/TypeRenderer.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/debugging/TypeRenderer.java @@ -10,7 +10,10 @@ import hu.bme.mit.semantifyr.oxsts.lang.OxstsStandaloneSetup; import hu.bme.mit.semantifyr.oxsts.lang.naming.NamingUtil; import hu.bme.mit.semantifyr.oxsts.lang.serializer.ExpressionSerializer; -import hu.bme.mit.semantifyr.oxsts.model.oxsts.*; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.DomainDeclaration; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.Expression; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.Instance; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.NamedElement; import org.eclipse.emf.ecore.EObject; import java.util.ArrayList; diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/ResourceBasedOxstsLibrary.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/ResourceBasedOxstsLibrary.java index 6508d94f..75443cdf 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/ResourceBasedOxstsLibrary.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/library/ResourceBasedOxstsLibrary.java @@ -43,6 +43,7 @@ public void loadLibrary(ResourceSet resourceSet) { } protected abstract void saveResources(); + protected abstract ClassLoader getClassLoader(); protected void saveResource(String resourceKey, Path subPath) { diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/resource/OxstsResourceDescription.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/resource/OxstsResourceDescription.java index 71e0a8dd..fe6b4a99 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/resource/OxstsResourceDescription.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/resource/OxstsResourceDescription.java @@ -6,7 +6,10 @@ package hu.bme.mit.semantifyr.oxsts.lang.resource; -import hu.bme.mit.semantifyr.oxsts.model.oxsts.*; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.Declaration; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.EnumDeclaration; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.InlinedOxsts; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.OxstsModelPackage; import org.apache.log4j.Logger; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.xtext.resource.IDefaultResourceDescriptionStrategy; diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/OxstsGlobalScopeProvider.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/OxstsGlobalScopeProvider.java index c1b9ec82..1f4ee9f2 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/OxstsGlobalScopeProvider.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/OxstsGlobalScopeProvider.java @@ -22,7 +22,6 @@ import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.scoping.impl.ResourceSetGlobalScopeProvider; import org.eclipse.xtext.scoping.impl.SelectableBasedScope; -import org.eclipse.xtext.util.IResourceScopeCache; import java.util.ArrayList; import java.util.Collection; @@ -94,6 +93,7 @@ protected IScope createScope(IScope parent, Collection ch protected record LoadedImportScopes( List implicitScopes, List explicitScopes - ) { } + ) { + } } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/domain/DeclarationHolder.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/domain/DeclarationHolder.java index a01c97e4..998d4c56 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/domain/DeclarationHolder.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/domain/DeclarationHolder.java @@ -10,15 +10,15 @@ public class DeclarationHolder { protected Declaration declaration; - + public DeclarationHolder(Declaration declaration) { this.declaration = declaration; } - + public Declaration getDeclaration() { return this.declaration; } - + public void setDeclaration(Declaration declaration) { this.declaration = declaration; } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/domain/MergedDomainMemberCollection.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/domain/MergedDomainMemberCollection.java index 7aea0d11..2f8d9e8e 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/domain/MergedDomainMemberCollection.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/domain/MergedDomainMemberCollection.java @@ -20,6 +20,6 @@ public MergedDomainMemberCollection(List parents, Redefi @Override public String toString() { - return "MERGED#" ; + return "MERGED#"; } } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/imports/Import.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/imports/Import.java index 08d2c8d7..e5e449fc 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/imports/Import.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/imports/Import.java @@ -15,7 +15,7 @@ public static Import implicit(URI importedPackage) { } public static Import explicit(URI uri) { - return new Import(uri,false); + return new Import(uri, false); } } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/selectables/TrimPrefixSelectable.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/selectables/TrimPrefixSelectable.java index ab6632ac..e304a50b 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/selectables/TrimPrefixSelectable.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/scoping/selectables/TrimPrefixSelectable.java @@ -41,8 +41,8 @@ public Iterable getExportedObjects() { public Iterable getExportedObjects(EClass type, QualifiedName name, boolean ignoreCase) { var originalName = prefix.append(name); return Iterables.transform( - delegateSelectable.getExportedObjects(type, originalName, ignoreCase), - description -> new AliasedEObjectDescription(description.getName().skipFirst(prefix.getSegmentCount()), description) + delegateSelectable.getExportedObjects(type, originalName, ignoreCase), + description -> new AliasedEObjectDescription(description.getName().skipFirst(prefix.getSegmentCount()), description) ); } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/MultiplicityRangeEvaluator.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/MultiplicityRangeEvaluator.java index 38745b7e..04b4e634 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/MultiplicityRangeEvaluator.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/MultiplicityRangeEvaluator.java @@ -12,8 +12,9 @@ import hu.bme.mit.semantifyr.oxsts.lang.semantics.expression.IntegerEvaluation; import hu.bme.mit.semantifyr.oxsts.lang.semantics.expression.RangeEvaluation; import hu.bme.mit.semantifyr.oxsts.lang.utils.OnResourceSetChangeEvictingCache; -import hu.bme.mit.semantifyr.oxsts.model.oxsts.*; -import org.eclipse.xtext.util.IResourceScopeCache; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.DefiniteMultiplicity; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.TypeSpecification; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.UnboundedMultiplicity; import org.eclipse.xtext.util.Tuples; @Singleton diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/OppositeHandler.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/OppositeHandler.java index 1ac23bae..e856eaad 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/OppositeHandler.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/OppositeHandler.java @@ -10,7 +10,6 @@ import com.google.inject.Singleton; import hu.bme.mit.semantifyr.oxsts.lang.utils.OnResourceSetChangeEvictingCache; import hu.bme.mit.semantifyr.oxsts.model.oxsts.FeatureDeclaration; -import org.eclipse.xtext.util.IResourceScopeCache; import org.eclipse.xtext.util.Tuples; @Singleton diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/RedefinersFinder.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/RedefinersFinder.java index 42e86c44..11e61be4 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/RedefinersFinder.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/RedefinersFinder.java @@ -10,10 +10,9 @@ import com.google.common.collect.Lists; import com.google.inject.Inject; import hu.bme.mit.semantifyr.oxsts.lang.utils.OnResourceSetChangeEvictingCache; -import hu.bme.mit.semantifyr.oxsts.model.oxsts.*; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.RedefinableDeclaration; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.ResourceSet; -import org.eclipse.xtext.util.Tuples; import java.util.*; diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/SubsetHandler.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/SubsetHandler.java index 8c1c761d..615b9f1c 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/SubsetHandler.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/SubsetHandler.java @@ -8,10 +8,8 @@ import com.google.inject.Inject; import com.google.inject.Singleton; -import hu.bme.mit.semantifyr.oxsts.lang.library.builtin.BuiltinSymbolResolver; import hu.bme.mit.semantifyr.oxsts.lang.utils.OnResourceSetChangeEvictingCache; import hu.bme.mit.semantifyr.oxsts.model.oxsts.FeatureDeclaration; -import org.eclipse.xtext.util.IResourceScopeCache; import org.eclipse.xtext.util.Tuples; @Singleton diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ConstantExpressionEvaluator.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ConstantExpressionEvaluator.java index 3c2eaafa..ad88b33c 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ConstantExpressionEvaluator.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ConstantExpressionEvaluator.java @@ -47,7 +47,7 @@ protected ExpressionEvaluation visit(ComparisonOperator expression) { return switch (expression.getOp()) { case EQ -> new BooleanEvaluation(lValue == rValue); case NOT_EQ -> new BooleanEvaluation(lValue != rValue); - default -> throw new IllegalArgumentException("Boolean expression can only be == or !=!"); + default -> throw new IllegalArgumentException("Boolean expression can only be == or !=!"); }; } @@ -55,7 +55,7 @@ protected ExpressionEvaluation visit(ComparisonOperator expression) { return switch (expression.getOp()) { case EQ -> new BooleanEvaluation(lValue == rValue); case NOT_EQ -> new BooleanEvaluation(lValue != rValue); - default -> throw new IllegalArgumentException("Boolean expression can only be == or !=!"); + default -> throw new IllegalArgumentException("Boolean expression can only be == or !=!"); }; } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ExpressionEvaluator.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ExpressionEvaluator.java index 0db6e0f6..cf72b1cb 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ExpressionEvaluator.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/semantics/expression/ExpressionEvaluator.java @@ -7,7 +7,7 @@ package hu.bme.mit.semantifyr.oxsts.lang.semantics.expression; import hu.bme.mit.semantifyr.oxsts.lang.utils.ExpressionVisitor; -import hu.bme.mit.semantifyr.oxsts.model.oxsts.*; +import hu.bme.mit.semantifyr.oxsts.model.oxsts.Expression; import java.util.HashMap; import java.util.Map; diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/serializer/ExpressionSerializer.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/serializer/ExpressionSerializer.java index 37bbe1a8..887a850b 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/serializer/ExpressionSerializer.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/serializer/ExpressionSerializer.java @@ -43,6 +43,7 @@ protected String stringifyOperator(ComparisonOp operator) { protected String visit(ComparisonOperator expression) { return visit(expression.getLeft()) + stringifyOperator(expression.getOp()) + visit(expression.getRight()); } + protected String stringifyOperator(ArithmeticOp operator) { return switch (operator) { case ADD -> " + "; diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OnResourceSetChangeEvictingCache.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OnResourceSetChangeEvictingCache.java index cc9e2515..ba2d461f 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OnResourceSetChangeEvictingCache.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OnResourceSetChangeEvictingCache.java @@ -14,7 +14,10 @@ import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.EcoreUtil; -import org.eclipse.xtext.util.*; +import org.eclipse.xtext.util.IResourceScopeCache; +import org.eclipse.xtext.util.NonRecursiveEContentAdapter; +import org.eclipse.xtext.util.Pair; +import org.eclipse.xtext.util.Tuples; import org.eclipse.xtext.util.concurrent.IUnitOfWork; import java.util.Map; @@ -41,7 +44,7 @@ public void clear(Resource resource) { @Override public T get(Object key, Resource resource, Provider provider) { - if(resource == null) { + if (resource == null) { return provider.get(); } var adapter = getOrCreate(resource.getResourceSet()); @@ -191,7 +194,7 @@ protected boolean isSemanticStateChange(Notification notification) { return false; } if (notification.getNotifier() instanceof Resource) { - switch(notification.getFeatureID(Resource.class)) { + switch (notification.getFeatureID(Resource.class)) { case Resource.RESOURCE__IS_MODIFIED: case Resource.RESOURCE__IS_TRACKING_MODIFICATION: case Resource.RESOURCE__TIME_STAMP: diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OxstsUtils.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OxstsUtils.java index a9a7cf10..51226407 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OxstsUtils.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/utils/OxstsUtils.java @@ -167,7 +167,7 @@ public static Expression getAnnotationValue(Annotation annotation, ParameterDecl public static boolean isWriteExpression(Expression expression) { return expression.eContainmentFeature() == OxstsPackage.Literals.ASSIGNMENT_OPERATION__REFERENCE - || expression.eContainmentFeature() == OxstsPackage.Literals.HAVOC_OPERATION__REFERENCE; + || expression.eContainmentFeature() == OxstsPackage.Literals.HAVOC_OPERATION__REFERENCE; } public static boolean isCallable(Element declaration) { @@ -180,8 +180,8 @@ public static boolean isInstanceFeature(FeatureDeclaration featureDeclaration) { public static boolean isDataFeature(FeatureDeclaration featureDeclaration) { return featureDeclaration.getTypeSpecification().getDomain() instanceof DataTypeDeclaration - || featureDeclaration.getTypeSpecification().getDomain() instanceof EnumDeclaration - || featureDeclaration.getTypeSpecification().getDomain() instanceof RecordDeclaration; + || featureDeclaration.getTypeSpecification().getDomain() instanceof EnumDeclaration + || featureDeclaration.getTypeSpecification().getDomain() instanceof RecordDeclaration; } public static boolean isMemberAbstract(Declaration declaration) { diff --git a/subprojects/oxsts.lang/src/test/java/hu/bme/mit/semantifyr/oxsts/lang/tests/SimpleOxstsParsingTest.java b/subprojects/oxsts.lang/src/test/java/hu/bme/mit/semantifyr/oxsts/lang/tests/SimpleOxstsParsingTest.java index e5cabae7..9044e8a5 100644 --- a/subprojects/oxsts.lang/src/test/java/hu/bme/mit/semantifyr/oxsts/lang/tests/SimpleOxstsParsingTest.java +++ b/subprojects/oxsts.lang/src/test/java/hu/bme/mit/semantifyr/oxsts/lang/tests/SimpleOxstsParsingTest.java @@ -22,26 +22,26 @@ public class SimpleOxstsParsingTest { @Test void simpleTest() { var model = parseHelper.parse(""" - package test - - class Element - class Holder { - features elements: Element[0..*] - contains e1: Element[1] subsets elements - contains e2: Element subsets elements - contains e3: Element[1..1] subsets elements - refers size: int = 3 - refers twiceSize: int = size * 2 - } - class Model { - var x: int := 10 - prop p1(): bool { return false } - init { } - tran { x := 20 } - tran named() { } - tran named(p: int) { x := p } - } - """); + package test + + class Element + class Holder { + features elements: Element[0..*] + contains e1: Element[1] subsets elements + contains e2: Element subsets elements + contains e3: Element[1..1] subsets elements + refers size: int = 3 + refers twiceSize: int = size * 2 + } + class Model { + var x: int := 10 + prop p1(): bool { return false } + init { } + tran { x := 20 } + tran named() { } + tran named(p: int) { x := p } + } + """); assertThat(model.getResourceErrors()).isEmpty(); } diff --git a/subprojects/semantics/src/main/kotlin/expression/StaticElementValueEvaluatorProvider.kt b/subprojects/semantics/src/main/kotlin/expression/StaticElementValueEvaluatorProvider.kt index 427ef294..f9485224 100644 --- a/subprojects/semantics/src/main/kotlin/expression/StaticElementValueEvaluatorProvider.kt +++ b/subprojects/semantics/src/main/kotlin/expression/StaticElementValueEvaluatorProvider.kt @@ -9,7 +9,6 @@ package hu.bme.mit.semantifyr.semantics.expression import com.google.inject.Inject import hu.bme.mit.semantifyr.oxsts.lang.semantics.expression.ExpressionEvaluation import hu.bme.mit.semantifyr.oxsts.model.oxsts.Element -import hu.bme.mit.semantifyr.oxsts.model.oxsts.Expression import hu.bme.mit.semantifyr.oxsts.model.oxsts.Instance import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped diff --git a/subprojects/semantics/src/main/kotlin/expression/StaticExpressionEvaluatorProvider.kt b/subprojects/semantics/src/main/kotlin/expression/StaticExpressionEvaluatorProvider.kt index 6d1eb385..7b3af881 100644 --- a/subprojects/semantics/src/main/kotlin/expression/StaticExpressionEvaluatorProvider.kt +++ b/subprojects/semantics/src/main/kotlin/expression/StaticExpressionEvaluatorProvider.kt @@ -7,7 +7,6 @@ package hu.bme.mit.semantifyr.semantics.expression import com.google.inject.Inject -import com.google.inject.Provider import hu.bme.mit.semantifyr.oxsts.lang.semantics.expression.ExpressionEvaluation import hu.bme.mit.semantifyr.oxsts.model.oxsts.Expression import hu.bme.mit.semantifyr.oxsts.model.oxsts.Instance diff --git a/subprojects/semantics/src/main/kotlin/optimization/ConstantFalseAssumptionPropagatorOptimizer.kt b/subprojects/semantics/src/main/kotlin/optimization/ConstantFalseAssumptionPropagatorOptimizer.kt index 9614a157..529769ed 100644 --- a/subprojects/semantics/src/main/kotlin/optimization/ConstantFalseAssumptionPropagatorOptimizer.kt +++ b/subprojects/semantics/src/main/kotlin/optimization/ConstantFalseAssumptionPropagatorOptimizer.kt @@ -34,9 +34,9 @@ class ConstantFalseAssumptionPropagatorOptimizer : AbstractLoopedOptimizer() { override fun doOptimizationStep(element: Element): Boolean { return rewriteConstantTrueOr(element) - || rewriteConstantFalseAnd(element) - || rewriteRedundantOr(element) - || rewriteRedundantAnd(element) - || rewriteDuplicateNegation(element) - || rewriteConstantExpression(element) - || bubbleEF(element) - || bubbleAG(element) + || rewriteConstantFalseAnd(element) + || rewriteRedundantOr(element) + || rewriteRedundantAnd(element) + || rewriteDuplicateNegation(element) + || rewriteConstantExpression(element) + || bubbleEF(element) + || bubbleAG(element) } // FIXME: replace with constant evaluator! diff --git a/subprojects/semantics/src/main/kotlin/optimization/InlinedOxstsOperationOptimizer.kt b/subprojects/semantics/src/main/kotlin/optimization/InlinedOxstsOperationOptimizer.kt index 0d88e807..66d2cd70 100644 --- a/subprojects/semantics/src/main/kotlin/optimization/InlinedOxstsOperationOptimizer.kt +++ b/subprojects/semantics/src/main/kotlin/optimization/InlinedOxstsOperationOptimizer.kt @@ -30,10 +30,10 @@ class InlinedOxstsOperationOptimizer : AbstractLoopedOptimizer() { override fun doOptimizationStep(element: InlinedOxsts): Boolean { return constantFalseAssumptionPropagatorOptimizer.optimize(element) - || operationFlattenerOptimizer.optimize(element) - || redundantOperationRemoverOptimizer.optimize(element) - || expressionOptimizer.optimize(element) - || variableOptimizer.optimize(element) + || operationFlattenerOptimizer.optimize(element) + || redundantOperationRemoverOptimizer.optimize(element) + || expressionOptimizer.optimize(element) + || variableOptimizer.optimize(element) } } diff --git a/subprojects/semantics/src/main/kotlin/optimization/OperationFlattenerOptimizer.kt b/subprojects/semantics/src/main/kotlin/optimization/OperationFlattenerOptimizer.kt index 520e4a4e..71e7e897 100644 --- a/subprojects/semantics/src/main/kotlin/optimization/OperationFlattenerOptimizer.kt +++ b/subprojects/semantics/src/main/kotlin/optimization/OperationFlattenerOptimizer.kt @@ -23,8 +23,8 @@ class OperationFlattenerOptimizer : AbstractLoopedOptimizer() { override fun doOptimizationStep(element: Element): Boolean { return flattenNestedSequenceOperations(element) - || flattenNestedChoiceOperations(element) - || flattenSingleBranchChoiceOperations(element) + || flattenNestedChoiceOperations(element) + || flattenSingleBranchChoiceOperations(element) } private fun flattenNestedSequenceOperations(element: Element): Boolean { diff --git a/subprojects/semantics/src/main/kotlin/optimization/RedundantOperationRemoverOptimizer.kt b/subprojects/semantics/src/main/kotlin/optimization/RedundantOperationRemoverOptimizer.kt index 0425cea4..b293c701 100644 --- a/subprojects/semantics/src/main/kotlin/optimization/RedundantOperationRemoverOptimizer.kt +++ b/subprojects/semantics/src/main/kotlin/optimization/RedundantOperationRemoverOptimizer.kt @@ -28,11 +28,11 @@ class RedundantOperationRemoverOptimizer : AbstractLoopedOptimizer() { override fun doOptimizationStep(element: Element): Boolean { return removeConstantTrueAssumptions(element) - || removeRedundantEmptyChoiceBranches(element) - || removeEmptyForOperations(element) - || removeEmptyIfElseBranches(element) - || removeEmptyIfBodyBranches(element) - || rewriteConstantGuardIfOperations(element) + || removeRedundantEmptyChoiceBranches(element) + || removeEmptyForOperations(element) + || removeEmptyIfElseBranches(element) + || removeEmptyIfBodyBranches(element) + || rewriteConstantGuardIfOperations(element) } private fun removeConstantTrueAssumptions(element: Element): Boolean { diff --git a/subprojects/semantics/src/main/kotlin/optimization/VariableOptimizer.kt b/subprojects/semantics/src/main/kotlin/optimization/VariableOptimizer.kt index 88c4f938..54e8b060 100644 --- a/subprojects/semantics/src/main/kotlin/optimization/VariableOptimizer.kt +++ b/subprojects/semantics/src/main/kotlin/optimization/VariableOptimizer.kt @@ -50,12 +50,12 @@ class VariableOptimizer { } val variableAssignments = ( - inlinedOxsts.eAllOfType().groupBy { - evaluator.evaluateTyped(VariableDeclaration::class.java, it.reference) - } + inlinedOxsts.eAllOfType().groupBy { - evaluator.evaluateTyped(VariableDeclaration::class.java, it.reference) - } - ).toMutableMap() + inlinedOxsts.eAllOfType().groupBy { + evaluator.evaluateTyped(VariableDeclaration::class.java, it.reference) + } + inlinedOxsts.eAllOfType().groupBy { + evaluator.evaluateTyped(VariableDeclaration::class.java, it.reference) + } + ).toMutableMap() val unreadVariables: MutableSet val unassignedInitializedVariables: MutableSet @@ -71,7 +71,7 @@ class VariableOptimizer { override fun doOptimizationStep(element: Element): Boolean { return removeUnreadVariable() - || removeUnassignedInitializedVariables() + || removeUnassignedInitializedVariables() } private fun removeUnreadVariable(): Boolean { diff --git a/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt b/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt index 3949bae1..99456979 100644 --- a/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt +++ b/subprojects/semantics/src/main/kotlin/reader/SemantifyrLoader.kt @@ -10,7 +10,6 @@ import com.google.inject.Inject import com.google.inject.Provider import hu.bme.mit.semantifyr.oxsts.lang.library.LibraryAdapterFinder import hu.bme.mit.semantifyr.oxsts.lang.utils.ResourceUriProvider -import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration import hu.bme.mit.semantifyr.oxsts.model.oxsts.OxstsModelPackage import hu.bme.mit.semantifyr.semantics.utils.ResourceSetLoader import hu.bme.mit.semantifyr.semantics.utils.SemantifyrUtils.modelPathsUnder diff --git a/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt b/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt index bd8cf757..fd6ebd53 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt @@ -18,8 +18,6 @@ import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.Compilatio import hu.bme.mit.semantifyr.semantics.transformation.instantiation.InstanceManager import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.utils.OxstsFactory -import org.eclipse.emf.common.util.URI -import java.io.File @CompilationScoped class InlinedOxstsModelCreator { diff --git a/subprojects/semantics/src/main/kotlin/transformation/OxstsClassInliner.kt b/subprojects/semantics/src/main/kotlin/transformation/OxstsClassInliner.kt index 80263a72..0fb7bb9f 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/OxstsClassInliner.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/OxstsClassInliner.kt @@ -14,7 +14,6 @@ import hu.bme.mit.semantifyr.semantics.transformation.inliner.OxstsCallInliner import hu.bme.mit.semantifyr.semantics.transformation.instantiation.OxstsInflator import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.transformation.serializer.CompilationStateManager -import java.io.File @CompilationScoped class OxstsClassInliner { diff --git a/subprojects/semantics/src/main/kotlin/transformation/backannotation/OxstsClassAssumptionWitnessTransformer.kt b/subprojects/semantics/src/main/kotlin/transformation/backannotation/OxstsClassAssumptionWitnessTransformer.kt index 9c913431..9a7bd781 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/backannotation/OxstsClassAssumptionWitnessTransformer.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/backannotation/OxstsClassAssumptionWitnessTransformer.kt @@ -48,13 +48,13 @@ class OxstsClassAssumptionWitnessTransformer { return OxstsClassAssumptionWitnessStateValue( variableReference, - oxstsInflator.backAnnotateInstancePointers(variableValue.variable, variableValue.value) + oxstsInflator.backAnnotateInstancePointers(variableValue.variable, variableValue.value), ) } private fun transform(trace: InlinedOxstsAssumptionActivatedTrace): OxstsClassAssumptionActivatedTrace { return OxstsClassAssumptionActivatedTrace( - trace.traceOperation + trace.traceOperation, ) } @@ -81,7 +81,7 @@ class OxstsClassAssumptionWitnessTransformer { initializedState, transitionStates, nextStateMap, - inlinedOxstsAssumptionWitness.inlinedOxsts + inlinedOxstsAssumptionWitness.inlinedOxsts, ) } diff --git a/subprojects/semantics/src/main/kotlin/transformation/inliner/OperationCallInliner.kt b/subprojects/semantics/src/main/kotlin/transformation/inliner/OperationCallInliner.kt index fcbd1d5a..9a96e3fd 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/inliner/OperationCallInliner.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/inliner/OperationCallInliner.kt @@ -37,9 +37,9 @@ import hu.bme.mit.semantifyr.semantics.expression.RedefinitionAwareReferenceReso import hu.bme.mit.semantifyr.semantics.expression.StaticExpressionEvaluatorProvider import hu.bme.mit.semantifyr.semantics.expression.evaluateTyped import hu.bme.mit.semantifyr.semantics.optimization.ConstantFalseAssumptionPropagatorOptimizer +import hu.bme.mit.semantifyr.semantics.optimization.ExpressionOptimizer import hu.bme.mit.semantifyr.semantics.optimization.OperationFlattenerOptimizer import hu.bme.mit.semantifyr.semantics.optimization.RedundantOperationRemoverOptimizer -import hu.bme.mit.semantifyr.semantics.optimization.ExpressionOptimizer import hu.bme.mit.semantifyr.semantics.transformation.serializer.CompilationStateManager import hu.bme.mit.semantifyr.semantics.transformation.tracer.TransitionCallTracer import hu.bme.mit.semantifyr.semantics.utils.OxstsFactory diff --git a/subprojects/semantics/src/main/kotlin/transformation/serializer/DomainMappingSerializer.kt b/subprojects/semantics/src/main/kotlin/transformation/serializer/DomainMappingSerializer.kt index fcb96584..c73da2cb 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/serializer/DomainMappingSerializer.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/serializer/DomainMappingSerializer.kt @@ -55,7 +55,7 @@ class DomainMappingSerializer { instanceIds.map { (instance, id) -> val reference = instanceReferenceProvider.getReference(instance) InstanceIdMapping( - expressionSerializer.serialize(reference), id + expressionSerializer.serialize(reference), id, ) }, ) diff --git a/subprojects/semantics/src/main/kotlin/transformation/tracer/TraceSerializer.kt b/subprojects/semantics/src/main/kotlin/transformation/tracer/TraceSerializer.kt index e7cf8aaf..8ff5cd0f 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/tracer/TraceSerializer.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/tracer/TraceSerializer.kt @@ -83,10 +83,10 @@ class TraceSerializer { expressionEvaluationSerializer.serialize(it.evaluation) } else { "" - } + }, ) }, - null // TODO: implement structural tracing -> call stack + null, // TODO: implement structural tracing -> call stack ) } @@ -104,7 +104,7 @@ class TraceSerializer { }, state.values.map { transformInlinedOxstsAssumptionWitnessStateValue(it) - } + }, ) } @@ -113,7 +113,7 @@ class TraceSerializer { transformInlinedOxstsAssumptionWitnessState(inlinxOxstsAssumptionWitness.initialState), inlinxOxstsAssumptionWitness.transitionStates.map { transformInlinedOxstsAssumptionWitnessState(it) - } + }, ) } diff --git a/subprojects/semantics/src/main/kotlin/transformation/tracer/TransitionCallTracer.kt b/subprojects/semantics/src/main/kotlin/transformation/tracer/TransitionCallTracer.kt index 8236cff1..0cbaa145 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/tracer/TransitionCallTracer.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/tracer/TransitionCallTracer.kt @@ -54,7 +54,7 @@ class TransitionCallTracer { transitionDeclaration, callExpression.arguments.map { ArgumentTrace(it.parameter, evaluator.tryEvaluateTypedOrNull(ExpressionEvaluation::class.java, it.expression)) - } + }, ) transitionCallTraceMap[transitionTraceOperation.name] = transitionCallTrace diff --git a/subprojects/semantics/src/main/kotlin/utils/OxstsFactory.kt b/subprojects/semantics/src/main/kotlin/utils/OxstsFactory.kt index 7f8934eb..8d9833ae 100644 --- a/subprojects/semantics/src/main/kotlin/utils/OxstsFactory.kt +++ b/subprojects/semantics/src/main/kotlin/utils/OxstsFactory.kt @@ -60,6 +60,7 @@ object OxstsFactory : OxstsFactoryImpl() { it.feature = feature } } + fun createVariableMapping(variableDeclaration: VariableDeclaration): VariableMapping { return createVariableMapping().also { it.original = variableDeclaration diff --git a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt index a4fa7f1e..5bf43b5d 100644 --- a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt +++ b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt @@ -17,7 +17,6 @@ import hu.bme.mit.semantifyr.semantics.transformation.backannotation.OxstsClassA import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.transformation.tracer.TraceSerializer import kotlinx.serialization.Serializable -import java.util.concurrent.TimeUnit import kotlin.time.Duration import kotlin.time.toKotlinDuration diff --git a/subprojects/semantics/src/main/resources/log4j2.properties b/subprojects/semantics/src/main/resources/log4j2.properties index 2817d8fa..6bdba308 100644 --- a/subprojects/semantics/src/main/resources/log4j2.properties +++ b/subprojects/semantics/src/main/resources/log4j2.properties @@ -1,8 +1,8 @@ # The root logger with appender name -rootLogger = INFO, STDOUT +rootLogger=INFO, STDOUT # Assign STDOUT a valid appender & define its layout -appender.console.name = STDOUT -appender.console.type = Console -appender.console.layout.type = PatternLayout -appender.console.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n +appender.console.name=STDOUT +appender.console.type=Console +appender.console.layout.type=PatternLayout +appender.console.layout.pattern=[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n diff --git a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt index 939928b6..b0c7a016 100644 --- a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt +++ b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt @@ -26,7 +26,6 @@ import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Named import org.junit.jupiter.params.provider.Arguments import org.slf4j.Logger -import java.util.concurrent.TimeUnit import kotlin.streams.asSequence import kotlin.time.Duration import kotlin.time.DurationUnit diff --git a/subprojects/semantifyr-cli/build.gradle.kts b/subprojects/semantifyr-cli/build.gradle.kts deleted file mode 100644 index bf72a0db..00000000 --- a/subprojects/semantifyr-cli/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -plugins { - id("hu.bme.mit.semantifyr.gradle.conventions.application") - kotlin("jvm") -} - -repositories { - mavenCentral() - maven("https://repo.eclipse.org/content/groups/viatra/") -} - -val distributionOutput by configurations.creating { - isCanBeConsumed = true - isCanBeResolved = false -} - -artifacts { - add(distributionOutput.name, layout.buildDirectory.dir("install")) { - builtBy(tasks.installDist) - } -} - -dependencies { - implementation(project(":semantics")) - implementation(project(":theta")) - - runtimeOnly(libs.slf4j.log4j) - implementation(libs.clikt) -} - -application { - mainClass = "hu.bme.mit.semantifyr.cli.SemantifyrCliKt" -} diff --git a/subprojects/semantifyr-cli/src/main/kotlin/SemantifyrCli.kt b/subprojects/semantifyr-cli/src/main/kotlin/SemantifyrCli.kt deleted file mode 100644 index 679df500..00000000 --- a/subprojects/semantifyr-cli/src/main/kotlin/SemantifyrCli.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023-2024 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package hu.bme.mit.semantifyr.cli - -import com.github.ajalt.clikt.core.CliktCommand -import com.github.ajalt.clikt.core.main -import com.github.ajalt.clikt.core.subcommands -import hu.bme.mit.semantifyr.cli.commands.CompileCommand - -class SemantifyrCommand : CliktCommand("semantifyr") { - override fun run() = Unit -} - -fun main(args: Array) { - SemantifyrCommand().subcommands( - CompileCommand(), -// VerifyCommand(), -// VerifyXstsCommand(), - ).main(args) -} diff --git a/subprojects/semantifyr-cli/src/main/kotlin/commands/CompileCommand.kt b/subprojects/semantifyr-cli/src/main/kotlin/commands/CompileCommand.kt deleted file mode 100644 index 5415fd59..00000000 --- a/subprojects/semantifyr-cli/src/main/kotlin/commands/CompileCommand.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Semantifyr Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ - -package hu.bme.mit.semantifyr.cli.commands - -import com.github.ajalt.clikt.core.CliktCommand -import com.github.ajalt.clikt.parameters.arguments.argument -import com.github.ajalt.clikt.parameters.options.multiple -import com.github.ajalt.clikt.parameters.options.option -import com.github.ajalt.clikt.parameters.types.file -import hu.bme.mit.semantifyr.semantics.transformation.OxstsToXstsTransformer -import hu.bme.mit.semantifyr.semantics.StandaloneSemantifyrModule -import hu.bme.mit.semantifyr.semantics.loading.SemantifyrLoader -import hu.bme.mit.semantifyr.semantics.utils.loggerFactory - -class CompileCommand : CliktCommand("compile") { - - val logger by loggerFactory() - - val model by argument().file(mustExist = true, canBeFile = true) - val targetName by argument() - val library by option("-l", "--library").file(mustExist = true, canBeDir = true, canBeFile = false).multiple() - val output by option("-o", "--output").file(mustExist = false, canBeFile = true) - - override fun run() { - val loader = StandaloneSemantifyrModule.getInstance() - - loader.extraPaths(library.map { it.toPath() }) - - val model = loader.loadStandaloneModelContext(model.toPath()) - - val transformer = StandaloneSemantifyrModule.getInstance() - - transformer.transform(model, "", false) - -// logger.info("Compiling target $targetName") -// -// val transformer = XstsTransformer(reader) -// -// val xsts = transformer.transform(targetName, rewriteChoice = true) -// val xstsString = XstsSerializer.serialize(xsts) -// -// val outputFile = output ?: File(model.path.replace(".oxsts", ".xsts")) -// -// logger.info("Producing xsts file to $outputFile") -// -// outputFile.writeText(xstsString) - } - -} diff --git a/subprojects/semantifyr-cli/src/main/kotlin/commands/VerifyCommand.kt b/subprojects/semantifyr-cli/src/main/kotlin/commands/VerifyCommand.kt deleted file mode 100644 index 6d613ea8..00000000 --- a/subprojects/semantifyr-cli/src/main/kotlin/commands/VerifyCommand.kt +++ /dev/null @@ -1,113 +0,0 @@ -package hu.bme.mit.semantifyr.cli.commands - -import com.github.ajalt.clikt.core.CliktCommand -import com.github.ajalt.clikt.parameters.arguments.argument -import com.github.ajalt.clikt.parameters.options.default -import com.github.ajalt.clikt.parameters.options.flag -import com.github.ajalt.clikt.parameters.options.help -import com.github.ajalt.clikt.parameters.options.multiple -import com.github.ajalt.clikt.parameters.options.option -import com.github.ajalt.clikt.parameters.types.file -import com.github.ajalt.clikt.parameters.types.long -import hu.bme.mit.semantifyr.backends.theta.ThetaExecutor -import hu.bme.mit.semantifyr.backends.theta.ThetaRuntimeDetails -import hu.bme.mit.semantifyr.semantics.utils.loggerFactory -import org.eclipse.emf.common.util.URI -import java.io.File -import java.util.concurrent.TimeUnit - -class VerifyCommand : CliktCommand("verify") { - - val logger by loggerFactory() - - val model by argument().file(mustExist = true, canBeFile = true, canBeDir = false) - val timeout by option().long().default(5).help("Timeout in minutes") - val thetaVersion by option().default("6.5.2") - val thetaConfiguration by option().multiple( - default = listOf( - "--domain EXPL --refinement SEQ_ITP --maxenum 250 --initprec CTRL --stacktrace", - "--domain EXPL_PRED_COMBINED --autoexpl NEWOPERANDS --initprec CTRL --stacktrace", - "--domain PRED_CART --refinement SEQ_ITP --stacktrace", - "--stacktrace", - ), - ) - - val libraryDirectory by argument().file(mustExist = true, canBeDir = true) - val targetName by argument() - val generateWitness by option("-w", "--witness").flag() - - fun runVerification(xstsPath: String): ThetaRuntimeDetails { - val xstsFile = File(xstsPath) - - logger.info("Executing Theta (v$thetaVersion) on $xstsPath") - - val thetaExecutor = ThetaExecutor( - thetaVersion, - thetaConfiguration, - timeout, - TimeUnit.MINUTES - ) - - val workingDirectory = xstsFile.parentFile.absolutePath - val fileName = xstsFile.nameWithoutExtension - - val runtimeDetails = thetaExecutor.run(workingDirectory, fileName) - - logger.info("Verification result: isUnsafe = ${runtimeDetails.isUnsafe}") - - return runtimeDetails - } - - override fun run() { -// logger.info("Preparing Xtext Language") -// -// prepareOxsts() -// -// logger.info("Reading model $model") -// -// val reader = OxstsReader(libraryDirectory.path) -// reader.readModel(model.path) -// -// logger.info("Compiling target $targetName") -// -// val transformer = XstsTransformer(reader) -// -// val xsts = transformer.transform(targetName, rewriteChoice = true) -// val xstsString = XstsSerializer.serialize(xsts) -// -// val output = model.path.replace(".oxsts", ".xsts") -// -// File(output).writeText(xstsString) -// -// logger.info("Producing xsts file to $output") -// -// val result = runVerification(output) -// -// if (generateWitness && result.isUnsafe) { -// generateWitness(result, reader) -// } - } - -// private fun generateWitness( -// result: ThetaRuntimeDetails, -// reader: OxstsReader -// ) { -// logger.info("Generating witness from ${result.cexPath}") -// -// prepareCex() -// -// val cexReader = CexReader() -// val cex = cexReader.readCexFile(File(result.cexPath)) -// -// val witnessCreator = WitnessCreator(reader) -// -// val witnessPath = model.path.replace(".oxsts", ".cex.oxsts") -// val resource = reader.resourceSet.createResource(URI.createFileURI(witnessPath)) -// resource.contents += witnessCreator.createWitness(targetName, cex) -// -// resource.save(null) -// -// logger.info("Saved witness to $witnessPath") -// } - -} diff --git a/subprojects/semantifyr-cli/src/main/resources/log4j2.properties b/subprojects/semantifyr-cli/src/main/resources/log4j2.properties deleted file mode 100644 index 2817d8fa..00000000 --- a/subprojects/semantifyr-cli/src/main/resources/log4j2.properties +++ /dev/null @@ -1,8 +0,0 @@ -# The root logger with appender name -rootLogger = INFO, STDOUT - -# Assign STDOUT a valid appender & define its layout -appender.console.name = STDOUT -appender.console.type = Console -appender.console.layout.type = PatternLayout -appender.console.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n diff --git a/subprojects/semantifyr-vscode-server/build.gradle.kts b/subprojects/semantifyr-vscode-server/build.gradle.kts index 2e8f1336..114382ee 100644 --- a/subprojects/semantifyr-vscode-server/build.gradle.kts +++ b/subprojects/semantifyr-vscode-server/build.gradle.kts @@ -32,7 +32,7 @@ dependencies { val cloneDistribution by tasks.registering(Sync::class) { inputs.files(distributionClasspath) - from (distributionClasspath) + from(distributionClasspath) into("extensions") } @@ -40,19 +40,19 @@ val cloneDistribution by tasks.registering(Sync::class) { val cloneTheta by tasks.registering(Sync::class) { inputs.files(thetaClasspath) - from (thetaClasspath) + from(thetaClasspath) into("theta-xsts-cli") } val cloneGammaLibrary by tasks.registering(Sync::class) { - from (project(":gamma-semantics").layout.projectDirectory.dir("Library")) - into ("examples/gamma/Library") + from(project(":gamma-semantics").layout.projectDirectory.dir("Library")) + into("examples/gamma/Library") } val cloneSysMLLibrary by tasks.registering(Sync::class) { - from (project(":sysmlv2-semantics").layout.projectDirectory.dir("Library")) - into ("examples/sysml/Library") + from(project(":sysmlv2-semantics").layout.projectDirectory.dir("Library")) + into("examples/sysml/Library") } val cloneLibraries by tasks.registering { @@ -61,17 +61,17 @@ val cloneLibraries by tasks.registering { } val cloneGammaTestModels by tasks.registering(Sync::class) { - from (project(":gamma-semantics").layout.projectDirectory.dir("TestModels")) { + from(project(":gamma-semantics").layout.projectDirectory.dir("TestModels")) { include("*.gamma") } - into ("examples/gamma/TestModels") + into("examples/gamma/TestModels") } val cloneSysMLTestModels by tasks.registering(Sync::class) { - from (project(":sysmlv2-semantics").layout.projectDirectory.dir("TestModels")) { + from(project(":sysmlv2-semantics").layout.projectDirectory.dir("TestModels")) { include("*.sysml") } - into ("examples/sysml/TestModels") + into("examples/sysml/TestModels") } val cloneTestModels by tasks.registering { diff --git a/subprojects/semantifyr-vscode/.vscode/extensions.json b/subprojects/semantifyr-vscode/.vscode/extensions.json index 057f0a04..b308e589 100644 --- a/subprojects/semantifyr-vscode/.vscode/extensions.json +++ b/subprojects/semantifyr-vscode/.vscode/extensions.json @@ -1,3 +1,5 @@ { - "recommendations": [ "dbaeumer.vscode-eslint" ] + "recommendations": [ + "dbaeumer.vscode-eslint" + ] } diff --git a/subprojects/semantifyr-vscode/.vscode/launch.json b/subprojects/semantifyr-vscode/.vscode/launch.json index 477dad84..52051c22 100644 --- a/subprojects/semantifyr-vscode/.vscode/launch.json +++ b/subprojects/semantifyr-vscode/.vscode/launch.json @@ -1,79 +1,79 @@ { - "version": "0.2.0", - "configurations": [ - { - "name": "Run Extension", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/dist/**/*.cjs" - ], - "preLaunchTask": "Build" - }, - { - "name": "Run Extension (attach to OXSTS LSP)", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "env": { - "DEBUG_OXSTS_LSP": "5007" - }, - "outFiles": [ - "${workspaceFolder}/dist/**/*.cjs" - ], - "preLaunchTask": "Build" - }, - { - "name": "Run Extension (attach to XSTS LSP)", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "env": { - "DEBUG_XSTS_LSP": "5008" - }, - "outFiles": [ - "${workspaceFolder}/dist/**/*.cjs" - ], - "preLaunchTask": "Build" - }, - { - "name": "Run Extension (attach to Gamma LSP)", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "env": { - "DEBUG_GAMMA_LSP": "5010" - }, - "outFiles": [ - "${workspaceFolder}/dist/**/*.cjs" - ], - "preLaunchTask": "Build" - }, - { - "name": "Run Extension (attach to each LSP)", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "env": { - "DEBUG_OXSTS_LSP": "5007", - "DEBUG_XSTS_LSP": "5008", - "DEBUG_GAMMA_LSP": "5010" - }, - "outFiles": [ - "${workspaceFolder}/dist/**/*.cjs" - ], - "preLaunchTask": "Build" - } - ] + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "outFiles": [ + "${workspaceFolder}/dist/**/*.cjs" + ], + "preLaunchTask": "Build" + }, + { + "name": "Run Extension (attach to OXSTS LSP)", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "env": { + "DEBUG_OXSTS_LSP": "5007" + }, + "outFiles": [ + "${workspaceFolder}/dist/**/*.cjs" + ], + "preLaunchTask": "Build" + }, + { + "name": "Run Extension (attach to XSTS LSP)", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "env": { + "DEBUG_XSTS_LSP": "5008" + }, + "outFiles": [ + "${workspaceFolder}/dist/**/*.cjs" + ], + "preLaunchTask": "Build" + }, + { + "name": "Run Extension (attach to Gamma LSP)", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "env": { + "DEBUG_GAMMA_LSP": "5010" + }, + "outFiles": [ + "${workspaceFolder}/dist/**/*.cjs" + ], + "preLaunchTask": "Build" + }, + { + "name": "Run Extension (attach to each LSP)", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "env": { + "DEBUG_OXSTS_LSP": "5007", + "DEBUG_XSTS_LSP": "5008", + "DEBUG_GAMMA_LSP": "5010" + }, + "outFiles": [ + "${workspaceFolder}/dist/**/*.cjs" + ], + "preLaunchTask": "Build" + } + ] } diff --git a/subprojects/semantifyr-vscode/.vscode/settings.json b/subprojects/semantifyr-vscode/.vscode/settings.json index e2eb11d6..b05407cc 100644 --- a/subprojects/semantifyr-vscode/.vscode/settings.json +++ b/subprojects/semantifyr-vscode/.vscode/settings.json @@ -1,9 +1,9 @@ { - "files.exclude": { - "dist": false - }, - "search.exclude": { - "dist": true - }, - "typescript.tsc.autoDetect": "off" + "files.exclude": { + "dist": false + }, + "search.exclude": { + "dist": true + }, + "typescript.tsc.autoDetect": "off" } diff --git a/subprojects/semantifyr-vscode/.vscode/tasks.json b/subprojects/semantifyr-vscode/.vscode/tasks.json index 22bf1c89..fca643da 100644 --- a/subprojects/semantifyr-vscode/.vscode/tasks.json +++ b/subprojects/semantifyr-vscode/.vscode/tasks.json @@ -1,19 +1,19 @@ { - "version": "2.0.0", - "tasks": [ - { - "label": "Build", - "command": "npm run build", - "type": "shell", - "group": { - "kind": "build", - "isDefault": true - }, - "detail": "Build the VSCode extension", - "icon": { - "color": "terminal.ansiGreen", - "id": "server-process" - } - } - ] + "version": "2.0.0", + "tasks": [ + { + "label": "Build", + "command": "npm run build", + "type": "shell", + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Build the VSCode extension", + "icon": { + "color": "terminal.ansiGreen", + "id": "server-process" + } + } + ] } diff --git a/subprojects/semantifyr-vscode/build.gradle.kts b/subprojects/semantifyr-vscode/build.gradle.kts index 8e66f211..ba659c73 100644 --- a/subprojects/semantifyr-vscode/build.gradle.kts +++ b/subprojects/semantifyr-vscode/build.gradle.kts @@ -18,6 +18,7 @@ node { } abstract class NpmService : BuildService + val npmService = gradle.sharedServices.registerIfAbsent("npmService", NpmService::class.java) { maxParallelUsages.set(1) } @@ -52,9 +53,11 @@ dependencies { val cloneDistribution by tasks.registering(Sync::class) { inputs.files(distributionClasspath) - from (distributionClasspath.map { - fileTree(it) - }) + from( + distributionClasspath.map { + fileTree(it) + }, + ) into("bin") } @@ -71,7 +74,7 @@ val buildExtension by tasks.registering(NpmTask::class) { listOf( "run", "build", - ) + ), ) outputs.dir("dist") @@ -92,7 +95,7 @@ val bundleExtension by tasks.registering(NpmTask::class) { listOf( "run", "bundle", - ) + ), ) outputs.file(project.layout.buildDirectory.file("semantifyr-0.0.1.vsix")) diff --git a/subprojects/semantifyr-vscode/language-configuration.json b/subprojects/semantifyr-vscode/language-configuration.json index ed4a7570..d871e49b 100644 --- a/subprojects/semantifyr-vscode/language-configuration.json +++ b/subprojects/semantifyr-vscode/language-configuration.json @@ -1,39 +1,93 @@ { - "comments": { - "lineComment": "//", - "blockComment": ["/*", "*/"] + "comments": { + "lineComment": "//", + "blockComment": [ + "/*", + "*/" + ] + }, + "brackets": [ + [ + "{", + "}" + ], + [ + "[", + "]" + ], + [ + "(", + ")" + ] + ], + "autoClosingPairs": [ + { + "open": "{", + "close": "}" + }, + { + "open": "[", + "close": "]" + }, + { + "open": "(", + "close": ")" + }, + { + "open": "/**", + "close": " */", + "notIn": [ + "string" + ] }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] + { + "open": "/*", + "close": " */", + "notIn": [ + "string" + ] + }, + { + "open": "'", + "close": "'" + }, + { + "open": "\"", + "close": "\"" + } + ], + "autoCloseBefore": ";:.,=}])>` \n\t", + "surroundingPairs": [ + [ + "{", + "}" ], - "autoClosingPairs": [ - { "open": "{", "close": "}" }, - { "open": "[", "close": "]" }, - { "open": "(", "close": ")" }, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "/*", "close": " */", "notIn": ["string"] }, - { "open": "'", "close": "'" }, - { "open": "\"", "close": "\"" } + [ + "[", + "]" ], - "autoCloseBefore": ";:.,=}])>` \n\t", - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["'", "'"], - ["\"", "\""], + [ + "(", + ")" ], - "folding": { - "markers": { - "start": "^\\s*//\\s*#?region\\b", - "end": "^\\s*//\\s*#?endregion\\b" - } - }, - "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)", - "indentationRules": { - "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$", - "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$" + [ + "'", + "'" + ], + [ + "\"", + "\"" + ] + ], + "folding": { + "markers": { + "start": "^\\s*//\\s*#?region\\b", + "end": "^\\s*//\\s*#?endregion\\b" } + }, + "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)", + "indentationRules": { + "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$", + "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$" } +} diff --git a/subprojects/semantifyr-vscode/package.json b/subprojects/semantifyr-vscode/package.json index 8079c88b..6a382f02 100644 --- a/subprojects/semantifyr-vscode/package.json +++ b/subprojects/semantifyr-vscode/package.json @@ -49,20 +49,32 @@ "languages": [ { "id": "oxsts", - "extensions": [".oxsts"], - "aliases": ["OXSTS"], + "extensions": [ + ".oxsts" + ], + "aliases": [ + "OXSTS" + ], "configuration": "./language-configuration.json" }, { "id": "xsts", - "extensions": [".xsts"], - "aliases": ["XSTS"], + "extensions": [ + ".xsts" + ], + "aliases": [ + "XSTS" + ], "configuration": "./language-configuration.json" }, { "id": "gamma", - "extensions": [".gamma"], - "aliases": ["Gamma"], + "extensions": [ + ".gamma" + ], + "aliases": [ + "Gamma" + ], "configuration": "./language-configuration.json" } ], diff --git a/subprojects/semantifyr-vscode/syntaxes/oxsts.tmLanguage.json b/subprojects/semantifyr-vscode/syntaxes/oxsts.tmLanguage.json index 09eac476..9d66af1a 100644 --- a/subprojects/semantifyr-vscode/syntaxes/oxsts.tmLanguage.json +++ b/subprojects/semantifyr-vscode/syntaxes/oxsts.tmLanguage.json @@ -70,8 +70,16 @@ "comment": "\"begin\" & \"end\" can create a multi-line region", "begin": "\"", "end": "\"", - "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.languageId" } }, - "endCaptures": { "0": { "name": "punctuation.definition.string.end.languageId" } }, + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.languageId" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.languageId" + } + }, "name": "string.quoted.double.languageId", "patterns": [ { diff --git a/subprojects/semantifyr-vscode/tsconfig.json b/subprojects/semantifyr-vscode/tsconfig.json index 890e27c0..97128f6d 100644 --- a/subprojects/semantifyr-vscode/tsconfig.json +++ b/subprojects/semantifyr-vscode/tsconfig.json @@ -1,22 +1,27 @@ { - "compilerOptions": { - "skipLibCheck": true, - "allowJs": true, - "checkJs": true, - "declaration": true, - "emitDeclarationOnly": true, - //"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - //"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - //"skipLibCheck": true - "target": "ES2023", - "module": "Node16", - "outDir": "./dist", - "strict": true, - //"noUnusedLocals": true, - //"noImplicitReturns": true, - //"noImplicitOverride": true, - "forceConsistentCasingInFileNames": true - }, - "include": ["**/*.ts", "**/*.js", "**/*.cjs", "**/*.mjs"], - "exclude": ["./dist", "./node_modules"] -} \ No newline at end of file + "compilerOptions": { + "skipLibCheck": true, + "allowJs": true, + "checkJs": true, + "declaration": true, + "emitDeclarationOnly": true, + "target": "ES2023", + "module": "Node16", + "outDir": "./dist", + "strict": true, + "noUnusedLocals": true, + "noImplicitReturns": true, + "noImplicitOverride": true, + "forceConsistentCasingInFileNames": true + }, + "include": [ + "**/*.ts", + "**/*.js", + "**/*.cjs", + "**/*.mjs" + ], + "exclude": [ + "./dist", + "./node_modules" + ] +} From dea6322f4b1aeb695893c0968311e3bb60ac2578 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Thu, 26 Mar 2026 12:24:42 +0100 Subject: [PATCH 079/115] Fixed incorrect uri --- .../src/main/kotlin/transformation/InlinedOxstsModelCreator.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt b/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt index fd6ebd53..028ea06a 100644 --- a/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt +++ b/subprojects/semantics/src/main/kotlin/transformation/InlinedOxstsModelCreator.kt @@ -36,8 +36,7 @@ class InlinedOxstsModelCreator { fun createInlinedOxsts(classDeclaration: ClassDeclaration): InlinedOxsts { val resourceSet = classDeclaration.eResource().resourceSet - val path = artifactManager.resolve("inlined.oxsts").path - val uri = URI.createURI(path) + val uri = artifactManager.resolveUri("inlined.oxsts") val inlinedOxsts = OxstsFactory.createInlinedOxsts() inlinedOxsts.classDeclaration = classDeclaration From d588f130b35087f8449f43e3a526a3331e5a9fae Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Thu, 26 Mar 2026 21:49:37 +0100 Subject: [PATCH 080/115] Extended the allotted time for the full model --- .../frontends/sysml/semantics/SysMLVerificationTests.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index 117ac3ac..2e37153d 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -24,6 +24,8 @@ import org.junit.jupiter.params.provider.MethodSource import java.util.stream.Stream import kotlin.io.path.Path import kotlin.streams.asStream +import kotlin.time.DurationUnit +import kotlin.time.toDuration @Tag("verification") @InjectWithOxstsSemantics @@ -135,7 +137,7 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { @ParameterizedTest @MethodSource fun `Full Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { - checkVerificationCase(verificationCase) + checkVerificationCase(verificationCase, 2.toDuration(DurationUnit.HOURS)) } } From 0c98da2111c55a8cc897507e5b40f105f27a453f Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 27 Mar 2026 14:35:49 +0100 Subject: [PATCH 081/115] Increased ram of theta script --- .../backends/theta/theta-wrapper/scripts/theta-xsts-cli | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli index b88eb8fb..ac81c455 100755 --- a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli +++ b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli @@ -2,7 +2,7 @@ set -e SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [ "$1" = "--version" ]; then - LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss512M -Xmx4G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" CEGAR --version + LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss1G -Xmx8G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" CEGAR --version exit fi -LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss512M -Xmx4G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" +LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss1G -Xmx8G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" From 41322149b7bbde1123a907dfc1ebb39858dcc2c1 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 27 Mar 2026 15:11:12 +0100 Subject: [PATCH 082/115] Added additional logging information to verification --- .../src/main/kotlin/ThetaVerifier.kt | 16 +++++++++++++++- .../kotlin/SemantifyrVerificationHelper.kt | 17 +---------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index 9fbd6f10..424009fa 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -24,6 +24,7 @@ import hu.bme.mit.semantifyr.oxsts.model.oxsts.InlinedOxsts import hu.bme.mit.semantifyr.semantics.transformation.ProgressContext import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager +import hu.bme.mit.semantifyr.semantics.utils.loggerFactory import hu.bme.mit.semantifyr.semantics.verification.AbstractOxstsVerifier import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult import hu.bme.mit.semantifyr.semantics.verification.VerificationResult @@ -38,6 +39,8 @@ import kotlin.time.measureTimedValue @CompilationScoped open class ThetaVerifier : AbstractOxstsVerifier() { + val logger by loggerFactory() + @Inject private lateinit var oxstsTransformer: OxstsTransformer @@ -121,21 +124,26 @@ open class ThetaVerifier : AbstractOxstsVerifier() { ): VerificationCaseRunResult { val verificationTimeMetrics = VerificationTimeMetrics() + logger.info("Inlining class") progressContext.reportProgress("Inlining class") val (inlinedOxsts, inliningDuration) = measureTimedValue { inlineClass(progressContext, classDeclaration) } verificationTimeMetrics.inliningMs = inliningDuration + logger.info("Inlining took: $inliningDuration") progressContext.checkIsCancelled() + logger.info("Transforming to Xsts") progressContext.reportProgress("Transforming to Xsts") val (xstsModel, xstsDuration) = measureTimedValue { transformToXsts(progressContext, inlinedOxsts) } verificationTimeMetrics.xstsTransformationMs = xstsDuration + logger.info("Xsts transformation took: $xstsDuration") progressContext.checkIsCancelled() - progressContext.reportProgress("Running Theta Portfolio") + logger.info("Running verification") + progressContext.reportProgress("Running verification") val (result, verifyDuration) = measureTimedValue { try { // Because of the Temporal bubbling optimizations these are the only options @@ -144,6 +152,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { val result = verifyXsts(progressContext, xstsModel, timeout) if (result.hasWitness) { + logger.info("Creating witness") progressContext.reportProgress("Creating witness") val backAnnotationDuration = measureTime { val cexPath = Path(result.runtimeDetails.workingDirectory, result.runtimeDetails.cexPath) @@ -154,6 +163,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { backAnnotateWitness(inlinedOxstsWitness) } verificationTimeMetrics.backAnnotationMs = backAnnotationDuration + logger.info("Back annotation took: $backAnnotationDuration") } when (property) { @@ -168,13 +178,17 @@ open class ThetaVerifier : AbstractOxstsVerifier() { } } } catch (e: Exception) { + logger.error("Exception during verification: ", e) VerificationCaseRunResult(VerificationResult.Errored, e.message) } } verificationTimeMetrics.verificationMs = verifyDuration + logger.info("Verification took: $verifyDuration") thetaArtifactManager.serialize(verificationTimeMetrics) + logger.info("Result is ${result.result} - ${result.message ?: "No message"}") + return result } diff --git a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt index b0c7a016..3878693e 100644 --- a/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt +++ b/subprojects/semantics/src/testFixtures/kotlin/SemantifyrVerificationHelper.kt @@ -126,21 +126,6 @@ abstract class BaseSemantifyrVerificationTest { abstract val logger: Logger - val loggerContext = object : ProgressContext { - override fun checkIsCancelled() { - // never cancelled - } - - override fun reportProgress(message: String, percentage: Int) { - logger.info { "$message - $percentage%" } - } - - override fun reportProgress(message: String) { - logger.info { message } - } - - } - @Inject lateinit var oxstsQualifiedNameProvider: OxstsQualifiedNameProvider @@ -157,7 +142,7 @@ abstract class BaseSemantifyrVerificationTest { "Verifying class: ${oxstsQualifiedNameProvider.getFullyQualifiedNameString(classDeclaration)}" } - return oxstsVerifierProvider.get().verify(loggerContext, classDeclaration, timeout) + return oxstsVerifierProvider.get().verify(ProgressContext.NoOp, classDeclaration, timeout) } fun checkVerificationCase( From 8a3ba7ad74491cdf31be979660ae58bc081e129c Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 27 Mar 2026 16:10:44 +0100 Subject: [PATCH 083/115] Fixed qualified identifier value conv. --- .../OxstsValueConverterService.java | 8 +++ .../QualifiedIdentifierValueConverter.java | 52 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/QualifiedIdentifierValueConverter.java diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/OxstsValueConverterService.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/OxstsValueConverterService.java index 854a3364..03a18463 100644 --- a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/OxstsValueConverterService.java +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/OxstsValueConverterService.java @@ -19,6 +19,9 @@ public class OxstsValueConverterService extends DefaultTerminalConverters { @Inject private IdentifierValueConverter identifierValueConverter; + @Inject + private QualifiedIdentifierValueConverter qualifiedIdentifierValueConverter; + @ValueConverter(rule = "QUOTED_ID") public IValueConverter QUOTED_ID() { return quotedIdValueConverter; @@ -29,4 +32,9 @@ public IValueConverter Identifier() { return identifierValueConverter; } + @ValueConverter(rule = "QualifiedIdentifier") + public IValueConverter QualifiedIdentifier() { + return qualifiedIdentifierValueConverter; + } + } diff --git a/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/QualifiedIdentifierValueConverter.java b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/QualifiedIdentifierValueConverter.java new file mode 100644 index 00000000..753e0980 --- /dev/null +++ b/subprojects/oxsts.lang/src/main/java/hu/bme/mit/semantifyr/oxsts/lang/conversion/QualifiedIdentifierValueConverter.java @@ -0,0 +1,52 @@ +/* + * SPDX-FileCopyrightText: 2025 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.oxsts.lang.conversion; + +import com.google.inject.Inject; +import hu.bme.mit.semantifyr.oxsts.lang.naming.NamingUtil; +import org.eclipse.xtext.conversion.IValueConverter; +import org.eclipse.xtext.conversion.ValueConverterException; +import org.eclipse.xtext.nodemodel.INode; + +public class QualifiedIdentifierValueConverter implements IValueConverter { + private static final String DELIMITER = "::"; + + @Inject + private IdentifierValueConverter identifierValueConverter; + + @Override + public String toValue(String string, INode node) throws ValueConverterException { + if (string == null) { + return null; + } + var builder = new StringBuilder(); + int index = 0; + while (index < string.length()) { + int endIndex = NamingUtil.getEndOfIdentifierSegment(string, index); + var segment = string.substring(index, endIndex); + if (!builder.isEmpty()) { + builder.append(DELIMITER); + } + builder.append(identifierValueConverter.toValue(segment, node)); + index = endIndex + DELIMITER.length(); + } + return builder.toString(); + } + + @Override + public String toString(String value) throws ValueConverterException { + var segments = value.split("::", -1); + var builder = new StringBuilder(); + for (var segment : segments) { + if (!builder.isEmpty()) { + builder.append(DELIMITER); + } + builder.append(identifierValueConverter.toString(segment)); + } + return builder.toString(); + } +} From e68d590f580ef4d889a4b1a58fd6116a9bccc0fc Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Fri, 27 Mar 2026 20:13:04 +0100 Subject: [PATCH 084/115] Increased the max JVM memory to 20G --- .../backends/theta/theta-wrapper/scripts/theta-xsts-cli | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli index ac81c455..2175df07 100755 --- a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli +++ b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli @@ -2,7 +2,7 @@ set -e SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [ "$1" = "--version" ]; then - LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss1G -Xmx8G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" CEGAR --version + LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss1G -Xmx20G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" CEGAR --version exit fi -LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss1G -Xmx8G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" +LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss1G -Xmx20G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" From e9e25b83d828f5b7a5372283ddb9644435d9df8c Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sat, 28 Mar 2026 09:18:25 +0100 Subject: [PATCH 085/115] Added extra logging information --- .../src/main/kotlin/execution/ThetaPorfolioExecutor.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt index b5bb05a3..f4da619e 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt @@ -49,8 +49,12 @@ class ThetaPortfolioRunner { name: String, timeout: Duration ) = supervisorScope { + logger.info("Starting verification portfolio") + val jobs = parameters.indices.map { index -> async { + logger.info("Starting configuration: ($index) ${parameters[index]}") + val thetaVerificationSpecification = ThetaVerificationSpecification(workingDirectory, name, index, parameters[index], timeout) thetaVerificationExecutor.execute(thetaVerificationSpecification) } @@ -70,6 +74,8 @@ class ThetaPortfolioRunner { try { jobs.awaitFirstSuccess() } finally { + logger.info("Portfolio finished, cancelling remaining jobs") + if (checkAllResults) { checkAllModelCheckerResults(jobs) } @@ -136,6 +142,8 @@ class ThetaPortfolioRunner { cancellationChecker.cancel() + logger.info("Winning configuration: (${result.runtimeDetails.id}) ${result.runtimeDetails.parameter}") + thetaArtifactManager.serialize( VerificationPortfolioResult( result.runtimeDetails, From f73955c7db36c1bd501b4000329c7ff91cde5d63 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sat, 28 Mar 2026 09:26:30 +0100 Subject: [PATCH 086/115] Updated theta jvm parameters --- .../backends/theta/theta-wrapper/scripts/theta-xsts-cli | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli index 2175df07..841b14bc 100755 --- a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli +++ b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli @@ -2,7 +2,7 @@ set -e SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [ "$1" = "--version" ]; then - LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss1G -Xmx20G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" CEGAR --version + LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" CEGAR --version exit fi -LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss1G -Xmx20G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" +LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss512M -Xms1G -Xmx20G -XX:+UseG1GC -XX:+UseTransparentHugePages "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" From a4cf2823ffd3c4ea875a6d0420cddfe69622a98d Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sat, 28 Mar 2026 10:04:17 +0100 Subject: [PATCH 087/115] Added error logs --- .../main/kotlin/execution/ThetaPorfolioExecutor.kt | 12 ++++++++++-- .../kotlin/execution/ThetaVerificationExecutor.kt | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt index f4da619e..c1cb438d 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaPorfolioExecutor.kt @@ -55,8 +55,16 @@ class ThetaPortfolioRunner { async { logger.info("Starting configuration: ($index) ${parameters[index]}") - val thetaVerificationSpecification = ThetaVerificationSpecification(workingDirectory, name, index, parameters[index], timeout) - thetaVerificationExecutor.execute(thetaVerificationSpecification) + try { + val thetaVerificationSpecification = ThetaVerificationSpecification(workingDirectory, name, index, parameters[index], timeout) + thetaVerificationExecutor.execute(thetaVerificationSpecification) + } catch (t: CancellationException) { + // cancellation is not logged + throw t + } catch (t: Throwable) { + logger.error("Configuration failed: ($index)", t) + throw t + } } } diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt index 45c474d4..eb1fbd54 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/execution/ThetaVerificationExecutor.kt @@ -17,7 +17,7 @@ import java.io.File import kotlin.time.Duration @Serializable -class ThetaVerificationSpecification( +data class ThetaVerificationSpecification( val workingDirectory: String, val name: String, val id: Int, From 211c05a624b9f262ab1b2519829739369b4e508f Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sat, 28 Mar 2026 10:26:23 +0100 Subject: [PATCH 088/115] Fixed verification time including witness creation --- .../src/main/kotlin/ThetaVerifier.kt | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index 424009fa..79347241 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -141,49 +141,49 @@ open class ThetaVerifier : AbstractOxstsVerifier() { verificationTimeMetrics.xstsTransformationMs = xstsDuration logger.info("Xsts transformation took: $xstsDuration") - progressContext.checkIsCancelled() - logger.info("Running verification") - progressContext.reportProgress("Running verification") - val (result, verifyDuration) = measureTimedValue { - try { - // Because of the Temporal bubbling optimizations these are the only options - val property = inlinedOxsts.property.expression - - val result = verifyXsts(progressContext, xstsModel, timeout) - - if (result.hasWitness) { - logger.info("Creating witness") - progressContext.reportProgress("Creating witness") - val backAnnotationDuration = measureTime { - val cexPath = Path(result.runtimeDetails.workingDirectory, result.runtimeDetails.cexPath) - val cexModel = cexReader.loadCexModel(cexPath) - val cexWitness = cexAssumptionWitnessTransformer.transform(cexModel) - val xstsWitness = xstsAssumptionWitnessTransformer.transform(xstsModel, cexWitness) - val inlinedOxstsWitness = inlinedOxstsAssumptionWitnessTransformer.transform(inlinedOxsts, xstsWitness) - backAnnotateWitness(inlinedOxstsWitness) - } - verificationTimeMetrics.backAnnotationMs = backAnnotationDuration - logger.info("Back annotation took: $backAnnotationDuration") + val result = try { + // Because of the Temporal bubbling optimizations these are the only options + val property = inlinedOxsts.property.expression + + progressContext.checkIsCancelled() + logger.info("Running verification") + progressContext.reportProgress("Running verification") + val (result, verifyDuration) = measureTimedValue { + verifyXsts(progressContext, xstsModel, timeout) + } + verificationTimeMetrics.verificationMs = verifyDuration + logger.info("Verification took: $verifyDuration") + + if (result.hasWitness) { + logger.info("Creating witness") + progressContext.reportProgress("Creating witness") + val backAnnotationDuration = measureTime { + val cexPath = Path(result.runtimeDetails.workingDirectory, result.runtimeDetails.cexPath) + val cexModel = cexReader.loadCexModel(cexPath) + val cexWitness = cexAssumptionWitnessTransformer.transform(cexModel) + val xstsWitness = xstsAssumptionWitnessTransformer.transform(xstsModel, cexWitness) + val inlinedOxstsWitness = inlinedOxstsAssumptionWitnessTransformer.transform(inlinedOxsts, xstsWitness) + backAnnotateWitness(inlinedOxstsWitness) } + verificationTimeMetrics.backAnnotationMs = backAnnotationDuration + logger.info("Back annotation took: $backAnnotationDuration") + } - when (property) { - is AG if result is ThetaUnsafeVerificationResult -> { - VerificationCaseRunResult(VerificationResult.Failed, "Expected Safe result, got Unsafe instead!") - } - is EF if result is ThetaSafeVerificationResult -> { - VerificationCaseRunResult(VerificationResult.Failed, "Expected Unsafe result, got Safe instead!") - } - else -> { - VerificationCaseRunResult(VerificationResult.Passed) - } + when (property) { + is AG if result is ThetaUnsafeVerificationResult -> { + VerificationCaseRunResult(VerificationResult.Failed, "Expected Safe result, got Unsafe instead!") + } + is EF if result is ThetaSafeVerificationResult -> { + VerificationCaseRunResult(VerificationResult.Failed, "Expected Unsafe result, got Safe instead!") + } + else -> { + VerificationCaseRunResult(VerificationResult.Passed) } - } catch (e: Exception) { - logger.error("Exception during verification: ", e) - VerificationCaseRunResult(VerificationResult.Errored, e.message) } + } catch (e: Exception) { + logger.error("Exception during verification: ", e) + VerificationCaseRunResult(VerificationResult.Errored, e.message) } - verificationTimeMetrics.verificationMs = verifyDuration - logger.info("Verification took: $verifyDuration") thetaArtifactManager.serialize(verificationTimeMetrics) From 39d3061332a1ac01dc0bbc5d700409a8f9e2efd6 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 01:26:31 +0100 Subject: [PATCH 089/115] Use 30 minute timeout everywhere --- .../frontends/sysml/semantics/SysMLVerificationTests.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index 2e37153d..69291eb8 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -137,7 +137,7 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { @ParameterizedTest @MethodSource fun `Full Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { - checkVerificationCase(verificationCase, 2.toDuration(DurationUnit.HOURS)) + checkVerificationCase(verificationCase) } } From 37b3b707d1c51e3e2e501dc97709083b3a62fc11 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 01:44:09 +0100 Subject: [PATCH 090/115] Moved the timing information into the results --- .../src/main/kotlin/ThetaArtifactManager.kt | 10 +--------- .../src/main/kotlin/ThetaVerifier.kt | 17 +++++++++-------- .../main/kotlin/verification/OxstsVerifier.kt | 10 ++++++++++ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt index 3f13bbc6..53c2ba13 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt @@ -11,6 +11,7 @@ import hu.bme.mit.semantifyr.backends.theta.verification.execution.ThetaVerifica import hu.bme.mit.semantifyr.semantics.transformation.injection.scope.CompilationScoped import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult +import hu.bme.mit.semantifyr.semantics.verification.VerificationTimeMetrics import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import kotlinx.serialization.json.encodeToStream @@ -35,15 +36,6 @@ data class VerificationPortfolioResult( val allArguments: List, ) -@Serializable -data class VerificationTimeMetrics( - var inliningMs: Duration = Duration.ZERO, - var xstsTransformationMs: Duration = Duration.ZERO, - var verificationMs: Duration = Duration.ZERO, - var backAnnotationMs: Duration = Duration.ZERO, - var totalMs: Duration = Duration.ZERO, -) - @CompilationScoped class ThetaArtifactManager { diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index 79347241..c400fce3 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -28,6 +28,7 @@ import hu.bme.mit.semantifyr.semantics.utils.loggerFactory import hu.bme.mit.semantifyr.semantics.verification.AbstractOxstsVerifier import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult import hu.bme.mit.semantifyr.semantics.verification.VerificationResult +import hu.bme.mit.semantifyr.semantics.verification.VerificationTimeMetrics import hu.bme.mit.semantifyr.xsts.lang.xsts.XstsModel import java.io.File import kotlin.io.path.Path @@ -129,7 +130,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { val (inlinedOxsts, inliningDuration) = measureTimedValue { inlineClass(progressContext, classDeclaration) } - verificationTimeMetrics.inliningMs = inliningDuration + verificationTimeMetrics.inliningDuration = inliningDuration logger.info("Inlining took: $inliningDuration") progressContext.checkIsCancelled() @@ -138,7 +139,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { val (xstsModel, xstsDuration) = measureTimedValue { transformToXsts(progressContext, inlinedOxsts) } - verificationTimeMetrics.xstsTransformationMs = xstsDuration + verificationTimeMetrics.xstsTransformationDuration = xstsDuration logger.info("Xsts transformation took: $xstsDuration") val result = try { @@ -151,7 +152,7 @@ open class ThetaVerifier : AbstractOxstsVerifier() { val (result, verifyDuration) = measureTimedValue { verifyXsts(progressContext, xstsModel, timeout) } - verificationTimeMetrics.verificationMs = verifyDuration + verificationTimeMetrics.verificationDuration = verifyDuration logger.info("Verification took: $verifyDuration") if (result.hasWitness) { @@ -165,24 +166,24 @@ open class ThetaVerifier : AbstractOxstsVerifier() { val inlinedOxstsWitness = inlinedOxstsAssumptionWitnessTransformer.transform(inlinedOxsts, xstsWitness) backAnnotateWitness(inlinedOxstsWitness) } - verificationTimeMetrics.backAnnotationMs = backAnnotationDuration + verificationTimeMetrics.backAnnotationDuration = backAnnotationDuration logger.info("Back annotation took: $backAnnotationDuration") } when (property) { is AG if result is ThetaUnsafeVerificationResult -> { - VerificationCaseRunResult(VerificationResult.Failed, "Expected Safe result, got Unsafe instead!") + VerificationCaseRunResult(VerificationResult.Failed, verificationTimeMetrics, "Expected Safe result, got Unsafe instead!") } is EF if result is ThetaSafeVerificationResult -> { - VerificationCaseRunResult(VerificationResult.Failed, "Expected Unsafe result, got Safe instead!") + VerificationCaseRunResult(VerificationResult.Failed, verificationTimeMetrics, "Expected Unsafe result, got Safe instead!") } else -> { - VerificationCaseRunResult(VerificationResult.Passed) + VerificationCaseRunResult(VerificationResult.Passed, verificationTimeMetrics) } } } catch (e: Exception) { logger.error("Exception during verification: ", e) - VerificationCaseRunResult(VerificationResult.Errored, e.message) + VerificationCaseRunResult(VerificationResult.Errored, verificationTimeMetrics, e.message) } thetaArtifactManager.serialize(verificationTimeMetrics) diff --git a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt index 5bf43b5d..b1550ce8 100644 --- a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt +++ b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt @@ -20,9 +20,19 @@ import kotlinx.serialization.Serializable import kotlin.time.Duration import kotlin.time.toKotlinDuration +@Serializable +data class VerificationTimeMetrics( + var inliningDuration: Duration = Duration.ZERO, + var xstsTransformationDuration: Duration = Duration.ZERO, + var verificationDuration: Duration = Duration.ZERO, + var backAnnotationDuration: Duration = Duration.ZERO, + var totalDuration: Duration = Duration.ZERO, +) + @Serializable data class VerificationCaseRunResult( val result: VerificationResult, + val metrics: VerificationTimeMetrics, val message: String? = null ) From 467bc454a04836560ebba8700654f864b91353f8 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 03:24:42 +0200 Subject: [PATCH 091/115] Merged metrics and reports --- .../src/main/kotlin/ThetaArtifactManager.kt | 32 ++--------------- .../src/main/kotlin/ThetaVerifier.kt | 34 ++++++++++--------- .../main/kotlin/verification/OxstsVerifier.kt | 12 ++++++- 3 files changed, 32 insertions(+), 46 deletions(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt index 53c2ba13..fef6f459 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaArtifactManager.kt @@ -17,18 +17,6 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.json.encodeToStream import org.eclipse.emf.common.util.URI import java.io.File -import kotlin.time.Duration -import kotlin.time.Instant - -@Serializable -data class VerificationReport( - var className: String, - var modelPath: String, - var startedAt: Instant, - var totalDuration: Duration, - var result: VerificationCaseRunResult, - var timeout: Duration, -) @Serializable data class VerificationPortfolioResult( @@ -48,21 +36,7 @@ class ThetaArtifactManager { val xstsUri: URI get() = URI.createFileURI(xstsFile.absolutePath) - fun serialize(data: VerificationTimeMetrics) { - val file = artifactManager.resolve("metrics${File.separator}verification-metrics.json") - file.parentFile.mkdirs() - - val json = Json { - prettyPrint = true - prettyPrintIndent = " " - } - - file.outputStream().buffered().use { - json.encodeToStream(data, it) - } - } - - fun serialize(data: VerificationReport) { + fun serialize(result: VerificationCaseRunResult) { val file = artifactManager.resolve("report.json") file.parentFile.mkdirs() @@ -73,12 +47,12 @@ class ThetaArtifactManager { } file.outputStream().buffered().use { - json.encodeToStream(data, it) + json.encodeToStream(result, it) } } fun serialize(data: VerificationPortfolioResult) { - val file = artifactManager.resolve("metrics${File.separator}portfolio.json") + val file = artifactManager.resolve("portfolio.json") file.parentFile.mkdirs() val json = Json { diff --git a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt index c400fce3..06edb3ea 100644 --- a/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt +++ b/subprojects/backends/theta/xsts-verifier/src/main/kotlin/ThetaVerifier.kt @@ -27,6 +27,7 @@ import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.utils.loggerFactory import hu.bme.mit.semantifyr.semantics.verification.AbstractOxstsVerifier import hu.bme.mit.semantifyr.semantics.verification.VerificationCaseRunResult +import hu.bme.mit.semantifyr.semantics.verification.VerificationMetaData import hu.bme.mit.semantifyr.semantics.verification.VerificationResult import hu.bme.mit.semantifyr.semantics.verification.VerificationTimeMetrics import hu.bme.mit.semantifyr.xsts.lang.xsts.XstsModel @@ -34,6 +35,7 @@ import java.io.File import kotlin.io.path.Path import kotlin.time.Clock import kotlin.time.Duration +import kotlin.time.TimeSource.Monotonic.markNow import kotlin.time.measureTime import kotlin.time.measureTimedValue @@ -98,22 +100,12 @@ open class ThetaVerifier : AbstractOxstsVerifier() { val basePath = outPath.resolve(filePath.nameWithoutExtension + File.separator + classDeclaration.name) artifactManager.initialize(basePath) - val startedAt = Clock.System.now() val (result, duration) = measureTimedValue { doRunVerification(progressContext, classDeclaration, timeout) } - val verificationReport = VerificationReport( - oxstsQualifiedNameProvider.getFullyQualifiedNameString(classDeclaration), - classDeclaration.eResource().uri.toFileString(), - startedAt, - duration, - result, - timeout, - ) - - thetaArtifactManager.serialize(verificationReport) + thetaArtifactManager.serialize(result) return result } @@ -125,6 +117,16 @@ open class ThetaVerifier : AbstractOxstsVerifier() { ): VerificationCaseRunResult { val verificationTimeMetrics = VerificationTimeMetrics() + val startedAt = Clock.System.now() + val mark = markNow() + + val verificationMetaData = VerificationMetaData( + oxstsQualifiedNameProvider.getFullyQualifiedNameString(classDeclaration), + classDeclaration.eResource().uri.toFileString(), + startedAt, + timeout, + ) + logger.info("Inlining class") progressContext.reportProgress("Inlining class") val (inlinedOxsts, inliningDuration) = measureTimedValue { @@ -172,21 +174,21 @@ open class ThetaVerifier : AbstractOxstsVerifier() { when (property) { is AG if result is ThetaUnsafeVerificationResult -> { - VerificationCaseRunResult(VerificationResult.Failed, verificationTimeMetrics, "Expected Safe result, got Unsafe instead!") + VerificationCaseRunResult(VerificationResult.Failed, verificationTimeMetrics, verificationMetaData, "Expected Safe result, got Unsafe instead!") } is EF if result is ThetaSafeVerificationResult -> { - VerificationCaseRunResult(VerificationResult.Failed, verificationTimeMetrics, "Expected Unsafe result, got Safe instead!") + VerificationCaseRunResult(VerificationResult.Failed, verificationTimeMetrics, verificationMetaData, "Expected Unsafe result, got Safe instead!") } else -> { - VerificationCaseRunResult(VerificationResult.Passed, verificationTimeMetrics) + VerificationCaseRunResult(VerificationResult.Passed, verificationTimeMetrics, verificationMetaData) } } } catch (e: Exception) { logger.error("Exception during verification: ", e) - VerificationCaseRunResult(VerificationResult.Errored, verificationTimeMetrics, e.message) + VerificationCaseRunResult(VerificationResult.Errored, verificationTimeMetrics, verificationMetaData, e.message) } - thetaArtifactManager.serialize(verificationTimeMetrics) + verificationTimeMetrics.totalDuration = mark.elapsedNow() logger.info("Result is ${result.result} - ${result.message ?: "No message"}") diff --git a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt index b1550ce8..85a4424d 100644 --- a/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt +++ b/subprojects/semantics/src/main/kotlin/verification/OxstsVerifier.kt @@ -18,6 +18,7 @@ import hu.bme.mit.semantifyr.semantics.transformation.serializer.ArtifactManager import hu.bme.mit.semantifyr.semantics.transformation.tracer.TraceSerializer import kotlinx.serialization.Serializable import kotlin.time.Duration +import kotlin.time.Instant import kotlin.time.toKotlinDuration @Serializable @@ -29,11 +30,20 @@ data class VerificationTimeMetrics( var totalDuration: Duration = Duration.ZERO, ) +@Serializable +data class VerificationMetaData( + val className: String, + val modelPath: String, + val startedAt: Instant, + val timeout: Duration, +) + @Serializable data class VerificationCaseRunResult( val result: VerificationResult, val metrics: VerificationTimeMetrics, - val message: String? = null + val metaData: VerificationMetaData, + val message: String? = null, ) enum class VerificationResult { From ea4656a2b745b203bf546b8abb87a2afea8d5140 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 03:25:18 +0200 Subject: [PATCH 092/115] Added a benchmark test --- .../sysmlv2-semantics/build.gradle.kts | 30 ++++ .../sysml/semantics/SysMLBenchmarkTests.kt | 154 ++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts index 1599454f..13e18f65 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts @@ -8,6 +8,7 @@ plugins { id("hu.bme.mit.semantifyr.gradle.conventions.jvm") id("hu.bme.mit.semantifyr.gradle.conventions.theta") kotlin("jvm") + kotlin("plugin.serialization") } val cliClasspath by configurations.creating { @@ -25,6 +26,8 @@ dependencies { testFixturesApi(project(":xsts-verifier")) testFixturesApi(testFixtures(project(":xsts-verifier"))) + testImplementation(libs.kotlinx.serialization.json) + cliClasspath(project(":sysmlv2-frontend", configuration = "cliOutput")) } @@ -36,3 +39,30 @@ val prepareCli by tasks.registering(Sync::class) { tasks.withType(Test::class) { dependsOn(prepareCli) } + +val benchmarkVerificationCases by tasks.registering(Test::class) { + group = "verification" + description = "Run each verification case N times and aggregate timing. Pass -Pbenchmark.runs=N to override (default 3)." + + dependsOn(prepareCli) + + useJUnitPlatform { + includeTags("benchmark") + } + + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + minHeapSize = "512m" + maxHeapSize = "4G" + maxParallelForks = 1 + testLogging.showStandardStreams = true + testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL + + val thetaCliPath = project(":theta-wrapper").layout.buildDirectory.dir("theta-xsts-cli").get().asFile.absolutePath + val existingPath = environment["PATH"] ?: System.getenv("PATH") ?: "" + environment("PATH", "$thetaCliPath${File.pathSeparator}$existingPath") + + val benchmarkRuns = providers.gradleProperty("benchmark.runs").orElse("3") + systemProperty("benchmark.runs", benchmarkRuns.get()) +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt new file mode 100644 index 00000000..00171479 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt @@ -0,0 +1,154 @@ +/* + * SPDX-FileCopyrightText: 2026 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package hu.bme.mit.semantifyr.frontends.sysml.semantics + +import com.google.inject.Inject +import com.google.inject.Provider +import hu.bme.mit.semantifyr.backends.theta.verification.ThetaVerifier +import hu.bme.mit.semantifyr.oxsts.model.oxsts.ClassDeclaration +import hu.bme.mit.semantifyr.semantics.BaseSemantifyrVerificationTest +import hu.bme.mit.semantifyr.semantics.InjectWithOxstsSemantics +import hu.bme.mit.semantifyr.semantics.SemantifyrVerificationHelper +import hu.bme.mit.semantifyr.semantics.StandaloneOxstsSemanticsRuntimeModule +import hu.bme.mit.semantifyr.semantics.utils.info +import hu.bme.mit.semantifyr.semantics.utils.loggerFactory +import org.junit.jupiter.api.Named +import org.junit.jupiter.api.Tag +import org.junit.jupiter.api.Test +import java.io.File +import kotlin.io.path.Path +import kotlin.time.DurationUnit +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import kotlin.time.toDuration + +@Tag("benchmark") +@InjectWithOxstsSemantics +class SysMLBenchmarkTests : BaseSemantifyrVerificationTest() { + + @Serializable + private data class BenchmarkRow( + val model: String, + val case: String, + val run: Int, + val inliningS: Double, + val xstsTransformS: Double, + val verificationS: Double, + val backAnnotationS: Double, + val totalS: Double, + val result: String, + ) + + companion object { + + private val semantifyrVerificationHelper = + StandaloneOxstsSemanticsRuntimeModule.getInstance() + + private val transformer = StandaloneSysMLTransformer() + + private val BENCHMARK_MODELS = listOf( + "TestModels/crossroads.sysml" to "crossroads", + "TestModels/compressedspacecraft.sysml" to "compressedspacecraft", + "TestModels/spacecraft.sysml" to "spacecraft", + ) + + private fun loadModel(model: String) = run { + val sysmlModelPath = Path(model) + val sysmlModel = sysmlModelPath.toFile() + val oxstsModelPath = Path(sysmlModel.absolutePath.replace(".sysml", ".oxsts")) + transformer.transformModel(sysmlModel, oxstsModelPath.toFile()) + semantifyrVerificationHelper.semantifyrLoader.startContext() + .loadLibraries(Path("Library")) + .loadModel(oxstsModelPath) + .buildAndResolve() + } + + } + + override val logger by loggerFactory() + + @Inject + override lateinit var oxstsVerifierProvider: Provider + + @Test + fun `Benchmark Verification Cases`() { + val runs = System.getProperty("benchmark.runs", "5").toInt() + val rows = mutableListOf() + + for ((modelPath, modelName) in BENCHMARK_MODELS) { + logger.info { "Loading model for benchmark: $modelPath" } + val model = loadModel(modelPath) + val cases = semantifyrVerificationHelper.collectVerificationCases(model) + + for (case in cases) { + @Suppress("UNCHECKED_CAST") + val named = case.get()[0] as Named + val caseName = named.name + val classDeclaration = named.payload + + logger.info { "Benchmarking $modelName / $caseName ($runs run(s))" } + + repeat(runs) { runIndex -> + try { + logger.info { "Running $runIndex of $modelName / $caseName" } + + compilationScopeHelper.runInCompilationScope(classDeclaration) { scopedDecl -> + val result = executeVerificationCase(scopedDecl, 10.toDuration(DurationUnit.MINUTES)) + val m = result.metrics + rows += BenchmarkRow( + model = modelName, + case = caseName, + run = runIndex, + inliningS = m.inliningDuration.toDouble(DurationUnit.SECONDS), + xstsTransformS = m.xstsTransformationDuration.toDouble(DurationUnit.SECONDS), + verificationS = m.verificationDuration.toDouble(DurationUnit.SECONDS), + backAnnotationS = m.backAnnotationDuration.toDouble(DurationUnit.SECONDS), + totalS = m.totalDuration.toDouble(DurationUnit.SECONDS), + result = result.result.name, + ) + } + } catch (e: Exception) { + logger.error("Run $runIndex of $modelName / $caseName failed, skipping", e) + } + } + } + } + + writeResults(rows) + printSummary(rows, runs) + } + + // ------------------------------------------------------------------------- + + private fun writeResults(rows: List) { + val outputFile = File("TestModels/benchmark-results.json") + outputFile.parentFile?.mkdirs() + val prettyJson = Json { prettyPrint = true } + outputFile.writeText(prettyJson.encodeToString(rows)) + logger.info { "Benchmark results written to ${outputFile.absolutePath}" } + } + + private fun printSummary(rows: List, runs: Int) { + println("\n=== Benchmark Summary ($runs run(s) per case) ===") + println("%-60s %8s %8s %8s %8s %8s".format( + "model/case", "inl.mean", "inl.max", "ver.mean", "ver.max", "tot.mean")) + println("-".repeat(110)) + + val grouped = rows.groupBy { "${it.model}/${it.case}" } + for ((key, group) in grouped.entries.sortedBy { it.key }) { + val inl = group.map { it.inliningS } + val ver = group.map { it.verificationS } + val tot = group.map { it.totalS } + println("%-60s %8.3f %8.3f %8.3f %8.3f %8.3f".format( + key, + inl.average(), inl.max(), + ver.average(), ver.max(), + tot.average())) + } + } + +} From a3eaa365ca51078fd66054b7f9dd2feddbeabbfb Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 03:26:26 +0200 Subject: [PATCH 093/115] Do 5 runs for each verification case --- .../frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts index 13e18f65..72c9793d 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts @@ -63,6 +63,6 @@ val benchmarkVerificationCases by tasks.registering(Test::class) { val existingPath = environment["PATH"] ?: System.getenv("PATH") ?: "" environment("PATH", "$thetaCliPath${File.pathSeparator}$existingPath") - val benchmarkRuns = providers.gradleProperty("benchmark.runs").orElse("3") + val benchmarkRuns = providers.gradleProperty("benchmark.runs").orElse("5") systemProperty("benchmark.runs", benchmarkRuns.get()) } From 4095b892c63be076dfddea8bc77b47146bf8d0e0 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 10:06:31 +0200 Subject: [PATCH 094/115] Current stet --- .../sysmlv2-semantics/build.gradle.kts | 52 +++++++++---------- .../sysml/semantics/SysMLBenchmarkTests.kt | 2 +- .../sysml/semantics/SysMLVerificationTests.kt | 13 +++++ 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts index 72c9793d..b590950d 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts @@ -40,29 +40,29 @@ tasks.withType(Test::class) { dependsOn(prepareCli) } -val benchmarkVerificationCases by tasks.registering(Test::class) { - group = "verification" - description = "Run each verification case N times and aggregate timing. Pass -Pbenchmark.runs=N to override (default 3)." - - dependsOn(prepareCli) - - useJUnitPlatform { - includeTags("benchmark") - } - - testClassesDirs = sourceSets.test.get().output.classesDirs - classpath = sourceSets.test.get().runtimeClasspath - - minHeapSize = "512m" - maxHeapSize = "4G" - maxParallelForks = 1 - testLogging.showStandardStreams = true - testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL - - val thetaCliPath = project(":theta-wrapper").layout.buildDirectory.dir("theta-xsts-cli").get().asFile.absolutePath - val existingPath = environment["PATH"] ?: System.getenv("PATH") ?: "" - environment("PATH", "$thetaCliPath${File.pathSeparator}$existingPath") - - val benchmarkRuns = providers.gradleProperty("benchmark.runs").orElse("5") - systemProperty("benchmark.runs", benchmarkRuns.get()) -} +//val benchmarkVerificationCases by tasks.registering(Test::class) { +// group = "verification" +// description = "Run each verification case N times and aggregate timing. Pass -Pbenchmark.runs=N to override (default 3)." +// +// dependsOn(prepareCli) +// +// useJUnitPlatform { +// includeTags("benchmark") +// } +// +// testClassesDirs = sourceSets.test.get().output.classesDirs +// classpath = sourceSets.test.get().runtimeClasspath +// +// minHeapSize = "512m" +// maxHeapSize = "4G" +// maxParallelForks = 1 +// testLogging.showStandardStreams = true +// testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL +// +// val thetaCliPath = project(":theta-wrapper").layout.buildDirectory.dir("theta-xsts-cli").get().asFile.absolutePath +// val existingPath = environment["PATH"] ?: System.getenv("PATH") ?: "" +// environment("PATH", "$thetaCliPath${File.pathSeparator}$existingPath") +// +// val benchmarkRuns = providers.gradleProperty("benchmark.runs").orElse("5") +// systemProperty("benchmark.runs", benchmarkRuns.get()) +//} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt index 00171479..b528b743 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt @@ -74,7 +74,7 @@ class SysMLBenchmarkTests : BaseSemantifyrVerificationTest() { @Inject override lateinit var oxstsVerifierProvider: Provider - @Test +// @Test fun `Benchmark Verification Cases`() { val runs = System.getProperty("benchmark.runs", "5").toInt() val rows = mutableListOf() diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index 69291eb8..fcb118a9 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -74,6 +74,13 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() } + @JvmStatic + fun `Semantics Test Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/semanticstest.sysml") + + return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + } + @JvmStatic fun `Crossroads Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/crossroads.sysml") @@ -121,6 +128,12 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { checkVerificationCase(verificationCase) } + @ParameterizedTest + @MethodSource + fun `Semantics Test Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) + } + @ParameterizedTest @MethodSource fun `Crossroads Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { From d355b2e848e75b11c64ab17becb6235179e8c2c1 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 15:43:15 +0200 Subject: [PATCH 095/115] Updated sysmlv2 fronted to f469c8e21fd61348858e7b8cb1a726a6792b57e3 --- subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index e4e028f2..f363c0a0 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -13,7 +13,7 @@ plugins { alias(libs.plugins.gradle.node) } -val sysmlCommit = "f469c8e21fd61348858e7b8cb1a726a6792b57e3" // Improved cloning logic +val sysmlCommit = "f86a90c6a585df970d34bdcdfbbdb892a3d9d3dc" // Improved expression mapping val sysmlUrl = "https://github.com/arminzavada/sysml-2ls.git" val sysmlDir = layout.buildDirectory.dir("sysml-2ls").get() From 1c3c0ec22f10fe65a86638279c34eab3c89ddda1 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 15:43:52 +0200 Subject: [PATCH 096/115] Added semantic library tests --- .../TestModels/semanticstest.sysml | 693 ++++++++++++++++++ 1 file changed, 693 insertions(+) create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/semanticstest.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/semanticstest.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/semanticstest.sysml new file mode 100644 index 00000000..f68dd13a --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/semanticstest.sysml @@ -0,0 +1,693 @@ +private import ScalarValues::Integer; +private import ScalarValues::Boolean; +private import SI::s; + +// ── Shared item and port definitions ────────────────────────────────────────── + +item def EventE; +item def EventF; +item def EventG; +item def MessageM; + +port def PortE { in item e : EventE; } +port def PortFG { in item f : EventF; in item g : EventG; } +port def PortMOut { out item m : MessageM; } + +// ── 1. EntryActionModel ─────────────────────────────────────────────────────────── +// Verifies that a state's entry action fires when the state is activated. + +part def EntryActionModel { + attribute entered : Boolean default false; + + exhibit state Behaviour { + state S1 { + entry action { assign entered := true; } + } + transition first start then S1; + } +} + +verification def EntryActionModelEntered { + subject system : EntryActionModel; + objective { + verify requirement { + require constraint { eventually(system.entered == true) } + } + } +} + +// ── 2. ExitAction ──────────────────────────────────────────────────────────── +// Verifies that a state's exit action fires when the state is left. + +part def ExitActionModel { + attribute exited : Boolean default false; + port input : PortE; + + exhibit state Behaviour { + state S1 { + exit action { assign exited := true; } + } + state S2; + transition first start then S1; + transition first S1 accept : EventE via input then S2; + } +} + +verification def ExitActionExited { + subject system : ExitActionModel; + objective { + verify requirement { + require constraint { eventually(system.exited == true) } + } + } +} + +// ── 3. TransitionDoActionModel ──────────────────────────────────────────────────── +// Verifies that a transition's do-action fires when the transition is taken. + +part def TransitionDoActionModel { + attribute actionFired : Boolean default false; + port input : PortE; + + exhibit state Behaviour { + state S1; + state S2; + transition first start then S1; + transition + first S1 + accept : EventE via input + do action { assign actionFired := true; } + then S2; + } +} + +verification def TransitionDoActionModelFired { + subject system : TransitionDoActionModel; + objective { + verify requirement { + require constraint { eventually(system.actionFired == true) } + } + } +} + +// ── 4. HierarchicalEntryModel ───────────────────────────────────────────────────── +// Verifies that entering a composite state activates its initial substate. + +part def HierarchicalEntryModel { + exhibit state Behaviour { + state Outer { + state Inner; + transition first start then Inner; + } + transition first start then Outer; + } +} + +verification def HierarchicalEntryModelInner { + subject system : HierarchicalEntryModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.Outer.Inner)) } + } + } +} + +// ── 5. HierarchicalExitModel ────────────────────────────────────────────────────── +// Verifies that a transition from a composite state fires the state's exit action +// and reaches the target state, even when the active inner state has no own transitions. + +part def HierarchicalExitModel { + attribute outerExited : Boolean default false; + port input : PortE; + + exhibit state Behaviour { + state Outer { + state S1; + transition first start then S1; + exit action { assign outerExited := true; } + } + state Done; + transition first start then Outer; + transition first Outer accept : EventE via input then Done; + } +} + +verification def HierarchicalExitModelDone { + subject system : HierarchicalExitModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.Done)) } + } + } +} + +verification def HierarchicalExitModelExited { + subject system : HierarchicalExitModel; + objective { + verify requirement { + require constraint { eventually(system.outerExited == true) } + } + } +} + +// ── 6. TransitionPriorityModel ──────────────────────────────────────────────────── +// Verifies bottom-up (inner-first) transition priority: when both an inner +// transition and an enclosing transition accept the same event, the inner one fires. + +part def TransitionPriorityModel { + attribute innerFired : Boolean default false; + attribute outerFired : Boolean default false; + port input : PortE; + + exhibit state Behaviour { + state Outer { + state Inner; + state InnerDone; + transition first start then Inner; + transition + first Inner + accept : EventE via input + do action { assign innerFired := true; } + then InnerDone; + } + state OuterDone; + transition first start then Outer; + transition + first Outer + accept : EventE via input + do action { assign outerFired := true; } + then OuterDone; + } +} + +// Inner transition fires first (from Inner, E takes Inner→InnerDone). +verification def TransitionPriorityModelInnerFires { + subject system : TransitionPriorityModel; + objective { + verify requirement { + require constraint { eventually(system.innerFired == true) } + } + } +} + +// Inner→InnerDone is reachable (would not be so under top-down priority). +verification def TransitionPriorityModelInnerDoneReachable { + subject system : TransitionPriorityModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.Outer.InnerDone)) } + } + } +} + +// Once InnerDone is active (no inner transition on E), the outer transition fires. +verification def TransitionPriorityModelOuterFires { + subject system : TransitionPriorityModel; + objective { + verify requirement { + require constraint { eventually(system.outerFired == true) } + } + } +} + +// Safety: the outer transition never fires while Inner is the active inner state. +verification def TransitionPriorityModelBottomUpSafety { + subject system : TransitionPriorityModel; + objective { + verify requirement { + require constraint { + mustAlways( + not (isStateActive(system.Behaviour.Outer.Inner) + and system.outerFired == true) + ) + } + } + } +} + +// ── 7. ParallelRegionsModel ─────────────────────────────────────────────────────── +// Verifies that two concurrent regions execute independently and can both advance. + +part def ParallelRegionsModel { + port input : PortFG; + + exhibit state Behaviour parallel { + state R1 { + state A; + state B; + transition first start then A; + transition first A accept : EventF via input then B; + } + state R2 { + state C; + state D; + transition first start then C; + transition first C accept : EventG via input then D; + } + } +} + +verification def ParallelRegionsModelR1B { + subject system : ParallelRegionsModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.R1.B)) } + } + } +} + +verification def ParallelRegionsModelR2D { + subject system : ParallelRegionsModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.R2.D)) } + } + } +} + +verification def ParallelRegionsModelBothAdvanced { + subject system : ParallelRegionsModel; + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.R1.B) + and isStateActive(system.Behaviour.R2.D) + ) + } + } + } +} + +// ── 8. TimeoutTransitionModel ───────────────────────────────────────────────────── +// Verifies that an AcceptTimeoutAction triggers after the specified number of time steps. + +part def TimeoutTransitionModel { + exhibit state Behaviour { + state Waiting; + state Done; + transition first start then Waiting; + transition first Waiting accept after 2 [s] then Done; + } +} + +verification def TimeoutTransitionModelDone { + subject system : TimeoutTransitionModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.Done)) } + } + } +} + +// ── 9. GuardedTransitionModel ───────────────────────────────────────────────────── +// Verifies that integer guards correctly control which transition fires. +// Uses a self-transition loop to increment a counter until the exit guard is satisfied. + +part def GuardedTransitionModel { + attribute counter : Integer default 0; + + exhibit state Behaviour { + state Counting; + state Done; + transition first start then Counting; + transition + first Counting + if counter < 3 + do action { assign counter := counter + 1; } + then Counting; + transition + first Counting + if counter >= 3 + then Done; + } +} + +verification def GuardedTransitionModelDone { + subject system : GuardedTransitionModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.Done)) } + } + } +} + +verification def GuardedTransitionModelCount { + subject system : GuardedTransitionModel; + objective { + verify requirement { + require constraint { eventually(system.counter >= 3) } + } + } +} + +// ── 10. ItemFlow ───────────────────────────────────────────────────────────── +// Verifies that an item sent by one sub-part is delivered to another via a flow. + +part def SenderPartModel { + port output : PortMOut; + exhibit state Behaviour { + state Idle; + state Sent; + transition first start then Idle; + transition + first Idle + do action { send MessageM() via output; } + then Sent; + } +} + +part def ReceiverPartModel { + attribute received : Boolean default false; + port input : ~PortMOut; + exhibit state Behaviour { + state Idle; + state Got { + entry action { assign received := true; } + } + transition first start then Idle; + transition first Idle accept : MessageM via input then Got; + } +} + +part def ItemFlowModel { + part sender : SenderPartModel; + part receiver : ReceiverPartModel; + flow from sender.output to receiver.input; +} + +verification def ItemFlowReceived { + subject system : ItemFlowModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.receiver.Behaviour.Got)) } + } + } +} + +verification def ItemFlowAttribute { + subject system : ItemFlowModel; + objective { + verify requirement { + require constraint { eventually(system.receiver.received == true) } + } + } +} + +// ── 11. CrossHierarchyTransitionModel ───────────────────────────────────────────── +// Active configuration Outer.Middle.Inner → Other.Deep. +// Transition is from the outer boundary (Outer), so exit walks all three levels +// (Inner, Middle, Outer) and entry walks two levels (Other, Deep). +// Verifies that exit actions along the full chain fire and that the new deep +// target state is correctly activated. + +part def CrossHierarchyTransitionModel { + attribute middleExited : Boolean default false; + attribute outerExited : Boolean default false; + attribute otherEntered : Boolean default false; + attribute deepEntered : Boolean default false; + port input : PortE; + + exhibit state Behaviour { + state Outer { + state Middle { + state Inner; + transition first start then Inner; + exit action { assign middleExited := true; } + } + transition first start then Middle; + exit action { assign outerExited := true; } + } + state Other { + state Deep { + entry action { assign deepEntered := true; } + } + entry action { assign otherEntered := true; } + transition first start then Deep; + } + transition first start then Outer; + transition first Outer accept : EventE via input then Other; + } +} + +// Three-level deep initial state is reachable (active config before transition). +verification def CrossHierarchyInitialDeep { + subject system : CrossHierarchyTransitionModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.Outer.Middle.Inner)) } + } + } +} + +// After the cross-hierarchy transition, the two-level deep target is active. +verification def CrossHierarchyTargetDeep { + subject system : CrossHierarchyTransitionModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.Other.Deep)) } + } + } +} + +// Both exit actions along the departure chain (Middle, Outer) fire. +verification def CrossHierarchyExitChain { + subject system : CrossHierarchyTransitionModel; + objective { + verify requirement { + require constraint { + eventually(system.middleExited == true and system.outerExited == true) + } + } + } +} + +// Both entry actions along the arrival chain (Other, Deep) fire. +verification def CrossHierarchyEntryChain { + subject system : CrossHierarchyTransitionModel; + objective { + verify requirement { + require constraint { + eventually(system.otherEntered == true and system.deepEntered == true) + } + } + } +} + +// ── 12. ExitActionOrderModel ────────────────────────────────────────────────────── +// When leaving a 3-level hierarchy, exit actions fire innermost-first. +// Each exit action captures the current value of a step counter, then increments it. +// Correct order: Inner exit (step=0) → Middle exit (step=1) → Outer exit (step=2). +// Implementation detail: State.exit() calls deactivateRecursive(false) which +// deactivates children first, then exitRecursive() walks upward calling deactivate() +// on each ancestor up to (but not including) the commonState. + +part def ExitActionOrderModel { + attribute step : Integer default 0; + attribute innerExitStep : Integer default 0; + attribute middleExitStep : Integer default 0; + attribute outerExitStep : Integer default 0; + port input : PortE; + + exhibit state Behaviour { + state Outer { + state Middle { + state Inner { + exit action { assign innerExitStep := step; assign step := step + 1; } + } + transition first start then Inner; + exit action { assign middleExitStep := step; assign step := step + 1; } + } + transition first start then Middle; + exit action { assign outerExitStep := step; assign step := step + 1; } + } + state Done; + transition first start then Outer; + transition first Outer accept : EventE via input then Done; + } +} + +verification def ExitActionOrderModelInnerBeforeMiddle { + subject system : ExitActionOrderModel; + objective { + verify requirement { + require constraint { eventually(system.innerExitStep < system.middleExitStep) } + } + } +} + +verification def ExitActionOrderModelMiddleBeforeOuter { + subject system : ExitActionOrderModel; + objective { + verify requirement { + require constraint { eventually(system.middleExitStep < system.outerExitStep) } + } + } +} + +// ── 13. EntryActionOrderModel ───────────────────────────────────────────────────── +// When entering a 3-level hierarchy, entry actions fire outermost-first. +// Implementation detail: State.enter() calls enterRecursive(), which recurses UP +// first (toward commonState), then calls activate() (which fires entryAction) on the +// way back DOWN. activateRecursive() then fires the start transition into the next level. + +part def EntryActionOrderModel { + attribute step : Integer default 0; + attribute targetEntryStep : Integer default 0; + attribute middleEntryStep : Integer default 0; + attribute innerEntryStep : Integer default 0; + port input : PortE; + + exhibit state Behaviour { + state Source; + state Target { + state Middle { + state Inner { + entry action { assign innerEntryStep := step; assign step := step + 1; } + } + entry action { assign middleEntryStep := step; assign step := step + 1; } + transition first start then Inner; + } + entry action { assign targetEntryStep := step; assign step := step + 1; } + transition first start then Middle; + } + transition first start then Source; + transition first Source accept : EventE via input then Target; + } +} + +verification def EntryActionOrderModelTargetBeforeMiddle { + subject system : EntryActionOrderModel; + objective { + verify requirement { + require constraint { eventually(system.targetEntryStep < system.middleEntryStep) } + } + } +} + +verification def EntryActionOrderModelMiddleBeforeInner { + subject system : EntryActionOrderModel; + objective { + verify requirement { + require constraint { eventually(system.middleEntryStep < system.innerEntryStep) } + } + } +} + +// ── 14. ParallelStateExitModel ──────────────────────────────────────────────────── +// Exiting a parallel state must deactivate ALL concurrent regions. +// Implementation detail: ParallelState.exit() calls deactivateRecursive(false) which +// recursively deactivates every sub-region with _deactivate=true. + +part def ParallelStateExitModel { + port input : PortE; + + exhibit state Behaviour { + state Running parallel { + state R1 { + state R1On; + transition first start then R1On; + } + state R2 { + state R2On; + transition first start then R2On; + } + } + state Done; + transition first start then Running; + transition first Running accept : EventE via input then Done; + } +} + +// Both regions are concurrently active before the exit transition. +verification def ParallelStateExitModelBothActive { + subject system : ParallelStateExitModel; + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.Running.R1.R1On) + and isStateActive(system.Behaviour.Running.R2.R2On) + ) + } + } + } +} + +// Done is reachable (parallel state can be exited). +verification def ParallelStateExitModelDone { + subject system : ParallelStateExitModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.Done)) } + } + } +} + +// After exiting the parallel state, neither region is active (safety). +verification def ParallelStateExitModelR1Deactivated { + subject system : ParallelStateExitModel; + objective { + verify requirement { + require constraint { + mustAlways( + not (isStateActive(system.Behaviour.Done) + and isStateActive(system.Behaviour.Running.R1.R1On)) + ) + } + } + } +} + +// ── 15. ParallelNestedInSequentialModel ─────────────────────────────────────────── +// A parallel state nested inside a sequential state. +// Tests ParallelState.enterRecursive() when parent is a sequential State (not the root), +// and ParallelState.activate() setting the parent's activeState correctly. + +part def ParallelNestedInSequentialModel { + port input : PortE; + + exhibit state Behaviour { + state Outer { + state Inner parallel { + state P1 { + state P1A; + transition first start then P1A; + } + state P2 { + state P2A; + transition first start then P2A; + } + } + transition first start then Inner; + } + state Done; + transition first start then Outer; + transition first Outer accept : EventE via input then Done; + } +} + +// Both parallel sub-regions are active while inside the sequential Outer state. +verification def ParallelNestedBothActive { + subject system : ParallelNestedInSequentialModel; + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.Outer.Inner.P1.P1A) + and isStateActive(system.Behaviour.Outer.Inner.P2.P2A) + ) + } + } + } +} + +// The sequential state can be exited even when a parallel state is active inside. +verification def ParallelNestedExitDone { + subject system : ParallelNestedInSequentialModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.Done)) } + } + } +} From 92dd012808be2cd125b8d4e2f85e3f8af8e48b62 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 15:45:10 +0200 Subject: [PATCH 097/115] Added example sysmlv2 trace model --- .../Examples/crossroads-trace.sysml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/Examples/crossroads-trace.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/Examples/crossroads-trace.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Examples/crossroads-trace.sysml new file mode 100644 index 00000000..1f9a9980 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Examples/crossroads-trace.sysml @@ -0,0 +1,42 @@ +private import Occurrences::HappensJustBefore; +private import Occurrences::HappensWhile; + +part def TrafficLightControllerTrace :> TrafficLightController { + :>> timeSlices : TrafficLightController; + state B :>> Behaviour { + state n1 :> Normal { + state y1 :> Yellow; action tyr1 :> tyr; state r1 :> Red; } + action tni1 :> tni; + state i1 :> Interrupted { state y1 :> Yellow; } + action tin1 :> tin; + state n2 :> Normal { state y2 :> Yellow; } } + timeslice before; // before beginning execution + succession : HappensJustBefore first before then start; + timeslice start; // during startShot + succession : HappensWhile first B.startShot then start; + succession : HappensJustBefore first start then NY; + timeslice NY; // at state Normal.Yellow + succession : HappensWhile first B.n1 then NY; + succession : HappensWhile first B.n1.y1 then NY; + succession : HappensJustBefore first NY then NYtoNR; + timeslice NYtoNR; // executing transition Yellow -> Red + succession : HappensWhile first B.n1 then NYtoNR; + succession : HappensWhile first B.n1.tyr1 then NYtoNR; + succession : HappensJustBefore first NYtoNR then NR; + timeslice NR; // at state Normal.Red + succession : HappensWhile first B.n1 then NYtoNR; + succession : HappensWhile first B.n1.tyr1 then NYtoNR; + succession : HappensJustBefore first NYtoNR then NR; + timeslice NtoI; // executing transition Normal -> Interrupted + succession : HappensWhile first B.tni1 then NtoI; + succession : HappensJustBefore first NtoI then IY; + timeslice IY; // at state Interrupted.Yellow + succession : HappensWhile first B.i1 then IY; + succession : HappensWhile first B.i1.y1 then IY; + succession : HappensJustBefore first IY then NR; + timeslice ItoN2; // executing transition Interrupted -> Normal + succession : HappensWhile first B.tin1 then ItoN2; + succession : HappensJustBefore first ItoN2 then IY; + timeslice NY2; // at state Normal.Yellow + succession : HappensWhile first B.n2 then NY2; + succession : HappensWhile first B.n2.y2 then NY2; } From 8f76cdb51861ec9b6cbe8156629dd144fac80bda Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 17:24:29 +0200 Subject: [PATCH 098/115] Collect the raw cases --- .../test/kotlin/ThetaXstsVerificationTests.kt | 2 +- .../src/test/kotlin/GammaVerificationTests.kt | 23 ++++--------------- .../sysml/semantics/SysMLVerificationTests.kt | 12 ++++++---- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt b/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt index 9ef13458..7508463c 100644 --- a/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt +++ b/subprojects/backends/theta/xsts-verifier/src/test/kotlin/ThetaXstsVerificationTests.kt @@ -36,7 +36,7 @@ class ThetaXstsVerificationTests : BaseSemantifyrVerificationTest .loadModels(Path("test-models/Simple/simple.oxsts")) .buildAndResolve() - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } } diff --git a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt index 74b10555..6d3c3ed7 100644 --- a/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt +++ b/subprojects/frontends/gamma/gamma-semantics/src/test/kotlin/GammaVerificationTests.kt @@ -42,7 +42,7 @@ class GammaVerificationTests : BaseSemantifyrVerificationTest() { .loadModels(Path("Library")) .buildAndResolve() - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } val transformer = StandaloneGammaTransformer() @@ -65,28 +65,21 @@ class GammaVerificationTests : BaseSemantifyrVerificationTest() { fun `Simple Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/Simple.gamma") - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } @JvmStatic fun `Crossroads Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/Crossroads.gamma") - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } @JvmStatic fun `Spacecraft Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/Spacecraft.gamma") - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() - } - - @JvmStatic - fun `Slow Spacecraft Model Verification Cases Should Pass`(): Stream { - val model = loadModel("TestModels/Spacecraft.gamma") - - return semantifyrVerificationHelper.collectSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } } @@ -125,12 +118,4 @@ class GammaVerificationTests : BaseSemantifyrVerificationTest() { checkVerificationCase(verificationCase) } - @Tag("slow") - @ParameterizedTest - @MethodSource - @Disabled("There are no slow crossroads verification cases just yet.") - fun `Slow Spacecraft Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { - checkVerificationCase(verificationCase, 60.toDuration(DurationUnit.MINUTES)) - } - } diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index fcb118a9..b0388df4 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -41,7 +41,7 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { .loadModels(Path("Library")) .buildAndResolve() - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } val transformer = StandaloneSysMLTransformer() @@ -64,14 +64,14 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { fun `STM21 Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/stm21.sysml") - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } @JvmStatic fun `STM31 Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/stm31.sysml") - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } @JvmStatic @@ -79,20 +79,21 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { val model = loadModel("TestModels/semanticstest.sysml") return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } @JvmStatic fun `Crossroads Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/crossroads.sysml") - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } @JvmStatic fun `Compressed Spacecraft Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/compressedspacecraft.sysml") - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } @JvmStatic @@ -100,6 +101,7 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { val model = loadModel("TestModels/spacecraft.sysml") return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } } From d33a290cec791d35ea4f157df9cac13dd9938745 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 18:24:00 +0200 Subject: [PATCH 099/115] Added support for accept when triggers --- .../sysmlv2/sysmlv2-frontend/build.gradle.kts | 2 +- .../sysmlv2/sysmlv2-semantics/Library/Triggers.oxsts | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts index f363c0a0..72a8d729 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-frontend/build.gradle.kts @@ -13,7 +13,7 @@ plugins { alias(libs.plugins.gradle.node) } -val sysmlCommit = "f86a90c6a585df970d34bdcdfbbdb892a3d9d3dc" // Improved expression mapping +val sysmlCommit = "f829c1307799c278242ab456b8c6cd7adf44f156" // Added support for AcceptWhen triggers val sysmlUrl = "https://github.com/arminzavada/sysml-2ls.git" val sysmlDir = layout.buildDirectory.dir("sysml-2ls").get() diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Triggers.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Triggers.oxsts index 46ed9ec7..f280aa6f 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Triggers.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/Triggers.oxsts @@ -59,3 +59,13 @@ class AcceptTimeoutAction : AcceptAction { remainingTime := afterTime } } + +class AcceptWhenAction : AcceptAction { + + contains expression: Expression + + redefine prop isTriggered(): bool { + return expression.evaluate() + } + +} From 1e36cf9bc20217da2e46b4839c2c02966fc70b20 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 18:24:14 +0200 Subject: [PATCH 100/115] Parallel states can also have entry/exit actions --- .../sysmlv2/sysmlv2-semantics/Library/States.oxsts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/States.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/States.oxsts index b3e89bd5..828fd4c1 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/States.oxsts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/Library/States.oxsts @@ -18,6 +18,9 @@ abstract class AbstractState : StateNode { container parent: AbstractState[0..1] opposite states contains states: AbstractState[0..*] opposite parent + contains entryAction: Action[1] + contains exitAction: Action[1] + redefine prop isActive(): bool { return parent?.isInnerStateActive(self) } @@ -42,8 +45,6 @@ class State : AbstractState { contains start: EntryState[1] contains transitions: Transition[0..*] opposite parentState - contains entryAction: Action[1] - contains exitAction: Action[1] var activeState: states[0..1] := nothing @@ -297,11 +298,15 @@ class ParallelState : AbstractState { inline for (transition in outgoingTransitions) { inline transition.initialize() } + + inline entryAction.main() } } tran deactivate() { inline if (parent != nothing) { + inline exitAction.main() + if (parent.getActiveState() == self) { inline parent.setActiveState(nothing) } From f0d23b596e6503ffff33ba2e9ca6682a70f15082 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 18:55:15 +0200 Subject: [PATCH 101/115] Added additional models --- .../TestModels/aircraft_engine.sysml | 232 +++++++++ .../TestModels/autonomous_driving.sysml | 366 ++++++++++++++ .../TestModels/door_access.sysml | 133 +++++ .../TestModels/orion_protocol.sysml | 463 ++++++++++++++++++ .../TestModels/power_subsystems.sysml | 135 +++++ .../TestModels/semanticstest.sysml | 326 ++++++++++-- .../sysml/semantics/SysMLVerificationTests.kt | 66 ++- 7 files changed, 1689 insertions(+), 32 deletions(-) create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/aircraft_engine.sysml create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/autonomous_driving.sysml create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/door_access.sysml create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/orion_protocol.sysml create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/power_subsystems.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/aircraft_engine.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/aircraft_engine.sysml new file mode 100644 index 00000000..2df5b949 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/aircraft_engine.sysml @@ -0,0 +1,232 @@ +private import ScalarValues::Boolean; + +item def PowerOnSignal; +item def StartSignal; +item def IgnitionSuccessSignal; +item def FailureSignal; +item def WarmupCompleteSignal; +item def IdleCommand; +item def ResumeCommand; +item def OverheatSignal; +item def JFSFailureSignal; +item def ShutdownCommand; +item def CriticalFailureSignal; +item def PerformanceDegradation; +item def StabilizationSignal; +item def RestartCommand; +item def RestartSuccessSignal; +item def RestartFailureSignal; +item def IrrecoverableSignal; +item def MaintenanceStartSignal; +item def CompleteSignal; + +port def Control { + in item powerOnSignal : PowerOnSignal; + in item startSignal : StartSignal; + in item ignitionSuccessSignal : IgnitionSuccessSignal; + in item failureSignal : FailureSignal; + in item warmupCompleteSignal : WarmupCompleteSignal; + in item idleCommand : IdleCommand; + in item resumeCommand : ResumeCommand; + in item overheatSignal : OverheatSignal; + in item jFSFailureSignal : JFSFailureSignal; + in item shutdownCommand : ShutdownCommand; + in item criticalFailureSignal : CriticalFailureSignal; + in item performanceDegradation : PerformanceDegradation; + in item stabilizationSignal : StabilizationSignal; + in item restartCommand : RestartCommand; + in item restartSuccessSignal : RestartSuccessSignal; + in item restartFailureSignal : RestartFailureSignal; + in item irrecoverableSignal : IrrecoverableSignal; + in item maintenanceStartSignal : MaintenanceStartSignal; + in item completeSignal : CompleteSignal; +} + +part def EngineStateMachine { + attribute preStartupCheckOk: Boolean default true; + port control: Control; + + exhibit state Behaviour { + state Off; + state PoweringUp; + state Startup; + state Warmup; + state Nominal; + state Idle; + state Overheat; + state JFS_Failure; + state Restart; + state Maintenance; + state Shutdown; + state EmergencyShutdown; + state EngineDown; + + transition first start then Off; + + transition first Off + accept : PowerOnSignal via control + then PoweringUp; + + transition first PoweringUp + accept : StartSignal via control + if (preStartupCheckOk == true) + then Startup; + + transition first Startup + accept : IgnitionSuccessSignal via control + then Warmup; + + transition first Startup + accept : FailureSignal via control + then JFS_Failure; + + transition first Warmup + accept : WarmupCompleteSignal via control + then Nominal; + + transition first Nominal + accept : IdleCommand via control + then Idle; + + transition first Nominal + accept : OverheatSignal via control + then Overheat; + + transition first Nominal + accept : JFSFailureSignal via control + then JFS_Failure; + + transition first Nominal + accept : ShutdownCommand via control + then Shutdown; + + transition first Nominal + accept : CriticalFailureSignal via control + then EmergencyShutdown; + + transition first Nominal + accept : PerformanceDegradation via control + then EngineDown; + + transition first Idle + accept : ResumeCommand via control + then Nominal; + + transition first Overheat + accept : StabilizationSignal via control + then Nominal; + + transition first JFS_Failure + accept : RestartCommand via control + then Restart; + + transition first JFS_Failure + accept : IrrecoverableSignal via control + then EngineDown; + + transition first Restart + accept : RestartSuccessSignal via control + then Warmup; + + transition first Restart + accept : RestartFailureSignal via control + then EngineDown; + + transition first Maintenance + accept : MaintenanceStartSignal via control + then Off; + + transition first Shutdown + accept : CompleteSignal via control + then Off; + + transition first EmergencyShutdown + accept : CompleteSignal via control + then Off; + } +} + +verification def OffReachable { + subject system : EngineStateMachine; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.Off) + ) + } + } + } +} + +verification def NominalReachable { + subject system : EngineStateMachine; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.Nominal) + ) + } + } + } +} + +verification def JFS_FailureReachable { + subject system : EngineStateMachine; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.JFS_Failure) + ) + } + } + } +} + +verification def EngineDownReachable { + subject system : EngineStateMachine; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.EngineDown) + ) + } + } + } +} + +verification def MaintenanceUnreachable { + subject system : EngineStateMachine; + + objective { + verify requirement { + require constraint { + not eventually( + isStateActive(system.Behaviour.Maintenance) + ) + } + } + } +} + +verification def NominalAndIdleNeverSimultaneous { + subject system : EngineStateMachine; + + objective { + verify requirement { + require constraint { + mustAlways(not( + isStateActive(system.Behaviour.Nominal) + and isStateActive(system.Behaviour.Idle) + )) + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/autonomous_driving.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/autonomous_driving.sysml new file mode 100644 index 00000000..800ad1db --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/autonomous_driving.sysml @@ -0,0 +1,366 @@ +item def EngageAutonomous; +item def DisengageAutonomous; +item def PowerOff; +item def DetectHighway; +item def DetectUrban; +item def FrontObstacle; +item def FrontClear; +item def RearObstacle; +item def RearClear; +item def PedestrianDetected; +item def PedestrianClear; +item def AllClear; +item def NearExit; +item def IntersectionDetected; +item def Proceed; + +port def EnvironmentPort { + in item engageAutonomous : EngageAutonomous; + in item disengageAutonomous : DisengageAutonomous; + in item powerOff : PowerOff; + in item detectHighway : DetectHighway; + in item detectUrban : DetectUrban; + in item frontObstacle : FrontObstacle; + in item frontClear : FrontClear; + in item rearObstacle : RearObstacle; + in item rearClear : RearClear; + in item pedestrianDetected : PedestrianDetected; + in item pedestrianClear : PedestrianClear; + in item allClear : AllClear; + in item nearExit : NearExit; + in item intersectionDetected : IntersectionDetected; + in item proceed : Proceed; +} + +part def AutonomousVehicle { + port environment: EnvironmentPort; + + exhibit state Behaviour { + state HumanMode; + + state AutonomousMode parallel { + state AutonomousDriving { + state Initialize; + + state HighwayDriving { + state EnterHighway; + state Cruise; + state LaneChange; + state ExitHighway; + + transition first start then EnterHighway; + + transition first EnterHighway + accept : Proceed via environment + then Cruise; + + transition first Cruise + accept : FrontObstacle via environment + then LaneChange; + + transition first EnterHighway + accept : FrontObstacle via environment + then LaneChange; + + transition first LaneChange + accept : Proceed via environment + then Cruise; + + transition first LaneChange + accept : NearExit via environment + then ExitHighway; + + transition first Cruise + accept : NearExit via environment + then ExitHighway; + } + + state UrbanDriving { + state EnterUrban; + state Straight; + state Intersection; + state UrbanLaneChange; + state ExitUrban; + + transition first start then EnterUrban; + + transition first EnterUrban + accept : Proceed via environment + then Straight; + + transition first EnterUrban + accept : IntersectionDetected via environment + then Intersection; + + transition first Straight + accept : IntersectionDetected via environment + then Intersection; + + transition first Intersection + accept : Proceed via environment + then Straight; + + transition first Straight + accept : FrontObstacle via environment + then UrbanLaneChange; + + transition first EnterUrban + accept : FrontObstacle via environment + then UrbanLaneChange; + + transition first UrbanLaneChange + accept : Proceed via environment + then Straight; + + transition first UrbanLaneChange + accept : NearExit via environment + then ExitUrban; + + transition first Straight + accept : NearExit via environment + then ExitUrban; + } + + state Finish; + + transition first start then Initialize; + + transition first Initialize + accept : DetectHighway via environment + then HighwayDriving; + + transition first Initialize + accept : DetectUrban via environment + then UrbanDriving; + + transition first HighwayDriving + accept : PowerOff via environment + then Finish; + + transition first UrbanDriving + accept : PowerOff via environment + then Finish; + + transition first HighwayDriving + accept : DetectHighway via environment + then HighwayDriving; + + transition first UrbanDriving + accept : DetectUrban via environment + then UrbanDriving; + } + + state ObstacleDetection { + state CollisionAvoidanceDeactive; + + state CollisionAvoidanceActive { + state CollisionAvoidance parallel { + state Frontend { + state FrontInactive; + state AvoidFrontendCollision; + + transition first start then FrontInactive; + + transition first FrontInactive + accept : FrontObstacle via environment + then AvoidFrontendCollision; + + transition first AvoidFrontendCollision + accept : FrontClear via environment + then FrontInactive; + } + + state Rearend { + state RearInactive; + state AvoidRearendCollision; + + transition first start then RearInactive; + + transition first RearInactive + accept : RearObstacle via environment + then AvoidRearendCollision; + + transition first AvoidRearendCollision + accept : RearClear via environment + then RearInactive; + } + + state Pedestrian { + state PedestrianInactive; + state AvoidPedestrianCollision; + + transition first start then PedestrianInactive; + + transition first PedestrianInactive + accept : PedestrianDetected via environment + then AvoidPedestrianCollision; + + transition first AvoidPedestrianCollision + accept : PedestrianClear via environment + then PedestrianInactive; + } + } + + state CollisionAvoidanceDone; + + transition first start then CollisionAvoidance; + + transition first CollisionAvoidance + accept : AllClear via environment + then CollisionAvoidanceDone; + } + + transition first start then CollisionAvoidanceDeactive; + + transition first CollisionAvoidanceDeactive + accept : FrontObstacle via environment + then CollisionAvoidanceActive; + + transition first CollisionAvoidanceDeactive + accept : RearObstacle via environment + then CollisionAvoidanceActive; + + transition first CollisionAvoidanceDeactive + accept : PedestrianDetected via environment + then CollisionAvoidanceActive; + + transition first CollisionAvoidanceActive + accept : AllClear via environment + then CollisionAvoidanceDeactive; + } + } + + state Done; + + transition first start then HumanMode; + + transition first HumanMode + accept : EngageAutonomous via environment + then AutonomousMode; + + transition first AutonomousMode + accept : DisengageAutonomous via environment + then HumanMode; + + transition first HumanMode + accept : PowerOff via environment + then Done; + + transition first AutonomousMode + accept : PowerOff via environment + then Done; + } +} + +verification def HumanModeReachable { + subject system : AutonomousVehicle; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.HumanMode) + ) + } + } + } +} + +verification def AutonomousModeReachable { + subject system : AutonomousVehicle; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.AutonomousMode) + ) + } + } + } +} + +verification def CruiseReachable { + subject system : AutonomousVehicle; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.AutonomousMode.AutonomousDriving.HighwayDriving.Cruise) + ) + } + } + } +} + +verification def IntersectionReachable { + subject system : AutonomousVehicle; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.AutonomousMode.AutonomousDriving.UrbanDriving.Intersection) + ) + } + } + } +} + +verification def CollisionAvoidanceActiveReachable { + subject system : AutonomousVehicle; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.AutonomousMode.ObstacleDetection.CollisionAvoidanceActive) + ) + } + } + } +} + +verification def AvoidFrontendCollisionReachable { + subject system : AutonomousVehicle; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.AutonomousMode.ObstacleDetection.CollisionAvoidanceActive.CollisionAvoidance.Frontend.AvoidFrontendCollision) + ) + } + } + } +} + +verification def DoneReachable { + subject system : AutonomousVehicle; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.Done) + ) + } + } + } +} + +verification def HumanModeAndDoneNeverSimultaneous { + subject system : AutonomousVehicle; + + objective { + verify requirement { + require constraint { + mustAlways(not( + isStateActive(system.Behaviour.HumanMode) + and isStateActive(system.Behaviour.Done) + )) + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/door_access.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/door_access.sysml new file mode 100644 index 00000000..ded26804 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/door_access.sysml @@ -0,0 +1,133 @@ +private import ScalarValues::Integer; + +item def BadgeScanned; +item def AccessGranted; +item def DoorOpened; +item def DoorClosed; + +port def AccessPort { + in item badge : BadgeScanned; + in item grant : AccessGranted; + in item opened : DoorOpened; + in item closed : DoorClosed; +} + +part def AccessController { + attribute step: Integer default 0; + port accessPort: AccessPort; + + exhibit state Behaviour { + state Locked; + state Checking; + state Unlocked; + state Open; + + transition first start then Locked; + + transition first Locked + accept : BadgeScanned via accessPort + do action { assign step := 1; } + then Checking; + + transition first Checking + accept : AccessGranted via accessPort + do action { assign step := 2; } + then Unlocked; + + transition first Unlocked + accept : DoorOpened via accessPort + do action { assign step := 3; } + then Open; + + transition first Open + accept : DoorClosed via accessPort + do action { assign step := 4; } + then Locked; + } +} + +verification def LockedReachable { + subject system : AccessController; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.Locked) + ) + } + } + } +} + +verification def CheckingReachable { + subject system : AccessController; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.Checking) + ) + } + } + } +} + +verification def UnlockedReachable { + subject system : AccessController; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.Unlocked) + ) + } + } + } +} + +verification def OpenReachable { + subject system : AccessController; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.Open) + ) + } + } + } +} + +verification def LockedAndCheckingNeverSimultaneous { + subject system : AccessController; + + objective { + verify requirement { + require constraint { + mustAlways(not( + isStateActive(system.Behaviour.Locked) + and isStateActive(system.Behaviour.Checking) + )) + } + } + } +} + +verification def UnlockedAndOpenNeverSimultaneous { + subject system : AccessController; + + objective { + verify requirement { + require constraint { + mustAlways(not( + isStateActive(system.Behaviour.Unlocked) + and isStateActive(system.Behaviour.Open) + )) + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/orion_protocol.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/orion_protocol.sysml new file mode 100644 index 00000000..b01cbdc6 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/orion_protocol.sysml @@ -0,0 +1,463 @@ +private import ScalarValues::Boolean; +private import SI::s; + +item def Operation_Call_SendData; +item def Operation_Call_Invalid; +item def OrionDisconn; +item def OrionDisconnCause; +item def OrionConnReq; +item def OrionAppData; +item def OrionKeepAlive; +item def OrionConnConf; +item def OrionConnResp; +item def Operation_Call_Connect; +item def Operation_Call_Disconn; + +port def Block_Interface_ForOrion { + out item operation_Call_SendData : Operation_Call_SendData; + out item operation_Call_Invalid : Operation_Call_Invalid; +} + +port def StateMachine_Interface_For_Orion { + out item orionDisconn : OrionDisconn; + out item orionDisconnCause : OrionDisconnCause; + out item orionConnReq : OrionConnReq; + out item orionAppData : OrionAppData; + out item orionKeepAlive : OrionKeepAlive; + out item orionConnConf : OrionConnConf; + out item orionConnResp : OrionConnResp; +} + +port def Connection_Interface_For_Orion { + out item operation_Call_Connect : Operation_Call_Connect; + out item operation_Call_Disconn : Operation_Call_Disconn; +} + +part def Orion_Master_SM { + port Block_Port: ~Block_Interface_ForOrion; + port Connection_Port: ~Connection_Interface_For_Orion; + port StateMachine_Port: ~StateMachine_Interface_For_Orion; + port Send_StateMachine_Port: StateMachine_Interface_For_Orion; + port Process_StateMachine_Port: StateMachine_Interface_For_Orion; + + attribute is_Connected: Boolean default false; + + exhibit state Behaviour { + state Closed; + state Connecting; + + state Connected parallel { + entry action { assign is_Connected := true; } + exit action { assign is_Connected := false; } + + state Region1 { + state KeepAliveSendTimeout; + + transition first start then KeepAliveSendTimeout; + + transition first KeepAliveSendTimeout + accept after 4 [s] + do action { + send OrionKeepAlive() via Send_StateMachine_Port; + } + then KeepAliveSendTimeout; + + transition first KeepAliveSendTimeout + accept : Operation_Call_SendData via Block_Port + do action { + send OrionAppData() via Send_StateMachine_Port; + } + then KeepAliveSendTimeout; + } + + state Region2 { + state KeepAliveReceiveTimeout; + + transition first start then KeepAliveReceiveTimeout; + + transition first KeepAliveReceiveTimeout + accept after 5 [s] + then MasterMerge; + + transition first KeepAliveReceiveTimeout + accept : OrionAppData via StateMachine_Port + do action { + send OrionAppData() via Process_StateMachine_Port; + } + then KeepAliveReceiveTimeout; + + transition first KeepAliveReceiveTimeout + accept : OrionKeepAlive via StateMachine_Port + then KeepAliveReceiveTimeout; + } + } + + state MasterMerge; + state MasterMerge2; + + transition first start then Closed; + + // From Closed + transition first Closed + accept after 5 [s] + do action { + send OrionConnReq() via Send_StateMachine_Port; + } + then Connecting; + + transition first Closed + accept : Operation_Call_Connect via Connection_Port + do action { + send OrionConnReq() via Send_StateMachine_Port; + } + then Connecting; + + // From Connecting + transition first Connecting + accept : OrionConnResp via StateMachine_Port + do action { + send OrionConnConf() via Send_StateMachine_Port; + } + then Connected; + + transition first Connecting + accept after 5 [s] + then MasterMerge2; + + transition first Connecting + accept : OrionDisconnCause via StateMachine_Port + then Closed; + + transition first Connecting + accept : Operation_Call_Invalid via Block_Port + then MasterMerge2; + + transition first Connecting + accept : OrionConnConf via StateMachine_Port + then MasterMerge2; + + transition first Connecting + accept : OrionKeepAlive via StateMachine_Port + then MasterMerge2; + + transition first Connecting + accept : OrionAppData via StateMachine_Port + then MasterMerge2; + + transition first Connecting + accept : OrionConnReq via StateMachine_Port + then MasterMerge2; + + // From Connected + transition first Connected + accept : Operation_Call_Disconn via Connection_Port + then MasterMerge; + + transition first Connected + accept : OrionConnReq via StateMachine_Port + then MasterMerge; + + transition first Connected + accept : OrionDisconnCause via StateMachine_Port + then Closed; + + transition first Connected + accept : Operation_Call_Invalid via Block_Port + then MasterMerge; + + transition first Connected + accept : OrionConnResp via StateMachine_Port + then MasterMerge; + + transition first Connected + accept : OrionConnConf via StateMachine_Port + then MasterMerge; + + // Merge junctions + transition first MasterMerge + accept when true + do action { + send OrionDisconn() via Send_StateMachine_Port; + } + then Closed; + + transition first MasterMerge2 + accept when true + do action { + send OrionDisconn() via Send_StateMachine_Port; + } + then Closed; + } +} + +part def Orion_Slave_SM { + port Block_Port: ~Block_Interface_ForOrion; + port Connection_Port: ~Connection_Interface_For_Orion; + port StateMachine_Port: ~StateMachine_Interface_For_Orion; + port Send_StateMachine_Port: StateMachine_Interface_For_Orion; + port Process_StateMachine_Port: StateMachine_Interface_For_Orion; + port Handle_StateMachine_Port: StateMachine_Interface_For_Orion; + + exhibit state Behaviour { + state Closed; + state Connecting; + + state Connected parallel { + state Region1 { + state KeepAliveSendTimeout; + + transition first start then KeepAliveSendTimeout; + + transition first KeepAliveSendTimeout + accept after 4 [s] + do action { + send OrionKeepAlive() via Send_StateMachine_Port; + } + then KeepAliveSendTimeout; + + transition first KeepAliveSendTimeout + accept : Operation_Call_SendData via Block_Port + do action { + send OrionAppData() via Send_StateMachine_Port; + } + then KeepAliveSendTimeout; + } + + state Region2 { + state KeepAliveReceiveTimeout; + + transition first start then KeepAliveReceiveTimeout; + + transition first KeepAliveReceiveTimeout + accept after 5 [s] + then SlaveMerge; + + transition first KeepAliveReceiveTimeout + accept : OrionAppData via StateMachine_Port + do action { + send OrionAppData() via Process_StateMachine_Port; + } + then KeepAliveReceiveTimeout; + + transition first KeepAliveReceiveTimeout + accept : OrionKeepAlive via StateMachine_Port + then KeepAliveReceiveTimeout; + } + } + + state SlaveMerge; + state SlaveMerge2; + + transition first start then Closed; + + // From Closed + transition first Closed + accept : OrionConnReq via StateMachine_Port + do action { + send OrionConnResp() via Send_StateMachine_Port; + } + then Connecting; + + // From Connecting + transition first Connecting + accept : OrionConnConf via StateMachine_Port + do action { + send OrionConnConf() via Handle_StateMachine_Port; + } + then Connected; + + transition first Connecting + accept after 5 [s] + then SlaveMerge2; + + transition first Connecting + accept : OrionDisconnCause via StateMachine_Port + then Closed; + + transition first Connecting + accept : OrionConnResp via StateMachine_Port + then SlaveMerge2; + + transition first Connecting + accept : OrionConnReq via StateMachine_Port + then SlaveMerge2; + + transition first Connecting + accept : OrionAppData via StateMachine_Port + then SlaveMerge2; + + transition first Connecting + accept : Operation_Call_Invalid via Block_Port + then SlaveMerge2; + + transition first Connecting + accept : OrionKeepAlive via StateMachine_Port + then SlaveMerge2; + + // From Connected + transition first Connected + accept : Operation_Call_Invalid via Block_Port + then SlaveMerge; + + transition first Connected + accept : OrionConnResp via StateMachine_Port + then SlaveMerge; + + transition first Connected + accept : OrionConnReq via StateMachine_Port + then SlaveMerge; + + transition first Connected + accept : OrionConnConf via StateMachine_Port + then SlaveMerge; + + transition first Connected + accept : OrionDisconnCause via StateMachine_Port + then Closed; + + transition first Connected + accept : Operation_Call_Disconn via Connection_Port + then SlaveMerge; + + // Merge junctions + transition first SlaveMerge + accept when true + do action { + send OrionDisconn() via Send_StateMachine_Port; + } + then Closed; + + transition first SlaveMerge2 + accept when true + do action { + send OrionDisconn() via Send_StateMachine_Port; + } + then Closed; + } +} + +part def OrionSystem { + port Connection_Port: ~Connection_Interface_For_Orion; + + part master: Orion_Master_SM; + part slave: Orion_Slave_SM; + + bind Connection_Port = master.Connection_Port; + + flow from master.Send_StateMachine_Port to slave.StateMachine_Port; + flow from slave.Send_StateMachine_Port to master.StateMachine_Port; +} + +verification def MasterClosedReachable { + subject system : OrionSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.master.Behaviour.Closed) + ) + } + } + } +} + +verification def MasterConnectingReachable { + subject system : OrionSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.master.Behaviour.Connecting) + ) + } + } + } +} + +verification def MasterConnectedReachable { + subject system : OrionSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.master.Behaviour.Connected) + ) + } + } + } +} + +verification def SlaveClosedReachable { + subject system : OrionSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.slave.Behaviour.Closed) + ) + } + } + } +} + +verification def SlaveConnectedReachable { + subject system : OrionSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.slave.Behaviour.Connected) + ) + } + } + } +} + +verification def MasterConnectedAndClosedNeverSimultaneous { + subject system : OrionSystem; + + objective { + verify requirement { + require constraint { + mustAlways(not( + isStateActive(system.master.Behaviour.Connected) + and isStateActive(system.master.Behaviour.Closed) + )) + } + } + } +} + +verification def BothMasterAndSlaveConnectedReachable { + subject system : OrionSystem; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.master.Behaviour.Connected) + and isStateActive(system.slave.Behaviour.Connected) + ) + } + } + } +} + +verification def MasterIsConnectedReachable { + subject system : OrionSystem; + + objective { + verify requirement { + require constraint { + eventually( + system.master.is_Connected + ) + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/power_subsystems.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/power_subsystems.sysml new file mode 100644 index 00000000..bcb89767 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/power_subsystems.sysml @@ -0,0 +1,135 @@ +private import ScalarValues::Integer; + +item def BatteryLowAlert; + +port def PowerPort { + in item batteryLow : BatteryLowAlert; +} + +part def PowerManager { + attribute batteryLevel: Integer default 100; + port powerPort: PowerPort; + + exhibit state Behaviour { + state On { + entry action { + assign batteryLevel := batteryLevel - 1; + } + } + state LowPower { + entry action { + assign batteryLevel := batteryLevel - 1; + } + } + state Off; + + transition first start then On; + + transition first On + accept : BatteryLowAlert via powerPort + if batteryLevel < 20 + then LowPower; + + transition first On + accept : BatteryLowAlert via powerPort + if batteryLevel >= 20 + then On; + + transition first LowPower + accept : BatteryLowAlert via powerPort + if batteryLevel < 5 + then Off; + + transition first LowPower + accept : BatteryLowAlert via powerPort + if batteryLevel >= 5 + then LowPower; + } +} + +verification def OnReachable { + subject system : PowerManager; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.On) + ) + } + } + } +} + +verification def LowPowerReachable { + subject system : PowerManager; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.LowPower) + ) + } + } + } +} + +verification def OffReachable { + subject system : PowerManager; + + objective { + verify requirement { + require constraint { + eventually( + isStateActive(system.Behaviour.Off) + ) + } + } + } +} + +verification def OnAndLowPowerNeverSimultaneous { + subject system : PowerManager; + + objective { + verify requirement { + require constraint { + mustAlways(not( + isStateActive(system.Behaviour.On) + and isStateActive(system.Behaviour.LowPower) + )) + } + } + } +} + +verification def OnAndOffNeverSimultaneous { + subject system : PowerManager; + + objective { + verify requirement { + require constraint { + mustAlways(not( + isStateActive(system.Behaviour.On) + and isStateActive(system.Behaviour.Off) + )) + } + } + } +} + +verification def LowPowerAndOffNeverSimultaneous { + subject system : PowerManager; + + objective { + verify requirement { + require constraint { + mustAlways(not( + isStateActive(system.Behaviour.LowPower) + and isStateActive(system.Behaviour.Off) + )) + } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/semanticstest.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/semanticstest.sysml index f68dd13a..d40ee897 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/semanticstest.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/semanticstest.sysml @@ -27,7 +27,7 @@ part def EntryActionModel { } } -verification def EntryActionModelEntered { +verification def EntryActionFiresOnActivationTestCase { subject system : EntryActionModel; objective { verify requirement { @@ -36,6 +36,16 @@ verification def EntryActionModelEntered { } } +// Entry flag must already be set whenever S1 is the active state. +verification def EntryFlagAlwaysSetWhileStateIsActiveTestCase { + subject system : EntryActionModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.S1) and system.entered == false)) } + } + } +} + // ── 2. ExitAction ──────────────────────────────────────────────────────────── // Verifies that a state's exit action fires when the state is left. @@ -53,7 +63,7 @@ part def ExitActionModel { } } -verification def ExitActionExited { +verification def ExitActionFiresOnDeactivationTestCase { subject system : ExitActionModel; objective { verify requirement { @@ -62,6 +72,16 @@ verification def ExitActionExited { } } +// S2 can only be active if S1's exit action already fired. +verification def ExitFlagAlwaysSetWhenSuccessorIsActiveTestCase { + subject system : ExitActionModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.S2) and system.exited == false)) } + } + } +} + // ── 3. TransitionDoActionModel ──────────────────────────────────────────────────── // Verifies that a transition's do-action fires when the transition is taken. @@ -81,7 +101,7 @@ part def TransitionDoActionModel { } } -verification def TransitionDoActionModelFired { +verification def DoActionFiresOnTransitionTestCase { subject system : TransitionDoActionModel; objective { verify requirement { @@ -90,6 +110,16 @@ verification def TransitionDoActionModelFired { } } +// S2 can only be active if the do-action on the transition already fired. +verification def DoActionAlwaysFiredWhenTargetIsActiveTestCase { + subject system : TransitionDoActionModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.S2) and system.actionFired == false)) } + } + } +} + // ── 4. HierarchicalEntryModel ───────────────────────────────────────────────────── // Verifies that entering a composite state activates its initial substate. @@ -103,7 +133,7 @@ part def HierarchicalEntryModel { } } -verification def HierarchicalEntryModelInner { +verification def CompositeEntryActivatesInitialSubstateTestCase { subject system : HierarchicalEntryModel; objective { verify requirement { @@ -112,6 +142,16 @@ verification def HierarchicalEntryModelInner { } } +// A composite state being active implies its active substate is also active. +verification def CompositeActiveAlwaysImpliesSubstateActiveTestCase { + subject system : HierarchicalEntryModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.Outer) and not isStateActive(system.Behaviour.Outer.Inner))) } + } + } +} + // ── 5. HierarchicalExitModel ────────────────────────────────────────────────────── // Verifies that a transition from a composite state fires the state's exit action // and reaches the target state, even when the active inner state has no own transitions. @@ -132,7 +172,7 @@ part def HierarchicalExitModel { } } -verification def HierarchicalExitModelDone { +verification def CompositeExitReachesDoneStateTestCase { subject system : HierarchicalExitModel; objective { verify requirement { @@ -141,7 +181,7 @@ verification def HierarchicalExitModelDone { } } -verification def HierarchicalExitModelExited { +verification def CompositeExitFiresExitActionTestCase { subject system : HierarchicalExitModel; objective { verify requirement { @@ -150,6 +190,16 @@ verification def HierarchicalExitModelExited { } } +// Done can only be active if the composite exit action already fired. +verification def ExitActionAlwaysFiredWhenDoneIsActiveTestCase { + subject system : HierarchicalExitModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.Done) and system.outerExited == false)) } + } + } +} + // ── 6. TransitionPriorityModel ──────────────────────────────────────────────────── // Verifies bottom-up (inner-first) transition priority: when both an inner // transition and an enclosing transition accept the same event, the inner one fires. @@ -181,7 +231,7 @@ part def TransitionPriorityModel { } // Inner transition fires first (from Inner, E takes Inner→InnerDone). -verification def TransitionPriorityModelInnerFires { +verification def TransitionsHaveBottomUpPriorityTestCase { subject system : TransitionPriorityModel; objective { verify requirement { @@ -191,7 +241,7 @@ verification def TransitionPriorityModelInnerFires { } // Inner→InnerDone is reachable (would not be so under top-down priority). -verification def TransitionPriorityModelInnerDoneReachable { +verification def InnerDoneReachableWithBottomUpPriorityTestCase { subject system : TransitionPriorityModel; objective { verify requirement { @@ -201,7 +251,7 @@ verification def TransitionPriorityModelInnerDoneReachable { } // Once InnerDone is active (no inner transition on E), the outer transition fires. -verification def TransitionPriorityModelOuterFires { +verification def OuterTransitionFiresAfterInnerExhaustedTestCase { subject system : TransitionPriorityModel; objective { verify requirement { @@ -211,7 +261,7 @@ verification def TransitionPriorityModelOuterFires { } // Safety: the outer transition never fires while Inner is the active inner state. -verification def TransitionPriorityModelBottomUpSafety { +verification def OuterTransitionBlockedWhileInnerEnabledTestCase { subject system : TransitionPriorityModel; objective { verify requirement { @@ -225,6 +275,16 @@ verification def TransitionPriorityModelBottomUpSafety { } } +// OuterDone can only be reached after the inner transition exhausted first. +verification def OuterDoneAlwaysImpliesInnerFiredFirstTestCase { + subject system : TransitionPriorityModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.OuterDone) and system.innerFired == false)) } + } + } +} + // ── 7. ParallelRegionsModel ─────────────────────────────────────────────────────── // Verifies that two concurrent regions execute independently and can both advance. @@ -247,7 +307,7 @@ part def ParallelRegionsModel { } } -verification def ParallelRegionsModelR1B { +verification def FirstParallelRegionAdvancesIndependentlyTestCase { subject system : ParallelRegionsModel; objective { verify requirement { @@ -256,7 +316,7 @@ verification def ParallelRegionsModelR1B { } } -verification def ParallelRegionsModelR2D { +verification def SecondParallelRegionAdvancesIndependentlyTestCase { subject system : ParallelRegionsModel; objective { verify requirement { @@ -265,7 +325,7 @@ verification def ParallelRegionsModelR2D { } } -verification def ParallelRegionsModelBothAdvanced { +verification def BothParallelRegionsCanAdvanceSimultaneouslyTestCase { subject system : ParallelRegionsModel; objective { verify requirement { @@ -279,6 +339,16 @@ verification def ParallelRegionsModelBothAdvanced { } } +// Substates within a single region are mutually exclusive. +verification def RegionSubstatesAreMutuallyExclusiveTestCase { + subject system : ParallelRegionsModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.R1.A) and isStateActive(system.Behaviour.R1.B))) } + } + } +} + // ── 8. TimeoutTransitionModel ───────────────────────────────────────────────────── // Verifies that an AcceptTimeoutAction triggers after the specified number of time steps. @@ -291,7 +361,7 @@ part def TimeoutTransitionModel { } } -verification def TimeoutTransitionModelDone { +verification def TimeoutTransitionFiresAfterDelayTestCase { subject system : TimeoutTransitionModel; objective { verify requirement { @@ -300,6 +370,16 @@ verification def TimeoutTransitionModelDone { } } +// Waiting and Done are mutually exclusive — the system cannot be in both simultaneously. +verification def WaitingAndDoneAreMutuallyExclusiveTestCase { + subject system : TimeoutTransitionModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.Waiting) and isStateActive(system.Behaviour.Done))) } + } + } +} + // ── 9. GuardedTransitionModel ───────────────────────────────────────────────────── // Verifies that integer guards correctly control which transition fires. // Uses a self-transition loop to increment a counter until the exit guard is satisfied. @@ -323,7 +403,7 @@ part def GuardedTransitionModel { } } -verification def GuardedTransitionModelDone { +verification def GuardConditionGatesTransitionTestCase { subject system : GuardedTransitionModel; objective { verify requirement { @@ -332,7 +412,7 @@ verification def GuardedTransitionModelDone { } } -verification def GuardedTransitionModelCount { +verification def GuardAccumulatesCounterTestCase { subject system : GuardedTransitionModel; objective { verify requirement { @@ -341,6 +421,16 @@ verification def GuardedTransitionModelCount { } } +// Done is unreachable until the guard (counter >= 3) is satisfied. +verification def DoneNotReachableBeforeGuardSatisfiedTestCase { + subject system : GuardedTransitionModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.Done) and system.counter < 3)) } + } + } +} + // ── 10. ItemFlow ───────────────────────────────────────────────────────────── // Verifies that an item sent by one sub-part is delivered to another via a flow. @@ -376,7 +466,7 @@ part def ItemFlowModel { flow from sender.output to receiver.input; } -verification def ItemFlowReceived { +verification def ItemFlowDeliversToReceiverTestCase { subject system : ItemFlowModel; objective { verify requirement { @@ -385,7 +475,7 @@ verification def ItemFlowReceived { } } -verification def ItemFlowAttribute { +verification def ReceiverAttributeSetByItemFlowTestCase { subject system : ItemFlowModel; objective { verify requirement { @@ -394,6 +484,16 @@ verification def ItemFlowAttribute { } } +// The received flag must already be set whenever Got is the active state. +verification def ReceivedFlagAlwaysSetWhenGotIsActiveTestCase { + subject system : ItemFlowModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.receiver.Behaviour.Got) and system.receiver.received == false)) } + } + } +} + // ── 11. CrossHierarchyTransitionModel ───────────────────────────────────────────── // Active configuration Outer.Middle.Inner → Other.Deep. // Transition is from the outer boundary (Outer), so exit walks all three levels @@ -431,7 +531,7 @@ part def CrossHierarchyTransitionModel { } // Three-level deep initial state is reachable (active config before transition). -verification def CrossHierarchyInitialDeep { +verification def ThreeLevelDeepInitialStateReachableTestCase { subject system : CrossHierarchyTransitionModel; objective { verify requirement { @@ -441,7 +541,7 @@ verification def CrossHierarchyInitialDeep { } // After the cross-hierarchy transition, the two-level deep target is active. -verification def CrossHierarchyTargetDeep { +verification def CrossHierarchyTransitionReachesTwoLevelDeepStateTestCase { subject system : CrossHierarchyTransitionModel; objective { verify requirement { @@ -451,7 +551,7 @@ verification def CrossHierarchyTargetDeep { } // Both exit actions along the departure chain (Middle, Outer) fire. -verification def CrossHierarchyExitChain { +verification def CrossHierarchyExitActionsFireAtAllLevelsTestCase { subject system : CrossHierarchyTransitionModel; objective { verify requirement { @@ -463,7 +563,7 @@ verification def CrossHierarchyExitChain { } // Both entry actions along the arrival chain (Other, Deep) fire. -verification def CrossHierarchyEntryChain { +verification def CrossHierarchyEntryActionsFireAtAllLevelsTestCase { subject system : CrossHierarchyTransitionModel; objective { verify requirement { @@ -474,6 +574,16 @@ verification def CrossHierarchyEntryChain { } } +// Outer and Other are mutually exclusive — the cross-hierarchy transition is atomic. +verification def OuterAndOtherAreMutuallyExclusiveTestCase { + subject system : CrossHierarchyTransitionModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.Outer) and isStateActive(system.Behaviour.Other))) } + } + } +} + // ── 12. ExitActionOrderModel ────────────────────────────────────────────────────── // When leaving a 3-level hierarchy, exit actions fire innermost-first. // Each exit action captures the current value of a step counter, then increments it. @@ -507,7 +617,7 @@ part def ExitActionOrderModel { } } -verification def ExitActionOrderModelInnerBeforeMiddle { +verification def InnerExitActionFiresBeforeMiddleExitActionTestCase { subject system : ExitActionOrderModel; objective { verify requirement { @@ -516,7 +626,7 @@ verification def ExitActionOrderModelInnerBeforeMiddle { } } -verification def ExitActionOrderModelMiddleBeforeOuter { +verification def MiddleExitActionFiresBeforeOuterExitActionTestCase { subject system : ExitActionOrderModel; objective { verify requirement { @@ -525,6 +635,26 @@ verification def ExitActionOrderModelMiddleBeforeOuter { } } +// Middle never exits before inner (outermost-first order is always wrong). +verification def MiddleNeverExitsBeforeInnerTestCase { + subject system : ExitActionOrderModel; + objective { + verify requirement { + require constraint { mustAlways(not (system.middleExitStep < system.innerExitStep)) } + } + } +} + +// Outer never exits before middle. +verification def OuterNeverExitsBeforeMiddleTestCase { + subject system : ExitActionOrderModel; + objective { + verify requirement { + require constraint { mustAlways(not (system.outerExitStep < system.middleExitStep)) } + } + } +} + // ── 13. EntryActionOrderModel ───────────────────────────────────────────────────── // When entering a 3-level hierarchy, entry actions fire outermost-first. // Implementation detail: State.enter() calls enterRecursive(), which recurses UP @@ -556,7 +686,7 @@ part def EntryActionOrderModel { } } -verification def EntryActionOrderModelTargetBeforeMiddle { +verification def OutermostEntryActionFiresBeforeMiddleEntryActionTestCase { subject system : EntryActionOrderModel; objective { verify requirement { @@ -565,7 +695,7 @@ verification def EntryActionOrderModelTargetBeforeMiddle { } } -verification def EntryActionOrderModelMiddleBeforeInner { +verification def MiddleEntryActionFiresBeforeInnermostEntryActionTestCase { subject system : EntryActionOrderModel; objective { verify requirement { @@ -574,6 +704,26 @@ verification def EntryActionOrderModelMiddleBeforeInner { } } +// Middle never enters before target (innermost-first order is always wrong). +verification def MiddleNeverEntersBeforeTargetTestCase { + subject system : EntryActionOrderModel; + objective { + verify requirement { + require constraint { mustAlways(not (system.middleEntryStep < system.targetEntryStep)) } + } + } +} + +// Inner never enters before middle. +verification def InnerNeverEntersBeforeMiddleTestCase { + subject system : EntryActionOrderModel; + objective { + verify requirement { + require constraint { mustAlways(not (system.innerEntryStep < system.middleEntryStep)) } + } + } +} + // ── 14. ParallelStateExitModel ──────────────────────────────────────────────────── // Exiting a parallel state must deactivate ALL concurrent regions. // Implementation detail: ParallelState.exit() calls deactivateRecursive(false) which @@ -600,7 +750,7 @@ part def ParallelStateExitModel { } // Both regions are concurrently active before the exit transition. -verification def ParallelStateExitModelBothActive { +verification def BothParallelRegionsActiveBeforeExitTestCase { subject system : ParallelStateExitModel; objective { verify requirement { @@ -615,7 +765,7 @@ verification def ParallelStateExitModelBothActive { } // Done is reachable (parallel state can be exited). -verification def ParallelStateExitModelDone { +verification def ParallelStateCanBeExitedTestCase { subject system : ParallelStateExitModel; objective { verify requirement { @@ -625,7 +775,7 @@ verification def ParallelStateExitModelDone { } // After exiting the parallel state, neither region is active (safety). -verification def ParallelStateExitModelR1Deactivated { +verification def AllParallelRegionsDeactivatedOnExitTestCase { subject system : ParallelStateExitModel; objective { verify requirement { @@ -668,7 +818,7 @@ part def ParallelNestedInSequentialModel { } // Both parallel sub-regions are active while inside the sequential Outer state. -verification def ParallelNestedBothActive { +verification def ParallelRegionsActiveInsideSequentialStateTestCase { subject system : ParallelNestedInSequentialModel; objective { verify requirement { @@ -683,7 +833,7 @@ verification def ParallelNestedBothActive { } // The sequential state can be exited even when a parallel state is active inside. -verification def ParallelNestedExitDone { +verification def SequentialStateWithNestedParallelExitableTestCase { subject system : ParallelNestedInSequentialModel; objective { verify requirement { @@ -691,3 +841,117 @@ verification def ParallelNestedExitDone { } } } + +// Done and the nested parallel substates are mutually exclusive — all regions are deactivated on exit. +verification def DoneAndNestedParallelSubstatesAreMutuallyExclusiveTestCase { + subject system : ParallelNestedInSequentialModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.Done) and isStateActive(system.Behaviour.Outer.Inner.P1.P1A))) } + } + } +} + +// ── 16. SpontaneousTransitionModel ─────────────────────────────────────────────── +// Verifies that an `accept when true` (unconditional spontaneous transition) +// fires without any external event or timeout, executing its do-action. + +part def SpontaneousTransitionModel { + attribute transitioned : Boolean default false; + + exhibit state Behaviour { + state S1; + state S2; + transition first start then S1; + transition + first S1 + accept when true + do action { assign transitioned := true; } + then S2; + } +} + +// The spontaneous transition fires, reaching S2 without any external stimulus. +verification def SpontaneousTransitionReachesTargetTestCase { + subject system : SpontaneousTransitionModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.S2)) } + } + } +} + +// The do-action on the spontaneous transition fires. +verification def SpontaneousTransitionDoActionFiresTestCase { + subject system : SpontaneousTransitionModel; + objective { + verify requirement { + require constraint { eventually(system.transitioned == true) } + } + } +} + +// S2 can only be active if the do-action on the spontaneous transition already fired. +verification def SpontaneousDoActionAlwaysFiredWhenTargetIsActiveTestCase { + subject system : SpontaneousTransitionModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.S2) and system.transitioned == false)) } + } + } +} + +// ── 17. GuardedSpontaneousTransitionModel ──────────────────────────────────────── +// Verifies that `accept when ` (guarded spontaneous transition) fires +// only when its guard is satisfied, without any external event. +// A self-loop with `accept when counter < 3` increments a counter; when the +// counter reaches 3, an `accept when counter >= 3` transition exits. + +part def GuardedSpontaneousTransitionModel { + attribute counter : Integer default 0; + + exhibit state Behaviour { + state Incrementing; + state Done; + transition first start then Incrementing; + transition + first Incrementing + accept when counter < 3 + do action { assign counter := counter + 1; } + then Incrementing; + transition + first Incrementing + accept when counter >= 3 + then Done; + } +} + +// The guarded spontaneous exit transition eventually fires. +verification def GuardedSpontaneousTransitionReachesDoneTestCase { + subject system : GuardedSpontaneousTransitionModel; + objective { + verify requirement { + require constraint { eventually(isStateActive(system.Behaviour.Done)) } + } + } +} + +// The counter accumulates to the threshold. +verification def GuardedSpontaneousCounterReachesThresholdTestCase { + subject system : GuardedSpontaneousTransitionModel; + objective { + verify requirement { + require constraint { eventually(system.counter >= 3) } + } + } +} + +// Done is unreachable until the guard (counter >= 3) is satisfied. +verification def GuardedSpontaneousDoneNotReachableBeforeThresholdTestCase { + subject system : GuardedSpontaneousTransitionModel; + objective { + verify requirement { + require constraint { mustAlways(not (isStateActive(system.Behaviour.Done) and system.counter < 3)) } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index b0388df4..93ce8ac7 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -100,7 +100,41 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { fun `Full Spacecraft Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/spacecraft.sysml") - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() + } + + @JvmStatic + fun `Door Access Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/door_access.sysml") + + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() + } + + @JvmStatic + fun `Power Subsystems Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/power_subsystems.sysml") + + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() + } + + @JvmStatic + fun `Aircraft Engine Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/aircraft_engine.sysml") + + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() + } + + @JvmStatic + fun `Autonomous Driving Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/autonomous_driving.sysml") + + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() + } + + @JvmStatic + fun `Orion Protocol Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/orion_protocol.sysml") + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } @@ -155,4 +189,34 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { checkVerificationCase(verificationCase) } + @ParameterizedTest + @MethodSource + fun `Door Access Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) + } + + @ParameterizedTest + @MethodSource + fun `Power Subsystems Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) + } + + @ParameterizedTest + @MethodSource + fun `Aircraft Engine Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) + } + + @ParameterizedTest + @MethodSource + fun `Autonomous Driving Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) + } + + @ParameterizedTest + @MethodSource + fun `Orion Protocol Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) + } + } From 88e63da0dc62b08184df51066a5d793780706d60 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 18:57:52 +0200 Subject: [PATCH 102/115] Added benchmark task --- .../sysmlv2-semantics/build.gradle.kts | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts index b590950d..72c9793d 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/build.gradle.kts @@ -40,29 +40,29 @@ tasks.withType(Test::class) { dependsOn(prepareCli) } -//val benchmarkVerificationCases by tasks.registering(Test::class) { -// group = "verification" -// description = "Run each verification case N times and aggregate timing. Pass -Pbenchmark.runs=N to override (default 3)." -// -// dependsOn(prepareCli) -// -// useJUnitPlatform { -// includeTags("benchmark") -// } -// -// testClassesDirs = sourceSets.test.get().output.classesDirs -// classpath = sourceSets.test.get().runtimeClasspath -// -// minHeapSize = "512m" -// maxHeapSize = "4G" -// maxParallelForks = 1 -// testLogging.showStandardStreams = true -// testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL -// -// val thetaCliPath = project(":theta-wrapper").layout.buildDirectory.dir("theta-xsts-cli").get().asFile.absolutePath -// val existingPath = environment["PATH"] ?: System.getenv("PATH") ?: "" -// environment("PATH", "$thetaCliPath${File.pathSeparator}$existingPath") -// -// val benchmarkRuns = providers.gradleProperty("benchmark.runs").orElse("5") -// systemProperty("benchmark.runs", benchmarkRuns.get()) -//} +val benchmarkVerificationCases by tasks.registering(Test::class) { + group = "verification" + description = "Run each verification case N times and aggregate timing. Pass -Pbenchmark.runs=N to override (default 3)." + + dependsOn(prepareCli) + + useJUnitPlatform { + includeTags("benchmark") + } + + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + minHeapSize = "512m" + maxHeapSize = "4G" + maxParallelForks = 1 + testLogging.showStandardStreams = true + testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL + + val thetaCliPath = project(":theta-wrapper").layout.buildDirectory.dir("theta-xsts-cli").get().asFile.absolutePath + val existingPath = environment["PATH"] ?: System.getenv("PATH") ?: "" + environment("PATH", "$thetaCliPath${File.pathSeparator}$existingPath") + + val benchmarkRuns = providers.gradleProperty("benchmark.runs").orElse("5") + systemProperty("benchmark.runs", benchmarkRuns.get()) +} From f3534eaf0d2b8fcd7d639209d3dba9ebc7c4acd8 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 19:02:49 +0200 Subject: [PATCH 103/115] Added benchmark test --- .../semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt index b528b743..00171479 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt @@ -74,7 +74,7 @@ class SysMLBenchmarkTests : BaseSemantifyrVerificationTest() { @Inject override lateinit var oxstsVerifierProvider: Provider -// @Test + @Test fun `Benchmark Verification Cases`() { val runs = System.getProperty("benchmark.runs", "5").toInt() val rows = mutableListOf() From 470b2c88f6f94955c9c0a530365954eca58f7f17 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 21:26:19 +0200 Subject: [PATCH 104/115] Do not run benchmarks --- .../hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts | 2 ++ .../hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts index d680032b..d8cbce38 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/jvm.gradle.kts @@ -41,6 +41,8 @@ tasks { // TODO: refactor tests to use test suites test { useJUnitPlatform { + // we should use source sets instead + excludeTags("benchmark") excludeTags("verification") excludeTags("slow") } diff --git a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts index 56d38a71..762a0267 100644 --- a/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts +++ b/buildSrc/src/main/kotlin/hu/bme/mit/semantifyr/gradle/conventions/theta.gradle.kts @@ -39,6 +39,8 @@ tasks { group = "verification" useJUnitPlatform { + // we should use source sets instead + excludeTags("benchmark") includeTags("verification") excludeTags("slow") } @@ -69,6 +71,8 @@ tasks { group = "verification" useJUnitPlatform { + // we should use source sets instead + excludeTags("benchmark") // includeTags("verification") includeTags("slow") } From bd4d0593549c3a107e84bf4ae35235c085cbdddb Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 21:28:02 +0200 Subject: [PATCH 105/115] Added top-down variant --- .../TopDownLibrary/Actions.oxsts | 48 +++ .../TopDownLibrary/Attributes.oxsts | 52 +++ .../TopDownLibrary/Expressions.oxsts | 134 +++++++ .../TopDownLibrary/Items.oxsts | 9 + .../TopDownLibrary/Parts.oxsts | 101 +++++ .../TopDownLibrary/Ports.oxsts | 55 +++ .../LibraryVariants/TopDownLibrary/README.md | 18 + .../TopDownLibrary/States.oxsts | 344 ++++++++++++++++++ .../TopDownLibrary/Triggers.oxsts | 71 ++++ .../TopDownLibrary/Verification.oxsts | 40 ++ .../TestModels/topdowntransition.sysml | 73 ++++ .../sysml/semantics/SysMLVerificationTests.kt | 18 +- 12 files changed, 960 insertions(+), 3 deletions(-) create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Actions.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Attributes.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Expressions.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Items.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Parts.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Ports.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/README.md create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/States.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Triggers.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Verification.oxsts create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/topdowntransition.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Actions.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Actions.oxsts new file mode 100644 index 00000000..bab88d4c --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Actions.oxsts @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2025 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package semantifyr::sysml::actions + +import semantifyr::sysml::attributes +import semantifyr::sysml::expressions +import semantifyr::sysml::ports +import semantifyr::sysml::items + +abstract class Action + +class SendAction : Action { + refers viaPort: Port + refers payload: Item + + redefine tran { + inline viaPort.setOutgoingItem(payload) + } +} + +class AssignmentAction : Action { + refers attribute: Attribute + contains expression: Expression + redefine tran { + inline attribute.set(expression.evaluate()) + } +} + +class CompositeAction : Action { + contains children: Action[0..*] + redefine tran { + inline for (child in children) { + inline child.main() + } + } +} + +class Guard { + contains expression: Expression + + prop isOpen(): bool { + return expression.evaluate() + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Attributes.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Attributes.oxsts new file mode 100644 index 00000000..710db4e3 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Attributes.oxsts @@ -0,0 +1,52 @@ +package semantifyr::sysml::attributes + +import semantifyr::sysml::expressions + +abstract class Attribute { + abstract prop evaluate(): any + + abstract tran set(value: any) +} + +class IntegerAttribute : Attribute { + refers defaultValue: int = 0 + + var value: int := defaultValue + + redefine init { + value := defaultValue + } + + redefine prop evaluate(): int { + return value + } + + redefine tran set(value: int) { + self.value := value + } +} + +class BooleanAttribute : Attribute { + refers defaultValue: bool = false + + var value: bool := defaultValue + + redefine init { + value := defaultValue + } + + redefine prop evaluate(): bool { + return value + } + + redefine tran set(value: bool) { + self.value := value + } +} + +class AttributeReferenceExpression : Expression { + refers attribute: Attribute + redefine prop evaluate(): any { + return attribute.evaluate() + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Expressions.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Expressions.oxsts new file mode 100644 index 00000000..41d74027 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Expressions.oxsts @@ -0,0 +1,134 @@ +package semantifyr::sysml::expressions + +abstract class Expression { + abstract prop evaluate(): any +} + +abstract class LiteralExpression : Expression +class LiteralBooleanExpression : LiteralExpression { + refers value: bool[1] + redefine prop evaluate(): bool { + return value + } +} +class LiteralIntegerExpression : LiteralExpression { + refers value: int[1] + redefine prop evaluate(): int { + return value + } +} + +abstract class BinaryOperatorExpression : Expression { + contains left: Expression[1] + contains right: Expression[1] +} + +class LessThanOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): bool { + return left.evaluate() < right.evaluate() + } +} + +class LessThanOrEqualsOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): bool { + return left.evaluate() <= right.evaluate() + } +} + +class GreaterThanOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): bool { + return left.evaluate() > right.evaluate() + } +} + +class GreaterThanOrEqualsOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): bool { + return left.evaluate() >= right.evaluate() + } +} + +class PlusOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): any { + return left.evaluate() + right.evaluate() + } +} + +class MinusOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): any { + return left.evaluate() - right.evaluate() + } +} + +class MultiplicationOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): any { + return left.evaluate() * right.evaluate() + } +} + +class DivisionOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): any { + return left.evaluate() / right.evaluate() + } +} + +class EqualityOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): bool { + return left.evaluate() == right.evaluate() + } +} + +class InequalityOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): bool { + return left.evaluate() != right.evaluate() + } +} + +class OrOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): bool { + return left.evaluate() || right.evaluate() + } +} + +class AndOperatorExpression : BinaryOperatorExpression { + redefine prop evaluate(): bool { + return left.evaluate() && right.evaluate() + } +} + +abstract class UnaryOperatorExpression : Expression { + contains operand: Expression[1] +} + +class UnaryNotExpression : UnaryOperatorExpression { + redefine prop evaluate(): bool { + return !operand.evaluate() + } +} + +class UnaryPlusExpression : UnaryOperatorExpression { + redefine prop evaluate(): any { + return operand.evaluate() + } +} + +class UnaryMinusExpression : UnaryOperatorExpression { + redefine prop evaluate(): any { + return -operand.evaluate() + } +} + +abstract class TemporalOperatorExpression : Expression { + contains body: Expression[1] +} + +class Eventually : TemporalOperatorExpression { + redefine prop evaluate(): any { + return EF body.evaluate() + } +} + +class MustAlways : TemporalOperatorExpression { + redefine prop evaluate(): any { + return AG body.evaluate() + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Items.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Items.oxsts new file mode 100644 index 00000000..6d77acb5 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Items.oxsts @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2025 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package semantifyr::sysml::items + +class Item diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Parts.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Parts.oxsts new file mode 100644 index 00000000..8a44f970 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Parts.oxsts @@ -0,0 +1,101 @@ +package semantifyr::sysml::parts + +import semantifyr::sysml::attributes +import semantifyr::sysml::ports +import semantifyr::sysml::states + +class Part { + contains parts: Part[0..*] + contains attributes: Attribute[0..*] + contains ports: Port[0..*] + contains exhibitState: AbstractState[0..1] + contains flows: Flow[0..*] + + tran resetInputEvents() { + inline for (port in ports) { + inline port.resetIncomingItem() + } + } + + tran havocInputEvents() { + inline for (port in ports) { + inline port.havocIncomingItem() + } + } + + tran resetOutputEvents() { + inline for (port in ports) { + inline port.resetOutgoingItem() + } + } + + tran passTime() { + inline for (part in parts) { + inline part.passTime() + } + + inline exhibitState?.passTime() + } + + tran executeExhibitState() { + choice { + inline exhibitState?.fireTransitions() + } or { + // do nothing, if no transition is enabled + inline exhibitState?.assumeNoTransitionEnabled() + } + } + + redefine init { + inline for (attribute in attributes) { + inline attribute.init() + } + + inline exhibitState?.activateRecursive() + + inline for (part in parts) { + inline part.init() + } + } + + redefine tran { + inline resetOutputEvents() + + inline for (part in parts) { + inline part.main() + } + + inline executeExhibitState() + + inline for (flow in flows) { + inline flow.main() + } + + inline resetInputEvents() + } + + tran executeMainComponent() { + inline resetOutputEvents() + + inline for (part in parts) { + inline part.main() + } + + inline executeExhibitState() + + inline for (flow in flows) { + inline flow.main() + } + } +} + +class Flow { + refers inputPort: Port[1] + refers outputPort: Port[1] + + redefine tran { + if (inputPort.hasOutgoing()) { + inline outputPort.setIncomingItem(inputPort.outgoingItem) + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Ports.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Ports.oxsts new file mode 100644 index 00000000..f3a34892 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Ports.oxsts @@ -0,0 +1,55 @@ +package semantifyr::sysml::ports + +import semantifyr::sysml::items + +abstract class Port { + var incomingItem: Item[0..1] := nothing + var outgoingItem: Item[0..1] := nothing + + prop hasIncoming(): bool { + return incomingItem != nothing + } + + prop hasOutgoing(): bool { + return outgoingItem != nothing + } + + prop hasIncomingItem(item: Item): bool { + return incomingItem == item + } + + prop hasOutgoingItem(item: Item): bool { + return outgoingItem == item + } + + tran assumeHasIncomingItem(item: Item) { + assume (hasIncomingItem(item)) + } + + tran setIncomingItem(item: Item) { + incomingItem := item + } + + tran setOutgoingItem(item: Item) { + outgoingItem := item + } + + tran resetIncomingItem() { + incomingItem := nothing + } + + tran resetOutgoingItem() { + outgoingItem := nothing + } + + tran havocIncomingItem() { + havoc (incomingItem) + } + + tran havocOutgoingItem() { + havoc (outgoingItem) + } +} + +class NormalPort : Port +class ConjugatedPort : Port diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/README.md b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/README.md new file mode 100644 index 00000000..7705259a --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/README.md @@ -0,0 +1,18 @@ +# Top-down transition priority + +Changes compared to the Library: + +States.oxsts: + +redefine tran fireTransitions() { + choice { + // commented out + // inline assumeNoInnerTransitionEnabled() + inline fireLocalTransitions() + } or { + // added + // specifies top-down transition priority + inline assumeNoLocalTransitionEnabled() + inline fireInnerTransitions() + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/States.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/States.oxsts new file mode 100644 index 00000000..92d5ceca --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/States.oxsts @@ -0,0 +1,344 @@ +package semantifyr::sysml::states + +import semantifyr::sysml::actions +import semantifyr::sysml::triggers +import semantifyr::sysml::expressions + +abstract class StateNode { + derived refers incomingTransitions: Transition[0..*] opposite to + derived refers outgoingTransitions: Transition[0..*] opposite from + + abstract prop isActive(): bool + + abstract tran enter(commonState: StateNode) + abstract tran exit(commonState: StateNode) +} + +abstract class AbstractState : StateNode { + container parent: AbstractState[0..1] opposite states + contains states: AbstractState[0..*] opposite parent + + contains entryAction: Action[1] + contains exitAction: Action[1] + + redefine prop isActive(): bool { + return parent?.isInnerStateActive(self) + } + + abstract prop getActiveState(): AbstractState + + abstract prop isInnerStateActive(state: AbstractState): bool + + abstract tran fireTransitions() + abstract tran assumeNoTransitionEnabled() + abstract tran activateRecursive() + abstract tran deactivateRecursive(deactivate: bool) + abstract tran passTime() + + abstract tran enterRecursive(commonState: StateNode) + abstract tran exitRecursive(commonState: StateNode) + + abstract tran setActiveState(state: AbstractState) +} + +class State : AbstractState { + contains start: EntryState[1] + + contains transitions: Transition[0..*] opposite parentState + + var activeState: states[0..1] := nothing + + redefine prop isInnerStateActive(state: AbstractState): bool { + return state == activeState + } + + redefine prop getActiveState(): AbstractState { + return activeState + } + + redefine tran setActiveState(state: AbstractState) { + activeState := state + } + + redefine tran fireTransitions() { + choice { + // inline assumeNoInnerTransitionEnabled() + inline fireLocalTransitions() + } or { + // specifies top-down transition priority + inline assumeNoLocalTransitionEnabled() + inline fireInnerTransitions() + } + } + tran fireLocalTransitions() { + inline for choice (transition in transitions) { + inline transition.fire() + } else { + assume (false) + } + } + tran fireInnerTransitions() { + inline for choice (state in states) { + inline state.fireTransitions() + } else { + assume (false) + } + } + + redefine tran assumeNoTransitionEnabled() { + inline assumeNoLocalTransitionEnabled() + inline assumeNoInnerTransitionEnabled() + } + tran assumeNoLocalTransitionEnabled() { + inline for (transition in transitions) { + assume (!transition.isEnabled()) + } + } + tran assumeNoInnerTransitionEnabled() { + inline for (state in states) { + inline state.assumeNoTransitionEnabled() + } + } + + redefine tran activateRecursive() { + inline start.enter() + } + + redefine tran deactivateRecursive(_deactivate: bool) { + inline for (state in states) { + inline state.deactivateRecursive(true) + } + + inline if (_deactivate) { + inline deactivate() + } + } + + redefine tran passTime() { + inline for (transition in transitions) { + inline transition.passTime() + } + inline for (state in states) { + inline state.passTime() + } + } + + redefine tran enterRecursive(commonState: StateNode) { + inline if (parent != nothing) { + inline if (commonState != parent) { + inline parent.enterRecursive(commonState) + } + + inline activate() + } + } + redefine tran enter(commonState: StateNode) { + inline enterRecursive(commonState) + inline activateRecursive() + } + + redefine tran exitRecursive(commonState: StateNode) { + inline if (parent != nothing) { + inline deactivate() + + inline if (commonState != parent) { + inline parent?.exitRecursive(commonState) + } + } + } + redefine tran exit(commonState: StateNode) { + inline deactivateRecursive(false) + inline exitRecursive(commonState) + } + + tran activate() { + inline parent.setActiveState(self) + + inline for (transition in outgoingTransitions) { + inline transition.initialize() + } + + inline entryAction.main() + } + + tran deactivate() { + if (parent.getActiveState() == self) { + inline exitAction.main() + + inline parent.setActiveState(nothing) + } + } + +} + +class Transition { + container parentState: State[1] opposite transitions + + refers from: StateNode[1] opposite outgoingTransitions + refers to: StateNode[1] opposite incomingTransitions + + contains action: Action + contains acceptAction: AcceptAction + contains guard: Guard[1] { // default guard is true + redefine contains expression: LiteralBooleanExpression { + redefine refers value: bool = true + } + } + + tran fire() { + assume (isEnabled()) + inline performTransition() + } + + prop isEnabled(): bool { + return acceptAction.isTriggered() && from.isActive() && guard.isOpen() + } + + tran performTransition() { + inline from.exit(parentState) + inline action.main() + inline to.enter(parentState) + } + + tran passTime() { + inline acceptAction.passTime() + } + + tran initialize() { + inline acceptAction.initialize() + } + +} + +class ParallelState : AbstractState { + contains start: EntryState[1] + + redefine prop getActiveState(): AbstractState { + return nothing + } + + redefine tran setActiveState(state: AbstractState) { + + } + + redefine prop isInnerStateActive(state: AbstractState): bool { + return isActive() + } + + redefine tran fireTransitions() { + var anyStateExecuted: bool := false + + inline for (state in states) { + choice { + anyStateExecuted := true + + inline state.fireTransitions() + } or { + inline state.assumeNoTransitionEnabled() + } + } + + assume (anyStateExecuted) + } + + redefine tran assumeNoTransitionEnabled() { + inline for (state in states) { + inline state.assumeNoTransitionEnabled() + } + } + + redefine tran activateRecursive() { + inline for (state in states) { + inline state.activateRecursive() + } + } + + redefine tran deactivateRecursive(_deactivate: bool) { + inline for (state in states) { + inline state.deactivateRecursive(true) + } + + inline if (_deactivate) { + inline deactivate() + } + } + + redefine tran passTime() { + inline for (state in states) { + inline state.passTime() + } + } + + redefine tran enterRecursive(commonState: StateNode) { + inline if (commonState != parent) { + inline parent?.enterRecursive(commonState) + } + + inline activate() + } + redefine tran enter(commonState: StateNode) { + inline enterRecursive(commonState) + inline activateRecursive() + } + + redefine tran exitRecursive(commonState: StateNode) { + inline deactivate() + + inline if (commonState != parent) { + inline parent?.exitRecursive(commonState) + } + } + redefine tran exit(commonState: StateNode) { + inline deactivateRecursive(false) + inline exitRecursive(commonState) + } + + tran activate() { + inline if (parent != nothing) { + inline parent.setActiveState(self) + + inline for (transition in outgoingTransitions) { + inline transition.initialize() + } + + inline entryAction.main() + } + } + + tran deactivate() { + inline if (parent != nothing) { + inline exitAction.main() + + if (parent.getActiveState() == self) { + inline parent.setActiveState(nothing) + } + } + } + +} + +class EntryState : StateNode { + + redefine prop isActive(): bool { + return false + } + + redefine tran enter() { + inline for choice (transition in outgoingTransitions) { + inline transition.performTransition() + } + } + + redefine tran exit() { + + } + +} + +class IsStateActiveExpression : Expression { + refers state: State + + redefine prop evaluate(): bool { + return state.isActive() + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Triggers.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Triggers.oxsts new file mode 100644 index 00000000..f280aa6f --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Triggers.oxsts @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2025 The Semantifyr Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package semantifyr::sysml::triggers + +import semantifyr::sysml::attributes +import semantifyr::sysml::expressions +import semantifyr::sysml::ports +import semantifyr::sysml::items +import semantifyr::sysml::actions + +abstract class AcceptAction { + + prop isTriggered(): bool { + return true // should be abstract, but no good way to specify defaults atm + } + + tran passTime() { + } + + tran assumeIsTriggered() { + assume (isTriggered()) + } + + tran initialize() { + } +} + +class AcceptItemAction : AcceptAction { + + refers viaPort: Port + refers payload: Item + + redefine prop isTriggered(): bool { + return viaPort.hasIncomingItem(payload) + } +} + +class AcceptTimeoutAction : AcceptAction { + + refers afterTime: int = 1 + + var remainingTime: int := 0 + + redefine tran passTime() { + if (remainingTime > 0) { + remainingTime := remainingTime - 1 + } + } + + redefine prop isTriggered(): bool { + return remainingTime <= 0 + } + + redefine tran initialize() { + remainingTime := afterTime + } +} + +class AcceptWhenAction : AcceptAction { + + contains expression: Expression + + redefine prop isTriggered(): bool { + return expression.evaluate() + } + +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Verification.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Verification.oxsts new file mode 100644 index 00000000..80ec6cfb --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Verification.oxsts @@ -0,0 +1,40 @@ +package semantifyr::sysml::verification + +import semantifyr::sysml::parts +import semantifyr::sysml::states +import semantifyr::sysml::expressions + +class Constraint : Expression { + contains requiredConstraint: Expression + + redefine prop evaluate(): bool { + return requiredConstraint.evaluate() + } +} + +class Requirement : Constraint { + contains verifyRequirement: Constraint + + redefine prop evaluate(): bool { + return verifyRequirement.evaluate() + } +} + +class VerificationCaseDefinition { + contains subject: Part + contains objective: Requirement + + redefine init { + inline subject.init() + } + + redefine tran { + inline subject.havocInputEvents() + inline subject.executeMainComponent() + inline subject.passTime() + } + + prop { + return objective.evaluate() + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/topdowntransition.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/topdowntransition.sysml new file mode 100644 index 00000000..0e74f70d --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/topdowntransition.sysml @@ -0,0 +1,73 @@ +private import ScalarValues::Integer; +private import ScalarValues::Boolean; +private import SI::s; + +// NOTE: use with the TopDownLibrary + +item def VarEventE; +item def VarEventF; + +port def VarPortE { in item e : VarEventE; } +port def VarPortF { in item f : VarEventF; } + +part def TransitionPriorityTopDownModel { + attribute innerFired : Boolean default false; + attribute outerFired : Boolean default false; + port input : VarPortE; + + exhibit state Behaviour { + state Outer { + state Inner; + state InnerDone; + transition first start then Inner; + transition + first Inner + accept : VarEventE via input + do action { assign innerFired := true; } + then InnerDone; + } + state OuterDone; + transition first start then Outer; + transition + first Outer + accept : VarEventE via input + do action { assign outerFired := true; } + then OuterDone; + } +} + +verification def OuterTransitionCanFireTestCase { + subject system : TransitionPriorityTopDownModel; + objective { + verify requirement { + require constraint { eventually (system.outerFired) } + } + } +} + +verification def OuterDoneReachableTestCase { + subject system : TransitionPriorityTopDownModel; + objective { + verify requirement { + require constraint { eventually (isStateActive(system.Behaviour.OuterDone)) } + } + } +} + +verification def InnerTransitionNeverFiresTestCase { + subject system : TransitionPriorityTopDownModel; + objective { + verify requirement { + require constraint { mustAlways(system.innerFired == false) } + } + } +} + +verification def InnerDoneNotReachableTestCase { + subject system : TransitionPriorityTopDownModel; + objective { + verify requirement { + require constraint { mustAlways(not isStateActive(system.Behaviour.Outer.InnerDone)) } + } + } +} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index 93ce8ac7..3d652e4b 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -46,7 +46,7 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { val transformer = StandaloneSysMLTransformer() - private fun loadModel(model: String): SemantifyrModelContext { + private fun loadModel(model: String, library: String = "Library"): SemantifyrModelContext { val sysmlModelPath = Path(model) val sysmlModel = sysmlModelPath.toFile() val oxstsModelPath = Path(sysmlModel.absolutePath.replace(".sysml", ".oxsts")) @@ -55,7 +55,7 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { transformer.transformModel(sysmlModel, oxstsModel) return semantifyrVerificationHelper.semantifyrLoader.startContext() - .loadLibraries(Path("Library")) + .loadLibraries(Path(library)) .loadModel(oxstsModelPath) .buildAndResolve() } @@ -78,7 +78,6 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { fun `Semantics Test Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/semanticstest.sysml") - return semantifyrVerificationHelper.collectNotSlowVerificationCases(model).asStream() return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } @@ -138,6 +137,13 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } + @JvmStatic + fun `Top Down Transition Test Model Verification Cases Should Pass`(): Stream { + val model = loadModel("TestModels/topdowntransition.sysml", "LibraryVariants/TopDownLibrary") + + return semantifyrVerificationHelper.collectVerificationCases(model).asStream() + } + } override val logger by loggerFactory() @@ -219,4 +225,10 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { checkVerificationCase(verificationCase) } + @ParameterizedTest + @MethodSource + fun `Top Down Transition Test Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { + checkVerificationCase(verificationCase) + } + } From 3146696c819f0c4e262d16cade0fdb8b939a4e94 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 21:28:17 +0200 Subject: [PATCH 106/115] Enable relevant models in the benchmark --- .../frontends/sysml/semantics/SysMLBenchmarkTests.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt index 00171479..b7e70d02 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt @@ -51,9 +51,17 @@ class SysMLBenchmarkTests : BaseSemantifyrVerificationTest() { private val transformer = StandaloneSysMLTransformer() private val BENCHMARK_MODELS = listOf( - "TestModels/crossroads.sysml" to "crossroads", - "TestModels/compressedspacecraft.sysml" to "compressedspacecraft", + "TestModels/crossroads.sysml" to "Crossraods", +// "TestModels/compressedspacecraft.sysml" to "spacecraft (compressed)", "TestModels/spacecraft.sysml" to "spacecraft", + "TestModels/aircraft_engine.sysml" to "aircraft_engine", + "TestModels/autonomous_driving.sysml" to "autonomous_driving", + "TestModels/door_access.sysml" to "door_access", + "TestModels/orion_protocol.sysml" to "orion_protocol", + "TestModels/power_subsystems.sysml" to "power_subsystems", + "TestModels/semanticstest.sysml" to "semanticstest", +// "TestModels/stm21.sysml" to "stm21", +// "TestModels/stm31.sysml" to "stm31", ) private fun loadModel(model: String) = run { From ca83694349506fd944536d3fb08745a0b0c3f287 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Sun, 29 Mar 2026 21:31:52 +0200 Subject: [PATCH 107/115] Use the correct models --- .../frontends/sysml/semantics/SysMLBenchmarkTests.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt index b7e70d02..ddba1b0f 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLBenchmarkTests.kt @@ -51,14 +51,14 @@ class SysMLBenchmarkTests : BaseSemantifyrVerificationTest() { private val transformer = StandaloneSysMLTransformer() private val BENCHMARK_MODELS = listOf( - "TestModels/crossroads.sysml" to "Crossraods", -// "TestModels/compressedspacecraft.sysml" to "spacecraft (compressed)", - "TestModels/spacecraft.sysml" to "spacecraft", "TestModels/aircraft_engine.sysml" to "aircraft_engine", "TestModels/autonomous_driving.sysml" to "autonomous_driving", + "TestModels/compressedspacecraft.sysml" to "spacecraft (compressed)", + "TestModels/crossroads.sysml" to "Crossraods", "TestModels/door_access.sysml" to "door_access", "TestModels/orion_protocol.sysml" to "orion_protocol", "TestModels/power_subsystems.sysml" to "power_subsystems", +// "TestModels/spacecraft.sysml" to "spacecraft", "TestModels/semanticstest.sysml" to "semanticstest", // "TestModels/stm21.sysml" to "stm21", // "TestModels/stm31.sysml" to "stm31", From 2bc3577e21ae47adb86e42708f4adf6693c4d619 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 30 Mar 2026 03:30:34 +0200 Subject: [PATCH 108/115] Removed the stm21 and stm31 models --- .../sysmlv2-semantics/TestModels/stm21.sysml | 92 ------------------- .../sysmlv2-semantics/TestModels/stm31.sysml | 85 ----------------- .../sysml/semantics/SysMLVerificationTests.kt | 26 ------ 3 files changed, 203 deletions(-) delete mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm21.sysml delete mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm31.sysml diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm21.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm21.sysml deleted file mode 100644 index 2ae208fc..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm21.sysml +++ /dev/null @@ -1,92 +0,0 @@ -private import ScalarValues::Integer; -private import ScalarValues::Boolean; - -item def F; -item def G; - -port def InputEvents { - in item f : F; - in item g : G; -} - -part def Stm21 { - port input : InputEvents; - - exhibit state Behaviour parallel { - state R1 { - state S11; - state S12; - - transition first start then S11; - transition - first S11 - accept : F via input - then S12; - } - state R2 { - state S13; - state S14; - transition first start then S13; - transition - first S13 - accept : G via input - then S14; - } - } -} - -verification def S11Reachable { - subject system : Stm21; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.R1.S11) - ) - } - } - } -} - -verification def S12Reachable { - subject system : Stm21; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.R1.S12) - ) - } - } - } -} - -verification def S13Reachable { - subject system : Stm21; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.R2.S13) - ) - } - } - } -} - -verification def S14Reachable { - subject system : Stm21; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.R2.S14) - ) - } - } - } -} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm31.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm31.sysml deleted file mode 100644 index f14c0889..00000000 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/stm31.sysml +++ /dev/null @@ -1,85 +0,0 @@ -private import ScalarValues::Integer; - -item def A; -item def B; -item def C; -item def D; -item def X; -item def E; - -port def OutputEvents { - out item a : A; - out item b : B; - out item c : C; - out item d : D; - out item x : X; -} - -port def InputEvents { - in item e : E; -} - -part def Stm31 { - attribute i : Integer default 0; - port input : InputEvents; - port output : OutputEvents; - - exhibit state Behaviour { - state S1 { - entry action { - send A() via output; - } - exit action { - assign i := i+1; - send B() via output; - } - } - state S2 { - entry action { - assign i := i*2; - send C() via output; - } - exit action { - send D() via output; - } - } - transition first start then S1; - - transition - first S1 - accept : E via input - do action { - assign i := i + 1; - send D() via output; - } - then S2; - } -} - -verification def S1Reachable { - subject system : Stm31; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.S1) - ) - } - } - } -} - -verification def S2Reachable { - subject system : Stm31; - - objective { - verify requirement { - require constraint { - eventually( - isStateActive(system.Behaviour.S2) - ) - } - } - } -} diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index 3d652e4b..579f7ae5 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -60,20 +60,6 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { .buildAndResolve() } - @JvmStatic - fun `STM21 Model Verification Cases Should Pass`(): Stream { - val model = loadModel("TestModels/stm21.sysml") - - return semantifyrVerificationHelper.collectVerificationCases(model).asStream() - } - - @JvmStatic - fun `STM31 Model Verification Cases Should Pass`(): Stream { - val model = loadModel("TestModels/stm31.sysml") - - return semantifyrVerificationHelper.collectVerificationCases(model).asStream() - } - @JvmStatic fun `Semantics Test Model Verification Cases Should Pass`(): Stream { val model = loadModel("TestModels/semanticstest.sysml") @@ -158,18 +144,6 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { checkVerificationCase(verificationCase) } - @ParameterizedTest - @MethodSource - fun `STM21 Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { - checkVerificationCase(verificationCase) - } - - @ParameterizedTest - @MethodSource - fun `STM31 Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { - checkVerificationCase(verificationCase) - } - @ParameterizedTest @MethodSource fun `Semantics Test Model Verification Cases Should Pass`(verificationCase: ClassDeclaration) { From 6a9f18c6cc2ab34e03395f23948f84fecbdacccf Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 30 Mar 2026 03:31:16 +0200 Subject: [PATCH 109/115] Moved the top-down library --- .../{LibraryVariants => }/TopDownLibrary/Actions.oxsts | 0 .../{LibraryVariants => }/TopDownLibrary/Attributes.oxsts | 0 .../{LibraryVariants => }/TopDownLibrary/Expressions.oxsts | 0 .../{LibraryVariants => }/TopDownLibrary/Items.oxsts | 0 .../{LibraryVariants => }/TopDownLibrary/Parts.oxsts | 0 .../{LibraryVariants => }/TopDownLibrary/Ports.oxsts | 0 .../{LibraryVariants => }/TopDownLibrary/README.md | 5 +++-- .../{LibraryVariants => }/TopDownLibrary/States.oxsts | 0 .../{LibraryVariants => }/TopDownLibrary/Triggers.oxsts | 0 .../{LibraryVariants => }/TopDownLibrary/Verification.oxsts | 0 .../frontends/sysml/semantics/SysMLVerificationTests.kt | 2 +- 11 files changed, 4 insertions(+), 3 deletions(-) rename subprojects/frontends/sysmlv2/sysmlv2-semantics/{LibraryVariants => }/TopDownLibrary/Actions.oxsts (100%) rename subprojects/frontends/sysmlv2/sysmlv2-semantics/{LibraryVariants => }/TopDownLibrary/Attributes.oxsts (100%) rename subprojects/frontends/sysmlv2/sysmlv2-semantics/{LibraryVariants => }/TopDownLibrary/Expressions.oxsts (100%) rename subprojects/frontends/sysmlv2/sysmlv2-semantics/{LibraryVariants => }/TopDownLibrary/Items.oxsts (100%) rename subprojects/frontends/sysmlv2/sysmlv2-semantics/{LibraryVariants => }/TopDownLibrary/Parts.oxsts (100%) rename subprojects/frontends/sysmlv2/sysmlv2-semantics/{LibraryVariants => }/TopDownLibrary/Ports.oxsts (100%) rename subprojects/frontends/sysmlv2/sysmlv2-semantics/{LibraryVariants => }/TopDownLibrary/README.md (73%) rename subprojects/frontends/sysmlv2/sysmlv2-semantics/{LibraryVariants => }/TopDownLibrary/States.oxsts (100%) rename subprojects/frontends/sysmlv2/sysmlv2-semantics/{LibraryVariants => }/TopDownLibrary/Triggers.oxsts (100%) rename subprojects/frontends/sysmlv2/sysmlv2-semantics/{LibraryVariants => }/TopDownLibrary/Verification.oxsts (100%) diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Actions.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Actions.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Actions.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Actions.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Attributes.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Attributes.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Attributes.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Attributes.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Expressions.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Expressions.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Expressions.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Expressions.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Items.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Items.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Items.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Items.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Parts.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Parts.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Parts.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Parts.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Ports.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Ports.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Ports.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Ports.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/README.md b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/README.md similarity index 73% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/README.md rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/README.md index 7705259a..5fdeb824 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/README.md +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/README.md @@ -1,9 +1,9 @@ # Top-down transition priority -Changes compared to the Library: +This directory contains an example top-down transition scheduling implementation. Changes compared to the shown Library: States.oxsts: - +```oxsts redefine tran fireTransitions() { choice { // commented out @@ -16,3 +16,4 @@ redefine tran fireTransitions() { inline fireInnerTransitions() } } +``` diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/States.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/States.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/States.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/States.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Triggers.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Triggers.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Triggers.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Triggers.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Verification.oxsts b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Verification.oxsts similarity index 100% rename from subprojects/frontends/sysmlv2/sysmlv2-semantics/LibraryVariants/TopDownLibrary/Verification.oxsts rename to subprojects/frontends/sysmlv2/sysmlv2-semantics/TopDownLibrary/Verification.oxsts diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt index 579f7ae5..cebbc00b 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/src/test/kotlin/hu/bme/mit/semantifyr/frontends/sysml/semantics/SysMLVerificationTests.kt @@ -125,7 +125,7 @@ class SysMLVerificationTests : BaseSemantifyrVerificationTest() { @JvmStatic fun `Top Down Transition Test Model Verification Cases Should Pass`(): Stream { - val model = loadModel("TestModels/topdowntransition.sysml", "LibraryVariants/TopDownLibrary") + val model = loadModel("TestModels/topdowntransition.sysml", "TopDownLibrary") return semantifyrVerificationHelper.collectVerificationCases(model).asStream() } From 76f0808be0f4c1b56564a7a69f998c0ef62dbcd1 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 30 Mar 2026 03:31:29 +0200 Subject: [PATCH 110/115] Added some readmes --- .../sysmlv2/sysmlv2-semantics/README.md | 7 +++++++ .../sysmlv2-semantics/TestModels/README.md | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/README.md create mode 100644 subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/README.md diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/README.md b/subprojects/frontends/sysmlv2/sysmlv2-semantics/README.md new file mode 100644 index 00000000..c3dbe951 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/README.md @@ -0,0 +1,7 @@ +# SysML v2 Semantics + +This subproject contains the modelled SysML v2 semantic library (./Library), a variant library (./TopDownLibrary), and the automated verification and benchmarking of the used test models (./TestModels). + +Running the benchmark: `./gradlew benchmarkVerificationCases` --- the outputs will be written to `./TestModels/benchmark-results.json`. + +Running the tests: `./gradlew :sysmlv2-semantics:testVerificationCases`, which excludes the uncompressed Spacecraft model --- or `./gradlew :sysmlv2-semantics:allTests` for all verification cases. diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/README.md b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/README.md new file mode 100644 index 00000000..e0d830a4 --- /dev/null +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/README.md @@ -0,0 +1,20 @@ +# Test Models + +This directory contains SysML v2 test models used for testing the Semantifyr SysML v2 frontend. + +The artifacts produced by Semantifyr will reside in the `./out` directory. + +| Model file | Origin | Description | +|----------------------------|--------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------| +| semanticstest.sysml | Original | Semantic validation test suite designed designed for Semantifyr | +| topdowntransition.sysml | Original | Top-down transition priority testing model, use the TopDownLibrary! | +| crossroads.sysml | [Gamma tutorial](https://github.com/ftsrg/gamma/tree/master/tutorial/hu.bme.mit.gamma.tutorial.finish/model) | Rewritten version of the Gamma Crossroads tutorial model | +| spacecraft.sysml | OpenMBEE Simple Space Mission | The Simple Space Mission's spacecraft model rewritten into SysML v2 | +| compressedspacecraft.sysml | OpenMBEE Simple Space Mission | Same as spacecraft but the battery and data variables are incremented/decremented by 10 instead of 1 | +| door_access.sysml | - | Sequential cyclic workflow, do-actions on transitions | +| power_subsystems.sysml | - | Guarded self-transitions, entry actions, terminal absorbing state | +| aircraft_engine.sysml | - | Large flat state machine (13 states), boolean guard, structurally unreachable state | +| autonomous_driving.sysml | Paper: "Automatic Formal Verification of SysML State Machine Diagrams for Vehicular Control Systems" | Model based on paper "Automatic Formal Verification of SysML State Machine Diagrams for Vehicular Control Systems" from Clemson University | +| orion_protocol.sysml | Prolan | Bidirectional protocol, `accept when true`, timed keep-alive, cross-hierarchy transitions | + +The verification cases were either added as natural "state reachability" properties, or were derived as safety properties from the model. From 4c1f22d5952ddc9bc63bd329768287355fd0eac9 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 30 Mar 2026 03:31:47 +0200 Subject: [PATCH 111/115] Added comments about theta --- .../src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt | 2 ++ .../src/main/kotlin/execution/ShellBasedThetaXstsExecutor.kt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt index 6b4b75fc..f67aac03 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/DockerBasedThetaXstsExecutor.kt @@ -68,6 +68,8 @@ class DockerBasedThetaXstsExecutor : ThetaXstsExecutor() { } } + // TODO: handle theta errors if any + ThetaExecutionResult(result.statusCode) } diff --git a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ShellBasedThetaXstsExecutor.kt b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ShellBasedThetaXstsExecutor.kt index e92de78d..9e6524fe 100644 --- a/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ShellBasedThetaXstsExecutor.kt +++ b/subprojects/backends/theta/theta-wrapper/src/main/kotlin/execution/ShellBasedThetaXstsExecutor.kt @@ -66,6 +66,8 @@ class ShellBasedThetaXstsExecutor : ThetaXstsExecutor() { } } + // TODO: handle theta errors if any + ThetaExecutionResult(process.exitValue()) } From 41c3142d8e3a1127f02c0b2b4e446df107e2a1dc Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 30 Mar 2026 04:03:31 +0200 Subject: [PATCH 112/115] Added log4j2.properties to log to files --- .../src/main/resources/log4j2.properties | 14 ++++++ .../src/main/resources/log4j2.properties | 14 ++++++ .../src/main/resources/log4j2.properties | 14 ++++++ .../TestModels/power_subsystems.sysml | 46 +++++++++---------- .../src/main/resources/log4j2.properties | 14 ++++++ 5 files changed, 79 insertions(+), 23 deletions(-) create mode 100644 subprojects/backends/theta/cex.lang.ide/src/main/resources/log4j2.properties create mode 100644 subprojects/backends/theta/xsts.lang.ide/src/main/resources/log4j2.properties create mode 100644 subprojects/frontends/gamma/gamma.lang.ide/src/main/resources/log4j2.properties create mode 100644 subprojects/oxsts.lang.ide/src/main/resources/log4j2.properties diff --git a/subprojects/backends/theta/cex.lang.ide/src/main/resources/log4j2.properties b/subprojects/backends/theta/cex.lang.ide/src/main/resources/log4j2.properties new file mode 100644 index 00000000..faaa8cd9 --- /dev/null +++ b/subprojects/backends/theta/cex.lang.ide/src/main/resources/log4j2.properties @@ -0,0 +1,14 @@ +# +# SPDX-FileCopyrightText: 2025 The Semantifyr Authors +# +# SPDX-License-Identifier: EPL-2.0 +# + +rootLogger.level=WARN +rootLogger.appenderRef.file.ref=FileAppender + +appender.file.name=FileAppender +appender.file.type=File +appender.file.fileName=cex.lsp.log +appender.file.layout.type=PatternLayout +appender.file.layout.pattern=%p\t%d{ISO8601}\t%r\t%c\t[%t]\t%m%n diff --git a/subprojects/backends/theta/xsts.lang.ide/src/main/resources/log4j2.properties b/subprojects/backends/theta/xsts.lang.ide/src/main/resources/log4j2.properties new file mode 100644 index 00000000..9b5b4de2 --- /dev/null +++ b/subprojects/backends/theta/xsts.lang.ide/src/main/resources/log4j2.properties @@ -0,0 +1,14 @@ +# +# SPDX-FileCopyrightText: 2025 The Semantifyr Authors +# +# SPDX-License-Identifier: EPL-2.0 +# + +rootLogger.level=INFO +rootLogger.appenderRef.file.ref=FileAppender + +appender.file.name=FileAppender +appender.file.type=File +appender.file.fileName=xsts.lsp.log +appender.file.layout.type=PatternLayout +appender.file.layout.pattern=%p\t%d{ISO8601}\t%r\t%c\t[%t]\t%m%n diff --git a/subprojects/frontends/gamma/gamma.lang.ide/src/main/resources/log4j2.properties b/subprojects/frontends/gamma/gamma.lang.ide/src/main/resources/log4j2.properties new file mode 100644 index 00000000..24a0d097 --- /dev/null +++ b/subprojects/frontends/gamma/gamma.lang.ide/src/main/resources/log4j2.properties @@ -0,0 +1,14 @@ +# +# SPDX-FileCopyrightText: 2025 The Semantifyr Authors +# +# SPDX-License-Identifier: EPL-2.0 +# + +rootLogger.level=WARN +rootLogger.appenderRef.file.ref=FileAppender + +appender.file.name=FileAppender +appender.file.type=File +appender.file.fileName=gamma.lsp.log +appender.file.layout.type=PatternLayout +appender.file.layout.pattern=%p\t%d{ISO8601}\t%r\t%c\t[%t]\t%m%n diff --git a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/power_subsystems.sysml b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/power_subsystems.sysml index bcb89767..7ab996ac 100644 --- a/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/power_subsystems.sysml +++ b/subprojects/frontends/sysmlv2/sysmlv2-semantics/TestModels/power_subsystems.sysml @@ -1,24 +1,24 @@ private import ScalarValues::Integer; -item def BatteryLowAlert; +item def BatteryCriticalAlert; -port def PowerPort { - in item batteryLow : BatteryLowAlert; +port def AlertPort { + in item batteryCritical : BatteryCriticalAlert; } part def PowerManager { - attribute batteryLevel: Integer default 100; - port powerPort: PowerPort; + attribute charge: Integer default 100; + port alertPort: AlertPort; exhibit state Behaviour { state On { entry action { - assign batteryLevel := batteryLevel - 1; + assign charge := charge - 1; } } - state LowPower { + state PowerCritical { entry action { - assign batteryLevel := batteryLevel - 1; + assign charge := charge - 1; } } state Off; @@ -26,24 +26,24 @@ part def PowerManager { transition first start then On; transition first On - accept : BatteryLowAlert via powerPort - if batteryLevel < 20 - then LowPower; + accept : BatteryCriticalAlert via alertPort + if charge < 20 + then PowerCritical; transition first On - accept : BatteryLowAlert via powerPort - if batteryLevel >= 20 + accept : BatteryCriticalAlert via alertPort + if charge >= 20 then On; - transition first LowPower - accept : BatteryLowAlert via powerPort - if batteryLevel < 5 + transition first PowerCritical + accept : BatteryCriticalAlert via alertPort + if charge < 5 then Off; - transition first LowPower - accept : BatteryLowAlert via powerPort - if batteryLevel >= 5 - then LowPower; + transition first PowerCritical + accept : BatteryCriticalAlert via alertPort + if charge >= 5 + then PowerCritical; } } @@ -68,7 +68,7 @@ verification def LowPowerReachable { verify requirement { require constraint { eventually( - isStateActive(system.Behaviour.LowPower) + isStateActive(system.Behaviour.PowerCritical) ) } } @@ -97,7 +97,7 @@ verification def OnAndLowPowerNeverSimultaneous { require constraint { mustAlways(not( isStateActive(system.Behaviour.On) - and isStateActive(system.Behaviour.LowPower) + and isStateActive(system.Behaviour.PowerCritical) )) } } @@ -126,7 +126,7 @@ verification def LowPowerAndOffNeverSimultaneous { verify requirement { require constraint { mustAlways(not( - isStateActive(system.Behaviour.LowPower) + isStateActive(system.Behaviour.PowerCritical) and isStateActive(system.Behaviour.Off) )) } diff --git a/subprojects/oxsts.lang.ide/src/main/resources/log4j2.properties b/subprojects/oxsts.lang.ide/src/main/resources/log4j2.properties new file mode 100644 index 00000000..003deecd --- /dev/null +++ b/subprojects/oxsts.lang.ide/src/main/resources/log4j2.properties @@ -0,0 +1,14 @@ +# +# SPDX-FileCopyrightText: 2025 The Semantifyr Authors +# +# SPDX-License-Identifier: EPL-2.0 +# + +rootLogger.level=WARN +rootLogger.appenderRef.file.ref=FileAppender + +appender.file.name=FileAppender +appender.file.type=File +appender.file.fileName=oxsts.lsp.log +appender.file.layout.type=PatternLayout +appender.file.layout.pattern=%p\t%d{ISO8601}\t%r\t%c\t[%t]\t%m%n From 6a41473c4a5f7b7cd15b077c2242b9f043660266 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 30 Mar 2026 04:34:52 +0200 Subject: [PATCH 113/115] Use consistent JVM parameters --- .../backends/theta/theta-wrapper/scripts/theta-xsts-cli | 2 +- .../backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli index 841b14bc..e0d9bf8b 100755 --- a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli +++ b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli @@ -5,4 +5,4 @@ if [ "$1" = "--version" ]; then LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" CEGAR --version exit fi -LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss512M -Xms1G -Xmx20G -XX:+UseG1GC -XX:+UseTransparentHugePages "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" +LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss512M -Xms1G -Xmx4G -XX:+UseG1GC -XX:+UseTransparentHugePages "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" diff --git a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd index 4c82f807..bc388cd1 100644 --- a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd +++ b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd @@ -4,7 +4,7 @@ set SCRIPTDIR=%~dp0 set PATH=%SCRIPTDIR%lib;%PATH% set VERIFIER_NAME=Theta if "%1"=="--version" ( - java -Xss512M -Xmx4G "-Djava.library.path=%SCRIPTDIR%lib" -jar "%SCRIPTDIR%jars\theta-xsts-cli.jar" CEGAR --version + java "-Djava.library.path=%SCRIPTDIR%lib" -jar "%SCRIPTDIR%jars\theta-xsts-cli.jar" CEGAR --version exit /b %ERRORLEVEL% ) -java -Xss512M -Xmx4G "-Djava.library.path=%SCRIPTDIR%lib" -jar "%SCRIPTDIR%jars\theta-xsts-cli.jar" %* +java -Xss512M -Xms1G -Xmx4G -XX:+UseG1GC -XX:+UseTransparentHugePages "-Djava.library.path=%SCRIPTDIR%lib" -jar "%SCRIPTDIR%jars\theta-xsts-cli.jar" %* From ebb13b5fa93dd96abdd29edc767d7144378cdeaf Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 30 Mar 2026 04:35:54 +0200 Subject: [PATCH 114/115] Removed slow verification CI step --- .github/workflows/verification.yml | 39 ------------------------------ 1 file changed, 39 deletions(-) delete mode 100644 .github/workflows/verification.yml diff --git a/.github/workflows/verification.yml b/.github/workflows/verification.yml deleted file mode 100644 index e68804c5..00000000 --- a/.github/workflows/verification.yml +++ /dev/null @@ -1,39 +0,0 @@ -# SPDX-FileCopyrightText: 2023-2024 The Semantifyr Authors -# -# SPDX-License-Identifier: EPL-2.0 - -name: All Verification Tests -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] -env: - CI: true -jobs: - run-verification: - permissions: - contents: read - strategy: - fail-fast: false - matrix: - os: - - ubuntu-latest - - windows-latest - - macos-latest - runs-on: ${{ matrix.os }} - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - submodules: true - - name: Set up JDK - uses: actions/setup-java@v5 - with: - java-version: 25 - distribution: adopt - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 - - name: Run verification tests - shell: bash - run: ./gradlew allTests --continue From a5e130a69d2a9f9f109f440f4860f089bae2d481 Mon Sep 17 00:00:00 2001 From: Armin Zavada Date: Mon, 30 Mar 2026 04:42:33 +0200 Subject: [PATCH 115/115] Removed extra flags --- subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli | 2 +- .../backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli index e0d9bf8b..44a7c06b 100755 --- a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli +++ b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli @@ -5,4 +5,4 @@ if [ "$1" = "--version" ]; then LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" CEGAR --version exit fi -LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss512M -Xms1G -Xmx4G -XX:+UseG1GC -XX:+UseTransparentHugePages "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" +LD_LIBRARY_PATH="$SCRIPTDIR/lib" DYLD_LIBRARY_PATH="$SCRIPTDIR/lib" java -Xss512M -Xms1G -Xmx4G "-Djava.library.path=$SCRIPTDIR/lib" -jar "$SCRIPTDIR/jars/theta-xsts-cli.jar" "$@" diff --git a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd index bc388cd1..a82ca196 100644 --- a/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd +++ b/subprojects/backends/theta/theta-wrapper/scripts/theta-xsts-cli.cmd @@ -7,4 +7,4 @@ if "%1"=="--version" ( java "-Djava.library.path=%SCRIPTDIR%lib" -jar "%SCRIPTDIR%jars\theta-xsts-cli.jar" CEGAR --version exit /b %ERRORLEVEL% ) -java -Xss512M -Xms1G -Xmx4G -XX:+UseG1GC -XX:+UseTransparentHugePages "-Djava.library.path=%SCRIPTDIR%lib" -jar "%SCRIPTDIR%jars\theta-xsts-cli.jar" %* +java -Xss512M -Xms1G -Xmx4G "-Djava.library.path=%SCRIPTDIR%lib" -jar "%SCRIPTDIR%jars\theta-xsts-cli.jar" %*