Actions#
Role in SysML v2#
An action can be used to represent a behavior of a part. An action definition may have features with directions in ,out or inout that act as the parameters of the action.
An action usage inherits the parameters of its definitions, if any, and it can also define its own parameters to augment or redefine those of its definitions.
Actions can coordinate the performance of other actions and generate effects on parts
Action definitions and action usages can be decomposed into lower-level action usages to create an action tree, and action usages can be referenced by other actions.
Action ordering can be specified using successions.
A succession between action usages may, additionally, have aguard condition, represented as a Boolean expression.
The sequencing of action usagesmay be further controlled usingcontrol nodes, which are special kinds of action usages.
Presently only decision nodes are supported by the code generato. A decision node has one incoming succession and one or more outgoing successions. Exactly one of the actions connected to an outgoing succession can start after the action connected to the incoming succession has completed. Which of the downstream actions is performed can be controlled by placing guards on the outgoing successions.
An output parameter of one action usage may bebound to the input parameter of another action usage.
Example#
SysML v2 source code:#
private import ScalarValues::*;
package Test {
part def AParent{
attribute anAttributeOfAParent:Integer;
}
part def A specializes AParent {
attribute anAttributeOfA : Integer;
action def ParentAction{}
action def ParentWithPara{
attribute test:Integer;
in x:Real;
out p:Real;
assign p := x*x;
assign anAttributeOfA := p;
assign anAttributeOfAParent := p;
}
action def run{
in n:Real;
out p:Real;
out u:Real;
attribute x : Real;
action act1:ParentAction;
action act2:ParentWithPara;
action act3{in n:Real; out u:Real;
assign u:=8;
}
action Path1{}
then terminate;
action Path2;
then terminate;
first start;
then assign x := n;
then act1;
then assign x:=2;
then action act1_1;
then act2{in x:Real;out p:Real;}
then assign p:=act2.p;
then act3{in n:Real;out u:Real;}
then assign u:=act3.u;
then decide d1;
if n==1 then Path1;
if act2.p==4 then Path2;
else done;
}
}
}C++ source code#
For each action definition a C++ struct is generated that has a pointer to its surrounding part. It also has an operator method that receives the parent part as parameter. A context object ensures that parameter access to all local as well as all parent or other attributes and parts that are visisble to the action is given. This ensures that assign and attribute access construct written in SysML can simply be mapped to C++.
Action usages that are decomposed into lower-level action usages are mapped to executable C++ code representing the SysML intention.
class A : public AParent {
public:
A() {}
// elements of this part
int anAttributeOfA = 0;
virtual void process() override {}
// must be called by derived classes after constructing the parts
virtual void init(void) override {}
struct ParentActionDef {
// Top-level activity: parent is the part
A *part_ptr_ = nullptr;
A &getPart() {
assert(part_ptr_);
return *part_ptr_;
}
virtual void operator()(A &parent_) {
part_ptr_ = &parent_;
struct ParentActionContext {
// owning part
A &parent;
// indirect accessible features
int &anAttributeOfA;
int &anAttributeOfAParent;
ParentActionContext(A &parent_)
: parent(parent_), anAttributeOfA(parent_.anAttributeOfA),
anAttributeOfAParent(parent_.anAttributeOfAParent) {}
} ctx{parent_};
// make context available
auto &anAttributeOfA = ctx.anAttributeOfA;
auto &anAttributeOfAParent = ctx.anAttributeOfAParent;
} // end run method
virtual ~ParentActionDef() = default;
}; // ParentAction
...
};Supported structured control actions constructs#
Loop / until actions#
The loop runs as long until a given condition becomes true.
-
Extra action
action def Test{ out chargeStatus:Integer; action addCharge:AddCharge{} then assign chargeStatus := batLevel; then done; first start; then action monitor : MonitorBattery { out charge; } then decide; if monitor.charge < 100 then addCharge; else done; } action def ChargeBattery { in a:Integer; first start; then loop action charging:Test { } until charging.chargeStatus <= 100; then action endCharging : EndCharging; then done; } -
Inline action
action def ChargeBattery { first start; then loop action charging { action addCharge:AddCharge; then done; first start; then action monitor : MonitorBattery { out charge; } then decide; if monitor.charge <= 100 then addCharge; else done; } until charging.monitor.charge < 100; then action endCharging : EndCharging; then done; }
While loop actions#
A while loop action usage performs a body clause action usage iteratively, as long as its while expression continues to evaluate to true and its until expression continues to evaluate to false (if existing).
-
While with guard check before body clause
attribute whileGuard:Integer default 1; action def WhileUntilAction { first start; then while whileGuard <= 5 { assign whileGuard := whileGuard +1; } then done; } -
While / until combined with check before and after body clause
attribute whileGuard:Integer default 1; attribute untilGuard:Boolean default true; action def SecondAction{ assign whileGuard := whileGuard +1; if whileGuard == 5{ assign untilGuard := false; } } action def WhileUntilAction { first start; then while whileGuard >= 1 { action secondAction:SecondAction{} first start; then secondAction; }until untilGuard == false; then done; }
If/then/else action#
An if action usage evaluates a condition expression and then performs a then clause action usage if the expression evaluates to true, or, optionally, an else clause action usage if the expression evaluates to false.
-
if/then
action def XAct{ attribute x:Integer; first start; then action Act if p==0{ assign b:=4; assign p:=2; then terminate; }else action Act2{ then action aActUse:AAct{} } } -
if/else if/then
action def YAct { first start; then if batLevel<4{ attribute a:Integer default 33; then assign n:=a; then action s:setM{in x=n;} }else if batLevel>=5 and batLevel<90{ attribute a:Integer default 66; then assign n:=a; then action s:setM{in x=a;} }else if batLevel>=90 and batLevel<95{ attribute a:Integer default 99; then assign n:=a; then action s:setM{in x=a;} }else { attribute a:Integer default 100; then assign n:=a; then action s:setM{in x=n;} } }
For loop actions#
A for loop action usage performs a body clause action usage iteratively, assigning a loop variable successively for each iteration to the values resulting from the evaluation of a sequence expression.
1part a[4] : A;
2
3action def AAction{
4
5 first start then forAction;
6
7 action forAction for anA in a {
8 assign anA.n := 34;
9 }
10 then action forAction1 for anA1 in a{
11 forAction2 for anA2 in a{
12 assign anA1.n := 2;
13 assign anA2.n := 35;
14 }
15 }
16
17 then terminate;
18}