Skip to content

Instantly share code, notes, and snippets.

@tinkerer-red
Last active October 12, 2023 16:04
Show Gist options
  • Save tinkerer-red/30aa7efe7a1f42ba7d077ace3183fc22 to your computer and use it in GitHub Desktop.
Save tinkerer-red/30aa7efe7a1f42ba7d077ace3183fc22 to your computer and use it in GitHub Desktop.
GML constructor `base` keyword
#macro base __base(_GMFUNCTION_);
function __base(_func_name) {
static __lookup = {};
if (struct_exists(__lookup, _func_name)){
return __lookup[$ _func_name];
}
//used to break out once we have found a reliable answer
repeat(1) {
//this is only ever true when a constructor it's self is calling super
if (asset_get_index(_func_name) != -1) {
var _str = _func_name;
log(["case 1 _str", _str])
break;
}
//from here unfoertunately we have to guess a lot of it, though we can make some educated guesses
//secondly if the naming convention sticks to the standards of camel case, we can find the last "_" check if the next charactor is upper case, and if so we will be pretty sure it's the full name of the constructor
var _pos = string_last_pos("_", _func_name);
//make sure the constructor doesnt end with a "_"
if (_pos != string_length(_func_name))
&& (_pos) {
var _char = string_copy(_func_name, _pos+1, 1)
if (_char == string_upper(_char)){
var _str = string_copy(_func_name, _pos+1, string_length(_func_name)-_pos);
if (asset_get_index(_str) != -1) {
log(["case 2 _str", _str])
break
}
}
}
//if there is only a single "_" we know the structure is `<function name>_<Constructo name>` like bar_Foo which would be Foo.bar()
//given that this happens fairly rarely, we've deprioritized this check
var _count = string_count("_", _func_name);
if (_count == 1) {
var _arr = string_split(_func_name, "_", false);
var _str = _arr[1];
if (asset_get_index(_str) != -1) {
log(["case 1 _str", _str])
break
}
}
//cooincidently, if the constructor does end with a "_" likely because it's private, then we are in luck because we can simply find how many it has, then find the seppoerator for it. bar___Foo__ has 2 "_" on the end so we know somewhere in the string we will find 3 "_" in a row.
var _pos = string_last_pos("_", _func_name);
if (_pos = string_length(_func_name)) {
var _current_index = _pos;
while (string_char_at(_func_name, _current_index) == "_") {
_current_index -= 1;
}
_current_index += 1;
var _string_to_search = "_"+string_copy(_func_name, _current_index, string_length(_func_name)-_current_index+1);
var _pos = string_pos(_string_to_search, _func_name)
if (_pos) {
var _str = string_copy(_func_name, _pos+1, string_length(_func_name)-_pos);
if (asset_get_index(_str) != -1) {
log(["case 4 _str", _str])
break
}
}
}
//any other structure is very problematic, so as a last ditch effort, since we know the information provided will have the constructor at the very end, we loop backwards until we find a function of the same name. This is not ideal as a constructor of "A_B_C" will return the constructor "C"
var _i=string_length(_func_name)-1;
repeat(string_length(_func_name)-1) {
var _str = string_copy(_func_name, _i, string_length(_func_name)-_i+1)
if (asset_get_index(_str) != -1) {
log(["case 5 _str", _str]);
break
}
_i-=1}//end repeat loop
if (asset_get_index(_str) != -1) {
break
}
//else we should just drop an error message
show_error($"Super string manipulation is unable to reliably find the constructor from the supplied function {_func_name} please consider using camel case for your constructor names", true);
}
__lookup[$ _func_name] = _str;
return _str
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment