# matrix `matrix` is a programming language, for use as a calculator, general math, and other scripting. To compile and install matrix run `cargo install --path .`. ## Types `matrix` contains 16 builtin types. | Type | Description | Examples | |-------------|---------------------------------------------------------|-----------------------------------| | `Nil` | Represents nothing (null) | `Nil` | | `Bool` | Boolean type `true` or `false` | `true`, `false`, | | `Int` | A 64bit signed integer | `0`, `-13`, `999` | | `Float` | A 64bit floating point decimal | `1.3`, `NaN`, `inf` | | `Ratio` | A fratcional object consisting of two 64bit signed ints | `1/3`, `0/5`, `-3/8` | | `Complex` | A complex number consisting of two 64bit floats | `0+1i`, `13-2i`, | | `Regex` | A compiled regex string | `r'$test'`, `r"test"` | | `String` | A variable length string | `'test'`, `"test"` | | `List` | A heterogeneous list | `[]`, `[1 true]`, | | `Matrix` | A heterogeneous matrix with a domain and codomain | `[1 2;3 4]`, `mat([1 2])` | | `Table` | A heterogeneous table or map | `:{}`, `:{bees = 'bees'}` | | `Function` | A compiled or builtin native function | `fn a (e) { e }`, `a = \e => e` | | `Range` | A iterator from one Int to another Int | `0..1`, `10..=20` | | `Iter` | A closed iterator object | `iter()`, `once()` | | `File` | A currently open file on the system | `file_open('test.txt', 'r')` | | `Exception` | A error or exception thrown by the vm or the user | `throw()`, `throw(1,2,3)` | ## Truthiness All types are automatically considered true unless - `Nil` - `Int`, `Float`, `Ratio`, or `Complex` of value 0 - `Bool` of value false - `String` of length 0 ## String Escapes When writing strings (or regexies), these are the following escapes you can use | Escape | Character | |------------|---------------------------| | `\\` | Backslash | | `\0` | Null Byte | | `\a` | Bell | | `\b` | Backspace | | `\t` | Horizontal Tab | | `\n` | Line Feed | | `\v` | Vertical Tab | | `\f` | Form Feed | | `\r` | Cariage Return | | `\e` | Escape | | `\x##` | Utf8 codepoint (single) | | `\u{##..}` | Utf8 codepoint (any size) | ## Operators All `matrix` operators in order of high to low precedence from top down | Name | Operator | Associativity | Examples | |--------------------------------|----------------------------------------------------------------------------------------|---------------|--------------------| | Field access | | left to right | `a.b` | | Function calls | | left to right | `a()`, `a(1, 2)` | | `Negate`, `Not` | `-`, `!` | none (unary) | `-3`, `!a` | | `Power` | `**` | right to left | `3**4` | | `Multiply`, `Divide`, `Modulo` | `*`, `/`, `%` | left to right | `2 * 3 / 4` | | `Add`, `Subtract` | `+`, `-` | left to right | `1 + 2` | | Bitwise shift | `<<`, `>>` | left to right | `13 << 2` | | Bitwise `And` | `&` | left to right | `a & 0xC3` | | Bitwise `Xor` | `^` | left to right | `3 ^ 4` | | Bitwise `Or` | `\|` | left to right | `b \| 0xC3` | | Comparison | `==`, `!=`, `<`, `>`, `<=`, `>=` | left to right | `a == b`, `c != d` | | `And` | `&&` | left to right | `res && other` | | `Or` | `\|\|` | left to right | `this \|| that` | | `Range` | `..`, `..=` | left to right | `1..2`, `10..=20` | | `Assign`, `OpAssign` | `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `\|=`, `^=`, `<<=`, `>>=`, `**=`, `&&=`, `\|\|=` | right to left | `a = 3`, `i += 1` | ## Variables and Scope Unless running inside a REPL, all variables besides the standard library functions are locally scopped. Meaning they are only accessable from inside their scope, and will be deleted once that scope is left. If running in a REPL, all variables in the root scope will be globals. Variables can be defiend though `Assignment`, `Let`, or `Const`. Assignment will overwrite if the variable already exists, or create if it doesnt. Let will only create a mutable variable. Cosnt will only create a immutable variable. If `Let` or `Cosnt` try to redefine a variable, an exception will be thrown. ``` a = 3; // a is 3 { println(a); // prints 3 let a = 4; // local a is 4 println(a); // prints 4 b = 3 // b is 3 } println(b) // undefined b, error println(a); // prints 3 let a = 5; // redefined a, error ``` ## Expression Control Flow `matrix` is an expression based language, meaning everything is data, and everything is control flow. Every type of expression will always return a value, even if its `Nil`. You can assign functions to variables, blocks to tables, or function calls to lists. The order of execution is always from left to right, unless when using a pipeline when its left to righ t for the pipeline and right to left to each pipeline component. ``` let a = { const bees = \a => a * 2; bees(33) } // a is 66 for i in 0..a { // prints 0 inclusive though 66 exclusive println(i) } ``` ## Looping `matrix` supports four types of loops, `Loop`, `While`, `DoWhile`, and `For`. `While` and `Loop` are the same except `Loop` doesn't have a condition while `While` does. Both of these loops will check the condition first, then run the body if true. If false it will break the loop. `DoWhile` is a backwards `While`, in which the body is run first, when the condition is checked. `For` is the special out of the four since it takes an `Iterator` as an argument (see iterators). For will run the body until the `Iterator` stops (returns `Nil`). ``` while 1 { ... } loop { ... } do { ... } while 1; for i in 0..10 { ... } ``` ## Functions `matrix` supports a single function type, but with two seperate syntaxes. First you can create a normal function with the `Function` or `Fn` keywords, specify the name, optionally specify the paramaters, and then specify the function body. Second you can create a lambda function with the lambda syntax, which is the same except paramaters must be specified. ``` fn bees {} fn bees a a fn bees (a) a fn bees (a,b) a+b let bees = \=> {} let bees = \a => a let bees = \(a,b) => a + b ``` ## Partial Function Application If you dont specify the full amount of paramaters to a function, instead of throwing an error, instead you get back a partial function call. This is another special function that takes in the remaining paramaters to the origonal function, and appends them to the inital paramaters. ``` let bees = \(a,b,c) => a+b*c; let bees2 = bees(2) let bees24 = bees2(4) bees24(5) // is the same as bees(2,4,5) ``` ## Iterators `Iterators` are a special closed object in `matrix` that cannot be accessed or called. They can only be used inside forloops, pipelines, and the `next` std function. Iterators will be called forever until they return a stop value, which in matrix is always `Nil`. This has the side effect of stopping iteration early if there is a `Nil` in the middle of your data, so do not let this happen. Iterators must always be able to be called unlimited times, since its not gurenteed that after the first `Nil`, that it will never be called again. To retrieve values from a iterator: - run it inside a `for` loop consuming the entire iterator - run it in a pipeline consuming an arbitrary amount of the iterator - run `next()` to consime and return a single value from the iterator Finally, many different types can be auto promoted to an iterator. These include `List`, `Range`, and `Function`. Lists will iterate over their elements. Ranges will iterate from the range start inclsive to the range end execlusive, stepping by 1. And functions will be called forever until they return `Nil`. ## Pipelines Pipelines are syntax sugar for nested function calls. ``` b(a(3)) // is the same as 3 |> a |> b ``` The only difference is that each part of a pipeline is evaluated from right to left instead of left to right. ``` 0..4 |> map(\a=>a**2) |> filter(\a=>a!=0) |> list // [1, 3, 9] ``` ## License This project is licensed under the MIT License