Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Hierarchic (java-like) scoping
Hierarchic (java-like) scoping [message #704206] Thu, 28 July 2011 11:36 Go to next message
Julien Bigot is currently offline Julien BigotFriend
Messages: 26
Registered: July 2009
Junior Member
Hi, I'm trying to get a java-like nested scoping to work.
That is, having blocks inside each others with elements hiding and shadowing.

block {
  var v1 = CST;
  block {
    var v2 = v1;
  }
  var v3 = v2; // error, v2 is hidden
  block {
    var v2 = CST; 
    var v3 = v2; // shadow upper v3, v2 is unambiguous since the other v2 is hidden
  }
}


Right now I'm working on single file instances, so I have no problem of classpath or importURI and I have no notion of named namespace or namespace import so it seems to me this is a rather simple case.

What I have done is create a new ResourceDescriptionStrategy that only exposes the top level declarations, that is it only enters the top level element and only accepts declarations ... rather straightforward.

public class HlaResourceDescriptionStrategy extends DefaultResourceDescriptionStrategy {
	public boolean createEObjectDescriptions(EObject eObject, IAcceptor<IEObjectDescription> acceptor) {
		if (eObject instanceof Declaration)
			super.createEObjectDescriptions(eObject, acceptor);
		return eObject instanceof HlaModel;
	}
}


However when it comes to the LocalScopeProvider, I dont get what the right implementation is.

I started with a SimpleLocalScopeProvider, however it seems to have no support for nested block hiding/shadowing. From what I understand, it returns (resource scope)->(global scope) where the resource scope contains every named element of the current resource.

So I switched to ImportedNamespaceAwareLocalScopeProvider. Even if I don't have namespace imports, the blocks are (anonymous) namespaces so it makes sense. However, once again I have a problem. from what I understand, it returns (block scope)->...->(block scope)->(resource scope)->(global scope).However, once again, a block scope ionly supports namespace imports, either explicit (I don't have any) or implicit in the case of named blocks.
Once again, the resource scope contains each and every named elements of the current resource with no notion of nesting.

I investigated using a QualifiedNameProvider instead of a SimpleNameProvider but that does not solve the problem of anonymous blocks.

So I guess the conclusion of all that is that I will have to implement my own LocalScopeProvider. It sounds to me like I'm doing a mistake as I am surprised that nested scopes is not part of the common ground supported by xtext.

However, if I have to do it, what would be the right way ?
I see at list two options:

  • inherit from AbstractGlobalScopeDelegatingScopeProvider and somehow delegate to AbstractGlobalScopeDelegatingScopeProvider if I want to add namespaces;
  • or inherit from AbstractGlobalScopeDelegatingScopeProvider

[Updated on: Thu, 28 July 2011 11:37]

Report message to a moderator

Re: Hierarchic (java-like) scoping [message #705171 is a reply to message #704206] Fri, 29 July 2011 14:29 Go to previous messageGo to next message
alex.ren2006 is currently offline alex.ren2006Friend
Messages: 46
Registered: June 2011
Member
Hi, I think I am currently facing the same problem. (see http://www.eclipse.org/forums/index.php/t/226107/). One solution I come up with is as follows (just think of the "scope" in my code as the "block" in yours)
==========================
package org.xtext.example.mydsl.naming;

import java.util.Hashtable;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.naming.QualifiedName;
import org.xtext.example.mydsl.myScope.scope;

import com.google.inject.Inject;

public class MyScopeQualifiedNameProvider extends
		DefaultDeclarativeQualifiedNameProvider {
	
	@Inject
	private IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
	
	private int counter = 0;
	private Hashtable<EObject, String> nametable = new Hashtable<EObject, String>();

	public QualifiedName getFullyQualifiedName(final EObject obj) {
		QualifiedName t = super.getFullyQualifiedName(obj);
		if (obj instanceof scope) {
			String name = nametable.get(obj);
			if (name == null) {
				name = Integer.toString(counter++);
				nametable.put(obj, name);
			}
			t=converter.toQualifiedName(name);
		}
		if (t != null) {
			System.out.println("====================" + t.toString());
		}
		return t;
	}

}
===================================

It works but I am not sure it's a good solution since I keep inserting more objects into the map but I never take them out, which seems to be kind of memory leak.
Re: Hierarchic (java-like) scoping [message #705180 is a reply to message #705171] Fri, 29 July 2011 14:39 Go to previous message
Julien Bigot is currently offline Julien BigotFriend
Messages: 26
Registered: July 2009
Junior Member
I came up with a distinct solution involving nested IScopes. I don't know if it's the way it's expected to be done but ...

Regarding your memory leak problem, you can solve it by replacing your Hashtable by a java.util.WeakHashMap I guess.

package fr.inria.graal.hlcm.scoping;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.naming.IQualifiedNameProvider;
import org.eclipse.xtext.resource.ISelectable;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.Scopes;
import org.eclipse.xtext.scoping.impl.AbstractGlobalScopeDelegatingScopeProvider;
import org.eclipse.xtext.scoping.impl.MultimapBasedSelectable;
import org.eclipse.xtext.scoping.impl.SelectableBasedScope;
import org.eclipse.xtext.util.IResourceScopeCache;
import org.eclipse.xtext.util.Tuples;

import com.google.inject.Inject;
import com.google.inject.Provider;

public class HlaScopeProvider extends AbstractGlobalScopeDelegatingScopeProvider {

  @Inject
  private IQualifiedNameProvider qualifiedNameProvider;

  @Inject
  private IResourceScopeCache cache;
  
  public void setCache(IResourceScopeCache cache) {
    this.cache = cache;
  }

  public void setNameProvider(IQualifiedNameProvider nameProvider) {
    this.qualifiedNameProvider = nameProvider;
  }

  protected IQualifiedNameProvider getNameProvider() {
    return qualifiedNameProvider;
  }

  public IScope getScope(final EObject context, final EReference reference) {
    IScope result = null; 
    if ( context.eContainer() != null ) {
      result = getScope(context.eContainer(), reference);
    } else {
      result = getGlobalScope(context.eResource(), reference);
    }
    result = createScope(result, context, reference);
    return result;
  }
  
  protected IScope createScope(IScope parent, final EObject context, EReference reference) {
    ISelectable contextContent = cache.get(Tuples.create(HlaScopeProvider.class.getName(), context, reference), 
        context.eResource(), new Provider<ISelectable>() {
      public ISelectable get() {
        return new MultimapBasedSelectable(Scopes.scopedElementsFor(context.eContents(), qualifiedNameProvider));
      }
    });
    return SelectableBasedScope.createScope(parent, contextContent, reference.getEReferenceType(), isIgnoreCase(reference));
  }

}

[Updated on: Fri, 29 July 2011 14:41]

Report message to a moderator

Previous Topic:Re: [Xtend 2] Access dynamically generated EPackages from Xtend 2 files
Next Topic:Creating grammar mixin
Goto Forum:
  


Current Time: Fri Apr 16 09:14:40 GMT 2021

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

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

Back to the top