From 19bd86b6cf243aa5ba5beda04b941fa2bc6ebc3f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 6 Jan 2023 15:23:36 -0500 Subject: [PATCH 01/25] preliminary strings work, type added to Hir and abi --- crates/nargo/tests/test_data/strings/Nargo.toml | 5 +++++ crates/nargo/tests/test_data/strings/Prover.toml | 1 + crates/nargo/tests/test_data/strings/src/main.nr | 3 +++ crates/noirc_abi/src/lib.rs | 7 +++++-- crates/noirc_evaluator/src/lib.rs | 10 ++++++++++ crates/noirc_evaluator/src/ssa/code_gen.rs | 3 +++ crates/noirc_frontend/src/hir_def/types.rs | 7 ++++++- crates/noirc_frontend/src/monomorphisation/ast.rs | 2 ++ crates/noirc_frontend/src/monomorphisation/mod.rs | 1 + 9 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 crates/nargo/tests/test_data/strings/Nargo.toml create mode 100644 crates/nargo/tests/test_data/strings/Prover.toml create mode 100644 crates/nargo/tests/test_data/strings/src/main.nr diff --git a/crates/nargo/tests/test_data/strings/Nargo.toml b/crates/nargo/tests/test_data/strings/Nargo.toml new file mode 100644 index 00000000000..e0b467ce5da --- /dev/null +++ b/crates/nargo/tests/test_data/strings/Nargo.toml @@ -0,0 +1,5 @@ +[package] +authors = [""] +compiler_version = "0.1" + +[dependencies] \ No newline at end of file diff --git a/crates/nargo/tests/test_data/strings/Prover.toml b/crates/nargo/tests/test_data/strings/Prover.toml new file mode 100644 index 00000000000..e0024f56f2d --- /dev/null +++ b/crates/nargo/tests/test_data/strings/Prover.toml @@ -0,0 +1 @@ +message = "hello world" diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr new file mode 100644 index 00000000000..5e723bd629c --- /dev/null +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -0,0 +1,3 @@ +fn main(message : str) { + constrain message == "hello world"; +} \ No newline at end of file diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index 8f27e00d4a5..c46d4497dab 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -31,6 +31,7 @@ pub enum AbiType { Array { length: u128, typ: Box }, Integer { sign: Sign, width: u32 }, Struct { fields: BTreeMap }, + String { length: u128 }, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -63,6 +64,7 @@ impl AbiType { AbiType::Field | AbiType::Integer { .. } => 1, AbiType::Array { length, typ: _ } => *length as usize, AbiType::Struct { fields, .. } => fields.len(), + AbiType::String { length} => *length as usize, } } @@ -74,6 +76,7 @@ impl AbiType { AbiType::Struct { fields, .. } => { fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count()) } + AbiType::String { length } => *length as u32, } } } @@ -229,7 +232,7 @@ impl Abi { InputValue::Field(field_element) } - AbiType::Array { length, .. } => { + AbiType::Array { length, .. } | AbiType::String { length }=> { let field_elements = &encoded_inputs[index..index + (*length as usize)]; index += *length as usize; @@ -264,7 +267,7 @@ impl Serialize for Abi { for param in &self.parameters { match param.typ { AbiType::Field => map.serialize_entry(¶m.name, "")?, - AbiType::Array { .. } => map.serialize_entry(¶m.name, &vec)?, + AbiType::Array { .. } | AbiType::String { .. } => map.serialize_entry(¶m.name, &vec)?, AbiType::Integer { .. } => map.serialize_entry(¶m.name, "")?, AbiType::Struct { .. } => map.serialize_entry(¶m.name, "")?, }; diff --git a/crates/noirc_evaluator/src/lib.rs b/crates/noirc_evaluator/src/lib.rs index bfe6e78dd60..099aa384258 100644 --- a/crates/noirc_evaluator/src/lib.rs +++ b/crates/noirc_evaluator/src/lib.rs @@ -152,6 +152,11 @@ impl Evaluator { self.generate_struct_witnesses(&mut struct_witnesses, visibility, &new_fields)?; igen.abi_struct(name, Some(def), fields, struct_witnesses); } + AbiType::String { length } => { + let typ = AbiType::Integer { sign: noirc_abi::Sign::Unsigned, width: 8 }; + let witnesses = self.generate_array_witnesses(visibility, length, &typ)?; + igen.abi_array(name, Some(def), &typ, *length, witnesses); + } } Ok(()) } @@ -192,6 +197,11 @@ impl Evaluator { } self.generate_struct_witnesses(struct_witnesses, visibility, &new_fields)? } + AbiType::String { length } => { + let typ = AbiType::Integer { sign: noirc_abi::Sign::Unsigned, width: 8 }; + let internal_str_witnesses = self.generate_array_witnesses(visibility, length, &typ)?; + struct_witnesses.insert(name.clone(), internal_str_witnesses); + } } } Ok(()) diff --git a/crates/noirc_evaluator/src/ssa/code_gen.rs b/crates/noirc_evaluator/src/ssa/code_gen.rs index 2dcb026dd49..f0f34724b4e 100644 --- a/crates/noirc_evaluator/src/ssa/code_gen.rs +++ b/crates/noirc_evaluator/src/ssa/code_gen.rs @@ -158,6 +158,9 @@ impl IRGenerator { noirc_abi::AbiType::Struct { .. } => { unreachable!("array of structs are not supported for now") } + noirc_abi::AbiType::String { .. } => { + unreachable!("array of strings are not supported for now") + } } } diff --git a/crates/noirc_frontend/src/hir_def/types.rs b/crates/noirc_frontend/src/hir_def/types.rs index 42b62dfda6e..6cafea347ea 100644 --- a/crates/noirc_frontend/src/hir_def/types.rs +++ b/crates/noirc_frontend/src/hir_def/types.rs @@ -195,6 +195,7 @@ pub enum Type { Integer(Comptime, Signedness, u32), // u32 = Integer(unsigned, 32) PolymorphicInteger(Comptime, TypeVariable), Bool(Comptime), + String(u32), Unit, Struct(Shared, Vec), Tuple(Vec), @@ -479,6 +480,7 @@ impl std::fmt::Display for Type { write!(f, "({})", elements.join(", ")) } Type::Bool(comptime) => write!(f, "{}bool", comptime), + Type::String(_) => write!(f, "str"), Type::Unit => write!(f, "()"), Type::Error => write!(f, "error"), Type::TypeVariable(id) => write!(f, "{}", id.borrow()), @@ -962,6 +964,7 @@ impl Type { TypeBinding::Unbound(_) => Type::default_int_type(None).as_abi_type(), }, Type::Bool(_) => AbiType::Integer { sign: noirc_abi::Sign::Unsigned, width: 1 }, + Type::String(len) => AbiType::String { length: *len as u128 }, Type::Error => unreachable!(), Type::Unit => unreachable!(), Type::ArrayLength(_) => unreachable!(), @@ -1090,6 +1093,7 @@ impl Type { | Type::Integer(_, _, _) | Type::Bool(_) | Type::ArrayLength(_) + | Type::String(_) | Type::Error | Type::Unit => self.clone(), } @@ -1119,6 +1123,7 @@ impl Type { | Type::Integer(_, _, _) | Type::Bool(_) | Type::ArrayLength(_) + | Type::String(_) | Type::Error | Type::Unit => false, } @@ -1158,7 +1163,7 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - FieldElement(_) | Integer(_, _, _) | Bool(_) | ArrayLength(_) | Unit | Error => { + FieldElement(_) | Integer(_, _, _) | Bool(_) | ArrayLength(_) | String(_) | Unit | Error => { self.clone() } } diff --git a/crates/noirc_frontend/src/monomorphisation/ast.rs b/crates/noirc_frontend/src/monomorphisation/ast.rs index f43a25d5e7b..6c18cc13eef 100644 --- a/crates/noirc_frontend/src/monomorphisation/ast.rs +++ b/crates/noirc_frontend/src/monomorphisation/ast.rs @@ -166,6 +166,7 @@ pub enum Type { Array(/*len:*/ u64, Box), // Array(4, Field) = [Field; 4] Integer(Signedness, /*bits:*/ u32), // u32 = Integer(unsigned, 32) Bool, + String(u32), Unit, Tuple(Vec), } @@ -255,6 +256,7 @@ impl std::fmt::Display for Type { Signedness::Signed => write!(f, "i{}", bits), }, Type::Bool => write!(f, "bool"), + Type::String(_) => write!(f, "str"), Type::Unit => write!(f, "()"), Type::Tuple(elems) => { let elems = vecmap(elems, ToString::to_string); diff --git a/crates/noirc_frontend/src/monomorphisation/mod.rs b/crates/noirc_frontend/src/monomorphisation/mod.rs index 2554ad0bf9a..b2ee2d7979d 100644 --- a/crates/noirc_frontend/src/monomorphisation/mod.rs +++ b/crates/noirc_frontend/src/monomorphisation/mod.rs @@ -416,6 +416,7 @@ impl Monomorphiser { HirType::FieldElement(_) => ast::Type::Field, HirType::Integer(_, sign, bits) => ast::Type::Integer(*sign, *bits), HirType::Bool(_) => ast::Type::Bool, + HirType::String(len) => ast::Type::String(*len), HirType::Unit => ast::Type::Unit, HirType::Array(size, element) => { From 4a2d6dadb1b2c5348c586017059c3258c05c99ce Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 6 Jan 2023 16:53:48 -0500 Subject: [PATCH 02/25] nargo build working for simple str types --- crates/noirc_abi/src/lib.rs | 8 +++++--- crates/noirc_evaluator/src/lib.rs | 3 ++- crates/noirc_frontend/src/ast/mod.rs | 4 ++++ .../src/hir/resolution/resolver.rs | 1 + .../noirc_frontend/src/hir/type_check/expr.rs | 7 ++++--- crates/noirc_frontend/src/hir_def/types.rs | 20 +++++++++++-------- crates/noirc_frontend/src/lexer/token.rs | 9 ++++++++- .../src/monomorphisation/ast.rs | 4 ++-- .../src/monomorphisation/mod.rs | 2 +- crates/noirc_frontend/src/parser/parser.rs | 5 +++++ 10 files changed, 44 insertions(+), 19 deletions(-) diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index c46d4497dab..ef29f1dd7f6 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -64,7 +64,7 @@ impl AbiType { AbiType::Field | AbiType::Integer { .. } => 1, AbiType::Array { length, typ: _ } => *length as usize, AbiType::Struct { fields, .. } => fields.len(), - AbiType::String { length} => *length as usize, + AbiType::String { length } => *length as usize, } } @@ -232,7 +232,7 @@ impl Abi { InputValue::Field(field_element) } - AbiType::Array { length, .. } | AbiType::String { length }=> { + AbiType::Array { length, .. } | AbiType::String { length } => { let field_elements = &encoded_inputs[index..index + (*length as usize)]; index += *length as usize; @@ -267,7 +267,9 @@ impl Serialize for Abi { for param in &self.parameters { match param.typ { AbiType::Field => map.serialize_entry(¶m.name, "")?, - AbiType::Array { .. } | AbiType::String { .. } => map.serialize_entry(¶m.name, &vec)?, + AbiType::Array { .. } | AbiType::String { .. } => { + map.serialize_entry(¶m.name, &vec)? + } AbiType::Integer { .. } => map.serialize_entry(¶m.name, "")?, AbiType::Struct { .. } => map.serialize_entry(¶m.name, "")?, }; diff --git a/crates/noirc_evaluator/src/lib.rs b/crates/noirc_evaluator/src/lib.rs index 099aa384258..dcd296b003c 100644 --- a/crates/noirc_evaluator/src/lib.rs +++ b/crates/noirc_evaluator/src/lib.rs @@ -199,7 +199,8 @@ impl Evaluator { } AbiType::String { length } => { let typ = AbiType::Integer { sign: noirc_abi::Sign::Unsigned, width: 8 }; - let internal_str_witnesses = self.generate_array_witnesses(visibility, length, &typ)?; + let internal_str_witnesses = + self.generate_array_witnesses(visibility, length, &typ)?; struct_witnesses.insert(name.clone(), internal_str_witnesses); } } diff --git a/crates/noirc_frontend/src/ast/mod.rs b/crates/noirc_frontend/src/ast/mod.rs index 5fc3d2717ab..82d75161ab6 100644 --- a/crates/noirc_frontend/src/ast/mod.rs +++ b/crates/noirc_frontend/src/ast/mod.rs @@ -5,6 +5,8 @@ mod function; mod statement; mod structure; +use std::fmt::write; + pub use expression::*; pub use function::*; @@ -24,6 +26,7 @@ pub enum UnresolvedType { Array(Option, Box), // [4]Witness = Array(4, Witness) Integer(Comptime, Signedness, u32), // u32 = Integer(unsigned, 32) Bool(Comptime), + String, Unit, /// A Named UnresolvedType can be a struct type or a type variable @@ -68,6 +71,7 @@ impl std::fmt::Display for UnresolvedType { write!(f, "({})", elements.join(", ")) } Bool(is_const) => write!(f, "{}bool", is_const), + String => write!(f, "str"), Unit => write!(f, "()"), Error => write!(f, "error"), Unspecified => write!(f, "unspecified"), diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index f18231f324a..c51d6b6ad0a 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -298,6 +298,7 @@ impl<'a> Resolver<'a> { } UnresolvedType::Integer(comptime, sign, bits) => Type::Integer(comptime, sign, bits), UnresolvedType::Bool(comptime) => Type::Bool(comptime), + UnresolvedType::String => Type::String, UnresolvedType::Unit => Type::Unit, UnresolvedType::Unspecified => Type::Error, UnresolvedType::Error => Type::Error, diff --git a/crates/noirc_frontend/src/hir/type_check/expr.rs b/crates/noirc_frontend/src/hir/type_check/expr.rs index 4acb2e0ef8a..fef61f2a2b4 100644 --- a/crates/noirc_frontend/src/hir/type_check/expr.rs +++ b/crates/noirc_frontend/src/hir/type_check/expr.rs @@ -70,9 +70,7 @@ pub(crate) fn type_check_expression( Shared::new(TypeBinding::Unbound(id)), ) } - HirLiteral::Str(_) => unimplemented!( - "[Coming Soon] : Currently string literal types have not been implemented" - ), + HirLiteral::Str(_) => Type::String, } } HirExpression::Infix(infix_expr) => { @@ -715,6 +713,9 @@ pub fn comparator_operand_type_rules( } Err(format!("Unsupported types for comparison: {} and {}", name_a, name_b)) } + (String, String) => { + Ok(Bool(Comptime::Yes(None))) + } (lhs, rhs) => Err(format!("Unsupported types for comparison: {} and {}", lhs, rhs)), } } diff --git a/crates/noirc_frontend/src/hir_def/types.rs b/crates/noirc_frontend/src/hir_def/types.rs index 6cafea347ea..1796aafd17c 100644 --- a/crates/noirc_frontend/src/hir_def/types.rs +++ b/crates/noirc_frontend/src/hir_def/types.rs @@ -195,7 +195,7 @@ pub enum Type { Integer(Comptime, Signedness, u32), // u32 = Integer(unsigned, 32) PolymorphicInteger(Comptime, TypeVariable), Bool(Comptime), - String(u32), + String, Unit, Struct(Shared, Vec), Tuple(Vec), @@ -480,7 +480,7 @@ impl std::fmt::Display for Type { write!(f, "({})", elements.join(", ")) } Type::Bool(comptime) => write!(f, "{}bool", comptime), - Type::String(_) => write!(f, "str"), + Type::String => write!(f, "str"), Type::Unit => write!(f, "()"), Type::Error => write!(f, "error"), Type::TypeVariable(id) => write!(f, "{}", id.borrow()), @@ -964,7 +964,7 @@ impl Type { TypeBinding::Unbound(_) => Type::default_int_type(None).as_abi_type(), }, Type::Bool(_) => AbiType::Integer { sign: noirc_abi::Sign::Unsigned, width: 1 }, - Type::String(len) => AbiType::String { length: *len as u128 }, + Type::String => AbiType::String { length: u128::MAX }, // TODO: change str type to have hardcoded size like array or get slices fully working Type::Error => unreachable!(), Type::Unit => unreachable!(), Type::ArrayLength(_) => unreachable!(), @@ -1093,7 +1093,7 @@ impl Type { | Type::Integer(_, _, _) | Type::Bool(_) | Type::ArrayLength(_) - | Type::String(_) + | Type::String | Type::Error | Type::Unit => self.clone(), } @@ -1123,7 +1123,7 @@ impl Type { | Type::Integer(_, _, _) | Type::Bool(_) | Type::ArrayLength(_) - | Type::String(_) + | Type::String | Type::Error | Type::Unit => false, } @@ -1163,9 +1163,13 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - FieldElement(_) | Integer(_, _, _) | Bool(_) | ArrayLength(_) | String(_) | Unit | Error => { - self.clone() - } + FieldElement(_) + | Integer(_, _, _) + | Bool(_) + | ArrayLength(_) + | String + | Unit + | Error => self.clone(), } } } diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index 6b1ea9cb63f..31f8b8097ce 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -1,6 +1,10 @@ use acvm::FieldElement; use noirc_errors::{Position, Span, Spanned}; -use std::{fmt, iter::Map, vec::IntoIter}; +use std::{ + fmt::{self, write}, + iter::Map, + vec::IntoIter, +}; use crate::lexer::errors::LexerErrorKind; @@ -379,6 +383,7 @@ pub enum Keyword { Mod, Mut, Pub, + String, Struct, Use, While, @@ -405,6 +410,7 @@ impl fmt::Display for Keyword { Keyword::Mod => write!(f, "mod"), Keyword::Mut => write!(f, "mut"), Keyword::Pub => write!(f, "pub"), + Keyword::String => write!(f, "str"), Keyword::Struct => write!(f, "struct"), Keyword::Use => write!(f, "use"), Keyword::While => write!(f, "while"), @@ -436,6 +442,7 @@ impl Keyword { "mod" => Keyword::Mod, "mut" => Keyword::Mut, "pub" => Keyword::Pub, + "str" => Keyword::String, "struct" => Keyword::Struct, "use" => Keyword::Use, "while" => Keyword::While, diff --git a/crates/noirc_frontend/src/monomorphisation/ast.rs b/crates/noirc_frontend/src/monomorphisation/ast.rs index 6c18cc13eef..017aad54bd9 100644 --- a/crates/noirc_frontend/src/monomorphisation/ast.rs +++ b/crates/noirc_frontend/src/monomorphisation/ast.rs @@ -166,7 +166,7 @@ pub enum Type { Array(/*len:*/ u64, Box), // Array(4, Field) = [Field; 4] Integer(Signedness, /*bits:*/ u32), // u32 = Integer(unsigned, 32) Bool, - String(u32), + String, Unit, Tuple(Vec), } @@ -256,7 +256,7 @@ impl std::fmt::Display for Type { Signedness::Signed => write!(f, "i{}", bits), }, Type::Bool => write!(f, "bool"), - Type::String(_) => write!(f, "str"), + Type::String => write!(f, "str"), Type::Unit => write!(f, "()"), Type::Tuple(elems) => { let elems = vecmap(elems, ToString::to_string); diff --git a/crates/noirc_frontend/src/monomorphisation/mod.rs b/crates/noirc_frontend/src/monomorphisation/mod.rs index b2ee2d7979d..04c9e005e43 100644 --- a/crates/noirc_frontend/src/monomorphisation/mod.rs +++ b/crates/noirc_frontend/src/monomorphisation/mod.rs @@ -416,7 +416,7 @@ impl Monomorphiser { HirType::FieldElement(_) => ast::Type::Field, HirType::Integer(_, sign, bits) => ast::Type::Integer(*sign, *bits), HirType::Bool(_) => ast::Type::Bool, - HirType::String(len) => ast::Type::String(*len), + HirType::String => ast::Type::String, HirType::Unit => ast::Type::Unit, HirType::Array(size, element) => { diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index 949e0f34253..256b6a4db12 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -448,6 +448,7 @@ where array_type(recursive_type_parser.clone(), expr_parser), tuple_type(recursive_type_parser), bool_type(), + string_type(), )) } @@ -473,6 +474,10 @@ fn bool_type() -> impl NoirParser { maybe_comptime().then_ignore(keyword(Keyword::Bool)).map(UnresolvedType::Bool) } +fn string_type() -> impl NoirParser { + keyword(Keyword::String).map(|_| UnresolvedType::String) +} + fn int_type() -> impl NoirParser { maybe_comptime() .then(filter_map(|span, token: Token| match token { From a627b025e25237245241b0bcd0fc657d9e46148e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 9 Jan 2023 15:23:21 -0500 Subject: [PATCH 03/25] initial strings work. can input to abi and compare string literal. strings currently mock array functionality --- .../nargo/tests/test_data/strings/src/main.nr | 6 +++- crates/noirc_abi/src/input_parser/mod.rs | 5 +++ crates/noirc_abi/src/input_parser/toml.rs | 7 ++-- crates/noirc_abi/src/lib.rs | 12 ++++++- crates/noirc_evaluator/src/ssa/code_gen.rs | 33 ++++++++++++++++++- crates/noirc_frontend/src/ast/mod.rs | 9 ++--- .../src/hir/resolution/resolver.rs | 20 ++++++++++- .../noirc_frontend/src/hir/type_check/expr.rs | 13 ++++++-- crates/noirc_frontend/src/hir_def/types.rs | 33 ++++++++++++------- crates/noirc_frontend/src/lexer/token.rs | 3 ++ .../src/monomorphisation/ast.rs | 4 +-- .../src/monomorphisation/mod.rs | 5 ++- crates/noirc_frontend/src/parser/parser.rs | 19 ++++++++--- 13 files changed, 137 insertions(+), 32 deletions(-) diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index 5e723bd629c..2d115b75340 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -1,3 +1,7 @@ -fn main(message : str) { +fn main(message : [char; 11]) { + let bad_message = "helld world"; + constrain message == "hello world"; + + constrain message != bad_message; } \ No newline at end of file diff --git a/crates/noirc_abi/src/input_parser/mod.rs b/crates/noirc_abi/src/input_parser/mod.rs index 46c56725245..6f1379a2b10 100644 --- a/crates/noirc_abi/src/input_parser/mod.rs +++ b/crates/noirc_abi/src/input_parser/mod.rs @@ -14,6 +14,7 @@ use crate::AbiType; pub enum InputValue { Field(FieldElement), Vec(Vec), + String(String), Struct(BTreeMap), Undefined, } @@ -38,6 +39,10 @@ impl InputValue { .all(|field_element| Self::Field(*field_element).matches_abi(typ)) } + (InputValue::String(string), AbiType::String { length }) => { + string.len() == *length as usize + } + (InputValue::Struct(map), AbiType::Struct { fields, .. }) => { if map.len() != fields.len() { return false; diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index d9357995f88..7b44aa2717b 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -55,9 +55,11 @@ fn toml_map_to_field( for (parameter, value) in toml_map { let mapped_value = match value { TomlTypes::String(string) => { - let new_value = parse_str(&string)?; + let new_value = parse_str(&string); - if let Some(field_element) = new_value { + if new_value.is_err() { + InputValue::String(string) + } else if let Some(field_element) = new_value.unwrap() { InputValue::Field(field_element) } else { InputValue::Undefined @@ -116,6 +118,7 @@ fn toml_remap(map: &BTreeMap) -> BTreeMap let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect(); TomlTypes::ArrayString(array) } + InputValue::String(s) => TomlTypes::String(s.clone()), InputValue::Struct(map) => { let map_with_toml_types = toml_remap(map); TomlTypes::Table(map_with_toml_types) diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index ef29f1dd7f6..bcef82c6f32 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -18,7 +18,7 @@ pub const MAIN_RETURN_NAME: &str = "return"; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] /// Types that are allowed in the (main function in binary) /// -/// we use this separation so that we can have types like Strings +/// we use this separation so that we can have types like St∫rings /// without needing to introduce this in the Noir types /// /// NOTE: If Strings are introduced as a native type, the translation will @@ -180,6 +180,15 @@ impl Abi { match value { InputValue::Field(elem) => encoded_value.push(elem), InputValue::Vec(vec_elem) => encoded_value.extend(vec_elem), + InputValue::String(string) => { + let str_as_fields = string + .clone() + .into_bytes() + .into_iter() + .map(|byte| FieldElement::from_be_bytes_reduce(&[byte])) + .collect::>(); + encoded_value.extend(str_as_fields) + } InputValue::Struct(object) => { for (field_name, value) in object { let new_name = format!("{}.{}", param_name, field_name); @@ -233,6 +242,7 @@ impl Abi { InputValue::Field(field_element) } AbiType::Array { length, .. } | AbiType::String { length } => { + // TODO need to separate String decoding from arrays let field_elements = &encoded_inputs[index..index + (*length as usize)]; index += *length as usize; diff --git a/crates/noirc_evaluator/src/ssa/code_gen.rs b/crates/noirc_evaluator/src/ssa/code_gen.rs index f0f34724b4e..5a74051753e 100644 --- a/crates/noirc_evaluator/src/ssa/code_gen.rs +++ b/crates/noirc_evaluator/src/ssa/code_gen.rs @@ -518,6 +518,29 @@ impl IRGenerator { } Ok(Value::Single(new_var)) } + Expression::Literal(Literal::Str(string)) => { + let string_as_integers = string + .clone() + .into_bytes() + .into_iter() + .map(|byte| { + let f = FieldElement::from_be_bytes_reduce(&[byte]); + Expression::Literal(Literal::Integer( + f, + Type::Integer(noirc_frontend::Signedness::Unsigned, 8), + )) + }) + .collect::>(); + + let string_arr_literal = ArrayLiteral { + contents: string_as_integers, + element_type: Type::Integer(noirc_frontend::Signedness::Unsigned, 8), + }; + + let new_value = self + .codegen_expression(&Expression::Literal(Literal::Array(string_arr_literal)))?; + Ok(new_value) + } Expression::Ident(ident) => { Ok(self.codegen_identifier(ident)) //n.b this creates a new variable if it does not exist, may be we should delegate this to explicit statements (let) - TODO @@ -630,7 +653,15 @@ impl IRGenerator { } } Literal::Integer(f, typ) => self.context.get_or_create_const(*f, typ.into()), - _ => todo!(), //todo: add support for Array(ArrayLiteral), Str(String) + // Literal::Str(string) => { + // let element_type = ObjectType::Unsigned(8); + // let str_bytes = string.as_bytes(); + // for byte in str_bytes { + // let f = FieldElement::from_be_bytes_reduce([byte]); + // self.context.get_or_create_const(f, element_type) + // } + // } + _ => todo!(), //todo: ad d support for Array(ArrayLiteral), Str(String) } } diff --git a/crates/noirc_frontend/src/ast/mod.rs b/crates/noirc_frontend/src/ast/mod.rs index 82d75161ab6..73c2fdb9603 100644 --- a/crates/noirc_frontend/src/ast/mod.rs +++ b/crates/noirc_frontend/src/ast/mod.rs @@ -5,8 +5,6 @@ mod function; mod statement; mod structure; -use std::fmt::write; - pub use expression::*; pub use function::*; @@ -26,7 +24,7 @@ pub enum UnresolvedType { Array(Option, Box), // [4]Witness = Array(4, Witness) Integer(Comptime, Signedness, u32), // u32 = Integer(unsigned, 32) Bool(Comptime), - String, + String(Option), Unit, /// A Named UnresolvedType can be a struct type or a type variable @@ -71,7 +69,10 @@ impl std::fmt::Display for UnresolvedType { write!(f, "({})", elements.join(", ")) } Bool(is_const) => write!(f, "{}bool", is_const), - String => write!(f, "str"), + String(len) => match len { + None => write!(f, "[char]"), + Some(len) => write!(f, "[char; {}]", len), + }, Unit => write!(f, "()"), Error => write!(f, "error"), Unspecified => write!(f, "unspecified"), diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index c51d6b6ad0a..a116f380ef5 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -298,7 +298,25 @@ impl<'a> Resolver<'a> { } UnresolvedType::Integer(comptime, sign, bits) => Type::Integer(comptime, sign, bits), UnresolvedType::Bool(comptime) => Type::Bool(comptime), - UnresolvedType::String => Type::String, + UnresolvedType::String(size) => { + let resolved_size = match &size { + None => { + let id = self.interner.next_type_variable_id(); + let typevar = Shared::new(TypeBinding::Unbound(id)); + new_variables.push((id, typevar.clone())); + + // 'Named'Generic is a bit of a misnomer here, we want a type variable that + // wont be bound over but this one has no name since we do not currently + // require users to explicitly be generic over array lengths. + Type::NamedGeneric(typevar, Rc::new("".into())) + } + Some(expr) => { + let len = self.eval_array_length(expr); + Type::ArrayLength(len) + } + }; + Type::String(Box::new(resolved_size)) + } UnresolvedType::Unit => Type::Unit, UnresolvedType::Unspecified => Type::Error, UnresolvedType::Error => Type::Error, diff --git a/crates/noirc_frontend/src/hir/type_check/expr.rs b/crates/noirc_frontend/src/hir/type_check/expr.rs index fef61f2a2b4..8e71aa243fa 100644 --- a/crates/noirc_frontend/src/hir/type_check/expr.rs +++ b/crates/noirc_frontend/src/hir/type_check/expr.rs @@ -70,7 +70,9 @@ pub(crate) fn type_check_expression( Shared::new(TypeBinding::Unbound(id)), ) } - HirLiteral::Str(_) => Type::String, + HirLiteral::Str(string) => { + Type::String(Box::new(Type::ArrayLength(string.len() as u64))) + } } } HirExpression::Infix(infix_expr) => { @@ -713,8 +715,13 @@ pub fn comparator_operand_type_rules( } Err(format!("Unsupported types for comparison: {} and {}", name_a, name_b)) } - (String, String) => { - Ok(Bool(Comptime::Yes(None))) + (String(x_size), String(y_size)) => { + if x_size != y_size { + return Err(format!("Can only compare strings of the same length. Here LHS is of length {}, and RHS is {} ", + x_size, y_size)); + } + + Ok(Bool(Comptime::No(Some(op.location.span)))) } (lhs, rhs) => Err(format!("Unsupported types for comparison: {} and {}", lhs, rhs)), } diff --git a/crates/noirc_frontend/src/hir_def/types.rs b/crates/noirc_frontend/src/hir_def/types.rs index 1796aafd17c..3bf896d99f1 100644 --- a/crates/noirc_frontend/src/hir_def/types.rs +++ b/crates/noirc_frontend/src/hir_def/types.rs @@ -195,7 +195,7 @@ pub enum Type { Integer(Comptime, Signedness, u32), // u32 = Integer(unsigned, 32) PolymorphicInteger(Comptime, TypeVariable), Bool(Comptime), - String, + String(Box), Unit, Struct(Shared, Vec), Tuple(Vec), @@ -480,7 +480,10 @@ impl std::fmt::Display for Type { write!(f, "({})", elements.join(", ")) } Type::Bool(comptime) => write!(f, "{}bool", comptime), - Type::String => write!(f, "str"), + Type::String(len) => match len.array_length() { + Some(len) => write!(f, "[char; {}]", len), + None => write!(f, "[char]"), + }, Type::Unit => write!(f, "()"), Type::Error => write!(f, "error"), Type::TypeVariable(id) => write!(f, "{}", id.borrow()), @@ -964,7 +967,13 @@ impl Type { TypeBinding::Unbound(_) => Type::default_int_type(None).as_abi_type(), }, Type::Bool(_) => AbiType::Integer { sign: noirc_abi::Sign::Unsigned, width: 1 }, - Type::String => AbiType::String { length: u128::MAX }, // TODO: change str type to have hardcoded size like array or get slices fully working + Type::String(size) => { + let size = size + .array_length() + .expect("Cannot have variable sized strings as a parameter to main"); + AbiType::String { length: size as u128 } + // AbiType::String { length: u8::MAX as u128 }, // TODO: change str type to have hardcoded size like array or get slices fully working + } Type::Error => unreachable!(), Type::Unit => unreachable!(), Type::ArrayLength(_) => unreachable!(), @@ -1060,6 +1069,10 @@ impl Type { let element = Box::new(element.substitute(type_bindings)); Type::Array(size, element) } + Type::String(size) => { + let size = Box::new(size.substitute(type_bindings)); + Type::String(size) + } Type::PolymorphicInteger(_, binding) | Type::NamedGeneric(binding, _) | Type::TypeVariable(binding) => substitute_binding(binding), @@ -1093,7 +1106,6 @@ impl Type { | Type::Integer(_, _, _) | Type::Bool(_) | Type::ArrayLength(_) - | Type::String | Type::Error | Type::Unit => self.clone(), } @@ -1104,6 +1116,7 @@ impl Type { fn occurs(&self, target_id: TypeVariableId) -> bool { match self { Type::Array(len, elem) => len.occurs(target_id) || elem.occurs(target_id), + Type::String(len) => len.occurs(target_id), Type::Struct(_, generic_args) => generic_args.iter().any(|arg| arg.occurs(target_id)), Type::Tuple(fields) => fields.iter().any(|field| field.occurs(target_id)), Type::PolymorphicInteger(_, binding) @@ -1123,7 +1136,6 @@ impl Type { | Type::Integer(_, _, _) | Type::Bool(_) | Type::ArrayLength(_) - | Type::String | Type::Error | Type::Unit => false, } @@ -1141,6 +1153,7 @@ impl Type { Array(size, elem) => { Array(Box::new(size.follow_bindings()), Box::new(elem.follow_bindings())) } + String(size) => String(Box::new(size.follow_bindings())), Struct(def, args) => { let args = vecmap(args, |arg| arg.follow_bindings()); Struct(def.clone(), args) @@ -1163,13 +1176,9 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - FieldElement(_) - | Integer(_, _, _) - | Bool(_) - | ArrayLength(_) - | String - | Unit - | Error => self.clone(), + FieldElement(_) | Integer(_, _, _) | Bool(_) | ArrayLength(_) | Unit | Error => { + self.clone() + } } } } diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index 31f8b8097ce..c598aceea6e 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -367,6 +367,7 @@ impl AsRef for Attribute { pub enum Keyword { As, Bool, + Char, Comptime, Constrain, Crate, @@ -394,6 +395,7 @@ impl fmt::Display for Keyword { match *self { Keyword::As => write!(f, "as"), Keyword::Bool => write!(f, "bool"), + Keyword::Char => write!(f, "char"), Keyword::Comptime => write!(f, "comptime"), Keyword::Constrain => write!(f, "constrain"), Keyword::Crate => write!(f, "crate"), @@ -426,6 +428,7 @@ impl Keyword { let keyword = match word { "as" => Keyword::As, "bool" => Keyword::Bool, + "char" => Keyword::Char, "comptime" => Keyword::Comptime, "constrain" => Keyword::Constrain, "crate" => Keyword::Crate, diff --git a/crates/noirc_frontend/src/monomorphisation/ast.rs b/crates/noirc_frontend/src/monomorphisation/ast.rs index 017aad54bd9..7ba58838ca2 100644 --- a/crates/noirc_frontend/src/monomorphisation/ast.rs +++ b/crates/noirc_frontend/src/monomorphisation/ast.rs @@ -166,7 +166,7 @@ pub enum Type { Array(/*len:*/ u64, Box), // Array(4, Field) = [Field; 4] Integer(Signedness, /*bits:*/ u32), // u32 = Integer(unsigned, 32) Bool, - String, + String(/*len:*/ u64), // String(4) = [char; 4] Unit, Tuple(Vec), } @@ -256,7 +256,7 @@ impl std::fmt::Display for Type { Signedness::Signed => write!(f, "i{}", bits), }, Type::Bool => write!(f, "bool"), - Type::String => write!(f, "str"), + Type::String(len) => write!(f, "[char; {}]", len), Type::Unit => write!(f, "()"), Type::Tuple(elems) => { let elems = vecmap(elems, ToString::to_string); diff --git a/crates/noirc_frontend/src/monomorphisation/mod.rs b/crates/noirc_frontend/src/monomorphisation/mod.rs index 04c9e005e43..bb6fe81d074 100644 --- a/crates/noirc_frontend/src/monomorphisation/mod.rs +++ b/crates/noirc_frontend/src/monomorphisation/mod.rs @@ -416,7 +416,10 @@ impl Monomorphiser { HirType::FieldElement(_) => ast::Type::Field, HirType::Integer(_, sign, bits) => ast::Type::Integer(*sign, *bits), HirType::Bool(_) => ast::Type::Bool, - HirType::String => ast::Type::String, + HirType::String(size) => { + let size = size.array_length().unwrap_or(0); + ast::Type::String(size) + } HirType::Unit => ast::Type::Unit, HirType::Array(size, element) => { diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index 256b6a4db12..635216fd2cd 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -445,10 +445,10 @@ where field_type(), int_type(), named_type(recursive_type_parser.clone()), - array_type(recursive_type_parser.clone(), expr_parser), + array_type(recursive_type_parser.clone(), expr_parser.clone()), tuple_type(recursive_type_parser), bool_type(), - string_type(), + string_type(expr_parser), )) } @@ -474,8 +474,19 @@ fn bool_type() -> impl NoirParser { maybe_comptime().then_ignore(keyword(Keyword::Bool)).map(UnresolvedType::Bool) } -fn string_type() -> impl NoirParser { - keyword(Keyword::String).map(|_| UnresolvedType::String) +// fn string_type() -> impl NoirParser { +// keyword(Keyword::String).map(|_| UnresolvedType::String) +// } + +fn string_type

(expr_parser: P) -> impl NoirParser +where + P: NoirParser, +{ + just(Token::LeftBracket) + .ignore_then(keyword(Keyword::Char)) + .ignore_then(just(Token::Semicolon).ignore_then(expr_parser).or_not()) + .then_ignore(just(Token::RightBracket)) + .map(|size| UnresolvedType::String(size)) } fn int_type() -> impl NoirParser { From c6f40b5f30d06d0311906b43859ed13db704bf3f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 9 Jan 2023 15:47:09 -0500 Subject: [PATCH 04/25] little cleanup and test addition --- crates/nargo/tests/test_data/strings/Prover.toml | 2 +- crates/nargo/tests/test_data/strings/src/main.nr | 3 ++- crates/noirc_abi/src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/nargo/tests/test_data/strings/Prover.toml b/crates/nargo/tests/test_data/strings/Prover.toml index e0024f56f2d..a7fd24f8107 100644 --- a/crates/nargo/tests/test_data/strings/Prover.toml +++ b/crates/nargo/tests/test_data/strings/Prover.toml @@ -1 +1 @@ -message = "hello world" +message = "hello world" \ No newline at end of file diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index 2d115b75340..0b3ca118f63 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -1,7 +1,8 @@ fn main(message : [char; 11]) { - let bad_message = "helld world"; + let mut bad_message = "hello world"; constrain message == "hello world"; + bad_message = "helld world"; constrain message != bad_message; } \ No newline at end of file diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index bcef82c6f32..6b9998cc194 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -18,7 +18,7 @@ pub const MAIN_RETURN_NAME: &str = "return"; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] /// Types that are allowed in the (main function in binary) /// -/// we use this separation so that we can have types like St∫rings +/// we use this separation so that we can have types like Strings /// without needing to introduce this in the Noir types /// /// NOTE: If Strings are introduced as a native type, the translation will From b4f9e5c8d63b1283333987917be9a7f75c1dcb1e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 9 Jan 2023 16:21:54 -0500 Subject: [PATCH 05/25] cargo clippy and fixed decoding of public string values in toml --- crates/nargo/src/cli/prove_cmd.rs | 1 + .../nargo/tests/test_data/strings/src/main.nr | 2 +- crates/noirc_abi/src/input_parser/toml.rs | 2 +- crates/noirc_abi/src/lib.rs | 26 ++++++--- crates/noirc_evaluator/src/ssa/code_gen.rs | 10 +--- .../src/hir/resolution/resolver.rs | 57 ++++++++----------- crates/noirc_frontend/src/hir_def/types.rs | 1 - crates/noirc_frontend/src/lexer/token.rs | 9 +-- crates/noirc_frontend/src/parser/parser.rs | 6 +- 9 files changed, 50 insertions(+), 64 deletions(-) diff --git a/crates/nargo/src/cli/prove_cmd.rs b/crates/nargo/src/cli/prove_cmd.rs index d076e464b97..bc501eecb5b 100644 --- a/crates/nargo/src/cli/prove_cmd.rs +++ b/crates/nargo/src/cli/prove_cmd.rs @@ -74,6 +74,7 @@ pub fn parse_and_solve_witness>( .collect(); let public_abi = compiled_program.abi.as_ref().unwrap().clone().public_abi(); + dbg!(encoded_public_inputs.clone()); let public_inputs = public_abi.decode(&encoded_public_inputs)?; // Write public inputs into Verifier.toml diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index 0b3ca118f63..14150c9cdd7 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -1,4 +1,4 @@ -fn main(message : [char; 11]) { +fn main(message : pub [char; 11]) { let mut bad_message = "hello world"; constrain message == "hello world"; diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index 7b44aa2717b..3d8736cbb32 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -59,7 +59,7 @@ fn toml_map_to_field( if new_value.is_err() { InputValue::String(string) - } else if let Some(field_element) = new_value.unwrap() { + } else if let Ok(Some(field_element)) = new_value { InputValue::Field(field_element) } else { InputValue::Undefined diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index 6b9998cc194..4cd024ea056 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -1,4 +1,4 @@ -use std::{collections::BTreeMap, convert::TryInto}; +use std::{collections::BTreeMap, convert::TryInto, str}; use acvm::FieldElement; use errors::AbiError; @@ -182,7 +182,6 @@ impl Abi { InputValue::Vec(vec_elem) => encoded_value.extend(vec_elem), InputValue::String(string) => { let str_as_fields = string - .clone() .into_bytes() .into_iter() .map(|byte| FieldElement::from_be_bytes_reduce(&[byte])) @@ -241,13 +240,27 @@ impl Abi { InputValue::Field(field_element) } - AbiType::Array { length, .. } | AbiType::String { length } => { - // TODO need to separate String decoding from arrays + AbiType::Array { length, .. } => { let field_elements = &encoded_inputs[index..index + (*length as usize)]; index += *length as usize; InputValue::Vec(field_elements.to_vec()) } + AbiType::String { length } => { + let field_elements = &encoded_inputs[index..index + (*length as usize)]; + + let string_as_slice = field_elements + .iter() + .map(|e| { + *e.to_bytes().last().unwrap() // A character in a string is represented by a u8, thus we just want the last byte of the element + }) + .collect::>(); + + let final_string = str::from_utf8(&string_as_slice).unwrap(); + + index += *length as usize; + InputValue::String(final_string.to_owned()) + } AbiType::Struct { fields, .. } => { let mut struct_map = BTreeMap::new(); @@ -277,9 +290,8 @@ impl Serialize for Abi { for param in &self.parameters { match param.typ { AbiType::Field => map.serialize_entry(¶m.name, "")?, - AbiType::Array { .. } | AbiType::String { .. } => { - map.serialize_entry(¶m.name, &vec)? - } + AbiType::Array { .. } => map.serialize_entry(¶m.name, &vec)?, + AbiType::String { .. } => map.serialize_entry(¶m.name, "")?, AbiType::Integer { .. } => map.serialize_entry(¶m.name, "")?, AbiType::Struct { .. } => map.serialize_entry(¶m.name, "")?, }; diff --git a/crates/noirc_evaluator/src/ssa/code_gen.rs b/crates/noirc_evaluator/src/ssa/code_gen.rs index 5a74051753e..4245c33d446 100644 --- a/crates/noirc_evaluator/src/ssa/code_gen.rs +++ b/crates/noirc_evaluator/src/ssa/code_gen.rs @@ -653,15 +653,7 @@ impl IRGenerator { } } Literal::Integer(f, typ) => self.context.get_or_create_const(*f, typ.into()), - // Literal::Str(string) => { - // let element_type = ObjectType::Unsigned(8); - // let str_bytes = string.as_bytes(); - // for byte in str_bytes { - // let f = FieldElement::from_be_bytes_reduce([byte]); - // self.context.get_or_create_const(f, element_type) - // } - // } - _ => todo!(), //todo: ad d support for Array(ArrayLiteral), Str(String) + _ => todo!(), //todo: add support for Array(ArrayLiteral), Str(String) } } diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index a116f380ef5..00f7c27adf2 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -277,44 +277,14 @@ impl<'a> Resolver<'a> { match typ { UnresolvedType::FieldElement(comptime) => Type::FieldElement(comptime), UnresolvedType::Array(size, elem) => { - let resolved_size = match &size { - None => { - let id = self.interner.next_type_variable_id(); - let typevar = Shared::new(TypeBinding::Unbound(id)); - new_variables.push((id, typevar.clone())); - - // 'Named'Generic is a bit of a misnomer here, we want a type variable that - // wont be bound over but this one has no name since we do not currently - // require users to explicitly be generic over array lengths. - Type::NamedGeneric(typevar, Rc::new("".into())) - } - Some(expr) => { - let len = self.eval_array_length(expr); - Type::ArrayLength(len) - } - }; + let resolved_size = self.resolve_array_size(size, new_variables); let elem = Box::new(self.resolve_type_inner(*elem, new_variables)); Type::Array(Box::new(resolved_size), elem) } UnresolvedType::Integer(comptime, sign, bits) => Type::Integer(comptime, sign, bits), UnresolvedType::Bool(comptime) => Type::Bool(comptime), UnresolvedType::String(size) => { - let resolved_size = match &size { - None => { - let id = self.interner.next_type_variable_id(); - let typevar = Shared::new(TypeBinding::Unbound(id)); - new_variables.push((id, typevar.clone())); - - // 'Named'Generic is a bit of a misnomer here, we want a type variable that - // wont be bound over but this one has no name since we do not currently - // require users to explicitly be generic over array lengths. - Type::NamedGeneric(typevar, Rc::new("".into())) - } - Some(expr) => { - let len = self.eval_array_length(expr); - Type::ArrayLength(len) - } - }; + let resolved_size = self.resolve_array_size(size, new_variables); Type::String(Box::new(resolved_size)) } UnresolvedType::Unit => Type::Unit, @@ -344,6 +314,29 @@ impl<'a> Resolver<'a> { } } + fn resolve_array_size( + &mut self, + size: Option, + new_variables: &mut Generics, + ) -> Type { + match &size { + None => { + let id = self.interner.next_type_variable_id(); + let typevar = Shared::new(TypeBinding::Unbound(id)); + new_variables.push((id, typevar.clone())); + + // 'Named'Generic is a bit of a misnomer here, we want a type variable that + // wont be bound over but this one has no name since we do not currently + // require users to explicitly be generic over array lengths. + Type::NamedGeneric(typevar, Rc::new("".into())) + } + Some(expr) => { + let len = self.eval_array_length(expr); + Type::ArrayLength(len) + } + } + } + fn get_ident_from_path(&mut self, path: Path) -> HirIdent { if path.segments.len() == 1 { match path.as_ident() { diff --git a/crates/noirc_frontend/src/hir_def/types.rs b/crates/noirc_frontend/src/hir_def/types.rs index 3bf896d99f1..95f9314736f 100644 --- a/crates/noirc_frontend/src/hir_def/types.rs +++ b/crates/noirc_frontend/src/hir_def/types.rs @@ -972,7 +972,6 @@ impl Type { .array_length() .expect("Cannot have variable sized strings as a parameter to main"); AbiType::String { length: size as u128 } - // AbiType::String { length: u8::MAX as u128 }, // TODO: change str type to have hardcoded size like array or get slices fully working } Type::Error => unreachable!(), Type::Unit => unreachable!(), diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index c598aceea6e..8bd40645950 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -1,10 +1,6 @@ use acvm::FieldElement; use noirc_errors::{Position, Span, Spanned}; -use std::{ - fmt::{self, write}, - iter::Map, - vec::IntoIter, -}; +use std::{fmt, iter::Map, vec::IntoIter}; use crate::lexer::errors::LexerErrorKind; @@ -384,7 +380,6 @@ pub enum Keyword { Mod, Mut, Pub, - String, Struct, Use, While, @@ -412,7 +407,6 @@ impl fmt::Display for Keyword { Keyword::Mod => write!(f, "mod"), Keyword::Mut => write!(f, "mut"), Keyword::Pub => write!(f, "pub"), - Keyword::String => write!(f, "str"), Keyword::Struct => write!(f, "struct"), Keyword::Use => write!(f, "use"), Keyword::While => write!(f, "while"), @@ -445,7 +439,6 @@ impl Keyword { "mod" => Keyword::Mod, "mut" => Keyword::Mut, "pub" => Keyword::Pub, - "str" => Keyword::String, "struct" => Keyword::Struct, "use" => Keyword::Use, "while" => Keyword::While, diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index 635216fd2cd..18b4c97e8e3 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -474,10 +474,6 @@ fn bool_type() -> impl NoirParser { maybe_comptime().then_ignore(keyword(Keyword::Bool)).map(UnresolvedType::Bool) } -// fn string_type() -> impl NoirParser { -// keyword(Keyword::String).map(|_| UnresolvedType::String) -// } - fn string_type

(expr_parser: P) -> impl NoirParser where P: NoirParser, @@ -486,7 +482,7 @@ where .ignore_then(keyword(Keyword::Char)) .ignore_then(just(Token::Semicolon).ignore_then(expr_parser).or_not()) .then_ignore(just(Token::RightBracket)) - .map(|size| UnresolvedType::String(size)) + .map(UnresolvedType::String) } fn int_type() -> impl NoirParser { From a1eaba37308ab38b097c49b3d33d86c6885c97d1 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 10 Jan 2023 23:13:22 -0500 Subject: [PATCH 06/25] some pr comments, moving to use str keyword --- crates/nargo/src/cli/prove_cmd.rs | 1 - crates/nargo/tests/test_data/strings/src/main.nr | 2 +- crates/noirc_frontend/src/lexer/token.rs | 3 +++ crates/noirc_frontend/src/parser/parser.rs | 8 ++++---- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/nargo/src/cli/prove_cmd.rs b/crates/nargo/src/cli/prove_cmd.rs index bc501eecb5b..d076e464b97 100644 --- a/crates/nargo/src/cli/prove_cmd.rs +++ b/crates/nargo/src/cli/prove_cmd.rs @@ -74,7 +74,6 @@ pub fn parse_and_solve_witness>( .collect(); let public_abi = compiled_program.abi.as_ref().unwrap().clone().public_abi(); - dbg!(encoded_public_inputs.clone()); let public_inputs = public_abi.decode(&encoded_public_inputs)?; // Write public inputs into Verifier.toml diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index 14150c9cdd7..36d2a702ce3 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -1,4 +1,4 @@ -fn main(message : pub [char; 11]) { +fn main(message : pub str[11]) { let mut bad_message = "hello world"; constrain message == "hello world"; diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index 8bd40645950..10ae95001bb 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -380,6 +380,7 @@ pub enum Keyword { Mod, Mut, Pub, + String, Struct, Use, While, @@ -407,6 +408,7 @@ impl fmt::Display for Keyword { Keyword::Mod => write!(f, "mod"), Keyword::Mut => write!(f, "mut"), Keyword::Pub => write!(f, "pub"), + Keyword::String => write!(f, "str"), Keyword::Struct => write!(f, "struct"), Keyword::Use => write!(f, "use"), Keyword::While => write!(f, "while"), @@ -439,6 +441,7 @@ impl Keyword { "mod" => Keyword::Mod, "mut" => Keyword::Mut, "pub" => Keyword::Pub, + "str" => Keyword::String, "struct" => Keyword::Struct, "use" => Keyword::Use, "while" => Keyword::While, diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index 18b4c97e8e3..9a235e55ea1 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -478,10 +478,10 @@ fn string_type

(expr_parser: P) -> impl NoirParser where P: NoirParser, { - just(Token::LeftBracket) - .ignore_then(keyword(Keyword::Char)) - .ignore_then(just(Token::Semicolon).ignore_then(expr_parser).or_not()) - .then_ignore(just(Token::RightBracket)) + keyword(Keyword::String) + .ignore_then( + expr_parser.delimited_by(just(Token::LeftBracket), just(Token::RightBracket)).or_not(), + ) .map(UnresolvedType::String) } From 8aeab6a9025bf68a5f5fb61f1cd9142a361cc8f7 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 10 Jan 2023 23:21:50 -0500 Subject: [PATCH 07/25] clarifying comment for string toml type to input value --- crates/noirc_abi/src/input_parser/toml.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index 3d8736cbb32..c34788ff45b 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -55,9 +55,12 @@ fn toml_map_to_field( for (parameter, value) in toml_map { let mapped_value = match value { TomlTypes::String(string) => { - let new_value = parse_str(&string); + let new_value = try_str_to_field(&string); - if new_value.is_err() { + // We accept UTF-8 strings as input as well as hex strings representing field elements. + // We still want developers to be able to pass in hex strings for FieldElement inputs. + // Thus, we first try to parse the string into a field element, and if that fails we assume that the input is meant to be a plain string + if new_value.is_err() { InputValue::String(string) } else if let Ok(Some(field_element)) = new_value { InputValue::Field(field_element) @@ -86,7 +89,7 @@ fn toml_map_to_field( TomlTypes::ArrayString(arr_str) => { let array_elements: Vec<_> = arr_str .into_iter() - .map(|elem_str| parse_str(&elem_str).unwrap().unwrap()) + .map(|elem_str| try_str_to_field(&elem_str).unwrap().unwrap()) .collect(); InputValue::Vec(array_elements) @@ -148,7 +151,7 @@ enum TomlTypes { Table(BTreeMap), } -fn parse_str(value: &str) -> Result, InputParserError> { +fn try_str_to_field(value: &str) -> Result, InputParserError> { if value.is_empty() { Ok(None) } else if value.starts_with("0x") { From 87803111caeef51852f875bcebd7b7f03da80109 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 10 Jan 2023 23:51:56 -0500 Subject: [PATCH 08/25] pr comments --- crates/noirc_abi/src/input_parser/toml.rs | 4 ++-- crates/noirc_abi/src/lib.rs | 8 +++++--- crates/noirc_evaluator/src/ssa/code_gen.rs | 3 +-- .../noirc_frontend/src/hir/type_check/expr.rs | 20 +++++++++++-------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index c34788ff45b..e67caeb7f55 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -58,9 +58,9 @@ fn toml_map_to_field( let new_value = try_str_to_field(&string); // We accept UTF-8 strings as input as well as hex strings representing field elements. - // We still want developers to be able to pass in hex strings for FieldElement inputs. + // We still want developers to be able to pass in hex strings for FieldElement inputs. // Thus, we first try to parse the string into a field element, and if that fails we assume that the input is meant to be a plain string - if new_value.is_err() { + if new_value.is_err() { InputValue::String(string) } else if let Ok(Some(field_element)) = new_value { InputValue::Field(field_element) diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index 4cd024ea056..24df52290fe 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -184,8 +184,7 @@ impl Abi { let str_as_fields = string .into_bytes() .into_iter() - .map(|byte| FieldElement::from_be_bytes_reduce(&[byte])) - .collect::>(); + .map(|byte| FieldElement::from_be_bytes_reduce(&[byte])); encoded_value.extend(str_as_fields) } InputValue::Struct(object) => { @@ -252,7 +251,10 @@ impl Abi { let string_as_slice = field_elements .iter() .map(|e| { - *e.to_bytes().last().unwrap() // A character in a string is represented by a u8, thus we just want the last byte of the element + let mut field_as_bytes = e.to_bytes(); + let char_byte = field_as_bytes.pop().unwrap(); // A character in a string is represented by a u8, thus we just want the last byte of the element + assert!(field_as_bytes.into_iter().all(|b| b == 0)); // Assert that the rest of the field element's bytes are empty + char_byte }) .collect::>(); diff --git a/crates/noirc_evaluator/src/ssa/code_gen.rs b/crates/noirc_evaluator/src/ssa/code_gen.rs index 4245c33d446..296cfc8912e 100644 --- a/crates/noirc_evaluator/src/ssa/code_gen.rs +++ b/crates/noirc_evaluator/src/ssa/code_gen.rs @@ -520,8 +520,7 @@ impl IRGenerator { } Expression::Literal(Literal::Str(string)) => { let string_as_integers = string - .clone() - .into_bytes() + .bytes() .into_iter() .map(|byte| { let f = FieldElement::from_be_bytes_reduce(&[byte]); diff --git a/crates/noirc_frontend/src/hir/type_check/expr.rs b/crates/noirc_frontend/src/hir/type_check/expr.rs index 8e71aa243fa..c7602b2c26b 100644 --- a/crates/noirc_frontend/src/hir/type_check/expr.rs +++ b/crates/noirc_frontend/src/hir/type_check/expr.rs @@ -701,10 +701,12 @@ pub fn comparator_operand_type_rules( } }); - if x_size != y_size { - return Err(format!("Can only compare arrays of the same length. Here LHS is of length {}, and RHS is {} ", - x_size, y_size)); - } + x_size.unify(y_size, op.location.span, errors, || { + TypeCheckError::Unstructured { + msg: format!("Can only compare arrays of the same length. Here LHS is of length {}, and RHS is {} ", x_size, y_size), + span: op.location.span, + } + }); // We could check if all elements of all arrays are comptime but I am lazy Ok(Bool(Comptime::No(Some(op.location.span)))) @@ -716,10 +718,12 @@ pub fn comparator_operand_type_rules( Err(format!("Unsupported types for comparison: {} and {}", name_a, name_b)) } (String(x_size), String(y_size)) => { - if x_size != y_size { - return Err(format!("Can only compare strings of the same length. Here LHS is of length {}, and RHS is {} ", - x_size, y_size)); - } + x_size.unify(y_size, op.location.span, errors, || { + TypeCheckError::Unstructured { + msg: format!("Can only compare arrays of the same length. Here LHS is of length {}, and RHS is {} ", x_size, y_size), + span: op.location.span, + } + }); Ok(Bool(Comptime::No(Some(op.location.span)))) } From 82af97364091820c3e6f21de973bb76997c5c382 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 11 Jan 2023 12:20:52 -0500 Subject: [PATCH 09/25] update display for string types --- crates/noirc_frontend/src/ast/mod.rs | 4 ++-- crates/noirc_frontend/src/hir_def/types.rs | 4 ++-- crates/noirc_frontend/src/monomorphisation/ast.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/noirc_frontend/src/ast/mod.rs b/crates/noirc_frontend/src/ast/mod.rs index 73c2fdb9603..841d8030066 100644 --- a/crates/noirc_frontend/src/ast/mod.rs +++ b/crates/noirc_frontend/src/ast/mod.rs @@ -70,8 +70,8 @@ impl std::fmt::Display for UnresolvedType { } Bool(is_const) => write!(f, "{}bool", is_const), String(len) => match len { - None => write!(f, "[char]"), - Some(len) => write!(f, "[char; {}]", len), + None => write!(f, "str[]"), + Some(len) => write!(f, "str[{}]", len), }, Unit => write!(f, "()"), Error => write!(f, "error"), diff --git a/crates/noirc_frontend/src/hir_def/types.rs b/crates/noirc_frontend/src/hir_def/types.rs index 95f9314736f..ccbe0f3b676 100644 --- a/crates/noirc_frontend/src/hir_def/types.rs +++ b/crates/noirc_frontend/src/hir_def/types.rs @@ -481,8 +481,8 @@ impl std::fmt::Display for Type { } Type::Bool(comptime) => write!(f, "{}bool", comptime), Type::String(len) => match len.array_length() { - Some(len) => write!(f, "[char; {}]", len), - None => write!(f, "[char]"), + Some(len) => write!(f, "str[{}]", len), + None => write!(f, "str[]]"), }, Type::Unit => write!(f, "()"), Type::Error => write!(f, "error"), diff --git a/crates/noirc_frontend/src/monomorphisation/ast.rs b/crates/noirc_frontend/src/monomorphisation/ast.rs index 7ba58838ca2..9842bf87fd2 100644 --- a/crates/noirc_frontend/src/monomorphisation/ast.rs +++ b/crates/noirc_frontend/src/monomorphisation/ast.rs @@ -166,7 +166,7 @@ pub enum Type { Array(/*len:*/ u64, Box), // Array(4, Field) = [Field; 4] Integer(Signedness, /*bits:*/ u32), // u32 = Integer(unsigned, 32) Bool, - String(/*len:*/ u64), // String(4) = [char; 4] + String(/*len:*/ u64), // String(4) = str[4] Unit, Tuple(Vec), } @@ -256,7 +256,7 @@ impl std::fmt::Display for Type { Signedness::Signed => write!(f, "i{}", bits), }, Type::Bool => write!(f, "bool"), - Type::String(len) => write!(f, "[char; {}]", len), + Type::String(len) => write!(f, "str[{}]", len), Type::Unit => write!(f, "()"), Type::Tuple(elems) => { let elems = vecmap(elems, ToString::to_string); From 279d266a3955b1514d55ea09e6f2252c541786e1 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 17 Jan 2023 16:05:35 -0500 Subject: [PATCH 10/25] fix convert type for new string type --- Cargo.lock | 247 +++++++++------------- crates/noirc_evaluator/src/ssa/context.rs | 1 + 2 files changed, 101 insertions(+), 147 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a7d8052128..782480d662d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -264,7 +264,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -375,9 +375,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byteorder" @@ -393,9 +393,9 @@ checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "cc" -version = "1.0.77" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" [[package]] name = "cexpr" @@ -521,16 +521,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" dependencies = [ "encode_unicode", "lazy_static", "libc", - "terminal_size", "unicode-width", - "winapi", + "windows-sys", ] [[package]] @@ -685,9 +684,9 @@ dependencies = [ [[package]] name = "downloader" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074093edfa907e8203c17c5111b04e114e03bde5ccdfa21a388fa4f34dabad96" +checksum = "d05213e96f184578b5f70105d4d0a644a168e99e12d7bea0b200c15d67b5c182" dependencies = [ "futures", "rand 0.8.5", @@ -983,9 +982,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "gloo-utils" @@ -1054,6 +1053,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -1190,9 +1198,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec947b7a4ce12e3b87e353abae7ce124d025b6c7d6c5aea5cc0bcf92e9510ded" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" [[package]] name = "iter-extended" @@ -1200,9 +1208,9 @@ version = "0.1.0" [[package]] name = "itoa" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "js-sys" @@ -1239,9 +1247,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.138" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libloading" @@ -1336,7 +1344,7 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -1347,7 +1355,6 @@ dependencies = [ "barretenberg_static_lib", "cfg-if 1.0.0", "clap 2.34.0", - "dirs 3.0.2", "dirs 4.0.0", "fm", "hex", @@ -1427,7 +1434,7 @@ name = "noirc_driver" version = "0.1.0" dependencies = [ "acvm", - "dirs 3.0.2", + "dirs 4.0.0", "fm", "noirc_abi", "noirc_errors", @@ -1483,9 +1490,9 @@ dependencies = [ [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", @@ -1532,11 +1539,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -1548,9 +1555,9 @@ checksum = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a" [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "opaque-debug" @@ -1560,9 +1567,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.44" +version = "0.10.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d971fd5722fec23977260f6e81aa67d2f22cadbdc2aa049f1022d9a3be1566" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -1592,9 +1599,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.79" +version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5454462c0eced1e97f2ec09036abc8da362e66802f66fd20f86854d9d8cbcbc4" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ "autocfg", "cc", @@ -1622,9 +1629,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if 1.0.0", "instant", @@ -1636,9 +1643,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "pathdiff" @@ -1660,9 +1667,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.5.1" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0" +checksum = "4257b4a04d91f7e9e6290be5d3da4804dd5784fafde3a497d73eb2b4a158c30a" dependencies = [ "thiserror", "ucd-trie", @@ -1703,9 +1710,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" dependencies = [ "unicode-ident", ] @@ -1721,9 +1728,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -1829,9 +1836,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -1929,18 +1936,17 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "windows-sys 0.36.1", + "windows-sys", ] [[package]] @@ -1998,18 +2004,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.149" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.149" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -2018,9 +2024,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "itoa", "ryu", @@ -2151,9 +2157,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.105" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -2198,23 +2204,13 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] -[[package]] -name = "terminal_size" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "textwrap" version = "0.11.0" @@ -2232,18 +2228,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -2267,19 +2263,19 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.23.0" +version = "1.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae" dependencies = [ "autocfg", "bytes", "libc", "memchr", "mio", - "num_cpus 1.14.0", + "num_cpus 1.15.0", "pin-project-lite", "socket2", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -2308,9 +2304,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" dependencies = [ "serde", ] @@ -2355,9 +2351,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "typenum" @@ -2379,9 +2375,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" @@ -2593,19 +2589,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - [[package]] name = "windows-sys" version = "0.42.0" @@ -2613,85 +2596,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" - -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "winreg" diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 438585d81fb..43ed6f4a65e 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -1127,6 +1127,7 @@ impl SsaContext { Type::Unit => ObjectType::NotAnObject, Type::Function(..) => ObjectType::Function, Type::Tuple(_) => todo!("Conversion to ObjectType is unimplemented for tuples"), + Type::String(_) => todo!("Conversion to ObjectType is unimplemented for strings"), } } From dcb3a0ac2986b4623d9a570833469a3746f827c7 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 17 Jan 2023 17:40:26 -0500 Subject: [PATCH 11/25] fix up some minor PR nitpicks --- crates/noirc_abi/src/lib.rs | 6 ++---- crates/noirc_evaluator/src/ssa/code_gen.rs | 1 - crates/noirc_frontend/src/hir/type_check/expr.rs | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index 6c8371b8e50..13e4caaec5e 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -201,10 +201,8 @@ impl Abi { InputValue::Field(elem) => encoded_value.push(elem), InputValue::Vec(vec_elem) => encoded_value.extend(vec_elem), InputValue::String(string) => { - let str_as_fields = string - .into_bytes() - .into_iter() - .map(|byte| FieldElement::from_be_bytes_reduce(&[byte])); + let str_as_fields = + string.bytes().map(|byte| FieldElement::from_be_bytes_reduce(&[byte])); encoded_value.extend(str_as_fields) } InputValue::Struct(object) => { diff --git a/crates/noirc_evaluator/src/ssa/code_gen.rs b/crates/noirc_evaluator/src/ssa/code_gen.rs index 8cc23ec8ba6..60e3b201d2e 100644 --- a/crates/noirc_evaluator/src/ssa/code_gen.rs +++ b/crates/noirc_evaluator/src/ssa/code_gen.rs @@ -550,7 +550,6 @@ impl IRGenerator { Expression::Literal(Literal::Str(string)) => { let string_as_integers = string .bytes() - .into_iter() .map(|byte| { let f = FieldElement::from_be_bytes_reduce(&[byte]); Expression::Literal(Literal::Integer( diff --git a/crates/noirc_frontend/src/hir/type_check/expr.rs b/crates/noirc_frontend/src/hir/type_check/expr.rs index b42e8da56b4..df64bd19b89 100644 --- a/crates/noirc_frontend/src/hir/type_check/expr.rs +++ b/crates/noirc_frontend/src/hir/type_check/expr.rs @@ -737,7 +737,7 @@ pub fn comparator_operand_type_rules( (String(x_size), String(y_size)) => { x_size.unify(y_size, op.location.span, errors, || { TypeCheckError::Unstructured { - msg: format!("Can only compare arrays of the same length. Here LHS is of length {}, and RHS is {} ", x_size, y_size), + msg: format!("Can only compare strings of the same length. Here LHS is of length {}, and RHS is {} ", x_size, y_size), span: op.location.span, } }); From deeabd3ba38202d5f724531b8c274fba9837a45e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 19 Jan 2023 09:06:32 -0500 Subject: [PATCH 12/25] parsing toml now follow abi --- crates/nargo/src/cli/mod.rs | 8 +++- crates/nargo/src/cli/prove_cmd.rs | 7 ++- crates/nargo/src/cli/verify_cmd.rs | 3 +- crates/noirc_abi/src/input_parser/mod.rs | 5 ++- crates/noirc_abi/src/input_parser/toml.rs | 54 +++++++++++++++-------- crates/noirc_abi/src/lib.rs | 25 +++++++++++ 6 files changed, 77 insertions(+), 25 deletions(-) diff --git a/crates/nargo/src/cli/mod.rs b/crates/nargo/src/cli/mod.rs index da0de1c3227..12f229b0b7d 100644 --- a/crates/nargo/src/cli/mod.rs +++ b/crates/nargo/src/cli/mod.rs @@ -1,6 +1,9 @@ pub use build_cmd::build_from_path; use clap::{App, AppSettings, Arg}; -use noirc_abi::input_parser::{Format, InputValue}; +use noirc_abi::{ + input_parser::{Format, InputValue}, + Abi, +}; use noirc_driver::Driver; use noirc_frontend::graph::{CrateName, CrateType}; use std::{ @@ -138,6 +141,7 @@ pub fn read_inputs_from_file>( path: P, file_name: &str, format: Format, + abi: Abi, ) -> Result, CliError> { let file_path = { let mut dir_path = path.as_ref().to_path_buf(); @@ -150,7 +154,7 @@ pub fn read_inputs_from_file>( } let input_string = std::fs::read_to_string(file_path).unwrap(); - Ok(format.parse(&input_string)?) + Ok(format.parse(&input_string, abi)?) } fn write_inputs_to_file>( diff --git a/crates/nargo/src/cli/prove_cmd.rs b/crates/nargo/src/cli/prove_cmd.rs index 5cc5a3d9605..a7a5cd59105 100644 --- a/crates/nargo/src/cli/prove_cmd.rs +++ b/crates/nargo/src/cli/prove_cmd.rs @@ -57,8 +57,10 @@ pub fn parse_and_solve_witness>( program_dir: P, compiled_program: &noirc_driver::CompiledProgram, ) -> Result, CliError> { + let abi = compiled_program.abi.as_ref().expect("compiled program is missing an abi object"); // Parse the initial witness values from Prover.toml - let witness_map = read_inputs_from_file(&program_dir, PROVER_INPUT_FILE, Format::Toml)?; + let witness_map = + read_inputs_from_file(&program_dir, PROVER_INPUT_FILE, Format::Toml, abi.clone())?; // Solve the remaining witnesses let solved_witness = solve_witness(compiled_program, &witness_map)?; @@ -73,7 +75,8 @@ pub fn parse_and_solve_witness>( .map(|index| solved_witness[index]) .collect(); - let public_abi = compiled_program.abi.as_ref().unwrap().clone().public_abi(); + // let public_abi = compiled_program.abi.as_ref().unwrap().clone().public_abi(); + let public_abi = abi.clone().public_abi(); let public_inputs = public_abi.decode(&encoded_public_inputs)?; // Write public inputs into Verifier.toml diff --git a/crates/nargo/src/cli/verify_cmd.rs b/crates/nargo/src/cli/verify_cmd.rs index 842e608b7d9..71312d8763d 100644 --- a/crates/nargo/src/cli/verify_cmd.rs +++ b/crates/nargo/src/cli/verify_cmd.rs @@ -47,7 +47,8 @@ pub fn verify_with_path>( let num_pub_params = public_abi.num_parameters(); if num_pub_params != 0 { let curr_dir = program_dir; - public_inputs = read_inputs_from_file(curr_dir, VERIFIER_INPUT_FILE, Format::Toml)?; + public_inputs = + read_inputs_from_file(curr_dir, VERIFIER_INPUT_FILE, Format::Toml, public_abi)?; } let valid_proof = verify_proof(compiled_program, public_inputs, load_proof(proof_path)?)?; diff --git a/crates/noirc_abi/src/input_parser/mod.rs b/crates/noirc_abi/src/input_parser/mod.rs index 6f1379a2b10..7c05246eaee 100644 --- a/crates/noirc_abi/src/input_parser/mod.rs +++ b/crates/noirc_abi/src/input_parser/mod.rs @@ -6,7 +6,7 @@ use acvm::FieldElement; use serde::Serialize; use crate::errors::InputParserError; -use crate::AbiType; +use crate::{Abi, AbiType}; /// This is what all formats eventually transform into /// For example, a toml file will parse into TomlTypes /// and those TomlTypes will be mapped to Value @@ -89,9 +89,10 @@ impl Format { pub fn parse( &self, input_string: &str, + abi: Abi, ) -> Result, InputParserError> { match self { - Format::Toml => toml::parse_toml(input_string), + Format::Toml => toml::parse_toml(input_string, abi), } } diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index e67caeb7f55..d3cca86ec28 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -1,5 +1,5 @@ use super::InputValue; -use crate::errors::InputParserError; +use crate::{errors::InputParserError, Abi, AbiType}; use acvm::FieldElement; use serde::Serialize; use serde_derive::Deserialize; @@ -7,11 +7,18 @@ use std::collections::BTreeMap; pub(crate) fn parse_toml( input_string: &str, + abi: Abi, ) -> Result, InputParserError> { // Parse input.toml into a BTreeMap, converting the argument to field elements let data: BTreeMap = toml::from_str(input_string) .map_err(|err_msg| InputParserError::ParseTomlMap(err_msg.to_string()))?; - toml_map_to_field(data) + + let mut sorted_abi = abi.clone(); + sorted_abi.sort(); + let flat_abi_types = sorted_abi.flattened_param_types(); + + let (_, toml_map) = toml_map_to_field(data, flat_abi_types, 0)?; + Ok(toml_map) } pub(crate) fn serialise_to_toml( @@ -50,32 +57,39 @@ pub(crate) fn serialise_to_toml( /// understands for Inputs fn toml_map_to_field( toml_map: BTreeMap, -) -> Result, InputParserError> { + flat_abi_types: Vec, + initial_index: usize, +) -> Result<(usize, BTreeMap), InputParserError> { let mut field_map = BTreeMap::new(); + let mut abi_index = initial_index; for (parameter, value) in toml_map { let mapped_value = match value { TomlTypes::String(string) => { - let new_value = try_str_to_field(&string); - - // We accept UTF-8 strings as input as well as hex strings representing field elements. - // We still want developers to be able to pass in hex strings for FieldElement inputs. - // Thus, we first try to parse the string into a field element, and if that fails we assume that the input is meant to be a plain string - if new_value.is_err() { - InputValue::String(string) - } else if let Ok(Some(field_element)) = new_value { - InputValue::Field(field_element) - } else { - InputValue::Undefined + let param_type = flat_abi_types[abi_index].clone(); + abi_index += 1; + match param_type { + AbiType::String { .. } => InputValue::String(string), + AbiType::Field | AbiType::Integer { .. } => { + let new_value = parse_str_to_field(&string)?; + if let Some(field_element) = new_value { + InputValue::Field(field_element) + } else { + InputValue::Undefined + } + } + _ => unreachable!("abi type specified does not match with TomlType::String"), } } TomlTypes::Integer(integer) => { let new_value = FieldElement::from(i128::from(integer)); + abi_index += 1; InputValue::Field(new_value) } TomlTypes::Bool(boolean) => { let new_value = if boolean { FieldElement::one() } else { FieldElement::zero() }; + abi_index += 1; InputValue::Field(new_value) } TomlTypes::ArrayNum(arr_num) => { @@ -84,18 +98,22 @@ fn toml_map_to_field( .map(|elem_num| FieldElement::from(i128::from(elem_num))) .collect(); + abi_index += 1; InputValue::Vec(array_elements) } TomlTypes::ArrayString(arr_str) => { let array_elements: Vec<_> = arr_str .into_iter() - .map(|elem_str| try_str_to_field(&elem_str).unwrap().unwrap()) + .map(|elem_str| parse_str_to_field(&elem_str).unwrap().unwrap()) .collect(); + abi_index += 1; InputValue::Vec(array_elements) } TomlTypes::Table(table) => { - let native_table = toml_map_to_field(table)?; + let (new_index, native_table) = + toml_map_to_field(table, flat_abi_types.clone(), abi_index)?; + abi_index = new_index; InputValue::Struct(native_table) } @@ -106,7 +124,7 @@ fn toml_map_to_field( }; } - Ok(field_map) + Ok((abi_index, field_map)) } fn toml_remap(map: &BTreeMap) -> BTreeMap { @@ -151,7 +169,7 @@ enum TomlTypes { Table(BTreeMap), } -fn try_str_to_field(value: &str) -> Result, InputParserError> { +fn parse_str_to_field(value: &str) -> Result, InputParserError> { if value.is_empty() { Ok(None) } else if value.starts_with("0x") { diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index 13e4caaec5e..2c853444bea 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -134,6 +134,31 @@ impl Abi { self.parameters.iter().map(|param| param.typ.field_count()).sum() } + pub fn sort(&mut self) { + self.parameters.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()) + } + + pub fn flattened_param_types(&mut self) -> Vec { + let mut new_params = Vec::new(); + for param in self.parameters.iter() { + new_params.extend(Self::flatten_param_type(param.typ.clone())) + } + new_params + } + + fn flatten_param_type(typ: AbiType) -> Vec { + match typ { + AbiType::Struct { fields } => { + let mut flat_struct = Vec::new(); + for (_, param_type) in fields { + flat_struct.extend(Self::flatten_param_type(param_type)) + } + flat_struct + } + _ => vec![typ], + } + } + /// ABI with only the public parameters #[must_use] pub fn public_abi(self) -> Abi { From c11a1bc5e8dcb535dbb391dc1b5817478a5fc7fe Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 19 Jan 2023 11:09:15 -0500 Subject: [PATCH 13/25] additional parser error and some comments --- crates/noirc_abi/src/errors.rs | 10 +++++++++- crates/noirc_abi/src/input_parser/toml.rs | 5 ++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/noirc_abi/src/errors.rs b/crates/noirc_abi/src/errors.rs index 41436f25b64..bafdd10dddb 100644 --- a/crates/noirc_abi/src/errors.rs +++ b/crates/noirc_abi/src/errors.rs @@ -1,4 +1,4 @@ -use crate::{input_parser::InputValue, AbiParameter}; +use crate::{input_parser::InputValue, AbiParameter, AbiType}; #[derive(Debug)] pub enum InputParserError { @@ -6,6 +6,8 @@ pub enum InputParserError { ParseStr(String), ParseHexStr(String), DuplicateVariableName(String), + AbiTypeMismatch(AbiType), + EmptyArrayString(String), } impl std::fmt::Display for InputParserError { @@ -24,6 +26,12 @@ impl std::fmt::Display for InputParserError { InputParserError::DuplicateVariableName(err_msg) => { write!(f, "duplicate variable name {err_msg}") } + InputParserError::AbiTypeMismatch(abi_type) => { + write!(f, "cannot parse a string toml type into {:?}", abi_type) + } + InputParserError::EmptyArrayString(arr_str) => { + write!(f, "array of strings has an empty value: {arr_str}") + } } } } diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index d3cca86ec28..2c97909d794 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -13,6 +13,9 @@ pub(crate) fn parse_toml( let data: BTreeMap = toml::from_str(input_string) .map_err(|err_msg| InputParserError::ParseTomlMap(err_msg.to_string()))?; + // The toml map is stored in an ordered BTreeMap. As the keys are strings the map is in alphanumerical order. + // When parsing the toml map we recursively go through each field to enable struct inputs. + // To match this map with the correct abi type we must sort our abi parameters and then flatten each struct. let mut sorted_abi = abi.clone(); sorted_abi.sort(); let flat_abi_types = sorted_abi.flattened_param_types(); @@ -77,7 +80,7 @@ fn toml_map_to_field( InputValue::Undefined } } - _ => unreachable!("abi type specified does not match with TomlType::String"), + _ => return Err(InputParserError::AbiTypeMismatch(param_type)), } } TomlTypes::Integer(integer) => { From 755417fd509bb2e0325af5ba492419064a82b9c7 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 19 Jan 2023 14:38:22 -0500 Subject: [PATCH 14/25] fix usage of to_bytes with master merge --- Cargo.lock | 2 +- crates/nargo/tests/test_data/struct_inputs/Prover.toml | 3 ++- crates/nargo/tests/test_data/struct_inputs/src/foo/bar.nr | 1 + crates/nargo/tests/test_data/struct_inputs/src/main.nr | 2 ++ crates/noirc_abi/src/lib.rs | 2 +- 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d23aa3a08d..b7ec0af3167 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -419,7 +419,7 @@ dependencies = [ [[package]] name = "barretenberg_wrapper" version = "0.1.0" -source = "git+https://github.com/noir-lang/aztec-connect?branch=kw/noir-dsl#2ef8be41993ead9993c09b1d99fef6dc68e231a6" +source = "git+https://github.com/noir-lang/aztec-connect?branch=kw/noir-dsl#95988ba712d03b139e3ee116ad4d5c4050bcef5c" dependencies = [ "bindgen", "cmake", diff --git a/crates/nargo/tests/test_data/struct_inputs/Prover.toml b/crates/nargo/tests/test_data/struct_inputs/Prover.toml index e319f65d502..d12a6b222fd 100644 --- a/crates/nargo/tests/test_data/struct_inputs/Prover.toml +++ b/crates/nargo/tests/test_data/struct_inputs/Prover.toml @@ -12,4 +12,5 @@ array = [0, 1] [a] [a.bar_struct] val = "1" -array = [0, 1] \ No newline at end of file +array = [0, 1] +message = "hello" \ No newline at end of file diff --git a/crates/nargo/tests/test_data/struct_inputs/src/foo/bar.nr b/crates/nargo/tests/test_data/struct_inputs/src/foo/bar.nr index a80cfa2af65..1cda8011a3d 100644 --- a/crates/nargo/tests/test_data/struct_inputs/src/foo/bar.nr +++ b/crates/nargo/tests/test_data/struct_inputs/src/foo/bar.nr @@ -3,4 +3,5 @@ global N = 2; struct barStruct { val: Field, array: [Field; 2], + message: str[5], } \ No newline at end of file diff --git a/crates/nargo/tests/test_data/struct_inputs/src/main.nr b/crates/nargo/tests/test_data/struct_inputs/src/main.nr index a4d08b3ff7c..8b50be1df8b 100644 --- a/crates/nargo/tests/test_data/struct_inputs/src/main.nr +++ b/crates/nargo/tests/test_data/struct_inputs/src/main.nr @@ -20,6 +20,8 @@ fn main(x : Field, y : pub myStruct, z: pub foo::bar::barStruct, a: pub foo::foo constrain (struct_from_bar.val * x) == x; constrain x != y.bar; + + constrain a.bar_struct.message == "hello"; a.bar_struct.array[1] } diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index 2c853444bea..7037aecfc8b 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -294,7 +294,7 @@ impl Abi { let string_as_slice = field_elements .iter() .map(|e| { - let mut field_as_bytes = e.to_bytes(); + let mut field_as_bytes = e.to_be_bytes(); let char_byte = field_as_bytes.pop().unwrap(); // A character in a string is represented by a u8, thus we just want the last byte of the element assert!(field_as_bytes.into_iter().all(|b| b == 0)); // Assert that the rest of the field element's bytes are empty char_byte From 31ded355956e7085504dda0bfc3b58131acb3ffe Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 19 Jan 2023 15:04:44 -0500 Subject: [PATCH 15/25] working string inputs inside struct inputs to main --- .../tests/test_data/struct_inputs/Prover.toml | 2 ++ .../tests/test_data/struct_inputs/src/main.nr | 6 ++++-- crates/noirc_evaluator/src/ssa/code_gen.rs | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/crates/nargo/tests/test_data/struct_inputs/Prover.toml b/crates/nargo/tests/test_data/struct_inputs/Prover.toml index d12a6b222fd..46aae99b425 100644 --- a/crates/nargo/tests/test_data/struct_inputs/Prover.toml +++ b/crates/nargo/tests/test_data/struct_inputs/Prover.toml @@ -4,10 +4,12 @@ return = "" [y] foo = "5" bar = "10" +message = "hello" [z] val = "1" array = [0, 1] +message = "helld" [a] [a.bar_struct] diff --git a/crates/nargo/tests/test_data/struct_inputs/src/main.nr b/crates/nargo/tests/test_data/struct_inputs/src/main.nr index 8b50be1df8b..3c9a3ba2df7 100644 --- a/crates/nargo/tests/test_data/struct_inputs/src/main.nr +++ b/crates/nargo/tests/test_data/struct_inputs/src/main.nr @@ -5,10 +5,11 @@ mod foo; struct myStruct { foo: u32, bar: Field, + message: str[5], } fn main(x : Field, y : pub myStruct, z: pub foo::bar::barStruct, a: pub foo::fooStruct) -> pub Field { - let struct_from_bar = foo::bar::barStruct { val: 1, array: [0, 1] }; + let struct_from_bar = foo::bar::barStruct { val: 1, array: [0, 1], message: "hello" }; check_inner_struct(a, z); @@ -21,7 +22,8 @@ fn main(x : Field, y : pub myStruct, z: pub foo::bar::barStruct, a: pub foo::foo constrain x != y.bar; - constrain a.bar_struct.message == "hello"; + constrain y.message == "hello"; + constrain a.bar_struct.message == struct_from_bar.message; a.bar_struct.array[1] } diff --git a/crates/noirc_evaluator/src/ssa/code_gen.rs b/crates/noirc_evaluator/src/ssa/code_gen.rs index 60e3b201d2e..33ec133ff25 100644 --- a/crates/noirc_evaluator/src/ssa/code_gen.rs +++ b/crates/noirc_evaluator/src/ssa/code_gen.rs @@ -196,6 +196,18 @@ impl IRGenerator { let new_name = format!("{struct_name}.{name}"); self.abi_struct(&new_name, None, fields, witnesses.clone()) } + noirc_abi::AbiType::String { length } => { + let typ = + noirc_abi::AbiType::Integer { sign: noirc_abi::Sign::Unsigned, width: 8 }; + let v_id = self.abi_array( + &new_name, + None, + &typ, + *length, + witnesses[&new_name].clone(), + ); + Value::Single(v_id) + } _ => { let obj_type = self.get_object_type_from_abi(field_typ); let v_id = self.create_new_variable( @@ -361,6 +373,12 @@ impl IRGenerator { let (v_id, _) = self.new_array(base_name, obj_type, len.try_into().unwrap(), def); Value::Single(v_id) } + Type::String(len) => { + let obj_type = ObjectType::Unsigned(8); + let len = *len; + let (v_id, _) = self.new_array(base_name, obj_type, len.try_into().unwrap(), def); + Value::Single(v_id) + } _ => { let obj_type = self.context.convert_type(typ); let v_id = self.create_new_variable(base_name.to_string(), def, obj_type, None); From 2715eb005a70a9d19607e6caa8c91ab3f7ff76a1 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 19 Jan 2023 15:10:10 -0500 Subject: [PATCH 16/25] cargo clippy cleanup --- crates/nargo/src/cli/prove_cmd.rs | 1 - crates/noirc_abi/src/input_parser/toml.rs | 7 +++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/nargo/src/cli/prove_cmd.rs b/crates/nargo/src/cli/prove_cmd.rs index 43813bf9cb4..172e56c9d1e 100644 --- a/crates/nargo/src/cli/prove_cmd.rs +++ b/crates/nargo/src/cli/prove_cmd.rs @@ -75,7 +75,6 @@ pub fn parse_and_solve_witness>( .map(|index| solved_witness[index]) .collect(); - // let public_abi = compiled_program.abi.as_ref().unwrap().clone().public_abi(); let public_abi = abi.clone().public_abi(); let public_inputs = public_abi.decode(&encoded_public_inputs)?; diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index 2c97909d794..6d02024abae 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -7,7 +7,7 @@ use std::collections::BTreeMap; pub(crate) fn parse_toml( input_string: &str, - abi: Abi, + mut abi: Abi, ) -> Result, InputParserError> { // Parse input.toml into a BTreeMap, converting the argument to field elements let data: BTreeMap = toml::from_str(input_string) @@ -16,9 +16,8 @@ pub(crate) fn parse_toml( // The toml map is stored in an ordered BTreeMap. As the keys are strings the map is in alphanumerical order. // When parsing the toml map we recursively go through each field to enable struct inputs. // To match this map with the correct abi type we must sort our abi parameters and then flatten each struct. - let mut sorted_abi = abi.clone(); - sorted_abi.sort(); - let flat_abi_types = sorted_abi.flattened_param_types(); + abi.sort(); + let flat_abi_types = abi.flattened_param_types(); let (_, toml_map) = toml_map_to_field(data, flat_abi_types, 0)?; Ok(toml_map) From 09998b911f3a62feeaa63b40a05cf6c096531135 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 19 Jan 2023 16:29:36 -0500 Subject: [PATCH 17/25] remove unused err --- crates/noirc_abi/src/errors.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/noirc_abi/src/errors.rs b/crates/noirc_abi/src/errors.rs index bafdd10dddb..78094562d6a 100644 --- a/crates/noirc_abi/src/errors.rs +++ b/crates/noirc_abi/src/errors.rs @@ -7,7 +7,6 @@ pub enum InputParserError { ParseHexStr(String), DuplicateVariableName(String), AbiTypeMismatch(AbiType), - EmptyArrayString(String), } impl std::fmt::Display for InputParserError { @@ -29,9 +28,6 @@ impl std::fmt::Display for InputParserError { InputParserError::AbiTypeMismatch(abi_type) => { write!(f, "cannot parse a string toml type into {:?}", abi_type) } - InputParserError::EmptyArrayString(arr_str) => { - write!(f, "array of strings has an empty value: {arr_str}") - } } } } From cf2eb4471fc2e3d4812db4b5d03f17ead37d3f67 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 19 Jan 2023 16:34:31 -0500 Subject: [PATCH 18/25] additional test case for type directed toml parsing --- crates/nargo/tests/test_data/strings/Prover.toml | 4 +++- crates/nargo/tests/test_data/strings/src/main.nr | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/nargo/tests/test_data/strings/Prover.toml b/crates/nargo/tests/test_data/strings/Prover.toml index a7fd24f8107..1e5f7c6f6e2 100644 --- a/crates/nargo/tests/test_data/strings/Prover.toml +++ b/crates/nargo/tests/test_data/strings/Prover.toml @@ -1 +1,3 @@ -message = "hello world" \ No newline at end of file +message = "hello world" +hex_as_string = "0x41" +hex_as_field = "0x41" \ No newline at end of file diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index 36d2a702ce3..3016a3fe8c9 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -1,8 +1,12 @@ -fn main(message : pub str[11]) { +fn main(message : pub str[11], hex_as_string : str[4], hex_as_field : Field) { let mut bad_message = "hello world"; constrain message == "hello world"; bad_message = "helld world"; constrain message != bad_message; + + constrain hex_as_string == "0x41"; + // constrain hex_as_string != 0x41; This will fail with a type mismatch between str[4] and Field + constrain hex_as_field == 0x41; } \ No newline at end of file From 6bfcfdad6dd17fc386fbd1fc1b6d3d5af8925bf4 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 23 Jan 2023 12:44:22 -0500 Subject: [PATCH 19/25] using less and greater than for str type --- .../nargo/tests/test_data/strings/src/main.nr | 2 +- crates/noirc_frontend/src/parser/mod.rs | 21 ++++++- crates/noirc_frontend/src/parser/parser.rs | 61 +++++++++++++++++-- 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index 3016a3fe8c9..83574e9c068 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -1,4 +1,4 @@ -fn main(message : pub str[11], hex_as_string : str[4], hex_as_field : Field) { +fn main(message : pub str<11>, hex_as_string : str<4>, hex_as_field : Field) { let mut bad_message = "hello world"; constrain message == "hello world"; diff --git a/crates/noirc_frontend/src/parser/mod.rs b/crates/noirc_frontend/src/parser/mod.rs index 227dda4fcab..c8c66114dac 100644 --- a/crates/noirc_frontend/src/parser/mod.rs +++ b/crates/noirc_frontend/src/parser/mod.rs @@ -292,7 +292,7 @@ impl Precedence { Some(precedence) } - fn higher(self) -> Self { + fn next(self) -> Self { use Precedence::*; match self { Lowest => Or, @@ -306,6 +306,25 @@ impl Precedence { Highest => Highest, } } + + /// Type expressions only contain basic arithmetic operators and + /// notably exclude `>` due to parsing conflicts with generic type brackets. + fn next_type_precedence(self) -> Self { + use Precedence::*; + match self { + Lowest => Sum, + Sum => Product, + Product => Highest, + Highest => Highest, + other => unreachable!("Unexpected precedence level in type expression: {:?}", other), + } + } + + /// The operators with the lowest precedence still useable in type expressions + /// are '+' and '-' with precedence Sum. + fn lowest_type_precedence() -> Self { + Precedence::Sum + } } enum ForRange { diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index 1f7c28f736c..53278521c6d 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -481,7 +481,7 @@ where { keyword(Keyword::String) .ignore_then( - expr_parser.delimited_by(just(Token::LeftBracket), just(Token::RightBracket)).or_not(), + type_expression().delimited_by(just(Token::Less), just(Token::Greater)).or_not(), ) .map(UnresolvedType::String) } @@ -515,6 +515,11 @@ fn generic_type_args( .map(Option::unwrap_or_default) } +fn type_expression() -> impl NoirParser { + recursive(|expr| expression_with_precedence(Precedence::lowest_type_precedence(), expr, true)) + .labelled("type expression") +} + fn array_type(type_parser: T, expr_parser: P) -> impl NoirParser where T: NoirParser, @@ -548,7 +553,8 @@ where } fn expression() -> impl ExprParser { - recursive(|expr| expression_with_precedence(Precedence::Lowest, expr)).labelled("expression") + recursive(|expr| expression_with_precedence(Precedence::Lowest, expr, false)) + .labelled("expression") } // An expression is a single term followed by 0 or more (OP subexpr)* @@ -557,18 +563,39 @@ fn expression() -> impl ExprParser { fn expression_with_precedence<'a, P>( precedence: Precedence, expr_parser: P, + // True if we should only parse the restricted subset of operators valid within type expressions + is_type_expression: bool, ) -> impl NoirParser + 'a where P: ExprParser + 'a, { if precedence == Precedence::Highest { - term(expr_parser).boxed().labelled("term") + // term(expr_parser).boxed().labelled("term") + if is_type_expression { + type_expression_term(expr_parser).boxed().labelled("term") + } else { + term(expr_parser).boxed().labelled("term") + } } else { - expression_with_precedence(precedence.higher(), expr_parser.clone()) + // expression_with_precedence(precedence.higher(), expr_parser.clone()) + // .then( + // then_commit( + // operator_with_precedence(precedence), + // expression_with_precedence(precedence.higher(), expr_parser), + // ) + // .repeated(), + // ) + // .foldl(create_infix_expression) + // .boxed() + // .labelled("expression") + let next_precedence = + if is_type_expression { precedence.next_type_precedence() } else { precedence.next() }; + + expression_with_precedence(precedence.next(), expr_parser.clone(), is_type_expression) .then( then_commit( operator_with_precedence(precedence), - expression_with_precedence(precedence.higher(), expr_parser), + expression_with_precedence(next_precedence, expr_parser, is_type_expression), ) .repeated(), ) @@ -610,6 +637,17 @@ where }) } +/// The equivalent of a 'term' for use in type expressions. Unlike regular terms, the grammar here +/// is restricted to no longer include right-unary expressions, unary not, and most atoms. +fn type_expression_term<'a, P>(expr_parser: P) -> impl NoirParser + 'a +where + P: ExprParser + 'a, +{ + recursive(move |term_parser| { + negation(term_parser).map_with_span(Expression::new).or(type_expression_atom(expr_parser)) + }) +} + fn atom_or_right_unary<'a, P>(expr_parser: P) -> impl NoirParser + 'a where P: ExprParser + 'a, @@ -783,6 +821,19 @@ where .labelled("atom") } +/// Atoms within type expressions are limited to only variables, literals, and parenthesized +/// type expressions. +fn type_expression_atom<'a, P>(expr_parser: P) -> impl NoirParser + 'a +where + P: ExprParser + 'a, +{ + variable() + .or(literal()) + .map_with_span(Expression::new) + .or(parenthesized(expr_parser)) + .labelled("atom") +} + fn tuple

(expr_parser: P) -> impl NoirParser where P: ExprParser, From 0917038610e714fdf0f6c0f511ad6511ee4308b8 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 23 Jan 2023 13:01:23 -0500 Subject: [PATCH 20/25] cargo clippy --- crates/noirc_frontend/src/parser/parser.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index 53278521c6d..0192fe556c2 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -445,10 +445,10 @@ where field_type(), int_type(), named_type(recursive_type_parser.clone()), - array_type(recursive_type_parser.clone(), expr_parser.clone()), + array_type(recursive_type_parser.clone(), expr_parser), tuple_type(recursive_type_parser.clone()), bool_type(), - string_type(expr_parser), + string_type(), function_type(recursive_type_parser), )) } @@ -475,10 +475,7 @@ fn bool_type() -> impl NoirParser { maybe_comptime().then_ignore(keyword(Keyword::Bool)).map(UnresolvedType::Bool) } -fn string_type

(expr_parser: P) -> impl NoirParser -where - P: NoirParser, -{ +fn string_type() -> impl NoirParser { keyword(Keyword::String) .ignore_then( type_expression().delimited_by(just(Token::Less), just(Token::Greater)).or_not(), From 41e6a80a945a32ce90beba84732505fb6b76b06b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 23 Jan 2023 13:14:31 -0500 Subject: [PATCH 21/25] fix type def for str fields in struct_inputs test --- crates/nargo/tests/test_data/struct_inputs/src/foo/bar.nr | 2 +- crates/nargo/tests/test_data/struct_inputs/src/main.nr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/nargo/tests/test_data/struct_inputs/src/foo/bar.nr b/crates/nargo/tests/test_data/struct_inputs/src/foo/bar.nr index 1cda8011a3d..d1963f4a0a7 100644 --- a/crates/nargo/tests/test_data/struct_inputs/src/foo/bar.nr +++ b/crates/nargo/tests/test_data/struct_inputs/src/foo/bar.nr @@ -3,5 +3,5 @@ global N = 2; struct barStruct { val: Field, array: [Field; 2], - message: str[5], + message: str<5>, } \ No newline at end of file diff --git a/crates/nargo/tests/test_data/struct_inputs/src/main.nr b/crates/nargo/tests/test_data/struct_inputs/src/main.nr index 3c9a3ba2df7..61637d95ca1 100644 --- a/crates/nargo/tests/test_data/struct_inputs/src/main.nr +++ b/crates/nargo/tests/test_data/struct_inputs/src/main.nr @@ -5,7 +5,7 @@ mod foo; struct myStruct { foo: u32, bar: Field, - message: str[5], + message: str<5>, } fn main(x : Field, y : pub myStruct, z: pub foo::bar::barStruct, a: pub foo::fooStruct) -> pub Field { From 861da205511d96d259023e81b28e2eaef31b6e46 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 23 Jan 2023 21:31:54 -0500 Subject: [PATCH 22/25] uncommit accidental prover input to test and cargo fmt --- crates/nargo/tests/test_data/struct/Prover.toml | 3 +-- crates/noirc_frontend/src/hir_def/types.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/nargo/tests/test_data/struct/Prover.toml b/crates/nargo/tests/test_data/struct/Prover.toml index 7cd9a881923..7d59cc81807 100644 --- a/crates/nargo/tests/test_data/struct/Prover.toml +++ b/crates/nargo/tests/test_data/struct/Prover.toml @@ -1,3 +1,2 @@ x = "0" -y = "1" -q = 0x5 \ No newline at end of file +y = "1" \ No newline at end of file diff --git a/crates/noirc_frontend/src/hir_def/types.rs b/crates/noirc_frontend/src/hir_def/types.rs index 3c1c6342e25..1102ad0cb35 100644 --- a/crates/noirc_frontend/src/hir_def/types.rs +++ b/crates/noirc_frontend/src/hir_def/types.rs @@ -966,7 +966,7 @@ impl Type { TypeBinding::Bound(typ) => typ.as_abi_type(), TypeBinding::Unbound(_) => Type::default_int_type(None).as_abi_type(), }, - Type::Bool(_) => AbiType::Boolean, + Type::Bool(_) => AbiType::Boolean, Type::String(size) => { let size = size .array_length() From 7d0b3e406c69acef8b95984810cd7c58f9f2f3cd Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 23 Jan 2023 22:51:30 -0500 Subject: [PATCH 23/25] switch to using abi BTreeMap instead of flattened vec --- crates/noirc_abi/src/input_parser/toml.rs | 36 ++++++++++------------- crates/noirc_abi/src/lib.rs | 25 +++------------- 2 files changed, 20 insertions(+), 41 deletions(-) diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index 6d02024abae..ef9d8109172 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -7,7 +7,7 @@ use std::collections::BTreeMap; pub(crate) fn parse_toml( input_string: &str, - mut abi: Abi, + abi: Abi, ) -> Result, InputParserError> { // Parse input.toml into a BTreeMap, converting the argument to field elements let data: BTreeMap = toml::from_str(input_string) @@ -15,11 +15,11 @@ pub(crate) fn parse_toml( // The toml map is stored in an ordered BTreeMap. As the keys are strings the map is in alphanumerical order. // When parsing the toml map we recursively go through each field to enable struct inputs. - // To match this map with the correct abi type we must sort our abi parameters and then flatten each struct. - abi.sort(); - let flat_abi_types = abi.flattened_param_types(); + // To match this map with the correct abi type we reorganize our ABI by parameter name, while the struct fields + // in the abi are already stored in a BTreeMap. + let abi_map = abi.to_btree_map(); - let (_, toml_map) = toml_map_to_field(data, flat_abi_types, 0)?; + let toml_map = toml_map_to_field(data, abi_map)?; Ok(toml_map) } @@ -59,16 +59,13 @@ pub(crate) fn serialise_to_toml( /// understands for Inputs fn toml_map_to_field( toml_map: BTreeMap, - flat_abi_types: Vec, - initial_index: usize, -) -> Result<(usize, BTreeMap), InputParserError> { + abi_map: BTreeMap, +) -> Result, InputParserError> { let mut field_map = BTreeMap::new(); - let mut abi_index = initial_index; for (parameter, value) in toml_map { let mapped_value = match value { TomlTypes::String(string) => { - let param_type = flat_abi_types[abi_index].clone(); - abi_index += 1; + let param_type = abi_map.get(¶meter).unwrap(); match param_type { AbiType::String { .. } => InputValue::String(string), AbiType::Field | AbiType::Integer { .. } => { @@ -79,19 +76,17 @@ fn toml_map_to_field( InputValue::Undefined } } - _ => return Err(InputParserError::AbiTypeMismatch(param_type)), + _ => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), } } TomlTypes::Integer(integer) => { let new_value = FieldElement::from(i128::from(integer)); - abi_index += 1; InputValue::Field(new_value) } TomlTypes::Bool(boolean) => { let new_value = if boolean { FieldElement::one() } else { FieldElement::zero() }; - abi_index += 1; InputValue::Field(new_value) } TomlTypes::ArrayNum(arr_num) => { @@ -100,7 +95,6 @@ fn toml_map_to_field( .map(|elem_num| FieldElement::from(i128::from(elem_num))) .collect(); - abi_index += 1; InputValue::Vec(array_elements) } TomlTypes::ArrayString(arr_str) => { @@ -109,13 +103,15 @@ fn toml_map_to_field( .map(|elem_str| parse_str_to_field(&elem_str).unwrap().unwrap()) .collect(); - abi_index += 1; InputValue::Vec(array_elements) } TomlTypes::Table(table) => { - let (new_index, native_table) = - toml_map_to_field(table, flat_abi_types.clone(), abi_index)?; - abi_index = new_index; + let param_type = abi_map.get(¶meter).unwrap(); + let fields = match param_type { + AbiType::Struct { fields } => fields.clone(), + _ => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), + }; + let native_table = toml_map_to_field(table, fields)?; InputValue::Struct(native_table) } @@ -126,7 +122,7 @@ fn toml_map_to_field( }; } - Ok((abi_index, field_map)) + Ok(field_map) } fn toml_remap(map: &BTreeMap) -> BTreeMap { diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index 51c381c88f4..d1e0a1d5146 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -135,29 +135,12 @@ impl Abi { self.parameters.iter().map(|param| param.typ.field_count()).sum() } - pub fn sort(&mut self) { - self.parameters.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()) - } - - pub fn flattened_param_types(&mut self) -> Vec { - let mut new_params = Vec::new(); + pub fn to_btree_map(&self) -> BTreeMap { + let mut map = BTreeMap::new(); for param in self.parameters.iter() { - new_params.extend(Self::flatten_param_type(param.typ.clone())) - } - new_params - } - - fn flatten_param_type(typ: AbiType) -> Vec { - match typ { - AbiType::Struct { fields } => { - let mut flat_struct = Vec::new(); - for (_, param_type) in fields { - flat_struct.extend(Self::flatten_param_type(param_type)) - } - flat_struct - } - _ => vec![typ], + map.insert(param.name.clone(), param.typ.clone()); } + map } /// ABI with only the public parameters From 4019440ad54cae61cd5984969432449ee30da2d6 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 23 Jan 2023 22:53:10 -0500 Subject: [PATCH 24/25] comments --- crates/noirc_abi/src/input_parser/toml.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index ef9d8109172..16316a1ecd6 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -15,7 +15,7 @@ pub(crate) fn parse_toml( // The toml map is stored in an ordered BTreeMap. As the keys are strings the map is in alphanumerical order. // When parsing the toml map we recursively go through each field to enable struct inputs. - // To match this map with the correct abi type we reorganize our ABI by parameter name, while the struct fields + // To match this map with the correct abi type we reorganize our abi by parameter name in a BTreeMap, while the struct fields // in the abi are already stored in a BTreeMap. let abi_map = abi.to_btree_map(); From 099828aa25ad9aa7a56e02cfda1fbac0b629983d Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 25 Jan 2023 12:19:11 -0500 Subject: [PATCH 25/25] pr comments, mainly style --- crates/noirc_evaluator/src/ssa/code_gen.rs | 17 +++++++---------- crates/noirc_frontend/src/parser/parser.rs | 12 ------------ 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/code_gen.rs b/crates/noirc_evaluator/src/ssa/code_gen.rs index b610443494f..43387ffdf40 100644 --- a/crates/noirc_evaluator/src/ssa/code_gen.rs +++ b/crates/noirc_evaluator/src/ssa/code_gen.rs @@ -567,16 +567,13 @@ impl IRGenerator { Ok(Value::Single(new_var)) } Expression::Literal(Literal::Str(string)) => { - let string_as_integers = string - .bytes() - .map(|byte| { - let f = FieldElement::from_be_bytes_reduce(&[byte]); - Expression::Literal(Literal::Integer( - f, - Type::Integer(noirc_frontend::Signedness::Unsigned, 8), - )) - }) - .collect::>(); + let string_as_integers = vecmap(string.bytes(), |byte| { + let f = FieldElement::from_be_bytes_reduce(&[byte]); + Expression::Literal(Literal::Integer( + f, + Type::Integer(noirc_frontend::Signedness::Unsigned, 8), + )) + }); let string_arr_literal = ArrayLiteral { contents: string_as_integers, diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index 0192fe556c2..e3fcb2d7e36 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -567,24 +567,12 @@ where P: ExprParser + 'a, { if precedence == Precedence::Highest { - // term(expr_parser).boxed().labelled("term") if is_type_expression { type_expression_term(expr_parser).boxed().labelled("term") } else { term(expr_parser).boxed().labelled("term") } } else { - // expression_with_precedence(precedence.higher(), expr_parser.clone()) - // .then( - // then_commit( - // operator_with_precedence(precedence), - // expression_with_precedence(precedence.higher(), expr_parser), - // ) - // .repeated(), - // ) - // .foldl(create_infix_expression) - // .boxed() - // .labelled("expression") let next_precedence = if is_type_expression { precedence.next_type_precedence() } else { precedence.next() };