Генерация явно несовместимых экземпляров сплава

Я делаю метамодель в сплаве для подмножества 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, подобную новой A().x(). Кроме того, метод x() может быть вызван только в том случае, если он не является приватным методом класса A. Итак, я поставил следующее ограничение (внутри подписи ConstructorMethodInvocation), чтобы избежать вызова приватных методов класса id_Class:

(this.@cmethodInvoked in (this.@id_Class).methods || this.@cmethodInvoked in ((this.@id_Class).^extend).methods && (this.@cmethodInvoked).acc != private_)

Однако, несмотря на это ограничение, решатель настаивает на создании экземпляров (для ConstructorMethodInvocation), где cmmethodInvoked — это закрытый метод id_Class. То же самое происходит и с ConstructorFieldInvocation .

Кто-нибудь видит, что я делаю неправильно?


person Tarciana    schedule 25.09.2013    source источник


Ответы (1)


Это потому, что вы неправильно разместили круглые скобки в добавленных фактах знака ConstructorMethodInvocation: так, как сейчас, у вас есть дизъюнкция верхнего уровня, которая допускает экземпляры, где либо (cmethodInvoked находится в id_Class.methods), либо (это в id_Class.^extend.methods и не является частным). Если вы измените этот блок добавленных фактов на

{
   this.@cmethodInvoked in this.@id_Class.*extend.methods 
   [email protected] != private_
}

вы получите предполагаемое поведение (оператор звезды (*) является отражающим транзитивным закрытием, и в основном это означает то же самое, что и исходная дизъюнкция, которую вы намеревались написать; вы все еще можете использовать свое старое ограничение и просто исправить круглые скобки).

Чтобы убедиться, что не может существовать никаких ConstructorMethodInvocation экземпляров, где метод является закрытым, я выполнил

check {
  no c: ConstructorMethodInvocation {
    c.cmethodInvoked.acc = private_
  }
}

который не нашел контрпримера.

person Aleksandar Milicevic    schedule 25.09.2013
comment
Привет, Александр, я понимаю, что экземпляр, сгенерированный вашим кодом, верен, поскольку вы запрещаете ему вызывать частный метод через c.cmethodInvoked.acc != private_. По этой причине я не понял вашего аргумента. Мое намерение почти такое же, но я также должен связать этот метод с классом, на который ссылается id_class. Я предполагаю, что я предотвратил бы вызов частного метода из этого класса, выполнив: this.@cmethodInvoked in (this.@id_Class).methods) || (this.@cmethodInvoked in ((this.@id_Class).^extend).methods && (this.@cmethodInvoked).acc != private_ - person Tarciana; 26.09.2013
comment
продолжение: я бы запретил вызывать приватный метод из этого класса, за исключением случая, когда метод сам находится в классе, где вызов разрешен и удерживается первой частью факта: this.@cmethodInvoked in ( this.@id_Class).методы). Чтобы лучше прояснить, ниже приведен пример сгенерированного экземпляра: [продолжить в следующем комментарии из-за ограничения символов] - person Tarciana; 26.09.2013
comment
открытый класс Teste { public static void main(String[] args){ new ClassId_6().methodid_0(); System.out.println(новый ClassId_6().methodid_0()); } } что невозможно, так как methodid_0 является закрытым методом, а сигнатура ConstructorMethodInvocation предотвращает это создание. - person Tarciana; 26.09.2013
comment
я сделал ошибку с первой частью this.@cmethodInvoked in (this.@id_Class).methods). Но даже когда я поставил в подписи ограничение: (this.@cmethodInvoked in (this.@id_Class).methods || this.@cmethodInvoked in ((this.@id_Class).^extend).methods && this.@cmethodInvoked .acc != private_), результат тот же. - person Tarciana; 26.09.2013
comment
Наверное, я не понял (и до сих пор не понимаю), в чем заключается ваш вопрос. Я думал, вы спрашиваете, почему все сгенерированные экземпляры вызывают только частные методы. Я ответил на это, что неверно, что все действительные экземпляры вашей модели всегда вызывают закрытый метод. Не могли бы вы отредактировать свой вопрос и попытаться лучше объяснить, что именно вы считаете неправильным в своей модели? - person Aleksandar Milicevic; 26.09.2013
comment
хорошо, Александр, я только что отредактировал свой вопрос. Пожалуйста, дайте мне знать, если это ясно сейчас. Спасибо за внимание. - person Tarciana; 26.09.2013
comment
вы явно написали круглые скобки вокруг предложения AND - person Aleksandar Milicevic; 29.09.2013