0

I am currently writing an interpreter for an Xtext language that extends Xbase.

To do so I am inheriting from XbaseInterpreter, adding my own run method and override the dispatch method doEvaluateProgram with my new abstract concepts.

The problem arises in the interpretation of the CondStmt. Its semantics is to evaluate the exp XExpression and call the stmts statements only if the evaluation of exp returns true.

When the interpreter is called (let's say from the test case below), the evaluation of the exp XExpression fails with a java.lang.IllegalArgumentException: Segment cannot be null exception.

Both sides of the == statement, e.g. _inPort and inSide are supposed to be variables defined in the interpretation context using the newValue method.

I'm guessing the runtime error has something to do with a failure to identify the type and/or the value of the variables, but I can't figure out how to fix this issues.

PS: The full stack trace below.

The grammar:

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* ")";

// ...

The interpreter

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

The test case

@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

        // ...
    }
}

The stack trace

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)
...  
Manuel Leduc
  • 1,849
  • 3
  • 23
  • 39

1 Answers1

0

here is an example of loading the model without 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
Christian Dietrich
  • 11,778
  • 4
  • 24
  • 32
  • Thanks. This example is working properly but regarding my runtime exception issue, I'm obtaining the same result with both parsing methods. – Manuel Leduc Feb 07 '18 at 16:52
  • Can you share a reproducible example – Christian Dietrich Feb 07 '18 at 16:53
  • https://github.com/manuelleduc/gpfl is the "real world" project with the issue. Run https://github.com/manuelleduc/gpfl/blob/master/fr.mleduc.gpfl.tests/src/fr/mleduc/gpfl/tests/GpflInterpreterTest.xtend to reproduce the issue – Manuel Leduc Feb 07 '18 at 17:09
  • you did not implement ITypeComputer nor did you assign your expressions to a body or initializer – Christian Dietrich Feb 07 '18 at 18:09
  • Thanks, I'll look at it. Currently, my only source of examples if the TortoiseShell language of the seven languages repository (https://github.com/xtext/seven-languages-xtext/tree/master/languages/org.xtext.tortoiseshell). And it does not seem to use ITypeComputer. Is there any resource I could read to gain some insights on how to use it? – Manuel Leduc Feb 07 '18 at 18:14