Skip to content

Commit d8bd78f

Browse files
vezenovmTomAFrench
andauthored
feat(abi): Tuples as inputs/outputs to main (#2899)
Co-authored-by: Tom French <[email protected]> Co-authored-by: Tom French <[email protected]>
1 parent d942de8 commit d8bd78f

File tree

8 files changed

+132
-1
lines changed

8 files changed

+132
-1
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "tuple_inputs"
3+
type = "bin"
4+
authors = [""]
5+
compiler_version = "0.14.1"
6+
7+
[dependencies]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
pair = [1, 0]
2+
x = [[0, 1, 2], [3, 4, 5]]
3+
4+
[[struct_pair]]
5+
a = "1"
6+
b = ["2", "3", "20"]
7+
8+
[struct_pair.bar]
9+
inner = ["100", "101", "102"]
10+
11+
[[struct_pair]]
12+
inner = ["103", "104", "105"]
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
struct Bar {
2+
inner: [Field; 3],
3+
}
4+
5+
struct Foo {
6+
a: Field,
7+
b: [Field; 3],
8+
bar: Bar,
9+
}
10+
11+
fn main(pair : (Field, Field), x: [(u8, u8, u8); 2], struct_pair: (Foo, Bar)) -> pub (Field, u8) {
12+
assert(pair.0 == 1);
13+
assert(pair.1 == 0);
14+
15+
let mut start_val = 0;
16+
for i in 0..2 {
17+
assert(x[i].0 == start_val);
18+
assert(x[i].1 == start_val + 1);
19+
assert(x[i].2 == start_val + 2);
20+
start_val += 3;
21+
}
22+
23+
assert(struct_pair.0.a == 1);
24+
assert(struct_pair.0.b == [2, 3, 20]);
25+
assert(struct_pair.0.bar.inner == [100, 101, 102]);
26+
assert(struct_pair.1.inner == [103, 104, 105]);
27+
28+
let (u, v) = if pair.0 as u32 < 1 {
29+
(pair.0, pair.0 + 1)
30+
} else {
31+
(pair.0 + 1, pair.0)
32+
};
33+
assert(u == pair.0 + 1);
34+
assert(v == pair.0);
35+
36+
(u, v as u8)
37+
}

tooling/noirc_abi/src/input_parser/json.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ impl JsonTypes {
104104
JsonTypes::Table(map_with_json_types)
105105
}
106106

107+
(InputValue::Vec(vector), AbiType::Tuple { fields }) => {
108+
let fields = try_vecmap(vector.iter().zip(fields), |(value, typ)| {
109+
JsonTypes::try_from_input_value(value, typ)
110+
})?;
111+
JsonTypes::Array(fields)
112+
}
113+
107114
_ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())),
108115
};
109116
Ok(json_value)
@@ -169,6 +176,13 @@ impl InputValue {
169176
InputValue::Struct(native_table)
170177
}
171178

179+
(JsonTypes::Array(array), AbiType::Tuple { fields }) => {
180+
let tuple_fields = try_vecmap(array.into_iter().zip(fields), |(value, typ)| {
181+
InputValue::try_from_json(value, typ, arg_name)
182+
})?;
183+
InputValue::Vec(tuple_fields)
184+
}
185+
172186
(_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())),
173187
};
174188

tooling/noirc_abi/src/input_parser/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ impl InputValue {
6464
})
6565
}
6666

67+
(InputValue::Vec(vec_elements), AbiType::Tuple { fields }) => {
68+
if vec_elements.len() != fields.len() {
69+
return false;
70+
}
71+
72+
vec_elements
73+
.iter()
74+
.zip(fields)
75+
.all(|(input_value, abi_param)| input_value.matches_abi(abi_param))
76+
}
77+
6778
// All other InputValue-AbiType combinations are fundamentally incompatible.
6879
_ => false,
6980
}

tooling/noirc_abi/src/input_parser/toml.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ impl TomlTypes {
102102
TomlTypes::Table(map_with_toml_types)
103103
}
104104

105+
(InputValue::Vec(vector), AbiType::Tuple { fields }) => {
106+
let fields = try_vecmap(vector.iter().zip(fields), |(value, typ)| {
107+
TomlTypes::try_from_input_value(value, typ)
108+
})?;
109+
TomlTypes::Array(fields)
110+
}
111+
105112
_ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())),
106113
};
107114
Ok(toml_value)
@@ -156,6 +163,13 @@ impl InputValue {
156163
InputValue::Struct(native_table)
157164
}
158165

166+
(TomlTypes::Array(array), AbiType::Tuple { fields }) => {
167+
let tuple_fields = try_vecmap(array.into_iter().zip(fields), |(value, typ)| {
168+
InputValue::try_from_toml(value, typ, arg_name)
169+
})?;
170+
InputValue::Vec(tuple_fields)
171+
}
172+
159173
(_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())),
160174
};
161175

tooling/noirc_abi/src/lib.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ pub enum AbiType {
6262
)]
6363
fields: Vec<(String, AbiType)>,
6464
},
65+
Tuple {
66+
fields: Vec<AbiType>,
67+
},
6568
String {
6669
length: u64,
6770
},
@@ -164,7 +167,10 @@ impl AbiType {
164167
context.fully_qualified_struct_path(context.root_crate_id(), struct_type.id);
165168
Self::Struct { fields, path }
166169
}
167-
Type::Tuple(_) => todo!("AbiType::from_type not yet implemented for tuple types"),
170+
Type::Tuple(fields) => {
171+
let fields = vecmap(fields, |typ| Self::from_type(context, typ));
172+
Self::Tuple { fields }
173+
}
168174
Type::TypeVariable(_, _) => unreachable!(),
169175
Type::NamedGeneric(..) => unreachable!(),
170176
Type::Forall(..) => unreachable!(),
@@ -182,6 +188,9 @@ impl AbiType {
182188
AbiType::Struct { fields, .. } => {
183189
fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count())
184190
}
191+
AbiType::Tuple { fields } => {
192+
fields.iter().fold(0, |acc, field_typ| acc + field_typ.field_count())
193+
}
185194
AbiType::String { length } => *length as u32,
186195
}
187196
}
@@ -370,6 +379,11 @@ impl Abi {
370379
encoded_value.extend(Self::encode_value(object[field].clone(), typ)?);
371380
}
372381
}
382+
(InputValue::Vec(vec_elements), AbiType::Tuple { fields }) => {
383+
for (value, typ) in vec_elements.into_iter().zip(fields) {
384+
encoded_value.extend(Self::encode_value(value, typ)?);
385+
}
386+
}
373387
_ => unreachable!("value should have already been checked to match abi type"),
374388
}
375389
Ok(encoded_value)
@@ -462,6 +476,14 @@ fn decode_value(
462476

463477
InputValue::Struct(struct_map)
464478
}
479+
AbiType::Tuple { fields } => {
480+
let mut tuple_elements = Vec::with_capacity(fields.len());
481+
for field_typ in fields {
482+
tuple_elements.push(decode_value(field_iterator, field_typ)?);
483+
}
484+
485+
InputValue::Vec(tuple_elements)
486+
}
465487
};
466488

467489
Ok(value)

tooling/noirc_abi_wasm/src/temp.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ impl JsonTypes {
5555
JsonTypes::Table(map_with_json_types)
5656
}
5757

58+
(InputValue::Vec(vector), AbiType::Tuple { fields }) => {
59+
let fields = try_vecmap(vector.iter().zip(fields), |(value, typ)| {
60+
JsonTypes::try_from_input_value(value, typ)
61+
})?;
62+
JsonTypes::Array(fields)
63+
}
64+
5865
_ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())),
5966
};
6067
Ok(json_value)
@@ -104,6 +111,13 @@ pub(super) fn input_value_from_json_type(
104111
InputValue::Struct(native_table)
105112
}
106113

114+
(JsonTypes::Array(array), AbiType::Tuple { fields }) => {
115+
let tuple_fields = try_vecmap(array.into_iter().zip(fields), |(value, typ)| {
116+
input_value_from_json_type(value, typ, arg_name)
117+
})?;
118+
InputValue::Vec(tuple_fields)
119+
}
120+
107121
(_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())),
108122
};
109123

0 commit comments

Comments
 (0)