diff --git a/examples/ZoKrates/pf/arr_str_arr_str2.zok b/examples/ZoKrates/pf/arr_str_arr_str2.zok new file mode 100644 index 000000000..f6866d14f --- /dev/null +++ b/examples/ZoKrates/pf/arr_str_arr_str2.zok @@ -0,0 +1,10 @@ +struct Pt { + field x + field y +} +struct Pts { + Pt[2] pts +} + +def main(private Pts[1] pts) -> Pt: + return Pt {x: pts[0].pts[0].x * pts[0].pts[1].x, y: pts[0].pts[0].y * pts[0].pts[1].y} diff --git a/examples/ZoKrates/pf/arr_str_arr_str2.zok.pin b/examples/ZoKrates/pf/arr_str_arr_str2.zok.pin new file mode 100644 index 000000000..2a76b6e22 --- /dev/null +++ b/examples/ZoKrates/pf/arr_str_arr_str2.zok.pin @@ -0,0 +1,12 @@ +(set_default_modulus 52435875175126190479447740508185965837690552500527637822603658699938581184513 +(let ( + (pts.0.pts.0.x #f2) + (pts.0.pts.0.y #f4) + (pts.0.pts.1.x #f2) + (pts.0.pts.1.y #f4) +) true ;ignored +) +) + + + diff --git a/examples/ZoKrates/pf/arr_str_arr_str2.zok.vin b/examples/ZoKrates/pf/arr_str_arr_str2.zok.vin new file mode 100644 index 000000000..233b7b9e2 --- /dev/null +++ b/examples/ZoKrates/pf/arr_str_arr_str2.zok.vin @@ -0,0 +1,8 @@ +(set_default_modulus 52435875175126190479447740508185965837690552500527637822603658699938581184513 +(let ( + (return.x #f4) + (return.y #f16) +) true ;ignored +) +) + diff --git a/src/front/zsharp/term.rs b/src/front/zsharp/term.rs index 2e6810fde..9cbcdcc12 100644 --- a/src/front/zsharp/term.rs +++ b/src/front/zsharp/term.rs @@ -169,6 +169,43 @@ impl T { s => Err(format!("Not an array: {s}")), } } + fn unwrap_struct_ir(self) -> Result, String> { + match &self.ty { + Ty::Struct(_, map) => Ok(FieldList::new( + map.fields() + .map(|(field, _)| { + let (idx, _) = map + .search(field) + .unwrap_or_else(|| panic!("{}", "No field '{field}'")); + (field.clone(), term![Op::Field(idx); self.term.clone()]) + }) + .collect(), + )), + s => Err(format!("{s} is not a struct")), + } + } + pub fn unwrap_struct(self) -> Result, String> { + match &self.ty { + Ty::Struct(_, fields) => { + let fields = (*fields).clone(); + Ok(FieldList::new( + self.unwrap_struct_ir()? + .fields() + .map(|(field, t)| { + let f_ty = fields + .search(field) + .unwrap_or_else(|| panic!("{}", "No field '{field}'")) + .1 + .clone(); + + (field.clone(), T::new(f_ty, t.clone())) + }) + .collect(), + )) + } + s => Err(format!("Not a struct: {s}")), + } + } pub fn new_array(v: Vec) -> Result { array(v) } @@ -1209,30 +1246,37 @@ impl Embeddable for ZSharp { None => std::iter::repeat(None).take(*n).collect(), }; debug_assert_eq!(*n, ps.len()); - array( - ps.into_iter().enumerate().map(|(i, p)| { - self.declare_input(ctx, &Ty::Field, idx_name(&name, i), visibility, p) - }), - ) + array(ps.into_iter().enumerate().map(|(i, p)| { + self.declare_input(ctx, &Ty::Field, idx_name(&name, i), visibility, p) + })) .unwrap() } - Ty::Struct(n, fs) => T::new_struct( - n.clone(), - fs.fields() - .map(|(f_name, f_ty)| { - ( - f_name.clone(), - self.declare_input( - ctx, - f_ty, - field_name(&name, f_name), - visibility, - precompute.as_ref().map(|_| unimplemented!("precomputations for declared inputs that are Z# structures")), - ), - ) - }) - .collect(), - ), + + Ty::Struct(n, fs) => { + let ps = match precompute.map(|p| p.unwrap_struct()) { + Some(Ok(fl)) => fl, + Some(Err(e)) => panic!("{}", e), + None => FieldList::new(vec![]), + }; + + Self::T::new_struct( + n.clone(), + fs.fields() + .map(|(f_name, f_ty)| { + ( + f_name.clone(), + self.declare_input( + ctx, + f_ty, + field_name(&name, f_name), + visibility, + ps.search(f_name).map(|(_, p)| p.clone()), + ), + ) + }) + .collect(), + ) + } } } fn ite(&self, _ctx: &mut CirCtx, cond: Term, t: Self::T, f: Self::T) -> Self::T {