9.5 KiB
Cordial Language Reference Guide
Cordial is a simple, expression-based programming language embedded in Swiftly. This guide documents every working feature.
Evaluation Prefix
All evaluation in the editor uses the /= prefix:
/= 2 + 3
Output:
5
Types
Cordial has five value types:
- number: floating-point numbers (internally f64). Displayed as integers when they have no fractional part.
- bool:
trueorfalse - str: strings in double quotes, with escape sequences (
\n,\t,\\,\") - array: ordered collections of values
- void: the value returned by statements with no explicit value
Variables
Declaration
Use let to declare and initialize a variable:
let x = 5
/= x
Output:
5
Type Annotations
Optionally annotate the type after the variable name:
let x: int = 3.7
/= x
Output:
3
Supported type annotations:
int: truncates numbers to integersfloat: accepts any number (no coercion)bool: converts 0 tofalse, 1 totrue; rejects other numbersstr: only accepts strings
let b: bool = 1
/= b
Output:
true
Assignment
Reassign an existing variable without let:
let x = 5
x = 10
/= x
Output:
10
Operators
Arithmetic
+: addition or string concatenation-: subtraction*: multiplication/: division (errors on division by zero)%: modulo^: exponentiation (right-associative)
/= 2 ^ 3 ^ 2
Output:
512
(Evaluated as 2 ^ (3 ^ 2) = 2 ^ 9 = 512)
Comparison
All comparison operators return booleans:
<: less than>: greater than<=: less than or equal>=: greater than or equal==: equality!=: inequality
/= 5 > 3
Output:
true
Logical
&&: logical AND (short-circuits)||: logical OR (short-circuits)!: logical NOT
/= true && false
Output:
false
/= !true
Output:
false
Operator Precedence
From lowest to highest:
||&&==,!=,<,>,<=,>=+,-*,/,%^(right-associative)- unary
-,! - function calls, array literals
Strings
String literals use double quotes:
/= "hello"
Output:
hello
Escape sequences:
\n: newline\t: tab\\: backslash\": double quote
String Concatenation
Strings concatenate with the + operator. Numbers and booleans are automatically converted:
/= "value: " + 42
Output:
value: 42
/= 100 + " items"
Output:
100 items
Arrays
Literals
Create arrays with square brackets:
/= [1, 2, 3]
Output:
[1, 2, 3]
Arrays can contain mixed types:
/= [1, "two", true]
Output:
[1, "two", true]
Empty arrays:
/= []
Output:
[]
Indexing
Access elements by index (zero-based):
let arr = [10, 20, 30]
/= arr[1]
Output:
20
Negative indices count from the end:
/= [10, 20, 30][-1]
Output:
30
Out-of-bounds access returns an error.
String Indexing
Strings support the same index syntax, returning individual characters:
/= "hello"[0]
Output:
h
Functions
Definition
Define functions with the fn keyword:
fn add(a, b) {
a + b
}
The last expression in the function body is returned implicitly. An explicit return statement is also available for early exit.
fn square(x) {
x * x
}
/= square(5)
Output:
25
Scope
Function parameters are local to the function. The function saves and restores the variable scope:
let x = 10
fn modify() {
x = 5
}
modify()
/= x
Output:
10
(x inside the function is a separate variable; the outer x is unchanged)
Recursion
Functions can call themselves recursively, up to a maximum call depth of 256:
fn fib(n) {
let a = 0
let b = 1
let i = 0
while (i < n) {
let tmp = b
b = a + b
a = tmp
i = i + 1
}
a
}
/= fib(10)
Output:
55
Control Flow
While Loops
Loop while a condition is truthy:
let i = 0
let sum = 0
while (i < 10) {
sum = sum + i
i = i + 1
}
/= sum
Output:
45
Parentheses around the condition are optional (but recommended for clarity).
Loop safety: while loops are limited to 10,000 iterations to prevent infinite loops.
If/Else
Conditional branching with optional else clause:
let x = 10
if x > 5 {
x = 1
} else {
x = 0
}
/= x
Output:
1
Parentheses around the condition are optional. Else-if chaining works:
let grade = 85
let letter = "F"
if grade >= 90 {
letter = "A"
} else if grade >= 80 {
letter = "B"
} else if grade >= 70 {
letter = "C"
}
/= letter
Output:
B
For Loops
Iterate over arrays or ranges:
let sum = 0
for x in [1, 2, 3, 4, 5] {
sum = sum + x
}
/= sum
Output:
15
Using a range expression (start..end, exclusive of end):
let sum = 0
for i in 0..5 {
sum = sum + i
}
/= sum
Output:
10
The range(start, end) builtin function also works:
let sum = 0
for i in range(1, 6) {
sum = sum + i
}
/= sum
Output:
15
For loops are limited to 10,000 iterations.
Return Statements
Use return for early exit from functions:
fn abs_val(x) {
if x < 0 {
return -x
}
x
}
/= abs_val(-7)
Output:
7
Bare return (with no value) returns false.
Builtin Functions
Math Functions
All math functions accept a single number and return a number:
sin(x): sinecos(x): cosinetan(x): tangentasin(x): arc sineacos(x): arc cosineatan(x): arc tangentsqrt(x): square rootabs(x): absolute valuefloor(x): round downceil(x): round upround(x): round to nearest integerln(x): natural logarithmlog(x): base-10 logarithm
/= sqrt(16)
Output:
4
/= abs(-5)
Output:
5
/= floor(3.7)
Output:
3
Range Function
range(start, end) returns an array of numbers from start to end (exclusive):
/= range(0, 5)
Output:
[0, 1, 2, 3, 4]
Length Function
len() returns the length of a string or array:
/= len("hello")
Output:
5
/= len([1, 2, 3])
Output:
3
Truthiness
In boolean contexts (conditions, logical operators), values are truthy or falsy:
- bool:
trueis truthy,falseis falsy - number: 0 is falsy, all other numbers are truthy
- string: empty string is falsy, all other strings are truthy
- array: empty array is falsy, all other arrays are truthy
- void: falsy
- error: falsy
Truthiness matters for if, while, for conditions and &&/|| operators.
Ranges
The .. operator creates an array from start to end (exclusive):
/= 0..5
Output:
[0, 1, 2, 3, 4]
Ranges are primarily useful with for loops and can be stored in variables.
Negative Numbers
Negative number literals are recognized in appropriate contexts:
/= -5
Output:
-5
/= 10 + -3
Output:
7
The unary minus operator also works:
/= -(5 + 3)
Output:
-8
Error Handling
Errors are propagated as error values and displayed with an error: prefix:
/= undefined_var
Output:
error: undefined variable 'undefined_var'
/= 1 / 0
Output:
error: division by zero
Multiple statements execute in sequence, and errors in one statement don't prevent subsequent statements from executing.
Comments
Single-line comments use //:
// This is a comment
let x = 5
/= x
Comments can appear at the end of lines too.
Examples
Multi-step Calculation
let principal = 1000
let rate = 0.05
let years = 10
let amount = principal * (1 + rate) ^ years
/= amount
Output:
1628.89462382...
Fibonacci
fn fib(n) {
let a = 0
let b = 1
let i = 0
while (i < n) {
let tmp = b
b = a + b
a = tmp
i = i + 1
}
a
}
/= fib(15)
Output:
610
String Building
let greeting = "Hello"
let name = "World"
/= greeting + ", " + name + "!"
Output:
Hello, World!
Display Formats
Inline (default)
The standard /= prefix displays the result as a single value on the right edge of the editor:
let x = 42
/= x
Result appears as: → 42
Arrays display inline:
/= [1, 2, 3]
Result: → [1, 2, 3]
Table (/=|)
The /=| prefix renders a 2D array (array of arrays) as a visual table overlay:
let data = [["Name", "Age"], ["Alice", 30], ["Bob", 25]]
/=| data
The first row is treated as the header (rendered bold). Each subsequent row becomes a table row. Non-array values fall back to inline display.
Works with any 2D array:
let matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
/=| matrix
Tree (/=\)
The /=\ prefix renders nested data as an indented tree overlay:
let tree = [1, [2, 3], [4, [5, 6]]]
/=\ tree
Nested arrays are expanded with tree-drawing characters showing depth. Leaf values display inline. The root shows the total element count.
Limitations
- No array mutation: Arrays cannot be modified after creation (no
arr[i] = val) - No mutable references: Variable reassignment creates new bindings in the current scope
- Maximum call depth: 256 function calls deep
- Maximum loop iterations: 10,000 iterations per while/for loop
- No user-defined types or structs
- No imports or modules
- No pattern matching or destructuring
- No closures or lambdas