passerine 0.7.1

A small extensible programming language designed for concise expression with little code.
Documentation
-{
    # A complete overview of Passerine, in Passerine
    Passerine intends to be a fast, extensible, modern programming language.
    Passerine is structurally typed, and has support for traits and the like.
}-

-{
    ## Part I: Datatypes
    Passerine supports all the standard datatypes you'd expect.
    First off, the atomic datatypes:
}-

-- Numeric Tower
69    -- Naturals
-420  -- Integers
2/3   -- Rationals
6.25  -- Reals
2+3i  -- Imaginaries

-- Booleans
true
false -- all values but true are false

-- Strings
"Hello, World!" -- Strings
"Really? 😮"    -- Unicode Support
"\b00\bFF"      -- Insert bytes

-{
    Passerine also supports algebraic datatypes, such as:
}-

-- Tuples
(1, "Hello", true) -- sized collections of different datatypes

-- Lists
[1, 2, 3, 4, 5] -- variable length collections of the same datatype

-- Unions
2D {x, y} ~ 3D {x, y, z} ~ ND [d..] -- Tagged enumerations of different datatypes -- Tagged yay/nay?

-- Structures
{x, y, z} -- Named fields that hold values

-- Maps
{"Heck": true, 0: (1, False)} -- Dictionaries, a catch-all hodgepodge -- Include?

-{
    ## PART II: Patterns
    A pattern de-structures a datatype into bindings.
    Patterns mirror the datatypes they de-structure, but with symbols capturing the values in the corresponding places.
    `..` and `_` are used to collect and/or discard extra leftover values.
}-

-- For example, the pattern:
{x: (a, b, [h, t..]), ..}

-- matches
{y: 0, x: (1, "Hello", [true, false, true])}

-- and would produce the bindings:
a = 1
b = "Hello"
h = true
t = [false, true]

-- Additionally, patterns can contain guards: conditions that must be met for the pattern to match.
-- For example, the pattern:
x | x > 0

-- matches all values `x` where `x` is greater than `0`.
-- To check multiple conditions, use `and`.
(x, y) | x > 0 and y > 0

-{
    ## Part III: Assignment
    An assignment produces a binding in the current scope, or updates an older binding by the same name.
    A binding maps a name (symbol) to a value - it's a variable.
}-

-- An assignment takes the form:
p = e

-- where p is a pattern and e is an expression.
-{
    To evaluate an assignment:
    1. Evaluate expression `e` into value `v`.
    2. Match value `v` against the pattern `p`, producing a set of bindings `b`.
    3. For each binding in `b`, update old binding in current scope or produce new one.
    4. Evaluates to Unit: `()`.
}-

-- For example:
(a, b) = (1 + 2, 3 * 5)

-- 1. Evaluate `e`:
(a, b) = (3, 15)

-- 2. Produce bindings:
a = 3
b = 15

-- 3. Update...

-- 4. Evaluate to unit:
()

-{
    # Part IV: Lambda
    A lambda expression produces an anonymous function that transforms one value into another.
    Lambda expressions are used to create closures, and in combination with assignment, named functions.
}-

-- A lambda expression takes the form:
p -> e0

-- Where `p` is a pattern, and `e` is an expression, and produces a new anonymous function.
-- To evaluate an anonymous function, given:
(p -> e0) e1

-- Where `(p -> e0)` is an anonymous function, and `e1` is an expression:
-- 1. Evaluate `e1` to the value `v0`.
-- 2. Match value `v0` against the pattern `p`, producing a set of bindings `b`.
-- 3. Evaluate the expression `e0` in a new scope with bindings `b`, producing a new value `v1`.
-- 4. Evaluates to `v1`.

-{
    # Part IV: Blocks
    Blocks evaluate multiple expressions in a row, and take on the value of the last expression.
}-

-- For instance:

{
    x = 5
    y = x + 2
    x * y + 2
}

-- would evaluate to:
37

-- Blocks are very useful in combination with functions:

perms = seq -> {
    match (len sequence) [
        x | x <= 1 -> yield seq
        x -> {
            [head, tail..] = seq
            for perm (perms tail) {
                for i 0..((len perm)) {
                    yield perm[..i] + head + perm[i..]
                }
            }
        }
    ]
}


# Macros
# Fibers

Fibers can be:
- called: `<standard>`
- run: `!`
- tried: `?`
- yielded: `yield`
- aborted: `error`