Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // This is a VERY rough proof-of-concept for a few ideas I've been working on,
- // much of this is implementation details, and other bits will be wrapped up in
- // macros.
- //
- // ========================================================================== //
- // ========================================================================== //
- // || || //
- // || SCROLL DOWN FOR THE USER CODE. || //
- // || || //
- // ========================================================================== //
- // ========================================================================== //
- //
- #include <a_samp>
- #define YSI_MAX_STRING (144)
- #define string:
- #define strcpy(%0,%1) strcat((%0[0] = 0, %0), %1)
- enum e_RET_DATA_STRUCT
- {
- e_RET_DATA_VAL,
- e_RET_DATA_STR,
- e_RET_DATA:e_RET_DATA_RET[YSI_MAX_STRING] = 0,
- e_RET_DATA_PAD
- }
- new
- YSI_g_sSearchClass = 0,
- YSI_gReturnAddr,
- YSI_gReturnData[e_RET_DATA_STRUCT];
- // Only defined for classes that exist.
- stock _CLASS_TAG:operator=(CObjects:n) return YSI_g_sSearchClass=0x1010,_CLASS_TAG:n;
- // Unique class number (constructor address)? Used to find the correct classes.
- stock _CLASS_TAG:operator=(CPlayers:n) return YSI_g_sSearchClass=0x2020,_CLASS_TAG:n;
- // Define for all valid return tags.
- stock Float:operator=(e_RET_DATA:n) return Float:n;
- // The "o:" macro - sadly this is still the best way I can find to code "OOPS".
- #define o:%0->%1(%2) (CallMethod((%0), (_METHOD_NAME:#%1), %2),YSI_gReturnData[e_RET_DATA_RET])
- // Define macros. This is done in two stages to not incorrectly detect colons.
- #define method%0(%1) forward _METHOD_DO(%0|||%1);public _METHOD_DO(%0|||%1)
- #define _METHOD_DO(%0|||%1) _METHOD_RET:%0(_THIS_TAG:this,%1)
- // Consume empty parameter lists.
- #define _METHOD_NAME:#%1),) _METHOD_NAME:#%1))
- // "this" won't be an inline function parameter but a container class variable.
- #define _THIS_TAG:this,) _THIS_TAG:this)
- // Consume return tags and suffix names.
- #define _METHOD_RET:%5:%0(%1) _METHOD_TAG%5:%0(%1)
- #define _METHOD_TAG%9\32;%5:%0(%1) _METHOD_TAG%5:%0(%1)
- #define _METHOD_TAGstring:%0(%1) %0@s(%1)
- #define _METHOD_TAGFloat:%0(%1) %0@f(%1)
- #define _METHOD_TAG_:%0(%1) %0@i(%1)
- CallMethod(_CLASS_TAG:object, const _METHOD_NAME:name[], {Float, _}:...)
- {
- static
- sToCall[32];
- new
- bool:isString;
- // Only set this up once in reality.
- #emit CONST.pri YSI_gReturnData
- #emit ADD.C 4
- #emit STOR.pri YSI_gReturnAddr
- // Update for more parameters later.
- assert(numargs() == 3); // Just for now.
- // HACK HACK HACK.
- if (strcmp(_:name, !"StrReturn"))
- {
- format(sToCall, sizeof (sToCall), "%s@s", _:name);
- if (funcidx(sToCall) != -1) { isString = true; goto CallMethod_alt_1; }
- format(sToCall, sizeof (sToCall), "%s@i", _:name);
- if (funcidx(sToCall) != -1) goto CallMethod_alt_1;
- format(sToCall, sizeof (sToCall), "%s@f", _:name);
- if (funcidx(sToCall) != -1) goto CallMethod_alt_1;
- sToCall[0] = '\0';
- strcat(sToCall, _:name);
- CallMethod_alt_1:
- CallLocalFunction(sToCall, "ii", object, getarg(2));
- }
- else
- {
- static const
- szType[] = "is";
- // Make passing the string work without implementing the full system.
- // All this code does is correctly passes the string's address to
- // "CallLocalFunction", but that will be corrected better later.
- format(sToCall, sizeof (sToCall), "%s@s", _:name);
- if (funcidx(sToCall) != -1) { isString = true; goto CallMethod_alt_2; }
- format(sToCall, sizeof (sToCall), "%s@i", _:name);
- if (funcidx(sToCall) != -1) goto CallMethod_alt_2;
- format(sToCall, sizeof (sToCall), "%s@f", _:name);
- if (funcidx(sToCall) != -1) goto CallMethod_alt_2;
- strcpy(sToCall, _:name);
- CallMethod_alt_2:
- #emit LOAD.S.pri 20
- #emit PUSH.pri
- #emit ADDR.pri object
- #emit PUSH.pri
- #emit PUSH.C szType
- #emit PUSH.C sToCall
- #emit PUSH.C 16
- #emit SYSREQ.C CallLocalFunction
- #emit STACK 20
- }
- if (isString)
- {
- // Move the data slightly.
- memcpy(YSI_gReturnData[e_RET_DATA_STR], YSI_gReturnData[e_RET_DATA_VAL], 0, YSI_MAX_STRING * 4, YSI_MAX_STRING);
- YSI_gReturnData[e_RET_DATA_VAL] = YSI_gReturnAddr;
- }
- }
- stock _Return()
- {
- // Manipulate the stack to end an inline early and simulate a real "return".
- }
- #define _return%0; (YSI_gReturnData[e_RET_DATA_RET] = e_RET_DATA:(%0),_Return());
- //
- // ========================================================================== //
- // ========================================================================== //
- // || || //
- // || THIS IS THE USER CODE. || //
- // || || //
- // ========================================================================== //
- // ========================================================================== //
- //
- method IntReturn(n)
- {
- printf("IntReturn called for class %x", YSI_g_sSearchClass);
- _return n;
- }
- method Float:FltReturn(Float:n)
- {
- printf("FltReturn called for class %x", YSI_g_sSearchClass);
- _return n;
- }
- method string:StrReturn(string:n[])
- {
- printf("StrReturn called for class %x", YSI_g_sSearchClass);
- // You can't return a string parameter directly (plus unknown size).
- new
- str[YSI_MAX_STRING];
- strcpy(str, n);
- _return str;
- }
- //
- // ========================================================================== //
- // ========================================================================== //
- // || || //
- // || HERE IS IT SORT OF IN USE. || //
- // || || //
- // ========================================================================== //
- // ========================================================================== //
- //
- public OnFilterScriptInit()
- {
- new
- CObjects:obj1,
- CPlayers:obj2,
- CWorlds:obj3,
- var,
- Float:flt,
- str[YSI_MAX_STRING];
- // With returns.
- var = o:obj1->IntReturn(88);
- str = o:obj1->StrReturn("Woop");
- flt = o:obj1->FltReturn(8.6);
- printf("%d, \"%s\", %.2f", var, str, flt);
- // Without returns.
- printf("%d", o:obj2->IntReturn(50));
- // Don't do this - it prints the first character too (the bad address).
- printf("%s", o:obj1->StrReturn("Yeah"));
- printf("%f", o:obj2->FltReturn(9.9));
- // With warnings (gives the wrong results).
- o:obj3->IntReturn(88);
- o:obj3->StrReturn("Woop");
- o:obj3->FltReturn(8.6);
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment