polenta 0.1.1

A toy language about polynomials over finite-fields
Documentation
# Polenta

![Crates.io Version](https://img.shields.io/crates/v/polenta)
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/erhant/polenta/tests.yml?label=tests)
![Crates.io License](https://img.shields.io/crates/l/polenta)

Polenta is a toy polynomial arithmetic language, and **everything** is a polynomial. As such, it is more suited towards having fun instead of having performance.

## Features

- [x] Polynomial arithmetic using [lambdaworks]https://github.com/lambdaclass/lambdaworks
- [x] REPL to play around with
- [x] `let` and `assert` expressions
- [ ] `prove` and `commit` expressions

> The project mostly started to learn more about Pest, and it is a lovely project! See <https://pest.rs> for more!

## Installation

You can add the library with:

```sh
cargo add polenta
```

You can install the REPL with:

```sh
cargo install polenta --bin repl --features="repl"
```

## Usage

In this section we go over what can be done with Polenta.

> All code shown below are valid Polenta code. To follow along, you can use the REPL installed above!

### Statements

You can use Polenta as a calculator-over-field.

```rs
> 10 - 2^3 * 2;
18446744069414584315
```

However, you should keep in mind that all operations are defined over the field, so division might not always work as you expect:

```rs
> 1 / 2; // some number x such that 2*x = 1, not 0.5!
9223372034707292161
```

> Polenta supports single line comments using `//`, as shown above.

### Creating a Polynomial

A polynomial is created by specifying its terms.

```rs
> let P(x) = 3*x^2 + 5;
3*x^2 + 5
```

Behind the scenes all terms are considered a monomial, and they are composed together. As such, you can repeat a term with the same degree and the result will have them added up:

```rs
> let P(x) = 3*x^2 + 2*x^2 + 1*x^2;
6*x^2
> let Q(x) = 5*x - 5*x + 1;
1
```

You can also multiply polynomials:

```rs
> let P(x) = (x + 1)*(x + 2)*(x + 4);
x^3 + 7*x^2 + 14*x + 8
```

You can create a polynomial from an existing one:

```rs
> let P(x) = 3*x;
3*x
> let Q(x) = P^2 + 2*P;
9*x^2 + 6*x
```

Shadowing is allowed:

```rs
> let P(x) = 3*x;
3*x
> let P(x) = 3*P + 5;
9*x + 5
```

You can use an identifier within a polynomial, but if the identifier has the same name as the term, it will be ignored.

```rs
> let t = 2;
> let x = 5;
> let P(x) = x^t + 2*x;
x^2 + 2*x
```

### Equality

Polenta has `==` and `!=` operators that return either a 1 or 0 based on the equality.

```rs
> 2 == 3
0
> let P(x) = 2*x
2*x
> let Q(x) = 3*x - x
2*x
> P == Q
1
```

### Evaluating a Polynomial

Evaluation is achieved using a binary operation `@`, so that `P@2` means "evaluate polynomial `P` at point `2`.

```rs
> let P(x) = 3*x;
3*x
> let z = P@3;
9
> let Q(x) = x^z + z*x;
x^9 + 9*x
```

Remember that everything is a polynomial in Polenta, so you could evaluate a number as well. Evaluation will not have an effect because a number is treated as a constant polynomial.

```rs
> 4@2
4
```

Since evaluation is a binary operation, you can chain them together:

```rs
> let P(x) = 3*x + 1;
3*x + 1
> let Q(x) = x/2;
9223372034707292161*x
> Q@P@Q@P@3; // Q(P(Q(P(3))))
8
```

### Assertions

You can make assertions within Polenta for safety, where a failed assertion throws an `AssertionError`.
An assertion fails if the expression that they are given is a zero polynomial.

```rs
> assert 1
1
> assert 0
  × Assertion Failed

> assert 43
43
```

### Errors in REPL

While using REPL, if there is an error you will see it on screen with clear logs.

```sh
> let x = idontexist;
  × Unknown Identifier: idontexist
> 5/0;
  × Division by Zero
> let a = ++syntaxerror--;
  × Syntax Error
   ╭─[input:1:9]
 1 │ let a = ++syntaxerror--;
   ·         ─
   ╰────
  help: Expected one of [expr], got []
```

## Testing

Run all tests with:

```sh
cargo test
```

## License

Polenta is MIT licensed.