add ability to dynamically load/reload programs

* uses shared_ptr to do memory management instead of bare pointers
* todo: we'd like to have program manage kernels, so that if a program object destroys, it releases the kernels it owns.

Signed-off-by: tgfrerer <tim@poniesandlight.co.uk>