In homoiconic languages like Lisp or Mathematica the program is just "data" and can be transformed arbitrarily, even at runtime.
This allows you to write utility functions that transform programs in all sorts of useful ways to find bugs.
A simple example is to just transform the program so that it traces whatever you want to a log, much like Visual Studio Intellitrace, but completely flexible.
You can do things like replace all floating point numbers with a "dual number" (a 2-number tuple) where the first number is always rounded down when operated on, and the second number is always rounded up. This then lets you robustly determine if your numerical accuracy is guaranteed to be within a certain range (due to floating point error, at any rate).
You can symbolically evaluate programs involving random variables using their distributions instead, symbolically working out the products of functions instead of scalar values. This allows things like video poker or lottery programs to be robustly evaluated for average payout even if some of the plays are rare, such as jackpots. A friend of mine did this using Mathematica back in the early 2000s.
This needs some explanation.