Skip to main content



      Home
Home » Modeling » TMF (Xtext) » How to extend default scope with attributes from superclass?
How to extend default scope with attributes from superclass? [message #885219] Tue, 12 June 2012 12:20 Go to next message
Eclipse UserFriend
Consider following grammar definition (... a little part of):


Model: declarations+=(DeclaredConstant | DeclaredFunction | DeclaredEntity)*;

...

EvaluableID : DeclaredAttribute | DeclaredConstant | DeclaredOperation | DeclaredFunction | DeclaredParameter | DeclaredVariable

EvaluableIDRef 	: ref=[EvaluableID] | builtInC=BuildInConstant | builtInF=BuiltInFunction;

...
PrimaryExpression returns Expression:  {Literal} val=INT | {Evaluation} ref=EvaluableIDRef;
...
Statement:  ... /* is using of Expressions */ ...;
...

DeclaredFunction: 'FUNCTION' name=ID ... /* is using of Statements */ ...;
DeclaredOperation: 'OPERATION' name=ID ... /* is using of Statements */ ...;

...

DeclaredEntity:
  'ENTITY' name=ID ('EXTENDS' super=[DeclaredEntity])?
  attrs+=DeclaredAttribute*
  opers+=DeclaredOperation*
;

...



What is the easiest way to extend the default scope for "EvaluableIDRef" (which will be given by a standard scope provider) with a list of additional attributes given from all superclasses of the current entity (for example if the current context is Model -> DeclaredEntity -> DeclaredOperation -> "SomeStatement" -> PrimaryExpression -> EvaluableIDRef ...).

I need some code snippet (of expected implementation) to understand how it works.

Once again to clarify -> i don't need to replace the standard scope provider function for this case -> much more i would use the scope returned from this function and extend it with additional attributes from whole superclass hierarchy (attribute names are (can be) also not unique).

Thank you!

[Updated on: Tue, 12 June 2012 12:22] by Moderator

Re: How to extend default scope with attributes from superclass? [message #885228 is a reply to message #885219] Tue, 12 June 2012 12:29 Go to previous messageGo to next message
Eclipse UserFriend
Hi a complete simplified reproducable grammar would be nice.

The general solution is
(a) collect the stuff explicitly.
(b) do some (multiple) index querying
Re: How to extend default scope with attributes from superclass? [message #885258 is a reply to message #885228] Tue, 12 June 2012 13:36 Go to previous messageGo to next message
Eclipse UserFriend
Simplified grammar definition:

Model: declarations+=Declaration*;

enum BuildInConstant: PI | TRUE | FALSE | NULL;
enum BuiltInFunction: SQRT | ABS | MOD;

Declaration: DeclaredConstant | DeclaredFunction | DeclaredEntity;

EvaluableID: DeclaredParameter | DeclaredVariable | DeclaredAttribute | DeclaredOperation | DeclaredConstant | DeclaredFunction;
EvaluableIDRef: ref=[EvaluableID] | builtInC=BuildInConstant | builtInF=BuiltInFunction;

AssignableID: DeclaredParameter | DeclaredVariable | DeclaredAttribute;
AssignableIDRef: ref=[AssignableID];

Expression: {Literal} val=INT | {Evaluation} ref=EvaluableIDRef ( '(' arguments+=Expression+ ')' )?;

Statement:
	{ AssignmentStmt } ref=AssignableIDRef '=' expr=Expression ';'
	| { ForStmt } 'FOR' var=DeclaredVariable '=' from=Expression 'TO' to=Expression ('STEP' step=Expression)? '{' stmts+=Statement* '}'
	| { ReturnStmt } kwd='RETURN' ( expr=Expression )? ';'
;

DeclaredConstant: 'CONST' name=ID '=' value=Expression ';';
DeclaredVariable: name=ID;
DeclaredAttribute: name=ID;
DeclaredParameter: name=ID;

DeclaredFunction:
	'FUNCTION' name=ID ( '(' parameters+=DeclaredParameter* ')' )? '{'
	('VAR' vars+=DeclaredVariable+ ';')*
	statements+=Statement*
	'}'
;

DeclaredOperation:
	'OPERATION' name=ID ( '(' parameters+=DeclaredParameter* ')' )? '{'
	('VAR' vars+=DeclaredVariable+ ';')*
	statements+=Statement*
	'}'
;


DeclaredEntity:
  'ENTITY' name=ID ('EXTENDS' super=[DeclaredEntity])? '{'
  ('ATT' attrs+=DeclaredAttribute+ ';')*
  opers+=DeclaredOperation*
  '}'
;


Example:

See here: --> img195.imageshack.us/img195/9311/clipboard03dy.jpg

ENTITY A {
	ATT x y;
}

ENTITY B EXTENDS A {
	ATT a b;
	OPERATION init() {
		VAR v1;
		v1 =  ... // <--- Here i also would like to have a possibility to reference additional attributes x,y from ENTITY A ....
	}
}


...

[Updated on: Tue, 12 June 2012 13:41] by Moderator

Re: How to extend default scope with attributes from superclass? [message #885278 is a reply to message #885258] Tue, 12 June 2012 14:22 Go to previous messageGo to next message
Eclipse UserFriend
Hi,

to get a basic understanding this grammar is still way to complex
since there is some problematics with precedence/multiple types

public class MyDslScopeProvider extends AbstractDeclarativeScopeProvider {

	IScope scope_EvaluableIDRef_ref(DeclaredEntity context, EReference reference) {
		IScope outerAttrs = getOuterAttrScope(context.getSuper());
		return MultimapBasedScope.createScope(outerAttrs, delegateGetScope(context, reference).getAllElements(), false);
		
	}


	private IScope getOuterAttrScope(final DeclaredEntity parent) {
		System.out.println(parent);
		if (parent == null) {
			return IScope.NULLSCOPE;
		} else {
			return Scopes.scopeFor(parent.getAttrs() , getOuterAttrScope(parent.getSuper()));
		}
	}
	
}
Re: How to extend default scope with attributes from superclass? [message #885593 is a reply to message #885278] Wed, 13 June 2012 05:45 Go to previous messageGo to next message
Eclipse UserFriend
Thank you Christian, it was (very!) helpful.
I've changed your code a bit to get it more generic.
public class MyDslSP extends AbstractDeclarativeScopeProvider {

	IScope scope_EvaluableIDRef_ref(DeclaredEntity context, EReference reference) {
		//System.out.println("GET_SCOPE: " + context + " - " + reference);
		if (context == null)
			return IScope.NULLSCOPE;
		IScope ctxScope = delegateGetScope(context, reference);
		IScope inhScope = scope_EvaluableIDRef_ref(context.getSuper(), reference);  // resolve inheritance scoping
		return MultimapBasedScope.createScope(ctxScope, inhScope.getAllElements(), false);
	}	
}


Can you check it please if it is correct or if you have a better idea how to optimize it ...

[Updated on: Wed, 13 June 2012 08:09] by Moderator

Re: How to extend default scope with attributes from superclass? [message #885658 is a reply to message #885593] Wed, 13 June 2012 08:06 Go to previous messageGo to next message
Eclipse UserFriend
Hi Christian,
it works now with inherited attributes (and operations) but i've got 2 additional (much bigger) problems after that:

1. For a real example (with 300-400 Entities and 5-10 Operations per Entity and 100 Expressions per Operation and inheritance deep over 10 levels and more (also with multiple inheritance)) - build performance is now very-very ( x 1000 ) poor - it is no more acceptable at the moment.

2. The referencing to local variables does not work anymore:

Example:


ENTITY A {
	ATT a;
}

ENTITY B EXTENDS A {
	ATT q;
	OPERATION replace_q_a {
		VAR v;
		v = q;    // OK
		q = a;    // OK
		a =       // ERROR:  "Couldn't resolve reference to EvaluableID a" (Attribute "a" not visible, it needs scope provider implementation for AssignableRefID)
		    v;    // ERROR:  "Couldn't resolve reference to EvaluableID v" ( ... why?? )
	}
}


How can i solve it?

[Updated on: Wed, 13 June 2012 08:40] by Moderator

Re: How to extend default scope with attributes from superclass? [message #885696 is a reply to message #885658] Wed, 13 June 2012 08:53 Go to previous messageGo to next message
Eclipse UserFriend
Think about storing the stuff in the index and query it multiple
times. Maybe I'll find an example this evening. I will ease your
grammar to have attributes only
Re: How to extend default scope with attributes from superclass? [message #885860 is a reply to message #885696] Wed, 13 June 2012 14:25 Go to previous messageGo to next message
Eclipse UserFriend
Hi,

of course you have to do the same for the other side (AssignableIDRef) - this is one reason why i said your grammar is still way to complex to get started with advanced scoping.

and yes if you do scoping this way it will be performance pain in the ass. this is why i suggested you to use the index

(1) introducing dynamic implicit imports
(2) collect all stuff from the index

here an example for (2)

First we have to care the the attributes get a simple name

public class MyDslNameProvider extends DefaultDeclarativeQualifiedNameProvider {

	public QualifiedName qualifiedName(DeclaredAttribute attr) {
		return QualifiedName.create(attr.getName());
	}
	
}


then we care that the entities add their parent's name to the index
the attributes add their entity's name to the index

public class MyDslResourceDescriptionStrategy extends
		DefaultResourceDescriptionStrategy {

	
	public boolean createEObjectDescriptions(EObject eObject, IAcceptor<IEObjectDescription> acceptor) {
		
		if (eObject instanceof DeclaredEntity ) {
			Map<String, String> data = new HashMap<String, String>();
			List<INode> nodes = NodeModelUtils.findNodesForFeature(eObject, MyDslPackage.Literals.DECLARED_ENTITY__SUPER);
			if (nodes.size()>0) {
				String parentName = nodes.get(0).getText().trim();
				data.put("entity", parentName);
			}
			return createEOD(eObject, acceptor, data );
		} else if (eObject instanceof DeclaredAttribute ) {
			Map<String, String> data = new HashMap<String, String>();
			DeclaredEntity entity = EcoreUtil2.getContainerOfType(eObject, DeclaredEntity.class);
			data.put("entity", entity.getName());
			return createEOD(eObject, acceptor, data);
		}
		return super.createEObjectDescriptions(eObject, acceptor);
		
	}

	private boolean createEOD(EObject eObject,
			IAcceptor<IEObjectDescription> acceptor, Map<String, String> data) {
		if (getQualifiedNameProvider() == null)
			return false;
		try {
			QualifiedName qualifiedName = getQualifiedNameProvider().getFullyQualifiedName(eObject);
			if (qualifiedName != null) {
				acceptor.accept(EObjectDescription.create(qualifiedName, eObject, data));
			}
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return true;
	}

}


since scoping for the local file is not done via index we have to fix this too

//fix handling of the local file
public class MyDslImportedNamespaceAwareLocalScopeProvider extends ImportedNamespaceAwareLocalScopeProvider{
	
	@Inject
	private IDefaultResourceDescriptionStrategy rds;
	
	@Override
	protected ISelectable internalGetAllDescriptions(final Resource resource) {
		Iterable<EObject> allContents = new Iterable<EObject>(){
			public Iterator<EObject> iterator() {
				return EcoreUtil.getAllContents(resource, false);
			}
		}; 
		final List<IEObjectDescription> allDescriptions = new ArrayList<IEObjectDescription>();
		IAcceptor<IEObjectDescription> acceptor = new IAcceptor<IEObjectDescription>() {
			
			@Override
			public void accept(IEObjectDescription t) {
				allDescriptions.add(t);
			}
		};
		for (EObject o : allContents) {
			rds.createEObjectDescriptions(o, acceptor);
		}
		return new MultimapBasedSelectable(allDescriptions);
	}

}


at last step we fix the scoping and
calculate all parent's names using the index
filter the attributes by the parents names

public class MyDslScopeProvider extends AbstractDeclarativeScopeProvider {

	IScope scope_EvaluableIDRef_ref(DeclaredEntity context, EReference reference) {
		final Set<String> allEntities = getAllEntities(context);
		Predicate<IEObjectDescription> filter = new Predicate<IEObjectDescription>() {
			@Override
			public boolean apply(IEObjectDescription input) {
				String entity = input.getUserData("entity");
				return entity != null && allEntities.contains(entity);
			}
		};
		return new FilteringScope(delegateGetScope(context, reference), filter );
		
	}
	
	Set<String> getAllEntities(DeclaredEntity context) {
		Map<String,String> allEntities = new HashMap<String,String>();
		for (IEObjectDescription e : delegateGetScope(context, MyDslPackage.Literals.DECLARED_ENTITY__SUPER).getAllElements()) {
			String parent = e.getUserData("entity");
			if (parent != null) {
				allEntities.put(e.getQualifiedName().toString(), parent);
			}
		}
		Set<String> result = Sets.newHashSet();
		String current = context.getName();
		while(current != null && result.add(current)) {
			current = allEntities.get(current);
		}
		return result;
	}


	
}


please note: this only handles attributes
the have to be some extra changes to be made to fix
it for other Evaluable types

~Christian
Re: How to extend default scope with attributes from superclass? [message #885861 is a reply to message #885860] Wed, 13 June 2012 14:26 Go to previous messageGo to next message
Eclipse UserFriend
P.S: here for completeness the runtime module that binds all the stuff

public class MyDslRuntimeModule extends org.xtext.example.mydsl.AbstractMyDslRuntimeModule {

	@Override
	public Class<? extends IQualifiedNameProvider> bindIQualifiedNameProvider() {
		return MyDslNameProvider.class;
	}
	
	public Class<? extends IDefaultResourceDescriptionStrategy> bindIDefaultResourceDescriptionStrategy() {
		return MyDslResourceDescriptionStrategy.class;
	}
	
	public void configureIScopeProviderDelegate(com.google.inject.Binder binder) {
		binder.bind(org.eclipse.xtext.scoping.IScopeProvider.class)
		.annotatedWith(com.google.inject.name.Names.named(
				org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.NAMED_DELEGATE))
				.to(MyDslImportedNamespaceAwareLocalScopeProvider.class);
	}
	
}
Re: How to extend default scope with attributes from superclass? [message #886131 is a reply to message #885861] Thu, 14 June 2012 05:52 Go to previous messageGo to next message
Eclipse UserFriend
Hi Christian,

a lot of thanks for the excellent support. I now need time to have understand this indexing stuff before i will start to integrate it into my grammar. I'm not sure if it will be also a way to redesign the grammar and get it more simplified and preformant.
Therefore, as long, i will use the previous solution which is working fine at the moment (for small/middle models -> performance is acceptable). Can u give me a hint why it stops to resolve the variable "v" (see example above) when i try to use my scope provider (scope_EvaluableIDRef_ref(...))? Thanks!

[Updated on: Thu, 14 June 2012 05:56] by Moderator

Re: How to extend default scope with attributes from superclass? [message #886143 is a reply to message #886131] Thu, 14 June 2012 06:22 Go to previous messageGo to next message
Eclipse UserFriend
No would have to use the Debugger too
Re: How to extend default scope with attributes from superclass? [message #889505 is a reply to message #886143] Tue, 19 June 2012 05:53 Go to previous message
Eclipse UserFriend
Hi, here is my solution which i use at the moment. Not so performant as the one from Christian (-> using of indexes, see above), but for the most cases it is OK.

Xtext (snippet):


...

Statement:
	{ AssignmentStmt } ref=AssignableIDRef '=' expr=Expression ';'
	| { ForStmt } kwd='FOR' var=DeclaredVariable '=' from=Expression 'TO' to=Expression ('STEP' step=Expression)? '{' stmts+=Statement* '}'
	| { ReturnStmt } kwd='RETURN' ( expr=Expression )? ';'
;

...

DeclaredEntity:
  'ENTITY' name=ID ('EXTENDS' parents+=EntityRef*)? '{'
  ('ATT' attrs+=DeclaredAttribute+ ';')*
  opers+=DeclaredOperation*
  '}'
;

EntityRef 		: ref=[DeclaredEntity];

...



Java:


public class MyDslSP extends AbstractDeclarativeScopeProvider {

	private EObject origCtx = null;

	public IScope getScope(EObject context, EReference reference) {
		origCtx = context;
		return super.getScope(context, reference);
	}

	IScope scope_EvaluableIDRef_ref(DeclaredEntity context, EReference reference) {
		return extendInheritanceScope(context, reference);
	}

	IScope scope_AssignableIDRef_ref(DeclaredEntity context, EReference reference) {
		return extendInheritanceScope(context, reference);
	}
	
	IScope extendInheritanceScope(DeclaredEntity context, EReference reference) {


		// get original context scope
		IScope ctxScope = delegateGetScope(origCtx, reference);

		// add inheritance scopes
		Set<DeclaredEntity> allParents = collectAllParrents(context, new HashSet<DeclaredEntity>()); 
		for (DeclaredEntity ent : allParents)
			ctxScope = ((MyDslINALSP)getDelegate()).getLocalScope(ctxScope, ent, reference);

		return ctxScope;
	}
	
	Set<DeclaredEntity> collectAllParrents(DeclaredEntity context, Set<DeclaredEntity> elements) {
		for (EntityRef ref : context.getParents())
		{
			DeclaredEntity de = ref.getRef();
			elements.add(de);
			collectAllParrents(de, elements);
		}
		return elements;
	}
}


public class MyDslINALSP extends ImportedNamespaceAwareLocalScopeProvider {

	public IScope getLocalScope(IScope parent, final EObject context, final EReference reference) {
		return getLocalElementsScope(parent, context, reference); 
	}
}


public class MyDslQNP extends DefaultDeclarativeQualifiedNameProvider {

	int cnt = 0;
	// providing of local visibility for "ForStmt" variables
	QualifiedName qualifiedName(ForStmt f) {
		if ("FOR".equals(f.getKwd()))
			f.setKwd("FORSTMT:" + cnt++);
		return QualifiedName.create(f.getKwd());
	}
}



public class MyDslRuntimeModule extends org.xtext.example.mydsl.AbstractMyDslRuntimeModule {


    @Override
    public Class<? extends IQualifiedNameProvider> bindIQualifiedNameProvider() {
    	return MyDslQNP.class;
	}
    
    @Override
    public Class<? extends IScopeProvider> bindIScopeProvider() {
    	return MyDslSP.class;
	}
    
    @Override
	public void configureIScopeProviderDelegate(com.google.inject.Binder binder) {
		binder.bind(org.eclipse.xtext.scoping.IScopeProvider.class)
		.annotatedWith(com.google.inject.name.Names.named(
				org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.NAMED_DELEGATE))
				.to(MyDslINALSP.class);
	}
}

[Updated on: Tue, 19 June 2012 05:54] by Moderator

Previous Topic:[EPackage import] "Make sure the EPackage has been registered." error
Next Topic:Strange behavior of the JvmModelInferrer
Goto Forum:
  


Current Time: Sun Nov 02 12:56:18 EST 2025

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

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

Back to the top