Readme
kz80_lisp
A minimal LISP interpreter and compiler for the RetroShield Z80. This project provides both a Rust-based development interpreter and a native Z80 LISP system that runs on actual Z80 hardware.
Features
Rust Interpreter : Full LISP interpreter for development and testing
Z80 Code Generator : Generates native Z80 machine code for the RetroShield
Self-Hosted Compiler : A LISP-to-Z80 compiler written in LISP itself
Floating Point Library : Pure LISP decimal floating point arithmetic
Comprehensive Test Suite : Tests for interpreter, compiler, and float library
Quick Start
Building
cargo build -- release
Running the REPL
./target/release/kz80_lisp
Example session:
kz80_lisp v0.1.0 - A minimal LISP for RetroShield Z80
Type ( HELP) for help, ( QUIT) to exit
> ( + 1 2 3 )
6
> ( DEFINE ( FACTORIAL N) ( IF ( <= N 1 ) 1 ( * N ( FACTORIAL ( - N 1 ) ) ) ) )
FACTORIAL
> ( FACTORIAL 5 )
120
> ( QUIT)
Generating Z80 Binary
./target/release/kz80_lisp -- generate-z80 lisp.bin
This generates a 32KB ROM image that can be run on the RetroShield Z80 emulator or actual hardware.
Running on the Emulator
../emulator/retroshield lisp.bin
Language Reference
Form
Description
( QUOTE x) or 'x
Return x unevaluated
( IF test then else )
Conditional expression
( COND ( test1 result1) ... )
Multi-way conditional
( LAMBDA ( args) body)
Anonymous function
( DEFINE name value)
Define a variable
( DEFINE ( name args) body)
Define a function (shorthand)
( SETQ name value)
Set a variable's value
( LET ( ( var val) ... ) body)
Local bindings
( PROGN expr ... )
Sequential evaluation
( AND expr ... )
Logical and (short-circuit)
( OR expr ... )
Logical or (short-circuit)
Built-in Functions
List Operations
Function
Description
( CAR list)
First element of a list
( CDR list)
Rest of a list (all but first)
( CONS a b)
Construct a pair
( LIST a b ... )
Create a list
( LENGTH list)
Number of elements
( APPEND list1 list2)
Concatenate lists
( REVERSE list)
Reverse a list
( NTH n list)
Get nth element (0-indexed)
Predicates
Function
Description
( NULL x)
Is x NIL?
( ATOM x)
Is x an atom (not a cons)?
( CONSP x)
Is x a cons cell?
( NUMBERP x)
Is x a number?
( SYMBOLP x)
Is x a symbol?
( EQ a b)
Are a and b identical?
( EQUAL a b)
Are a and b structurally equal?
( ZEROP n)
Is n zero?
Arithmetic
Function
Description
( + a b ... )
Addition
( - a b)
Subtraction
( * a b ... )
Multiplication
( / a b)
Integer division
( MOD a b)
Modulo
( ABS n)
Absolute value
Comparison
Function
Description
( = a b)
Numeric equality
( < a b)
Less than
( > a b)
Greater than
( <= a b)
Less than or equal
( >= a b)
Greater than or equal
Logic
Function
Description
( NOT x)
Logical not
I/O
Function
Description
( PRINT x)
Print with newline
( PRINC x)
Print without newline
( TERPRI )
Print newline
Libraries
Floating Point Library (float.lisp)
A pure LISP implementation of decimal floating point arithmetic. Floats are represented as cons cells: ( SIGN . ( EXP . MANT ) ) .
; ; Load the library
> ( DEFINE F1 ( FINT 42 ) ) ; Convert integer to float
> ( DEFINE F2 ( FINT 10 ) )
> ( FPLUS F1 F2) ; Add floats
( 0 129 . 5200 )
> ( FTRUNC ( FPLUS F1 F2) ) ; Convert back to integer
52
Float Functions
Function
Description
( FMAKE sign exp mant)
Construct a float
( FSIGN f)
Get sign (0=positive, 1=negative)
( FEXP f)
Get exponent
( FMANT f)
Get mantissa
( FZEROP f)
Is float zero?
( FNEGP f)
Is float negative?
( FPOSP f)
Is float positive?
( FNEG f)
Negate float
( FABS f)
Absolute value
( FINT n)
Integer to float
( FTRUNC f)
Float to integer (truncate)
( FPLUS a b)
Float addition
( FMINUS a b)
Float subtraction
( FTIMES a b)
Float multiplication
( FDIVIDE a b)
Float division
Self-Hosted Compiler (compiler.lisp)
A LISP-to-Z80 compiler written in LISP. Compiles arithmetic expressions to native Z80 machine code.
> ( COMPILE '( + 1 2 ) )
21
> ( DUMP 256 32 ) ; View generated code
0100: 21 05 00 E5 21 09 00 D1 19 21 01 00 D1 B7 ED 52
0110: 76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
The compiler supports:
Integer arithmetic: + , - , * , /
Nested expressions: ( + 1 ( + 2 3 ) )
Float operations via the float library
Project Structure
kz80_lisp/
├── src/
│ ├── main. rs # REPL and CLI
│ ├── types. rs # Core LISP types
│ ├── reader. rs # S- expression parser
│ ├── printer. rs # Value printer
│ ├── interpret. rs # Interpreter core
│ ├── builtins. rs # Built- in functions
│ └── codegen. rs # Z80 code generator
├── tests/
│ ├── test_interpreter. lisp # Interpreter tests
│ ├── test_float_library. lisp # Float library tests
│ ├── test_compiler. lisp # Compiler tests
│ └── run_all_tests. sh # Test runner
├── float. lisp # Floating point library
├── compiler. lisp # Self - hosted compiler
├── Cargo. toml
├── LICENSE # BSD 3 - Clause
└── README . md
Testing
Run the Rust unit tests:
cargo test
Run the LISP test suites:
# Interpreter tests
cat tests/test_interpreter.lisp | ./target/release/kz80_lisp
# Float library tests
cat float.lisp tests/test_float_library.lisp | ./target/release/kz80_lisp
# Compiler tests
cat compiler.lisp tests/test_compiler.lisp | ./target/release/kz80_lisp
# Or run all tests
./tests/run_all_tests.sh
Technical Details
Value Representation
The interpreter uses a tagged enum representation:
NIL - The empty list / false
T - True
Fixnum( i16 ) - 16-bit signed integers
Symbol( String ) - Interned symbols
Cons( Rc< RefCell< ( Value, Value) > > ) - Cons cells
Lambda { params, body, env } - User functions
Builtin( fn ) - Built-in functions
Z80 Target
The Z80 code generator produces:
32KB ROM image (0x0000-0x7FFF)
Uses MC6850 ACIA for serial I/O (ports 0x80/0x81)
Tagged pointer representation with 2-bit tags
Garbage collection via mark-and-sweep
Memory Map (Z80)
Address
Size
Description
0x0000-0x1FFF
8KB
ROM (interpreter)
0x2000-0x7FFF
24KB
RAM (heap, stack)
Examples
Recursive Functions
; ; Fibonacci
( DEFINE ( FIB N)
( COND ( ( <= N 1 ) N)
( T ( + ( FIB ( - N 1 ) ) ( FIB ( - N 2 ) ) ) ) ) )
( FIB 10 ) ; => 55
Higher-Order Functions
; ; Map function
( DEFINE ( MAP F LST)
( IF ( NULL LST)
NIL
( CONS ( F ( CAR LST) ) ( MAP F ( CDR LST) ) ) ) )
( MAP ( LAMBDA ( X) ( * X X) ) '( 1 2 3 4 5 ) )
; => (1 4 9 16 25)
Floating Point Arithmetic
; ; Load float library first
; ; Calculate area of circle with radius 5
( DEFINE PI ( FMAKE 0 128 3142 ) ) ; 3.142
( DEFINE R ( FINT 5 ) )
( DEFINE AREA ( FTIMES PI ( FTIMES R R) ) )
( FTRUNC AREA) ; => 78
License
BSD 3-Clause License. See LICENSE for details.