Xtext 2.1: using Xbase variables

Xtext 2.1: using Xbase variables

On a previous post, I started to blog about how Xtext 2.1 made it extremely easy to have a powerful integration with Java thanks to Xbase, a new expression language library which allows to integrate (Java-like) expressions in your DSL. I had also blogged about using JVM types from your DSL.

In this post, IÔÇÖd like to continue to inspect how to use only a small part of Xbase and still have the control on the generation part: in particular (for other projects) I would like to retain the control on the generation for my model, while relying on the Xbase generation for the Xbase parts mobile ebs videos. Thus, in this post IÔÇÖll describe:

  • how to integrate Xbase variables (XVariableDeclaration) and expressions (XExpression) in your DSL
  • how to extend Xbase scoping for making the variables visible in the expressions
  • write a generator for your DSL and reuse the XbaseCompiler for the code of XVariableDeclaration and XExpressions

Following the spirit of the previous post, I wonÔÇÖt use the Domainmodel example, but something really simple, like the Greeting example, i.e., the very basic DSL you will get when creating an Xtext project inside Eclipse. In particular, you might want to go through the previous posts before reading this post (since we reuse some of the concepts seen there):

  • the one about JVM types (concerning how to use the ImportManager for generating correct code for accessing Java types and the corresponding import statements)
  • and the one about Xbase expressions (concerning how to use the XbaseCompiler for generating code corresponding to Xbase expressions) 러브 액츄얼리 다운로드.

So, first of all, create a new Xtext project; IÔÇÖll call this project org.xtext.example.helloxvars (and the files will have extension helloxvars). Now, we can start generate Xtext artifacts. With the defaults, youÔÇÖll also get a HelloXvarsGenerator.xtend, which we now to generate Java code 윈도우10 home 다운로드. The basic idea of the generator is: for each Greeting element we will obtain a package and a class named according to the Greeting name feature (package all lower case, and class name with the first letter capital). We’ll deal with the generator later in this post.

Now, the idea is to enrich the greeting DSL with some Xbase variables (before the greeting statements) and some Xbase expressions (used within the greeting statements) which can access the declared variables; thus, we modify the grammar of the language (HelloXvars.xtext) as follows (you should be familiar with ÔÇÿimportÔÇÖ functionalities of Xtext):

The idea is to end up (at the end of this post) with a DSL which allows us to write programs as follows:

Note that Xbase (its validator) already checks that the types are correct, i.e., that the initialization expression has a type which is a subtype of the declared type for the variable gdfr 다운로드. But, more important, you will reuse the type inference mechanism of Xbase: you don’t need to declare the type for the variable when this can be inferred by Xbase itself!

Regenerate the Xtext artefacts, and start a new runtime eclipse instance. Create a new plugin project (say ÔÇÿhelloxvarsÔÇÖ), and in the source folder we create a .helloxvars file (say ÔÇÿMy.helloxvarsÔÇÖ) and accept to add the Xtext nature uaexpert 다운로드. To fully enjoy Xbase syntax, please make sure that in the project you created in the runtime workspace you also have org.eclipse.xtext.xbase.lib as a dependency in the MANIFEST.

Now, if you try to write code like in the above image you’ll get errors due to the Xbase expressions that cannot access Xbase variables; in fact, Xbase variables are automatically visible to Xbase expressions only when they are both part of an XBlockExpression, which we don’t use in our case 디아블로2 정품 다운로드. Thus, we must extend the Xbase scoping mechanism in order to make all the variables declared before the greetings to all the expressions of the greetings.

As soon as we start to use Xbase in our grammar, the generated runtime module will bind the IScopeProvider to XbaseScopeProvider; so, first of all, we must override this binding in our runtime module, in order to bind the scope provider to the one of our DSL:

And now, we make our scope provider extend the XbaseScopeProvider; by inspecting the code of XbaseScopeProvider we find a possible good candidate method for customizing the scope of variables:

Take a look at the code of this method in XbaseScopeProvider, and you should get the general idea (the base implementation walks through the containment hierarchy of the model to build the scope for local variables); in particular, LocalVariableScopeContext contains the context for the scope Download counterstrike source. In our case, we need to provide a custom scope when the context is the greeting Model (in all other cases we rely on the base implementation):

So, when the context is the root of our model (Model) we return as the scope all the variables declared in our greeting model.

Now, restart your eclipse runtime instance and you’ll see that errors go away: the expressions in the greetings can access the variables declared above websource!

Note that the scoping does not concern only the expressions in the greetings, but also the initialization expressions of local variable declarations themselves:

Now, if you do some experiments you’ll note that we provide scopes that contain too much! Try the following:

This code should raise errors, since the initialization expression for v should not be able to access variables declared afterwards (e.g., v2); while, with our scope implementation, this code would be silently accepted 영웅문 s 다운로드.

So, we need to tweak our scope implementation; however, let’s stop following the workflow of trying a modification, restart the runtime eclipse instance, and see whether we made it… let’s be agile 🙂 and write some unit tests! Create an Xtend2 class in the tests plugin project org.xtext.example.helloxvars.tests and add in the MANIFEST org.eclipse.xtext.xtend2.lib as a dependency How to Use YouTube.

You see, the first test checks a greeting program without variables, the second checks a valid program with variable access, the third one checks a valid program with variable access and a closure, the forth one checks that accessing a variable which is not declared generates an error, and the last one checks that variable initialization expressions cannot access variable declared afterwards. Of course, the last test fails! And we need to get the green bar back now 🙂

So now we modify the scoping:

This time we do something different: the scope will still be all the variables of the containing greeting Model; but if we’re inside a XVariableDeclaration, the scope will be the list of all the variable declarations up to the current variable, and we get the green line back… oh oh… something it’s still wrong: the previous failing test now succeeds, but the test for closure now fails! It says it cannot resolve the reference to ‘s’, the local variable of the closure itself:

If you take a look at our implementation of scoping, you’ll soon realize that we customized it too much: we basically override completely the method of XbaseScopeProvider, which will then be unable to build the scope for local variables declared in the expressions, and closures declare local variable themselves!

Indeed, the right solution is something in between the two implementations of scoping we saw here:

  1. we must check whether the container of the context is a greeting Model
  2. if it is, then the scope is the list of variables up to the current one, if the context is a variable declaration (we can simply search for the context in the list of variable declarations, since List.indexOf accept any Object
  3. otherwise, we delegate to XbaseScopeProvider

We finally get the green line for our tests 🙂

Now let’s move on to generation! Similarly to the previous post about Xbase expressions, we will generate a main method for each Greeting, and we will generate the Java code for all the variable declarations and initializations by reusing the XbaseCompiler. Most of the code for the generation has already been explained in the previous post.

Let us concentrate on the interesting part

We basically use the XbaseCompiler for generating the Java code corresponding to variable declarations and initializations; then we need to access the generated Java variable name corresponding to the XExpression of the current Greeting element. We use the getName method, as explained in the previous post; however, this time, we need to distinguish the case when the XExpression is a XFeatureCall: this is the case when the XExpression is just the name of a declared variable, as in this code

In this case, we need to get the variable name which corresponds to the feature of the XFeatureCall, and not to the XFeatureCall itself (since no synthetic expression is generated for the XFeatureCall itself). Let’s try the generator

Remember, that we did not want to generate something meaningful: we wanted to experiment with code generation 🙂

You can find the sources for the project helloxvars at

https://github.com/LorenzoBettini/Xtext2-experiments

Hope you find this post useful, and stay tuned for new posts about Xtext 🙂

By |2012-06-08T11:14:50+00:00December 26th, 2011|

15 Comments

  1. Marcus Mathioudakis Wednesday July 4th, 2012 at 01:38 PM - Reply

    Lorenzo I wanted to thank you, these are the best tutorials on Xtext I have found so far (much better than the official ones on the Xtext website). They really helped me get started with Xtext. Keep up the great work :)!

  2. Lorenzo Bettini Wednesday July 4th, 2012 at 01:53 PM - Reply

    Thank you Marcus!
    I’m glad you find these tutorials useful 🙂

  3. nomuna Thursday August 16th, 2012 at 08:52 AM - Reply

    How about using XVariableDeclaration and XBaseCompiler to write

    Integer v1 = 1 // There will be a warning after the code generation, I know.
    Integer v2 = null
    String blah = “12313”
    in the grammar and get java code generated from it.

  4. Lorenzo Bettini Thursday August 16th, 2012 at 09:38 AM - Reply

    @nonuma, I’m not sure I understand what you mean, can you elaborate please?

  5. nomuna Monday August 20th, 2012 at 03:12 PM - Reply

    Thanks for the info on xtext and especially on JvmInferrer…

    What I mean is…
    I have my own grammar. I have expressions, statements and variables etc. I want to use the
    Inferrer/XbaseCompiler to generate the java code. So… what I am trying to do is to get the element
    created from the grammar in the inferrer code and create the corresponding xbase artifact
    — int a; would be for example the featurecall of Xbase — and fill the properties with my
    info and then call necessary method of the xbase compiler passing the xbase artifact as parameter.
    Is this a feasible approach? Bad/Whacky idea?

    The inferrer is very badly documented. I am spending a lot of time just for the simplest things.
    I am using the inferrer in the hope that the debugging will be (according to the docs anyway)
    taken care of automatically. If you could tell me if there are things that I should be aware of
    documents that I need to read and examples I should checkout, I will be very thankful.

    I am using java 1.5, linux/ubuntu machine Xtext 2.3.0.

    • Lorenzo Bettini Monday August 20th, 2012 at 03:44 PM - Reply

      have you looked at my last article on the inferrer?

      • nomuna Tuesday August 21st, 2012 at 02:59 PM - Reply

        Yes I have the Xtext experiments from github. The helloinferrer project
        is throwing NPE on

        typeof(HelloResult).getTypeForName(o, o.parameterType)

        in the inferrer’s returnType method. Debugging is not wroking too.
        I can set a breakpoint in the helloinferrer source but the
        debugger goes to the generated java source or crashes.

        • nomuna Tuesday August 21st, 2012 at 03:31 PM - Reply

          Well the class HelloResult had to be added in the
          java project created using the helloinferrer.ui plugin.

          After that I have no NPEs. Is there a possibility that the
          ui/JavaProject becomes the classes needed by the
          generated source code automatically?

          • nomuna Tuesday August 21st, 2012 at 03:34 PM

            No NPE but the debugging is not working. Am I missing something? 😀

          • Lorenzo Bettini Tuesday August 21st, 2012 at 03:40 PM

            I think it’s better to move this discussion on the article concerning helloinferrer 🙂

            by the way, after Xtext 2.3 was officially released I haven’t updated that example…

            however, probably, the problem you’re experiencing might be due to the fact that you created the project yourself and not through the wizard? I mean the project where you’re trying the DSL and the debugging…

  6. nomuna Monday August 20th, 2012 at 03:14 PM - Reply

    Is there a IRC channel or something where I can bug the developers with my questions?

    • Lorenzo Bettini Monday August 20th, 2012 at 03:45 PM - Reply

      Do you mean Xtext’s developers? in that case, I don’t know of any IRC channel… but there’s the Xtext forum 🙂

  7. Ambreen Hussain Friday November 9th, 2012 at 09:21 AM - Reply

    Hi Lorenzo,
    Thank you very much for this post. It is very useful. I am using the Xtext documentation DSL example following this post. I want to declare a property of type Entity but getting error saying Couldn’t resolve reference to JvmType ‘Entity Name’. It cannot recognise Entity as JvmTypeReference. How can I make entity as JvmTypeReference using JvmGenericType. Thanks for your help.

    Best Regards,
    Ambreen

    • Lorenzo Bettini Friday December 14th, 2012 at 11:02 PM - Reply

      Ambreen, I’m not sure I understand your question: are you referring to this example or to another example?

  8. Vicky Friday July 20th, 2018 at 06:33 PM - Reply

    Hi Lorenzo,
    Iam designing a DSL with support of XBlockExpression. I don’t need the code generation feature, but only the interpreter. while interpreting the xblock i need to pass an object and need to work on the object fields. Object is the data on which xblock xpression should work. Feature is to implement validations on the data.
    I am not finding any way to access the object and access its members inside.
    Grammer is like:
    …..
    Entity:
    annotations+=XAnnotation*
    ‘entity’ name=ID
    (”)?
    (‘extends’ superType=JvmParameterizedTypeReference)? ‘{‘
    operations += Operation*
    ‘}’;

    Operation:
    ‘op’ (type=JvmTypeReference)? name=ID
    ‘(‘ (params+=FullJvmFormalParameter (‘,’
    params+=FullJvmFormalParameter)*)? ‘)’
    body=XBlockExpression;
    …..

    Sample input:
    import java.util.ArrayList
    import java.util.Date

    entity A {
    attr int i=0;
    op meth() {
    var x=self.a.b.d1 as Date
    var y=self.a.b.d2 as Date
    return x.after(y)
    }
    }

    Interpreter:
    var self= new HashMap();
    self.put(“a”, new HashMap());
    self.get(“a”).put(“b”,new HashMap());
    self.get(“a”).get(“b”).put(“d1”, new Date());
    self.get(“a”).get(“b”).put(“d2”, new Date());

    context.newValue(QualifiedName.create(“self”), self)

    var result=evaluate(expression, context, CancelIndicator.NullImpl);

    I have created a name provider also:
    override getSimpleName(JvmIdentifiableElement element) {
    if (element.simpleName.equals(“self”))
    ‘self’
    else
    super.getSimpleName(element)
    }

    Can you please guide in this.
    Basically i need to access an object inside the xblock interpretation mechanism

Leave A Comment