Home   Archive   Permalink



Debug using DO

Hey Nick,
    
I have a problem that i'm struggling with regarding debugging of code. I'd like to hear your approach to such issues, at least in r3.
    
I like using a structured code approach where code is defined into a block and then at the end do 'ing the blocks to execute the code, like:
    
1000-mainline: [
do 1100-get-input
do 1200-calc-value
]
1100-get-input: [ ... ]
1200-calc-value: [...]
do 1000-mainline
    
What I want to do is re-define the "do" statment to print a sequential number, then the do-block name, like this:
    
1 1000-mainline
2 1100-get-input
3 1200-calc-value
    
How can I re-define the "do" to increment a counter, then print the do-block name and then perform the do itself? I tried to use the source command, but it didn't help much.
    
I'd appreciate any insight you can give me. Thanks.

posted by:   Patrick       19-Nov-2013/18:37:14-8:00



mainline-1000: [
     ++ c
     print join c " mainline-1000"
     ++ c
     print join c " get-input-1100"
     do get-input-1100
     ++ c
     print join c " calc-value-1200"
     do calc-value-1200
]
c: 0
get-input-1100: [print "Doing Code Block 1"]
calc-value-1200: [print "Doing Code Block 2"]
loop 10 [do mainline-1000]

posted by:   Nick       19-Nov-2013/21:53:36-8:00



If you put the debug code in each action block, you see a pattern (counter variable is incremented, action block label is printed, and some code is executed)):
    
R E B O L []
mainline-1000: [
     ++ c
     print join c " mainline-1000"
     do get-input-1100
     do calc-value-1200
]
c: 0
get-input-1100: [
     ++ c
     print join c " get-input-1100"
     ; do your stuff here
]
calc-value-1200: [
     ++ c
     print join c " calc-value-1200"
     ; do your stuff here
]
loop 10 [do mainline-1000]
halt

posted by:   Nick       20-Nov-2013/5:47:30-8:00



Because of that pattern, you can reduce the debug process above into a repeatable function, so that you don't need to include the debug code in any of your action blocks. 'Do is native, so I just created a new function called 'Doo:
    
doo: func [x] [
     ++ c
     print rejoin [c " " x]
     do to-word x
]
mainline-1000: [
     doo "get-input-1100"
     doo "calc-value-1200"
]
c: 0
get-input-1100: []
calc-value-1200: []
loop 10 [doo "mainline-1000"]

posted by:   Nick       20-Nov-2013/5:54:30-8:00



Notice that the action block names are passed to the doo function as string arguments (x), so that they can be printed. "do to-word x" does the actual word referred to by that string (which itself is a label for an action block).

posted by:   Nick       20-Nov-2013/8:17:40-8:00



Excellent,
    
I had hoped to somehow redefine the DO, but I understand what you are doing with DOO -- But wait, could I do this:
    
native-do: :do    ; takes on the native do
do: func [x] [
     ++ c
     print rejoin [c " " x]
     native-do to-word x
]
    
Would this work for all "do" statements -- at least until I restore it back by
do: :native-do
    
Would that work??? -- What do you think and could there be other issues?

posted by:   Patrick       20-Nov-2013/20:36:37-8:00



Yep, you can do that, but I wouldn't - I expect that there might be other mezzanine functions that potentially use 'do.

posted by:   Nick       21-Nov-2013/7:34:01-8:00



"1000-mainline?" I would almost be willing to place money on you being a former COBOL programmer. Instead of creating a new function called "doo," why not call it "perform?"    
    
I like your idea, by the way. Instead of printing your trace information, you could write it to a "circular" file where you keep only the last hundred-or-so entries, so if you program crashed you could see where it was and how it got there.
    
I don't really know how all this works, but I wonder if the "get" function could help. What I am thinking of is a function (called PERFORM) that takes as a parameter a word that has as a value your code. In other words, you would code
    
PERFORM '1000-mainline
    
Note the apostrophe in front of the word so that it is not evaluated. Then, what the PERFORM function does is to print its parameter (the word 1000-mainline) and the "get" the value of 1000-mainline (your code) and "do" that code. It would be something like this: Note that I have not tested this. I can't do too much fun stuff at work these days.
    
TRACE-COUNTER: 0
PERFORM: func [paragraph-name] [
     TRACE-COUNTER: TRACE-COUNTER + 1
     print rejoin [
         TRACE-COUNTER
         ": "
         paragraph-name
     ]
     do get 'paragraph-name
]

posted by:   Steven White       5-Dec-2013/11:42:24-8:00