mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
program a==1 compiles and generates constraints
This commit is contained in:
parent
c798635e29
commit
4a83a0e879
@ -1 +1 @@
|
|||||||
return a + b
|
return a == 1
|
17
src/aleo_program/mod.rs
Normal file
17
src/aleo_program/mod.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//! Module containing structs and types that make up a zokrates_program.
|
||||||
|
//!
|
||||||
|
//! @file zokrates_program.rs
|
||||||
|
//! @author Collin Chin <collin@aleo.org>
|
||||||
|
//! @date 2020
|
||||||
|
|
||||||
|
pub mod types;
|
||||||
|
pub use self::types::*;
|
||||||
|
|
||||||
|
pub mod setup;
|
||||||
|
pub use self::setup::*;
|
||||||
|
|
||||||
|
pub mod types_display;
|
||||||
|
pub use self::types_display::*;
|
||||||
|
|
||||||
|
pub mod types_from;
|
||||||
|
pub use self::types_from::*;
|
15
src/aleo_program/setup.rs
Normal file
15
src/aleo_program/setup.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// use crate::{
|
||||||
|
// aleo_program::program::{
|
||||||
|
// Program,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// impl Program {
|
||||||
|
// pub fn setup(&self) {
|
||||||
|
// self.statements
|
||||||
|
// .iter()
|
||||||
|
// .for_each(|statement| {
|
||||||
|
//
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
162
src/aleo_program/types.rs
Normal file
162
src/aleo_program/types.rs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
//! A zokrates_program consists of nodes that keep track of position and wrap zokrates_program types.
|
||||||
|
//!
|
||||||
|
//! @file types.rs
|
||||||
|
//! @author Collin Chin <collin@aleo.org>
|
||||||
|
//! @date 2020
|
||||||
|
|
||||||
|
// id == 0 for field values
|
||||||
|
// id < 0 for boolean values
|
||||||
|
/// A variable in a constraint system.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Variable(pub String);
|
||||||
|
//
|
||||||
|
// /// Linear combination of variables in a program. (a + b + c)
|
||||||
|
// #[derive(Debug, Clone)]
|
||||||
|
// pub struct LinearCombination (pub Vec<Variable>);
|
||||||
|
//
|
||||||
|
// impl LinearCombination {
|
||||||
|
// pub fn one() -> Self {
|
||||||
|
// LinearCombination(vec![Variable{ id: 0, value: "1".into() }])
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// pub fn value(&self) -> String {
|
||||||
|
// self.0[0].value.clone()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// Quadratic combination of variables in a program (a * b)
|
||||||
|
// #[derive(Debug, Clone)]
|
||||||
|
// pub struct QuadraticCombination (pub LinearCombination, pub LinearCombination);
|
||||||
|
|
||||||
|
/// Expression that evaluates to a field value
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum FieldExpression {
|
||||||
|
Variable(Variable),
|
||||||
|
Number(u32),
|
||||||
|
Add(Box<FieldExpression>, Box<FieldExpression>),
|
||||||
|
Sub(Box<FieldExpression>, Box<FieldExpression>),
|
||||||
|
Mul(Box<FieldExpression>, Box<FieldExpression>),
|
||||||
|
Div(Box<FieldExpression>, Box<FieldExpression>),
|
||||||
|
Pow(Box<FieldExpression>, Box<FieldExpression>),
|
||||||
|
IfElse(
|
||||||
|
Box<BooleanExpression>,
|
||||||
|
Box<FieldExpression>,
|
||||||
|
Box<FieldExpression>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Expression that evaluates to a boolean value
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum BooleanExpression {
|
||||||
|
Variable(Variable),
|
||||||
|
Value(bool),
|
||||||
|
// Boolean operators
|
||||||
|
Not(Box<BooleanExpression>),
|
||||||
|
Or(Box<BooleanExpression>, Box<BooleanExpression>),
|
||||||
|
And(Box<BooleanExpression>, Box<BooleanExpression>),
|
||||||
|
BoolEq(Box<BooleanExpression>, Box<BooleanExpression>),
|
||||||
|
// Field operators
|
||||||
|
FieldEq(Box<FieldExpression>, Box<FieldExpression>),
|
||||||
|
Geq(Box<FieldExpression>, Box<FieldExpression>),
|
||||||
|
Gt(Box<FieldExpression>, Box<FieldExpression>),
|
||||||
|
Leq(Box<FieldExpression>, Box<FieldExpression>),
|
||||||
|
Lt(Box<FieldExpression>, Box<FieldExpression>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Expression that evaluates to a value
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Expression {
|
||||||
|
Boolean(BooleanExpression),
|
||||||
|
FieldElement(FieldExpression),
|
||||||
|
Variable(Variable),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Program statement that defines some action (or expression) to be carried out.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum Statement {
|
||||||
|
/// A statement that could be directly translated to a R1CS constraint a * b = c to be enforced
|
||||||
|
// Constraint(QuadraticCombination, LinearCombination),
|
||||||
|
Declaration(Variable),
|
||||||
|
Definition(Variable, Expression),
|
||||||
|
Return(Vec<Expression>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A simple program with statement expressions, program arguments and program returns.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Program {
|
||||||
|
pub id: String,
|
||||||
|
pub statements: Vec<Statement>,
|
||||||
|
pub arguments: Vec<Variable>,
|
||||||
|
pub returns: Vec<Variable>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_variable() {
|
||||||
|
let variable = Variable("1".into());
|
||||||
|
|
||||||
|
println!("{:#?}", variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn test_linear_combination() {
|
||||||
|
// let variable_0 = Variable { id: 0, value: "1".into() };
|
||||||
|
// let variable_1 = Variable { id: 0, value: "1".into() };
|
||||||
|
// let linear_combination = LinearCombination(vec![variable_0, variable_1]);
|
||||||
|
//
|
||||||
|
// println!("{:#?}", linear_combination);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn test_statement_linear() {
|
||||||
|
// let linear_combination = LinearCombination(vec![Variable { id: 0 }, Variable { id: 1 }]);
|
||||||
|
// let statement_linear = Statement::Linear(linear_combination);
|
||||||
|
//
|
||||||
|
// println!("{:#?}", statement_linear);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// #[test]
|
||||||
|
// fn test_statement_quadratic() {
|
||||||
|
// let linear_combination_0 = LinearCombination(vec![Variable { id: 0 }]);
|
||||||
|
// let linear_combination_1 = LinearCombination(vec![Variable { id: 1 }]);
|
||||||
|
// let statement_quadratic = Statement::Quadratic(linear_combination_0, linear_combination_1);
|
||||||
|
//
|
||||||
|
// println!("{:#?}", statement_quadratic);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// #[test]
|
||||||
|
// fn test_program() {
|
||||||
|
// let variable_0 = Variable{ id: 0};
|
||||||
|
// let linear_combination = LinearCombination(vec![variable_0.clone()]);
|
||||||
|
// let statement_linear = Statement::Linear(linear_combination.clone());
|
||||||
|
// let statement_quadratic = Statement::Quadratic(linear_combination.clone(), linear_combination);
|
||||||
|
// let program = Program{
|
||||||
|
// id: "main".into(),
|
||||||
|
// statements: vec![statement_linear, statement_quadratic],
|
||||||
|
// arguments: vec![variable_0.clone()],
|
||||||
|
// returns: vec![variable_0.clone()]
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// println!("{:#?}", program);
|
||||||
|
// }
|
||||||
|
#[test]
|
||||||
|
fn test_basic_prog() {
|
||||||
|
// return 1 == 1
|
||||||
|
let prog = Program {
|
||||||
|
id: "main".into(),
|
||||||
|
statements: vec![Statement::Return(vec![Expression::Boolean(
|
||||||
|
BooleanExpression::FieldEq(
|
||||||
|
Box::new(FieldExpression::Number(1)),
|
||||||
|
Box::new(FieldExpression::Number(1)),
|
||||||
|
),
|
||||||
|
)])],
|
||||||
|
arguments: vec![],
|
||||||
|
returns: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{:#?}", prog);
|
||||||
|
}
|
||||||
|
}
|
111
src/aleo_program/types_display.rs
Normal file
111
src/aleo_program/types_display.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
//! Format display functions for zokrates_program types.
|
||||||
|
//!
|
||||||
|
//! @file zokrates_program.rs
|
||||||
|
//! @author Collin Chin <collin@aleo.org>
|
||||||
|
//! @date 2020
|
||||||
|
|
||||||
|
use crate::aleo_program::{BooleanExpression, Expression, FieldExpression, Statement, Variable};
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
impl fmt::Display for Variable {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> fmt::Display for FieldExpression {
|
||||||
|
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) => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> fmt::Display for BooleanExpression {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
BooleanExpression::Variable(ref variable) => write!(f, "{}", variable),
|
||||||
|
BooleanExpression::Value(ref value) => write!(f, "{}", value),
|
||||||
|
BooleanExpression::Not(ref expression) => write!(f, "!{}", expression),
|
||||||
|
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::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),
|
||||||
|
BooleanExpression::Gt(ref lhs, ref rhs) => write!(f, "{} > {}", lhs, rhs),
|
||||||
|
BooleanExpression::Leq(ref lhs, ref rhs) => write!(f, "{} <= {}", lhs, rhs),
|
||||||
|
BooleanExpression::Lt(ref lhs, ref rhs) => write!(f, "{} < {}", lhs, rhs),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> fmt::Display for Expression {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Expression::Boolean(ref boolean_expression) => write!(f, "{}", boolean_expression),
|
||||||
|
Expression::FieldElement(ref field_expression) => write!(f, "{}", field_expression),
|
||||||
|
Expression::Variable(ref variable) => write!(f, "{}", variable),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::Display for Statement {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Statement::Return(ref statements) => {
|
||||||
|
statements.iter().for_each(|statement| {
|
||||||
|
write!(f, "return {}", statement).unwrap();
|
||||||
|
});
|
||||||
|
write!(f, "")
|
||||||
|
}
|
||||||
|
_ => unimplemented!(), // Statement::Constraint(ref quadratic, ref linear) => {
|
||||||
|
// let a = (quadratic.0).0[0].value.clone();
|
||||||
|
// let b = (quadratic.1).0[0].value.clone();
|
||||||
|
// let c = linear.0[0].value.clone();
|
||||||
|
//
|
||||||
|
// write!(f, "constraint {} * {} = {}", a, b, c)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::Debug for Statement {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Statement::Return(ref statements) => {
|
||||||
|
statements.iter().for_each(|statement| {
|
||||||
|
write!(f, "return {}", statement).unwrap();
|
||||||
|
});
|
||||||
|
write!(f, "")
|
||||||
|
}
|
||||||
|
_ => unimplemented!(), // Statement::Constraint(ref quadratic, ref linear) => {
|
||||||
|
// let a = (quadratic.0).0[0].value.clone();
|
||||||
|
// let b = (quadratic.1).0[0].value.clone();
|
||||||
|
// let c = linear.0[0].value.clone();
|
||||||
|
//
|
||||||
|
// write!(f, "constraint {} * {} = {}", a, b, c)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl fmt::Debug for Statement {
|
||||||
|
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
// match *self {
|
||||||
|
// Statement::Constraint(ref quadratic, ref linear) => {
|
||||||
|
// let a = (quadratic.0).0[0].value.clone();
|
||||||
|
// let b = (quadratic.1).0[0].value.clone();
|
||||||
|
// let c = linear.0[0].value.clone();
|
||||||
|
//
|
||||||
|
// write!(f, "constraint {} * {} = {}", a, b, c)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
325
src/aleo_program/types_from.rs
Normal file
325
src/aleo_program/types_from.rs
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
//! Logic to convert from an abstract syntax tree (ast) representation to a typed zokrates_program.
|
||||||
|
//! We implement "unwrap" functions instead of the From trait to handle nested statements (flattening).
|
||||||
|
//!
|
||||||
|
//! @file zokrates_program.rs
|
||||||
|
//! @author Collin Chin <collin@aleo.org>
|
||||||
|
//! @date 2020
|
||||||
|
|
||||||
|
use crate::aleo_program::{BooleanExpression, Expression, FieldExpression};
|
||||||
|
use crate::{aleo_program::types, ast};
|
||||||
|
|
||||||
|
// use crate::{
|
||||||
|
// ast,
|
||||||
|
// aleo_program::{program, types, NodeValue},
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// impl<'ast> From<ast::Boolean<'ast>> for types::ExpressionNode<'ast> {
|
||||||
|
// fn from(boolean: ast::Boolean<'ast>) -> Self {
|
||||||
|
// types::Expression::Boolean(
|
||||||
|
// boolean
|
||||||
|
// .value
|
||||||
|
// .parse::<bool>()
|
||||||
|
// .expect("unable to parse boolean"),
|
||||||
|
// )
|
||||||
|
// .span(boolean.span)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> From<ast::Field<'ast>> for types::ExpressionNode<'ast> {
|
||||||
|
// fn from(field: ast::Field<'ast>) -> Self {
|
||||||
|
// types::Expression::Field(field.span.as_str()).span(field.span)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> From<ast::Value<'ast>> for types::ExpressionNode<'ast> {
|
||||||
|
// fn from(value: ast::Value<'ast>) -> Self {
|
||||||
|
// match value {
|
||||||
|
// ast::Value::Boolean(boolean) => types::ExpressionNode::from(boolean),
|
||||||
|
// ast::Value::Field(field) => types::ExpressionNode::from(field),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> From<ast::Variable<'ast>> for types::VariableNode<'ast> {
|
||||||
|
// fn from(variable: ast::Variable<'ast>) -> Self {
|
||||||
|
// types::Variable {
|
||||||
|
// id: variable.span.as_str(),
|
||||||
|
// }
|
||||||
|
// .span(variable.span)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> From<ast::Variable<'ast>> for types::ExpressionNode<'ast> {
|
||||||
|
// fn from(variable: ast::Variable<'ast>) -> Self {
|
||||||
|
// types::Expression::Variable(types::VariableNode::from(variable.clone())).span(variable.span)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> From<ast::NotExpression<'ast>> for types::ExpressionNode<'ast> {
|
||||||
|
// fn from(expression: ast::NotExpression<'ast>) -> Self {
|
||||||
|
// types::Expression::Not(Box::new(types::ExpressionNode::from(
|
||||||
|
// *expression.expression,
|
||||||
|
// )))
|
||||||
|
// .span(expression.span)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl<'ast> From<ast::Field<'ast>> for types::FieldExpression {
|
||||||
|
fn from(field: ast::Field<'ast>) -> Self {
|
||||||
|
let number = field.value.parse::<u32>().expect("unable to unwrap field");
|
||||||
|
FieldExpression::Number(number)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<ast::Boolean<'ast>> for types::BooleanExpression {
|
||||||
|
fn from(boolean: ast::Boolean<'ast>) -> Self {
|
||||||
|
let boolean = boolean
|
||||||
|
.value
|
||||||
|
.parse::<bool>()
|
||||||
|
.expect("unable to unwrap boolean");
|
||||||
|
BooleanExpression::Value(boolean)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<ast::Value<'ast>> for types::Expression {
|
||||||
|
fn from(value: ast::Value<'ast>) -> Self {
|
||||||
|
match value {
|
||||||
|
ast::Value::Boolean(value) => Expression::Boolean(BooleanExpression::from(value)),
|
||||||
|
ast::Value::Field(value) => Expression::FieldElement(FieldExpression::from(value)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<ast::Variable<'ast>> for types::FieldExpression {
|
||||||
|
fn from(variable: ast::Variable<'ast>) -> Self {
|
||||||
|
FieldExpression::Variable(types::Variable(variable.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<ast::Variable<'ast>> for types::BooleanExpression {
|
||||||
|
fn from(variable: ast::Variable<'ast>) -> Self {
|
||||||
|
BooleanExpression::Variable(types::Variable(variable.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<ast::Variable<'ast>> for types::Expression {
|
||||||
|
fn from(variable: ast::Variable<'ast>) -> Self {
|
||||||
|
types::Expression::Variable(types::Variable(variable.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> types::BooleanExpression {
|
||||||
|
/// Find out which types we are comparing and output the corresponding expression.
|
||||||
|
fn from_eq(expression: ast::BinaryExpression<'ast>) -> Self {
|
||||||
|
let left = types::Expression::from(*expression.left);
|
||||||
|
let right = types::Expression::from(*expression.right);
|
||||||
|
|
||||||
|
// When matching a variable, look at the opposite side to see what we are comparing to and assume that variable type
|
||||||
|
match (left, right) {
|
||||||
|
// Boolean equality
|
||||||
|
(Expression::Boolean(lhs), Expression::Boolean(rhs)) => {
|
||||||
|
BooleanExpression::BoolEq(Box::new(lhs), Box::new(rhs))
|
||||||
|
}
|
||||||
|
(Expression::Boolean(lhs), Expression::Variable(rhs)) => {
|
||||||
|
BooleanExpression::BoolEq(Box::new(lhs), Box::new(BooleanExpression::Variable(rhs)))
|
||||||
|
}
|
||||||
|
(Expression::Variable(lhs), Expression::Boolean(rhs)) => {
|
||||||
|
BooleanExpression::BoolEq(Box::new(BooleanExpression::Variable(lhs)), Box::new(rhs))
|
||||||
|
}
|
||||||
|
// Field equality
|
||||||
|
(Expression::FieldElement(lhs), Expression::FieldElement(rhs)) => {
|
||||||
|
BooleanExpression::FieldEq(Box::new(lhs), Box::new(rhs))
|
||||||
|
}
|
||||||
|
(Expression::FieldElement(lhs), Expression::Variable(rhs)) => {
|
||||||
|
BooleanExpression::FieldEq(Box::new(lhs), Box::new(FieldExpression::Variable(rhs)))
|
||||||
|
}
|
||||||
|
(Expression::Variable(lhs), Expression::FieldElement(rhs)) => {
|
||||||
|
BooleanExpression::FieldEq(Box::new(FieldExpression::Variable(lhs)), Box::new(rhs))
|
||||||
|
}
|
||||||
|
|
||||||
|
(_, _) => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<ast::BinaryExpression<'ast>> for types::Expression {
|
||||||
|
fn from(expression: ast::BinaryExpression<'ast>) -> Self {
|
||||||
|
match expression.operation {
|
||||||
|
// Boolean operations
|
||||||
|
ast::BinaryOperator::Or => unimplemented!(),
|
||||||
|
ast::BinaryOperator::And => unimplemented!(),
|
||||||
|
ast::BinaryOperator::Eq => {
|
||||||
|
types::Expression::Boolean(BooleanExpression::from_eq(expression))
|
||||||
|
}
|
||||||
|
ast::BinaryOperator::Neq => unimplemented!(),
|
||||||
|
ast::BinaryOperator::Geq => unimplemented!(),
|
||||||
|
ast::BinaryOperator::Gt => unimplemented!(),
|
||||||
|
ast::BinaryOperator::Leq => unimplemented!(),
|
||||||
|
ast::BinaryOperator::Lt => unimplemented!(),
|
||||||
|
// Field operations
|
||||||
|
ast::BinaryOperator::Add => unimplemented!(),
|
||||||
|
ast::BinaryOperator::Sub => unimplemented!(),
|
||||||
|
ast::BinaryOperator::Mul => unimplemented!(),
|
||||||
|
ast::BinaryOperator::Div => unimplemented!(),
|
||||||
|
ast::BinaryOperator::Pow => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<ast::Expression<'ast>> for types::Expression {
|
||||||
|
fn from(expression: ast::Expression<'ast>) -> Self {
|
||||||
|
match expression {
|
||||||
|
ast::Expression::Value(value) => types::Expression::from(value),
|
||||||
|
ast::Expression::Variable(variable) => types::Expression::from(variable),
|
||||||
|
ast::Expression::Not(_expression) => unimplemented!(),
|
||||||
|
ast::Expression::Binary(expression) => types::Expression::from(expression),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl<'ast> From<ast::AssignStatement<'ast>> for types::StatementNode<'ast> {
|
||||||
|
// fn from(statement: ast::AssignStatement<'ast>) -> Self {
|
||||||
|
// types::Statement::Definition(
|
||||||
|
// types::VariableNode::from(statement.variable),
|
||||||
|
// types::ExpressionNode::from(statement.expression),
|
||||||
|
// )
|
||||||
|
// .span(statement.span)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
impl<'ast> From<ast::ReturnStatement<'ast>> for types::Statement {
|
||||||
|
fn from(statement: ast::ReturnStatement<'ast>) -> Self {
|
||||||
|
types::Statement::Return(
|
||||||
|
statement
|
||||||
|
.expressions
|
||||||
|
.into_iter()
|
||||||
|
.map(|expression| types::Expression::from(expression))
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<ast::Statement<'ast>> for types::Statement {
|
||||||
|
fn from(statement: ast::Statement<'ast>) -> Self {
|
||||||
|
match statement {
|
||||||
|
ast::Statement::Assign(_statement) => unimplemented!(),
|
||||||
|
ast::Statement::Return(statement) => types::Statement::from(statement),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<ast::File<'ast>> for types::Program {
|
||||||
|
fn from(file: ast::File<'ast>) -> Self {
|
||||||
|
let statements = file
|
||||||
|
.statement
|
||||||
|
.into_iter()
|
||||||
|
.map(|statement| types::Statement::from(statement))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
types::Program {
|
||||||
|
id: "main".into(),
|
||||||
|
statements,
|
||||||
|
arguments: vec![],
|
||||||
|
returns: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[cfg(test)]
|
||||||
|
// mod tests {
|
||||||
|
// use super::*;
|
||||||
|
//
|
||||||
|
// #[test]
|
||||||
|
// fn test_file() {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<'ast> From<ast::Variable<'ast>> for types::LinearCombination {
|
||||||
|
// fn from(variable: ast::Variable<'ast>) -> Self {
|
||||||
|
// LinearCombination(vec![Variable { id: 1, value: variable.value }])
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> From<ast::Boolean<'ast>> for types::LinearCombination {
|
||||||
|
// fn from(boolean: ast::Boolean<'ast>) -> Self {
|
||||||
|
// LinearCombination(vec![Variable { id: -1, value: boolean.value }])
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> From<ast::Field<'ast>> for types::LinearCombination {
|
||||||
|
// fn from(field: ast::Field<'ast>) -> Self {
|
||||||
|
// LinearCombination(vec![Variable { id: 0, value: field.value }])
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl<'ast> From<ast::Value<'ast>> for types::LinearCombination {
|
||||||
|
// fn from(value: ast::Value<'ast>) -> Self {
|
||||||
|
// match value {
|
||||||
|
// ast::Value::Boolean(boolean) => types::LinearCombination::from(boolean),
|
||||||
|
// ast::Value::Field(field) => types::LinearCombination::from(field),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> From<ast::Expression<'ast>> for types::LinearCombination {
|
||||||
|
// fn from(expression: ast::Expression<'ast>) -> Self {
|
||||||
|
// match expression {
|
||||||
|
// ast::Expression::Value(value) => types::LinearCombination::from(value),
|
||||||
|
// ast::Expression::Variable(variable) => types::LinearCombination::from(variable),
|
||||||
|
// ast::Expression::Not(_) => unimplemented!(),
|
||||||
|
// ast::Expression::Binary(_) => unimplemented!(),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> types::Expression {
|
||||||
|
// fn unwrap_expression(expression: ast::Expression<'ast>) -> Vec<Self> {
|
||||||
|
// match expression {
|
||||||
|
// ast::Expression::Value(value) => unimplemented!(),
|
||||||
|
// ast::Expression::Variable(variable) => unimplemented!(),
|
||||||
|
// ast::Expression::Not(expression) => unimplemented!(),
|
||||||
|
// ast::Expression::Binary(expression) => Self::unwrap_binary(expression),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fn unwrap_binary(expression: ast::BinaryExpression<'ast>) -> Vec<Self> {
|
||||||
|
// match expression.operation {
|
||||||
|
// ast::BinaryOperator::Eq => ,
|
||||||
|
// _ => unimplemented!()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fn unwrap_eq(expression: ast::BinaryExpression<'ast>) -> Vec<Self> {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> types::Statement {
|
||||||
|
// fn unwrap_statement(statement: ast::Statement<'ast>) -> Self {
|
||||||
|
// match statement {
|
||||||
|
// ast::Statement::Assign(statement) => unimplemented!(),
|
||||||
|
// ast::Statement::Return(statement) => Self::unwrap_return(statement),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fn unwrap_return(statement: ast::ReturnStatement<'ast>) -> Self {
|
||||||
|
// let mut expressions: Vec<types::Expression> = vec![];
|
||||||
|
//
|
||||||
|
// statement
|
||||||
|
// .expressions
|
||||||
|
// .into_iter()
|
||||||
|
// .map(|expression| {
|
||||||
|
// expressions.extend_from_slice(&types::Expression::unwrap_expression(expression))
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// types::Statement::Return(expressions)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl<'ast> From<ast::Statement<'ast>> for types::Statement {
|
||||||
|
// fn from(statement: ast::Statement<'ast>) -> Self {
|
||||||
|
// match statement {
|
||||||
|
// ast::Statement::Assign(statement) => unimplemented!()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
@ -1,3 +1,9 @@
|
|||||||
|
//! Abstract syntax tree (ast) representation from language.pest.
|
||||||
|
//!
|
||||||
|
//! @file zokrates_program.rs
|
||||||
|
//! @author Howard Wu <howard@aleo.org>
|
||||||
|
//! @date 2020
|
||||||
|
|
||||||
use from_pest::{ConversionError, FromPest, Void};
|
use from_pest::{ConversionError, FromPest, Void};
|
||||||
use pest::{
|
use pest::{
|
||||||
error::Error,
|
error::Error,
|
||||||
|
@ -11,4 +11,6 @@ extern crate lazy_static;
|
|||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
|
|
||||||
pub mod program;
|
pub mod aleo_program;
|
||||||
|
|
||||||
|
pub mod zokrates_program;
|
||||||
|
108
src/main.rs
108
src/main.rs
@ -2,17 +2,16 @@ use language::*;
|
|||||||
|
|
||||||
use from_pest::FromPest;
|
use from_pest::FromPest;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
// use std::env;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// use snarkos_gadgets::curves::edwards_bls12::FqGadget;
|
// use snarkos_gadgets::curves::edwards_bls12::FqGadget;
|
||||||
// use snarkos_models::gadgets::{
|
use snarkos_models::gadgets::{
|
||||||
// r1cs::{ConstraintSystem, TestConstraintSystem, Fr},
|
r1cs::{ConstraintSystem, Fr, TestConstraintSystem},
|
||||||
// utilities::{
|
utilities::{
|
||||||
// alloc::{AllocGadget},
|
alloc::AllocGadget, boolean::Boolean, eq::ConditionalEqGadget, uint32::UInt32,
|
||||||
// boolean::Boolean,
|
},
|
||||||
// uint32::UInt32,
|
};
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Read in file as string
|
// Read in file as string
|
||||||
let unparsed_file = fs::read_to_string("simple.program").expect("cannot read file");
|
let unparsed_file = fs::read_to_string("simple.program").expect("cannot read file");
|
||||||
@ -22,10 +21,88 @@ fn main() {
|
|||||||
|
|
||||||
// Build the abstract syntax tree
|
// Build the abstract syntax tree
|
||||||
let syntax_tree = ast::File::from_pest(&mut file).expect("infallible");
|
let syntax_tree = ast::File::from_pest(&mut file).expect("infallible");
|
||||||
|
// println!("{:#?}", syntax_tree);
|
||||||
|
|
||||||
let program = program::Program::from(syntax_tree);
|
let program = aleo_program::Program::from(syntax_tree);
|
||||||
|
println!(" compiled: {:#?}", program);
|
||||||
|
|
||||||
println!("{:?}", program);
|
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||||
|
let argument = std::env::args()
|
||||||
|
.nth(1)
|
||||||
|
.unwrap_or("1".into())
|
||||||
|
.parse::<u32>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!(" argument passed to command line a = {:?}", argument);
|
||||||
|
|
||||||
|
program
|
||||||
|
.statements
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|statement| match statement {
|
||||||
|
aleo_program::Statement::Return(statements) => {
|
||||||
|
statements
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|expression| match expression {
|
||||||
|
aleo_program::Expression::Boolean(operation) => match operation {
|
||||||
|
aleo_program::BooleanExpression::FieldEq(lhs, rhs) => match *lhs {
|
||||||
|
aleo_program::FieldExpression::Variable(variable) => {
|
||||||
|
let left_variable =
|
||||||
|
UInt32::alloc(cs.ns(|| variable.0), Some(argument))
|
||||||
|
.unwrap();
|
||||||
|
match *rhs {
|
||||||
|
aleo_program::FieldExpression::Number(number) => {
|
||||||
|
let right_number = UInt32::constant(number);
|
||||||
|
|
||||||
|
let bool = Boolean::alloc(
|
||||||
|
cs.ns(|| format!("boolean")),
|
||||||
|
|| Ok(true),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
left_variable
|
||||||
|
.conditional_enforce_equal(
|
||||||
|
cs.ns(|| format!("enforce equal")),
|
||||||
|
&right_number,
|
||||||
|
&bool,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
},
|
||||||
|
_ => unimplemented!(),
|
||||||
|
},
|
||||||
|
_ => unimplemented!(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// program
|
||||||
|
// .statements
|
||||||
|
// .into_iter()
|
||||||
|
// .for_each(|statement| {
|
||||||
|
// match statement {
|
||||||
|
// aleo_program::Statement::Constraint(quadratic, linear) => {
|
||||||
|
// let a_var = (quadratic.0).0[0].clone();
|
||||||
|
// assert!(a_var.id > 0);
|
||||||
|
//
|
||||||
|
// let c_var = linear.0[0].clone();
|
||||||
|
// let c_value = c_var.value.parse::<u32>().unwrap();
|
||||||
|
//
|
||||||
|
// let a_bit = UInt32::alloc(cs.ns(|| "a_bit"), Some(argument)).unwrap();
|
||||||
|
// let c_bit = UInt32::constant(c_value);
|
||||||
|
// let bool = Boolean::alloc(cs.ns(|| format!("boolean")), || Ok(true)).unwrap();
|
||||||
|
//
|
||||||
|
// a_bit.conditional_enforce_equal(cs.ns(|| format!("enforce equal")), &c_bit, &bool).unwrap();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// let program = zokrates_program::Program::from(syntax_tree);
|
||||||
|
|
||||||
|
// println!("{:#?}", program);
|
||||||
|
|
||||||
// // Use this code when proving
|
// // Use this code when proving
|
||||||
// let left_u32 = left_string.parse::<u32>().unwrap();
|
// let left_u32 = left_string.parse::<u32>().unwrap();
|
||||||
@ -41,16 +118,19 @@ fn main() {
|
|||||||
//
|
//
|
||||||
// left_constraint.conditional_enforce_equal(cs.ns(|| format!("enforce left == right")), &right_constraint, &bool).unwrap();
|
// left_constraint.conditional_enforce_equal(cs.ns(|| format!("enforce left == right")), &right_constraint, &bool).unwrap();
|
||||||
|
|
||||||
// // Constraint testing
|
// Constraint testing
|
||||||
// let bool = Boolean::alloc(cs.ns(|| format!("boolean")), || Ok(true)).unwrap();
|
// let bool = Boolean::alloc(cs.ns(|| format!("boolean")), || Ok(true)).unwrap();
|
||||||
// let a_bit = UInt32::alloc(cs.ns(|| "a_bit"), Some(4u32)).unwrap();
|
// let a_bit = UInt32::alloc(cs.ns(|| "a_bit"), Some(4u32)).unwrap();
|
||||||
// let b_bit = UInt32::constant(5u32);
|
// let b_bit = UInt32::constant(4u32);
|
||||||
//
|
//
|
||||||
// a_bit.conditional_enforce_equal(cs.ns(|| format!("enforce equal")), &b_bit, &bool).unwrap();
|
// a_bit.conditional_enforce_equal(cs.ns(|| format!("enforce equal")), &b_bit, &bool).unwrap();
|
||||||
|
|
||||||
// println!("satisfied: {:?}", cs.is_satisfied());
|
println!("\n satisfied: {:?}", cs.is_satisfied());
|
||||||
|
|
||||||
// println!("\n\n number of constraints for input: {}", cs.num_constraints());
|
println!(
|
||||||
|
"\n number of constraints for input: {}",
|
||||||
|
cs.num_constraints()
|
||||||
|
);
|
||||||
|
|
||||||
// for token in file.into_inner() {
|
// for token in file.into_inner() {
|
||||||
// match token.as_rule() {
|
// match token.as_rule() {
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
//! Module containing structs and types that make up a zokrates_program.
|
||||||
|
//!
|
||||||
|
//! @file zokrates_program.rs
|
||||||
|
//! @author Collin Chin <collin@aleo.org>
|
||||||
|
//! @date 2020
|
||||||
|
|
||||||
pub mod program;
|
pub mod program;
|
||||||
pub use self::program::*;
|
pub use self::program::*;
|
||||||
|
|
@ -1,11 +1,15 @@
|
|||||||
use crate::program::{Expression, ExpressionList, Statement, StatementNode, Variable};
|
//! A zokrates_program consists of nodes that keep track of position and wrap zokrates_program types.
|
||||||
|
//!
|
||||||
|
//! @file zokrates_program.rs
|
||||||
|
//! @author Collin Chin <collin@aleo.org>
|
||||||
|
//! @date 2020
|
||||||
|
|
||||||
|
use crate::zokrates_program::{Expression, ExpressionList, Statement, StatementNode, Variable};
|
||||||
|
|
||||||
use pest::Span;
|
use pest::Span;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Formatter;
|
use std::fmt::Formatter;
|
||||||
|
|
||||||
// AST -> Program
|
|
||||||
|
|
||||||
/// Position in input file
|
/// Position in input file
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
@ -25,7 +29,7 @@ impl fmt::Debug for Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Building blocks for a program
|
/// Building blocks for a zokrates_program
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Node<T: fmt::Display> {
|
pub struct Node<T: fmt::Display> {
|
||||||
start: Position,
|
start: Position,
|
@ -1,6 +1,11 @@
|
|||||||
use crate::program::Node;
|
//! A zokrates_program type constrains data that an expression might take.
|
||||||
|
//!
|
||||||
|
//! @file zokrates_program.rs
|
||||||
|
//! @author Collin Chin <collin@aleo.org>
|
||||||
|
//! @date 2020
|
||||||
|
|
||||||
|
use crate::zokrates_program::Node;
|
||||||
|
|
||||||
// Program Nodes - Wrappers for different types in a program.
|
|
||||||
pub type ExpressionNode<'ast> = Node<Expression<'ast>>;
|
pub type ExpressionNode<'ast> = Node<Expression<'ast>>;
|
||||||
pub type ExpressionListNode<'ast> = Node<ExpressionList<'ast>>;
|
pub type ExpressionListNode<'ast> = Node<ExpressionList<'ast>>;
|
||||||
pub type StatementNode<'ast> = Node<Statement<'ast>>;
|
pub type StatementNode<'ast> = Node<Statement<'ast>>;
|
@ -1,4 +1,10 @@
|
|||||||
use crate::program::{Expression, ExpressionList, Statement, Variable};
|
//! Format display functions for zokrates_program types.
|
||||||
|
//!
|
||||||
|
//! @file zokrates_program.rs
|
||||||
|
//! @author Collin Chin <collin@aleo.org>
|
||||||
|
//! @date 2020
|
||||||
|
|
||||||
|
use crate::zokrates_program::{Expression, ExpressionList, Statement, Variable};
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
@ -1,6 +1,12 @@
|
|||||||
|
//! Logic to convert from an abstract syntax tree (ast) representation to a typed zokrates_program.
|
||||||
|
//!
|
||||||
|
//! @file zokrates_program.rs
|
||||||
|
//! @author Collin Chin <collin@aleo.org>
|
||||||
|
//! @date 2020
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast,
|
ast,
|
||||||
program::{program, types, NodeValue},
|
zokrates_program::{program, types, NodeValue},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'ast> From<ast::Boolean<'ast>> for types::ExpressionNode<'ast> {
|
impl<'ast> From<ast::Boolean<'ast>> for types::ExpressionNode<'ast> {
|
||||||
@ -169,10 +175,5 @@ impl<'ast> From<ast::File<'ast>> for program::Program<'ast> {
|
|||||||
.map(|statement| types::StatementNode::from(statement.clone()))
|
.map(|statement| types::StatementNode::from(statement.clone()))
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
// for statement in file.statement {
|
|
||||||
// // println!("statement {:?}", statement);
|
|
||||||
// let node = program::StatementNode::from(statement);
|
|
||||||
// println!("node {:?}", node);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user