kestell.org

Willow

Willow is an interpreter for a dynamically-typed imperative programming language.

Core Concepts

Variables and Assignment

Variables store values and are created through assignment. No declaration is needed.

name = "Alice"
age = 30
pi = 3.14159
is_active = true

Data Types

Willow supports several primitive data types:

Strings

Text enclosed in quotes.

greeting = "Hello, world!"

Numbers

Integer or floating-point values.

integer = 42
decimal = 3.14

Booleans

Logical true/false values.

is_enabled = true
has_errors = false

Lists

Ordered collections of values, can be mixed types.

numbers = [1, 2, 3, 4, 5]
mixed = [1, "two", true, 3.14]
empty = []

Operators

Arithmetic Operators

sum = 10 + 5      # Addition (15)
diff = 10 - 5     # Subtraction (5)
prod = 10 * 5     # Multiplication (50)
quot = 10 / 5     # Division (2)
neg = -5          # Negation (-5)

Follows standard order of operations:

result1 = 1 + 2 * 3     # 7 (multiplication first)
result2 = (1 + 2) * 3   # 9 (parentheses first)

Comparison Operators

x = 10
y = 20

x < y      # Less than (true)
x > y      # Greater than (false)
x == y     # Equal to (false)
x != y     # Not equal to (true)
x <= y     # Less than or equal to (true)
x >= y     # Greater than or equal to (false)

Logical Operators

a = true
b = false

a && b     # Logical AND (false)
a || b     # Logical OR (true)
!a         # Logical NOT (false)
!b         # Logical NOT (true)

String Concatenation

The + operator concatenates strings with any type.

name = "Alice"
greeting = "Hello, " + name + "!"  # "Hello, Alice!"

Control Structures

Conditional Statements

Basic if-else structure:

if x > y do
    print("x is greater than y")
else
    print("x is not greater than y")
end

Nested conditionals:

if x > 100 do
    print("x is very large")
else if x > 50 do
    print("x is large")
else if x > 5 do
    print("x is medium")
else
    print("x is small")
end

Loops

For Loops

Iterate through a range of numbers:

for i = 1 to 5 do
    print("i = " + i)
end

While Loops

Execute while a condition is true:

count = 5
while count > 0 do
    print("count = " + count)
    count = count - 1
end

Breaking out of Loops

The break statement exits a loop:

i = 0
while true do  # Infinite loop
    i = i + 1
    print("i = " + i)
    if i >= 3 do
        print("Breaking the loop")
        break
    end
end

Data Structures

Lists

Creating Lists

numbers = [1, 2, 3, 4, 5]       # List of numbers
mixed = [1, "two", true, 3.14]  # Mixed types
empty = []                      # Empty list

Accessing Elements

Lists are zero-indexed:

first = numbers[0]   # 1
last = numbers[4]    # 5

Modifying Elements

numbers[2] = 999     # [1, 2, 999, 4, 5]

List Functions

len(numbers)         # 5 (length of list)
push(numbers, 6)     # Adds 6 to the end: [1, 2, 999, 4, 5, 6]
popped = pop(numbers) # Removes last element: popped = 6, numbers = [1, 2, 999, 4, 5]

Nested Lists

Lists can contain other lists:

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

element = matrix[1][2]  # Access element (6)

Functions

Defining Functions

def greet(person) do
    return "Hello, " + person + "!"
end

Calling Functions

message = greet("Bob")  # "Hello, Bob!"

Multiple Parameters

def add(a, b) do
    return a + b
end

sum = add(5, 10)  # 15

Conditionals in Functions

def max(a, b) do
    if a > b do
        return a
    else
        return b
    end
end

maximum = max(15, 10)  # 15

Recursive Functions

Functions can call themselves:

def factorial(n) do
    if n <= 1 do
        return 1
    end
    return n * factorial(n - 1)
end

fact5 = factorial(5)  # 120 (5 * 4 * 3 * 2 * 1)

Working with Lists

Functions can manipulate lists:

def sum_list(list) do
    total = 0
    for i = 0 to len(list) - 1 do
        total = total + list[i]
    end
    return total
end

total = sum_list([1, 2, 3, 4, 5])  # 15

Returning Lists

Functions can return lists:

def create_range(start_val, end_val) do
    result = []
    for i = start_val to end_val do
        push(result, i)
    end
    return result
end

range = create_range(1, 5)  # [1, 2, 3, 4, 5]

Higher-Order Functions

Functions can take other functions as parameters:

def apply_twice(func, x) do
    return func(func(x))
end

def double(x) do
    return x * 2
end

result = apply_twice(double, 3)  # 12 (double(double(3)))

Advanced Examples

Fibonacci Sequence (Recursive)

def fibonacci(n) do
    if n <= 1 do
        return n
    end
    return fibonacci(n - 1) + fibonacci(n - 2)
end

fib6 = fibonacci(6)  # 8

Fibonacci Sequence (Iterative)

def fibonacci_list(n) do
    result = [0, 1]
    if n <= 1 do
        return [result[0]]
    end

    for i = 2 to n do
        next_fib = result[i-1] + result[i-2]
        push(result, next_fib)
    end

    return result
end

fibs = fibonacci_list(10)  # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

Built-in Functions

Willow provides several built-in functions:

print()

Displays values to the output.

print("Hello, world!")
print(42)
print([1, 2, 3])

len()

Returns the length of a string or list.

len("hello")  # 5
len([1, 2, 3])  # 3

push()

Adds an element to the end of a list.

list = [1, 2, 3]
push(list, 4)  # list becomes [1, 2, 3, 4]

pop()

Removes and returns the last element of a list.

list = [1, 2, 3, 4]
value = pop(list)  # value = 4, list becomes [1, 2, 3]

Source

The source code for Willow is available on GitHub.