【发布时间】:2016-09-26 03:44:11
【问题描述】:
我试图在 Alloy 中生成两组类,例如,重构应用程序之前的类和重构应用程序之后的类。假设在第一组中我们有以下类:
a -> br -> cr
class1
class2
表示 a 是 br 的父级,br 又是 cr、class1 和 class2 的父级。
另一方面,按照相同的推理,我们在第二组中有以下一组类:
a -> bl -> cl
class1
class2
类 br、bl、cr 和 cl 是实际参与重构的类。此外,br 和bl 实际上是同一个类(并且具有相同的标识)但时间顺序不同(不同的状态),cr 和cl 也是如此。所表示的重构是对下推方法的简化,其中方法从 br 下推到 cl 类。
支持这种转换的模型简化如下:
open util/relation
abstract sig Id {}
sig ClassId, MethodId, FieldId extends Id {}
abstract sig Accessibility {}
one sig public, private_, protected extends Accessibility {}
abstract sig Type {}
abstract sig PrimitiveType extends Type {}
one sig Long_ extends PrimitiveType {}
abstract sig Class {
extend: lone ClassId,
methods: MethodId -> one Method,
fields: set Field
}
sig Field {
id: one FieldId,
type: one Type,
acc : one Accessibility,
}
sig Method {
return: lone Type,
acc: one Accessibility,
body: seq Statement
}
abstract sig Expression {}
abstract sig Statement{}
abstract sig PrimaryExpression extends Expression {
}
one sig this_, super extends PrimaryExpression {}
sig newCreator extends PrimaryExpression {
id_cf : one ClassId
}
sig MethodInvocation extends Statement{
pExp: one PrimaryExpression,
id_methodInvoked: one MethodId
}
sig Program {
classDeclarations: ClassId -> one Class
}
pred wellFormedProgram [p:Program] {
all c:ClassId | c in (p.classDeclarations).univ => wellFormedClass[p, c]
}
pred wellFormedClass[p:Program, c:ClassId] {
let class = c.(p.classDeclarations) {
all m:Method, mId:MethodId | m = mId.(class.methods) => wellFormedMethod[p, class, m, mId]
}
}
pred wellFormedMethod[p:Program, c:Class, m:Method, mId:MethodId]{
let body = (m.body).elems
{
all stm : Statement | stm in body => wellFormedStatement[p, c, stm]
}
}
pred wellFormedStatement[p:Program, c:Class, st:Statement]{
st in MethodInvocation => wellFormedMethodInvocation[p,c,st/*,m.param*/]
}
pred wellFormedMethodInvocation[p:Program, c:Class, stm: MethodInvocation] {
stm.pExp in PrimaryExpression => wellFormedPrimaryExpression[p, c, stm.pExp]
let target = stm.pExp {
target in newCreator => stm.id_methodInvoked in ((target.id_cf).(p.classDeclarations).*(extend.(p.classDeclarations)).methods).univ
target in this_ => stm.id_methodInvoked in (c.*(extend.(p.classDeclarations)).methods).univ
target in super => stm.id_methodInvoked in (c.^(extend.(p.classDeclarations)).methods).univ
}
}
pred wellFormedPrimaryExpression[p:Program, c:Class, stm: PrimaryExpression] {
stm in newCreator => classIsDeclared[p, stm.id_cf]
}
pred classIsDeclared[p:Program, c:ClassId] {
let cds = p.classDeclarations {
c in cds.univ
}
}
pred law14RL[b, c:ClassId, mId:MethodId, left, right: Program] {
wellFormedProgram[right]
let leftCds = left.classDeclarations,
rightCds= right.classDeclarations,
bl = b.leftCds,
br = b.rightCds,
cl = c.leftCds,
cr = c.rightCds,
mRight = mId.(br.methods),
mLeft = mId.(cl.methods)
{
mRight = mLeft
cr.extend = b
cl.extend = b
bl.extend = br.extend
leftCds = rightCds ++ {b -> bl} ++ {c -> cl}
all c:{Class - br - cl} | mId !in (c.methods).univ
cl.fields = cr.fields
bl.fields = br.fields
bl.methods = br.methods - {mId -> mRight}
cl.methods - {mId -> mLeft} = cr.methods
}
}
assert law14Prop {
all b, c:ClassId, mId:MethodId, left, right: Program |
law14RL[b, c, mId, left, right] implies wellFormedProgram[left]
}
check law14Prop for 15 but exactly 2 Program
看到谓词 law14RL 描述了转换本身以及 b 和 c 类的等价性(通过比较它们的方法和字段 - 在这个谓词的末尾)。我们看到 b 类之间的唯一区别是 br 类中的方法 mRight;类似地,方法 mLeft 存在于 cl 类中,但不存在于 cr 类中。创建断言 law14Prop 是为了返回 Alloy 实例,该实例描述了由于方法的移动而具有编译错误问题(在转换的结果侧)的程序表示。
例如,假设在 br 类中有一个方法 m',其主体包含类似 this.mId() 的语句。如上所述,mId 表示mRight 方法的标识。该语句应该会导致 bl 类中的编译错误,因为方法 m' 也存在于那里,但是由 mId 标识表示的方法(方法 mLeft)在 cl 类中而是。
关键(问题)是这个模型没有返回任何反例,我不明白为什么。我做错了什么?
奇怪的是,当我将 sig Class 中的关系 methods 替换为 set Method (而不是 MethodId -> Method em>) - 当然在模型中进行必要的修改 - 返回反例。
【问题讨论】: