Last active
October 12, 2023 16:04
-
-
Save tinkerer-red/30aa7efe7a1f42ba7d077ace3183fc22 to your computer and use it in GitHub Desktop.
GML constructor `base` keyword
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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