Skip to content

About

A modern, beginner-friendly scripting language written in C with an interpreter and bytecode virtual machine.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

23 stars

Watchers

0 watching

Forks

Repository files navigation

QuantoScript

A small, readable scripting language with three execution engines.

Dynamic typing · try/oops exceptions · classes with shared identity · a tree-walk interpreter, a bytecode VM, and an optional native-C compiler.

CI version language license platforms

Documentation · Examples · Changelog · Contributing


Table of Contents


Why QuantoScript?

QuantoScript is a small, embeddable scripting language designed for readability and simplicity — think Python's clarity with a simpler, brace-based syntax. It ships with three execution engines: a tree-walk interpreter for fast iteration, a bytecode VM for performance, and an optional native-C compiler for compute-heavy numeric code.

Braces, not indentation Blocks are delimited with { } — no significant whitespace.
Friendly keywords maybe instead of elif, oops instead of except.
1-based indexing Lists and strings start at index 1.
Shared object identity Class instances are references, not copies.
Matching engines The same program runs on the interpreter or the bytecode VM with identical output.
Native fast-path Arithmetic-heavy code can compile to C for a ~10× speedup.
Single-file core The whole language is one C99 amalgamation — easy to embed and vendor.

Installation

The fastest way to get QuantoScript is the one-line installer. It downloads a prebuilt, self-contained binary (OpenSSL bundled in — no dependencies to install), places it under ~/.quanto, and adds it to your PATH. No compiler and no sudo required.

macOS / Linux

curl -fsSL https://raw.githubusercontent.com/PySudo/QuantoScript/main/install.sh | sh

Windows (PowerShell)

irm https://raw.githubusercontent.com/PySudo/QuantoScript/main/install.ps1 | iex

Then open a new terminal and run qs --help.

Prebuilt binaries are provided for macOS (Apple Silicon), Linux (x86-64), and Windows (x86-64). On Intel Macs and ARM64 Linux, the installer will ask you to build from source until binaries for those platforms are published.

Installer options

macOS / Linux (install.sh)

# Install a specific version
curl -fsSL https://raw.githubusercontent.com/PySudo/QuantoScript/main/install.sh | sh -s -- --version 1.1.3

# Custom install prefix (default: ~/.quanto)
QUANTO_INSTALL="$HOME/.local" curl -fsSL .../install.sh | sh

# Don't touch your shell profile
NO_MODIFY_PATH=1 curl -fsSL .../install.sh | sh

# Uninstall
curl -fsSL https://raw.githubusercontent.com/PySudo/QuantoScript/main/install.sh | sh -s -- --uninstall

Windows (install.ps1)

# Install a specific version
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/PySudo/QuantoScript/main/install.ps1))) -Version 1.1.3

# Uninstall
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/PySudo/QuantoScript/main/install.ps1))) -Uninstall

Prefer to build it yourself? See Building from Source.


Quick Start

Already installed? Skip straight to Hello World. Otherwise build the interpreter with make (see Building from Source for OpenSSL notes).

qs examples/full_tour.qs   # run a script
qs                         # or drop into the REPL

Hello, World!

print("Hello, World!")

func greet(name) {
    return "Hello, " + name + "!"
}

print(greet("QuantoScript"))
qs hello.qs          # tree-walk interpreter
qs vm hello.qs       # bytecode VM (identical output)

Language Tour

Variables and Types

x       = 42                # integer
pi      = 3.14              # float
name    = "QS"              # string
flag    = true              # boolean
nothing = null              # null
items   = [1, 2, 3]         # list
user    = {"name": "QS"}    # map

Functions and Lambdas

func add(a, b) {
    return a + b
}
print(add(3, 4))            # 7

double = fn(x) -> x * 2     # lambda expression
print(double(5))            # 10

Control Flow

if x > 10 {
    print("big")
} maybe x > 5 {             # "maybe" == "else if"
    print("medium")
} else {
    print("small")
}

repeat 5 { i = i + 1 }      # counted loop
while x < 100 { x = x * 2 } # conditional loop

Exception Handling — try / oops

func safe_div(a, b) {
    if b == 0 {
        oops("division by zero")   # raise
    }
    return a / b
}

try {
    print(safe_div(10, 0))
} oops e {                          # catch, binding the error to `e`
    print("caught: " + e)
}

Classes with Shared Identity

class Person {
    init(name) {
        self.name = name
    }

    greet() {
        print("Hi, I'm " + self.name)
    }
}

p = Person("Alice")
p.greet()           # Hi, I'm Alice

c = p               # c and p reference the SAME object
c.name = "Bob"
p.greet()           # Hi, I'm Bob

Note: Put each statement in a method body on its own line — semicolon-separated statements are not supported.

Collections

nums = [3, 1, 4, 1, 5]
print(len(nums))            # 5
nums.append(9)
print(nums.contains(4))     # true

user = {"name": "QS", "version": 1}
print(user["name"])         # QS
print(user.keys())          # [name, version]

Built-in methods

Type Methods
String title · contains · replace · startsWith · endsWith · split · join · indexOf · substring · trimStart · trimEnd · repeat · reverse
List append · extend · sort · contains · flatten · map · filter · find · find_type · sum
Map keys · values · items · has · remove · extend

len(value) is a built-in function (not a method) that works on strings and lists.

See The QuantoScript Guide for the complete language reference.


Execution Engines

The interpreter and the bytecode VM run the same source and produce identical output.

Engine Command Best for
Tree-walk interpreter qs program.qs Development, debugging, quick scripts
Bytecode VM qs vm program.qs Better runtime performance
Native C compiler qs native program.qs ~10× speedup on arithmetic-heavy code

Compiled Bytecode (.qvm)

Compile QuantoScript to a stable binary bytecode format for faster startup and distribution without shipping source.

qs build program.qs                 # -> program.qvm
qs build program.qs -o custom.qvm   # custom output path

qs vm program.qvm                   # run compiled bytecode
qs vm --dump-bytecode program.qs    # disassemble for debugging

The .qvm format (version 4) includes a magic-header check, version validation, and a CRC32 checksum of the source, and it rejects malformed files. See Bytecode and Native Builds for details.


Native Compiler

For arithmetic-heavy workloads, QuantoScript can emit C and compile it to a native binary:

qs native program.qs        # emit a_native.c
gcc -O2 a_native.c -o program_native
./program_native

Supported: integer arithmetic, if/else, while, repeat, variable assignment, print. Not supported: functions, strings, lists, maps, closures, classes, exceptions.


Standard Library

Import modules with from "<module>" import <names>. Public modules live in stdlib/; internal runtime hooks (sys_*) stay hidden.

User code  →  stdlib modules  →  native runtime  →  OS
from "stdlib/http.qs"      import get, post
from "stdlib/json.qs"      import parse, stringify
from "stdlib/os.qs"        import run, capture, cwd, chdir, exists
from "stdlib/fs.qs"        import read, write, list_dir
from "stdlib/text.qs"      import lower, upper, split
from "stdlib/time.qs"      import now, localtime
from "stdlib/log.qs"       import info, warn, error
from "stdlib/websocket.qs" import connect, send, recv, close

Examples

# HTTP
from "stdlib/http.qs" import get
resp = get("https://httpbin.org/get")
print(resp)

# JSON
from "stdlib/json.qs" import parse
data = parse("{\"key\": \"value\"}")

# Process execution
from "stdlib/os.qs" import run, capture, exists
run("echo Hello")                   # returns exit code
version = capture("git --version")  # returns stdout
print(exists("gcc"))                # true / false
Module Purpose
core.qs Environment-variable helpers (env)
math.qs Numeric utilities
text.qs String processing
fs.qs File system operations
os.qs Process execution & working directory
http.qs HTTP client (get, post, put, delete, patch)
net.qs Low-level networking
websocket.qs WebSocket client
json.qs JSON parse / stringify
url.qs URL percent-encoding (url_encode, url_decode)
time.qs Time and clock operations
log.qs Structured logging
random.qs Pseudo-random numbers
async.qs Task queue (experimental — see Known Limitations)

At runtime, stdlib modules are resolved via the QUANTO_HOME environment variable. Run qs home to print the configured location. See Imports for how paths are resolved.


Command-Line Interface

qs                          interactive REPL
qs <file.qs>                run with the tree-walk interpreter
qs run <file.qs|.qvm>       run with the bytecode VM
qs vm <file.qs|.qvm>        run with the bytecode VM (alias for run)
qs build <file.qs> [-o out.qvm]   compile to .qvm bytecode
qs native <file.qs>         emit native C (a_native.c)
qs compile <file.qs> [out]  compile to a native binary
qs init                     scaffold a new project
qs check <file.qs>          validate syntax without executing
qs fmt <file.qs>            format source code
qs lint <file.qs>           report common mistakes
qs doc <file.qs>            generate documentation from comments
qs profile <file.qs>        profile function calls
qs test [directory]         run *_test.qs files
qs install <github-url>     install a package
qs list                     list installed packages
qs remove <package>         remove a package
qs home                     print the QUANTO_HOME directory
qs version                  print the version

Flags

--dump-bytecode     print compiled bytecode to stderr
--trace             print a per-instruction VM trace
--sandbox [path]    restrict file access to the given path

Package Manager

QuantoScript has a built-in, git-backed package manager. Packages are cloned from GitHub into a local packages/ directory, and their quanto.json dependencies are resolved recursively.

qs install https://github.com/owner/repo
qs list
qs remove repo
from "packages/owner_repo/main.qs" import something

Scaffold a project with a manifest via qs init, which creates main.qs, a test/ directory, and a quanto.json.


Building from Source

QuantoScript is a single C99 amalgamation (src/quanto.c). It requires a C compiler and OpenSSL (used by the HTTP/WebSocket stack). Networking libraries differ per platform.

Prerequisites

Platform Toolchain OpenSSL
macOS Xcode Command Line Tools (clang) or gcc brew install openssl@3
Linux gcc / clang libssl-dev (Debian/Ubuntu) or openssl-devel (Fedora)
Windows MSYS2 / MinGW-w64 gcc pacman -S mingw-w64-ucrt-x86_64-openssl

macOS

Homebrew installs OpenSSL outside the default search path, so point the compiler at it:

SSL=$(brew --prefix openssl@3)
cc -std=c99 -O2 -Isrc -I"$SSL/include" src/quanto.c -o qs \
   -L"$SSL/lib" -lssl -lcrypto -lpthread -lm

Linux

gcc -std=c99 -O2 -Isrc src/quanto.c -o qs \
    -lssl -lcrypto -lpthread -ldl -lm

Windows (MSYS2 / MinGW-w64)

gcc -std=c99 -O2 -Isrc src/quanto.c -o qs.exe \
    -lssl -lcrypto -lws2_32 -lwinhttp -lwininet -lcrypt32 -lbcrypt -lregex

The -lregex flag (package mingw-w64-ucrt-x86_64-libsystre) enables the real regular-expression back-end for regex_match / regex_find / regex_replace. It is optional: without it those built-ins fall back to literal substring matching. The Makefile detects it automatically.

Using Make (recommended)

The Makefile auto-detects OpenSSL (Homebrew on macOS, pkg-config elsewhere):

make          # build build/qs
make test     # build and run the regression suite
make clean    # remove build artifacts

Useful overrides:

make OPENSSL_DIR=/path/to/openssl   # point at a specific OpenSSL prefix
make STATIC_SSL=1                   # statically link OpenSSL (self-contained binary)
make CC=clang                       # choose the compiler

Using CMake

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
# Optional: self-contained binary and packaging
cmake -S . -B build -DQS_STATIC_OPENSSL=ON && cmake --build build
cpack --config build/CPackConfig.cmake      # produce a .tar.gz / .zip

Optional: Python embedding

Building with -DQS_PYTHON and the Python headers enables the Python FFI examples.


Project Structure

src/                C source (single-file amalgamation)
  quanto.c          Entry point that includes the parts below
  parts/            Language modules (.inc): parser, VM, compiler, runtime, CLI, …
stdlib/             Standard library modules (.qs)
examples/           Example programs (see full_tour.qs)
tests/              Regression and stress test suite
docs/guide/         The QuantoScript Guide (language documentation)
tools/              Benchmarks, CMake helpers, packaging metadata
scripts/            Build and install scripts
build/              Build output (gitignored)

Known Limitations

This is a v1.1.3 release. The following are known and tracked:

  • Closures that capture an enclosing function's local variables work in the tree-walk interpreter but not in the bytecode VM, which reports an unknown variable. Nested func declarations are not supported.
  • Class method bodies take one statement per line; semicolon-separated statements are not supported.
  • Return type annotations are parsed but not yet enforced.
  • Async/await is not functional. The stdlib/async.qs task queue hangs with two or more tasks and can crash non-deterministically under load. Single-task spawn/run/result work. See Standard Library § async.
  • Python embedding requires the -DQS_PYTHON build flag and Python headers.

Roadmap

Version Focus
v1.2.0 Working closures, richer string/map methods
v2.0.0 Async/await, broader native-compiler coverage

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md for guidelines and CHANGELOG.md for release history. When submitting changes, please run the regression suite first:

make test

License

Released under the MIT License.

About

A modern, beginner-friendly scripting language written in C with an interpreter and bytecode virtual machine.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages