Language Guide

Everything you need to start programming in Zym. This guide covers the basics — variables, types, operators, control flow, functions, and more — with brief examples for each feature. For deeper exploration, each section links to a dedicated page with full documentation and edge cases.

Variables

Variables are declared with var. Zym is dynamically typed — any variable can hold any value.

variables
var name = "Zym"
var version = 1
var active = true
var nothing = null

Multiple variables can be declared on a single line:

multi-var
var x = 1, y = 2, z = 3

Types

Zym has the following built-in types:

TypeExamples
number42, 3.14, -7, 1e10
string"hello", "café"
booleantrue, false
nullnull
list[1, 2, 3]
map{ name: "Alice", age: 30 }
structUser-defined compound types
enumUser-defined enumeration types
functionNamed, anonymous, and arrow functions

Number literals

Numbers support decimal, hexadecimal, and binary literals. Underscores can be used as separators for readability.

number formats
// Decimal
var a = 42
var b = 3.14
var c = 1e10

// Hexadecimal (0x prefix)
var hex = 0xFF        // 255
var hex2 = 0xABCD     // 43981

// Binary (0b prefix)
var bin = 0b1010      // 10
var bin2 = 0b11111111 // 255

// Underscore separators (ignored by parser)
var large = 1_000_000      // 1000000
var hexSep = 0xAB_CD       // 43981
var binSep = 0b1111_0000   // 240

Operators

Arithmetic

10 + 3     // 13
10 - 3     // 7
10 * 3     // 30
10 / 3     // 3.333...
10 % 3     // 1

Comparison

x == y     // equal
x != y     // not equal
x < y      // less than
x > y      // greater than
x <= y     // less or equal
x >= y     // greater or equal

Logical

a and b     // logical AND
a or b      // logical OR
!a          // logical NOT

String concatenation

"hello" + " world"   // "hello world"

Truthiness

Zym’s truthiness rules for conditional expressions:

TypeTruthyFalsy
booltruefalse
nullalways falsy
numbernon-zero0
all othersalways truthy

Strings, lists, maps, structs, and functions are always truthy — even empty ones.

Semicolons

Semicolons are optional. You may use them or omit them — Zym handles both styles.

var a = 1
var b = 2;
var c = a + b

Control Flow

Zym provides the standard control flow constructs you’d expect. Conditions must be wrapped in parentheses and bodies in braces.

conditionals
if (x > 0) {
    print("positive")
} else if (x == 0) {
    print("zero")
} else {
    print("negative")
}
loops
// while loop
while (x > 0) {
    x = x - 1
}

// do-while — always runs at least once
do {
    x = x + 1
} while (x < 10)

// for loop
for (var i = 0; i < 10; i = i + 1) {
    print(i)
}
switch
switch (value) {
    case 1:
        print("one")
        break
    case 2:
        print("two")    // falls through to case 3
    case 3:
        print("two or three")
        break
    default:
        print("other")
}

Cases fall through by default — use break to exit. Each case can have its own block scope with braces.

Loops support break to exit early and continue to skip to the next iteration. Zym also has goto — a safe jump that performs proper cleanup before transferring control.

goto
goto skip
x = 999       // never reached
skip:
x = x + 1    // execution continues here

Full details: Control Flow — nested loops, outward scope jumps, state machines, jump tables, and more.

Functions

Functions are declared with func. They are first-class values — you can store them in variables, pass them as arguments, and return them from other functions.

functions
// Named function
func add(a, b) {
    return a + b
}

// Arrow function
var double = (x) => x * 2

// Anonymous function
var greet = func(name) {
    return "Hello, " + name
}

Functions are hoisted — you can call a function before its declaration in the same scope. Zym also supports overloading by arity (number of parameters):

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

greet()          // "Hello!"
greet("Zym")    // "Hello, Zym"

Full details: Functions — closures, dispatchers, shared/independent closure state, and more.

Structs & Enums

Structs are user-defined compound types with named fields. Enums are fixed sets of named variants with type-safe comparison.

structs
struct Point { x; y }

var p = Point(10, 20)    // positional init
p.x                      // 10
p.y = 30                 // field mutation
enums
enum Color { RED, GREEN, BLUE }

var c = Color.RED
c == Color.RED     // true
c == Color.BLUE    // false

Full details: Structs & Enums — named init, nested structs, spread, schema scope hoisting, enum scoping, and more.

Memory Semantics

Zym gives you explicit control over how values pass between scopes with four keywords:

KeywordWhat it does
refCreates an alias — writes go through to the original
valDeep-copies the value (but refs keep the same target)
slotBinds to the variable slot — can rebind refs
cloneTrue isolation — deep-copies both value and any refs
memory basics
var x = 42
var r = ref x       // r is an alias for x
r = 100              // x is now 100

func safe(val data) {
    data[0] = 999    // local copy — caller unchanged
}

var copy = clone x  // fully independent copy

Full details: Memory Semantics — ref flattening, val vs clone with references, slot rebinding, and more.

Spread Operator

The spread operator (...) expands a list, map, or struct inline. It’s useful for combining collections and creating modified copies.

spread
var a = [1, 2]
var b = [3, 4]
var combined = [...a, ...b]   // [1, 2, 3, 4]

var defaults = { color: "red", size: 10 }
var custom = { ...defaults, size: 20 }  // override size

var p2 = Point{...p1, .y = 99}  // struct spread with override

Full details: Spread Operator — override ordering, nested spread, function argument spreading, and more.

Tail-Call Optimization

Zym supports opt-in tail-call optimization via the @tco directive. This lets recursive functions run in constant stack space, enabling deep recursion without overflow.

TCO
@tco aggressive

func factorial(n, acc) {
    if (n <= 1) return acc
    return factorial(n - 1, n * acc)
}

factorial(100000, 1)  // no stack overflow

Three active modes: aggressive (any tail call), safe (compile-time verified only), and smart (compile-time first, runtime fallback). Use off to disable for debugging.

Full details: Tail-Call Optimization — mode comparison, mutual recursion, accordion patterns, closures with TCO, and more.

Collections

Zym has two built-in collection types: lists (ordered, indexed) and maps (key-value pairs).

collections
// Lists
var nums = [1, 2, 3]
nums[0]              // 1
push(nums, 4)        // [1, 2, 3, 4]
length(nums)          // 4

// Maps
var user = { name: "Alice", age: 30 }
user["name"]         // "Alice"
user.age              // 30

→ See the List API and Map API for all available functions.

Macros & Preprocessor

Zym includes a built-in preprocessor that runs before compilation. Use #define to create compile-time constants, function-like macros, and multi-line block macros. Conditional compilation directives (#if, #ifdef, #ifndef) let you include or exclude code based on configuration.

macros
#define MAX_SIZE 100
#define SQUARE(x) x * x

var arr = [null] * MAX_SIZE
var result = SQUARE(5)   // expands to: 5 * 5

#ifdef DEBUG
    print("Debug mode")
#endif

Full details: Macros & Preprocessor — block macros, conditional compilation, expression evaluation, common patterns, and more.

Modules

Zym’s module system lets you split code across files. Use import("path") to load a module. Modules are cached by default — every import of the same file returns the same instance, sharing state automatically. Use the "use fresh" directive to opt out.

modules
// math_utils.zym
func add(a, b) { return a + b }
return { add }

// main.zym
var math = import("math_utils.zym")
print(math.add(2, 3))   // 5

Full details: Modules — caching, "use fresh", named imports, path resolution, circular detection, and common patterns.

Deep Dive

Each language feature above has its own dedicated page with comprehensive documentation, examples, and edge cases:

TopicWhat’s Covered
Control Flow if/else, while, do-while, for loops, switch statements, break & continue, goto/labels, state machines, jump tables
Functions Named functions, hoisting, overloading by arity, anonymous functions, arrow syntax, closures, dispatchers
Memory Semantics ref (aliasing), val (deep copy), slot (rebinding), clone (true isolation), ref flattening
Structs & Enums Struct declaration, positional/named init, field mutation, nested structs, schema hoisting; enum variants, type safety, scoping
Tail-Call Optimization @tco directive, modes (aggressive/safe/smart/off), mutual recursion, accordion & shattered patterns
Spread Operator List spread, map spread, struct spread, override ordering, function argument spreading
Macros & Preprocessor #define macros, function-like macros, block macros (##define), conditional compilation, #if/#ifdef/#ifndef, expression evaluation
Modules import("path"), module caching, "use fresh" directive, named imports, path resolution, circular detection