1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00
ZoKrates/zokrates_ast/src/zir/mod.rs
2022-11-09 18:57:30 +01:00

845 lines
26 KiB
Rust

pub mod folder;
mod from_typed;
mod identifier;
pub mod lqc;
mod parameter;
pub mod result_folder;
pub mod types;
mod uint;
mod variable;
pub use self::parameter::Parameter;
pub use self::types::{Type, UBitwidth};
pub use self::variable::Variable;
use crate::common::{FlatEmbed, FormatString};
use crate::typed::ConcreteType;
pub use crate::zir::uint::{ShouldReduce, UExpression, UExpressionInner, UMetadata};
use crate::zir::types::Signature;
use std::convert::TryFrom;
use std::fmt;
use zokrates_field::Field;
pub use self::folder::Folder;
pub use self::identifier::{Identifier, SourceIdentifier};
use serde::{Deserialize, Serialize};
/// A typed program as a collection of modules, one of them being the main
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct ZirProgram<'ast, T> {
pub main: ZirFunction<'ast, T>,
}
impl<'ast, T: fmt::Display> fmt::Display for ZirProgram<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.main)
}
}
/// A typed function
#[derive(Clone, PartialEq, Hash, Eq, Serialize, Deserialize)]
pub struct ZirFunction<'ast, T> {
/// Arguments of the function
#[serde(borrow)]
pub arguments: Vec<Parameter<'ast>>,
/// Vector of statements that are executed when running the function
#[serde(borrow)]
pub statements: Vec<ZirStatement<'ast, T>>,
/// function signature
pub signature: Signature,
}
impl<'ast, T: fmt::Display> fmt::Display for ZirFunction<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(
f,
"({}) -> ({}) {{",
self.arguments
.iter()
.map(|x| format!("{}", x))
.collect::<Vec<_>>()
.join(", "),
self.signature
.outputs
.iter()
.map(|x| format!("{}", x))
.collect::<Vec<_>>()
.join(", ")
)?;
for s in &self.statements {
s.fmt_indented(f, 1)?;
writeln!(f)?;
}
writeln!(f, "}}")
}
}
impl<'ast, T: fmt::Debug> fmt::Debug for ZirFunction<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"ZirFunction(arguments: {:?}, ...):\n{}",
self.arguments,
self.statements
.iter()
.map(|x| format!("\t{:?}", x))
.collect::<Vec<_>>()
.join("\n")
)
}
}
pub type ZirAssignee<'ast> = Variable<'ast>;
#[derive(Debug, Clone, PartialEq, Hash, Eq, Serialize, Deserialize)]
pub enum RuntimeError {
SourceAssertion(String),
SelectRangeCheck,
DivisionByZero,
IncompleteDynamicRange,
}
impl fmt::Display for RuntimeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RuntimeError::SourceAssertion(message) => write!(f, "{}", message),
RuntimeError::SelectRangeCheck => write!(f, "Range check on array access"),
RuntimeError::DivisionByZero => write!(f, "Division by zero"),
RuntimeError::IncompleteDynamicRange => write!(f, "Dynamic comparison is incomplete"),
}
}
}
impl RuntimeError {
pub fn mock() -> Self {
RuntimeError::SourceAssertion(String::default())
}
}
#[derive(Clone, PartialEq, Hash, Eq, Debug, Serialize, Deserialize)]
pub enum ZirAssemblyStatement<'ast, T> {
Assignment(
#[serde(borrow)] Vec<ZirAssignee<'ast>>,
ZirFunction<'ast, T>,
),
Constraint(
FieldElementExpression<'ast, T>,
FieldElementExpression<'ast, T>,
),
}
impl<'ast, T: fmt::Display> fmt::Display for ZirAssemblyStatement<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ZirAssemblyStatement::Assignment(ref lhs, ref rhs) => {
write!(
f,
"{} <-- {}",
lhs.iter()
.map(|a| a.id.to_string())
.collect::<Vec<String>>()
.join(", "),
rhs
)
}
ZirAssemblyStatement::Constraint(ref lhs, ref rhs) => {
write!(f, "{} === {}", lhs, rhs)
}
}
}
}
/// A statement in a `ZirFunction`
#[derive(Clone, PartialEq, Hash, Eq, Debug, Serialize, Deserialize)]
pub enum ZirStatement<'ast, T> {
Return(Vec<ZirExpression<'ast, T>>),
Definition(ZirAssignee<'ast>, ZirExpression<'ast, T>),
IfElse(
BooleanExpression<'ast, T>,
Vec<ZirStatement<'ast, T>>,
Vec<ZirStatement<'ast, T>>,
),
Assertion(BooleanExpression<'ast, T>, RuntimeError),
MultipleDefinition(Vec<ZirAssignee<'ast>>, ZirExpressionList<'ast, T>),
Log(
FormatString,
Vec<(ConcreteType, Vec<ZirExpression<'ast, T>>)>,
),
Assembly(#[serde(borrow)] Vec<ZirAssemblyStatement<'ast, T>>),
}
impl<'ast, T: fmt::Display> fmt::Display for ZirStatement<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.fmt_indented(f, 0)
}
}
impl<'ast, T: fmt::Display> ZirStatement<'ast, T> {
fn fmt_indented(&self, f: &mut fmt::Formatter, depth: usize) -> fmt::Result {
write!(f, "{}", "\t".repeat(depth))?;
match self {
ZirStatement::Return(ref exprs) => {
write!(f, "return")?;
if !exprs.is_empty() {
write!(
f,
" {}",
exprs
.iter()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join(", ")
)?;
}
write!(f, ";")
}
ZirStatement::Definition(ref lhs, ref rhs) => {
write!(f, "{} = {};", lhs, rhs)
}
ZirStatement::IfElse(ref condition, ref consequence, ref alternative) => {
writeln!(f, "if {} {{", condition)?;
for s in consequence {
s.fmt_indented(f, depth + 1)?;
writeln!(f)?;
}
writeln!(f, "{}}} else {{", "\t".repeat(depth))?;
for s in alternative {
s.fmt_indented(f, depth + 1)?;
writeln!(f)?;
}
write!(f, "{}}}", "\t".repeat(depth))
}
ZirStatement::Assertion(ref e, ref error) => {
write!(f, "assert({}", e)?;
match error {
RuntimeError::SourceAssertion(message) => write!(f, ", \"{}\");", message),
error => write!(f, "); // {}", error),
}
}
ZirStatement::MultipleDefinition(ref ids, ref rhs) => {
for (i, id) in ids.iter().enumerate() {
write!(f, "{}", id)?;
if i < ids.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, " = {};", rhs)
}
ZirStatement::Log(ref l, ref expressions) => write!(
f,
"log(\"{}\"), {});",
l,
expressions
.iter()
.map(|(_, e)| format!(
"[{}]",
e.iter()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join(", ")
))
.collect::<Vec<_>>()
.join(", ")
),
ZirStatement::Assembly(statements) => {
writeln!(f, "asm {{")?;
for s in statements {
writeln!(f, "{}{}", "\t".repeat(depth + 1), s)?;
}
write!(f, "{}}}", "\t".repeat(depth))
}
}
}
}
pub trait Typed {
fn get_type(&self) -> Type;
}
#[derive(Debug, Clone, PartialEq, Hash, Eq, Serialize, Deserialize)]
pub struct ConditionalExpression<'ast, T, E> {
#[serde(borrow)]
pub condition: Box<BooleanExpression<'ast, T>>,
pub consequence: Box<E>,
pub alternative: Box<E>,
}
impl<'ast, T, E> ConditionalExpression<'ast, T, E> {
pub fn new(condition: BooleanExpression<'ast, T>, consequence: E, alternative: E) -> Self {
ConditionalExpression {
condition: box condition,
consequence: box consequence,
alternative: box alternative,
}
}
}
impl<'ast, T: fmt::Display, E: fmt::Display> fmt::Display for ConditionalExpression<'ast, T, E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{} ? {} : {}",
self.condition, self.consequence, self.alternative
)
}
}
#[derive(Debug, Clone, PartialEq, Hash, Eq, Serialize, Deserialize)]
pub struct SelectExpression<'ast, T, E> {
pub array: Vec<E>,
#[serde(borrow)]
pub index: Box<UExpression<'ast, T>>,
}
impl<'ast, T, E> SelectExpression<'ast, T, E> {
pub fn new(array: Vec<E>, index: UExpression<'ast, T>) -> Self {
SelectExpression {
array,
index: box index,
}
}
}
impl<'ast, T: fmt::Display, E: fmt::Display> fmt::Display for SelectExpression<'ast, T, E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}[{}]",
self.array
.iter()
.map(|a| a.to_string())
.collect::<Vec<_>>()
.join(", "),
self.index
)
}
}
/// A typed expression
#[derive(Clone, PartialEq, Hash, Eq, Serialize, Deserialize)]
pub enum ZirExpression<'ast, T> {
Boolean(BooleanExpression<'ast, T>),
FieldElement(FieldElementExpression<'ast, T>),
Uint(#[serde(borrow)] UExpression<'ast, T>),
}
impl<'ast, T: Field> From<BooleanExpression<'ast, T>> for ZirExpression<'ast, T> {
fn from(e: BooleanExpression<'ast, T>) -> ZirExpression<T> {
ZirExpression::Boolean(e)
}
}
impl<'ast, T: Field> From<FieldElementExpression<'ast, T>> for ZirExpression<'ast, T> {
fn from(e: FieldElementExpression<'ast, T>) -> ZirExpression<T> {
ZirExpression::FieldElement(e)
}
}
impl<'ast, T: Field> From<UExpression<'ast, T>> for ZirExpression<'ast, T> {
fn from(e: UExpression<'ast, T>) -> ZirExpression<T> {
ZirExpression::Uint(e)
}
}
impl<'ast, T: fmt::Display> fmt::Display for ZirExpression<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ZirExpression::Boolean(ref e) => write!(f, "{}", e),
ZirExpression::FieldElement(ref e) => write!(f, "{}", e),
ZirExpression::Uint(ref e) => write!(f, "{}", e),
}
}
}
impl<'ast, T: fmt::Debug> fmt::Debug for ZirExpression<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ZirExpression::Boolean(ref e) => write!(f, "{:?}", e),
ZirExpression::FieldElement(ref e) => write!(f, "{:?}", e),
ZirExpression::Uint(ref e) => write!(f, "{:?}", e),
}
}
}
impl<'ast, T: Field> Typed for ZirExpression<'ast, T> {
fn get_type(&self) -> Type {
match *self {
ZirExpression::Boolean(ref e) => e.get_type(),
ZirExpression::FieldElement(ref e) => e.get_type(),
ZirExpression::Uint(ref e) => e.get_type(),
}
}
}
impl<'ast, T: Field> Typed for FieldElementExpression<'ast, T> {
fn get_type(&self) -> Type {
Type::FieldElement
}
}
impl<'ast, T: Field> Typed for UExpression<'ast, T> {
fn get_type(&self) -> Type {
Type::Uint(self.bitwidth)
}
}
impl<'ast, T: Field> Typed for BooleanExpression<'ast, T> {
fn get_type(&self) -> Type {
Type::Boolean
}
}
pub trait MultiTyped {
fn get_types(&self) -> &Vec<Type>;
}
#[derive(Clone, PartialEq, Hash, Eq, Serialize, Deserialize)]
pub enum ZirExpressionList<'ast, T> {
EmbedCall(
FlatEmbed,
Vec<u32>,
#[serde(borrow)] Vec<ZirExpression<'ast, T>>,
),
}
/// An expression of type `field`
#[derive(Clone, PartialEq, Hash, Eq, Debug, Serialize, Deserialize)]
pub enum FieldElementExpression<'ast, T> {
Number(T),
#[serde(borrow)]
Identifier(Identifier<'ast>),
Select(SelectExpression<'ast, T, Self>),
Add(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Sub(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Mult(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Div(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Pow(
Box<FieldElementExpression<'ast, T>>,
#[serde(borrow)] Box<UExpression<'ast, T>>,
),
And(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Or(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Xor(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
LeftShift(Box<FieldElementExpression<'ast, T>>, u32),
RightShift(Box<FieldElementExpression<'ast, T>>, u32),
Conditional(ConditionalExpression<'ast, T, FieldElementExpression<'ast, T>>),
}
/// An expression of type `bool`
#[derive(Clone, PartialEq, Hash, Eq, Debug, Serialize, Deserialize)]
pub enum BooleanExpression<'ast, T> {
Value(bool),
#[serde(borrow)]
Identifier(Identifier<'ast>),
Select(SelectExpression<'ast, T, Self>),
FieldLt(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
FieldLe(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
FieldEq(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
UintLt(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
UintLe(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
UintEq(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
BoolEq(
Box<BooleanExpression<'ast, T>>,
Box<BooleanExpression<'ast, T>>,
),
Or(
Box<BooleanExpression<'ast, T>>,
Box<BooleanExpression<'ast, T>>,
),
And(
Box<BooleanExpression<'ast, T>>,
Box<BooleanExpression<'ast, T>>,
),
Not(Box<BooleanExpression<'ast, T>>),
Conditional(ConditionalExpression<'ast, T, BooleanExpression<'ast, T>>),
}
pub struct ConjunctionIterator<T> {
current: Vec<T>,
}
impl<'ast, T> Iterator for ConjunctionIterator<BooleanExpression<'ast, T>> {
type Item = BooleanExpression<'ast, T>;
fn next(&mut self) -> Option<Self::Item> {
self.current.pop().and_then(|n| match n {
BooleanExpression::And(box left, box right) => {
self.current.push(left);
self.current.push(right);
self.next()
}
n => Some(n),
})
}
}
impl<'ast, T> BooleanExpression<'ast, T> {
pub fn into_conjunction_iterator(self) -> ConjunctionIterator<Self> {
ConjunctionIterator {
current: vec![self],
}
}
}
// Downcasts
impl<'ast, T> TryFrom<ZirExpression<'ast, T>> for FieldElementExpression<'ast, T> {
type Error = ();
fn try_from(
te: ZirExpression<'ast, T>,
) -> Result<FieldElementExpression<'ast, T>, Self::Error> {
match te {
ZirExpression::FieldElement(e) => Ok(e),
_ => Err(()),
}
}
}
impl<'ast, T> TryFrom<ZirExpression<'ast, T>> for BooleanExpression<'ast, T> {
type Error = ();
fn try_from(te: ZirExpression<'ast, T>) -> Result<BooleanExpression<'ast, T>, Self::Error> {
match te {
ZirExpression::Boolean(e) => Ok(e),
_ => Err(()),
}
}
}
impl<'ast, T> TryFrom<ZirExpression<'ast, T>> for UExpression<'ast, T> {
type Error = ();
fn try_from(te: ZirExpression<'ast, T>) -> Result<UExpression<'ast, T>, Self::Error> {
match te {
ZirExpression::Uint(e) => Ok(e),
_ => Err(()),
}
}
}
impl<'ast, T: fmt::Display> fmt::Display for FieldElementExpression<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
FieldElementExpression::Number(ref i) => write!(f, "{}", i),
FieldElementExpression::Identifier(ref var) => write!(f, "{}", var),
FieldElementExpression::Select(ref e) => write!(f, "{}", e),
FieldElementExpression::Add(ref lhs, ref rhs) => write!(f, "({} + {})", lhs, rhs),
FieldElementExpression::Sub(ref lhs, ref rhs) => write!(f, "({} - {})", lhs, rhs),
FieldElementExpression::Mult(ref lhs, ref rhs) => write!(f, "({} * {})", lhs, rhs),
FieldElementExpression::Div(ref lhs, ref rhs) => write!(f, "({} / {})", lhs, rhs),
FieldElementExpression::Pow(ref lhs, ref rhs) => write!(f, "{}**{}", lhs, rhs),
FieldElementExpression::And(ref lhs, ref rhs) => write!(f, "({} & {})", lhs, rhs),
FieldElementExpression::Or(ref lhs, ref rhs) => write!(f, "({} | {})", lhs, rhs),
FieldElementExpression::Xor(ref lhs, ref rhs) => write!(f, "({} ^ {})", lhs, rhs),
FieldElementExpression::LeftShift(ref lhs, ref rhs) => {
write!(f, "({} << {})", lhs, rhs)
}
FieldElementExpression::RightShift(ref lhs, ref rhs) => {
write!(f, "({} >> {})", lhs, rhs)
}
FieldElementExpression::Conditional(ref c) => {
write!(f, "{}", c)
}
}
}
}
impl<'ast, T: fmt::Display> fmt::Display for UExpression<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.inner {
UExpressionInner::Value(ref v) => write!(f, "{}", v),
UExpressionInner::Identifier(ref var) => write!(f, "{}", var),
UExpressionInner::Select(ref e) => write!(f, "{}", e),
UExpressionInner::Add(ref lhs, ref rhs) => write!(f, "({} + {})", lhs, rhs),
UExpressionInner::Sub(ref lhs, ref rhs) => write!(f, "({} - {})", lhs, rhs),
UExpressionInner::Mult(ref lhs, ref rhs) => write!(f, "({} * {})", lhs, rhs),
UExpressionInner::Div(ref lhs, ref rhs) => write!(f, "({} * {})", lhs, rhs),
UExpressionInner::Rem(ref lhs, ref rhs) => write!(f, "({} % {})", lhs, rhs),
UExpressionInner::Xor(ref lhs, ref rhs) => write!(f, "({} ^ {})", lhs, rhs),
UExpressionInner::And(ref lhs, ref rhs) => write!(f, "({} & {})", lhs, rhs),
UExpressionInner::Or(ref lhs, ref rhs) => write!(f, "({} | {})", lhs, rhs),
UExpressionInner::LeftShift(ref e, ref by) => write!(f, "({} << {})", e, by),
UExpressionInner::RightShift(ref e, ref by) => write!(f, "({} >> {})", e, by),
UExpressionInner::Not(ref e) => write!(f, "!{}", e),
UExpressionInner::Conditional(ref c) => {
write!(f, "{}", c)
}
}
}
}
impl<'ast, T: fmt::Display> fmt::Display for BooleanExpression<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
BooleanExpression::Identifier(ref var) => write!(f, "{}", var),
BooleanExpression::Value(b) => write!(f, "{}", b),
BooleanExpression::Select(ref e) => write!(f, "{}", e),
BooleanExpression::FieldLt(ref lhs, ref rhs) => write!(f, "({} < {})", lhs, rhs),
BooleanExpression::UintLt(ref lhs, ref rhs) => write!(f, "({} < {})", lhs, rhs),
BooleanExpression::FieldLe(ref lhs, ref rhs) => write!(f, "({} <= {})", lhs, rhs),
BooleanExpression::UintLe(ref lhs, ref rhs) => write!(f, "({} <= {})", lhs, rhs),
BooleanExpression::FieldEq(ref lhs, ref rhs) => write!(f, "({} == {})", lhs, rhs),
BooleanExpression::BoolEq(ref lhs, ref rhs) => write!(f, "({} == {})", lhs, rhs),
BooleanExpression::UintEq(ref lhs, ref rhs) => write!(f, "({} == {})", lhs, rhs),
BooleanExpression::Or(ref lhs, ref rhs) => write!(f, "({} || {})", lhs, rhs),
BooleanExpression::And(ref lhs, ref rhs) => write!(f, "({} && {})", lhs, rhs),
BooleanExpression::Not(ref exp) => write!(f, "!{}", exp),
BooleanExpression::Conditional(ref c) => {
write!(f, "{}", c)
}
}
}
}
impl<'ast, T: fmt::Display> fmt::Display for ZirExpressionList<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ZirExpressionList::EmbedCall(ref embed, ref generics, ref p) => {
write!(
f,
"{}{}(",
embed.id(),
if generics.is_empty() {
"".into()
} else {
format!(
"::<{}>",
generics
.iter()
.map(|g| g.to_string())
.collect::<Vec<_>>()
.join(", ")
)
}
)?;
for (i, param) in p.iter().enumerate() {
write!(f, "{}", param)?;
if i < p.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
}
}
impl<'ast, T: fmt::Debug> fmt::Debug for ZirExpressionList<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ZirExpressionList::EmbedCall(ref embed, ref generics, ref p) => {
write!(f, "EmbedCall({:?}, {:?}, (", generics, embed)?;
f.debug_list().entries(p.iter()).finish()?;
write!(f, ")")
}
}
}
}
// Common behaviour accross expressions
pub trait Expr<'ast, T>: fmt::Display + PartialEq {
type Inner;
type Ty: Clone + IntoType;
fn ty(&self) -> &Self::Ty;
fn into_inner(self) -> Self::Inner;
fn as_inner(&self) -> &Self::Inner;
fn as_inner_mut(&mut self) -> &mut Self::Inner;
}
impl<'ast, T: Field> Expr<'ast, T> for FieldElementExpression<'ast, T> {
type Inner = Self;
type Ty = Type;
fn ty(&self) -> &Self::Ty {
&Type::FieldElement
}
fn into_inner(self) -> Self::Inner {
self
}
fn as_inner(&self) -> &Self::Inner {
self
}
fn as_inner_mut(&mut self) -> &mut Self::Inner {
self
}
}
impl<'ast, T: Field> Expr<'ast, T> for BooleanExpression<'ast, T> {
type Inner = Self;
type Ty = Type;
fn ty(&self) -> &Self::Ty {
&Type::Boolean
}
fn into_inner(self) -> Self::Inner {
self
}
fn as_inner(&self) -> &Self::Inner {
self
}
fn as_inner_mut(&mut self) -> &mut Self::Inner {
self
}
}
impl<'ast, T: Field> Expr<'ast, T> for UExpression<'ast, T> {
type Inner = UExpressionInner<'ast, T>;
type Ty = UBitwidth;
fn ty(&self) -> &Self::Ty {
&self.bitwidth
}
fn into_inner(self) -> Self::Inner {
self.inner
}
fn as_inner(&self) -> &Self::Inner {
&self.inner
}
fn as_inner_mut(&mut self) -> &mut Self::Inner {
&mut self.inner
}
}
pub trait Conditional<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
) -> Self;
}
pub enum ConditionalOrExpression<'ast, T, E: Expr<'ast, T>> {
Conditional(ConditionalExpression<'ast, T, E>),
Expression(E::Inner),
}
impl<'ast, T> Conditional<'ast, T> for FieldElementExpression<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
) -> Self {
FieldElementExpression::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
))
}
}
impl<'ast, T> Conditional<'ast, T> for BooleanExpression<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
) -> Self {
BooleanExpression::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
))
}
}
impl<'ast, T> Conditional<'ast, T> for UExpression<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
) -> Self {
let bitwidth = consequence.bitwidth;
UExpressionInner::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
))
.annotate(bitwidth)
}
}
pub trait Select<'ast, T>: Sized {
fn select(array: Vec<Self>, index: UExpression<'ast, T>) -> Self;
}
pub enum SelectOrExpression<'ast, T, E: Expr<'ast, T>> {
Select(SelectExpression<'ast, T, E>),
Expression(E::Inner),
}
impl<'ast, T> Select<'ast, T> for FieldElementExpression<'ast, T> {
fn select(array: Vec<Self>, index: UExpression<'ast, T>) -> Self {
FieldElementExpression::Select(SelectExpression::new(array, index))
}
}
impl<'ast, T> Select<'ast, T> for BooleanExpression<'ast, T> {
fn select(array: Vec<Self>, index: UExpression<'ast, T>) -> Self {
BooleanExpression::Select(SelectExpression::new(array, index))
}
}
impl<'ast, T> Select<'ast, T> for UExpression<'ast, T> {
fn select(array: Vec<Self>, index: UExpression<'ast, T>) -> Self {
let bitwidth = array[0].bitwidth;
UExpressionInner::Select(SelectExpression::new(array, index)).annotate(bitwidth)
}
}
pub trait IntoType {
fn into_type(self) -> Type;
}
impl IntoType for Type {
fn into_type(self) -> Type {
self
}
}
impl IntoType for UBitwidth {
fn into_type(self) -> Type {
Type::Uint(self)
}
}