首页 > 解决方案 > 在 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?剩下的,我也许能做到……

另一个 StackOverflow 条目相关,我有在推断器中将 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 声明从静态修改为抽象(错误)

标签: xtext

解决方案


我不认为你可以使用 jvm 模型推断器生成你需要的东西。

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


推荐阅读