On Wed, 03 Mar 2010, francesco perillo wrote: Hi,
> I'm writing a personal message so that info won't get public :-) OK, but I'm setting CC to harbour-devel list in answer because it may help other users and I hope future HVM developers :-) to understand how HVM works. > but I must say that at least one function is documented in > doc/en/hvm.txt: * __DBGVMVARLGET( <nProcLevel>, <nLocal> ) --> <xRetVal> Serious mistake. I'll remove it ASAP. BTW this description is wrong. <nLocal> is not an index to local variable. > I now "think to know" what valtype S is in the stack... it IS the > first item pushed in the stack and is the pointer to the function that > is going to be executed... > Let's see in a real life example, where the code from .ppo is DevOut( > aPrinter[ s_ptr_selec ] ): > > Local 13: S Symbol: DEVOUT > Local 14: U <don't know to display type U> "U" is NIL, Try ? valtype( "NIL" ) It's QSELF() value. Inside method it's an object. > Local 15: A Len: 4 > Local 16: N 13.00 > Local 17: C "W/B,GR+/W,N/N,B/N,W+/BG,B/N" > Local 18: N 0.00 > > aPrinter (local15) has len 4, s_ptr_selec (local16) is 17 so out of > bound error is generated... There are no local<n> variables. There are only items on HVM stack. Some of them belongs to declared function parameters, some of them contains additional parameters when user passed more parameters then was declared by function, some others belongs to local variables and rest is used by currently executed code, i.e. partially calculated expressions, WITH OBJECT values, FOR EACH iterators, BEGIN SEQUENCE envelopes, called function parameters, etc. The function stack frame contains: 1 FUNCTION SYMBOL OR METHOD SYMBOL 2 QSELF() VALUE (NIL FOR FUNC/PROC, OBJ FOR METHODS) 3 DECLARED PARAMETERS <n> ... 3 + <n> ADDITIONAL <m> PARAMETERS IF PASSED MORE THEN <n> PARAMS ... 3 + <n> + <m> LOCAL VARIABLE <l> ... 3 + <n> + <m> + <l> ITEMS ALLOCATED BY EXECUTED CODE <k> ... 3 + <n> + <m> + <l> + <k> NEXT FUNCTION FRAME SYMBOL > I could not explain what Local17 and 18 were for... but then realized > the following: > the function has 5 parameters but in this specific case there are only > 3 of them specified in the function call... > Since LocalCount = number_of_locals - number_of_params > and since number_of_params is 2 less than what should be, LocalCount > is 2 bigger than necessary... and so 2 spurious stack elements are > printed... > So, question 1: is it possible to retrieve the number of parameters > declared in a function ? Yes. It's possible to retrieve number of declared parameters (<n>+<m> in above scheme). It's also possible to retrieve number of passed parameters (<n> in above scheme) It's not possible to detect number of local variables (<l> in above scheme) so it's not possible to guess when local variables stops and begins execution context items. It's possible to detect the whole frame size so <k> is also known. > Question 2: for object method I get valtype S... but for function > invocation not always... is there a rule ? In all cases you have function or method symbol as 1-st item in function method frame. > > __DBGVMVARL[GS]ET() is internal debug function function and > > it cannot be used without additional information which is available > > only for debugger. > but it works at the moment, in harbour 2.0.0, the one I will use for > at least one year... And after a year you decided to check what it exactly does and you are asking why your code does not work as you want ;-) You can always use any internal HVM functions for your own risk. It's your choice. I only hope that I do not see any message from you when we remove above functions i.e. making some modifications in HVM stack or debugger code. > >> Is it also possible that the compiler removes local variables (both > >> LOCAL or parameters) present in function definition not used in the > >> function ? or that they are changed position in the LocalX list ? > > Yes it's possible though in current compiler code it is used only to > > eliminate unused local variables > Ok, I had such case... 2 unused locals did shift all the others and > they didn't match the values. No, you do not have such case. You only wrongly expected that 2-nd parameter of __DBGVMVARL[GS]ET() function is index to local variables and it isn't. In a while I'll add to SVN new function __DBGVMLOCALLIST() which returns array with <l> and <k> items in the above function frame scheme and below I'm attaching the code which should help you to understand few things if you look at <k> items attached to LOCAL variables. As I said it's not possible to detect real number of local variables in current code. It may change in the future if we store this information in hb_vm[V]Frame() function but now it can be done only indirectly for code compiled for debugger with -b switch catching the messages with names of local variables which are sent to debugger from HVM. > The debugger builds aCallStack calling a c function passing it a > "info" parameter... is it possible to use such "info" not inside the > debugger (I didn't check myself... ) Any other way ? You have to modify the debugger code. In my opinion it's much easier and cleaner to create own mini debugger. best regards, Przemek
proc main( ... ) local l1 := "L1", l2 := "L2" begin sequence with { |e| break( e ) } f0( "P1", "P2", "P3", "P4" ) recove ? "error..." endsequence return func F0() return F1( "f0:p1", "f0:p2", "f0:p3" ) func F1( p1, p2, p3 ) local l1 := "f1:l1", l2 := "f1:l2", l3 := "f1:l3", l4 := "f1:l4" return DUMMY( "dum1", "dum2", F2( "f1:p1", "f1:p2" ) ) func F2( p1, p2, p3 ) local l1 := "f2:l1", l2 := "f2:l2", l3 := "f2:l3", l4 := "f2:l4" return FN( "f2:p1", "f2:p2", "f3:p2" ) func FN( p1, p2, p3 ) local l1 := "fn:l1", l2 := "fn:l2", l3 := "fn:l3", l4 := "fn:l4" with object "with_value" dispStack() endwith return nil proc dummy() return proc dispStack() local cProcName, nProcLine, cProcFile local aParams, cParams local i := 0 while ! empty( cProcName := PROCNAME( ++i ) ) nProcLine := PROCLINE( i ) cProcFile := PROCFILE( i ) aParams := HB_APARAMS( i ) cParams := hb_valToExp( aParams ) cParams := substr( cParams, 2, len( cParams ) - 2 ) ? cProcFile + "[" + hb_ntos( nProcLine ) + "]: " + ; cProcName + "(" + cParams + ")" ? " LOCALS:", hb_valToExp( __DBGVMLOCALLIST( i ) ) enddo return
_______________________________________________ Harbour mailing list (attachment size limit: 40KB) Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour