merge split
This commit is contained in:
commit
81d670e531
382 changed files with 2783 additions and 4198 deletions
1
changelogs/unreleased/1168-schaeff
Normal file
1
changelogs/unreleased/1168-schaeff
Normal file
|
@ -0,0 +1 @@
|
|||
Introduce the `mut` keyword and make variables immutable by default
|
1
changelogs/unreleased/1170-dark64
Normal file
1
changelogs/unreleased/1170-dark64
Normal file
|
@ -0,0 +1 @@
|
|||
Remove multiple returns
|
1
changelogs/unreleased/1172-dark64
Normal file
1
changelogs/unreleased/1172-dark64
Normal file
|
@ -0,0 +1 @@
|
|||
Use signature output for constant parameter inference
|
|
@ -277,7 +277,7 @@ fn parse_value<T: Field>(
|
|||
.map_err(|_| Error::Type(format!("Could not parse `{}` to u64 type", s))),
|
||||
(ConcreteType::Boolean, serde_json::Value::Bool(b)) => Ok(Value::Boolean(b)),
|
||||
(ConcreteType::Array(array_type), serde_json::Value::Array(a)) => {
|
||||
let size = array_type.size;
|
||||
let size = *array_type.size;
|
||||
if a.len() != size as usize {
|
||||
Err(Error::Type(format!(
|
||||
"Expected array of size {}, found array of size {}",
|
||||
|
|
|
@ -108,103 +108,6 @@ impl<T: Field + ArkFieldExtensions> Backend<T, GM17> for Ark {
|
|||
}
|
||||
}
|
||||
|
||||
// impl NonUniversalBackend<Bw6_761Field, GM17> for Ark {
|
||||
// fn setup<I: IntoIterator<Item = Statement<Bw6_761Field>>>(
|
||||
// program: ProgIterator<Bw6_761Field, I>,
|
||||
// ) -> SetupKeypair<<GM17 as Scheme<Bw6_761Field>>::VerificationKey> {
|
||||
// let computation = Computation::without_witness(program);
|
||||
|
||||
// let rng = &mut StdRng::from_entropy();
|
||||
// let (pk, vk) = ArkGM17::<BW6_761>::circuit_specific_setup(computation, rng).unwrap();
|
||||
|
||||
// let mut pk_vec: Vec<u8> = Vec::new();
|
||||
// pk.serialize_uncompressed(&mut pk_vec).unwrap();
|
||||
|
||||
// let vk = VerificationKey {
|
||||
// h: parse_g2_fq::<Bw6_761Field>(&vk.h_g2),
|
||||
// g_alpha: parse_g1::<Bw6_761Field>(&vk.g_alpha_g1),
|
||||
// h_beta: parse_g2_fq::<Bw6_761Field>(&vk.h_beta_g2),
|
||||
// g_gamma: parse_g1::<Bw6_761Field>(&vk.g_gamma_g1),
|
||||
// h_gamma: parse_g2_fq::<Bw6_761Field>(&vk.h_gamma_g2),
|
||||
// query: vk.query.iter().map(parse_g1::<Bw6_761Field>).collect(),
|
||||
// };
|
||||
|
||||
// SetupKeypair::new(vk, pk_vec)
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl Backend<Bw6_761Field, GM17> for Ark {
|
||||
// fn generate_proof<I: IntoIterator<Item = Statement<Bw6_761Field>>>(
|
||||
// program: ProgIterator<Bw6_761Field, I>,
|
||||
// witness: Witness<Bw6_761Field>,
|
||||
// proving_key: Vec<u8>,
|
||||
// ) -> Proof<Bw6_761Field, GM17> {
|
||||
// let computation = Computation::with_witness(program, witness);
|
||||
|
||||
// let inputs = computation
|
||||
// .public_inputs_values()
|
||||
// .iter()
|
||||
// .map(parse_fr::<Bw6_761Field>)
|
||||
// .collect::<Vec<_>>();
|
||||
|
||||
// let pk =
|
||||
// ProvingKey::<<Bw6_761Field as ArkFieldExtensions>::ArkEngine>::deserialize_uncompressed(
|
||||
// &mut proving_key.as_slice(),
|
||||
// )
|
||||
// .unwrap();
|
||||
|
||||
// let rng = &mut StdRng::from_entropy();
|
||||
// let proof = ArkGM17::<BW6_761>::prove(&pk, computation, rng).unwrap();
|
||||
|
||||
// let proof_points = ProofPoints {
|
||||
// a: parse_g1::<Bw6_761Field>(&proof.a),
|
||||
// b: parse_g2_fq::<Bw6_761Field>(&proof.b),
|
||||
// c: parse_g1::<Bw6_761Field>(&proof.c),
|
||||
// };
|
||||
|
||||
// Proof::new(proof_points, inputs)
|
||||
// }
|
||||
|
||||
// fn verify(
|
||||
// vk: <GM17 as Scheme<Bw6_761Field>>::VerificationKey,
|
||||
// proof: Proof<Bw6_761Field, GM17>,
|
||||
// ) -> bool {
|
||||
// let vk = VerifyingKey {
|
||||
// h_g2: serialization::to_g2_fq::<Bw6_761Field>(vk.h),
|
||||
// g_alpha_g1: serialization::to_g1::<Bw6_761Field>(vk.g_alpha),
|
||||
// h_beta_g2: serialization::to_g2_fq::<Bw6_761Field>(vk.h_beta),
|
||||
// g_gamma_g1: serialization::to_g1::<Bw6_761Field>(vk.g_gamma),
|
||||
// h_gamma_g2: serialization::to_g2_fq::<Bw6_761Field>(vk.h_gamma),
|
||||
// query: vk
|
||||
// .query
|
||||
// .into_iter()
|
||||
// .map(serialization::to_g1::<Bw6_761Field>)
|
||||
// .collect(),
|
||||
// };
|
||||
|
||||
// let ark_proof = ArkProof {
|
||||
// a: serialization::to_g1::<Bw6_761Field>(proof.proof.a),
|
||||
// b: serialization::to_g2_fq::<Bw6_761Field>(proof.proof.b),
|
||||
// c: serialization::to_g1::<Bw6_761Field>(proof.proof.c),
|
||||
// };
|
||||
|
||||
// let pvk: PreparedVerifyingKey<<Bw6_761Field as ArkFieldExtensions>::ArkEngine> =
|
||||
// prepare_verifying_key(&vk);
|
||||
|
||||
// let public_inputs: Vec<_> = proof
|
||||
// .inputs
|
||||
// .iter()
|
||||
// .map(|s| {
|
||||
// Bw6_761Field::try_from_str(s.trim_start_matches("0x"), 16)
|
||||
// .unwrap()
|
||||
// .into_ark()
|
||||
// })
|
||||
// .collect::<Vec<_>>();
|
||||
|
||||
// verify_proof(&pvk, &ark_proof, &public_inputs).unwrap()
|
||||
// }
|
||||
// }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use zokrates_ast::flat::{Parameter, Variable};
|
||||
|
|
|
@ -12,12 +12,6 @@ use zokrates_ast::common::Variable;
|
|||
use zokrates_ast::ir::{CanonicalLinComb, ProgIterator, Statement, Witness};
|
||||
use zokrates_field::{ArkFieldExtensions, Field};
|
||||
|
||||
use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field};
|
||||
pub trait NotBw6_761Field {}
|
||||
impl NotBw6_761Field for Bls12_377Field {}
|
||||
impl NotBw6_761Field for Bls12_381Field {}
|
||||
impl NotBw6_761Field for Bn128Field {}
|
||||
|
||||
pub use self::parse::*;
|
||||
|
||||
pub struct Ark;
|
||||
|
@ -162,6 +156,7 @@ impl<T: Field + ArkFieldExtensions, I: IntoIterator<Item = Statement<T>>>
|
|||
mod parse {
|
||||
use super::*;
|
||||
use ark_ff::ToBytes;
|
||||
use zokrates_field::G2Type;
|
||||
use zokrates_proof_systems::{Fr, G1Affine, G2Affine, G2AffineFq, G2AffineFq2};
|
||||
|
||||
pub fn parse_g1<T: Field + ArkFieldExtensions>(
|
||||
|
@ -192,48 +187,46 @@ mod parse {
|
|||
e.write(&mut bytes).unwrap();
|
||||
|
||||
let length = bytes.len() - 1; // [x, y, infinity] - infinity
|
||||
let element_length = length / 4;
|
||||
|
||||
let mut elements = vec![];
|
||||
for i in 0..4 {
|
||||
let start = i * element_length;
|
||||
let end = start + element_length;
|
||||
let mut e = bytes[start..end].to_vec();
|
||||
e.reverse();
|
||||
elements.push(e);
|
||||
match T::G2_TYPE {
|
||||
G2Type::Fq2 => {
|
||||
let element_length = length / 4;
|
||||
|
||||
let mut elements = vec![];
|
||||
for i in 0..4 {
|
||||
let start = i * element_length;
|
||||
let end = start + element_length;
|
||||
let mut e = bytes[start..end].to_vec();
|
||||
e.reverse();
|
||||
elements.push(e);
|
||||
}
|
||||
|
||||
G2Affine::Fq2(G2AffineFq2(
|
||||
(
|
||||
format!("0x{}", hex::encode(&elements[0])),
|
||||
format!("0x{}", hex::encode(&elements[1])),
|
||||
),
|
||||
(
|
||||
format!("0x{}", hex::encode(&elements[2])),
|
||||
format!("0x{}", hex::encode(&elements[3])),
|
||||
),
|
||||
))
|
||||
}
|
||||
G2Type::Fq => {
|
||||
let element_length = length / 2;
|
||||
|
||||
let mut x = bytes[0..element_length].to_vec();
|
||||
let mut y = bytes[element_length..length].to_vec();
|
||||
|
||||
x.reverse();
|
||||
y.reverse();
|
||||
|
||||
G2Affine::Fq(G2AffineFq(
|
||||
format!("0x{}", hex::encode(&x)),
|
||||
format!("0x{}", hex::encode(&y)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
G2Affine::Fq2(G2AffineFq2(
|
||||
(
|
||||
format!("0x{}", hex::encode(&elements[0])),
|
||||
format!("0x{}", hex::encode(&elements[1])),
|
||||
),
|
||||
(
|
||||
format!("0x{}", hex::encode(&elements[2])),
|
||||
format!("0x{}", hex::encode(&elements[3])),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn parse_g2_fq<T: ArkFieldExtensions>(
|
||||
e: &<T::ArkEngine as PairingEngine>::G2Affine,
|
||||
) -> G2Affine {
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
e.write(&mut bytes).unwrap();
|
||||
|
||||
let length = bytes.len() - 1; // [x, y, infinity] - infinity
|
||||
let element_length = length / 2;
|
||||
|
||||
let mut x = bytes[0..element_length].to_vec();
|
||||
let mut y = bytes[element_length..length].to_vec();
|
||||
|
||||
x.reverse();
|
||||
y.reverse();
|
||||
|
||||
G2Affine::Fq(G2AffineFq(
|
||||
format!("0x{}", hex::encode(&x)),
|
||||
format!("0x{}", hex::encode(&y)),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn parse_fr<T: ArkFieldExtensions>(e: &<T::ArkEngine as PairingEngine>::Fr) -> Fr {
|
||||
|
|
|
@ -62,66 +62,76 @@ impl FlatEmbed {
|
|||
)
|
||||
.into(),
|
||||
])
|
||||
.outputs(vec![UnresolvedType::Boolean.into()]),
|
||||
.output(UnresolvedType::Boolean.into()),
|
||||
FlatEmbed::Unpack => UnresolvedSignature::new()
|
||||
.generics(vec!["N".into()])
|
||||
.inputs(vec![UnresolvedType::FieldElement.into()])
|
||||
.outputs(vec![UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::Identifier("N").into(),
|
||||
)
|
||||
.into()]),
|
||||
.output(
|
||||
UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::Identifier("N").into(),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
FlatEmbed::U8ToBits => UnresolvedSignature::new()
|
||||
.inputs(vec![UnresolvedType::Uint(8).into()])
|
||||
.outputs(vec![UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(8).into(),
|
||||
)
|
||||
.into()]),
|
||||
.output(
|
||||
UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(8).into(),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
FlatEmbed::U16ToBits => UnresolvedSignature::new()
|
||||
.inputs(vec![UnresolvedType::Uint(16).into()])
|
||||
.outputs(vec![UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(16).into(),
|
||||
)
|
||||
.into()]),
|
||||
.output(
|
||||
UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(16).into(),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
FlatEmbed::U32ToBits => UnresolvedSignature::new()
|
||||
.inputs(vec![UnresolvedType::Uint(32).into()])
|
||||
.outputs(vec![UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(32).into(),
|
||||
)
|
||||
.into()]),
|
||||
.output(
|
||||
UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(32).into(),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
FlatEmbed::U64ToBits => UnresolvedSignature::new()
|
||||
.inputs(vec![UnresolvedType::Uint(64).into()])
|
||||
.outputs(vec![UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(64).into(),
|
||||
)
|
||||
.into()]),
|
||||
.output(
|
||||
UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(64).into(),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
FlatEmbed::U8FromBits => UnresolvedSignature::new()
|
||||
.outputs(vec![UnresolvedType::Uint(8).into()])
|
||||
.output(UnresolvedType::Uint(8).into())
|
||||
.inputs(vec![UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(8).into(),
|
||||
)
|
||||
.into()]),
|
||||
FlatEmbed::U16FromBits => UnresolvedSignature::new()
|
||||
.outputs(vec![UnresolvedType::Uint(16).into()])
|
||||
.output(UnresolvedType::Uint(16).into())
|
||||
.inputs(vec![UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(16).into(),
|
||||
)
|
||||
.into()]),
|
||||
FlatEmbed::U32FromBits => UnresolvedSignature::new()
|
||||
.outputs(vec![UnresolvedType::Uint(32).into()])
|
||||
.output(UnresolvedType::Uint(32).into())
|
||||
.inputs(vec![UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(32).into(),
|
||||
)
|
||||
.into()]),
|
||||
FlatEmbed::U64FromBits => UnresolvedSignature::new()
|
||||
.outputs(vec![UnresolvedType::Uint(64).into()])
|
||||
.output(UnresolvedType::Uint(64).into())
|
||||
.inputs(vec![UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(64).into(),
|
||||
|
@ -141,11 +151,13 @@ impl FlatEmbed {
|
|||
)
|
||||
.into(),
|
||||
])
|
||||
.outputs(vec![UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(256).into(),
|
||||
)
|
||||
.into()]),
|
||||
.output(
|
||||
UnresolvedType::array(
|
||||
UnresolvedType::Boolean.into(),
|
||||
Expression::U32Constant(256).into(),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
#[cfg(feature = "ark")]
|
||||
FlatEmbed::SnarkVerifyBls12377 => UnresolvedSignature::new()
|
||||
.generics(vec!["N".into(), "V".into()])
|
||||
|
@ -166,7 +178,7 @@ impl FlatEmbed {
|
|||
)
|
||||
.into(), // 18 + (2 * n) // vk
|
||||
])
|
||||
.outputs(vec![UnresolvedType::Boolean.into()]),
|
||||
.output(UnresolvedType::Boolean.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,60 +198,48 @@ impl FlatEmbed {
|
|||
GenericIdentifier::with_name("N").with_index(0),
|
||||
)),
|
||||
])
|
||||
.outputs(vec![DeclarationType::Boolean]),
|
||||
.output(DeclarationType::Boolean),
|
||||
FlatEmbed::Unpack => DeclarationSignature::new()
|
||||
.generics(vec![Some(DeclarationConstant::Generic(
|
||||
GenericIdentifier::with_name("N").with_index(0),
|
||||
))])
|
||||
.inputs(vec![DeclarationType::FieldElement])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
.output(DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
GenericIdentifier::with_name("N").with_index(0),
|
||||
))]),
|
||||
))),
|
||||
FlatEmbed::U8ToBits => DeclarationSignature::new()
|
||||
.inputs(vec![DeclarationType::uint(8)])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
8u32,
|
||||
))]),
|
||||
.output(DeclarationType::array((DeclarationType::Boolean, 8u32))),
|
||||
FlatEmbed::U16ToBits => DeclarationSignature::new()
|
||||
.inputs(vec![DeclarationType::uint(16)])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
16u32,
|
||||
))]),
|
||||
.output(DeclarationType::array((DeclarationType::Boolean, 16u32))),
|
||||
FlatEmbed::U32ToBits => DeclarationSignature::new()
|
||||
.inputs(vec![DeclarationType::uint(32)])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
32u32,
|
||||
))]),
|
||||
.output(DeclarationType::array((DeclarationType::Boolean, 32u32))),
|
||||
FlatEmbed::U64ToBits => DeclarationSignature::new()
|
||||
.inputs(vec![DeclarationType::uint(64)])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
64u32,
|
||||
))]),
|
||||
.output(DeclarationType::array((DeclarationType::Boolean, 64u32))),
|
||||
FlatEmbed::U8FromBits => DeclarationSignature::new()
|
||||
.outputs(vec![DeclarationType::uint(8)])
|
||||
.output(DeclarationType::uint(8))
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
8u32,
|
||||
))]),
|
||||
FlatEmbed::U16FromBits => DeclarationSignature::new()
|
||||
.outputs(vec![DeclarationType::uint(16)])
|
||||
.output(DeclarationType::uint(16))
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
16u32,
|
||||
))]),
|
||||
FlatEmbed::U32FromBits => DeclarationSignature::new()
|
||||
.outputs(vec![DeclarationType::uint(32)])
|
||||
.output(DeclarationType::uint(32))
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
32u32,
|
||||
))]),
|
||||
FlatEmbed::U64FromBits => DeclarationSignature::new()
|
||||
.outputs(vec![DeclarationType::uint(64)])
|
||||
.output(DeclarationType::uint(64))
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
64u32,
|
||||
|
@ -250,10 +250,7 @@ impl FlatEmbed {
|
|||
DeclarationType::array((DeclarationType::Boolean, 512u32)),
|
||||
DeclarationType::array((DeclarationType::Boolean, 256u32)),
|
||||
])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
256u32,
|
||||
))]),
|
||||
.output(DeclarationType::array((DeclarationType::Boolean, 256u32))),
|
||||
#[cfg(feature = "ark")]
|
||||
FlatEmbed::SnarkVerifyBls12377 => DeclarationSignature::new()
|
||||
.generics(vec![
|
||||
|
@ -275,7 +272,7 @@ impl FlatEmbed {
|
|||
GenericIdentifier::with_name("V").with_index(1),
|
||||
)), // 18 + (2 * n) // vk
|
||||
])
|
||||
.outputs(vec![DeclarationType::Boolean]),
|
||||
.output(DeclarationType::Boolean),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -693,73 +690,60 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
// MOVE TO CORE
|
||||
// #[cfg(feature = "bellman")]
|
||||
// #[cfg(test)]
|
||||
// mod sha256 {
|
||||
// use super::*;
|
||||
// use crate::ir::Interpreter;
|
||||
#[cfg(feature = "bellman")]
|
||||
#[cfg(test)]
|
||||
mod sha256 {
|
||||
use super::*;
|
||||
|
||||
// #[test]
|
||||
// fn generate_sha256_constraints() {
|
||||
// let compiled = sha256_round::<Bn128Field>();
|
||||
#[test]
|
||||
fn generate_sha256_constraints() {
|
||||
let compiled = sha256_round::<Bn128Field>();
|
||||
|
||||
// let compiled = compiled.collect();
|
||||
let compiled = compiled.collect();
|
||||
|
||||
// // function should have 768 inputs
|
||||
// assert_eq!(compiled.arguments.len(), 768);
|
||||
// function should have 768 inputs
|
||||
assert_eq!(compiled.arguments.len(), 768);
|
||||
|
||||
// // function should return 256 values
|
||||
// assert_eq!(compiled.return_count, 256,);
|
||||
// function should return 256 values
|
||||
assert_eq!(compiled.return_count, 256,);
|
||||
|
||||
// // directive should take 768 inputs and return n_var outputs
|
||||
// let directive = compiled
|
||||
// .statements
|
||||
// .iter()
|
||||
// .filter_map(|s| match s {
|
||||
// FlatStatement::Directive(d) => Some(d.clone()),
|
||||
// _ => None,
|
||||
// })
|
||||
// .next()
|
||||
// .unwrap();
|
||||
// assert_eq!(directive.inputs.len(), 768);
|
||||
// assert_eq!(directive.outputs.len(), 26935);
|
||||
// // function input should be offset by variable_count
|
||||
// assert_eq!(
|
||||
// compiled.arguments[0].id,
|
||||
// Variable::new(directive.outputs.len() + 1)
|
||||
// );
|
||||
// directive should take 768 inputs and return n_var outputs
|
||||
let directive = compiled
|
||||
.statements
|
||||
.iter()
|
||||
.filter_map(|s| match s {
|
||||
FlatStatement::Directive(d) => Some(d.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.next()
|
||||
.unwrap();
|
||||
assert_eq!(directive.inputs.len(), 768);
|
||||
assert_eq!(directive.outputs.len(), 26935);
|
||||
// function input should be offset by variable_count
|
||||
assert_eq!(
|
||||
compiled.arguments[0].id,
|
||||
Variable::new(directive.outputs.len() + 1)
|
||||
);
|
||||
|
||||
// // bellman variable #0: index 0 should equal 1
|
||||
// assert_eq!(
|
||||
// compiled.statements[1],
|
||||
// FlatStatement::Condition(
|
||||
// Variable::new(0).into(),
|
||||
// FlatExpression::Number(Bn128Field::from(1)),
|
||||
// RuntimeError::BellmanOneBinding
|
||||
// )
|
||||
// );
|
||||
// bellman variable #0: index 0 should equal 1
|
||||
assert_eq!(
|
||||
compiled.statements[1],
|
||||
FlatStatement::Condition(
|
||||
Variable::new(0).into(),
|
||||
FlatExpression::Number(Bn128Field::from(1)),
|
||||
RuntimeError::BellmanOneBinding
|
||||
)
|
||||
);
|
||||
|
||||
// // bellman input #0: index 1 should equal zokrates input #0: index v_count
|
||||
// assert_eq!(
|
||||
// compiled.statements[2],
|
||||
// FlatStatement::Condition(
|
||||
// Variable::new(1).into(),
|
||||
// Variable::new(26936).into(),
|
||||
// RuntimeError::BellmanInputBinding
|
||||
// )
|
||||
// );
|
||||
|
||||
// let input: Vec<_> = (0..512)
|
||||
// .map(|_| 0)
|
||||
// .chain((0..256).map(|_| 1))
|
||||
// .map(Bn128Field::from)
|
||||
// .collect();
|
||||
|
||||
// let ir = zokrates_ast::ir::from_flat::from_flat(compiled);
|
||||
|
||||
// let interpreter = Interpreter::default();
|
||||
// interpreter.execute(ir, &input).unwrap();
|
||||
// }
|
||||
// }
|
||||
// bellman input #0: index 1 should equal zokrates input #0: index v_count
|
||||
assert_eq!(
|
||||
compiled.statements[2],
|
||||
FlatStatement::Condition(
|
||||
Variable::new(1).into(),
|
||||
Variable::new(26936).into(),
|
||||
RuntimeError::BellmanInputBinding
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ pub type AbiOutput = ConcreteType;
|
|||
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Abi {
|
||||
pub inputs: Vec<AbiInput>,
|
||||
pub outputs: Vec<AbiOutput>,
|
||||
pub output: AbiOutput,
|
||||
}
|
||||
|
||||
impl Abi {
|
||||
|
@ -22,7 +22,7 @@ impl Abi {
|
|||
ConcreteSignature {
|
||||
generics: vec![],
|
||||
inputs: self.inputs.iter().map(|i| i.ty.clone()).collect(),
|
||||
outputs: self.outputs.clone(),
|
||||
output: box self.output.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,10 @@ impl Abi {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::typed::types::{
|
||||
ConcreteArrayType, ConcreteFunctionKey, ConcreteStructMember, ConcreteStructType, UBitwidth,
|
||||
ConcreteArrayType, ConcreteFunctionKey, ConcreteStructMember, ConcreteStructType,
|
||||
GTupleType, UBitwidth,
|
||||
};
|
||||
use crate::typed::DeclarationType;
|
||||
use crate::typed::{
|
||||
parameter::DeclarationParameter, variable::DeclarationVariable, ConcreteTupleType,
|
||||
ConcreteType, TypedFunction, TypedFunctionSymbol, TypedFunctionSymbolDeclaration,
|
||||
|
@ -48,18 +50,18 @@ mod tests {
|
|||
TypedFunctionSymbol::Here(TypedFunction {
|
||||
arguments: vec![
|
||||
DeclarationParameter {
|
||||
id: DeclarationVariable::field_element("a"),
|
||||
id: DeclarationVariable::new("a", DeclarationType::FieldElement, true),
|
||||
private: true,
|
||||
},
|
||||
DeclarationParameter {
|
||||
id: DeclarationVariable::boolean("b"),
|
||||
id: DeclarationVariable::new("b", DeclarationType::Boolean, false),
|
||||
private: false,
|
||||
},
|
||||
],
|
||||
statements: vec![],
|
||||
signature: ConcreteSignature::new()
|
||||
.inputs(vec![ConcreteType::FieldElement, ConcreteType::Boolean])
|
||||
.outputs(vec![ConcreteType::FieldElement])
|
||||
.output(ConcreteType::FieldElement)
|
||||
.into(),
|
||||
}),
|
||||
)
|
||||
|
@ -87,7 +89,7 @@ mod tests {
|
|||
ty: ConcreteType::Boolean,
|
||||
},
|
||||
],
|
||||
outputs: vec![ConcreteType::FieldElement],
|
||||
output: ConcreteType::FieldElement,
|
||||
};
|
||||
|
||||
assert_eq!(expected_abi, abi);
|
||||
|
@ -97,11 +99,14 @@ mod tests {
|
|||
fn serialize_empty() {
|
||||
let abi: Abi = Abi {
|
||||
inputs: vec![],
|
||||
outputs: vec![],
|
||||
output: ConcreteType::Tuple(GTupleType::new(vec![])),
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&abi).unwrap();
|
||||
assert_eq!(&json, r#"{"inputs":[],"outputs":[]}"#);
|
||||
assert_eq!(
|
||||
&json,
|
||||
r#"{"inputs":[],"output":{"type":"tuple","components":{"elements":[]}}}"#
|
||||
);
|
||||
let de_abi: Abi = serde_json::from_str(json.as_ref()).unwrap();
|
||||
assert_eq!(de_abi, abi);
|
||||
}
|
||||
|
@ -113,7 +118,7 @@ mod tests {
|
|||
|
||||
let abi: Abi = Abi {
|
||||
inputs: vec![],
|
||||
outputs: vec![ConcreteType::Int],
|
||||
output: ConcreteType::Int,
|
||||
};
|
||||
|
||||
let _ = serde_json::to_string_pretty(&abi).unwrap();
|
||||
|
@ -134,7 +139,7 @@ mod tests {
|
|||
ty: ConcreteType::FieldElement,
|
||||
},
|
||||
],
|
||||
outputs: vec![ConcreteType::FieldElement],
|
||||
output: ConcreteType::FieldElement,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string_pretty(&abi).unwrap();
|
||||
|
@ -153,11 +158,9 @@ mod tests {
|
|||
"type": "field"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"type": "field"
|
||||
}
|
||||
]
|
||||
"output": {
|
||||
"type": "field"
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
|
@ -185,7 +188,7 @@ mod tests {
|
|||
ty: ConcreteType::Uint(UBitwidth::B32),
|
||||
},
|
||||
],
|
||||
outputs: vec![],
|
||||
output: ConcreteType::Tuple(GTupleType::new(vec![])),
|
||||
};
|
||||
|
||||
let json = serde_json::to_string_pretty(&abi).unwrap();
|
||||
|
@ -209,7 +212,12 @@ mod tests {
|
|||
"type": "u32"
|
||||
}
|
||||
],
|
||||
"outputs": []
|
||||
"output": {
|
||||
"type": "tuple",
|
||||
"components": {
|
||||
"elements": []
|
||||
}
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
|
@ -236,7 +244,7 @@ mod tests {
|
|||
)],
|
||||
)),
|
||||
}],
|
||||
outputs: vec![ConcreteType::Struct(ConcreteStructType::new(
|
||||
output: ConcreteType::Struct(ConcreteStructType::new(
|
||||
"".into(),
|
||||
"Foo".into(),
|
||||
vec![],
|
||||
|
@ -244,7 +252,7 @@ mod tests {
|
|||
ConcreteStructMember::new(String::from("a"), ConcreteType::FieldElement),
|
||||
ConcreteStructMember::new(String::from("b"), ConcreteType::Boolean),
|
||||
],
|
||||
))],
|
||||
)),
|
||||
};
|
||||
|
||||
let json = serde_json::to_string_pretty(&abi).unwrap();
|
||||
|
@ -274,25 +282,23 @@ mod tests {
|
|||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"type": "struct",
|
||||
"components": {
|
||||
"name": "Foo",
|
||||
"generics": [],
|
||||
"members": [
|
||||
{
|
||||
"name": "a",
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"name": "b",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
"output": {
|
||||
"type": "struct",
|
||||
"components": {
|
||||
"name": "Foo",
|
||||
"generics": [],
|
||||
"members": [
|
||||
{
|
||||
"name": "a",
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"name": "b",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
|
@ -330,7 +336,7 @@ mod tests {
|
|||
)],
|
||||
)),
|
||||
}],
|
||||
outputs: vec![],
|
||||
output: ConcreteType::Tuple(GTupleType::new(vec![])),
|
||||
};
|
||||
|
||||
let json = serde_json::to_string_pretty(&abi).unwrap();
|
||||
|
@ -368,7 +374,12 @@ mod tests {
|
|||
}
|
||||
}
|
||||
],
|
||||
"outputs": []
|
||||
"output": {
|
||||
"type": "tuple",
|
||||
"components": {
|
||||
"elements": []
|
||||
}
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
|
@ -398,7 +409,7 @@ mod tests {
|
|||
2u32,
|
||||
)),
|
||||
}],
|
||||
outputs: vec![ConcreteType::Boolean],
|
||||
output: ConcreteType::Boolean,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string_pretty(&abi).unwrap();
|
||||
|
@ -430,11 +441,9 @@ mod tests {
|
|||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
"output": {
|
||||
"type": "bool"
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
|
@ -453,7 +462,7 @@ mod tests {
|
|||
2u32,
|
||||
)),
|
||||
}],
|
||||
outputs: vec![ConcreteType::FieldElement],
|
||||
output: ConcreteType::FieldElement,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string_pretty(&abi).unwrap();
|
||||
|
@ -475,11 +484,9 @@ mod tests {
|
|||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"type": "field"
|
||||
}
|
||||
]
|
||||
"output": {
|
||||
"type": "field"
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
|
@ -498,9 +505,7 @@ mod tests {
|
|||
ConcreteType::Boolean,
|
||||
])),
|
||||
}],
|
||||
outputs: vec![ConcreteType::Tuple(ConcreteTupleType::new(vec![
|
||||
ConcreteType::FieldElement,
|
||||
]))],
|
||||
output: ConcreteType::Tuple(ConcreteTupleType::new(vec![ConcreteType::FieldElement])),
|
||||
};
|
||||
|
||||
let json = serde_json::to_string_pretty(&abi).unwrap();
|
||||
|
@ -524,18 +529,16 @@ mod tests {
|
|||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"type": "tuple",
|
||||
"components": {
|
||||
"elements": [
|
||||
{
|
||||
"type": "field"
|
||||
}
|
||||
]
|
||||
}
|
||||
"output": {
|
||||
"type": "tuple",
|
||||
"components": {
|
||||
"elements": [
|
||||
{
|
||||
"type": "field"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ pub trait Folder<'ast, T: Field>: Sized {
|
|||
Variable {
|
||||
id: self.fold_name(v.id),
|
||||
_type: self.fold_type(v._type),
|
||||
is_mutable: v.is_mutable,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,6 +153,7 @@ pub trait Folder<'ast, T: Field>: Sized {
|
|||
DeclarationVariable {
|
||||
id: self.fold_name(v.id),
|
||||
_type: self.fold_declaration_type(v._type),
|
||||
is_mutable: v.is_mutable,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,14 +168,10 @@ pub trait Folder<'ast, T: Field>: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
fn fold_types(&mut self, tys: Types<'ast, T>) -> Types<'ast, T> {
|
||||
fold_types(self, tys)
|
||||
}
|
||||
|
||||
fn fold_array_type(&mut self, t: ArrayType<'ast, T>) -> ArrayType<'ast, T> {
|
||||
ArrayType {
|
||||
ty: box self.fold_type(*t.ty),
|
||||
size: self.fold_uint_expression(t.size),
|
||||
size: box self.fold_uint_expression(*t.size),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,7 +217,7 @@ pub trait Folder<'ast, T: Field>: Sized {
|
|||
) -> DeclarationArrayType<'ast, T> {
|
||||
DeclarationArrayType {
|
||||
ty: box self.fold_declaration_type(*t.ty),
|
||||
size: self.fold_declaration_constant(t.size),
|
||||
size: box self.fold_declaration_constant(*t.size),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,6 +264,10 @@ pub trait Folder<'ast, T: Field>: Sized {
|
|||
fold_statement(self, s)
|
||||
}
|
||||
|
||||
fn fold_embed_call(&mut self, e: EmbedCall<'ast, T>) -> EmbedCall<'ast, T> {
|
||||
fold_embed_call(self, e)
|
||||
}
|
||||
|
||||
fn fold_expression_or_spread(
|
||||
&mut self,
|
||||
e: TypedExpressionOrSpread<'ast, T>,
|
||||
|
@ -301,15 +303,7 @@ pub trait Folder<'ast, T: Field>: Sized {
|
|||
}
|
||||
|
||||
fn fold_expression(&mut self, e: TypedExpression<'ast, T>) -> TypedExpression<'ast, T> {
|
||||
match e {
|
||||
TypedExpression::FieldElement(e) => self.fold_field_expression(e).into(),
|
||||
TypedExpression::Boolean(e) => self.fold_boolean_expression(e).into(),
|
||||
TypedExpression::Uint(e) => self.fold_uint_expression(e).into(),
|
||||
TypedExpression::Array(e) => self.fold_array_expression(e).into(),
|
||||
TypedExpression::Tuple(e) => self.fold_tuple_expression(e).into(),
|
||||
TypedExpression::Struct(e) => self.fold_struct_expression(e).into(),
|
||||
TypedExpression::Int(e) => self.fold_int_expression(e).into(),
|
||||
}
|
||||
fold_expression(self, e)
|
||||
}
|
||||
|
||||
fn fold_block_expression<E: Fold<'ast, T>>(
|
||||
|
@ -395,21 +389,6 @@ pub trait Folder<'ast, T: Field>: Sized {
|
|||
fold_tuple_expression(self, e)
|
||||
}
|
||||
|
||||
fn fold_expression_list(
|
||||
&mut self,
|
||||
es: TypedExpressionList<'ast, T>,
|
||||
) -> TypedExpressionList<'ast, T> {
|
||||
fold_expression_list(self, es)
|
||||
}
|
||||
|
||||
fn fold_expression_list_inner(
|
||||
&mut self,
|
||||
tys: Types<'ast, T>,
|
||||
es: TypedExpressionListInner<'ast, T>,
|
||||
) -> TypedExpressionListInner<'ast, T> {
|
||||
fold_expression_list_inner(self, tys, es)
|
||||
}
|
||||
|
||||
fn fold_int_expression(&mut self, e: IntExpression<'ast, T>) -> IntExpression<'ast, T> {
|
||||
fold_int_expression(self, e)
|
||||
}
|
||||
|
@ -420,12 +399,14 @@ pub trait Folder<'ast, T: Field>: Sized {
|
|||
) -> FieldElementExpression<'ast, T> {
|
||||
fold_field_expression(self, e)
|
||||
}
|
||||
|
||||
fn fold_boolean_expression(
|
||||
&mut self,
|
||||
e: BooleanExpression<'ast, T>,
|
||||
) -> BooleanExpression<'ast, T> {
|
||||
fold_boolean_expression(self, e)
|
||||
}
|
||||
|
||||
fn fold_uint_expression(&mut self, e: UExpression<'ast, T>) -> UExpression<'ast, T> {
|
||||
fold_uint_expression(self, e)
|
||||
}
|
||||
|
@ -515,16 +496,10 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
|
|||
s: TypedStatement<'ast, T>,
|
||||
) -> Vec<TypedStatement<'ast, T>> {
|
||||
let res = match s {
|
||||
TypedStatement::Return(expressions) => TypedStatement::Return(
|
||||
expressions
|
||||
.into_iter()
|
||||
.map(|e| f.fold_expression(e))
|
||||
.collect(),
|
||||
),
|
||||
TypedStatement::Return(e) => TypedStatement::Return(f.fold_expression(e)),
|
||||
TypedStatement::Definition(a, e) => {
|
||||
TypedStatement::Definition(f.fold_assignee(a), f.fold_expression(e))
|
||||
}
|
||||
TypedStatement::Declaration(v) => TypedStatement::Declaration(f.fold_variable(v)),
|
||||
TypedStatement::Assertion(e, error) => {
|
||||
TypedStatement::Assertion(f.fold_boolean_expression(e), error)
|
||||
}
|
||||
|
@ -537,18 +512,49 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
|
|||
.flat_map(|s| f.fold_statement(s))
|
||||
.collect(),
|
||||
),
|
||||
TypedStatement::MultipleDefinition(assignees, elist) => TypedStatement::MultipleDefinition(
|
||||
assignees.into_iter().map(|a| f.fold_assignee(a)).collect(),
|
||||
f.fold_expression_list(elist),
|
||||
),
|
||||
TypedStatement::Log(s, e) => {
|
||||
TypedStatement::Log(s, e.into_iter().map(|e| f.fold_expression(e)).collect())
|
||||
}
|
||||
TypedStatement::EmbedCallDefinition(assignee, embed_call) => {
|
||||
TypedStatement::EmbedCallDefinition(
|
||||
f.fold_assignee(assignee),
|
||||
f.fold_embed_call(embed_call),
|
||||
)
|
||||
}
|
||||
s => s,
|
||||
};
|
||||
vec![res]
|
||||
}
|
||||
|
||||
pub fn fold_embed_call<'ast, T: Field, F: Folder<'ast, T>>(
|
||||
f: &mut F,
|
||||
e: EmbedCall<'ast, T>,
|
||||
) -> EmbedCall<'ast, T> {
|
||||
EmbedCall {
|
||||
arguments: e
|
||||
.arguments
|
||||
.into_iter()
|
||||
.map(|s| f.fold_expression(s))
|
||||
.collect(),
|
||||
..e
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fold_expression<'ast, T: Field, F: Folder<'ast, T>>(
|
||||
f: &mut F,
|
||||
e: TypedExpression<'ast, T>,
|
||||
) -> TypedExpression<'ast, T> {
|
||||
match e {
|
||||
TypedExpression::FieldElement(e) => f.fold_field_expression(e).into(),
|
||||
TypedExpression::Boolean(e) => f.fold_boolean_expression(e).into(),
|
||||
TypedExpression::Uint(e) => f.fold_uint_expression(e).into(),
|
||||
TypedExpression::Array(e) => f.fold_array_expression(e).into(),
|
||||
TypedExpression::Tuple(e) => f.fold_tuple_expression(e).into(),
|
||||
TypedExpression::Struct(e) => f.fold_struct_expression(e).into(),
|
||||
TypedExpression::Int(e) => f.fold_int_expression(e).into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fold_array_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
|
||||
f: &mut F,
|
||||
ty: &ArrayType<'ast, T>,
|
||||
|
@ -1137,11 +1143,7 @@ fn fold_signature<'ast, T: Field, F: Folder<'ast, T>>(
|
|||
.into_iter()
|
||||
.map(|o| f.fold_declaration_type(o))
|
||||
.collect(),
|
||||
outputs: s
|
||||
.outputs
|
||||
.into_iter()
|
||||
.map(|o| f.fold_declaration_type(o))
|
||||
.collect(),
|
||||
output: box f.fold_declaration_type(*s.output),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1170,54 +1172,6 @@ pub fn fold_array_expression<'ast, T: Field, F: Folder<'ast, T>>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn fold_expression_list<'ast, T: Field, F: Folder<'ast, T>>(
|
||||
f: &mut F,
|
||||
es: TypedExpressionList<'ast, T>,
|
||||
) -> TypedExpressionList<'ast, T> {
|
||||
let types = f.fold_types(es.types);
|
||||
|
||||
TypedExpressionList {
|
||||
inner: f.fold_expression_list_inner(types.clone(), es.inner),
|
||||
types,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fold_types<'ast, T: Field, F: Folder<'ast, T>>(
|
||||
f: &mut F,
|
||||
tys: Types<'ast, T>,
|
||||
) -> Types<'ast, T> {
|
||||
Types {
|
||||
inner: tys.inner.into_iter().map(|t| f.fold_type(t)).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fold_expression_list_inner<'ast, T: Field, F: Folder<'ast, T>>(
|
||||
f: &mut F,
|
||||
tys: Types<'ast, T>,
|
||||
es: TypedExpressionListInner<'ast, T>,
|
||||
) -> TypedExpressionListInner<'ast, T> {
|
||||
match es {
|
||||
TypedExpressionListInner::FunctionCall(function_call) => {
|
||||
match f.fold_function_call_expression(&tys, function_call) {
|
||||
FunctionCallOrExpression::FunctionCall(function_call) => {
|
||||
TypedExpressionListInner::FunctionCall(function_call)
|
||||
}
|
||||
FunctionCallOrExpression::Expression(u) => u,
|
||||
}
|
||||
}
|
||||
TypedExpressionListInner::EmbedCall(embed, generics, arguments) => {
|
||||
TypedExpressionListInner::EmbedCall(
|
||||
embed,
|
||||
generics,
|
||||
arguments
|
||||
.into_iter()
|
||||
.map(|a| f.fold_expression(a))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fold_struct_expression<'ast, T: Field, F: Folder<'ast, T>>(
|
||||
f: &mut F,
|
||||
e: StructExpression<'ast, T>,
|
||||
|
|
|
@ -86,7 +86,7 @@ impl<'ast, T: Clone> IntegerInference for ArrayType<'ast, T> {
|
|||
Ok(DeclarationArrayType::new(
|
||||
self.ty
|
||||
.get_common_pattern(*other.ty)
|
||||
.map_err(|(t, u)| (ArrayType::new(t, s0), ArrayType::new(u, s1)))?,
|
||||
.map_err(|(t, u)| (ArrayType::new(t, *s0), ArrayType::new(u, *s1)))?,
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("DUMMY")), // sizes are not checked at this stage, therefore we insert a dummy generic variable which will be equal to all possible sizes
|
||||
))
|
||||
}
|
||||
|
@ -659,28 +659,28 @@ impl<'ast, T: Field> ArrayExpression<'ast, T> {
|
|||
|
||||
let inner_ty = res.0[0].get_type().0;
|
||||
|
||||
Ok(ArrayExpressionInner::Value(res).annotate(inner_ty, array_ty.size))
|
||||
Ok(ArrayExpressionInner::Value(res).annotate(inner_ty, *array_ty.size))
|
||||
}
|
||||
ArrayExpressionInner::Repeat(box e, box count) => {
|
||||
match &*target_array_ty.ty {
|
||||
GType::Int => Ok(ArrayExpressionInner::Repeat(box e, box count)
|
||||
.annotate(Type::Int, array_ty.size)),
|
||||
.annotate(Type::Int, *array_ty.size)),
|
||||
// try to align the repeated element to the target type
|
||||
t => TypedExpression::align_to_type(e, t)
|
||||
.map(|e| {
|
||||
let ty = e.get_type().clone();
|
||||
|
||||
ArrayExpressionInner::Repeat(box e, box count)
|
||||
.annotate(ty, array_ty.size)
|
||||
.annotate(ty, *array_ty.size)
|
||||
})
|
||||
.map_err(|(e, _)| e),
|
||||
}
|
||||
}
|
||||
a => {
|
||||
if *target_array_ty.ty == *array_ty.ty {
|
||||
Ok(a.annotate(*array_ty.ty, array_ty.size))
|
||||
Ok(a.annotate(*array_ty.ty, *array_ty.size))
|
||||
} else {
|
||||
Err(a.annotate(*array_ty.ty, array_ty.size).into())
|
||||
Err(a.annotate(*array_ty.ty, *array_ty.size).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,10 +22,11 @@ pub use self::types::{
|
|||
CanonicalConstantIdentifier, ConcreteFunctionKey, ConcreteSignature, ConcreteTupleType,
|
||||
ConcreteType, ConstantIdentifier, DeclarationArrayType, DeclarationConstant,
|
||||
DeclarationFunctionKey, DeclarationSignature, DeclarationStructType, DeclarationType,
|
||||
GArrayType, GStructType, GType, GenericIdentifier, IntoTypes, Signature, StructType, TupleType,
|
||||
Type, Types, UBitwidth,
|
||||
GArrayType, GStructType, GType, GenericIdentifier, Signature, StructType, TupleType, Type,
|
||||
UBitwidth,
|
||||
};
|
||||
use crate::typed::types::ConcreteGenericsAssignment;
|
||||
|
||||
use crate::typed::types::{ConcreteGenericsAssignment, IntoType};
|
||||
use crate::untyped::Position;
|
||||
|
||||
pub use self::variable::{ConcreteVariable, DeclarationVariable, GVariable, Variable};
|
||||
|
@ -117,21 +118,13 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
|
|||
.unwrap()
|
||||
})
|
||||
.collect(),
|
||||
outputs: main
|
||||
.signature
|
||||
.outputs
|
||||
.iter()
|
||||
.map(|ty| {
|
||||
types::ConcreteType::try_from(
|
||||
crate::typed::types::try_from_g_type::<
|
||||
DeclarationConstant<'ast, T>,
|
||||
UExpression<'ast, T>,
|
||||
>(ty.clone())
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
.collect(),
|
||||
output: types::ConcreteType::try_from(
|
||||
types::try_from_g_type::<DeclarationConstant<'ast, T>, UExpression<'ast, T>>(
|
||||
*main.signature.output.clone(),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -356,23 +349,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedFunction<'ast, T> {
|
|||
.join(", "),
|
||||
)?;
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{} {{",
|
||||
match self.signature.outputs.len() {
|
||||
0 => "".into(),
|
||||
1 => format!(" -> {}", self.signature.outputs[0]),
|
||||
_ => format!(
|
||||
" -> ({})",
|
||||
self.signature
|
||||
.outputs
|
||||
.iter()
|
||||
.map(|x| format!("{}", x))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
}
|
||||
)?;
|
||||
write!(f, " -> {} {{", self.signature.output)?;
|
||||
|
||||
writeln!(f)?;
|
||||
|
||||
|
@ -622,13 +599,59 @@ impl fmt::Display for RuntimeError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
|
||||
pub struct EmbedCall<'ast, T> {
|
||||
pub embed: FlatEmbed,
|
||||
pub generics: Vec<u32>,
|
||||
pub arguments: Vec<TypedExpression<'ast, T>>,
|
||||
}
|
||||
|
||||
impl<'ast, T> EmbedCall<'ast, T> {
|
||||
pub fn new(
|
||||
embed: FlatEmbed,
|
||||
generics: Vec<u32>,
|
||||
arguments: Vec<TypedExpression<'ast, T>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
embed,
|
||||
generics,
|
||||
arguments,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T: fmt::Display> fmt::Display for EmbedCall<'ast, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.embed.id())?;
|
||||
if !self.generics.is_empty() {
|
||||
write!(
|
||||
f,
|
||||
"::<{}>",
|
||||
self.generics
|
||||
.iter()
|
||||
.map(|g| g.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)?;
|
||||
}
|
||||
write!(f, "(")?;
|
||||
let len = self.arguments.len();
|
||||
for (i, arg) in self.arguments.iter().enumerate() {
|
||||
write!(f, "{}", arg)?;
|
||||
if i < len - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
|
||||
/// A statement in a `TypedFunction`
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
|
||||
pub enum TypedStatement<'ast, T> {
|
||||
Return(Vec<TypedExpression<'ast, T>>),
|
||||
Return(TypedExpression<'ast, T>),
|
||||
Definition(TypedAssignee<'ast, T>, TypedExpression<'ast, T>),
|
||||
Declaration(Variable<'ast, T>),
|
||||
Assertion(BooleanExpression<'ast, T>, RuntimeError),
|
||||
For(
|
||||
Variable<'ast, T>,
|
||||
|
@ -636,8 +659,8 @@ pub enum TypedStatement<'ast, T> {
|
|||
UExpression<'ast, T>,
|
||||
Vec<TypedStatement<'ast, T>>,
|
||||
),
|
||||
MultipleDefinition(Vec<TypedAssignee<'ast, T>>, TypedExpressionList<'ast, T>),
|
||||
Log(FormatString, Vec<TypedExpression<'ast, T>>),
|
||||
EmbedCallDefinition(TypedAssignee<'ast, T>, EmbedCall<'ast, T>),
|
||||
// Aux
|
||||
PushCallLog(
|
||||
DeclarationFunctionKey<'ast, T>,
|
||||
|
@ -666,17 +689,9 @@ impl<'ast, T: fmt::Display> TypedStatement<'ast, T> {
|
|||
impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
TypedStatement::Return(ref exprs) => {
|
||||
write!(f, "return ")?;
|
||||
for (i, expr) in exprs.iter().enumerate() {
|
||||
write!(f, "{}", expr)?;
|
||||
if i < exprs.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, ";")
|
||||
TypedStatement::Return(ref e) => {
|
||||
write!(f, "return {};", e)
|
||||
}
|
||||
TypedStatement::Declaration(ref var) => write!(f, "{};", var),
|
||||
TypedStatement::Definition(ref lhs, ref rhs) => write!(f, "{} = {};", lhs, rhs),
|
||||
TypedStatement::Assertion(ref e, ref error) => {
|
||||
write!(f, "assert({}", e)?;
|
||||
|
@ -695,14 +710,8 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> {
|
|||
}
|
||||
write!(f, "\t}}")
|
||||
}
|
||||
TypedStatement::MultipleDefinition(ref ids, ref rhs) => {
|
||||
for (i, id) in ids.iter().enumerate() {
|
||||
write!(f, "{}", id)?;
|
||||
if i < ids.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, " = {};", rhs)
|
||||
TypedStatement::EmbedCallDefinition(ref lhs, ref rhs) => {
|
||||
write!(f, "{} = {};", lhs, rhs)
|
||||
}
|
||||
TypedStatement::Log(ref l, ref expressions) => write!(
|
||||
f,
|
||||
|
@ -883,41 +892,6 @@ impl<'ast, T: Clone> Typed<'ast, T> for BooleanExpression<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait MultiTyped<'ast, T> {
|
||||
fn get_types(&self) -> &Vec<Type<'ast, T>>;
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
|
||||
|
||||
pub struct TypedExpressionList<'ast, T> {
|
||||
pub inner: TypedExpressionListInner<'ast, T>,
|
||||
pub types: Types<'ast, T>,
|
||||
}
|
||||
|
||||
impl<'ast, T: fmt::Display> fmt::Display for TypedExpressionList<'ast, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
|
||||
pub enum TypedExpressionListInner<'ast, T> {
|
||||
FunctionCall(FunctionCallExpression<'ast, T, TypedExpressionList<'ast, T>>),
|
||||
EmbedCall(FlatEmbed, Vec<u32>, Vec<TypedExpression<'ast, T>>),
|
||||
}
|
||||
|
||||
impl<'ast, T> MultiTyped<'ast, T> for TypedExpressionList<'ast, T> {
|
||||
fn get_types(&self) -> &Vec<Type<'ast, T>> {
|
||||
&self.types.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> TypedExpressionListInner<'ast, T> {
|
||||
pub fn annotate(self, types: Types<'ast, T>) -> TypedExpressionList<'ast, T> {
|
||||
TypedExpressionList { inner: self, types }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
|
||||
pub struct EqExpression<E> {
|
||||
pub left: Box<E>,
|
||||
|
@ -1305,7 +1279,7 @@ impl<'ast, T: Field> ArrayValue<'ast, T> {
|
|||
.map(|i| {
|
||||
Some(U::select(
|
||||
a.clone()
|
||||
.annotate(*array_ty.ty.clone(), array_ty.size.clone()),
|
||||
.annotate(*array_ty.ty.clone(), *array_ty.size.clone()),
|
||||
i as u32,
|
||||
))
|
||||
})
|
||||
|
@ -1381,7 +1355,7 @@ impl<'ast, T: Clone> ArrayExpression<'ast, T> {
|
|||
}
|
||||
|
||||
pub fn size(&self) -> UExpression<'ast, T> {
|
||||
self.ty.size.clone()
|
||||
*self.ty.size.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1568,15 +1542,6 @@ impl<'ast, T> From<TypedExpression<'ast, T>> for TupleExpression<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
// `TypedExpressionList` can technically not be constructed from `TypedExpression`
|
||||
// However implementing `From<TypedExpression>` is required for `TypedExpressionList` to be `Expr`, which makes generic treatment of function calls possible
|
||||
// This could maybe be avoided by splitting the `Expr` trait into many, but I did not find a way
|
||||
impl<'ast, T> From<TypedExpression<'ast, T>> for TypedExpressionList<'ast, T> {
|
||||
fn from(_: TypedExpression<'ast, T>) -> TypedExpressionList<'ast, T> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> From<TypedConstant<'ast, T>> for FieldElementExpression<'ast, T> {
|
||||
fn from(tc: TypedConstant<'ast, T>) -> FieldElementExpression<'ast, T> {
|
||||
tc.expression.into()
|
||||
|
@ -1750,38 +1715,6 @@ impl<'ast, T: fmt::Display> fmt::Display for ArrayExpressionInner<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ast, T: fmt::Display> fmt::Display for TypedExpressionListInner<'ast, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
TypedExpressionListInner::FunctionCall(ref function_call) => {
|
||||
write!(f, "{}", function_call)
|
||||
}
|
||||
TypedExpressionListInner::EmbedCall(ref embed, ref generics, ref p) => {
|
||||
write!(f, "{}", embed.id())?;
|
||||
if !generics.is_empty() {
|
||||
write!(
|
||||
f,
|
||||
"::<{}>",
|
||||
generics
|
||||
.iter()
|
||||
.map(|g| g.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)?;
|
||||
}
|
||||
write!(f, "(")?;
|
||||
for (i, param) in p.iter().enumerate() {
|
||||
write!(f, "{}", param)?;
|
||||
if i < p.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Variable to TypedExpression conversion
|
||||
|
||||
impl<'ast, T: Field> From<Variable<'ast, T>> for TypedExpression<'ast, T> {
|
||||
|
@ -1790,7 +1723,7 @@ impl<'ast, T: Field> From<Variable<'ast, T>> for TypedExpression<'ast, T> {
|
|||
Type::FieldElement => FieldElementExpression::Identifier(v.id).into(),
|
||||
Type::Boolean => BooleanExpression::Identifier(v.id).into(),
|
||||
Type::Array(ty) => ArrayExpressionInner::Identifier(v.id)
|
||||
.annotate(*ty.ty, ty.size)
|
||||
.annotate(*ty.ty, *ty.size)
|
||||
.into(),
|
||||
Type::Struct(ty) => StructExpressionInner::Identifier(v.id).annotate(ty).into(),
|
||||
Type::Tuple(ty) => TupleExpressionInner::Identifier(v.id).annotate(ty).into(),
|
||||
|
@ -1804,7 +1737,7 @@ impl<'ast, T: Field> From<Variable<'ast, T>> for TypedExpression<'ast, T> {
|
|||
|
||||
pub trait Expr<'ast, T>: fmt::Display + From<TypedExpression<'ast, T>> {
|
||||
type Inner;
|
||||
type Ty: Clone + IntoTypes<'ast, T>;
|
||||
type Ty: Clone + IntoType<'ast, T>;
|
||||
|
||||
fn ty(&self) -> &Self::Ty;
|
||||
|
||||
|
@ -1962,27 +1895,6 @@ impl<'ast, T: Field> Expr<'ast, T> for IntExpression<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ast, T: Field> Expr<'ast, T> for TypedExpressionList<'ast, T> {
|
||||
type Inner = TypedExpressionListInner<'ast, T>;
|
||||
type Ty = Types<'ast, T>;
|
||||
|
||||
fn ty(&self) -> &Self::Ty {
|
||||
&self.types
|
||||
}
|
||||
|
||||
fn into_inner(self) -> Self::Inner {
|
||||
self.inner
|
||||
}
|
||||
|
||||
fn as_inner(&self) -> &Self::Inner {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
fn as_inner_mut(&mut self) -> &mut Self::Inner {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
// Enums types to enable returning e.g a member expression OR another type of expression of this type
|
||||
|
||||
pub enum FunctionCallOrExpression<'ast, T, E: Expr<'ast, T>> {
|
||||
|
@ -2199,7 +2111,8 @@ impl<'ast, T: Clone> Select<'ast, T> for ArrayExpression<'ast, T> {
|
|||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
ArrayExpressionInner::Select(SelectExpression::new(array, index.into())).annotate(*ty, size)
|
||||
ArrayExpressionInner::Select(SelectExpression::new(array, index.into()))
|
||||
.annotate(*ty, *size)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2265,7 +2178,7 @@ impl<'ast, T: Clone> Member<'ast, T> for ArrayExpression<'ast, T> {
|
|||
}) => (*array_ty.ty.clone(), array_ty.size.clone()),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
ArrayExpressionInner::Member(MemberExpression::new(s, id)).annotate(ty, size)
|
||||
ArrayExpressionInner::Member(MemberExpression::new(s, id)).annotate(ty, *size)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2331,7 +2244,7 @@ impl<'ast, T: Clone> Element<'ast, T> for ArrayExpression<'ast, T> {
|
|||
Type::Array(array_ty) => (*array_ty.ty.clone(), array_ty.size.clone()),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
ArrayExpressionInner::Element(ElementExpression::new(s, id)).annotate(ty, size)
|
||||
ArrayExpressionInner::Element(ElementExpression::new(s, id)).annotate(ty, *size)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2397,15 +2310,6 @@ impl<'ast, T: Field> Id<'ast, T> for TupleExpression<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
// `TypedExpressionList` does not have an Identifier variant
|
||||
// However implementing `From<TypedExpression>` is required for `TypedExpressionList` to be `Expr`, which makes generic treatment of function calls possible
|
||||
// This could maybe be avoided by splitting the `Expr` trait into many, but I did not find a way
|
||||
impl<'ast, T: Field> Id<'ast, T> for TypedExpressionList<'ast, T> {
|
||||
fn identifier(_: Identifier<'ast>) -> Self::Inner {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FunctionCall<'ast, T>: Expr<'ast, T> {
|
||||
fn function_call(
|
||||
key: DeclarationFunctionKey<'ast, T>,
|
||||
|
@ -2474,18 +2378,6 @@ impl<'ast, T: Field> FunctionCall<'ast, T> for StructExpression<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ast, T: Field> FunctionCall<'ast, T> for TypedExpressionList<'ast, T> {
|
||||
fn function_call(
|
||||
key: DeclarationFunctionKey<'ast, T>,
|
||||
generics: Vec<Option<UExpression<'ast, T>>>,
|
||||
arguments: Vec<TypedExpression<'ast, T>>,
|
||||
) -> Self::Inner {
|
||||
TypedExpressionListInner::FunctionCall(FunctionCallExpression::new(
|
||||
key, generics, arguments,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Block<'ast, T> {
|
||||
fn block(statements: Vec<TypedStatement<'ast, T>>, value: Self) -> Self;
|
||||
}
|
||||
|
@ -2513,7 +2405,7 @@ impl<'ast, T: Field> Block<'ast, T> for ArrayExpression<'ast, T> {
|
|||
fn block(statements: Vec<TypedStatement<'ast, T>>, value: Self) -> Self {
|
||||
let array_ty = value.ty().clone();
|
||||
ArrayExpressionInner::Block(BlockExpression::new(statements, value))
|
||||
.annotate(*array_ty.ty, array_ty.size)
|
||||
.annotate(*array_ty.ty, *array_ty.size)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2634,7 +2526,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> {
|
|||
.collect::<Vec<_>>()
|
||||
.into(),
|
||||
)
|
||||
.annotate(*array_ty.ty, array_ty.size),
|
||||
.annotate(*array_ty.ty, *array_ty.size),
|
||||
ArrayExpressionInner::Slice(box a, box from, box to) => {
|
||||
let from = match from.into_inner() {
|
||||
UExpressionInner::Value(from) => from as usize,
|
||||
|
@ -2660,7 +2552,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> {
|
|||
.collect::<Vec<_>>()
|
||||
.into(),
|
||||
)
|
||||
.annotate(*array_ty.ty, array_ty.size)
|
||||
.annotate(*array_ty.ty, *array_ty.size)
|
||||
}
|
||||
ArrayExpressionInner::Repeat(box e, box count) => {
|
||||
let count = match count.into_inner() {
|
||||
|
@ -2673,7 +2565,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> {
|
|||
ArrayExpressionInner::Value(
|
||||
vec![TypedExpressionOrSpread::Expression(e); count].into(),
|
||||
)
|
||||
.annotate(*array_ty.ty, array_ty.size)
|
||||
.annotate(*array_ty.ty, *array_ty.size)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
|
@ -170,6 +170,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
|||
Ok(Variable {
|
||||
id: self.fold_name(v.id)?,
|
||||
_type: self.fold_type(v._type)?,
|
||||
is_mutable: v.is_mutable,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -180,6 +181,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
|||
Ok(DeclarationVariable {
|
||||
id: self.fold_name(v.id)?,
|
||||
_type: self.fold_declaration_type(v._type)?,
|
||||
is_mutable: v.is_mutable,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -194,10 +196,6 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
fn fold_types(&mut self, tys: Types<'ast, T>) -> Result<Types<'ast, T>, Self::Error> {
|
||||
fold_types(self, tys)
|
||||
}
|
||||
|
||||
fn fold_conditional_expression<
|
||||
E: Expr<'ast, T> + PartialEq + Conditional<'ast, T> + ResultFold<'ast, T>,
|
||||
>(
|
||||
|
@ -273,7 +271,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
|||
) -> Result<ArrayType<'ast, T>, Self::Error> {
|
||||
Ok(ArrayType {
|
||||
ty: box self.fold_type(*t.ty)?,
|
||||
size: self.fold_uint_expression(t.size)?,
|
||||
size: box self.fold_uint_expression(*t.size)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -333,7 +331,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
|||
) -> Result<DeclarationArrayType<'ast, T>, Self::Error> {
|
||||
Ok(DeclarationArrayType {
|
||||
ty: box self.fold_declaration_type(*t.ty)?,
|
||||
size: self.fold_declaration_constant(t.size)?,
|
||||
size: box self.fold_declaration_constant(*t.size)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -387,6 +385,13 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
|||
fold_statement(self, s)
|
||||
}
|
||||
|
||||
fn fold_embed_call(
|
||||
&mut self,
|
||||
e: EmbedCall<'ast, T>,
|
||||
) -> Result<EmbedCall<'ast, T>, Self::Error> {
|
||||
fold_embed_call(self, e)
|
||||
}
|
||||
|
||||
fn fold_expression_or_spread(
|
||||
&mut self,
|
||||
e: TypedExpressionOrSpread<'ast, T>,
|
||||
|
@ -414,15 +419,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
|||
&mut self,
|
||||
e: TypedExpression<'ast, T>,
|
||||
) -> Result<TypedExpression<'ast, T>, Self::Error> {
|
||||
match e {
|
||||
TypedExpression::FieldElement(e) => Ok(self.fold_field_expression(e)?.into()),
|
||||
TypedExpression::Boolean(e) => Ok(self.fold_boolean_expression(e)?.into()),
|
||||
TypedExpression::Uint(e) => Ok(self.fold_uint_expression(e)?.into()),
|
||||
TypedExpression::Array(e) => Ok(self.fold_array_expression(e)?.into()),
|
||||
TypedExpression::Struct(e) => Ok(self.fold_struct_expression(e)?.into()),
|
||||
TypedExpression::Tuple(e) => Ok(self.fold_tuple_expression(e)?.into()),
|
||||
TypedExpression::Int(e) => Ok(self.fold_int_expression(e)?.into()),
|
||||
}
|
||||
fold_expression(self, e)
|
||||
}
|
||||
|
||||
fn fold_array_expression(
|
||||
|
@ -446,21 +443,6 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
|||
fold_tuple_expression(self, e)
|
||||
}
|
||||
|
||||
fn fold_expression_list_inner(
|
||||
&mut self,
|
||||
tys: &Types<'ast, T>,
|
||||
es: TypedExpressionListInner<'ast, T>,
|
||||
) -> Result<TypedExpressionListInner<'ast, T>, Self::Error> {
|
||||
fold_expression_list_inner(self, tys, es)
|
||||
}
|
||||
|
||||
fn fold_expression_list(
|
||||
&mut self,
|
||||
es: TypedExpressionList<'ast, T>,
|
||||
) -> Result<TypedExpressionList<'ast, T>, Self::Error> {
|
||||
fold_expression_list(self, es)
|
||||
}
|
||||
|
||||
fn fold_int_expression(
|
||||
&mut self,
|
||||
e: IntExpression<'ast, T>,
|
||||
|
@ -524,16 +506,10 @@ pub fn fold_statement<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
|||
s: TypedStatement<'ast, T>,
|
||||
) -> Result<Vec<TypedStatement<'ast, T>>, F::Error> {
|
||||
let res = match s {
|
||||
TypedStatement::Return(expressions) => TypedStatement::Return(
|
||||
expressions
|
||||
.into_iter()
|
||||
.map(|e| f.fold_expression(e))
|
||||
.collect::<Result<_, _>>()?,
|
||||
),
|
||||
TypedStatement::Return(e) => TypedStatement::Return(f.fold_expression(e)?),
|
||||
TypedStatement::Definition(a, e) => {
|
||||
TypedStatement::Definition(f.fold_assignee(a)?, f.fold_expression(e)?)
|
||||
}
|
||||
TypedStatement::Declaration(v) => TypedStatement::Declaration(f.fold_variable(v)?),
|
||||
TypedStatement::Assertion(e, error) => {
|
||||
TypedStatement::Assertion(f.fold_boolean_expression(e)?, error)
|
||||
}
|
||||
|
@ -549,24 +525,37 @@ pub fn fold_statement<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
|||
.flatten()
|
||||
.collect(),
|
||||
),
|
||||
TypedStatement::MultipleDefinition(variables, elist) => TypedStatement::MultipleDefinition(
|
||||
variables
|
||||
.into_iter()
|
||||
.map(|v| f.fold_assignee(v))
|
||||
.collect::<Result<_, _>>()?,
|
||||
f.fold_expression_list(elist)?,
|
||||
),
|
||||
TypedStatement::Log(s, e) => TypedStatement::Log(
|
||||
s,
|
||||
e.into_iter()
|
||||
.map(|e| f.fold_expression(e))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
),
|
||||
TypedStatement::EmbedCallDefinition(assignee, embed_call) => {
|
||||
TypedStatement::EmbedCallDefinition(
|
||||
f.fold_assignee(assignee)?,
|
||||
f.fold_embed_call(embed_call)?,
|
||||
)
|
||||
}
|
||||
s => s,
|
||||
};
|
||||
Ok(vec![res])
|
||||
}
|
||||
|
||||
pub fn fold_embed_call<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||
f: &mut F,
|
||||
e: EmbedCall<'ast, T>,
|
||||
) -> Result<EmbedCall<'ast, T>, F::Error> {
|
||||
Ok(EmbedCall {
|
||||
arguments: e
|
||||
.arguments
|
||||
.into_iter()
|
||||
.map(|s| f.fold_expression(s))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
..e
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fold_array_expression_inner<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||
f: &mut F,
|
||||
ty: &ArrayType<'ast, T>,
|
||||
|
@ -1208,11 +1197,7 @@ pub fn fold_signature<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
|||
.into_iter()
|
||||
.map(|o| f.fold_declaration_type(o))
|
||||
.collect::<Result<_, _>>()?,
|
||||
outputs: s
|
||||
.outputs
|
||||
.into_iter()
|
||||
.map(|o| f.fold_declaration_type(o))
|
||||
.collect::<Result<_, _>>()?,
|
||||
output: box f.fold_declaration_type(*s.output)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1231,6 +1216,21 @@ pub fn fold_declaration_constant<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn fold_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||
f: &mut F,
|
||||
e: TypedExpression<'ast, T>,
|
||||
) -> Result<TypedExpression<'ast, T>, F::Error> {
|
||||
match e {
|
||||
TypedExpression::FieldElement(e) => Ok(f.fold_field_expression(e)?.into()),
|
||||
TypedExpression::Boolean(e) => Ok(f.fold_boolean_expression(e)?.into()),
|
||||
TypedExpression::Uint(e) => Ok(f.fold_uint_expression(e)?.into()),
|
||||
TypedExpression::Array(e) => Ok(f.fold_array_expression(e)?.into()),
|
||||
TypedExpression::Struct(e) => Ok(f.fold_struct_expression(e)?.into()),
|
||||
TypedExpression::Tuple(e) => Ok(f.fold_tuple_expression(e)?.into()),
|
||||
TypedExpression::Int(e) => Ok(f.fold_int_expression(e)?.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fold_array_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||
f: &mut F,
|
||||
e: ArrayExpression<'ast, T>,
|
||||
|
@ -1243,58 +1243,6 @@ pub fn fold_array_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
|||
})
|
||||
}
|
||||
|
||||
pub fn fold_expression_list<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||
f: &mut F,
|
||||
es: TypedExpressionList<'ast, T>,
|
||||
) -> Result<TypedExpressionList<'ast, T>, F::Error> {
|
||||
let types = f.fold_types(es.types)?;
|
||||
|
||||
Ok(TypedExpressionList {
|
||||
inner: f.fold_expression_list_inner(&types, es.inner)?,
|
||||
types,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fold_types<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||
f: &mut F,
|
||||
tys: Types<'ast, T>,
|
||||
) -> Result<Types<'ast, T>, F::Error> {
|
||||
Ok(Types {
|
||||
inner: tys
|
||||
.inner
|
||||
.into_iter()
|
||||
.map(|t| f.fold_type(t))
|
||||
.collect::<Result<_, _>>()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fold_expression_list_inner<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||
f: &mut F,
|
||||
tys: &Types<'ast, T>,
|
||||
es: TypedExpressionListInner<'ast, T>,
|
||||
) -> Result<TypedExpressionListInner<'ast, T>, F::Error> {
|
||||
match es {
|
||||
TypedExpressionListInner::FunctionCall(function_call) => {
|
||||
match f.fold_function_call_expression(tys, function_call)? {
|
||||
FunctionCallOrExpression::FunctionCall(function_call) => {
|
||||
Ok(TypedExpressionListInner::FunctionCall(function_call))
|
||||
}
|
||||
FunctionCallOrExpression::Expression(list) => Ok(list),
|
||||
}
|
||||
}
|
||||
TypedExpressionListInner::EmbedCall(embed, generics, arguments) => {
|
||||
Ok(TypedExpressionListInner::EmbedCall(
|
||||
embed,
|
||||
generics,
|
||||
arguments
|
||||
.into_iter()
|
||||
.map(|a| f.fold_expression(a))
|
||||
.collect::<Result<_, _>>()?,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fold_struct_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||
f: &mut F,
|
||||
e: StructExpression<'ast, T>,
|
||||
|
|
|
@ -8,62 +8,37 @@ use std::fmt;
|
|||
use std::hash::{Hash, Hasher};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub trait IntoTypes<'ast, T> {
|
||||
fn into_types(self) -> Types<'ast, T>;
|
||||
pub trait IntoType<'ast, T> {
|
||||
fn into_type(self) -> Type<'ast, T>;
|
||||
}
|
||||
|
||||
impl<'ast, T> IntoTypes<'ast, T> for Type<'ast, T> {
|
||||
fn into_types(self) -> Types<'ast, T> {
|
||||
Types { inner: vec![self] }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> IntoTypes<'ast, T> for StructType<'ast, T> {
|
||||
fn into_types(self) -> Types<'ast, T> {
|
||||
Types {
|
||||
inner: vec![Type::Struct(self)],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> IntoTypes<'ast, T> for ArrayType<'ast, T> {
|
||||
fn into_types(self) -> Types<'ast, T> {
|
||||
Types {
|
||||
inner: vec![Type::Array(self)],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> IntoTypes<'ast, T> for TupleType<'ast, T> {
|
||||
fn into_types(self) -> Types<'ast, T> {
|
||||
Types {
|
||||
inner: vec![Type::Tuple(self)],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> IntoTypes<'ast, T> for UBitwidth {
|
||||
fn into_types(self) -> Types<'ast, T> {
|
||||
Types {
|
||||
inner: vec![Type::Uint(self)],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> IntoTypes<'ast, T> for Types<'ast, T> {
|
||||
fn into_types(self) -> Types<'ast, T> {
|
||||
impl<'ast, T> IntoType<'ast, T> for Type<'ast, T> {
|
||||
fn into_type(self) -> Type<'ast, T> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
|
||||
pub struct Types<'ast, T> {
|
||||
pub inner: Vec<Type<'ast, T>>,
|
||||
impl<'ast, T> IntoType<'ast, T> for StructType<'ast, T> {
|
||||
fn into_type(self) -> Type<'ast, T> {
|
||||
Type::Struct(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> Types<'ast, T> {
|
||||
pub fn new(types: Vec<Type<'ast, T>>) -> Self {
|
||||
Self { inner: types }
|
||||
impl<'ast, T> IntoType<'ast, T> for ArrayType<'ast, T> {
|
||||
fn into_type(self) -> Type<'ast, T> {
|
||||
Type::Array(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> IntoType<'ast, T> for TupleType<'ast, T> {
|
||||
fn into_type(self) -> Type<'ast, T> {
|
||||
Type::Tuple(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> IntoType<'ast, T> for UBitwidth {
|
||||
fn into_type(self) -> Type<'ast, T> {
|
||||
Type::Uint(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,7 +312,7 @@ impl<'ast, T> From<ConcreteStructMember> for StructMember<'ast, T> {
|
|||
|
||||
#[derive(Clone, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord, Debug)]
|
||||
pub struct GArrayType<S> {
|
||||
pub size: S,
|
||||
pub size: Box<S>,
|
||||
#[serde(flatten)]
|
||||
pub ty: Box<GType<S>>,
|
||||
}
|
||||
|
@ -348,7 +323,7 @@ pub type ArrayType<'ast, T> = GArrayType<UExpression<'ast, T>>;
|
|||
|
||||
impl<'ast, S, R: PartialEq<S>> PartialEq<GArrayType<S>> for GArrayType<R> {
|
||||
fn eq(&self, other: &GArrayType<S>) -> bool {
|
||||
*self.ty == *other.ty && self.size == other.size
|
||||
*self.ty == *other.ty && *self.size == *other.size
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,7 +357,7 @@ fn try_from_g_array_type<T: TryInto<U>, U>(
|
|||
t: GArrayType<T>,
|
||||
) -> Result<GArrayType<U>, SpecializationError> {
|
||||
Ok(GArrayType {
|
||||
size: t.size.try_into().map_err(|_| SpecializationError)?,
|
||||
size: box (*t.size).try_into().map_err(|_| SpecializationError)?,
|
||||
ty: box try_from_g_type(*t.ty)?,
|
||||
})
|
||||
}
|
||||
|
@ -830,7 +805,7 @@ impl<S, U: Into<S>> From<(GType<S>, U)> for GArrayType<S> {
|
|||
fn from(tup: (GType<S>, U)) -> Self {
|
||||
GArrayType {
|
||||
ty: box tup.0,
|
||||
size: tup.1.into(),
|
||||
size: box tup.1.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -838,8 +813,8 @@ impl<S, U: Into<S>> From<(GType<S>, U)> for GArrayType<S> {
|
|||
impl<S> GArrayType<S> {
|
||||
pub fn new<U: Into<S>>(ty: GType<S>, size: U) -> Self {
|
||||
GArrayType {
|
||||
ty: Box::new(ty),
|
||||
size: size.into(),
|
||||
ty: box ty,
|
||||
size: box size.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -922,7 +897,7 @@ impl<'ast, T: fmt::Display + PartialEq + fmt::Debug> Type<'ast, T> {
|
|||
(Array(l), Array(r)) => match l.ty.can_be_specialized_to(&r.ty) {
|
||||
true => {
|
||||
// check the size if types match
|
||||
match (&l.size.as_inner(), &r.size) {
|
||||
match (&l.size.as_inner(), &*r.size) {
|
||||
// compare the sizes for concrete ones
|
||||
(UExpressionInner::Value(v), DeclarationConstant::Concrete(c)) => {
|
||||
(*v as u32) == *c
|
||||
|
@ -953,7 +928,7 @@ impl ConcreteType {
|
|||
GType::Boolean => 1,
|
||||
GType::Uint(_) => 1,
|
||||
GType::Array(array_type) => {
|
||||
array_type.size as usize * array_type.ty.get_primitive_count()
|
||||
*array_type.size as usize * array_type.ty.get_primitive_count()
|
||||
}
|
||||
GType::Tuple(tuple_type) => tuple_type
|
||||
.elements
|
||||
|
@ -1123,7 +1098,7 @@ pub fn check_type<'ast, T, S: Clone + PartialEq + PartialEq<u32>>(
|
|||
(DeclarationType::Array(t0), GType::Array(t1)) => {
|
||||
// both the inner type and the size must match
|
||||
check_type(&t0.ty, &t1.ty, constants)
|
||||
&& check_generic(&t0.size, Some(&t1.size), constants)
|
||||
&& check_generic(&*t0.size, Some(&*t1.size), constants)
|
||||
}
|
||||
(DeclarationType::FieldElement, GType::FieldElement)
|
||||
| (DeclarationType::Boolean, GType::Boolean) => true,
|
||||
|
@ -1164,7 +1139,7 @@ impl<'ast, T> From<CanonicalConstantIdentifier<'ast>> for DeclarationConstant<'a
|
|||
pub fn specialize_declaration_type<
|
||||
'ast,
|
||||
T: Clone,
|
||||
S: Clone + PartialEq + From<u32> + fmt::Debug + From<CanonicalConstantIdentifier<'ast>>,
|
||||
S: Clone + PartialEq + From<u32> + From<CanonicalConstantIdentifier<'ast>>,
|
||||
>(
|
||||
decl_ty: DeclarationType<'ast, T>,
|
||||
generics: &GGenericsAssignment<'ast, S>,
|
||||
|
@ -1172,10 +1147,10 @@ pub fn specialize_declaration_type<
|
|||
Ok(match decl_ty {
|
||||
DeclarationType::Int => unreachable!(),
|
||||
DeclarationType::Array(t0) => {
|
||||
let ty = box specialize_declaration_type(*t0.ty, generics)?;
|
||||
let ty = specialize_declaration_type(*t0.ty, generics)?;
|
||||
let size = t0.size.map(generics)?;
|
||||
|
||||
GType::Array(GArrayType { size, ty })
|
||||
GType::Array(GArrayType::new(ty, size))
|
||||
}
|
||||
DeclarationType::Tuple(t0) => {
|
||||
let elements = t0
|
||||
|
@ -1244,12 +1219,22 @@ pub mod signature {
|
|||
pub struct GSignature<S> {
|
||||
pub generics: Vec<Option<S>>,
|
||||
pub inputs: Vec<GType<S>>,
|
||||
pub outputs: Vec<GType<S>>,
|
||||
pub output: Box<GType<S>>,
|
||||
}
|
||||
|
||||
impl<S> Default for GSignature<S> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
generics: vec![],
|
||||
inputs: vec![],
|
||||
output: box GType::Tuple(GTupleType::new(vec![])),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: PartialEq> PartialEq for GSignature<S> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inputs == other.inputs && self.outputs == other.outputs
|
||||
self.inputs == other.inputs && self.output == other.output
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1257,7 +1242,7 @@ pub mod signature {
|
|||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
self.inputs
|
||||
.partial_cmp(&other.inputs)
|
||||
.map(|c| self.outputs.partial_cmp(&other.outputs).map(|d| c.then(d)))
|
||||
.map(|c| self.output.partial_cmp(&other.output).map(|d| c.then(d)))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -1271,17 +1256,7 @@ pub mod signature {
|
|||
impl<S: Hash> Hash for GSignature<S> {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.inputs.hash(state);
|
||||
self.outputs.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Default for GSignature<S> {
|
||||
fn default() -> Self {
|
||||
GSignature {
|
||||
generics: vec![],
|
||||
inputs: vec![],
|
||||
outputs: vec![],
|
||||
}
|
||||
self.output.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1297,13 +1272,13 @@ pub mod signature {
|
|||
other
|
||||
.inputs
|
||||
.iter()
|
||||
.chain(other.outputs.iter())
|
||||
.zip(self.inputs.iter().chain(self.outputs.iter()))
|
||||
.chain(std::iter::once(&*other.output))
|
||||
.zip(self.inputs.iter().chain(std::iter::once(&*self.output)))
|
||||
.all(|(decl_ty, ty)| check_type::<T, u32>(decl_ty, ty, &mut constants))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T: Clone + PartialEq + fmt::Debug> DeclarationSignature<'ast, T> {
|
||||
impl<'ast, T: Clone + PartialEq> DeclarationSignature<'ast, T> {
|
||||
pub fn specialize(
|
||||
&self,
|
||||
values: Vec<Option<u32>>,
|
||||
|
@ -1312,9 +1287,8 @@ pub mod signature {
|
|||
// we keep track of the value of constants in a map, as a given constant can only have one value
|
||||
let mut constants = ConcreteGenericsAssignment::default();
|
||||
|
||||
assert_eq!(self.inputs.len(), signature.inputs.len());
|
||||
assert_eq!(self.outputs.len(), signature.outputs.len());
|
||||
assert_eq!(self.generics.len(), values.len());
|
||||
assert_eq!(self.inputs.len(), signature.inputs.len());
|
||||
|
||||
let decl_generics = self.generics.iter().map(|g| match g.clone().unwrap() {
|
||||
DeclarationConstant::Generic(g) => g,
|
||||
|
@ -1330,8 +1304,13 @@ pub mod signature {
|
|||
let condition = self
|
||||
.inputs
|
||||
.iter()
|
||||
.chain(self.outputs.iter())
|
||||
.zip(signature.inputs.iter().chain(signature.outputs.iter()))
|
||||
.chain(std::iter::once(&*self.output))
|
||||
.zip(
|
||||
signature
|
||||
.inputs
|
||||
.iter()
|
||||
.chain(std::iter::once(&*signature.output)),
|
||||
)
|
||||
.all(|(decl_ty, ty)| check_type(decl_ty, ty, &mut constants));
|
||||
|
||||
if constants.0.len() != self.generics.len() {
|
||||
|
@ -1344,11 +1323,11 @@ pub mod signature {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_output_types(
|
||||
pub fn get_output_type(
|
||||
&self,
|
||||
generics: Vec<Option<UExpression<'ast, T>>>,
|
||||
inputs: Vec<Type<'ast, T>>,
|
||||
) -> Result<Vec<Type<'ast, T>>, GenericIdentifier<'ast>> {
|
||||
) -> Result<Type<'ast, T>, GenericIdentifier<'ast>> {
|
||||
// we keep track of the value of constants in a map, as a given constant can only have one value
|
||||
let mut constants = GenericsAssignment::default();
|
||||
|
||||
|
@ -1375,12 +1354,8 @@ pub mod signature {
|
|||
.zip(inputs.iter())
|
||||
.all(|(decl_ty, ty)| check_type(decl_ty, ty, &mut constants));
|
||||
|
||||
// get the outputs from the map
|
||||
self.outputs
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|t| specialize_declaration_type(t, &constants))
|
||||
.collect::<Result<_, _>>()
|
||||
// get the specialized output
|
||||
specialize_declaration_type(*self.output.clone(), &constants)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1401,11 +1376,7 @@ pub mod signature {
|
|||
.into_iter()
|
||||
.map(try_from_g_type)
|
||||
.collect::<Result<_, _>>()?,
|
||||
outputs: t
|
||||
.outputs
|
||||
.into_iter()
|
||||
.map(try_from_g_type)
|
||||
.collect::<Result<_, _>>()?,
|
||||
output: box try_from_g_type(*t.output)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1453,21 +1424,7 @@ pub mod signature {
|
|||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, ")")?;
|
||||
match self.outputs.len() {
|
||||
0 => write!(f, ""),
|
||||
1 => write!(f, " -> {}", self.outputs[0]),
|
||||
_ => {
|
||||
write!(f, " -> (")?;
|
||||
for (i, t) in self.outputs.iter().enumerate() {
|
||||
write!(f, "{}", t)?;
|
||||
if i < self.outputs.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
write!(f, ") -> {}", self.output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1486,8 +1443,8 @@ pub mod signature {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn outputs(mut self, outputs: Vec<GType<S>>) -> Self {
|
||||
self.outputs = outputs;
|
||||
pub fn output(mut self, output: GType<S>) -> Self {
|
||||
self.output = Box::new(output);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -1501,7 +1458,7 @@ pub mod signature {
|
|||
fn signature() {
|
||||
let s = ConcreteSignature::new()
|
||||
.inputs(vec![ConcreteType::FieldElement, ConcreteType::Boolean])
|
||||
.outputs(vec![ConcreteType::Boolean]);
|
||||
.output(ConcreteType::Boolean);
|
||||
|
||||
assert_eq!(s.to_string(), String::from("(field, bool) -> bool"));
|
||||
}
|
||||
|
|
|
@ -5,10 +5,11 @@ use crate::typed::UExpression;
|
|||
use crate::typed::{TryFrom, TryInto};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
|
||||
#[derive(Clone, PartialEq, Hash, Eq, PartialOrd, Ord, Debug)]
|
||||
pub struct GVariable<'ast, S> {
|
||||
pub id: Identifier<'ast>,
|
||||
pub _type: GType<S>,
|
||||
pub is_mutable: bool,
|
||||
}
|
||||
|
||||
pub type DeclarationVariable<'ast, T> = GVariable<'ast, DeclarationConstant<'ast, T>>;
|
||||
|
@ -21,7 +22,11 @@ impl<'ast, T> TryFrom<Variable<'ast, T>> for ConcreteVariable<'ast> {
|
|||
fn try_from(v: Variable<'ast, T>) -> Result<Self, Self::Error> {
|
||||
let _type = v._type.try_into()?;
|
||||
|
||||
Ok(Self { _type, id: v.id })
|
||||
Ok(Self {
|
||||
_type,
|
||||
id: v.id,
|
||||
is_mutable: v.is_mutable,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +34,11 @@ impl<'ast, T> From<ConcreteVariable<'ast>> for Variable<'ast, T> {
|
|||
fn from(v: ConcreteVariable<'ast>) -> Self {
|
||||
let _type = v._type.into();
|
||||
|
||||
Self { _type, id: v.id }
|
||||
Self {
|
||||
_type,
|
||||
id: v.id,
|
||||
is_mutable: v.is_mutable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,34 +47,47 @@ pub fn try_from_g_variable<T: TryInto<U>, U>(
|
|||
) -> Result<GVariable<U>, SpecializationError> {
|
||||
let _type = crate::typed::types::try_from_g_type(v._type)?;
|
||||
|
||||
Ok(GVariable { _type, id: v.id })
|
||||
Ok(GVariable {
|
||||
_type,
|
||||
id: v.id,
|
||||
is_mutable: v.is_mutable,
|
||||
})
|
||||
}
|
||||
|
||||
impl<'ast, S: Clone> GVariable<'ast, S> {
|
||||
pub fn field_element<I: Into<Identifier<'ast>>>(id: I) -> Self {
|
||||
Self::with_id_and_type(id, GType::FieldElement)
|
||||
Self::immutable(id, GType::FieldElement)
|
||||
}
|
||||
|
||||
pub fn boolean<I: Into<Identifier<'ast>>>(id: I) -> Self {
|
||||
Self::with_id_and_type(id, GType::Boolean)
|
||||
Self::immutable(id, GType::Boolean)
|
||||
}
|
||||
|
||||
pub fn uint<I: Into<Identifier<'ast>>, W: Into<UBitwidth>>(id: I, bitwidth: W) -> Self {
|
||||
Self::with_id_and_type(id, GType::uint(bitwidth))
|
||||
Self::immutable(id, GType::uint(bitwidth))
|
||||
}
|
||||
|
||||
pub fn array<I: Into<Identifier<'ast>>, U: Into<S>>(id: I, ty: GType<S>, size: U) -> Self {
|
||||
Self::with_id_and_type(id, GType::array((ty, size.into())))
|
||||
Self::immutable(id, GType::array((ty, size.into())))
|
||||
}
|
||||
|
||||
pub fn struc<I: Into<Identifier<'ast>>>(id: I, ty: GStructType<S>) -> Self {
|
||||
Self::with_id_and_type(id, GType::Struct(ty))
|
||||
Self::immutable(id, GType::Struct(ty))
|
||||
}
|
||||
|
||||
pub fn with_id_and_type<I: Into<Identifier<'ast>>>(id: I, _type: GType<S>) -> Self {
|
||||
pub fn immutable<I: Into<Identifier<'ast>>>(id: I, _type: GType<S>) -> Self {
|
||||
Self::new(id, _type, false)
|
||||
}
|
||||
|
||||
pub fn mutable<I: Into<Identifier<'ast>>>(id: I, _type: GType<S>) -> Self {
|
||||
Self::new(id, _type, true)
|
||||
}
|
||||
|
||||
pub fn new<I: Into<Identifier<'ast>>>(id: I, _type: GType<S>, is_mutable: bool) -> Self {
|
||||
GVariable {
|
||||
id: id.into(),
|
||||
_type,
|
||||
is_mutable,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,9 +101,3 @@ impl<'ast, S: fmt::Display> fmt::Display for GVariable<'ast, S> {
|
|||
write!(f, "{} {}", self._type, self.id,)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, S: fmt::Debug> fmt::Debug for GVariable<'ast, S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Variable(type: {:?}, id: {:?})", self._type, self.id,)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use crate::untyped;
|
||||
|
||||
use crate::untyped::{ConditionalExpression, SymbolDefinition};
|
||||
use crate::untyped::{self, ConditionalExpression, SymbolDefinition};
|
||||
use num_bigint::BigUint;
|
||||
use std::path::Path;
|
||||
use zokrates_pest_ast as pest;
|
||||
|
@ -183,16 +181,13 @@ impl<'ast> From<pest::FunctionDefinition<'ast>> for untyped::SymbolDeclarationNo
|
|||
.into_iter()
|
||||
.map(|p| untyped::UnresolvedTypeNode::from(p.ty))
|
||||
.collect(),
|
||||
)
|
||||
.outputs(
|
||||
function
|
||||
.returns
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(untyped::UnresolvedTypeNode::from)
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let signature = match function.return_type {
|
||||
Some(ret_ty) => signature.output(untyped::UnresolvedTypeNode::from(ret_ty)),
|
||||
None => signature,
|
||||
};
|
||||
|
||||
let id = function.id.span.as_str();
|
||||
|
||||
let function = untyped::Function {
|
||||
|
@ -201,11 +196,7 @@ impl<'ast> From<pest::FunctionDefinition<'ast>> for untyped::SymbolDeclarationNo
|
|||
.into_iter()
|
||||
.map(untyped::ParameterNode::from)
|
||||
.collect(),
|
||||
statements: function
|
||||
.statements
|
||||
.into_iter()
|
||||
.flat_map(statements_from_statement)
|
||||
.collect(),
|
||||
statements: function.statements.into_iter().map(|s| s.into()).collect(),
|
||||
signature,
|
||||
}
|
||||
.span(span.clone());
|
||||
|
@ -232,7 +223,7 @@ impl<'ast> From<pest::Parameter<'ast>> for untyped::ParameterNode<'ast> {
|
|||
fn from(param: pest::Parameter<'ast>) -> untyped::ParameterNode<'ast> {
|
||||
use crate::untyped::NodeValue;
|
||||
|
||||
let private = param
|
||||
let is_private = param
|
||||
.visibility
|
||||
.map(|v| match v {
|
||||
pest::Visibility::Private(_) => true,
|
||||
|
@ -240,23 +231,16 @@ impl<'ast> From<pest::Parameter<'ast>> for untyped::ParameterNode<'ast> {
|
|||
})
|
||||
.unwrap_or(false);
|
||||
|
||||
let is_mutable = param.mutable.is_some();
|
||||
|
||||
let variable = untyped::Variable::new(
|
||||
param.id.span.as_str(),
|
||||
untyped::UnresolvedTypeNode::from(param.ty),
|
||||
is_mutable,
|
||||
)
|
||||
.span(param.id.span);
|
||||
|
||||
untyped::Parameter::new(variable, private).span(param.span)
|
||||
}
|
||||
}
|
||||
|
||||
fn statements_from_statement(statement: pest::Statement) -> Vec<untyped::StatementNode> {
|
||||
match statement {
|
||||
pest::Statement::Definition(s) => statements_from_definition(s),
|
||||
pest::Statement::Iteration(s) => vec![untyped::StatementNode::from(s)],
|
||||
pest::Statement::Assertion(s) => vec![untyped::StatementNode::from(s)],
|
||||
pest::Statement::Return(s) => vec![untyped::StatementNode::from(s)],
|
||||
pest::Statement::Log(s) => vec![untyped::StatementNode::from(s)],
|
||||
untyped::Parameter::new(variable, is_private).span(param.span)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,101 +258,53 @@ impl<'ast> From<pest::LogStatement<'ast>> for untyped::StatementNode<'ast> {
|
|||
}
|
||||
}
|
||||
|
||||
fn statements_from_definition(
|
||||
definition: pest::DefinitionStatement,
|
||||
) -> Vec<untyped::StatementNode> {
|
||||
use crate::untyped::NodeValue;
|
||||
impl<'ast> From<pest::TypedIdentifier<'ast>> for untyped::VariableNode<'ast> {
|
||||
fn from(i: pest::TypedIdentifier<'ast>) -> Self {
|
||||
use crate::untyped::NodeValue;
|
||||
|
||||
let lhs = definition.lhs;
|
||||
untyped::Variable::new(
|
||||
i.identifier.span.as_str(),
|
||||
untyped::UnresolvedTypeNode::from(i.ty),
|
||||
i.mutable.is_some(),
|
||||
)
|
||||
.span(i.span)
|
||||
}
|
||||
}
|
||||
|
||||
match lhs.len() {
|
||||
1 => {
|
||||
// Definition or assignment
|
||||
let a = lhs[0].clone();
|
||||
impl<'ast> From<pest::Statement<'ast>> for untyped::StatementNode<'ast> {
|
||||
fn from(statement: pest::Statement<'ast>) -> Self {
|
||||
match statement {
|
||||
pest::Statement::Definition(s) => untyped::StatementNode::from(s),
|
||||
pest::Statement::Iteration(s) => untyped::StatementNode::from(s),
|
||||
pest::Statement::Assertion(s) => untyped::StatementNode::from(s),
|
||||
pest::Statement::Return(s) => untyped::StatementNode::from(s),
|
||||
pest::Statement::Log(s) => untyped::StatementNode::from(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let e: untyped::ExpressionNode = untyped::ExpressionNode::from(definition.expression);
|
||||
impl<'ast> From<pest::DefinitionStatement<'ast>> for untyped::StatementNode<'ast> {
|
||||
fn from(definition: pest::DefinitionStatement<'ast>) -> Self {
|
||||
use crate::untyped::NodeValue;
|
||||
|
||||
match a {
|
||||
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => {
|
||||
let declaration = untyped::Statement::Declaration(
|
||||
untyped::Variable::new(
|
||||
i.identifier.span.as_str(),
|
||||
untyped::UnresolvedTypeNode::from(i.ty),
|
||||
)
|
||||
.span(i.identifier.span.clone()),
|
||||
)
|
||||
.span(definition.span.clone());
|
||||
let lhs = definition.lhs;
|
||||
let e: untyped::ExpressionNode = untyped::ExpressionNode::from(definition.expression);
|
||||
|
||||
let s = match e.value {
|
||||
untyped::Expression::FunctionCall(..) => {
|
||||
untyped::Statement::MultipleDefinition(
|
||||
vec![untyped::AssigneeNode::from(i.identifier.clone())],
|
||||
e,
|
||||
)
|
||||
}
|
||||
_ => untyped::Statement::Definition(
|
||||
untyped::AssigneeNode::from(i.identifier.clone()),
|
||||
e,
|
||||
),
|
||||
};
|
||||
|
||||
vec![declaration, s.span(definition.span)]
|
||||
}
|
||||
pest::TypedIdentifierOrAssignee::Assignee(a) => {
|
||||
let s = match e.value {
|
||||
untyped::Expression::FunctionCall(..) => {
|
||||
untyped::Statement::MultipleDefinition(
|
||||
vec![untyped::AssigneeNode::from(a)],
|
||||
e,
|
||||
)
|
||||
}
|
||||
_ => untyped::Statement::Definition(untyped::AssigneeNode::from(a), e),
|
||||
};
|
||||
|
||||
vec![s.span(definition.span)]
|
||||
}
|
||||
match lhs {
|
||||
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => untyped::Statement::Definition(
|
||||
untyped::Variable::new(
|
||||
i.identifier.span.as_str(),
|
||||
untyped::UnresolvedTypeNode::from(i.ty),
|
||||
i.mutable.is_some(),
|
||||
)
|
||||
.span(i.span.clone()),
|
||||
e,
|
||||
),
|
||||
pest::TypedIdentifierOrAssignee::Assignee(a) => {
|
||||
untyped::Statement::Assignment(untyped::AssigneeNode::from(a), e)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Multidefinition
|
||||
let declarations = lhs.clone().into_iter().filter_map(|i| match i {
|
||||
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => {
|
||||
let ty = i.ty;
|
||||
let id = i.identifier;
|
||||
|
||||
Some(
|
||||
untyped::Statement::Declaration(
|
||||
untyped::Variable::new(
|
||||
id.span.as_str(),
|
||||
untyped::UnresolvedTypeNode::from(ty),
|
||||
)
|
||||
.span(id.span),
|
||||
)
|
||||
.span(i.span),
|
||||
)
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
let lhs = lhs
|
||||
.into_iter()
|
||||
.map(|i| match i {
|
||||
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => {
|
||||
untyped::Assignee::Identifier(i.identifier.span.as_str())
|
||||
.span(i.identifier.span)
|
||||
}
|
||||
pest::TypedIdentifierOrAssignee::Assignee(a) => untyped::AssigneeNode::from(a),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let multi_def = untyped::Statement::MultipleDefinition(
|
||||
lhs,
|
||||
untyped::ExpressionNode::from(definition.expression),
|
||||
)
|
||||
.span(definition.span);
|
||||
|
||||
declarations.chain(std::iter::once(multi_def)).collect()
|
||||
}
|
||||
.span(definition.span.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,17 +312,8 @@ impl<'ast> From<pest::ReturnStatement<'ast>> for untyped::StatementNode<'ast> {
|
|||
fn from(statement: pest::ReturnStatement<'ast>) -> untyped::StatementNode<'ast> {
|
||||
use crate::untyped::NodeValue;
|
||||
|
||||
untyped::Statement::Return(
|
||||
untyped::ExpressionList {
|
||||
expressions: statement
|
||||
.expressions
|
||||
.into_iter()
|
||||
.map(untyped::ExpressionNode::from)
|
||||
.collect(),
|
||||
}
|
||||
.span(statement.span.clone()),
|
||||
)
|
||||
.span(statement.span)
|
||||
untyped::Statement::Return(statement.expression.map(untyped::ExpressionNode::from))
|
||||
.span(statement.span)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,19 +332,13 @@ impl<'ast> From<pest::AssertionStatement<'ast>> for untyped::StatementNode<'ast>
|
|||
impl<'ast> From<pest::IterationStatement<'ast>> for untyped::StatementNode<'ast> {
|
||||
fn from(statement: pest::IterationStatement<'ast>) -> untyped::StatementNode<'ast> {
|
||||
use crate::untyped::NodeValue;
|
||||
let index = untyped::VariableNode::from(statement.index);
|
||||
let from = untyped::ExpressionNode::from(statement.from);
|
||||
let to = untyped::ExpressionNode::from(statement.to);
|
||||
let index = statement.id.identifier.span.as_str();
|
||||
let ty = untyped::UnresolvedTypeNode::from(statement.id.ty);
|
||||
let statements: Vec<untyped::StatementNode<'ast>> = statement
|
||||
.statements
|
||||
.into_iter()
|
||||
.flat_map(statements_from_statement)
|
||||
.collect();
|
||||
let statements: Vec<untyped::StatementNode<'ast>> =
|
||||
statement.statements.into_iter().map(|s| s.into()).collect();
|
||||
|
||||
let var = untyped::Variable::new(index, ty).span(statement.id.identifier.span);
|
||||
|
||||
untyped::Statement::For(var, from, to, statements).span(statement.span)
|
||||
untyped::Statement::For(index, from, to, statements).span(statement.span)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -536,13 +457,13 @@ impl<'ast> From<pest::IfElseExpression<'ast>> for untyped::ExpressionNode<'ast>
|
|||
consequence_statements: expression
|
||||
.consequence_statements
|
||||
.into_iter()
|
||||
.flat_map(statements_from_statement)
|
||||
.map(untyped::StatementNode::from)
|
||||
.collect(),
|
||||
consequence: box untyped::ExpressionNode::from(*expression.consequence),
|
||||
alternative_statements: expression
|
||||
.alternative_statements
|
||||
.into_iter()
|
||||
.flat_map(statements_from_statement)
|
||||
.map(untyped::StatementNode::from)
|
||||
.collect(),
|
||||
alternative: box untyped::ExpressionNode::from(*expression.alternative),
|
||||
kind: untyped::ConditionalKind::IfElse,
|
||||
|
@ -966,18 +887,13 @@ mod tests {
|
|||
symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(
|
||||
untyped::Function {
|
||||
arguments: vec![],
|
||||
statements: vec![untyped::Statement::Return(
|
||||
untyped::ExpressionList {
|
||||
expressions: vec![
|
||||
untyped::Expression::IntConstant(42usize.into()).into()
|
||||
],
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
statements: vec![untyped::Statement::Return(Some(
|
||||
untyped::Expression::IntConstant(42usize.into()).into(),
|
||||
))
|
||||
.into()],
|
||||
signature: UnresolvedSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![UnresolvedType::FieldElement.mock()]),
|
||||
.output(UnresolvedType::FieldElement.mock()),
|
||||
}
|
||||
.into(),
|
||||
)),
|
||||
|
@ -991,37 +907,31 @@ mod tests {
|
|||
fn return_true() {
|
||||
let source = "def main() -> bool { return true; }";
|
||||
let ast = pest::generate_ast(source).unwrap();
|
||||
let expected: untyped::Module =
|
||||
untyped::Module {
|
||||
symbols: vec![untyped::SymbolDeclaration {
|
||||
id: &source[4..8],
|
||||
symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(
|
||||
untyped::Function {
|
||||
arguments: vec![],
|
||||
statements: vec![untyped::Statement::Return(
|
||||
untyped::ExpressionList {
|
||||
expressions: vec![
|
||||
untyped::Expression::BooleanConstant(true).into()
|
||||
],
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into()],
|
||||
signature: UnresolvedSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![UnresolvedType::Boolean.mock()]),
|
||||
}
|
||||
.into(),
|
||||
)),
|
||||
}
|
||||
.into()],
|
||||
};
|
||||
let expected: untyped::Module = untyped::Module {
|
||||
symbols: vec![untyped::SymbolDeclaration {
|
||||
id: &source[4..8],
|
||||
symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(
|
||||
untyped::Function {
|
||||
arguments: vec![],
|
||||
statements: vec![untyped::Statement::Return(Some(
|
||||
untyped::Expression::BooleanConstant(true).into(),
|
||||
))
|
||||
.into()],
|
||||
signature: UnresolvedSignature::new()
|
||||
.inputs(vec![])
|
||||
.output(UnresolvedType::Boolean.mock()),
|
||||
}
|
||||
.into(),
|
||||
)),
|
||||
}
|
||||
.into()],
|
||||
};
|
||||
assert_eq!(untyped::Module::from(ast), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arguments() {
|
||||
let source = "def main(private field a, bool b) -> field { return 42; }";
|
||||
let source = "def main(private field a, bool mut b) -> field { return 42; }";
|
||||
let ast = pest::generate_ast(source).unwrap();
|
||||
|
||||
let expected: untyped::Module = untyped::Module {
|
||||
|
@ -1031,37 +941,29 @@ mod tests {
|
|||
untyped::Function {
|
||||
arguments: vec![
|
||||
untyped::Parameter::private(
|
||||
untyped::Variable::new(
|
||||
&source[23..24],
|
||||
untyped::Variable::immutable(
|
||||
"a",
|
||||
UnresolvedType::FieldElement.mock(),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
untyped::Parameter::public(
|
||||
untyped::Variable::new(
|
||||
&source[31..32],
|
||||
UnresolvedType::Boolean.mock(),
|
||||
)
|
||||
.into(),
|
||||
untyped::Variable::mutable("b", UnresolvedType::Boolean.mock())
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
],
|
||||
statements: vec![untyped::Statement::Return(
|
||||
untyped::ExpressionList {
|
||||
expressions: vec![
|
||||
untyped::Expression::IntConstant(42usize.into()).into()
|
||||
],
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
statements: vec![untyped::Statement::Return(Some(
|
||||
untyped::Expression::IntConstant(42usize.into()).into(),
|
||||
))
|
||||
.into()],
|
||||
signature: UnresolvedSignature::new()
|
||||
.inputs(vec![
|
||||
UnresolvedType::FieldElement.mock(),
|
||||
UnresolvedType::Boolean.mock(),
|
||||
])
|
||||
.outputs(vec![UnresolvedType::FieldElement.mock()]),
|
||||
.output(UnresolvedType::FieldElement.mock()),
|
||||
}
|
||||
.into(),
|
||||
)),
|
||||
|
@ -1083,16 +985,10 @@ mod tests {
|
|||
symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(
|
||||
untyped::Function {
|
||||
arguments: vec![untyped::Parameter::private(
|
||||
untyped::Variable::new("a", ty.clone().mock()).into(),
|
||||
)
|
||||
.into()],
|
||||
statements: vec![untyped::Statement::Return(
|
||||
untyped::ExpressionList {
|
||||
expressions: vec![],
|
||||
}
|
||||
.into(),
|
||||
untyped::Variable::new("a", ty.clone().mock(), false).into(),
|
||||
)
|
||||
.into()],
|
||||
statements: vec![untyped::Statement::Return(None).into()],
|
||||
signature: UnresolvedSignature::new().inputs(vec![ty.mock()]),
|
||||
}
|
||||
.into(),
|
||||
|
@ -1156,13 +1052,9 @@ mod tests {
|
|||
symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(
|
||||
untyped::Function {
|
||||
arguments: vec![],
|
||||
statements: vec![untyped::Statement::Return(
|
||||
untyped::ExpressionList {
|
||||
expressions: vec![expression.into()],
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.into()],
|
||||
statements: vec![
|
||||
untyped::Statement::Return(Some(expression.into())).into()
|
||||
],
|
||||
signature: UnresolvedSignature::new(),
|
||||
}
|
||||
.into(),
|
||||
|
@ -1294,20 +1186,18 @@ mod tests {
|
|||
|
||||
let span = Span::new("", 0, 0).unwrap();
|
||||
|
||||
// For different definitions, we generate declarations
|
||||
// Case 1: `id = expr` where `expr` is not a function call
|
||||
// This is a simple assignment, doesn't implicitely declare a variable
|
||||
// A `Definition` is generated and no `Declaration`s
|
||||
// Case 1: `id = expr`
|
||||
// A simple assignment to an already defined variable
|
||||
|
||||
let definition = pest::DefinitionStatement {
|
||||
lhs: vec![pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee {
|
||||
lhs: pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee {
|
||||
id: pest::IdentifierExpression {
|
||||
value: String::from("a"),
|
||||
span: span.clone(),
|
||||
},
|
||||
accesses: vec![],
|
||||
span: span.clone(),
|
||||
})],
|
||||
}),
|
||||
expression: pest::Expression::Literal(pest::LiteralExpression::DecimalLiteral(
|
||||
pest::DecimalLiteralExpression {
|
||||
value: pest::DecimalNumber {
|
||||
|
@ -1320,28 +1210,30 @@ mod tests {
|
|||
span: span.clone(),
|
||||
};
|
||||
|
||||
let statements: Vec<untyped::StatementNode> = statements_from_definition(definition);
|
||||
let statement = untyped::StatementNode::from(definition);
|
||||
|
||||
assert_eq!(statements.len(), 1);
|
||||
match &statements[0].value {
|
||||
untyped::Statement::Definition(..) => {}
|
||||
match statement.value {
|
||||
untyped::Statement::Assignment(..) => {}
|
||||
s => {
|
||||
panic!("should be a Definition, found {}", s);
|
||||
panic!("should be an Assignment, found {}", s);
|
||||
}
|
||||
};
|
||||
|
||||
// Case 2: `id = expr` where `expr` is a function call
|
||||
// A MultiDef is generated
|
||||
// Case 2: `type id = expr`
|
||||
// A definition statement is generated
|
||||
|
||||
let definition = pest::DefinitionStatement {
|
||||
lhs: vec![pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee {
|
||||
id: pest::IdentifierExpression {
|
||||
lhs: pest::TypedIdentifierOrAssignee::TypedIdentifier(pest::TypedIdentifier {
|
||||
ty: pest::Type::Basic(pest::BasicType::Field(pest::FieldType {
|
||||
span: span.clone(),
|
||||
})),
|
||||
identifier: pest::IdentifierExpression {
|
||||
value: String::from("a"),
|
||||
span: span.clone(),
|
||||
},
|
||||
accesses: vec![],
|
||||
mutable: None,
|
||||
span: span.clone(),
|
||||
})],
|
||||
}),
|
||||
expression: pest::Expression::Postfix(pest::PostfixExpression {
|
||||
base: box pest::Expression::Identifier(pest::IdentifierExpression {
|
||||
value: String::from("foo"),
|
||||
|
@ -1360,64 +1252,10 @@ mod tests {
|
|||
span: span.clone(),
|
||||
};
|
||||
|
||||
let statements: Vec<untyped::StatementNode> = statements_from_definition(definition);
|
||||
let statement = untyped::StatementNode::from(definition);
|
||||
|
||||
assert_eq!(statements.len(), 1);
|
||||
match &statements[0].value {
|
||||
untyped::Statement::MultipleDefinition(..) => {}
|
||||
s => {
|
||||
panic!("should be a Definition, found {}", s);
|
||||
}
|
||||
};
|
||||
// Case 3: `ids = expr` where `expr` is a function call
|
||||
// This implicitely declares all variables which are type annotated
|
||||
|
||||
// `field a, b = foo()`
|
||||
|
||||
let definition = pest::DefinitionStatement {
|
||||
lhs: vec![
|
||||
pest::TypedIdentifierOrAssignee::TypedIdentifier(pest::TypedIdentifier {
|
||||
ty: pest::Type::Basic(pest::BasicType::Field(pest::FieldType {
|
||||
span: span.clone(),
|
||||
})),
|
||||
identifier: pest::IdentifierExpression {
|
||||
value: String::from("a"),
|
||||
span: span.clone(),
|
||||
},
|
||||
span: span.clone(),
|
||||
}),
|
||||
pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee {
|
||||
id: pest::IdentifierExpression {
|
||||
value: String::from("b"),
|
||||
span: span.clone(),
|
||||
},
|
||||
accesses: vec![],
|
||||
span: span.clone(),
|
||||
}),
|
||||
],
|
||||
expression: pest::Expression::Postfix(pest::PostfixExpression {
|
||||
base: box pest::Expression::Identifier(pest::IdentifierExpression {
|
||||
value: String::from("foo"),
|
||||
span: span.clone(),
|
||||
}),
|
||||
accesses: vec![pest::Access::Call(pest::CallAccess {
|
||||
explicit_generics: None,
|
||||
arguments: pest::Arguments {
|
||||
expressions: vec![],
|
||||
span: span.clone(),
|
||||
},
|
||||
span: span.clone(),
|
||||
})],
|
||||
span: span.clone(),
|
||||
}),
|
||||
span: span.clone(),
|
||||
};
|
||||
|
||||
let statements: Vec<untyped::StatementNode> = statements_from_definition(definition);
|
||||
|
||||
assert_eq!(statements.len(), 2);
|
||||
match &statements[1].value {
|
||||
untyped::Statement::MultipleDefinition(..) => {}
|
||||
match statement.value {
|
||||
untyped::Statement::Definition(..) => {}
|
||||
s => {
|
||||
panic!("should be a Definition, found {}", s);
|
||||
}
|
||||
|
|
|
@ -386,9 +386,9 @@ impl<'ast> fmt::Display for Assignee<'ast> {
|
|||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Statement<'ast> {
|
||||
Return(ExpressionListNode<'ast>),
|
||||
Declaration(VariableNode<'ast>),
|
||||
Definition(AssigneeNode<'ast>, ExpressionNode<'ast>),
|
||||
Return(Option<ExpressionNode<'ast>>),
|
||||
Definition(VariableNode<'ast>, ExpressionNode<'ast>),
|
||||
Assignment(AssigneeNode<'ast>, ExpressionNode<'ast>),
|
||||
Assertion(ExpressionNode<'ast>, Option<String>),
|
||||
For(
|
||||
VariableNode<'ast>,
|
||||
|
@ -396,7 +396,6 @@ pub enum Statement<'ast> {
|
|||
ExpressionNode<'ast>,
|
||||
Vec<StatementNode<'ast>>,
|
||||
),
|
||||
MultipleDefinition(Vec<AssigneeNode<'ast>>, ExpressionNode<'ast>),
|
||||
Log(&'ast str, Vec<ExpressionNode<'ast>>),
|
||||
}
|
||||
|
||||
|
@ -405,9 +404,17 @@ pub type StatementNode<'ast> = Node<Statement<'ast>>;
|
|||
impl<'ast> fmt::Display for Statement<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Statement::Return(ref expr) => write!(f, "return {};", expr),
|
||||
Statement::Declaration(ref var) => write!(f, "{};", var),
|
||||
Statement::Definition(ref lhs, ref rhs) => write!(f, "{} = {};", lhs, rhs),
|
||||
Statement::Return(ref expr) => {
|
||||
write!(f, "return")?;
|
||||
match expr {
|
||||
Some(e) => write!(f, " {};", e),
|
||||
None => write!(f, ";"),
|
||||
}
|
||||
}
|
||||
Statement::Definition(ref var, ref rhs) => {
|
||||
write!(f, "{} = {};", var, rhs)
|
||||
}
|
||||
Statement::Assignment(ref lhs, ref rhs) => write!(f, "{} = {};", lhs, rhs),
|
||||
Statement::Assertion(ref e, ref message) => {
|
||||
write!(f, "assert({}", e)?;
|
||||
match message {
|
||||
|
@ -422,15 +429,6 @@ impl<'ast> fmt::Display for Statement<'ast> {
|
|||
}
|
||||
write!(f, "\t}}")
|
||||
}
|
||||
Statement::MultipleDefinition(ref ids, ref rhs) => {
|
||||
for (i, id) in ids.iter().enumerate() {
|
||||
write!(f, "{}", id)?;
|
||||
if i < ids.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, " = {};", rhs)
|
||||
}
|
||||
Statement::Log(ref l, ref expressions) => write!(
|
||||
f,
|
||||
"log!({}, {})",
|
||||
|
@ -714,23 +712,3 @@ impl<'ast> fmt::Display for Expression<'ast> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of expressions, used in return statements
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct ExpressionList<'ast> {
|
||||
pub expressions: Vec<ExpressionNode<'ast>>,
|
||||
}
|
||||
|
||||
pub type ExpressionListNode<'ast> = Node<ExpressionList<'ast>>;
|
||||
|
||||
impl<'ast> fmt::Display for ExpressionList<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for (i, param) in self.expressions.iter().enumerate() {
|
||||
write!(f, "{}", param)?;
|
||||
if i < self.expressions.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, "")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,6 @@ impl<V: NodeValue> From<V> for Node<V> {
|
|||
use super::*;
|
||||
|
||||
impl<'ast> NodeValue for Expression<'ast> {}
|
||||
impl<'ast> NodeValue for ExpressionList<'ast> {}
|
||||
impl<'ast> NodeValue for Assignee<'ast> {}
|
||||
impl<'ast> NodeValue for Statement<'ast> {}
|
||||
impl<'ast> NodeValue for SymbolDeclaration<'ast> {}
|
||||
|
|
|
@ -4,26 +4,20 @@ use std::fmt;
|
|||
#[derive(Clone, PartialEq)]
|
||||
pub struct Parameter<'ast> {
|
||||
pub id: VariableNode<'ast>,
|
||||
pub private: bool,
|
||||
pub is_private: bool,
|
||||
}
|
||||
|
||||
impl<'ast> Parameter<'ast> {
|
||||
pub fn new(v: VariableNode<'ast>, private: bool) -> Self {
|
||||
Parameter { id: v, private }
|
||||
}
|
||||
|
||||
pub fn public(v: VariableNode<'ast>) -> Self {
|
||||
Parameter {
|
||||
id: v,
|
||||
private: false,
|
||||
}
|
||||
pub fn new(v: VariableNode<'ast>, is_private: bool) -> Self {
|
||||
Parameter { id: v, is_private }
|
||||
}
|
||||
|
||||
pub fn private(v: VariableNode<'ast>) -> Self {
|
||||
Parameter {
|
||||
id: v,
|
||||
private: true,
|
||||
}
|
||||
Self::new(v, true)
|
||||
}
|
||||
|
||||
pub fn public(v: VariableNode<'ast>) -> Self {
|
||||
Self::new(v, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +25,7 @@ pub type ParameterNode<'ast> = Node<Parameter<'ast>>;
|
|||
|
||||
impl<'ast> fmt::Display for Parameter<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let visibility = if self.private { "private " } else { "" };
|
||||
let visibility = if self.is_private { "private " } else { "" };
|
||||
write!(
|
||||
f,
|
||||
"{}{} {}",
|
||||
|
@ -47,7 +41,7 @@ impl<'ast> fmt::Debug for Parameter<'ast> {
|
|||
write!(
|
||||
f,
|
||||
"Parameter(variable: {:?}, private: {:?})",
|
||||
self.id, self.private
|
||||
self.id, self.is_private
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,15 +85,15 @@ mod signature {
|
|||
pub struct UnresolvedSignature<'ast> {
|
||||
pub generics: Vec<ConstantGenericNode<'ast>>,
|
||||
pub inputs: Vec<UnresolvedTypeNode<'ast>>,
|
||||
pub outputs: Vec<UnresolvedTypeNode<'ast>>,
|
||||
pub output: Option<UnresolvedTypeNode<'ast>>,
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Debug for UnresolvedSignature<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Signature(inputs: {:?}, outputs: {:?})",
|
||||
self.inputs, self.outputs
|
||||
"Signature(inputs: {:?}, output: {:?})",
|
||||
self.inputs, self.output
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -107,14 +107,10 @@ mod signature {
|
|||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, ") -> (")?;
|
||||
for (i, t) in self.outputs.iter().enumerate() {
|
||||
write!(f, "{}", t)?;
|
||||
if i < self.outputs.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
match &self.output {
|
||||
Some(ty) => write!(f, ") -> {}", ty),
|
||||
None => write!(f, ")"),
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,8 +129,8 @@ mod signature {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn outputs(mut self, outputs: Vec<UnresolvedTypeNode<'ast>>) -> Self {
|
||||
self.outputs = outputs;
|
||||
pub fn output(mut self, output: UnresolvedTypeNode<'ast>) -> Self {
|
||||
self.output = Some(output);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use super::Identifier;
|
|||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Variable<'ast> {
|
||||
pub is_mutable: bool,
|
||||
pub id: Identifier<'ast>,
|
||||
pub _type: UnresolvedTypeNode<'ast>,
|
||||
}
|
||||
|
@ -13,13 +14,26 @@ pub struct Variable<'ast> {
|
|||
pub type VariableNode<'ast> = Node<Variable<'ast>>;
|
||||
|
||||
impl<'ast> Variable<'ast> {
|
||||
pub fn new<S: Into<&'ast str>>(id: S, t: UnresolvedTypeNode<'ast>) -> Variable<'ast> {
|
||||
pub fn new<S: Into<&'ast str>>(
|
||||
id: S,
|
||||
t: UnresolvedTypeNode<'ast>,
|
||||
is_mutable: bool,
|
||||
) -> Variable<'ast> {
|
||||
Variable {
|
||||
is_mutable,
|
||||
id: id.into(),
|
||||
_type: t,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn immutable<S: Into<&'ast str>>(id: S, t: UnresolvedTypeNode<'ast>) -> Self {
|
||||
Self::new(id, t, false)
|
||||
}
|
||||
|
||||
pub fn mutable<S: Into<&'ast str>>(id: S, t: UnresolvedTypeNode<'ast>) -> Self {
|
||||
Self::new(id, t, true)
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> &UnresolvedType<'ast> {
|
||||
&self._type.value
|
||||
}
|
||||
|
@ -33,6 +47,10 @@ impl<'ast> fmt::Display for Variable<'ast> {
|
|||
|
||||
impl<'ast> fmt::Debug for Variable<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Variable(type: {:?}, id: {:?})", self._type, self.id,)
|
||||
write!(
|
||||
f,
|
||||
"Variable(type: {:?}, id: {:?}, is_mutable: {:?})",
|
||||
self._type, self.id, self.is_mutable
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ impl From<typed_absy::types::ConcreteSignature> for zir::types::Signature {
|
|||
fn from(s: typed_absy::types::ConcreteSignature) -> zir::types::Signature {
|
||||
zir::types::Signature {
|
||||
inputs: s.inputs.into_iter().flat_map(from_type).collect(),
|
||||
outputs: s.outputs.into_iter().flat_map(from_type).collect(),
|
||||
outputs: from_type(*s.output),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ fn from_type(t: typed_absy::types::ConcreteType) -> Vec<zir::types::Type> {
|
|||
}
|
||||
typed_absy::types::ConcreteType::Array(array_type) => {
|
||||
let inner = from_type(*array_type.ty);
|
||||
(0..array_type.size).flat_map(|_| inner.clone()).collect()
|
||||
(0..*array_type.size).flat_map(|_| inner.clone()).collect()
|
||||
}
|
||||
typed_absy::types::ConcreteType::Struct(members) => members
|
||||
.into_iter()
|
||||
|
|
|
@ -8,11 +8,13 @@ Function calls help make programs clear and modular.
|
|||
|
||||
Arguments are passed by value.
|
||||
|
||||
Function parameters can be declared as mutable to allow for mutation within the function's body. However, mutable function arguments are still passed by value, so the original value can never be mutated.
|
||||
|
||||
```zokrates
|
||||
{{#include ../../../zokrates_cli/examples/book/side_effects.zok}}
|
||||
```
|
||||
|
||||
Generic paramaters, if any, must be compile-time constants. They are inferred by the compiler if that is possible, but can also be provided explicitly.
|
||||
Generic parameters, if any, must be compile-time constants. They are inferred by the compiler if that is possible, but can also be provided explicitly.
|
||||
|
||||
```zokrates
|
||||
{{#include ../../../zokrates_cli/examples/book/generic_call.zok}}
|
||||
|
|
|
@ -18,18 +18,4 @@ The generic parameters can be provided explicitly, especially when they cannot b
|
|||
|
||||
```zokrates
|
||||
{{#include ../../../zokrates_cli/examples/book/explicit_generic_parameters.zok}}
|
||||
```
|
||||
|
||||
Functions can return multiple values by providing them as a comma-separated list.
|
||||
|
||||
```zokrates
|
||||
{{#include ../../../zokrates_cli/examples/book/multi_return.zok}}
|
||||
```
|
||||
|
||||
### Variable declaration
|
||||
|
||||
When defining a variable as the return value of a function, types are provided when the variable needs to be declared:
|
||||
|
||||
```zokrates
|
||||
{{#include ../../../zokrates_cli/examples/book/multi_def.zok}}
|
||||
```
|
|
@ -8,7 +8,7 @@ You can separate your code into multiple ZoKrates files using `import` statement
|
|||
|
||||
The preferred way to import a symbol is by module and name:
|
||||
```zokrates
|
||||
from "./path/to/my/module" import MySymbol
|
||||
from "./path/to/my/module" import MySymbol;
|
||||
|
||||
// `MySymbol` is now in scope.
|
||||
```
|
||||
|
@ -16,7 +16,7 @@ from "./path/to/my/module" import MySymbol
|
|||
To import multiple symbols with a single import statement, separate the symbols names with commas:
|
||||
|
||||
```zokrates
|
||||
from "./path/to/my/module" import MySymbol, MyOtherSymbol
|
||||
from "./path/to/my/module" import MySymbol, MyOtherSymbol;
|
||||
```
|
||||
|
||||
#### Aliasing
|
||||
|
@ -24,7 +24,7 @@ from "./path/to/my/module" import MySymbol, MyOtherSymbol
|
|||
The `as` keyword enables renaming symbols:
|
||||
|
||||
```zokrates
|
||||
from "./path/to/my/module" import MySymbol as MyAlias
|
||||
from "./path/to/my/module" import MySymbol as MyAlias;
|
||||
|
||||
// `MySymbol` is now in scope under the alias MyAlias.
|
||||
```
|
||||
|
@ -32,11 +32,11 @@ from "./path/to/my/module" import MySymbol as MyAlias
|
|||
|
||||
The legacy way to import a symbol is by only specifying a module:
|
||||
```
|
||||
import "./path/to/my/module"
|
||||
import "./path/to/my/module";
|
||||
```
|
||||
In this case, the name of the symbol is assumed to be `main` and the alias is assumed to be the module's filename so that the above is equivalent to
|
||||
```zokrates
|
||||
from "./path/to/my/module" import main as module
|
||||
from "./path/to/my/module" import main as module;
|
||||
|
||||
// `main` is now in scope under the alias `module`.
|
||||
```
|
||||
|
@ -59,12 +59,12 @@ Constants declared with the `const` keyword are imported by name.
|
|||
|
||||
You can import a resource in the same folder directly, like this:
|
||||
```zokrates
|
||||
from "./mycode" import foo
|
||||
from "./mycode" import foo;
|
||||
```
|
||||
|
||||
Imports up the file-system tree are supported:
|
||||
```zokrates
|
||||
from "../../../mycode" import foo
|
||||
from "../../../mycode" import foo;
|
||||
```
|
||||
|
||||
### Absolute Imports
|
||||
|
|
|
@ -71,8 +71,8 @@ ZoKrates offers a special shorthand syntax to initialize an array with a constan
|
|||
|
||||
The following code provides examples for declaration and initialization:
|
||||
```zokrates
|
||||
field[3] a = [1, 2, 3] // initialize a field array with field values
|
||||
bool[13] b = [false; 13] // initialize a bool array with value false
|
||||
field[3] a = [1, 2, 3]; // initialize a field array with field values
|
||||
bool[13] b = [false; 13]; // initialize a bool array with value false
|
||||
```
|
||||
|
||||
#### Multidimensional Arrays
|
||||
|
@ -95,16 +95,16 @@ ZoKrates provides some syntactic sugar to retrieve subsets of arrays.
|
|||
The spread operator `...` applied to an array copies the elements of the existing array.
|
||||
This can be used to conveniently compose new arrays, as shown in the following example:
|
||||
```
|
||||
field[3] a = [1, 2, 3]
|
||||
field[4] c = [...a, 4] // initialize an array copying values from `a`, followed by 4
|
||||
field[3] a = [1, 2, 3];
|
||||
field[4] c = [...a, 4]; // initialize an array copying values from `a`, followed by 4
|
||||
```
|
||||
|
||||
##### Slices
|
||||
An array can also be assigned to by creating a copy of a subset of an existing array.
|
||||
This operation is called slicing, and the following example shows how to slice in ZoKrates:
|
||||
```
|
||||
field[3] a = [1, 2, 3]
|
||||
field[2] b = a[1..3] // initialize an array copying a slice from `a`
|
||||
field[3] a = [1, 2, 3];
|
||||
field[2] b = a[1..3]; // initialize an array copying a slice from `a`
|
||||
```
|
||||
|
||||
### Tuples
|
||||
|
@ -132,8 +132,8 @@ A struct definition starts with the `struct` keyword followed by a name. Afterwa
|
|||
|
||||
```zokrates
|
||||
struct Point {
|
||||
field x
|
||||
field y
|
||||
field x;
|
||||
field y;
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -10,6 +10,13 @@ Variables need to be declared to be used. Declaration and definition are always
|
|||
{{#include ../../../zokrates_cli/examples/book/declaration.zok}}
|
||||
```
|
||||
|
||||
### Mutability
|
||||
|
||||
Variables are immutable by default. In order to declare a mutable variable, the `mut` keyword is used.
|
||||
```zokrates
|
||||
{{#include ../../../zokrates_cli/examples/book/mutable.zok}}
|
||||
```
|
||||
|
||||
### Shadowing
|
||||
|
||||
Shadowing is not allowed.
|
||||
|
|
|
@ -59,11 +59,9 @@ In this example, the ABI specification is:
|
|||
"type":"field"
|
||||
}
|
||||
],
|
||||
"outputs":[
|
||||
{
|
||||
"type":"field"
|
||||
}
|
||||
]
|
||||
"output": {
|
||||
"type":"field"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ const { initialize } = require('zokrates-js')
|
|||
## Example
|
||||
```js
|
||||
initialize().then((zokratesProvider) => {
|
||||
const source = "def main(private field a) -> field: return a * a";
|
||||
const source = "def main(private field a) -> field { return a * a; }";
|
||||
|
||||
// compilation
|
||||
const artifacts = zokratesProvider.compile(source);
|
||||
|
@ -88,7 +88,7 @@ Returns: `CompilationArtifacts`
|
|||
|
||||
Compilation:
|
||||
```js
|
||||
const artifacts = zokratesProvider.compile("def main() -> (): return");
|
||||
const artifacts = zokratesProvider.compile("def main() { return; }");
|
||||
```
|
||||
|
||||
Compilation with custom options:
|
||||
|
@ -99,7 +99,7 @@ const options = {
|
|||
resolveCallback: (currentLocation, importLocation) => {
|
||||
console.log(currentLocation + ' is importing ' + importLocation);
|
||||
return {
|
||||
source: "def main() -> (): return",
|
||||
source: "def main() { return; }",
|
||||
location: importLocation
|
||||
};
|
||||
}
|
||||
|
@ -135,13 +135,13 @@ Returns: `ComputationResult`
|
|||
**Example:**
|
||||
|
||||
```js
|
||||
const code = 'def main(private field a) -> (field): return a * a';
|
||||
const code = 'def main(private field a) -> field { return a * a; }';
|
||||
const artifacts = zokratesProvider.compile(code);
|
||||
|
||||
const { witness, output } = zokratesProvider.computeWitness(artifacts, ["2"]);
|
||||
|
||||
console.log(witness); // Resulting witness which can be used to generate a proof
|
||||
console.log(output); // Computation output: ["4"]
|
||||
console.log(output); // Computation output: "4"
|
||||
```
|
||||
|
||||
##### setup(program)
|
||||
|
|
|
@ -11,5 +11,5 @@ def fill<R, C>(field v) -> matrix<R, C> {
|
|||
def main(uint32 a, uint32 b) -> (UInt32Array<2>, matrix<2, 4>) {
|
||||
UInt32Array<2> res = [a, b];
|
||||
matrix<2, 4> m = fill(1);
|
||||
return res, m;
|
||||
return (res, m);
|
||||
}
|
||||
|
|
|
@ -12,5 +12,5 @@ def buzz<N>() -> Buzz<N> {
|
|||
|
||||
def main(matrix_2x4 m) -> (Buzz<2>, matrix_2x4) {
|
||||
Buzz<2> b = buzz::<2>();
|
||||
return b, m;
|
||||
return (b, m);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
def sub(field a) -> field {
|
||||
def sub(field mut a) -> field {
|
||||
a = a + 3;
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
def main() -> u32 {
|
||||
u32[3] a = [1, 2, 3];
|
||||
u32 c = 0;
|
||||
u32 mut c = 0;
|
||||
for u32 i in 0..3 {
|
||||
c = c + a[i];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
def main() -> (u32[3]) {
|
||||
def main() -> u32[3] {
|
||||
u32[3] a = [1, 2, 3];
|
||||
u32[3] c = [4, 5, 6];
|
||||
u32[3] mut c = [4, 5, 6];
|
||||
for u32 i in 0..3 {
|
||||
c[i] = c[i] + a[i];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
def main(bool[3] a) -> (field[3]) {
|
||||
def main(bool[3] mut a) -> field[3] {
|
||||
bool[3] c = [true, true || false, true];
|
||||
a[1] = true || a[2];
|
||||
a[2] = a[0];
|
||||
field[3] result = [0; 3];
|
||||
field[3] mut result = [0; 3];
|
||||
for u32 i in 0..3 {
|
||||
result[i] = a[i] ? 33 : 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
def main(field[2][2][2] cube) -> field {
|
||||
field res = 0;
|
||||
field mut res = 0;
|
||||
|
||||
for u32 i in 0..2 {
|
||||
for u32 j in 0..2 {
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
def main(field value) -> (field[3]) {
|
||||
def main(field value) -> field[3] {
|
||||
return [value, value, value];
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
def main(field[10][10][10] a, u32 i, u32 j, u32 k) -> (field[3]) {
|
||||
def main(field[10][10][10] mut a, u32 i, u32 j, u32 k) -> field[3] {
|
||||
a[i][j][k] = 42;
|
||||
field[3][3] b = [[1, 2, 3], [1, 2, 3], [1, 2, 3]];
|
||||
return b[0];
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
def foo(field[3] a) -> field {
|
||||
def foo(field[3] mut a) -> field {
|
||||
a[1] = 2;
|
||||
return a[1];
|
||||
}
|
||||
|
@ -7,6 +7,5 @@ def main() -> (field, field) {
|
|||
field[3] a = [0, 0, 0];
|
||||
field res = foo(a);
|
||||
assert(a[1] == 0);
|
||||
return res, a[1];
|
||||
}
|
||||
|
||||
return (res, a[1]);
|
||||
}
|
|
@ -3,9 +3,9 @@ def foo(field a) -> field {
|
|||
}
|
||||
|
||||
def main(field a) -> (field, field) {
|
||||
field[2] result = [0, 0];
|
||||
field[2] mut result = [0, 0];
|
||||
field r = foo(a);
|
||||
result[1] = r;
|
||||
assert(result[1] == r);
|
||||
return result[1], r;
|
||||
}
|
||||
return (result[1], r);
|
||||
}
|
|
@ -2,12 +2,8 @@ def foo() -> u32 {
|
|||
return 0;
|
||||
}
|
||||
|
||||
def bar() -> (u32, u32) {
|
||||
return 0, 0;
|
||||
}
|
||||
|
||||
def main(u32[1] a, u32 b) {
|
||||
def main(u32[1] mut a, (u32,) mut b) {
|
||||
a[0] = foo();
|
||||
a[0], b = bar();
|
||||
b.0 = foo();
|
||||
return;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
def main() -> field {
|
||||
field[3] a = [1, 2, 3]; // initialize a field array with field values
|
||||
field[3] mut a = [1, 2, 3]; // initialize a field array with field values
|
||||
a[2] = 4; // set a member to a value
|
||||
field[4] b = [42; 4]; // initialize an array of 4 values all equal to 42
|
||||
field[4] c = [...a, 4]; // initialize an array copying values from `a`, followed by 4
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
def main() -> () {
|
||||
def main() {
|
||||
assert(1f + 1f == 2f);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
def swap(u32 a, u32 b, bool c) -> (u32, u32) {
|
||||
def swap(u32 a, u32 mut b, bool c) -> (u32, u32) {
|
||||
u32 a_prime = c ? b : a;
|
||||
b = c ? a : b;
|
||||
return a_prime, b;
|
||||
b = c ? a : b;
|
||||
return (a_prime, b);
|
||||
}
|
||||
|
||||
def bubblesort<N>(u32[N] a) -> u32[N] {
|
||||
def bubblesort<N>(u32[N] mut a) -> u32[N] {
|
||||
for u32 i in 0..(N-1) {
|
||||
for u32 j in 0..(N-1-i) {
|
||||
bool need_swap = a[j + 1] < a[j];
|
||||
a[j], a[j + 1] = swap(a[j], a[j + 1], need_swap);
|
||||
(u32, u32) swapped = swap(a[j], a[j + 1], need_swap);
|
||||
a[j] = swapped.0;
|
||||
a[j + 1] = swapped.1;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
|
@ -17,4 +19,3 @@ def bubblesort<N>(u32[N] a) -> u32[N] {
|
|||
def main(u32[10] a) -> u32[10] {
|
||||
return bubblesort(a);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
def main() {
|
||||
// declare and define `my_variable`
|
||||
field my_variable = 2;
|
||||
field mut my_variable = 2;
|
||||
// redefine `my_variable`
|
||||
my_variable = 3;
|
||||
return;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// a function to sum the N first powers of a field element
|
||||
def sum_powers<N>(field a) -> field {
|
||||
field res = 0;
|
||||
field mut res = 0;
|
||||
for u32 i in 0..N {
|
||||
res = res + a ** i;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
def main() -> u32 {
|
||||
u32 res = 0;
|
||||
u32 mut res = 0;
|
||||
for u32 i in 0..4 {
|
||||
for u32 j in i..5 {
|
||||
res = res + i;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
def main() -> u32 {
|
||||
u32 a = 0;
|
||||
u32 mut a = 0;
|
||||
for u32 i in 0..5 {
|
||||
a = a + i;
|
||||
}
|
||||
// return i <- not allowed
|
||||
// return i; <- not allowed
|
||||
return a;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
def foo() -> field {
|
||||
// return myGlobal <- not allowed
|
||||
// return myGlobal; <- not allowed
|
||||
return 42;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
def sum<N>(field[N] a) -> field {
|
||||
field res = 0;
|
||||
field mut res = 0;
|
||||
for u32 i in 0..N {
|
||||
res = res + a[i];
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
def foo() -> (field, field) {
|
||||
return 21, 42;
|
||||
}
|
||||
|
||||
def main() {
|
||||
// a is declared here
|
||||
field a = 1;
|
||||
// b is declared here
|
||||
a, field b = foo();
|
||||
return;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
def main() -> (field, field[3]) {
|
||||
return 1, [2, 3, 4];
|
||||
}
|
|
@ -7,4 +7,3 @@ def main() -> field {
|
|||
// allowed access [0..2][0..3]
|
||||
return a[1][2];
|
||||
}
|
||||
|
||||
|
|
7
zokrates_cli/examples/book/mutable.zok
Normal file
7
zokrates_cli/examples/book/mutable.zok
Normal file
|
@ -0,0 +1,7 @@
|
|||
def main() {
|
||||
field a = 42;
|
||||
// a = 43; <- not allowed, as `a` is immutable
|
||||
field mut b = 42;
|
||||
b = 43; // ok
|
||||
return;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
def main() -> field {
|
||||
field a = 2;
|
||||
// field a = 3 <- not allowed
|
||||
// field a = 3; <- not allowed
|
||||
for u32 i in 0..5 {
|
||||
// field a = 7 <- not allowed
|
||||
// field a = 7; <- not allowed
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
def main(field a, field b) -> (bool) {
|
||||
def main(field a, field b) -> bool {
|
||||
return !(a == b);
|
||||
}
|
|
@ -8,12 +8,12 @@ import "utils/casts/u32_to_bits" as u32_to_bits;
|
|||
// the remaining preimage bits.
|
||||
def main(private u32[16] preimage, u32 bitNum) -> (u32[8], bool) {
|
||||
// Convert the preimage to bits
|
||||
bool[512] preimageBits = [false; 512];
|
||||
bool[512] mut preimageBits = [false; 512];
|
||||
for u32 i in 0..16 {
|
||||
bool[32] val = u32_to_bits(preimage[i]);
|
||||
for u32 bit in 0..32 {
|
||||
preimageBits[i*32 + bit] = val[bit];
|
||||
}
|
||||
}
|
||||
return sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum];
|
||||
return (sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum]);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
def incr(field a) -> field {
|
||||
def incr(field mut a) -> field {
|
||||
a = a + 1;
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ struct Point {
|
|||
field y;
|
||||
}
|
||||
|
||||
def main(field a) -> (Point) {
|
||||
Point p = Point { x: 1, y: 0 };
|
||||
def main(field a) -> Point {
|
||||
Point mut p = Point { x: 1, y: 0 };
|
||||
p.x = a;
|
||||
p.y = p.x;
|
||||
return p;
|
||||
|
|
|
@ -3,8 +3,7 @@ struct Point {
|
|||
field y;
|
||||
}
|
||||
|
||||
def main() -> (Point) {
|
||||
def main() -> Point {
|
||||
Point p = Point { x: 1, y: 0 };
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,8 @@ struct Foo<P> {
|
|||
bool b;
|
||||
}
|
||||
|
||||
def main() -> (Foo<2>) {
|
||||
Foo<2>[2] f = [Foo { a: Bar { c: [0, 0], d: false }, b: true}, Foo { a: Bar {c: [0, 0], d: false}, b: true }];
|
||||
def main() -> Foo<2> {
|
||||
Foo<2>[2] mut f = [Foo { a: Bar { c: [0, 0], d: false }, b: true}, Foo { a: Bar {c: [0, 0], d: false}, b: true }];
|
||||
f[0].a.c = [42, 43];
|
||||
return f[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
def main() -> bool {
|
||||
(field[2], bool) v = ([1, 2], true);
|
||||
(field[2], bool) mut v = ([1, 2], true);
|
||||
v.0 = [42, 43];
|
||||
return v.1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
def foo() -> (field, field[3]) {
|
||||
return 1, [2, 3, 4];
|
||||
return (1, [2, 3, 4]);
|
||||
}
|
||||
|
||||
def foo() -> (field, field) {
|
||||
return 1, 2;
|
||||
return (1, 2);
|
||||
}
|
||||
|
||||
def main() {
|
||||
field a, field[3] b = foo();
|
||||
(field, field[3]) a = foo();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// comparison operator example
|
||||
def main(field x) -> field {
|
||||
field y = x >= 3 ? 1 : 5;
|
||||
field z = y <= x ? x**3 : y**3;
|
||||
def main(field mut x) -> field {
|
||||
field mut y = x >= 3 ? 1 : 5;
|
||||
field mut z = y <= x ? x**3 : y**3;
|
||||
y = x < 3 ? 2 : 6;
|
||||
z = y > z ? 1 : 2;
|
||||
x = x == x ? x : y;
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
def foo<N>() -> field[N] {
|
||||
return [42; N];
|
||||
}
|
||||
|
||||
def main() -> field[2] {
|
||||
return foo(); // N is currently not infered to 2 here
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
def bar() -> field[3] {
|
||||
return [1, 2, 3];
|
||||
}
|
||||
|
||||
def foo<N>() -> field[N] {
|
||||
return bar();
|
||||
}
|
||||
|
||||
def main() -> field[2] {
|
||||
return foo();
|
||||
}
|
|
@ -2,6 +2,5 @@ def assert() {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
return
|
|
@ -0,0 +1,4 @@
|
|||
def main():
|
||||
field a = 2
|
||||
a = 3
|
||||
return
|
|
@ -0,0 +1,7 @@
|
|||
def foo() -> (field, field):
|
||||
return 1, 2
|
||||
|
||||
def main():
|
||||
field a, field b = foo()
|
||||
a = 3
|
||||
return
|
|
@ -1,6 +1,6 @@
|
|||
struct Foo {}
|
||||
struct Bar {}
|
||||
|
||||
def main() -> (Foo) {
|
||||
def main() -> Foo {
|
||||
return Bar {};
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
def constant() -> u32 {
|
||||
u32 res = 0;
|
||||
u32 mut res = 0;
|
||||
u32 x = 3;
|
||||
for u32 y in 0..x {
|
||||
res = res + 1;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
def func<N>() -> bool {
|
||||
u64[N] y = [...[0; N-1], 1]; // the rhs should *not* be reduced to [1] because the spread is not empty
|
||||
u64 q = 0;
|
||||
u64 mut q = 0;
|
||||
|
||||
for u32 i in 0..N {
|
||||
q = y[i];
|
||||
|
|
|
@ -3,7 +3,7 @@ def bound(field x) -> u32 {
|
|||
}
|
||||
|
||||
def main(field a) -> field {
|
||||
field x = 7;
|
||||
field mut x = 7;
|
||||
x = x + 1;
|
||||
for u32 i in 0..bound(x) + bound(x + 1) {
|
||||
x = x + a;
|
||||
|
|
|
@ -16,8 +16,7 @@ def cubeThing(field thing) -> field {
|
|||
}
|
||||
|
||||
def main(u32 index) -> bool {
|
||||
field thing = getThing(index);
|
||||
field mut thing = getThing(index);
|
||||
thing = cubeThing(thing);
|
||||
return lt(cutoff(), thing);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ def add(field a, field b) -> field {
|
|||
}
|
||||
|
||||
def main(field a, field b, field c, field d) -> field {
|
||||
field g = a + b;
|
||||
field mut g = a + b;
|
||||
field x = add(a, b);
|
||||
field y = add(c, d);
|
||||
g = add(x, g);
|
||||
|
|
|
@ -2,7 +2,7 @@ def constant() -> field {
|
|||
return 123123;
|
||||
}
|
||||
|
||||
def add(field a, field b) -> field {
|
||||
def add(field mut a, field b) -> field {
|
||||
a = constant();
|
||||
return a + b;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ def add(field a,field b) -> field {
|
|||
}
|
||||
|
||||
def main(field a,field b) -> field {
|
||||
field c = add(a, b);
|
||||
field mut c = add(a, b);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ const u32 DEPTH = 3;
|
|||
|
||||
def main(u32[8] root, private u32[8] leaf, private bool[DEPTH] directionSelector, private u32[DEPTH][8] path) -> bool {
|
||||
// Start from the leaf
|
||||
u32[8] digest = leaf;
|
||||
u32[8] mut digest = leaf;
|
||||
|
||||
// Loop up the tree
|
||||
for u32 i in 0..DEPTH {
|
||||
|
|
|
@ -4,7 +4,7 @@ import "hashes/utils/256bitsDirectionHelper" as multiplex;
|
|||
const u32 DEPTH = 3;
|
||||
|
||||
def select(bool condition, u32[8] left, u32[8] right) -> (u32[8], u32[8]) {
|
||||
return condition ? right : left, condition ? left : right;
|
||||
return (condition ? right : left, condition ? left : right);
|
||||
}
|
||||
|
||||
// Merke-Tree inclusion proof for tree depth 4 using sha256
|
||||
|
@ -12,13 +12,13 @@ def select(bool condition, u32[8] left, u32[8] right) -> (u32[8], u32[8]) {
|
|||
|
||||
def main(u32[8] root, private u32[8] leaf, private bool[DEPTH] directionSelector, private u32[DEPTH][8] path) -> bool {
|
||||
// Start from the leaf
|
||||
u32[8] digest = leaf;
|
||||
u32[8] mut digest = leaf;
|
||||
|
||||
// Loop up the tree
|
||||
for u32 i in 0..DEPTH {
|
||||
u32[8] left, u32[8] right = select(directionSelector[i], digest, path[i]);
|
||||
digest = hash(left, right);
|
||||
}
|
||||
// Loop up the tree
|
||||
for u32 i in 0..DEPTH {
|
||||
(u32[8], u32[8]) s = select(directionSelector[i], digest, path[i]);
|
||||
digest = hash(s.0, s.1);
|
||||
}
|
||||
|
||||
return digest == root;
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
def foo(field a) -> (field, field, field, field) {
|
||||
field b = 12 * a;
|
||||
return a, 2 * a, 5 * b, a * b;
|
||||
}
|
||||
|
||||
def main(field i) {
|
||||
field x, field y, field z, field t = foo(i);
|
||||
return;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
def foo() -> (field, field) {
|
||||
return 1, 2;
|
||||
}
|
||||
|
||||
def main() -> (field, field) {
|
||||
field a, field b = foo();
|
||||
return a + b, b - a;
|
||||
}
|
|
@ -2,8 +2,8 @@ import "utils/casts/u32_to_field" as to_field;
|
|||
|
||||
// Binomial Coeffizient, n!/(k!*(n-k)!).
|
||||
def fac(field x) -> field {
|
||||
field f = 1;
|
||||
field counter = 0;
|
||||
field mut f = 1;
|
||||
field mut counter = 0;
|
||||
for u32 i in 1..100 {
|
||||
f = counter == x ? f : f * to_field(i);
|
||||
counter = counter == x ? counter : counter + 1;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
def main() {
|
||||
field x = 2**4;
|
||||
field mut x = 2**4;
|
||||
assert(x == 16);
|
||||
x = x**2;
|
||||
assert(x == 256);
|
||||
|
@ -7,7 +7,7 @@ def main() {
|
|||
assert(y == 27);
|
||||
field z = y**2;
|
||||
assert(z == 729);
|
||||
field a = 5**2;
|
||||
field mut a = 5**2;
|
||||
assert(a == 25);
|
||||
a = a**2;
|
||||
assert(a == 625);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
def main() -> field {
|
||||
field a = 1 + 2 + 3;
|
||||
field b = 1 < a ? 3 : a + 3;
|
||||
field c = b + a == 2 ? 1 : b;
|
||||
field mut c = b + a == 2 ? 1 : b;
|
||||
for u32 e in 0..2 {
|
||||
field g = 4;
|
||||
c = c + g;
|
||||
}
|
||||
return c * a;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
def foo(field a, field b) -> (field, field) {
|
||||
assert(a == b);
|
||||
return a, b;
|
||||
assert(a == b);
|
||||
return (a, b);
|
||||
}
|
||||
|
||||
def main() -> field {
|
||||
field a, field b = foo(1, 1);
|
||||
return a + b;
|
||||
(field, field) v = foo(1, 1);
|
||||
return v.0 + v.1;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
def main(field x) -> field {
|
||||
field a = x + 5;
|
||||
field mut a = x + 5;
|
||||
field b = a + x;
|
||||
a = 7;
|
||||
field c = a + b;
|
||||
a = a + 5;
|
||||
return a + c;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ struct Foo {
|
|||
}
|
||||
|
||||
def main() -> Foo {
|
||||
Foo[2] f = [
|
||||
Foo[2] mut f = [
|
||||
Foo {
|
||||
a: Bar {
|
||||
c: [0, 0],
|
||||
|
|
|
@ -26,7 +26,7 @@ def checkNoDuplicates(field a, field b, field c, field d) -> bool {
|
|||
|
||||
// returns true if and only if `x` is one of the `4` primes
|
||||
def validateInput(field x) -> bool {
|
||||
field res = 1;
|
||||
field mut res = 1;
|
||||
|
||||
for u32 i in 0..4 {
|
||||
res = res * (x - PRIMES[i]);
|
||||
|
@ -39,7 +39,7 @@ def validateInput(field x) -> bool {
|
|||
def main(field a21, field b11, field b22, field c11, field c22, field d21, private field a11, private field a12, private field a22, private field b12, private field b21, private field c12, private field c21, private field d11, private field d12, private field d22) -> bool {
|
||||
|
||||
Grid<4> a = [[a11, a12, b11, b12], [a21, a22, b21, b22], [c11, c12, d11, d12], [c21, c22, d21, d22]];
|
||||
bool res = true;
|
||||
bool mut res = true;
|
||||
|
||||
// go through the whole grid and check that all elements are valid
|
||||
for u32 i in 0..4 {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// We use a naive encoding of the values as `[1, 2, 3, 4]` and rely on if-else statements to detect duplicates
|
||||
|
||||
def countDuplicates(field e11, field e12, field e21, field e22) -> field {
|
||||
field duplicates = e11 == e12 ? 1 : 0;
|
||||
field mut duplicates = e11 == e12 ? 1 : 0;
|
||||
duplicates = duplicates + e11 == e21 ? 1 : 0;
|
||||
duplicates = duplicates + e11 == e22 ? 1 : 0;
|
||||
duplicates = duplicates + e12 == e21 ? 1 : 0;
|
||||
|
@ -49,7 +49,7 @@ def main(field a21, field b11, field b22, field c11, field c22, field d21, priva
|
|||
assert(validateInput(d21));
|
||||
assert(validateInput(d22));
|
||||
|
||||
field duplicates = 0; // globally counts duplicate entries in boxes, rows and columns
|
||||
field mut duplicates = 0; // globally counts duplicate entries in boxes, rows and columns
|
||||
|
||||
// check box correctness
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
def main((field, field) p, (field, field) q) -> ((field, field)) {
|
||||
def main((field, field) p, (field, field) q) -> (field, field) {
|
||||
field a = 42;
|
||||
field d = 21;
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ struct Foo {
|
|||
bool b;
|
||||
}
|
||||
|
||||
def main() -> (((field[2], bool), bool)) {
|
||||
((field[2], bool), bool)[2] f = [
|
||||
(([0, 0], false), true),
|
||||
(([0, 0], false), true)
|
||||
];
|
||||
f[0].0.0 = [42, 43];
|
||||
return f[0];
|
||||
def main() -> ((field[2], bool), bool) {
|
||||
((field[2], bool), bool)[2] mut f = [
|
||||
(([0, 0], false), true),
|
||||
(([0, 0], false), true)
|
||||
];
|
||||
f[0].0.0 = [42, 43];
|
||||
return f[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use zokrates_abi::Encode;
|
|||
use zokrates_ast::ir::{self, ProgEnum};
|
||||
use zokrates_ast::typed::{
|
||||
abi::Abi,
|
||||
types::{ConcreteSignature, ConcreteType},
|
||||
types::{ConcreteSignature, ConcreteType, GTupleType},
|
||||
};
|
||||
use zokrates_field::Field;
|
||||
|
||||
|
@ -104,7 +104,9 @@ fn cli_compute<T: Field, I: Iterator<Item = ir::Statement<T>>>(
|
|||
}
|
||||
false => ConcreteSignature::new()
|
||||
.inputs(vec![ConcreteType::FieldElement; ir_prog.arguments.len()])
|
||||
.outputs(vec![ConcreteType::FieldElement; ir_prog.return_count]),
|
||||
.output(ConcreteType::Tuple(GTupleType::new(
|
||||
vec![ConcreteType::FieldElement; ir_prog.return_count],
|
||||
))),
|
||||
};
|
||||
|
||||
use zokrates_abi::Inputs;
|
||||
|
@ -166,7 +168,7 @@ fn cli_compute<T: Field, I: Iterator<Item = ir::Statement<T>>>(
|
|||
use zokrates_abi::Decode;
|
||||
|
||||
let results_json_value: serde_json::Value =
|
||||
zokrates_abi::Values::decode(witness.return_values(), signature.outputs).into_serde_json();
|
||||
zokrates_abi::Value::decode(witness.return_values(), *signature.output).into_serde_json();
|
||||
|
||||
if verbose {
|
||||
println!("\nWitness: \n{}\n", results_json_value);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
def main(field[2][2] a) -> field[2][2] {
|
||||
def main(field[2][2] mut a) -> field[2][2] {
|
||||
a[1][1] = 42;
|
||||
return a;
|
||||
}
|
||||
}
|
|
@ -2,8 +2,8 @@ import "utils/casts/u32_to_field" as to_field;
|
|||
|
||||
// Binomial Coeffizient, n!/(k!*(n-k)!).
|
||||
def fac(field x) -> field {
|
||||
field f = 1;
|
||||
field counter = 0;
|
||||
field mut f = 1;
|
||||
field mut counter = 0;
|
||||
for u32 i in 1..100 {
|
||||
f = counter == x ? f : f * to_field(i);
|
||||
counter = counter == x ? counter : counter + 1;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
def main(private field[3] a, private field b, private field[4] c) -> (field, field[3], field[4]) {
|
||||
return b, a, c;
|
||||
return (b, a, c);
|
||||
}
|
||||
|
|
|
@ -476,7 +476,7 @@ struct Bar { field a; }
|
|||
}]
|
||||
))
|
||||
}],
|
||||
outputs: vec![]
|
||||
output: ConcreteType::Tuple(GTupleType::new(vec![]))
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
use zokrates_ast::typed::{
|
||||
folder::*, BlockExpression, BooleanExpression, Conditional, ConditionalExpression,
|
||||
ConditionalOrExpression, CoreIdentifier, Expr, Identifier, TypedProgram, TypedStatement,
|
||||
ConditionalOrExpression, CoreIdentifier, Expr, Identifier, Type, TypedProgram, TypedStatement,
|
||||
Variable,
|
||||
};
|
||||
use zokrates_field::Field;
|
||||
|
@ -66,7 +66,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConditionRedefiner<'ast, T> {
|
|||
condition => {
|
||||
let condition_id = Identifier::from(CoreIdentifier::Condition(self.index));
|
||||
self.buffer.push(TypedStatement::Definition(
|
||||
Variable::boolean(condition_id.clone()).into(),
|
||||
Variable::immutable(condition_id.clone(), Type::Boolean).into(),
|
||||
condition.into(),
|
||||
));
|
||||
self.index += 1;
|
||||
|
@ -164,7 +164,7 @@ mod tests {
|
|||
let expected = vec![
|
||||
// define condition
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(CoreIdentifier::Condition(0), Type::Boolean).into(),
|
||||
Variable::immutable(CoreIdentifier::Condition(0), Type::Boolean).into(),
|
||||
condition.into(),
|
||||
),
|
||||
// rewrite statement
|
||||
|
@ -233,11 +233,11 @@ mod tests {
|
|||
let expected = vec![
|
||||
// define conditions
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(CoreIdentifier::Condition(0), Type::Boolean).into(),
|
||||
Variable::immutable(CoreIdentifier::Condition(0), Type::Boolean).into(),
|
||||
condition_0.into(),
|
||||
),
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(CoreIdentifier::Condition(1), Type::Boolean).into(),
|
||||
Variable::immutable(CoreIdentifier::Condition(1), Type::Boolean).into(),
|
||||
condition_1.into(),
|
||||
),
|
||||
// rewrite statement
|
||||
|
@ -341,7 +341,7 @@ mod tests {
|
|||
let expected = vec![
|
||||
// define conditions
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(CoreIdentifier::Condition(0), Type::Boolean).into(),
|
||||
Variable::immutable(CoreIdentifier::Condition(0), Type::Boolean).into(),
|
||||
condition_0.into(),
|
||||
),
|
||||
// rewrite statement
|
||||
|
@ -356,11 +356,8 @@ mod tests {
|
|||
FieldElementExpression::Number(Bn128Field::from(1)).into(),
|
||||
),
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(
|
||||
CoreIdentifier::Condition(1),
|
||||
Type::Boolean,
|
||||
)
|
||||
.into(),
|
||||
Variable::immutable(CoreIdentifier::Condition(1), Type::Boolean)
|
||||
.into(),
|
||||
condition_1.into(),
|
||||
),
|
||||
],
|
||||
|
@ -378,11 +375,8 @@ mod tests {
|
|||
FieldElementExpression::Number(Bn128Field::from(2)).into(),
|
||||
),
|
||||
TypedStatement::Definition(
|
||||
Variable::with_id_and_type(
|
||||
CoreIdentifier::Condition(2),
|
||||
Type::Boolean,
|
||||
)
|
||||
.into(),
|
||||
Variable::immutable(CoreIdentifier::Condition(2), Type::Boolean)
|
||||
.into(),
|
||||
condition_2.into(),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -3,8 +3,8 @@ use zokrates_ast::common::FlatEmbed;
|
|||
use zokrates_ast::typed::TypedProgram;
|
||||
use zokrates_ast::typed::{
|
||||
result_folder::ResultFolder,
|
||||
result_folder::{fold_expression_list_inner, fold_uint_expression_inner},
|
||||
Constant, TypedExpressionListInner, Types, UBitwidth, UExpressionInner,
|
||||
result_folder::{fold_statement, fold_uint_expression_inner},
|
||||
Constant, EmbedCall, TypedStatement, UBitwidth, UExpressionInner,
|
||||
};
|
||||
use zokrates_field::Field;
|
||||
|
||||
|
@ -28,6 +28,46 @@ impl fmt::Display for Error {
|
|||
impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantArgumentChecker {
|
||||
type Error = Error;
|
||||
|
||||
fn fold_statement(
|
||||
&mut self,
|
||||
s: TypedStatement<'ast, T>,
|
||||
) -> Result<Vec<TypedStatement<'ast, T>>, Self::Error> {
|
||||
match s {
|
||||
TypedStatement::EmbedCallDefinition(assignee, embed_call) => match embed_call {
|
||||
EmbedCall {
|
||||
embed: FlatEmbed::BitArrayLe,
|
||||
..
|
||||
} => {
|
||||
let arguments = embed_call
|
||||
.arguments
|
||||
.into_iter()
|
||||
.map(|a| self.fold_expression(a))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
if arguments[1].is_constant() {
|
||||
Ok(vec![TypedStatement::EmbedCallDefinition(
|
||||
assignee,
|
||||
EmbedCall {
|
||||
embed: FlatEmbed::BitArrayLe,
|
||||
generics: embed_call.generics,
|
||||
arguments,
|
||||
},
|
||||
)])
|
||||
} else {
|
||||
Err(Error(format!(
|
||||
"Cannot compare to a variable value, found `{}`",
|
||||
arguments[1]
|
||||
)))
|
||||
}
|
||||
}
|
||||
embed_call => Ok(vec![TypedStatement::EmbedCallDefinition(
|
||||
assignee, embed_call,
|
||||
)]),
|
||||
},
|
||||
s => fold_statement(self, s),
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_uint_expression_inner(
|
||||
&mut self,
|
||||
bitwidth: UBitwidth,
|
||||
|
@ -63,33 +103,4 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantArgumentChecker {
|
|||
e => fold_uint_expression_inner(self, bitwidth, e),
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_expression_list_inner(
|
||||
&mut self,
|
||||
tys: &Types<'ast, T>,
|
||||
l: TypedExpressionListInner<'ast, T>,
|
||||
) -> Result<TypedExpressionListInner<'ast, T>, Error> {
|
||||
match l {
|
||||
TypedExpressionListInner::EmbedCall(FlatEmbed::BitArrayLe, generics, arguments) => {
|
||||
let arguments = arguments
|
||||
.into_iter()
|
||||
.map(|a| self.fold_expression(a))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
if arguments[1].is_constant() {
|
||||
Ok(TypedExpressionListInner::EmbedCall(
|
||||
FlatEmbed::BitArrayLe,
|
||||
generics,
|
||||
arguments,
|
||||
))
|
||||
} else {
|
||||
Err(Error(format!(
|
||||
"Cannot compare to a variable value, found `{}`",
|
||||
arguments[1]
|
||||
)))
|
||||
}
|
||||
}
|
||||
l => fold_expression_list_inner(self, tys, l),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantResolver<'ast, T> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use zokrates_ast::typed::types::DeclarationSignature;
|
||||
use zokrates_ast::typed::types::{DeclarationSignature, GTupleType};
|
||||
use zokrates_ast::typed::{
|
||||
DeclarationArrayType, DeclarationFunctionKey, DeclarationType, FieldElementExpression,
|
||||
GType, Identifier, TypedConstant, TypedExpression, TypedFunction, TypedFunctionSymbol,
|
||||
|
@ -130,12 +130,12 @@ mod tests {
|
|||
let const_id = "a";
|
||||
let main: TypedFunction<Bn128Field> = TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
statements: vec![TypedStatement::Return(
|
||||
FieldElementExpression::Identifier(Identifier::from(const_id)).into(),
|
||||
])],
|
||||
)],
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
};
|
||||
|
||||
let program = TypedProgram {
|
||||
|
@ -158,7 +158,7 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
),
|
||||
TypedFunctionSymbol::Here(main),
|
||||
)
|
||||
|
@ -190,13 +190,12 @@ mod tests {
|
|||
let const_id = CanonicalConstantIdentifier::new("a", "main".into());
|
||||
let main: TypedFunction<Bn128Field> = TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![TypedStatement::Return(vec![BooleanExpression::Identifier(
|
||||
Identifier::from(const_id.clone()),
|
||||
)
|
||||
.into()])],
|
||||
statements: vec![TypedStatement::Return(
|
||||
BooleanExpression::Identifier(Identifier::from(const_id.clone())).into(),
|
||||
)],
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::Boolean]),
|
||||
.output(DeclarationType::Boolean),
|
||||
};
|
||||
|
||||
let program = TypedProgram {
|
||||
|
@ -217,7 +216,7 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::Boolean]),
|
||||
.output(DeclarationType::Boolean),
|
||||
),
|
||||
TypedFunctionSymbol::Here(main),
|
||||
)
|
||||
|
@ -249,14 +248,14 @@ mod tests {
|
|||
let const_id = CanonicalConstantIdentifier::new("a", "main".into());
|
||||
let main: TypedFunction<Bn128Field> = TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![TypedStatement::Return(vec![UExpressionInner::Identifier(
|
||||
Identifier::from(const_id.clone()),
|
||||
)
|
||||
.annotate(UBitwidth::B32)
|
||||
.into()])],
|
||||
statements: vec![TypedStatement::Return(
|
||||
UExpressionInner::Identifier(Identifier::from(const_id.clone()))
|
||||
.annotate(UBitwidth::B32)
|
||||
.into(),
|
||||
)],
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::Uint(UBitwidth::B32)]),
|
||||
.output(DeclarationType::Uint(UBitwidth::B32)),
|
||||
};
|
||||
|
||||
let program = TypedProgram {
|
||||
|
@ -279,7 +278,7 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::Uint(UBitwidth::B32)]),
|
||||
.output(DeclarationType::Uint(UBitwidth::B32)),
|
||||
),
|
||||
TypedFunctionSymbol::Here(main),
|
||||
)
|
||||
|
@ -311,24 +310,26 @@ mod tests {
|
|||
let const_id = CanonicalConstantIdentifier::new("a", "main".into());
|
||||
let main: TypedFunction<Bn128Field> = TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![TypedStatement::Return(vec![FieldElementExpression::Add(
|
||||
FieldElementExpression::select(
|
||||
ArrayExpressionInner::Identifier(Identifier::from(const_id.clone()))
|
||||
.annotate(GType::FieldElement, 2u32),
|
||||
UExpressionInner::Value(0u128).annotate(UBitwidth::B32),
|
||||
statements: vec![TypedStatement::Return(
|
||||
FieldElementExpression::Add(
|
||||
FieldElementExpression::select(
|
||||
ArrayExpressionInner::Identifier(Identifier::from(const_id.clone()))
|
||||
.annotate(GType::FieldElement, 2u32),
|
||||
UExpressionInner::Value(0u128).annotate(UBitwidth::B32),
|
||||
)
|
||||
.into(),
|
||||
FieldElementExpression::select(
|
||||
ArrayExpressionInner::Identifier(Identifier::from(const_id.clone()))
|
||||
.annotate(GType::FieldElement, 2u32),
|
||||
UExpressionInner::Value(1u128).annotate(UBitwidth::B32),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
FieldElementExpression::select(
|
||||
ArrayExpressionInner::Identifier(Identifier::from(const_id.clone()))
|
||||
.annotate(GType::FieldElement, 2u32),
|
||||
UExpressionInner::Value(1u128).annotate(UBitwidth::B32),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into()])],
|
||||
)],
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
};
|
||||
|
||||
let program = TypedProgram {
|
||||
|
@ -363,7 +364,7 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
),
|
||||
TypedFunctionSymbol::Here(main),
|
||||
)
|
||||
|
@ -396,12 +397,12 @@ mod tests {
|
|||
|
||||
let main: TypedFunction<Bn128Field> = TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
statements: vec![TypedStatement::Return(
|
||||
FieldElementExpression::Identifier(Identifier::from(const_b_id.clone())).into(),
|
||||
])],
|
||||
)],
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
};
|
||||
|
||||
let program = TypedProgram {
|
||||
|
@ -437,7 +438,7 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
),
|
||||
TypedFunctionSymbol::Here(main),
|
||||
)
|
||||
|
@ -522,12 +523,17 @@ mod tests {
|
|||
)
|
||||
.into(),
|
||||
TypedFunctionSymbolDeclaration::new(
|
||||
DeclarationFunctionKey::with_location("foo", "main")
|
||||
.signature(DeclarationSignature::new().inputs(vec![]).outputs(vec![])),
|
||||
DeclarationFunctionKey::with_location("foo", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.output(DeclarationType::Tuple(GTupleType::new(vec![]))),
|
||||
),
|
||||
TypedFunctionSymbol::Here(TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![],
|
||||
signature: DeclarationSignature::new().inputs(vec![]).outputs(vec![]),
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.output(DeclarationType::Tuple(GTupleType::new(vec![]))),
|
||||
}),
|
||||
)
|
||||
.into(),
|
||||
|
@ -546,19 +552,19 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
),
|
||||
TypedFunctionSymbol::Here(TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
statements: vec![TypedStatement::Return(
|
||||
FieldElementExpression::Identifier(Identifier::from(
|
||||
main_const_id.clone(),
|
||||
))
|
||||
.into(),
|
||||
])],
|
||||
)],
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
}),
|
||||
)
|
||||
.into(),
|
||||
|
@ -592,19 +598,19 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
),
|
||||
TypedFunctionSymbol::Here(TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
statements: vec![TypedStatement::Return(
|
||||
FieldElementExpression::Identifier(Identifier::from(
|
||||
main_const_id.clone(),
|
||||
))
|
||||
.into(),
|
||||
])],
|
||||
)],
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
}),
|
||||
)
|
||||
.into(),
|
||||
|
@ -702,12 +708,17 @@ mod tests {
|
|||
)
|
||||
.into(),
|
||||
TypedFunctionSymbolDeclaration::new(
|
||||
DeclarationFunctionKey::with_location("foo", "main")
|
||||
.signature(DeclarationSignature::new().inputs(vec![]).outputs(vec![])),
|
||||
DeclarationFunctionKey::with_location("foo", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.output(DeclarationType::Tuple(GTupleType::new(vec![]))),
|
||||
),
|
||||
TypedFunctionSymbol::Here(TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![],
|
||||
signature: DeclarationSignature::new().inputs(vec![]).outputs(vec![]),
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.output(DeclarationType::Tuple(GTupleType::new(vec![]))),
|
||||
}),
|
||||
)
|
||||
.into(),
|
||||
|
@ -748,19 +759,19 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
),
|
||||
TypedFunctionSymbol::Here(TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
statements: vec![TypedStatement::Return(
|
||||
FieldElementExpression::Identifier(Identifier::from(
|
||||
main_foo_const_id.clone(),
|
||||
))
|
||||
.into(),
|
||||
])],
|
||||
)],
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
}),
|
||||
)
|
||||
.into(),
|
||||
|
@ -823,19 +834,19 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "main").signature(
|
||||
DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
),
|
||||
TypedFunctionSymbol::Here(TypedFunction {
|
||||
arguments: vec![],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
statements: vec![TypedStatement::Return(
|
||||
FieldElementExpression::Identifier(Identifier::from(
|
||||
main_foo_const_id.clone(),
|
||||
))
|
||||
.into(),
|
||||
])],
|
||||
)],
|
||||
signature: DeclarationSignature::new()
|
||||
.inputs(vec![])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
.output(DeclarationType::FieldElement),
|
||||
}),
|
||||
)
|
||||
.into(),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue