Compilers
Compilers are software programs that translate source code written in high-level programming languages into machine code or an intermediate representation that can be executed by a computer’s processor. macOS uses the Apple-modified Clang front end with the LLVM back end (commonly invoked via clang
in Xcode) as its default system compiler.
interpreter
An interpreter reads your program’s source (or an intermediate form) and executes it one statement at a time at runtime. Because there’s no separate build step, you get immediate feedback—which makes interpreters ideal for scripting, rapid prototyping, and interactive debugging—but that convenience comes at the cost of performance: each line must be parsed and translated on the fly, so interpreted code generally runs more slowly than precompiled code.
Types of compilers
Ahead-of-time (AOT) compiler
An ahead-of-time (AOT) compiler, by contrast, translates your entire source into native machine instructions before you ever run the program. This up-front compilation step means you pay a “build” penalty whenever you change your code, but once the executable is produced it starts up quickly and delivers peak performance, since no translation occurs at runtime.
When people talk about “a compiler” in the traditional sense, they almost always mean an ahead-of-time (AOT) compiler. Languages like C, C++ or Rust use standard AOT compilers: you run the compiler once to translate all your source files into native machine code, producing an executable that you then run directly. In contrast, JIT compilers delay some of that translation until runtime, and interpreters don’t produce native binaries at all.
Just-in-time (JIT) compiler
A just-in-time (JIT) compiler blends the two approaches. It typically begins by interpreting or executing an intermediate form (like bytecode) and, as the program runs, watches for “hot” code paths—functions or loops you use most frequently. It then compiles those hotspots on the fly into optimized machine code, applying runtime information (for example, inlining or specializing types) to squeeze out extra speed. The result is faster performance than pure interpretation, without the long compile times of AOT builds—though initial startup can be slower until the JIT has warmed up.
In practice, you’d reach for an interpreter when you need the fastest edit–run cycle; an AOT compiler when you need predictable, maximal performance (games, system utilities, embedded software); and a JIT compiler when you want a balance of rapid development and high, workload-aware optimization—exactly why platforms like the JVM and .NET CLR embrace JIT techniques.
https://www.youtube.com/watch?v=mQ-vQ2BlKrw&t