ENIGMA Forums

General fluff => Announcements => Topic started by: Josh @ Dreamland on July 28, 2010, 10:34:26 pm

Title: Shortcuts
Post by: Josh @ Dreamland on July 28, 2010, 10:34:26 pm
Long, long ago, in a land far-- actually, it was in this chair. Or some chair that looked similar. Be it as it may, a while back, I took a shortcut and thought, "If this ever comes back to bite me, it'll be after the rest of the project is stable and I can fix it without fear." Well, that mostly came true. There are no detrimental effects at this time, simply because the amount of skill required for the malefaction to manifest simply isn't being exhibited by ENIGMA users at this time. For those who wish to be weary, this is the issue:

When I designed the C++ parser, I did not implement a proper overloading system. Overloads were, instead of instantiated as children of a main instance as I considered doing, applied to the current copy by way of modifying the bounds for acceptable parameter numbers. For instance,
Code: (C++) [Select]
string func(int a) { return "test"; }
double func(int a, int b) { return  "test2"; }

is stored only as a function returning double that takes either 1 or 2 parameters. Had the second function taken three parameters, the choices would be 1, 2, or 3, even though 3 was actually an invalid option. This makes for a blazingly inaccurate syntax check in rare situations (a GML user would never come close to noticing).

It also means a less pleasant inaccuracy on a more important system.
The following expressions were passed to a new type resolution system of mine:

room_speed
var
*var
room
room + room
room + 1
room - 1
var[5]

The results were, respectively, as follows:
Let's see if I can't waste some space and make a nicer table.

room_speed=>int
var=>var
*var=>double
room=>roomv
room + room=>variant
room + 1=>variant
room - 1=>double
var[5]=>variant

The more curious of you have a few questions. I'll do my best to answer those here:
room_speed and the like are being left integers. I see no point in wasting memory and speed so users can set some random array element in global scalars.
The type resolution system doesn't distinguish between cast and type at the moment (by choice, so I can debug without thinking of a global by that type. :P)
The type "roomv" is a special type with an overloaded operator= that calls room_goto(). It inherits from variant.
Because "roomv" is a special variant, room + room will return variant. This is correct. Room + anything will, in fact, so you can keep adding things such as strings.
However, room - 1 is double because subtraction only works on such. It wasn't worth it to avoid a warning on re-cast. Maybe I'll change my mind later, but in any case, the resolver was accurate.
Calls to [] on var are indeed variants.

So what's the problem? Look at item three, "*var". The parser can't distinguish between binary and unary *. Even though it knew it wanted the unary version, it couldn't get the accurate type, because I only store the type of the last declared overload, and so the parser was given `double`, the type returned by the multiplication operator.

When I need, I will store all overloads with argument counts and types, but that is a job for after the basics are all working. I want one more thing to work before I proceed, and it is indeed a trick; I would like for templated types to work, and if possible (by which I mean, it shall pass), templated casts. This way, if you have map<int,int> amap, you can say amap[whatever].x and have it behave correctly. That has been important to me since square one.




Another nice thing I can implement with the help of this system is the switch() optimization, as well as something brand new.

It befuddles me that neither C++ nor GML have a foreach construct. ENIGMA will be given one. It will work rather uniquely, since neither language was designed for it. Basically, it will have the following syntaxes:

foreach (array as element)
foreach (element in array)
foreach (element : array) //Java-esque

Trouble is getting it to work around this little issue: "in" and "as" are common variable names. So, I'm going to work around that thanks to how carefree my parser is when it operates.

Code: [Select]
foreach in in as
  do_something()

will work fine.

To ease the sadistic and curious, that will look like this in intermediate parse:
foreach(in)in;as;do_something();
sssssss(nn)nn;nn;nnnnnnnnnnnn();

Which makes it very easy to parse out. The first item, in (), is either what I'll be iterating, or the element name. The second, of form "nn;", will determine which; it should be "in" or "as". The third set, denoted easily by regexp /;(^;);/, is the corresponding element of the foreach.

So, how will that work from there? Simple. I determine which is the container to iterate. I then check for the following:
Depending on which of those I find, the foreach will be replaced with code to iterate each. The real trick is managing to proxy the "as" component in as a method of retrieving the element itself, and not the iterator type. Mind all of you, I'm not afraid to implement a macro if I must. But I imagine I can find a creative way to cram more instructions into the mix using operator, .


Anyway, I'll be busy. Thanks for your patience. I know this is taking a while, but the level of detail Ism and I've put into this goes far beyond the previous releases' quicker development time.

Peace.
Title: Re: Shortcuts
Post by: freezway on July 29, 2010, 12:06:24 pm
cool?
Title: Re: Shortcuts
Post by: Josh @ Dreamland on July 29, 2010, 12:25:19 pm
This is not why I write intricate news posts.
Title: Re: Shortcuts
Post by: freezway on July 29, 2010, 12:28:16 pm
My c++ knowledge (or lack there of) leaves me going:
 ???
Title: Re: Shortcuts
Post by: IsmAvatar on July 29, 2010, 01:26:45 pm
Your intricate new posts are too intricate for many of us to follow.

I think you'd be lucky if most of the people here are able to gather from it that you are introducing foreach into the language.
Title: Re: Shortcuts
Post by: Josh @ Dreamland on July 29, 2010, 03:53:42 pm
That actually made me laugh. I'm sorry. I'll do something interesting and easily understood when sounds work after revision 310.
Title: Re: Shortcuts
Post by: RetroX on July 30, 2010, 01:28:55 pm
foreach?

What about the C++0x for?

http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html
Code: [Select]
int array[5] = { 1, 2, 3, 4, 5 };
for (int& x : array)
  x *= 2;

You should probably use that syntax primarily for var considering how it's planned to be an actual element of C++ eventually.
Title: Re: Shortcuts
Post by: Josh @ Dreamland on July 30, 2010, 07:08:01 pm
I used foreach for multiple reasons. One was so it didn't conflict with the 0x model. Frankly, C++ has had room for one for a while. If all the 0x model can do is const arrays (with explicit bounds, I mean), fuck it.
Title: Re: Shortcuts
Post by: kkg on July 30, 2010, 11:21:55 pm
I managed to read through this entire post

That's an achievement in itself for me!

Anyway good to hear from you guys again, schoolwork is raping my ability to visit on IRC >:
Title: Re: Shortcuts
Post by: Rusky on July 31, 2010, 11:46:19 am
The C++0x foreach works with c-style arrays, the new initializer lists, and anything that follows the stl iterator interface (begin()/end()/::iterator): http://en.wikipedia.org/wiki/C++0x#Range-based_for-loop (http://en.wikipedia.org/wiki/C++0x#Range-based_for-loop)
Title: Re: Shortcuts
Post by: luiscubal on July 31, 2010, 12:36:37 pm
@Rusky Cool. It means it'll actually be useful.
Title: Re: Shortcuts
Post by: The 11th plague of Egypt on August 07, 2010, 11:37:03 am
When I studied overloading at uni, they told me it was a crucial part of C++.

Sure you can postpone it, but a fix should be scheduled.
Title: Re: Shortcuts
Post by: Josh @ Dreamland on August 07, 2010, 06:23:22 pm
Haha. Rest assured, I know how crucial it is. Don't worry, it's functional, it's just not as precise as it should be. The performance and ability to use it for most purposes isn't really affected. It will only cause issue if two functions are overloaded with radically different return types.
Title: Re: Shortcuts
Post by: RetroX on August 09, 2010, 08:51:24 am
Another thing to mention, in C++0x:

Code: [Select]
int f(int x) { return x; }
double f(double x) { return x; }

This code wouldn't work:
Code: [Select]
variant x;
int y=f(x);
nor would this:
Code: [Select]
variant x;
int y=f((double)x);

Because it's ambiguous.  It won't choose the highest precision by default, because functions could be completely different depending on the type.  This is also in the regular C++ standard for GCC 4.5+, as I believe, which is why I had that ambiguous error in r208 or something like that.
Title: Re: Shortcuts
Post by: Josh @ Dreamland on August 09, 2010, 10:59:20 pm
That's already implemented. You can see it in abs(). It's fine, because I Just do this:

double abs(variant& x) { return abs(double(x)); }
double abs(var& y) { return abs(double(y)); }