如何为XExpression子类型生成代码?

时间:2017-01-04 15:06:09

标签: xtext xbase

我有一个简单的DSL应该为表达式生成异步代码(这是我能想出的最简单的例子来说明我的观点)。我刚刚在scripting example添加了一条新的async声明:

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
;

这个想法是async代码在另一个线程中执行。

我的问题是,如何使用ScriptingJvmModelInferrerAsync.expression生成代码?

在最简单的情况下,我会像这样包装Async.expression的代码吗?

    AsyncRunner.exec(new Runnable() {
        @Override
        public void run() {
            // the Async.expression would end up here
        }
    })

这样做的钩子在哪里?

2 个答案:

答案 0 :(得分:1)

您必须进行3次更改:

  1. 扩展编译器以处理您的语言。关键是要处理Async表达式。

    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) 
        }
    }
    
  2. 必须指定表达式的类型

    class ScriptingTypeComputer extends XbaseWithAnnotationsTypeComputer {
    
        override computeTypes(XExpression expression, ITypeComputationState state) {
            if(expression instanceof Async) {
                super.computeTypes(expression.expression, state);
            } else {
                super.computeTypes(expression, state)
            }
        }
    }
    
  3. 必须注入两个扩展名:

    class ScriptingRuntimeModule extends AbstractScriptingRuntimeModule {
        def Class<? extends XbaseCompiler> bindXbaseCompiler() {
            return ScriptingCompiler
        }
    
        def Class<? extends ITypeComputer> bindITypeComputer() {
            return ScriptingTypeComputer
        }
    }
    

答案 1 :(得分:0)

如果你扩展Xbase,你通常不会接受JvmModelInferrer进行编译,但你扩展XbaseTypeComputerXbaseCompiler.doInternalToJavaStatement/internalToConvertedExpression(取决于你实际介绍的内容)