--- layout: page published: true noToc: false noComments: false noDate: false title: Handbook subtitle: Comprehensive handbook for the Fun language and VM, install/build, configuration flags, usage, and full feature overview. description: Comprehensive handbook for the Fun language and VM, install/build, configuration flags, usage, and full feature overview. permalink: /documentation/handbook/ lang: en tags: - handbook - build - configuration - edition - feature - flags - full - install - language - second --- This is a refreshed, deduplicated, and fully up-to-date handbook for the Fun programming language and its virtual machine (VM). It keeps the same section layout as the original handbook while consolidating repeated content and documenting all currently available features, including the latest SQLite support. ## Overview Fun is a small, strict, and simple programming language executed by a stack-based virtual machine. Most of the ecosystem is written in Fun itself; only a minimal core is implemented in C. The design focuses on simplicity, consistency, and joy in coding. ## Introduction - Dynamic and optionally statically typed - Type safety - Written in C (C99) and Fun - Minimal C core; most core functions and libraries implemented in Fun - Internal libraries use snake_case for functions even when written in Fun; class names are CamelCase ## Installation ### Requirements - A C compiler, a libc, and Git #### FreeBSD: - CMake - Clang #### Linux: - CMake - GCC (Clang should also work) #### Windows: - Cygwin (not covered in detail here) - CMake - GCC via Cygwin ### Build Fun Linux/UNIX and Cygwin are covered here. Clone repository:
git clone https://git.xw3.org/fun/fun.git cd funConfigure and build (examples shown with several optional features enabled):
cmake -S . -B build \ -DFUN_DEBUG=OFF \ -DFUN_WITH_REPL=ON \ -DFUN_WITH_JSON=ON \ -DFUN_WITH_PCRE2=ON \ -DFUN_WITH_CURL=ON \ -DFUN_WITH_PCSC=OFF \ -DFUN_WITH_SQLITE=OFF cmake --build build --target funRun the demo (without installing):
FUN_LIB_DIR="$(pwd)/lib" ./build/fun ./demo.funTracing execution:
FUN_LIB_DIR="$(pwd)/lib" ./build/fun --trace ./demo.funDrop into the REPL when an error occurs:
FUN_LIB_DIR="$(pwd)/lib" ./build/fun --repl-on-error --trace ./demo.funStart the REPL directly (build with -DFUN_WITH_REPL=ON):
FUN_LIB_DIR="$(pwd)/lib" ./build/fun#### CMake options Pass all options as -DNAME=VALUE. The most relevant toggles are: - FUN_DEBUG=ON/OFF - verbose VM debug logging (default OFF) - FUN_WITH_CURL=ON/OFF - enable CURL (libcurl) support (default OFF) - FUN_WITH_JSON=ON/OFF - enable JSON (json-c) support (default OFF) - FUN_WITH_XML2=ON/OFF - enable XML (libxml2) support (default OFF) - FUN_WITH_PCRE2=ON/OFF - enable PCRE2 (Perl-Compatible Regular Expressions) (default OFF) - FUN_WITH_PCSC=ON/OFF - enable PC/SC smart card (PCSC lite) support (default OFF) - FUN_WITH_REPL=ON/OFF - enable the interactive REPL (default OFF) - FUN_WITH_SQLITE=ON/OFF - enable SQLite (sqlite3) support (default OFF) - FUN_WITH_INI=ON/OFF - enable INI (iniparser) support (default OFF) You can also set the default search path for the bundled stdlib with DEFAULT_LIB_DIR:
cmake -S . -B build -DDEFAULT_LIB_DIR="/usr/share/fun/lib" -DFUN_WITH_REPL=ONIf you encounter a CMake error such as: CMake Error: Parse error in command line argument: FUN_WITH_JSON Should be: VAR:type=value It means you passed a -D option without a value. Always use the form -DNAME=VALUE (e.g., -DFUN_WITH_JSON=ON). #### SQLite example (optional feature) SQLite support is optional and disabled by default. To build with it and run the example:
cmake -S . -B build -DFUN_WITH_SQLITE=ON cmake --build build --target fun `sqlite3 ./database.sqlite < ./examples/data/database.sql` FUN_LIB_DIR="$(pwd)/lib" ./build/fun ./examples/sqlite_example.fun#### XML example (optional feature) XML support (via libxml2) is optional and disabled by default. To build with it and run the example:
cmake -S . -B build -DFUN_WITH_XML2=ON cmake --build build --target fun FUN_LIB_DIR="$(pwd)/lib" ./build/fun ./examples/xml_class_example.funAvailable VM builtins when built with -DFUN_WITH_XML2=ON: - xml_parse(text: string) -> doc_handle (int > 0) or 0 on error - xml_root(doc_handle: int) -> node_handle (int > 0) or 0 if missing - xml_name(node_handle: int) -> string (node tag name) - xml_text(node_handle: int) -> string (concatenated text of subtree) Standard library wrapper (lib/io/xml.fun): - class XML - parse(text: string): int (doc handle) - from_file(path: string): int (doc handle) - root(doc: int): int (node handle) - name(node: int): string - text(node: int): string Example Fun code:
include <io/xml.fun><
xml = XML()
doc = xml.from_file("./examples/data/example.xml")
if (doc == 0)
print("Failed to load XML file")
else
root = xml.root(doc)
print(xml.name(root))
print(xml.text(root))
Notes:
- Handles are simple integers managed by the VM; nodes are owned by their document.
- This initial integration focuses on parsing and basic navigation. Attributes, children iteration, and XPath may be added later.
### Install Fun to the OS (optional)
Not recommended during early development, but supported:
sudo cmake --build build --target installAfter installation, FUN_LIB_DIR usually isn’t needed because libs are placed in the system default directory (e.g., /usr/share/fun/lib). ## Usage Run a script:
fun ./demo.fun## Table of contents - Language overview and VM internals - Command line interface and REPL - Core types and operations - Built-ins overview (what the VM provides) - Standard library APIs - io.console - io.process - io.socket - io.thread - utils.datetime - regex - crypt (MD5, SHA-1/256/384/512) - encoding.base64 - arrays, strings, maps helpers (hex, range) - Extra libraries - JSON (via json-c) - CURL (via libcurl) - PCSC (PC/SC smart card) - SQLite (sqlite3) - Examples reference ## Language overview and VM internals Fun compiles .fun source files to bytecode and executes them on a stack-based VM. Functions and methods push/pop their arguments and return values on a value stack. High-level architecture: - Front-end: parses .fun files, handles includes and constant folding, emits bytecode with debug markers (OP_LINE) used by tracing and REPL-on-error. - VM core: runs a loop over opcodes (see src/bytecode.h). Values include numbers (integers), strings, arrays, maps, booleans (1/0), functions, and nil. - Built-ins: I/O, strings, arrays, regex, date/time, OS, networking, threading, and optional JSON/PCRE2/CURL/PCSC/SQLite. Selected VM concepts (non-exhaustive): - Control flow: OP_JUMP, OP_JUMP_IF_FALSE, OP_RETURN - Arithmetic/logic: OP_ADD/SUB/MUL/DIV, OP_MOD, OP_LT/LTE/GT/GTE, OP_EQ/NEQ, OP_AND/OR/NOT - Stack helpers: OP_DUP, OP_SWAP, OP_POP - Arrays: OP_MAKE_ARRAY, OP_INDEX_GET/SET, OP_LEN, OP_PUSH, OP_APOP, OP_INSERT/REMOVE, OP_SLICE - Strings: OP_SUBSTR, OP_SPLIT, OP_JOIN, OP_FIND - Maps: OP_MAKE_MAP; index ops shared with arrays - Conversion/typing: OP_TO_NUMBER, OP_TO_STRING, OP_CAST, OP_TYPEOF, OP_UCLAMP/OP_SCLAMP - Regex: OP_REGEX_MATCH/SEARCH/REPLACE (requires PCRE2 when built) - Math: OP_MIN/MAX/CLAMP/ABS/POW, OP_RANDOM_SEED/RANDOM_INT - Iteration helpers: OP_ENUMERATE, OP_ZIP - OS/IO/network: sockets, files, processes, environment, threads, etc. - Optional features: JSON (src/vm/json/*), CURL, PCSC, SQLite (src/vm/sqlite/*) Error handling and debugging: - Build with FUN_DEBUG=ON for verbose traces - Run with --trace to print executed lines/opcodes - Run with --repl-on-error to drop into an interactive REPL when a runtime error occurs ## Command line interface and REPL - Run a script: fun path/to/script.fun - Common options: --trace, --repl-on-error (can be combined). REPL requires FUN_WITH_REPL=ON at build time. - In trace/repl-on-error modes, the VM annotates output with file:line and function names for easier debugging (see examples/debug_reporting.fun). ## Core types and operations Types: - number: signed integer (with helpers for unsigned behavior) - float: 64-bit IEEE-754 floating point - string: immutable bytes; len(s), join, split, substr, find - array: ordered list; len, push, apop, insert, remove, slice - map: associative dictionary typically keyed by strings - boolean: represented as 1 (true) or 0 (false); operators &&, ||, ! - nil: absence of value Numeric variants: - byte (uint8) - Fixed width ints: int8/16/32/64 and uint8/16/32/64 Control flow: - if/else, while; break, continue; range helpers in utils.range Functions and classes: - Define a function: fun name(args) ... - Define a class: class Name(constructor params) with method definitions fun method(this, ...) - _construct acts as the constructor if present; methods use explicit this Exceptions: - try { ... } catch (e) { ... } finally { ... } - Throwing/catching is defined by the spec; some runtimes may implement handling progressively. Examples: try_catch_finally.fun Modules and includes: - #include
include <io/json.fun>
j = JSON()
data = j.parse('{"name":"Fun","year":2026,"ok":true,"tags":["vm","lang"]}')
print(typeof(data)) // map
print(data["name"])
ok = j.to_file("./tmp/out.json", data, 1) // pretty = 1
print("saved:", ok)
Notes:
- JSON types map to Fun types: object -> map, array -> array, string -> string, number -> number/float, true/false -> 1/0, null -> nil.
- When writing, prettyFlag=1 enables pretty printing.
### cURL (optional)
Build flag: -DFUN_WITH_CURL=ON; requires libcurl.
VM API:
- curl_get(url) -> string (empty string on error)
- curl_post(url, body) -> string (empty string on error)
- curl_download(url, path) -> 1/0
Stdlib wrapper:
- None (call built-ins directly). See examples in examples/extra/.
Example:
url = "https://httpbin.org/get"
resp = curl_get(url)
if (len(resp) == 0)
print("GET failed")
else
print(substr(resp, 0, 60), "...")
Examples:
- curl_get_json.fun, curl_post.fun, curl_download.fun
### PCSC (optional)
Build flag: -DFUN_WITH_PCSC=ON; requires PC/SC (pcsc-lite).
VM API:
- pcsc_establish() -> context id (>0) or 0
- pcsc_list_readers(ctx) -> array of reader names or nil
- pcsc_connect(ctx, readerName) -> handle id (>0) or 0
- pcsc_disconnect(handle) -> 1/0
- pcsc_transmit(handle, bytesArray) -> { data: arrayincludeExamples: - examples/extra/pcsc_example.fun, examples/extra/pcsc_demo.fun Notes: - Smart card operations depend on the reader, card, and drivers installed. Ensure pcscd/service is running. ### SQLite (optional) Build flag: -DFUN_WITH_SQLITE=ON; requires sqlite3 development headers. VM API: - sqlite_open(path) -> handle (>0) or 0 - sqlite_exec(handle, sql) -> rc (0 = SQLITE_OK) - sqlite_query(handle, sql) -> array of maps (columns as string keys) - sqlite_close(handle) -> nil Result mapping notes: - INTEGER -> number - FLOAT -> number (floating point) - TEXT -> string - NULL -> nil - BLOB is currently not returned (mapped to nil) Example flow (examples/sqlite_example.fun): - h = sqlite_open("./todo.sqlite") - rows = sqlite_query(h, "SELECT id, title, done, created_at FROM tasks ORDER BY id;") - rc = sqlite_exec(h, "INSERT INTO tasks (title, done) VALUES ('Try Fun + SQLite', 0);") - rows2 = sqlite_query(h, "SELECT count(*) AS cnt FROM tasks;") - sqlite_close(h) ### INI (optional) Build flag: -DFUN_WITH_INI=ON; requires iniparser (>= 4.2.6). VM API: - ini_load(path) -> handle (>0) or 0 on error - ini_free(handle) -> 1/0 - ini_get_string(handle, section, key, default) -> string - ini_get_int(handle, section, key, defaultNumber) -> number - ini_get_double(handle, section, key, defaultFloat) -> float - ini_get_bool(handle, section, key, defaultBool) -> 1/0 - ini_set(handle, section, key, valueString) -> 1/0 - ini_unset(handle, section, key) -> 1/0 - ini_save(handle, path) -> 1/0 Notes: - Section/key may be looked up flexibly ("section:key" and "section.key"). - Always free handles with ini_free when done. Example:sc = PCSC() ctx = pcsc_establish() if (ctx == 0) print("PCSC not available") else readers = pcsc_list_readers(ctx) if (readers == nil || len(readers) == 0) print("No readers found") else h = pcsc_connect(ctx, readers[0]) if (h) // Example APDU: GET RESPONSE (illustrative only) res = pcsc_transmit(h, [0x00, 0xC0, 0x00, 0x00, 0x00]) print("SW:", res["sw1"], res["sw2"], "code:", res["code"]) pcsc_disconnect(h)
h = ini_load("./examples/data/example.ini")
if (h == 0)
print("Failed to load INI")
else
host = ini_get_string(h, "server", "host", "localhost")
port = ini_get_int(h, "server", "port", 8080)
print("server:", host, port)
ok = ini_set(h, "server", "host", "127.0.0.1")
if (ok)
ini_save(h, "./tmp/updated.ini")
ini_free(h)
### XML (optional)
Build flag: -DFUN_WITH_XML2=ON; requires libxml2.
VM API:
- xml_parse(text) -> doc_handle (>0) or 0 on error
- xml_root(doc_handle) -> node_handle (>0) or 0 if missing
- xml_name(node_handle) -> string
- xml_text(node_handle) -> string
Stdlib wrapper:
- class XML (lib/io/xml.fun)
- parse(text): int
- from_file(path): int
- root(doc): int
- name(node): string
- text(node): string
Example:
includeNotes: - Handles are integers managed by the VM; nodes belong to their document. ### PCRE2 / Regex (optional) Build flag: -DFUN_WITH_PCRE2=ON; requires PCRE2 (8-bit API). VM API: - regex_match(text, pattern) -> 1/0 - regex_search(text, pattern) -> map { match, start, end, groups } - regex_replace(text, pattern, repl) -> string Stdlib wrapper: - class Regex (lib/regex.fun) providing match/search/replace helpers. Examples: regex_demo.fun, regex_procedural.fun Notes: - Patterns use PCRE2 syntax. ### REPL (optional) Build flag: -DFUN_WITH_REPL=ON. Description: - Enables the interactive Read–Eval–Print Loop and the --repl-on-error mode. No additional VM API functions; this feature is part of the executable. ## Examples reference You can run examples without installing by pointing FUN_LIB_DIR to the repository lib directory: `FUN_LIB_DIR="$(pwd)/lib" ./build/fun examples/xml = XML() doc = xml.from_file("./examples/data/example.xml") if (doc == 0) print("Failed to load XML file") else root = xml.root(doc) print(xml.name(root)) print(xml.text(root))