diverse-project / melange

The Melange Language Workbench
http://melange-lang.org
Eclipse Public License 1.0
28 stars 7 forks source link

Issue on copying aspects that reuses Util classes outside of the k3 project #102

Open eduardoafs opened 6 years ago

eduardoafs commented 6 years ago

Hey all, I'm facing some issues when trying to add calls to an Util class that is part of the original language I'm extending with Melange. The original language contains an Util class that is used by it's own semantic validator. However, this class contains methods I need in the k3 aspects, therefore I imported the package and used it. K3 works fine, it generates the aspects correctly.

The problem is when it comes to melange, when copying the aspects it tries to pass the parameters as in the extended language, which is not accepted by the Util class. Should it use the adapters to provide the parameters in the original language, in this case. I managed to fix the issue manually, but it is a bit annoying re-doing this everytime I re-generate the language runtime.

ebousse commented 6 years ago

This is a known problem: Melange is only able to work on aspects, and is not able to adapt code define outside of aspects. Therefore, the only solution I can suggest is to move the methods of the Util class into K3 aspects of your semantics.

Would that be doable for you? Usually, the parameters of utility methods use are typed by your EClasses hence you should be able to move these methods to appropriate aspects.

eduardoafs commented 6 years ago

I can copy the methods, yes. But it is not maintainable, I can't move the methods since they're used by the original language's semantic validator.

ebousse commented 6 years ago

Ah, I see, you are reusing in your K3 aspects:

@tdegueul @fcoulon any clue how to handle that case?

tdegueul commented 6 years ago

As @ebousse mentioned, Melange assumes that every part of the semantics is encapsulated in a K3 aspect: you cannot "escape" to an external utility class.

However, if I understand correctly, your problem is slightly different. Originally, the aspects call Util in that way:

@Aspect(className = myecore.C)
class CAspect {
  void foo() {
    Util::m(_self)
  }
}

And these methods break when the new aspects are generated because _self is not a myecore.C anymore, but a mynewecore.C (the new meta-classes that are generated by Melange when extending). Is that right?

If yes, it's the expected behavior, and the only solution is to refactor Util :( If Util::m expects a myecore.C, it cannot work on a mynewecore.C and the only way to make it work is to use the model type generated for your original language (myecoremt.C), use it to type Util::m, and benefit from model polymorphism. Otherwise, you need to move all the code from Util to the corresponding aspects, and you can keep the methods of Util as dispatchers to the corresponding aspects. I'm not sure this is feasible in your case though.

I'm sorry for the clunky explanation, but this is a complex problem :) Do you have a piece of code or repo to share so that we can have a look?

eduardoafs commented 6 years ago

Yes, this is right. I can paste some example here.

So, in this example there is a class named ArchitectureDecl, it has a feature named constituents (of type Constituent). Each Constituent is composed of a IdentExpression, roughly a qualified name. In the ModelUtils class there is a static method that resolves this IdentExpression, returning the EObject it refers to.

In the ArchitectureDeclAspect main method I need to call this method to resolve the IdentExpression, so I can proceed on the execution of the EObjects.

melange_util

In the generated code, c.value is an instance of the extended IdentExpression (which is identical to the original IdentExpression), therefore the ModelUtils.resolve does not accept it as parameter.