mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-08-15 16:50:22 +03:00
constraints inline array
This commit is contained in:
parent
2f9e4b31e0
commit
83763a6817
@ -1,7 +1,3 @@
|
||||
struct Foo {
|
||||
field a
|
||||
bool b
|
||||
}
|
||||
def main() -> (field) :
|
||||
a = 1 + 1
|
||||
return a
|
||||
field[3] a = [1, 2, 3]
|
||||
//b = 2 + 2
|
||||
return a
|
@ -1,5 +1,6 @@
|
||||
use crate::aleo_program::{
|
||||
BooleanExpression, Expression, FieldExpression, Function, Program, Statement, Struct, Variable,
|
||||
BooleanExpression, BooleanSpreadOrExpression, Expression, FieldExpression,
|
||||
FieldSpreadOrExpression, Function, Program, Statement, Struct, Variable,
|
||||
};
|
||||
|
||||
use snarkos_models::curves::{Field, PrimeField};
|
||||
@ -9,15 +10,37 @@ use snarkos_models::gadgets::{
|
||||
utilities::{alloc::AllocGadget, boolean::Boolean, eq::ConditionalEqGadget, uint32::UInt32},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum ResolvedValue {
|
||||
Boolean(Boolean),
|
||||
BooleanArray(Vec<Boolean>),
|
||||
FieldElement(UInt32),
|
||||
FieldElementArray(Vec<UInt32>),
|
||||
Struct(Struct),
|
||||
Function(Function),
|
||||
}
|
||||
|
||||
impl fmt::Display for ResolvedValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ResolvedValue::FieldElement(ref value) => write!(f, "{}", value.value.unwrap()),
|
||||
ResolvedValue::FieldElementArray(ref array) => {
|
||||
write!(f, "[")?;
|
||||
for (i, e) in array.iter().enumerate() {
|
||||
write!(f, "{}", e.value.unwrap())?;
|
||||
if i < array.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
_ => unimplemented!("resolve values not finished"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ResolvedProgram {
|
||||
pub resolved_variables: HashMap<Variable, ResolvedValue>,
|
||||
}
|
||||
@ -101,7 +124,10 @@ impl ResolvedProgram {
|
||||
match expression {
|
||||
FieldExpression::Variable(variable) => self.u32_from_variable(cs, variable),
|
||||
FieldExpression::Number(number) => UInt32::constant(number),
|
||||
field => self.enforce_field_expression(cs, field),
|
||||
field => match self.enforce_field_expression(cs, field) {
|
||||
ResolvedValue::FieldElement(value) => value,
|
||||
_ => unimplemented!("value not resolved"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,15 +321,29 @@ impl ResolvedProgram {
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
expression: FieldExpression,
|
||||
) -> UInt32 {
|
||||
) -> ResolvedValue {
|
||||
match expression {
|
||||
FieldExpression::Variable(variable) => self.u32_from_variable(cs, variable),
|
||||
FieldExpression::Number(number) => UInt32::constant(number),
|
||||
FieldExpression::Add(left, right) => self.enforce_add(cs, *left, *right),
|
||||
FieldExpression::Sub(left, right) => self.enforce_sub(cs, *left, *right),
|
||||
FieldExpression::Mul(left, right) => self.enforce_mul(cs, *left, *right),
|
||||
FieldExpression::Div(left, right) => self.enforce_div(cs, *left, *right),
|
||||
FieldExpression::Pow(left, right) => self.enforce_pow(cs, *left, *right),
|
||||
FieldExpression::Variable(variable) => {
|
||||
ResolvedValue::FieldElement(self.u32_from_variable(cs, variable))
|
||||
}
|
||||
FieldExpression::Number(number) => {
|
||||
ResolvedValue::FieldElement(UInt32::constant(number))
|
||||
}
|
||||
FieldExpression::Add(left, right) => {
|
||||
ResolvedValue::FieldElement(self.enforce_add(cs, *left, *right))
|
||||
}
|
||||
FieldExpression::Sub(left, right) => {
|
||||
ResolvedValue::FieldElement(self.enforce_sub(cs, *left, *right))
|
||||
}
|
||||
FieldExpression::Mul(left, right) => {
|
||||
ResolvedValue::FieldElement(self.enforce_mul(cs, *left, *right))
|
||||
}
|
||||
FieldExpression::Div(left, right) => {
|
||||
ResolvedValue::FieldElement(self.enforce_div(cs, *left, *right))
|
||||
}
|
||||
FieldExpression::Pow(left, right) => {
|
||||
ResolvedValue::FieldElement(self.enforce_pow(cs, *left, *right))
|
||||
}
|
||||
FieldExpression::IfElse(first, second, third) => {
|
||||
if self
|
||||
.enforce_boolean_expression(cs, *first)
|
||||
@ -314,6 +354,23 @@ impl ResolvedProgram {
|
||||
self.enforce_field_expression(cs, *third)
|
||||
}
|
||||
}
|
||||
FieldExpression::Array(array) => ResolvedValue::FieldElementArray(
|
||||
array
|
||||
.into_iter()
|
||||
.map(|element| match *element {
|
||||
FieldSpreadOrExpression::Spread(spread) => {
|
||||
unimplemented!("spreads not enforced yet")
|
||||
}
|
||||
FieldSpreadOrExpression::FieldExpression(expression) => {
|
||||
let resolved = self.enforce_field_expression(cs, expression);
|
||||
match resolved {
|
||||
ResolvedValue::FieldElement(value) => value,
|
||||
_ => unimplemented!("cannot resolve field"),
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<UInt32>>(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,12 +392,8 @@ impl ResolvedProgram {
|
||||
}
|
||||
Expression::FieldElement(field_expression) => {
|
||||
let res = self.enforce_field_expression(cs, field_expression);
|
||||
println!(
|
||||
" variable field result: {} = {}",
|
||||
variable.0,
|
||||
res.value.unwrap()
|
||||
);
|
||||
self.insert(variable, ResolvedValue::FieldElement(res));
|
||||
println!(" variable field result: {} = {}", variable.0, res);
|
||||
self.insert(variable, res);
|
||||
}
|
||||
Expression::Variable(unresolved_variable) => {
|
||||
if self.resolved_variables.contains_key(&unresolved_variable) {
|
||||
@ -392,7 +445,7 @@ impl ResolvedProgram {
|
||||
}
|
||||
Expression::FieldElement(field_expression) => {
|
||||
let res = self.enforce_field_expression(cs, field_expression);
|
||||
println!("\n Field result = {}", res.value.unwrap());
|
||||
println!("\n Field result = {}", res);
|
||||
}
|
||||
Expression::Variable(variable) => {
|
||||
match self.resolved_variables.get_mut(&variable).unwrap().clone() {
|
||||
@ -435,18 +488,19 @@ impl ResolvedProgram {
|
||||
.insert(variable, ResolvedValue::Function(function));
|
||||
});
|
||||
|
||||
let main = resolved_program
|
||||
.resolved_variables
|
||||
.get_mut(&Variable("main".into()))
|
||||
.expect("main function not defined");
|
||||
match main {
|
||||
ResolvedValue::Function(function) => function
|
||||
.statements
|
||||
.clone()
|
||||
.into_iter()
|
||||
.for_each(|statement| resolved_program.enforce_statement(cs, statement)),
|
||||
_ => unimplemented!("main must be a function"),
|
||||
}
|
||||
// let main = resolved_program
|
||||
// .resolved_variables
|
||||
// .get_mut(&Variable("main".into()))
|
||||
// .expect("main function not defined");
|
||||
//
|
||||
// match main {
|
||||
// ResolvedValue::Function(function) => function
|
||||
// .statements
|
||||
// .clone()
|
||||
// .into_iter()
|
||||
// .for_each(|statement| resolved_program.enforce_statement(cs, statement)),
|
||||
// _ => unimplemented!("main must be a function"),
|
||||
// }
|
||||
|
||||
program
|
||||
.statements
|
||||
|
@ -10,6 +10,17 @@ use std::collections::HashMap;
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Variable(pub String);
|
||||
|
||||
/// Spread operator
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FieldSpread(pub FieldExpression);
|
||||
|
||||
/// Spread or field expression enum
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum FieldSpreadOrExpression {
|
||||
Spread(FieldSpread),
|
||||
FieldExpression(FieldExpression),
|
||||
}
|
||||
|
||||
/// Expression that evaluates to a field value
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum FieldExpression {
|
||||
@ -27,6 +38,19 @@ pub enum FieldExpression {
|
||||
Box<FieldExpression>,
|
||||
Box<FieldExpression>,
|
||||
),
|
||||
// Arrays
|
||||
Array(Vec<Box<FieldSpreadOrExpression>>),
|
||||
}
|
||||
|
||||
/// Spread operator
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BooleanSpread(pub BooleanExpression);
|
||||
|
||||
/// Spread or field expression enum
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum BooleanSpreadOrExpression {
|
||||
Spread(BooleanSpread),
|
||||
BooleanExpression(BooleanExpression),
|
||||
}
|
||||
|
||||
/// Expression that evaluates to a boolean value
|
||||
@ -51,6 +75,8 @@ pub enum BooleanExpression {
|
||||
Box<BooleanExpression>,
|
||||
Box<BooleanExpression>,
|
||||
),
|
||||
// Arrays
|
||||
Array(Vec<Box<BooleanSpreadOrExpression>>),
|
||||
}
|
||||
|
||||
/// Expression that evaluates to a value
|
||||
|
@ -5,7 +5,8 @@
|
||||
//! @date 2020
|
||||
|
||||
use crate::aleo_program::{
|
||||
BooleanExpression, Expression, FieldExpression, Statement, Struct, StructField, Type, Variable,
|
||||
BooleanExpression, Expression, FieldExpression, FieldSpread, FieldSpreadOrExpression,
|
||||
Statement, Struct, StructField, Type, Variable,
|
||||
};
|
||||
|
||||
use std::fmt;
|
||||
@ -16,6 +17,21 @@ impl fmt::Display for Variable {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for FieldSpread {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "...{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for FieldSpreadOrExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
FieldSpreadOrExpression::Spread(ref spread) => write!(f, "{}", spread),
|
||||
FieldSpreadOrExpression::FieldExpression(ref expression) => write!(f, "{}", expression),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for FieldExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
@ -29,6 +45,16 @@ impl<'ast> fmt::Display for FieldExpression {
|
||||
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, "]")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,6 +77,7 @@ impl<'ast> fmt::Display for BooleanExpression {
|
||||
BooleanExpression::IfElse(ref a, ref b, ref c) => {
|
||||
write!(f, "if {} then {} else {} fi", a, b, c)
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,6 +286,9 @@ impl<'ast> From<ast::Expression<'ast>> for types::Expression {
|
||||
ast::Expression::Not(expression) => types::Expression::from(expression),
|
||||
ast::Expression::Binary(expression) => types::Expression::from(expression),
|
||||
ast::Expression::Ternary(expression) => types::Expression::from(expression),
|
||||
ast::Expression::ArrayInline(expression) => {
|
||||
unimplemented!("unknown type for inline array expression")
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
@ -300,11 +303,120 @@ impl<'ast> From<ast::AssignStatement<'ast>> for types::Statement {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::Spread<'ast>> for types::BooleanSpread {
|
||||
fn from(spread: ast::Spread<'ast>) -> Self {
|
||||
let boolean_expression = types::Expression::from(spread.expression);
|
||||
match boolean_expression {
|
||||
types::Expression::Boolean(expression) => types::BooleanSpread(expression),
|
||||
_ => unimplemented!("cannot create boolean spread from field type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::Spread<'ast>> for types::FieldSpread {
|
||||
fn from(spread: ast::Spread<'ast>) -> Self {
|
||||
let field_expression = types::Expression::from(spread.expression);
|
||||
match field_expression {
|
||||
types::Expression::FieldElement(expression) => types::FieldSpread(expression),
|
||||
_ => unimplemented!("cannot create field spread from boolean type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::SpreadOrExpression<'ast>> for types::BooleanSpreadOrExpression {
|
||||
fn from(s_or_e: ast::SpreadOrExpression<'ast>) -> Self {
|
||||
match s_or_e {
|
||||
ast::SpreadOrExpression::Spread(spread) => {
|
||||
types::BooleanSpreadOrExpression::Spread(types::BooleanSpread::from(spread))
|
||||
}
|
||||
ast::SpreadOrExpression::Expression(expression) => {
|
||||
let boolean_expression = types::Expression::from(expression);
|
||||
match boolean_expression {
|
||||
types::Expression::Boolean(expression) => {
|
||||
types::BooleanSpreadOrExpression::BooleanExpression(expression)
|
||||
}
|
||||
_ => unimplemented!("cannot create boolean expression from field type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::SpreadOrExpression<'ast>> for types::FieldSpreadOrExpression {
|
||||
fn from(s_or_e: ast::SpreadOrExpression<'ast>) -> Self {
|
||||
match s_or_e {
|
||||
ast::SpreadOrExpression::Spread(spread) => {
|
||||
types::FieldSpreadOrExpression::Spread(types::FieldSpread::from(spread))
|
||||
}
|
||||
ast::SpreadOrExpression::Expression(expression) => {
|
||||
let field_expression = types::Expression::from(expression);
|
||||
match field_expression {
|
||||
types::Expression::FieldElement(expression) => {
|
||||
types::FieldSpreadOrExpression::FieldExpression(expression)
|
||||
}
|
||||
_ => unimplemented!("cannot create field expression from boolean type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> types::Expression {
|
||||
fn from_basic(ty: ast::BasicType<'ast>, expression: ast::Expression<'ast>) -> Self {
|
||||
unimplemented!("from basic not impl");
|
||||
}
|
||||
|
||||
fn from_array(ty: ast::ArrayType<'ast>, expression: ast::Expression<'ast>) -> Self {
|
||||
match ty.ty {
|
||||
ast::BasicType::Boolean(_ty) => {
|
||||
let elements: Vec<Box<types::BooleanSpreadOrExpression>> = match expression {
|
||||
ast::Expression::ArrayInline(array) => array
|
||||
.expressions
|
||||
.into_iter()
|
||||
.map(|s_or_e| Box::new(types::BooleanSpreadOrExpression::from(s_or_e)))
|
||||
.collect(),
|
||||
ast::Expression::ArrayInitializer(expression) => {
|
||||
unimplemented!("no array init yet")
|
||||
}
|
||||
_ => unimplemented!("expected array after array type"),
|
||||
};
|
||||
types::Expression::Boolean(types::BooleanExpression::Array(elements))
|
||||
}
|
||||
ast::BasicType::Field(_ty) => {
|
||||
let elements: Vec<Box<types::FieldSpreadOrExpression>> = 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(expression) => {
|
||||
unimplemented!("array init not yet")
|
||||
}
|
||||
_ => unimplemented!("expected array after array type"),
|
||||
};
|
||||
types::Expression::FieldElement(types::FieldExpression::Array(elements))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn from_struct(ty: ast::StructType<'ast>, expression: ast::Expression<'ast>) -> Self {
|
||||
unimplemented!("from struct not impl");
|
||||
}
|
||||
|
||||
fn from_type(ty: ast::Type<'ast>, expression: ast::Expression<'ast>) -> Self {
|
||||
match ty {
|
||||
ast::Type::Basic(ty) => Self::from_basic(ty, expression),
|
||||
ast::Type::Array(ty) => Self::from_array(ty, expression),
|
||||
ast::Type::Struct(ty) => Self::from_struct(ty, expression),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::DefinitionStatement<'ast>> for types::Statement {
|
||||
fn from(statement: ast::DefinitionStatement<'ast>) -> Self {
|
||||
types::Statement::Definition(
|
||||
types::Variable::from(statement.variable),
|
||||
types::Expression::from(statement.expression),
|
||||
types::Expression::from_type(statement.ty, statement.expression),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -333,8 +445,8 @@ impl<'ast> From<ast::Statement<'ast>> for types::Statement {
|
||||
match statement {
|
||||
ast::Statement::Assign(statement) => types::Statement::from(statement),
|
||||
ast::Statement::Definition(statement) => types::Statement::from(statement),
|
||||
ast::Statement::Return(statement) => types::Statement::from(statement),
|
||||
ast::Statement::Iteration(statement) => types::Statement::from(statement),
|
||||
ast::Statement::Return(statement) => types::Statement::from(statement),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ ty_bool = {"bool"}
|
||||
ty_basic = { ty_field | ty_bool }
|
||||
ty_struct = { variable }
|
||||
ty_basic_or_struct = {ty_basic | ty_struct }
|
||||
ty_array = {ty_basic ~ ("[" ~ expression ~ "]")+ }
|
||||
ty_array = {ty_basic ~ ("[" ~ value ~ "]")+ }
|
||||
ty = {ty_array | ty_basic | ty_struct}
|
||||
type_list = _{(ty ~ ("," ~ ty)*)?}
|
||||
|
||||
@ -140,8 +140,8 @@ statement_iteration = { "for" ~ ty ~ variable ~ "in" ~ expression ~ ".." ~ expre
|
||||
statement = {
|
||||
(statement_return
|
||||
| (statement_iteration
|
||||
| statement_assign
|
||||
| statement_definition
|
||||
| statement_assign
|
||||
) ~ NEWLINE
|
||||
) ~ NEWLINE*
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user