The agony of debugging

Ovid on 2005-02-13T00:50:48

I only have time to work on AI::Prolog during the weekends, so I was chomping at the bit to tear into it today. The main problem I faced was simple: it was horribly broken and I couldn't figure out why. It's been nagging at me all week. I was trying to borrow the bits from XProlog that I needed, but the XProlog compiler is useless to me. That meant I had to figure out my own method of compiling Prolog code and still get it to work with the new internals. Since the core engines of the Java and Perl versions were the same, I was painstakingly going through and inserting synchronized print statements in them. It was taking forever, but then I realized how stupid I was being. I was editing this in vim. Why not let vim do this for me? Here's the important bit of my vim plugin:

noremap  ,pp :call Println()

func Println()
  call DoPrintln(line("."))
endfunc

" other functions call this which is why we have a wrapper
func DoPrintln(number)
  let curr_line  = getline(a:number)

  if &ft == "perl"
    let curr_line  = "print '" . curr_line . "'. \"\\n\"; # XXX debug "
  elseif &ft == "java"
    let curr_line  = "System.out.println(\"" . curr_line . "\"); // XXX debug"
  endif

  if curr_line != getline(a:number)
    call append(a:number - 1, curr_line)
  endif
endfunc

With that, I can type ,pp in either a Java or Perl program and it will insert a line in the code which prints the next line of code. The programs print themselves out while running and it's trivial to create program traces. That quickly led me to my problem.

while ($clause = $clause->nextClause) {...}

That's something I use to walk through lists of clauses to find the clause I need to examine. Unfortunately, the following held true:

$clause eq $clause->nextClause;

Thus leading me into an infinite loop. So I went to wash the dishes.

I figured the problem was in my new parser, but an hour of playing with that convinced me I was wrong. So I went and paid all of my bills.

So the new database has to be storing information incorrectly. Yeah, that's it!

No, that's not it. So I went and did my taxes.

I came back to the computer, sat down, got up and went and bought some books. Came back to the computer, sat down, got up and made lunch. I was stumped. Every time I touched the damned computer I walked away, frustrated.

Then it dawned on me: in order to improve performance, I was violating encapsulation and had no way of knowing what was assinging the incorrect data to nextClause. So I found every place in the code where I was assiging to the object hashref directly and converted that to $clause->nextClause($newClause);. Then I went to &nextClause and inserted a test to see if I was assigning a clause as its own next clause and died with a stacktrace. A few seconds later I found my bug. I deleted one line of code and the engine worked.

Today or tomorrow I should have a new version uploaded.

Update: or maybe I won't. Just found another bug. Were it not for the tests, I would've uploaded :/


Program traces

Aristotle on 2005-02-13T17:48:38

Maybe you want to know about Devel::Trace?

Re:Program traces

Ovid on 2005-02-13T18:37:54

That doesn't work for me. What I was doing was synchronizing the print statements between Java and Perl and then opening them up side by side in a terminal window. I then just glanced at them and as soon as they diverged, I nailed the difference.