Extending the scope of a scope provider / Refining baseLanguage concepts

Hey,

I did quite some research, but couldn't find a good solution for my issue yet. Let me describe my problem first.

Let's assume that my language extends the BlockStatement of baseLanguage. Thus, my NewBlockStatement can be added everywhere in a class, where statements are allowed. However, what I'd like to do now is telling the next available scope provider that it should also include variables in its nlist<LocalVariableDeclaration> that are declared within a NewBlockStatement node. A code snippet would look like this:

public void foo(){
// new block "extends" the scope of foo
MyNewBlockStatement[
int x = 0;
]
x = 0; // perfectly fine as in scope
}

I had some ideas, but didn't know how to do it.

  1. It would be nice and easy to have a language extension, which "injects" the required code into baseLanguage concepts that implement getScopeVariables(), but I doubt that there's a way in MPS?!
  2. My second less elegant thought was to have a mechanism that automatically replaces the affected nodes (i.e., the ancestor implementing getScopeVariables()), either every time or just when a NewBlockStatement is added. For instance, we would replace the StatementList child of the method declaration with a NewStatementList node. The NewStatementList concept extends StatementList and overrides getScopeVariables() in order to introduce the additional variable declarations.

I can imagine how to substitute nodes, when a NewBlockStatement node is added, however it would be nicer to have only NewStatementList nodes instead of StatementList nodes in the tree. I don't know how to achieve that. However, IMHO the most elegant solution is option 1. Something like Categories and method swizzling in Objective-C, aspects, mixins, ...

Maybe, I'm totally on the wrong track... Any help is greatly appreciated!

Thx and cheers,
Ben

 

 

4 comments

Hi,

the first approach is certainly more elegant, but is not supported in BL. The second approach, unfortunately, would indeed have to be implemented manually, as you suggest. I can't think of any useful automation here, I'm afraid.

Vaclav

 

0

Hi Vaclav,

thanks for the response. That's a pity... I already started doing it manually and it works like a charm, but I had hope for a better solution...

Thx and cheers,

Ben

0

Hi Ben

A slightly more elegant variant of the less elegant solution would be not to replace the enclosing statement list itself, rather attach/deattach a node attribute to it. Node attributes should behave like parents when the search for scope providers goes up the tree (see jetbrains.mps.scope.Scope.parent() ). This would definitely be a more maintainable solution, as you wouldn't mess with the existing structure, and what's more you wouldn't have to rely on the details of base language implementation too much.

As for the first approach, currently mps doesn't allow you to embed your stuff into scopes freely like that. So, it's up to the language designers of the language being extended to decide if they provide an extension point at that place. As Valcav said, baseLanguage doesn't do that in this particular place.

Daniil

0

Hi Daniil,

thanks for the feedback! Interesting idea. My solution currently adds hooks/extension points to the base language using lang.extension. It works quite nicely. However, it has obviously the drawback that I need to update mps through git resolving conflicts with my own baselanguage version.

Thanks and cheers

Ben

 

0

Please sign in to leave a comment.