Page 6: Source Code to Machine Instructions: Compilers, Interpreters, and JIT Engines
Understanding how parsers build Abstract Syntax Trees (ASTs) explains how linters, formatters (Prettier), bundlers (Vite/esbuild), and TypeScript type-checkers analyze your code.
Processors cannot execute source code text like `const total = price * quantity;` directly. A translation system must first verify that the syntax is valid and then convert the high-level constructs into binary instructions or bytecode. Historically, programming languages were divided into two camps: Ahead-of-Time (AOT) compiled languages (such as C, C++, and Rust) and interpreted languages.
Today, high-performance runtimes like the V8 JavaScript engine, the JVM, and .NET CLR combine both techniques using multi-tier Just-in-Time (JIT) compilation. They start executing code immediately using a fast bytecode interpreter while profiling which functions run most frequently, then compile those "hot" functions directly into optimized native machine code on the fly.
6.1 Lexing (Tokenization) and Parsing into an AST
The first phase of any compiler or interpreter is lexical analysis (lexing). The lexer scans raw characters and groups them into meaningful tokens—such as keywords (`const`), identifiers (`total`), operators (`=`, `+`), and literals (`42`).
Next, the parser consumes that flat stream of tokens and constructs a hierarchical tree called an Abstract Syntax Tree (AST) that captures operator precedence and nesting structure. If a closing parenthesis or brace is missing, the parser halts during this stage with a `SyntaxError` before a single line of program logic executes.
6.2 AOT Compilation vs. JIT Profiling
An Ahead-of-Time (AOT) compiler translates the entire program into target-specific machine code (e.g., x86-64 or ARM64) before distribution. This yields zero warm-up overhead and predictable memory usage, which is why operating systems and game engines use AOT languages.
A Just-in-Time (JIT) engine like V8 parses JavaScript into an AST, generates compact bytecode for its Ignition interpreter, and collects type feedback as the program runs. If a function is called thousands of times with numbers, the TurboFan optimizing compiler emits specialized machine code for numeric addition. If a later call unexpectedly passes an object or string, the engine safely "deoptimizes" back to bytecode.