我正在使用合金的元模型来获取Java的一个子集。
下面我们有一些签名:
abstract sig Id {}
sig Package{}
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 Int_, Long_ extends PrimitiveType {}
sig Class extends Type {
package: one Package,
id: one ClassId,
extend: lone Class,
methods: set Method,
fields: set Field
}
sig Field {
id : one FieldId,
type: one Type,
acc : lone Accessibility
}
sig Method {
id : one MethodId,
param: lone Type,
acc: lone Accessibility,
return: one Type,
b: one Body
}
abstract sig Body {}
sig LiteralValue extends Body {} // returns a random value
abstract sig Qualifier {}
one sig this_, super_ extends Qualifier {}
sig MethodInvocation extends Body {
id_methodInvoked : one Method,
q: lone Qualifier
}
// return new A().k();
sig ConstructorMethodInvocation extends Body {
id_Class : one Class,
cmethodInvoked: one Method
}{
(this.@cmethodInvoked in (this.@id_Class).methods) || (this.@cmethodInvoked in ((this.@id_Class).^extend).methods && (this.@cmethodInvoked).acc != private_)
}
// return x;
// return this.x;
// return super.x;
sig FieldInvocation extends Body {
id_fieldInvoked : one Field,
qField: lone Qualifier
}
// return new A().x;
sig ConstructorFieldInvocation extends Body {
id_cf : one Class,
cfieldInvoked: one Field
}{
(this.@cfieldInvoked in (this.@id_cf).fields) || ( this.@cfieldInvoked in ((this.@id_cf).^extend).fields && (this.@cfieldInvoked).acc != private_)
}
在Java语言中,如果此方法不是私有方法,我们只能调用类中的方法(通过此类的实例化)。我试图通过以下签名在我的合金模型中表示这种限制:
sig ConstructorMethodInvocation extends Body {
id_Class : one Class,
cmethodInvoked: one Method
}{
(this.@cmethodInvoked in (this.@id_Class).methods || this.@cmethodInvoked in ((this.@id_Class).^extend).methods && (this.@cmethodInvoked).acc != private_)
因此,合金中的ConstructorMethodInvocation签名试图表示java中的结构,如new A()。x()。另外,方法x()只有在它不是类A的私有方法时才能被调用。因此,我将以下限制(在ConstructorMethodInvocation签名中)以避免调用类id_Class的私有方法:
(这个。@ cmethodInvoked in(this。@ id_Class).methods || this。@ cmethodInvoked in((this。@ id_Class)。^ extend).methods&&(this。@ cmethodInvoked).acc! =私人_)
但是,尽管存在此限制,解算器仍然坚持生成实例(对于ConstructorMethodInvocation),其中cmethodInvoked是id_Class的私有方法。使用ConstructorFieldInvocation也是如此。
有人看到我做错了吗?
答案 0 :(得分:1)
这是因为你在ConstructorMethodInvocation
sig的附加事实中错误地放置了括号:现在的方式,你有一个顶级析取,允许其中任何一个(cmethodInvoked
在{{1}中的实例或者(它在id_Class.methods
而不是私有)。如果您将附加的事实块更改为
id_Class.^extend.methods
你会得到预期的行为(星号运算符({
this.@cmethodInvoked in this.@id_Class.*extend.methods
this.@cmethodInvoked.acc != private_
}
)是反射传递闭包,它基本上与你想要写的原始析取相同;你仍然可以使用你的旧约束而只是修复括号)。
要检查是否存在方法为私有的任何*
个实例,我执行了
ConstructorMethodInvocation
没有找到反例。