Pages: 1
  Print  
Author Topic: Weird stuff that works in GM but fails in ENIGMA  (Read 6649 times)
Offline (Unknown gender) Ideka
Posted on: January 02, 2013, 11:33:04 am

Member
Joined: Apr 2011
Posts: 85

View Profile
Trying to compile an old GM editable of mine with enigma, I stumbled upon some problems. That is, stuff that GM is OK with but not ENIGMA.

1. Bogus for statment.
Code: [Select]
for (i = 0; i < stuff; i += 1;) {}(Note the third semicolon.)
The generated C++ code was some weird crap like:
Code: [Select]
for ((i = 0; i < stuff; i += 1); ); {}Don't know about you, but I find that hilarious.
Anyway.

2. Checking for inequality with <>.
Code: [Select]
if (a <> b) {}That is equal to
Code: [Select]
if (a != b) {}in GM. In ENIGMA, the generated C++ looks like this:
Code: [Select]
if (a < > b) {}and of course doesn't compile. I also find this hilarious, specially how ENIGMA sticks a space between the symbols.

3. Giving a variable the name of a C++ data type or the name of a function.
I had a variable named int. Probably short for intelligence. The problem here is not that it doesn't work (because I guess it's only reasonable), but that ENIGMA didn't catch it at first, and it only became a problem during compilation.
A certain GML code looked like this:
Code: [Select]
alarm[0]=100-random(int);and the resulting C++ was something like
Code: [Select]
alarm(0)= 100 - random;
(int);
and... yeah, I'm sorry but, that is, like, HILARIOUS. Console was all like "invalid operands of type 'int' and '<unresolved overloaded function type>' to binary 'operator-'".
(Also another variable named rand fucked things up too, apparently because it's the name of a function.)

4. Resources that would have the same name, if not for an asterisk one of them has.
e.g. sprCharacter and sprCharacter*. ENIGMA apparently removes the asterisk and ends up trying to define the same thing twice.

5. Other stuff you probably know about already.
dll functions (actually I'm using Linux so I'm not sure).
ini functions.
execute_string
variable_local_exists
user_event
event_inherited (why is this not implemented?)
sprite_create_from_screen
file_exists


And that's pretty much it. I'm posting because I thought this may be useful. Is it? Is there a specific place to put this stuff?
« Last Edit: January 02, 2013, 04:29:30 pm by Ideka » Logged
Offline (Unknown gender) TheExDeus
Reply #1 Posted on: January 02, 2013, 12:52:52 pm

Developer
Joined: Apr 2008
Posts: 1860

View Profile
I think Josh has mentioned the for(){} thing and said it won't be supported.
If you check inequality with <> then you are hilarious.
The (int) looks like a cast, so it could be the the reason it was not reported. Have you tried JDI?
If you use asterisk or some non ascii char for resources names then you are very hilarious.

execute_string will not be supported. At least in C++ version. Maybe in javascript if that ever happens.
I think ini functions were done. Dll functions also worked at some point. I made sprite_create_from_screen, but didn't commit as it had some positioning problems. File functions should be working. The rest is kind of on a todo list.

There are some bugs like local variables getting fubared in scripts, but I think all of that is fixed in JDI so I won't complain until I see it.

edit: I think much more hilarious problem is that this code crashes LGM:
Code: [Select]
local int intensity_res=32,
intmap_w=int(room_width/intensity_res),
intmap_h=int(room_height/intensity_res);
I think the plugin crashes and takes LGM with it, but I am not sure. This problem has been here for years, as I posted this code (though longer version) a very long time ago. No one seems to be able to fix it.
« Last Edit: January 02, 2013, 12:59:44 pm by TheExDeus » Logged
Offline (Unknown gender) Ideka
Reply #2 Posted on: January 02, 2013, 04:28:11 pm

Member
Joined: Apr 2011
Posts: 85

View Profile
I think Josh has mentioned the for(){} thing and said it won't be supported.
OK. Still, ENIGMA should probably catch that before attempting to compile, I think.

If you check inequality with <> then you are hilarious.
Dude, I don't, I swear. That was some really old code, I don't know what I was thinking. And for all I know, it might have been someone else who wrote that code (it was only used in a single piece of code, everywhere else, != is used).

The (int) looks like a cast, so it could be the the reason it was not reported. Have you tried JDI?
Nope. Is that the new parser Josh is working on?

If you use asterisk or some non ascii char for resources names then you are very hilarious.
I only do that when I have two versions of the same thing, and want to try the game with both. Kind of like having two lines of code that do the same thing in a different way, and one is commented.

execute_string will not be supported. At least in C++ version. Maybe in javascript if that ever happens.
Figured as much.

I think ini functions were done. Dll functions also worked at some point. I made sprite_create_from_screen, but didn't commit as it had some positioning problems. File functions should be working. The rest is kind of on a todo list.
But I have the latest version from the git repository, and I'm pretty sure ini_open doesn't work, and neither does file_exists. About dll functions, actually I wouldn't know since I'm running Linux. I'm adding that to the first post.

edit: I think much more hilarious problem is that this code crashes LGM:
Code: [Select]
local int intensity_res=32,
intmap_w=int(room_width/intensity_res),
intmap_h=int(room_height/intensity_res);
I think the plugin crashes and takes LGM with it, but I am not sure. This problem has been here for years, as I posted this code (though longer version) a very long time ago. No one seems to be able to fix it.
Whoa.
I only find hilarious the kind of outputs programs give after recieving a bogus input without complaying, though.
Logged
Offline (Male) Josh @ Dreamland
Reply #3 Posted on: January 02, 2013, 07:37:17 pm

Prince of all Goldfish
Developer
Location: Pittsburgh, PA, USA
Joined: Feb 2008
Posts: 2950

View Profile Email
I haven't forgotten about you. But I want my response to be more thorough than I can give right now with the project in pieces before me. Give me a bit.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) Ideka
Reply #4 Posted on: January 02, 2013, 11:21:13 pm

Member
Joined: Apr 2011
Posts: 85

View Profile
I haven't forgotten about you. But I want my response to be more thorough than I can give right now with the project in pieces before me. Give me a bit.
OK. There's no need to hurry.
Logged
Offline (Female) IsmAvatar
Reply #5 Posted on: January 04, 2013, 04:48:47 pm

LateralGM Developer
LGM Developer
Location: Pennsylvania/USA
Joined: Apr 2008
Posts: 877

View Profile Email
Quote
I'm posting because I thought this may be useful. Is it? Is there a specific place to put this stuff?
I think we already know about most of this stuff, but it's nice to be reminded periodically, just to make sure we're not missing anything. Really, this information probably already exists on the wiki somewhere, or if not, it should.
Like josh said, give him a couple days, because he's in the middle of deconstructing and reconstructing the parser right now and needs to focus on it - and then he'll get back to you and make sure everything's documented on the wiki or already fixed in the new parser or whatever.
Logged
Offline (Male) Josh @ Dreamland
Reply #6 Posted on: January 08, 2013, 02:50:22 am

Prince of all Goldfish
Developer
Location: Pittsburgh, PA, USA
Joined: Feb 2008
Posts: 2950

View Profile Email
Okay, sorry this reply took so long; it took insanely longer than I thought to the compiler building correctly again, but now it's mostly up with the new system and I can at least use it to prepare a response.

1. Bogus for statment.
Your [snip=edl]for (i = 0; i < stuff; i += 1;) {}[/snip] is actually the less bogus of the two for() issues. The weirder one is [snip=edl]for ({i = 0;} i < stuff; { i += 1; } ) {}[/snip]. The raw output for the two of these in the new parser is as follows:

Code: [Select]
Warning(Code,38,6): Blocks not actually allowed in `for' parameters
Warning(Code,38,26): Blocks not actually allowed in `for' parameters
Warning(Code,38,33): Semicolon should follow statement at this point

  for ((i) = (0); (i) < (stuff); (i) += (1);)
    {}
  for (  (i) = (0); (i) < (stuff);   (i) += (1);)
    {}

It doesn't warn about the trailing semicolon, and in fact, includes it in the output because the dump function always puts a semicolon after statements. The C++ pretty-printer will not do that.

In fact, more work will need done in the pretty printer to support the latter for() loop, as it is basically unsalvageable. Code output will look like this instead:

Code: (cpp) [Select]
{
  {i = 0;}
  while (i < stuff) {
    {}
    continue_destination:
    i += 1;
  };
  break_destination:
}

The pretty-printer already needs to be able to support custom break and continue labels in order to support [snip=edl]continue 2[/snip].

2. Checking for inequality with <>.
When I wrote the old pretty-printer, I'd forgotten about <>. It pretty much indiscriminately puts spaces everywhere. Output for [snip=edl]if a <>  b c = d[/snip] is as follows:

Code: [Select]
  if ((a) <> (b))
    (c) = (d);

3. Giving a variable the name of a C++ data type or the name of a function.
Yes, its silence on the matter is an issue. The new parser accepts the code as well; this is its text-dump:

Code: [Select]
  ((alarm)[0]) = ((100) - ((random)  (int)));

The AST tells another story:


I haven't decided if I want it to bitch out in a frenzy or let the pretty-printer salvage it (which, as you can see, is possible). In compatibility mode, the lexer will not honor "int" as a type, and the problem becomes moot, so really, it's in the air. I have a little more work to do to help scope resolution in the AST builder anyway, so we shall see.

4. Resources that would have the same name, if not for an asterisk one of them has.
Asterisks are invalid in resource names in GM and ENIGMA alike. GM doesn't care because it is in charge of the entire AST, anyway. ENIGMA is in charge of the AST only until it is converted to C++. While it was originally supposed to be LGM's job to verify resource name integrity, during my rewrite of practically everything in the compiler, I decided to handle this myself. A correct structure name is now generated for the objects up front, and objects themselves are referred to exclusively by ID during print.

5. Other stuff you probably know about already.
dll functions: These are implemented in Windows using libFFI. The same code can be ported to Linux with very little modification (only what is required to use the system FFI library instead of the one included in ENIGMA for Windows).
ini functions: I think someone started working on these, but probably got bored. No one uses INI anymore, so they've been given pretty low priority.
execute_string: This is implemented in EGMJS, and is liable to stay that way for quite some time. Otherwise, a substantial portion of the compiler must be included with the engine; it's just messy. ENIGMA is compiled, not interpreted.
variable_local_exists: In C++ (among other compiled languages), a variable can't conditionally exist. A key in a map can conditionally exist. I might implement this for var and variant, but the truth is, there is never a good reason to use this function. Its only valid use case in GM is to work around the stupid order in which Mark handled instance creation codes in rooms (room instance creation code was fired before instance creation code). In ENIGMA, as well as in later versions of GM, this has been corrected.
user_event: I have a bigger, better plan for these that doesn't involve Mark's shoddy, pathetically finite and otherwise very ugly and limited implementation of "User events". Think local scripts.
event_inherited: I wanted polygone to implement this as practice. Never happened. So I guess I'll handle it while I finish recoding the rest of the compiler.
sprite_create_from_screen: I thought someone had coded this by copying my implementation of screen_save. I guess that isn't the case, but for anyone whose interested, this can be written by copying my implementation of screen_save.
file_exists: I can't believe this isn't implemented. On Windows, this is [snip]CreateFile()[/snip]. On Linux, this is [snip]stat()[/snip].

I was already aware of most of this stuff, but I don't mind a refresher.
« Last Edit: January 08, 2013, 03:07:26 am by Josh @ Dreamland » Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) TheExDeus
Reply #7 Posted on: January 08, 2013, 03:11:14 am

Developer
Joined: Apr 2008
Posts: 1860

View Profile
Quote
I thought someone had coded this by copying my implementation of screen_save. I guess that isn't the case, but for anyone whose interested, this can be written by copying my implementation of screen_save.
Yeah I tried that. The problem is that surfaces are flipped, so I actually had to use "surface_save" function as the basis. I still got the wrong position no matter what I tried. I will later post my code when I get home. Maybe someone can figure it out as I can't be bothered.
Logged
Offline (Unknown gender) Ideka
Reply #8 Posted on: January 08, 2013, 01:14:07 pm

Member
Joined: Apr 2011
Posts: 85

View Profile
Thanks for your answer, Josh. I see you were far ahead of me.

A couple of things:

dll functions: These are implemented in Windows using libFFI. The same code can be ported to Linux with very little modification (only what is required to use the system FFI library instead of the one included in ENIGMA for Windows).
You would use .so files in Linux, right?

Quote
execute_string: This is implemented in EGMJS, and is liable to stay that way for quite some time. Otherwise, a substantial portion of the compiler must be included with the engine; it's just messy. ENIGMA is compiled, not interpreted.
Honestly, I wouldn't bother.

Quote
variable_local_exists: In C++ (among other compiled languages), a variable can't conditionally exist. A key in a map can conditionally exist. I might implement this for var and variant, but the truth is, there is never a good reason to use this function. Its only valid use case in GM is to work around the stupid order in which Mark handled instance creation codes in rooms (room instance creation code was fired before instance creation code). In ENIGMA, as well as in later versions of GM, this has been corrected.
Funny, that's exactly what I was using them for in that old proyect. Once again, I wouldn't bother.

Quote
user_event: I have a bigger, better plan for these that doesn't involve Mark's shoddy, pathetically finite and otherwise very ugly and limited implementation of "User events". Think local scripts.
Awesome.
Logged
Offline (Male) Josh @ Dreamland
Reply #9 Posted on: January 08, 2013, 06:26:24 pm

Prince of all Goldfish
Developer
Location: Pittsburgh, PA, USA
Joined: Feb 2008
Posts: 2950

View Profile Email
You would use .so files in Linux, right?
Correct. FFI works with whatever's native; it's pretty extensive.

Honestly, I wouldn't bother.
If I were to seriously implement an execute_string, it would be language sensitive, with the default being loose GML which I would format as JavaScript. It would serve 99.9% of all "legitimate" execute_string purposes, not to imply that there's a very legitimate purpose for it.

Funny, that's exactly what I was using them for in that old project. Once again, I wouldn't bother.
That's all anyone uses them for, ever. For var and variant, it's as simple as assigning a bogus default type. The type will be fixed upon assignment. The only issue is packing them all into a map by reference. So variable_local_exists will only ever check if implicit vars exist, never declared types. Really not that hard, which is why I thought polygone could do it.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) TheExDeus
Reply #10 Posted on: January 08, 2013, 06:45:23 pm

Developer
Joined: Apr 2008
Posts: 1860

View Profile
For the record, I never got FFI to work (so dll functions in general). The one bundles with ENIGMA was also out of date by a year or two. I mentioned that at the forum some time ago, but I don't think anyone noticed.
Logged
Pages: 1
  Print