You can use one hash table per type of shape (that would be called a class in many other languages :). For example, a hash called sphere and one called plane. Each of these hashes would have an entry whose key is the generic name of the function (intersect, etc.) and whose value would be the implementation of the function for that type.
Finally, if x is your object and (car x) gives you its type, you can call its intersect function this way :
(withs (type (car x)
class (classes type)
function (class 'intersect))
(function x))
If you have parameters, they must be added after x in the last line. Basically, that's it. But there are many other possibilities if you don't like this one for any reason. And anyway, maybe someone else will give you a better one.
I would like to emphasize the bit "once that is working"... it can be a bit much to get the whole mechanism working at the same time as developing the macro. So get the flow going from a text file being read in to the correct function being called for that shape and maybe do a few shapes until you are sure the beast is about right, then do the macrology. Especially if a macro is in a separate file (as it should be) and you are not reloading the whole shebang each time you run, you'll go nuts running old code even after changing the macro if you just reload the macro-defining file. Add to that the fact that the mechanism itself will be a moving target... well, I like to divide and conquer these deals.