mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-29 11:43:28 +03:00
impl field element operations
This commit is contained in:
parent
1bbe71d726
commit
16d27629f9
@ -1,5 +1,4 @@
|
||||
from "./simple_import" import Point
|
||||
|
||||
def main() -> (Point):
|
||||
Point p = Point { x: 1u32, y: 2u32}
|
||||
return p
|
||||
def main() -> (fe[2u32]):
|
||||
// initialize an integer array with field values
|
||||
fe[2u32] a = [1fe, 2fe]
|
||||
return a
|
@ -1,7 +1,8 @@
|
||||
use crate::aleo_program::{
|
||||
Assignee, BooleanExpression, BooleanSpreadOrExpression, Expression, Function, Import, Integer,
|
||||
IntegerExpression, IntegerRangeOrExpression, IntegerSpreadOrExpression, Program, Statement,
|
||||
Struct, StructMember, Type, Variable,
|
||||
Assignee, BooleanExpression, BooleanSpreadOrExpression, Expression, FieldExpression,
|
||||
FieldSpreadOrExpression, Function, Import, Integer, IntegerExpression,
|
||||
IntegerRangeOrExpression, IntegerSpreadOrExpression, Program, Statement, Struct, StructMember,
|
||||
Type, Variable,
|
||||
};
|
||||
use crate::ast;
|
||||
|
||||
@ -16,13 +17,16 @@ use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum ResolvedValue<F: Field + PrimeField> {
|
||||
Boolean(Boolean),
|
||||
BooleanArray(Vec<Boolean>),
|
||||
U32(UInt32),
|
||||
U32Array(Vec<UInt32>),
|
||||
FieldElement(F),
|
||||
FieldElementArray(Vec<F>),
|
||||
Boolean(Boolean),
|
||||
BooleanArray(Vec<Boolean>),
|
||||
StructDefinition(Struct<F>),
|
||||
StructExpression(Variable<F>, Vec<StructMember<F>>),
|
||||
Function(Function<F>),
|
||||
@ -32,22 +36,33 @@ pub enum ResolvedValue<F: Field + PrimeField> {
|
||||
impl<F: Field + PrimeField> fmt::Display for ResolvedValue<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ResolvedValue::Boolean(ref value) => write!(f, "{}", value.get_value().unwrap()),
|
||||
ResolvedValue::BooleanArray(ref array) => {
|
||||
ResolvedValue::U32(ref value) => write!(f, "{}", value.value.unwrap()),
|
||||
ResolvedValue::U32Array(ref array) => {
|
||||
write!(f, "[")?;
|
||||
for (i, e) in array.iter().enumerate() {
|
||||
write!(f, "{}", e.get_value().unwrap())?;
|
||||
write!(f, "{}", e.value.unwrap())?;
|
||||
if i < array.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
ResolvedValue::U32(ref value) => write!(f, "{}", value.value.unwrap()),
|
||||
ResolvedValue::U32Array(ref array) => {
|
||||
ResolvedValue::FieldElement(ref value) => write!(f, "{}", value),
|
||||
ResolvedValue::FieldElementArray(ref array) => {
|
||||
write!(f, "[")?;
|
||||
for (i, e) in array.iter().enumerate() {
|
||||
write!(f, "{}", e.value.unwrap())?;
|
||||
write!(f, "{}", e)?;
|
||||
if i < array.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
ResolvedValue::Boolean(ref value) => write!(f, "{}", value.get_value().unwrap()),
|
||||
ResolvedValue::BooleanArray(ref array) => {
|
||||
write!(f, "[")?;
|
||||
for (i, e) in array.iter().enumerate() {
|
||||
write!(f, "{}", e.get_value().unwrap())?;
|
||||
if i < array.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
@ -182,7 +197,7 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
self.integer_from_variable(cs, scope, variable)
|
||||
}
|
||||
IntegerExpression::Number(number) => Self::get_integer_constant(number),
|
||||
field => self.enforce_integer_expression(cs, scope, field),
|
||||
expression => self.enforce_integer_expression(cs, scope, expression),
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,7 +242,7 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
)
|
||||
}
|
||||
|
||||
fn enforce_add(
|
||||
fn enforce_integer_add(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
@ -257,7 +272,7 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
)
|
||||
}
|
||||
|
||||
fn enforce_sub(
|
||||
fn enforce_integer_sub(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
@ -287,7 +302,7 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
)
|
||||
}
|
||||
|
||||
fn enforce_mul(
|
||||
fn enforce_integer_mul(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
@ -317,7 +332,7 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
)
|
||||
}
|
||||
|
||||
fn enforce_div(
|
||||
fn enforce_integer_div(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
@ -353,7 +368,7 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
)
|
||||
}
|
||||
|
||||
fn enforce_pow(
|
||||
fn enforce_integer_pow(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
@ -384,11 +399,21 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
self.integer_from_variable(cs, scope, variable)
|
||||
}
|
||||
IntegerExpression::Number(number) => Self::get_integer_constant(number),
|
||||
IntegerExpression::Add(left, right) => self.enforce_add(cs, scope, *left, *right),
|
||||
IntegerExpression::Sub(left, right) => self.enforce_sub(cs, scope, *left, *right),
|
||||
IntegerExpression::Mul(left, right) => self.enforce_mul(cs, scope, *left, *right),
|
||||
IntegerExpression::Div(left, right) => self.enforce_div(cs, scope, *left, *right),
|
||||
IntegerExpression::Pow(left, right) => self.enforce_pow(cs, scope, *left, *right),
|
||||
IntegerExpression::Add(left, right) => {
|
||||
self.enforce_integer_add(cs, scope, *left, *right)
|
||||
}
|
||||
IntegerExpression::Sub(left, right) => {
|
||||
self.enforce_integer_sub(cs, scope, *left, *right)
|
||||
}
|
||||
IntegerExpression::Mul(left, right) => {
|
||||
self.enforce_integer_mul(cs, scope, *left, *right)
|
||||
}
|
||||
IntegerExpression::Div(left, right) => {
|
||||
self.enforce_integer_div(cs, scope, *left, *right)
|
||||
}
|
||||
IntegerExpression::Pow(left, right) => {
|
||||
self.enforce_integer_pow(cs, scope, *left, *right)
|
||||
}
|
||||
IntegerExpression::IfElse(first, second, third) => {
|
||||
let resolved_first =
|
||||
match self.enforce_boolean_expression(cs, scope.clone(), *first) {
|
||||
@ -438,6 +463,190 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Constrain field elements
|
||||
|
||||
fn field_from_variable(&mut self, _cs: &mut CS, scope: String, variable: Variable<F>) -> F {
|
||||
// Evaluate variable name in current function scope
|
||||
let variable_name = new_scope_from_variable(scope, &variable);
|
||||
|
||||
if self.contains_name(&variable_name) {
|
||||
// TODO: return synthesis error: "assignment missing" here
|
||||
match self.get(&variable_name).unwrap() {
|
||||
ResolvedValue::FieldElement(field) => field.clone(),
|
||||
value => unimplemented!("expected field element, got {}", value),
|
||||
}
|
||||
} else {
|
||||
// TODO: remove this after resolving arguments
|
||||
let argument = std::env::args()
|
||||
.nth(1)
|
||||
.unwrap_or("1".into())
|
||||
.parse::<u32>()
|
||||
.unwrap();
|
||||
|
||||
println!(" argument passed to command line a = {:?}\n", argument);
|
||||
|
||||
// let a = 1;
|
||||
F::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_field_value(&mut self, cs: &mut CS, scope: String, expression: FieldExpression<F>) -> F {
|
||||
match expression {
|
||||
FieldExpression::Variable(variable) => self.field_from_variable(cs, scope, variable),
|
||||
FieldExpression::Number(element) => element,
|
||||
expression => match self.enforce_field_expression(cs, scope, expression) {
|
||||
ResolvedValue::FieldElement(element) => element,
|
||||
value => unimplemented!("expected field element, got {}", value),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn enforce_field_equality(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
left: FieldExpression<F>,
|
||||
right: FieldExpression<F>,
|
||||
) -> Boolean {
|
||||
let left = self.get_field_value(cs, scope.clone(), left);
|
||||
let right = self.get_field_value(cs, scope.clone(), right);
|
||||
|
||||
Boolean::Constant(left.eq(&right))
|
||||
}
|
||||
|
||||
fn enforce_field_add(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
left: FieldExpression<F>,
|
||||
right: FieldExpression<F>,
|
||||
) -> ResolvedValue<F> {
|
||||
let left = self.get_field_value(cs, scope.clone(), left);
|
||||
let right = self.get_field_value(cs, scope.clone(), right);
|
||||
|
||||
ResolvedValue::FieldElement(left.add(&right))
|
||||
}
|
||||
|
||||
fn enforce_field_sub(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
left: FieldExpression<F>,
|
||||
right: FieldExpression<F>,
|
||||
) -> ResolvedValue<F> {
|
||||
let left = self.get_field_value(cs, scope.clone(), left);
|
||||
let right = self.get_field_value(cs, scope.clone(), right);
|
||||
|
||||
ResolvedValue::FieldElement(left.sub(&right))
|
||||
}
|
||||
|
||||
fn enforce_field_mul(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
left: FieldExpression<F>,
|
||||
right: FieldExpression<F>,
|
||||
) -> ResolvedValue<F> {
|
||||
let left = self.get_field_value(cs, scope.clone(), left);
|
||||
let right = self.get_field_value(cs, scope.clone(), right);
|
||||
|
||||
ResolvedValue::FieldElement(left.mul(&right))
|
||||
}
|
||||
|
||||
fn enforce_field_div(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
left: FieldExpression<F>,
|
||||
right: FieldExpression<F>,
|
||||
) -> ResolvedValue<F> {
|
||||
let left = self.get_field_value(cs, scope.clone(), left);
|
||||
let right = self.get_field_value(cs, scope.clone(), right);
|
||||
|
||||
ResolvedValue::FieldElement(left.div(&right))
|
||||
}
|
||||
|
||||
fn enforce_field_pow(
|
||||
&mut self,
|
||||
_cs: &mut CS,
|
||||
_scope: String,
|
||||
_left: FieldExpression<F>,
|
||||
_right: FieldExpression<F>,
|
||||
) -> ResolvedValue<F> {
|
||||
unimplemented!("field element exponentiation not supported")
|
||||
// let left = self.get_field_value(cs, scope.clone(), left);
|
||||
// let right = self.get_field_value(cs, scope.clone(), right);
|
||||
//
|
||||
// ResolvedValue::FieldElement(left.pow(&right))
|
||||
}
|
||||
|
||||
fn enforce_field_expression(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
scope: String,
|
||||
expression: FieldExpression<F>,
|
||||
) -> ResolvedValue<F> {
|
||||
match expression {
|
||||
FieldExpression::Variable(variable) => {
|
||||
ResolvedValue::FieldElement(self.field_from_variable(cs, scope, variable))
|
||||
}
|
||||
FieldExpression::Number(field) => ResolvedValue::FieldElement(field),
|
||||
FieldExpression::Add(left, right) => self.enforce_field_add(cs, scope, *left, *right),
|
||||
FieldExpression::Sub(left, right) => self.enforce_field_sub(cs, scope, *left, *right),
|
||||
FieldExpression::Mul(left, right) => self.enforce_field_mul(cs, scope, *left, *right),
|
||||
FieldExpression::Div(left, right) => self.enforce_field_div(cs, scope, *left, *right),
|
||||
FieldExpression::Pow(left, right) => self.enforce_field_pow(cs, scope, *left, *right),
|
||||
FieldExpression::IfElse(first, second, third) => {
|
||||
let resolved_first =
|
||||
match self.enforce_boolean_expression(cs, scope.clone(), *first) {
|
||||
ResolvedValue::Boolean(resolved) => resolved,
|
||||
_ => unimplemented!("if else conditional must resolve to boolean"),
|
||||
};
|
||||
|
||||
if resolved_first.eq(&Boolean::Constant(true)) {
|
||||
self.enforce_field_expression(cs, scope, *second)
|
||||
} else {
|
||||
self.enforce_field_expression(cs, scope, *third)
|
||||
}
|
||||
}
|
||||
FieldExpression::Array(array) => {
|
||||
let mut result = vec![];
|
||||
array.into_iter().for_each(|element| match *element {
|
||||
FieldSpreadOrExpression::Spread(spread) => match spread {
|
||||
FieldExpression::Variable(variable) => {
|
||||
let array_name = new_scope_from_variable(scope.clone(), &variable);
|
||||
match self.get(&array_name) {
|
||||
Some(value) => match value {
|
||||
ResolvedValue::FieldElementArray(array) => {
|
||||
result.extend(array.clone())
|
||||
}
|
||||
value => unimplemented!(
|
||||
"spreads only implemented for arrays, got {}",
|
||||
value
|
||||
),
|
||||
},
|
||||
None => unimplemented!(
|
||||
"cannot copy elements from array that does not exist {}",
|
||||
variable.name
|
||||
),
|
||||
}
|
||||
}
|
||||
value => {
|
||||
unimplemented!("spreads only implemented for arrays, got {}", value)
|
||||
}
|
||||
},
|
||||
FieldSpreadOrExpression::Expression(expression) => {
|
||||
match self.enforce_field_expression(cs, scope.clone(), expression) {
|
||||
ResolvedValue::FieldElement(value) => result.push(value),
|
||||
_ => unimplemented!("cannot resolve field"),
|
||||
}
|
||||
}
|
||||
});
|
||||
ResolvedValue::FieldElementArray(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn bool_from_variable(&mut self, cs: &mut CS, scope: String, variable: Variable<F>) -> Boolean {
|
||||
// Evaluate variable name in current function scope
|
||||
let variable_name = new_scope_from_variable(scope, &variable);
|
||||
@ -549,11 +758,14 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
BooleanExpression::And(left, right) => {
|
||||
ResolvedValue::Boolean(self.enforce_and(cs, scope, *left, *right))
|
||||
}
|
||||
BooleanExpression::BoolEq(left, right) => {
|
||||
ResolvedValue::Boolean(self.enforce_bool_equality(cs, scope, *left, *right))
|
||||
BooleanExpression::IntegerEq(left, right) => {
|
||||
ResolvedValue::Boolean(self.enforce_integer_equality(cs, scope, *left, *right))
|
||||
}
|
||||
BooleanExpression::FieldEq(left, right) => {
|
||||
ResolvedValue::Boolean(self.enforce_integer_equality(cs, scope, *left, *right))
|
||||
ResolvedValue::Boolean(self.enforce_field_equality(cs, scope, *left, *right))
|
||||
}
|
||||
BooleanExpression::BoolEq(left, right) => {
|
||||
ResolvedValue::Boolean(self.enforce_bool_equality(cs, scope, *left, *right))
|
||||
}
|
||||
BooleanExpression::IfElse(first, second, third) => {
|
||||
let resolved_first =
|
||||
@ -745,8 +957,11 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
Expression::Boolean(boolean_expression) => {
|
||||
self.enforce_boolean_expression(cs, scope, boolean_expression)
|
||||
}
|
||||
Expression::Integer(field_expression) => {
|
||||
self.enforce_integer_expression(cs, scope, field_expression)
|
||||
Expression::Integer(integer_expression) => {
|
||||
self.enforce_integer_expression(cs, scope, integer_expression)
|
||||
}
|
||||
Expression::FieldElement(field_expression) => {
|
||||
self.enforce_field_expression(cs, scope, field_expression)
|
||||
}
|
||||
Expression::Variable(unresolved_variable) => {
|
||||
let variable_name = new_scope_from_variable(scope, &unresolved_variable);
|
||||
@ -787,8 +1002,7 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
}
|
||||
Expression::FunctionCall(function, arguments) => {
|
||||
self.enforce_function_access_expression(cs, scope, function, arguments)
|
||||
}
|
||||
expression => unimplemented!("expression not impl {}", expression),
|
||||
} // expression => unimplemented!("expression not impl {}", expression),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,32 +61,32 @@ pub enum IntegerExpression<F: Field + PrimeField> {
|
||||
Array(Vec<Box<IntegerSpreadOrExpression<F>>>),
|
||||
}
|
||||
|
||||
// /// Spread or field expression enum
|
||||
// #[derive(Debug, Clone)]
|
||||
// pub enum FieldSpreadOrExpression<F: Field + PrimeField> {
|
||||
// Spread(FieldExpression<F>),
|
||||
// Expression(FieldExpression<F>),
|
||||
// }
|
||||
/// Spread or field expression enum
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum FieldSpreadOrExpression<F: Field + PrimeField> {
|
||||
Spread(FieldExpression<F>),
|
||||
Expression(FieldExpression<F>),
|
||||
}
|
||||
|
||||
/// Expression that evaluates to a field value
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum FieldExpression<F: Field + PrimeField> {
|
||||
Variable(Variable<F>),
|
||||
Number(F),
|
||||
// // Operators
|
||||
// Add(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
// Sub(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
// Mul(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
// Div(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
// Pow(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
// // Conditionals
|
||||
// IfElse(
|
||||
// Box<BooleanExpression>,
|
||||
// Box<FieldExpression<F>>,
|
||||
// Box<FieldExpression<F>>,
|
||||
// ),
|
||||
// // Arrays
|
||||
// Array(Vec<Box<FieldSpreadOrExpression<F>>>),
|
||||
// Operators
|
||||
Add(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
Sub(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
Mul(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
Div(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
Pow(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
// Conditionals
|
||||
IfElse(
|
||||
Box<BooleanExpression<F>>,
|
||||
Box<FieldExpression<F>>,
|
||||
Box<FieldExpression<F>>,
|
||||
),
|
||||
// Arrays
|
||||
Array(Vec<Box<FieldSpreadOrExpression<F>>>),
|
||||
}
|
||||
|
||||
/// Spread or field expression enum
|
||||
@ -106,12 +106,14 @@ pub enum BooleanExpression<F: Field + PrimeField> {
|
||||
Or(Box<BooleanExpression<F>>, Box<BooleanExpression<F>>),
|
||||
And(Box<BooleanExpression<F>>, Box<BooleanExpression<F>>),
|
||||
BoolEq(Box<BooleanExpression<F>>, Box<BooleanExpression<F>>),
|
||||
// Field operators
|
||||
FieldEq(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
|
||||
// Integer operators
|
||||
IntegerEq(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
|
||||
Geq(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
|
||||
Gt(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
|
||||
Leq(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
|
||||
Lt(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
|
||||
// Field operators
|
||||
FieldEq(Box<FieldExpression<F>>, Box<FieldExpression<F>>),
|
||||
// Conditionals
|
||||
IfElse(
|
||||
Box<BooleanExpression<F>>,
|
||||
|
@ -5,9 +5,10 @@
|
||||
//! @date 2020
|
||||
|
||||
use crate::aleo_program::{
|
||||
Assignee, BooleanExpression, BooleanSpreadOrExpression, Expression, Function, FunctionName,
|
||||
Integer, IntegerExpression, IntegerRangeOrExpression, IntegerSpreadOrExpression, Parameter,
|
||||
Statement, Struct, StructField, Type, Variable,
|
||||
Assignee, BooleanExpression, BooleanSpreadOrExpression, Expression, FieldExpression,
|
||||
FieldSpreadOrExpression, Function, FunctionName, Integer, IntegerExpression,
|
||||
IntegerRangeOrExpression, IntegerSpreadOrExpression, Parameter, Statement, Struct, StructField,
|
||||
Type, Variable,
|
||||
};
|
||||
|
||||
use snarkos_models::curves::{Field, PrimeField};
|
||||
@ -41,6 +42,22 @@ impl<F: Field + PrimeField> fmt::Display for IntegerSpreadOrExpression<F> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> fmt::Display for IntegerRangeOrExpression<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
IntegerRangeOrExpression::Range(ref from, ref to) => write!(
|
||||
f,
|
||||
"{}..{}",
|
||||
from.as_ref()
|
||||
.map(|e| e.to_string())
|
||||
.unwrap_or("".to_string()),
|
||||
to.as_ref().map(|e| e.to_string()).unwrap_or("".to_string())
|
||||
),
|
||||
IntegerRangeOrExpression::Expression(ref e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> fmt::Display for IntegerExpression<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
@ -68,6 +85,42 @@ impl<'ast, F: Field + PrimeField> fmt::Display for IntegerExpression<F> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> fmt::Display for FieldSpreadOrExpression<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
FieldSpreadOrExpression::Spread(ref spread) => write!(f, "...{}", spread),
|
||||
FieldSpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> fmt::Display for FieldExpression<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
FieldExpression::Variable(ref variable) => write!(f, "{}", variable),
|
||||
FieldExpression::Number(ref number) => write!(f, "{}", number),
|
||||
FieldExpression::Add(ref lhs, ref rhs) => write!(f, "{} + {}", lhs, rhs),
|
||||
FieldExpression::Sub(ref lhs, ref rhs) => write!(f, "{} - {}", lhs, rhs),
|
||||
FieldExpression::Mul(ref lhs, ref rhs) => write!(f, "{} * {}", lhs, rhs),
|
||||
FieldExpression::Div(ref lhs, ref rhs) => write!(f, "{} / {}", lhs, rhs),
|
||||
FieldExpression::Pow(ref lhs, ref rhs) => write!(f, "{} ** {}", lhs, rhs),
|
||||
FieldExpression::IfElse(ref a, ref b, ref c) => {
|
||||
write!(f, "if {} then {} else {} fi", a, b, c)
|
||||
}
|
||||
FieldExpression::Array(ref array) => {
|
||||
write!(f, "[")?;
|
||||
for (i, e) in array.iter().enumerate() {
|
||||
write!(f, "{}", e)?;
|
||||
if i < array.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, "]")
|
||||
} // _ => unimplemented!("not all field expressions can be displayed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> fmt::Display for BooleanSpreadOrExpression<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
@ -86,6 +139,7 @@ impl<'ast, F: Field + PrimeField> fmt::Display for BooleanExpression<F> {
|
||||
BooleanExpression::Or(ref lhs, ref rhs) => write!(f, "{} || {}", lhs, rhs),
|
||||
BooleanExpression::And(ref lhs, ref rhs) => write!(f, "{} && {}", lhs, rhs),
|
||||
BooleanExpression::BoolEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
BooleanExpression::IntegerEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
BooleanExpression::FieldEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
// BooleanExpression::Neq(ref lhs, ref rhs) => write!(f, "{} != {}", lhs, rhs),
|
||||
BooleanExpression::Geq(ref lhs, ref rhs) => write!(f, "{} >= {}", lhs, rhs),
|
||||
@ -109,29 +163,11 @@ impl<'ast, F: Field + PrimeField> fmt::Display for BooleanExpression<F> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> fmt::Display for IntegerRangeOrExpression<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
IntegerRangeOrExpression::Range(ref from, ref to) => write!(
|
||||
f,
|
||||
"{}..{}",
|
||||
from.as_ref()
|
||||
.map(|e| e.to_string())
|
||||
.unwrap_or("".to_string()),
|
||||
to.as_ref().map(|e| e.to_string()).unwrap_or("".to_string())
|
||||
),
|
||||
IntegerRangeOrExpression::Expression(ref e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> fmt::Display for Expression<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Expression::Integer(ref integer_expression) => write!(f, "{}", integer_expression),
|
||||
Expression::FieldElement(ref _field_expression) => {
|
||||
unimplemented!("field elem not impl ")
|
||||
}
|
||||
Expression::FieldElement(ref field_expression) => write!(f, "{}", field_expression),
|
||||
Expression::Boolean(ref boolean_expression) => write!(f, "{}", boolean_expression),
|
||||
Expression::Variable(ref variable) => write!(f, "{}", variable),
|
||||
Expression::Struct(ref var, ref members) => {
|
||||
|
@ -48,7 +48,7 @@ impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>> for types::Integer
|
||||
match types::Expression::from(expression) {
|
||||
types::Expression::Integer(integer_expression) => integer_expression,
|
||||
types::Expression::Variable(variable) => types::IntegerExpression::Variable(variable),
|
||||
_ => unimplemented!("expected field in field expression"),
|
||||
_ => unimplemented!("expected integer in integer expression"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,7 +61,7 @@ impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>>
|
||||
types::Expression::Integer(expression) => {
|
||||
types::IntegerSpreadOrExpression::Expression(expression)
|
||||
}
|
||||
_ => unimplemented!("cannot create field expression from boolean type"),
|
||||
_ => unimplemented!("cannot create integer expression from boolean type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,13 +90,13 @@ impl<'ast, F: Field + PrimeField> From<ast::RangeOrExpression<'ast>>
|
||||
let from = range
|
||||
.from
|
||||
.map(|from| match types::Expression::from(from.0) {
|
||||
types::Expression::Integer(field) => field,
|
||||
types::Expression::Integer(number) => number,
|
||||
expression => {
|
||||
unimplemented!("Range bounds should be numbers, found {}", expression)
|
||||
}
|
||||
});
|
||||
let to = range.to.map(|to| match types::Expression::from(to.0) {
|
||||
types::Expression::Integer(field) => field,
|
||||
types::Expression::Integer(number) => number,
|
||||
expression => {
|
||||
unimplemented!("Range bounds should be numbers, found {}", expression)
|
||||
}
|
||||
@ -106,19 +106,98 @@ impl<'ast, F: Field + PrimeField> From<ast::RangeOrExpression<'ast>>
|
||||
}
|
||||
ast::RangeOrExpression::Expression(expression) => {
|
||||
match types::Expression::from(expression) {
|
||||
types::Expression::Integer(field_expression) => {
|
||||
types::IntegerRangeOrExpression::Expression(field_expression)
|
||||
types::Expression::Integer(expression) => {
|
||||
types::IntegerRangeOrExpression::Expression(expression)
|
||||
}
|
||||
// types::Expression::ArrayAccess(expression, field), // recursive array access
|
||||
expression => unimplemented!("expression must be field, found {}", expression),
|
||||
expression => unimplemented!("expression must be number, found {}", expression),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// pest ast -> types::FieldExpression
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Variable<'ast>> for types::FieldExpression<F> {
|
||||
fn from(variable: ast::Variable<'ast>) -> Self {
|
||||
types::FieldExpression::Variable(types::Variable::from(variable))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Field<'ast>> for types::FieldExpression<F> {
|
||||
fn from(field: ast::Field<'ast>) -> Self {
|
||||
types::FieldExpression::Number(F::from_str(&field.number.value).unwrap_or_default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>> for types::FieldExpression<F> {
|
||||
fn from(expression: ast::Expression<'ast>) -> Self {
|
||||
match types::Expression::from(expression) {
|
||||
types::Expression::FieldElement(field_expression) => field_expression,
|
||||
types::Expression::Variable(variable) => types::FieldExpression::Variable(variable),
|
||||
_ => unimplemented!("expected field in field expression"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>>
|
||||
for types::FieldSpreadOrExpression<F>
|
||||
{
|
||||
fn from(expression: ast::Expression<'ast>) -> Self {
|
||||
match types::Expression::from(expression) {
|
||||
types::Expression::FieldElement(expression) => {
|
||||
types::FieldSpreadOrExpression::Expression(expression)
|
||||
}
|
||||
ty => unimplemented!("cannot create field expression from type {}", ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::SpreadOrExpression<'ast>>
|
||||
for types::FieldSpreadOrExpression<F>
|
||||
{
|
||||
fn from(s_or_e: ast::SpreadOrExpression<'ast>) -> Self {
|
||||
match s_or_e {
|
||||
ast::SpreadOrExpression::Spread(spread) => {
|
||||
types::FieldSpreadOrExpression::from(spread.expression)
|
||||
}
|
||||
ast::SpreadOrExpression::Expression(expression) => {
|
||||
types::FieldSpreadOrExpression::from(expression)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// pest ast -> types::Boolean
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Variable<'ast>> for types::BooleanExpression<F> {
|
||||
fn from(variable: ast::Variable<'ast>) -> Self {
|
||||
types::BooleanExpression::Variable(types::Variable::from(variable))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Boolean<'ast>> for types::BooleanExpression<F> {
|
||||
fn from(boolean: ast::Boolean<'ast>) -> Self {
|
||||
types::BooleanExpression::Value(
|
||||
boolean
|
||||
.value
|
||||
.parse::<bool>()
|
||||
.expect("unable to unwrap boolean"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>> for types::BooleanExpression<F> {
|
||||
fn from(expression: ast::Expression<'ast>) -> Self {
|
||||
match types::Expression::from(expression) {
|
||||
types::Expression::Boolean(boolean_expression) => boolean_expression,
|
||||
types::Expression::Variable(variable) => types::BooleanExpression::Variable(variable),
|
||||
_ => unimplemented!("expected boolean in boolean expression"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>>
|
||||
for types::BooleanSpreadOrExpression<F>
|
||||
{
|
||||
@ -147,33 +226,6 @@ impl<'ast, F: Field + PrimeField> From<ast::SpreadOrExpression<'ast>>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Variable<'ast>> for types::BooleanExpression<F> {
|
||||
fn from(variable: ast::Variable<'ast>) -> Self {
|
||||
types::BooleanExpression::Variable(types::Variable::from(variable))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Boolean<'ast>> for types::BooleanExpression<F> {
|
||||
fn from(boolean: ast::Boolean<'ast>) -> Self {
|
||||
types::BooleanExpression::Value(
|
||||
boolean
|
||||
.value
|
||||
.parse::<bool>()
|
||||
.expect("unable to unwrap boolean"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>> for types::BooleanExpression<F> {
|
||||
fn from(expression: ast::Expression<'ast>) -> Self {
|
||||
match types::Expression::from(expression) {
|
||||
types::Expression::Boolean(boolean_expression) => boolean_expression,
|
||||
types::Expression::Variable(variable) => types::BooleanExpression::Variable(variable),
|
||||
_ => unimplemented!("expected boolean in boolean expression"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// pest ast -> types::Expression
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Value<'ast>> for types::Expression<F> {
|
||||
@ -182,7 +234,9 @@ impl<'ast, F: Field + PrimeField> From<ast::Value<'ast>> for types::Expression<F
|
||||
ast::Value::U32(value) => {
|
||||
types::Expression::Integer(types::IntegerExpression::from(value))
|
||||
}
|
||||
ast::Value::Field(_field) => unimplemented!("cannot declare field values yet"),
|
||||
ast::Value::Field(field) => {
|
||||
types::Expression::FieldElement(types::FieldExpression::from(field))
|
||||
}
|
||||
ast::Value::Boolean(value) => {
|
||||
types::Expression::Boolean(types::BooleanExpression::from(value))
|
||||
}
|
||||
@ -228,22 +282,38 @@ impl<'ast, F: Field + PrimeField> types::BooleanExpression<F> {
|
||||
Box::new(rhs),
|
||||
)
|
||||
} //TODO: check case for two variables?
|
||||
// Field equality
|
||||
// Integer equality
|
||||
(types::Expression::Integer(lhs), types::Expression::Integer(rhs)) => {
|
||||
types::BooleanExpression::FieldEq(Box::new(lhs), Box::new(rhs))
|
||||
types::BooleanExpression::IntegerEq(Box::new(lhs), Box::new(rhs))
|
||||
}
|
||||
(types::Expression::Integer(lhs), types::Expression::Variable(rhs)) => {
|
||||
types::BooleanExpression::FieldEq(
|
||||
types::BooleanExpression::IntegerEq(
|
||||
Box::new(lhs),
|
||||
Box::new(types::IntegerExpression::Variable(rhs)),
|
||||
)
|
||||
}
|
||||
(types::Expression::Variable(lhs), types::Expression::Integer(rhs)) => {
|
||||
types::BooleanExpression::FieldEq(
|
||||
types::BooleanExpression::IntegerEq(
|
||||
Box::new(types::IntegerExpression::Variable(lhs)),
|
||||
Box::new(rhs),
|
||||
)
|
||||
}
|
||||
// Field equality
|
||||
(types::Expression::FieldElement(lhs), types::Expression::FieldElement(rhs)) => {
|
||||
types::BooleanExpression::FieldEq(Box::new(lhs), Box::new(rhs))
|
||||
}
|
||||
(types::Expression::FieldElement(lhs), types::Expression::Variable(rhs)) => {
|
||||
types::BooleanExpression::FieldEq(
|
||||
Box::new(lhs),
|
||||
Box::new(types::FieldExpression::Variable(rhs)),
|
||||
)
|
||||
}
|
||||
(types::Expression::Variable(lhs), types::Expression::FieldElement(rhs)) => {
|
||||
types::BooleanExpression::FieldEq(
|
||||
Box::new(types::FieldExpression::Variable(lhs)),
|
||||
Box::new(rhs),
|
||||
)
|
||||
}
|
||||
|
||||
(lhs, rhs) => unimplemented!("pattern {} == {} unimplemented", lhs, rhs),
|
||||
}
|
||||
@ -253,6 +323,27 @@ impl<'ast, F: Field + PrimeField> types::BooleanExpression<F> {
|
||||
types::BooleanExpression::Not(Box::new(Self::from_eq(expression)))
|
||||
}
|
||||
}
|
||||
impl<'ast, F: Field + PrimeField> types::Type<F> {
|
||||
fn resolve_type(left: &Box<ast::Expression<'ast>>, right: &Box<ast::Expression<'ast>>) -> Self {
|
||||
let left = types::Expression::<F>::from(*left.clone());
|
||||
let right = types::Expression::<F>::from(*right.clone());
|
||||
|
||||
match (left, right) {
|
||||
// Integer operation
|
||||
(types::Expression::Integer(_), _) => types::Type::U32,
|
||||
(_, types::Expression::Integer(_)) => types::Type::FieldElement,
|
||||
// Field operation
|
||||
(types::Expression::FieldElement(_), _) => types::Type::FieldElement,
|
||||
(_, types::Expression::FieldElement(_)) => types::Type::FieldElement,
|
||||
// Unmatched: two array accesses, two variables
|
||||
(lhs, rhs) => unimplemented!(
|
||||
"operand types {} and {} must match for binary expression",
|
||||
lhs,
|
||||
rhs
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::BinaryExpression<'ast>> for types::Expression<F> {
|
||||
fn from(expression: ast::BinaryExpression<'ast>) -> Self {
|
||||
@ -288,27 +379,82 @@ impl<'ast, F: Field + PrimeField> From<ast::BinaryExpression<'ast>> for types::E
|
||||
Box::new(types::IntegerExpression::from(*expression.left)),
|
||||
Box::new(types::IntegerExpression::from(*expression.right)),
|
||||
)),
|
||||
// Field operations
|
||||
ast::BinaryOperator::Add => types::Expression::Integer(types::IntegerExpression::Add(
|
||||
// Operations
|
||||
ast::BinaryOperator::Add => {
|
||||
match types::Type::<F>::resolve_type(&expression.left, &expression.right) {
|
||||
types::Type::U32 => types::Expression::Integer(types::IntegerExpression::Add(
|
||||
Box::new(types::IntegerExpression::from(*expression.left)),
|
||||
Box::new(types::IntegerExpression::from(*expression.right)),
|
||||
)),
|
||||
ast::BinaryOperator::Sub => types::Expression::Integer(types::IntegerExpression::Sub(
|
||||
types::Type::FieldElement => {
|
||||
types::Expression::FieldElement(types::FieldExpression::Add(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
))
|
||||
}
|
||||
_ => unimplemented!("unreachable"),
|
||||
}
|
||||
}
|
||||
ast::BinaryOperator::Sub => {
|
||||
match types::Type::<F>::resolve_type(&expression.left, &expression.right) {
|
||||
types::Type::U32 => types::Expression::Integer(types::IntegerExpression::Sub(
|
||||
Box::new(types::IntegerExpression::from(*expression.left)),
|
||||
Box::new(types::IntegerExpression::from(*expression.right)),
|
||||
)),
|
||||
ast::BinaryOperator::Mul => types::Expression::Integer(types::IntegerExpression::Mul(
|
||||
types::Type::FieldElement => {
|
||||
types::Expression::FieldElement(types::FieldExpression::Sub(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
))
|
||||
}
|
||||
_ => unimplemented!("unreachable"),
|
||||
}
|
||||
}
|
||||
ast::BinaryOperator::Mul => {
|
||||
match types::Type::<F>::resolve_type(&expression.left, &expression.right) {
|
||||
types::Type::U32 => types::Expression::Integer(types::IntegerExpression::Mul(
|
||||
Box::new(types::IntegerExpression::from(*expression.left)),
|
||||
Box::new(types::IntegerExpression::from(*expression.right)),
|
||||
)),
|
||||
ast::BinaryOperator::Div => types::Expression::Integer(types::IntegerExpression::Div(
|
||||
types::Type::FieldElement => {
|
||||
types::Expression::FieldElement(types::FieldExpression::Mul(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
))
|
||||
}
|
||||
_ => unimplemented!("unreachable"),
|
||||
}
|
||||
}
|
||||
ast::BinaryOperator::Div => {
|
||||
match types::Type::<F>::resolve_type(&expression.left, &expression.right) {
|
||||
types::Type::U32 => types::Expression::Integer(types::IntegerExpression::Div(
|
||||
Box::new(types::IntegerExpression::from(*expression.left)),
|
||||
Box::new(types::IntegerExpression::from(*expression.right)),
|
||||
)),
|
||||
ast::BinaryOperator::Pow => types::Expression::Integer(types::IntegerExpression::Pow(
|
||||
types::Type::FieldElement => {
|
||||
types::Expression::FieldElement(types::FieldExpression::Div(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
))
|
||||
}
|
||||
_ => unimplemented!("unreachable"),
|
||||
}
|
||||
}
|
||||
ast::BinaryOperator::Pow => {
|
||||
match types::Type::<F>::resolve_type(&expression.left, &expression.right) {
|
||||
types::Type::U32 => types::Expression::Integer(types::IntegerExpression::Pow(
|
||||
Box::new(types::IntegerExpression::from(*expression.left)),
|
||||
Box::new(types::IntegerExpression::from(*expression.right)),
|
||||
)),
|
||||
types::Type::FieldElement => {
|
||||
types::Expression::FieldElement(types::FieldExpression::Pow(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
))
|
||||
}
|
||||
_ => unimplemented!("unreachable"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -343,7 +489,7 @@ impl<'ast, F: Field + PrimeField> From<ast::TernaryExpression<'ast>> for types::
|
||||
Box::new(third),
|
||||
))
|
||||
}
|
||||
// Field Result
|
||||
// Integer Result
|
||||
(types::Expression::Integer(second), types::Expression::Integer(third)) => {
|
||||
types::Expression::Integer(types::IntegerExpression::IfElse(
|
||||
Box::new(first),
|
||||
@ -365,6 +511,28 @@ impl<'ast, F: Field + PrimeField> From<ast::TernaryExpression<'ast>> for types::
|
||||
Box::new(third),
|
||||
))
|
||||
}
|
||||
// Field Result
|
||||
(types::Expression::FieldElement(second), types::Expression::FieldElement(third)) => {
|
||||
types::Expression::FieldElement(types::FieldExpression::IfElse(
|
||||
Box::new(first),
|
||||
Box::new(second),
|
||||
Box::new(third),
|
||||
))
|
||||
}
|
||||
(types::Expression::FieldElement(second), types::Expression::Variable(third)) => {
|
||||
types::Expression::FieldElement(types::FieldExpression::IfElse(
|
||||
Box::new(first),
|
||||
Box::new(second),
|
||||
Box::new(types::FieldExpression::Variable(third)),
|
||||
))
|
||||
}
|
||||
(types::Expression::Variable(second), types::Expression::FieldElement(third)) => {
|
||||
types::Expression::FieldElement(types::FieldExpression::IfElse(
|
||||
Box::new(first),
|
||||
Box::new(types::FieldExpression::Variable(second)),
|
||||
Box::new(third),
|
||||
))
|
||||
}
|
||||
|
||||
(second, third) => unimplemented!(
|
||||
"pattern if {} then {} else {} unimplemented",
|
||||
@ -444,6 +612,17 @@ impl<'ast, F: Field + PrimeField> types::Expression<F> {
|
||||
unimplemented!("from basic not impl");
|
||||
}
|
||||
|
||||
fn get_count(count: ast::Value<'ast>) -> usize {
|
||||
match count {
|
||||
ast::Value::U32(f) => f
|
||||
.number
|
||||
.value
|
||||
.parse::<usize>()
|
||||
.expect("Unable to read array size"),
|
||||
size => unimplemented!("Array size should be an integer {}", size),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_array(ty: ast::ArrayType<'ast>, expression: ast::Expression<'ast>) -> Self {
|
||||
match ty.ty {
|
||||
ast::BasicType::U32(_ty) => {
|
||||
@ -454,14 +633,7 @@ impl<'ast, F: Field + PrimeField> types::Expression<F> {
|
||||
.map(|s_or_e| Box::new(types::IntegerSpreadOrExpression::from(s_or_e)))
|
||||
.collect(),
|
||||
ast::Expression::ArrayInitializer(array) => {
|
||||
let count = match array.count {
|
||||
ast::Value::U32(f) => f
|
||||
.number
|
||||
.value
|
||||
.parse::<usize>()
|
||||
.expect("Unable to read array size"),
|
||||
_ => unimplemented!("Array size should be an integer"),
|
||||
};
|
||||
let count = types::Expression::<F>::get_count(array.count);
|
||||
let expression =
|
||||
Box::new(types::IntegerSpreadOrExpression::from(*array.expression));
|
||||
|
||||
@ -471,7 +643,24 @@ impl<'ast, F: Field + PrimeField> types::Expression<F> {
|
||||
};
|
||||
types::Expression::Integer(types::IntegerExpression::Array(elements))
|
||||
}
|
||||
ast::BasicType::Field(_ty) => unimplemented!("from array field basic types unimpl"),
|
||||
ast::BasicType::Field(_ty) => {
|
||||
let elements: Vec<Box<types::FieldSpreadOrExpression<F>>> = match expression {
|
||||
ast::Expression::ArrayInline(array) => array
|
||||
.expressions
|
||||
.into_iter()
|
||||
.map(|s_or_e| Box::new(types::FieldSpreadOrExpression::from(s_or_e)))
|
||||
.collect(),
|
||||
ast::Expression::ArrayInitializer(array) => {
|
||||
let count = types::Expression::<F>::get_count(array.count);
|
||||
let expression =
|
||||
Box::new(types::FieldSpreadOrExpression::from(*array.expression));
|
||||
|
||||
vec![expression; count]
|
||||
}
|
||||
_ => unimplemented!("expected array after array type"),
|
||||
};
|
||||
types::Expression::FieldElement(types::FieldExpression::Array(elements))
|
||||
}
|
||||
ast::BasicType::Boolean(_ty) => {
|
||||
let elements: Vec<Box<types::BooleanSpreadOrExpression<F>>> = match expression {
|
||||
ast::Expression::ArrayInline(array) => array
|
||||
@ -480,14 +669,7 @@ impl<'ast, F: Field + PrimeField> types::Expression<F> {
|
||||
.map(|s_or_e| Box::new(types::BooleanSpreadOrExpression::from(s_or_e)))
|
||||
.collect(),
|
||||
ast::Expression::ArrayInitializer(array) => {
|
||||
let count = match array.count {
|
||||
ast::Value::U32(f) => f
|
||||
.number
|
||||
.value
|
||||
.parse::<usize>()
|
||||
.expect("Unable to read array size"),
|
||||
_ => unimplemented!("Array size should be an integer"),
|
||||
};
|
||||
let count = types::Expression::<F>::get_count(array.count);
|
||||
let expression =
|
||||
Box::new(types::BooleanSpreadOrExpression::from(*array.expression));
|
||||
|
||||
@ -631,14 +813,8 @@ impl<'ast, F: Field + PrimeField> From<ast::BasicType<'ast>> for types::Type<F>
|
||||
impl<'ast, F: Field + PrimeField> From<ast::ArrayType<'ast>> for types::Type<F> {
|
||||
fn from(array_type: ast::ArrayType<'ast>) -> Self {
|
||||
let element_type = Box::new(types::Type::from(array_type.ty));
|
||||
let count = match array_type.count {
|
||||
ast::Value::Field(f) => f
|
||||
.number
|
||||
.value
|
||||
.parse::<usize>()
|
||||
.expect("Unable to read array size"),
|
||||
_ => unimplemented!("Array size should be an integer"),
|
||||
};
|
||||
let count = types::Expression::<F>::get_count(array_type.count);
|
||||
|
||||
types::Type::Array(element_type, count)
|
||||
}
|
||||
}
|
||||
|
10
src/ast.rs
10
src/ast.rs
@ -99,15 +99,15 @@ pub struct U32Type<'ast> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::ty_bool))]
|
||||
pub struct BooleanType<'ast> {
|
||||
#[pest_ast(rule(Rule::ty_field))]
|
||||
pub struct FieldType<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::ty_field))]
|
||||
pub struct FieldType<'ast> {
|
||||
#[pest_ast(rule(Rule::ty_bool))]
|
||||
pub struct BooleanType<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
@ -197,7 +197,7 @@ impl<'ast> fmt::Display for U32<'ast> {
|
||||
#[pest_ast(rule(Rule::value_field))]
|
||||
pub struct Field<'ast> {
|
||||
pub number: Number<'ast>,
|
||||
pub ty: U32Type<'ast>,
|
||||
pub ty: FieldType<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ operation_binary = _ {
|
||||
|
||||
/// Types
|
||||
ty_u32 = {"u32"}
|
||||
ty_field = {"field"}
|
||||
ty_field = {"fe"}
|
||||
ty_bool = {"bool"}
|
||||
ty_basic = { ty_u32 | ty_field | ty_bool }
|
||||
ty_struct = { variable }
|
||||
|
Loading…
Reference in New Issue
Block a user