Migrates expressions, type, and variable to leo-types

This commit is contained in:
howardwu 2020-06-07 19:19:38 -07:00
parent b9baafd57f
commit 5cdcdd5c12
14 changed files with 759 additions and 737 deletions

View File

@ -4,13 +4,11 @@ use crate::{
constraints::{ConstrainedCircuitMember, ConstrainedProgram, ConstrainedValue},
errors::ExpressionError,
new_scope,
types::{
CircuitFieldDefinition, CircuitMember, Expression, RangeOrExpression,
SpreadOrExpression,
},
FieldType, GroupType, Type,
types::CircuitMember,
FieldType, GroupType,
};
use leo_types::{Identifier, Integer, IntegerType};
use leo_types::{CircuitFieldDefinition, Expression, RangeOrExpression,
SpreadOrExpression, Identifier, Integer, IntegerType, Type};
use snarkos_models::{
curves::{Field, PrimeField},

View File

@ -5,9 +5,9 @@ use crate::{
constraints::{new_scope, ConstrainedProgram, ConstrainedValue},
errors::{FunctionError, ImportError},
field_from_input, group_from_input,
types::{Expression, Function, Program, Type},
types::{Function, Program},
GroupType};
use leo_types::{Identifier, InputValue, Integer};
use leo_types::{Expression, Identifier, InputValue, Integer, Type};
use snarkos_models::{
curves::{Field, PrimeField},

View File

@ -5,12 +5,11 @@ use crate::{
errors::StatementError,
new_scope,
types::{
Assignee, ConditionalNestedOrEnd, ConditionalStatement, Expression,
RangeOrExpression, Statement, Type,
Assignee, ConditionalNestedOrEnd, ConditionalStatement, Statement,
},
GroupType, Variable,
GroupType,
};
use leo_types::{Identifier, Integer};
use leo_types::{Expression, Identifier, Integer, RangeOrExpression, Type, Variable};
use snarkos_models::{
curves::{Field, PrimeField},

View File

@ -2,10 +2,10 @@
use crate::{
errors::ValueError,
types::{Circuit, Function, Type},
types::{Circuit, Function},
FieldType, GroupType,
};
use leo_types::{Identifier, Integer, IntegerType};
use leo_types::{Identifier, Integer, IntegerType, Type};
use snarkos_models::{
curves::{Field, PrimeField},

View File

@ -2,81 +2,10 @@
//! Each defined type consists of typed statements and expressions.
use crate::Import;
use leo_types::{Identifier, Integer, IntegerType};
use leo_types::{Expression, Identifier, Integer, RangeOrExpression, Type, Variable};
use snarkos_models::gadgets::utilities::{
boolean::Boolean,
};
use std::collections::HashMap;
/// A variable that is assigned to a value in the constrained program
#[derive(Clone, PartialEq, Eq)]
pub struct Variable {
pub identifier: Identifier,
pub mutable: bool,
pub _type: Option<Type>,
}
/// Range or expression enum
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RangeOrExpression {
Range(Option<Integer>, Option<Integer>),
Expression(Expression),
}
/// Spread or expression
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SpreadOrExpression {
Spread(Expression),
Expression(Expression),
}
/// Expression that evaluates to a value
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Expression {
// Identifier
Identifier(Identifier),
// Values
Integer(Integer),
Field(String),
Group(String),
Boolean(Boolean),
Implicit(String),
// Number operations
Add(Box<Expression>, Box<Expression>),
Sub(Box<Expression>, Box<Expression>),
Mul(Box<Expression>, Box<Expression>),
Div(Box<Expression>, Box<Expression>),
Pow(Box<Expression>, Box<Expression>),
// Boolean operations
Not(Box<Expression>),
Or(Box<Expression>, Box<Expression>),
And(Box<Expression>, Box<Expression>),
Eq(Box<Expression>, Box<Expression>),
Ge(Box<Expression>, Box<Expression>),
Gt(Box<Expression>, Box<Expression>),
Le(Box<Expression>, Box<Expression>),
Lt(Box<Expression>, Box<Expression>),
// Conditionals
IfElse(Box<Expression>, Box<Expression>, Box<Expression>),
// Arrays
Array(Vec<Box<SpreadOrExpression>>),
ArrayAccess(Box<Expression>, Box<RangeOrExpression>), // (array name, range)
// Circuits
Circuit(Identifier, Vec<CircuitFieldDefinition>),
CircuitMemberAccess(Box<Expression>, Identifier), // (declared circuit name, circuit member name)
CircuitStaticFunctionAccess(Box<Expression>, Identifier), // (defined circuit name, circuit static member name)
// Functions
FunctionCall(Box<Expression>, Vec<Expression>),
}
/// Definition assignee: v, arr[0..2], Point p.x
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Assignee {
@ -85,46 +14,6 @@ pub enum Assignee {
CircuitField(Box<Assignee>, Identifier), // (circuit name, circuit field name)
}
/// Explicit type used for defining a variable or expression type
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Type {
IntegerType(IntegerType),
Field,
Group,
Boolean,
Array(Box<Type>, Vec<usize>),
Circuit(Identifier),
SelfType,
}
impl Type {
pub fn outer_dimension(&self, dimensions: &Vec<usize>) -> Self {
let _type = self.clone();
if dimensions.len() > 1 {
let mut next = vec![];
next.extend_from_slice(&dimensions[1..]);
return Type::Array(Box::new(_type), next);
}
_type
}
pub fn inner_dimension(&self, dimensions: &Vec<usize>) -> Self {
let _type = self.clone();
if dimensions.len() > 1 {
let mut next = vec![];
next.extend_from_slice(&dimensions[..dimensions.len() - 1]);
return Type::Array(Box::new(_type), next);
}
_type
}
}
#[derive(Clone, PartialEq, Eq)]
pub enum ConditionalNestedOrEnd {
Nested(Box<ConditionalStatement>),
@ -153,12 +42,6 @@ pub enum Statement {
/// Circuits
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CircuitFieldDefinition {
pub identifier: Identifier,
pub expression: Expression,
}
#[derive(Clone, PartialEq, Eq)]
pub enum CircuitMember {
CircuitField(Identifier, Type),

View File

@ -1,138 +1,12 @@
//! Format display functions for Leo types.
use crate::{
Assignee, Circuit, CircuitMember, ConditionalNestedOrEnd, ConditionalStatement, Expression,
Function, InputModel, RangeOrExpression,
SpreadOrExpression, Statement, Type, Variable,
Assignee, Circuit, CircuitMember, ConditionalNestedOrEnd, ConditionalStatement,
Function, InputModel, Statement,
};
use std::fmt;
impl fmt::Display for Variable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.mutable {
write!(f, "mut ")?;
}
write!(f, "{}", self.identifier)?;
if self._type.is_some() {
write!(f, ": {}", self._type.as_ref().unwrap())?;
}
write!(f, "")
}
}
impl<'ast> fmt::Display for RangeOrExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
RangeOrExpression::Range(ref from, ref to) => write!(
f,
"{}..{}",
from.as_ref()
.map(|e| format!("{}", e))
.unwrap_or("".to_string()),
to.as_ref()
.map(|e| format!("{}", e))
.unwrap_or("".to_string())
),
RangeOrExpression::Expression(ref e) => write!(f, "{}", e),
}
}
}
impl fmt::Display for SpreadOrExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
SpreadOrExpression::Spread(ref spread) => write!(f, "...{}", spread),
SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression),
}
}
}
impl<'ast> fmt::Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
// Variables
Expression::Identifier(ref variable) => write!(f, "{}", variable),
// Values
Expression::Integer(ref integer) => write!(f, "{}", integer),
Expression::Field(ref field) => write!(f, "{}", field),
Expression::Group(ref group) => write!(f, "{}", group),
Expression::Boolean(ref bool) => write!(f, "{}", bool.get_value().unwrap()),
Expression::Implicit(ref value) => write!(f, "{}", value),
// Number operations
Expression::Add(ref left, ref right) => write!(f, "{} + {}", left, right),
Expression::Sub(ref left, ref right) => write!(f, "{} - {}", left, right),
Expression::Mul(ref left, ref right) => write!(f, "{} * {}", left, right),
Expression::Div(ref left, ref right) => write!(f, "{} / {}", left, right),
Expression::Pow(ref left, ref right) => write!(f, "{} ** {}", left, right),
// Boolean operations
Expression::Not(ref expression) => write!(f, "!{}", expression),
Expression::Or(ref lhs, ref rhs) => write!(f, "{} || {}", lhs, rhs),
Expression::And(ref lhs, ref rhs) => write!(f, "{} && {}", lhs, rhs),
Expression::Eq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
Expression::Ge(ref lhs, ref rhs) => write!(f, "{} >= {}", lhs, rhs),
Expression::Gt(ref lhs, ref rhs) => write!(f, "{} > {}", lhs, rhs),
Expression::Le(ref lhs, ref rhs) => write!(f, "{} <= {}", lhs, rhs),
Expression::Lt(ref lhs, ref rhs) => write!(f, "{} < {}", lhs, rhs),
// Conditionals
Expression::IfElse(ref first, ref second, ref third) => {
write!(f, "if {} then {} else {} fi", first, second, third)
}
// Arrays
Expression::Array(ref array) => {
write!(f, "[")?;
for (i, e) in array.iter().enumerate() {
write!(f, "{}", e)?;
if i < array.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "]")
}
Expression::ArrayAccess(ref array, ref index) => write!(f, "{}[{}]", array, index),
// Circuits
Expression::Circuit(ref var, ref members) => {
write!(f, "{} {{", var)?;
for (i, member) in members.iter().enumerate() {
write!(f, "{}: {}", member.identifier, member.expression)?;
if i < members.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "}}")
}
Expression::CircuitMemberAccess(ref circuit_name, ref member) => {
write!(f, "{}.{}", circuit_name, member)
}
Expression::CircuitStaticFunctionAccess(ref circuit_name, ref member) => {
write!(f, "{}::{}", circuit_name, member)
}
// Function calls
Expression::FunctionCall(ref function, ref arguments) => {
write!(f, "{}(", function,)?;
for (i, param) in arguments.iter().enumerate() {
write!(f, "{}", param)?;
if i < arguments.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
}
}
impl fmt::Display for Assignee {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@ -218,26 +92,6 @@ impl fmt::Display for Statement {
}
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type),
Type::Field => write!(f, "field"),
Type::Group => write!(f, "group"),
Type::Boolean => write!(f, "bool"),
Type::Circuit(ref variable) => write!(f, "{}", variable),
Type::SelfType => write!(f, "Self"),
Type::Array(ref array, ref dimensions) => {
write!(f, "{}", *array)?;
for row in dimensions {
write!(f, "[{}]", row)?;
}
write!(f, "")
}
}
}
}
impl fmt::Display for CircuitMember {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {

View File

@ -3,35 +3,20 @@
use crate::{types, Import, ImportSymbol};
use leo_ast::{
access::{
Access,
AssigneeAccess,
},
circuits::{
Circuit,
CircuitField,
CircuitFieldDefinition,
CircuitFieldDefinition as AstCircuitFieldDefinition,
CircuitFunction,
CircuitMember
},
common::{
Assignee,
Identifier as AstIdentifier,
RangeOrExpression as AstRangeOrExpression,
SpreadOrExpression as AstSpreadOrExpression,
Variable as AstVariable,
Visibility,
Private,
},
expressions::{
ArrayInitializerExpression,
ArrayInlineExpression,
BinaryExpression,
CircuitInlineExpression,
Expression,
NotExpression,
PostfixExpression,
TernaryExpression
},
files::File,
functions::{
Function,
@ -44,7 +29,6 @@ use leo_ast::{
},
operations::{
AssignOperation,
BinaryOperation,
},
statements::{
AssertStatement,
@ -58,370 +42,11 @@ use leo_ast::{
ReturnStatement,
Statement,
},
types::{
ArrayType,
CircuitType,
DataType,
Type as AstType
},
values::{
BooleanValue,
FieldValue,
GroupValue,
IntegerValue,
NumberImplicitValue,
Value
}
};
use leo_types::{Identifier, Integer, IntegerType};
use leo_types::{Expression, Identifier, Integer, RangeOrExpression, Type, Variable};
use snarkos_models::gadgets::utilities::{
boolean::Boolean,
};
use std::collections::HashMap;
impl<'ast> From<AstIdentifier<'ast>> for types::Expression {
fn from(identifier: AstIdentifier<'ast>) -> Self {
types::Expression::Identifier(Identifier::from(identifier))
}
}
/// pest ast -> types::Variable
impl<'ast> From<AstVariable<'ast>> for types::Variable {
fn from(variable: AstVariable<'ast>) -> Self {
types::Variable {
identifier: Identifier::from(variable.identifier),
mutable: variable.mutable.is_some(),
_type: variable._type.map(|_type| types::Type::from(_type)),
}
}
}
/// pest ast - Integer
impl<'ast> From<IntegerValue<'ast>> for types::Expression {
fn from(field: IntegerValue<'ast>) -> Self {
types::Expression::Integer(Integer::from(field.number, field._type))
}
}
impl<'ast> From<AstRangeOrExpression<'ast>> for types::RangeOrExpression {
fn from(range_or_expression: AstRangeOrExpression<'ast>) -> Self {
match range_or_expression {
AstRangeOrExpression::Range(range) => {
let from = range
.from
.map(|from| match types::Expression::from(from.0) {
types::Expression::Integer(number) => number,
types::Expression::Implicit(string) => {
Integer::from_implicit(string)
}
expression => {
unimplemented!("Range bounds should be integers, found {}", expression)
}
});
let to = range.to.map(|to| match types::Expression::from(to.0) {
types::Expression::Integer(number) => number,
types::Expression::Implicit(string) => Integer::from_implicit(string),
expression => {
unimplemented!("Range bounds should be integers, found {}", expression)
}
});
types::RangeOrExpression::Range(from, to)
}
AstRangeOrExpression::Expression(expression) => {
types::RangeOrExpression::Expression(types::Expression::from(expression))
}
}
}
}
/// pest ast -> types::Field
impl<'ast> From<FieldValue<'ast>> for types::Expression {
fn from(field: FieldValue<'ast>) -> Self {
types::Expression::Field(field.number.value)
}
}
/// pest ast -> types::Group
impl<'ast> From<GroupValue<'ast>> for types::Expression {
fn from(group: GroupValue<'ast>) -> Self {
types::Expression::Group(group.to_string())
}
}
/// pest ast -> types::Boolean
impl<'ast> From<BooleanValue<'ast>> for types::Expression {
fn from(boolean: BooleanValue<'ast>) -> Self {
types::Expression::Boolean(Boolean::Constant(
boolean
.value
.parse::<bool>()
.expect("unable to parse boolean"),
))
}
}
/// pest ast -> types::NumberImplicit
impl<'ast> From<NumberImplicitValue<'ast>> for types::Expression {
fn from(number: NumberImplicitValue<'ast>) -> Self {
types::Expression::Implicit(number.number.value)
}
}
/// pest ast -> types::Expression
impl<'ast> From<Value<'ast>> for types::Expression {
fn from(value: Value<'ast>) -> Self {
match value {
Value::Integer(num) => types::Expression::from(num),
Value::Field(field) => types::Expression::from(field),
Value::Group(group) => types::Expression::from(group),
Value::Boolean(bool) => types::Expression::from(bool),
Value::Implicit(value) => types::Expression::from(value),
}
}
}
impl<'ast> From<NotExpression<'ast>> for types::Expression {
fn from(expression: NotExpression<'ast>) -> Self {
types::Expression::Not(Box::new(types::Expression::from(*expression.expression)))
}
}
impl<'ast> From<AstSpreadOrExpression<'ast>> for types::SpreadOrExpression {
fn from(s_or_e: AstSpreadOrExpression<'ast>) -> Self {
match s_or_e {
AstSpreadOrExpression::Spread(spread) => {
types::SpreadOrExpression::Spread(types::Expression::from(spread.expression))
}
AstSpreadOrExpression::Expression(expression) => {
types::SpreadOrExpression::Expression(types::Expression::from(expression))
}
}
}
}
impl<'ast> From<BinaryExpression<'ast>> for types::Expression {
fn from(expression: BinaryExpression<'ast>) -> Self {
match expression.operation {
// Boolean operations
BinaryOperation::Or => types::Expression::Or(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
BinaryOperation::And => types::Expression::And(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
BinaryOperation::Eq => types::Expression::Eq(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
BinaryOperation::Ne => {
types::Expression::Not(Box::new(types::Expression::from(expression)))
}
BinaryOperation::Ge => types::Expression::Ge(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
BinaryOperation::Gt => types::Expression::Gt(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
BinaryOperation::Le => types::Expression::Le(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
BinaryOperation::Lt => types::Expression::Lt(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
// Number operations
BinaryOperation::Add => types::Expression::Add(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
BinaryOperation::Sub => types::Expression::Sub(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
BinaryOperation::Mul => types::Expression::Mul(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
BinaryOperation::Div => types::Expression::Div(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
BinaryOperation::Pow => types::Expression::Pow(
Box::new(types::Expression::from(*expression.left)),
Box::new(types::Expression::from(*expression.right)),
),
}
}
}
impl<'ast> From<TernaryExpression<'ast>> for types::Expression {
fn from(expression: TernaryExpression<'ast>) -> Self {
types::Expression::IfElse(
Box::new(types::Expression::from(*expression.first)),
Box::new(types::Expression::from(*expression.second)),
Box::new(types::Expression::from(*expression.third)),
)
}
}
impl<'ast> From<ArrayInlineExpression<'ast>> for types::Expression {
fn from(array: ArrayInlineExpression<'ast>) -> Self {
types::Expression::Array(
array
.expressions
.into_iter()
.map(|s_or_e| Box::new(types::SpreadOrExpression::from(s_or_e)))
.collect(),
)
}
}
impl<'ast> From<ArrayInitializerExpression<'ast>> for types::Expression {
fn from(array: ArrayInitializerExpression<'ast>) -> Self {
let count = types::Expression::get_count(array.count);
let expression = Box::new(types::SpreadOrExpression::from(*array.expression));
types::Expression::Array(vec![expression; count])
}
}
impl<'ast> From<CircuitField<'ast>> for types::CircuitFieldDefinition {
fn from(member: CircuitField<'ast>) -> Self {
types::CircuitFieldDefinition {
identifier: Identifier::from(member.identifier),
expression: types::Expression::from(member.expression),
}
}
}
impl<'ast> From<CircuitInlineExpression<'ast>> for types::Expression {
fn from(expression: CircuitInlineExpression<'ast>) -> Self {
let variable = Identifier::from(expression.identifier);
let members = expression
.members
.into_iter()
.map(|member| types::CircuitFieldDefinition::from(member))
.collect::<Vec<types::CircuitFieldDefinition>>();
types::Expression::Circuit(variable, members)
}
}
impl<'ast> From<PostfixExpression<'ast>> for types::Expression {
fn from(expression: PostfixExpression<'ast>) -> Self {
let variable =
types::Expression::Identifier(Identifier::from(expression.identifier));
// ast::PostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but Access call expressions
// are recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here
// we start with the id, and we fold the array of accesses by wrapping the current value
expression
.accesses
.into_iter()
.fold(variable, |acc, access| match access {
// Handle array accesses
Access::Array(array) => types::Expression::ArrayAccess(
Box::new(acc),
Box::new(types::RangeOrExpression::from(array.expression)),
),
// Handle function calls
Access::Call(function) => types::Expression::FunctionCall(
Box::new(acc),
function
.expressions
.into_iter()
.map(|expression| types::Expression::from(expression))
.collect(),
),
// Handle circuit member accesses
Access::Object(circuit_object) => types::Expression::CircuitMemberAccess(
Box::new(acc),
Identifier::from(circuit_object.identifier),
),
Access::StaticObject(circuit_object) => {
types::Expression::CircuitStaticFunctionAccess(
Box::new(acc),
Identifier::from(circuit_object.identifier),
)
}
})
}
}
impl<'ast> From<Expression<'ast>> for types::Expression {
fn from(expression: Expression<'ast>) -> Self {
match expression {
Expression::Value(value) => types::Expression::from(value),
Expression::Identifier(variable) => types::Expression::from(variable),
Expression::Not(expression) => types::Expression::from(expression),
Expression::Binary(expression) => types::Expression::from(expression),
Expression::Ternary(expression) => types::Expression::from(expression),
Expression::ArrayInline(expression) => types::Expression::from(expression),
Expression::ArrayInitializer(expression) => types::Expression::from(expression),
Expression::CircuitInline(expression) => types::Expression::from(expression),
Expression::Postfix(expression) => types::Expression::from(expression),
}
}
}
impl<'ast> types::Expression {
fn get_count(count: Value<'ast>) -> usize {
match count {
Value::Integer(integer) => integer
.number
.value
.parse::<usize>()
.expect("Unable to read array size"),
Value::Implicit(number) => number
.number
.value
.parse::<usize>()
.expect("Unable to read array size"),
size => unimplemented!("Array size should be an integer {}", size),
}
}
}
// Assignee -> types::Expression for operator assign statements
impl<'ast> From<Assignee<'ast>> for types::Expression {
fn from(assignee: Assignee<'ast>) -> Self {
let variable = types::Expression::Identifier(Identifier::from(assignee.identifier));
// 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 {
AssigneeAccess::Member(circuit_member) => {
types::Expression::CircuitMemberAccess(
Box::new(acc),
Identifier::from(circuit_member.identifier),
)
}
AssigneeAccess::Array(array) => types::Expression::ArrayAccess(
Box::new(acc),
Box::new(types::RangeOrExpression::from(array.expression)),
),
})
}
}
/// pest ast -> types::Assignee
impl<'ast> From<AstIdentifier<'ast>> for types::Assignee {
@ -441,7 +66,7 @@ impl<'ast> From<Assignee<'ast>> for types::Assignee {
.fold(variable, |acc, access| match access {
AssigneeAccess::Array(array) => types::Assignee::Array(
Box::new(acc),
types::RangeOrExpression::from(array.expression),
RangeOrExpression::from(array.expression),
),
AssigneeAccess::Member(circuit_field) => types::Assignee::CircuitField(
Box::new(acc),
@ -459,7 +84,7 @@ impl<'ast> From<ReturnStatement<'ast>> for types::Statement {
statement
.expressions
.into_iter()
.map(|expression| types::Expression::from(expression))
.map(|expression| Expression::from(expression))
.collect(),
)
}
@ -468,8 +93,8 @@ impl<'ast> From<ReturnStatement<'ast>> for types::Statement {
impl<'ast> From<DefinitionStatement<'ast>> for types::Statement {
fn from(statement: DefinitionStatement<'ast>) -> Self {
types::Statement::Definition(
types::Variable::from(statement.variable),
types::Expression::from(statement.expression),
Variable::from(statement.variable),
Expression::from(statement.expression),
)
}
}
@ -479,46 +104,46 @@ impl<'ast> From<AssignStatement<'ast>> for types::Statement {
match statement.assign {
AssignOperation::Assign(ref _assign) => types::Statement::Assign(
types::Assignee::from(statement.assignee),
types::Expression::from(statement.expression),
Expression::from(statement.expression),
),
operation_assign => {
// convert assignee into postfix expression
let converted = types::Expression::from(statement.assignee.clone());
let converted = Expression::from(statement.assignee.clone());
match operation_assign {
AssignOperation::AddAssign(ref _assign) => types::Statement::Assign(
types::Assignee::from(statement.assignee),
types::Expression::Add(
Expression::Add(
Box::new(converted),
Box::new(types::Expression::from(statement.expression)),
Box::new(Expression::from(statement.expression)),
),
),
AssignOperation::SubAssign(ref _assign) => types::Statement::Assign(
types::Assignee::from(statement.assignee),
types::Expression::Sub(
Expression::Sub(
Box::new(converted),
Box::new(types::Expression::from(statement.expression)),
Box::new(Expression::from(statement.expression)),
),
),
AssignOperation::MulAssign(ref _assign) => types::Statement::Assign(
types::Assignee::from(statement.assignee),
types::Expression::Mul(
Expression::Mul(
Box::new(converted),
Box::new(types::Expression::from(statement.expression)),
Box::new(Expression::from(statement.expression)),
),
),
AssignOperation::DivAssign(ref _assign) => types::Statement::Assign(
types::Assignee::from(statement.assignee),
types::Expression::Div(
Expression::Div(
Box::new(converted),
Box::new(types::Expression::from(statement.expression)),
Box::new(Expression::from(statement.expression)),
),
),
AssignOperation::PowAssign(ref _assign) => types::Statement::Assign(
types::Assignee::from(statement.assignee),
types::Expression::Pow(
Expression::Pow(
Box::new(converted),
Box::new(types::Expression::from(statement.expression)),
Box::new(Expression::from(statement.expression)),
),
),
AssignOperation::Assign(ref _assign) => {
@ -535,17 +160,17 @@ impl<'ast> From<MultipleAssignmentStatement<'ast>> for types::Statement {
let variables = statement
.variables
.into_iter()
.map(|typed_variable| types::Variable::from(typed_variable))
.map(|typed_variable| Variable::from(typed_variable))
.collect();
types::Statement::MultipleAssign(
variables,
types::Expression::FunctionCall(
Box::new(types::Expression::from(statement.function_name)),
Expression::FunctionCall(
Box::new(Expression::from(statement.function_name)),
statement
.arguments
.into_iter()
.map(|e| types::Expression::from(e))
.map(|e| Expression::from(e))
.collect(),
),
)
@ -571,7 +196,7 @@ impl<'ast> From<ConditionalNestedOrEndStatement<'ast>> for types::ConditionalNes
impl<'ast> From<ConditionalStatement<'ast>> for types::ConditionalStatement {
fn from(statement: ConditionalStatement<'ast>) -> Self {
types::ConditionalStatement {
condition: types::Expression::from(statement.condition),
condition: Expression::from(statement.condition),
statements: statement
.statements
.into_iter()
@ -587,14 +212,14 @@ impl<'ast> From<ConditionalStatement<'ast>> for types::ConditionalStatement {
impl<'ast> From<ForStatement<'ast>> for types::Statement {
fn from(statement: ForStatement<'ast>) -> Self {
let from = match types::Expression::from(statement.start) {
types::Expression::Integer(number) => number,
types::Expression::Implicit(string) => Integer::from_implicit(string),
let from = match Expression::from(statement.start) {
Expression::Integer(number) => number,
Expression::Implicit(string) => Integer::from_implicit(string),
expression => unimplemented!("Range bounds should be integers, found {}", expression),
};
let to = match types::Expression::from(statement.stop) {
types::Expression::Integer(number) => number,
types::Expression::Implicit(string) => Integer::from_implicit(string),
let to = match Expression::from(statement.stop) {
Expression::Integer(number) => number,
Expression::Implicit(string) => Integer::from_implicit(string),
expression => unimplemented!("Range bounds should be integers, found {}", expression),
};
@ -615,8 +240,8 @@ impl<'ast> From<AssertStatement<'ast>> for types::Statement {
fn from(statement: AssertStatement<'ast>) -> Self {
match statement {
AssertStatement::AssertEq(assert_eq) => types::Statement::AssertEq(
types::Expression::from(assert_eq.left),
types::Expression::from(assert_eq.right),
Expression::from(assert_eq.left),
Expression::from(assert_eq.right),
),
}
}
@ -624,7 +249,7 @@ impl<'ast> From<AssertStatement<'ast>> for types::Statement {
impl<'ast> From<ExpressionStatement<'ast>> for types::Statement {
fn from(statement: ExpressionStatement<'ast>) -> Self {
types::Statement::Expression(types::Expression::from(statement.expression))
types::Statement::Expression(Expression::from(statement.expression))
}
}
@ -645,58 +270,13 @@ impl<'ast> From<Statement<'ast>> for types::Statement {
}
}
/// pest ast -> Explicit types::Type for defining circuit members and function params
impl From<DataType> for types::Type {
fn from(basic_type: DataType) -> Self {
match basic_type {
DataType::Integer(_type) => {
types::Type::IntegerType(IntegerType::from(_type))
}
DataType::Field(_type) => types::Type::Field,
DataType::Group(_type) => types::Type::Group,
DataType::Boolean(_type) => types::Type::Boolean,
}
}
}
impl<'ast> From<ArrayType<'ast>> for types::Type {
fn from(array_type: ArrayType<'ast>) -> Self {
let element_type = Box::new(types::Type::from(array_type._type));
let dimensions = array_type
.dimensions
.into_iter()
.map(|row| types::Expression::get_count(row))
.collect();
types::Type::Array(element_type, dimensions)
}
}
impl<'ast> From<CircuitType<'ast>> for types::Type {
fn from(circuit_type: CircuitType<'ast>) -> Self {
types::Type::Circuit(Identifier::from(circuit_type.identifier))
}
}
impl<'ast> From<AstType<'ast>> for types::Type {
fn from(_type: AstType<'ast>) -> Self {
match _type {
AstType::Basic(_type) => types::Type::from(_type),
AstType::Array(_type) => types::Type::from(_type),
AstType::Circuit(_type) => types::Type::from(_type),
AstType::SelfType(_type) => types::Type::SelfType,
}
}
}
/// pest ast -> types::Circuit
impl<'ast> From<CircuitFieldDefinition<'ast>> for types::CircuitMember {
fn from(circuit_value: CircuitFieldDefinition<'ast>) -> Self {
impl<'ast> From<AstCircuitFieldDefinition<'ast>> for types::CircuitMember {
fn from(circuit_value: AstCircuitFieldDefinition<'ast>) -> Self {
types::CircuitMember::CircuitField(
Identifier::from(circuit_value.identifier),
types::Type::from(circuit_value._type),
Type::from(circuit_value._type),
)
}
}
@ -750,7 +330,7 @@ impl<'ast> From<FunctionInput<'ast>> for types::InputModel {
private: parameter.visibility.map_or(true, |visibility| {
visibility.eq(&Visibility::Private(Private {}))
}),
_type: types::Type::from(parameter._type),
_type: Type::from(parameter._type),
}
}
}
@ -768,7 +348,7 @@ impl<'ast> From<Function<'ast>> for types::Function {
let returns = function_definition
.returns
.into_iter()
.map(|return_type| types::Type::from(return_type))
.map(|return_type| Type::from(return_type))
.collect();
let statements = function_definition
.statements

View File

@ -0,0 +1,17 @@
use crate::{Identifier, Expression};
use leo_ast::circuits::CircuitField;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CircuitFieldDefinition {
pub identifier: Identifier,
pub expression: Expression,
}
impl<'ast> From<CircuitField<'ast>> for CircuitFieldDefinition {
fn from(member: CircuitField<'ast>) -> Self {
CircuitFieldDefinition {
identifier: Identifier::from(member.identifier),
expression: Expression::from(member.expression),
}
}
}

432
types/src/expression.rs Normal file
View File

@ -0,0 +1,432 @@
use crate::{CircuitFieldDefinition, Identifier, Integer, SpreadOrExpression, RangeOrExpression};
use leo_ast::{
access::{Access, AssigneeAccess},
common::{
Assignee,
Identifier as AstIdentifier,
},
expressions::{
Expression as AstExpression,
CircuitInlineExpression,
PostfixExpression,
ArrayInitializerExpression,
ArrayInlineExpression,
TernaryExpression,
BinaryExpression,
NotExpression
},
operations::{
BinaryOperation,
},
values::{
Value,
FieldValue,
BooleanValue,
GroupValue,
NumberImplicitValue,
IntegerValue
}
};
use snarkos_models::gadgets::utilities::{
boolean::Boolean,
};
use std::fmt;
/// Expression that evaluates to a value
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Expression {
// Identifier
Identifier(Identifier),
// Values
Integer(Integer),
Field(String),
Group(String),
Boolean(Boolean),
Implicit(String),
// Number operations
Add(Box<Expression>, Box<Expression>),
Sub(Box<Expression>, Box<Expression>),
Mul(Box<Expression>, Box<Expression>),
Div(Box<Expression>, Box<Expression>),
Pow(Box<Expression>, Box<Expression>),
// Boolean operations
Not(Box<Expression>),
Or(Box<Expression>, Box<Expression>),
And(Box<Expression>, Box<Expression>),
Eq(Box<Expression>, Box<Expression>),
Ge(Box<Expression>, Box<Expression>),
Gt(Box<Expression>, Box<Expression>),
Le(Box<Expression>, Box<Expression>),
Lt(Box<Expression>, Box<Expression>),
// Conditionals
IfElse(Box<Expression>, Box<Expression>, Box<Expression>),
// Arrays
Array(Vec<Box<SpreadOrExpression>>),
ArrayAccess(Box<Expression>, Box<RangeOrExpression>), // (array name, range)
// Circuits
Circuit(Identifier, Vec<CircuitFieldDefinition>),
CircuitMemberAccess(Box<Expression>, Identifier), // (declared circuit name, circuit member name)
CircuitStaticFunctionAccess(Box<Expression>, Identifier), // (defined circuit name, circuit static member name)
// Functions
FunctionCall(Box<Expression>, Vec<Expression>),
}
impl<'ast> Expression {
pub(crate) fn get_count(count: Value<'ast>) -> usize {
match count {
Value::Integer(integer) => integer
.number
.value
.parse::<usize>()
.expect("Unable to read array size"),
Value::Implicit(number) => number
.number
.value
.parse::<usize>()
.expect("Unable to read array size"),
size => unimplemented!("Array size should be an integer {}", size),
}
}
}
impl<'ast> fmt::Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
// Variables
Expression::Identifier(ref variable) => write!(f, "{}", variable),
// Values
Expression::Integer(ref integer) => write!(f, "{}", integer),
Expression::Field(ref field) => write!(f, "{}", field),
Expression::Group(ref group) => write!(f, "{}", group),
Expression::Boolean(ref bool) => write!(f, "{}", bool.get_value().unwrap()),
Expression::Implicit(ref value) => write!(f, "{}", value),
// Number operations
Expression::Add(ref left, ref right) => write!(f, "{} + {}", left, right),
Expression::Sub(ref left, ref right) => write!(f, "{} - {}", left, right),
Expression::Mul(ref left, ref right) => write!(f, "{} * {}", left, right),
Expression::Div(ref left, ref right) => write!(f, "{} / {}", left, right),
Expression::Pow(ref left, ref right) => write!(f, "{} ** {}", left, right),
// Boolean operations
Expression::Not(ref expression) => write!(f, "!{}", expression),
Expression::Or(ref lhs, ref rhs) => write!(f, "{} || {}", lhs, rhs),
Expression::And(ref lhs, ref rhs) => write!(f, "{} && {}", lhs, rhs),
Expression::Eq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
Expression::Ge(ref lhs, ref rhs) => write!(f, "{} >= {}", lhs, rhs),
Expression::Gt(ref lhs, ref rhs) => write!(f, "{} > {}", lhs, rhs),
Expression::Le(ref lhs, ref rhs) => write!(f, "{} <= {}", lhs, rhs),
Expression::Lt(ref lhs, ref rhs) => write!(f, "{} < {}", lhs, rhs),
// Conditionals
Expression::IfElse(ref first, ref second, ref third) => {
write!(f, "if {} then {} else {} fi", first, second, third)
}
// Arrays
Expression::Array(ref array) => {
write!(f, "[")?;
for (i, e) in array.iter().enumerate() {
write!(f, "{}", e)?;
if i < array.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "]")
}
Expression::ArrayAccess(ref array, ref index) => write!(f, "{}[{}]", array, index),
// Circuits
Expression::Circuit(ref var, ref members) => {
write!(f, "{} {{", var)?;
for (i, member) in members.iter().enumerate() {
write!(f, "{}: {}", member.identifier, member.expression)?;
if i < members.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "}}")
}
Expression::CircuitMemberAccess(ref circuit_name, ref member) => {
write!(f, "{}.{}", circuit_name, member)
}
Expression::CircuitStaticFunctionAccess(ref circuit_name, ref member) => {
write!(f, "{}::{}", circuit_name, member)
}
// Function calls
Expression::FunctionCall(ref function, ref arguments) => {
write!(f, "{}(", function,)?;
for (i, param) in arguments.iter().enumerate() {
write!(f, "{}", param)?;
if i < arguments.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
}
}
impl<'ast> From<CircuitInlineExpression<'ast>> for Expression {
fn from(expression: CircuitInlineExpression<'ast>) -> Self {
let variable = Identifier::from(expression.identifier);
let members = expression
.members
.into_iter()
.map(|member| CircuitFieldDefinition::from(member))
.collect::<Vec<CircuitFieldDefinition>>();
Expression::Circuit(variable, members)
}
}
impl<'ast> From<PostfixExpression<'ast>> for Expression {
fn from(expression: PostfixExpression<'ast>) -> Self {
let variable =
Expression::Identifier(Identifier::from(expression.identifier));
// ast::PostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but Access call expressions
// are recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here
// we start with the id, and we fold the array of accesses by wrapping the current value
expression
.accesses
.into_iter()
.fold(variable, |acc, access| match access {
// Handle array accesses
Access::Array(array) => Expression::ArrayAccess(
Box::new(acc),
Box::new(RangeOrExpression::from(array.expression)),
),
// Handle function calls
Access::Call(function) => Expression::FunctionCall(
Box::new(acc),
function
.expressions
.into_iter()
.map(|expression| Expression::from(expression))
.collect(),
),
// Handle circuit member accesses
Access::Object(circuit_object) => Expression::CircuitMemberAccess(
Box::new(acc),
Identifier::from(circuit_object.identifier),
),
Access::StaticObject(circuit_object) => {
Expression::CircuitStaticFunctionAccess(
Box::new(acc),
Identifier::from(circuit_object.identifier),
)
}
})
}
}
impl<'ast> From<AstExpression<'ast>> for Expression {
fn from(expression: AstExpression<'ast>) -> Self {
match expression {
AstExpression::Value(value) => Expression::from(value),
AstExpression::Identifier(variable) => Expression::from(variable),
AstExpression::Not(expression) => Expression::from(expression),
AstExpression::Binary(expression) => Expression::from(expression),
AstExpression::Ternary(expression) => Expression::from(expression),
AstExpression::ArrayInline(expression) => Expression::from(expression),
AstExpression::ArrayInitializer(expression) => Expression::from(expression),
AstExpression::CircuitInline(expression) => Expression::from(expression),
AstExpression::Postfix(expression) => Expression::from(expression),
}
}
}
// Assignee -> Expression for operator assign statements
impl<'ast> From<Assignee<'ast>> for Expression {
fn from(assignee: Assignee<'ast>) -> Self {
let variable = Expression::Identifier(Identifier::from(assignee.identifier));
// 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 {
AssigneeAccess::Member(circuit_member) => {
Expression::CircuitMemberAccess(
Box::new(acc),
Identifier::from(circuit_member.identifier),
)
}
AssigneeAccess::Array(array) => Expression::ArrayAccess(
Box::new(acc),
Box::new(RangeOrExpression::from(array.expression)),
),
})
}
}
impl<'ast> From<BinaryExpression<'ast>> for Expression {
fn from(expression: BinaryExpression<'ast>) -> Self {
match expression.operation {
// Boolean operations
BinaryOperation::Or => Expression::Or(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
BinaryOperation::And => Expression::And(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
BinaryOperation::Eq => Expression::Eq(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
BinaryOperation::Ne => {
Expression::Not(Box::new(Expression::from(expression)))
}
BinaryOperation::Ge => Expression::Ge(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
BinaryOperation::Gt => Expression::Gt(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
BinaryOperation::Le => Expression::Le(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
BinaryOperation::Lt => Expression::Lt(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
// Number operations
BinaryOperation::Add => Expression::Add(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
BinaryOperation::Sub => Expression::Sub(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
BinaryOperation::Mul => Expression::Mul(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
BinaryOperation::Div => Expression::Div(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
BinaryOperation::Pow => Expression::Pow(
Box::new(Expression::from(*expression.left)),
Box::new(Expression::from(*expression.right)),
),
}
}
}
impl<'ast> From<TernaryExpression<'ast>> for Expression {
fn from(expression: TernaryExpression<'ast>) -> Self {
Expression::IfElse(
Box::new(Expression::from(*expression.first)),
Box::new(Expression::from(*expression.second)),
Box::new(Expression::from(*expression.third)),
)
}
}
impl<'ast> From<ArrayInlineExpression<'ast>> for Expression {
fn from(array: ArrayInlineExpression<'ast>) -> Self {
Expression::Array(
array
.expressions
.into_iter()
.map(|s_or_e| Box::new(SpreadOrExpression::from(s_or_e)))
.collect(),
)
}
}
impl<'ast> From<ArrayInitializerExpression<'ast>> for Expression {
fn from(array: ArrayInitializerExpression<'ast>) -> Self {
let count = Expression::get_count(array.count);
let expression = Box::new(SpreadOrExpression::from(*array.expression));
Expression::Array(vec![expression; count])
}
}
impl<'ast> From<Value<'ast>> for Expression {
fn from(value: Value<'ast>) -> Self {
match value {
Value::Integer(num) => Expression::from(num),
Value::Field(field) => Expression::from(field),
Value::Group(group) => Expression::from(group),
Value::Boolean(bool) => Expression::from(bool),
Value::Implicit(value) => Expression::from(value),
}
}
}
impl<'ast> From<NotExpression<'ast>> for Expression {
fn from(expression: NotExpression<'ast>) -> Self {
Expression::Not(Box::new(Expression::from(*expression.expression)))
}
}
impl<'ast> From<FieldValue<'ast>> for Expression {
fn from(field: FieldValue<'ast>) -> Self {
Expression::Field(field.number.value)
}
}
impl<'ast> From<GroupValue<'ast>> for Expression {
fn from(group: GroupValue<'ast>) -> Self {
Expression::Group(group.to_string())
}
}
impl<'ast> From<BooleanValue<'ast>> for Expression {
fn from(boolean: BooleanValue<'ast>) -> Self {
Expression::Boolean(Boolean::Constant(
boolean
.value
.parse::<bool>()
.expect("unable to parse boolean"),
))
}
}
impl<'ast> From<NumberImplicitValue<'ast>> for Expression {
fn from(number: NumberImplicitValue<'ast>) -> Self {
Expression::Implicit(number.number.value)
}
}
impl<'ast> From<IntegerValue<'ast>> for Expression {
fn from(field: IntegerValue<'ast>) -> Self {
Expression::Integer(Integer::from(field.number, field._type))
}
}
impl<'ast> From<AstIdentifier<'ast>> for Expression {
fn from(identifier: AstIdentifier<'ast>) -> Self {
Expression::Identifier(Identifier::from(identifier))
}
}

View File

@ -1,9 +1,15 @@
#[macro_use]
extern crate thiserror;
pub mod circuit_field_definition;
pub use circuit_field_definition::*;
pub mod errors;
pub use errors::*;
pub mod expression;
pub use expression::*;
pub mod identifier;
pub use identifier::*;
@ -15,3 +21,15 @@ pub use integer::*;
pub mod integer_type;
pub use integer_type::*;
pub mod range_or_expression;
pub use range_or_expression::*;
pub mod spread_or_expression;
pub use spread_or_expression::*;
pub mod type_;
pub use type_::*;
pub mod variable;
pub use variable::*;

View File

@ -0,0 +1,61 @@
use crate::{Integer, Expression};
use leo_ast::common::RangeOrExpression as AstRangeOrExpression;
use std::fmt;
/// Range or expression enum
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RangeOrExpression {
Range(Option<Integer>, Option<Integer>),
Expression(Expression),
}
impl<'ast> From<AstRangeOrExpression<'ast>> for RangeOrExpression {
fn from(range_or_expression: AstRangeOrExpression<'ast>) -> Self {
match range_or_expression {
AstRangeOrExpression::Range(range) => {
let from = range
.from
.map(|from| match Expression::from(from.0) {
Expression::Integer(number) => number,
Expression::Implicit(string) => {
Integer::from_implicit(string)
}
expression => {
unimplemented!("Range bounds should be integers, found {}", expression)
}
});
let to = range.to.map(|to| match Expression::from(to.0) {
Expression::Integer(number) => number,
Expression::Implicit(string) => Integer::from_implicit(string),
expression => {
unimplemented!("Range bounds should be integers, found {}", expression)
}
});
RangeOrExpression::Range(from, to)
}
AstRangeOrExpression::Expression(expression) => {
RangeOrExpression::Expression(Expression::from(expression))
}
}
}
}
impl<'ast> fmt::Display for RangeOrExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
RangeOrExpression::Range(ref from, ref to) => write!(
f,
"{}..{}",
from.as_ref()
.map(|e| format!("{}", e))
.unwrap_or("".to_string()),
to.as_ref()
.map(|e| format!("{}", e))
.unwrap_or("".to_string())
),
RangeOrExpression::Expression(ref e) => write!(f, "{}", e),
}
}
}

View File

@ -0,0 +1,33 @@
use crate::Expression;
use leo_ast::common::SpreadOrExpression as AstSpreadOrExpression;
use std::fmt;
/// Spread or expression
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SpreadOrExpression {
Spread(Expression),
Expression(Expression),
}
impl<'ast> From<AstSpreadOrExpression<'ast>> for SpreadOrExpression {
fn from(s_or_e: AstSpreadOrExpression<'ast>) -> Self {
match s_or_e {
AstSpreadOrExpression::Spread(spread) => {
SpreadOrExpression::Spread(Expression::from(spread.expression))
}
AstSpreadOrExpression::Expression(expression) => {
SpreadOrExpression::Expression(Expression::from(expression))
}
}
}
}
impl fmt::Display for SpreadOrExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
SpreadOrExpression::Spread(ref spread) => write!(f, "...{}", spread),
SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression),
}
}
}

109
types/src/type_.rs Normal file
View File

@ -0,0 +1,109 @@
use crate::{Expression, IntegerType, Identifier};
use leo_ast::types::{DataType, ArrayType, CircuitType, Type as AstType};
use std::fmt;
/// Explicit type used for defining a variable or expression type
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Type {
IntegerType(IntegerType),
Field,
Group,
Boolean,
Array(Box<Type>, Vec<usize>),
Circuit(Identifier),
SelfType,
}
/// pest ast -> Explicit Type for defining circuit members and function params
impl From<DataType> for Type {
fn from(basic_type: DataType) -> Self {
match basic_type {
DataType::Integer(_type) => {
Type::IntegerType(IntegerType::from(_type))
}
DataType::Field(_type) => Type::Field,
DataType::Group(_type) => Type::Group,
DataType::Boolean(_type) => Type::Boolean,
}
}
}
impl<'ast> From<ArrayType<'ast>> for Type {
fn from(array_type: ArrayType<'ast>) -> Self {
let element_type = Box::new(Type::from(array_type._type));
let dimensions = array_type
.dimensions
.into_iter()
.map(|row| Expression::get_count(row))
.collect();
Type::Array(element_type, dimensions)
}
}
impl<'ast> From<CircuitType<'ast>> for Type {
fn from(circuit_type: CircuitType<'ast>) -> Self {
Type::Circuit(Identifier::from(circuit_type.identifier))
}
}
impl<'ast> From<AstType<'ast>> for Type {
fn from(_type: AstType<'ast>) -> Self {
match _type {
AstType::Basic(_type) => Type::from(_type),
AstType::Array(_type) => Type::from(_type),
AstType::Circuit(_type) => Type::from(_type),
AstType::SelfType(_type) => Type::SelfType,
}
}
}
impl Type {
pub fn outer_dimension(&self, dimensions: &Vec<usize>) -> Self {
let _type = self.clone();
if dimensions.len() > 1 {
let mut next = vec![];
next.extend_from_slice(&dimensions[1..]);
return Type::Array(Box::new(_type), next);
}
_type
}
pub fn inner_dimension(&self, dimensions: &Vec<usize>) -> Self {
let _type = self.clone();
if dimensions.len() > 1 {
let mut next = vec![];
next.extend_from_slice(&dimensions[..dimensions.len() - 1]);
return Type::Array(Box::new(_type), next);
}
_type
}
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type),
Type::Field => write!(f, "field"),
Type::Group => write!(f, "group"),
Type::Boolean => write!(f, "bool"),
Type::Circuit(ref variable) => write!(f, "{}", variable),
Type::SelfType => write!(f, "Self"),
Type::Array(ref array, ref dimensions) => {
write!(f, "{}", *array)?;
for row in dimensions {
write!(f, "[{}]", row)?;
}
write!(f, "")
}
}
}
}

38
types/src/variable.rs Normal file
View File

@ -0,0 +1,38 @@
use crate::{Identifier, Type};
use leo_ast::common::Variable as AstVariable;
use std::fmt;
/// A variable that is assigned to a value in the constrained program
#[derive(Clone, PartialEq, Eq)]
pub struct Variable {
pub identifier: Identifier,
pub mutable: bool,
pub _type: Option<Type>,
}
impl<'ast> From<AstVariable<'ast>> for Variable {
fn from(variable: AstVariable<'ast>) -> Self {
Variable {
identifier: Identifier::from(variable.identifier),
mutable: variable.mutable.is_some(),
_type: variable._type.map(|_type| Type::from(_type)),
}
}
}
impl fmt::Display for Variable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.mutable {
write!(f, "mut ")?;
}
write!(f, "{}", self.identifier)?;
if self._type.is_some() {
write!(f, ": {}", self._type.as_ref().unwrap())?;
}
write!(f, "")
}
}