В Xtext, как настроить определенные вызовы функций - PullRequest
0 голосов
/ 16 мая 2019

Я использую 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, чтобы включить классы, чтобы заставить ее работать ...

Я полностью понимаю, что вопрос не очевиден, извините ...

Спасибо,

Martin

EDIT: изменено объявление DoSleepCallback со статического на абстрактное (было ошибочным)

1 Ответ

0 голосов
/ 20 мая 2019

Я не думаю, что вы можете сгенерировать то, что вам нужно, используя вывод модели jvm.

Вы должны предоставить свой собственный подкласс XbaseCompiler (или JBaseCompiler, если таковой имеется ... и не забудьте зарегистрироваться с guice в своем модуле времени выполнения) и переопределить doInternalToJavaStatement (выражение XExpression, ITreeAppendable it, логическое isReferenced) для управлять тем, как должно быть сгенерировано ваше FunctionDeclaration.

...