1. Calling Func/Proc
- Posted by c.k.lester <euphoric at ckl?ster.com> Jul 11, 2007
- 707 views
I would really like to have a function that returns the name of the calling func/proc. To be used like as follows: function query_db(sequence s) if debug then logfile( calling_proc() ) end if ... end function logfile() is my output function. In this case, I am using it for debugging purposes. Instead of putting hundreds of lines of code (one for each function that would call query_db()), I'd rather just have the one line in query_db(). That seems reasonable, doesn't it? Is this possible, and how easy if so?
2. Re: Calling Func/Proc
- Posted by CChris <christian.cuvier at agriculture.gou?.fr> Jul 11, 2007
- 674 views
c.k.lester wrote: > > I would really like to have a function that returns the name of the > calling func/proc. To be used like as follows: > > function query_db(sequence s) > if debug then > logfile( calling_proc() ) > end if > ... > end function > > logfile() is my output function. In this case, I am using it for debugging > purposes. > > Instead of putting hundreds of lines of code (one for each function > that would call query_db()), I'd rather just have the one line in query_db(). > That seems reasonable, doesn't it? > > Is this possible, and how easy if so? I would use this sort of stuff a lot for debugging. Not straightforward if you want to avoid any impact at all on performance. In il.e, you can see that routine names are kept in the stripped down symbol table passed on to the backend. So there's a hope. The SymTab index of the callee is computed when calling a routine, but not kept (sub is a local var in the big switch routine in be_execute.c). You could get a full image of the call stack by keeping a "sequence", which doesn't exist in C, of indexes of called routines, and your routine would query the symtab image for routine names. It is relatively easy to make the mod, except for the details of dynamically growing the sequence of called symtabs when the preallocated quota is about to overflow. I'd suggest limiting such recording to sections bracketed by a with debug and without debug directives, without debug being the default. In this case, the only impact on performance with debug off would be testing a flag to decide whether to record subroutine symtab indexes or not, on every routine call. CChris
3. Re: Calling Func/Proc
- Posted by c.k.lester <euphoric at ckl?ster.com> Jul 11, 2007
- 638 views
CChris wrote: > > c.k.lester wrote: > > I would really like to have a function that returns the name of the > > calling func/proc. > The SymTab index of the callee is computed when calling a routine, but not > kept > (sub is a local var in the big switch routine in be_execute.c). It doesn't seem to me like you'd need to store anything extra. Doesn't the interpreter already know what routine called another routine? proc A calls +- proc B which calls +- proc C which calls +- proc D Is there a list kept like this by the interpreter? If so, then when I'm in proc D and want to know the parent, I just return parent_proc( current_proc ). > You could get a full image of the call stack by keeping a "sequence", which > doesn't exist in C, of indexes of called routines, and your routine would > query > the symtab image for routine names. I would be surprised if the interpreter couldn't already provide this information, quickly and easily.
4. Re: Calling Func/Proc
- Posted by CChris <christian.cuvier at agriculture.gou?.fr> Jul 11, 2007
- 659 views
- Last edited Jul 12, 2007
c.k.lester wrote: > > CChris wrote: > > > > c.k.lester wrote: > > > I would really like to have a function that returns the name of the > > > calling func/proc. > > The SymTab index of the callee is computed when calling a routine, but not > > kept > > (sub is a local var in the big switch routine in be_execute.c). > > It doesn't seem to me like you'd need to store anything extra. Doesn't the > interpreter already know what routine called another routine? > > proc A calls > +- proc B which calls > +- proc C which calls > +- proc D > > Is there a list kept like this by the interpreter? If so, then when I'm in > proc D and want to know the parent, I just return parent_proc( current_proc > ). > > > You could get a full image of the call stack by keeping a "sequence", which > > doesn't exist in C, of indexes of called routines, and your routine would > > query > > the symtab image for routine names. > > I would be surprised if the interpreter couldn't already provide this > information, quickly and easily. You are right in the sense that indeed there's a C variable (search for expr_top) which records both the calling routine and the calling point, if I got it right. Hence all "dynamic growth details" are already taken care of. I must look at this more carefully, but then there would be no performance issue in having a function return the last caller name/the whole list. As I said, I'd use it too. Any objections? There must be some around <smile/>. CChris
5. Re: Calling Func/Proc
- Posted by c.k.lester <euphoric at cklester?com> Jul 11, 2007
- 643 views
- Last edited Jul 12, 2007
CChris wrote: > I must look at this more carefully, but then there would be no performance > issue > in having a function return the last caller name/the whole list. > > As I said, I'd use it too. > Any objections? There must be some around <smile/>. + No performance hit + Enhancement is beneficial to programmers There better be no objections! :P Do it! Do it! Do it! :)
6. Re: Calling Func/Proc
- Posted by CChris <christian.cuvier at agriculture.gou?.fr> Jul 12, 2007
- 665 views
c.k.lester wrote: > > CChris wrote: > > > I must look at this more carefully, but then there would be no performance > > issue > > in having a function return the last caller name/the whole list. > > > > As I said, I'd use it too. > > Any objections? There must be some around <smile/>. > > + No performance hit > + Enhancement is beneficial to programmers > > There better be no objections! :P > > Do it! Do it! Do it! :) I had some eyestrain problems lately, keeping coding at a minimum this week. Things look better now. I'd like to plug once for all a probable DC leak in win32lib "Patch #67" so that I can send Derek (and the testers, remember?)what I can consider beta-stage code for him to merge into his code base, ultimately leading to a new public release of the lib. The consequence of the leak is the slowing down of all graphic rendering. When this is done, I'll look into the <prospective doc entry> s=function get_callers(i) Returns a sequence of pairs of strings if /i/ is greater than or equal to 0. The pairs are of the form {/routine name,file name/} and represent (part of) the current list of callers of the routine being executed. The first pair in the returned list, if any, shows the routine that directly called the code being executed. The second pair shows the routine that called the latter, and so on. If the list is empty, it means that your routine was called from code outside of any routine, or that your statement is outside of any routine itself. If /i/ is greater than zero, the /i/ first calling routines are returned, or less if there are less. If /i/ is 0, the whole list is returned. A value less than 0 will trigger a run time error. </prospective doc entry> This introduces a new opcode in the IL spec, and causes many places to need small modificattions (just like find_from()). As a result, it would appear in v3.2 at the earliest if it ever does. Any thoughts? CChris
7. Re: Calling Func/Proc
- Posted by Robert Craig <rds at RapidEuph?ria.com> Jul 12, 2007
- 642 views
CChris wrote: > c.k.lester wrote: > > CChris wrote: > > > > > I must look at this more carefully, but then there would be no performance > > > issue > > > in having a function return the last caller name/the whole list. > > > > > > As I said, I'd use it too. > > > Any objections? There must be some around <smile/>. > > > > + No performance hit > > + Enhancement is beneficial to programmers > > > > There better be no objections! :P > > > > Do it! Do it! Do it! :) > > I had some eyestrain problems lately, keeping coding at a minimum this week. > > > Things look better now. I'd like to plug once for all a probable DC leak in > win32lib "Patch #67" so that I can send Derek (and the testers, remember?)what > I can consider beta-stage code for him to merge into his code base, ultimately > leading to a new public release of the lib. The consequence of the leak is the > slowing down of all graphic rendering. > > When this is done, I'll look into the > <prospective doc entry> > s=function get_callers(i) > > Returns a sequence of pairs of strings if /i/ is greater than or equal to 0. > The pairs are of the form {/routine name,file name/} and represent (part of) > the current list of callers of the routine being executed. > > The first pair in the returned list, if any, shows the routine that directly > called the code being executed. The second pair shows the routine that called > the latter, and so on. If the list is empty, it means that your routine was > called from code outside of any routine, or that your statement is outside of > any routine itself. > > If /i/ is greater than zero, the /i/ first calling routines are returned, or > less if there are less. If /i/ is 0, the whole list is returned. A value less > than 0 will trigger a run time error. > </prospective doc entry> > > This introduces a new opcode in the IL spec, and causes many places to need > small modificattions (just like find_from()). As a result, it would appear in > v3.2 at the earliest if it ever does. > > Any thoughts? Be aware that these sorts of things are not easy to implement in the Translator. Translated code has no real symbol table, except for a stripped-down (often empty) table that only has entries for routines that might be referenced by a call to routine_id(). Also, the call stack (one per task) is just a bare hardware stack, not like the high-level software stacks controlled by the interpreter. Currently the Translator can handle any program that the interpreter can handle. I don't think we want to start adding features that are not supported by the Translator, unless there is a very good reason for it. It will create confusion for people, when they try to remember the list of features (and libraries) that they shouldn't use if they want to ever translate their code. Is it that inconvenient to just add a parameter to the routine, or set a global variable with the name of the calling routine? Can we see some examples of where this would be useful. C.K.? Regards, Rob Craig Rapid Deployment Software http://www.RapidEuphoria.com
8. Re: Calling Func/Proc
- Posted by c.k.lester <euphoric at ckle?ter.com> Jul 12, 2007
- 639 views
Robert Craig wrote: > > I don't think we want to start > adding features that are not supported by the Translator, > unless there is a very good reason for it. I agree. > Is it that inconvenient to just add a parameter to the routine, > or set a global variable with the name of the calling routine? It is inconvenient and would violate the DRY principle. (http://en.wikipedia.org/wiki/Don't_repeat_yourself) I would have to add parameters to hundreds of routines. > Can we see some examples of where this would be useful. C.K.? I have a procedure called err() that gets passed an error message. err() is called from hundreds of functions and procedures all spread throughout my code. I usually call it like in this small example: function rev_string(sequence x) if length(x) = 0 then err("rev_string(): Must be at least 1 character in length." else if length(x) > 17 then err("rev_string(): String too long." else x = reverse(x) end if end if return x end function A "fixed" version would look like this: function rev_string(sequence x) if length(x) = 0 then err("Must be at least 1 character in length." else if length(x) > 17 then err("String too long." else x = reverse(x) end if end if return x end function This is a very short example. When dealing with a much larger func/proc, there may be many more calls to err. Sometimes I change the name of a func/proc. When that happens, I also have to adjust all the calls to err. You suggest something like this: function my_super_function() CURR_ROUTINE = "my_super_function" --or set_routine_name( "my_super_function" ) ... end function but that violates DRY and, again, would have to be done for hundreds of func/proc in my code. It is unnecessary overhead to something that should be quite simple to resolve. What about if I want to trace the call back a few func/procs? It makes manual tracking even more complicated and time consuming. Say that a calls b calls c which calls my_super_function... To track the progress, you need something like: function my_super_function() add_routine_name( "my_super_function" ) -- do your stuff remove_routine_name( "my_super_function" ) end function I'm open to suggestions, but the fact is, the most efficient way to do this tracking of func/proc hierarchy is to let the interpreter/translated program handle it. The reason I need it is primarily for error handling/messaging and debugging.
9. Re: Calling Func/Proc
- Posted by CChris <christian.cuvier at agric?lture.gouv.fr> Jul 12, 2007
- 643 views
Robert Craig wrote: > > CChris wrote: > > c.k.lester wrote: > > > CChris wrote: > > > > > > > I must look at this more carefully, but then there would be no > > > > performance > issue</font></i> > > > > in having a function return the last caller name/the whole list. > > > > > > > > As I said, I'd use it too. > > > > Any objections? There must be some around <smile/>. > > > > > > + No performance hit > > > + Enhancement is beneficial to programmers > > > > > > There better be no objections! :P > > > > > > Do it! Do it! Do it! :) > > > > I had some eyestrain problems lately, keeping coding at a minimum this week. > > > > > > Things look better now. I'd like to plug once for all a probable DC leak in > > win32lib "Patch #67" so that I can send Derek (and the testers, > > remember?)what > > I can consider beta-stage code for him to merge into his code base, > > ultimately > > leading to a new public release of the lib. The consequence of the leak is > > the > > slowing down of all graphic rendering. > > > > When this is done, I'll look into the > > <prospective doc entry> > > s=function get_callers(i) > > > > Returns a sequence of pairs of strings if /i/ is greater than or equal to 0. > > The pairs are of the form {/routine name,file name/} and represent (part of) > > the current list of callers of the routine being executed. > > > > The first pair in the returned list, if any, shows the routine that directly > > called the code being executed. The second pair shows the routine that > > called > > the latter, and so on. If the list is empty, it means that your routine was > > called from code outside of any routine, or that your statement is outside > > of > > any routine itself. > > > > If /i/ is greater than zero, the /i/ first calling routines are returned, or > > less if there are less. If /i/ is 0, the whole list is returned. A value > > less > > than 0 will trigger a run time error. > > </prospective doc entry> > > > > This introduces a new opcode in the IL spec, and causes many places to need > > small modificattions (just like find_from()). As a result, it would appear > > in > > v3.2 at the earliest if it ever does. > > > > Any thoughts? > > Be aware that these sorts of things are not easy to > implement in the Translator. Translated code has no real > symbol table, except for a stripped-down (often empty) table that only > has entries for routines that might be referenced by a > call to routine_id(). Also, the call stack (one per task) > is just a bare hardware stack, not like the high-level > software stacks controlled by the interpreter. > > Currently the Translator can handle any program that the > interpreter can handle. I don't think we want to start > adding features that are not supported by the Translator, > unless there is a very good reason for it. It will create > confusion for people, when they try to remember the list > of features (and libraries) that they shouldn't use > if they want to ever translate their code. > > Is it that inconvenient to just add a parameter to the routine, > or set a global variable with the name of the calling routine? > Can we see some examples of where this would be useful. C.K.? > > Regards, > Rob Craig > Rapid Deployment Software > <a href="http://www.RapidEuphoria.com">http://www.RapidEuphoria.com</a> Dang! Didn't notice that unconspicuous "free(fe.lit)" statement... It trashes all the required information. So: * either it is removed to allow some functions to play with variable names, à la OOEu or what CK wishes; * or it becomes allowed that some routines can't go into translated code, but I agree that this is not a good idea; * or nothing gets done in this direction. I'd be in favor of having the option to keep the litterals, turning it on either on demand or when the backend (whichever) knows from the front end that a certain set of predefined routines is being tapped. The latter seems more consistent. Users have to be warned that, if they use routines from a given set, this requires extra information being kept, and leads to bigger exeutables. I don't see why performance would be affected after loading into RAM, it's just some more disk and RAM space being required. But clearly, this is a design decision that needs thorough discussion and testing of prototype executables. CChris
10. Re: Calling Func/Proc
- Posted by Bernie Ryan <xotron at bl?efrog.com> Jul 13, 2007
- 671 views
c.k.lester wrote: > > I have a procedure called err() that gets passed an error message. err() is > called from hundreds of functions and procedures all spread throughout my > code. I usually call it like in this small example: CK: A suggestion !
-- MastError sequence will contain a list of all routines -- up to the failure plus the error message of where it failed. -- This is dynamic so it any code changes need only be made -- in a single location. sequence MastError MastError = {}
procedure err() printf(1,"\n%s: %s\n",{MastError[$-1],MastError[$]}) end procedure
function rev_string(sequence x) MastError &= {"rev_string"} if length(x) = 0 then MastError &= {"Must be at least 1 character in length."} err() err() else if length(x) > 17 then MastError &= {"String too long."} err() else x = reverse(x) end if end if return x end function
</eucode
Bernie
My files in archive: WMOTOR, XMOTOR, W32ENGIN, MIXEDLIB, EU_ENGIN, WIN32ERU, WIN32API
Can be downloaded here: http://www.rapideuphoria.com/cgi-bin/asearch.exu?dos=on&win=on&lnx=on&gen=on&keywords=bernie+ryan }}}
11. Re: Calling Func/Proc
- Posted by c.k.lester <euphoric at cklest?r.com> Jul 13, 2007
- 649 views
Bernie Ryan wrote: > > }}} <eucode> > -- MastError sequence will contain a list of all routines > -- up to the failure plus the error message of where it failed. > -- This is dynamic so it any code changes need only be made > -- in a single location. Hey, Bernie, Yeah, that would work. The problem is the huge hit in performance I expect would occur. Plus, I would have to add a line of code to each and every routine that, at least now, contains a call to err(). > sequence MastError MastError = {} Can you imagine, though, how large MastError would grow in even a moderately sized program? I'm thinking of something like the IDE. For every func/proc call, it would add another sequence to MastError. It could probably done efficiently, but not as efficiently as if it were built-in to the interpreter/translator. I didn't understand Rob's post regarding it's non-doability in regard to the Translator, but I've got a moment now to read for comprehension. :)
12. Re: Calling Func/Proc
- Posted by c.k.lester <euphoric at ckleste?.com> Jul 13, 2007
- 639 views
Also, Bernie, with your method, you would want to remove the last bit off MastError each time you exited a routine. So you would have to do: function rev_string(sequence x) MastError &= {"rev_string"} if length(x) = 0 then MastError &= {"Must be at least 1 character in length."} err() err() else if length(x) > 17 then MastError &= {"String too long."} err() else x = reverse(x) end if end if MastError = MastError[1..$-2] -- <-- if only one message was issued from this routine return x end function I have database processing functions that could potentially have several levels of messages (more than just one message per routine), so returning [$-1] and [$] from MastError would not suffice. I use it for messaging, also, not just error messages. Things like status notifications, etc.
13. Re: Calling Func/Proc
- Posted by Robert Craig <rds at RapidEup?oria.com> Jul 13, 2007
- 678 views
c.k.lester wrote: > Robert Craig wrote: > > I don't think we want to start > > adding features that are not supported by the Translator, > > unless there is a very good reason for it. > > I agree. > > > Is it that inconvenient to just add a parameter to the routine, > > or set a global variable with the name of the calling routine? > > It is inconvenient and would violate the DRY principle. > (<a > href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">http://en.wikipedia.org/wiki/Don't_repeat_yourself</a>) > > I would have to add parameters to hundreds of routines. > > > Can we see some examples of where this would be useful. C.K.? > > I have a procedure called err() that gets passed an error message. err() is > called from hundreds of functions and procedures all spread throughout my > code. I usually call it like in this small example: > > function rev_string(sequence x) > if length(x) = 0 then > err("rev_string(): Must be at least 1 character in length." > else > if length(x) > 17 then > err("rev_string(): String too long." > else > x = reverse(x) > end if > end if > return x > end function > > A "fixed" version would look like this: > > function rev_string(sequence x) > if length(x) = 0 then > err("Must be at least 1 character in length." > else > if length(x) > 17 then > err("String too long." > else > x = reverse(x) > end if > end if > return x > end function > > This is a very short example. When dealing with a much larger func/proc, > there may be many more calls to err. Sometimes I change the name of a > func/proc. When that happens, I also have to adjust all the calls to err. > > You suggest something like this: > > function my_super_function() > CURR_ROUTINE = "my_super_function" > --or > set_routine_name( "my_super_function" ) > ... > end function > > but that violates DRY and, again, would have to be done for hundreds of > func/proc in my code. It is unnecessary overhead to something that should > be quite simple to resolve. > > What about if I want to trace the call back a few func/procs? It makes > manual tracking even more complicated and time consuming. > > Say that a calls b calls c which calls my_super_function... To track the > progress, you need something like: > > function my_super_function() > add_routine_name( "my_super_function" ) > -- do your stuff > remove_routine_name( "my_super_function" ) > end function > > I'm open to suggestions, but the fact is, the most efficient way to > do this tracking of func/proc hierarchy is to let the interpreter/translated > program handle it. > > The reason I need it is primarily for error handling/messaging and debugging. Have you considered using crash_routine()? http://www.rapideuphoria.com/lib_c_d.htm#crash_routine After displaying your message, you could force an error, say with ?1/0, and then display part of the ex.err file (e.g. traceback) for the user, and maybe even email the full ex.err to yourself, before dying. Most of my CGI programs email the ex.err to me when they are about to die. It works fine. Sometimes I add an extra message in the email along with the ex.err. Regards, Rob Craig Rapid Deployment Software http://www.RapidEuphoria.com
14. Re: Calling Func/Proc
- Posted by Matt Lewis <matthewwalkerlewis at gmail?com> Jul 13, 2007
- 669 views
c.k.lester wrote: > > I didn't understand Rob's post regarding it's non-doability in regard to the > Translator, but I've got a moment now to read for comprehension. :) The issue is that, in the interpreter, you have a compiled C program that maintains the state of your euphoria application, including its own call stack, which would be fairly trivial to see where you came from (obviously, since you get this in ex.err). However, once you translate, you now have a compiled C program, and the interpreter no longer maintains all that information. The stack is the native stack, and while you could, in theory, walk the stack (like a debugger would do), you'd lose a lot of information (well, in theory, you could read debugging symbols like a debugger would). I guess there's a case to be made that this is a debugging tool (like trace), and that some differences to the interpreter and translator are acceptable. We could, in theory, maintain a custom call stack in the translator by automatically calling some library routine to maintain this stuff for us, at least within "with trace" code. It's not a trivial thing to do, but might be possible, and be faithful to the interpreter/translator compatibility goal. Matt
15. Re: Calling Func/Proc
- Posted by Bernie Ryan <xotron at b?uefrog.com> Jul 13, 2007
- 661 views
c.k.lester wrote: > > Hey, Bernie, > > Yeah, that would work. The problem is the huge hit in performance I expect > would occur. Plus, I would have to add a line of code to each and every > routine that, at least now, contains a call to err(). Hi CK: I think you should take a new look at your code because I think you are confusing when you should be performing error checking and when you should be performing debugging. Debugging should only be necessary when your code is causing errors and should be turned on/off only when it's need to find bugs. User input errors should be the only things you are checking when the code has been debugged. You need to be able to shut off the debug phase when its not needed that way you will not have any performance hit. Bernie My files in archive: WMOTOR, XMOTOR, W32ENGIN, MIXEDLIB, EU_ENGIN, WIN32ERU, WIN32API Can be downloaded here: http://www.rapideuphoria.com/cgi-bin/asearch.exu?dos=on&win=on&lnx=on&gen=on&keywords=bernie+ryan
16. Re: Calling Func/Proc
- Posted by c.k.lester <euphoric at cklester.?om> Jul 13, 2007
- 644 views
Robert Craig wrote: > > c.k.lester wrote: > > The reason I need it is primarily for error handling/messaging and > > debugging. > Have you considered using crash_routine()? Well, I should have written, "error handling, messaging, and debugging." That is, I gather up a bunch of messages to display on the page. They could be standard messages like, "The operation was completed." The err() messages are usually something like, "Could not find that record." Crash messages aren't part of this vision, but you're right that I should redirect on a crash. :) I often write these things to a log, as well.
17. Re: Calling Func/Proc
- Posted by c.k.lester <euphoric at cklester.?om> Jul 13, 2007
- 649 views
Matt Lewis wrote: > > It's not a trivial thing to do, but might be possible, and be faithful to > the interpreter/translator compatibility goal. I'll start the bounty for this with $50.
18. Re: Calling Func/Proc
- Posted by c.k.lester <euphoric at cklester.c?m> Jul 13, 2007
- 633 views
Bernie Ryan wrote: > > I think you should take a new look at your code because I > think you are confusing when you should be performing error > checking and when you should be performing debugging. Yeah, I wasn't clear when stating my case. Many times, more often than not, the messages I'm looking for aren't crash messages. They are either status messages ("The operation completed.") or other error messages ("Could not open the database."). In these cases, I'm not dealing with bugs.
19. Re: Calling Func/Proc
- Posted by CChris <christian.cuvier at agriculture.gouv.?r> Jul 13, 2007
- 654 views
c.k.lester wrote: > > Bernie Ryan wrote: > > > > I think you should take a new look at your code because I > > think you are confusing when you should be performing error > > checking and when you should be performing debugging. > > Yeah, I wasn't clear when stating my case. Many times, more often than not, > the messages I'm looking for aren't crash messages. They are either status > messages ("The operation completed.") or other error messages ("Could not > open the database."). > > In these cases, I'm not dealing with bugs. In the OpenEU specifications, there was a planned feature called "events". It was not very popular at the time, but would have solved your problem nicely I think. Lua's methods are close kins of these events. Among the planned events were the BeforeCall and AfterCall ones. The handler for the BeforeCall was supposed to operate in the scope of the caller, and perform some stuff in that scope right before calling. The handler for the AfterCall event would perform likewise some stuff, but on return from the call. Both default handlers do nothing, of course. Wouldn't it be time to revive these constructs? Go to http://oedoc.free.fr for the latest (v1.4) specs, and the event system description therein. A few more useful features could also be brought in, as the only thing really needed here is a system to replay already scanned tokens. Among these: desequencing, arrays (symbolic sequences, rather), defaulted arguments in routines (when the default value is not a constant), pass by reference abilities and more. I have such a system working inside the 2.5 eu.ex. CChris