Skip to content

Latest commit

 

History

History
131 lines (98 loc) · 4.28 KB

File metadata and controls

131 lines (98 loc) · 4.28 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is nqcc-ts, a TypeScript/Deno implementation of the C compiler from Nora Sandler's "Writing a C Compiler" book. The compiler implements a complete pipeline from C source to executable binaries, targeting x86-64 architecture.

Build and Development Commands

Prerequisites

  • Deno runtime installed
  • GCC (required for preprocessing and final linking)
  • x86-64 architecture (on Apple Silicon, run arch -x86_64 zsh to emulate)

Core Commands

Build the compiler:

deno compile --allow-all --output driver main.ts

Run with file watching for development:

deno task dev

Run the compiler directly:

deno run --allow-all main.ts [FLAGS] <input.c>

Test with intermediate outputs:

deno run --allow-all main.ts --lex input.c        # Stop after lexing
deno run --allow-all main.ts --parse input.c      # Stop after parsing
deno run --allow-all main.ts --validate input.c   # Stop after type checking
deno run --allow-all main.ts --tacky input.c      # Stop after tacky generation
deno run --allow-all main.ts --codegen input.c    # Stop after code generation

Compiler Architecture

The compiler follows a traditional multi-pass architecture with these stages:

1. Preprocessing (External)

  • Uses GCC's -E -P flags to expand macros and includes
  • Converts file.c to file.i

2. Lexical Analysis (Lex.ts)

  • Tokenizes the preprocessed source
  • Handles C keywords, identifiers, constants, and operators
  • Supports integer, long, unsigned, and double literals

3. Parsing (Parse.ts)

  • Recursive descent parser
  • Builds untyped AST (Abstract Syntax Tree)
  • Handles declarations, statements, expressions, and control flow

4. Resolution (Resolve.ts)

  • Resolves identifiers and scopes
  • Handles function and variable declarations

5. Loop Labeling (LabelLoops.ts)

  • Adds labels to loop constructs for break/continue statements

6. Type Checking (TypeCheck.ts)

  • Performs semantic analysis
  • Type inference and validation
  • Uses symbol table for scope management

7. Tacky Generation (TackyGen.ts)

  • Converts AST to three-address code (TAC)
  • Intermediate representation for optimization

8. Code Generation (CodeGen.ts)

  • Converts TAC to assembly instructions
  • Handles register allocation and calling conventions
  • Supports both integer and floating-point operations

9. Assembly Processing

  • Pseudo Register Replacement (ReplacePseudos.ts): Replaces pseudo-registers with actual registers/memory
  • Instruction Fixup (InstructionFixup.ts): Handles instruction-specific adjustments

10. Emission (Emit.ts)

  • Converts internal assembly representation to x86-64 assembly text
  • Outputs .s files

11. Final Assembly and Linking (External)

  • Uses GCC to assemble .s to .o object files
  • Links object files to create final executable

Key Data Structures

Symbol Tables

  • SymbolTable (Symbols.ts): Manages C-level symbols and scopes
  • AssemblySymbolTable (AssemblySymbols.ts): Manages assembly-level symbols

Type System (Types.ts)

  • Supports basic types: int, long, unsigned, double, char
  • Complex types: arrays, pointers, functions, structs
  • Type utilities in TypeUtils.ts

AST Nodes (Ast.ts)

  • Untyped AST for initial parsing
  • Typed AST after type checking
  • Comprehensive node types for all C constructs

Assembly Representation (Assembly.ts)

  • Internal representation of x86-64 assembly
  • Instruction types, operands, and addressing modes

Development Notes

File Organization

  • Core compiler phases are in individual .ts files
  • Utility modules: Const.ts, ConstConvert.ts, Initializers.ts, Rounding.ts, Settings.ts, TypeUtils.ts, UniqueId.ts

Platform Requirements

  • Only works on x86-64 macOS
  • Requires GCC for preprocessing and final linking
  • Uses system calling conventions (System V AMD64 ABI)

Dependencies

  • Uses Deno standard library assertions (@std/assert)
  • Minimal external dependencies

Testing

  • Use compiler flags to test individual phases
  • Compare generated assembly with expected output
  • Binary files are created alongside assembly files for testing