Выполнение расширенного интерпретатора Xbase приводит к исключению во время выполнения

В настоящее время я пишу интерпретатор для языка Xtext, который расширяет Xbase.

Для этого я наследую от XbaseInterpreter, добавляя свой собственный метод run и переопределяя метод отправки doEvaluateProgram своими новыми абстрактными концепциями.

Проблема возникает при интерпретации CondStmt. Его семантика заключается в оценке exp XExpression и вызове операторов stmts только в том случае, если оценка exp возвращает true.

Когда вызывается интерпретатор (скажем, из тестового примера ниже), оценка выражения XExpression завершается ошибкой с исключением java.lang.IllegalArgumentException: Segment cannot be null.

Обе стороны оператора ==, например. Предполагается, что _inPort и inSide являются переменными, определенными в контексте интерпретации с использованием метода newValue.

Я предполагаю, что ошибка времени выполнения как-то связана с невозможностью определить тип и/или значение переменных, но я не могу понять, как решить эту проблему.

PS: Полная трассировка стека ниже.

Грамматика:

grammar MyLang with org.eclipse.xtext.xbase.Xbase

generate mylang "http://MyLang"
import "http://www.eclipse.org/xtext/xbase/Xbase" as xbase

// ...

CondStmt returns xbase::XExpression:
    {CondStmt} "cond" "(" exp=XExpression "," stmts+=Stmt* ")";

// ...

Переводчик

class MyLangInterpreter extends XbaseInterpreter {

    val indicator = CancelIndicator.NullImpl

    def run(MyProgram program) {
        // ...
        val context = this.createContext
        // ...
        val newContext = context.fork
        newContext.newValue(QualifiedName.create("_inPort"), "something"))
        myElement.doEvaluate(newContext, indicator)
       // ...
    }

    def dispatch doEvaluateProgram(MyElem elem, IEvaluationContext context, CancelIndicator indicator) {
        // ...
    }

    def dispatch doEvaluateProgram(CondStmt condStmt, IEvaluationContext context, CancelIndicator indicator) {
        val exp = this.evaluate(condStmt.exp, context, indicator)

        if (Boolean.TRUE == exp) {
            condStmt.stmts.map [
                this.internalEvaluate(it, context, indicator)
            ].last
        }
    } 
}

Тестовый пример

@RunWith(XtextRunner)
@InjectWith(GpflInjectorProvider)
class GpflInterpreterTest {

    @Inject private extension ParseHelper<Program> parseHelper
    @Inject private extension GpflInterpreter

    @Test
    def test1() {
        val program = '''
            // ...
            cond(_inPort == inSide, 
              // ...
            )
            // ....
        '''.parse

        val res = program.run

        // ...
    }
}

Трассировка стека

java.lang.IllegalArgumentException: Segment cannot be null
    at org.eclipse.xtext.naming.QualifiedName.create(QualifiedName.java:203)
    at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1008)
    at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:993)
    at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:901)
    at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:864)
    at mylang.MyLangInterpreter.doEvaluate(GpflInterpreter.java:414)
    at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203)
    at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:900)
    at mylang.MyLangInterpreter.doEvaluate(GpflInterpreter.java:450)
    at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203)
    at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:189)
    at mylang.MyLangInterpreter._doEvaluate(GpflInterpreter.java:314)
    at mylang.MyLangInterpreter.doEvaluate(GpflInterpreter.java:430)
    at mylang.MyLangInterpreter.lambda$3(GpflInterpreter.java:263)
    at mylang.MyLangInterpreter$$Lambda$13/974320615.accept(Unknown Source)
    at java.lang.Iterable.forEach(Iterable.java:75)
    at mylang.MyLangInterpreter.run(GpflInterpreter.java:265)
    at fr.mleduc.gpfl.tests.MyLangInterpreterTest.test1(GpflInterpreterTest.java:113)
...  

person Manuel Leduc    schedule 07.02.2018    source источник
comment
вы отлаживали, если функция является прокси?   -  person Christian Dietrich    schedule 07.02.2018
comment
и если да, то какая функция прокси? ==   -  person Christian Dietrich    schedule 07.02.2018
comment
кроме того, я не буду использовать помощника синтаксического анализа для синтаксического анализа, потому что он может работать в сочетании с xbase.   -  person Christian Dietrich    schedule 07.02.2018
comment
Функция действительно является прокси типа JvmVoidImplCustom (toString: JvmVoid: (eProxyURI: __synthetic0.mylang#|9)). Как следствие, ваша реализация getSimpleName возвращает null при выполнении с этой функцией. Кроме того, как я могу избежать использования помощника синтаксического анализа?   -  person Manuel Leduc    schedule 07.02.2018
comment
выложил вам фрагмент. я не вижу toString в вашем примере кода   -  person Christian Dietrich    schedule 07.02.2018
comment
JvmVoid: (eProxyURI: __synthetic0.mylang#|9) является результатом вызова метода toString для оцениваемой функции XFeatureCall (_inPort в моем тесте).   -  person Manuel Leduc    schedule 07.02.2018


Ответы (1)


вот пример загрузки модели без parsehelper

@RunWith(XtextRunner)
@InjectWith(DomainmodelInjectorProvider)
class DullyTest{

    @Inject Provider<XtextResourceSet> rsp
    @Inject ValidationTestHelper helper

    @Test
    def void xxxxx() {
        val rs = rsp.get
        rs.classpathURIContext = DullyTest
        val r = rs.createResource(URI.createURI("dummy.dmodel"))
        val text = '''
        entity Person {
            op xxxx() {
                1==1
            }
        }
        '''
        r.load(new StringInputStream(text), null)
        helper.assertNoIssues(r)
        val m = r.contents.head as DomainModel
person Christian Dietrich    schedule 07.02.2018
comment
Спасибо. Этот пример работает правильно, но что касается моей проблемы с исключением во время выполнения, я получаю тот же результат с обоими методами синтаксического анализа. - person Manuel Leduc; 07.02.2018
comment
Можете ли вы поделиться воспроизводимым примером - person Christian Dietrich; 07.02.2018
comment
github.com/manuelleduc/gpfl — это реальный проект с проблемой. Запустите github.com/manuelleduc/gpfl/blob/master/fr.mleduc.gpfl.tests/, чтобы воспроизвести проблему. - person Manuel Leduc; 07.02.2018
comment
вы не реализовали ITypeComputer и не присвоили свои выражения телу или инициализатору - person Christian Dietrich; 07.02.2018
comment
Спасибо, посмотрю. В настоящее время мой единственный источник примеров — это язык TortoiseShell из репозитория семи языков (github.com/xtext/seven-languages-xtext/tree/master/languages/). И, похоже, он не использует ITypeComputer. Есть ли какой-нибудь ресурс, который я мог бы прочитать, чтобы получить представление о том, как его использовать? - person Manuel Leduc; 07.02.2018