Search code examples
xtext

XText - get content (compiled value) of XExpression


I have a certain part of my XText grammer that defines a block for classes that shall print all its expressions. The XText grammar part for this looks as follows:

Print: 
    {Print}
    'print' '{' 
        print += PrintLine* 
    '}';
PrintLine:
    obj += XExpression;

Now I use the following inferrer code to create a print() method:

Print: {
    members += feature.toMethod('print', typeRef(void)) [
    body = '''
        «FOR printline : feature.print»
            System.out.println(«printline.obj»);
        «ENDFOR»
        '''
    ]
}

Ok, I go ahead and test it with the following code in a class:

print {
    "hallo"
    4
    6 + 7
}

And the result is the following:

public void print() {
   System.out.println([org.eclipse.xtext.xbase.impl.XStringLiteralImpl@20196ba8 (value: hallo)]);
   System.out.println([org.eclipse.xtext.xbase.impl.XNumberLiteralImpl@7d0b0f7d (value: 4)]);
   System.out.println([<XNumberLiteralImpl> + <XNumberLiteralImpl>]);}

Of course, I was hoping for:

public void print() {
   System.out.println("hallo");
   System.out.println(4);
   System.out.println(6+7);
}

I understand that I might have to call the compiler somehow in the inferrer for «printline.obj», but I am really not sure how.


Solution

  • i think you are doing this on a wrong basis. this sounds to me like an extension of xbase, not only a simple use.

    import "http://www.eclipse.org/xtext/xbase/Xbase" as xbase
    
    Print: 
        {Print}
        'print' 
            print=XPrintBlock
        ;
    
    XPrintBlock returns xbase::XBlockExpression:
        {xbase::XBlockExpression}'{'
            expressions+=XPrintLine*
        '}'
    ;
    
    XPrintLine returns xbase::XExpression:
        {PrintLine} obj=XExpression
    
    ;
    

    Type Computer

    class MyDslTypeComputer extends XbaseTypeComputer {
    
         def dispatch computeTypes(XPrintLine literal, ITypeComputationState state) {
            state.withNonVoidExpectation.computeTypes(literal.obj)
            state.acceptActualType(getPrimitiveVoid(state))
        }
    
    }
    

    Compiler

    class MyDslXbaseCompiler extends XbaseCompiler {
    
        override protected doInternalToJavaStatement(XExpression obj, ITreeAppendable appendable, boolean isReferenced) {
            if (obj instanceof XPrintLine) {
                appendable.trace(obj)
                appendable.append("System.out.println(")
                internalToJavaExpression(obj.obj,appendable);
                appendable.append(");")
                appendable.newLine
                return
            }
    
            super.doInternalToJavaStatement(obj, appendable, isReferenced)
        }
    
    }
    

    XExpressionHelper

    class MyDslXExpressionHelper extends XExpressionHelper {
    
        override hasSideEffects(XExpression expr) {
            if (expr instanceof XPrintLine || expr.eContainer instanceof XPrintLine) {
                return true
            }
            super.hasSideEffects(expr)
        }
    
    }
    

    JvmModelInferrer

    def dispatch void infer(Print print, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
        acceptor.accept(
            print.toClass("a.b.C") [
                members+=print.toMethod("demo", Void.TYPE.typeRef) [
                    body = print.print
                ]
            ]
    
        )
    }
    

    Bindings

    class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {
    
        def Class<? extends ITypeComputer> bindITypeComputer() {
            MyDslTypeComputer
        }
    
        def Class<? extends XbaseCompiler> bindXbaseCompiler() {
            MyDslXbaseCompiler
        }
    
        def Class<? extends XExpressionHelper> bindXExpressionHelper() {
            MyDslXExpressionHelper
        }
    }