adventuregamestudio / ags

AGS editor and engine source code
Other
705 stars 159 forks source link

Support script object pointer downcast #2018

Open ivan-mogilko opened 1 year ago

ivan-mogilko commented 1 year ago

CC @fernewelten

After RTTI was added in ags4, it is now theoretically possible to find out the managed object's parent(s), knowing its type. This opens a possibility to support downcasting, that is - a conversion from the base type pointer to a child type pointer. As opposed to the upcasting, which may be calculated at compile time, downcasting has to be performed at runtime, as compiler cannot know which type will be stored in the base pointer.

What would be required for this?

  1. From compiler's side: a pointer cast syntax. The two obvious options here are:
    • C style: Child* child_ptr = (Child*)parent_ptr;
    • C# style: Child* child_ptr = parent_ptr as Child;
    • there's also C++ style, with cast<T>(parent_ptr) or cast<T*>(parent_ptr), but it looks more complicated.
    • EDIT: an approach not requiring a bytecode, but another instance of a "psuedo-function" (like array_Length): a static method that casts from parent to the given type, something like
      child_ptr = ChildType.CastFrom(parent_ptr);
  2. A new bytecode instruction, which requests a dynamic cast. This instruction likely should take a ptr from a reg, analyze if it's possible to cast, cast, and store back in a reg (or reg1->reg2 if it's more convenient for any reason). If cast fails, a null pointer is written.
  3. From the engine's side: an ability to know object's type. The user managed structs are already storing typeid in their headers. The builtin objects do not; they may get one using the "manager"; but I have not thought this through yet. This also may be related to resolving #1228 first.
  4. There's an interesting question about types exported by plugin. Script compiler may see their relationship, and they should normally be a part of RTTI, but I am not sure how to match an object received from the plugin with RTTI yet. Something is missing in this picture.
ericoporto commented 1 year ago

There is also the python approach of using super. It would be something like this.super() would give the reference for that object as its parent class whatever that is - but this would be tricky with the type system we have in place.

Overall, I like the C# style best, as it doesn't automatically invite other types of casting as a complexity.

ivan-mogilko commented 1 year ago

There is also the python approach of using super. It would be something like this.super() would give the reference for that object as its parent class whatever that is - but this would be tricky with the type system we have in place.

Hmm, but that upcasts as opposed of downcast? AGS already supports getting parent's pointer, you can do:

GUIControl *control = myButton;

EDIT: I think I forgot to mention another variant, idk how good it is, but worth mentioning: a static method that casts to this type from parent, like:

child_ptr = ChildType.CastFrom(parent_ptr);

I got this idea while thinking that GUIControl.AsButton, AsLabel etc is bad, because it hardcodes the list of descendants, so I wondered if we could instead have

Button.FromControl(control_ptr)

or similar.