Skip to main content



      Home
Home » Modeling » TMF (Xtext) » Overloaded method determination
Overloaded method determination [message #1755794] Wed, 08 March 2017 04:17 Go to next message
Eclipse UserFriend
Hello,

A few days ago I noticed that the overloaded methods aren't working well. If I want to Ctrl+click or hovering on the function call, it jumps/shows the first occurence of the function, no matter whether arguments are correct or not.

I recognized, SimpleNameProvider gets the wrong EObject as parameter in getFullyQualifiedName method.

I am looking for a solution in which I can specify the correct function. Could you help me, please?
(Is it possible, that I should change something in the .xtext file in order to make it work?)

Thanks for your help.
Re: Overloaded method determination [message #1755795 is a reply to message #1755794] Wed, 08 March 2017 04:20 Go to previous messageGo to next message
Eclipse UserFriend
how does your implementation of the scopeprovider look like. ususally you do determine the right matching candidate there.
if the language supports parameter overloading then this might be not trivial
Re: Overloaded method determination [message #1755799 is a reply to message #1755795] Wed, 08 March 2017 04:30 Go to previous messageGo to next message
Eclipse UserFriend
Thank you for your quick answer.
Well, nothing special regarding the functions (only handling of variables is overriden here), it only calls the getScope method of AbstractDeclarativeScopeProvider class.

The goal is not complex, I believe the solution shouldn't be either.
If I have functions in the same file like:
function funcname() end
function funcname(integer i) end
function funcname(string s) end,
then it should match the right one calling "funcname(5);"
Re: Overloaded method determination [message #1755811 is a reply to message #1755799] Wed, 08 March 2017 06:01 Go to previous messageGo to next message
Eclipse UserFriend
Yes but this needs to be done in scoping
And depending on your typesytem this might not be trivial
=> without a complete spec how function are defined and how your types
Work it is hard to tell how to best implement scoping
Re: Overloaded method determination [message #1755822 is a reply to message #1755811] Wed, 08 March 2017 07:47 Go to previous messageGo to next message
Eclipse UserFriend
Hmm, this is a bit simplified, but the most important things can be found here:

Function: 'function' name=ID '(' (parameters+=Parameter (',' parameters+=Parameter)*)? ')' 'endfunction';
Parameter: type=ParameterType reference?='&'? name=ID;
ParameterType: BasicType | 'any';
BasicType: 'integer'| 'float' | 'string';
Re: Overloaded method determination [message #1755830 is a reply to message #1755822] Wed, 08 March 2017 08:52 Go to previous messageGo to next message
Eclipse UserFriend
and the function calls? how do they look like?
Re: Overloaded method determination [message #1755836 is a reply to message #1755830] Wed, 08 March 2017 09:22 Go to previous messageGo to next message
Eclipse UserFriend
Let's keep it simple:
function=[Function] '(' arguments+=Expression? (',' arguments+=Expression)* ')'

Expression is pretty hard. It is built with rules that are able to recognize precedence level operations and other things, that I hope, are not needed.
And somewhere very deep constants - for instance - are potential expressions.
SomeRule returns Expression:
 ...
 | constant = Constant
 | function=[Function] '(' arguments+=Expression? (',' arguments+=Expression)* ')'
 (that is mentioned above)
 | ...
;
Constant: IntegerConstant | FloatConstant | StringConstant | CharacterConstant;
IntegerConstant: value=INTEGER | value=HEXA;
FloatConstant: value=FLOAT;
StringConstant: value=STRING;
CharacterConstant: value=CHARACTER;

Those types are terminals. Let's exclude integer -> float conversions for the sake of "simplicity".
Re: Overloaded method determination [message #1755838 is a reply to message #1755836] Wed, 08 March 2017 09:23 Go to previous messageGo to next message
Eclipse UserFriend
well that means function calls are recursive,
and you call that trivial?

that is way too much to create a small example
Re: Overloaded method determination [message #1755840 is a reply to message #1755838] Wed, 08 March 2017 09:24 Go to previous messageGo to next message
Eclipse UserFriend
e.f

calla(callb(callc(calld(1,2),3,calle())))1,)....
Re: Overloaded method determination [message #1755844 is a reply to message #1755840] Wed, 08 March 2017 09:33 Go to previous messageGo to next message
Eclipse UserFriend
This is assuredly not trivial. Anyway, I hope I don't have to give up and there's a solution Smile
Re: Overloaded method determination [message #1755846 is a reply to message #1755844] Wed, 08 March 2017 09:39 Go to previous messageGo to next message
Eclipse UserFriend
yes of course but i need to understand your requirements to give an adequate answer
Re: Overloaded method determination [message #1755871 is a reply to message #1755846] Wed, 08 March 2017 13:25 Go to previous messageGo to next message
Eclipse UserFriend
Idea: Store the signature infos in the xtext index / scope entries and adapt scoping.

lets start with a way way way less complicated grammar
Model:
	functions+=Function*
	calls+=Call*;
	
Function:
	"func" name=ID '(' (types+=DeclaredParameter (',' types+=DeclaredParameter)*)? ')' ':' returnType=Type
;
	
DeclaredParameter:
	name=ID ":" type=Type
;
Expression:
	Literal | Call
;

Literal:
	IntegerLiteral | StringLiteral
;

IntegerLiteral:
	value=INT
;

StringLiteral:
	value=STRING
;


enum Type: String | Integer;

Call:
	 func=[Function] '(' (params+=Expression (',' params+=Expression)*)? ')'
;	


// indexing
class MyDslResourceDescriptionStrategy extends DefaultResourceDescriptionStrategy {

	private final static Logger LOG = Logger.getLogger(MyDslResourceDescriptionStrategy);

	override createEObjectDescriptions(EObject eObject, IAcceptor<IEObjectDescription> acceptor) {
		if (eObject instanceof Function) {
			if (getQualifiedNameProvider() === null)
				return false;
			try {
				val QualifiedName qualifiedName = getQualifiedNameProvider().getFullyQualifiedName(eObject);
				if (qualifiedName !== null) {
					val userData = newHashMap
					if (eObject.returnType !== null) {
						userData.put("RETURN_TYPE", eObject.returnType.literal)
					}
					userData.put("PARAM_TYPES", eObject.types.map[type.literal].join(","))
					acceptor.accept(EObjectDescription.create(qualifiedName, eObject, userData));
				}
			} catch (Exception exc) {
				LOG.error(exc.getMessage(), exc);
			}
			return true;
		}
		return super.createEObjectDescriptions(eObject, acceptor)
	}

}


// scope entries for local file

class MyDslImportedNamespaceAwareLocalScopeProvider extends ImportedNamespaceAwareLocalScopeProvider {

	override protected internalGetAllDescriptions(Resource resource) {
		var Iterable<EObject> allContents = new Iterable<EObject>() {
			override Iterator<EObject> iterator() {
				return EcoreUtil.getAllContents(resource, false)
			}
		}
		var Iterable<IEObjectDescription> allDescriptions = scopedElementsFor(allContents, qualifiedNameProvider)
		return new MultimapBasedSelectable(allDescriptions)

	}

	def static <T extends EObject> Iterable<IEObjectDescription> scopedElementsFor(Iterable<? extends T> elements,
		Function<T, QualifiedName> nameComputation) {
		var Iterable<IEObjectDescription> transformed = Iterables.transform(elements, [ T from |
			val QualifiedName qualifiedName = nameComputation.apply(from)

			if (qualifiedName !== null) {
				if (from instanceof org.xtext.example.mydsl1.myDsl.Function) {
					val userData = newHashMap
					if (from.returnType !== null) {
						userData.put("RETURN_TYPE", from.returnType.literal)
					}
					userData.put("PARAM_TYPES", from.types.map[type.literal].join(","))
					return new EObjectDescription(qualifiedName, from, userData)
				}
				return new EObjectDescription(qualifiedName, from, null)
			}
		])
		return Iterables.filter(transformed, Predicates.notNull())
	}

}



// scope provider
class MyDslScopeProvider extends AbstractMyDslScopeProvider {
	
	override getScope(EObject context, EReference reference) {
		if (reference === MyDslPackage.Literals.CALL__FUNC) {
			if (context instanceof Call) {
				val actualSignature =
					context.params.map[
						p |
						if (p instanceof StringLiteral) {
							return Type.STRING.literal
						}
						if (p instanceof IntegerLiteral) {
							return Type.INTEGER.literal
						}
						if (p instanceof Call) {
							return p.func.returnType.literal
						}
					].join(",")
				return new FilteringScope(delegateGetScope(context, reference)) [
					val sig = getUserData("PARAM_TYPES")
					if (sig !== null) {
						return actualSignature == sig
					}
					return true
				]
			}
		}
		super.getScope(context, reference)
	}

}


// bindings
class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {
    
    def Class<? extends IDefaultResourceDescriptionStrategy> bindIDefaultResourceDescriptionStrategy() {
        MyDslResourceDescriptionStrategy
    }

 override configureIScopeProviderDelegate(Binder binder) {
        binder.bind(IScopeProvider).annotatedWith(Names.named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)).to(
            MyDslImportedNamespaceAwareLocalScopeProvider);

    }
}
Re: Overloaded method determination [message #1756025 is a reply to message #1755871] Fri, 10 March 2017 03:55 Go to previous message
Eclipse UserFriend
Wow, this solution is working, thank you for your help!

I just tried it and I believe, that adaptation to our language will be hard (e.g. I'm afraid of rules that "returns Expression"). Anyway, it's my turn, I need to think over all of this, that takes some time.
You, sir, are really great.
Previous Topic:Input with multiple alternatives
Next Topic:IAutoWrapFormatter with indent ignores newline under certain conditions
Goto Forum:
  


Current Time: Mon May 12 15:40:19 EDT 2025

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

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

Back to the top