diff --git a/README.md b/README.md index ce13d3ad57..7972ef1f4c 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,27 @@ graph LR 2. Circuit definitions 3. Function definitions +## Defining Variables +Leo supports `let` and `const` keywords for variable definition. + +```let a = true;``` defines an **allocated** program variable `a` with boolean value `true`. + +```const a = true;``` defines a **constant** program variable `a` with boolean value `true`. + +**Allocated** variables define private variables in the constraint system. Their value is constrained in the circuit on initialization. + +**Constant** variables do not define a variable in the constraint system. Their value is constrained in the circuit on computation with an **allocated** variable. +**Constant** variables can be mutable. They do not have the same functionality as `const` variables in other languages. +```rust +function addOne() -> { + let a = 0u8; // allocated, value enforced on this line + const b = 1u8; // constant, value not enforced yet + + return a + b // allocated, computed value is enforced to be the sum of both values +} +``` +Computations are expressed in terms of arithmetic circuits, in particular rank-1 quadratic constraint systems. Thus computing on an allocated variable always results in another allocated variable. + ## Mutability * All defined variables in Leo are immutable by default. * Variables can be made mutable with the `mut` keyword. diff --git a/ast/src/common/declare.rs b/ast/src/common/declare.rs new file mode 100644 index 0000000000..344f9c5c73 --- /dev/null +++ b/ast/src/common/declare.rs @@ -0,0 +1,18 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::declare))] +pub enum Declare { + Const(Const), + Let(Let), +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::const_))] +pub struct Const {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::let_))] +pub struct Let {} diff --git a/ast/src/common/mod.rs b/ast/src/common/mod.rs index fb64745c9a..54945c1bf4 100644 --- a/ast/src/common/mod.rs +++ b/ast/src/common/mod.rs @@ -1,6 +1,9 @@ pub mod assignee; pub use assignee::*; +pub mod declare; +pub use declare::*; + pub mod eoi; pub use eoi::*; diff --git a/ast/src/leo.pest b/ast/src/leo.pest index 35bb6dd60e..caaefc02cd 100644 --- a/ast/src/leo.pest +++ b/ast/src/leo.pest @@ -8,7 +8,11 @@ file = { SOI ~ NEWLINE* ~ import* ~ NEWLINE* ~ circuit_definition* ~ NEWLINE* ~ // Declared in common/identifier.rs identifier = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } -protected_name = { "let" | "for"| "if" | "else" | "as" | "return" } +protected_name = { + "for"| "if" | "else" | "as" | "return" + | declare | mutable | static_ | value_boolean + | type_array | type_data +} // Declared in common/line_end.rs LINE_END = { ";" ~ NEWLINE* } @@ -36,6 +40,11 @@ static_ = { "static" } // Declared in common/variable.rs variable = { mutable? ~ identifier ~ (":" ~ type_)? } +// Declared in common/declare.rs +declare = { let_ | const_ } +const_ = { "const" } +let_ = { "let" } + /// Operations // Declared in operations/not_operation.rs @@ -249,7 +258,7 @@ statement_conditional = {"if" ~ (expression | "(" ~ expression ~ ")") ~ "{" ~ NE conditional_nested_or_end_statement = { statement_conditional | "{" ~ NEWLINE* ~ statement+ ~ "}"} // Declared in statements/definition_statement.rs -statement_definition = { "let" ~ variable ~ "=" ~ expression ~ LINE_END} +statement_definition = { declare ~ variable ~ "=" ~ expression ~ LINE_END} // Declared in statements/expression_statement.rs statement_expression = { expression ~ LINE_END } @@ -258,7 +267,7 @@ statement_expression = { expression ~ LINE_END } statement_for = { "for" ~ identifier ~ "in" ~ expression ~ ".." ~ expression ~ "{" ~ NEWLINE* ~ statement+ ~ "}"} // Declared in statements/multiple_assignment_statement.rs -statement_multiple_assignment = { "let" ~ "(" ~ variable_tuple ~ ")" ~ "=" ~ identifier ~ "(" ~ expression_tuple ~ ")" ~ LINE_END} +statement_multiple_assignment = { declare ~ "(" ~ variable_tuple ~ ")" ~ "=" ~ identifier ~ "(" ~ expression_tuple ~ ")" ~ LINE_END} variable_tuple = _{ variable ~ ("," ~ variable)* } // Declared in statements/return_statement.rs diff --git a/ast/src/statements/definition_statement.rs b/ast/src/statements/definition_statement.rs index bb539a3119..a3ad1e11e4 100644 --- a/ast/src/statements/definition_statement.rs +++ b/ast/src/statements/definition_statement.rs @@ -1,6 +1,6 @@ use crate::{ ast::Rule, - common::{LineEnd, Variable}, + common::{Declare, LineEnd, Variable}, expressions::Expression, }; @@ -11,6 +11,7 @@ use std::fmt; #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::statement_definition))] pub struct DefinitionStatement<'ast> { + pub declare: Declare, pub variable: Variable<'ast>, pub expression: Expression<'ast>, pub line_end: LineEnd, diff --git a/ast/src/statements/multiple_assignment_statement.rs b/ast/src/statements/multiple_assignment_statement.rs index e61814f400..f64b811726 100644 --- a/ast/src/statements/multiple_assignment_statement.rs +++ b/ast/src/statements/multiple_assignment_statement.rs @@ -1,6 +1,6 @@ use crate::{ ast::Rule, - common::{Identifier, LineEnd, Variable}, + common::{Declare, Identifier, LineEnd, Variable}, expressions::Expression, }; @@ -11,6 +11,7 @@ use std::fmt; #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::statement_multiple_assignment))] pub struct MultipleAssignmentStatement<'ast> { + pub declare: Declare, pub variables: Vec>, pub function_name: Identifier<'ast>, pub arguments: Vec>, diff --git a/compiler/src/constraints/statement.rs b/compiler/src/constraints/statement.rs index 5fc5e77b10..add36fa538 100644 --- a/compiler/src/constraints/statement.rs +++ b/compiler/src/constraints/statement.rs @@ -10,6 +10,7 @@ use leo_types::{ Assignee, ConditionalNestedOrEndStatement, ConditionalStatement, + Declare, Expression, Identifier, Integer, @@ -221,6 +222,7 @@ impl> ConstrainedProgram { cs: &mut CS, file_scope: String, function_scope: String, + declare: Declare, variable: Variable, expression: Expression, ) -> Result<(), StatementError> { @@ -228,7 +230,7 @@ impl> ConstrainedProgram { if let Some(ref _type) = variable._type { expected_types.push(_type.clone()); } - let value = self.enforce_expression( + let mut value = self.enforce_expression( cs, file_scope.clone(), function_scope.clone(), @@ -236,6 +238,10 @@ impl> ConstrainedProgram { expression, )?; + if let Declare::Let = declare { + value.allocate_value(cs)?; + } + self.store_definition(function_scope, variable, value) } @@ -484,8 +490,8 @@ impl> ConstrainedProgram { Statement::Return(expressions) => { res = Some(self.enforce_return_statement(cs, file_scope, function_scope, expressions, return_types)?); } - Statement::Definition(variable, expression) => { - self.enforce_definition_statement(cs, file_scope, function_scope, variable, expression)?; + Statement::Definition(declare, variable, expression) => { + self.enforce_definition_statement(cs, file_scope, function_scope, declare, variable, expression)?; } Statement::Assign(variable, expression) => { self.enforce_assign_statement(cs, file_scope, function_scope, indicator, variable, expression)?; diff --git a/compiler/src/constraints/value.rs b/compiler/src/constraints/value.rs index bf658c4691..77a9cf31a4 100644 --- a/compiler/src/constraints/value.rs +++ b/compiler/src/constraints/value.rs @@ -9,6 +9,7 @@ use snarkos_models::{ gadgets::{ r1cs::ConstraintSystem, utilities::{ + alloc::AllocGadget, boolean::Boolean, eq::ConditionalEqGadget, select::CondSelectGadget, @@ -105,6 +106,74 @@ impl> ConstrainedValue { *self = *inner.clone() } } + + pub(crate) fn allocate_value>(&mut self, mut cs: CS) -> Result<(), ValueError> { + match self { + // allocated values + ConstrainedValue::Boolean(boolean) => { + let option = boolean.get_value(); + + *boolean = Boolean::alloc(cs, || option.ok_or(SynthesisError::AssignmentMissing))?; + } + ConstrainedValue::Integer(integer) => { + let integer_type = integer.get_type(); + let option = integer.get_value(); + let name = format!("clone {}", integer); + + *integer = Integer::allocate_type(&mut cs, integer_type, name, option)?; + } + ConstrainedValue::Field(field) => { + let option = field.get_value().map(|v| format!("{}", v)); + + *field = FieldType::alloc(cs, || option.ok_or(SynthesisError::AssignmentMissing))?; + } + ConstrainedValue::Group(group) => { + let string = format!("{}", group); // may need to implement u256 -> decimal formatting + + *group = G::alloc(cs, || Ok(string))?; + } + // value wrappers + ConstrainedValue::Array(array) => { + array + .iter_mut() + .enumerate() + .map(|(i, value)| value.allocate_value(cs.ns(|| format!("allocate array member {}", i)))) + .collect::>()?; + } + ConstrainedValue::CircuitExpression(_id, members) => { + members + .iter_mut() + .enumerate() + .map(|(i, member)| { + member + .1 + .allocate_value(cs.ns(|| format!("allocate circuit member {}", i))) + }) + .collect::>()?; + } + ConstrainedValue::Return(array) => { + array + .iter_mut() + .enumerate() + .map(|(i, value)| value.allocate_value(cs.ns(|| format!("allocate return member {}", i)))) + .collect::>()?; + } + ConstrainedValue::Mutable(value) => { + value.allocate_value(cs)?; + } + ConstrainedValue::Static(value) => { + value.allocate_value(cs)?; + } + // empty wrappers + ConstrainedValue::CircuitDefinition(_) => {} + ConstrainedValue::Function(_, _) => {} + ConstrainedValue::Unresolved(_) => { + return Err(ValueError::SynthesisError(SynthesisError::AssignmentMissing)); + } + } + + Ok(()) + } } impl> fmt::Display for ConstrainedValue { diff --git a/compiler/src/errors/constraints/value.rs b/compiler/src/errors/constraints/value.rs index ad25aa443a..b8eda405df 100644 --- a/compiler/src/errors/constraints/value.rs +++ b/compiler/src/errors/constraints/value.rs @@ -1,6 +1,7 @@ use crate::errors::{FieldError, GroupError}; use leo_types::IntegerError; +use snarkos_errors::gadgets::SynthesisError; use std::{num::ParseIntError, str::ParseBoolError}; #[derive(Debug, Error)] @@ -19,4 +20,7 @@ pub enum ValueError { #[error("{}", _0)] ParseIntError(#[from] ParseIntError), + + #[error("{}", _0)] + SynthesisError(#[from] SynthesisError), } diff --git a/compiler/tests/array/multi.leo b/compiler/tests/array/multi.leo index 32465a0717..7dc37aa8d4 100644 --- a/compiler/tests/array/multi.leo +++ b/compiler/tests/array/multi.leo @@ -1,8 +1,8 @@ // Multidimensional array syntax in leo function main() -> u32[3][2] { - let m = [[0u32, 0u32, 0u32], [0u32, 0u32, 0u32]]; // inline + const m = [[0u32, 0u32, 0u32], [0u32, 0u32, 0u32]]; // inline - let m: u32[3][2] = [[0; 3]; 2]; // initializer + const m: u32[3][2] = [[0; 3]; 2]; // initializer return m } \ No newline at end of file diff --git a/compiler/tests/boolean/all.leo b/compiler/tests/boolean/all.leo index fde553f2a3..ef95729b4e 100644 --- a/compiler/tests/boolean/all.leo +++ b/compiler/tests/boolean/all.leo @@ -1,8 +1,8 @@ // !(true && (false || true)) function main() -> bool { - let a = true; - let b = false || a; - let c = !(true && b); + const a = true; + const b = false || a; + const c = !(true && b); return c } \ No newline at end of file diff --git a/compiler/tests/function/scope_fail.leo b/compiler/tests/function/scope_fail.leo index 1361a80812..e25a0f1e6b 100644 --- a/compiler/tests/function/scope_fail.leo +++ b/compiler/tests/function/scope_fail.leo @@ -3,6 +3,6 @@ function foo() -> field { } function main() -> field { - let myGlobal = 42field; + const myGlobal = 42field; return foo() } \ No newline at end of file diff --git a/compiler/tests/function/value_unchanged.leo b/compiler/tests/function/value_unchanged.leo index c986efa816..46bcd78f1b 100644 --- a/compiler/tests/function/value_unchanged.leo +++ b/compiler/tests/function/value_unchanged.leo @@ -12,7 +12,7 @@ function bad_mutate(mut x: u32) { } function main() -> u32 { - let a = 1; + let a = 1u32; bad_mutate(a); return a // <- returns 1 diff --git a/compiler/tests/group/add.leo b/compiler/tests/group/add.leo index 19496a03f7..28cbcd67b8 100644 --- a/compiler/tests/group/add.leo +++ b/compiler/tests/group/add.leo @@ -1,6 +1,6 @@ function main() -> group { - let point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - let point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; + const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; + const point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; return point_1 + point_2 } \ No newline at end of file diff --git a/compiler/tests/group/assert_eq_false.leo b/compiler/tests/group/assert_eq_false.leo index 1ac3f02fd7..5e130610aa 100644 --- a/compiler/tests/group/assert_eq_false.leo +++ b/compiler/tests/group/assert_eq_false.leo @@ -1,6 +1,6 @@ function main() { - let point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - let point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; + const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; + const point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; assert_eq!(point_1, point_2); } \ No newline at end of file diff --git a/compiler/tests/group/assert_eq_true.leo b/compiler/tests/group/assert_eq_true.leo index b940016ce0..fecce61611 100644 --- a/compiler/tests/group/assert_eq_true.leo +++ b/compiler/tests/group/assert_eq_true.leo @@ -1,6 +1,6 @@ function main() { - let point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - let point_2 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; + const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; + const point_2 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; assert_eq!(point_1, point_2); } \ No newline at end of file diff --git a/compiler/tests/group/eq_false.leo b/compiler/tests/group/eq_false.leo index 62630c66ac..004c44b731 100644 --- a/compiler/tests/group/eq_false.leo +++ b/compiler/tests/group/eq_false.leo @@ -1,6 +1,6 @@ function main() -> bool { - let point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - let point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; + const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; + const point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; return point_1 == point_2 } \ No newline at end of file diff --git a/compiler/tests/group/eq_true.leo b/compiler/tests/group/eq_true.leo index d98a3ca492..490c0e9432 100644 --- a/compiler/tests/group/eq_true.leo +++ b/compiler/tests/group/eq_true.leo @@ -1,6 +1,6 @@ function main() -> bool { - let point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - let point_2 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; + const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; + const point_2 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; return point_1 == point_2 } \ No newline at end of file diff --git a/compiler/tests/group/sub.leo b/compiler/tests/group/sub.leo index d1c582e635..a1f95b5a3c 100644 --- a/compiler/tests/group/sub.leo +++ b/compiler/tests/group/sub.leo @@ -1,6 +1,6 @@ function main() -> group { - let point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - let point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; + const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; + const point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; return point_1 - point_2 } \ No newline at end of file diff --git a/compiler/tests/group/ternary.leo b/compiler/tests/group/ternary.leo index 1841fc6bd8..094cede5b2 100644 --- a/compiler/tests/group/ternary.leo +++ b/compiler/tests/group/ternary.leo @@ -1,6 +1,6 @@ function main (b: bool) -> group { - let point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - let point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; + const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; + const point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; return if b ? point_1 : point_2 } \ No newline at end of file diff --git a/types/src/common/declare.rs b/types/src/common/declare.rs new file mode 100644 index 0000000000..d543100fd1 --- /dev/null +++ b/types/src/common/declare.rs @@ -0,0 +1,27 @@ +use leo_ast::common::Declare as AstDeclare; + +use std::fmt; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Declare { + Const, + Let, +} + +impl<'ast> From for Declare { + fn from(declare: AstDeclare) -> Self { + match declare { + AstDeclare::Const(_) => Declare::Const, + AstDeclare::Let(_) => Declare::Let, + } + } +} + +impl fmt::Display for Declare { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Declare::Const => write!(f, "const"), + Declare::Let => write!(f, "let"), + } + } +} diff --git a/types/src/common/mod.rs b/types/src/common/mod.rs index a338bc954f..047ca0b8fd 100644 --- a/types/src/common/mod.rs +++ b/types/src/common/mod.rs @@ -1,6 +1,9 @@ pub mod assignee; pub use assignee::*; +pub mod declare; +pub use declare::*; + pub mod identifier; pub use identifier::*; diff --git a/types/src/integer.rs b/types/src/integer.rs index fe3e4dad1a..3f04b72085 100644 --- a/types/src/integer.rs +++ b/types/src/integer.rs @@ -58,16 +58,20 @@ impl<'ast> Integer { } impl Integer { - pub fn to_usize(&self) -> usize { + pub fn get_value(&self) -> Option { match self { - Integer::U8(u8) => u8.value.unwrap() as usize, - Integer::U16(u16) => u16.value.unwrap() as usize, - Integer::U32(u32) => u32.value.unwrap() as usize, - Integer::U64(u64) => u64.value.unwrap() as usize, - Integer::U128(u128) => u128.value.unwrap() as usize, + Integer::U8(u8) => u8.value.map(|v| v as u128), + Integer::U16(u16) => u16.value.map(|v| v as u128), + Integer::U32(u32) => u32.value.map(|v| v as u128), + Integer::U64(u64) => u64.value.map(|v| v as u128), + Integer::U128(u128) => u128.value.map(|v| v as u128), } } + pub fn to_usize(&self) -> usize { + self.get_value().unwrap() as usize + } + pub fn get_type(&self) -> IntegerType { match self { Integer::U8(_u8) => IntegerType::U8, @@ -78,6 +82,47 @@ impl Integer { } } + pub fn allocate_type>( + cs: &mut CS, + integer_type: IntegerType, + name: String, + option: Option, + ) -> Result { + Ok(match integer_type { + IntegerType::U8 => { + let u8_option = option.map(|integer| integer as u8); + let u8_result = UInt8::alloc(cs.ns(|| name), || u8_option.ok_or(SynthesisError::AssignmentMissing))?; + + Integer::U8(u8_result) + } + IntegerType::U16 => { + let u16_option = option.map(|integer| integer as u16); + let u16_result = UInt16::alloc(cs.ns(|| name), || u16_option.ok_or(SynthesisError::AssignmentMissing))?; + + Integer::U16(u16_result) + } + IntegerType::U32 => { + let u32_option = option.map(|integer| integer as u32); + let u32_result = UInt32::alloc(cs.ns(|| name), || u32_option.ok_or(SynthesisError::AssignmentMissing))?; + + Integer::U32(u32_result) + } + IntegerType::U64 => { + let u64_option = option.map(|integer| integer as u64); + let u64_result = UInt64::alloc(cs.ns(|| name), || u64_option.ok_or(SynthesisError::AssignmentMissing))?; + + Integer::U64(u64_result) + } + IntegerType::U128 => { + let u128_option = option.map(|integer| integer as u128); + let u128_result = + UInt128::alloc(cs.ns(|| name), || u128_option.ok_or(SynthesisError::AssignmentMissing))?; + + Integer::U128(u128_result) + } + }) + } + pub fn from_input>( cs: &mut CS, integer_type: IntegerType, @@ -85,7 +130,7 @@ impl Integer { integer_value: Option, ) -> Result { // Check that the input value is the correct type - let integer_option = match integer_value { + let option = match integer_value { Some(input) => { if let InputValue::Integer(_type_, integer) = input { Some(integer) @@ -96,39 +141,7 @@ impl Integer { None => None, }; - Ok(match integer_type { - IntegerType::U8 => { - let u8_option = integer_option.map(|integer| integer as u8); - let u8_result = UInt8::alloc(cs.ns(|| name), || u8_option.ok_or(SynthesisError::AssignmentMissing))?; - - Integer::U8(u8_result) - } - IntegerType::U16 => { - let u16_option = integer_option.map(|integer| integer as u16); - let u16_result = UInt16::alloc(cs.ns(|| name), || u16_option.ok_or(SynthesisError::AssignmentMissing))?; - - Integer::U16(u16_result) - } - IntegerType::U32 => { - let u32_option = integer_option.map(|integer| integer as u32); - let u32_result = UInt32::alloc(cs.ns(|| name), || u32_option.ok_or(SynthesisError::AssignmentMissing))?; - - Integer::U32(u32_result) - } - IntegerType::U64 => { - let u64_option = integer_option.map(|integer| integer as u64); - let u64_result = UInt64::alloc(cs.ns(|| name), || u64_option.ok_or(SynthesisError::AssignmentMissing))?; - - Integer::U64(u64_result) - } - IntegerType::U128 => { - let u128_option = integer_option.map(|integer| integer as u128); - let u128_result = - UInt128::alloc(cs.ns(|| name), || u128_option.ok_or(SynthesisError::AssignmentMissing))?; - - Integer::U128(u128_result) - } - }) + Self::allocate_type(cs, integer_type, name, option) } pub fn add>( diff --git a/types/src/statements/statement.rs b/types/src/statements/statement.rs index fd34134acd..1ce46adf14 100644 --- a/types/src/statements/statement.rs +++ b/types/src/statements/statement.rs @@ -1,4 +1,4 @@ -use crate::{Assignee, ConditionalStatement, Expression, Identifier, Integer, Variable}; +use crate::{Assignee, ConditionalStatement, Declare, Expression, Identifier, Integer, Variable}; use leo_ast::{ operations::AssignOperation, statements::{ @@ -19,7 +19,7 @@ use std::fmt; #[derive(Clone, PartialEq, Eq)] pub enum Statement { Return(Vec), - Definition(Variable, Expression), + Definition(Declare, Variable, Expression), Assign(Assignee, Expression), MultipleAssign(Vec, Expression), Conditional(ConditionalStatement), @@ -43,6 +43,7 @@ impl<'ast> From> for Statement { impl<'ast> From> for Statement { fn from(statement: DefinitionStatement<'ast>) -> Self { Statement::Definition( + Declare::from(statement.declare), Variable::from(statement.variable), Expression::from(statement.expression), ) @@ -176,7 +177,9 @@ impl fmt::Display for Statement { } write!(f, ")\n") } - Statement::Definition(ref variable, ref expression) => write!(f, "let {} = {};", variable, expression), + Statement::Definition(ref declare, ref variable, ref expression) => { + write!(f, "{} {} = {};", declare, variable, expression) + } Statement::Assign(ref variable, ref statement) => write!(f, "{} = {};", variable, statement), Statement::MultipleAssign(ref assignees, ref function) => { write!(f, "let (")?;