Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » [Xtext] Signature based crosslinks
[Xtext] Signature based crosslinks [message #780396] Tue, 17 January 2012 18:03 Go to next message
Jens von Pilgrim is currently offline Jens von PilgrimFriend
Messages: 313
Registered: July 2009
Senior Member
Hi all,

crosslinks in Xtext are name based, by default. However, in my DSL, I
want to implement a feature similar to method overloading in Java, for
which I need a more complicated crosslink resolving. I call it
"signature based crosslink", as I need to evaluate the signature of a
method.

Example grammar snippet:
-----------------------------------
MethodDeclaration: "def" name=ID "("
(parameters+=Parameter ("," parameters+=Parameter )*)?
")";
Parameter: type=ID name=ID;

....

MethodCall: "call" method=[MethodDeclaration] "("
(argument+=Argument ("," argument+=Argument )*)?
")";
Argument: type=ID;
-----------------------------------

Crosslinks are working out of the box, but only if all methods have
unique names. However, if methods can be overloaded, resolving becomes a
problem. E.g., in

def foo()
def foo(int i)
call foo(int)

call foo should be linked to foo(int i) rather then foo().

My question is how to solve that problem with Xtext (I'm using Xtext
1.0, maybe there exist different solutions for Xtext 2.0?).

I have already tried to implement custom scoping or
IQualifiedNameProvider. However I run into cycles when trying to
retrieve the name of the method used in the MethodCall (Cyclic
resolution of lazy links).

Actually, I have a workaround I'm not happy with. It doesn't make use of
Xtext's crosslink feature: instead of a crosslink, a simple ID is used
in MethodCall. Then, a new field method is added to the generated ecore
element "MethodCall", and this field is set manually after parsing the
code. That is

MethodCall: "call" methodName=ID "(" argument+=Argument
("," argument+=Argument )* ")";
// field "MethodDeclaration method" added in post processing step
// and set in separate resolution step

However, in that case I need a separate resolution step when reading a
model, and I have duplicate code in the binding and in the proposal
provider (for "emulating" the crosslink behaviour), and the crosslinks
are not navigable in the editor.

Is it possible to add a custom resolution/binding step to the Xtext
parser, in order to "fix" crosslinks? The example above is rather
simple, in the real example I have to resolve the type of the arguments
first of course, which makes the whole resolution rather complicated.

Cheers,
Jens
Re: [Xtext] Signature based crosslinks [message #780425 is a reply to message #780396] Tue, 17 January 2012 20:31 Go to previous messageGo to next message
Karsten Thoms is currently offline Karsten ThomsFriend
Messages: 762
Registered: July 2009
Location: Dortmund, Germany
Senior Member

Hi Jens,

the qualified name has just to include the parameters, then methods with the same name but different signature are handled differently. The scope for MethodCall_method would have to take the Arguments into account.

Kind regards,
~Karsten



Need professional support for Xtext, EMF, Eclipse IDE?
Go to: http://devhub.karakun.com
Twitter : @kthoms
Blog : www.karsten-thoms.de
Re: [Xtext] Signature based crosslinks [message #780448 is a reply to message #780396] Tue, 17 January 2012 23:33 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Hi Jens,

please dive into the Xbase scoping implementation to learn how we handle
overloaded methods there. BestMatchingFeatureScope could serve as a starter.

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 17.01.12 19:03, schrieb Jens v.P.:
> Hi all,
>
> crosslinks in Xtext are name based, by default. However, in my DSL, I
> want to implement a feature similar to method overloading in Java, for
> which I need a more complicated crosslink resolving. I call it
> "signature based crosslink", as I need to evaluate the signature of a
> method.
>
> Example grammar snippet:
> -----------------------------------
> MethodDeclaration: "def" name=ID "("
> (parameters+=Parameter ("," parameters+=Parameter )*)?
> ")";
> Parameter: type=ID name=ID;
>
> ....
>
> MethodCall: "call" method=[MethodDeclaration] "("
> (argument+=Argument ("," argument+=Argument )*)?
> ")";
> Argument: type=ID;
> -----------------------------------
>
> Crosslinks are working out of the box, but only if all methods have
> unique names. However, if methods can be overloaded, resolving becomes a
> problem. E.g., in
>
> def foo()
> def foo(int i)
> call foo(int)
>
> call foo should be linked to foo(int i) rather then foo().
>
> My question is how to solve that problem with Xtext (I'm using Xtext
> 1.0, maybe there exist different solutions for Xtext 2.0?).
>
> I have already tried to implement custom scoping or
> IQualifiedNameProvider. However I run into cycles when trying to
> retrieve the name of the method used in the MethodCall (Cyclic
> resolution of lazy links).
>
> Actually, I have a workaround I'm not happy with. It doesn't make use of
> Xtext's crosslink feature: instead of a crosslink, a simple ID is used
> in MethodCall. Then, a new field method is added to the generated ecore
> element "MethodCall", and this field is set manually after parsing the
> code. That is
>
> MethodCall: "call" methodName=ID "(" argument+=Argument
> ("," argument+=Argument )* ")";
> // field "MethodDeclaration method" added in post processing step
> // and set in separate resolution step
>
> However, in that case I need a separate resolution step when reading a
> model, and I have duplicate code in the binding and in the proposal
> provider (for "emulating" the crosslink behaviour), and the crosslinks
> are not navigable in the editor.
>
> Is it possible to add a custom resolution/binding step to the Xtext
> parser, in order to "fix" crosslinks? The example above is rather
> simple, in the real example I have to resolve the type of the arguments
> first of course, which makes the whole resolution rather complicated.
>
> Cheers,
> Jens
Re: [Xtext] Signature based crosslinks [message #780472 is a reply to message #780425] Wed, 18 January 2012 07:52 Go to previous message
Jens von Pilgrim is currently offline Jens von PilgrimFriend
Messages: 313
Registered: July 2009
Senior Member
Thank you, Karsten! My error in reasoning was to assume that the scoping
provider has to handle the name of the method. However, this is
magically done by Xtext, all I have to care about are the parameters as
you described.

Here's a brief description of the solution for interested readers:

Problem:
Crosslinks have to take other circumstances into account
besides the referencing name. Most popular example:
Overloaded methods must take into account number and types
of arguments and parameters respectively.

Solution:
Custom scope provider only collects possible link targets which
match the additional circumstances. The actual name is handled
later on.

Example:

Assume you want to allow a kind of method overloading. For keeping the
example small, only the number of arguments and parameters are to be
matched.

Grammar snippet:
-------------------------------------------------------------------
MethodDeclaration: "def" name=ID "("
(parameters+=Parameter ("," parameters+=Parameter )*)?
")";
Parameter: type=ID name=ID;
MethodCall: "call" method=[MethodDeclaration] "("
(argument+=Argument ("," argument+=Argument )*)?
")";
Argument: type=ID;
-------------------------------------------------------------------

Scope provider snippet:
-------------------------------------------------------------------
public class MyScopeProvider extends AbstractDeclarativeScopeProvider {

IScope scope_MethodCall_method(MethodCall methodCall, EReference ref) {
int numberOfArguments = methodCall.getArguments().size();
List<EObject> matchingMethods = new ArrayList<EObject>();
for (MethodDeclaration methodDeclaration: getAllMethods()) {
if (methodDeclaration.getParameters().size() == numberOfArguments) {
matchingMethods.add(methodDeclaration);
}
}
return Scopes.scopeFor(matchingMethods);
}

}
-------------------------------------------------------------------
Of course, in a real application, getAllMethods() and the matching
expression (here the comparison of paremeter size and number of
arguments) will be more complicated.

Sample program/model:
-------------------------------------------------------------------
def foo()
def foo(type1 p1)
call foo()
call foo(x)
-------------------------------------------------------------------

foo() call will be correctly bound to def foo(), and foo(x) to foo(type1
p1).


Cheers,
Jens
Previous Topic:Scope for import rule
Next Topic:Lexer too big
Goto Forum:
  


Current Time: Thu Apr 25 14:41:17 GMT 2024

Powered by FUDForum. Page generated in 0.07243 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top