openbirch-rs/README.md
2025-03-20 12:30:31 +01:00

207 lines
4 KiB
Markdown

# Openbirch Rust
Openbirch rewritten in rust.
Very messy and bad, im gonna start the umpteenth rewrite soon.
# Features
- [x] Constants (numbers)
- [x] Addition
- [x] Subtraction
- [x] Multiplication
- [x] Division
- [x] Arbitrary float precision
- [ ] Sets (or lists, arrays, etc)
- [x] Definition
- [x] Multiplication with constants
- [x] Concattenation
- [ ] Index operator
- [x] Functions
- [x] Native functions
- [x] User defined functions
- [x] Currying
- [x] Closures
- [x] Calling
- [x] Scopes
- [x] Shadowing variables
- [ ] Ranges
- [x] Defining ranges (`1..5` is a range of `[1..5)`)
- [ ] Iterating ranges
- [x] Evaluating ranges (very hacky, but defining a Set of length 1 with a range expands said range into the set, eg `[1..3]` becomes `[1,2]`)
- [ ] Loops
- [x] Infinite loops (`loop ... end` block)
- [ ] For loops (`for x in y ... end` block)
- [x] Break keyword
- [ ] Match expression
- [x] If expression
- [x] If expression
- [x] If-else expression
## Wanted
- [ ] More concise syntax, i dont like how it is right now
- [ ] Fix stack overflow with recursive functions (internally convert to loops)
- [ ] Generally implement more
- [ ] Implicit multiplication (may not be possible to implement non-ambiguously)
- [ ] Differentiation
- [ ] Integration
- [ ] Better error handling (i was lazy and skimped on errors, bad move)
# Syntax
Every Openbirch program is made up of 0 or more *expressions*.
An expression is anything from a binary operation like `2+2` to function calls `f(x)` and
even assignments `x := 5`.
All expressions return a value. For expressions that "dont" they return an `Empty`, which cant
be used for anything and will error if used in other operations (eg. `2+{Empty}`).
## Definition
Variables can be defined with a `define` expression.
```
x := 5 # define x as 5
print(x+x) # prints 10
```
As openbirch is a symbolic language variables can be used before assignment
```
y := x^2
print(y) # prints x^2
x := 5
print(y) # prints 25
```
### Scopes
Some expressions define a *scope*, where all defined variables inside will be deleted once the scope ends.
Expressions that create a scope include, but are not limited to,
- If-else
- Loop
- Functions
- Closures
If a variable is defined outside a scope it will be *shadowed* inside the scope. What this means
is that inside the scope the variable will have the shadowed value, while outside the scope it
will have the previous value.
```
x := 5 # Global scope
print(x) # prints 5
if true then # Define a new scope
x := 5000 # Shadow the value of x
print(x) # prints 5000
end # Scope ends here
print(x) # prints 5
```
### Assignment
Since you may want to change the value of a variable outside the current scope you can use an `assignment` rather than a definition.
```
x := 5
if true then
x <- 500 # Assign to x rather than defining it and shadowing it
end
print(x) # prints 500
```
## If-else
If expressions are defined as such
```
if {condition} then
# 0 or more statements
end
```
and if-else as
```
if {condition} then
# 0 or more statements
else
{expression}
end
```
Since `if` is an expression the body of the else branch can be another if expression, in which
case only 1 `end` keyword is needed.
```
if {condition} then
# 0 or more statements
else if {condition} then
# 0 or more statements
end
```
Since all expressions evaluate to a value the value of the if expression is the resulting value
of the last statement in the chosen branch, eg.
```
x := if true then
# Evaluate some expressions
2+2
f(x)
y := f(f(x))
# Last expression is returned
5
else
0
end
print(x) # prints 5
```
if a branch is empty then `Empty` is returned.
## Loops
Currently the only type of loop is an infinite loop.
```
loop
# This will repeat forever
end
```
# Running
## Linux
```sh
$ cargo run
```
### Nixos
```sh
$ nix develop
$ cargo run
```
## Windows
idfk, havent used that shit in years, but probably just `cargo run`.
## MacOS
never used, but again probably `cargo run`