diff --git a/compiler/src/value/field/field_type.rs b/compiler/src/value/field/field_type.rs index 2febb4bbc6..4ca3c1d87c 100644 --- a/compiler/src/value/field/field_type.rs +++ b/compiler/src/value/field/field_type.rs @@ -16,7 +16,7 @@ //! A data type that represents a field value -use crate::errors::FieldError; +use crate::{errors::FieldError, number_string_typing}; use leo_ast::Span; use snarkvm_errors::gadgets::SynthesisError; @@ -54,22 +54,14 @@ impl FieldType { } pub fn constant(string: String, span: &Span) -> Result { - let first_char = string.chars().next().unwrap(); - let new_string: &str; - let value; + let number_info = number_string_typing(&string); - // Check if first symbol is a negative. - // If so strip it, parse rest of string and then negate it. - if first_char == '-' { - new_string = string - .chars() - .next() - .map(|c| &string[c.len_utf8()..]) - .ok_or_else(|| FieldError::invalid_field(string.clone(), span.to_owned()))?; - value = -F::from_str(&new_string).map_err(|_| FieldError::invalid_field(string, span.to_owned()))?; - } else { - value = F::from_str(&string).map_err(|_| FieldError::invalid_field(string, span.to_owned()))?; - } + let value = match number_info { + (number, neg) if neg => { + -F::from_str(&number).map_err(|_| FieldError::invalid_field(string, span.to_owned()))? + } + (number, _) => F::from_str(&number).map_err(|_| FieldError::invalid_field(string, span.to_owned()))?, + }; Ok(FieldType::Constant(value)) } diff --git a/compiler/src/value/field/input.rs b/compiler/src/value/field/input.rs index 7b06967a31..56cb302db3 100644 --- a/compiler/src/value/field/input.rs +++ b/compiler/src/value/field/input.rs @@ -16,7 +16,7 @@ //! Methods to enforce constraints on input field values in a compiled Leo program. -use crate::{errors::FieldError, value::ConstrainedValue, FieldType, GroupType}; +use crate::{errors::FieldError, number_string_typing, value::ConstrainedValue, FieldType, GroupType}; use leo_ast::{InputValue, Span}; use snarkvm_errors::gadgets::SynthesisError; @@ -31,11 +31,26 @@ pub(crate) fn allocate_field>( option: Option, span: &Span, ) -> Result, FieldError> { - FieldType::alloc( - cs.ns(|| format!("`{}: field` {}:{}", name, span.line, span.start)), - || option.ok_or(SynthesisError::AssignmentMissing), - ) - .map_err(|_| FieldError::missing_field(format!("{}: field", name), span.to_owned())) + match option { + Some(string) => { + let number_info = number_string_typing(&string); + + match number_info { + (number, neg) if neg => FieldType::alloc( + cs.ns(|| format!("`{}: field` {}:{}", name, span.line, span.start)), + || Some(number).ok_or(SynthesisError::AssignmentMissing), + ) + .map(|value| value.negate(cs, span)) + .map_err(|_| FieldError::missing_field(format!("{}: field", name), span.to_owned()))?, + (number, _) => FieldType::alloc( + cs.ns(|| format!("`{}: field` {}:{}", name, span.line, span.start)), + || Some(number).ok_or(SynthesisError::AssignmentMissing), + ) + .map_err(|_| FieldError::missing_field(format!("{}: field", name), span.to_owned())), + } + } + None => return Err(FieldError::missing_field(format!("{}: field", name), span.to_owned())), + } } pub(crate) fn field_from_input<'a, F: Field + PrimeField, G: GroupType, CS: ConstraintSystem>( diff --git a/compiler/src/value/group/targets/edwards_bls12.rs b/compiler/src/value/group/targets/edwards_bls12.rs index 309ff3aa50..85c2b391e3 100644 --- a/compiler/src/value/group/targets/edwards_bls12.rs +++ b/compiler/src/value/group/targets/edwards_bls12.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{errors::GroupError, GroupType}; +use crate::{errors::GroupError, number_string_typing, GroupType}; use leo_asg::{GroupCoordinate, GroupValue, Span}; use snarkvm_curves::{ @@ -133,23 +133,6 @@ impl GroupType for EdwardsGroupType { } } -fn number_string_typing(number: &str, span: &Span) -> Result<(String, bool), GroupError> { - let first_char = number.chars().next().unwrap(); - - // Check if first symbol is a negative. - // If so strip it, parse rest of string and then negate it. - if first_char == '-' { - let uint = number - .chars() - .next() - .map(|c| &number[c.len_utf8()..]) - .ok_or_else(|| GroupError::invalid_group(number.to_string(), span.to_owned()))?; - Ok((uint.to_string(), true)) - } else { - Ok((number.to_string(), false)) - } -} - impl EdwardsGroupType { pub fn edwards_affine_from_value(value: &GroupValue, span: &Span) -> Result { match value { @@ -159,7 +142,7 @@ impl EdwardsGroupType { } pub fn edwards_affine_from_single(number: &str, span: &Span) -> Result { - let number_info = number_string_typing(number, &span.clone())?; + let number_info = number_string_typing(number); if number_info.0.eq("0") { Ok(EdwardsAffine::zero()) @@ -189,41 +172,35 @@ impl EdwardsGroupType { match (x, y) { // (x, y) (GroupCoordinate::Number(x_string), GroupCoordinate::Number(y_string)) => Self::edwards_affine_from_pair( - number_string_typing(&x_string, &span.clone())?, - number_string_typing(&y_string, &span.clone())?, + number_string_typing(&x_string), + number_string_typing(&y_string), span, span, span, ), // (x, +) (GroupCoordinate::Number(x_string), GroupCoordinate::SignHigh) => { - Self::edwards_affine_from_x_str(number_string_typing(&x_string, &span.clone())?, span, Some(true), span) + Self::edwards_affine_from_x_str(number_string_typing(&x_string), span, Some(true), span) } // (x, -) - (GroupCoordinate::Number(x_string), GroupCoordinate::SignLow) => Self::edwards_affine_from_x_str( - number_string_typing(&x_string, &span.clone())?, - span, - Some(false), - span, - ), + (GroupCoordinate::Number(x_string), GroupCoordinate::SignLow) => { + Self::edwards_affine_from_x_str(number_string_typing(&x_string), span, Some(false), span) + } // (x, _) (GroupCoordinate::Number(x_string), GroupCoordinate::Inferred) => { - Self::edwards_affine_from_x_str(number_string_typing(&x_string, &span.clone())?, span, None, span) + Self::edwards_affine_from_x_str(number_string_typing(&x_string), span, None, span) } // (+, y) (GroupCoordinate::SignHigh, GroupCoordinate::Number(y_string)) => { - Self::edwards_affine_from_y_str(number_string_typing(&y_string, &span.clone())?, span, Some(true), span) + Self::edwards_affine_from_y_str(number_string_typing(&y_string), span, Some(true), span) } // (-, y) - (GroupCoordinate::SignLow, GroupCoordinate::Number(y_string)) => Self::edwards_affine_from_y_str( - number_string_typing(&y_string, &span.clone())?, - span, - Some(false), - span, - ), + (GroupCoordinate::SignLow, GroupCoordinate::Number(y_string)) => { + Self::edwards_affine_from_y_str(number_string_typing(&y_string), span, Some(false), span) + } // (_, y) (GroupCoordinate::Inferred, GroupCoordinate::Number(y_string)) => { - Self::edwards_affine_from_y_str(number_string_typing(&y_string, &span.clone())?, span, None, span) + Self::edwards_affine_from_y_str(number_string_typing(&y_string), span, None, span) } // Invalid (x, y) => Err(GroupError::invalid_group(format!("({}, {})", x, y), span.clone())), diff --git a/compiler/src/value/mod.rs b/compiler/src/value/mod.rs index 384ab2f797..824e1324d1 100644 --- a/compiler/src/value/mod.rs +++ b/compiler/src/value/mod.rs @@ -32,3 +32,16 @@ pub use self::integer::*; pub mod value; pub use self::value::*; + +pub(crate) fn number_string_typing(number: &str) -> (String, bool) { + let first_char = number.chars().next().unwrap(); + + // Check if first symbol is a negative. + // If so strip it, parse rest of string and then negate it. + if first_char == '-' { + let uint = number.chars().next().map(|c| &number[c.len_utf8()..]).unwrap_or(""); + (uint.to_string(), true) + } else { + (number.to_string(), false) + } +} diff --git a/compiler/tests/input_files/program_input/input/main_field.in b/compiler/tests/input_files/program_input/input/main_field.in index c3512fa1c4..fe9eebbd56 100644 --- a/compiler/tests/input_files/program_input/input/main_field.in +++ b/compiler/tests/input_files/program_input/input/main_field.in @@ -1,2 +1,3 @@ [main] -a: field = 1; \ No newline at end of file +a: field = 1; +b: field = -1; \ No newline at end of file diff --git a/compiler/tests/input_files/program_input/input/main_group.in b/compiler/tests/input_files/program_input/input/main_group.in new file mode 100644 index 0000000000..2a7aecd0ad --- /dev/null +++ b/compiler/tests/input_files/program_input/input/main_group.in @@ -0,0 +1,4 @@ +[main] +a: group = 1group; +b: group = -1group; +c: group = (0, -1)group; \ No newline at end of file diff --git a/compiler/tests/input_files/program_input/main_field.leo b/compiler/tests/input_files/program_input/main_field.leo index 2fbcbd2b90..19bf456ee7 100644 --- a/compiler/tests/input_files/program_input/main_field.leo +++ b/compiler/tests/input_files/program_input/main_field.leo @@ -1,4 +1,5 @@ -function main(a: field) { +function main(a: field, b: field) { // Change to assert when == is implemented for field. console.log("a: {}", a); + console.log("b: {}", b); } \ No newline at end of file diff --git a/compiler/tests/input_files/program_input/main_group.leo b/compiler/tests/input_files/program_input/main_group.leo new file mode 100644 index 0000000000..b7795ac7e7 --- /dev/null +++ b/compiler/tests/input_files/program_input/main_group.leo @@ -0,0 +1,6 @@ +function main(a: group, b: group, c: group) { + // Change to assert when == is implemented for group. + console.log("a: {}", a); + console.log("b: {}", b); + console.log("c: {}", c); +} \ No newline at end of file diff --git a/compiler/tests/input_files/program_input/mod.rs b/compiler/tests/input_files/program_input/mod.rs index fc0ca80527..529a512fdb 100644 --- a/compiler/tests/input_files/program_input/mod.rs +++ b/compiler/tests/input_files/program_input/mod.rs @@ -103,3 +103,13 @@ fn test_field_input() { assert_satisfied(program); } + +#[test] +fn test_group_input() { + let program_string = include_str!("main_group.leo"); + let input_string = include_str!("input/main_group.in"); + + let program = parse_program_with_input(program_string, input_string).unwrap(); + + assert_satisfied(program); +}