The AVR Tiny's without any ram have a dedicated return stack that can be used for up to three (IIRC) nested function calls. That, along with inlining of functions meant that I could write reasonably normal C. I did put everything within the one file, and I had to be particularly careful about variables - you can't have them in ram, nor can you have stack frames in your functions. And since the compiler doesn't know about these limitations, there was a bit of trial and error involved. But overall, it worked quite nicely.