A break statement completes execution of an enclosing switch, while, do or for statement.
Syntax
BreakStatement(s: BreakStatement)
= "break" ";"
Figure 9 55 Abstract Syntax of break Statements
Cross References
-
Statement see Subclause 9.1
Semantics
A break statement may only be used directly or indirectly within the body of a switch, while, do or for statement (see Subclauses 9.9, 9.10, 9.11 and 9.12, respectively), except that the innermost enclosing such statement must not be a for statement with a @parallel annotation. When a break statement is executed, it transfers control to the innermost enclosing switch, while, do or for statement, which then immediately completes normally.
9.14return Statements
If an activity has a return parameter, then a return statement may be used to provide a value for that parameter and terminate execution of the activity.
Examples
return item;
return list[index];
return x * factorial(x-1);
Syntax
ReturnStatement(s: ReturnStatement)
= "return" Expression(s.expression) ";"
Figure 9 56 Abstract Syntax of return Statements
Cross References
-
Expression see Subclause 8.1
-
Statement see Subclause 9.1
Semantics
A return statement may only be used within the definition of a behavior that has a return parameter. The expression in the return statement must be assignable to the return parameter (see Subclause 8.8 for the definition of assignability.)
When a return statement is executed, its expression is evaluated and the resulting values, if any, are assigned to the return parameter. The execution of the enclosing behavior then immediately terminates.
9.15accept Statements
An accept statement is used to accept the receipt of one or more types of signals.
NOTE. accept statements are not available at the minium conformance level (see Subclause 2.1).
Examples
accept (sig: SignalNewArrival, SignalTermination);
accept (arrival: SignalNewArrival) {
WriteLine(arrival.name);
terminate = false;
} or accept (SignalTermination) {
terminate = true;
}
Syntax
AcceptStatement(s: AcceptStatement)
= SimpleAcceptStatement(s)
| CompoundAcceptStatement(s)
SimpleAcceptStatement(s: AcceptStatement)
= AcceptClause(s.acceptBlock) ";"
CompoundAcceptStatement(s: AcceptStatement)
= AcceptBlock(s.acceptBlock) { "or" AcceptBlock(s.acceptBlock) }
AcceptBlock(a: AcceptBlock)
= AcceptClause(a) Block(a.block)
AcceptClause(a: AcceptBlock)
= "accept" "(" [ Name(a.name) ":" ] QualifiedNameList(a.signalNames)
")"
QualifiedNameList(qList: QualifiedNameList)
= QualifiedName(qList.name) { "," QualifiedName(qList.name) }
Figure 9 57 Abstract Syntax of accept Statements
Cross References
-
Name see Subclause 7.5
-
Expression see Subclause 8.1
-
QualifiedNameList see Subclause 8.2
-
Statement see Subclause 9.1
-
Block see Subclause 9.1
Semantics
An accept statement can only be used within the definition of an active behavior or the classifier behavior of an active class. All listed qualified names in an accept clause of an accept statement must resolve to signals for which the enclosing behavior has a reception. These signals must not be templates, though they can be the bindings of template signals (see Subclause 8.2). No signal may be named in more than one accept clause of an accept statement.
Simple accept Statements
In its simplest form, an accept statement simply identifies a signal by name:
accept (SignalNewArrival);
When this statement is executed, the thread of execution it is on is suspended, waiting for the receipt of an instance of the signal SignalNewArrival. When such a receipt later triggers the accept statement, it completes its execution, and further execution on its thread can continue.
An accept statement can also optionally include the definition of a local name that is used to hold an accepted signal instance:
accept (arrival: SignalNewArrival);
WriteLine(arrival.name);
A local name so defined has the signal as its type. It must be unassigned before the accept statement.
A single accept statement can list multiple signals, any one of which may trigger it. If the accept statement includes a local name, then this local name will hold whichever signal instance is actually received. The type of such a local name is the effective common ancestor of the listed signals (as defined in Subclause 8.7), if one exists, and is untyped otherwise.
For example:
accept (sig: SignalNewArrival, SignalTermination);
if (sig instanceof SignalNewArrival) {
WriteLine(((SignalNewArrival)sig).name);
terminate = false;
} else {
terminate = true;
}
Compound accept Statements
In the example above, which of multiple signals was actually received is determined by testing the type of the instance received. This is such a typical pattern that Alf provides a compound version of the accept statement that allows the explicit specification of separate clauses for the receipt of different signals. Each clause is triggered on a specific set of signals and, if any one of them is received, an associated block is executed, after which execution of the accept statement is complete.
For example, the above example can be rewritten as follows using a compound accept statement:
accept (arrival: SignalNewArrival) {
WriteLine(arrival.name);
terminate = false;
} or accept (SignalTermination) {
terminate = true;
}
For a compound accept statement, a local named defined in an accept clause (such as arrival in the example above) is available only in the body of that clause and is considered unassigned after the accept statement. New local names may be defined within the accept statement (such as terminate in the example above), but only if the same names are defined in every block of the accept statement. After the accept statement, such new local names have a type that is the effective common ancestor (as defined in Subclause 8.7) of its type in each of the blocks of the accept statement, if one exists, and is untyped otherwise.
Share with your friends: |