## What is the purpose of the compiler?
The compiler aims to translate expressions (`Expr<usize>`) produced by the interpreter into gates (`Gate`) read by async-mpc.
## Why are there generic parameters on `Expr`?
We wanted to be able to express both that
1. Add(expr_1, expr_2) is an expression.
2. Add(a, b) = a + b
You'll encounter these `Expr<..>` in the code:
1. `Expr<usize>` is the first one. The `usize` are expression ids.
2. `Expr<ScalarField, bool, BaseField, CurvePoint>` is the second one. `ScalarField`, `bool`, `BaseField`, `CurvePoint` are different types of values used in expressions.
3. `Expr<FieldBounds<ScalarField>, BoolBounds, FieldBounds<BaseField>, CurveBounds>` is used to represent bounds.
4. `Expr<bool>` is sometimes also used.
If you have a function `f: fn(T) -> U`, you can transform `expr: Expr<T>` into `Expr<U>` with `expr.apply(f)`.
If you have 4 functions `f_0: fn(T_0) -> U_0`, `f_1: fn(T_1) -> U_1`, ..., bundled together into `f` through the `ApplyExpr` trait,
you can transform `expr: Expr<T_0, T_1, T_2, T_3>` into `Expr<U_0, U_1, U_2, U_3>` with `expr.apply_2(f)`.
The macros used to make `apply`, `apply_2`, and others work are in the arcis-internal-expr-macro crate.
## Why are there "bounds"?
Some operations, like comparisons, can be done more efficiently on small numbers.
To be able to do such optimizations, we track the interval of possible values of each arithmetic expression.
As we use finite fields, we needed to properly define such possible intervals. See `FieldBounds` to see our choice.
## What is "plaintext"?
Plaintext data is public data. We need this for a few reasons:
* A lot of MPC algorithms use a combination of randomness and opening ("revealing") of data to function.
* A lot of user-written instructions work on a combination of private and public data.
## What are there "global" and "local" "expr_store"?
The expressions are stored in a `IRBuilder`, that is sometimes called an `ExprStore`.
At some point we got tired of writing `let new_expr_id = expr_store.push(Expr::Scalar(FieldExpr::Add(expr_id_0, expr_id_1)));`
and we wanted to write instead `let new_expr = expr_0 + expr_1;`. But the `expr_store` is missing in this code line and needs to be found somehow.
So we created a `thread_local!` global variable which has the expr_store that these functions will target. This global variable and functions to handle it correctly can be found in arcis-compiler/src/core/global_value/global_expr_store.rs.
This is the global `expr_store`. Local `expr_store`s are the ones on the stack, that have to be referenced in the old way.
## Why are there `Field`, `UsedField`, and `ActuallyUsedField`?
`Field` is an external trait of the ff crate.
`UsedField` is a trait that requires `Field`. We created it to have additional functions and performance optimizations (like the caching of powers of 2) that we wanted on our field.
`ActuallyUsedField` is a trait that requires `UsedField`. This means a `Field` that can be actually used in `Expr`, like `ScalarField` and `BaseField`. It has functions to convert from `FieldExpr<Self>` to `Expr<Self>` for instance.
All `UsedField` will eventually be `ActuallyUsedField`. `Mersenne107` will be the next `UsedField` and `ActuallyUedField`.
The traits `UsedField`, and `ActuallyUsedField` can probably be merged together, but we have not tried.
## What is all the code in [circuits](src/core/circuits) about?
There are a lot of more complex MPC algorithms. By putting them here instead of directly in `Expr` or `FieldExpr`, we keep the enums `Expr`, `FieldExpr`, ... small-ish.
This also allows them to be unit-tested automatically via the `TestedArithmeticCircuit` (for arithmetic circuits) trait.
Some of these complex algorithms can be used in expressions through `FieldExpr::SubCircuit`
## What tests do you have?
We have a lot of tests generating random data and testing if our compilation/bound computation works. See [compile_tests.rs](src/core/compile_tests.rs) for the main one.
## What are the known holes in your tests?
We do not have tests checking whether the compiler marks too many expressions as plaintext.
If an arcis-compiler bug were to mark all expressions as plaintext, and therefore visible to everyone, the tests would only detect this because the performance tests would become too good.
We rely on developer review to detect unwanted data leaks in the circuits.