A block (see Subclause 9.1) may itself be executed as a statement.
Examples
{ index = this.getIndex(); this.list[index] = this.update(index); }
The example below represents the activity graph shown in Figure 9 -45.
//@parallel
{
'activity' = (Activity)(this.types[1]); // Segment 1
{ // Segment 2
group = new ActivityNodeActivationGroup();
group.activityExecution = this;
}
{ // Segment 3
this.activationGroup = group;
group.activation('activity'.node, 'activity'.edge);
}
}
Figure 9 45 Sample Activity Diagram
Syntax
BlockStatement(s: Statement)
= Block(s.block)
Figure 9 46 Abstract Syntax for Block Statements
Cross References
-
Statement see Subclause 9.1
-
Block see Subclause 9.1
Semantics
Sequential Execution
The execution of a block statement consists simply in the execution of the block (see Subclause 9.1). Unless the block statement has a @parallel annotation (see below), this means that the statements in the block are executed sequentially in order.
Local names assigned before a block statement may be reassigned within the constinuent block of the statement. Further, new local names may be defined within the block. Such new local names are available outside the block after completion of execution of the block statement, with the values they held at the completion of execution of the block. Thus, blocks do not introduce lexically nested scopes for defining local names in Alf.
Parallel Execution
A block statement may have a @parallel annotation. In this case, the statements in the block are all executed concurrently. All the statements of a parallel block are enabled to start executing when the block is executed and the block does not complete execution until all statements complete their execution (that is, there is an implicit join of the concurrent executions of the statements).
If a block statement has a @parallel annotation, any name assigned in one statement of the block may not be further assigned in any subsequent statement in the same block.
NOTE. The above rule allows a name assigned in one statement in a parallel block to be used in a subsequent statement, but not reassigned. This allows data dependencies between otherwise parallel executions of these statements. However, such dependencies are somewhat restricted, since a newly defined name is still only visible in lexically following statements, as for a sequential block. This restriction prevents the possibility of a block statement being invalidated simply by removing a @parallel annotation from it.
For example, in the block
//@parallel
{
a = F(1);
b = G(2);
}
the invocations of the behaviors F and G will execute concurrently with no dependencies between them. The block as a whole completes execution only after both invocations are complete.
However, there may be data dependencies between the statements in a parallel block. For example, the statements in the block
//@parallel
{
a = F(1);
b = G(a);
}
will execute sequentially, despite the @parallel annotation, because the invocation of G cannot proceed until a value is available for a.
In order to prevent data conflicts, it is illegal to assign the same name in more than one statement in a parallel block. Thus, the block
//@parallel
{
a = 1;
a = F(a); // Illegal!
b = G(2);
}
is illegal, since the name a is reassigned in the second statement. However, the following block is legal:
//@parallel
{
{
a = 1;
a = F(a); // Legal
}
b = G(2);
}
This is because the block now consists of just two statements, the first of which happens to be a (sequential) block statement. Only the first of these actually assigns a value to the name a. The value of a after the first statement in the parallel block, and hence after the parallel block as a whole, is the value given to it (sequentially) by the second assignment.
9.5Empty Statements
An empty statement does nothing.
Syntax
EmptyStatement(s: EmptyStatement)
= ";"
Figure 9 47 Abstract Syntax of Empty Statements
Cross References
-
Statement see Subclause 9.1
Semantics
Any empty statement has no effect when it is executed.
A local name declaration is used to define a local name, declare its type and provide an initial value for it. The local name declaration statement has two forms. In the first form, the local name being defined precedes the type name:
let interest : CurrencyAmount = this.principal * this.rate * period;
In the second form, the type name precedes the local name:
CurrencyAmount interest = this.principal * this.rate * period;
The two forms are completely equivalent. In both cases, the local name is assigned the result of evaluating the expression.
NOTE. The first form of local name declaration is consistent with the usual UML notation for declaring the type of a name. The second form is consistent with the form of declarations in many common programming languages and also emphasizes the essential semantics of the statement as an assignment with an added type constraint.
Examples
let currentOffer : Offer = this.offers[1];
let origin : Point = new(0,0);
CurrencyAmount interest = this.principal * this.rate * period;
let inactiveMembers : Member[] = members -> select member (!member.active);
RealProperty[] realProperties = (RealProperty)assets;
IntegerList list = {1, 2, 3};
Set fixedAssets = new { land, home, condominium };
Syntax
LocalNameDeclarationStatement(s: LocalNameDeclarationStatement)
= NameDeclaration(s) "=" InitializationExpression(s.expression) ";"
InitializationExpression(e: Expression)
= Expression(e)
| SequenceInitializationExpression(e)
| InstanceInitializationExpression(e)
InstanceInitializationExpression(e: InstanceCreationExpression)
= "new" Tuple(e.tuple)
NameDeclaration(s: LocalNameDeclarationStatement)
= "let" Name(s.name) ":" TypeName(s.typeName)
[ MultiplicityIndicator (s.hasMultiplicity=true) ]
| TypeName(s.typeName)
[ MultiplicityIndicator (s.hasMultiplicity=true) ] Name(s.name)
Figure 9 48 Abstract Syntax of Local Name Declaration Statements
Cross References
-
Name see Subclause 7.5
-
Expression see Subclause 8.1
-
QualifiedName see Subclause 8.2
-
TypeName see Subclause 8.2
-
SequenceInitializationExpression see Subclause 8.3.15
-
MultiplicityIndicator see Subclause 8.3.15
-
Statement see Subclause 9.1
Semantics
The local name in a local name declaration statement must be unassigned before the statement and before the expression in the statement. It must remain unassigned after the expression. The assigned source for the name after the local name declaration statement is the statement itself.
Typing
The new local name has the type given by the type name in the statement (see Subclause 8.2 on type names). If the type name is a qualified name, it must resolve to a classifier that is not a template, though it may be the binding of a template. If the multiplicity indicator “[]” is specified with the type, then the multiplicity of the local name is [0..*]. Otherwise it is [0..1] and the multiplicity upper bound of the assigned expression must not be greater than 1.
Alf does not require that a local name be explicitly declared before its first use. If not explicitly declared, the type of the local name is determined by its first assignment (see Subclause 8.8). However, if the type is explicitly declared, it may be more general than the type of the initially assigned expression, allowing a wider range of values in later assignments.
For example, the following is legal:
let v: Vehicle = new Car();
v = new Truck();
presuming that Car and Truck are both subclasses of Vehicle. However, the following would not be legal:
v = new Car();
v = new Truck(); // Type error!
because the initial assignment would determine the type of v as being Car, which is not compatible with Truck.
A similar effect to the legal assignment above can be achieved using a type cast (see Subclause 8.5.5):
v = (Vehicle)new Car();
v = new Truck(); // Legal
Even though the initial value assigned to v here is a Car, the type of the expression “(Vehicle)new Car()” is Vehicle, due to the cast. Therefore, the initial assignment determines the type of v as being Vehicle, so the second assignment is legal.
However, there is an important semantic difference. Type casts in Alf filter values that cannot be cast, so that
v = (Vehicle)new House();
is legal and will assign null to v. On the other hand, the following is not legal:
let v: Vehicle = new House(); // Type error!
since the class House does not statically conform to the declared type Vehicle.
Initialization Expressions
Since a local name declaration statement already includes an explicit declaration of the type of a new name, it is possible to use simplified forms for sequence construction expressions (see Subclause 8.3.15) and instance creation expressions (see Subclause 8.3.12) used as initialization expressions in local name declaration statements. In these simplified forms, the explicit type part usually included in the expressions may be omitted, with the type declared as part of the statement being used instead.
For example, in the statement
let fixedAssets: RealProperty[] = { land, home, condominium };
the type part normally required for a sequence construction expression has been omitted. The statement is equivalent to one in which the type part for the sequence construction expression is the same as the type declared for the new local name:
let fixedAssets: RealProperty[] = RealProperty[]{ land, home, condominium };
This simplified form may also be used when initializing collection objects. Thus, the statement
let fixedAssets: Set = { land, home, condominium };
is equivalent to
let fixedAssets: Set =
Set{ land, home, condominium };
Similarly, in the statement
let origin : Point = new(0,0);
the explicit constructor description has been omitted from the instance creation expression, leaving only the keyword new and the tuple. The statement is equivalent to one in which the instance creation expression is explicitly for the type declared for the new local name:
let origin : Point = new Point(0,0);
NOTE. The initialization expression short hands can also be used in Alf expressions representing default values, either as integrated with a non-Alf representation of a property or parameter (see Subclause 8.1) or as the initializer for the definition of an attribute in Alf (see Subclause 10.5.2).
Share with your friends: |