Toy scripting language to calculate math
Everything in this language are math expressions
- Intuitive scripting experience for math
- Eazy to learn with simple language syntax
- With VSCode language extension support
- Mathematic skills are all matters!
- get the
math-langbinary
make sure you have installed rustc and cargo
using the rustup will be helpful
git clone https://github.com/revival0728/math-lang.git
cd math-lang
cargo build --profile releaseYou can download math-lang binary from Release page.
- run the binary
./target/release/math-lang$ math-lang --help
toy scripting language to calculate math
Usage: math-lang [SOURCE]
Arguments:
[SOURCE] Path of source file
Options:
-h, --help Print help
-V, --version Print version
rnum = [raw-number] | [scientific-notation]
vars = [user-defined-variable] | [builtin-constants]
idnt = [vars] | [rnum]
b_op = [+][-][*][/][^][=][mod][:]
s_op = [-]
expr = [idnt] |
[fun-call] |
([expr]) |
[s_op][expr] |
[rnum][[expr]/[rnum]]
[vars][[expr]/[rnum]]
[expr][b_op][expr] |
fun-call = [fun-name]([[] | [expr] | [expr], ...])
def-fun = ([fun-name]([[] | [var] | [var], ...]) = [expr])
- compiler parses the source line by line
- you can checkout MLS script exmaples in the
examples/folder.
the variable or function name must matches regex ([_]|[A-Z]|[a-z])([_]|[A-Z]|[a-z]|[0-9])* which n, _n, n1, _n1, N, ... are all valid
you should never use variable name with format __[name]__, it is used by ENV, compiler and runtime
(s_op)(-) > (:) > (^) > (/) = (*) > (b_op)(-) = (+) > (mod) > (=)
:: is for indexing an arraymod: calculates euclid remainder, which isrand0 <= r < abs(rhs)*: auto insertion bewteen- number and variable
- variable and variable
- right paren and left paren
- number and left paren
types are automatically determined, depends on precision and size of value
Sequence | BigNum > f64 > i64 > i32
where f64, i64, i32 are Rust primitve types, BigNum is used only when precision or size of value is required
BigNum is not implemented yet
currently values are limited by Rust primitive type f64, will change after implementing BigNum
which is in [-1.7976931348623157e+308, 1.7976931348623157e+308]
- just like array in other language
- create a sequence with function
Sequence(len) - indexing a sequence with operator
: - you can chose to use 0-base or 1-base
checkout the example
use char # to comment something, check out example here
- use
import()to import module - module path is Unix like, independant to OS, relative to main script file path
import()checks for duplicate function nameimport()WON'T checks for duplicate variable name- scripts in module will be executed, variables and functions in global scope of module will be imported to parent script
- modules cannot produce outputs
checkout example
| name | value |
|---|---|
| pi | 3.14159265358979323846264338327950288 (std::f64::consts::PI) |
| e | 2.71828182845904523536028747135266250 (std::f64::consts::E) |
| true | 0 |
| false | 1 |
- NOTICE:
trueis 0 andfalseis 1, else if(true) will be false right?
| name | document |
|---|---|
| $(x) | always return None, usually uses as entry point |
| .(x) | always return 1, usually to connect expressions |
- special functions allows you to write formattive code
- the compiler still parses it as single line
- check out example here
In math, it just all ONEs, or should I say only ONE?
| name | document |
|---|---|
| if(x) | return x == 0 where x must be an integer |
| else(x) | return x != 0 where x must be an integer |
| sign(x) | return 1 if x > 0, 0 if x == 0, -1 if x < 0, using Rust f64::total_cmp to compare |
- it works because runtime will check
lhs == 0, if true then will not calcuaterhs
| name | document |
|---|---|
| int32(x) | trunc(x) function but guarantees return type is I32 or else gets RuntimeError |
| name | document |
|---|---|
| print(x) | output x |
| println(x) | output x and a newline |
- outputs by output functions will be buffered until calling
println()or reached end of source - source in REPL is single line
- source in file is entire file
- output functions always output data of variables (including sequences)
| name | document |
|---|---|
| Sequence(len) | return a sequence of length len with elements set to 0 |
| len(seq) | return the length of seq(must be Sequence) |
| name | document |
|---|---|
| import(module) | import the module from Unix like path module which is relative to main script file path |
| name | document |
|---|---|
| abort(msg) | abort the Runtime with msg |
| assert_eq(lhs, rhs, msg) | checks if lhs == rhs by value or else abort the Runtime with msg |
| assert_ne(lhs, rhs, msg) | checks if lhs != rhs by value or else abort the Runtime with msg |
| name | document |
|---|---|
| sin(x) | Rust function |
| cos(x) | Rust function |
| tan(x) | Rust function |
| asin(x) | Rust function |
| acos(x) | Rust function |
| atan(x) | Rust function |
| abs(x) | Rust function |
| sqrt(x) | Rust function |
| ceil(x) | Rust function |
| floor(x) | Rust function |
| round(x) | Rust function |
| exp(x) | Rust function |
| log(x) | Rust function (log10) |
| log2(x) | Rust function (log2) |
| ln(x) | Rust function (log(x, std::f64::consts::E)) |
| trunc(x) | Rust function, return integer part of the argument |
| cbrt(x) | Rust function, return cube root of the argument |
- using
f64::builtin(x)for all Rust primitive types
it is possible to read or get ENV by function __[ENV_name]__(), where [ENV_name] only contains lower case alphabets
- the function always returns current ENV value
- function with argument sets current ENV to the argument value
| ENV | document | default | constraint |
|---|---|---|---|
| PRECISION | the precision of float output | 7 | [0, 15] |
| PRINT_SET_INST | to print set intruction result or not |
repl=1, source=0 | [0, 1] |
| DETAIL_DEPTH | the output level of detail information | repl=0, source=1 | [0, 1] |
| MAX_STACK_DEPTH | the maximum stack depth of recrusive function | 512 | [0, inf] |
| INDEX_BASE | the base of indexing | 0 | [0, 1] |
- maximum stack size is not ENV, but can be configured by execution argument, by default is 64MB
- string literals cannot be stored in variable, parsed as None in this language
- use it to have better output
- escape chars are not supported
- added type function int32()
- added builtin constants true and false
- added control functions abort(), assert_eq() and assert_ne()
- passing variable references into function instead of values
- accessing parent Scope variable while doing recursion
- file ends with comment causes CE::("invalid token")
- implement BigNum, fix i64 and f64 overflow problem (rarely happened)
- improve error message
- fix tail call optimization to recursion
- add type(), hash()
- add function info expression