Pages: 1 2 »
  Print  
Author Topic: New ENIGMA Implementers' API; this concerns all developers  (Read 4432 times)
Offline (Male) Josh @ Dreamland
Posted on: March 15, 2012, 09:16:17 PM

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

View Profile Email
As the new parser approaches completion, it is time to start considering the implications. I have already made the executive decision of implementing half of this in the past, but what has been implemented will need some recoding, and the new parser allows for marvelous new extensions I would like to take advantage of. As such, I figure it would be good of me to draw up this proposal both to inform developers and open the floor for comments before they are implemented.

Developers heretofore have used the global enigma::instance_event_iterator to determine the current instance and interface with its locals. At first glance, there's nothing wrong with this, but when we really consider its implications, we start to see its limitations:
  • Threads cannot manipulate this variable concurrently.
  • Sideways casts between virtual ancestors cannot be made correctly in other files.
  • Functions which change scope must synchronize their use of this variable.
  • This variable does not, in itself, affect the scoping of scripts and functions called therein.
We can correct all of this by having reflexive functions, such as instance_destroy(), take an additional parameter, _E_SELF, of a particular C++ instance type (eg, _OBJ_object0*).

This is similar to the mechanism with which you are likely already familiar, the  varargs type, which allows you to request an stdargs-like overload which you can treat like an array of parameters. It is similar in that each of these are semantics that can be declared in C++, but only used in EDL via the intervention of the parser.

The proposal, then, is as follows:
  • Any parameter with the type enigma::varargs will be allowed to be passed an infinite number of parameters, as an array. The parser will handle packing the parameters given into the array in an efficient manner.
  • Any parameter with the name _E_SELF and a pointer-to type will be invisible to the user and filled in by the compiler with a pointer to the instance in question, meaning this in events and member scripts, and with->inst in with statements.

The lexical stipulations should be my concern rather than yours. Basically, don't assume you can do anything stupid. For instance, the following is a set of legal overloads:
Code: (C++) [Select]
int max(double, double);
int max(double, double, varargs);
While the following is ambiguous:
Code: (C++) [Select]
int max(double, double);
int max(varargs);

The reason, of course, is that if you pass it two doubles, both functions are equally logical choices. Now, I could choose to give weight to the concrete matches precedence, but I'm asking for your opinions on that, first.

Now, as for the _E_SELF parameter, if you think you have a better method of unambiguous identification for this which corrects issue (2) given above, let me know. Or, if you prefer a different name, such as just SELF, let me know as well. Otherwise, this will be the new format for the prototype:
Code: (C++) [Select]
void instance_destroy(enigma::object_basic* _E_SELF);
So, post suggestions, or be aware that these two modifications mean changes to the API, including existing functions.

Floor's open. Be informed. Feel free to contribute.
« Last Edit: March 20, 2012, 06:23:16 PM 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 (Female) IsmAvatar
Reply #1 Posted on: March 15, 2012, 10:03:28 PM

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

View Profile Email
Looks good to me. I can't think of any particular need for ambiguity resolution. And I don't think anybody really cares what you name it, as long as it's not too hard to remember/look up and doesn't take 10 seconds to type, like enigma::instance_event_iterator
Logged
Offline (Unknown gender) TheExDeus
Reply #2 Posted on: March 16, 2012, 07:10:02 AM

Developer
Joined: Apr 2008
Posts: 1872

View Profile
So instance_destroy() would look like this?:
Code: [Select]
void instance_destroy(enigma::object_basic* _E_SELF)
{
  if (enigma::cleanups.find(a) == enigma::cleanups.end()) {
    _E_SELF->inst->myevent_destroy();
    _E_SELF->inst->unlink();
  }
}
I guess the function wouldn't error with "not enough arguments" when called empty (like usual) because of the parser?

But this doesn't concern me I guess. I don't make these kinds of functions, but this seems important when I get around doing path_start (as no one else plans to).
Logged
Offline (Male) Josh @ Dreamland
Reply #3 Posted on: March 16, 2012, 09:48:11 AM

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

View Profile Email
Code: [Select]
void instance_destroy(enigma::object_basic* _E_SELF)
{
  if (enigma::cleanups.find(_E_SELF) == enigma::cleanups.end()) {
    _E_SELF->myevent_destroy();
    _E_SELF->unlink();
  }
}

Code: [Select]
void path_start(object_pathext* _E_SELF, int pathid, .......)
{
  _E_SELF->path_index = pathid;
  .........
}
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 #4 Posted on: March 16, 2012, 11:25:15 AM

Developer
Joined: Apr 2008
Posts: 1872

View Profile
That's cool.

edit: And there is no overhead because that is done on compile time?
edit2: Is it faster is what I am asking..
Logged
Offline (Male) Josh @ Dreamland
Reply #5 Posted on: March 16, 2012, 02:16:15 PM

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

View Profile Email
There is no more overhead than using the old system. In fact, there might be less, since this is probably somewhere close at all times.
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 (Male) RetroX
Reply #6 Posted on: March 18, 2012, 02:20:29 PM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
Questions:
  • Can varargs contain zero values?
  • Can varargs be statically typed? (i.e., varargs<double> instead of varargs<var>) ?
  • Will varargs be a variable-storage type (i.e., std::vector) or static arrays?
« Last Edit: March 18, 2012, 02:42:41 PM by RetroX » Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Offline (Male) Josh @ Dreamland
Reply #7 Posted on: March 18, 2012, 09:19:28 PM

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

View Profile Email
1) Yes.
2) No. varargs uses only variant. I will see about supporting varargs<typename>.
3) It will more than likely be a static array, as the compiler will know the exact space to allocate. It will still offer quicksort and reverse functions.
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 #8 Posted on: March 20, 2012, 07:33:48 AM

Developer
Joined: Apr 2008
Posts: 1872

View Profile
I hope you took into consideration varargs in the parser, so we don't have problems with them. Like the two problems we have now:
1) min/max always defaults to varargs even when only two arguments are given (this is slow).
2) varargs fuck up variable name access, so we get a compile error (like max(5,global.somevar) will fuck up the global.somevar).

Also, its cool that the parser does trivial mathematical operations. I usually do draw_sprite(x+10,y+10+64) and such when drawing and positioning items, so its cool that it will just return 74 and doesn't do that calculation all the time during runtime (although doesn't gcc already do this?). And does shit like this break it: x+5*(4/somevar)*64, so will it return x+320*(4/somevar)?
Logged
Offline (Male) Josh @ Dreamland
Reply #9 Posted on: March 20, 2012, 09:15:59 AM

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

View Profile Email
I moved your post here because it seemed more appropriate. And yes; the reason I posted this topic at this stage is because I wanted input on precisely how varargs overloads would be resolved. I think it will be a lot easier on everyone if I resolve them like this:

1) Check if an exact overload exists.
2) Check if a castable overload exists.
3) Check if a varargs overload exists which would encompass it.

That way, max(double,double) is still used for max(int,int), but max(1,2,3) gets the varargs overload.

Also, the above makes it possible to extend a JDI method for the job.
Code: (C++) [Select]
function* get_overload(args) {
  function *r = jdi::get_overload(args);
  if (!r) {
    for (overload *o in r) {
       // Magically check for varargs overloading
    }
  }
  return r;
}

While I am on the subject... Would anyone be interested in int function(int a, varargs bcdwxy, int z) being a valid overload?
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: March 21, 2012, 08:08:36 AM

Developer
Joined: Apr 2008
Posts: 1872

View Profile
And what about undefined variables? I hate that ENIGMA just takes 0 or something when a variable is not defined - it creates A LOT of headaches (just a few days ago I wasted 3h figuring out why ds_ functions don't work properly, in reality I didn't create the ds_ in the first place, but I can't know that if it takes 0 by default).
Logged
Offline (Male) Josh @ Dreamland
Reply #11 Posted on: March 21, 2012, 09:42:57 AM

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

View Profile Email
Debug mode.
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 #12 Posted on: March 21, 2012, 11:54:41 AM

Developer
Joined: Apr 2008
Posts: 1872

View Profile
You mean that debug mode will show an error in that case (because it doesn't now)?
Logged
Offline (Male) polygone
Reply #13 Posted on: March 21, 2012, 12:28:02 PM

Contributor
Location: England
Joined: Mar 2009
Posts: 803

View Profile
Did you forget my suggestion you said you was going to do?

Code: (C++) [Select]
var  &varaccess_a(int x)
{
    object_basic *inst = fetch_instance_by_int(x);
    if (inst) switch (inst->object_index)
    {
      case obj_0: return ((OBJ_obj_0*)inst)->a;
      case global: return ((ENIGMA_global_structure*)ENIGMA_global_instance)->a;
    }
    #ifndef TREAT_UNINITS_AS_0
    show_error("Variable Undeclared");
    #endif
    dummy_0 = 0;
    return dummy_0;
}

You wasn't entirely happy with the overall local functions suggestions (http://pastebin.com/cS2A12CL) but you said changing the varaccess part was fine.
« Last Edit: March 21, 2012, 04:00:24 PM by polygone » Logged
I honestly don't know wtf I'm talking about but hopefully I can muddle my way through.
Offline (Male) Josh @ Dreamland
Reply #14 Posted on: March 21, 2012, 03:37:09 PM

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

View Profile Email
I implemented uninitialized variable reporting in debug mode a while ago. Apparently it's since been broken. I'll reimplement it at some point. In the meantime, disregard polygone—that function is unrelated.
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
Pages: 1 2 »
  Print