How to debug Small Basic programs

I started to write Small Basic programs when Small Basic v0.8 was released.  And I created many programs and published them to Small Basic server.  Some information about my programs are introduced in Small Basic Forum.

Today, I'd like to introduce follwoing tips about how to debug your program written in Small Basic language.  And I will show you real samples for debugging with my programs.

I hope these information will help your development in Small Basic.

•	Use TextWindow.WriteLine() to show contents of variables
•	Write debug code such as "If debug Then..."
•	Write test programs for subroutines
•	List up bugs
•	Meaning of error messages
•	Use "Graduate" and Visual Studio debugger

Use TextWindow.WriteLine() to show contents of variables

When you find something wrong in you program, how do you find the cause?  Small Basic IDE (integrated development environment) doesn't have ability such like variable watching.  But in many cases, some variables have unexpected values in them.  To find that, let's add TextWindow.Write() or TextWindow.WriteLine() to look in variables for debugging.

To show an array "arry", you can simply do TextWindow.WriteLine(arry) or write such as following code.

TextWindow.ForegroundColor = "Yellow"
num = Array.GetItemCount(arry)
index = Array.GetAllIndices(arry)
For i = 1 To num
  TextWindow.WriteLine("arry[" + index[i] + "]=" + arry[index[i]])
EndFor
TextWindow.ForegroundColor = "Gray"

For text base program debugging, changing foreground color may help you to distinguish program original outputs and debugging messages.

Write debug code such as "If debug Then..."

If you wrote a subroutine to show such like an array for debug, that code will be useful also in the future.  But, these code will be needed only when you debug.  So I recommend you to use debug flag to on and off your debug routines.

Maze 0.4 (PNC833-0) is a sample which has debug flag.  Following line sets debug flag off.  And debug = "True" will turn on the flag.

27 debug = "False"

Following lines call a subroutine to show array "cell" of created maze as text.

61 If debug Then
62  DumpMaze()
63  TextWindow.WriteLine(title)
64 EndIf

Following lines slow down creating maze to look and show variables and pause the program using TextWindow.Read().

229      If debug Then
230        Program.Delay(20)
231      EndIf
232      ' 2. Add the neighboring walls of the cell to the wall list.
234      AddWallToList()
235      If debug Then
236        TextWindow.WriteLine("iWalls=" + iWalls)
237        TextWindow.Write("nWalls=" + nWalls)
238        TextWindow.Read()
239      EndIf

And after debugging completed, these lins are easily found (with [Ctrl]+F in Small Basic IDE) and removed.  Actually I removed these routines in Maze 0.5 (not published).

Write test programs for subroutines

To write generic subroutines (for general-purpose) will help your productivity.  In my case, some subroutines for colors, maths, mouse, and etc. are reused in many programs.  But generic subroutines should be well tested and have no bugs.  No (or less) bugs will be a prior condition for productivity.

To test your subroutines, I recommend you to write test program for them.  Good test program will find bugs from your subroutines and make easy to check regression after debugging.

A program which calculate comination nCr for big n (CPQ608) has a test routine TestDiv() for a generic subroutine Div().

Follwing parameters were found with TestDiv() and caused problem in Div().

  'a = "434399216531770650390143258708"
  'b = "6752306690329"
  'a = "397896921587794748049229269710"
  'b = "8642083658481"

List up bugs

Following list is written when I debug Shapes 1.1 (TLW744).  When you write lots of code, you may happen to meet many strange behavior in your program.  If so, I recommend you to write a list of each phenomenon.  Because there may be many defferent causes of the phenomena.  And after debubbing, this list will be a good test set for your program.

•	CalcOpposite() returns wrong value when shape re-sizing
cause: variable func was not be set for the routine
•	Pinchs (small circles) remain after click out of shapes
cause: not implemented yet
•	Frame sometimes not appear when shape moving
cause: variable i didn't set as selectedshape
•	Pinches sometimes remain when cut and paste
cause: duplicate as follows
•	Pinches don't redraw after copy
cause: pinches are not displayed after paste
•	Shape moves after mouse release
cause: needed to keep mouse released in mouse handler
•	Other shape size and position become wrong after color change
cause: unnecessary RegisterShapeData() called and broke variable i
•	Other shape selected after adding ellipse or triangle
cause: cancel adding procedure (when menu item clicked) set needless variable obj
•	Sometimes shape can't be moved
cause: mouse released flag should be cleared

Meaning of error messages

There are two types of error messages given by Small Basic.  One is compile errors.  Another one is runtime errors.  These messages help your development.

Compile errors appear under source code just after "Run" button is clicked if your program has any syntax errors.  Following picutre shows errors of a program "Fifty" (BRQ733) :

Sorry, we found some errors...
11,28: The avairable 'files' is used, but its value is not assinged.  Are you sure you have spelled it correctly?
29,24: The avairable 'buf' is used, but its value is not assinged.  Are you sure you have spelled it correctly?

Numbers mean lines and columns of source code, and you can jump into the point in source program by double clicking the error message.  These kind of compile error messages show you what happened and some advice to fix them. In this case, errors happened because lines with File.GetFiles(path) and File.ReadContents(filename) have been automatically commented out by Small Basic server.

On the other hand, runtime error appears while a program runs but happens to meet trouble which make the program stop.  Following picture is a sample of divsion by 0 error message.

Decimal type value is too large or too small.
Location System.Decimal..ctor(Double value)
Location Microsoft.SmallBasic.Library.Math.Remainder(Primitive dividend, Primitive divisor)
Location _SmallBasicProgram._Main()

List shown in text box is called stack trace.  This list shows you relations which subroutine calls whitch subroutine at the error.  In this case, the stack trace shows that main part of the program calls Math.Remainder() and occurs error.

Use "Graduate" and Visual Studio debugger

Despite writing many debug routines, some bugs may be too complicated to find their causes.  As a last option, I recommend you to use "Graduate" button to convert Small Basic program to Visual Basic program.  This allows you to use strong Visual Studio debugger to find causes of bugs originally in your Small Basic program.

Step 1: Install Visual Basic 2010 Express if you don't install yet.
Step 2: Push "Graduate" button and input folder name for converted Visual Basic program.
Step 3: Push [Next] or [Finish] buttons in Visual Studio conversion wizard.
           Program XXX.sb (or XXX.smallbasic) will be converted to XXXModule.vb.
Step 4: Rewrite from 'For i = 1 To n' to 'For i As Primitive = 1 To n' to avoid scope error.
Step 5: Double click a source line to make the line as break point if needed.
Step 6: Push "Debug Start" button or [F5] to start program.
Step 7: If program stops at break point, push "Step In (F8)" or "Step Over (Shift+F8)" to continue.
Step 8: See "Auto Variable", "Local" or "Watch" tab and confirm the values of variables.
Step 9: If you find a bug, push "Step Debugging" button and rewrite your program with comment.
Step 10: Repeat from step 6 again.

If you confirmed bug fix, go back to Small Basic IDE and fix program just as you did in Visual Studio.

There are some differences between Small Basic and Visual Basic syntax as listed below.

•	Array : arry[i][j] in Small Basic, arry(i, j) in Visual Basic
•	Variable type : Small Basic variables are type "Primitive" so sometimes need type conversion such as 'If ans = CType("", Primitive) Then'. 

Conclusion

I learned these tips within the last couple of years.  And I realized that Small Basic is very compact and a good language to learn programming.  I hope many people will also learn and enjoy programming with Small Basic.  It's easy and powerful.