Reputation: 837
So I have the following XText grammar:
grammar org.xtext.example.hyrule.HyRule with org.eclipse.xtext.xbase.Xbase
generate hyRule "http://www.xtext.org/example/hyrule/HyRule"
Start:
rules+=Rule+;
Rule:
constantDecs+= XVariableDeclaration*
elementDecs+=elementDec+
'PAYLOAD' payload=PAYLOAD 'CONSTRAINT' expression= XExpression
;
elementDec:
variable=FullJvmFormalParameter '=' xpath=XPATH
;
PAYLOAD:
"Stacons" | "any" | "sse";
//we override the definition in Xtype.xtext, so that we can have // in Xpaths
terminal SL_COMMENT:
'#' !('\n' | '\r')* ('\r'? '\n')?;
terminal XPATH:
(('//'|'/')('a'..'z'|'A'..'Z'|'_')('a'..'z'|'A'..'Z'|'_'|':'|'0'..'9')*)+
;
And I am using a JvmModelInferrer to infer a method for each Rule. The relevant part of the inferrer's code is:
def dispatch void infer(Start start, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
for (rule: start.rules) {
acceptor.accept(rule.toClass("Rule" + counter)).initializeLater[
...
// method used to check the rule this class represents
members += rule.toMethod("checkRule",rule.newTypeRef('boolean'))[
for (e : rule.elementDecs) {
parameters += e.variable.toParameter(e.variable.name, e.variable.parameterType)
}
setStatic(true)
body = expression
]
What I can't figure out how to do is make the values of the variable decalarations in constantDecs visible to the expression, and more specifically how to generate code for that expression which contains those values. At the moment the variable declarations are in scope in the generated code, but their value is declared to be their name. For example input:
val j = Integer::parseInt('199')
int x = //val/v
PAYLOAD Stacons CONSTRAINT x>j
results in the generated method:
public static boolean checkRule(final int x) {
int _j = j;
boolean _greaterThan = (x > _j);
return _greaterThan;
}
whereas I would like it to generate the method:
public static boolean checkRule(final int x) {
int _j = 199;
boolean _greaterThan = (x > _j);
return _greaterThan;
}
My scope provider looks like this:
@Inject
IJvmModelAssociations associations;
@Override
protected IScope createLocalVarScopeForJvmOperation(JvmOperation context, IScope parentScope) {
parentScope = super.createLocalVarScopeForJvmOperation(context, parentScope);
// retrieve the AST element associated to the method
// created by our model inferrer
EObject sourceElement = associations.getPrimarySourceElement(context);
if (sourceElement instanceof Rule) {
Rule rule = (Rule) sourceElement;
return Scopes.scopeFor(rule.getConstantDecs(), parentScope);
}
return parentScope;
I have tried fiddling with the scopes and the inferrer but to no avail. Is what I'm trying to do possible?
Upvotes: 0
Views: 1085
Reputation: 6729
There are basically two options:
Since I find (2) way too bad, I suggest to go for (1).
acceptor.accept(rule.toClass("Rule" + counter)).initializeLater[
..
for(varDecl : constantDecs) {
switch(varDecl) {
XVariableDeclaration: members += varDecl.toField(varDecl.name, varDecl.type) [
initializer = varDecl.right
setStatic(true)
setFinal(true)
]
}
}
// method used to check the rule this class represents
members += rule.toMethod("checkRule",rule.newTypeRef('boolean'))[
for (e : rule.elementDecs) {
parameters += e.variable.toParameter(e.variable.name, e.variable.parameterType)
}
setStatic(true)
body = expression
]
]
Upvotes: 2