Scope issue when extending BaseLanguage?
As part of exploring MPS I've created a new language and defined it as "extends BaseLanguage".
For starter, all that this new language has is a root concept which contains children:
elements : BaseConcept[0..n]
When I create a new solution (using this new language)and I choose that new concept, I'm able to add to the solution some LocalVariableDecelaration (e.g. int myVal = 3;)
yet when I add an IfStatement I'm unable to choose myVal (as part of the condition or as part of the statement).
Is that a scope issue? How can it be fixed?
For starter, all that this new language has is a root concept which contains children:
elements : BaseConcept[0..n]
When I create a new solution (using this new language)and I choose that new concept, I'm able to add to the solution some LocalVariableDecelaration (e.g. int myVal = 3;)
yet when I add an IfStatement I'm unable to choose myVal (as part of the condition or as part of the statement).
Is that a scope issue? How can it be fixed?
Please sign in to leave a comment.
In BaseLanguage, statements are typically contained within a StatementList, which implements ScopeProvider and thus allows the VariableReference to "see" the VariableDeclarations.
A detailed explanation with a sample can be found here: https://confluence.jetbrains.com/display/MPSD32/Scopes
There is only one concept (the root concept) in the new language. So if defining it as the ScopeProvider doesn't help, how can this scope issue be solved?
public Scope getScope(conceptNode<> kind, node<> child) overrides ScopeProvider.getScope { new ListScope(this.descendants<concept = VariableDeclaration>) { public string getName(node<> child) { child : INamedConcept.name; } }; }"Error: Variable myVar is already defined in the scope".
I guess this happens since any local variable is part of the root concept which is also the concept that provides the scope, so whichever name you give the variable it enters the list and therefore "is already defined".
I've tried another approach: I've cancelled the "implements ScopeProvider" for the root concept (and also deleted its behavior) and changed its children definition to:
statements : StatementList[0..n]
Since StatementList is implements ScopeProvider I've expected this will solve the problem. Yet this solves only the "is already defined" issue but scoping is not as expected - the local variable names are not available for the if statement.
I see that the getScope() of StatementList behavior is:
if (kind.isExactly(VariableDeclaration)) {
}
So the StatementList scope is meant for VariableDeclaration types only?
Is there a way to change my root concept (maybe define another type of children?) to enable usage of local variables and also have their names in the scope (for other statements)?
Once both VariableDeclarations and IfStatements are in the same StatementList, things will work the way you expect.
Thanks!