Libraries: MQL Plus Enhanced Debugging Support - page 6

 
Alain Verleyen #:
Typo in "EXAPND"...should be "EXPAND".

yes! corrected.

 
amrali #:

What do you think of implementing the API tracer like this:

It handles all operators, nicely. https://www.mql5.com/en/docs/basis/operations/rules

Yes, but it has one major issue....

My first approach was like that, but macros do not allow for varying amount of parameters.

So my second attempt was to leave everything after the function name itself as it is, thats why I went down this road.

The field of functions which would needed to be replaced by macros is to big in its variance to fit into simple macros. - It would not be as generic as it is now.


BTW, I just updated the sources, with some error corrections, the mql-api-tracer is available in the code, but still considered beta for now. (And not compatible with its own macros...) 

EDIT:

One example would be 

ChartGetDouble, but there are multiple functions with same name, but varying parameters....

Its impossible to have them substituted by macros.

 
While thinking about the abusive usage of the operator "*", I can only think of one scenario that would break the tracer.

It's with GetPointer(). Reason for this is, above the operator "*" are the operators "[]"and "." with left to right operation.

So it could be possible to get a pointer from GetPointer and instantly use it with one of these above mentioned operators. Now there would be a problem, because the returned "whatever" from this object's operator would now go to the "pass_through" operator* and break the chain.

Why? Because it could be anything, and it's not possible to write a function that takes in an l-value, an r-value or an object at the same time.

I am thinking about removing this one function from the API-tracer.

Any other case should be covered consistently, after all the * operation is irrespective of it's order concerning the result it produces.

I guess some "edge-case" testing is required to verify the stability of the solution.


 

Does not compile:

#define LIB_DEBUG
#define LIB_DEBUG_MQLAPI
#include "lib_debug.mqh"
void OnStart()
  {
   if(!MathIsValidNumber(1.23))
      Print("number is non valid");
   else
      Print("valid");
  }


Compiles with warnings, a gives logical errors on run (unary ! operator is not evaluated)

#define LIB_DEBUG
#define LIB_DEBUG_MQLAPI
#include "lib_debug.mqh"
void OnStart()
  {
   if ( MathIsValidNumber(MathRand()) )    Print("number is valid");
   if (!MathIsValidNumber(MathRand()) )    Print("number is non valid");
  }

//      >test.mq5< OnStart(){ @6: MQL5-API Function => () MathRand                           [int]    = 21565                     (0x0000543D) }
//      >test.mq5< OnStart(){ @6: MQL5-API Function => () MathIsValidNumber                  [bool]   = true }
//      >test.mq5< OnStart(){ @6: MQL5-API Function => Print() [void] }
// number is valid
//      >test.mq5< OnStart(){ @7: MQL5-API Function => () MathRand                           [int]    = 23183                     (0x00005A8F) }
// number is non valid
I think the above 2 examples are likely common in the code.
 
amrali #:

Does not compile:


Compiles with warnings, a gives logical errors on run (unary ! operator is not evaluated)

So funny, thats exactly what I tested after last post....

Updated, now works....

Here are the changes in detail:

            static class pass_through
            { public:
                uchar   _rtol_op;
                string  _type;
                string  _msg;
                pass_through() : _rtol_op(NULL), _type(NULL), _msg (NULL)   { };
                pass_through(const pass_through& s)                         { _msg = s._msg; _type = s._type; };
                pass_through* msg(const string in, const string t_in)       { _type = t_in; _msg = in; ResetLastError(); return(GetPointer(this)); };
                pass_through* operator!()                                   { _rtol_op = 1; return(GetPointer(this)); };
                pass_through* operator~()                                   { _rtol_op = 2; return(GetPointer(this)); };
                pass_through* operator-()                                   { _rtol_op = 3; return(GetPointer(this)); };
                pass_through* operator--()                                  { _rtol_op = 4; return(GetPointer(this)); };
                pass_through* operator++()                                  { _rtol_op = 5; return(GetPointer(this)); };
                template <typename T>
                T operator*(T in)                                           {
                                                                                if(LIB_DBG_NAMESPACE(dbg_lib, trace_api_calls))
                                                                                {
                                                                                    const int err_no = GetLastError();
                                                                                    const string _typename = LIB_DBG_NAMESPACE(dbg_lib, dbg_typename_to_string)(typename(T), true);
                                                                                    LIB_DBG_NAMESPACE(dbg_lib, dbg_printf)("%s", StringFormat(_msg, (err_no != DBG_ERR_SUCCESS) ? StringFormat("Error: %i", err_no) : ((StringFind(_type, "void") == -1) && (StringFind(_type, _typename) == -1) ? StringFormat("Type mismatch. Expected: %s, Got: %s", _type, _typename) : LIB_DBG_NAMESPACE(dbg_lib, var_out)("", in, NULL, "", 59))));
                                                                                    _msg = NULL;
                                                                                }
                                                                                switch(_rtol_op)
                                                                                {
                                                                                    case 1:     return(!in);
                                                                                    case 2:     return(~in);
                                                                                    case 3:     return(-in);
                                                                                    case 4:     return(--in);
                                                                                    case 5:     return(++in);
                                                                                }
                                                                                return(in);
                                                                            };
            } LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_mql_api_retval);

Operators above need overloading, as they are evaluated right to left....

Available on Cloud-Storage....

 
What about un-braced if..else?
 
amrali #:
What about un-braced if..else?


There are lots of issues with the case you have shown inside the if-statement....

I have to think about it.

un-braced if..else, hopefully the trick with do... while is applicable.


 
amrali #:

Does not compile:


Compiles with warnings, a gives logical errors on run (unary ! operator is not evaluated)

I think the above 2 examples are likely common in the code.

I think I have solved the evaluation issue inside of if-statements, 

I am really greatful for your contribution.

Current version available in cloud storage.


I am still thinking about unbraced if-statements, the trivk with do{}while will not work, as I am not in control of the end of the statement. I guess I need a different route for void-functions... There are only 20 overall. maybe there is another way to approach them... thinking about macros again.

 
Dominik Christian Egert #:

I think I have solved the evaluation issue inside of if-statements, 

I am really greatful for your contribution.

Current version available in cloud storage.


I am still thinking about unbraced if-statements, the trivk with do{}while will not work, as I am not in control of the end of the statement. I guess I need a different route for void-functions... There are only 20 overall. maybe there is another way to approach them... thinking about macros again.

I have re-tested with the latest version "4.9997" in cloud storage.

Still, the same issues with the above 2 examples in #54

Edit: another problem

Print(MathRand() + MathRand());   // '+' - illegal operation use
 
amrali #:

I have re-tested with the latest version "4.9997" in cloud storage.

Still, the same issues with the above 2 examples in #54

Edit: another problem

Oh, that's great. Thank you.

I haven't updated the version number, sorry for the confusion.

I am currently working on solutions to your reported issues and it looks like next version has them solved.

Void-Functions need a different approach for non-braced condition statements. I have a solution to that already working.

Finalizing the handling of Alert, Print, printf and PrintFormat...