我在Alloy中做一个模型来表示Java语言的一个子集。下面我们有这个模型的一些元素:
sig Method {
id : one MethodId,
param: lone Type,
return: one Type,
acc: lone Accessibility,
b: one Block
}
abstract sig Expression {}
abstract sig StatementExpression extends Expression {}
sig MethodInvocation extends StatementExpression{
pExp: lone PrimaryExpression,
id_methodInvoked: one Method,
param: lone Type
}
sig Block {
statements: seq StatementExpression
}
pred noRecursiveMethodInvocationCall [] {
no m:Method | m in ^getMethodInvokedInsideBody[m]
}
fun getMethodInvokedInsideBody [m: Method] : Method {
(univ.(m.b.statements)).id_methodInvoked
}
问题是Block必须是一个StatementExpression序列,同时应避免对同一方法的递归调用。因此,我在上面的解决方案中想到了。
当我尝试生成相应的实例时,我得到以下错误类型:
.
Name cannot be resolved; possible incorrect
function/predicate call; perhaps you used ( ) when you
should have used [ ]
This cannot be a correct call to fun
genericLawsMetaModel/javametamodel_withfield_final/getMethodInvokedInsideBody.
The parameters are
m:
{genericLawsMetaModel/javametamodel_withfield_final/Method}
so the arguments cannot be empty.
仍然关于这个问题,我也尝试更改谓词noRecursiveMethodInvocationCall的定义(从而消除了上述功能):
pred noRecursiveMethodInvocationCall [] {
no m:Method | m in ^( (univ.(m.b.statements)).id_methodInvoked )
}
但是,会出现新类型错误:
^ can be used only with a binary relation.
Instead, its possible type(s) are:
{genericLawsMetaModel/javametamodel_withfield_final/Method}
有任何线索吗?我只是想避免对同一方法的递归调用。 提前谢谢,
答案 0 :(得分:4)
您滥用传递闭包运算符 ^ 。 后者仅适用于二元关系,而不适用于函数。
因此我将MethodInvokedInsideBody声明为Method的一个字段,并按照你的方式使用传递闭包。
希望有所帮助:)
修改强>
以下是如何使用传递闭包运算符以实现您想要实现的目标的示例:
sig Method {
id : one MethodId,
param: lone Type,
return: one Type,
acc: lone Accessibility,
b: one Block
methodsInvokedInsideBody: set Method
}
pred noRecursiveMethodInvocationCall{
no m:Method | m in m.^methodsInvokedInsideBody
}