Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » Epsilon » Global Variables in imported EOL(global var-clause ignored?)
Global Variables in imported EOL [message #891021] Sat, 23 June 2012 15:46 Go to next message
Lukas Baron is currently offline Lukas Baron
Messages: 10
Registered: June 2012
Junior Member
Hi,

I have two EOL Scripts A and B, A imports B, both declare global variables with var [name] : [Type] = [Value];
This means they are declared outside of an "operation {...}".

In such operations I can only access Variables of Script A. Any access to a global variable of Script B even inside of a B-operation results in an exception.

Why is this the case? Is there a workaround expect declaring each variables in A, this would not be very nice? I have multiple operations in B, which need such a global variable.

Thanks in Advance
Lukas
Re: Global Variables in imported EOL [message #891028 is a reply to message #891021] Sat, 23 June 2012 16:16 Go to previous messageGo to next message
Antonio Garcia-Dominguez is currently offline Antonio Garcia-Dominguez
Messages: 304
Registered: January 2010
Senior Member
Hi Lukas,

Sorry, but the E*L languages do not support module-wide variables. We have a single frame stack for storing all variables, so we would need to run the imported EOL scripts before running the main EOL script and bring all their global variables into the same stack frame. However, this would probably introduce nasty side effects that would break existing EOL code if the modules were imported in the "wrong" order. To avoid all that, we do not run the EOL imports: we just load their operations.

I assume that you always use script B through its "import" statement in script A, right? In that case, you can simply put all the global variables in script A and remove them from script B.

Cheers,
Antonio
Re: Global Variables in imported EOL [message #891040 is a reply to message #891028] Sat, 23 June 2012 17:07 Go to previous messageGo to next message
Lukas Baron is currently offline Lukas Baron
Messages: 10
Registered: June 2012
Junior Member
Hi Antonio,
thank you for that quick reply. I have many EOL Scripts. To put all global Variables in one script is not a very clear approach (my opinion).
May it be possible to provide a mechanism to declare a global variable out of an operation from different scripts?

Thanks again
Lukas
Re: Global Variables in imported EOL [message #891269 is a reply to message #891040] Sun, 24 June 2012 10:08 Go to previous messageGo to next message
Antonio Garcia-Dominguez is currently offline Antonio Garcia-Dominguez
Messages: 304
Registered: January 2010
Senior Member
We'll need to think a bit more about this. We have a bug somewhat related to your problem, though in our case it's because we might want to run "subscripts" (nested subtemplates in EGL or nested data bindings in EUnit). Still, your problem covers another usage scenario for global variables, so you might want to describe your problem here:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=347367

I still think that we shouldn't switch to always executing imported EOL scripts, as that might break existing code. We'd probably need to either define a new statement which worked like "import" but ran the imported script as well. However, that means you probably wouldn't be able to run it as a standalone program (as you can now).

Alternatively, we could define a variant of the "var" statement which produced a global variable instead of a local variable, like this:
  global x := 0;

You'd need to use such a statement inside an operation ("init()" for example), import its module and then run its init() operation. It does feel a bit cumbersome, hmm.

Another option would be to allow for an optional "init" block in EOL scripts (like the "BEGIN" blocks in Perl), which would be always run before anything else, whether imported or directly executed. The rest of the code at the global scope would be run only when directly executed, though.

Something like this:

-- imported.eol
init {
  var x := 0;
}

("zero is: " + x).println();

-- main.eol
import "imported.eol"; -- only defines x, does not print anything

("one is: " + ( x + 1 )).println();


What do you think? I like the third approach, though: it doesn't break anything and it feels more comfortable to use than the other two.
Re: Global Variables in imported EOL [message #891271 is a reply to message #891040] Sun, 24 June 2012 10:11 Go to previous messageGo to next message
Antonio Garcia-Dominguez is currently offline Antonio Garcia-Dominguez
Messages: 304
Registered: January 2010
Senior Member
By the way, there's another way to emulate shared global variables between models: try storing them as extended properties of the root object in one of your models. You're probably working with the same models across all your EOL scripts, right?
Re: Global Variables in imported EOL [message #891513 is a reply to message #891271] Mon, 25 June 2012 02:41 Go to previous messageGo to next message
Louis Rose is currently offline Louis Rose
Messages: 439
Registered: July 2009
Location: York, United Kingdom
Senior Member
Antonio Garcia-Dominguez wrote on Sun, 24 June 2012 10:11
By the way, there's another way to emulate shared global variables between models: try storing them as extended properties of the root object in one of your models. You're probably working with the same models across all your EOL scripts, right?


This is the approach that I normally use. (On one occasion, this even led me to realise that these global variables were better represented as a separate model).
Re: Global Variables in imported EOL [message #891552 is a reply to message #891513] Mon, 25 June 2012 04:26 Go to previous messageGo to next message
Lukas Baron is currently offline Lukas Baron
Messages: 10
Registered: June 2012
Junior Member
Hi everyone,

@Antonio:
Quote:
Another option would be to allow for an optional "init" block in EOL scripts (like the "BEGIN" blocks in Perl), which would be always run before anything else, whether imported or directly executed. The rest of the code at the global scope would be run only when directly executed, though.


I would like this option the most too. I would call this block maybe "onimport" or something like that. I think this would lead to the cleanest code, because the existance of global variables is not dependent on execution of certain operations. Everything you might have to do is throw an exception if a name is defined twice. Or you may rename variables internally by prefix the modulename.

@Louis:
Quote:
On one occasion, this even led me to realise that these global variables were better represented as a separate model


I like this too, but I think creating a model just to share global variables should be a feature the programming-language has to provide.

For now I wrote an eclipse plugin by myself which creates a global variable in the framestack. Works fine too.

Greetings
Lukas
Re: Global Variables in imported EOL [message #891556 is a reply to message #891513] Mon, 25 June 2012 04:28 Go to previous messageGo to next message
Steffen Zschaler is currently offline Steffen Zschaler
Messages: 228
Registered: July 2009
Senior Member
I would agree. In general, global variables are considered evil in
structured programming---why should this be different for EOL programs?

Cheers,

Steffen

On 25/06/2012 07:41, Louis Rose wrote:
> Antonio Garcia-Dominguez wrote on Sun, 24 June 2012 10:11
>> By the way, there's another way to emulate shared global variables
>> between models: try storing them as extended properties of the root
>> object in one of your models. You're probably working with the same
>> models across all your EOL scripts, right?
>
>
> This is the approach that I normally use. (On one occasion, this even
> led me to realise that these global variables were better represented
> as a separate model).
Re: Global Variables in imported EOL [message #891582 is a reply to message #891552] Mon, 25 June 2012 05:46 Go to previous messageGo to next message
Antonio Garcia-Dominguez is currently offline Antonio Garcia-Dominguez
Messages: 304
Registered: January 2010
Senior Member
Steffen: I don't like global variables very much either. They don't scale well and are hard to debug :-/. However, they might be useful in some limited scenarios, I guess. "init" blocks might be useful to set up in a single place some data structures required to get an EOL script running.

Lukas: I'm afraid naming it as "onimport" would be slightly misleading, as we'd probably need to run it whenever it is loaded, not just when it is imported. We'd run it both when the script was run directly and when it was first imported, to avoid having to duplicate its code. I still think "init" would be better: "begin" (like in Perl) would confuse users into which code ran first (the code in the global scope, or the "begin" blocks?), and we already have "pre" annotations for the preconditions in an operation.

Lukas, could you open an enhancement request for the "init" blocks? Please include a link to this thread in the report Smile.
Re: Global Variables in imported EOL [message #891816 is a reply to message #891582] Tue, 26 June 2012 02:46 Go to previous messageGo to next message
Louis Rose is currently offline Louis Rose
Messages: 439
Registered: July 2009
Location: York, United Kingdom
Senior Member
Antonio Garcia-Dominguez wrote on Mon, 25 June 2012 05:46
Lukas: I'm afraid naming it as "onimport" would be slightly misleading, as we'd probably need to run it whenever it is loaded, not just when it is imported. We'd run it both when the script was run directly and when it was first imported, to avoid having to duplicate its code. I still think "init" would be better: "begin" (like in Perl) would confuse users into which code ran first (the code in the global scope, or the "begin" blocks?), and we already have "pre" annotations for the preconditions in an operation.


Perhaps pre would be a better name, as we already have pre blocks in the rule-based languages. Furthermore, this could be implemented by pulling up the implementation of pre blocks from ErlModule to EolModule.

At the moment, I think I'd be inclined to vote against adding this feature. Like Steffen, I dislike global variables, and suspect we should not be encouraging their use (nor fixing the obscure bugs that may arise from their use!)

[Updated on: Tue, 26 June 2012 02:47]

Report message to a moderator

Re: Global Variables in imported EOL [message #892020 is a reply to message #891816] Tue, 26 June 2012 16:35 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 804
Registered: July 2009
Senior Member
I also dislike global variables but given that EOL is not OO (in the sense that one cannot define custom classes) I think this makes sense. Instead of adding another keyword (init), we could just not ignore the top-level statements of imported EOL modules. E.g.

imported.eol
----------------
var x = 0;

operation recordVisit() {
x = x + 1;
return x;
}

main.eol
----------------
import "imported.eol";

recordVisit().println(); // prints 1
recordVisit().println(); // prints 2

Any thoughts on this?

Cheers,
Dimitris
Re: Global Variables in imported EOL [message #892142 is a reply to message #892020] Wed, 27 June 2012 04:23 Go to previous messageGo to next message
Antonio Garcia-Dominguez is currently offline Antonio Garcia-Dominguez
Messages: 304
Registered: January 2010
Senior Member
Dimitris: wouldn't that break code in some cases?

By now, users may have relied on EOL ignoring those bits of code, so they may have small programs for debugging at the global level in those imported scripts. They probably won't expect that code to be suddenly run in a new version.

We should either add a big warning to the next version, or ask users to explicitly tell EOL to run that code.

I'd revise your example into this:

imported.eol
----------------
pre {
  var x = 0;
}

("Debugging: " + x).println();

operation recordVisit() {
x = x + 1;
return x;
}

main.eol
----------------
import "imported.eol"; // doesn't print anything (only runs the "pre" block)

recordVisit().println(); // prints 1
recordVisit().println(); // prints 2


or this (notice the switch from "import" - old behaviour - to "require" - new behaviour):

imported.eol
----------------
var x = 0;
("Debugging: " + x).println();

operation recordVisit() {
x = x + 1;
return x;
}

main.eol
----------------
require "imported.eol"; // prints "Debugging: 0"

recordVisit().println(); // prints 1
recordVisit().println(); // prints 2


We would have to deprecate "import" in favor of "require" in the second case, which would be somewhat bothersome. Also, we wouldn't be able to separate initialization from the code used to debug that EOL script.

[Updated on: Wed, 27 June 2012 04:24]

Report message to a moderator

Re: Global Variables in imported EOL [message #892153 is a reply to message #892142] Wed, 27 June 2012 04:52 Go to previous message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 804
Registered: July 2009
Senior Member
Hi Antonio,

One way or another, this won't be a completely backwards compatible change as we'll either be introducing new keywords or we'll be changing the behaviour of existing scripts :S I'll need to think more about this.

Cheers,
Dimitris
Previous Topic:EVL validation fixes are not usable when having multiple EVL files
Next Topic:Problem with namespaces
Goto Forum:
  


Current Time: Sat Aug 02 02:41:27 EDT 2014

Powered by FUDForum. Page generated in 0.03230 seconds