In Xtext, how to tweak certain function calls

走远了吗. 提交于 2019-12-11 19:45:20

问题


I am using Xtext 2.15 to generate a language that, among other things, processes asynchronous calls in a way they look synchronous.

For instance, the following code in my language:

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

would generate the following Java code:

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

To achieve it, I defined the grammar this way:

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
;

The FunctionDeclaration rule is used to define asynchronous calls. In my language library, I would have as system call:

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

The underlying Java implementation would be:

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

So, using the inferrer, type computer and compiler, how to identify calls to FunctionDeclaration elements, add a callback parameter and process the rest of the body in an inner class?

I could, for instance, override appendFeatureCall in the language compiler, would it work? There is still a part I don't know how to do...

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(');')
        }
    }

So basically, how to tell if "feature" points to FunctionDeclaration? The rest, I may be able to do it...

Related to another StackOverflow entry, I had the idea of implementing FunctionDeclaration in the inferrer as a class instead of as a method:

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)
            ]
        }
    }
}

The generated class would extend FunctionDeclarationObject, so I thought there was a way to identify FunctionDeclaration as FunctionDeclarationObject subclasses. But then, I would need to extend the XFeatureCall default scoping to include classes in order to making it work...

I fully realize the question is not obvious, sorry...

Thanks,

Martin

EDIT: modified DoSleepCallback declaration from static to abstract (was erroneous)


回答1:


I don't think you can generate what you need using the jvm model inferrer.

You should provide your own subclass of the XbaseCompiler (or JBaseCompiler, if any... and don't forget to register with guice in your runtime module), and override doInternalToJavaStatement(XExpression expr, ITreeAppendable it, boolean isReferenced) to manage how your FunctionDeclaration should be generated.



来源:https://stackoverflow.com/questions/56168010/in-xtext-how-to-tweak-certain-function-calls

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!