Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » Epsilon » Using reflection
Using reflection [message #1820543] Wed, 22 January 2020 13:48 Go to next message
Ludovico Iovino is currently offline Ludovico IovinoFriend
Messages: 33
Registered: July 2019
Member
Hi all. I was wondering if there is a way to call a user defined operation in EOL with a sort of reflection style ...for instance by name.

This means that if I have an operation in my eol file called :

getPersons() on a specific context, i would like to call it by operation name. this is because I have this info in my models. Is it possible ?

Re: Using reflection [message #1820550 is a reply to message #1820543] Wed, 22 January 2020 15:45 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ludovico,

To my knowledge this is not possible, however I'm not sure why you would need this. There are two workarounds I can think of. The first is to generate your EOL program using EGL/EGX for a given model. Basically you paste your EOL code into an EGL template and use dynamic sections to retrieve and output the operation call. Another is to define helper methods which call the desired operation based on the model. For example, if the operation you want to call is defined in your model, you could have an operation with a "switch" statement on the model element property which defines this method and call it like that.

operation Any callOperation(operationName : String) {
    switch (operationName) {
        case "foo": return self.foo();
        case "bar": return self.bar();
        case "baz": return self.baz();
        default: throw "Unknown operation '"+operationName+"'";
    }
}
Re: Using reflection [message #1820551 is a reply to message #1820550] Wed, 22 January 2020 15:50 Go to previous messageGo to next message
Ludovico Iovino is currently offline Ludovico IovinoFriend
Messages: 33
Registered: July 2019
Member
Thanks Sina, actually the first solution is how I have already implemented, but I thought I could further automate the process. Thanks for confirming it.
Re: Using reflection [message #1820562 is a reply to message #1820551] Wed, 22 January 2020 21:32 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris KolovosFriend
Messages: 2165
Registered: July 2009
Location: York, UK
Senior Member

Hi Ludovico,

Below is a terrible solution for calling operations reflectively.

var s = "";

s.call("foo").println();
s.call("bar").println();

operation String foo() : String {
	return "foo";
}

operation String bar() : String {
	return "bar";
}

operation Any call(op : String) : Any {
	var m = new Native("org.eclipse.epsilon.eol.EolModule");
	m.parse("return target." + op + "();");
	m.operations.addAll(System.context.module.operations);
	m.context.frameStack.put("target", self);
	return m.execute();
}


Cheers,
Dimitris
Re: Using reflection [message #1820563 is a reply to message #1820562] Wed, 22 January 2020 21:41 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris KolovosFriend
Messages: 2165
Registered: July 2009
Location: York, UK
Senior Member

... and below is a more decent solution.

var s = "";

s.call("foo").println();
s.call("bar").println();

operation String foo() : String {
	return "foo";
}

operation String bar() : String {
	return "bar";
}

operation Any call(op : String) : Any {
	return System.context.module.
		operations.selectOne(o|o.name = op).
		execute(self, /*parameters*/ Sequence{}, System.context);
}


Cheers,
Dimitris
Re: Using reflection [message #1820587 is a reply to message #1820563] Thu, 23 January 2020 14:03 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
I suppose we could also add this logic to the end of OperationCallExpression.execute. For example the following seems to work:

if (module instanceof IEolModule &&
    "call".equals(operationName) &&
     parameterValuesArray.length > 0 &&
     parameterValuesArray[0] instanceof String) {
		String reflectiveOpName = (String) parameterValuesArray[0];
		Operation refOp = ((IEolModule) module).getOperations().stream()
			.filter(op -> reflectiveOpName.equals(op.getName()))
			.findAny()
			.orElse(null);
		
		if (refOp != null) {
			return refOp.execute(targetObject, parameterValues.subList(1, parameterValues.size()), context);
		}
}


and in EOL:

call("foo").println();

operation String foo() {
	return "foo called";
}
Re: Using reflection [message #1820657 is a reply to message #1820587] Sat, 25 January 2020 09:29 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris KolovosFriend
Messages: 2165
Registered: July 2009
Location: York, UK
Senior Member

Hi Sina,

If we want to add proper built-in support for calling operations reflectively I guess we should also check argument types, consider operation contributors, dot vs. arrow etc.

Cheers,
Dimitris
Re: Using reflection [message #1820671 is a reply to message #1820657] Sat, 25 January 2020 18:36 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Dimitris,

That's a good point. I assume this would essentially mean calling OperationCallExpression.execute reflectively, rather than adding this minimal logic to OperationCallExpression itself, or at least factoring out the operation call logic. An alternative is to add some sort of "EOL Evaluator" built in to System, which operates on the current context's module. I'm wondering whether it is a worthwhile feature to have in the language or too niche of a requirement to support?

Thanks,
Sina
Re: Using reflection [message #1820728 is a reply to message #1820671] Mon, 27 January 2020 20:52 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris KolovosFriend
Messages: 2165
Registered: July 2009
Location: York, UK
Senior Member

Hi Sina,

Given that there's a sensible workaround, I'd be inclined to wait for a couple of similar use-cases to show up before we consider implementing this feature.

Cheers,
Dimitris
Re: Using reflection [message #1838211 is a reply to message #1820728] Thu, 18 February 2021 15:31 Go to previous messageGo to next message
Ludovico Iovino is currently offline Ludovico IovinoFriend
Messages: 33
Registered: July 2019
Member
I forgot about this discussion! Very nice! I'm already using the first solution.
Re: Using reflection [message #1838217 is a reply to message #1838211] Thu, 18 February 2021 16:32 Go to previous messageGo to next message
Ludovico Iovino is currently offline Ludovico IovinoFriend
Messages: 33
Registered: July 2019
Member
since we are here I couldn't get the context of an operation declaration...how is this defined?
Re: Using reflection [message #1838222 is a reply to message #1838217] Thu, 18 February 2021 18:19 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris KolovosFriend
Messages: 2165
Registered: July 2009
Location: York, UK
Senior Member

op.getContextType(System.context) should do the trick.

Thanks,
Dimitris
Re: Using reflection [message #1838226 is a reply to message #1838222] Thu, 18 February 2021 21:37 Go to previous message
Ludovico Iovino is currently offline Ludovico IovinoFriend
Messages: 33
Registered: July 2019
Member
Perfect, it works
Previous Topic:[ETL]Creating xmi file from ETL transformation output file(.model)
Next Topic:accessing runtime models with reflection
Goto Forum:
  


Current Time: Sat Apr 27 09:56:53 GMT 2024

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

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

Back to the top