Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » xbaseCompiler methods
xbaseCompiler methods [message #1736369] Tue, 28 June 2016 23:40 Go to next message
Mansour Al is currently offline Mansour AlFriend
Messages: 44
Registered: June 2016
Member
May be this is obivious for some of you, but I am a bit confused with methods that I need to override for my own expressions. In the XbaseCompiler we have:

toJavaStatement
toJavaExpression
doInternalToJavaStatement
internalToJavaStatement
internalToJavaExpression

The purpose of each of them is not clear to me, especially with the lack of javadoc, and an example. So here's my question, which ones I need to override, to define my own expressions, and which one should I avoid touching ?

Thank you.
Re: xbaseCompiler methods [message #1736379 is a reply to message #1736369] Wed, 29 June 2016 04:58 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
you shoud override the ones that contain the if else cascades

doInternalToJavaStatement(XExpression, ITreeAppendable, boolean)
internalToConvertedExpression(XExpression, ITreeAppendable)

if one or both depends if your expression can act as statement as well or as expression only.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: xbaseCompiler methods [message #1736508 is a reply to message #1736379] Thu, 30 June 2016 02:13 Go to previous messageGo to next message
Mansour Al is currently offline Mansour AlFriend
Messages: 44
Registered: June 2016
Member
Now, here comes the confusing part. We go back again to "Expression-Vs-Statement". Reading on the Xtend pages https://www.eclipse.org/xtend/documentation/203_xtend_expressions.html :

Quote:

In Xtend everything is an expression and has a return type. Statements do not exist. That allows you to compose your code in interesting ways.
For example, you can have a try catch expression on the right hand side of an ...


So, here comes the question of what is an expression and what is a statement in Xtext ?
Assuming, that an expression has no side effect and always is a value, why XMemberCall in Xbase is considered an expression, when a member call may have side effect ?

Then we go to the DSL tutorial for a template language : https://eclipse.org/Xtext/documentation/207_template.html , and we see:

Quote:

The compiler now knows how to handle the new expressions in a statement context. In addition, we have to teach it to compile them in an expression context.
This is what the second method does: ....


Which makes me conclude, that a statement in Xtext may contain an expression, but an expression can not be a statement ... Am I wrong here ?
Assuming, this is correct (which I don't think), a XblockExpression is an "XExpression", however, it may contain multiple statements !

This is a bit confusing, especially when combined with writting the grammar. For example in Xtext, we write the grammar in a way not only to define the parsing, but we keep in the mind the processing
in the inferrer, compiler, ... etc.

So, assuming I have some parsing rule that I need to infer to:

SomeAction   Optional_InstanceOfObjectInAnotherClass    "MyValue1" "MyValue2"   ;
AnotherAction  123  987 ;


Would this be an expression or a statement ? It has no assignment.
Anyone can help me by clarifying these concepts in "Xbase", or a link to a tutorial/documentation page would be highly appreciated, as I was not able to find one that explains this topic.

Thank you a lot in advance.
Re: xbaseCompiler methods [message #1736510 is a reply to message #1736508] Thu, 30 June 2016 04:18 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
There is unfortunately no explanation nor tutorials.

You are doing advanced stuff. Xbase is usually just about inferrer and or api. Having custom expressions or statements is not a intended common usecase.
The example code you show is no valid Java.



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: xbaseCompiler methods [message #1736511 is a reply to message #1736510] Thu, 30 June 2016 04:24 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
In you case it are statements cause they are lines in a block, can not be used inside other expressions e.g. As left or right inside a binary expression or as right hand side in an assignment.



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: xbaseCompiler methods [message #1736512 is a reply to message #1736511] Thu, 30 June 2016 04:37 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
P.s. In xbase things are usually both since you can do stuff like

Var x = if (true) 1 else 2

Thus the if can occur in an expression context as well.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: xbaseCompiler methods [message #1736994 is a reply to message #1736512] Tue, 05 July 2016 01:54 Go to previous messageGo to next message
Mansour Al is currently offline Mansour AlFriend
Messages: 44
Registered: June 2016
Member
Thank you.
But both:

doInternalToJavaStatement(XExpression, ITreeAppendable, boolean)
internalToConvertedExpression(XExpression, ITreeAppendable)

take only expressions as parameters. None takes a token generated from a parser rule, unless it's an expression. Assuming, I have this grammar:

Action returns xbase::XExpression:
	{Action} type=JvmTypeReference args=Arguments ";";

Arguments:
	{Arguments} targets+=(UIElement)* (":" data+=Datum+)?;

UIElement : //;returns xbase::XExpression:
	{UIElement} block=XExpression;

Datum returns xbase::XExpression:
	 XLiteral | PropRef;

ConjunctionExpression returns xbase::XExpression:
	{ConjunctionExpression} pos=("after" | "before");

PropRef:
	ns=NS ":" prop=QualifiedName;


Not sure which method to override to process/compile UIElement. None of the methods will accept it. This is the reason I had to wrap UIElement around "block=expression" !

Re: xbaseCompiler methods [message #1736995 is a reply to message #1736994] Tue, 05 July 2016 03:07 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
There is the inferrer part

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: xbaseCompiler methods [message #1736996 is a reply to message #1736995] Tue, 05 July 2016 03:08 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
It has to assign your root expression to a body or initializer

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: xbaseCompiler methods [message #1737127 is a reply to message #1736996] Wed, 06 July 2016 00:35 Go to previous messageGo to next message
Mansour Al is currently offline Mansour AlFriend
Messages: 44
Registered: June 2016
Member
Sorry Christian, I didn't clarify my question. After I reread it, it's a bit confusing. Let's try again !
I have an expression. The expression is processing in the inferrer. Once the Compiler is called to process EObjects under this expression, the inferrer role is over, and it's the compiler role to produce the valid java code (assuming we are producing java).
Now inside the compiler, we have many methods to process an expression. These methods, mainly produce a valid java code from predefined expressions in xbase. When we are processing of creating a new expression, this XExpression may contain other EObjects.
My question is, how do we process them ? With what method ? So, let's say I have this grammar:

Action returns xbase::XExpression:
	{Action} type=JvmTypeReference args=Arguments ";";

Arguments:
	{Arguments} targets+=(UIElement)* (":" data+=Datum+)?;

UIElement :
	{UIElement} value=XExpression;

Datum returns xbase::XExpression:
	{Datum} value=(XLiteral | PropRef);

PropRef:
	ns=NS ":" prop=QualifiedName;



Note that UIElement is not an expression, but it's a delegate ParserRule and a wrapper for an expression.
Note that PropRef is NOT an expression, but XLiteral is an expression, and both create an instance of Datum Expression ! (Is this the right way) ?


Now, we have in the compiler:

override protected doInternalToJavaStatement(XExpression expr, ITreeAppendable tree, boolean isReferenced) {
		switch expr {
			.....
			Action: {
				..........
				for (target : action.args.targets) {
					target.value.internalToConvertedExpression(tree);
				}
				for (datum : action.args.data) {
					datum.internalToConvertedExpression(tree);
				}
				......
			}
			default: {
				super.doInternalToJavaStatement(expr, tree
....


And,

override protected internalToConvertedExpression(XExpression expr, ITreeAppendable tree) {
		switch expr {
			UIElement: {
				internalToConvertedExpression(expr.value, tree)
			}
			Datum: {
				internalToConvertedExpression(expr.value, tree)  // This will not work because expr.value does not always yield an expression. It can be XLiteral or PropRef !
			}
			PropRef: {.....}
			default: {
				super.internalToConvertedExpression(expr, tree)
			}
....


Based on this, how can I process the "Argument" Expression ? What I am after here, is a method like:

compile(Datum d){
if (d.value instance of PropRef) ...
else if (d instance of XLiteral) .... 
}


None, of the exiting methods takes a non-Expression. Is there one that we can override ?

Am I using doInternalToJavaStatement and internalToConvertedExpression in the correct place ??
None of the methods can take an instance of EObject !

Thank you.



Re: xbaseCompiler methods [message #1737133 is a reply to message #1737127] Wed, 06 July 2016 04:32 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Can you please Share what your expected code and semantic is. What should should be the output. Can you share a complete example project to work on.
Where is the action rule called? Why do you expect to be able to use the existing methods for non expressions. You have to handle that inside the code of datum.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: xbaseCompiler methods [message #1737293 is a reply to message #1737133] Thu, 07 July 2016 03:28 Go to previous messageGo to next message
Mansour Al is currently offline Mansour AlFriend
Messages: 44
Registered: June 2016
Member
Christian, this is the grammar: https://github.com/malakeel/myDsl/blob/master/org.xtext.example.mydsl/src/org/xtext/example/mydsl/MyDsl.xtext

and the compiler: https://github.com/malakeel/myDsl/blob/master/org.xtext.example.mydsl/src/org/xtext/example/mydsl/jvmmodel/MyDslCompiler.xtend

As you can see the compiler is really messy but working. A small model test file:

suite MyTest using (testFile.xml ){
Click MyOtherPage.text ;  
     prepare {
		Fill MyPage2.element : "How to use this text" ;
		Fill MyPage.text :  and:my.impl "How to use this 123" ;
		Click MyOtherPage.element ;
		Fill MyPage.text MyPage.text :  and:my.impl "How to use this 123" ;
		Fill ; 
		Fill MyPage.text :  and:my.impl "How to use this 123 " ;
		Fill MyPage.getValues(9) : "wow";
		test anotherTest using (some.xml){
			Fill MyPage.text ;
			Fill MyPage.text : "How to use this 123" ;
		}
		test myTestCaseSample using (some.xml ) {
			 Fill MyPage2.element ;
		}
	}
}


produces the desired following results. However, since I need to do add more eclipse support, like inferring and auto suggest constructor arguments with their types, I need the grammar and compiler to be as clean as possible. I am hoping to eliminate the use of expression where it's not needed, and reduce ParserRules or increase them for clarity.
@SuppressWarnings("all")
public class MyTest {
  private MyContextManager ctx;
  
  @BeforeClass
  public static void beforeSuite() {
    (new actions.Click(MyOtherPage.text)).exec();
    
  }
  
  @Before
  public void beforeTest() {
    (new actions.Fill(MyPage2.element,"How to use this text")).exec();
    (new actions.Fill(MyPage.text,ctx.get("and:my.impl"),"How to use this 123")).exec();
    (new actions.Click(MyOtherPage.element)).exec();
    (new actions.Fill(MyPage.text,MyPage.text,ctx.get("and:my.impl"),"How to use this 123")).exec();
    (new actions.Fill()).exec();
    (new actions.Fill(MyPage.text,ctx.get("and:my.impl"),"How to use this 123 ")).exec();
    (new actions.Fill(MyPage.getValues(9),"wow")).exec();
    
  }
  
  @Test
  public void anotherTest() {
    (new actions.Fill(MyPage.text)).exec();
    (new actions.Fill(MyPage.text,"How to use this 123")).exec();
    
  }
  
  @Test
  public void myTestCaseSample() {
    (new actions.Fill(MyPage2.element)).exec();
    
  }
  
  @After
  public void afterTest() {
    
  }
}


If I can your recommendations it will be great. The reason I asked about using existing method for compiling non-expressions is to ensure I am not adding anything that does not need to be there. I am having hard utilizing unassigned actions in my grammars, and I don't know if they will help reducing the complexity a bit.

Thank you.

Re: xbaseCompiler methods [message #1737294 is a reply to message #1737293] Thu, 07 July 2016 03:47 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Well what I don't understand: why is my page etc Java and not the same or another dsl

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: xbaseCompiler methods [message #1737299 is a reply to message #1737294] Thu, 07 July 2016 06:11 Go to previous message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
i would have thought of

class MyDslTypeComputer extends XbaseTypeComputer {

	override computeTypes(XExpression expression, ITypeComputationState state) {
		if (expression instanceof Action) {
			_computeTypes(expression as Action, state);
		} else if (expression instanceof PropRef) {
			state.acceptActualType(state.getReferenceOwner().newReferenceTo(Object))
		} else {
			super.computeTypes(expression, state)
		}
	}

	protected def void _computeTypes(Action action, ITypeComputationState state) {
		for (t : action.args.targets) {
			println("TODO better logic here ?!?")

			val iaction = state.getReferenceOwner().getServices().getTypeReferences().findDeclaredType(
				"org.example.ILocator", state.referenceOwner.contextResourceSet)
			state.withExpectation(
				state.referenceOwner.newParameterizedTypeReference(iaction)
			).computeTypes(t)
		}
		
		for (t : action.args.data)  {
			state.withNonVoidExpectation.computeTypes(t)
		}
		state.acceptActualType(getTypeForName(Void.TYPE, state), ConformanceFlags.CHECKED_SUCCESS)

	}

}


class MyDslCompiler extends XbaseCompiler {

	override protected doInternalToJavaStatement(XExpression expr, ITreeAppendable tree, boolean isReferenced) {
		switch expr {
			InitBody: {
				tree.newLine
				for (action : expr.expressions)
					action.doInternalToJavaStatement(tree, isReferenced);
			}
			TestBody: {
				tree.newLine
				for (action : expr.expressions)
					action.doInternalToJavaStatement(tree, false);
			}
			PropRef: {
				if (isReferenced) {
					val propRef = expr
					tree.newLine().append("final ");
					serialize(getType(propRef), propRef, tree);
					tree.append(" ");
					val variableName = tree.declareSyntheticVariable(propRef, "_propRef");
					tree.append(variableName).append(" = ");
					propRef.compile(tree)
					tree.append(";");
				} else {
					throw new IllegalStateException
				}
			}
			Action: {
				val action = expr as Action;
				for (t : action.args.targets) {
					internalToJavaStatement(t, tree, true);
				}
				for (d : action.args.data) {
					tree.newLine
					val name = tree.declareVariable(d, "data")
					serialize(getType(d), d, tree);
					tree.append(" ")
					tree.append(name);
					tree.append(" = ")
					internalToConvertedExpression(d, tree)
					tree.append(";").newLine
				}
				tree.newLine
				tree.trace(action)
				tree.append("(new ");
				tree.append(action.type.qualifiedName + "(");
				var itr = action.args.targets.iterator
				while (itr.hasNext) {
					tree.append(itr.next.getVarName(tree))
					if (itr.hasNext)
						tree.append(",")
				}

				if (action.args.targets.size > 0 && action.args.data.size > 0) {
					tree.append(",")
				}
				val dataItr = action.args.data.iterator

				while (dataItr.hasNext) {
					tree.append(dataItr.next.getVarName(tree))
					if (dataItr.hasNext)
						tree.append(",")
				}
				tree.append(")).exec();").newLine
			}
			default: {
				super.doInternalToJavaStatement(expr, tree, isReferenced)
			}
		}
	}

	override protected internalToConvertedExpression(XExpression expr, ITreeAppendable tree) {
		switch expr {
			PropRef: {
				expr.compile(tree)
			}
			default: {
				super.internalToConvertedExpression(expr, tree)
			}
		}
	}

	def void compile(PropRef ref, ITreeAppendable tree) {
		tree.append("ctx.get(\"");
		tree.append(ref.ns);
		tree.append(":" + ref.prop + "\")");
	}

}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Previous Topic:Error creating Xtext Web Editor (Ace) in custom div
Next Topic:Problem with importing several projects
Goto Forum:
  


Current Time: Fri Mar 29 15:10:28 GMT 2024

Powered by FUDForum. Page generated in 0.02361 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top