Yeah, graphs with cycles are tricky to do without GC. You would need to
walk the graph and basically do manual GC now and then. That's a hundred
lines of extra code which runs when you want it to run. Trying to do more
classic manual memory management would be horrific indeed, but when done in
a way that fits the situation it adds negligible coding/complexity overhead.
For complication/translation/optimization stuff you generally can just
allocate everything you need and throw everything away afterwards, e.g.
at program exit. Usually the optimization complexity explodes, so you
want to limit the size of the problem anyway.
It's like with locking; You don't have to always use the same granularity.