From Source Code to Machine Code
You write text; the CPU eats binary instructions. The journeys differ — compiled ahead of time (C, Rust, Go), compiled just-in-time (JavaScript, Java), or interpreted (pure Python) — with very different performance consequences.
Ahead-of-time compilation (C, C++, Rust, Go, Swift): a compiler translates the whole program to machine code once, before it runs. The binary is native instructions; startup is instant and speed is maximal, but the binary is built for one CPU architecture and OS.
Interpretation (classic Python, Ruby): a program (the interpreter) reads your code — usually pre-parsed into simple bytecode — and performs each operation itself. A bytecode 'ADD' might cost the interpreter 50+ real instructions of dispatching, type checking, and boxing. Flexible and portable, 10-100x slower for tight loops.
Just-in-time (JIT) compilation (JavaScript's V8, the JVM, C#, PyPy): start by interpreting, watch which functions run hot, compile those to native machine code at runtime — optimizing for the types actually seen. That's how JavaScript went from toy speed to within a few x of C for many workloads.
Architectures matter: x86-64 (Intel/AMD desktops, most servers) and ARM64 (every phone, Apple Silicon, AWS Graviton) speak different instruction sets. A binary for one can't run natively on the other — that's why Apple built Rosetta 2, a translator, for the Intel-to-M1 transition.