v1.0 · Written in Pure C

ZayneScript

A dynamic, interpreted scripting language written in pure C. First-class functions, closures, async/await, BigInt, OOP, and a rich built-in standard library — all in a single executable.

Language Guide Standard Library Quick Start

Dynamic Typing

Variables hold any type at runtime. No annotations required — write expressive code without ceremony.

🔒

First-Class Functions

Functions are values. Pass them around, return them from other functions, and capture variables in closures. Anonymous functions support a concise => expression body: fn(x) => x * 2.

🔄

Async / Await

Declare async functions and use await to suspend execution. Includes Promise chaining with .then() and .error().

🔢

BigInt Support

Arbitrary-precision integers using the n suffix — 100n + 2n. No overflow surprises with large numbers.

🏗️

Object-Oriented

Class-based inheritance, constructors, static methods/properties, and this binding.

📦

Module System

Named and wildcard imports, core: built-ins, lib: user libraries, and relative path imports.

🗃️

Rich Data Structures

Dynamic arrays with methods (push, pop, each, keep), and flexible key-value objects with spread syntax.

🎛️

Expressive Control Flow

if/for/while/do-while, switch expressions, try/catch, raise, assert, and ternary forms.

📚

Standard Library

Core modules for I/O, math, OS, paths, objects, arrays, dates, regex, promises, SQLite, Unicode, blobs, and HTTP.

🌐

HTTP Server

Express.js-style HTTP server via core:mongoose. Register GET/POST/… routes, attach middleware, and serve JSON APIs — all from ZayneScript.

Quick Start

Build — choose the method that matches your platform.

Makefile — Linux / macOS (recommended):

# Debug build with AddressSanitizer (default)
make

# Super-optimised release build (clang + LTO)
make release

# Force architecture on native build
make 64
make 32
make 32i686

# Cross-compile Windows builds via MinGW
make win32          # auto arch
make win32-64
make win32-32
make win32-32i686

# Build then run immediately
make run

# Install to /usr/local/bin
make install

# Remove the binary
make clean

run.sh — Linux / macOS shell script (uses gcc):

# Debug build + run
./run.sh

# Optimised release build + run
./run.sh --release

# Compile only (no run)
./run.sh --compile

# Format all source files with clang-format
./run.sh --format

# Debug a script with GDB
./run.sh --dbg tests/test_async.zs

Manual — any platform with GCC:

mkdir -p dist && gcc -O3 -DNDEBUG -Wno-pointer-sign \
    main.c src/core/*.c src/*.c utf/*.c utf/utf8proc/*.c ./libbf/*.c \
    -o dist/zscript.exe -lm -ldl -lpthread
Write a script — create hello.zs:
import { println } from "core:io";

println("Hello, ZayneScript!");
Run it (the Makefile writes the binary to dist/):
./dist/zscript.exe --run hello.zs

A Taste of ZayneScript

The following snippet demonstrates variables, closures, classes, async/await, error handling, and the standard library:

import { println, format } from "core:io";
import { sqrt, pi }        from "core:math";

// ----- Closures -----
fn makeCounter() {
    local count = 0;
    return fn() {
        count += 1;
        return count;
    };
}

var tick = makeCounter();
println(tick(), tick(), tick()); // 1 2 3

// Expression-body function (implicit return)
const triple = fn(n) => n * 3;
println(triple(4)); // 12

// ----- Classes with inheritance -----
class Shape {
    fn area() { return 0; }
}

class Circle (Shape) {
    fn init(r) {
        assert r > 0, "radius must be positive";
        this.r = r;
    }
    fn area() { return pi * this.r * this.r; }
}

const c = new Circle(5);
println(format("Area: {}", c.area())); // Area: 78.539816...

// ----- Error handling: raise & try/catch -----
fn safeSqrt(x) {
    if (x < 0) { raise "cannot take sqrt of negative number"; }
    return sqrt(x);
}

try {
    println(safeSqrt(9));   // 3
    println(safeSqrt(-1));  // throws
} catch (e) {
    println("Error:", e);   // Error: cannot take sqrt of negative number
}

// ----- Async / Await -----
fn fetchData() async { return "payload"; }

fn main() async {
    const data = await fetchData();
    println("Got:", data); // Got: payload
}

main();

// ----- BigInt -----
println(2n ** 64n); // 18446744073709551616n

Building

The Makefile validates required programs before building and exits early with install hints if tools are missing.

Required tools

Build type Required programs
Native Linux / macOS builds clang, lld, cmake
Windows cross-builds (MinGW) x86_64-w64-mingw32-gcc or i686-w64-mingw32-gcc, $(prefix)-windres, and CMake ($(prefix)-cmake if available, else plain cmake), plus MinGW CMake toolchain files from mingw-w64-cmake

Architecture selection

By default, BUILD_ARCH=auto detects the current host machine. You can also force an architecture explicitly.

Setting Description Typical command
auto (default) Use host machine architecture make
64 64-bit x86_64 make 64
32 32-bit x86_64 (x32 ABI on native builds) make 32
32i686 32-bit i686 baseline make 32i686

Makefile targets

Target Description
make / make debug Debug build with AddressSanitizer & leak detection (clang -g3 -fsanitize=address,leak)
make release Super-optimised build (-O3 -march=native -flto=thin, stripped binary)
make run Debug build then launch the interpreter
make clean Remove dist/, win32/, and temporary build directories
make install Install binary to /usr/local/bin/zscript and libs to /usr/local/lib/zscript/
make uninstall Remove installed binary and library directory
make amalgamate Bundle everything into a single source file via amalgamate.py

Windows cross-compilation (MinGW)

Target Description Output directory
make win32 Cross-compile for Windows using auto architecture win32/auto/
make win32-64 Cross-compile 64-bit Windows build win32/64/
make win32-32 Cross-compile 32-bit Windows build (i686) win32/32/
make win32-32i686 Cross-compile 32-bit Windows build (i686 baseline) win32/32i686/

Each Windows output folder contains zscript.exe, sqlite3.dll, libmariadb.dll, libmariadb.dll.a, and copied lib/ and tests/ directories.

Windows MariaDB binaries are built from thirdparty/mariadb-connector-c/ using the MinGW CMake toolchain file (for example /usr/share/mingw/toolchain-i686-w64-mingw32.cmake), not copied from a system DLL package.

run.sh flags (Linux / macOS)

Flag Description
(none) Debug build then run the interpreter
--release Release build then run
--compile Compile only, no run
--format Run clang-format over all src/ files
--dbg <file.zs> Launch gdb with auto run and bt on the given script

Usage

Command Description
./dist/zscript.exe --run <file.zs> Execute a script file
./dist/zscript.exe --tests Run all scripts in the bundled tests/ directory
./dist/zscript.exe --help Print help text

Project Structure

Path Contents
src/ Interpreter core: lexer, parser, compiler, bytecode evaluator
src/core/ Builtin core: modules: io (print/scan and File disk I/O), math, os, path, date, regex, object, array, blob, promise, sqlite, utf8, mongoose
dist/ Compiler output: zscript.exe. On each build, lib/ and tests/ are copied into dist/ so lib:name imports resolve next to the executable (for example lib:http, lib:argparser).
tests/ Example .zs scripts demonstrating every feature
lib/ User-level libraries importable via lib: (for example lib/http.zs, lib/argparser.zs)
utf/ UTF-8 processing helpers (utf8proc)
libbf/ BigInt backend (libbf)
main.c Interpreter entry point