xbasic64 1.0.0

A BASIC-to-x86_64 native code compiler targeting 1980s-era BASIC dialects
# CLAUDE.md

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

## Project Overview

xbasic64 is a BASIC-to-x86_64 native code compiler written in Rust. It targets 1980s-era BASIC dialects (Tandy Color BASIC, GW-BASIC, QuickBASIC) and compiles to native executables using the System V AMD64 ABI.

## Build Commands

```bash
cargo build           # Build the compiler
cargo test            # Run all tests
cargo test test_name  # Run a specific test
cargo clippy          # Run linter
cargo fmt             # Format code
```

## Usage

```bash
xbasic64 program.bas              # Compile to executable
xbasic64 program.bas -o output    # Specify output name
xbasic64 -S program.bas           # Emit assembly only
```

## Architecture

The compiler uses a simple three-stage pipeline with no intermediate representation:

1. **Lexer** (`src/lexer.rs`) - Tokenizes BASIC source (case-insensitive keywords, line numbers, type suffixes)
2. **Parser** (`src/parser.rs`) - Recursive descent parser producing an AST
3. **Code Generator** (`src/codegen.rs`) - Direct AST-to-x86-64 assembly translation

Assembly output is passed to the system assembler (`as`) and linker (`cc`).

### Runtime Library

The runtime (`src/runtime/`) is hand-written x86-64 assembly using libc for portability:
- `data_defs.s` - Format strings, buffers
- `print.s` - PRINT functions
- `input.s` - INPUT functions
- `string.s` - String manipulation (LEFT$, MID$, etc.)
- `math.s` - Math functions (SQR, SIN, RND, etc.)
- `data.s` - DATA/READ support
- `file.s` - File I/O (OPEN, CLOSE, PRINT#, INPUT#)

### Type System

Following GW-BASIC/QuickBASIC conventions with type suffixes:
- `%` INTEGER - 16-bit signed (i16), stored in eax
- `&` LONG - 32-bit signed (i32), stored in eax
- `!` SINGLE - 32-bit float (f32), stored in xmm0
- `#` DOUBLE - 64-bit float (f64), stored in xmm0 - **DEFAULT for unsuffixed variables**
- `$` STRING - heap-allocated, managed as (ptr, len) pairs

Division follows GW-BASIC semantics:
- `/` always produces Double result
- `\` integer division produces Long result

Type coercion is automatic: Integer < Long < Single < Double. Comparisons return Long (-1 for true, 0 for false).

### Key Design Decisions

- **No IR** - Direct AST to assembly for simplicity
- **Type-aware codegen** - Integers in eax, floats in xmm0 with automatic coercion
- **Variables are global** - No local scoping except procedure parameters
- **System V AMD64 ABI** - Standard calling convention for libc interop

## Platforms

- macOS (x86-64, ARM64 via Rosetta)
- Linux (x86-64)

## Requirements

- Rust toolchain
- System assembler (`as`)
- System C compiler/linker (`cc`) with libc