The Evaluations Package


This section defines the evaluations of OCL expressions. The evaluations package is a mirror image of the expressions package from the abstract syntax. Figure 19  shows how the environment of an OCL expression evaluation is structured. The environment is determined by the placement of the expression within the UML model as discussed in Chapter 12 ("The Use of Ocl Expressions in UML Models"). The calculation of the environment is done in the ExpressionInOclEval, which will be left undefined here.

Figure 20 shows the core part of the Evaluations package. The basic elements in the package are the classes OclEvaluation, PropertyCallExpEval and VariableExpEval. An OclEvaluation always has a result value, and a name space that binds names to values. In Figure 21 the various subtypes of model propertycall evaluation are defined.

Most of the OCL expressions can be simply evaluated, i.e. their value can be determined based on a non-changing set of name value bindings. Operation call expressions, however, need the execution of the called operation. The semantics of the execution of an operation will be defined in the UML infrastructure. For our purposes it is enough to assume that an operation execution will add to the environment of an OCL expression the name `result' bound to a certain value. In order
not to become tangled in a mix of terms, the term evaluation is used in the following to denote both the `normal' OCL evaluations and the executions of operation call expressions.

In sections 10.3.2 ("Model PropertyCall Evaluations") to 10.3.6 ("Let expressions") special subclasses of OclExpEval will be defined.

Definitions of concepts for the Evaluations package

The section lists the definitions of concepts in the Evaluations package in alphabetical order.

EvalEnvironment

A EvalEnvironment is a set of NameValueBindings that form the environment in which an OCL expression is evaluated.
A EvalEnvironment has three operations which are defined in the section ("Additional operations of the Evaluations package").

Associations
IterateExpEval

An IterateExpEval is an expression evaluation which evaluates its body expression for each element of a collection value, and accumulates a value in a result variable. It evaluates an IterateExp.

IteratorExpEval

An IteratorExp is an expression evaluation which evaluates its body expression for each element of a collection.







ExpressionInOclEval

An ExpressionInOclEval is an evaluation of the context of an OCL expression. It is the counterpart in the domain of the ExpressionInOcl metaclass defined in Chapter 12 ("The Use of Ocl Expressions in UML Models"). It is merely included here to be able to determine the environment of an OCL expression.

LiteralExpEval

A Literal expression evaluation is an evaluation of a Literal expression.

LoopExpEval

A loop expression evaluation is an evaluation of a Loop expression.

Associations
ModelPropertyCallExpEval

A model property call expression evaluation is an evaluation of a ModelPropertyCallExp. In Figure 21 on page 106 the various subclasses of ModelPropertyCallExpEval are shown.

Operations

OclExpEval

An ocl expression evaluation is an evaluation of an OclExpression. It has a result value, and it is associated with a set of name-value bindings, called environment. These bindings represent the values that are visible for this evaluation, and the names by which they can be referenced. A second set of name-value bindings is used to evaluate any sub expression for which the operation atPre returns true, called beforeEnvironment.

Note that as explained in chapters 9 ("Concrete Syntax") and 12 ("The Use of Ocl Expressions in UML Models"), these bindings need to be established, based on the placement of the OCL expression within the UML model. A binding for an invariant will not need the beforeEnvironment, and it will be different from a binding of the same expression when used as precondition.

Associations
OclMessageExpEval

An ocl message expression evaluation is defined in Section 10.3.4 ("Ocl Message Expression Evaluations"), but included in this diagram for completeness.

PropertyCallExpEval

A property call expression evaluation is an evaluation of a PropertyCallExp.

Associations
VariableDeclEval

A variable declaration evaluation represents the evaluation of a variable declaration. Note that this is not a subtype of OclExpEval, therefore it has no resultValue.

Associations


VariableExpEval

A variable expression evaluation is an evaluation of a VariableExp, which in effect is the search of the value that is bound  to the variable name within the environment of the expression.

Associations

Model PropertyCall Evaluations

The subtypes of ModelPropertyCallExpEval are shown in Figure 21, and are defined in this section in alphabetical order.



AssociationClassCallExpEval

An association end call expression evaluation is an evaluation of a AssociationClassCallExp, which in effect is the search of the value that is bound to the associationClass name within the expression environment.

Associations
AssociationEndCallExpEval

An association end call expression evaluation is an evaluation of a AssociationEndCallExp, which in effect is the search of the value that is bound to the associationEnd name within the expression environment.

Associations
AttributeCallExpEval

An attribute call expression evaluation is an evaluation of an AttributeCallExp, which in effect is the search of the value that is bound to the attribute name within the expression environment.

Associations
NavigationCallExpEval

A navigation call expression evaluation is an evaluation of a NavigationCallExp.

Associations
OperationCallExp

An operation call expression evaluation is an evaluation of an OperationCallExp.

Associations

 If Expression Evaluations

If expression evaluations are shown in Figure 22, and defined in this section.



IfExpEval

An IfExpEval is an evaluation of an IfExp.

Associations

Ocl Message Expression Evaluations

Ocl message expressions are used to specify the fact that an object has, or will sent some message to another object at a some moment in time. Ocl message expresssion evaluations are shown in Figure 23 , and defined in this section.

OclMessageArgEval

An ocl message argument evaluation is an evaluation of a OclMessageArg. It represents the evaluation of the actual parameters to the Operation or Signal. An argument of a message expression is either an ocl expression, or a variable declaration.

Associations

OclMessageExpEval

An ocl message expression evaluation is an evaluation of a OclMessageExp. As explained in [Kleppe2000] the only demand we can put on the ocl message expression is that the OclMessageValue it represents (either an operation call, or a UML signal), has been at some time between `now' and a reference point in time in the output queue of the sending instance. The `now' timepoint is the point in time at which this evaluation is performed. This point is represented by the
environment link of the OclMessageExpEval (inherited from OclExpEval).

Associations
UnspecifiedValueExpEval

An unspecified value expression evaluation is an evaluation of an UnSpecifiedValueExp. It results in a randomly picked instance of the type of the expression.

Literal Expression Evaluations

This section defines the different types of literal expression evaluations in OCL, as shown in Figure 24 .Again it is a complete mirror image of the abstract syntax.

BooleanLiteralExpEval

A boolean literal expression evaluation represents the evaluation of a boolean literal expression.

CollectionItemEval

A collection item evaluation represents the evaluation of a collection item.

CollectionLiteralExpEval

A collection literal expression evaluation represents the evaluation of a collection literal expression.

CollectionLiteralPartEval

A collection literal part evaluation represents the evaluation of a collection literal part.

CollectionRangeEval

A collection range evaluation represents the evaluation of a collection range.


EnumLiteralExpEval

An enumeration literal expression evaluation represents the evaluation of an enumeration literal expression.

IntegerLiteralExpEval

A integer literal expression evaluation represents the evaluation of a integer literal expression.

NumericLiteralExpEval

A numeric literal expression evaluation represents the evaluation of a numeric literal expression.

PrimitiveLiteralExpEval

A primitive literal expression evaluation represents the evaluation of a primitive literal expression.

RealLiteralExpEval

A real literal expression evaluation represents the evaluation of a real literal expression.

StringLiteralExpEval

A string literal expression evaluation represents the evaluation of a string literal expression.

TupleLiteralExpEval

A tuple literal expression evaluation represents the evaluation of a tuple literal expression.

TupleLiteralExpPartEval

A tuple literal expression part evaluation represents the evaluation of a tuple literal expression part.

Let expressions

Let expressions define new variables. The structure of the let expression evaluation is shown in Figure 25.


LetExpEval

A Let expression evaluation is an evaluation of a Let expression that defines a new variable with an initial value. A Let expression evaluation changes the environment of the in expression evaluation.

Associations

Well-formedness Rules of the Evaluations package

The metaclasses defined in the evaluations package have the following well-formednes rules. These rules state how the result value is determined. This defines the semantics of the OCL expressions.

AssociationClassCallExpEval

[1] The result value of an association class call expression is the value bound to the name of the association class to which it refers. Note that the determination of the result value when qualifiers are present is specified in Section 10.4.3 ("Well-formedness rules for the AS-Domain-Mapping.exp-eval Package"). The operation getCurrentValueOf is an operation defined on ObjectValue in Section 10.2.3 ("Additional operations for the Values Package").

    context AssociationClassCallExpEval inv: 1
        qualifiers->size = 0 implies
            resultValue =
                source.resultValue.getCurrentValueOf(referredAssociationClass.name)

AssociationEndCallExpEval

[1] The result value of an association end call expression is the value bound to the name of the association end to which it refers. Note that the determination of the result value when qualifiers are present is specified in Section 10.4.3 ("Well-formedness rules for the AS-Domain-Mapping.exp-eval Package").

context AssociationEndCallExpEval inv:
    qualifiers->size = 0 implies
        resultValue =
            source.resultValue.getCurrentValueOf(referredAssociationEnd.name)


AttributeCallExpEval

[1] The result value of an attribute call expression is the value bound to the name of the attribute to which it refers.

context AttributeCallExpEval inv:
    resultValue = if source.resultValue->isOclType( ObjectValue) then
                    source.resultValue->asOclType( ObjectValue )
                           .getCurrentValueOf(referredAttribute.name)
              else -- must be a tuple value
                    source.resultValue->asOclType( TupleValue )
                        .getValueOf(referredAttribute.name)
              endif

BooleanLiteralExpEval

No extra well-formedness rules. The manner in which the resultValue is determined is given in Section 10.4.3 ("Well-formedness rules for the AS-Domain-Mapping.exp-eval Package").

CollectionItemEval

[1] The value of a collection item is the result value of its item expression. The environment of this item expression is equalto the environment of the collection item evaluation.

context CollectionItemEval
inv: element = item.resultValue
inv: item.environment = self.environment

CollectionLiteralExpEval

[1] The environment of its parts is equal to the environment of the collection literal expression evaluation.

context CollectionLiteralExpEval
inv: parts->forAll( p | p.environment = self.environment )

[2] The result value of a collection literal expression evaluation is a collection literal value, or one of its subtypes.

context CollectionLiteralExpEval inv:
        resultValue.isOclKind( CollectionValue )

[3] The number of elements in the result value is equal to the number of elements in the collection literal parts, taking into account that a collection range can result in many elements.

context CollectionLiteralExpEval inv:
        resultValue.elements->size() = parts->collect( element )->size()->sum()

[4] The elements in the result value are the elements in the collection literal parts, taking into account that a collection range can result in many elements.

context CollectionLiteralExpEval inv:
let allElements = parts->collect( element )->flatten() in
    Sequence{1..allElements->size()}->forAll( i: Integer |
        resultValue.elements->at(i).name = '' and
        resultValue.elements->at(i).value = allElements->at(i) and
        self.kind = CollectionKind::Sequence implies
            resultValue.elements->at(i).indexNr = i )

CollectionLiteralPartEval

No extra well-formedness rules. The manner in which its value is determined is given by its subtypes.

CollectionRangeEval

[1] The value of a collection range is the range of integer numbers between the result value of its first expression and its last expression.

context CollectionRangeEval
inv: element.isOclType( Sequence(Integer) ) and
        element = getRange( first->asOclType(Integer), last->asOclType(Integer) )

EnumLiteralExpEval

No extra well-formedness rules.

EvalEnvironment

[1] All names in a name space must be unique.

context EvalEnvironment inv:
    bindings->collect(name)->forAll( name: String | bindings->collect(name)->isUnique(name))

ExpressionInOclEval

No extra well-formedness rules.

IfExpEval

[1] The result value of an if expression is the result of the thenExpression if the condition is true, else it is the result of the elseExpression.

context IfExpEval inv:
    resultValue = if condition then thenExpression.resultValue else elseExpression.resultValue

[2] The environment of the condition, thenExpression and elseExpression are both equal to the environment of the if expression.

context IfExpEval
inv: condition.environment = environment
inv: thenExpression.environment = environment
inv: elseExpression.environment = environment

IntegerLiteralExpEval

No extra well-formedness rules. The manner in which the resultValue is determined is given in Section 10.4.3 ("Well-formedness rules for the AS-Domain-Mapping.exp-eval Package").

IterateExpEval

[1] All sub evaluations have a different environment. The first sub evaluation will start with an environment in which all iterator variables are bound to the first element of the source, plus the result variable which is bound to the init expression of the variable declaration in which it is defined.

context IterateExpEval
inv: let bindings: Sequence( NameValueBindings ) =
    iterators->collect( i |
            NameValueBinding( i.varName, source->asSequence()->first() )
        in
             bodyEvals->at(1).environment = self.environment->addAll( bindings )
                    ->add( NameValueBinding( result.name, result.initExp.resultValue ))

[2] The environment of any sub evaluation is the same environment as the one from its previous sub evaluation, taking  into account the bindings of the iterator variables, plus the result variable which is bound to the result value of the last  sub evaluation.

inv: let SS: Integer = source.value->size()
    in if iterators->size() = 1 then
           Sequence{2..SS}->forAll( i: Integer |
                body  Evals->at(i).environment = bodyEvals->at(i-1).environment
                    ->replace( NameValueBinding( iterators->at(1).varName,
                        source.value->asSequence()->at(i)))
                ->replace( NameValueBinding( result.varName,
                        bodyEvals->at(i-1).resultValue )))
        else -- iterators->size() = 2
            Sequence{2..SS*SS}->forAll( i: Integer |
                bodyEvals->at(i).environment = bodyEvals->at(i-1).environment
                     ->replace( NameValueBinding( iterators->at(1).varName,
                         source->asSequence()->at(i.div(SS) + 1) ))
                ->replace( NameValueBinding( iterators->at(2).varName,
                    source.value->asSequence()->at(i.mod(SS))))
        ->replace( NameValueBinding( result.varName,
    bodyEvals->at(i-1).resultValue )))
endif

[3] The result value of an IteratorExpEval is the result of the last of its body evaluations.

context IteratorExpEval
inv: resultValue = bodyEvals->last().resultValue

IteratorExpEval

The IteratorExp in the abstract syntax is merely a placeholder for the occurence of one of the predefined iterator  expressions in the standard library (see Chapter 11 ("The OCL Standard Library")). These predefined iterator expressions are all defined in terms of an iterate expression. The semantics defined for the iterate expression are sufficient to define  the iterator expression. No well-formedness rules for IteratorExpEval are defined.

LetExpEval

[1] A let expression results in the value of its in expression.

context LetExpEval inv:
resultValue = in.resultValue

[2] A let expression evaluation adds a name value binding that binds the variable to the value of its initExpression, to the environment of its in expression.

context LetExpEval
inv: in.environment = self.environment
    ->add( NameValueBinding( variable.varName, variable.initExpression.resultValue ))

[3] The environment of the initExpression is equal to the environment of this Let expression evaluation.

context LetExpEval
inv: initExpression.environment = self.environment

LiteralExpEval

No extra well-formedness rules.

LoopExpEval

The result value of a loop expression evaluation is determined by its subtypes.

[1] There is an OclExpEval (a sub evaluation) for combination of values for the iterator variables. Each iterator variable will run through every element of the source collection.

context LoopExpEval
inv: bodyEvals->size() =
    if iterators->size() = 1 then
        source.value->size()
    else -- iterators->size() = 2
        source.value->size() * source.value->size()
endif

[2] All sub evaluations (in the sequence bodyEvals) have a different environment. The first sub evaluation will start with  an environment in which all iterator variables are bound to the first element of the source. Note that this is an  arbitrary choice, one could easily well start with the last element of the source, or any other combination.

context LoopExpEval
inv: let bindings: Sequence( NameValueBindings ) =
    iterators->collect( i |
        NameValueBinding( i.varName, source->asSequence()->first() )
    in
        bodyEvals->at(1).environment = self.environment->addAll( bindings )

[3] All sub evaluations (in the sequence bodyEvals) have a different environment. The environment is the same  environment as the one from the previous bodyEval, where the iterator variable or variables are bound to the subsequent elements of the source.

context LoopExpEval
inv:
    let SS: Integer = source.value->size()
        in if iterators->size() = 1 then
            Sequence{2..SS}->forAll( i: Integer |
                bodyEvals->at(i).environment = bodyEvals->at(i-1).environment
                        ->replace( NameValueBinding( iterators->at(1).varName,
                            source.value->asSequence()->at(i) )))
             else -- iterators->size() = 2
                    Sequence{2..SS*SS}->forAll( i: Integer |
                          bodyEvals->at(i).environment = bodyEvals->at(i-1).environment
                                ->replace( NameValueBinding( iterators->at(1).varName,
                                        source->asSequence()->at(i.div(SS) + 1) ))
                                ->replace( NameValueBinding( iterators->at(2).varName,
                                        source.value->asSequence()->at(i.mod(SS)) )) ) ))
            endif

ModelPropertyCallExpEval

Result value is determined by its subtypes.

[1] The environment of an ModelPropertyCall expression is equal to the environment of its source.

    context ModelPropertyCallExpEval inv:
  environment = source.environment

NavigationCallExpEval

[1] When the navigation call expression has qualifiers, the result value is limited to those elements for which the qualifier value equals the value of the attribute.

-- To be done.

NumericLiteralExpEval

No extra well-formedness rules. Result value is determined by its subtypes.

OclExpEval

The result value of an ocl expression is determined by its subtypes.

[1] The environment of an OclExpEval is determined by its context, i.e. the ExpressionInOclEval.

    context OclExpEval
  inv: environment = context.environment

[2] Every OclExpEval has an environment in which at most one self instance is known.

  context OclExpEval
  inv: environment->select( name = 'self' )->size() = 1

OclMessageExpEval

[1] The result value of an ocl message expression is an ocl message value.

    context OclMessageExpEval
    inv: resultValue->isTypeOf( OclMessageValue )


[2] The result value of an ocl message expression is the sequence of the outgoing messages of the `self' object that matches the expression. Note that this may result in an empty sequence when the expression does not match to any of the outgoing messages.

context OclMessageExpEval
inv: resultValue =
    environment.getValueOf( 'self' ).outgoingMessages->select( m |
        m.target = target.resultValue and
        m.name = self.name and
        self.arguments->forAll( expArg: OclMessageArgEval |
        not expArg.resultValue.oclIsUndefined() implies
                m.arguments->exists( messArg | messArg.value = expArg.value ))


[3] The source of the resulting ocl message value is equal to the `self' object of the ocl message expression.

    context OclMessageExpEval
  inv: resultValue.source = environment.getValueOf( 'self' )

[4] The isSent attribute of the resulting ocl message value is true only if the message value is in the outgoing messages of the `self' object.

context OclMessageExpEval
inv:
    if resultValue.oclIsUndefined()
        resultValue.isSent = false
    else
        resultValue.isSent = true
    endif

[5] The target of an ocl message expression is an object value.

    context OclMessageExpEval
    inv: target.resultValue->isTypeOf( ObjectValue )

[6] The environment of all arguments, and the environment of the target expression are equal to the environment of  this ocl message value.

context OclMessageExpEval
inv: arguments->forAll( a | a.environment = self.environment )
inv: target.environment = self.environment

OclMessageArgEval
[1] An ocl message argument evaluation has either an ocl expression evaluation, or an unspecified value expression evaluation, not both.

    context OclMessageArgEval inv:
        expression->size() = 1 implies unspecified->size() = 0
        expression->size() = 0 implies unspecified->size() = 1

[2] The result value of an ocl message argument is determined by the result value of its expression, or its unspecified  value expression.

    context OclMessageArgEval inv:
        if expression->size() = 1
        then resultValue = expression.resultValue
        else resultValue = unspecified.resultValue
        endif

[3] The environment of the expression and unspecified value are equal to the environment of this ocl message argument.

    context OclMessageArgEval
    inv: expression.environment = self.environment
    inv: unspecified.environment = self.environment

OperationCallExpEval

The definition of the semantics of the operation call expression depends on the definition of operation call execution in the UML semantics. This is part of the UML infrastructure specification, and will not be defined here. For the semantics of the OperationCallExp it suffices to know that the execution of an operation call will produce a result of the correct type. The latter will be specified in Section 10.4 ("The AS-Domain-Mapping Package").

[1] The environments of the arguments of an operation call expression are equal to the environment of this call.

    context OperationCallExpEval inv:
    arguments->forall( a | a.environment = self.environment )

PropertyCallExpEval

The result value and environment are determined by its subtypes.

[1] The environment of the source of an property call expression is equal to the environment of this call.

    context PropertyCallExpEval inv:
    source.environment = self.environment

PrimitiveLiteralExpEval

No extra well-formedness rules. The result value is determined by its subtypes.

RealLiteralExpEval

No extra well-formedness rules. The manner in which the resultValue is determined is given in Section 10.4.3 ("Well-formedness rules for the AS-Domain-Mapping.exp-eval Package").

StringLiteralExpEval

No extra well-formedness rules. The manner in which the resultValue is determined is given in Section 10.4.3 ("Well-formedness rules for the AS-Domain-Mapping.exp-eval Package").

TupleLiteralExpEval

[1] The result value of a tuple literal expression evaluation is a tuple value whose elements correspond to the parts of the tuple literal expression evaluation.

context TupleLiteralExpEval inv:
    resultValue.isOclType( TupleValue ) and
    tuplePart->size() = resultValue.elements->size() and
    Sequence{1..tuplePart->size()}->forAll( i: Integer |
            resultValue.elements->at(i).name = tuplePart.name and
            resultValue.elements->at(i).value = tuplePart.initExpression.resultValue )

UnspecifiedValueExpEval

The result of an unspecified value expression is a randomly picked instance of the type of the expression. This rule will be defined in 10.4.3 ("Well-formedness rules for the AS-Domain-Mapping.exp-eval Package").

VariableDeclEval

No extra well-formedness rules.

VariableExpEval

[1] The result of a VariableExpEval is the value bound to the name of the variable to which it refers.

    context VariableExpEval inv:
  resultValue = environment.getValueOf(referredVariable.varName)


Additional operations of the Evaluations package


EvalEnvironment

[1] The operation getValueOf results in the value that is bound to the name parameter in the bindings of a name space. Note that the value may be the UndefinedValue.

    context EvalEnvironment::getValueOf(n: String): Value
    pre: -- none
    post: result = bindings->any(name = n).value

[2] The operation replace replaces the value of a name, by the value given in the nvb parameter.

    context EvalEnvironment::replace(nvb: NameValueBinding): EvalEnvironment
    pre: -- none
    post: result.bindings = self.bindings
            ->excluding( self.bindings->any( name = nvb.name) )->including( nvb )

[3] The operation add adds the name and value indicated by the NameValueBinding given by the nvb parameter.

    context EvalEnvironment::add(nvb: NameValueBinding): EvalEnvironment
    pre: -- none
    post: result.bindings = self.bindings->including( nvb )

[4] The operation addAll adds all NameValueBindings in the nvbs parameter.

    context EvalEnvironment::add(nvbs: Collection(NameValueBinding)): EvalEnvironment
  pre: -- none
  post: result.bindings = self.bindings->union( nvbs )

CollectionRangeEval

[1] The operation getRange() returns a sequence of integers that contains all integer in the collection range.

    context CollectionRangeEval::getRange(first, last: Integer): Sequence(Integer)
    pre: -- none
    post: result = if first = last then
                            first->asSequence()
                        else
                            first->asSequence()->union(getRange(first + 1, last))
                        endif

Overview of the Values package


Figure 26  shows an overview of the inheritance relationships between the classes in the Values package.