mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-22 22:44:47 +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 pest::{
|
||||
error::Error,
|
||||
|
@ -11,4 +11,6 @@ extern crate lazy_static;
|
||||
|
||||
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 std::fs;
|
||||
// use std::env;
|
||||
|
||||
fn main() {
|
||||
// use snarkos_gadgets::curves::edwards_bls12::FqGadget;
|
||||
// use snarkos_models::gadgets::{
|
||||
// r1cs::{ConstraintSystem, TestConstraintSystem, Fr},
|
||||
// utilities::{
|
||||
// alloc::{AllocGadget},
|
||||
// boolean::Boolean,
|
||||
// uint32::UInt32,
|
||||
// }
|
||||
// };
|
||||
use snarkos_models::gadgets::{
|
||||
r1cs::{ConstraintSystem, Fr, TestConstraintSystem},
|
||||
utilities::{
|
||||
alloc::AllocGadget, boolean::Boolean, eq::ConditionalEqGadget, uint32::UInt32,
|
||||
},
|
||||
};
|
||||
|
||||
// Read in file as string
|
||||
let unparsed_file = fs::read_to_string("simple.program").expect("cannot read file");
|
||||
@ -22,10 +21,88 @@ fn main() {
|
||||
|
||||
// Build the abstract syntax tree
|
||||
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
|
||||
// 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();
|
||||
|
||||
// // Constraint testing
|
||||
// Constraint testing
|
||||
// let bool = Boolean::alloc(cs.ns(|| format!("boolean")), || Ok(true)).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();
|
||||
|
||||
// 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() {
|
||||
// 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 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 std::fmt;
|
||||
use std::fmt::Formatter;
|
||||
|
||||
// AST -> Program
|
||||
|
||||
/// Position in input file
|
||||
#[derive(Clone, Copy)]
|
||||
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)]
|
||||
pub struct Node<T: fmt::Display> {
|
||||
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 ExpressionListNode<'ast> = Node<ExpressionList<'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;
|
||||
|
@ -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::{
|
||||
ast,
|
||||
program::{program, types, NodeValue},
|
||||
zokrates_program::{program, types, NodeValue},
|
||||
};
|
||||
|
||||
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()))
|
||||
.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