Acord/CORDIAL_GUIDE.md

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: true or false
  • 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 integers
  • float: accepts any number (no coercion)
  • bool: converts 0 to false, 1 to true; rejects other numbers
  • str: 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:

  1. ||
  2. &&
  3. ==, !=, <, >, <=, >=
  4. +, -
  5. *, /, %
  6. ^ (right-associative)
  7. unary -, !
  8. 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): sine
  • cos(x): cosine
  • tan(x): tangent
  • asin(x): arc sine
  • acos(x): arc cosine
  • atan(x): arc tangent
  • sqrt(x): square root
  • abs(x): absolute value
  • floor(x): round down
  • ceil(x): round up
  • round(x): round to nearest integer
  • ln(x): natural logarithm
  • log(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: true is truthy, false is 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