From 19bd86b6cf243aa5ba5beda04b941fa2bc6ebc3f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 6 Jan 2023 15:23:36 -0500 Subject: [PATCH 01/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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 094cbd6a633e582efc5ecfe276940a92001f34ad Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 11 Jan 2023 12:18:16 -0500 Subject: [PATCH 09/47] starting log work --- crates/noirc_frontend/src/ast/statement.rs | 4 +++- crates/noirc_frontend/src/hir/resolution/resolver.rs | 4 ++++ crates/noirc_frontend/src/hir_def/stmt.rs | 1 + crates/noirc_frontend/src/monomorphisation/ast.rs | 3 +-- crates/noirc_frontend/src/monomorphisation/mod.rs | 1 + 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/noirc_frontend/src/ast/statement.rs b/crates/noirc_frontend/src/ast/statement.rs index 054d579a08d..e30d05d9dc7 100644 --- a/crates/noirc_frontend/src/ast/statement.rs +++ b/crates/noirc_frontend/src/ast/statement.rs @@ -131,7 +131,7 @@ pub enum Statement { // This is an expression with a trailing semi-colon // terminology Taken from rustc Semi(Expression), - + Log(UnresolvedType), // This statement is the result of a recovered parse error. // To avoid issuing multiple errors in later steps, it should // be skipped in any future analysis if possible. @@ -163,6 +163,7 @@ impl Statement { | Statement::Constrain(_) | Statement::Assign(_) | Statement::Semi(_) + | Statement::Log(_) | Statement::Error => { // To match rust, statements always require a semicolon, even at the end of a block if semi.is_none() { @@ -349,6 +350,7 @@ impl Display for Statement { Statement::Expression(expression) => expression.fmt(f), Statement::Assign(assign) => assign.fmt(f), Statement::Semi(semi) => write!(f, "{};", semi), + Statement::Log(log) => log.fmt(f), Statement::Error => write!(f, "Error"), } } diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index 00f7c27adf2..ee92983cd77 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -495,6 +495,10 @@ impl<'a> Resolver<'a> { let stmt = HirAssignStatement { lvalue: identifier, expression }; HirStatement::Assign(stmt) } + Statement::Log(log_stmt) => { + let log_type = self.resolve_type(log_stmt); + HirStatement::Log(log_type) + } Statement::Error => HirStatement::Error, } } diff --git a/crates/noirc_frontend/src/hir_def/stmt.rs b/crates/noirc_frontend/src/hir_def/stmt.rs index ebd2741676b..aab25424918 100644 --- a/crates/noirc_frontend/src/hir_def/stmt.rs +++ b/crates/noirc_frontend/src/hir_def/stmt.rs @@ -43,6 +43,7 @@ pub enum HirStatement { Assign(HirAssignStatement), Expression(ExprId), Semi(ExprId), + Log(Type), Error, } diff --git a/crates/noirc_frontend/src/monomorphisation/ast.rs b/crates/noirc_frontend/src/monomorphisation/ast.rs index 7ba58838ca2..78bf10e219f 100644 --- a/crates/noirc_frontend/src/monomorphisation/ast.rs +++ b/crates/noirc_frontend/src/monomorphisation/ast.rs @@ -26,6 +26,7 @@ pub enum Expression { Constrain(Box, Location), Assign(Assign), Semi(Box), + Log(Type), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -166,7 +167,6 @@ 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] Unit, Tuple(Vec), } @@ -256,7 +256,6 @@ 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::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 bb6fe81d074..dcb82abab92 100644 --- a/crates/noirc_frontend/src/monomorphisation/mod.rs +++ b/crates/noirc_frontend/src/monomorphisation/mod.rs @@ -282,6 +282,7 @@ impl Monomorphiser { HirStatement::Assign(assign) => self.assign(assign), HirStatement::Expression(expr) => self.expr_infer(expr), HirStatement::Semi(expr) => ast::Expression::Semi(Box::new(self.expr_infer(expr))), + HirStatement::Log(log_type) => ast::Expression::Log(Self::convert_type(&log_type)), HirStatement::Error => unreachable!(), } } From 9df593489bb1c5e534b9a6784e9f7711fee998bc Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 11 Jan 2023 12:19:48 -0500 Subject: [PATCH 10/47] update missing type from monomorphisation ast --- crates/noirc_frontend/src/monomorphisation/ast.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/noirc_frontend/src/monomorphisation/ast.rs b/crates/noirc_frontend/src/monomorphisation/ast.rs index 78bf10e219f..e67a9657b1b 100644 --- a/crates/noirc_frontend/src/monomorphisation/ast.rs +++ b/crates/noirc_frontend/src/monomorphisation/ast.rs @@ -167,6 +167,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] Unit, Tuple(Vec), } @@ -256,6 +257,7 @@ impl std::fmt::Display for Type { Signedness::Signed => write!(f, "i{}", bits), }, Type::Bool => write!(f, "bool"), + Type::String(len) => write!(f, "str[{}]", len), Type::Unit => write!(f, "()"), Type::Tuple(elems) => { let elems = vecmap(elems, ToString::to_string); From 82af97364091820c3e6f21de973bb76997c5c382 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 11 Jan 2023 12:20:52 -0500 Subject: [PATCH 11/47] 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 715873efae8c71182f87f5a74c7f938b1c6c1bde Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 12 Jan 2023 14:35:34 -0500 Subject: [PATCH 12/47] preliminary logging work, can log strings and arrays stored in idents. need to create Log directive for more accurate logging logic --- .../nargo/tests/test_data/strings/Prover.toml | 3 +- .../nargo/tests/test_data/strings/src/main.nr | 15 +++- crates/noirc_evaluator/src/ssa/acir_gen.rs | 82 ++++++++++++++++++- crates/noirc_evaluator/src/ssa/code_gen.rs | 31 ++++++- crates/noirc_evaluator/src/ssa/context.rs | 12 ++- crates/noirc_evaluator/src/ssa/inline.rs | 2 +- crates/noirc_evaluator/src/ssa/integer.rs | 1 + crates/noirc_evaluator/src/ssa/node.rs | 25 ++++++ crates/noirc_frontend/src/ast/statement.rs | 2 +- .../src/hir/resolution/resolver.rs | 6 +- .../noirc_frontend/src/hir/type_check/stmt.rs | 1 + crates/noirc_frontend/src/hir_def/stmt.rs | 2 +- crates/noirc_frontend/src/lexer/token.rs | 3 + .../src/monomorphisation/ast.rs | 2 +- .../src/monomorphisation/mod.rs | 2 +- .../src/monomorphisation/printer.rs | 4 + crates/noirc_frontend/src/parser/parser.rs | 12 +++ 17 files changed, 188 insertions(+), 17 deletions(-) diff --git a/crates/nargo/tests/test_data/strings/Prover.toml b/crates/nargo/tests/test_data/strings/Prover.toml index a7fd24f8107..1124cf54c6d 100644 --- a/crates/nargo/tests/test_data/strings/Prover.toml +++ b/crates/nargo/tests/test_data/strings/Prover.toml @@ -1 +1,2 @@ -message = "hello world" \ No newline at end of file +message = "hello world" +y = 5 \ 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..5092cddecee 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -1,8 +1,21 @@ -fn main(message : pub str[11]) { +use dep::std; + +fn main(message : pub str[11], y : Field) { let mut bad_message = "hello world"; constrain message == "hello world"; bad_message = "helld world"; + let x = 2; + log(x); + + // Currently broken + // let hash = std::hash::pedersen([x])[0]; + // log(bad_message); + log("five"); + + let array = [1, 2, 3, 5, 8]; + constrain y != 5; + log(array); constrain message != bad_message; } \ No newline at end of file diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index f7efc7111de..8e5727f7ad6 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -1,14 +1,12 @@ use super::mem::{ArrayId, MemArray, Memory}; -use super::node::{BinaryOp, Instruction, ObjectType, Operation}; +use super::node::{BinaryOp, Instruction, LogInfo, NodeId, ObjectType, Operation}; use acvm::acir::OPCODE; use acvm::FieldElement; -use super::node::NodeId; - use num_traits::{One, Zero}; use std::cmp::Ordering; -use std::collections::HashMap; use std::ops::{Mul, Neg}; +use std::{collections::HashMap, str}; //use crate::acir::native_types::{Arithmetic, Witness}; use crate::ssa::context::SsaContext; use crate::ssa::node::Node; @@ -210,6 +208,82 @@ impl Acir { todo!("dynamic arrays are not implemented yet"); } } + + Operation::Log(log_id) => { + // TODO: switch these prints to string creation and make a Directive to use when solving the ACIR + match log_id { + LogInfo::Node(node_id) => match ctx.get_as_constant(*node_id) { + Some(field) => { + println!("{}", field) + } + None => unreachable!("array objects should not be marked as single values"), + }, + LogInfo::Array(array_log) => { + let mem_array = &ctx.mem[array_log.array_id]; + let mut field_elements = Vec::new(); + for idx in 0..mem_array.len { + let absolute_adr = mem_array.absolute_adr(idx); + if self.memory_map.contains_key(&absolute_adr) { + let array_elem_expr = + self.memory_map[&absolute_adr].expression.clone(); + if array_elem_expr.is_const() { + field_elements.push(array_elem_expr.q_c) + } else { + unreachable!("array elements being logging must be const"); + } + } else { + // TODO add handling for if key not found + unreachable!( + "array element being logging does not exist in memory" + ); + } + } + if array_log.is_string { + // TODO: make a decode_string_value method in noirc_abi and use it here this is reused code + let string_as_slice = field_elements + .iter() + .map(|e| { + 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::>(); + + let final_string = str::from_utf8(&string_as_slice).unwrap(); + println!("{}", final_string); + } else { + print!("["); + let mut iter = field_elements.iter().peekable(); + while let Some(elem) = iter.next() { + if iter.peek().is_none() { + print!("{}", elem); + } else { + print!("{}, ", elem) + } + } + println!("]"); + } + // for idx in 0..mem_array.len { + // let absolute_adr = mem_array.absolute_adr(idx); + // if self.memory_map.contains_key(&absolute_adr) { + // let array_elem_expr = self.memory_map[&absolute_adr].expression.clone(); + // if array_elem_expr.is_const() { + // let field_element = array_elem_expr.q_c; + // if array_log.is_string { + + // } else { + // print!("{}, ",field_element) + // } + // } + // // dbg!(self.memory_map[&absolute_adr].expression.to_string()); + // } + // } + } + } + //we do not generate constraint, so no output. + InternalVar::default() + } }; output.id = Some(ins.id); self.arith_cache.insert(ins.id, output); diff --git a/crates/noirc_evaluator/src/ssa/code_gen.rs b/crates/noirc_evaluator/src/ssa/code_gen.rs index 296cfc8912e..f904230eca3 100644 --- a/crates/noirc_evaluator/src/ssa/code_gen.rs +++ b/crates/noirc_evaluator/src/ssa/code_gen.rs @@ -1,7 +1,7 @@ use super::context::SsaContext; use super::function::FuncIndex; use super::mem::ArrayId; -use super::node::{Binary, BinaryOp, NodeId, ObjectType, Operation, Variable}; +use super::node::{ArrayLog, Binary, BinaryOp, LogInfo, NodeId, ObjectType, Operation, Variable}; use super::{block, node, ssa_form}; use std::collections::{BTreeMap, HashMap}; use std::convert::TryInto; @@ -627,9 +627,38 @@ impl IRGenerator { self.codegen_expression(expr.as_ref())?; Ok(Value::dummy()) } + Expression::Log(expr) => { + // dbg!(expr.as_ref()); + self.codegen_log(expr.as_ref()) + } } } + fn codegen_log(&mut self, expression: &Expression) -> Result { + let is_string = match expression { + Expression::Ident(ident) => match ident.typ { + Type::String(_) => true, + _ => false, + }, + Expression::Literal(literal) => match literal { + Literal::Str(_) => true, + _ => false, + }, + _ => unreachable!("logging this expression type is not supported"), + }; + + let node_id = self.codegen_expression(expression)?.unwrap_id(); + let obj_type = self.context.get_object_type(node_id); + let operation = match obj_type { + ObjectType::Pointer(array_id) => { + Operation::Log(LogInfo::Array(ArrayLog { array_id, is_string })) + } + _ => Operation::Log(LogInfo::Node(node_id)), + }; + self.context.new_instruction(operation, ObjectType::NotAnObject)?; + Ok(Value::dummy()) + } + fn codegen_lowlevel(&mut self, call: &CallLowLevel) -> Result { match OPCODE::lookup(&call.opcode) { Some(func) => self.call_low_level(func, call), diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 28439f05573..b2ec0ffc8c5 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -3,7 +3,7 @@ use super::conditional::{DecisionTree, TreeBuilder}; use super::function::{FuncIndex, SSAFunction}; use super::inline::StackFrame; use super::mem::{ArrayId, Memory}; -use super::node::{BinaryOp, Instruction, NodeId, NodeObj, ObjectType, Operation}; +use super::node::{BinaryOp, Instruction, LogInfo, NodeId, NodeObj, ObjectType, Operation}; use super::{block, flatten, inline, integer, node, optim}; use std::collections::{HashMap, HashSet}; @@ -138,7 +138,7 @@ impl SsaContext { } //Display an object for debugging puposes - fn node_to_string(&self, id: NodeId) -> String { + pub fn node_to_string(&self, id: NodeId) -> String { let mut result = String::new(); if let Some(var) = self.try_get_node(id) { result = format!("{}", var); @@ -240,6 +240,14 @@ impl SsaContext { let call = self.node_to_string(*call_instruction); format!("result {} of {}", index, call) } + Operation::Log(log_id) => match log_id { + LogInfo::Array(array_log) => { + format!("log {:?}", array_log.array_id) + } + LogInfo::Node(node_id) => { + format!("log {:?}", self.node_to_string(*node_id)) + } + }, } } diff --git a/crates/noirc_evaluator/src/ssa/inline.rs b/crates/noirc_evaluator/src/ssa/inline.rs index 87ee1914841..1300e4b8aaa 100644 --- a/crates/noirc_evaluator/src/ssa/inline.rs +++ b/crates/noirc_evaluator/src/ssa/inline.rs @@ -408,7 +408,7 @@ impl node::Operation { ) { match self { //default way to handle arrays during inlining; we map arrays using the stack_frame - Operation::Binary(_) | Operation::Constrain(..) | Operation::Intrinsic(_,_) + Operation::Binary(_) | Operation::Constrain(..) | Operation::Intrinsic(_,_) | Operation::Log { .. } => { self.map_id_mut(|id| { if let Some(a) = Memory::deref(ctx, id) { diff --git a/crates/noirc_evaluator/src/ssa/integer.rs b/crates/noirc_evaluator/src/ssa/integer.rs index 6c493562d46..e7a36a5964c 100644 --- a/crates/noirc_evaluator/src/ssa/integer.rs +++ b/crates/noirc_evaluator/src/ssa/integer.rs @@ -481,6 +481,7 @@ fn get_max_value(ins: &Instruction, max_map: &mut HashMap) -> B Operation::Result { .. } => { unreachable!("Functions must have been inlined before checking for overflows") } + Operation::Log { .. } => ins.res_type.max_size(), Operation::Intrinsic(opcode, _) => { match opcode { OPCODE::SHA256 diff --git a/crates/noirc_evaluator/src/ssa/node.rs b/crates/noirc_evaluator/src/ssa/node.rs index c3caccbfd3c..c569dac322f 100644 --- a/crates/noirc_evaluator/src/ssa/node.rs +++ b/crates/noirc_evaluator/src/ssa/node.rs @@ -384,6 +384,7 @@ impl Instruction { Operation::Call { .. } => false, //return values are in the return statment, should we truncate function arguments? probably but not lhs and rhs anyways. Operation::Return(_) => true, Operation::Result { .. } => false, + Operation::Log { .. } => false, } } @@ -550,9 +551,23 @@ pub enum Operation { Intrinsic(OPCODE, Vec), //Custom implementation of usefull primitives which are more performant with Aztec backend + Log(LogInfo), + Nop, // no op } +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub enum LogInfo { + Node(NodeId), + Array(ArrayLog), +} + +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub struct ArrayLog { + pub array_id: ArrayId, + pub is_string: bool, +} + #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] pub enum Opcode { Add, @@ -601,6 +616,9 @@ pub enum Opcode { Store(ArrayId), Intrinsic(OPCODE), //Custom implementation of usefull primitives which are more performant with Aztec backend Nop, // no op + + //logging + Log, } #[derive(Debug, PartialEq, Eq, Hash, Clone)] @@ -1100,6 +1118,10 @@ impl Operation { Result { call_instruction, index } => { Result { call_instruction: f(*call_instruction), index: *index } } + Log(id) => match id { + LogInfo::Array(array_log) => Log(LogInfo::Array(array_log.clone())), + LogInfo::Node(node_id) => Log(LogInfo::Node(f(*node_id))), + }, } } @@ -1154,6 +1176,7 @@ impl Operation { Result { call_instruction, index: _ } => { *call_instruction = f(*call_instruction); } + Log(_) => (), } } @@ -1195,6 +1218,7 @@ impl Operation { Result { call_instruction, .. } => { f(*call_instruction); } + Log(_) => (), } } @@ -1217,6 +1241,7 @@ impl Operation { Operation::Store { array_id, .. } => Opcode::Store(*array_id), Operation::Intrinsic(opcode, _) => Opcode::Intrinsic(*opcode), Operation::Nop => Opcode::Nop, + Operation::Log { .. } => Opcode::Log, } } } diff --git a/crates/noirc_frontend/src/ast/statement.rs b/crates/noirc_frontend/src/ast/statement.rs index e30d05d9dc7..58d039e1b5d 100644 --- a/crates/noirc_frontend/src/ast/statement.rs +++ b/crates/noirc_frontend/src/ast/statement.rs @@ -131,7 +131,7 @@ pub enum Statement { // This is an expression with a trailing semi-colon // terminology Taken from rustc Semi(Expression), - Log(UnresolvedType), + Log(Expression), // This statement is the result of a recovered parse error. // To avoid issuing multiple errors in later steps, it should // be skipped in any future analysis if possible. diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index ee92983cd77..40a173fca6e 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -495,9 +495,9 @@ impl<'a> Resolver<'a> { let stmt = HirAssignStatement { lvalue: identifier, expression }; HirStatement::Assign(stmt) } - Statement::Log(log_stmt) => { - let log_type = self.resolve_type(log_stmt); - HirStatement::Log(log_type) + Statement::Log(log_expr) => { + let expr_id = self.resolve_expression(log_expr); + HirStatement::Log(expr_id) } Statement::Error => HirStatement::Error, } diff --git a/crates/noirc_frontend/src/hir/type_check/stmt.rs b/crates/noirc_frontend/src/hir/type_check/stmt.rs index 9c3ef494b86..a35f3588d75 100644 --- a/crates/noirc_frontend/src/hir/type_check/stmt.rs +++ b/crates/noirc_frontend/src/hir/type_check/stmt.rs @@ -49,6 +49,7 @@ pub(crate) fn type_check( HirStatement::Assign(assign_stmt) => { type_check_assign_stmt(interner, assign_stmt, stmt_id, errors) } + HirStatement::Log(_) => (), // Do not need to type check log expressions right now as we are simply printing a single expressions HirStatement::Error => (), } Type::Unit diff --git a/crates/noirc_frontend/src/hir_def/stmt.rs b/crates/noirc_frontend/src/hir_def/stmt.rs index aab25424918..ed7ec0b8537 100644 --- a/crates/noirc_frontend/src/hir_def/stmt.rs +++ b/crates/noirc_frontend/src/hir_def/stmt.rs @@ -43,7 +43,7 @@ pub enum HirStatement { Assign(HirAssignStatement), Expression(ExprId), Semi(ExprId), - Log(Type), + Log(ExprId), Error, } diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index 10ae95001bb..5791ce8ad0e 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -377,6 +377,7 @@ pub enum Keyword { If, In, Let, + Log, Mod, Mut, Pub, @@ -405,6 +406,7 @@ impl fmt::Display for Keyword { Keyword::If => write!(f, "if"), Keyword::In => write!(f, "in"), Keyword::Let => write!(f, "let"), + Keyword::Log => write!(f, "log"), Keyword::Mod => write!(f, "mod"), Keyword::Mut => write!(f, "mut"), Keyword::Pub => write!(f, "pub"), @@ -438,6 +440,7 @@ impl Keyword { "if" => Keyword::If, "in" => Keyword::In, "let" => Keyword::Let, + "log" => Keyword::Log, "mod" => Keyword::Mod, "mut" => Keyword::Mut, "pub" => Keyword::Pub, diff --git a/crates/noirc_frontend/src/monomorphisation/ast.rs b/crates/noirc_frontend/src/monomorphisation/ast.rs index db5675a6173..2dee0277f22 100644 --- a/crates/noirc_frontend/src/monomorphisation/ast.rs +++ b/crates/noirc_frontend/src/monomorphisation/ast.rs @@ -26,7 +26,7 @@ pub enum Expression { Constrain(Box, Location), Assign(Assign), Semi(Box), - Log(Type), + Log(Box), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/crates/noirc_frontend/src/monomorphisation/mod.rs b/crates/noirc_frontend/src/monomorphisation/mod.rs index dcb82abab92..4e9d811defc 100644 --- a/crates/noirc_frontend/src/monomorphisation/mod.rs +++ b/crates/noirc_frontend/src/monomorphisation/mod.rs @@ -282,7 +282,7 @@ impl Monomorphiser { HirStatement::Assign(assign) => self.assign(assign), HirStatement::Expression(expr) => self.expr_infer(expr), HirStatement::Semi(expr) => ast::Expression::Semi(Box::new(self.expr_infer(expr))), - HirStatement::Log(log_type) => ast::Expression::Log(Self::convert_type(&log_type)), + HirStatement::Log(expr) => ast::Expression::Log(Box::new(self.expr_infer(expr))), HirStatement::Error => unreachable!(), } } diff --git a/crates/noirc_frontend/src/monomorphisation/printer.rs b/crates/noirc_frontend/src/monomorphisation/printer.rs index fd9f5dfbd8a..e0376102c54 100644 --- a/crates/noirc_frontend/src/monomorphisation/printer.rs +++ b/crates/noirc_frontend/src/monomorphisation/printer.rs @@ -73,6 +73,10 @@ impl AstPrinter { self.print_expr(expr, f)?; write!(f, ";") } + Expression::Log(expr) => { + write!(f, "log ")?; + self.print_expr(expr, f) + } } } diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index 9a235e55ea1..88342e1e588 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -336,10 +336,22 @@ where constrain(expr_parser.clone()), declaration(expr_parser.clone()), assignment(expr_parser.clone()), + log(expr_parser.clone()), expr_parser.map(Statement::Expression), )) } +fn log<'a, P>(expr_parser: P) -> impl NoirParser + 'a +where + P: ExprParser + 'a, +{ + let p = ignore_then_commit( + keyword(Keyword::Log).labelled("log"), + expr_parser.delimited_by(just(Token::LeftParen), just(Token::RightParen)), + ); + p.map(|x| Statement::Log(x)) +} + fn constrain<'a, P>(expr_parser: P) -> impl NoirParser + 'a where P: ExprParser + 'a, From 211f14d7d7e6499e2c407f935538ca3f8881acc4 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 12 Jan 2023 15:00:41 -0500 Subject: [PATCH 13/47] switch to using Log directive --- crates/acir/src/circuit/gate.rs | 6 +++++ crates/acvm/src/lib.rs | 4 +++ crates/noirc_evaluator/src/ssa/acir_gen.rs | 30 ++++++---------------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/crates/acir/src/circuit/gate.rs b/crates/acir/src/circuit/gate.rs index c44cb6ccb2c..7d143c2c3a2 100644 --- a/crates/acir/src/circuit/gate.rs +++ b/crates/acir/src/circuit/gate.rs @@ -43,6 +43,7 @@ impl Gate { Gate::Directive(Directive::Oddrange { .. }) => "odd_range", Gate::Directive(Directive::Split { .. }) => "split", Gate::Directive(Directive::ToBytes { .. }) => "to_bytes", + Gate::Directive(Directive::Log(_)) => "log", Gate::GadgetCall(g) => g.name.name(), } } @@ -138,6 +139,9 @@ impl std::fmt::Debug for Gate { b.last().unwrap().witness_index(), ) } + Gate::Directive(Directive::Log(log_string)) => { + write!(f, "Log: {}", log_string) + } } } } @@ -189,6 +193,8 @@ pub enum Directive { b: Vec, byte_size: u32, }, + + Log(String), } // Note: Some gadgets will not use all of the witness diff --git a/crates/acvm/src/lib.rs b/crates/acvm/src/lib.rs index cd561f623a2..01122f585c3 100644 --- a/crates/acvm/src/lib.rs +++ b/crates/acvm/src/lib.rs @@ -227,6 +227,10 @@ pub trait PartialWitnessGenerator { } _ => true, }, + Directive::Log(log_string) => { + println!("{}", log_string); + true + } }, }; if unsolved { diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index 8e5727f7ad6..608c5c95bdf 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -210,11 +210,11 @@ impl Acir { } Operation::Log(log_id) => { - // TODO: switch these prints to string creation and make a Directive to use when solving the ACIR + let mut log_string = "".to_owned(); match log_id { LogInfo::Node(node_id) => match ctx.get_as_constant(*node_id) { Some(field) => { - println!("{}", field) + log_string.push_str(&field.to_hex()); } None => unreachable!("array objects should not be marked as single values"), }, @@ -251,36 +251,22 @@ impl Acir { .collect::>(); let final_string = str::from_utf8(&string_as_slice).unwrap(); - println!("{}", final_string); + log_string.push_str(&final_string); } else { - print!("["); + log_string.push_str("["); let mut iter = field_elements.iter().peekable(); while let Some(elem) = iter.next() { if iter.peek().is_none() { - print!("{}", elem); + log_string.push_str(&elem.to_hex()); } else { - print!("{}, ", elem) + log_string.push_str(&format!("{}, ", elem)); } } - println!("]"); + log_string.push_str("]"); } - // for idx in 0..mem_array.len { - // let absolute_adr = mem_array.absolute_adr(idx); - // if self.memory_map.contains_key(&absolute_adr) { - // let array_elem_expr = self.memory_map[&absolute_adr].expression.clone(); - // if array_elem_expr.is_const() { - // let field_element = array_elem_expr.q_c; - // if array_log.is_string { - - // } else { - // print!("{}, ",field_element) - // } - // } - // // dbg!(self.memory_map[&absolute_adr].expression.to_string()); - // } - // } } } + evaluator.gates.push(Gate::Directive(Directive::Log(log_string))); //we do not generate constraint, so no output. InternalVar::default() } From fce1c8fe4aecf5facaa3208ddf9e8cdf515a2072 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 17 Jan 2023 15:31:28 -0500 Subject: [PATCH 14/47] switch to using builtin function for println rather than having a new opcode in ssa --- crates/acvm/src/lib.rs | 2 +- .../nargo/tests/test_data/strings/src/main.nr | 14 ++-- crates/noirc_abi/src/lib.rs | 4 +- crates/noirc_evaluator/src/ssa/acir_gen.rs | 70 +++++++++++++++++++ crates/noirc_evaluator/src/ssa/builtin.rs | 8 ++- crates/noirc_evaluator/src/ssa/code_gen.rs | 54 ++++++-------- crates/noirc_evaluator/src/ssa/optim.rs | 33 +++++---- crates/noirc_frontend/src/ast/statement.rs | 3 - .../src/hir/resolution/resolver.rs | 4 -- .../noirc_frontend/src/hir/type_check/stmt.rs | 1 - crates/noirc_frontend/src/hir_def/stmt.rs | 1 - .../src/monomorphisation/ast.rs | 1 - .../src/monomorphisation/mod.rs | 1 - .../src/monomorphisation/printer.rs | 4 -- crates/noirc_frontend/src/parser/parser.rs | 12 ---- noir_stdlib/src/lib.nr | 3 +- 16 files changed, 133 insertions(+), 82 deletions(-) diff --git a/crates/acvm/src/lib.rs b/crates/acvm/src/lib.rs index cbc8c2e705b..d39dbdbd0a7 100644 --- a/crates/acvm/src/lib.rs +++ b/crates/acvm/src/lib.rs @@ -210,7 +210,7 @@ pub trait PartialWitnessGenerator { }, Directive::Log(log_string) => { println!("{}", log_string); - true + false } }, }; diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index 5092cddecee..e3fe7365042 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -5,17 +5,19 @@ fn main(message : pub str[11], y : Field) { constrain message == "hello world"; bad_message = "helld world"; - let x = 2; - log(x); + let x = 10; + let z = x * 5; + std::println(x); + std::println(z); + std::println(bad_message); // Currently broken // let hash = std::hash::pedersen([x])[0]; - // log(bad_message); - log("five"); + // std::println("five"); let array = [1, 2, 3, 5, 8]; - constrain y != 5; - log(array); + constrain y == 5; + std::println(array); 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 d6341be87d9..6c8371b8e50 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -46,7 +46,9 @@ pub enum AbiType { )] fields: BTreeMap, }, - String { length: u64 }, + String { + length: u64, + }, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index d93e91f50dd..e0df30ad2cd 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -642,6 +642,10 @@ impl Acir { self.map_array(a, &outputs, ctx); } } + Opcode::Println(is_string_output) => { + outputs = Vec::new(); // print statements do not output anything + self.evaluate_println(is_string_output, args, ctx, evaluator); + } Opcode::LowLevel(op) => { let inputs = self.prepare_inputs(args, ctx, evaluator); let output_count = op.definition().output_size.0 as u32; @@ -684,6 +688,72 @@ impl Acir { } outputs } + + fn evaluate_println( + &mut self, + is_string_output: bool, + args: &[NodeId], + ctx: &SsaContext, + evaluator: &mut Evaluator, + ) { + assert!(args.len() == 1, "print statements currently only support one argument"); + let node_id = args[0]; + let obj_type = ctx.get_object_type(node_id); + let mut log_string = "".to_owned(); + match obj_type { + ObjectType::Pointer(array_id) => { + let mem_array = &ctx.mem[array_id]; + let mut field_elements = Vec::new(); + for idx in 0..mem_array.len { + let absolute_adr = mem_array.absolute_adr(idx); + if self.memory_map.contains_key(&absolute_adr) { + let array_elem_expr = self.memory_map[&absolute_adr].expression.clone(); + if array_elem_expr.is_const() { + field_elements.push(array_elem_expr.q_c) + } else { + unreachable!("array elements being logging must be const"); + } + } else { + // TODO add handling for if key not found + unreachable!("array element being logging does not exist in memory"); + } + } + if is_string_output { + // TODO: make a decode_string_value method in noirc_abi and use it here this is reused code + let string_as_slice = field_elements + .iter() + .map(|e| { + 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::>(); + + let final_string = str::from_utf8(&string_as_slice).unwrap(); + log_string.push_str(&final_string); + } else { + log_string.push_str("["); + let mut iter = field_elements.iter().peekable(); + while let Some(elem) = iter.next() { + if iter.peek().is_none() { + log_string.push_str(&format!("{}", elem)); + } else { + log_string.push_str(&format!("{}, ", elem)); + } + } + log_string.push_str("]"); + } + } + _ => match ctx.get_as_constant(node_id) { + Some(field) => { + log_string.push_str(&field.to_hex()); + } + None => unreachable!("array objects should not be marked as single values"), + }, + }; + evaluator.gates.push(Gate::Directive(Directive::Log(log_string))); + } } pub fn evaluate_sdiv( diff --git a/crates/noirc_evaluator/src/ssa/builtin.rs b/crates/noirc_evaluator/src/ssa/builtin.rs index 41f7a7ca1d7..f0e26074691 100644 --- a/crates/noirc_evaluator/src/ssa/builtin.rs +++ b/crates/noirc_evaluator/src/ssa/builtin.rs @@ -9,6 +9,9 @@ pub enum Opcode { LowLevel(OPCODE), ToBits, ToRadix, + // We store strings as arrays and there is no differentiation between them in the SSA. + // This bool simply states whether an array that is to be printed should be outputted as a utf8 string + Println(bool), } impl std::fmt::Display for Opcode { @@ -22,6 +25,7 @@ impl Opcode { match op_name { "to_bits" => Some(Opcode::ToBits), "to_radix" => Some(Opcode::ToRadix), + "println" => Some(Opcode::Println(false)), _ => OPCODE::lookup(op_name).map(Opcode::LowLevel), } } @@ -31,6 +35,7 @@ impl Opcode { Opcode::LowLevel(op) => op.name(), Opcode::ToBits => "to_bits", Opcode::ToRadix => "to_radix", + Opcode::Println(_) => "println", } } @@ -49,7 +54,7 @@ impl Opcode { _ => todo!("max value must be implemented for opcode {} ", op), } } - Opcode::ToBits | Opcode::ToRadix => BigUint::zero(), //pointers do not overflow + Opcode::ToBits | Opcode::ToRadix | Opcode::Println(_) => BigUint::zero(), //pointers do not overflow } } @@ -71,6 +76,7 @@ impl Opcode { } Opcode::ToBits => (FieldElement::max_num_bits(), ObjectType::Boolean), Opcode::ToRadix => (FieldElement::max_num_bits(), ObjectType::NativeField), + Opcode::Println(_) => (0, ObjectType::NotAnObject), } } } diff --git a/crates/noirc_evaluator/src/ssa/code_gen.rs b/crates/noirc_evaluator/src/ssa/code_gen.rs index 2145d897535..ba92c7aab20 100644 --- a/crates/noirc_evaluator/src/ssa/code_gen.rs +++ b/crates/noirc_evaluator/src/ssa/code_gen.rs @@ -626,48 +626,38 @@ impl IRGenerator { self.codegen_expression(expr.as_ref())?; Ok(Value::dummy()) } - Expression::Log(expr) => { - // dbg!(expr.as_ref()); - self.codegen_log(expr.as_ref()) - } } } - fn codegen_log(&mut self, expression: &Expression) -> Result { - let is_string = match expression { - Expression::Ident(ident) => match ident.typ { - Type::String(_) => true, - _ => false, - }, - Expression::Literal(literal) => match literal { - Literal::Str(_) => true, - _ => false, - }, - _ => unreachable!("logging this expression type is not supported"), - }; - - let node_id = self.codegen_expression(expression)?.unwrap_id(); - let obj_type = self.context.get_object_type(node_id); - let operation = match obj_type { - ObjectType::Pointer(array_id) => { - Operation::Log(LogInfo::Array(ArrayLog { array_id, is_string })) - } - _ => Operation::Log(LogInfo::Node(node_id)), - }; - self.context.new_instruction(operation, ObjectType::NotAnObject)?; - Ok(Value::dummy()) - } - fn codegen_lowlevel(&mut self, call: &CallLowLevel) -> Result { - match super::builtin::Opcode::lookup(&call.opcode) { - Some(func) => self.call_low_level(func, call), + let func = match super::builtin::Opcode::lookup(&call.opcode) { + Some(super::builtin::Opcode::Println(_)) => { + assert!( + call.arguments.len() == 1, + "print statements currently only support one argument" + ); + let is_string = match &call.arguments[0] { + Expression::Ident(ident) => match ident.typ { + Type::String(_) => true, + _ => false, + }, + Expression::Literal(literal) => match literal { + Literal::Str(_) => true, + _ => false, + }, + _ => unreachable!("logging this expression type is not supported"), + }; + super::builtin::Opcode::Println(is_string) + } + Some(func) => func, None => { unreachable!( "cannot find a low level opcode with the name {} in the IR", &call.opcode ) } - } + }; + self.call_low_level(func, call) } fn codegen_literal(&mut self, l: &Literal) -> NodeId { diff --git a/crates/noirc_evaluator/src/ssa/optim.rs b/crates/noirc_evaluator/src/ssa/optim.rs index 07e6b481a2d..56072534f8d 100644 --- a/crates/noirc_evaluator/src/ssa/optim.rs +++ b/crates/noirc_evaluator/src/ssa/optim.rs @@ -67,6 +67,8 @@ fn evaluate_intrinsic( res_type: &ObjectType, block_id: BlockId, ) -> Vec { + dbg!(args.clone()); + dbg!(res_type.clone()); match op { builtin::Opcode::ToBits => { let bit_count = args[1] as u32; @@ -353,19 +355,24 @@ fn cse_block_with_anchor( //cannot simplify to_bits() in the previous call because it get replaced with multiple instructions if let Operation::Intrinsic(opcode, args) = &update2.operation { - let args = args.iter().map(|arg| { - NodeEval::from_id(ctx, *arg).into_const_value().map(|f| f.to_u128()) - }); - - if let Some(args) = args.collect() { - update2.mark = Mark::Deleted; - new_list.extend(evaluate_intrinsic( - ctx, - *opcode, - args, - &update2.res_type, - block_id, - )); + match opcode { + builtin::Opcode::Println(_) => (), + _ => { + let args = args.iter().map(|arg| { + NodeEval::from_id(ctx, *arg).into_const_value().map(|f| f.to_u128()) + }); + + if let Some(args) = args.collect() { + update2.mark = Mark::Deleted; + new_list.extend(evaluate_intrinsic( + ctx, + *opcode, + args, + &update2.res_type, + block_id, + )); + } + } } } let update3 = ctx.get_mut_instruction(*ins_id); diff --git a/crates/noirc_frontend/src/ast/statement.rs b/crates/noirc_frontend/src/ast/statement.rs index 8ddbe4bfcd6..2f823ef2c4f 100644 --- a/crates/noirc_frontend/src/ast/statement.rs +++ b/crates/noirc_frontend/src/ast/statement.rs @@ -131,7 +131,6 @@ pub enum Statement { // This is an expression with a trailing semi-colon // terminology Taken from rustc Semi(Expression), - Log(Expression), // This statement is the result of a recovered parse error. // To avoid issuing multiple errors in later steps, it should // be skipped in any future analysis if possible. @@ -163,7 +162,6 @@ impl Statement { | Statement::Constrain(_) | Statement::Assign(_) | Statement::Semi(_) - | Statement::Log(_) | Statement::Error => { // To match rust, statements always require a semicolon, even at the end of a block if semi.is_none() { @@ -350,7 +348,6 @@ impl Display for Statement { Statement::Expression(expression) => expression.fmt(f), Statement::Assign(assign) => assign.fmt(f), Statement::Semi(semi) => write!(f, "{semi};"), - Statement::Log(log) => log.fmt(f), Statement::Error => write!(f, "Error"), } } diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index 2f4e3458bc5..b05c6a54be3 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -495,10 +495,6 @@ impl<'a> Resolver<'a> { let stmt = HirAssignStatement { lvalue: identifier, expression }; HirStatement::Assign(stmt) } - Statement::Log(log_expr) => { - let expr_id = self.resolve_expression(log_expr); - HirStatement::Log(expr_id) - } Statement::Error => HirStatement::Error, } } diff --git a/crates/noirc_frontend/src/hir/type_check/stmt.rs b/crates/noirc_frontend/src/hir/type_check/stmt.rs index 46b87b869d7..bcd50112cf1 100644 --- a/crates/noirc_frontend/src/hir/type_check/stmt.rs +++ b/crates/noirc_frontend/src/hir/type_check/stmt.rs @@ -49,7 +49,6 @@ pub(crate) fn type_check( HirStatement::Assign(assign_stmt) => { type_check_assign_stmt(interner, assign_stmt, stmt_id, errors) } - HirStatement::Log(_) => (), // Do not need to type check log expressions right now as we are simply printing a single expressions HirStatement::Error => (), } Type::Unit diff --git a/crates/noirc_frontend/src/hir_def/stmt.rs b/crates/noirc_frontend/src/hir_def/stmt.rs index 59b02230a75..551b72931fb 100644 --- a/crates/noirc_frontend/src/hir_def/stmt.rs +++ b/crates/noirc_frontend/src/hir_def/stmt.rs @@ -43,7 +43,6 @@ pub enum HirStatement { Assign(HirAssignStatement), Expression(ExprId), Semi(ExprId), - Log(ExprId), Error, } diff --git a/crates/noirc_frontend/src/monomorphisation/ast.rs b/crates/noirc_frontend/src/monomorphisation/ast.rs index 7df72b42752..121c9e64adc 100644 --- a/crates/noirc_frontend/src/monomorphisation/ast.rs +++ b/crates/noirc_frontend/src/monomorphisation/ast.rs @@ -26,7 +26,6 @@ pub enum Expression { Constrain(Box, Location), Assign(Assign), Semi(Box), - Log(Box), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/crates/noirc_frontend/src/monomorphisation/mod.rs b/crates/noirc_frontend/src/monomorphisation/mod.rs index 4e9d811defc..bb6fe81d074 100644 --- a/crates/noirc_frontend/src/monomorphisation/mod.rs +++ b/crates/noirc_frontend/src/monomorphisation/mod.rs @@ -282,7 +282,6 @@ impl Monomorphiser { HirStatement::Assign(assign) => self.assign(assign), HirStatement::Expression(expr) => self.expr_infer(expr), HirStatement::Semi(expr) => ast::Expression::Semi(Box::new(self.expr_infer(expr))), - HirStatement::Log(expr) => ast::Expression::Log(Box::new(self.expr_infer(expr))), HirStatement::Error => unreachable!(), } } diff --git a/crates/noirc_frontend/src/monomorphisation/printer.rs b/crates/noirc_frontend/src/monomorphisation/printer.rs index 648b0023e92..567def2ec34 100644 --- a/crates/noirc_frontend/src/monomorphisation/printer.rs +++ b/crates/noirc_frontend/src/monomorphisation/printer.rs @@ -73,10 +73,6 @@ impl AstPrinter { self.print_expr(expr, f)?; write!(f, ";") } - Expression::Log(expr) => { - write!(f, "log ")?; - self.print_expr(expr, f) - } } } diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index 73bb6580142..ef08249f882 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -336,22 +336,10 @@ where constrain(expr_parser.clone()), declaration(expr_parser.clone()), assignment(expr_parser.clone()), - log(expr_parser.clone()), expr_parser.map(Statement::Expression), )) } -fn log<'a, P>(expr_parser: P) -> impl NoirParser + 'a -where - P: ExprParser + 'a, -{ - let p = ignore_then_commit( - keyword(Keyword::Log).labelled("log"), - expr_parser.delimited_by(just(Token::LeftParen), just(Token::RightParen)), - ); - p.map(|x| Statement::Log(x)) -} - fn constrain<'a, P>(expr_parser: P) -> impl NoirParser + 'a where P: ExprParser + 'a, diff --git a/noir_stdlib/src/lib.nr b/noir_stdlib/src/lib.nr index 828a8f39ee4..87434aba5f2 100644 --- a/noir_stdlib/src/lib.nr +++ b/noir_stdlib/src/lib.nr @@ -20,7 +20,8 @@ fn to_bytes(x : Field, byte_size: u32) -> [u8] { //_radix must be less than 256 fn to_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] {} - +#[builtin(println)] +fn println(_input : T) {} // Returns base^exponent. // ^ means to the power of and not xor From 68ceb23a4a81bbe1528ba8aa5c1a18210b808db4 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 17 Jan 2023 15:35:52 -0500 Subject: [PATCH 15/47] some missing cleanup to remove Log operation from SSA --- crates/noirc_evaluator/src/ssa/acir_gen.rs | 62 ---------------------- crates/noirc_evaluator/src/ssa/context.rs | 8 --- crates/noirc_evaluator/src/ssa/inline.rs | 2 +- crates/noirc_evaluator/src/ssa/integer.rs | 1 - crates/noirc_evaluator/src/ssa/node.rs | 13 ----- 5 files changed, 1 insertion(+), 85 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index e0df30ad2cd..c39a249ee25 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -229,68 +229,6 @@ impl Acir { todo!("dynamic arrays are not implemented yet"); } } - - Operation::Log(log_id) => { - let mut log_string = "".to_owned(); - match log_id { - LogInfo::Node(node_id) => match ctx.get_as_constant(*node_id) { - Some(field) => { - log_string.push_str(&field.to_hex()); - } - None => unreachable!("array objects should not be marked as single values"), - }, - LogInfo::Array(array_log) => { - let mem_array = &ctx.mem[array_log.array_id]; - let mut field_elements = Vec::new(); - for idx in 0..mem_array.len { - let absolute_adr = mem_array.absolute_adr(idx); - if self.memory_map.contains_key(&absolute_adr) { - let array_elem_expr = - self.memory_map[&absolute_adr].expression.clone(); - if array_elem_expr.is_const() { - field_elements.push(array_elem_expr.q_c) - } else { - unreachable!("array elements being logging must be const"); - } - } else { - // TODO add handling for if key not found - unreachable!( - "array element being logging does not exist in memory" - ); - } - } - if array_log.is_string { - // TODO: make a decode_string_value method in noirc_abi and use it here this is reused code - let string_as_slice = field_elements - .iter() - .map(|e| { - 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::>(); - - let final_string = str::from_utf8(&string_as_slice).unwrap(); - log_string.push_str(&final_string); - } else { - log_string.push_str("["); - let mut iter = field_elements.iter().peekable(); - while let Some(elem) = iter.next() { - if iter.peek().is_none() { - log_string.push_str(&elem.to_hex()); - } else { - log_string.push_str(&format!("{}, ", elem)); - } - } - log_string.push_str("]"); - } - } - } - evaluator.gates.push(Gate::Directive(Directive::Log(log_string))); - //we do not generate constraint, so no output. - InternalVar::default() - } }; output.id = Some(ins.id); self.arith_cache.insert(ins.id, output); diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 5f1fa077ea7..bd0d2e74af3 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -236,14 +236,6 @@ impl SsaContext { let call = self.node_to_string(*call_instruction); format!("result {index} of {call}") } - Operation::Log(log_id) => match log_id { - LogInfo::Array(array_log) => { - format!("log {:?}", array_log.array_id) - } - LogInfo::Node(node_id) => { - format!("log {:?}", self.node_to_string(*node_id)) - } - }, } } diff --git a/crates/noirc_evaluator/src/ssa/inline.rs b/crates/noirc_evaluator/src/ssa/inline.rs index 1300e4b8aaa..87ee1914841 100644 --- a/crates/noirc_evaluator/src/ssa/inline.rs +++ b/crates/noirc_evaluator/src/ssa/inline.rs @@ -408,7 +408,7 @@ impl node::Operation { ) { match self { //default way to handle arrays during inlining; we map arrays using the stack_frame - Operation::Binary(_) | Operation::Constrain(..) | Operation::Intrinsic(_,_) | Operation::Log { .. } + Operation::Binary(_) | Operation::Constrain(..) | Operation::Intrinsic(_,_) => { self.map_id_mut(|id| { if let Some(a) = Memory::deref(ctx, id) { diff --git a/crates/noirc_evaluator/src/ssa/integer.rs b/crates/noirc_evaluator/src/ssa/integer.rs index 0d4531b5df6..03450c36072 100644 --- a/crates/noirc_evaluator/src/ssa/integer.rs +++ b/crates/noirc_evaluator/src/ssa/integer.rs @@ -481,7 +481,6 @@ fn get_max_value(ins: &Instruction, max_map: &mut HashMap) -> B Operation::Result { .. } => { unreachable!("Functions must have been inlined before checking for overflows") } - Operation::Log { .. } => ins.res_type.max_size(), Operation::Intrinsic(opcode, _) => opcode.get_max_value(), }; diff --git a/crates/noirc_evaluator/src/ssa/node.rs b/crates/noirc_evaluator/src/ssa/node.rs index fc10cda9b47..c119bff09e0 100644 --- a/crates/noirc_evaluator/src/ssa/node.rs +++ b/crates/noirc_evaluator/src/ssa/node.rs @@ -383,7 +383,6 @@ impl Instruction { Operation::Call { .. } => false, //return values are in the return statment, should we truncate function arguments? probably but not lhs and rhs anyways. Operation::Return(_) => true, Operation::Result { .. } => false, - Operation::Log { .. } => false, } } @@ -550,8 +549,6 @@ pub enum Operation { Intrinsic(builtin::Opcode, Vec), //Custom implementation of usefull primitives which are more performant with Aztec backend - Log(LogInfo), - Nop, // no op } @@ -615,9 +612,6 @@ pub enum Opcode { Store(ArrayId), Intrinsic(builtin::Opcode), //Custom implementation of useful primitives Nop, // no op - - // TODO: switch this to use Instrinsic opcode to avoid a new operation in the SSA for logging - Log, //logging } #[derive(Debug, PartialEq, Eq, Hash, Clone)] @@ -1117,10 +1111,6 @@ impl Operation { Result { call_instruction, index } => { Result { call_instruction: f(*call_instruction), index: *index } } - Log(id) => match id { - LogInfo::Array(array_log) => Log(LogInfo::Array(array_log.clone())), - LogInfo::Node(node_id) => Log(LogInfo::Node(f(*node_id))), - }, } } @@ -1175,7 +1165,6 @@ impl Operation { Result { call_instruction, index: _ } => { *call_instruction = f(*call_instruction); } - Log(_) => (), } } @@ -1217,7 +1206,6 @@ impl Operation { Result { call_instruction, .. } => { f(*call_instruction); } - Log(_) => (), } } @@ -1240,7 +1228,6 @@ impl Operation { Operation::Store { array_id, .. } => Opcode::Store(*array_id), Operation::Intrinsic(opcode, _) => Opcode::Intrinsic(*opcode), Operation::Nop => Opcode::Nop, - Operation::Log { .. } => Opcode::Log, } } } From 279d266a3955b1514d55ea09e6f2252c541786e1 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 17 Jan 2023 16:05:35 -0500 Subject: [PATCH 16/47] 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 e5f39270151d106234fe13c76e8b590623ce60f7 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 17 Jan 2023 16:24:55 -0500 Subject: [PATCH 17/47] cargo fmt --- crates/noirc_evaluator/src/ssa/acir_gen.rs | 8 ++-- crates/noirc_evaluator/src/ssa/context.rs | 48 +++++++++++----------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index a81d8e74935..87cfa1e11bc 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -3,10 +3,6 @@ use super::mem::{ArrayId, MemArray, Memory}; use super::node::{BinaryOp, Instruction, NodeId, ObjectType, Operation}; use acvm::FieldElement; -use num_traits::{One, Zero}; -use std::cmp::Ordering; -use std::ops::{Mul, Neg}; -use std::{collections::HashMap, str}; use crate::ssa::context::SsaContext; use crate::ssa::node::Node; use crate::ssa::{mem, node}; @@ -16,6 +12,10 @@ use crate::RuntimeErrorKind; use acvm::acir::circuit::gate::{Directive, GadgetCall, GadgetInput}; use acvm::acir::native_types::{Expression, Linear, Witness}; use num_bigint::BigUint; +use num_traits::{One, Zero}; +use std::cmp::Ordering; +use std::ops::{Mul, Neg}; +use std::{collections::HashMap, str}; #[derive(Default)] pub struct Acir { diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 2bbe53d7013..d0f41959a8c 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -14,7 +14,7 @@ use crate::ssa::node::{Mark, Node}; use crate::Evaluator; use acvm::FieldElement; use iter_extended::vecmap; -use noirc_frontend::monomorphisation::ast::{Definition, FuncId, Expression, Type, Literal}; +use noirc_frontend::monomorphisation::ast::{Definition, Expression, FuncId, Literal, Type}; use num_bigint::BigUint; use num_traits::{One, Zero}; @@ -1100,30 +1100,32 @@ impl SsaContext { NodeId(index) } - pub fn get_builtin_opcode(&self, node_id: NodeId, arguments: &[Expression]) -> Option { + pub fn get_builtin_opcode( + &self, + node_id: NodeId, + arguments: &[Expression], + ) -> Option { match &self[node_id] { - NodeObj::Function(FunctionKind::Builtin(opcode), ..) => { - match opcode { - builtin::Opcode::Println(_) => { - assert!( - arguments.len() == 1, - "print statements currently only support one argument" - ); - let is_string = match &arguments[0] { - Expression::Ident(ident) => match ident.typ { - Type::String(_) => true, - _ => false, - }, - Expression::Literal(literal) => match literal { - Literal::Str(_) => true, - _ => false, - }, - _ => unreachable!("logging this expression type is not supported"), - }; - Some(builtin::Opcode::Println(is_string)) - } - _ => Some(*opcode), + NodeObj::Function(FunctionKind::Builtin(opcode), ..) => match opcode { + builtin::Opcode::Println(_) => { + assert!( + arguments.len() == 1, + "print statements currently only support one argument" + ); + let is_string = match &arguments[0] { + Expression::Ident(ident) => match ident.typ { + Type::String(_) => true, + _ => false, + }, + Expression::Literal(literal) => match literal { + Literal::Str(_) => true, + _ => false, + }, + _ => unreachable!("logging this expression type is not supported"), + }; + Some(builtin::Opcode::Println(is_string)) } + _ => Some(*opcode), }, _ => None, } From dcb3a0ac2986b4623d9a570833469a3746f827c7 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 17 Jan 2023 17:40:26 -0500 Subject: [PATCH 18/47] 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 3f7a7fc0ed7089459eae83ea3ed399245ad96552 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 17 Jan 2023 22:23:21 -0500 Subject: [PATCH 19/47] decode method for string of field into abi string --- crates/noirc_abi/src/lib.rs | 27 +++++++++++++--------- crates/noirc_evaluator/src/ssa/acir_gen.rs | 15 ++---------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index 6c8371b8e50..22130b71e5a 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -268,17 +268,7 @@ impl Abi { AbiType::String { length } => { let field_elements = &encoded_inputs[index..index + (*length as usize)]; - let string_as_slice = field_elements - .iter() - .map(|e| { - 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::>(); - - let final_string = str::from_utf8(&string_as_slice).unwrap(); + let final_string = decode_string_value(field_elements); index += *length as usize; InputValue::String(final_string.to_owned()) @@ -301,3 +291,18 @@ impl Abi { Ok((index, value)) } } + +pub fn decode_string_value(field_elements: &[FieldElement]) -> String { + let string_as_slice = field_elements + .iter() + .map(|e| { + 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::>(); + + let final_string = str::from_utf8(&string_as_slice).unwrap(); + final_string.to_owned() +} diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index 87cfa1e11bc..b068e565fe2 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -632,7 +632,7 @@ impl Acir { ctx: &SsaContext, evaluator: &mut Evaluator, ) { - assert!(args.len() == 1, "print statements currently only support one argument"); + assert!(args.len() == 1, "print statements can only support one argument"); let node_id = args[0]; let obj_type = ctx.get_object_type(node_id); let mut log_string = "".to_owned(); @@ -655,18 +655,7 @@ impl Acir { } } if is_string_output { - // TODO: make a decode_string_value method in noirc_abi and use it here this is reused code - let string_as_slice = field_elements - .iter() - .map(|e| { - 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::>(); - - let final_string = str::from_utf8(&string_as_slice).unwrap(); + let final_string = noirc_abi::decode_string_value(&field_elements); log_string.push_str(&final_string); } else { log_string.push_str("["); From 3dbee515eda644eee5ef5ec158e34f39d283924f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 17 Jan 2023 22:31:21 -0500 Subject: [PATCH 20/47] small cleanuo --- crates/noirc_evaluator/src/ssa/acir_gen.rs | 2 +- crates/noirc_evaluator/src/ssa/optim.rs | 2 -- crates/noirc_frontend/src/lexer/token.rs | 3 --- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index b068e565fe2..04ca306ed96 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -672,7 +672,7 @@ impl Acir { } _ => match ctx.get_as_constant(node_id) { Some(field) => { - log_string.push_str(&field.to_hex()); + log_string.push_str(&format!("{}", field)); } None => unreachable!("array objects should not be marked as single values"), }, diff --git a/crates/noirc_evaluator/src/ssa/optim.rs b/crates/noirc_evaluator/src/ssa/optim.rs index 1eaa22aa8a5..cfb22072757 100644 --- a/crates/noirc_evaluator/src/ssa/optim.rs +++ b/crates/noirc_evaluator/src/ssa/optim.rs @@ -67,8 +67,6 @@ fn evaluate_intrinsic( res_type: &ObjectType, block_id: BlockId, ) -> Vec { - dbg!(args.clone()); - dbg!(res_type.clone()); match op { builtin::Opcode::ToBits => { let bit_count = args[1] as u32; diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index f4e9fe30dd4..860f00b1f1f 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -377,7 +377,6 @@ pub enum Keyword { If, In, Let, - Log, Mod, Mut, Pub, @@ -407,7 +406,6 @@ impl fmt::Display for Keyword { Keyword::If => write!(f, "if"), Keyword::In => write!(f, "in"), Keyword::Let => write!(f, "let"), - Keyword::Log => write!(f, "log"), Keyword::Mod => write!(f, "mod"), Keyword::Mut => write!(f, "mut"), Keyword::Pub => write!(f, "pub"), @@ -442,7 +440,6 @@ impl Keyword { "if" => Keyword::If, "in" => Keyword::In, "let" => Keyword::Let, - "log" => Keyword::Log, "mod" => Keyword::Mod, "mut" => Keyword::Mut, "pub" => Keyword::Pub, From a1756b9273ca755e3767bfd13f71e78b69248484 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 18 Jan 2023 17:50:46 -0500 Subject: [PATCH 21/47] println for blackbox func output now working. need to still do some final testing and cleanup --- crates/acir/src/circuit/gate.rs | 23 +++++-- crates/acvm/src/lib.rs | 40 +++++++++++- .../nargo/tests/test_data/strings/src/main.nr | 15 ++--- crates/noirc_evaluator/src/ssa/acir_gen.rs | 61 +++++++++++++++---- crates/noirc_evaluator/src/ssa/optim.rs | 11 +++- 5 files changed, 125 insertions(+), 25 deletions(-) diff --git a/crates/acir/src/circuit/gate.rs b/crates/acir/src/circuit/gate.rs index 300c8fe034c..1f2cd50e477 100644 --- a/crates/acir/src/circuit/gate.rs +++ b/crates/acir/src/circuit/gate.rs @@ -42,7 +42,7 @@ impl Gate { Gate::Directive(Directive::Quotient { .. }) => "quotient", Gate::Directive(Directive::Oddrange { .. }) => "odd_range", Gate::Directive(Directive::ToRadix { .. }) => "to_radix", - Gate::Directive(Directive::Log(_)) => "log", + Gate::Directive(Directive::Log { .. }) => "log", Gate::GadgetCall(g) => g.name.name(), } } @@ -130,8 +130,17 @@ impl std::fmt::Debug for Gate { b.last().unwrap().witness_index(), ) } - Gate::Directive(Directive::Log(log_string)) => { - write!(f, "Log: {}", log_string) + Gate::Directive(Directive::Log { output_string, witnesses }) => { + if !witnesses.is_empty() { + write!( + f, + "Log: x{}...x{}", + witnesses.first().unwrap().witness_index(), + witnesses.last().unwrap().witness_index() + ) + } else { + write!(f, "Log: {}", output_string) + } } } } @@ -178,7 +187,13 @@ pub enum Directive { radix: u32, }, - Log(String), + // If values are compile time and known during evaluation we can form an output string during ACIR gen + // Otherwise, we must store the witnesses to fetch during the PWG. If the witnesses vector is not empty + // we know that we must construct the output string in the PWG. + Log { + output_string: String, + witnesses: Vec, + }, } // Note: Some gadgets will not use all of the witness diff --git a/crates/acvm/src/lib.rs b/crates/acvm/src/lib.rs index d39dbdbd0a7..fbc4652f4bc 100644 --- a/crates/acvm/src/lib.rs +++ b/crates/acvm/src/lib.rs @@ -208,8 +208,44 @@ pub trait PartialWitnessGenerator { } _ => true, }, - Directive::Log(log_string) => { - println!("{}", log_string); + Directive::Log { output_string, witnesses } => { + if !witnesses.is_empty() { + if witnesses.len() == 1 { + match initial_witness.entry(witnesses[0]) { + std::collections::btree_map::Entry::Vacant(_) => { + unreachable!("log entry does must have a witness"); + } + std::collections::btree_map::Entry::Occupied(e) => { + println!("{}", e.get().to_hex()); + } + } + } else { + let mut output_witnesses_string = "".to_owned(); + output_witnesses_string.push_str("["); + let mut iter = witnesses.iter().peekable(); + while let Some(w) = iter.next() { + let elem = match initial_witness.entry(*w) { + std::collections::btree_map::Entry::Vacant(_) => { + unreachable!("log entry does must have a witness"); + } + std::collections::btree_map::Entry::Occupied(e) => { + e.get().clone() + } + }; + if iter.peek().is_none() { + output_witnesses_string + .push_str(&format!("{}", elem.to_hex())); + } else { + output_witnesses_string + .push_str(&format!("{}, ", elem.to_hex())); + } + } + output_witnesses_string.push_str("]"); + println!("{}", output_witnesses_string); + } + } else { + println!("{}", output_string); + } false } }, diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index e3fe7365042..ce12584e041 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -7,17 +7,18 @@ fn main(message : pub str[11], y : Field) { bad_message = "helld world"; let x = 10; let z = x * 5; - std::println(x); - std::println(z); - std::println(bad_message); + std::println(10); - // Currently broken - // let hash = std::hash::pedersen([x])[0]; - // std::println("five"); + std::println(z); // x * 5 in println not yet supported + std::println(x); let array = [1, 2, 3, 5, 8]; - constrain y == 5; + constrain y == 5; // Change to y != 5 to see how the later print statements are not called std::println(array); + std::println(bad_message); constrain message != bad_message; + + let hash = std::hash::pedersen([x]); + std::println(hash); } \ No newline at end of file diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index 04ca306ed96..16e0ea3d3d5 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -14,8 +14,8 @@ use acvm::acir::native_types::{Expression, Linear, Witness}; use num_bigint::BigUint; use num_traits::{One, Zero}; use std::cmp::Ordering; +use std::collections::HashMap; use std::ops::{Mul, Neg}; -use std::{collections::HashMap, str}; #[derive(Default)] pub struct Acir { @@ -634,8 +634,11 @@ impl Acir { ) { assert!(args.len() == 1, "print statements can only support one argument"); let node_id = args[0]; - let obj_type = ctx.get_object_type(node_id); + let mut log_string = "".to_owned(); + let mut log_witnesses = Vec::new(); + + let obj_type = ctx.get_object_type(node_id); match obj_type { ObjectType::Pointer(array_id) => { let mem_array = &ctx.mem[array_id]; @@ -647,24 +650,36 @@ impl Acir { if array_elem_expr.is_const() { field_elements.push(array_elem_expr.q_c) } else { - unreachable!("array elements being logging must be const"); + if self.arith_cache.contains_key(&node_id) { + let var = self.arith_cache[&node_id].clone(); + if let Some(w) = var.witness { + log_witnesses.push(w); + } + } else { + let var = InternalVar::from(array_elem_expr); + if let Some(w) = var.witness { + log_witnesses.push(w); + } else { + unreachable!("array element to be logged is missing a witness"); + } + } } } else { - // TODO add handling for if key not found - unreachable!("array element being logging does not exist in memory"); + unreachable!("array element being logged does not exist in memory"); } } + if is_string_output { let final_string = noirc_abi::decode_string_value(&field_elements); log_string.push_str(&final_string); - } else { + } else if !field_elements.is_empty() { log_string.push_str("["); let mut iter = field_elements.iter().peekable(); while let Some(elem) = iter.next() { if iter.peek().is_none() { - log_string.push_str(&format!("{}", elem)); + log_string.push_str(&format!("{}", elem.to_hex())); } else { - log_string.push_str(&format!("{}, ", elem)); + log_string.push_str(&format!("{}, ", elem.to_hex())); } } log_string.push_str("]"); @@ -672,12 +687,36 @@ impl Acir { } _ => match ctx.get_as_constant(node_id) { Some(field) => { - log_string.push_str(&format!("{}", field)); + log_string.push_str(&format!("{}", field.to_hex())); + } + None => { + if self.arith_cache.contains_key(&node_id) { + let var = self.arith_cache[&node_id].clone(); + dbg!(var.clone()); + if let Some(field) = var.to_const() { + log_string.push_str(&format!("{}", field.to_hex())); + } else if let Some(w) = var.witness { + log_witnesses.push(w); + } else { + unreachable!("array element to be logged is missing a witness"); + } + } else { + unreachable!( + "invalid input for print statement: {:?}", + ctx.try_get_node(node_id).expect("node is missing from SSA") + ) + } } - None => unreachable!("array objects should not be marked as single values"), }, }; - evaluator.gates.push(Gate::Directive(Directive::Log(log_string))); + + // Only one of the witness vector or the output string should be non-empty + assert!(log_witnesses.is_empty() ^ log_string.is_empty()); + + evaluator.gates.push(Gate::Directive(Directive::Log { + output_string: log_string, + witnesses: log_witnesses, + })); } } diff --git a/crates/noirc_evaluator/src/ssa/optim.rs b/crates/noirc_evaluator/src/ssa/optim.rs index cfb22072757..6b69d778c7b 100644 --- a/crates/noirc_evaluator/src/ssa/optim.rs +++ b/crates/noirc_evaluator/src/ssa/optim.rs @@ -300,9 +300,16 @@ fn cse_block_with_anchor( new_list.push(*ins_id); } Operation::Return(..) => new_list.push(*ins_id), - Operation::Intrinsic(_, args) => { + Operation::Intrinsic(opcode, args) => { + // dbg!(args.clone()); //Add dunmmy load for function arguments and enable CSE only if no array in argument let mut activate_cse = true; + match opcode { + // We do not want to replace any print intrinsics as we want them to remain in order and unchanged + builtin::Opcode::Println(_) => activate_cse = false, + _ => (), + } + for arg in args { if let Some(obj) = ctx.try_get_node(*arg) { if let ObjectType::Pointer(a) = obj.get_type() { @@ -320,6 +327,7 @@ fn cse_block_with_anchor( if activate_cse { if let Some(similar) = anchor.find_similar_instruction(&operator) { + dbg!(similar); *modified = true; new_mark = Mark::ReplaceWith(similar); } else { @@ -355,6 +363,7 @@ fn cse_block_with_anchor( //cannot simplify to_bits() in the previous call because it get replaced with multiple instructions if let Operation::Intrinsic(opcode, args) = &update2.operation { match opcode { + // We do not simplify print statements builtin::Opcode::Println(_) => (), _ => { let args = args.iter().map(|arg| { From 49546e75e0439c8af75364e8770c0729b25350d1 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 18 Jan 2023 18:00:10 -0500 Subject: [PATCH 22/47] little cleanup and additional comments --- crates/acir/src/circuit/gate.rs | 6 +++--- crates/acvm/src/lib.rs | 4 +++- crates/noirc_evaluator/src/ssa/acir_gen.rs | 20 ++++++++------------ 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/crates/acir/src/circuit/gate.rs b/crates/acir/src/circuit/gate.rs index 1f2cd50e477..ea877435985 100644 --- a/crates/acir/src/circuit/gate.rs +++ b/crates/acir/src/circuit/gate.rs @@ -187,9 +187,9 @@ pub enum Directive { radix: u32, }, - // If values are compile time and known during evaluation we can form an output string during ACIR gen - // Otherwise, we must store the witnesses to fetch during the PWG. If the witnesses vector is not empty - // we know that we must construct the output string in the PWG. + // If values are compile time and/or known during evaluation, we can form an output string during ACIR gen. + // Otherwise, we must store witnesses whose values will be fetched during the PWG. + // If the witnesses vector is not empty we know that we must instead construct the standard output in the PWG. Log { output_string: String, witnesses: Vec, diff --git a/crates/acvm/src/lib.rs b/crates/acvm/src/lib.rs index fbc4652f4bc..8ed5dae36d0 100644 --- a/crates/acvm/src/lib.rs +++ b/crates/acvm/src/lib.rs @@ -220,6 +220,8 @@ pub trait PartialWitnessGenerator { } } } else { + // If multiple witnesses are to be fetched for a log directive, + // it assumed that an array is meant to be printed to standard output let mut output_witnesses_string = "".to_owned(); output_witnesses_string.push_str("["); let mut iter = witnesses.iter().peekable(); @@ -239,7 +241,7 @@ pub trait PartialWitnessGenerator { output_witnesses_string .push_str(&format!("{}, ", elem.to_hex())); } - } + } output_witnesses_string.push_str("]"); println!("{}", output_witnesses_string); } diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index 16e0ea3d3d5..374a1585d54 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -650,18 +650,15 @@ impl Acir { if array_elem_expr.is_const() { field_elements.push(array_elem_expr.q_c) } else { - if self.arith_cache.contains_key(&node_id) { - let var = self.arith_cache[&node_id].clone(); - if let Some(w) = var.witness { - log_witnesses.push(w); - } + let var = if self.arith_cache.contains_key(&node_id) { + self.arith_cache[&node_id].clone() } else { - let var = InternalVar::from(array_elem_expr); - if let Some(w) = var.witness { - log_witnesses.push(w); - } else { - unreachable!("array element to be logged is missing a witness"); - } + InternalVar::from(array_elem_expr) + }; + if let Some(w) = var.witness { + log_witnesses.push(w); + } else { + unreachable!("array element to be logged is missing a witness"); } } } else { @@ -692,7 +689,6 @@ impl Acir { None => { if self.arith_cache.contains_key(&node_id) { let var = self.arith_cache[&node_id].clone(); - dbg!(var.clone()); if let Some(field) = var.to_const() { log_string.push_str(&format!("{}", field.to_hex())); } else if let Some(w) = var.witness { From deeabd3ba38202d5f724531b8c274fba9837a45e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 19 Jan 2023 09:06:32 -0500 Subject: [PATCH 23/47] 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 24/47] 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 25/47] 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 26/47] 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 27/47] 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 28/47] 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 29/47] 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 735d9d0c5e1c72d2f79ceea769581e88398c058d Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 20 Jan 2023 11:57:40 -0500 Subject: [PATCH 30/47] use remote acvm repo, do not merge as need to wait for acvm to be updated first --- Cargo.lock | 18 +++++++----------- Cargo.toml | 2 +- crates/nargo/Cargo.toml | 4 ++-- .../nargo/tests/test_data/strings/src/main.nr | 2 +- crates/noirc_evaluator/src/ssa/acir_gen.rs | 13 ++++++++----- crates/noirc_evaluator/src/ssa/optim.rs | 2 -- 6 files changed, 19 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7ec0af3167..dd36cdc4e3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,8 +27,7 @@ dependencies = [ [[package]] name = "acir" version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aad7977c11d19ae0dd983b50dc5fd9eb96c002072f75643e45daa6dc0c23fba5" +source = "git+https://github.com/vezenovm/acvm?branch=mv/logging#c1577fe22ca2fe64c11d67cb1f80055f5bb4f0b5" dependencies = [ "acir_field", "flate2", @@ -39,8 +38,7 @@ dependencies = [ [[package]] name = "acir_field" version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687506e635efa7ce15d6b93ceae14dec1519ed2e54c24298fc8c40e86edbce24" +source = "git+https://github.com/vezenovm/acvm?branch=mv/logging#c1577fe22ca2fe64c11d67cb1f80055f5bb4f0b5" dependencies = [ "ark-bn254", "ark-ff", @@ -88,8 +86,7 @@ dependencies = [ [[package]] name = "acvm" version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99007127e84602134226eefc2245c59b7fe55853bfeba572714b04c5b3fefdea" +source = "git+https://github.com/vezenovm/acvm?branch=mv/logging#c1577fe22ca2fe64c11d67cb1f80055f5bb4f0b5" dependencies = [ "acir 0.3.1", "acir_field", @@ -107,8 +104,7 @@ dependencies = [ [[package]] name = "acvm_stdlib" version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f5ef183f4a10b4a257d25c3a37fd090b9e8fbb7dff0902329fb6606b524114" +source = "git+https://github.com/vezenovm/acvm?branch=mv/logging#c1577fe22ca2fe64c11d67cb1f80055f5bb4f0b5" dependencies = [ "acir 0.3.1", "acir_field", @@ -386,7 +382,7 @@ dependencies = [ [[package]] name = "barretenberg_static_lib" version = "0.1.0" -source = "git+https://github.com/noir-lang/aztec_backend?rev=441de9d897683f770f8cd09c34ddca69fe41f3f2#441de9d897683f770f8cd09c34ddca69fe41f3f2" +source = "git+https://github.com/noir-lang/aztec_backend?branch=mv/logging#5fb7f08d4c8e40d79298233b6bc9ad626f77470c" dependencies = [ "barretenberg_wrapper", "blake2", @@ -406,7 +402,7 @@ dependencies = [ [[package]] name = "barretenberg_wasm" version = "0.1.0" -source = "git+https://github.com/noir-lang/aztec_backend?rev=441de9d897683f770f8cd09c34ddca69fe41f3f2#441de9d897683f770f8cd09c34ddca69fe41f3f2" +source = "git+https://github.com/noir-lang/aztec_backend?branch=mv/logging#5fb7f08d4c8e40d79298233b6bc9ad626f77470c" dependencies = [ "blake2", "common", @@ -649,7 +645,7 @@ dependencies = [ [[package]] name = "common" version = "0.1.0" -source = "git+https://github.com/noir-lang/aztec_backend?rev=441de9d897683f770f8cd09c34ddca69fe41f3f2#441de9d897683f770f8cd09c34ddca69fe41f3f2" +source = "git+https://github.com/noir-lang/aztec_backend?branch=mv/logging#5fb7f08d4c8e40d79298233b6bc9ad626f77470c" dependencies = [ "acvm 0.3.1", "blake2", diff --git a/Cargo.toml b/Cargo.toml index f92d5589ad2..08328d77394 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ rust-version = "1.64" [workspace.dependencies] acir = { path = "crates/acir" } -acvm = "0.3.1" +acvm = { git = "https://github.com/vezenovm/acvm", branch = "mv/logging" } arena = { path = "crates/arena" } fm = { path = "crates/fm" } iter-extended = { path = "crates/iter-extended" } diff --git a/crates/nargo/Cargo.toml b/crates/nargo/Cargo.toml index 50c47219e8b..c62c02a3c44 100644 --- a/crates/nargo/Cargo.toml +++ b/crates/nargo/Cargo.toml @@ -29,8 +29,8 @@ hex.workspace = true tempdir.workspace = true # Backends -aztec_backend = { optional = true, package = "barretenberg_static_lib", git = "https://github.com/noir-lang/aztec_backend", rev = "441de9d897683f770f8cd09c34ddca69fe41f3f2" } -aztec_wasm_backend = { optional = true, package = "barretenberg_wasm", git = "https://github.com/noir-lang/aztec_backend", rev = "441de9d897683f770f8cd09c34ddca69fe41f3f2" } +aztec_backend = { optional = true, package = "barretenberg_static_lib", git = "https://github.com/noir-lang/aztec_backend", branch = "mv/logging" } +aztec_wasm_backend = { optional = true, package = "barretenberg_wasm", git = "https://github.com/noir-lang/aztec_backend", branch = "mv/logging" } marlin_arkworks_backend = { optional = true, git = "https://github.com/noir-lang/marlin_arkworks_backend", rev = "601e24dcb5dcbe72e3de7a33879aaf84e171d541" } [features] diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index 33522089e48..33b0017f11f 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -1,6 +1,6 @@ use dep::std; -fn main(message : pub str[11], hex_as_string : str[4], hex_as_field : Field) { +fn main(message : pub str[11], y : Field, hex_as_string : str[4], hex_as_field : Field) { let mut bad_message = "hello world"; constrain message == "hello world"; diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index e7d82b8ee1d..28f97dcb9b4 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -8,7 +8,7 @@ use crate::ssa::node::Node; use crate::ssa::{mem, node}; use crate::Evaluator; use crate::RuntimeErrorKind; -use acvm::acir::circuit::directives::Directive; +use acvm::acir::circuit::directives::{Directive, LogInfo}; use acvm::acir::circuit::opcodes::{BlackBoxFuncCall, FunctionInput}; use acvm::acir::circuit::Opcode as AcirOpcode; @@ -712,10 +712,13 @@ impl Acir { // Only one of the witness vector or the output string should be non-empty assert!(log_witnesses.is_empty() ^ log_string.is_empty()); - evaluator.gates.push(Gate::Directive(Directive::Log { - output_string: log_string, - witnesses: log_witnesses, - })); + let log_directive = if !log_string.is_empty() { + Directive::Log(LogInfo::FinalizedOutput(log_string)) + } else { + Directive::Log(LogInfo::WitnessOutput(log_witnesses)) + }; + + evaluator.opcodes.push(AcirOpcode::Directive(log_directive)); } } diff --git a/crates/noirc_evaluator/src/ssa/optim.rs b/crates/noirc_evaluator/src/ssa/optim.rs index 6b69d778c7b..137d1d15809 100644 --- a/crates/noirc_evaluator/src/ssa/optim.rs +++ b/crates/noirc_evaluator/src/ssa/optim.rs @@ -301,7 +301,6 @@ fn cse_block_with_anchor( } Operation::Return(..) => new_list.push(*ins_id), Operation::Intrinsic(opcode, args) => { - // dbg!(args.clone()); //Add dunmmy load for function arguments and enable CSE only if no array in argument let mut activate_cse = true; match opcode { @@ -327,7 +326,6 @@ fn cse_block_with_anchor( if activate_cse { if let Some(similar) = anchor.find_similar_instruction(&operator) { - dbg!(similar); *modified = true; new_mark = Mark::ReplaceWith(similar); } else { From cccba893700a9c71080cfc23649ab3104bbe6c33 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 20 Jan 2023 12:30:36 -0500 Subject: [PATCH 31/47] update cargo lock --- Cargo.lock | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9547857e0ae..b9fe4011be9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -387,11 +387,7 @@ dependencies = [ [[package]] name = "barretenberg_wrapper" version = "0.1.0" -<<<<<<< HEAD -source = "git+https://github.com/noir-lang/aztec-connect?branch=kw/noir-dsl#95988ba712d03b139e3ee116ad4d5c4050bcef5c" -======= source = "git+https://github.com/noir-lang/aztec-connect?branch=kw/noir-dsl#85dcb7c404b824b420c92e1010a9e363fe91fbd2" ->>>>>>> master dependencies = [ "bindgen", "cmake", @@ -401,9 +397,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bindgen" @@ -2357,9 +2353,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ "base64", "bytes", @@ -2863,9 +2859,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] @@ -3376,9 +3372,9 @@ dependencies = [ [[package]] name = "which" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", "libc", From 11c1c6165987aa169ba2cbaf0b51f9e21aa46d80 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 25 Jan 2023 15:28:24 -0500 Subject: [PATCH 32/47] clippy --- crates/noirc_abi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index aad8a106061..42fa28e5e10 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -278,7 +278,7 @@ impl Abi { let final_string = decode_string_value(field_elements); index += *length as usize; - InputValue::String(final_string.to_owned()) + InputValue::String(final_string) } AbiType::Struct { fields, .. } => { let mut struct_map = BTreeMap::new(); From c04ee6b71e35e9b9c4b0970f1c13e5472d9f8223 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 25 Jan 2023 16:06:49 -0500 Subject: [PATCH 33/47] more cargo clippy fixes --- crates/noirc_evaluator/src/ssa/acir_gen.rs | 10 +++++----- crates/noirc_evaluator/src/ssa/context.rs | 10 ++-------- crates/noirc_evaluator/src/ssa/optim.rs | 7 +++---- crates/noirc_frontend/src/parser/parser.rs | 2 +- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index 5ee897e8b9c..d5c2861c17f 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -673,27 +673,27 @@ impl Acir { let final_string = noirc_abi::decode_string_value(&field_elements); log_string.push_str(&final_string); } else if !field_elements.is_empty() { - log_string.push_str("["); + log_string.push('['); let mut iter = field_elements.iter().peekable(); while let Some(elem) = iter.next() { if iter.peek().is_none() { - log_string.push_str(&format!("{}", elem.to_hex())); + log_string.push_str(&elem.to_hex()); } else { log_string.push_str(&format!("{}, ", elem.to_hex())); } } - log_string.push_str("]"); + log_string.push(']'); } } _ => match ctx.get_as_constant(node_id) { Some(field) => { - log_string.push_str(&format!("{}", field.to_hex())); + log_string.push_str(&field.to_hex()); } None => { if self.arith_cache.contains_key(&node_id) { let var = self.arith_cache[&node_id].clone(); if let Some(field) = var.to_const() { - log_string.push_str(&format!("{}", field.to_hex())); + log_string.push_str(&field.to_hex()); } else if let Some(w) = var.witness { log_witnesses.push(w); } else { diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 21c3e1dccf7..118dd72ebfe 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -1113,14 +1113,8 @@ impl SsaContext { "print statements currently only support one argument" ); let is_string = match &arguments[0] { - Expression::Ident(ident) => match ident.typ { - Type::String(_) => true, - _ => false, - }, - Expression::Literal(literal) => match literal { - Literal::Str(_) => true, - _ => false, - }, + Expression::Ident(ident) => matches!(ident.typ, Type::String(_)), + Expression::Literal(literal) => matches!(literal, Literal::Str(_)), _ => unreachable!("logging this expression type is not supported"), }; Some(builtin::Opcode::Println(is_string)) diff --git a/crates/noirc_evaluator/src/ssa/optim.rs b/crates/noirc_evaluator/src/ssa/optim.rs index 137d1d15809..4effa937e92 100644 --- a/crates/noirc_evaluator/src/ssa/optim.rs +++ b/crates/noirc_evaluator/src/ssa/optim.rs @@ -303,10 +303,9 @@ fn cse_block_with_anchor( Operation::Intrinsic(opcode, args) => { //Add dunmmy load for function arguments and enable CSE only if no array in argument let mut activate_cse = true; - match opcode { - // We do not want to replace any print intrinsics as we want them to remain in order and unchanged - builtin::Opcode::Println(_) => activate_cse = false, - _ => (), + // We do not want to replace any print intrinsics as we want them to remain in order and unchanged + if let builtin::Opcode::Println(_) = opcode { + activate_cse = false } for arg in args { diff --git a/crates/noirc_frontend/src/parser/parser.rs b/crates/noirc_frontend/src/parser/parser.rs index 9abdb38f3db..e3fcb2d7e36 100644 --- a/crates/noirc_frontend/src/parser/parser.rs +++ b/crates/noirc_frontend/src/parser/parser.rs @@ -445,7 +445,7 @@ 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(), From bcdc61776e8e7d017b27e6029704afbb89b6ca45 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Wed, 8 Feb 2023 16:11:56 +0000 Subject: [PATCH 34/47] chore: remove unwanted dependency to old acir crate --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2d5fc7776f3..299bc530e53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ edition = "2021" rust-version = "1.64" [workspace.dependencies] -acir = { path = "crates/acir" } acvm = { git = "https://github.com/vezenovm/acvm", branch = "mv/logging" } arena = { path = "crates/arena" } fm = { path = "crates/fm" } From 6bd75bb39f8ff87a72e3cc2e27c99fb773a5aa29 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 10 Feb 2023 11:57:00 -0500 Subject: [PATCH 35/47] remove old comments --- .../src/ssa/acir_gen/operations/intrinsics.rs | 45 ------------------- 1 file changed, 45 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 6db08297d98..7762cdc150b 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -226,36 +226,6 @@ fn evaluate_println( } else { unreachable!("array element being logged does not exist in memory"); } - - // let absolute_adr = mem_array.absolute_adr(idx); - // if memory_map.contains_key(&absolute_adr) { - // let array_elem_expr = memory_map[&absolute_adr].expression.clone(); - // if array_elem_expr.is_const() { - // field_elements.push(array_elem_expr.q_c) - // } else { - // // let var = if self.arith_cache.contains_key(&node_id) { - // // self.arith_cache[&node_id].clone() - // // } else { - // // InternalVar::from(array_elem_expr) - // // }; - // // if let Some(w) = var.witness { - // // log_witnesses.push(w); - // // } else { - // // unreachable!("array element to be logged is missing a witness"); - // // } - // let var = match var_cache.get(&node_id) { - // Some(var) => *var, - // _ => InternalVar::from(array_elem_expr), - // }; - // if let Some(w) = var.cached_witness() { - // log_witnesses.push(*w); - // } else { - // unreachable!("array element to be logged is missing a witness"); - // } - // } - // } else { - // unreachable!("array element being logged does not exist in memory"); - // } } if is_string_output { @@ -279,21 +249,6 @@ fn evaluate_println( log_string.push_str(&field.to_hex()); } None => { - // if self.arith_cache.contains_key(&node_id) { - // let var = self.arith_cache[&node_id].clone(); - // if let Some(field) = var.to_const() { - // log_string.push_str(&field.to_hex()); - // } else if let Some(w) = var.witness { - // log_witnesses.push(w); - // } else { - // unreachable!("array element to be logged is missing a witness"); - // } - // } else { - // unreachable!( - // "invalid input for print statement: {:?}", - // ctx.try_get_node(node_id).expect("node is missing from SSA") - // ) - // } if let Some(var) = var_cache.get(&node_id) { if let Some(field) = var.to_const() { log_string.push_str(&field.to_hex()); From 75d9b07a66fa676b753f93e40c3ca77642c3d023 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 10 Feb 2023 17:20:37 -0500 Subject: [PATCH 36/47] add nocapture flag to test and start println output on new line --- crates/nargo/src/cli/mod.rs | 7 ++++++- crates/nargo/src/cli/test_cmd.rs | 12 ++++++----- .../nargo/tests/test_data/strings/src/main.nr | 21 +++++++++++++++++++ crates/noirc_driver/src/lib.rs | 5 +++-- crates/noirc_evaluator/src/lib.rs | 6 ++++-- crates/noirc_evaluator/src/ssa/acir_gen.rs | 14 ++++++++++--- .../src/ssa/acir_gen/operations/intrinsics.rs | 12 +++++------ crates/noirc_evaluator/src/ssa/context.rs | 12 ++++++++--- 8 files changed, 67 insertions(+), 22 deletions(-) diff --git a/crates/nargo/src/cli/mod.rs b/crates/nargo/src/cli/mod.rs index 8e5028bac5b..2299a0abf96 100644 --- a/crates/nargo/src/cli/mod.rs +++ b/crates/nargo/src/cli/mod.rs @@ -92,7 +92,12 @@ pub fn start_cli() { Arg::with_name("test_name") .help("If given, only tests with names containing this string will be run"), ) - .arg(allow_warnings.clone()), + .arg(allow_warnings.clone()) + .arg( + Arg::with_name("nocapture") + .long("nocapture") + .help("Display output of println statements during tests"), + ), ) .subcommand( App::new("compile") diff --git a/crates/nargo/src/cli/test_cmd.rs b/crates/nargo/src/cli/test_cmd.rs index 0a46f35e585..719939d6c80 100644 --- a/crates/nargo/src/cli/test_cmd.rs +++ b/crates/nargo/src/cli/test_cmd.rs @@ -14,10 +14,11 @@ pub(crate) fn run(args: ArgMatches) -> Result<(), CliError> { let args = args.subcommand_matches("test").unwrap(); let test_name = args.value_of("test_name").unwrap_or(""); let allow_warnings = args.is_present("allow-warnings"); - run_tests(test_name, allow_warnings) + let capture_output = !args.is_present("nocapture"); + run_tests(test_name, allow_warnings, capture_output) } -fn run_tests(test_name: &str, allow_warnings: bool) -> Result<(), CliError> { +fn run_tests(test_name: &str, allow_warnings: bool, capture_output: bool) -> Result<(), CliError> { let backend = crate::backends::ConcreteBackend; let package_dir = std::env::current_dir().unwrap(); @@ -37,10 +38,10 @@ fn run_tests(test_name: &str, allow_warnings: bool) -> Result<(), CliError> { for test_function in test_functions { let test_name = driver.function_name(test_function); - write!(writer, "Testing {test_name}... ").expect("Failed to write to stdout"); + write!(writer, "Testing {test_name}...\n").expect("Failed to write to stdout"); writer.flush().ok(); - match run_test(test_name, test_function, &driver, allow_warnings) { + match run_test(test_name, test_function, &driver, allow_warnings, capture_output) { Ok(_) => { writer.set_color(ColorSpec::new().set_fg(Some(Color::Green))).ok(); writeln!(writer, "ok").ok(); @@ -70,12 +71,13 @@ fn run_test( main: FuncId, driver: &Driver, allow_warnings: bool, + capture_output: bool, ) -> Result<(), CliError> { let backend = crate::backends::ConcreteBackend; let language = backend.np_language(); let program = driver - .compile_no_check(language, false, allow_warnings, Some(main)) + .compile_no_check(language, false, allow_warnings, Some(main), capture_output) .map_err(|_| CliError::Generic(format!("Test '{test_name}' failed to compile")))?; let mut solved_witness = BTreeMap::new(); diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index 89b53441009..ecfdd82d6b8 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -25,4 +25,25 @@ fn main(message : pub str<11>, y : Field, hex_as_string : str<4>, hex_as_field : 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; +} + +#[test] +fn test_prints_strings() { + let message = "hello world!"; + + std::println(message); + + let bad_message = "goodbye world"; + + std::println(bad_message); +} + +#[test] +fn test_prints_array() { + let array = [1, 2, 3, 5, 8]; + + std::println(array); + + let hash = std::hash::pedersen(array); + std::println(hash); } \ No newline at end of file diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index dc568419105..580a6494f98 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -166,7 +166,7 @@ impl Driver { allow_warnings: bool, ) -> Result { self.check_crate(allow_warnings)?; - self.compile_no_check(np_language, show_ssa, allow_warnings, None) + self.compile_no_check(np_language, show_ssa, allow_warnings, None, false) } /// Compile the current crate. Assumes self.check_crate is called beforehand! @@ -178,6 +178,7 @@ impl Driver { allow_warnings: bool, // Optional override to provide a different `main` function to start execution main_function: Option, + capture_output: bool, ) -> Result { // Find the local crate, one should always be present let local_crate = self.context.def_map(LOCAL_CRATE).unwrap(); @@ -202,7 +203,7 @@ impl Driver { let program = monomorphize(main_function, &self.context.def_interner); let blackbox_supported = acvm::default_is_black_box_supported(np_language.clone()); - match create_circuit(program, np_language, blackbox_supported, show_ssa) { + match create_circuit(program, np_language, blackbox_supported, show_ssa, capture_output) { Ok(circuit) => Ok(CompiledProgram { circuit, abi: Some(abi) }), Err(err) => { // The FileId here will be the file id of the file with the main file diff --git a/crates/noirc_evaluator/src/lib.rs b/crates/noirc_evaluator/src/lib.rs index a7c5f43fead..a4db7429393 100644 --- a/crates/noirc_evaluator/src/lib.rs +++ b/crates/noirc_evaluator/src/lib.rs @@ -38,11 +38,12 @@ pub fn create_circuit( np_language: Language, is_blackbox_supported: IsBlackBoxSupported, enable_logging: bool, + capture_output: bool, ) -> Result { let mut evaluator = Evaluator::new(); // First evaluate the main function - evaluator.evaluate_main_alt(program, enable_logging)?; + evaluator.evaluate_main_alt(program, enable_logging, capture_output)?; let witness_index = evaluator.current_witness_index(); @@ -109,6 +110,7 @@ impl Evaluator { &mut self, program: Program, enable_logging: bool, + capture_output: bool, ) -> Result<(), RuntimeError> { let mut ir_gen = IRGenerator::new(program); self.parse_abi_alt(&mut ir_gen); @@ -117,7 +119,7 @@ impl Evaluator { ir_gen.codegen_main()?; //Generates ACIR representation: - ir_gen.context.ir_to_acir(self, enable_logging)?; + ir_gen.context.ir_to_acir(self, enable_logging, capture_output)?; Ok(()) } diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index 52fe4de857f..ee7343d75bf 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -34,6 +34,7 @@ impl Acir { ins: &Instruction, evaluator: &mut Evaluator, ctx: &SsaContext, + capture_output: bool, ) -> Result<(), RuntimeErrorKind> { use operations::{ binary, condition, constrain, intrinsics, load, not, r#return, store, truncate, @@ -56,9 +57,16 @@ impl Acir { Operation::Truncate { value, bit_size, max_bit_size } => { truncate::evaluate(value, *bit_size, *max_bit_size, var_cache, evaluator, ctx) } - Operation::Intrinsic(opcode, args) => { - intrinsics::evaluate(args, ins, *opcode, var_cache, memory_map, ctx, evaluator) - } + Operation::Intrinsic(opcode, args) => intrinsics::evaluate( + args, + ins, + *opcode, + var_cache, + memory_map, + ctx, + evaluator, + capture_output, + ), Operation::Return(node_ids) => { r#return::evaluate(node_ids, memory_map, var_cache, evaluator, ctx)? } diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 7762cdc150b..63d3390a254 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -28,6 +28,7 @@ pub(crate) fn evaluate( memory_map: &mut MemoryMap, ctx: &SsaContext, evaluator: &mut Evaluator, + capture_output: bool, ) -> Option { use builtin::Opcode; @@ -57,7 +58,9 @@ pub(crate) fn evaluate( } Opcode::Println(is_string_output) => { outputs = Vec::new(); // print statements do not output anything - evaluate_println(var_cache, memory_map, is_string_output, args, ctx, evaluator); + if !capture_output { + evaluate_println(var_cache, memory_map, is_string_output, args, ctx, evaluator); + } } Opcode::LowLevel(op) => { let inputs = prepare_inputs(var_cache, memory_map, args, ctx, evaluator); @@ -76,11 +79,8 @@ pub(crate) fn evaluate( // If more than witness is returned, // the result is inside the result type of `Instruction` // as a pointer to an array - if outputs.len() == 1 { - Some(InternalVar::from(Expression::from(&outputs[0]))) - } else { - None - } + // (outputs.len() == 1).then(|| Expression::from(&outputs[0])).map(InternalVar::from) + (outputs.len() == 1).then(|| InternalVar::from(outputs[0])) } // Transform the arguments of intrinsic functions into witnesses diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 68c98a34f08..623da0b6c73 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -694,6 +694,7 @@ impl SsaContext { &mut self, evaluator: &mut Evaluator, enable_logging: bool, + capture_output: bool, ) -> Result<(), RuntimeError> { //SSA self.log(enable_logging, "SSA:", "\ninline functions"); @@ -739,7 +740,7 @@ impl SsaContext { integer::overflow_strategy(self)?; self.log(enable_logging, "\noverflow:", ""); //ACIR - self.acir(evaluator)?; + self.acir(evaluator, capture_output)?; if enable_logging { print_acir_circuit(&evaluator.opcodes); println!("DONE"); @@ -748,13 +749,18 @@ impl SsaContext { Ok(()) } - pub fn acir(&self, evaluator: &mut Evaluator) -> Result<(), RuntimeError> { + pub fn acir( + &self, + evaluator: &mut Evaluator, + capture_output: bool, + ) -> Result<(), RuntimeError> { let mut acir = Acir::default(); let mut fb = Some(&self[self.first_block]); while let Some(block) = fb { for iter in &block.instructions { let ins = self.get_instruction(*iter); - acir.acir_gen_instruction(ins, evaluator, self).map_err(RuntimeError::from)?; + acir.acir_gen_instruction(ins, evaluator, self, capture_output) + .map_err(RuntimeError::from)?; } //TODO we should rather follow the jumps fb = block.left.map(|block_id| &self[block_id]); From 5fd266bcd6ee64ee271cd60f265aec249e70da12 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 13 Feb 2023 10:22:44 -0500 Subject: [PATCH 37/47] use refactored SsaContext methods --- .../noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs | 4 ++-- crates/noirc_evaluator/src/ssa/context.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 63d3390a254..4e040c6a56b 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -11,7 +11,7 @@ use crate::{ use acvm::acir::circuit::directives::{Directive, LogInfo}; use acvm::acir::{ circuit::opcodes::{BlackBoxFuncCall, FunctionInput, Opcode as AcirOpcode}, - native_types::{Expression, Witness}, + native_types::Witness, }; use iter_extended::vecmap; @@ -202,7 +202,7 @@ fn evaluate_println( let mut log_string = "".to_owned(); let mut log_witnesses = Vec::new(); - let obj_type = ctx.get_object_type(node_id); + let obj_type = ctx.object_type(node_id); match obj_type { ObjectType::Pointer(array_id) => { let mem_array = &ctx.mem[array_id]; diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 41d347c1cb8..577941930d9 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -758,7 +758,7 @@ impl SsaContext { let mut fb = Some(&self[self.first_block]); while let Some(block) = fb { for iter in &block.instructions { - let ins = self.get_instruction(*iter); + let ins = self.instruction(*iter); acir.acir_gen_instruction(ins, evaluator, self, capture_output) .map_err(RuntimeError::from)?; } From a91b501d7f3ae132470014b52c1854a6295fbfe0 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 13 Feb 2023 10:59:42 -0500 Subject: [PATCH 38/47] switc to show-logs over nocapture flag for printing test output --- crates/nargo/src/cli/mod.rs | 4 ++-- crates/nargo/src/cli/test_cmd.rs | 17 +++++++++++------ crates/noirc_driver/src/lib.rs | 4 ++-- crates/noirc_evaluator/src/lib.rs | 8 ++++---- crates/noirc_evaluator/src/ssa/acir_gen.rs | 4 ++-- .../src/ssa/acir_gen/operations/intrinsics.rs | 4 ++-- crates/noirc_evaluator/src/ssa/context.rs | 12 ++++-------- 7 files changed, 27 insertions(+), 26 deletions(-) diff --git a/crates/nargo/src/cli/mod.rs b/crates/nargo/src/cli/mod.rs index 03dac8c1e33..a83726d4b33 100644 --- a/crates/nargo/src/cli/mod.rs +++ b/crates/nargo/src/cli/mod.rs @@ -94,8 +94,8 @@ pub fn start_cli() { ) .arg(allow_warnings.clone()) .arg( - Arg::with_name("nocapture") - .long("nocapture") + Arg::with_name("show-logs") + .long("show-logs") .help("Display output of println statements during tests"), ), ) diff --git a/crates/nargo/src/cli/test_cmd.rs b/crates/nargo/src/cli/test_cmd.rs index 4535383d1a8..4e855fe0895 100644 --- a/crates/nargo/src/cli/test_cmd.rs +++ b/crates/nargo/src/cli/test_cmd.rs @@ -18,14 +18,19 @@ pub(crate) fn run(args: ArgMatches) -> Result<(), CliError> { let args = args.subcommand_matches("test").unwrap(); let test_name = args.value_of("test_name").unwrap_or(""); let allow_warnings = args.is_present("allow-warnings"); - let capture_output = !args.is_present("nocapture"); + let show_output = args.is_present("show-logs"); let program_dir = args.value_of("path").map_or_else(|| std::env::current_dir().unwrap(), PathBuf::from); - run_tests(&program_dir, test_name, allow_warnings, capture_output) + run_tests(&program_dir, test_name, allow_warnings, show_output) } -fn run_tests(program_dir: &Path, test_name: &str, allow_warnings: bool, capture_output: bool) -> Result<(), CliError> { +fn run_tests( + program_dir: &Path, + test_name: &str, + allow_warnings: bool, + show_output: bool, +) -> Result<(), CliError> { let backend = crate::backends::ConcreteBackend; let mut driver = Resolver::resolve_root_config(program_dir, backend.np_language())?; @@ -47,7 +52,7 @@ fn run_tests(program_dir: &Path, test_name: &str, allow_warnings: bool, capture_ write!(writer, "Testing {test_name}...\n").expect("Failed to write to stdout"); writer.flush().ok(); - match run_test(test_name, test_function, &driver, allow_warnings, capture_output) { + match run_test(test_name, test_function, &driver, allow_warnings, show_output) { Ok(_) => { writer.set_color(ColorSpec::new().set_fg(Some(Color::Green))).ok(); writeln!(writer, "ok").ok(); @@ -77,13 +82,13 @@ fn run_test( main: FuncId, driver: &Driver, allow_warnings: bool, - capture_output: bool, + show_output: bool, ) -> Result<(), CliError> { let backend = crate::backends::ConcreteBackend; let language = backend.np_language(); let program = driver - .compile_no_check(language, false, allow_warnings, Some(main), capture_output) + .compile_no_check(language, false, allow_warnings, Some(main), show_output) .map_err(|_| CliError::Generic(format!("Test '{test_name}' failed to compile")))?; let mut solved_witness = BTreeMap::new(); diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 90aa4ae778a..8c66bf6fca1 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -163,7 +163,7 @@ impl Driver { allow_warnings: bool, // Optional override to provide a different `main` function to start execution main_function: Option, - capture_output: bool, + show_output: bool, ) -> Result { // Find the local crate, one should always be present let local_crate = self.context.def_map(LOCAL_CRATE).unwrap(); @@ -188,7 +188,7 @@ impl Driver { let program = monomorphize(main_function, &self.context.def_interner); let blackbox_supported = acvm::default_is_black_box_supported(np_language.clone()); - match create_circuit(program, np_language, blackbox_supported, show_ssa, capture_output) { + match create_circuit(program, np_language, blackbox_supported, show_ssa, show_output) { Ok(circuit) => Ok(CompiledProgram { circuit, abi: Some(abi) }), Err(err) => { // The FileId here will be the file id of the file with the main file diff --git a/crates/noirc_evaluator/src/lib.rs b/crates/noirc_evaluator/src/lib.rs index b0919e98922..2172e4bf683 100644 --- a/crates/noirc_evaluator/src/lib.rs +++ b/crates/noirc_evaluator/src/lib.rs @@ -39,12 +39,12 @@ pub fn create_circuit( np_language: Language, is_blackbox_supported: IsBlackBoxSupported, enable_logging: bool, - capture_output: bool, + show_output: bool, ) -> Result { let mut evaluator = Evaluator::new(); // First evaluate the main function - evaluator.evaluate_main_alt(program, enable_logging, capture_output)?; + evaluator.evaluate_main_alt(program, enable_logging, show_output)?; let witness_index = evaluator.current_witness_index(); @@ -111,7 +111,7 @@ impl Evaluator { &mut self, program: Program, enable_logging: bool, - capture_output: bool, + show_output: bool, ) -> Result<(), RuntimeError> { let mut ir_gen = IrGenerator::new(program); self.parse_abi_alt(&mut ir_gen); @@ -120,7 +120,7 @@ impl Evaluator { ir_gen.ssa_gen_main()?; //Generates ACIR representation: - ir_gen.context.ir_to_acir(self, enable_logging, capture_output)?; + ir_gen.context.ir_to_acir(self, enable_logging, show_output)?; Ok(()) } diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index ee7343d75bf..bff097b7491 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -34,7 +34,7 @@ impl Acir { ins: &Instruction, evaluator: &mut Evaluator, ctx: &SsaContext, - capture_output: bool, + show_output: bool, ) -> Result<(), RuntimeErrorKind> { use operations::{ binary, condition, constrain, intrinsics, load, not, r#return, store, truncate, @@ -65,7 +65,7 @@ impl Acir { memory_map, ctx, evaluator, - capture_output, + show_output, ), Operation::Return(node_ids) => { r#return::evaluate(node_ids, memory_map, var_cache, evaluator, ctx)? diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 4e040c6a56b..e6eef53b809 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -28,7 +28,7 @@ pub(crate) fn evaluate( memory_map: &mut MemoryMap, ctx: &SsaContext, evaluator: &mut Evaluator, - capture_output: bool, + show_output: bool, ) -> Option { use builtin::Opcode; @@ -58,7 +58,7 @@ pub(crate) fn evaluate( } Opcode::Println(is_string_output) => { outputs = Vec::new(); // print statements do not output anything - if !capture_output { + if show_output { evaluate_println(var_cache, memory_map, is_string_output, args, ctx, evaluator); } } diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 577941930d9..456fdeafba2 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -694,7 +694,7 @@ impl SsaContext { &mut self, evaluator: &mut Evaluator, enable_logging: bool, - capture_output: bool, + show_output: bool, ) -> Result<(), RuntimeError> { //SSA self.log(enable_logging, "SSA:", "\ninline functions"); @@ -740,7 +740,7 @@ impl SsaContext { integer::overflow_strategy(self)?; self.log(enable_logging, "\noverflow:", ""); //ACIR - self.acir(evaluator, capture_output)?; + self.acir(evaluator, show_output)?; if enable_logging { print_acir_circuit(&evaluator.opcodes); println!("DONE"); @@ -749,17 +749,13 @@ impl SsaContext { Ok(()) } - pub fn acir( - &self, - evaluator: &mut Evaluator, - capture_output: bool, - ) -> Result<(), RuntimeError> { + pub fn acir(&self, evaluator: &mut Evaluator, show_output: bool) -> Result<(), RuntimeError> { let mut acir = Acir::default(); let mut fb = Some(&self[self.first_block]); while let Some(block) = fb { for iter in &block.instructions { let ins = self.instruction(*iter); - acir.acir_gen_instruction(ins, evaluator, self, capture_output) + acir.acir_gen_instruction(ins, evaluator, self, show_output) .map_err(RuntimeError::from)?; } //TODO we should rather follow the jumps From 8d90110fac0e407773800efa2c166920e5278c6b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 13 Feb 2023 12:04:16 -0500 Subject: [PATCH 39/47] cargo clippy changes --- crates/nargo/src/cli/test_cmd.rs | 2 +- crates/noirc_driver/src/lib.rs | 2 +- crates/noirc_evaluator/src/ssa/acir_gen.rs | 23 +++++++++++-------- .../src/ssa/acir_gen/operations/intrinsics.rs | 14 +++++++---- crates/noirc_evaluator/src/ssa/builtin.rs | 17 ++++++++++---- crates/noirc_evaluator/src/ssa/context.rs | 5 +++- .../src/hir/resolution/errors.rs | 2 +- 7 files changed, 43 insertions(+), 22 deletions(-) diff --git a/crates/nargo/src/cli/test_cmd.rs b/crates/nargo/src/cli/test_cmd.rs index 4e855fe0895..b651f3d7b66 100644 --- a/crates/nargo/src/cli/test_cmd.rs +++ b/crates/nargo/src/cli/test_cmd.rs @@ -49,7 +49,7 @@ fn run_tests( for test_function in test_functions { let test_name = driver.function_name(test_function); - write!(writer, "Testing {test_name}...\n").expect("Failed to write to stdout"); + writeln!(writer, "Testing {test_name}...").expect("Failed to write to stdout"); writer.flush().ok(); match run_test(test_name, test_function, &driver, allow_warnings, show_output) { diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 8c66bf6fca1..b0d33643398 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -151,7 +151,7 @@ impl Driver { allow_warnings: bool, ) -> Result { self.check_crate(allow_warnings)?; - self.compile_no_check(np_language, show_ssa, allow_warnings, None, false) + self.compile_no_check(np_language, show_ssa, allow_warnings, None, true) } /// Compile the current crate. Assumes self.check_crate is called beforehand! diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index bff097b7491..1c31bf2c516 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -1,4 +1,5 @@ use crate::ssa::{ + builtin, context::SsaContext, node::{Instruction, Operation}, }; @@ -57,16 +58,18 @@ impl Acir { Operation::Truncate { value, bit_size, max_bit_size } => { truncate::evaluate(value, *bit_size, *max_bit_size, var_cache, evaluator, ctx) } - Operation::Intrinsic(opcode, args) => intrinsics::evaluate( - args, - ins, - *opcode, - var_cache, - memory_map, - ctx, - evaluator, - show_output, - ), + Operation::Intrinsic(opcode, args) => { + let opcode = match opcode { + builtin::Opcode::Println(print_info) => { + builtin::Opcode::Println(builtin::PrintlnInfo { + is_string_output: print_info.is_string_output, + show_output, + }) + } + _ => *opcode, + }; + intrinsics::evaluate(args, ins, opcode, var_cache, memory_map, ctx, evaluator) + } Operation::Return(node_ids) => { r#return::evaluate(node_ids, memory_map, var_cache, evaluator, ctx)? } diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index e6eef53b809..054c680557c 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -28,7 +28,6 @@ pub(crate) fn evaluate( memory_map: &mut MemoryMap, ctx: &SsaContext, evaluator: &mut Evaluator, - show_output: bool, ) -> Option { use builtin::Opcode; @@ -56,10 +55,17 @@ pub(crate) fn evaluate( memory_map.map_array(a, &outputs, ctx); } } - Opcode::Println(is_string_output) => { + Opcode::Println(print_info) => { outputs = Vec::new(); // print statements do not output anything - if show_output { - evaluate_println(var_cache, memory_map, is_string_output, args, ctx, evaluator); + if print_info.show_output { + evaluate_println( + var_cache, + memory_map, + print_info.is_string_output, + args, + ctx, + evaluator, + ); } } Opcode::LowLevel(op) => { diff --git a/crates/noirc_evaluator/src/ssa/builtin.rs b/crates/noirc_evaluator/src/ssa/builtin.rs index 8b7464b7ed5..2e04f5b39cc 100644 --- a/crates/noirc_evaluator/src/ssa/builtin.rs +++ b/crates/noirc_evaluator/src/ssa/builtin.rs @@ -12,9 +12,7 @@ pub enum Opcode { LowLevel(BlackBoxFunc), ToBits, ToRadix, - // We store strings as arrays and there is no differentiation between them in the SSA. - // This bool simply states whether an array that is to be printed should be outputted as a utf8 string - Println(bool), + Println(PrintlnInfo), } impl std::fmt::Display for Opcode { @@ -33,7 +31,9 @@ impl Opcode { match op_name { "to_le_bits" => Some(Opcode::ToBits), "to_radix" => Some(Opcode::ToRadix), - "println" => Some(Opcode::Println(false)), + "println" => { + Some(Opcode::Println(PrintlnInfo { is_string_output: false, show_output: true })) + } _ => BlackBoxFunc::lookup(op_name).map(Opcode::LowLevel), } } @@ -99,3 +99,12 @@ impl Opcode { } } } + +#[derive(Clone, Debug, Hash, Copy, PartialEq, Eq)] +pub struct PrintlnInfo { + // We store strings as arrays and there is no differentiation between them in the SSA. + // This bool simply states whether an array that is to be printed should be outputted as a utf8 string + pub is_string_output: bool, + // This is a flag used during `nargo test` to determine whether to display println output. + pub show_output: bool, +} diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 456fdeafba2..41b352fae34 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -1127,7 +1127,10 @@ impl SsaContext { Expression::Literal(literal) => matches!(literal, Literal::Str(_)), _ => unreachable!("logging this expression type is not supported"), }; - Some(builtin::Opcode::Println(is_string)) + Some(builtin::Opcode::Println(builtin::PrintlnInfo { + is_string_output: is_string, + show_output: true, + })) } _ => Some(*opcode), }, diff --git a/crates/noirc_frontend/src/hir/resolution/errors.rs b/crates/noirc_frontend/src/hir/resolution/errors.rs index bf1d1ddfcf4..155288203d7 100644 --- a/crates/noirc_frontend/src/hir/resolution/errors.rs +++ b/crates/noirc_frontend/src/hir/resolution/errors.rs @@ -222,7 +222,7 @@ impl From for Diagnostic { ), ResolverError::NonStructUsedInConstructor { typ, span } => Diagnostic::simple_error( "Only struct types can be used in constructor expressions".into(), - format!("{} has no fields to construct it with", typ), + format!("{typ} has no fields to construct it with"), span, ), ResolverError::NonStructWithGenerics { span } => Diagnostic::simple_error( From 468e06a4caf29ea30ef2f1e79bd65e908d9d7d1b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 13 Feb 2023 13:23:00 -0500 Subject: [PATCH 40/47] remove comment --- crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 7f992543563..21ccca11b4e 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -128,7 +128,6 @@ pub(crate) fn evaluate( // If more than witness is returned, // the result is inside the result type of `Instruction` // as a pointer to an array - // (outputs.len() == 1).then(|| Expression::from(&outputs[0])).map(InternalVar::from) (outputs.len() == 1).then(|| InternalVar::from(outputs[0])) } From 5dde7a301b69a30f94a02eafc87c20a1c628f176 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 13 Feb 2023 15:49:06 -0500 Subject: [PATCH 41/47] PR comments --- .../nargo/tests/test_data/strings/src/main.nr | 15 +++-- crates/noirc_abi/src/lib.rs | 17 +++-- .../src/ssa/acir_gen/operations/intrinsics.rs | 63 ++++++++----------- crates/noirc_evaluator/src/ssa/context.rs | 12 +++- 4 files changed, 55 insertions(+), 52 deletions(-) diff --git a/crates/nargo/tests/test_data/strings/src/main.nr b/crates/nargo/tests/test_data/strings/src/main.nr index ecfdd82d6b8..a22ad06af0f 100644 --- a/crates/nargo/tests/test_data/strings/src/main.nr +++ b/crates/nargo/tests/test_data/strings/src/main.nr @@ -32,18 +32,25 @@ fn test_prints_strings() { let message = "hello world!"; std::println(message); - - let bad_message = "goodbye world"; - - std::println(bad_message); + std::println("goodbye world"); } #[test] fn test_prints_array() { let array = [1, 2, 3, 5, 8]; + // TODO: Printing structs currently not supported + // let s = Test { a: 1, b: 2, c: [3, 4] }; + // std::println(s); + std::println(array); let hash = std::hash::pedersen(array); std::println(hash); +} + +struct Test { + a: Field, + b: Field, + c: [Field; 2], } \ No newline at end of file diff --git a/crates/noirc_abi/src/lib.rs b/crates/noirc_abi/src/lib.rs index 11bbda8ed9a..685f1bf5e16 100644 --- a/crates/noirc_abi/src/lib.rs +++ b/crates/noirc_abi/src/lib.rs @@ -4,8 +4,8 @@ use std::{collections::BTreeMap, convert::TryInto, str}; use acvm::FieldElement; use errors::AbiError; use input_parser::InputValue; +use iter_extended::vecmap; use serde::{Deserialize, Serialize}; - // This is the ABI used to bridge the different TOML formats for the initial // witness, the partial witness generator and the interpreter. // @@ -283,15 +283,12 @@ impl Abi { } pub fn decode_string_value(field_elements: &[FieldElement]) -> String { - let string_as_slice = field_elements - .iter() - .map(|e| { - 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 - }) - .collect::>(); + let string_as_slice = vecmap(field_elements, |e| { + 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 + }); let final_string = str::from_utf8(&string_as_slice).unwrap(); final_string.to_owned() diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 21ccca11b4e..062a1dafcd7 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -244,7 +244,7 @@ fn evaluate_println( ctx: &SsaContext, evaluator: &mut Evaluator, ) { - assert!(args.len() == 1, "print statements can only support one argument"); + assert_eq!(args.len(), 1, "print statements can only support one argument"); let node_id = args[0]; let mut log_string = "".to_owned(); @@ -256,23 +256,21 @@ fn evaluate_println( let mem_array = &ctx.mem[array_id]; let mut field_elements = Vec::new(); for idx in 0..mem_array.len { - if let Some(var) = memory_map.load_array_element_constant_index(mem_array, idx) { - let array_elem_expr = var.expression(); - if array_elem_expr.is_const() { - field_elements.push(array_elem_expr.q_c); - } else { - let var = match var_cache.get(&node_id) { - Some(var) => var.clone(), - _ => InternalVar::from(array_elem_expr.clone()), - }; - if let Some(w) = var.cached_witness() { - log_witnesses.push(*w); - } else { - unreachable!("array element to be logged is missing a witness"); - } - } + let var = memory_map + .load_array_element_constant_index(mem_array, idx) + .expect("array element being logged does not exist in memory"); + let array_elem_expr = var.expression(); + if array_elem_expr.is_const() { + field_elements.push(array_elem_expr.q_c); } else { - unreachable!("array element being logged does not exist in memory"); + let var = match var_cache.get(&node_id) { + Some(var) => var.clone(), + _ => InternalVar::from(array_elem_expr.clone()), + }; + let w = var + .cached_witness() + .expect("array element to be logged is missing a witness"); + log_witnesses.push(w); } } @@ -280,16 +278,8 @@ fn evaluate_println( let final_string = noirc_abi::decode_string_value(&field_elements); log_string.push_str(&final_string); } else if !field_elements.is_empty() { - log_string.push('['); - let mut iter = field_elements.iter().peekable(); - while let Some(elem) = iter.next() { - if iter.peek().is_none() { - log_string.push_str(&elem.to_hex()); - } else { - log_string.push_str(&format!("{}, ", elem.to_hex())); - } - } - log_string.push(']'); + let fields = vecmap(field_elements, |elem| elem.to_hex()); + log_string = format!("[{}]", fields.join(", ")); } } _ => match ctx.get_as_constant(node_id) { @@ -297,19 +287,18 @@ fn evaluate_println( log_string.push_str(&field.to_hex()); } None => { - if let Some(var) = var_cache.get(&node_id) { - if let Some(field) = var.to_const() { - log_string.push_str(&field.to_hex()); - } else if let Some(w) = var.cached_witness() { - log_witnesses.push(*w); - } else { - unreachable!("array element to be logged is missing a witness"); - } - } else { - unreachable!( + let var = var_cache.get(&node_id).unwrap_or_else(|| { + panic!( "invalid input for print statement: {:?}", ctx.try_get_node(node_id).expect("node is missing from SSA") ) + }); + if let Some(field) = var.to_const() { + log_string.push_str(&field.to_hex()); + } else if let Some(w) = var.cached_witness() { + log_witnesses.push(*w); + } else { + unreachable!("array element to be logged is missing a witness"); } } }, diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 41b352fae34..91174e5411f 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -1118,12 +1118,22 @@ impl SsaContext { match &self[node_id] { NodeObject::Function(FunctionKind::Builtin(opcode), ..) => match opcode { builtin::Opcode::Println(_) => { + // Compiler sanity check. This should be caught during typechecking assert!( arguments.len() == 1, "print statements currently only support one argument" ); let is_string = match &arguments[0] { - Expression::Ident(ident) => matches!(ident.typ, Type::String(_)), + Expression::Ident(ident) => match ident.typ { + Type::String(_) => true, + Type::Tuple(_) => { + unreachable!("logging structs/tuples is not supported") + } + Type::Function { .. } => { + unreachable!("logging functions is not supported") + } + _ => false, + }, Expression::Literal(literal) => matches!(literal, Literal::Str(_)), _ => unreachable!("logging this expression type is not supported"), }; From 4f347b31e5e75be4a300078fe3e18fa535db0317 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 13 Feb 2023 16:57:25 -0500 Subject: [PATCH 42/47] some more pr comments, prepend 0x to hex strings and removed prepended inputs --- .../src/ssa/acir_gen/operations/intrinsics.rs | 8 +++++--- crates/noirc_evaluator/src/ssa/context.rs | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 062a1dafcd7..1a3c3de7f1e 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -278,13 +278,15 @@ fn evaluate_println( let final_string = noirc_abi::decode_string_value(&field_elements); log_string.push_str(&final_string); } else if !field_elements.is_empty() { - let fields = vecmap(field_elements, |elem| elem.to_hex()); + let fields = vecmap(field_elements, |elem| { + "0x".to_owned() + &elem.to_hex().trim_start_matches('0') + }); log_string = format!("[{}]", fields.join(", ")); } } _ => match ctx.get_as_constant(node_id) { Some(field) => { - log_string.push_str(&field.to_hex()); + log_string = "0x".to_owned() + &field.to_hex().trim_start_matches('0'); } None => { let var = var_cache.get(&node_id).unwrap_or_else(|| { @@ -294,7 +296,7 @@ fn evaluate_println( ) }); if let Some(field) = var.to_const() { - log_string.push_str(&field.to_hex()); + log_string = "0x".to_owned() + &field.to_hex().trim_start_matches('0'); } else if let Some(w) = var.cached_witness() { log_witnesses.push(*w); } else { diff --git a/crates/noirc_evaluator/src/ssa/context.rs b/crates/noirc_evaluator/src/ssa/context.rs index 91174e5411f..e93b12f22bb 100644 --- a/crates/noirc_evaluator/src/ssa/context.rs +++ b/crates/noirc_evaluator/src/ssa/context.rs @@ -755,8 +755,7 @@ impl SsaContext { while let Some(block) = fb { for iter in &block.instructions { let ins = self.instruction(*iter); - acir.acir_gen_instruction(ins, evaluator, self, show_output) - .map_err(RuntimeError::from)?; + acir.acir_gen_instruction(ins, evaluator, self, show_output)?; } //TODO we should rather follow the jumps fb = block.left.map(|block_id| &self[block_id]); @@ -1119,8 +1118,9 @@ impl SsaContext { NodeObject::Function(FunctionKind::Builtin(opcode), ..) => match opcode { builtin::Opcode::Println(_) => { // Compiler sanity check. This should be caught during typechecking - assert!( - arguments.len() == 1, + assert_eq!( + arguments.len(), + 1, "print statements currently only support one argument" ); let is_string = match &arguments[0] { From 31d56cdd6da97d18de8628e6b36415cf7d801f6c Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 13 Feb 2023 17:05:28 -0500 Subject: [PATCH 43/47] format_field_str method so that we have even number of digits in hex str --- .../src/ssa/acir_gen/operations/intrinsics.rs | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 1a3c3de7f1e..9c74fe303f2 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -13,12 +13,15 @@ use crate::{ }, Evaluator, }; -use acvm::acir::{ - circuit::{ - directives::{Directive, LogInfo}, - opcodes::{BlackBoxFuncCall, FunctionInput, Opcode as AcirOpcode}, +use acvm::{ + acir::{ + circuit::{ + directives::{Directive, LogInfo}, + opcodes::{BlackBoxFuncCall, FunctionInput, Opcode as AcirOpcode}, + }, + native_types::{Expression, Witness}, }, - native_types::{Expression, Witness}, + FieldElement, }; use iter_extended::vecmap; @@ -278,15 +281,13 @@ fn evaluate_println( let final_string = noirc_abi::decode_string_value(&field_elements); log_string.push_str(&final_string); } else if !field_elements.is_empty() { - let fields = vecmap(field_elements, |elem| { - "0x".to_owned() + &elem.to_hex().trim_start_matches('0') - }); + let fields = vecmap(field_elements, |elem| format_field_string(elem)); log_string = format!("[{}]", fields.join(", ")); } } _ => match ctx.get_as_constant(node_id) { Some(field) => { - log_string = "0x".to_owned() + &field.to_hex().trim_start_matches('0'); + log_string = format_field_string(field); } None => { let var = var_cache.get(&node_id).unwrap_or_else(|| { @@ -296,7 +297,7 @@ fn evaluate_println( ) }); if let Some(field) = var.to_const() { - log_string = "0x".to_owned() + &field.to_hex().trim_start_matches('0'); + log_string = format_field_string(field); } else if let Some(w) = var.cached_witness() { log_witnesses.push(*w); } else { @@ -317,3 +318,11 @@ fn evaluate_println( evaluator.opcodes.push(AcirOpcode::Directive(log_directive)); } + +fn format_field_string(field: FieldElement) -> String { + let mut trimmed_field = field.to_hex().trim_start_matches('0').to_owned(); + if trimmed_field.len() % 2 != 0 { + trimmed_field = "0".to_owned() + &trimmed_field + }; + "0x".to_owned() + &trimmed_field +} From d61f4220d29b5fdebb410b518228129e928a314f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 13 Feb 2023 17:16:36 -0500 Subject: [PATCH 44/47] added comment to format_field_string --- .../noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 9c74fe303f2..9fa485fe9cc 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -319,6 +319,9 @@ fn evaluate_println( evaluator.opcodes.push(AcirOpcode::Directive(log_directive)); } +/// This trims any leading zeroes and prepends a '0' if the trimmed string has an odd length. +/// A hex string's length needs to be even, as two digits correspond to +/// one byte. fn format_field_string(field: FieldElement) -> String { let mut trimmed_field = field.to_hex().trim_start_matches('0').to_owned(); if trimmed_field.len() % 2 != 0 { From ee14c9e6cdcf049b7271864f7fa6f722e5033924 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 13 Feb 2023 21:38:55 -0500 Subject: [PATCH 45/47] cargo clippy --- .../src/ssa/acir_gen/operations/intrinsics.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 9fa485fe9cc..08233c6a328 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -281,7 +281,7 @@ fn evaluate_println( let final_string = noirc_abi::decode_string_value(&field_elements); log_string.push_str(&final_string); } else if !field_elements.is_empty() { - let fields = vecmap(field_elements, |elem| format_field_string(elem)); + let fields = vecmap(field_elements, format_field_string); log_string = format!("[{}]", fields.join(", ")); } } @@ -319,8 +319,9 @@ fn evaluate_println( evaluator.opcodes.push(AcirOpcode::Directive(log_directive)); } -/// This trims any leading zeroes and prepends a '0' if the trimmed string has an odd length. -/// A hex string's length needs to be even, as two digits correspond to +/// This trims any leading zeroes. +/// A singular '0' will be prepended as well if the trimmed string has an odd length. +/// A hex string's length needs to be even to decode into bytes, as two digits correspond to /// one byte. fn format_field_string(field: FieldElement) -> String { let mut trimmed_field = field.to_hex().trim_start_matches('0').to_owned(); From 0a93b7facf630489332d64314c45f112098500e9 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 14 Feb 2023 12:31:39 -0500 Subject: [PATCH 46/47] bring back cached_witness() method on InternalVar --- crates/noirc_evaluator/src/ssa/acir_gen/internal_var.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/internal_var.rs b/crates/noirc_evaluator/src/ssa/acir_gen/internal_var.rs index a98888a9062..620db54bd5e 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/internal_var.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/internal_var.rs @@ -45,7 +45,10 @@ impl InternalVar { pub(crate) fn set_id(&mut self, id: NodeId) { self.id = Some(id) } - + pub(crate) fn cached_witness(&self) -> &Option { + &self.cached_witness + } + pub fn to_expression(&self) -> Expression { if let Some(w) = self.cached_witness { expression_from_witness(w) From e77c938e50f5f426a73d03b78f93a308583e1ea1 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 14 Feb 2023 12:36:43 -0500 Subject: [PATCH 47/47] cargo fmt --- crates/noirc_evaluator/src/ssa/acir_gen/internal_var.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/internal_var.rs b/crates/noirc_evaluator/src/ssa/acir_gen/internal_var.rs index 620db54bd5e..c614d940d50 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/internal_var.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/internal_var.rs @@ -48,7 +48,7 @@ impl InternalVar { pub(crate) fn cached_witness(&self) -> &Option { &self.cached_witness } - + pub fn to_expression(&self) -> Expression { if let Some(w) = self.cached_witness { expression_from_witness(w)