Reputation: 34498
I have a simple DSL that should generate async code for expressions (this is the simplest example I could come up with to illustrate my point). I just added to the scripting example an new async
statement:
grammar org.xtext.scripting.Scripting with org.eclipse.xtext.xbase.Xbase
generate scripting "http://www.xtext.org/scripting/Scripting"
import "http://www.eclipse.org/xtext/xbase/Xbase" as xbase
Script returns xbase::XBlockExpression:
{Script}
(expressions+=XExpressionOrVarDeclaration ';'?)*;
XExpression returns xbase::XExpression:
super | Async
;
Async:
'async' expression=XExpression
;
The idea would be that the async
code is executed in another thread.
My question is, how can I generate code for the Async.expression
using the ScriptingJvmModelInferrer
?
In the simplest case I would just wrap the code from the Async.expression
like this?
AsyncRunner.exec(new Runnable() {
@Override
public void run() {
// the Async.expression would end up here
}
})
Where is the hook to do that?
Upvotes: 1
Views: 228
Reputation: 34498
You have to make 3 changes:
Extend the compiler to deal with your language. The key point is to handle the Async
expression.
class ScriptingCompiler extends XbaseCompiler {
override protected doInternalToJavaStatement(XExpression expr, ITreeAppendable it, boolean isReferenced) {
switch expr {
Async : {
newLine
append('''
AsyncRunner.exec(new Runnable() {
@Override
public void run() {''')
expr.expression.doInternalToJavaStatement(it, false)
newLine
append('}});')
}
default :
super.doInternalToJavaStatement(expr, it, isReferenced)
}
}
override protected internalToConvertedExpression(XExpression obj, ITreeAppendable it) {
if (hasName(obj))
append(getName(obj))
else
super.internalToConvertedExpression(obj, it)
}
}
The type of the expression has to be specified
class ScriptingTypeComputer extends XbaseWithAnnotationsTypeComputer {
override computeTypes(XExpression expression, ITypeComputationState state) {
if(expression instanceof Async) {
super.computeTypes(expression.expression, state);
} else {
super.computeTypes(expression, state)
}
}
}
Both extensions have to be injected:
class ScriptingRuntimeModule extends AbstractScriptingRuntimeModule {
def Class<? extends XbaseCompiler> bindXbaseCompiler() {
return ScriptingCompiler
}
def Class<? extends ITypeComputer> bindITypeComputer() {
return ScriptingTypeComputer
}
}
Upvotes: 1
Reputation: 11868
If you extend Xbase you ususally don't apapt the JvmModelInferrer for Compilation but you extend XbaseTypeComputer
and XbaseCompiler.doInternalToJavaStatement/internalToConvertedExpression
(depending on what you actually introduce)
Upvotes: 0