在Xtext中,如何调整某些函数调用

时间:2019-05-16 11:56:55

标签: xtext

我正在使用Xtext 2.15生成一种语言,该语言除其他外,将以异步方式处理异步调用。

例如,用我的语言编写的以下代码:

int a = 1;
int b = 2;
boolean sleepSuccess = doSleep(2000); // sleep two seconds
int c = 3;
int d = 4;

将生成以下Java代码:

int a = 1;
int b = 2;
doSleep(2000, new DoSleepCallback() {
  public void onTrigger(boolean rc) {
    boolean sleepSuccess = rc;
    int c = 3;
    int d = 4;
  }
});

要实现这一点,我通过以下方式定义了语法:

grammar org.qedlang.qed.QED with jbase.Jbase // Jbase inherits Xbase

...

FunctionDeclaration return XExpression:
    =>({FunctionDeclaration} type=JvmTypeReference name=ValidID '(')
   (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)?
   ')' block=XBlockExpression
;

FunctionDeclaration规则用于定义异步调用。在我的语言库中,我将作为系统调用:

boolean doSleep(int millis) {} // async FunctionDeclaration element stub

底层Java实现为:

public abstract class DoSleepCallback {
  public abstract void onTrigger(boolean rc);
}
public void doSleep(int millis, DoSleepCallback callback) {
  <perform sleep and call callback.onTrigger(<success>)>
}

因此,使用推断器,键入计算机和编译器,如何识别对FunctionDeclaration元素的调用,添加回调参数并在内部类中处理正文的其余部分?

例如,我可以覆盖语言编译器中的appendFeatureCall,它将起作用吗?还有一部分我不知道该怎么做...

override appendFeatureCall(XAbstractFeatureCall call, ITreeAppendable b) {
...
        val feature = call.feature
  ...
        if (feature instanceof JvmExecutable) {
            b.append('(')

            val arguments = call.actualArguments

            if (!arguments.isEmpty) {
      ...
                arguments.appendArguments(b, shouldBreakFirstArgument)

      // HERE IS THE PART I DON'T KNOW HOW TO DO
      <IF feature IS A FunctionDeclaration>
        <argument.appendArgument(NEW GENERATED CALLBACK PARAMETER)>
        <INSERT REST OF XBlockExpression body INSIDE CALLBACK INSTANCE>
      <ENDIF>
            }

            b.append(');')
        }
    }

所以基本上,如何判断“功能”是否指向FunctionDeclaration?其余的,我也许可以做到...

another StackOverflow entry相关,我想到了在推断器中将FunctionDeclaration作为类而不是方法来实现:

def void inferExpressions(JvmDeclaredType it, FunctionDeclaration function) {
    // now let's go over the features
    for ( f : (function.block as XBlockExpression).expressions ) {
        if (f instanceof FunctionDeclaration) {
            members += f.toClass(f.fullyQualifiedName) [
                inferVariables(f)
                superTypes += typeRef(FunctionDeclarationObject)

                // let's add a default constructor
                members += f.toConstructor [
                    for (p : f.params)
                        parameters += p.toParameter(p.name, p.parameterType)
                    body = f.block
                ]
                inferExpressions(f)
            ]
        }
    }
}

生成的类将扩展FunctionDeclarationObject,所以我认为有一种方法可以将FunctionDeclaration标识为FunctionDeclarationObject子类。但是然后,我需要扩展XFeatureCall的默认作用域以包括类,以使其工作...

我完全意识到问题并不明显,对不起...

谢谢

马丁

编辑:将DoSleepCallback声明从静态修改为抽象(错误)

1 个答案:

答案 0 :(得分:0)

我认为您无法使用jvm模型推断器生成所需的内容。

您应该提供自己的XbaseCompiler子类(或JBaseCompiler,如果有的话……,并且不要忘记在运行时模块中向guice注册),并重写doInternalToJavaStatement(XExpression expr,ITreeAppendable it,boolean isReferenced)以管理应如何生成FunctionDeclaration。