mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-29 03:35:10 +03:00
Migrates expressions, type, and variable to leo-types
This commit is contained in:
parent
b9baafd57f
commit
5cdcdd5c12
@ -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},
|
||||
|
@ -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},
|
||||
|
@ -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},
|
||||
|
@ -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},
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
17
types/src/circuit_field_definition.rs
Normal file
17
types/src/circuit_field_definition.rs
Normal 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
432
types/src/expression.rs
Normal 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))
|
||||
}
|
||||
}
|
@ -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::*;
|
||||
|
61
types/src/range_or_expression.rs
Normal file
61
types/src/range_or_expression.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
}
|
33
types/src/spread_or_expression.rs
Normal file
33
types/src/spread_or_expression.rs
Normal 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
109
types/src/type_.rs
Normal 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
38
types/src/variable.rs
Normal 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, "")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user