add and constrain explict type for u32

This commit is contained in:
collin 2020-04-20 13:06:47 -07:00
parent dbbf816645
commit 1bbe71d726
9 changed files with 1247 additions and 1114 deletions

View File

@ -1,4 +1,5 @@
from "./simple_import" import foo
from "./simple_import" import Point
def main() -> (field):
return foo()
def main() -> (Point):
Point p = Point { x: 1u32, y: 2u32}
return p

View File

@ -1,3 +1,4 @@
def foo() -> (field):
// return myGlobal <- not allowed
return 42
struct Point {
u32 x
u32 y
}

File diff suppressed because it is too large Load Diff

View File

@ -1,146 +1,192 @@
//! A zokrates_program consists of nodes that keep track of position and wrap zokrates_program types.
//! A typed program in aleo consists of import, struct, and function definitions.
//! Each defined type consists of typed statements and expressions.
//!
//! @file types.rs
//! @author Collin Chin <collin@aleo.org>
//! @date 2020
use crate::aleo_program::Import;
use snarkos_models::curves::{Field, PrimeField};
use std::collections::HashMap;
use std::marker::PhantomData;
/// A variable in a constraint system.
#[derive(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),
pub struct Variable<F: Field + PrimeField> {
pub name: String,
pub(crate) _field: PhantomData<F>,
}
/// Range or field expression enum
/// An integer type enum wrapping the integer value
#[derive(Debug, Clone)]
pub enum FieldRangeOrExpression {
Range(Option<FieldExpression>, Option<FieldExpression>),
FieldExpression(FieldExpression),
pub enum Integer {
// U8(u8),
U32(u32),
// U64(u64),
}
/// Spread operator or u32 expression enum
#[derive(Debug, Clone)]
pub enum IntegerSpreadOrExpression<F: Field + PrimeField> {
Spread(IntegerExpression<F>),
Expression(IntegerExpression<F>),
}
/// Range or integer expression enum
#[derive(Debug, Clone)]
pub enum IntegerRangeOrExpression<F: Field + PrimeField> {
Range(Option<IntegerExpression<F>>, Option<IntegerExpression<F>>),
Expression(IntegerExpression<F>),
}
/// Expression that evaluates to a u32 value
#[derive(Debug, Clone)]
pub enum IntegerExpression<F: Field + PrimeField> {
Variable(Variable<F>),
Number(Integer),
// Operators
Add(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
Sub(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
Mul(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
Div(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
Pow(Box<IntegerExpression<F>>, Box<IntegerExpression<F>>),
// Conditionals
IfElse(
Box<BooleanExpression<F>>,
Box<IntegerExpression<F>>,
Box<IntegerExpression<F>>,
),
// Arrays
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>),
// }
/// Expression that evaluates to a field value
#[derive(Debug, Clone)]
pub enum FieldExpression {
Variable(Variable),
Number(u32),
// Operators
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>),
// Conditionals
IfElse(
Box<BooleanExpression>,
Box<FieldExpression>,
Box<FieldExpression>,
),
// Arrays
Array(Vec<Box<FieldSpreadOrExpression>>),
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>>>),
}
/// 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),
pub enum BooleanSpreadOrExpression<F: Field + PrimeField> {
Spread(BooleanExpression<F>),
Expression(BooleanExpression<F>),
}
/// Expression that evaluates to a boolean value
#[derive(Debug, Clone)]
pub enum BooleanExpression {
Variable(Variable),
pub enum BooleanExpression<F: Field + PrimeField> {
Variable(Variable<F>),
Value(bool),
// Boolean operators
Not(Box<BooleanExpression>),
Or(Box<BooleanExpression>, Box<BooleanExpression>),
And(Box<BooleanExpression>, Box<BooleanExpression>),
BoolEq(Box<BooleanExpression>, Box<BooleanExpression>),
Not(Box<BooleanExpression<F>>),
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<FieldExpression>, Box<FieldExpression>),
Geq(Box<FieldExpression>, Box<FieldExpression>),
Gt(Box<FieldExpression>, Box<FieldExpression>),
Leq(Box<FieldExpression>, Box<FieldExpression>),
Lt(Box<FieldExpression>, Box<FieldExpression>),
FieldEq(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>>),
// Conditionals
IfElse(
Box<BooleanExpression>,
Box<BooleanExpression>,
Box<BooleanExpression>,
Box<BooleanExpression<F>>,
Box<BooleanExpression<F>>,
Box<BooleanExpression<F>>,
),
// Arrays
Array(Vec<Box<BooleanSpreadOrExpression>>),
Array(Vec<Box<BooleanSpreadOrExpression<F>>>),
}
/// Expression that evaluates to a value
#[derive(Debug, Clone)]
pub enum Expression {
Boolean(BooleanExpression),
FieldElement(FieldExpression),
Variable(Variable),
Struct(Variable, Vec<StructMember>),
ArrayAccess(Box<Expression>, FieldRangeOrExpression),
StructMemberAccess(Box<Expression>, Variable), // (struct name, struct member name)
FunctionCall(Box<Expression>, Vec<Expression>),
pub enum Expression<F: Field + PrimeField> {
Integer(IntegerExpression<F>),
FieldElement(FieldExpression<F>),
Boolean(BooleanExpression<F>),
Variable(Variable<F>),
Struct(Variable<F>, Vec<StructMember<F>>),
ArrayAccess(Box<Expression<F>>, IntegerRangeOrExpression<F>),
StructMemberAccess(Box<Expression<F>>, Variable<F>), // (struct name, struct member name)
FunctionCall(Box<Expression<F>>, Vec<Expression<F>>),
}
/// Definition assignee: v, arr[0..2], Point p.x
#[derive(Debug, Clone)]
pub enum Assignee {
Variable(Variable),
Array(Box<Assignee>, FieldRangeOrExpression),
StructMember(Box<Assignee>, Variable),
pub enum Assignee<F: Field + PrimeField> {
Variable(Variable<F>),
Array(Box<Assignee<F>>, IntegerRangeOrExpression<F>),
StructMember(Box<Assignee<F>>, Variable<F>),
}
/// Program statement that defines some action (or expression) to be carried out.
#[derive(Clone)]
pub enum Statement {
pub enum Statement<F: Field + PrimeField> {
// Declaration(Variable),
Definition(Assignee, Expression),
For(Variable, FieldExpression, FieldExpression, Vec<Statement>),
Return(Vec<Expression>),
Definition(Assignee<F>, Expression<F>),
For(
Variable<F>,
IntegerExpression<F>,
IntegerExpression<F>,
Vec<Statement<F>>,
),
Return(Vec<Expression<F>>),
}
/// Explicit type used for defining struct members and function parameters
#[derive(Clone, Debug)]
pub enum Type {
Boolean,
pub enum Type<F: Field + PrimeField> {
U32,
FieldElement,
Array(Box<Type>, usize),
Struct(Variable),
Boolean,
Array(Box<Type<F>>, usize),
Struct(Variable<F>),
}
#[derive(Clone, Debug)]
pub struct StructMember {
pub variable: Variable,
pub expression: Expression,
pub struct StructMember<F: Field + PrimeField> {
pub variable: Variable<F>,
pub expression: Expression<F>,
}
#[derive(Clone)]
pub struct StructField {
pub variable: Variable,
pub ty: Type,
pub struct StructField<F: Field + PrimeField> {
pub variable: Variable<F>,
pub ty: Type<F>,
}
#[derive(Clone)]
pub struct Struct {
pub variable: Variable,
pub fields: Vec<StructField>,
pub struct Struct<F: Field + PrimeField> {
pub variable: Variable<F>,
pub fields: Vec<StructField<F>>,
}
/// Function parameters
#[derive(Clone, Debug)]
pub enum Visibility {
Public,
@ -148,10 +194,10 @@ pub enum Visibility {
}
#[derive(Clone)]
pub struct Parameter {
pub struct Parameter<F: Field + PrimeField> {
pub visibility: Option<Visibility>,
pub ty: Type,
pub variable: Variable,
pub ty: Type<F>,
pub variable: Variable<F>,
}
/// The given name for a defined function in the program.
@ -159,14 +205,14 @@ pub struct Parameter {
pub struct FunctionName(pub String);
#[derive(Clone)]
pub struct Function {
pub struct Function<F: Field + PrimeField> {
pub function_name: FunctionName,
pub parameters: Vec<Parameter>,
pub returns: Vec<Type>,
pub statements: Vec<Statement>,
pub parameters: Vec<Parameter<F>>,
pub returns: Vec<Type<F>>,
pub statements: Vec<Statement<F>>,
}
impl Function {
impl<F: Field + PrimeField> Function<F> {
pub fn get_name(&self) -> String {
self.function_name.0.clone()
}
@ -174,28 +220,19 @@ impl Function {
/// A simple program with statement expressions, program arguments and program returns.
#[derive(Debug, Clone)]
pub struct Program<'ast> {
pub name: Variable,
pub struct Program<'ast, F: Field + PrimeField> {
pub name: Variable<F>,
pub imports: Vec<Import<'ast>>,
pub structs: HashMap<Variable, Struct>,
pub functions: HashMap<FunctionName, Function>,
pub structs: HashMap<Variable<F>, Struct<F>>,
pub functions: HashMap<FunctionName, Function<F>>,
}
impl<'ast> Program<'ast> {
impl<'ast, F: Field + PrimeField> Program<'ast, F> {
pub fn name(mut self, name: String) -> Self {
self.name = Variable(name);
self.name = Variable {
name,
_field: PhantomData::<F>,
};
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_variable() {
let variable = Variable("1".into());
println!("{:#?}", variable);
}
}

View File

@ -5,53 +5,56 @@
//! @date 2020
use crate::aleo_program::{
Assignee, BooleanExpression, BooleanSpread, BooleanSpreadOrExpression, Expression,
FieldExpression, FieldRangeOrExpression, FieldSpread, FieldSpreadOrExpression, Function,
FunctionName, Parameter, Statement, Struct, StructField, Type, Variable,
Assignee, BooleanExpression, BooleanSpreadOrExpression, Expression, Function, FunctionName,
Integer, IntegerExpression, IntegerRangeOrExpression, IntegerSpreadOrExpression, Parameter,
Statement, Struct, StructField, Type, Variable,
};
use snarkos_models::curves::{Field, PrimeField};
use std::fmt;
impl fmt::Display for Variable {
impl<F: Field + PrimeField> fmt::Display for Variable<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
write!(f, "{}", self.name)
}
}
impl fmt::Debug for Variable {
impl<F: Field + PrimeField> fmt::Debug for Variable<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
write!(f, "{}", self.name)
}
}
impl fmt::Display for FieldSpread {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "...{}", self.0)
}
}
impl fmt::Display for FieldSpreadOrExpression {
impl fmt::Display for Integer {
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),
Integer::U32(ref num) => write!(f, "{}", num),
}
}
}
impl<'ast> fmt::Display for FieldExpression {
impl<F: Field + PrimeField> fmt::Display for IntegerSpreadOrExpression<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) => {
IntegerSpreadOrExpression::Spread(ref spread) => write!(f, "...{}", spread),
IntegerSpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression),
}
}
}
impl<'ast, F: Field + PrimeField> fmt::Display for IntegerExpression<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
IntegerExpression::Variable(ref variable) => write!(f, "{}", variable),
IntegerExpression::Number(ref number) => write!(f, "{}", number),
IntegerExpression::Add(ref lhs, ref rhs) => write!(f, "{} + {}", lhs, rhs),
IntegerExpression::Sub(ref lhs, ref rhs) => write!(f, "{} - {}", lhs, rhs),
IntegerExpression::Mul(ref lhs, ref rhs) => write!(f, "{} * {}", lhs, rhs),
IntegerExpression::Div(ref lhs, ref rhs) => write!(f, "{} / {}", lhs, rhs),
IntegerExpression::Pow(ref lhs, ref rhs) => write!(f, "{} ** {}", lhs, rhs),
IntegerExpression::IfElse(ref a, ref b, ref c) => {
write!(f, "if {} then {} else {} fi", a, b, c)
}
FieldExpression::Array(ref array) => {
IntegerExpression::Array(ref array) => {
write!(f, "[")?;
for (i, e) in array.iter().enumerate() {
write!(f, "{}", e)?;
@ -65,24 +68,16 @@ impl<'ast> fmt::Display for FieldExpression {
}
}
impl fmt::Display for BooleanSpread {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "...{}", self.0)
}
}
impl fmt::Display for BooleanSpreadOrExpression {
impl<F: Field + PrimeField> fmt::Display for BooleanSpreadOrExpression<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
BooleanSpreadOrExpression::Spread(ref spread) => write!(f, "{}", spread),
BooleanSpreadOrExpression::BooleanExpression(ref expression) => {
write!(f, "{}", expression)
}
BooleanSpreadOrExpression::Spread(ref spread) => write!(f, "...{}", spread),
BooleanSpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression),
}
}
}
impl<'ast> fmt::Display for BooleanExpression {
impl<'ast, F: Field + PrimeField> fmt::Display for BooleanExpression<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
BooleanExpression::Variable(ref variable) => write!(f, "{}", variable),
@ -114,10 +109,10 @@ impl<'ast> fmt::Display for BooleanExpression {
}
}
impl<'ast> fmt::Display for FieldRangeOrExpression {
impl<'ast, F: Field + PrimeField> fmt::Display for IntegerRangeOrExpression<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
FieldRangeOrExpression::Range(ref from, ref to) => write!(
IntegerRangeOrExpression::Range(ref from, ref to) => write!(
f,
"{}..{}",
from.as_ref()
@ -125,16 +120,19 @@ impl<'ast> fmt::Display for FieldRangeOrExpression {
.unwrap_or("".to_string()),
to.as_ref().map(|e| e.to_string()).unwrap_or("".to_string())
),
FieldRangeOrExpression::FieldExpression(ref e) => write!(f, "{}", e),
IntegerRangeOrExpression::Expression(ref e) => write!(f, "{}", e),
}
}
}
impl<'ast> fmt::Display for Expression {
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::Boolean(ref boolean_expression) => write!(f, "{}", boolean_expression),
Expression::FieldElement(ref field_expression) => write!(f, "{}", field_expression),
Expression::Variable(ref variable) => write!(f, "{}", variable),
Expression::Struct(ref var, ref members) => {
write!(f, "{} {{", var)?;
@ -164,7 +162,7 @@ impl<'ast> fmt::Display for Expression {
}
}
impl fmt::Display for Assignee {
impl<F: Field + PrimeField> fmt::Display for Assignee<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Assignee::Variable(ref variable) => write!(f, "{}", variable),
@ -176,7 +174,7 @@ impl fmt::Display for Assignee {
}
}
impl fmt::Display for Statement {
impl<F: Field + PrimeField> fmt::Display for Statement<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Statement::Definition(ref variable, ref statement) => {
@ -199,7 +197,7 @@ impl fmt::Display for Statement {
}
}
impl fmt::Debug for Statement {
impl<F: Field + PrimeField> fmt::Debug for Statement<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Statement::Definition(ref variable, ref statement) => {
@ -222,24 +220,25 @@ impl fmt::Debug for Statement {
}
}
impl fmt::Display for Type {
impl<F: Field + PrimeField> fmt::Display for Type<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Type::FieldElement => unimplemented!("field type unimpl"),
Type::U32 => write!(f, "field"),
Type::Boolean => write!(f, "bool"),
Type::FieldElement => write!(f, "field"),
Type::Struct(ref variable) => write!(f, "{}", variable),
Type::Array(ref array, ref count) => write!(f, "[{}; {}]", array, count),
}
}
}
impl fmt::Display for StructField {
impl<F: Field + PrimeField> fmt::Display for StructField<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} : {}", self.ty, self.variable)
}
}
impl fmt::Debug for Struct {
impl<F: Field + PrimeField> fmt::Debug for Struct<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "struct {} {{ \n", self.variable)?;
for field in self.fields.iter() {
@ -249,7 +248,7 @@ impl fmt::Debug for Struct {
}
}
impl fmt::Display for Parameter {
impl<F: Field + PrimeField> fmt::Display for Parameter<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// let visibility = if self.private { "private " } else { "" };
write!(
@ -262,7 +261,7 @@ impl fmt::Display for Parameter {
}
}
impl fmt::Debug for Parameter {
impl<F: Field + PrimeField> fmt::Debug for Parameter<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Parameter(variable: {:?})", self.ty)
}
@ -274,7 +273,7 @@ impl fmt::Debug for FunctionName {
}
}
impl fmt::Display for Function {
impl<F: Field + PrimeField> fmt::Display for Function<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
@ -293,7 +292,7 @@ impl fmt::Display for Function {
}
}
impl fmt::Debug for Function {
impl<F: Field + PrimeField> fmt::Debug for Function<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,

View File

@ -1,78 +1,170 @@
//! Logic to convert from an abstract syntax tree (ast) representation to a typed zokrates_program.
//! Logic to convert from an abstract syntax tree (ast) representation to a typed aleo program.
//!
//! @file zokrates_program.rs
//! @file types_from.rs
//! @author Collin Chin <collin@aleo.org>
//! @date 2020
use crate::aleo_program::{types, Import, PathString};
use crate::ast;
use snarkos_models::curves::{Field, PrimeField};
use std::collections::HashMap;
use std::marker::PhantomData;
use std::path::Path;
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");
types::FieldExpression::Number(number)
/// pest ast -> types::Variable
impl<'ast, F: Field + PrimeField> From<ast::Variable<'ast>> for types::Variable<F> {
fn from(variable: ast::Variable<'ast>) -> Self {
types::Variable {
name: variable.value,
_field: PhantomData::<F>,
}
}
}
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");
types::BooleanExpression::Value(boolean)
/// pest ast - types::Integer
impl<'ast, F: Field + PrimeField> From<ast::Variable<'ast>> for types::IntegerExpression<F> {
fn from(variable: ast::Variable<'ast>) -> Self {
types::IntegerExpression::Variable(types::Variable::from(variable))
}
}
impl<'ast> From<ast::Value<'ast>> for types::Expression {
fn from(value: ast::Value<'ast>) -> Self {
match value {
ast::Value::Boolean(value) => {
types::Expression::Boolean(types::BooleanExpression::from(value))
impl<'ast, F: Field + PrimeField> From<ast::U32<'ast>> for types::IntegerExpression<F> {
fn from(field: ast::U32<'ast>) -> Self {
types::IntegerExpression::Number(types::Integer::U32(
field
.number
.value
.parse::<u32>()
.expect("unable to unwrap u32"),
))
}
}
impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>> for types::IntegerExpression<F> {
fn from(expression: ast::Expression<'ast>) -> Self {
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"),
}
}
}
impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>>
for types::IntegerSpreadOrExpression<F>
{
fn from(expression: ast::Expression<'ast>) -> Self {
match types::Expression::from(expression) {
types::Expression::Integer(expression) => {
types::IntegerSpreadOrExpression::Expression(expression)
}
ast::Value::Field(value) => {
types::Expression::FieldElement(types::FieldExpression::from(value))
_ => unimplemented!("cannot create field expression from boolean type"),
}
}
}
impl<'ast, F: Field + PrimeField> From<ast::SpreadOrExpression<'ast>>
for types::IntegerSpreadOrExpression<F>
{
fn from(s_or_e: ast::SpreadOrExpression<'ast>) -> Self {
match s_or_e {
ast::SpreadOrExpression::Spread(spread) => {
types::IntegerSpreadOrExpression::from(spread.expression)
}
ast::SpreadOrExpression::Expression(expression) => {
types::IntegerSpreadOrExpression::from(expression)
}
}
}
}
impl<'ast> From<ast::Variable<'ast>> for types::Variable {
impl<'ast, F: Field + PrimeField> From<ast::RangeOrExpression<'ast>>
for types::IntegerRangeOrExpression<F>
{
fn from(range_or_expression: ast::RangeOrExpression<'ast>) -> Self {
match range_or_expression {
ast::RangeOrExpression::Range(range) => {
let from = range
.from
.map(|from| match types::Expression::from(from.0) {
types::Expression::Integer(field) => field,
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,
expression => {
unimplemented!("Range bounds should be numbers, found {}", expression)
}
});
types::IntegerRangeOrExpression::Range(from, to)
}
ast::RangeOrExpression::Expression(expression) => {
match types::Expression::from(expression) {
types::Expression::Integer(field_expression) => {
types::IntegerRangeOrExpression::Expression(field_expression)
}
// types::Expression::ArrayAccess(expression, field), // recursive array access
expression => unimplemented!("expression must be field, found {}", expression),
}
}
}
}
}
/// pest ast -> types::Boolean
impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>>
for types::BooleanSpreadOrExpression<F>
{
fn from(expression: ast::Expression<'ast>) -> Self {
match types::Expression::from(expression) {
types::Expression::Boolean(expression) => {
types::BooleanSpreadOrExpression::Expression(expression)
}
_ => unimplemented!("cannot create boolean expression from field type"),
}
}
}
impl<'ast, F: Field + PrimeField> From<ast::SpreadOrExpression<'ast>>
for types::BooleanSpreadOrExpression<F>
{
fn from(s_or_e: ast::SpreadOrExpression<'ast>) -> Self {
match s_or_e {
ast::SpreadOrExpression::Spread(spread) => {
types::BooleanSpreadOrExpression::from(spread.expression)
}
ast::SpreadOrExpression::Expression(expression) => {
types::BooleanSpreadOrExpression::from(expression)
}
}
}
}
impl<'ast, F: Field + PrimeField> From<ast::Variable<'ast>> for types::BooleanExpression<F> {
fn from(variable: ast::Variable<'ast>) -> Self {
types::Variable(variable.value)
types::BooleanExpression::Variable(types::Variable::from(variable))
}
}
impl<'ast> From<ast::Variable<'ast>> for types::FieldExpression {
fn from(variable: ast::Variable<'ast>) -> Self {
types::FieldExpression::Variable(types::Variable(variable.value))
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> From<ast::Variable<'ast>> for types::BooleanExpression {
fn from(variable: ast::Variable<'ast>) -> Self {
types::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> From<ast::NotExpression<'ast>> for types::Expression {
fn from(expression: ast::NotExpression<'ast>) -> Self {
types::Expression::Boolean(types::BooleanExpression::Not(Box::new(
types::BooleanExpression::from(*expression.expression),
)))
}
}
impl<'ast> From<ast::Expression<'ast>> for types::BooleanExpression {
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,
@ -82,17 +174,37 @@ impl<'ast> From<ast::Expression<'ast>> for types::BooleanExpression {
}
}
impl<'ast> From<ast::Expression<'ast>> for types::FieldExpression {
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"),
/// pest ast -> types::Expression
impl<'ast, F: Field + PrimeField> From<ast::Value<'ast>> for types::Expression<F> {
fn from(value: ast::Value<'ast>) -> Self {
match value {
ast::Value::U32(value) => {
types::Expression::Integer(types::IntegerExpression::from(value))
}
ast::Value::Field(_field) => unimplemented!("cannot declare field values yet"),
ast::Value::Boolean(value) => {
types::Expression::Boolean(types::BooleanExpression::from(value))
}
}
}
}
impl<'ast> types::BooleanExpression {
impl<'ast, F: Field + PrimeField> From<ast::Variable<'ast>> for types::Expression<F> {
fn from(variable: ast::Variable<'ast>) -> Self {
types::Expression::Variable(types::Variable::from(variable))
}
}
impl<'ast, F: Field + PrimeField> From<ast::NotExpression<'ast>> for types::Expression<F> {
fn from(expression: ast::NotExpression<'ast>) -> Self {
types::Expression::Boolean(types::BooleanExpression::Not(Box::new(
types::BooleanExpression::from(*expression.expression),
)))
}
}
impl<'ast, F: Field + PrimeField> types::BooleanExpression<F> {
/// 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);
@ -117,18 +229,18 @@ impl<'ast> types::BooleanExpression {
)
} //TODO: check case for two variables?
// Field equality
(types::Expression::FieldElement(lhs), types::Expression::FieldElement(rhs)) => {
(types::Expression::Integer(lhs), types::Expression::Integer(rhs)) => {
types::BooleanExpression::FieldEq(Box::new(lhs), Box::new(rhs))
}
(types::Expression::FieldElement(lhs), types::Expression::Variable(rhs)) => {
(types::Expression::Integer(lhs), types::Expression::Variable(rhs)) => {
types::BooleanExpression::FieldEq(
Box::new(lhs),
Box::new(types::FieldExpression::Variable(rhs)),
Box::new(types::IntegerExpression::Variable(rhs)),
)
}
(types::Expression::Variable(lhs), types::Expression::FieldElement(rhs)) => {
(types::Expression::Variable(lhs), types::Expression::Integer(rhs)) => {
types::BooleanExpression::FieldEq(
Box::new(types::FieldExpression::Variable(lhs)),
Box::new(types::IntegerExpression::Variable(lhs)),
Box::new(rhs),
)
}
@ -142,7 +254,7 @@ impl<'ast> types::BooleanExpression {
}
}
impl<'ast> From<ast::BinaryExpression<'ast>> for types::Expression {
impl<'ast, F: Field + PrimeField> From<ast::BinaryExpression<'ast>> for types::Expression<F> {
fn from(expression: ast::BinaryExpression<'ast>) -> Self {
match expression.operation {
// Boolean operations
@ -161,57 +273,47 @@ impl<'ast> From<ast::BinaryExpression<'ast>> for types::Expression {
types::Expression::Boolean(types::BooleanExpression::from_neq(expression))
}
ast::BinaryOperator::Geq => types::Expression::Boolean(types::BooleanExpression::Geq(
Box::new(types::FieldExpression::from(*expression.left)),
Box::new(types::FieldExpression::from(*expression.right)),
Box::new(types::IntegerExpression::from(*expression.left)),
Box::new(types::IntegerExpression::from(*expression.right)),
)),
ast::BinaryOperator::Gt => types::Expression::Boolean(types::BooleanExpression::Gt(
Box::new(types::FieldExpression::from(*expression.left)),
Box::new(types::FieldExpression::from(*expression.right)),
Box::new(types::IntegerExpression::from(*expression.left)),
Box::new(types::IntegerExpression::from(*expression.right)),
)),
ast::BinaryOperator::Leq => types::Expression::Boolean(types::BooleanExpression::Leq(
Box::new(types::FieldExpression::from(*expression.left)),
Box::new(types::FieldExpression::from(*expression.right)),
Box::new(types::IntegerExpression::from(*expression.left)),
Box::new(types::IntegerExpression::from(*expression.right)),
)),
ast::BinaryOperator::Lt => types::Expression::Boolean(types::BooleanExpression::Lt(
Box::new(types::FieldExpression::from(*expression.left)),
Box::new(types::FieldExpression::from(*expression.right)),
Box::new(types::IntegerExpression::from(*expression.left)),
Box::new(types::IntegerExpression::from(*expression.right)),
)),
// Field operations
ast::BinaryOperator::Add => {
types::Expression::FieldElement(types::FieldExpression::Add(
Box::new(types::FieldExpression::from(*expression.left)),
Box::new(types::FieldExpression::from(*expression.right)),
))
}
ast::BinaryOperator::Sub => {
types::Expression::FieldElement(types::FieldExpression::Sub(
Box::new(types::FieldExpression::from(*expression.left)),
Box::new(types::FieldExpression::from(*expression.right)),
))
}
ast::BinaryOperator::Mul => {
types::Expression::FieldElement(types::FieldExpression::Mul(
Box::new(types::FieldExpression::from(*expression.left)),
Box::new(types::FieldExpression::from(*expression.right)),
))
}
ast::BinaryOperator::Div => {
types::Expression::FieldElement(types::FieldExpression::Div(
Box::new(types::FieldExpression::from(*expression.left)),
Box::new(types::FieldExpression::from(*expression.right)),
))
}
ast::BinaryOperator::Pow => {
types::Expression::FieldElement(types::FieldExpression::Pow(
Box::new(types::FieldExpression::from(*expression.left)),
Box::new(types::FieldExpression::from(*expression.right)),
))
}
ast::BinaryOperator::Add => 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(
Box::new(types::IntegerExpression::from(*expression.left)),
Box::new(types::IntegerExpression::from(*expression.right)),
)),
ast::BinaryOperator::Mul => 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(
Box::new(types::IntegerExpression::from(*expression.left)),
Box::new(types::IntegerExpression::from(*expression.right)),
)),
ast::BinaryOperator::Pow => types::Expression::Integer(types::IntegerExpression::Pow(
Box::new(types::IntegerExpression::from(*expression.left)),
Box::new(types::IntegerExpression::from(*expression.right)),
)),
}
}
}
impl<'ast> From<ast::TernaryExpression<'ast>> for types::Expression {
impl<'ast, F: Field + PrimeField> From<ast::TernaryExpression<'ast>> for types::Expression<F> {
fn from(expression: ast::TernaryExpression<'ast>) -> Self {
// Evaluate expressions to find out result type
let first = types::BooleanExpression::from(*expression.first);
@ -242,24 +344,24 @@ impl<'ast> From<ast::TernaryExpression<'ast>> for types::Expression {
))
}
// Field Result
(types::Expression::FieldElement(second), types::Expression::FieldElement(third)) => {
types::Expression::FieldElement(types::FieldExpression::IfElse(
(types::Expression::Integer(second), types::Expression::Integer(third)) => {
types::Expression::Integer(types::IntegerExpression::IfElse(
Box::new(first),
Box::new(second),
Box::new(third),
))
}
(types::Expression::FieldElement(second), types::Expression::Variable(third)) => {
types::Expression::FieldElement(types::FieldExpression::IfElse(
(types::Expression::Integer(second), types::Expression::Variable(third)) => {
types::Expression::Integer(types::IntegerExpression::IfElse(
Box::new(first),
Box::new(second),
Box::new(types::FieldExpression::Variable(third)),
Box::new(types::IntegerExpression::Variable(third)),
))
}
(types::Expression::Variable(second), types::Expression::FieldElement(third)) => {
types::Expression::FieldElement(types::FieldExpression::IfElse(
(types::Expression::Variable(second), types::Expression::Integer(third)) => {
types::Expression::Integer(types::IntegerExpression::IfElse(
Box::new(first),
Box::new(types::FieldExpression::Variable(second)),
Box::new(types::IntegerExpression::Variable(second)),
Box::new(third),
))
}
@ -274,41 +376,7 @@ impl<'ast> From<ast::TernaryExpression<'ast>> for types::Expression {
}
}
impl<'ast> From<ast::RangeOrExpression<'ast>> for types::FieldRangeOrExpression {
fn from(range_or_expression: ast::RangeOrExpression<'ast>) -> Self {
match range_or_expression {
ast::RangeOrExpression::Range(range) => {
let from = range
.from
.map(|from| match types::Expression::from(from.0) {
types::Expression::FieldElement(field) => field,
expression => {
unimplemented!("Range bounds should be numbers, found {}", expression)
}
});
let to = range.to.map(|to| match types::Expression::from(to.0) {
types::Expression::FieldElement(field) => field,
expression => {
unimplemented!("Range bounds should be numbers, found {}", expression)
}
});
types::FieldRangeOrExpression::Range(from, to)
}
ast::RangeOrExpression::Expression(expression) => {
match types::Expression::from(expression) {
types::Expression::FieldElement(field_expression) => {
types::FieldRangeOrExpression::FieldExpression(field_expression)
}
// types::Expression::ArrayAccess(expression, field), // recursive array access
expression => unimplemented!("expression must be field, found {}", expression),
}
}
}
}
}
impl<'ast> From<ast::PostfixExpression<'ast>> for types::Expression {
impl<'ast, F: Field + PrimeField> From<ast::PostfixExpression<'ast>> for types::Expression<F> {
fn from(expression: ast::PostfixExpression<'ast>) -> Self {
let variable = types::Expression::Variable(types::Variable::from(expression.variable));
@ -339,13 +407,13 @@ impl<'ast> From<ast::PostfixExpression<'ast>> for types::Expression {
),
ast::Access::Array(array) => types::Expression::ArrayAccess(
Box::new(acc),
types::FieldRangeOrExpression::from(array.expression),
types::IntegerRangeOrExpression::from(array.expression),
),
})
}
}
impl<'ast> From<ast::Expression<'ast>> for types::Expression {
impl<'ast, F: Field + PrimeField> From<ast::Expression<'ast>> for types::Expression<F> {
fn from(expression: ast::Expression<'ast>) -> Self {
match expression {
ast::Expression::Value(value) => types::Expression::from(value),
@ -359,147 +427,53 @@ impl<'ast> From<ast::Expression<'ast>> for types::Expression {
ast::Expression::ArrayInitializer(_expression) => {
unimplemented!("unknown type for array initializer expression")
}
ast::Expression::StructInline(_expression) => {
unimplemented!("unknown type for inline struct expression")
}
ast::Expression::Postfix(expression) => types::Expression::from(expression),
_ => unimplemented!(),
}
}
}
impl<'ast> From<ast::Variable<'ast>> for types::Assignee {
fn from(variable: ast::Variable<'ast>) -> Self {
types::Assignee::Variable(types::Variable::from(variable))
}
}
impl<'ast> From<ast::Assignee<'ast>> for types::Assignee {
fn from(assignee: ast::Assignee<'ast>) -> Self {
let variable = types::Assignee::from(assignee.variable);
// we start with the id, and we fold the array of accesses by wrapping the current value
assignee
.accesses
.into_iter()
.fold(variable, |acc, access| match access {
ast::AssigneeAccess::Array(array) => types::Assignee::Array(
Box::new(acc),
types::FieldRangeOrExpression::from(array.expression),
),
ast::AssigneeAccess::Member(struct_member) => types::Assignee::StructMember(
Box::new(acc),
types::Variable::from(struct_member.variable),
),
})
}
}
impl<'ast> From<ast::AssignStatement<'ast>> for types::Statement {
fn from(statement: ast::AssignStatement<'ast>) -> Self {
types::Statement::Definition(
types::Assignee::from(statement.assignee),
types::Expression::from(statement.expression),
)
}
}
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),
types::Expression::Variable(variable) => {
types::BooleanSpread(types::BooleanExpression::Variable(variable))
}
_ => unimplemented!("cannot create boolean spread from field type"),
}
}
}
impl<'ast> From<ast::Expression<'ast>> for types::BooleanSpreadOrExpression {
fn from(expression: ast::Expression<'ast>) -> Self {
match types::Expression::from(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::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) => {
match types::Expression::from(expression) {
types::Expression::Boolean(expression) => {
types::BooleanSpreadOrExpression::BooleanExpression(expression)
}
_ => unimplemented!("cannot create boolean expression from field type"),
}
}
}
}
}
impl<'ast> From<ast::Spread<'ast>> for types::FieldSpread {
fn from(spread: ast::Spread<'ast>) -> Self {
match types::Expression::from(spread.expression) {
types::Expression::FieldElement(expression) => types::FieldSpread(expression),
types::Expression::Variable(variable) => {
types::FieldSpread(types::FieldExpression::Variable(variable))
}
expression => unimplemented!(
"cannot create field spread from boolean type {}",
expression
),
}
}
}
impl<'ast> From<ast::Expression<'ast>> for types::FieldSpreadOrExpression {
fn from(expression: ast::Expression<'ast>) -> Self {
match types::Expression::from(expression) {
types::Expression::FieldElement(expression) => {
types::FieldSpreadOrExpression::FieldExpression(expression)
}
_ => unimplemented!("cannot create field expression from boolean 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) => {
types::FieldSpreadOrExpression::from(expression)
}
}
}
}
impl<'ast> From<ast::InlineStructMember<'ast>> for types::StructMember {
fn from(member: ast::InlineStructMember<'ast>) -> Self {
types::StructMember {
variable: types::Variable::from(member.variable),
expression: types::Expression::from(member.expression),
}
}
}
impl<'ast> types::Expression {
/// pest ast -> typed types::Expression
/// For defined types (ex: u32[4]) we manually construct the expression instead of implementing the From trait.
/// This saves us from having to resolve things at a later point in time.
impl<'ast, F: Field + PrimeField> types::Expression<F> {
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::U32(_ty) => {
let elements: Vec<Box<types::IntegerSpreadOrExpression<F>>> = match expression {
ast::Expression::ArrayInline(array) => array
.expressions
.into_iter()
.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 expression =
Box::new(types::IntegerSpreadOrExpression::from(*array.expression));
vec![expression; count]
}
_ => unimplemented!("expected array after array type"),
};
types::Expression::Integer(types::IntegerExpression::Array(elements))
}
ast::BasicType::Field(_ty) => unimplemented!("from array field basic types unimpl"),
ast::BasicType::Boolean(_ty) => {
let elements: Vec<Box<types::BooleanSpreadOrExpression>> = match expression {
let elements: Vec<Box<types::BooleanSpreadOrExpression<F>>> = match expression {
ast::Expression::ArrayInline(array) => array
.expressions
.into_iter()
@ -507,9 +481,11 @@ impl<'ast> types::Expression {
.collect(),
ast::Expression::ArrayInitializer(array) => {
let count = match array.count {
ast::Value::Field(f) => {
f.value.parse::<usize>().expect("Unable to read array size")
}
ast::Value::U32(f) => f
.number
.value
.parse::<usize>()
.expect("Unable to read array size"),
_ => unimplemented!("Array size should be an integer"),
};
let expression =
@ -521,29 +497,6 @@ impl<'ast> types::Expression {
};
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(array) => {
let count = match array.count {
ast::Value::Field(f) => {
f.value.parse::<usize>().expect("Unable to read array size")
}
_ => unimplemented!("Array size should be an integer"),
};
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))
}
}
}
@ -559,7 +512,7 @@ impl<'ast> types::Expression {
.members
.into_iter()
.map(|member| types::StructMember::from(member))
.collect::<Vec<types::StructMember>>();
.collect::<Vec<types::StructMember<F>>>();
types::Expression::Struct(variable, members)
}
@ -576,7 +529,47 @@ impl<'ast> types::Expression {
}
}
impl<'ast> From<ast::DefinitionStatement<'ast>> for types::Statement {
/// pest ast -> types::Assignee
impl<'ast, F: Field + PrimeField> From<ast::Variable<'ast>> for types::Assignee<F> {
fn from(variable: ast::Variable<'ast>) -> Self {
types::Assignee::Variable(types::Variable::from(variable))
}
}
impl<'ast, F: Field + PrimeField> From<ast::Assignee<'ast>> for types::Assignee<F> {
fn from(assignee: ast::Assignee<'ast>) -> Self {
let variable = types::Assignee::from(assignee.variable);
// we start with the id, and we fold the array of accesses by wrapping the current value
assignee
.accesses
.into_iter()
.fold(variable, |acc, access| match access {
ast::AssigneeAccess::Array(array) => types::Assignee::Array(
Box::new(acc),
types::IntegerRangeOrExpression::from(array.expression),
),
ast::AssigneeAccess::Member(struct_member) => types::Assignee::StructMember(
Box::new(acc),
types::Variable::from(struct_member.variable),
),
})
}
}
/// pest ast -> types::Statement
impl<'ast, F: Field + PrimeField> From<ast::AssignStatement<'ast>> for types::Statement<F> {
fn from(statement: ast::AssignStatement<'ast>) -> Self {
types::Statement::Definition(
types::Assignee::from(statement.assignee),
types::Expression::from(statement.expression),
)
}
}
impl<'ast, F: Field + PrimeField> From<ast::DefinitionStatement<'ast>> for types::Statement<F> {
fn from(statement: ast::DefinitionStatement<'ast>) -> Self {
types::Statement::Definition(
types::Assignee::from(statement.variable),
@ -585,7 +578,7 @@ impl<'ast> From<ast::DefinitionStatement<'ast>> for types::Statement {
}
}
impl<'ast> From<ast::ReturnStatement<'ast>> for types::Statement {
impl<'ast, F: Field + PrimeField> From<ast::ReturnStatement<'ast>> for types::Statement<F> {
fn from(statement: ast::ReturnStatement<'ast>) -> Self {
types::Statement::Return(
statement
@ -597,12 +590,12 @@ impl<'ast> From<ast::ReturnStatement<'ast>> for types::Statement {
}
}
impl<'ast> From<ast::ForStatement<'ast>> for types::Statement {
impl<'ast, F: Field + PrimeField> From<ast::ForStatement<'ast>> for types::Statement<F> {
fn from(statement: ast::ForStatement<'ast>) -> Self {
types::Statement::For(
types::Variable::from(statement.index),
types::FieldExpression::from(statement.start),
types::FieldExpression::from(statement.stop),
types::IntegerExpression::from(statement.start),
types::IntegerExpression::from(statement.stop),
statement
.statements
.into_iter()
@ -612,7 +605,7 @@ impl<'ast> From<ast::ForStatement<'ast>> for types::Statement {
}
}
impl<'ast> From<ast::Statement<'ast>> for types::Statement {
impl<'ast, F: Field + PrimeField> From<ast::Statement<'ast>> for types::Statement<F> {
fn from(statement: ast::Statement<'ast>) -> Self {
match statement {
ast::Statement::Assign(statement) => types::Statement::from(statement),
@ -623,33 +616,40 @@ impl<'ast> From<ast::Statement<'ast>> for types::Statement {
}
}
impl<'ast> From<ast::BasicType<'ast>> for types::Type {
/// pest ast -> Explicit types::Type for defining struct members and function params
impl<'ast, F: Field + PrimeField> From<ast::BasicType<'ast>> for types::Type<F> {
fn from(basic_type: ast::BasicType<'ast>) -> Self {
match basic_type {
ast::BasicType::Field(_ty) => types::Type::FieldElement,
ast::BasicType::U32(_ty) => types::Type::U32,
ast::BasicType::Field(_ty) => types::Type::U32,
ast::BasicType::Boolean(_ty) => types::Type::Boolean,
}
}
}
impl<'ast> From<ast::ArrayType<'ast>> for types::Type {
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.value.parse::<usize>().expect("Unable to read array size"),
ast::Value::Field(f) => f
.number
.value
.parse::<usize>()
.expect("Unable to read array size"),
_ => unimplemented!("Array size should be an integer"),
};
types::Type::Array(element_type, count)
}
}
impl<'ast> From<ast::StructType<'ast>> for types::Type {
impl<'ast, F: Field + PrimeField> From<ast::StructType<'ast>> for types::Type<F> {
fn from(struct_type: ast::StructType<'ast>) -> Self {
types::Type::Struct(types::Variable::from(struct_type.variable))
}
}
impl<'ast> From<ast::Type<'ast>> for types::Type {
impl<'ast, F: Field + PrimeField> From<ast::Type<'ast>> for types::Type<F> {
fn from(ty: ast::Type<'ast>) -> Self {
match ty {
ast::Type::Basic(ty) => types::Type::from(ty),
@ -659,7 +659,18 @@ impl<'ast> From<ast::Type<'ast>> for types::Type {
}
}
impl<'ast> From<ast::StructField<'ast>> for types::StructField {
/// pest ast -> types::Struct
impl<'ast, F: Field + PrimeField> From<ast::InlineStructMember<'ast>> for types::StructMember<F> {
fn from(member: ast::InlineStructMember<'ast>) -> Self {
types::StructMember {
variable: types::Variable::from(member.variable),
expression: types::Expression::from(member.expression),
}
}
}
impl<'ast, F: Field + PrimeField> From<ast::StructField<'ast>> for types::StructField<F> {
fn from(struct_field: ast::StructField<'ast>) -> Self {
types::StructField {
variable: types::Variable::from(struct_field.variable),
@ -668,7 +679,7 @@ impl<'ast> From<ast::StructField<'ast>> for types::StructField {
}
}
impl<'ast> From<ast::Struct<'ast>> for types::Struct {
impl<'ast, F: Field + PrimeField> From<ast::Struct<'ast>> for types::Struct<F> {
fn from(struct_definition: ast::Struct<'ast>) -> Self {
let variable = types::Variable::from(struct_definition.variable);
let fields = struct_definition
@ -681,6 +692,8 @@ impl<'ast> From<ast::Struct<'ast>> for types::Struct {
}
}
/// pest ast -> function types::Parameters
impl From<ast::Visibility> for types::Visibility {
fn from(visibility: ast::Visibility) -> Self {
match visibility {
@ -690,7 +703,7 @@ impl From<ast::Visibility> for types::Visibility {
}
}
impl<'ast> From<ast::Parameter<'ast>> for types::Parameter {
impl<'ast, F: Field + PrimeField> From<ast::Parameter<'ast>> for types::Parameter<F> {
fn from(parameter: ast::Parameter<'ast>) -> Self {
let ty = types::Type::from(parameter.ty);
let variable = types::Variable::from(parameter.variable);
@ -712,13 +725,15 @@ impl<'ast> From<ast::Parameter<'ast>> for types::Parameter {
}
}
/// pest ast -> types::Function
impl<'ast> From<ast::FunctionName<'ast>> for types::FunctionName {
fn from(name: ast::FunctionName<'ast>) -> Self {
types::FunctionName(name.value)
}
}
impl<'ast> From<ast::Function<'ast>> for types::Function {
impl<'ast, F: Field + PrimeField> From<ast::Function<'ast>> for types::Function<F> {
fn from(function_definition: ast::Function<'ast>) -> Self {
let function_name = types::FunctionName::from(function_definition.function_name);
let parameters = function_definition
@ -746,6 +761,8 @@ impl<'ast> From<ast::Function<'ast>> for types::Function {
}
}
/// pest ast -> Import
impl<'ast> From<ast::Variable<'ast>> for PathString<'ast> {
fn from(import: ast::Variable<'ast>) -> Self {
import.span.as_str()
@ -766,7 +783,9 @@ impl<'ast> From<ast::Import<'ast>> for Import<'ast> {
}
}
impl<'ast> From<ast::File<'ast>> for types::Program<'ast> {
/// pest ast -> types::Program
impl<'ast, F: Field + PrimeField> From<ast::File<'ast>> for types::Program<'ast, F> {
fn from(file: ast::File<'ast>) -> Self {
// Compiled ast -> aleo program representation
let imports = file
@ -792,7 +811,10 @@ impl<'ast> From<ast::File<'ast>> for types::Program<'ast> {
});
types::Program {
name: types::Variable("".into()),
name: types::Variable {
name: "".into(),
_field: PhantomData::<F>,
},
imports,
structs,
functions,

View File

@ -30,203 +30,6 @@ lazy_static! {
static ref PRECEDENCE_CLIMBER: PrecClimber<Rule> = precedence_climber();
}
fn precedence_climber() -> PrecClimber<Rule> {
PrecClimber::new(vec![
Operator::new(Rule::operation_or, Assoc::Left),
Operator::new(Rule::operation_and, Assoc::Left),
Operator::new(Rule::operation_eq, Assoc::Left)
| Operator::new(Rule::operation_neq, Assoc::Left),
Operator::new(Rule::operation_geq, Assoc::Left)
| Operator::new(Rule::operation_gt, Assoc::Left)
| Operator::new(Rule::operation_leq, Assoc::Left)
| Operator::new(Rule::operation_lt, Assoc::Left),
Operator::new(Rule::operation_add, Assoc::Left)
| Operator::new(Rule::operation_sub, Assoc::Left),
Operator::new(Rule::operation_mul, Assoc::Left)
| Operator::new(Rule::operation_div, Assoc::Left),
Operator::new(Rule::operation_pow, Assoc::Left),
])
}
fn parse_term(pair: Pair<Rule>) -> Box<Expression> {
Box::new(match pair.as_rule() {
Rule::expression_term => {
let clone = pair.clone();
let next = clone.into_inner().next().unwrap();
match next.as_rule() {
Rule::expression => Expression::from_pest(&mut pair.into_inner()).unwrap(), // Parenthesis case
Rule::expression_inline_struct => {
Expression::StructInline(
StructInlineExpression::from_pest(&mut pair.into_inner()).unwrap(),
)
},
Rule::expression_array_inline => {
Expression::ArrayInline(
ArrayInlineExpression::from_pest(&mut pair.into_inner()).unwrap()
)
},
Rule::expression_array_initializer => {
Expression::ArrayInitializer(
ArrayInitializerExpression::from_pest(&mut pair.into_inner()).unwrap()
)
},
Rule::expression_conditional => {
Expression::Ternary(
TernaryExpression::from_pest(&mut pair.into_inner()).unwrap(),
)
},
Rule::expression_not => {
let span = next.as_span();
let mut inner = next.into_inner();
let operation = match inner.next().unwrap().as_rule() {
Rule::operation_pre_not => Not::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
rule => unreachable!("`expression_not` should yield `operation_pre_not`, found {:#?}", rule)
};
let expression = parse_term(inner.next().unwrap());
Expression::Not(NotExpression { operation, expression, span })
},
Rule::expression_increment => {
println!("expression increment");
let span = next.as_span();
let mut inner = next.into_inner();
let expression = parse_term(inner.next().unwrap());
let operation = match inner.next().unwrap().as_rule() {
Rule::operation_post_increment => Increment::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
rule => unreachable!("`expression_increment` should yield `operation_post_increment`, found {:#?}", rule)
};
Expression::Increment(IncrementExpression { operation, expression, span })
},
Rule::expression_decrement => {
println!("expression decrement");
let span = next.as_span();
let mut inner = next.into_inner();
let expression = parse_term(inner.next().unwrap());
let operation = match inner.next().unwrap().as_rule() {
Rule::operation_post_decrement => Decrement::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
rule => unreachable!("`expression_decrement` should yield `operation_post_decrement`, found {:#?}", rule)
};
Expression::Decrement(DecrementExpression { operation, expression, span })
},
Rule::expression_postfix => {
Expression::Postfix(
PostfixExpression::from_pest(&mut pair.into_inner()).unwrap(),
)
}
Rule::expression_primitive => {
let next = next.into_inner().next().unwrap();
match next.as_rule() {
Rule::value => Expression::Value(
Value::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap()
),
Rule::variable => Expression::Variable(
Variable::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
),
rule => unreachable!("`expression_primitive` should contain one of [`value`, `variable`], found {:#?}", rule)
}
},
rule => unreachable!("`term` should contain one of ['value', 'variable', 'expression', 'expression_not', 'expression_increment', 'expression_decrement'], found {:#?}", rule)
}
}
rule => unreachable!(
"`parse_expression_term` should be invoked on `Rule::expression_term`, found {:#?}",
rule
),
})
}
fn binary_expression<'ast>(
lhs: Box<Expression<'ast>>,
pair: Pair<'ast, Rule>,
rhs: Box<Expression<'ast>>,
) -> Box<Expression<'ast>> {
let (start, _) = lhs.span().clone().split();
let (_, end) = rhs.span().clone().split();
let span = start.span(&end);
Box::new(match pair.as_rule() {
Rule::operation_or => Expression::binary(BinaryOperator::Or, lhs, rhs, span),
Rule::operation_and => Expression::binary(BinaryOperator::And, lhs, rhs, span),
Rule::operation_eq => Expression::binary(BinaryOperator::Eq, lhs, rhs, span),
Rule::operation_neq => Expression::binary(BinaryOperator::Neq, lhs, rhs, span),
Rule::operation_geq => Expression::binary(BinaryOperator::Geq, lhs, rhs, span),
Rule::operation_gt => Expression::binary(BinaryOperator::Gt, lhs, rhs, span),
Rule::operation_leq => Expression::binary(BinaryOperator::Leq, lhs, rhs, span),
Rule::operation_lt => Expression::binary(BinaryOperator::Lt, lhs, rhs, span),
Rule::operation_add => Expression::binary(BinaryOperator::Add, lhs, rhs, span),
Rule::operation_sub => Expression::binary(BinaryOperator::Sub, lhs, rhs, span),
Rule::operation_mul => Expression::binary(BinaryOperator::Mul, lhs, rhs, span),
Rule::operation_div => Expression::binary(BinaryOperator::Div, lhs, rhs, span),
Rule::operation_pow => Expression::binary(BinaryOperator::Pow, lhs, rhs, span),
_ => unreachable!(),
})
}
// Types
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_bool))]
pub struct BooleanType<'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(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_struct))]
pub struct StructType<'ast> {
pub variable: Variable<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_basic))]
pub enum BasicType<'ast> {
Field(FieldType<'ast>),
Boolean(BooleanType<'ast>),
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_basic_or_struct))]
pub enum BasicOrStructType<'ast> {
Struct(StructType<'ast>),
Basic(BasicType<'ast>),
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_array))]
pub struct ArrayType<'ast> {
pub ty: BasicType<'ast>,
pub count: Value<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty))]
pub enum Type<'ast> {
Basic(BasicType<'ast>),
Array(ArrayType<'ast>),
Struct(StructType<'ast>),
}
impl<'ast> fmt::Display for Type<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Type::Basic(ref _ty) => write!(f, "basic"),
Type::Array(ref _ty) => write!(f, "array"),
Type::Struct(ref _ty) => write!(f, "struct"),
}
}
}
// Visibility
#[derive(Clone, Debug, FromPest, PartialEq)]
@ -286,7 +89,124 @@ pub enum BinaryOperator {
Pow,
}
// Types
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_u32))]
pub struct U32Type<'ast> {
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_bool))]
pub struct BooleanType<'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(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_struct))]
pub struct StructType<'ast> {
pub variable: Variable<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_basic))]
pub enum BasicType<'ast> {
U32(U32Type<'ast>),
Field(FieldType<'ast>),
Boolean(BooleanType<'ast>),
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_basic_or_struct))]
pub enum BasicOrStructType<'ast> {
Struct(StructType<'ast>),
Basic(BasicType<'ast>),
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty_array))]
pub struct ArrayType<'ast> {
pub ty: BasicType<'ast>,
pub count: Value<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::ty))]
pub enum Type<'ast> {
Basic(BasicType<'ast>),
Array(ArrayType<'ast>),
Struct(StructType<'ast>),
}
impl<'ast> fmt::Display for Type<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Type::Basic(ref _ty) => write!(f, "basic"),
Type::Array(ref _ty) => write!(f, "array"),
Type::Struct(ref _ty) => write!(f, "struct"),
}
}
}
// Values
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_number))]
pub struct Number<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for Number<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
}
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_u32))]
pub struct U32<'ast> {
pub number: Number<'ast>,
pub ty: U32Type<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for U32<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.number)
}
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_field))]
pub struct Field<'ast> {
pub number: Number<'ast>,
pub ty: U32Type<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for Field<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.number)
}
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_boolean))]
@ -303,33 +223,20 @@ impl<'ast> fmt::Display for Boolean<'ast> {
}
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_field))]
pub struct Field<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for Field<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
}
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value))]
pub enum Value<'ast> {
Boolean(Boolean<'ast>),
U32(U32<'ast>),
Field(Field<'ast>),
Boolean(Boolean<'ast>),
}
impl<'ast> Value<'ast> {
pub fn span(&self) -> &Span<'ast> {
match self {
Value::Boolean(value) => &value.span,
Value::U32(value) => &value.span,
Value::Field(value) => &value.span,
Value::Boolean(value) => &value.span,
}
}
}
@ -337,8 +244,9 @@ impl<'ast> Value<'ast> {
impl<'ast> fmt::Display for Value<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Value::Boolean(ref value) => write!(f, "{}", value),
Value::U32(ref value) => write!(f, "{}", value),
Value::Field(ref value) => write!(f, "{}", value),
Value::Boolean(ref value) => write!(f, "{}", value),
}
}
}
@ -720,6 +628,140 @@ impl<'ast> fmt::Display for Expression<'ast> {
}
}
fn precedence_climber() -> PrecClimber<Rule> {
PrecClimber::new(vec![
Operator::new(Rule::operation_or, Assoc::Left),
Operator::new(Rule::operation_and, Assoc::Left),
Operator::new(Rule::operation_eq, Assoc::Left)
| Operator::new(Rule::operation_neq, Assoc::Left),
Operator::new(Rule::operation_geq, Assoc::Left)
| Operator::new(Rule::operation_gt, Assoc::Left)
| Operator::new(Rule::operation_leq, Assoc::Left)
| Operator::new(Rule::operation_lt, Assoc::Left),
Operator::new(Rule::operation_add, Assoc::Left)
| Operator::new(Rule::operation_sub, Assoc::Left),
Operator::new(Rule::operation_mul, Assoc::Left)
| Operator::new(Rule::operation_div, Assoc::Left),
Operator::new(Rule::operation_pow, Assoc::Left),
])
}
fn parse_term(pair: Pair<Rule>) -> Box<Expression> {
Box::new(match pair.as_rule() {
Rule::expression_term => {
let clone = pair.clone();
let next = clone.into_inner().next().unwrap();
match next.as_rule() {
Rule::expression => Expression::from_pest(&mut pair.into_inner()).unwrap(), // Parenthesis case
Rule::expression_inline_struct => {
Expression::StructInline(
StructInlineExpression::from_pest(&mut pair.into_inner()).unwrap(),
)
},
Rule::expression_array_inline => {
Expression::ArrayInline(
ArrayInlineExpression::from_pest(&mut pair.into_inner()).unwrap()
)
},
Rule::expression_array_initializer => {
Expression::ArrayInitializer(
ArrayInitializerExpression::from_pest(&mut pair.into_inner()).unwrap()
)
},
Rule::expression_conditional => {
Expression::Ternary(
TernaryExpression::from_pest(&mut pair.into_inner()).unwrap(),
)
},
Rule::expression_not => {
let span = next.as_span();
let mut inner = next.into_inner();
let operation = match inner.next().unwrap().as_rule() {
Rule::operation_pre_not => Not::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
rule => unreachable!("`expression_not` should yield `operation_pre_not`, found {:#?}", rule)
};
let expression = parse_term(inner.next().unwrap());
Expression::Not(NotExpression { operation, expression, span })
},
Rule::expression_increment => {
println!("expression increment");
let span = next.as_span();
let mut inner = next.into_inner();
let expression = parse_term(inner.next().unwrap());
let operation = match inner.next().unwrap().as_rule() {
Rule::operation_post_increment => Increment::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
rule => unreachable!("`expression_increment` should yield `operation_post_increment`, found {:#?}", rule)
};
Expression::Increment(IncrementExpression { operation, expression, span })
},
Rule::expression_decrement => {
println!("expression decrement");
let span = next.as_span();
let mut inner = next.into_inner();
let expression = parse_term(inner.next().unwrap());
let operation = match inner.next().unwrap().as_rule() {
Rule::operation_post_decrement => Decrement::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
rule => unreachable!("`expression_decrement` should yield `operation_post_decrement`, found {:#?}", rule)
};
Expression::Decrement(DecrementExpression { operation, expression, span })
},
Rule::expression_postfix => {
Expression::Postfix(
PostfixExpression::from_pest(&mut pair.into_inner()).unwrap(),
)
}
Rule::expression_primitive => {
let next = next.into_inner().next().unwrap();
match next.as_rule() {
Rule::value => {
Expression::Value(
Value::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap()
)
},
Rule::variable => Expression::Variable(
Variable::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
),
rule => unreachable!("`expression_primitive` should contain one of [`value`, `variable`], found {:#?}", rule)
}
},
rule => unreachable!("`term` should contain one of ['value', 'variable', 'expression', 'expression_not', 'expression_increment', 'expression_decrement'], found {:#?}", rule)
}
}
rule => unreachable!(
"`parse_expression_term` should be invoked on `Rule::expression_term`, found {:#?}",
rule
),
})
}
fn binary_expression<'ast>(
lhs: Box<Expression<'ast>>,
pair: Pair<'ast, Rule>,
rhs: Box<Expression<'ast>>,
) -> Box<Expression<'ast>> {
let (start, _) = lhs.span().clone().split();
let (_, end) = rhs.span().clone().split();
let span = start.span(&end);
Box::new(match pair.as_rule() {
Rule::operation_or => Expression::binary(BinaryOperator::Or, lhs, rhs, span),
Rule::operation_and => Expression::binary(BinaryOperator::And, lhs, rhs, span),
Rule::operation_eq => Expression::binary(BinaryOperator::Eq, lhs, rhs, span),
Rule::operation_neq => Expression::binary(BinaryOperator::Neq, lhs, rhs, span),
Rule::operation_geq => Expression::binary(BinaryOperator::Geq, lhs, rhs, span),
Rule::operation_gt => Expression::binary(BinaryOperator::Gt, lhs, rhs, span),
Rule::operation_leq => Expression::binary(BinaryOperator::Leq, lhs, rhs, span),
Rule::operation_lt => Expression::binary(BinaryOperator::Lt, lhs, rhs, span),
Rule::operation_add => Expression::binary(BinaryOperator::Add, lhs, rhs, span),
Rule::operation_sub => Expression::binary(BinaryOperator::Sub, lhs, rhs, span),
Rule::operation_mul => Expression::binary(BinaryOperator::Mul, lhs, rhs, span),
Rule::operation_div => Expression::binary(BinaryOperator::Div, lhs, rhs, span),
Rule::operation_pow => Expression::binary(BinaryOperator::Pow, lhs, rhs, span),
_ => unreachable!(),
})
}
impl<'ast> FromPest<'ast> for Expression<'ast> {
type Rule = Rule;
type FatalError = Void;
@ -759,6 +801,14 @@ pub struct DefinitionStatement<'ast> {
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_return))]
pub struct ReturnStatement<'ast> {
pub expressions: Vec<Expression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_for))]
pub struct ForStatement<'ast> {
@ -770,21 +820,13 @@ pub struct ForStatement<'ast> {
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_return))]
pub struct ReturnStatement<'ast> {
pub expressions: Vec<Expression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement))]
pub enum Statement<'ast> {
Assign(AssignStatement<'ast>),
Definition(DefinitionStatement<'ast>),
Iteration(ForStatement<'ast>),
Return(ReturnStatement<'ast>),
Iteration(ForStatement<'ast>),
}
impl<'ast> fmt::Display for AssignStatement<'ast> {
@ -799,16 +841,6 @@ impl<'ast> fmt::Display for DefinitionStatement<'ast> {
}
}
impl<'ast> fmt::Display for ForStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"for {} in {}..{} do {:#?} endfor",
self.index, self.start, self.stop, self.statements
)
}
}
impl<'ast> fmt::Display for ReturnStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, expression) in self.expressions.iter().enumerate() {
@ -821,13 +853,23 @@ impl<'ast> fmt::Display for ReturnStatement<'ast> {
}
}
impl<'ast> fmt::Display for ForStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"for {} in {}..{} do {:#?} endfor",
self.index, self.start, self.stop, self.statements
)
}
}
impl<'ast> fmt::Display for Statement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Statement::Assign(ref statement) => write!(f, "{}", statement),
Statement::Definition(ref statement) => write!(f, "{}", statement),
Statement::Iteration(ref statement) => write!(f, "{}", statement),
Statement::Return(ref statement) => write!(f, "{}", statement),
Statement::Iteration(ref statement) => write!(f, "{}", statement),
}
}
}

View File

@ -48,10 +48,10 @@ operation_binary = _ {
// operation_div_assign = { "/=" }
/// Types
ty_u32 = {"u32"}
ty_field = {"field"}
ty_bool = {"bool"}
ty_basic = { ty_field | ty_bool }
ty_basic = { ty_u32 | ty_field | ty_bool }
ty_struct = { variable }
ty_basic_or_struct = {ty_basic | ty_struct }
ty_array = {ty_basic ~ ("[" ~ value ~ "]")+ }
@ -59,10 +59,11 @@ ty = {ty_array | ty_basic | ty_struct}
type_list = _{(ty ~ ("," ~ ty)*)?}
/// Values
value_number = @{ "-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*)}
value_u32 = { value_number ~ ty_u32}
value_field = { value_number ~ ty_field }
value_boolean = { "true" | "false" }
value_field = @{ "-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) }
value = { value_boolean | value_field }
value = { value_u32 | value_field | value_boolean }
/// Variables
@ -88,8 +89,8 @@ access_member = { "." ~ variable }
access = { access_array | access_call | access_member }
expression_postfix = { variable ~ access+ }
assignee = { variable ~ assignee_access* }
assignee_access = { access_array | access_member }
assignee = { variable ~ assignee_access* }
spread = { "..." ~ expression }
spread_or_expression = { spread | expression }

View File

@ -47,7 +47,7 @@ impl<F: Field + PrimeField> ConstraintSynthesizer<F> for Benchmark<F> {
let syntax_tree = ast::File::from_pest(&mut file).expect("infallible");
// println!("{:#?}", syntax_tree);
let program = aleo_program::Program::from(syntax_tree);
let program = aleo_program::Program::<'_, F>::from(syntax_tree);
println!(" compiled: {:#?}", program);
let program = program.name("simple".into());