What can we learn from how compilers are designed?