Set XEpression local scope [message #1748650] |
Fri, 25 November 2016 17:09 |
Sven Uthe Messages: 8 Registered: May 2016 |
Junior Member |
|
|
Hi,
I want to include an XExpression into my DSL which works like the check( Expression ) in VIATRA:
Quote:
qualifiedName == eval(parentName + "." + simpleName);
The Java types of variables are inferred based on the EMF Ecore specification (using the generated Java classes).
Additional attribute constraints using the check() construct, similarly to eval():
check(aNumberVariable > aStringVariable.length());
Semantically equivalent to true == eval(aNumberVariable > aStringVariable.length());
The Java types of variables are inferred based on the EMF Ecore specification (using the generated Java classes).
(From 5. under https://wiki.eclipse.org/VIATRA/Query/UserDocumentation/QueryLanguage#Advanced_Pattern_Constraints)
A shortened extract of my xtext grammar:
grammar eu.netide.deployment.topologyvalidation.Topo with org.eclipse.xtext.xbase.Xbase
import "http://www.eclipse.org/xtext/xbase/Xbase"
generate Topo "http://[..]/Topo"
Root:
(submodules+=Module)*
;
SwitchModule returns Module:
{SwitchModule}
name=ValidID ':'
Switch
('{'
constrain=XExpression
'}')?
;
Additionally, there is an external Plugin-Project containing an ECore Model which includes among others a Switch Class.
This Class should be the Scope of the constrain. (like described in the VIATRA doc)
So in the end the user can use the Auto Completion to see all the members and operations the Switch Class provides.
Also, the TypeSystem should validate that the written code returns a boolean value at runtime.
Therefore I added a TypeCompute Class to my DSL:
class TopoTypeComputer extends XbaseWithAnnotationsTypeComputer {
override computeTypes(XExpression expression, ITypeComputationState state) {
[...]
if (expression instanceof SwitchModule) {
val conditionExpectation = state.withExpectation(getRawTypeForName(typeof(Boolean), state));
val predicate = expression.constrain;
conditionExpectation.computeTypes(predicate);
[...]
}
}
}
To set the scope of the XExpression of the constrain I tried different approaches an none of them worked
Here is the last one:
import Topology.Switch // The Class of the external ECore Model
[...]
class TopoScopeProvider extends AbstractTopoScopeProvider {
@Inject extension JvmTypeReferenceBuilder
override getScope(EObject context, EReference reference) {
switch (context) {
[...]
SwitchModule case reference == TopoPackage.Literals.SWITCH_MODULE__CONSTRAIN: {
val declaredOperations = (typeRef(Switch).type as JvmDeclaredType).getDeclaredOperations();
return Scopes.scopeFor(declaredOperations, [JvmOperation op |
return QualifiedName.create(op.getSimpleName());
], IScope.NULLSCOPE);
}
default: {
return super.getScope(context, reference)
}
}
}
}
Side notes:
I use the the ModelInferrer to generate Java Classes.
Beside searching this forum and googling around (didn't find the right search term), I looked at the VIATRA implementation (http://git.eclipse.org/c/viatra/org.eclipse.viatra.git/tree/query/plugins/org.eclipse.viatra.query.patternlanguage/src/org/eclipse/viatra/query/patternlanguage/typing). But this is tooooo freaky
My Guess is, that I missed something like an URI/resource import of the ECore model to make it visible to the xtext grammar.
|
|
|
|
|
|
Re: Set XEpression local scope [message #1748655 is a reply to message #1748654] |
Fri, 25 November 2016 17:38 |
|
hmmm i had a look at xbase code and the code you pasted and your code seems to be strange regarding the types
inside the type computer you may try a
state.assignType(IFeatureNames.IT, knownType, expectedType);
e.g.
public class DomainmodelXbaseTypeComputer extends XbaseTypeComputer {
@Override
public void computeTypes(XExpression expression, ITypeComputationState state) {
if (expression.eContainer() instanceof Operation) {
state.assignType(IFeatureNames.IT, state.getReferenceOwner().newReferenceTo(Switch.class).getType(), state.getReferenceOwner().newReferenceTo(Switch.class));
}
super.computeTypes(expression, state);
}
}
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
[Updated on: Fri, 25 November 2016 18:35] Report message to a moderator
|
|
|
|
|
Re: Set XEpression local scope [message #1748681 is a reply to message #1748660] |
Sat, 26 November 2016 17:27 |
Sven Uthe Messages: 8 Registered: May 2016 |
Junior Member |
|
|
Thank you for your qualified and fast help.
Today, I poked around the computeTypes method: No success.
Overriding FeatureScopes is not an option because I am bounded to some deadlines.
At the end of this day I decided to take your first advice and it worked - as expected- like a charm.
So I hazard the consequences to have unnecessary functions in my generated code.
Cheers
[Updated on: Sun, 27 November 2016 11:54] Report message to a moderator
|
|
|
|
Re: Set XEpression local scope [message #1748683 is a reply to message #1748682] |
Sat, 26 November 2016 18:29 |
Sven Uthe Messages: 8 Registered: May 2016 |
Junior Member |
|
|
I have other construct in my language where I extended xbase XExpression and they will be compiled to java methods.
Therefore I wrote a class TopoXbaseCompiler extends XbaseCompiler.
My computeTypes(XExpression expression, ITypeComputationState state) also considers this extension. (There is another if else case in it)
But this should not affect this problem here?
state.assignType(IFeatureNames.IT,...) was never been called:
override computeTypes(XExpression expression, ITypeComputationState state) {
if (expression.eContainer() instanceof SwitchModule) {
state.assignType(IFeatureNames.IT,
state.getReferenceOwner().newReferenceTo(Switch).getType(),
state.getReferenceOwner().newReferenceTo(Switch)
)
} else {
super.computeTypes(expression, state);
}
}
[Updated on: Sat, 26 November 2016 18:50] Report message to a moderator
|
|
|
Re: Set XEpression local scope [message #1748684 is a reply to message #1748683] |
Sat, 26 November 2016 19:00 |
|
i have not any compile problems with ints in my example.
you should hook into the type computation at the correct place somwhere arround org.eclipse.xtext.xbase.typesystem.internal.LogicalContainerAwareReentrantTypeResolver.computeTypes(ResolvedTypes, IFeatureScopeSession)
usually this is done automatically if you assign the expression to a body or a initializer but you dont
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
|
|
Re: Set XEpression local scope [message #1748707 is a reply to message #1748705] |
Sun, 27 November 2016 12:06 |
|
No these are 3 different things
Inferrer
Type computer
jvmmodelgenerator / xbasecompiler
Lorenzo Beetins Xtext Book in the 2nd version contains some hints on that but I don't know if this covers your usecase since you are doing something xbase is not made for since you circumvent the inferrer
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
|
|
Powered by
FUDForum. Page generated in 0.02866 seconds