Language Reference

This page documents every feature of the SUB language. For the standard library modules, see the Standard Library page.

Comments

SUB uses # for single-line comments. Everything after # on a line is ignored by the parser.

# This is a comment
let x = 42  # inline comment

Variables

Declare mutable variables with let and immutable bindings with const.

let name = "Alice"     # mutable
const PI = 3.14159     # immutable — reassignment is an error

name = "Bob"           # OK
# PI = 3               # Error: cannot reassign const

Data Types

SUB has seven value types. The type is inferred from the assigned value — there are no type annotations.

TypeExampleNotes
int42, -7Arbitrary-precision integers
float3.14, -0.564-bit IEEE 754 double
string"hello"UTF-8, double-quoted
booltrue, falseLogical values
nullnullAbsence of a value
array[1, 2, 3]Ordered, heterogeneous
object{"key": "value"}Key-value map
let count = 100
let price = 9.99
let greeting = "Hello"
let active = true
let nothing = null
let items = [1, "two", 3.0]
let config = {"debug": true, "level": 5}

Functions

Define functions with the fn keyword. Functions can take parameters and return values with return.

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

fn add(a, b) {
    return a + b
}

println(greet("World"))   # Hello, World!
println(add(3, 4))        # 7

Note: Functions must be defined before they are called. There is no hoisting.

Control Flow

if / elif / else

let score = 85

if score >= 90 {
    println("A")
} elif score >= 80 {
    println("B")
} elif score >= 70 {
    println("C")
} else {
    println("F")
}

for-in loop

Iterate over arrays or ranges.

let fruits = ["apple", "banana", "cherry"]

for fruit in fruits {
    println(fruit)
}

# Using range
for i in range(0, 5) {
    println(i)   # 0, 1, 2, 3, 4
}

while loop

let count = 0
while count < 5 {
    println(count)
    count = count + 1
}

do-while loop

Executes the body at least once before checking the condition.

let x = 10
do {
    println(x)
    x = x - 1
} while x > 0

switch / case / default

Pattern matching over integers, strings, and floats. No fall-through — each case runs its body and exits.

let day = "Monday"

switch day {
    case "Monday":
        println("Start of the week")
    case "Friday":
        println("Almost weekend")
    case "Saturday", "Sunday":
        println("Weekend!")
    default:
        println("Midweek")
}

Classes

SUB supports class-based object-oriented programming. Define classes with class, create instances with .new, and access fields with dot notation.

class Point {
    let x = 0
    let y = 0
}

let p = Point.new
p.x = 10
p.y = 20

println(p.x)   # 10
println(p.y)   # 20

Tip: Classes transpile to idiomatic constructs in every target language — structs in Rust, classes in Java/Python, interfaces in TypeScript.

Error Handling

Use try/catch/finally for error handling and throw to raise errors.

fn divide(a, b) {
    if b == 0 {
        throw "Division by zero"
    }
    return a / b
}

try {
    let result = divide(10, 0)
    println(result)
} catch err {
    println("Error: " + err)
} finally {
    println("Cleanup done")
}

Modules

Import standard library modules or user-defined modules with import.

import math
import arrays
import strings

let result = math.sqrt(144)
println(result)   # 12

let nums = [3, 1, 4, 1, 5]
let total = arrays.sum_int(nums)
println(total)    # 14

Operators

CategoryOperators
Arithmetic+ - * / % **
Comparison== != < > <= >=
Logical&& !
Assignment=
String concat+
let a = 10 + 5      # 15
let b = 10 % 3      # 1
let c = 2 ** 8      # 256
let d = "Hello" + " " + "World"  # "Hello World"
let e = (5 > 3) && (2 != 4)      # true

Built-in Functions

These functions are available globally without importing any module.

I/O

print(value)

Print a value to stdout without a trailing newline.

println(value)

Print a value to stdout followed by a newline.

input(prompt)

Read a line of text from stdin. Displays the optional prompt string.

Type Conversion

str(value)

Convert any value to its string representation.

int(value)

Convert a string or float to an integer.

float(value)

Convert a string or integer to a float.

type(value)

Return the type name of a value as a string: "int", "float", "string", "bool", "null", "array", "object".

Collections

len(value)

Return the length of a string, array, or object.

push(array, value)

Append a value to the end of an array.

pop(array)

Remove and return the last element of an array.

Math

abs(value)

Return the absolute value of a number.

min(a, b)

Return the smaller of two numbers.

max(a, b)

Return the larger of two numbers.

sqrt(value)

Return the square root of a number.

floor(value)

Round a float down to the nearest integer.

ceil(value)

Round a float up to the nearest integer.

round(value)

Round a float to the nearest integer.

String Operations

upper(string)

Return the string with all characters converted to uppercase.

lower(string)

Return the string with all characters converted to lowercase.

trim(string)

Remove leading and trailing whitespace.

split(string, delimiter)

Split a string by a delimiter and return an array of substrings.

join(array, delimiter)

Join an array of strings with a delimiter into a single string.

substring(string, start, end)

Return a portion of the string from index start to end (exclusive).

contains(string, needle)

Return true if the string contains the substring.

replace(string, old, new)

Return a new string with all occurrences of old replaced by new.

char_at(string, index)

Return the character at the given index.

Utility

range(start, end)

Return an array of integers from start (inclusive) to end (exclusive).

Networking

net_fetch(url)

Perform an HTTP GET request and return the response body as a string.

net_post(url, body)

Perform an HTTP POST request with the given body and return the response.

net_download(url, path)

Download the contents of a URL and save them to a local file at path.

UI DSL

SUB includes a first-class declarative UI syntax for building graphical interfaces. UI trees are composed of ui.window, ui.label, ui.button, and other UI primitives.

ui.window {
    title: "My App"
    width: 400
    height: 300

    ui.label {
        text: "Hello, SUB!"
        font_size: 24
    }

    ui.button {
        text: "Click me"
        on_click: fn() {
            println("Button clicked!")
        }
    }
}

Note: The UI DSL is a declarative tree — it describes what the interface looks like, not how to draw it. Different renderers can interpret the same tree for different platforms.

Next Steps