Handout 12A

The purpose of this exercise is to practice debugging in LOGO. The STEP and TRACE commands are introduced here as tools for debugging.

Sometimes, computer programs don't work. The best way to fix a broken computer program is to carefully trace through the code to find the flaw. Modular programming, comments in code and indentation can be very helpful when doing this. LOGO also provides the STEP and TRACE commands to help find bugs in code.

The STEP command simply tells LOGO to go through a procedure line by line, so that you won't have to. To use it, type: STEP "PROCEDURENAME, where PROCEDURENAME is the name of the procedure to be traced. For example:

TO SQUARE :SIZE
  REPEAT 4 [FORWARD :SIZE RIGHT 90]
END

TO FANCYHOUSE :SIZE
 SQUARE :SIZE                             ; Draw the base of the house
 FD :SIZE RT 30 FD :SIZE RT 120 FD :SIZE  ; Draw the roof of the house
 RT 30 FD :SIZE RT 90 FD :SIZE RT 90      ; Return to starting position
 RT 90 FD :SIZE/2 RT 180 SQUARE :SIZE/3   ; Draw a door
 RT 90 PU FD :SIZE/2 PD SQUARE :SIZE/3    ; Draw a window   
 PU BK :SIZE/2 LT 90 FD :SIZE/2 RT 90 PD  ; Return to starting position
END

STEP "FANCYHOUSE

FANCYHOUSE
After typing the commands above, you will be shown each line of code in FANCYHOUSE before the computer runs it. Notice that you are not shown the REPEAT command in the SQUARE procedure; only the lines of FANCYHOUSE are presented for your approval. If you wrote a FANCVILLAGE procedure that used FANCYHOUSE then ran it, you would be allowed to view each line of FANCYHOUSE each time it was run from FANCYVILLAGE. You would not have to approve each line of FANCYVILLAGE unless you chose to STEP through that as well.

After stepping through the FANCYHOUSE procedure a few times, see what changes if you run it after typing STEP "SQUARE. Then write a simple FANCYVILLAGE procedure and run that. If you get tired of hitting enter, type UNSTEP "FANCYHOUSE or UNSTEP "SQUARE to turn off the trace on those procedures.


The procedures below are intended to average the items in a list, but the program is broken. Discuss it with your classmates to find as many errors as you can. If it's still broken once you've fixed those, use STEP to find and fix any remaining errors.

TO AVERAGELIST :LISTNUMS
  IF [EMPTY? :LISTNUMS] [PRINT (This list is empty.) STOP]
  PRINT FINDAVERAGE LISTNUMS 0
END

TO FINDAVERAGE :LISTNUMS :TOTAL :COUNT
  IF EMPTY? :LISTNUMS
    [ PRINT (SENTENCE [The average is ] :TOTAL/:COUNT) ]
  MAKE :TOTAL :TOTAL + (FIRSTITEM :LISTNUMS)
  MAKE :COUNT :COUNT + 1
  FINDAVERAGE (BUTFIRST :LISTNUMS) :TOTAL :COUNT
END

STEP is a very useful command that provides comprehensive information about the procedure being traced. Sometimes that much information can be overwhelming. Also, STEP does not always provide the information you need about the values of variables in your procedure.

LOGO's TRACE command can help here. UNSTEP any procedures you've been stepping through and type TRACE "FINDAVERAGE. Then run AVERAGELIST and see what happens.

The TRACE command has one argument: the name of a procedure. When you run a program, TRACE informs you every time that procedure is called and tells you what values its arguments have. It also tells you when that procedure exits. This can be very handy for problem solving in complex programs; for instance, you might want to trace the INSERT procedure in the insertion sort program. As with UNSTEP and STEP, there is an UNTRACE command that tells LOGO to stop listing all the calls to a procedure.


STEP and TRACE are powerful tools for debugging, but sometimes the best tool is the simplest: PRINT. You can add PRINT commands anywhere in your program to let you know when that point has been reached, and what the conditions are at that point. Once your program runs correctly you can delete these, or you can set a flag to turn these print commands on and off as desired. An example of the use of a debugging flag is shown below.

MAKE "DEBUG "FALSE

TO SUMUP :N
  MAKE "TOTAL 0
  FOR [I 1 :N] ~
   [
    MAKE "TOTAL :TOTAL+:I
    IF :DEBUG [PRINT (SENTENCE [In SUMUP, :I is] :I [and :TOTAL is] :TOTAL)]
   ]
  PRINT (SENTENCE [The sum of the numbers up to] :N [is] :TOTAL)
END

SUMUP 7
Entering the commands above results in the output:
The sum of the numbers up to 7 is 28
Running the commands:
MAKE "DEBUG "TRUE

SUMUP 5
yields:
In SUMUP, :I is 1 and :TOTAL is 1
In SUMUP, :I is 2 and :TOTAL is 3
In SUMUP, :I is 3 and :TOTAL is 6
In SUMUP, :I is 4 and :TOTAL is 10
In SUMUP, :I is 5 and :TOTAL is 15
The sum of the numbers up to 5 is 15
The PRINT command inside the FOR loop is executed, because the DEBUG variable has been "turned on".

Of course you don't want to force the people using your program to type MAKE "DEBUG "FALSE every time they load it. This command should be included in the first few lines of the first procedure of the program.


Mtht420