How interpreters and compilers work