Home » Modeling » TMF (Xtext) » Creating a wildcard reference
Creating a wildcard reference [message #1402895] |
Fri, 18 July 2014 09:17 |
Yann Bondue Messages: 11 Registered: May 2014 |
Junior Member |
|
|
Hello everyone,
I don't know if my title here is quite clear, basically what I'm trying to do is adding a reference to an array that was not defined specifically by the user, but rather is provided by the DSL.
My rule is the following :
Function returns Function:
'func' name=EString '{'
'parameters' '(' (parameters+=[Type|EString] ( "," parameters+=[Type|EString])* )? ')'
'}';
Parameters are references to a Type that are defined by the user, and I would like to be able to specify some kind of wildcard rather than having to reference one that has been defined.
The idea of the field 'parameters' is to specify the types and implicitly the number of parameters of a function.
There are several ways I could do that by modifying my meta-model and adding a wildcard type of parameter that is actually contained by the function rather than being a reference, but by doing so I would probably lose the order of the parameters as they are defined (e.g doing something like parameters(*, specificType, *) ).
So I was wondering if there were ways to have such null references or some kind of cool trick to pull that off.
Thank you, here's to hoping that my question was clear enough =)
Yann
|
|
| |
Re: Creating a wildcard reference [message #1403826 is a reply to message #1402949] |
Mon, 28 July 2014 07:45 |
Yann Bondue Messages: 11 Registered: May 2014 |
Junior Member |
|
|
I don't quite understand, this seems to suggest that parameters would have to be a containment reference, but how can it accept references within brackets if that's the case ? Is the "type" you've put in TypeRef: type[Type|EString]; some kind of keyword that instantiates a reference or something ?
Yann
[Updated on: Mon, 28 July 2014 07:46] Report message to a moderator
|
|
| |
Re: Creating a wildcard reference [message #1403850 is a reply to message #1403839] |
Mon, 28 July 2014 09:38 |
Yann Bondue Messages: 11 Registered: May 2014 |
Junior Member |
|
|
Well, when writing :
Param: TypeRef | Wildcard;
TypeRef: type[Type|EString];
Wildcard: {Wildcard}'*';
You're allowing the Param rule to return both a reference to an Object or an Object directly. This doesn't work for me (maybe I'm just missing something), but since parameters is not a containment relation, I can't use a rule such as Wildcard that would return an Object. (And it's not that I wouldn't, it just causes an error ^^ )
The aim of my DSL is to define types, then the prototypes of functions that take those types as parameters. The parameters relation is a simple reference, which allows me to refer to the types that were created just before (e.g type a; type b; type c; parameters(a, b, c); ), however, I would like to add wildcard parameters to the mix (e.g parameters(*, a, * , *, b, * , c , *) ). * has to exist in order to be referenced as a parameter, so I guess one of the options would be to have a rule that returns a reference to a new object rather than an object (returning null would be enough), but I don't know if that's possible.
The other possible way I see would be to make parameters a containment reference. Doing so, having a rule that returns a Wildcard would be very easy, but then I wouldn't be able to add references to a Type to parameters, I would have to instantiate specific types for each function, which I obviously don't want to.
Here's a sample that may help you understand :
type mass {
frames 2 // These are fields to the type Type, and are of no matter for this problem
fields(weight) // These are fields to the type Type, and are of no matter for this problem
}
type floor {
frames 2
fields(weight)
}
function connect {
parameters(mass, floor) // This I can do, but it won't cut it, as I want to be able to connect any types together
}
function trueConnect {
parameters(*, *) // Basically do this
}
function somethingElse {
parameters(mass, *, floor, *) // I still want to do this though
}
In terms of what I'm trying to achieve, we are still quite abstract, I am only defining function prototypes, so it matters very little if * is just an alias for null, as long as it is still referenced in the parameters relation and I can get the right number of parameters for a prototype. When actually using the functions defined here, my program will only check if types match when a type is actually defined and is not a *, but I guess that's kind of obvious.
I hope this helps, thank you for your help.
Yann
[Updated on: Mon, 28 July 2014 09:47] Report message to a moderator
|
|
| | | | | | |
Re: Creating a wildcard reference [message #1403945 is a reply to message #1403935] |
Mon, 28 July 2014 16:38 |
Yann Bondue Messages: 11 Registered: May 2014 |
Junior Member |
|
|
I will send you the complete grammar and models when I get to work tomorrow (I currently live in Japan, so it is 1 am for me at the moment).
I only want * to be a token, I don't want there to be any intelligent behaviour behind it. Think of it as, say I create the following Java method :
void foo(Integer a, Object b);
This allows me to call foo with any kind of object as b, I don't want to check if this object implements any interfaces or extends any class, it is just a wildcard, allowing me to call this function with any parameter.
By saying one of the parameters of a function is *, I basically only want to say that when I call this function, I won't have to check if the type of this parameter matches the type that was defined in the prototype.
By defining :
type mass;
function foo {
parameters(mass, *)
}
The important thing is to know that foo takes two parameters, the first one is a mass, the second is any of the types that the user defined.
It becomes tricky in the sense that types are user-defined, in the very same file that functions are defined.
This means that the parameters have to be a referencing relation, in order to be able to reference types such as mass that were created just above, but still be able to reference a special type, one that was not created by the user like mass was.
In that sense, adding * to the parameters could mean adding a reference to a special object, one that was not created by the user, and that us developers are aware of. This however (even if it's possible, which I doubt), seems like an unclean way of working things out.
More than ever, thank you for your help, and sorry for the trouble. I'm especially sorry if I'm not very clear with my explanations...
Yann
|
|
| |
Re: Creating a wildcard reference [message #1403990 is a reply to message #1403946] |
Tue, 29 July 2014 01:46 |
Yann Bondue Messages: 11 Registered: May 2014 |
Junior Member |
|
|
Please find the meta-model, the grammar and a sample model attached.
In this form of the grammar, there is but one error on line 20 of the grammar :
TypeRef returns Type:
[Type|EString];
I'm getting the following errors :
- no viable alternative at input 'EString'
- no viable alternative at input '['
But I sincerely doubt that these are the actual errors.
In the meta-model, I define the abstract supertype Type, three classes inherit it, two of them are actual types, the third one is WildcardType, which is basically all I do for handling *.
Thank you for your help.
[Updated on: Tue, 29 July 2014 02:41] Report message to a moderator
|
|
|
Re: Creating a wildcard reference [message #1404000 is a reply to message #1403990] |
Tue, 29 July 2014 06:02 |
|
Hi,
your metamodel actually does not allow that.
functions have only cross refs to variables - not types.
you dont even have a rule for variables.
thus there is no place for the wildcard information to be stored.
of course you could write the wildcards to /dev/null but they would be totally lost in the ast.
so again the question: what would you do if you create a model instance with the ecore tree editor and not with xtext.
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
|
Re: Creating a wildcard reference [message #1404001 is a reply to message #1404000] |
Tue, 29 July 2014 06:43 |
Yann Bondue Messages: 11 Registered: May 2014 |
Junior Member |
|
|
FunctionCall is actually not the class to look at in the meta-model. Prototype is the one that defines the types of the parameters of a function. FunctionCall references a Prototype and the Variables with which the function will be called, I then check if the types of the variables match the types of the parameters defined in Prototype. In the case one of the parameters of Prototype is a wildcard, that check is passed automatically.
There are two top elements in this meta-model which can be made as a model instance :
Context defines Types and Prototypes (and is the one that is important for this issue).
Model uses a Context and defines Variables that have a Type defined in the used Context. It also defines FunctionCalls that also reference a Prototype of the Context.
Sorry if the names I've been giving in my earlier explanations were kind of confusing, I didn't want to get too much into the details of my model.
[Updated on: Tue, 29 July 2014 06:48] Report message to a moderator
|
|
| |
Re: Creating a wildcard reference [message #1404008 is a reply to message #1404004] |
Tue, 29 July 2014 07:15 |
Yann Bondue Messages: 11 Registered: May 2014 |
Junior Member |
|
|
I tried both ways and neither seem to work for me.
Yann Bondue:If parameters is a simple reference, it will fail on "parameters+=Wildcard" because "parameters is not a containment reference".
If parameters is a containment reference, it will fail on "parameters+=[Type|EString]" because "parameters is a containment reference."
The aim of parameters is to hold references to a type that was defined by the user, so that we can create various prototypes that use the same types. If I made parameters a containment reference, I would have to recreate an actual instance of type for each prototype that uses it, OR there is a way to put a reference in a containment and that would solve the problem.
The other way around, which seems better the way I see it, is to keep parameters as as simple reference and have some kind of hidden reference to the wildcard type that can be used by the user.
We can look at it this way :
The following code would do the trick, but the reference is created by the user :
type mass {
// type related definitions
}
type floor {
// Type related defintions
}
type * {
// No definitions required, this is the wildcard
}
prototype connect {
parameters(mass, floor, *, *)
}
Now, if I had a way to simply have the type * exist, without asking the user to define it, I would be able to reference it, and the problem would be solved.
All I'd need is that global reference.
[Updated on: Tue, 29 July 2014 07:16] Report message to a moderator
|
|
| | | |
Re: Creating a wildcard reference [message #1404121 is a reply to message #1404045] |
Tue, 29 July 2014 17:51 |
|
Hi,
the problem still is that metamodel and grammar dont fit together.
i dont know what is set in the metamodel and what can be changed.
the TypeRef is not defined in the metamodel for example.
it should contain a cross ref to a type
here are a fixed grammar and metamodel
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
import "http://www.example.org/test"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
Context returns Context:
{Context}
'Context'
'{'
('types' '{' types+=ActualType ( "," types+=ActualType)* '}' )?
('prototypes' '{' prototypes+=Prototype ( "," prototypes+=Prototype)* '}' )?
'}';
Param returns Param:
WildcardType | TypeRef;
TypeRef:
type=[ActualType|ID];
WildcardType returns WildcardType:
{WildcardType}'*';
Prototype returns Prototype:
{Prototype}
'Prototype'
'{'
('parameters' '{' parameters+=Param ( "," parameters+=Param)* '}' )?
'}';
ActualType returns ActualType:
{ActualType}
name=ID
;
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="test" nsURI="http://www.example.org/test" nsPrefix="test">
<eClassifiers xsi:type="ecore:EClass" name="Prototype">
<eStructuralFeatures xsi:type="ecore:EReference" name="parameters" upperBound="-1"
eType="#//Param" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="WildcardType" eSuperTypes="#//Param"/>
<eClassifiers xsi:type="ecore:EClass" name="ActualType">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Context">
<eStructuralFeatures xsi:type="ecore:EReference" name="prototypes" upperBound="-1"
eType="#//Prototype" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="types" upperBound="-1"
eType="#//ActualType" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Param"/>
<eClassifiers xsi:type="ecore:EClass" name="TypeRef" eSuperTypes="#//Param">
<eStructuralFeatures xsi:type="ecore:EReference" name="type" eType="#//ActualType"/>
</eClassifiers>
</ecore:EPackage>
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
| | |
Goto Forum:
Current Time: Thu Sep 26 18:48:14 GMT 2024
Powered by FUDForum. Page generated in 0.05392 seconds
|