Skip to content

Latest commit

 

History

374 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Skeme

CMake GitHub License

What is Skeme

Skeme is a lightweight Scheme-like language interpreter written in portable C. It features a single-pass compiler that emits bytecode for a stack-based virtual machine with tail-call optimization, mark-sweep garbage collection, closures, and a REPL.

General curiosity about garbage collection methods was the primary motivation for this project. Since LISP was the first language to feature garbage collection, implementing a popular LISP dialect seemed like a good test case.

Not having any prior experience implementing garbage collectors, or with closures or functional programming, I found Crafting Interpreters by Robert Nystrom very helpful.

This project uses many of the parsing methods I learned from Jack Crenshaw a long time ago. And while I don't explicitly use my ParserKit library for this project, the same recursive descent primitives are here. The project does use my hash library and test framework.

Main Features of Skeme

  • Scheme R5RS-ish — lists, lambdas, closures, tail-call optimization, cond/case
  • Bytecode VM — compiled to bytecode (using computed gotos on GCC/Clang, and function pointer tables on MSVC)
  • Garbage collection — tri-color mark-sweep GC with automatic thresholds
  • First-class functions — lambdas, closures with captured upvalues, higher-order functions
  • Numeric types — integers and floats with tagged pointer representation
  • String interning — strings are interned to avoid duplicates and for fast equality checks
  • REPL — interactive read-eval-print loop with terminal colored output
  • Extensible — register custom C types and functions (see Extending Skeme)
  • Cross-platform — builds on Windows (MSVC), Linux (GCC/Clang), and macOS

Getting Started

git clone https://github.com/mseminatore/skeme.git
cd skeme
git submodule update --init --recursive

Building Skeme

CMake (recommended)

cmake -S . -B build
cmake --build build --config Release

The binaries are placed in build/Release/ (MSVC) or build/ (Make-based generators).

Make (Linux / macOS)

make

Usage

skeme [options] [inputfile]

Options

Flag Description
-i Start interactive REPL
-v Enable verbose output
-d Enable parser debug output
-p Enable parser logging
-profile Print VM profiling report on exit
-h Display usage help

Running a Script

skeme myprogram.scm

Interactive REPL

skeme -i

Or simply run skeme with no arguments to enter the REPL. Use (exit) to quit.

Loading Libraries

Use load at the top of your script to pull in additional definitions:

(load "stdlib.scm")

Standard Library

The file stdlib.scm provides common utility functions on top of the native builtins:

Function Description
apply Apply a function to each element of a list
filter Return elements satisfying a predicate
append Concatenate two lists
cadr (car (cdr x))
cddr (cdr (cdr x))
even? Test if a number is even
odd? Test if a number is odd
min Return the smaller of two numbers
max Return the larger of two numbers
assert Assert a condition or raise an error
list-ref Return the nth element of a list
list-tail Return sublist after dropping n elements
member Find first element equal? to a value
memq Find first element eq? to a value
assoc Look up key in association list (equal?)
assq Look up key in association list (eq?)
for-each Apply function to each element (side effects)
gcd Greatest common divisor
lcm Least common multiple

Built-in Functions

The following functions are implemented natively in C:

Arithmetic: +, -, *, /, =, <, >, <=, >=, modulo, abs, quotient, remainder, expt, sqrt, floor, ceiling, truncate, round

List operations: cons, car, cdr, list, length, reverse, set-car!, set-cdr!, map

Type predicates: null?, pair?, list?, number?, integer?, float?, boolean?, char?, string?, atom?, zero?, positive?, negative?, procedure?

Equality: eq?, eqv?, equal?

Boolean: not

Strings: string-append, string-length, string-ref, substring, string-copy, string->number, number->string, string->float, float->string

Characters: char->integer, integer->char

I/O: display, write, newline, read, read-line, read-char, write-char, write-line, printf, open-input-file, open-output-file, close-file, delete-file

Control: eval, error, exit

Introspection: typeof, disasm, gc, gc-stats, mem-allocated, getenv, command-line, pwd

Extending Skeme

Skeme supports registering custom C types and native functions. You can add new data types (with GC integration, printing, and equality) and expose C functions to Scheme code.

See EXTENDING.md for the full API reference and examples.

Testing

Scheme Test Suite

skeme -v test.scm

Runs the built-in test suite using the skunit.scm test framework.

C Unit Tests

# CMake
ctest --test-dir build -C Release

# Make
make unit-test

Run All Tests

# Make
make all-tests

License

MIT — Copyright (c) 2025 Mark Seminatore

About

Skeme is a portable and embeddable Scheme-like little language in C

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages