Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Standard Library

The Epitaph standard library provides built-in functions and importable modules for math, time, colors, formatting, JSON, byte manipulation, string utilities, and list operations.

Built-in functions are always available without any import. Modules require access <name> at the top of your script.


Built-in Functions

These are available everywhere, no access needed.

concat(a, b) -> text

Concatenates two values as text. Non-text values are stringified.

concat("hp: ", 100)    -- "hp: 100"

append(list, ...items) -> list

Appends one or more items to a list in place and returns the list.

let items = [1, 2]
append(items, 3, 4)    -- items is now [1, 2, 3, 4]

Errors if the first argument is not a list.

len(collection) -> int

Returns the length of a list, text, map, bytes buffer, or range. Returns 0 for other types.

len([1, 2, 3])         -- 3
len("hello")           -- 5
len(0..10)             -- 10

int_to_text(n) -> text

Converts an integer to its decimal text representation.

int_to_text(42)        -- "42"

math

access <math>

Host-backed module for common math operations.

Functions

FunctionReturnsDescription
math.floor(n)intFloor of n
math.ceil(n)intCeiling of n
math.round(n)intRound n to nearest integer
math.round(n, places)floatRound n to places decimal digits
math.abs(n)int/floatAbsolute value (preserves type if int)
math.clamp(v, lo, hi)int/floatClamp v to [lo, hi] (int if all args are int)
math.sqrt(n)floatSquare root
math.pow(base, exp)floatbase raised to exp
math.sin(n)floatSine (radians)
math.cos(n)floatCosine (radians)
math.atan2(y, x)floatTwo-argument arctangent
math.lerp(a, b, t)floatLinear interpolation: a + (b - a) * t
math.rand(min, max)intRandom integer in [min, max] inclusive
math.rand_float()floatRandom float in [0, 1)

Constants

NameValue
math.PI3.14159265…
math.TAU6.28318530…

Examples

access <math>

let angle = math.atan2(dy, dx)
let dist = math.sqrt(dx * dx + dy * dy)
let clamped = math.clamp(hp, 0, max_hp)
let roll = math.rand(1, 6)

time

access <time>

Host-backed module for elapsed time queries.

FunctionReturnsDescription
time.now()floatSeconds elapsed since engine start
time.ms()intMilliseconds elapsed since engine start

Example

access <time>

phase tick(dt) {
    let elapsed = time.now()
    when elapsed > 5.0 {
        log.info("Five seconds have passed")
    }
}

color

access <color>

Host-backed module for creating and using color records.

Functions

FunctionReturnsDescription
color.rgb(r, g, b)recordColor with alpha 255. Args default to 0 if missing.
color.rgba(r, g, b, a)recordColor with explicit alpha. a defaults to 255.
color.hex(s)recordParse a CSS-style hex string into the same Color record.

color.hex accepts:

  • #RRGGBB or RRGGBB — alpha 255
  • #RRGGBBAA or RRGGBBAA — includes alpha
  • #RGB or RGB — each digit is expanded (e.g. #f0a → red 255, green 0, blue 170)
  • #RGBA or RGBA — short form with alpha

Leading # is optional; surrounding whitespace is trimmed. Invalid length or digits produce a runtime error.

All constructors return a Color record with fields r, g, b, a (all ints, 0–255).

Preset Colors

NameRGBA
color.White255, 255, 255, 255
color.Black0, 0, 0, 255
color.Red255, 0, 0, 255
color.Green0, 255, 0, 255
color.Blue0, 0, 255, 255
color.Yellow255, 255, 0, 255
color.Cyan0, 255, 255, 255
color.Magenta255, 0, 255, 255
color.Transparent0, 0, 0, 0

Example

access <color>
access <gfx>

let sky = color.rgb(100, 149, 237)
gfx.fill_screen(sky)

let same_sky = color.hex("#6495ed")
gfx.fill_screen(same_sky)

let semi = color.rgba(255, 0, 0, 128)
gfx.fill_rect(10, 10, 50, 50, semi)

let semi_hex = color.hex("#ff000080")
gfx.fill_rect(60, 10, 50, 50, semi_hex)

fmt

access <fmt>

Host-backed module for text formatting.

Functions

FunctionReturnsDescription
fmt.str(v)textConvert any value to text. Text passes through; others are stringified.
fmt.join(items, sep?)textJoin a list into text with sep (default ""). Non-list → empty text.
fmt.format(template, ...args)textReplace {} placeholders with args in order.

Examples

access <fmt>

fmt.str(42)                          -- "42"
fmt.join(["a", "b", "c"], ", ")      -- "a, b, c"
fmt.format("HP: {}/{}", hp, max_hp)  -- "HP: 80/100"

Extra {} placeholders with no matching argument are left as literal {}.


json

access <json>

Host-backed module for JSON encoding and decoding.

Functions

FunctionReturnsDescription
json.decode(text)valueParse JSON text into an Epitaph value. Returns void on error.
json.encode(value)textCompact JSON string.
json.encode_pretty(value)textPretty-printed JSON string.

Type mapping

EpitaphJSON
int, floatnumber
boolboolean
textstring
voidnull
listarray
map, recordobject
symbolstring (:id format)
bytesarray of ints
range[start, end]

Example

access <json>

let data = json.decode("{\"name\": \"Kite\", \"level\": 5}")
let name = data["name"]       -- "Kite"

let out = json.encode({"hp": 100, "items": [1, 2, 3]})

string

access <string>

Pure Epitaph module for string utilities.

FunctionReturnsDescription
string.pad_left(s, width, ch)textLeft-pad s to width with character ch
string.pad_right(s, width, ch)textRight-pad s to width with character ch
string.repeat(s, count)textRepeat s count times

Examples

access <string>

string.pad_left("42", 5, "0")    -- "00042"
string.pad_right("hi", 10, ".")  -- "hi........"
string.repeat("ab", 3)           -- "ababab"

list

access <list>

Pure Epitaph module for list utilities.

FunctionReturnsDescription
list.contains(items, target)boolactive if target is in items
list.reverse(items)listNew list with elements in reverse order

Examples

access <list>

list.contains([1, 2, 3], 2)     -- active
list.contains([1, 2, 3], 9)     -- dormant
list.reverse([1, 2, 3])         -- [3, 2, 1]

vec

access <vec>

Pure Epitaph 2D / 3D vectors (fragment Vec2, fragment Vec3 with float x, y, z). After importing, build values with the module helpers (not Vec2(x, y) from another sector — that sugar only applies in the same file as the fragment):

FunctionReturnsDescription
vec.vec2(x, y)Vec2New vector
vec.vec3(x, y, z)Vec3New vector

Instance / static methods (same naming as other fragments):

CallReturnsDescription
u.add(v) / Vec2.add(u, v)Vec2 / Vec3Component-wise add
u.sub(v)Vec2 / Vec3Component-wise subtract
u.scale(s)Vec2 / Vec3Multiply each component by s
u.dot(v)numDot product
u.len_sq()numSquared Euclidean length
u.cross(v) (Vec3 only)Vec3Cross product

Examples

access <vec>

let u = vec.vec2(3.0, 4.0)
let v = vec.vec2(1.0, 0.0)
let w = Vec2.add(u, v)       -- static call; same-sector code can use u.add(v)
let d = u.x + u.y            -- 7.0

bytes

access <bytes>

Host-backed module for creating and manipulating binary data. Provides buffer constructors, slicing, encoding/decoding, and structured reader/writer APIs.

Buffer Creation

FunctionReturnsDescription
bytes.new(size)bytesZero-filled buffer of size bytes. Default 0.
bytes.from_list(list)bytesBuffer from a list of ints (each truncated to u8)
bytes.to_list(buf)listList of ints, one per byte
bytes.slice(buf, start?, end?)bytesSub-buffer. Bounds are clamped. Defaults: start=0, end=len.
bytes.from_text(text)bytesUTF-8 encoded bytes
bytes.to_text(buf)textDecode UTF-8. Errors if bytes are not valid UTF-8.

Examples

access <bytes>

let buf = bytes.new(4)
buf[0] = 72                         -- 'H'
buf[1] = 105                        -- 'i'

let greeting = bytes.from_text("Hello")
let back = bytes.to_text(greeting)   -- "Hello"

let nums = bytes.from_list([10, 20, 30])
let mid = bytes.slice(nums, 1, 3)   -- [20, 30]

ByteReader

A cursor-based reader for structured binary data. Reads advance the position automatically.

Creating a Reader

let reader = bytes.reader(buf)

Returns a record with fields buf (the byte buffer) and pos (current read position, starts at 0).

Read Functions

All read functions take the reader as the first argument and advance pos. Functions with a _le suffix read in little-endian byte order. Without a suffix, the default is big-endian.

FunctionReturnsDescription
bytes.read_u8(r)intRead 1 byte (0–255)
bytes.read_i16(r)intRead signed 16-bit integer (big-endian)
bytes.read_i16_le(r)intRead signed 16-bit integer (little-endian)
bytes.read_i32(r)intRead signed 32-bit integer (big-endian)
bytes.read_i32_le(r)intRead signed 32-bit integer (little-endian)
bytes.read_i64(r)intRead signed 64-bit integer (big-endian)
bytes.read_i64_le(r)intRead signed 64-bit integer (little-endian)
bytes.read_f32(r)floatRead 32-bit float (big-endian)
bytes.read_f32_le(r)floatRead 32-bit float (little-endian)
bytes.read_f64(r)floatRead 64-bit float (big-endian)
bytes.read_f64_le(r)floatRead 64-bit float (little-endian)
bytes.read_bytes(r, n)bytesRead n raw bytes
bytes.read_text(r, n)textRead n bytes as UTF-8 text
bytes.remaining(r)intBytes left to read

Reads error at runtime if there aren’t enough bytes remaining.

Example

access <bytes>

let data = bytes.from_list([0, 42, 0, 1, 0, 100])
let r = bytes.reader(data)

let header = bytes.read_u8(r)       -- 0
let id = bytes.read_u8(r)           -- 42
let value = bytes.read_i32(r)       -- 65636 (big-endian)
let left = bytes.remaining(r)       -- 0

ByteWriter

A growable buffer writer for building binary data.

Creating a Writer

let writer = bytes.writer()

Returns a record with a buf field (initially empty bytes buffer).

Write Functions

All write functions take the writer as the first argument and append bytes. Functions with a _le suffix write in little-endian byte order. Without a suffix, the default is big-endian.

FunctionArgsDescription
bytes.write_u8(w, val)intWrite 1 byte (truncated to u8)
bytes.write_i16(w, val)intWrite signed 16-bit (big-endian)
bytes.write_i16_le(w, val)intWrite signed 16-bit (little-endian)
bytes.write_i32(w, val)intWrite signed 32-bit (big-endian)
bytes.write_i32_le(w, val)intWrite signed 32-bit (little-endian)
bytes.write_i64(w, val)intWrite signed 64-bit (big-endian)
bytes.write_i64_le(w, val)intWrite signed 64-bit (little-endian)
bytes.write_f32(w, val)floatWrite 32-bit float (big-endian)
bytes.write_f32_le(w, val)floatWrite 32-bit float (little-endian)
bytes.write_f64(w, val)floatWrite 64-bit float (big-endian)
bytes.write_f64_le(w, val)floatWrite 64-bit float (little-endian)
bytes.write_bytes(w, src)bytesAppend raw bytes
bytes.write_text(w, text)textAppend UTF-8 bytes

All write functions return void.

Example

access <bytes>

let w = bytes.writer()
bytes.write_u8(w, 0x01)
bytes.write_i32(w, 1000)
bytes.write_text(w, "OK")

let result = w.buf               -- the built buffer
let size = result.len             -- 7 (1 + 4 + 2)

Roundtrip Example

access <bytes>

-- Write structured data
let w = bytes.writer()
bytes.write_u8(w, 1)             -- version
bytes.write_i32(w, 320)          -- width
bytes.write_i32(w, 240)          -- height
bytes.write_text(w, "hello")     -- payload

-- Read it back
let r = bytes.reader(w.buf)
let version = bytes.read_u8(r)   -- 1
let width = bytes.read_i32(r)    -- 320
let height = bytes.read_i32(r)   -- 240
let payload = bytes.read_text(r, 5)  -- "hello"