10.3.2 计算包的良构规则
定义在计算包的元类具有如下的良构规则。这些规则声明了如何决定结果值。它定义了OCL表达式的语义。
AssociationClassCallExpEval
[1] 关联类调用表达式的结果值是它所引用的关联类名称所绑定到的值。注意,当有限定符时对结果值的判定在10.4.2.1(AS-Domain-Mapping.exp-eval包的良构规则)中规定。操作 getCurrentValueOf 是一个定义在ObjectValue (在10.2.3 Values包的其它操作)上的操作。
context AssociationClassCallExpEval inv:
qualifiers->size() = 0 implies resultValue =
source.resultValue.getCurrentValueOf(referredAssociationClass.name)
AssociationEndCallExpEval
[1] 关联端调用表达式的结果值是它所引用的关联端名称所绑定的值。注意,当有限定符时对结果值的判定在10.4.2.1 AS-Domain-Mapping.exp-eval Package的良构规则中进行规定。
context AssociationEndCallExpEval inv:
qualifiers->size = 0 implies resultValue =
source.resultValue.getCurrentValueOf(referredAssociationEnd.name)
AttributeCallExpEval
[1] 属性调用表达式的结果值是属性名所绑定的值。
context AttributeCallExpEval inv:
resultValue = if source.resultValue->oclIsTypeOf( ObjectValue) then
source.resultValue->oclAsType( ObjectValue).getCurrentValueOf(referredAttribute.value)
else -- must be a tuple value
source.resultValue->oclAsType(TupleValue).getValueOf(referredAttribute.value)
endif
BooleanLiteralExpEval
无额外良构规则。结果值的判定方式在10.4.2.1 AS-Domain-Mapping.exp-eval Package的良构规则中给出。
CollectionItemEval
[1] 集合元素的值是它的item表达式的结果值。item表达式的环境等同于集合元素计算的环境。
context CollectionItemEval
inv: element = item.resultValue
inv: item.environment = self.environment
CollectionLiteralExpEval
[1] 它的成员环境等同于集合字面量表达式计算的环境。
context CollectionLiteralExpEval
inv: parts->forAll( p | p.environment = self.environment )
[2] 集合字面量表达式计算的结果值是一个集合(或它的子类的)字面量值。
context CollectionLiteralExpEval
inv: resultValue.oclIsKindOf(CollectionValue)
[3] 结果值中的元素数目等同于集合字面量成员的数量,要考虑到集合区间可以产生许多元素。
context CollectionLiteralExpEval
inv: resultValue.elements->size() = parts->collect(element)->size()->sum()
[4] 结果值中的元素是集合字面量成员元素,要考虑到集合区间可以产生许多元素。
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
没有额外良构规则。它的值的判定方式由其子类给出。
CollectionRangeEval
[1] 集合区间的值是first表达式和last表达式值之间的整数区间。
context CollectionRangeEval
inv: element.oclIsTypeOf( Sequence(Integer) ) and
element = getRange( first->oclAsType(Integer), last->oclAsType(Integer) )
EnumLiteralExpEval
无额外良构规则。
EvalEnvironment
[1] 命名空间内的所有名称必须唯一。
context EvalEnvironment inv:
bindings->collect(name)->forAll( name: String | bindings->collect(name)->isUnique(name))
ExpressionInOclEval
无额外良构规则。
IfExpEval
[1] if 表达式的结果值在条件表达式为真时是thenExpression的结果,否则是elseExpression的值,再否则结果是无效的。
context IfExpEval inv:
resultValue = if condition then thenExpression.resultValue else elseExpression.resultValue endif
[2] condition, thenExpression 和 elseExpression的环境等同于if 表达式的环境。
context IfExpEval
inv: condition.environment = environment
inv: thenExpression.environment = environment
inv: elseExpression.environment = environment
IntegerLiteralExpEval
无额外良构规则。结果值的判定方式在10.4.2.1 AS-Domain-Mapping.exp-eval Package的良构规则中给出。
IterateExpEval
[1] 所有的子表达式具有不同的环境。第一个子计算将以源中的第一个元素为环境,外加初始化表达式绑定的结果变量。
context IterateExpEval
inv: let bindings: Sequence( NameValueBinding ) =
iterators->collect( i | NameValueBinding( i.value, source->asSequence()->first() )
in
bodyEvals->at(1).environment = self.environment->addAll( bindings )
->add( NameValueBinding( result.name, result.initExp.resultValue ))
[2] 其它子计算的环境与它之前的子计算具有相同的环境,还需要考虑到迭代器变量,外加上一次子计算绑定的结果值。
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)))
->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] IteratorExpEval的结果值是它的最后一次body计算结果。
context IteratorExpEval
inv: resultValue = bodyEvals->last().resultValue
IteratorExpEval
抽象语法中的IteratorExp在标准库(11章 OCL标准库)中只是一个预定义迭代器表达式的占位符。这些预定义的迭代器表达式都是根据迭代表达式定义的。迭代表达式定义的语义对于迭代器表达式足够了。IteratorExpEval没有定义其它良构规则。
LetExpEval
[1] let表达式在它的 in 表达式中产生值。
context LetExpEval inv:
resultValue = in.resultValue
[2] let表达式把将variable绑定到initExpression的名值绑定添加到它的in表达式环境中。
context LetExpEval
inv: in.environment = self.environment
->add( NameValueBinding( variable.varName, variable.initExpression.resultValue ))
[3] initExpression的环境等同于let表达式计算的环境。
context LetExpEval
inv: initExpression.environment = self.environment
LiteralExpEval
无额外良构规则。
LoopExpEval
循环表达式计算的结果值由它的子类型决定。
[1] 对于迭代器变量的值组合有一个OclExpEval子计算。每个迭代器变量都要对源集合的每个元素进行遍历。
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] 所有的子计算有不同的环境。第一个子计算以所有迭代器变量都绑定到源中的第一个元素的环境开始。注意,这是一种任意选择,建模者可以从源中的最后一个原始开始,或任意其它的组合。
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] 所有的子计算有不同的环境。该环境与前一次bodyEval的环境相同,其中迭代器变量绑定到了源中的下一个元素。
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
结果值由其子类决定。
[1] ModelPropertyCall表达式的环境等同于它的源的环境。
context ModelPropertyCallExpEval inv:
environment = source.environment
NavigationCallExpEval
[1] 当导航调用表达式有限定符时,结果值被限制到那些限定符值等同于属性值的元素上。
---尚未完成
NumericLiteralExpEval
无额外良构规则。结果值由它的子类决定。
OclExpEval
结果值由它的子类决定。
[1] OclExpEval的环境由它的上下文,即ExpressionInOclEval决定。
context OclExpEval
inv: environment = context.environment
[2] 每个OclExpEval都有一个环境,其中至多有一个已知的self 实例。
context OclExpEval
inv: environment->select( name = ‘self’ )->size() = 1
OclMessageExpEval
[1] ocl消息表达式的结果值是一个ocl消息值。
context OclMessageExpEval
inv: resultValue->isTypeOf( OclMessageValue )
[2] ocl消息表达式的结果值是与该表达式匹配的‘self’对象的发送消息队列。注意,当表达式与任意发送消息都不匹配时,将产生一个空序列。
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] 结果ocl消息值的源等同于该ocl消息表达式的‘self’对象。
context OclMessageExpEval
inv: resultValue.source = environment.getValueOf( ‘self’ )
[4] 结果ocl消息值的 isSent属性只有在该消息值在‘self’对象的输出消息队列中时才为真。
context OclMessageExpEval
inv: if resultValue.oclIsUndefined() then
resultValue.isSent = false
else
resultValue.isSent = true
endif
[5] ocl消息表达式的目标是一个对象值。
context OclMessageExpEval
inv: target.resultValue->isTypeOf( ObjectValue )
[6] 所有实参的环境和目标表达式的环境都等同于ocl消息值的环境。
context OclMessageExpEval
inv: arguments->forAll( a | a.environment = self.environment )
inv: target.environment = self.environment
OclMessageArgEval
[1] ocl消息实参计算要么是一个ocl表达式计算,要么是一个未规定值表达式计算,不能二者兼之。
context OclMessageArgEval
inv: expression->size() = 1 implies unspecified->size() = 0
inv: expression->size() = 0 implies unspecified->size() = 1
[2] ocl消息实参的结果值由它的表达式或未规定值表达式的结果值类决定。
context OclMessageArgEval inv:
if expression->size() = 1
then resultValue = expression.resultValue
else resultValue = unspecified.resultValue
endif
[3] 表达式和为规定值表达式的环境等同于该ocl消息实参的环境。
context OclMessageArgEval
inv: expression.environment = self.environment
inv: unspecified.environment = self.environment
OperationCallExpEval
操作调用表达式的语义定义取决于UML语义中的操作调用执行定义。它是UML基础设施规范的一部分,不会在此进行定义。对于OperationCallExp的语义,知道操作调用的执行会产生正确类型的结果(在10.4 AS-Domain-Mapping包规定)就足够了。
[1] 操作调用表达式的实参的环境等同于该调用的环境。
context OperationCallExpEval inv:
arguments->forall( a | a.environment = self.environment )
PropertyCallExpEval
结果值和环境由它的子类决定。
[1] 属性调用表达式的源的环境等同于该调用的环境。
context PropertyCallExpEval inv:
source.environment = self.environment
PrimitiveLiteralExpEval
无额外良构规则。结果值由它的子类决定。
RealLiteralExpEval
无额外良构规则。结果值由10.4.2.1 AS-Domain-Mapping.exp-eval包的良构规则给出。
StringLiteralExpEval
无额外良构规则。结果值由10.4.2.1 AS-Domain-Mapping.exp-eval包的良构规则给出。
TupleLiteralExpEval
[1] 元组字面量表达式计算的结果值是一个元组值,它的成员对应元组字面量表达式计算的成员。
context TupleLiteralExpEval inv:
resultValue.oclIsTypeOf( 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 )
UnlimitedNaturalLiteralExpEval
无额外良构规则。结果值由10.4.2.1 AS-Domain-Mapping.exp-eval包的良构规则给出。
UnspecifiedValueExpEval
未规定值表达式的结果是随机选择的该表达式类型的一个实例。该规则将在10.4.2.1 AS-Domain-Mapping.exp-eval包的良构规则中定义。
VariableDeclEval
无额外良构规则。
VariableExpEval
[1] VariableExpEval的结果是该变量所指名称所绑定的值。
context VariableExpEval inv:
resultValue = environment.getValueOf(referredVariable.varName)