Examples
Faber code examples from the exempla/ directory, organized by feature category.
adfirma
in-functio
# Assertions in functions for preconditions and postconditions
#
# adfirma <condition>
# adfirma <condition>, "error message"
# Precondition: validate input at function start
functio divide(numerus a, numerus b) fit numerus {
adfirma b != 0, "divisor must not be zero"
redde a / b
}
# Multiple preconditions
functio calculateAge(numerus birthYear, numerus currentYear) fit numerus {
adfirma birthYear > 0, "birth year must be positive"
adfirma currentYear >= birthYear, "current year must be >= birth year"
redde currentYear - birthYear
}
# Postcondition: validate result before returning
functio absoluteValue(numerus n) fit numerus {
varia result = n
si n < 0 {
result = -n
}
adfirma result >= 0, "result must be non-negative"
redde result
}
incipit {
fixum quotient = divide(20, 4)
adfirma quotient == 5
fixum age = calculateAge(1990, 2024)
adfirma age == 34
fixum abs = absoluteValue(-42)
adfirma abs == 42
}
basic
# Basic adfirma (assert) statements
#
# adfirma <condition>
# adfirma <condition>, "error message"
incipit {
fixum x = 10
# Simple assertion without message
adfirma x > 0
# Assertion with custom error message
adfirma x == 10, "x must equal 10"
# Multiple assertions
fixum name = "Marcus"
adfirma name == "Marcus"
adfirma name != "", "name must not be empty"
# Boolean assertions
fixum active = verum
adfirma active
adfirma active == verum, "must be active"
}
cura
nested
# Nested allocator scopes
#
# cura arena fit <outer> { cura arena fit <inner> { } }
#
# Allocator scopes can nest. Inner scopes free before outer scopes.
incipit {
cura arena fit outer {
varia textus[] a = ["one"]
cura arena fit inner {
varia textus[] b = ["two"]
scribe "Inner:", b
}
# inner freed here
a.adde("three")
scribe "Outer:", a
}
# outer freed here
}
arena
# Arena allocator scope
#
# cura arena fit <identifier> { <body> }
#
# Arena allocators provide fast allocation with bulk deallocation.
# All memory is freed when the scope exits.
# On GC targets (TS, Python), allocator blocks are ignored.
incipit {
cura arena fit mem {
# All allocations in this block use the arena
varia textus[] items = ["hello", "world"]
scribe items
}
# Arena freed, all allocations released
# Page allocator variant
cura page fit pageMem {
scribe "Using page allocator"
}
}
custodi
basic
# Basic custodi (guard clause) statement
#
# custodi { si <condition> { <early-return> } }
#
# Groups early-exit checks at function start to separate
# validation from main logic.
functio divide(a, b) -> numerus {
custodi {
si b == 0 {
redde 0
}
}
redde a / b
}
functio processValue(x) -> numerus {
custodi {
si x < 0 {
redde -1
}
si x > 100 {
redde -1
}
}
# Main logic, clearly separated from guards
redde x * 2
}
functio clamp(value, min, max) -> numerus {
custodi {
si value < min {
redde min
}
si value > max {
redde max
}
}
redde value
}
incipit {
scribe divide(10, 2)
scribe divide(10, 0)
scribe processValue(50)
scribe processValue(-10)
scribe processValue(150)
scribe clamp(5, 0, 10)
scribe clamp(-5, 0, 10)
scribe clamp(15, 0, 10)
}
validation
# Input validation patterns with custodi
#
# Use custodi to group related precondition checks.
# Each guard should return early or throw on invalid input.
functio processAge(age) -> textus {
custodi {
si age < 0 {
redde "Invalid: negative age"
}
si age > 150 {
redde "Invalid: age too high"
}
}
si age < 18 {
redde "Minor"
}
secus {
redde "Adult"
}
}
functio createUser(name, email, age, curator alloc) -> textus {
custodi {
si name == nihil aut name == "" {
redde "Error: name required"
}
si email == nihil aut email == "" {
redde "Error: email required"
}
si age < 13 {
redde "Error: must be 13 or older"
}
si age > 120 {
redde "Error: invalid age"
}
}
redde scriptum("User created: §", name)
}
# Guards can throw instead of returning
functio sqrt(n) -> numerus {
custodi {
si n < 0 {
iace "Cannot compute square root of negative number"
}
}
redde n
}
incipit ergo cura arena {
scribe processAge(-5)
scribe processAge(200)
scribe processAge(25)
scribe processAge(12)
scribe createUser("Marcus", "marcus@roma.com", 30)
scribe createUser("", "test@test.com", 25)
scribe createUser("Julia", "julia@roma.com", 10)
scribe sqrt(16)
}
de-pro
basic
# Basic de...pro (for-in) key iteration
#
# de <object> pro <key> { <body> }
# de <array> pro <index> { <body> }
incipit ergo cura arena {
# Iterate over object keys
fixum persona = { nomen: "Marcus", aetas: 30, urbs: "Roma" }
de persona pro clavis {
scribe clavis
}
# Access values using the key
de persona pro clavis {
scribe scriptum("§: §", clavis, persona[clavis])
}
# Iterate over array indices
fixum numeri = [10, 20, 30]
de numeri pro index {
scribe scriptum("Index §: §", index, numeri[index])
}
# One-liner form with ergo
fixum data = { alpha: 1, beta: 2 }
de data pro k ergo scribe k
}
destructure
array
# Array destructuring patterns
#
# fixum [a, b, c] = array -- destructure into immutable bindings
# varia [x, y, z] = array -- destructure into mutable bindings
# fixum [first, ceteri rest] = arr -- with rest pattern
# fixum [_, second, _] = arr -- skip elements with underscore
incipit {
# Basic array destructuring
fixum numbers = [1, 2, 3]
fixum [a, b, c] = numbers
scribe a
scribe b
scribe c
# Destructure inline array literal
fixum [first, second, third] = [10, 20, 30]
scribe first
scribe second
scribe third
# Mutable destructuring with varia
fixum coords = [100, 200]
varia [x, y] = coords
scribe x
scribe y
x = x + 50
y = y + 50
scribe x
scribe y
# Partial destructuring (fewer variables than elements)
fixum values = [1, 2, 3, 4, 5]
fixum [one, two] = values
scribe one
scribe two
# Rest pattern with ceteri
fixum items = [1, 2, 3, 4, 5]
fixum [head, ceteri tail] = items
scribe head
scribe tail
# Skip elements with underscore
fixum triple = [10, 20, 30]
fixum [_, middle, _] = triple
scribe middle
# Nested arrays
fixum matrix = [[1, 2], [3, 4]]
fixum [row1, row2] = matrix
scribe row1
scribe row2
}
object
# Object destructuring patterns
#
# ex obj fixum field1, field2 -- extract fields into immutable bindings
# ex obj varia field1, field2 -- extract into mutable bindings
# ex obj fixum field ut alias -- extract with alias (rename)
# ex obj fixum field, ceteri rest -- extract with rest pattern
incipit {
# Basic field extraction
fixum person = { name: "Marcus", age: 30, city: "Roma" }
ex person fixum name, age
scribe name
scribe age
# Extract with alias using 'ut'
fixum user = { name: "Julia", email: "julia@roma.com" }
ex user fixum name ut userName, email ut userEmail
scribe userName
scribe userEmail
# Mutable destructuring with varia
fixum data = { count: 100, active: verum }
ex data varia count, active
scribe count
scribe active
count = 200
active = falsum
scribe count
scribe active
# Mixed alias and regular fields
fixum config = { host: "localhost", port: 8080, secure: verum }
ex config fixum host, port ut serverPort, secure
scribe host
scribe serverPort
scribe secure
# Rest pattern with ceteri
fixum fullUser = { id: 1, name: "Gaius", email: "g@roma.com", role: "admin" }
ex fullUser fixum id, ceteri details
scribe id
scribe details
# Destructure from nested access
fixum response = { data: { user: { name: "Claudia", verified: verum } } }
ex response.data.user fixum name ut nestedName, verified
scribe nestedName
scribe verified
# Single field extraction
fixum settings = { theme: "dark", lang: "la" }
ex settings fixum theme
scribe theme
}
discerne
basic
# Pattern matching with discerne (discriminate/distinguish)
#
# discerne <value> {
# casu <Variant> { <body> }
# casu <Variant> ut <alias> { <body> }
# casu <Variant> pro <bindings> { <body> }
# }
# Define discretio (tagged union) types
discretio Status {
Active,
Inactive,
Pending
}
discretio Event {
Click { numerus x, numerus y },
Keypress { textus key },
Quit
}
# Functions demonstrating discerne
functio describe_status(Status s) -> textus {
discerne s {
casu Active { redde "active" }
casu Inactive { redde "inactive" }
casu Pending { redde "pending" }
}
}
functio handle_event(Event e) -> nihil {
discerne e {
casu Click pro x, y {
scribe scriptum("Clicked at §, §", x, y)
}
casu Keypress pro key {
scribe scriptum("Key: §", key)
}
casu Quit {
scribe "quit"
}
}
}
incipit {
scribe "discerne patterns defined"
}
discretio
basic
# Basic discretio (discriminated union/tagged union)
#
# discretio Name {
# Variant1 { type field1, type field2 }
# Variant2 { type field }
# Variant3
# }
# Discretio with payload variants
discretio Result {
Success { textus message }
Failure { textus error }
}
# Discretio with mixed unit and payload variants
discretio Event {
Click { numerus x, numerus y }
Keypress { textus key }
Quit
}
# Discretio with many fields per variant
discretio Shape {
Rectangle { numerus x, numerus y, numerus width, numerus height }
Circle { numerus cx, numerus cy, numerus radius }
Point { numerus x, numerus y }
}
incipit {
scribe "Discretio types defined"
}
dum
in-functio
# While loops inside functions
functio factorial(numerus n) -> numerus {
varia numerus result = 1
varia numerus current = n
dum current > 1 {
result = result * current
current = current - 1
}
redde result
}
functio nextPowerOf2(numerus n) -> numerus {
varia numerus power = 1
dum power <= n {
power = power * 2
}
redde power
}
incipit {
scribe "5! =", factorial(5)
scribe "10! =", factorial(10)
scribe "Next power of 2 after 100:", nextPowerOf2(100)
scribe "Next power of 2 after 1000:", nextPowerOf2(1000)
}
basic
# Basic dum (while) loop with counter
#
# dum <condition> { <body> }
incipit {
varia numerus counter = 0
dum counter < 5 {
scribe counter
counter = counter + 1
}
# Countdown example
varia numerus countdown = 3
dum countdown > 0 {
scribe "Countdown:", countdown
countdown = countdown - 1
}
scribe "Done!"
}
complex-condition
# Dum with compound conditions
#
# dum <cond1> et <cond2> { } -- both must be true
# dum <cond1> aut <cond2> { } -- either must be true
incipit {
# Using "et" (and) - loop while running AND attempts < limit
varia bivalens running = verum
varia numerus attempts = 0
dum running et attempts < 5 {
scribe "Attempt:", attempts
attempts = attempts + 1
si attempts >= 3 {
running = falsum
}
}
# Using "aut" (or) - loop while either condition holds
varia numerus a = 5
varia numerus b = 3
dum a > 0 aut b > 0 {
scribe "a:", a, "b:", b
a = a - 1
b = b - 1
}
}
elige
in-functio
# Elige with early returns in functions
#
# elige <expr> {
# casu <value> { redde ... }
# casu <value> { redde ... }
# ceterum { redde ... }
# }
functio getGreeting(textus language) fit textus {
elige language {
casu "latin" {
redde "Salve"
}
casu "english" {
redde "Hello"
}
casu "spanish" {
redde "Hola"
}
casu "french" {
redde "Bonjour"
}
}
redde "Hi"
}
functio getHttpMessage(numerus code) fit textus {
elige code {
casu 200 {
redde "OK"
}
casu 201 {
redde "Created"
}
casu 400 {
redde "Bad Request"
}
casu 404 {
redde "Not Found"
}
casu 500 {
redde "Internal Server Error"
}
}
redde "Unknown"
}
incipit {
scribe getGreeting("latin")
scribe getGreeting("spanish")
scribe getGreeting("unknown")
scribe getHttpMessage(200)
scribe getHttpMessage(404)
scribe getHttpMessage(999)
}
with-aliter
# Elige with default case (ceterum)
#
# elige <expr> {
# casu <value> { <body> }
# ceterum { <default> }
# }
incipit ergo cura arena {
# ceterum handles unmatched cases
fixum day = "wednesday"
elige day {
casu "monday" {
scribe "Start of week"
}
casu "friday" {
scribe "End of week"
}
ceterum {
scribe "Midweek"
}
}
# ceterum with error handling
fixum command = "unknown"
elige command {
casu "start" {
scribe "Starting..."
}
casu "stop" {
scribe "Stopping..."
}
casu "restart" {
scribe "Restarting..."
}
ceterum {
scribe "Unknown command"
}
}
# Multiple statements in ceterum
fixum level = 99
elige level {
casu 1 {
scribe "Beginner"
}
casu 2 {
scribe "Intermediate"
}
casu 3 {
scribe "Advanced"
}
ceterum {
scribe "Custom level"
scribe scriptum("Level: §", level)
}
}
}
with-reddit
# Elige with reddit syntax
#
# 'reddit' is syntactic sugar for 'ergo redde' - a one-liner return.
# Use it when each case simply returns a value.
#
# casu <value> reddit <expression>
# ceterum reddit <expression>
# HTTP status code lookup using reddit
functio getStatusText(numerus code) -> textus {
elige code {
casu 200 reddit "OK"
casu 201 reddit "Created"
casu 204 reddit "No Content"
casu 400 reddit "Bad Request"
casu 401 reddit "Unauthorized"
casu 403 reddit "Forbidden"
casu 404 reddit "Not Found"
casu 500 reddit "Internal Server Error"
casu 502 reddit "Bad Gateway"
casu 503 reddit "Service Unavailable"
ceterum reddit "Unknown Status"
}
}
# Type mapping using reddit
functio getTypeCode(textus name) -> numerus {
elige name {
casu "textus" reddit 1
casu "numerus" reddit 2
casu "fractus" reddit 3
casu "bivalens" reddit 4
ceterum reddit 0
}
}
# Mixed reddit and blocks
# Use reddit for simple returns, blocks for complex logic
functio processCode(numerus code) -> textus {
elige code {
casu 1 reddit "simple"
casu 2 {
scribe "Processing code 2..."
redde "complex"
}
casu 3 reddit "also simple"
ceterum reddit "default"
}
}
incipit {
scribe getStatusText(200) # OK
scribe getStatusText(404) # Not Found
scribe getStatusText(999) # Unknown Status
scribe getTypeCode("textus") # 1
scribe getTypeCode("unknown") # 0
scribe processCode(1) # simple
scribe processCode(2) # Processing code 2... complex
}
basic
# Basic elige (switch) statement
#
# elige <expr> {
# casu <value> { <body> }
# casu <value> { <body> }
# ceterum { <body> }
# }
incipit {
# String matching
fixum status = "active"
elige status {
casu "pending" {
scribe "Waiting..."
}
casu "active" {
scribe "Running"
}
casu "done" {
scribe "Completed"
}
}
# Number matching
fixum code = 200
elige code {
casu 200 {
scribe "OK"
}
casu 404 {
scribe "Not Found"
}
casu 500 {
scribe "Server Error"
}
}
# Multiple statements per case
fixum mode = "production"
elige mode {
casu "development" {
scribe "Dev mode enabled"
scribe "Verbose logging on"
}
casu "production" {
scribe "Production mode"
scribe "Optimizations enabled"
}
}
}
ex
nested
# Nested ex...pro loops
incipit {
# Nested array iteration
fixum rows = [1, 2, 3]
fixum cols = ["A", "B", "C"]
ex rows pro row {
ex cols pro col {
scribe row, col
}
}
# Multiplication table
ex 1..4 pro i {
ex 1..4 pro j {
scribe i, "*", j, "=", i * j
}
}
# Nested ranges
ex 0..3 pro x {
ex 0..3 pro y {
scribe x, y
}
}
}
in-functio
# Using ex...pro inside functions
# Sum all numbers in an array
functio sumArray(numerus[] nums) -> numerus {
varia numerus total = 0
ex nums pro n {
total = total + n
}
redde total
}
# Find the maximum value
functio maxValue(numerus[] nums) -> numerus {
varia numerus max = nums[0]
ex nums pro n {
si n > max {
max = n
}
}
redde max
}
# Count items matching a condition
functio countAbove(numerus[] nums, numerus threshold) -> numerus {
varia numerus count = 0
ex nums pro n {
si n > threshold {
count = count + 1
}
}
redde count
}
incipit {
fixum numbers = [1, 2, 3, 4, 5]
scribe sumArray(numbers)
scribe maxValue(numbers)
scribe countAbove(numbers, 3)
scribe sumArray([10, 20, 30])
scribe maxValue([5, 12, 8, 20, 3])
}
array
# Iterating over arrays with ex...pro
#
# ex <collection> pro <item> { <body> }
incipit {
# Iterate over number array
fixum numbers = [1, 2, 3, 4, 5]
ex numbers pro n {
scribe n
}
# Iterate over string array
fixum names = ["Marcus", "Julia", "Claudia"]
ex names pro name {
scribe name
}
# Process items
fixum values = [10, 20, 30]
ex values pro v {
fixum doubled = v * 2
scribe doubled
}
}
fiunt-iteration
# Iterating over fiunt/fient function returns with ex...pro
#
# This demonstrates that fiunt/fient functions produce iterable results
# that can be consumed with ex...pro loops
# Multi-value sync function that yields values via cede
functio rangeSync(numerus n) fiunt numerus {
ex 0..n pro i {
cede i
}
}
# Multi-value async function that yields values via cede
functio rangeAsync(numerus n) fient numerus {
ex 0..n pro i {
cede i
}
}
incipit {
# Iterate over sync fiunt function results
scribe "Sync fiunt iteration:"
ex rangeSync(3) pro num {
scribe scriptum(" num: {num}")
}
# Collect all results from fiunt function
varia syncResults = []
ex rangeSync(5) pro num {
syncResults.adde(num * 2)
}
scribe("Sync collected:")
scribe(syncResults)
# Note: Async iteration would require async context
# ex rangeAsync(3) fiunt num {
# scribe num
# }
}
range-step
# Ranges with step using per
#
# ex <start>..<end> per <step> pro <item> { }
# ex <start> usque <end> per <step> pro <item> { }
incipit {
# Step by 2 (exclusive: 0, 2, 4, 6, 8)
ex 0..10 per 2 pro i {
scribe i
}
# Step by 2 (inclusive: 0, 2, 4, 6, 8, 10)
ex 0 usque 10 per 2 pro i {
scribe i
}
# Step by 3
ex 0..15 per 3 pro i {
scribe i
}
# Countdown with negative step
ex 10..0 per -1 pro i {
scribe i
}
# Countdown by 2
ex 10..0 per -2 pro i {
scribe i
}
}
1 more examples in this category
expressions
scriptum
# Format string expressions using scriptum()
incipit ergo cura arena {
fixum name = "Marcus"
fixum age = 30
# Single placeholder
fixum greeting = scriptum("Salve, §!", name)
scribe greeting
# Multiple placeholders
fixum info = scriptum("§ is § years old", name, age)
scribe info
# With expression
fixum calc = scriptum("10 + 20 = §", 10 + 20)
scribe calc
}
regex
# Regex literals using sed keyword
# Syntax: sed "pattern" [flags]
incipit {
# Simple patterns
fixum digits = sed "\d+"
fixum word = sed "\w+"
# With flags (i = case insensitive, m = multiline)
fixum insensitive = sed "hello" i
fixum multiline = sed "^start" im
# Complex patterns
fixum email = sed "[^@]+@[^@]+"
fixum paths = sed "/usr/local/.*"
}
qua
# Type casting with qua: converts values between types
functio getData() -> lista<numerus> {
redde [1, 2, 3]
}
functio getResponse() -> objectum {
redde { body: "body" }
}
functio getValue() -> numerus {
redde 42
}
incipit {
# Cast to string
fixum data = 42
fixum asText = data qua textus
scribe asText
# Cast to number
fixum input = "100"
fixum asNum = input qua numerus
scribe asNum
# Cast to boolean
fixum value = 1
fixum asBool = value qua bivalens
scribe asBool
# Cast to nullable type
fixum num = 10
fixum maybe = num qua numerus?
scribe maybe
# Cast to array type
fixum raw = getData()
fixum items = raw qua lista<textus>
scribe items
# Cast with member access
fixum response = getResponse()
fixum body = response.body qua textus
scribe body
# Cast call result directly
fixum result = getValue() qua textus
scribe result
# Cast in parenthesized expression for chaining
fixum len = (data qua textus).length
scribe len
}
literal
# Literal expressions: numbers, strings, booleans, null, templates
incipit {
# Numbers
fixum integer = 42
fixum decimal = 3.14
fixum negative = -100
# Strings
fixum greeting = "hello"
fixum single = 'single quotes'
# Booleans
fixum yes = verum
fixum no = falsum
# Null
fixum nothing = nihil
# Template literals
fixum name = "Mundus"
fixum message = `Hello ${name}`
}
ab
# Ab expression - collection filtering DSL
# 'ab' provides declarative filtering with optional transforms
incipit {
# Sample data - users with boolean properties
fixum users = [
{ nomen: "Marcus", activus: verum, aetas: 25 },
{ nomen: "Julia", activus: falsum, aetas: 30 },
{ nomen: "Gaius", activus: verum, aetas: 17 }
]
fixum items = [
{ valor: 10, visibilis: verum },
{ valor: 20, visibilis: falsum },
{ valor: 30, visibilis: verum },
{ valor: 40, visibilis: verum }
]
# Boolean property shorthand - filter where property is true
fixum active = ab users activus
scribe(active)
# Negated filter - filter where property is false
fixum inactive = ab users non activus
scribe(inactive)
# Filter with prima transform (first N elements)
fixum top2 = ab items visibilis, prima 2
scribe(top2)
# Filter with ultima transform (last N elements)
fixum last2 = ab items visibilis, ultima 2
scribe(last2)
# Filter with summa transform (sum of results)
fixum prices = [
{ pretium: 100, validum: verum },
{ pretium: 200, validum: verum },
{ pretium: 50, validum: falsum }
]
fixum validPrices = ab prices validum
scribe(validPrices)
# Multiple transforms chained
fixum result = ab items visibilis, prima 3, ultima 2
scribe(result)
# Without filter - just apply transforms to collection
fixum nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
fixum firstFive = ab nums, prima 5
scribe(firstFive)
# Chain transforms without filter
fixum sumFirst = ab nums, prima 5, summa
scribe(sumFirst)
# Complex source - member expression
fixum data = { users: users }
fixum dataActive = ab data.users activus
scribe(dataActive)
}
14 more examples in this category
fac
basic
# Basic fac (do) scope blocks
#
# fac { <body> }
incipit {
# Simple scope block
fac {
fixum x = 42
scribe x
}
# Scope block isolates variables
fac {
fixum message = "Hello from fac block"
scribe message
}
# Multiple statements in scope
fac {
fixum a = 10
fixum b = 20
fixum sum = a + b
scribe sum
}
}
with-cape
# Fac blocks with error handling (cape)
#
# fac { <body> } cape <error> { <handler> }
incipit {
# Basic fac with cape for error handling
fac {
fixum x = 10
scribe x
} cape err {
scribe err
}
# Scope block that might throw
fac {
fixum value = 42
scribe value
} cape error {
scribe "Error occurred:"
scribe error
}
}
functio
optional
# Optional parameters with si and vel
#
# si marks a parameter as optional
# vel provides a default value
#
# GRAMMAR:
# parameter := (preposition)? 'si'? type name ('ut' alias)? ('vel' default)?
# Optional parameter without default (receives nihil if omitted)
functio greet(textus nomen, si textus titulus) -> textus {
si titulus est nihil {
redde scriptum("Salve, §!", nomen)
}
redde scriptum("Salve, § §!", titulus, nomen)
}
# Optional parameter with default value
functio paginate(si numerus pagina vel 1, si numerus per_pagina vel 10) -> textus {
redde scriptum("Page § with § items", pagina, per_pagina)
}
# Preposition with optional: de si (borrowed, optional without default)
functio analyze(textus source, de si numerus depth) -> numerus {
si depth est nihil {
redde 3
}
redde depth
}
# Mixed required and optional parameters
functio createUser(textus nomen, si numerus aetas vel 0, si bivalens activus vel verum) -> textus {
redde scriptum("User: §, age: §, active: §", nomen, aetas, activus)
}
incipit {
# Without optional arg
scribe greet("Marcus")
# With optional arg
scribe greet("Marcus", "Dominus")
# Default pagination
scribe paginate()
# Custom pagination
scribe paginate(2, 25)
# Partial defaults
scribe paginate(5)
# With borrowed optional
scribe analyze("code")
scribe analyze("code", 5)
# Mixed args
scribe createUser("Julia")
scribe createUser("Julia", 25)
scribe createUser("Julia", 25, falsum)
}
basic
# Basic function declarations
#
# functio <name>() { <body> }
# functio <name>() -> <type> { <body> }
# Function with no parameters, no return
functio saluta() {
scribe "Salve, Mundus!"
}
# Function with parameter, no explicit return type
functio dic(verbum) {
scribe verbum
}
# Function with return type
functio nomen() -> textus {
redde "Marcus Aurelius"
}
# Function with parameter and return type
functio duplica(n) -> numerus {
redde n * 2
}
incipit {
saluta()
dic("Bonum diem!")
fixum rex = nomen()
scribe rex
scribe duplica(21)
}
recursion
# Recursive functions
#
# Functions that call themselves with a base case
# Factorial: n! = n * (n-1)!
functio factorial(numerus n) -> numerus {
si n <= 1 {
redde 1
}
redde n * factorial(n - 1)
}
# Fibonacci: fib(n) = fib(n-1) + fib(n-2)
functio fibonacci(numerus n) -> numerus {
si n <= 0 {
redde 0
}
si n == 1 {
redde 1
}
redde fibonacci(n - 1) + fibonacci(n - 2)
}
# Sum from 1 to n
functio summatio(numerus n) -> numerus {
si n <= 0 {
redde 0
}
redde n + summatio(n - 1)
}
incipit {
# Factorial examples
scribe factorial(0)
scribe factorial(1)
scribe factorial(5)
scribe factorial(10)
# Fibonacci examples
scribe fibonacci(0)
scribe fibonacci(1)
scribe fibonacci(10)
# Sum examples
scribe summatio(5)
scribe summatio(10)
}
typed
# Functions with typed parameters
#
# functio <name>(type param, type param) -> type { <body> }
# Single typed parameter
functio quadratum(numerus n) -> numerus {
redde n * n
}
# Multiple typed parameters
functio adde(numerus a, numerus b) -> numerus {
redde a + b
}
# Mixed types
functio describe(textus nomen, numerus aetas) -> textus {
redde scriptum("§ habet § annos", nomen, aetas)
}
# Boolean parameter and return
functio nega(bivalens valor) -> bivalens {
redde non valor
}
# Function with fractus (float) type
functio media(fractus a, fractus b) -> fractus {
redde (a + b) / 2.0
}
incipit {
scribe quadratum(7)
scribe adde(100, 200)
scribe describe("Julius", 30)
scribe nega(verum)
scribe nega(falsum)
scribe media(3.0, 7.0)
}
genus
basic
# Basic genus (class/struct) with properties
#
# genus <Name> {
# <type> <property>
# <type> <property>: <default>
# }
genus Punctum {
numerus x
numerus y
}
genus Persona {
textus nomen
numerus aetas: 0
bivalens activus: verum
}
incipit {
# Instantiate with all required fields
fixum p = novum Punctum {
x: 10,
y: 20
}
scribe p.x
scribe p.y
# Instantiate with required + optional defaults
fixum marcus = novum Persona {
nomen: "Marcus"
}
scribe marcus.nomen
scribe marcus.aetas
scribe marcus.activus
# Override defaults
fixum julia = novum Persona {
nomen: "Julia",
aetas: 25,
activus: falsum
}
scribe julia.nomen
scribe julia.aetas
scribe julia.activus
}
methods
# Genus with methods using ego (self) reference
#
# genus <Name> {
# <type> <property>
# functio <method>() -> <type> { ... ego.<property> ... }
# }
genus Rectangle {
numerus width: 1
numerus height: 1
functio area() -> numerus {
redde ego.width * ego.height
}
functio perimeter() -> numerus {
redde 2 * (ego.width + ego.height)
}
functio isSquare() -> bivalens {
redde ego.width == ego.height
}
}
genus Counter {
numerus count: 0
functio increment() {
ego.count = ego.count + 1
}
functio getValue() -> numerus {
redde ego.count
}
}
incipit {
# Methods that return values
fixum rect = novum Rectangle {
width: 10,
height: 5
}
scribe rect.area()
scribe rect.perimeter()
scribe rect.isSquare()
# Methods that modify state
varia counter = novum Counter
scribe counter.getValue()
counter.increment()
scribe counter.getValue()
counter.increment()
counter.increment()
scribe counter.getValue()
}
creo
# Genus with constructor hook (creo)
#
# genus <Name> {
# <type> <property>: <default>
# functio creo() { ... }
# }
#
# creo() runs after defaults and overrides are merged.
# Use for validation, clamping, or derived initialization.
genus BoundedValue {
numerus value: 0
functio creo() {
si ego.value < 0 {
ego.value = 0
}
si ego.value > 100 {
ego.value = 100
}
}
functio getValue() -> numerus {
redde ego.value
}
}
genus Circle {
numerus radius: 1
numerus diameter: 0
numerus area: 0
functio creo() {
ego.diameter = ego.radius * 2
ego.area = 3.14159 * ego.radius * ego.radius
}
}
incipit {
# Validation in creo
fixum normal = novum BoundedValue {
value: 50
}
scribe normal.getValue()
fixum clamped = novum BoundedValue {
value: 200
}
scribe clamped.getValue()
# Derived initialization in creo
fixum c = novum Circle {
radius: 5
}
scribe c.radius
scribe c.diameter
scribe c.area
}
iace
basic
# Basic iace (throw) statement
#
# iace <expression>
incipit {
# Throw with string literal
tempta {
iace "Something went wrong"
}
cape err {
scribe "Caught:", err
}
# Throw with formatted message
fixum code = 404
tempta {
iace scriptum("Error code: §", code)
}
cape err {
scribe "Caught:", err
}
# Throw from conditional
fixum value = -5
tempta {
si value < 0 {
iace "Value must be non-negative"
}
scribe "Value is valid"
}
cape err {
scribe "Validation failed:", err
}
}
importa
basic
# Import statements (importa)
#
# ex <source> importa <names> - named imports
# ex <source> importa <name> ut <alias> - import with alias
# ex <source> importa * ut <alias> - wildcard import with alias
# Named imports
ex "lodash" importa map
ex "@hono/hono" importa Hono, Context
ex "utils" importa helper ut h
ex "db" importa connect, query ut q, close
# Wildcard import (alias required for TypeScript target)
ex "@std/crypto" importa * ut crypto
# Multiple imports from different sources
ex "@oak/oak" importa Application
ex "std/path" importa join, resolve
# Relative imports
ex "./utils" importa helper
ex "../shared/utils" importa formatter
# Many named items
ex "helpers" importa a, b, c, d, e, f
# Multiple aliases
ex "mod" importa foo ut f, bar ut b, baz ut z
incipit {
scribe "Import statements are declarations at module scope"
}
importa-local
main
# Example of local file imports
# Import specific symbols from local file
ex "./utils" importa greet, ANSWER, Point
# Use the imported function
fixum textus message = greet("World")
scribe message
# Use the imported constant
scribe scriptum("The answer is §", ANSWER)
# Use the imported genus
fixum Point p = { x: 10, y: 20 } qua Point
utils
# Example utility module for local import testing
# A simple greeting function
functio greet(textus name) -> textus {
redde scriptum("Hello, §!", name)
}
# A constant value
fixum numerus ANSWER = 42
# A genus for testing
genus Point {
numerus x
numerus y
}
in
basic
# Basic in (mutation block) statements
#
# in <object> { <assignments> }
incipit {
# Create an object with initial values
varia user = { nomen: "", aetas: 0, active: falsum }
# Mutation block: set multiple fields at once
in user {
nomen = "Marcus"
aetas = 42
active = verum
}
scribe user.nomen
scribe user.aetas
# Single-line mutation block
varia stats = { count: 0 }
in stats { count = 1 }
scribe stats.count
# Mutation with computed values
fixum width = 10
fixum height = 20
varia rect = { w: 0, h: 0, area: 0 }
in rect {
w = width
h = height
area = width * height
}
scribe rect.area
# Nested object mutation
varia config = { server: { host: "", port: 0 } }
in config.server {
host = "localhost"
port = 8080
}
scribe config.server.host
}
incipit
basic
# Basic incipit (entry point)
#
# incipit { <body> }
incipit {
scribe "Salve, Munde!"
}
with-functions
# Entry point with functions defined outside
#
# Functions declared outside incipit become module-level declarations.
# The incipit block calls them as needed.
functio greet(textus name) -> textus {
redde scriptum("Salve, §!", name)
}
functio add(numerus a, numerus b) -> numerus {
redde a + b
}
incipit {
scribe greet("Marcus")
scribe "Sum:", add(3, 5)
}
ordo
basic
# Basic ordo (enum) declaration
#
# ordo Name { Member1, Member2, Member3 }
# ordo Name { Member1 = value1, Member2 = value2 }
ordo Color { rubrum, viridis, caeruleum }
ordo Status { pendens = 0, actum = 1, finitum = 2 }
incipit {
# Using enum values
fixum color = Color.rubrum
fixum status = Status.actum
# Switch on enum
elige color {
casu Color.rubrum {
scribe "Red"
}
casu Color.viridis {
scribe "Green"
}
casu Color.caeruleum {
scribe "Blue"
}
}
# Switch on enum with numeric values
elige status {
casu Status.pendens {
scribe "Pending"
}
casu Status.actum {
scribe "Active"
}
casu Status.finitum {
scribe "Finished"
}
}
}
pactum
basic
# Basic pactum (interface) definition and implementation
#
# pactum <Name> { functio <method>(<params>) -> <returnType> }
# genus <Name> implet <Pactum> { <implementation> }
pactum Drawable {
functio draw() -> vacuum
}
genus Circle implet Drawable {
numerus radius: 10
functio draw() {
scribe scriptum("Drawing circle with radius §", ego.radius)
}
}
genus Square implet Drawable {
numerus side: 5
functio draw() {
scribe scriptum("Drawing square with side §", ego.side)
}
}
incipit {
fixum circle = novum Circle { radius: 25 }
fixum square = novum Square { side: 15 }
circle.draw()
square.draw()
}
perge
basic
# Continue (perge) in loops
#
# perge skips to the next iteration of the innermost loop
incipit ergo cura arena {
# Skip even numbers
varia i = 0
dum i < 10 {
i = i + 1
si i % 2 == 0 {
perge
}
scribe i
}
# Continue in nested loop (affects inner only)
varia outer = 0
dum outer < 3 {
varia inner = 0
dum inner < 5 {
inner = inner + 1
si inner == 3 {
perge
}
scribe scriptum("outer=§, inner=§", outer, inner)
}
outer = outer + 1
}
}
proba
basic
# Basic proba (test) statements
#
# proba "name" { body }
# Simple test with single assertion
proba "one plus one equals two" {
adfirma 1 + 1 == 2
}
# Test with multiple assertions
proba "validates arithmetic" {
adfirma 2 + 2 == 4
adfirma 10 - 3 == 7
adfirma 3 * 4 == 12
}
# Test with variables
proba "string concatenation works" {
fixum greeting = "hello"
fixum name = "world"
fixum result = scriptum("§ §", greeting, name)
adfirma result == "hello world"
}
# Test boolean conditions
proba "comparison operators" {
fixum x = 10
adfirma x > 5
adfirma x < 20
adfirma x >= 10
adfirma x <= 10
}
# Test with negation
proba "negated assertions" {
adfirma non falsum
adfirma non (1 == 2)
}
# Test with complex logical assertion
proba "complex assertion" {
fixum x = 50
adfirma x > 0 et x < 100
}
modifiers
# Test modifiers: omitte (skip) and futurum (todo)
#
# proba omitte "reason" "name" { body }
# proba futurum "reason" "name" { body }
# Skip a test with reason and name
proba omitte "blocked by issue #42" "database connection test" {
adfirma falsum
}
# Todo test with reason and name
proba futurum "needs async support" "async file operations" {
adfirma verum
}
# Regular test alongside modifiers
proba "this test runs normally" {
adfirma 1 + 1 == 2
}
# Multiple skipped tests
proba omitte "flaky on CI" "network timeout test" {
adfirma falsum
}
proba omitte "platform specific" "windows-only behavior" {
adfirma falsum
}
# Multiple todo tests
proba futurum "needs new API" "graphql mutations" {
adfirma verum
}
proba futurum "depends on feature X" "caching layer" {
adfirma verum
}
# Skipped test with complex body
proba omitte "external service down" "api integration" {
fixum status = 500
adfirma status == 200
}
# Todo test with setup
proba futurum "needs database fixtures" "user creation flow" {
varia userId = 0
adfirma userId > 0
}
redde
basic
# Basic redde (return) statements
#
# redde <expression> -- return a value
# redde -- void return
functio add(numerus a, numerus b) fit numerus {
redde a + b
}
functio greet(textus name) fit textus {
redde "Hello, " + name
}
functio getFortyTwo() fit numerus {
redde 42
}
functio doNothing() fit vacuum {
redde
}
functio earlyExit(numerus x) fit numerus {
si x < 0 {
redde 0
}
redde x * 2
}
incipit {
scribe add(10, 20)
scribe greet("World")
scribe getFortyTwo()
doNothing()
scribe earlyExit(-5)
scribe earlyExit(10)
}
rumpe
basic
# Break (rumpe) in loops
#
# rumpe exits the innermost loop immediately
incipit ergo cura arena {
# Break when reaching 5
varia i = 0
dum i < 10 {
si i == 5 {
rumpe
}
scribe i
i = i + 1
}
# Break in nested loop (exits inner only)
varia outer = 0
dum outer < 3 {
varia inner = 0
dum inner < 10 {
si inner == 2 {
rumpe
}
scribe scriptum("outer=§, inner=§", outer, inner)
inner = inner + 1
}
outer = outer + 1
}
}
scribe
levels
# Output statements with different log levels
#
# scribe <expr> -> console.log (standard output)
# vide <expr> -> console.debug (debug output)
# mone <expr> -> console.warn (warning output)
incipit {
fixum status = "running"
fixum count = 42
# Standard output (console.log)
scribe "Application started"
scribe "Status:", status
# Debug output (console.debug)
vide "Debug: entering main loop"
vide "Debug: count =", count
# Warning output (console.warn)
mone "Warning: deprecated feature used"
mone "Warning: count exceeds threshold:", count
}
basic
# Basic scribe (print) statements
#
# scribe <expr>
# scribe <expr>, <expr>, ...
incipit {
# Simple string output
scribe "Hello, world!"
# Variable output
fixum nomen = "Marcus"
scribe nomen
# Multiple arguments
fixum aetas = 30
scribe "Name:", nomen
scribe "Age:", aetas
# Expressions
fixum x = 10
fixum y = 20
scribe "Sum:", x + y
# Multiple values in one statement
scribe "Coordinates:", x, y
}
si
nested
# Nested si conditionals
incipit {
fixum isLoggedIn = verum
fixum hasPermission = verum
si isLoggedIn {
si hasPermission {
scribe "Access granted"
}
secus {
scribe "Permission denied"
}
}
secus {
scribe "Please log in"
}
}
with-reddit
# Si with reddit syntax
#
# 'reddit' is syntactic sugar for 'ergo redde' - a one-liner return.
# Use it for early returns and guard clauses.
#
# si <condition> reddit <expression>
# sin <condition> reddit <expression>
# secus reddit <expression>
# Early return pattern
functio classify(numerus x) -> textus {
si x < 0 reddit "negative"
si x == 0 reddit "zero"
redde "positive"
}
# Guard clause pattern
functio divide(numerus a, numerus b) -> numerus? {
si b == 0 reddit nihil
redde a / b
}
# Sin/secus chain with reddit
functio grade(numerus score) -> textus {
si score >= 90 reddit "A"
sin score >= 80 reddit "B"
sin score >= 70 reddit "C"
sin score >= 60 reddit "D"
secus reddit "F"
}
# Find first in list (early return from loop)
functio findFirst(lista<numerus> items, numerus target) -> numerus? {
ex items pro item {
si item == target reddit item
}
redde nihil
}
# Check if key exists (early return from iteration)
functio hasKey(tabula<textus, numerus> obj, textus key) -> bivalens {
de obj pro k {
si k == key reddit verum
}
redde falsum
}
incipit {
scribe classify(-5) # negative
scribe classify(0) # zero
scribe classify(10) # positive
scribe divide(10, 2) # 5
scribe divide(10, 0) # nihil
scribe grade(95) # A
scribe grade(85) # B
scribe grade(55) # F
fixum nums = [1, 2, 3, 4, 5]
scribe findFirst(nums, 3) # 3
scribe findFirst(nums, 9) # nihil
}
si-aliter
# si-secus (if-else) conditionals
#
# si <condition> { <body> } secus { <body> }
# si <cond1> { } sin <cond2> { } secus { }
incipit {
# Simple if-else
fixum score = 85
si score >= 90 {
scribe "Grade: A"
}
secus {
scribe "Grade: B or lower"
}
# Multiple statements in branches
fixum temperature = 22
si temperature > 30 {
scribe "Hot"
scribe "Stay hydrated"
}
secus {
scribe "Comfortable"
scribe "Enjoy the weather"
}
# If-else-if chain
fixum grade = 75
si grade >= 90 {
scribe "A - Excellent"
}
sin grade >= 80 {
scribe "B - Good"
}
sin grade >= 70 {
scribe "C - Satisfactory"
}
sin grade >= 60 {
scribe "D - Passing"
}
secus {
scribe "F - Failing"
}
}
ergo
# One-liner conditionals with ergo
#
# si <condition> ergo <statement>
# si <condition> ergo <statement> secus <statement>
#
# ergo = "therefore, thus" (logical consequence)
incipit {
fixum x = 10
# Simple one-liner
si x > 5 ergo scribe "x is big"
# One-liner if-else
fixum age = 25
si age >= 18 ergo scribe "Adult" secus scribe "Minor"
# Multiple conditions
fixum score = 85
si score >= 90 ergo scribe "A" secus scribe "Not A"
# Simple validation
fixum valid = verum
si valid ergo scribe "OK"
}
si-sin-secus
# si-sin-secus (poetic if-else-if chain)
#
# Poetic alternative to si/sin/secus:
# si = if
# sin = else if ("but if")
# secus = else ("otherwise")
incipit {
fixum hour = 14
si hour < 6 {
scribe "Late night"
}
sin hour < 12 {
scribe "Morning"
}
sin hour < 18 {
scribe "Afternoon"
}
sin hour < 22 {
scribe "Evening"
}
secus {
scribe "Night"
}
}
2 more examples in this category
statements
si
# ============================================================================
# Si Statement (Conditionals)
# ============================================================================
#
# The 'si' statement provides conditional execution. It supports block form,
# one-liner form (ergo), else-if chains (sin), else clauses (secus), and
# inline error handling (cape).
#
# ----------------------------------------------------------------------------
# GRAMMAR: Si Statement
# ----------------------------------------------------------------------------
#
# ifStmt := 'si' expression (blockStmt | 'ergo' statement)
# ('cape' IDENTIFIER blockStmt)?
# (elseClause | 'sin' ifStmt)?
#
# elseClause := 'secus' (ifStmt | blockStmt | statement)
#
# Components:
# - 'si' expression { } — basic conditional
# - 'si' expression ergo stmt — one-liner form
# - 'cape' err { } — inline error handling
# - 'sin' expression { } — else-if branch
# - 'secus' { } — else branch
#
# ----------------------------------------------------------------------------
# KEYWORDS
# ----------------------------------------------------------------------------
#
# si = "if" (Latin: "if")
# sin = "else if" (Latin: "but if", contraction of 'si' + 'non')
# secus = "else" (Latin: "otherwise")
# ergo = "therefore" (Latin: enables one-liner consequent)
# cape = "catch" (Latin: "seize", inline error handling)
#
# ----------------------------------------------------------------------------
# READING THE CHAIN
# ----------------------------------------------------------------------------
#
# A complete conditional chain reads as classical Latin:
#
# si x > 0 { positive() } — "if x > 0..."
# sin x < 0 { negative() } — "but if x < 0..."
# secus { zero() } — "otherwise..."
#
# 'sin' is a contraction of 'si non' (if not / but if), common in Latin prose.
#
# ============================================================================
# LLM GUIDANCE
# ============================================================================
#
# ALWAYS use Latin keywords:
# - 'si' not 'if'
# - 'sin' not 'else if' or 'elif'
# - 'secus' not 'else'
# - 'ergo' for one-liners (no equivalent in JS/TS)
#
# NEVER use JavaScript/TypeScript patterns:
# - 'if' does not exist
# - 'else if' does not exist — use 'sin'
# - 'else' does not exist — use 'secus'
# - Parentheses around condition are NOT required: si x > 5 { }
#
# PREFER:
# - Block form for multiple statements
# - 'ergo' form for simple one-liners
# - 'sin' chains over nested 'si' when checking related conditions
#
# ============================================================================
# EXAMPLES
# ============================================================================
incipit {
# ==========================================================================
# SECTION: Basic Conditionals
# ==========================================================================
#
# si <condition> { <body> }
#
# The simplest form. Condition is evaluated, block executes if truthy.
# No parentheses required around the condition.
fixum x = 10
si x > 5 {
scribe "x is greater than 5"
}
si x > 20 {
scribe "x is greater than 20"
}
# Multiple statements in block
fixum age = 25
si age >= 18 {
scribe "Adult"
scribe "Can vote"
}
# ==========================================================================
# SECTION: One-liner Form (ergo)
# ==========================================================================
#
# si <condition> ergo <statement>
# si <condition> ergo <statement> secus <statement>
#
# 'ergo' (therefore) enables concise single-statement consequents.
# Can be combined with 'secus' for one-liner if-else.
# Simple one-liner
si x > 5 ergo scribe "x is big"
# One-liner if-else
si age >= 18 ergo scribe "Adult" secus scribe "Minor"
# Multiple conditions with ergo
fixum score = 85
si score >= 90 ergo scribe "A" secus scribe "Not A"
# Simple validation
fixum valid = verum
si valid ergo scribe "OK"
# ==========================================================================
# SECTION: If-Else (secus)
# ==========================================================================
#
# si <condition> { } secus { }
#
# 'secus' (otherwise) provides the else branch.
si score >= 90 {
scribe "Grade: A"
}
secus {
scribe "Grade: B or lower"
}
# Multiple statements in branches
fixum temperature = 22
si temperature > 30 {
scribe "Hot"
scribe "Stay hydrated"
}
secus {
scribe "Comfortable"
scribe "Enjoy the weather"
}
# ==========================================================================
# SECTION: If-Elseif-Else Chain (sin/secus)
# ==========================================================================
#
# si <cond1> { } sin <cond2> { } sin <cond3> { } secus { }
#
# 'sin' (but if) chains multiple conditions. More readable than nested si.
# Evaluates top-to-bottom, first match wins.
fixum grade = 75
si grade >= 90 {
scribe "A - Excellent"
}
sin grade >= 80 {
scribe "B - Good"
}
sin grade >= 70 {
scribe "C - Satisfactory"
}
sin grade >= 60 {
scribe "D - Passing"
}
secus {
scribe "F - Failing"
}
# Time of day example
fixum hour = 14
si hour < 6 {
scribe "Late night"
}
sin hour < 12 {
scribe "Morning"
}
sin hour < 18 {
scribe "Afternoon"
}
sin hour < 22 {
scribe "Evening"
}
secus {
scribe "Night"
}
# ==========================================================================
# SECTION: Type Checking (est / non est)
# ==========================================================================
#
# 'est' performs type/identity checks (like === for primitives).
# 'non est' negates the check.
# For null checks, prefer 'nihil x' or 'nonnihil x' unary forms.
fixum textus? maybeName = nihil
si maybeName est nihil {
scribe "Name is null"
}
fixum active = verum
si verum active {
scribe "Is exactly true"
}
si non falsum active {
scribe "Is not false"
}
# ==========================================================================
# SECTION: Nested Conditionals
# ==========================================================================
#
# Conditionals can be nested, but prefer sin chains when checking
# related conditions to reduce nesting depth.
fixum isLoggedIn = verum
fixum hasPermission = verum
si isLoggedIn {
si hasPermission {
scribe "Access granted"
}
secus {
scribe "Permission denied"
}
}
secus {
scribe "Please log in"
}
# Better: use 'et' to combine conditions when possible
si isLoggedIn et hasPermission {
scribe "Access granted (combined check)"
}
# ==========================================================================
# SECTION: Inline Error Handling (cape)
# ==========================================================================
#
# si <condition> { } cape <error> { }
#
# 'cape' (catch/seize) provides inline error handling for expressions
# that might throw. The error is bound to the identifier.
si riskyOperation() {
scribe "Operation succeeded"
}
cape err {
scribe "Operation failed"
scribe err
}
# Combined with else
si anotherRiskyOp() {
scribe "Success"
}
cape err {
scribe "Caught error"
}
secus {
scribe "Condition was falsy but no error"
}
# ==========================================================================
# SECTION: Unary Condition Operators
# ==========================================================================
#
# Faber provides Latin unary operators for common condition patterns.
# These read more naturally and reduce symbolic noise.
#
# GRAMMAR (from unary):
# unary := ('non' | 'nulla' | 'nonnulla' | 'nihil' | 'nonnihil'
# | 'negativum' | 'positivum' | ...) unary
#
# Operators:
# non x — logical not (replaces !x)
# nihil x — x is null (replaces x === null)
# nonnihil x — x is not null (replaces x !== null)
# nulla x — x is empty/none (empty string, empty list, 0)
# nonnulla x — x is non-empty/some
# negativum x — x < 0
# positivum x — x > 0
fixum value = 42
# Numeric sign checks
si positivum value {
scribe "value is positive"
}
si negativum value {
scribe "value is negative"
}
# Compare: si value > 0 vs si positivum value
# The unary form is more declarative
# Null checks
fixum textus? optionalName = nihil
si nihil optionalName {
scribe "name is null"
}
si nonnihil optionalName {
scribe "name has a value"
}
# Empty checks
fixum items = [] qua lista<numerus>
si nulla items {
scribe "list is empty"
}
fixum message = "hello"
si nonnulla message {
scribe "message is not empty"
}
# ==========================================================================
# SECTION: Logical Operators in Conditions
# ==========================================================================
#
# Use 'et' (and), 'aut' (or), 'non' (not) in conditions.
# PREFER Latin operators over && || !
fixum a = verum
fixum b = falsum
si a et b {
scribe "Both true"
}
si a aut b {
scribe "At least one true"
}
si non b {
scribe "b is false"
}
# Combined conditions
fixum userAge = 25
fixum hasID = verum
si userAge >= 21 et hasID {
scribe "Can purchase alcohol"
}
si userAge < 13 aut userAge >= 65 {
scribe "Eligible for discount"
}
}
# ==========================================================================
# Helper functions for error handling examples
# ==========================================================================
functio riskyOperation() -> bivalens {
redde verum
}
functio anotherRiskyOp() -> bivalens {
redde falsum
}
tempta-cape
in-functio
# Error handling in functions
#
# Functions can use tempta-cape to handle errors internally
# or let errors propagate to callers
functio safeDivide(numerus a, numerus b) -> numerus {
tempta {
si b == 0 {
iace "Division by zero"
}
redde a / b
}
cape err {
scribe "Error:", err
redde 0
}
}
functio validatePositive(numerus value) -> numerus {
tempta {
si value < 0 {
iace "Negative value not allowed"
}
redde value * 2
}
cape err {
scribe "Validation failed:", err
redde 0
}
}
functio processWithCleanup(textus name) {
varia resource = "pending"
tempta {
scribe "Opening:", name
resource = name
si name == "" {
iace "Empty name"
}
scribe "Processing:", resource
}
cape err {
scribe "Error:", err
}
demum {
scribe "Closing:", resource
}
}
functio withReturnInDemum() -> textus {
tempta {
scribe "Starting operation"
redde "success"
}
cape err {
redde "error"
}
demum {
scribe "Demum runs before return"
}
}
incipit {
scribe "Safe divide 10/2:", safeDivide(10, 2)
scribe "Safe divide 10/0:", safeDivide(10, 0)
scribe "Validate 5:", validatePositive(5)
scribe "Validate -3:", validatePositive(-3)
processWithCleanup("data.txt")
processWithCleanup("")
scribe "Result:", withReturnInDemum()
}
basic
# Basic tempta-cape (try-catch) with iace (throw)
#
# tempta { <body> }
# cape <errorName> { <handler> }
# iace <expression>
incipit {
# Basic try-catch
tempta {
scribe "Attempting operation..."
iace "Something went wrong"
scribe "This line never runs"
}
cape err {
scribe "Caught error:", err
}
# tempta-cape-demum (try-catch-finally)
tempta {
scribe "Opening resource..."
iace "Failed to open"
}
cape err {
scribe "Error occurred:", err
}
demum {
scribe "Cleanup: always runs"
}
# demum without cape
tempta {
scribe "Operation succeeds"
}
demum {
scribe "Cleanup runs anyway"
}
# Nested tempta blocks
tempta {
scribe "Outer try"
tempta {
scribe "Inner try"
iace "Inner error"
}
cape inner {
scribe "Caught inner:", inner
}
scribe "Continues after inner catch"
}
cape outer {
scribe "Outer catch:", outer
}
}
typealias
basic
# Basic type aliases
#
# typus Name = Type
# Primitive type aliases
typus UserId = numerus
typus Username = textus
typus IsActive = bivalens
# Generic type aliases
typus Names = lista<textus>
typus Scores = lista<numerus>
typus UserCache = tabula<textus, numerus>
# Nullable type alias
typus OptionalName = textus?
incipit {
# Using the type aliases
fixum UserId id = 42
fixum Username name = "Marcus"
fixum IsActive active = verum
scribe id
scribe name
scribe active
# Using generic type aliases
fixum Names friends = ["Gaius", "Lucius", "Titus"]
scribe friends
fixum Scores points = [100, 95, 87]
scribe points
}
varia
destructure
# Array destructuring declarations
#
# fixum [a, b, c] = array -- destructure into immutable bindings
# varia [x, y, z] = array -- destructure into mutable bindings
incipit {
# Basic array destructuring
fixum numbers = [1, 2, 3]
fixum [a, b, c] = numbers
scribe a
scribe b
scribe c
# Destructure inline array
fixum [first, second, third] = [10, 20, 30]
scribe first
scribe second
scribe third
# Mutable destructuring
fixum coords = [100, 200]
varia [x, y] = coords
scribe x
scribe y
x = x + 50
y = y + 50
scribe x
scribe y
# Destructure with fewer variables (partial)
fixum values = [1, 2, 3, 4, 5]
fixum [one, two] = values
scribe one
scribe two
# Nested arrays
fixum matrix = [[1, 2], [3, 4]]
fixum [row1, row2] = matrix
scribe row1
scribe row2
}
basic
# Basic varia and fixum declarations
#
# varia <name> = <expr> -- mutable binding
# fixum <name> = <expr> -- immutable binding
incipit {
# Mutable variable with varia
varia counter = 0
scribe counter
counter = 1
scribe counter
counter = counter + 10
scribe counter
# Immutable variable with fixum
fixum greeting = "Salve, Mundus!"
scribe greeting
# Multiple declarations
fixum x = 10
fixum y = 20
fixum sum = x + y
scribe sum
# Mutable reassignment
varia message = "Hello"
message = "Goodbye"
scribe message
}
typed
# Typed variable declarations
#
# varia <type> <name> = <expr> -- typed mutable
# fixum <type> <name> = <expr> -- typed immutable
incipit {
# Typed immutable declarations
fixum numerus age = 30
fixum textus name = "Marcus"
fixum bivalens active = verum
scribe age
scribe name
scribe active
# Typed mutable declarations
varia numerus count = 0
varia textus status = "pending"
varia bivalens running = falsum
scribe count
scribe status
scribe running
# Reassign mutable typed variables
count = 100
status = "complete"
running = verum
scribe count
scribe status
scribe running
# Fractional numbers
fixum fractus pi = 3.14159
varia fractus rate = 0.05
scribe pi
scribe rate
rate = 0.10
scribe rate
}