From 0d4a5c16014f77953afe95d7c90f472a37fd419d Mon Sep 17 00:00:00 2001 From: synthia Date: Tue, 12 Dec 2023 22:55:41 -0800 Subject: [PATCH 01/10] feat: Allow converting tuples to printable type --- compiler/noirc_frontend/src/hir_def/types.rs | 6 ++++-- compiler/noirc_printable_type/src/lib.rs | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 69ae6e36d22..82949f89175 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1612,8 +1612,10 @@ impl From<&Type> for PrintableType { let fields = vecmap(fields, |(name, typ)| (name, typ.into())); PrintableType::Struct { fields, name: struct_type.name.to_string() } } - Type::TraitAsType(..) => unreachable!(), - Type::Tuple(_) => todo!("printing tuple types is not yet implemented"), + Type::TraitAsType(_) => unreachable!(), + Type::Tuple(types) => { + PrintableType::Tuple { types: vecmap(types, |typ| typ.into()) } + } Type::TypeVariable(_, _) => unreachable!(), Type::NamedGeneric(..) => unreachable!(), Type::Forall(..) => unreachable!(), diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index 273e2d512ea..bf6b5e7e374 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -15,6 +15,9 @@ pub enum PrintableType { #[serde(rename = "type")] typ: Box, }, + Tuple { + types: Vec, + }, SignedInteger { width: u32, }, @@ -40,6 +43,7 @@ impl PrintableType { | Self::UnsignedInteger { .. } | Self::Boolean => 1, Self::Array { length, typ } => typ.field_count() * (*length as u32), + Self::Tuple { types } => types.iter().fold(0, |count,typ| count + typ.field_count()), Self::Struct { fields, .. } => { fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count()) } @@ -317,6 +321,9 @@ fn decode_value( PrintableValue::Vec(array_elements) } + PrintableType::Tuple { types } => { + PrintableValue::Vec(vecmap(types, |typ| decode_value(field_iterator, typ))) + } PrintableType::String { length } => { let field_elements: Vec = field_iterator.take(*length as usize).collect(); From c7b83f02f24b9f899f6d6fa82671c0c92a41a663 Mon Sep 17 00:00:00 2001 From: synthia Date: Thu, 14 Dec 2023 13:58:52 -0800 Subject: [PATCH 02/10] feat: Allow variable size arrays for printable type conversion --- compiler/noirc_frontend/src/hir_def/types.rs | 2 +- compiler/noirc_printable_type/src/lib.rs | 54 +++++++++++++++----- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 82949f89175..bdfd76944d3 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1583,7 +1583,7 @@ impl From<&Type> for PrintableType { match value { Type::FieldElement => PrintableType::Field, Type::Array(size, typ) => { - let length = size.evaluate_to_u64().expect("Cannot print variable sized arrays"); + let length = size.evaluate_to_u64(); let typ = typ.as_ref(); PrintableType::Array { length, typ: Box::new(typ.into()) } } diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index bf6b5e7e374..920a57ae901 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -11,7 +11,7 @@ use thiserror::Error; pub enum PrintableType { Field, Array { - length: u64, + length: Option, #[serde(rename = "type")] typ: Box, }, @@ -36,18 +36,28 @@ pub enum PrintableType { impl PrintableType { /// Returns the number of field elements required to represent the type once encoded. - fn field_count(&self) -> u32 { + fn field_count(&self) -> Option { match self { Self::Field | Self::SignedInteger { .. } | Self::UnsignedInteger { .. } - | Self::Boolean => 1, - Self::Array { length, typ } => typ.field_count() * (*length as u32), - Self::Tuple { types } => types.iter().fold(0, |count,typ| count + typ.field_count()), + | Self::Boolean => Some(1), + Self::Array { length, typ } => { + length.and_then(|len| { + typ.field_count().map(|x| x*(len as u32)) + }) + }, + Self::Tuple { types } => { + types.iter().fold(Some(0), |count,typ| { + count.and_then(|c| typ.field_count().map(|fc| c + fc)) + }) + }, Self::Struct { fields, .. } => { - fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count()) - } - Self::String { length } => *length as u32, + fields.iter().fold(Some(0), |count, (_, field_type)| { + count.and_then(|c| field_type.field_count().map(|fc| c + fc)) + }) + }, + Self::String { length } => Some(*length as u32), } } } @@ -137,9 +147,9 @@ fn convert_fmt_string_inputs( .enumerate() { let printable_type = fetch_printable_type(printable_value)?; - let type_size = printable_type.field_count() as usize; - let value = match printable_type { - PrintableType::Array { .. } | PrintableType::String { .. } => { + let field_count = printable_type.field_count(); + let value = match (field_count, &printable_type) { + (_, PrintableType::Array { .. } | PrintableType::String { .. }) => { // Arrays and strings are represented in a single value vector rather than multiple separate input values let mut input_values_as_fields = input_and_printable_values[i] .values() @@ -147,13 +157,16 @@ fn convert_fmt_string_inputs( .map(|value| value.to_field()); decode_value(&mut input_values_as_fields, &printable_type) } - _ => { + (Some(type_size), _) => { // We must use a flat map here as each value in a struct will be in a separate input value - let mut input_values_as_fields = input_and_printable_values[i..(i + type_size)] + let mut input_values_as_fields = input_and_printable_values[i..(i + (type_size as usize))] .iter() .flat_map(|param| vecmap(param.values(), |value| value.to_field())); decode_value(&mut input_values_as_fields, &printable_type) } + (None, _) => { + panic!("unexpected None field_count for type {printable_type:?}"); + } }; output.push((value, printable_type)); @@ -312,7 +325,20 @@ fn decode_value( PrintableValue::Field(field_element) } - PrintableType::Array { length, typ } => { + PrintableType::Array { length: None, typ } => { + // TODO: maybe the len is the first arg? not sure + let length = field_iterator.next() + .expect("not enough data to decode variable array length") + .to_u128() as usize; + println!["FIRST ARG (LENGTH?)={length}"]; + let mut array_elements = Vec::with_capacity(length); + for _ in 0..length { + array_elements.push(decode_value(field_iterator, typ)); + } + + PrintableValue::Vec(array_elements) + }, + PrintableType::Array { length: Some(length), typ } => { let length = *length as usize; let mut array_elements = Vec::with_capacity(length); for _ in 0..length { From baede20e4f0c5ba1e71cba24b85e0f324f9c2a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Tue, 19 Dec 2023 17:55:53 -0500 Subject: [PATCH 03/10] feat: Support printing variables of Function type --- compiler/noirc_frontend/src/hir_def/types.rs | 2 +- compiler/noirc_printable_type/src/lib.rs | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index bdfd76944d3..b19e1bdef12 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1619,7 +1619,7 @@ impl From<&Type> for PrintableType { Type::TypeVariable(_, _) => unreachable!(), Type::NamedGeneric(..) => unreachable!(), Type::Forall(..) => unreachable!(), - Type::Function(_, _, _) => unreachable!(), + Type::Function(_, _, _) => PrintableType::Function, Type::MutableReference(_) => unreachable!("cannot print &mut"), Type::NotConstant => unreachable!(), } diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index 920a57ae901..0e1e9371608 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -32,6 +32,7 @@ pub enum PrintableType { String { length: u64, }, + Function, } impl PrintableType { @@ -41,7 +42,8 @@ impl PrintableType { Self::Field | Self::SignedInteger { .. } | Self::UnsignedInteger { .. } - | Self::Boolean => Some(1), + | Self::Boolean + | Self::Function => Some(1), Self::Array { length, typ } => { length.and_then(|len| { typ.field_count().map(|x| x*(len as u32)) @@ -213,6 +215,9 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { output.push_str("false"); } } + (PrintableValue::Field(_), PrintableType::Function) => { + output.push_str("<>"); + } (PrintableValue::Vec(vector), PrintableType::Array { typ, .. }) => { output.push('['); let mut values = vector.iter().peekable(); @@ -320,7 +325,8 @@ fn decode_value( PrintableType::Field | PrintableType::SignedInteger { .. } | PrintableType::UnsignedInteger { .. } - | PrintableType::Boolean => { + | PrintableType::Boolean + | PrintableType::Function => { let field_element = field_iterator.next().unwrap(); PrintableValue::Field(field_element) From 9236d79ccd737a5dc22d39fe99823ad9f1fd5dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Wed, 20 Dec 2023 12:28:09 -0500 Subject: [PATCH 04/10] feat: Make tuples printable --- compiler/noirc_printable_type/src/lib.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index 0e1e9371608..007f16f7d3b 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -255,6 +255,20 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { output.push_str(" }"); } + (PrintableValue::Vec(values), PrintableType::Tuple { types }) => { + output.push_str("("); + let mut elems = values.iter().zip(types).peekable(); + while let Some((value, typ)) = elems.next() { + output.push_str( + &PrintableValueDisplay::Plain(value.clone(), typ.clone()).to_string(), + ); + if elems.peek().is_some() { + output.push_str(", "); + } + } + output.push_str(")"); + } + _ => return None, }; From f21d98c9dc3dff579893b4b8af60f2a34d5912db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Tue, 2 Jan 2024 17:09:33 -0500 Subject: [PATCH 05/10] feat: Print mutable references as an opaque string --- compiler/noirc_frontend/src/hir_def/types.rs | 4 ++-- compiler/noirc_printable_type/src/lib.rs | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index b19e1bdef12..15ac7b34f86 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1612,7 +1612,7 @@ impl From<&Type> for PrintableType { let fields = vecmap(fields, |(name, typ)| (name, typ.into())); PrintableType::Struct { fields, name: struct_type.name.to_string() } } - Type::TraitAsType(_) => unreachable!(), + Type::TraitAsType(_, _, _) => unreachable!(), Type::Tuple(types) => { PrintableType::Tuple { types: vecmap(types, |typ| typ.into()) } } @@ -1620,7 +1620,7 @@ impl From<&Type> for PrintableType { Type::NamedGeneric(..) => unreachable!(), Type::Forall(..) => unreachable!(), Type::Function(_, _, _) => PrintableType::Function, - Type::MutableReference(_) => unreachable!("cannot print &mut"), + Type::MutableReference(_) => PrintableType::MutableReference, Type::NotConstant => unreachable!(), } } diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index 007f16f7d3b..483260595b1 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -33,6 +33,7 @@ pub enum PrintableType { length: u64, }, Function, + MutableReference, } impl PrintableType { @@ -43,7 +44,8 @@ impl PrintableType { | Self::SignedInteger { .. } | Self::UnsignedInteger { .. } | Self::Boolean - | Self::Function => Some(1), + | Self::Function + | Self::MutableReference => Some(1), Self::Array { length, typ } => { length.and_then(|len| { typ.field_count().map(|x| x*(len as u32)) @@ -218,6 +220,9 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { (PrintableValue::Field(_), PrintableType::Function) => { output.push_str("<>"); } + (_, PrintableType::MutableReference { .. }) => { + output.push_str("<>"); + } (PrintableValue::Vec(vector), PrintableType::Array { typ, .. }) => { output.push('['); let mut values = vector.iter().peekable(); @@ -340,17 +345,16 @@ fn decode_value( | PrintableType::SignedInteger { .. } | PrintableType::UnsignedInteger { .. } | PrintableType::Boolean - | PrintableType::Function => { + | PrintableType::Function + | PrintableType::MutableReference => { let field_element = field_iterator.next().unwrap(); PrintableValue::Field(field_element) } PrintableType::Array { length: None, typ } => { - // TODO: maybe the len is the first arg? not sure let length = field_iterator.next() .expect("not enough data to decode variable array length") .to_u128() as usize; - println!["FIRST ARG (LENGTH?)={length}"]; let mut array_elements = Vec::with_capacity(length); for _ in 0..length { array_elements.push(decode_value(field_iterator, typ)); From 9bd048a73814e77d2325bebac9a579a2e7debf35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Tue, 16 Jan 2024 16:11:17 -0500 Subject: [PATCH 06/10] chore: cargo fmt & clippy --- compiler/noirc_frontend/src/hir_def/types.rs | 4 +-- compiler/noirc_printable_type/src/lib.rs | 34 +++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 15ac7b34f86..e2e732edb8d 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1613,9 +1613,7 @@ impl From<&Type> for PrintableType { PrintableType::Struct { fields, name: struct_type.name.to_string() } } Type::TraitAsType(_, _, _) => unreachable!(), - Type::Tuple(types) => { - PrintableType::Tuple { types: vecmap(types, |typ| typ.into()) } - } + Type::Tuple(types) => PrintableType::Tuple { types: vecmap(types, |typ| typ.into()) }, Type::TypeVariable(_, _) => unreachable!(), Type::NamedGeneric(..) => unreachable!(), Type::Forall(..) => unreachable!(), diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index 483260595b1..9a57ef26f07 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -47,20 +47,14 @@ impl PrintableType { | Self::Function | Self::MutableReference => Some(1), Self::Array { length, typ } => { - length.and_then(|len| { - typ.field_count().map(|x| x*(len as u32)) - }) - }, - Self::Tuple { types } => { - types.iter().fold(Some(0), |count,typ| { - count.and_then(|c| typ.field_count().map(|fc| c + fc)) - }) - }, - Self::Struct { fields, .. } => { - fields.iter().fold(Some(0), |count, (_, field_type)| { - count.and_then(|c| field_type.field_count().map(|fc| c + fc)) - }) - }, + length.and_then(|len| typ.field_count().map(|x| x * (len as u32))) + } + Self::Tuple { types } => types + .iter() + .fold(Some(0), |count, typ| count.and_then(|c| typ.field_count().map(|fc| c + fc))), + Self::Struct { fields, .. } => fields.iter().fold(Some(0), |count, (_, field_type)| { + count.and_then(|c| field_type.field_count().map(|fc| c + fc)) + }), Self::String { length } => Some(*length as u32), } } @@ -163,7 +157,8 @@ fn convert_fmt_string_inputs( } (Some(type_size), _) => { // We must use a flat map here as each value in a struct will be in a separate input value - let mut input_values_as_fields = input_and_printable_values[i..(i + (type_size as usize))] + let mut input_values_as_fields = input_and_printable_values + [i..(i + (type_size as usize))] .iter() .flat_map(|param| vecmap(param.values(), |value| value.to_field())); decode_value(&mut input_values_as_fields, &printable_type) @@ -261,7 +256,7 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { } (PrintableValue::Vec(values), PrintableType::Tuple { types }) => { - output.push_str("("); + output.push('('); let mut elems = values.iter().zip(types).peekable(); while let Some((value, typ)) = elems.next() { output.push_str( @@ -271,7 +266,7 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { output.push_str(", "); } } - output.push_str(")"); + output.push(')'); } _ => return None, @@ -352,7 +347,8 @@ fn decode_value( PrintableValue::Field(field_element) } PrintableType::Array { length: None, typ } => { - let length = field_iterator.next() + let length = field_iterator + .next() .expect("not enough data to decode variable array length") .to_u128() as usize; let mut array_elements = Vec::with_capacity(length); @@ -361,7 +357,7 @@ fn decode_value( } PrintableValue::Vec(array_elements) - }, + } PrintableType::Array { length: Some(length), typ } => { let length = *length as usize; let mut array_elements = Vec::with_capacity(length); From 8978897ec6bf6c1baf3da0b705ca95087a90a7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Tue, 16 Jan 2024 18:09:46 -0500 Subject: [PATCH 07/10] feat: Fix handling of functions, mutable refs and structs/tuples when printing --- compiler/noirc_frontend/src/hir_def/types.rs | 10 +++- compiler/noirc_printable_type/src/lib.rs | 60 +++++++++++++------- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index e2e732edb8d..eee2934dfc0 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1604,7 +1604,7 @@ impl From<&Type> for PrintableType { } Type::FmtString(_, _) => unreachable!("format strings cannot be printed"), Type::Error => unreachable!(), - Type::Unit => unreachable!(), + Type::Unit => PrintableType::Unit, Type::Constant(_) => unreachable!(), Type::Struct(def, ref args) => { let struct_type = def.borrow(); @@ -1617,8 +1617,12 @@ impl From<&Type> for PrintableType { Type::TypeVariable(_, _) => unreachable!(), Type::NamedGeneric(..) => unreachable!(), Type::Forall(..) => unreachable!(), - Type::Function(_, _, _) => PrintableType::Function, - Type::MutableReference(_) => PrintableType::MutableReference, + Type::Function(_, _, env) => { + PrintableType::Function { env: Box::new(env.as_ref().into()) } + } + Type::MutableReference(typ) => { + PrintableType::MutableReference { typ: Box::new(typ.as_ref().into()) } + } Type::NotConstant => unreachable!(), } } diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index 9a57ef26f07..a346ada015e 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -32,8 +32,13 @@ pub enum PrintableType { String { length: u64, }, - Function, - MutableReference, + Function { + env: Box, + }, + MutableReference { + typ: Box, + }, + Unit, } impl PrintableType { @@ -43,9 +48,7 @@ impl PrintableType { Self::Field | Self::SignedInteger { .. } | Self::UnsignedInteger { .. } - | Self::Boolean - | Self::Function - | Self::MutableReference => Some(1), + | Self::Boolean => Some(1), Self::Array { length, typ } => { length.and_then(|len| typ.field_count().map(|x| x * (len as u32))) } @@ -56,6 +59,9 @@ impl PrintableType { count.and_then(|c| field_type.field_count().map(|fc| c + fc)) }), Self::String { length } => Some(*length as u32), + Self::Function { env: typ } => Some(1 + typ.field_count().unwrap_or(0)), + Self::MutableReference { typ } => typ.field_count(), + Self::Unit => Some(0), } } } @@ -126,41 +132,45 @@ fn convert_string_inputs( fn convert_fmt_string_inputs( foreign_call_inputs: &[ForeignCallParam], ) -> Result { - let (message, input_and_printable_values) = + let (message, input_and_printable_types) = foreign_call_inputs.split_first().ok_or(ForeignCallError::MissingForeignCallInputs)?; let message_as_fields = vecmap(message.values(), |value| value.to_field()); let message_as_string = decode_string_value(&message_as_fields); - let (num_values, input_and_printable_values) = input_and_printable_values + let (num_values, input_and_printable_types) = input_and_printable_types .split_first() .ok_or(ForeignCallError::MissingForeignCallInputs)?; let mut output = Vec::new(); let num_values = num_values.unwrap_value().to_field().to_u128() as usize; - for (i, printable_value) in input_and_printable_values - .iter() - .skip(input_and_printable_values.len() - num_values) - .enumerate() + let mut next_value_index = 0usize; // index to input_and_printable_values to the current value + for printable_type in + input_and_printable_types.iter().skip(input_and_printable_types.len() - num_values) { - let printable_type = fetch_printable_type(printable_value)?; + let printable_type = fetch_printable_type(printable_type)?; let field_count = printable_type.field_count(); let value = match (field_count, &printable_type) { (_, PrintableType::Array { .. } | PrintableType::String { .. }) => { // Arrays and strings are represented in a single value vector rather than multiple separate input values - let mut input_values_as_fields = input_and_printable_values[i] + let mut input_values_as_fields = input_and_printable_types[next_value_index] .values() .into_iter() .map(|value| value.to_field()); + // Arrays and strings are encoded as arrays, so we advance the index for the next value by 1 + next_value_index += 1; decode_value(&mut input_values_as_fields, &printable_type) } (Some(type_size), _) => { // We must use a flat map here as each value in a struct will be in a separate input value - let mut input_values_as_fields = input_and_printable_values - [i..(i + (type_size as usize))] + let mut input_values_as_fields = input_and_printable_types + [next_value_index..(next_value_index + (type_size as usize))] .iter() .flat_map(|param| vecmap(param.values(), |value| value.to_field())); + // Other types will be flattened, so we need to advance the + // index for the next value by the field count of the current value + next_value_index += type_size as usize; decode_value(&mut input_values_as_fields, &printable_type) } (None, _) => { @@ -212,7 +222,7 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { output.push_str("false"); } } - (PrintableValue::Field(_), PrintableType::Function) => { + (PrintableValue::Field(_), PrintableType::Function { .. }) => { output.push_str("<>"); } (_, PrintableType::MutableReference { .. }) => { @@ -269,6 +279,8 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { output.push(')'); } + (_, PrintableType::Unit) => output.push_str("()"), + _ => return None, }; @@ -339,9 +351,7 @@ fn decode_value( PrintableType::Field | PrintableType::SignedInteger { .. } | PrintableType::UnsignedInteger { .. } - | PrintableType::Boolean - | PrintableType::Function - | PrintableType::MutableReference => { + | PrintableType::Boolean => { let field_element = field_iterator.next().unwrap(); PrintableValue::Field(field_element) @@ -386,6 +396,18 @@ fn decode_value( PrintableValue::Struct(struct_map) } + PrintableType::Function { env } => { + let field_element = field_iterator.next().unwrap(); + let func_ref = PrintableValue::Field(field_element); + // we want to consume the fields from the environment, but for now they are not actually printed + decode_value(field_iterator, env); + func_ref + } + PrintableType::MutableReference { typ } => { + // we decode the reference, but it's not really used for printing + decode_value(field_iterator, typ) + } + PrintableType::Unit => PrintableValue::Field(FieldElement::zero()), } } From a6d6384cc61f1b4238e2ebc77a4f30da146f938b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Wed, 17 Jan 2024 11:27:54 -0500 Subject: [PATCH 08/10] feat: stream values when decoding for format printing and lift restriction on slices --- .../src/monomorphization/mod.rs | 5 -- compiler/noirc_printable_type/src/lib.rs | 62 ++----------------- 2 files changed, 6 insertions(+), 61 deletions(-) diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index ac11e00ad20..782ce9459bc 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -1029,11 +1029,6 @@ impl<'interner> Monomorphizer<'interner> { } fn append_printable_type_info_inner(typ: &Type, arguments: &mut Vec) { - if let HirType::Array(size, _) = typ { - if let HirType::NotConstant = **size { - unreachable!("println does not support slices. Convert the slice to an array before passing it to println"); - } - } let printable_type: PrintableType = typ.into(); let abi_as_string = serde_json::to_string(&printable_type) .expect("ICE: expected PrintableType to serialize"); diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index a346ada015e..18f2fe0a873 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -41,31 +41,6 @@ pub enum PrintableType { Unit, } -impl PrintableType { - /// Returns the number of field elements required to represent the type once encoded. - fn field_count(&self) -> Option { - match self { - Self::Field - | Self::SignedInteger { .. } - | Self::UnsignedInteger { .. } - | Self::Boolean => Some(1), - Self::Array { length, typ } => { - length.and_then(|len| typ.field_count().map(|x| x * (len as u32))) - } - Self::Tuple { types } => types - .iter() - .fold(Some(0), |count, typ| count.and_then(|c| typ.field_count().map(|fc| c + fc))), - Self::Struct { fields, .. } => fields.iter().fold(Some(0), |count, (_, field_type)| { - count.and_then(|c| field_type.field_count().map(|fc| c + fc)) - }), - Self::String { length } => Some(*length as u32), - Self::Function { env: typ } => Some(1 + typ.field_count().unwrap_or(0)), - Self::MutableReference { typ } => typ.field_count(), - Self::Unit => Some(0), - } - } -} - /// 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 @@ -145,38 +120,13 @@ fn convert_fmt_string_inputs( let mut output = Vec::new(); let num_values = num_values.unwrap_value().to_field().to_u128() as usize; - let mut next_value_index = 0usize; // index to input_and_printable_values to the current value - for printable_type in - input_and_printable_types.iter().skip(input_and_printable_types.len() - num_values) - { + let types_start_at = input_and_printable_types.len() - num_values; + let mut input_iter = input_and_printable_types[0..types_start_at] + .iter() + .flat_map(|param| vecmap(param.values(), |value| value.to_field())); + for printable_type in input_and_printable_types.iter().skip(types_start_at) { let printable_type = fetch_printable_type(printable_type)?; - let field_count = printable_type.field_count(); - let value = match (field_count, &printable_type) { - (_, PrintableType::Array { .. } | PrintableType::String { .. }) => { - // Arrays and strings are represented in a single value vector rather than multiple separate input values - let mut input_values_as_fields = input_and_printable_types[next_value_index] - .values() - .into_iter() - .map(|value| value.to_field()); - // Arrays and strings are encoded as arrays, so we advance the index for the next value by 1 - next_value_index += 1; - decode_value(&mut input_values_as_fields, &printable_type) - } - (Some(type_size), _) => { - // We must use a flat map here as each value in a struct will be in a separate input value - let mut input_values_as_fields = input_and_printable_types - [next_value_index..(next_value_index + (type_size as usize))] - .iter() - .flat_map(|param| vecmap(param.values(), |value| value.to_field())); - // Other types will be flattened, so we need to advance the - // index for the next value by the field count of the current value - next_value_index += type_size as usize; - decode_value(&mut input_values_as_fields, &printable_type) - } - (None, _) => { - panic!("unexpected None field_count for type {printable_type:?}"); - } - }; + let value = decode_value(&mut input_iter, &printable_type); output.push((value, printable_type)); } From 823e83305f292be301fff053c157f962c65d674b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Wed, 17 Jan 2024 17:31:25 -0500 Subject: [PATCH 09/10] feat: Add new printable types to debug_logs test sample --- .../execution_success/debug_logs/src/main.nr | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test_programs/execution_success/debug_logs/src/main.nr b/test_programs/execution_success/debug_logs/src/main.nr index 6accdf725d9..398476dabf0 100644 --- a/test_programs/execution_success/debug_logs/src/main.nr +++ b/test_programs/execution_success/debug_logs/src/main.nr @@ -39,7 +39,28 @@ fn main(x: Field, y: pub Field) { let struct_string = if x != 5 { f"{foo}" } else { f"{bar}" }; std::println(struct_string); + let one_tuple = (1, 2, 3); + let another_tuple = (4, 5, 6); + std::println(f"one_tuple: {one_tuple}, another_tuple: {another_tuple}"); + std::println(one_tuple); + + let tuples_nested = (one_tuple, another_tuple); + std::println(f"tuples_nested: {tuples_nested}"); + std::println(tuples_nested); + regression_2906(); + + let free_lambda = |x| x + 1; + let sentinel: u32 = 8888; + std::println(f"free_lambda: {free_lambda}, sentinel: {sentinel}"); + std::println(free_lambda); + + let one = 1; + let closured_lambda = |x| x + one; + std::println(f"closured_lambda: {closured_lambda}, sentinel: {sentinel}"); + std::println(closured_lambda); + + types_printable_in_brillig_only(); } fn string_identity(string: fmtstr<14, (Field, Field)>) -> fmtstr<14, (Field, Field)> { @@ -79,3 +100,22 @@ fn regression_2906() { dep::std::println(f"array_five_vals: {array_five_vals}, label_five_vals: {label_five_vals}"); } + +unconstrained fn types_printable_in_brillig_only() { + let mut a_tuple = (1,2,3); + let mut tuple_mut_ref = &mut a_tuple; + let sentinel: u32 = 8888; + std::println(f"tuple_mut_ref: {tuple_mut_ref}, sentinel: {sentinel}"); + std::println(tuple_mut_ref); + + let mut a_vector: Vec = Vec::new(); + a_vector.push(10); + a_vector.push(20); + a_vector.push(30); + std::println(f"a_vector: {a_vector}, sentinel: {sentinel}"); + std::println(a_vector); + + let vec_slice = a_vector.slice; + std::println(f"vec_slice: {vec_slice}, sentinel: {sentinel}"); + std::println(vec_slice); +} From 2732c794d1cc3998aad8b5b0f427b23183404fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Thu, 18 Jan 2024 10:55:58 -0500 Subject: [PATCH 10/10] feat: Bring back restriction on printing slices and add one on mutable refs Even though the printing support is there, neither of them can be passed from ACIR into Brillig. So the restriction is for consistency and to be able to provide a better error message to users. --- .../src/monomorphization/mod.rs | 10 ++++++++++ .../execution_success/debug_logs/src/main.nr | 20 ------------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 782ce9459bc..b68cf30c3e5 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -1029,6 +1029,16 @@ impl<'interner> Monomorphizer<'interner> { } fn append_printable_type_info_inner(typ: &Type, arguments: &mut Vec) { + // Disallow printing slices and mutable references for consistency, + // since they cannot be passed from ACIR into Brillig + if let HirType::Array(size, _) = typ { + if let HirType::NotConstant = **size { + unreachable!("println does not support slices. Convert the slice to an array before passing it to println"); + } + } else if matches!(typ, HirType::MutableReference(_)) { + unreachable!("println does not support mutable references."); + } + let printable_type: PrintableType = typ.into(); let abi_as_string = serde_json::to_string(&printable_type) .expect("ICE: expected PrintableType to serialize"); diff --git a/test_programs/execution_success/debug_logs/src/main.nr b/test_programs/execution_success/debug_logs/src/main.nr index 398476dabf0..52c910065c1 100644 --- a/test_programs/execution_success/debug_logs/src/main.nr +++ b/test_programs/execution_success/debug_logs/src/main.nr @@ -59,8 +59,6 @@ fn main(x: Field, y: pub Field) { let closured_lambda = |x| x + one; std::println(f"closured_lambda: {closured_lambda}, sentinel: {sentinel}"); std::println(closured_lambda); - - types_printable_in_brillig_only(); } fn string_identity(string: fmtstr<14, (Field, Field)>) -> fmtstr<14, (Field, Field)> { @@ -101,21 +99,3 @@ fn regression_2906() { dep::std::println(f"array_five_vals: {array_five_vals}, label_five_vals: {label_five_vals}"); } -unconstrained fn types_printable_in_brillig_only() { - let mut a_tuple = (1,2,3); - let mut tuple_mut_ref = &mut a_tuple; - let sentinel: u32 = 8888; - std::println(f"tuple_mut_ref: {tuple_mut_ref}, sentinel: {sentinel}"); - std::println(tuple_mut_ref); - - let mut a_vector: Vec = Vec::new(); - a_vector.push(10); - a_vector.push(20); - a_vector.push(30); - std::println(f"a_vector: {a_vector}, sentinel: {sentinel}"); - std::println(a_vector); - - let vec_slice = a_vector.slice; - std::println(f"vec_slice: {vec_slice}, sentinel: {sentinel}"); - std::println(vec_slice); -}