this is done by metaprogramming