matrix-bin | ||
matrix-lang | ||
matrix-macros | ||
matrix-std | ||
.gitignore | ||
Cargo.lock | ||
Cargo.toml | ||
LICENSE | ||
README.md | ||
test.mat | ||
test.matc |
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(<iterable>) , once(<any>) |
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
, orComplex
of value 0Bool
of value falseString
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(<iter>)
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